trsvid – A video player for TRS-80 Model 1, 3 and 4
Here’s a video of trsvid in action:
What you see there is 60 frame per second, full-screen video.
Well, on the Model 4. The Model III manages just over 54 frames/second
and the Model I just over 51 frames/second. What you hear is about 15 Khz
audio with effectively 5 or 6 bits per sample.
Choose Your Adventure
While there’s nothing wrong with reading this page straight through, there’s
a lot to cover. If you’ve got something particular in mind here’s a handy
list of places to jump ahead.
Model 3 playing A-ha’s “Take On Me”. By way of a compliment YouTube has
muted the audio because they think it sounds like the original. How high
is trsvid’s fidelity? Enough to be considered copyright infringement!
Model 3 playing the intro sequence to “Doctor Who” (the 4th Doctor). Yeah,
it’s the same one I did from floppy disk, but on
the Model 3 instead of the 4P.
Model 3 playing The Pogue’s “Fairytale of New York”.
Sorry, no video! Amazingly YouTube considered it too similar in audio
and video to the original and blocked it. Banned in every country.
Scroll down and watch the Model I version which is about the same. I think
it got flagged because I had the Model 3 filling most of the frame.
Model 3 playing a Radio Shack TV ad for its successor the Model 4.
Model 3 playing the classic intro sequence to “The Six Million Dollar Man”.
Model 4P playing A-ha’s “Take On Me”. No audio because YouTube muted it
for being a copyright violation.
Model 4P playing the intro sequence to “Doctor Who” (the 4th Doctor). Yeah,
it’s the same one I did from floppy disk.
Same as above but the 4P is playing the Model I version.
Model 4P playing The Pogue’s “Fairytale of New York”. Another victory for
fidelity; they’ll let me play it but they get all the money. Bad deal for
them because I wasn’t getting any money. Except they’ll probably put an
ad into it so the joke’s on me.
Model 4P playing a Radio Shack TV ad for the Model 4.
Same as above but with the ad encoded in “.tv1” format for the Model I.
Model 4P playing the classic intro sequence to “The Six Million Dollar Man”.
Same as above but the “.tv1” version on the Model 4P.
Model I playing A-ha’s “Take On Me”. Once again, muted for sounding too good.
Model I playing the intro sequence to “Doctor Who” (the 4th Doctor). Yeah,
it’s the same one I did from floppy disk, but on
the Model I instead of the 4P.
Model I playing The Pogue’s “Fairytale of New York”. As before, it sounded
so nice they put an ad on it.
Model I playing a Radio Shack TV ad for its grandchild the Model 4.
Model I playing the classic intro sequence to “The Six Million Dollar Man”.
If a FreHD hard drive emulator is not attached it will print a message
to that effect and also list what video file formats your TRS-80 can play:
.tv1 and/or .tv3 and/or .tv6. If you have a FreHD but without the
enhanced firmware then you’ll still be able to browse the SD card for video
files and see the preview images, you just won’t be able to play any of them.
Once trsvid/cmd is running you can use the up and down arrow keys to select
from a list of files in the current directory which is displayed on the top
status line. Notice the right-angle bracket “>” which denotes the current
selection. When a video file is selected trsvid will automatically
display the preview image in the main window and the title of the video
and playing time in the status line.
Model I users will notice black bars on the screen when a video preview is
shown. But fear not, just tap the left or right arrow key a few times to
move them out of the way.
I had the choice between that and rolling static. I decided to go
with the bars since it’ll give the best display if you move them out of
Directories are shown in the file list with a trailing “/”. Press
the space-bar to enter a directory. The special directory entry “..”
is used to go up to the parent directory. As well, there is a “-=TRSVID=-“
entry that will go right to the top of the SD card. If you want to change
SD cards, select “-=TRSVID=-“, switch cards and then press space-bar. That
way trsvid will read the new card. This is important because if you switch
cards in any other fashion trsvid will crash or print some message about
an error talking to FreHD. There are some rough edges here.
To play a video simply select it and press space-bar. Note that trsvid will
show the preview image of a video even if it cannot play it. A “<Not playable
on this TRS-80>” message will be shown if either the video format is
not supported (for example, a .tv3 file on a Model I) or if your FreHD
hard drive emulator does not have the enhanced firmware in which case no
videos will be playable.
While a video is playing you can hold the space-bar to pause the video
until you release the space-bar. Or press “W” (or almost any key but
“W” is mnemonic) to pause the video until you press another key. You
can press the BREAK key at any time to stop video playback. When paused
the video will show a progress bar at the bottom indicating how much of
the video has been played and a “MM:SS” amount played indicator. There’s
currently no way to start in the middle of a video or rewind or fast-forward.
No technical reason why that can’t be done, I just got lazy.
TRS-80 Model I and 3 computers can only output audio through the cassette
port. TRS-80 Model 4P computers only have an internal speaker. Model 4
computers have both an internal speaker (I think all model 4’s do) and a
cassette port. So on the Model 4 it will show a “(S)peaker —> (C)assette”
line showing where audio output goes. You press “S” to change to the
speaker and “C” to change to the cassette port. You cannot do this when
a video is playing or even when a video is paused. Again, pure sloth on
me, the programmer’s part.
trsvid can only handle about 75 entries per directory. Use sub-directories
if, for some amazing reason, you have more video files than that.
trsvid shows a little information about what TRS-80 Model computer you have,
what the video refresh rate is (60 or 50 Hz) and the relative CPU speed
on Model 4 or 4P machines. Not something you really need to know, but good
info for our customer support staff. However, note that only Model 4 machines
with “CPU: fast” can play .tv6 files. Other Model 4’s will be limted to
.tv1 and .tv3 videos.
Since trsvid uses pretty much all the memory and generally takes over the
machine there’s no way to exit back to TRS-DOS or LDOS or whatever DOS.
You’ll just have to reset or power-cycle or trip a circuit-breaker to exit.
The trsvid player uses Einar Saukas’ zx7 compression library. Not on
the video data, mind you, but internally to keep the executable size down.
Most TRS-80 emulators can’t run trsvid because they don’t emulate a FreHD.
Best case is that trsvid would run, print a “sorry, no Frehd” sort of message
and exit back to DOS. By absolutely no coincidence, my trs80gp emulator works.
Here’s what you’ll need:
Extract files and put trs80gp.exe, trsvid.cmd and one or more of the
.tv1, .tv3 or .tv6 files into a directory and then run:
trs80gp -m4p -frehd trsvid.cmd
If you’d like to see how it goes on a TRS-80 Model I then use -m1 instead
of -m4p. Or -m3 to see it as it would be on a Model 3. Though there
isn’t much to it, you may want to read the trsvid manual.
For that matter, couldn’t hurt to look at the
I daresay the emulator does a reasonable job of showing what the real thing
is like. However, the sound quality is worse and the sound pitch will be
off on the Model 4 machines (this is due to incomplete understanding of
video wait state timing). And despite my efforts modern LCD screens are just
not the same as CRTs.
You’ll notice that FreHD emulator inside trs80gp is essentially treating
the current directory as the SD card. Just a word to the wise that while
trsvid can browse up and down directories it is rather limited in the
size of directory it can handle. If you think the directory is truncated
that is not a bug. And if the directory path gets too long it will crash.
And trs80gp won’t re-scan directories so don’t expect files to show up
magically if you add them while it is running.
To actually watch videos on your TRS-80 you’ll need
the enhanced FreHD firmware and special care in copying
video files. But trsvid will run with an unenhanced FreHD or no FreHD
at all. The latter is useful if you want to find out what video formats
your TRS-80 could handle. You’ll still get to browse files and see the
preview images. Think of it like just watching arcade games when you were
a kid and didn’t have a quarter. You’ll need:
If you’re feeling conservative, just download tv1.zip
to get video files that will play on any supported TRS-80. Otherwise you
can run trsvid/cmd on your TRS-80 first to see which formats it supports
and therefore which files you need to download and copy to the SD card.
The zip archives are 30 to 50 MB in size. Generally considered small by
today’s standards but still far from instantaneous downloads.
Get trsvid.cmd onto your emulated FreHD hard drive in whatever way you
usually copy files. Probably the easiest is to copy trsvid.cmd to the
SD card you put into the FreHD and use the import2 utility from within
TRS-DOS or LDOS to get it onto the emulated hard drive.
The video files are to be copied onto the SD card. They do not go onto
the FreHD emulated hard drive.
Then just run trsvid and read the manual if anything
is confusing from there on out.
Oh, boy, I’m glad you’re here. Let me tell you this is what all the cool
kids are doing these days. And I’m afraid there’s a reason it’s so cool — it’s
not going to be easy. The tricky bit is that your FreHD will need to be
ugraded to the enhanced firmware and it can’t be done via the TRS-80
itself. I wish it could but the enhancements required changes to the
bootloader. Here’s what you’ll need:
- A TRS-80 Model I with 48K
- or a TRS-80 Model 3 with 48K
- or a TRS-80 Model 4 with 64K
- A FreHD hard drive emulator
- trsvid itself: trsvid.zip which includes the ehanced FreHD firmware.
- Some way to flash the new firmware to the FreHD’s PIC
- A Windows PC and the contig
- or some special care when writing files to the SD card.
- One or more video files:
Right up front let me tell you that I’m more than willing to help anybody
who tries this. I’m even willing to flash PIC chips for you if that’s what
it takes. My e-mail address is at the bottom of this page.
I think it’s always best to do the hardest and riskiest part of a project
first. So the first thing to do is pull the enhanced FreHD firmware
FreHD_3.00.hex out of the trsvid.zip archive.
Pull the PIC chip (it’s the big one) off your FreHD board and flash the
new firmware on it. Put the PIC chip back and verify that your FreHD
still works. Everything should work the same and vhdutl (ver) will
show it having firmware version 3.00.
If “flashing a PIC chip” is meaningless or scary to you, I empathize. Heck,
if “pulling a PIC chip” is scary then I’m with you on that. I’ve done this
myself (obviously) but my process is essentially non-repeatable. You’d be
better off to mail your chip to me and I’ll flash it (uh, but e-mail me first
before you do so). If you don’t believe me, read this
Next, just import2 or some other method to get trsvid.cmd onto the
emulated FreHD hard drive. Then run it so it will show you what video
file formats (.tv1, .tv3, .tv6) your TRS-80 supports. You’re best to
use the highest numbered format supported. You only need to do this
for Model 4 machines. A Model I can only handle .tv1 and a Model 3
can only handle .tv3. A Model 4 might be able to handle .tv6 or
maybe only .tv1 and .tv3 files.
Now the only trick is to get the video files onto the SD card. The
problem is that for a video file to be playable it must not be fragmented.
That is, it must be written to the SD card as a contiguous series of sectors.
If you’re using Windows then the contig utility will help you out.
Copy a video file to your SD card (say smdm.tv1) and then run contig -a
on it. For instance, contig -a J:smdm.tv1). If it reports the file as
having a single fragment then all is well. Pop it into your FreHD and try
and play it. If not there are a few options. One is to use contig to
degragment the file with contig j:smdm.tv1). That works, but let me tell
you it took a long time when I did that once. Like 15 or 20 minutes. The
other option is to put another ocpy of the file onto the SD card and see
if that copy has only one fragment. If not, try another copy. That sounds
a bit silly but chances are you’ll quickly be writing the file into free
space which hasn’t been fragmented so you’ll get a contiguous set of sectors.
Even though it is slow, having contig defrag the file is better than moving
on to the next method for non-Windows computers.
I presume Linux has some program that does what contig does on Windows and
there’s probably even one for the Mac, but I don’t know what they are.
But if you start with a freshly formatted SD card then every file copy should
be contiguous. So grab an SD card, format it, copy on the files needed
by the FreHD itself and then copy on the video files. That should work,
but there’s no way to be sure. And trsvid itself doesn’t have the capability
of testing the files. All you can do is try to play them. Even if the file
is fragmented it will play fine for a while until the second fragment is hit.
At that point trsvid will be reading random data and most likely will crash.
SD cards have little computers in them for managing the flash memory and
answering sector read/write requests. They may look like a half stick of gum,
but they’re complicated. trsvid uses sector streaming to play videos. This
isn’t a commonly used feature and may not work properly. I’ve only had
one card that I think didn’t work, but keep in mind that using a different
SD card might be the answer if everything else seems in order.
Congratulations if it works. If you want to level up even further, then
try converting your own videos.
What’s in the enhanced FreHD Firmware?
The enhanced FreHD firmware has three new features:
- Minimize wait states on data read.
- FAT32 file open returns both file size and starting sector.
- New command to start and stop sector streaming.
The wait state minimization was what required a new bootloader. A stock
FreHD makes the Z-80 in a Model 4 wait 25 cycles for each data byte. I found
that reduced the raw data rate so much that decent video playback was
simply not viable. I managed to get that down to 3 wait states.
Even with that speedup I couldn’t make ordinary file reading fast enough.
The FreHD (correctly) computes and verifies the CRC for each 512 byte
sector read. The CRC routine can be considerably sped up but even then
it was quite a hit. But having a mode to skip CRC calculation if a file
were opened in unsafe mode was a reasonable workaround. After all, I’d
only be reading files so the worst case was a program crash. It wouldn’t
cause a problem in the file system itself. There were still lengthy
delays whenever the FreHD had to read a new cluster sector to find the
next data sector. In other words, every so often a read would take a
lot longer. Finally, there was a delay every second 256 byte read because
the FreHD has to break 512 byte SD card sectors into 256 byte chunks to
feed to the TRS-80. I tried a number of different schemes to reduce or
hide the overhead but the resulting data throughput was still a lot
lower than I’d like. And the lengthy and somewhat unpredictatable delays
between 256 byte reads would greatly complicate and slow down the video
Fortunately I found the sector streaming command. I think the
intent of it was for video cameras and other special-purpose devices that
needed higher throughput. I suspect it remains largely unused in recent
times as ordinary sector reads will suffice as long as your device has
a decent CPU. In any case it is perfect for trsvid’s needs. All I had
to do was have the file open command return the first sector of the file
and add a command to initiate sector streaming from that sector. As long
as the file was not fragmented everything would work perfectly.
Sector streaming doesn’t give a perfect data stream. After each 512 byte
sector it sends the CRC (which trsvid ignores, naturally) and then it
transmits an undetermined number of “stuff” bytes while the SD card
controller gets the next sector ready. Based on a few cards I tested
the number of stuff bytes is usually only a small amount like 10 or so.
That makes the player surprisingly more complicated but at least the
effective data rate remains high.
Once I decided I wanted FreHD firmware improvements I went down the
road of figuring out how to recompile the firmware (a journey in itself)
and how to flash new firmware on the PIC. My first step was to carefully
pry the PIC chip off the board and put a ZIF socket in there. That makes
it easy to remove and replace the chip on the PIC board because I’d be
doing that frequently. Oh, boy, did I ever.
Before rebuilding the firmware I better make sure I can flash an existing
version. So I did a little research and got some advice from Andrew Quinn.
I heard that something called a PICkit would do the trick. I also read a
lot about how the PICkit 2 was great but Microchip was phasing it out for
the PICkit 3 so it was hard to get them and their software tending toward
not working with the old version. Deciding to save a few bucks I ordered
a PICkit 3 clone from some random eBay seller. It came with a little circuit
board and its own ZIF socket. Just wire the board up to the PICkit, drop
the chip in, plug the PICkit to your PC’s USB port and run the burning software.
Again, various Google searches and embedded programming messages boards didn’t
give me a warm and cozy glow. Most of it were complaints that the old, simple
burning software wasn’t available or didn’t work with the PICkit 3 and that
you had to use Microchip’s fancy new MPLAB X IDE which is one of these
soup-to-nuts things that will compile your C code, assemble your assembler,
edit your files, link it all up and burn what remains to a PIC. Great! But
all I had was a .hex file. Nonetheless it wasn’t too hard to drill through
the IDE and make it happy with a mere .hex file. I also had to tell it exactly
what PIC chip I had. Sounds easy but there are a million different PIC chips
and their names look all the same.
I can’t remmeber exacty what I did next, but let me emphasize very carefully
that it was all my fault. Andrew’s guidance was nothing but sound. It seems
that for reasons no doubt involving electrons and other non-software entities
the PICkit 3 itself needs to be flashed with firmware depending on what PIC
it means to program. The message boards mention this as one of the many faults
of the PICkit 3 over the PICkit 2. I don’t know if I chose poorly, picked
the wrong chip, panicked and pulled a cable too soon or what but after a
failed attempt to flash the PICkit the IDE kept saying that I had no PICkit
attached. Fiddling with mysterious IDE settings and generally pleading did
nothing to resolve this. My PICkit 3 was bricked.
Cursing my stupidity and/or luck, I ordered a somewhat more expensive
but real Microchip brand PICkit 3. It didn’t come with a little board so
the original wasn’t a total loss. And the message boards assured me that
with a tiny bit of soldering my new PICkit 3 could be used to flash the
dead PICkit 3 and bring it back to life. Maybe someday I’ll do that, but
at the time it just sounded like a new and exciting way to brick my new
Fortunately this time around the flash of the PICkit 3 worked. It was ready
to program my chip. I super carefully looked up which of the 5 (of 6) wires
that came out of the PICkit needed to be hooked up to the pins of the chip.
Made all the necessary connections, checked them thrice (at least) and tried
again. Checked the connections several more times. After a while I realized
that I’d wired the PICkit to the wrong row of header pins on the board. Looking
at the board again I can’t quite see what my mistake was, but it meant that
the PICkit was wired to pins on the board that didn’t go to the chip.
Once I got that wiring problem sorted out it worked. Mostly. I got it to
burn once or twice but then it said something like “USB isn’t giving me enough
volts to get the job done.” More Googling and UI poking ensues. While the
recommended power setting for my PIC was 5 volts it seemed that a lower voltage
would work. So I turned the voltage setting in the IDE down to 4.5 V and it
didn’t complain about the power yet still flashed the chip.
And now it works perfectly. And by perfectly I mean sometimes it still
complains about the power but unplugging the USB cable and plugging it back
in will usually clear up that error. And sometimes it complains about how
there’s a short detected so it can’t do anything. That just means I haven’t
used it in a few months and have forgotten which way to put in the chip.
The chip survived! It also survived being put in backwards to the FreHD
and didn’t even kill the FreHD. Who says you have to be careful with hardware?
Anyhow, that’s my process for flashing PIC chips. Give it a try if you
like, but maybe you should find someone who knows what the hell they’re doing.
Awesome as they are, I’m sure you’ll tire of the 5 sample videos I provide.
trsvid includes the utility programs I use to convert video files to its format.
Most of the heavy lifting is done by a generic video processing tool
called ffmpeg. The rest are some fairly
simple C programs to marshal the data into .tv1, .tv3 or .tv6 format.
To do this you’ll need:
If you can compile C programs then I think this is all easily doable
on Mac or Linux. They both will have perl already installed and you’ll
find versions of ffmpeg for them in the same place as shown for the PC.
You’ll just need to compile the C programs from trsvid/convert.
Download and install perl and ffmpeg. The key thing is to have them
set up so that both
the command prompt.
From the trsvid/convert directory (inside trsvid.zip) copy mixtv.exe,
png2strip.exe, strip2txt.exe and tovid.pl so they’re in with vidlist.txt
where you unpacked convert-example.zip
tovid.pl is oriented towards batch style operation. By default it will
convert all the videos listed in a file to all known formats. As a start
I suggest just show what it will do to convert one video to .tv1 format with:
perl tovid.pl vidlist.txt -v drwho4 -f 1 -n
That will spit out a series of commands that will be run. To actually convert
a video just drop the -n flag:
perl tovid.pl vidlist.txt -v drwho4 -f 1
All going well that will leave drwho4.tv1 in the converted directory and
a bunch of temporary files in the tmp directory. I don’t delete the temporary
files as they’re useful for debugging pipeline problems and if you hack
the tovid.pl perl script or run the commands manually you can speed
re-processing of a video by skipping any steps that don’t change.
While you can see if that converted video works by running it on your TRS-80,
I do recommend using the trs80gp emulator which will make
inspecting the output much quicker.
To convert all the videos listed in vidlist.txt to all formats just run:
perl tovid.pl vidlist.txt
tovid.pl isn’t very friendly and doesn’t respond very well when things go
wrong like if ffmpeg decides it really couldn’t convert the file. But for
the most part it is just a wrapper around the commands themselves to
automate the process.
Though it needs to be documented, for now I suggest you look at the vidlist.txt
file to see how it names the temporary and output directories and how it
gives the parameters for each video file. Notice how you can give the title
and even the preview image to use. If no preview image is specified one will
be extracted some number of frames into the video file.
One feature not shown in the example is specifying an alternate audio track.
This is important as the trsvid sound is quite noisy so benefits from a
higher volume. Especially on the Model 4P with its internal speaker that
has no volume control so audio tends to be on the quiet side. The volume:
option will tell tovid.pl to have ffmpeg amplify the video’s audio volume.
Don’t be shy about turning up the volume as the distortion from clipping tends
to get lost in the general audio degredation anyways.
range compression can also be quite helpful. It tends to be referred to
as simple “compression” in audio editing programs, by the way.
Converting a video to trsvid format is conceptually pretty simple. The first
step is to run a general purpose utility such a ffmpeg to convert the .mp4
or whatever format video file into raw data. The video portion is converted
into a series of .png image files, one for each frame and the audio portion
is converted into a raw, unsigned 8 bit per sample audio file. We also rely on
the converter to resample the audio and video to specific sample rates. And the
video frames must be converted to greyscale and downsampled to TRS-80
resolutions. The rates and resolutions vary depending on the target format:
|128 x 48
|128 x 48
|160 x 72
The .png files are fed to png2strip which converts them to a single file
of raw grayscale pixels concatenated together.
The image strip is fed to strip2txt which does spatial and time domain
dithering to convert the grayscale data into monochrome and then outputs
it as TRS-80 graphics characters.
Finally, the raw audio data and strip2txt output are read by mixtv which
produces the final combined data stream. It also fills in the file header
so it has options to set the title and preview image. See video-format.txt
for information on how the trsvid data file header is organized.
Running tovid.pl with the -n flag will show you how ffmpeg is manipulated
into producing the required output. It will also show how my utilities are
used to take that raw data and convert them in to trsvid format files. Note
that the grayscale effect seen in preview images is done as a sort of mini
video conversion of a single image.
One thing that could defintely use improvement is audio/video sync. The
.tv6 format is OK, but .tv1 and .tv3 have very unusual frame rates
and ffmpeg only supports a few decimal places. So video and audio get
out of sync over time.
If you’re generating movies directly through CGI or other means you may want
to avoid the ffmpeg step and produce raw audio and grayscale PNG frames
directly. Or output the strip form of the image data directly. If you’re
generating TRS-80 graphics (say maybe from emulator screen captures) then
going straight to strip2txt output is best.
On the other side of things you may have some better ideas on how to convert
grayscale video into monochrome data. strip2txt does pretty well but is
hardly the last word. trsvid is not doing any clever processing. It merely
intends to display the frames as fast as it is able. A more complicated or
involved grayscale to monochrome process will make no difference to it.
mixtv.cpp is the only existing “documentation” of the low level trsvid
video format. But I do note that at a low level the file data is a series
of interleaved audio and video operations. There might well be some
things that can be done beyond simple video playback.
Most of trsvid can be built using zmac. So you
zmac comes with an executable for Windows but also includes source code
and should easily build for both Mac and Linux. With zmac.exe on your
PATH this command will do it:
zmac --zmac trsvid.z
And you can immediately test it with trs80gp
if you have it:
trs80gp -frehd zout/trsvid.bds
You can also give it trsvid.cmd instead, but using the .bds output
will enable source level debugging.
With only zmac you can modify the user interface and the .tv6 player. The
.tv1 and .tv3 players are generated by a perl script and compressed using
Einar Saukas’ zx7 compressor. To fully build trsvid you need:
From the trsvid download find zx7/src/zx7.exe and make sure it is on your PATH.
Should be easy to compile on Mac or Linux. Do a full build with:
perl mkplay.pl zmac --zmac trsvid.z
If you look at mkplay.pl you’ll see it mostly just runs genplayer.pl with
all the different variations of the .tv1 and .tv3 players, assembles the
resulting assembly file and compresses it with zx7. You can ignore the p4
commands it runs as those are just source code commands that are only needed
if you use Perforce. mkplay.pl also happens to compress the splash screen.
The user interface portion of trsvid is pretty straightforward Z-80 code.
The only really tricky bits are flipping the preview images quickly and
exactly once per frame. The Model I variant runs a loop that executes
in exactly the same number of cycles as a video frame thus it remains in
sync with the video but doesn’t with the relative phase. This is why the black
bars appear because the code has no way to know where they are.
The Model 3 preview displays a single frame, then waits a rough amount of time
to be guaranteed that the next frame is being displayed by the video. Since
video waits are on it can display the next frame and know it won’t show up
too soon. At that point it can wait on the 30 Hz interrupt to keep in
sync with the screen. In short, a simple cheat to maintain 60 Hz sync without
getting too involved. If run trs80gp as below you’ll see red lines indicating
when the Z-80 is accessing video memory. You can see how the video memory
trs80gp -bd -frehd zout/trsvid.bds
The Model 4 can get a 60 Hz (or 50 Hz) video interrupt so it simply draws a
frame quickly and waits for that.
Theory of Operation
While they differ in details, the players for each format are pretty similar.
Their main function is to read graphics data as quickly as possible and
put it on the screen. Nothing but a whole bunch of ini instructions.
There are two complicating factors: audio and inter-sector gaps. The only
reasonable way I found to play digitized audio with the TRS-80’s single bit
sound is to use
or PWM. What you do is read the usual amplitude samples from an audio stream
at some carrier frequency (I use around 15 KHz). Over that 1/15000 of a second
interval you turn the audio on for a percentage of time equal to the sample’s
percentage of maximum amplitude. So for a sample 25% of maximum you turn
the sound on for 1/60000 of a second and then off for the remaining 3/60000
of a second. Due to low-pass filtering (of the hardware? the air? your ears?
I’m not really sure) this ends up sounding like an actual 25% speaker
On a (fast) Model 4 the interval is 256 clock cycles. And I’ve learned the
hard way that if the player is not extremely consistent about that interval
the sound suffers terribly. And if you should happen to skip an interval
per frame you get a horrible and loud 60 Hz buzz. Since the audio only
has to go on and off in the interval there’s quite a bit of idle time.
During that time we read the graphics bytes and display them on screen.
The basic video format for .tv6 is one audio sample byte followed
by 8 graphics bytes. The code reads the audio sample, turns on sound and
then figures out how long it has until sound must turn off again. If the
sample is small then it will just idle for a short period, turn off the
sound and then do 8 ini instructions to display the graphics.
For a bigger sample it might do two graphics bytes, turn off sound and
then the remaining 6.
That’s how it works conceptually. Practically speaking there’s no time
to make decisions. The code supports 64 audio levels and has 64 different
chunks of code all ready to handle each case. To minimize overhead I
use the fastest dispatch mechanism I know:
in h,(c) jp (hl)
With L register always set to 0 then handler code for each audio
level is at $0000, $0100, $0200, $0300, … $3E00, $3F00. It’s a bit awkward
but amazingly workable.
The inter-sector gap makes this more difficult. After the 512 data bytes
of a sector the SD card needs a little time before it can start outputting
the next sector. Try as I might, I couldn’t hide this detail in the FreHD.
So the TRS-80 will see the $FF bytes that occur between sectors until a
$FE byte appears signalling the start of the next sector. Since we cannot
let the audio lapse for even one interval this means we must have some way
to buffer enough audio data to keep things going until the next sector starts.
Thus to our original 64 commands we add $40 through $7F which tell the
player that it must output a sample of $00 through $3F while it is reading
a few more audio bytes to play back when the gap is hit. Well, as you
might suspect, it isn’t buffering literal audio data but another of
a set of commands from $80 through $BF that tell the player to output
an audio sample of $00 through $3F while is is reading data bytes looking
for a $FE indicating the next sector is starting at which point we can
go back to directly executing commands.
The buffered commands have the special command $C0 at the end. If we
don’t see a $FE byte before the buffer runs out then $C0 is a loop that
simply reads until the $FE byte is found and continues on. Yes, that will
cause a glitch in the audio but there’s nothing to be done about it. It’s
just a safety valve in the very uncommon occurence that the SD card is
slow on sending the next sector.
The “waiting for $FE” commands actually work in two states. At first they
continue with L set to 0. But when the $FE is found they load
L with $80. Now the commands are slightly different. We still
must output an audio sample but we don’t want to be pulling in the sector
data. But we will check the buffer pointer so we know when to go back
to reading and executing commands from the SD card.
Of course, there’s a bunch of little details in getting this all to
work smoothly. After the screen has been filled HL' needs to be
reloaded with the start of screen VRAM. The SD card sends a two byte
CRC after the sector data. That problem is solved by having a few bytes
unusued in the audio buffering. mixtv sets those bytes to
whatever value is needed to ensure the CRC does not contain $FE. Thus
the CRC is skipped just like the stuff bytes.
There’s one more code to signal that the file is done. And somewhere in
there we peek at the keyboard so the video can be stopped or paused. And
for no particularly good reason all the codes have 2 added to them. Some
more of the unused audio buffer bytes are filled in with a seconds count
so the pause code can display how far along we are in the video.
The Model 4 has wait states added when writing to video memory. Thus the
timer interval for any commands that write graphics to the screen is
suitably reduced to account for the extra instruction time.
The Model I and 3 operate with a slightly longer interval and only have
time to do 4 bytes per graphics command. Which is OK because they have
about 1/2 the number of bytes to display per screen. They only have
48K of RAM so cannot use commands lower than $40 which limits them to
32 levels of audio. And time is so tight on the Model I that I had to
settle for some slight variation in the interval durations thus adding
more noise to the playback.
I’d hoped to define .tv4 and .tv5 formats that do
full-screen 160 x 72 video on the slower Model 4 computers. The idea
of a .tv2 format for Model II computers is a much more ambitious
goal. With non graphics character set like the others the video encoder
would have to make do with matching ASCII and other characters to video
data. It has been done on other platforms, but I had enough trouble getting
simple graphics data to work that I backed away from that challenge. In
fact, the project itself was stalled for a long time until I figured out
how to convert video frames that wasn’t a total mess.
For that matter I’m sure there’s quite a bit of room to improve encoding
of both the graphics and audio. Maybe the Model I/3/4 should take
advantage of ASCII characters — the video formats allow for it. And I’m
sure there are even better graphics conversion algorithms out there. That
goes double for audio. Some of the TRS-80 digitized speech is so good
despite incredibly low bit-rates. If I could reproduce that in an algorithm
then it could make for a better and simpler player.
Part of the fun and challenge of trsvid is using the stock hardware for
output. Making use of high-res graphics cards would be an interesting
challenge. There’s no way you can update the graphics screen at a decent
frame rate but you could update reasonble subsets. Makes for a lot of
hard work in the video converter. Proper digital audio hardware like
the Orchestra 80 would
vastly improve audio quality. Heck, it would make the player software
almost trivial. Where’s the fun in that?
Perhaps the most tantalizing prospect is using the ethernet capabilities of
M3SE expansion hardware.
Even 10 megabit ethernet has enough bandwidth to feed trsvid. The only
question is whether the expanders can deliver that data quickly to the
TRS-80. Hack up some server software and maybe we could have a YouTube
player for the TRS-80.
George Phillips, March 18, 2017, george -at- 48k.ca