Beamhacking: Loose Ends

In this series I've covered a useful subset of
specifics on the TRS-80 Model 3 and its graphics. Many things were
left until the end because either they weren't directly relevant
or, more importantly, not fully understood. Now let's speak of a few other
things that are known and look at what mysteries remain.

Alternate Characters

The Model 3 can switch between two different character sets of 64 characters
in the 192 to 255 range. Turns out you can switch between them without any
side effects. Timed carefully, all the characters can be shown on screen at
once:

Interlacing

Careful programming gives us 192 pixels vertically
rather than the nominal 48. That's because there really are
192 scan lines with 4 of them required to make
a single large pixel. Now, back then it was quite common for displays to be
interlaced. Could there be 384 vertical lines of resolution up
for grabs?

Is the monitor built in to the Model 3 interlaced? No,
it is not. The Model 1 monitor is based on a TV. Is it interlaced?
No, it is not. What if you hook it to a TV? Not on the ones I tried.

However...

When I plugged my Model 1 into a video capture card it captured the video
in an interlaced fashion. Hooked up in that fashion
I got a whopping 384 lines of vertical resolution. Way cool, but to me
it doesn't count unless it can be shown on an ordinary TV. Ideally one that
was plausibly available when Model 3's were in their heyday. Here's
a still from my video capture.

The top and bottom lines are the program's two attempts at a smooth line as
there's no way to determine even and odd fields. The one at the top came out wrong
in this case and the bottom one is nice and smooth at 384. The middle line is the
same slope but doesn't switch between fields and only has 192 line resolution.
The second HELLO at the bottom is display every second frame thus it is faint
and does look as if only every second line is displayed — furthur
confirmation that interlacing is in effect.

Double-wide Mode

Yes, all the characters can be made twice as wide. Counter-productive if you're
trying to increase the effective resolution but the mode has its uses.
Why

when you really want to

Besides, is there anything cooler than switching video modes part way down the
screen? Imagine having part of the screen a graphics display with maybe a
double wide scrolling message at the bottom. Easy stuff with all the syncing
and timing routines at my disposal. I gave it a whirl and things got weird.

Worked great except when it switched into 32 character mode the graphics were
shifted a bit to the right. At least it drifted back into position after a
couple rows. Going back into 64 character mode caused a shift to the left.
Some of the characters were shifted so far left they got drawn before the beam
had a chance to get back to the start of the line. That gives you the overlapping,
curved lines in the bottom left.

And that was one of the more successful tests. Even worse distortions happened
depending on when the switch was made. And if the switch happened too quickly
the display became entirely scrambled making me fear for the life of the machine's
analog hardware. Other times the program would go out of sync with the beam as
the video decided to skip a few cycles and draw the display a bit quicker.

It was one of the first beam synchronization effects I tried.
I decided to back away slowly and return to simpler things. Later on when
I got the best possible synchronization worked
out it seemed like a good time to verify the emulator's results in double
wide mode. A demo would surely follow. Instead, things got even stranger.

My reaction: HUH?!?! Now, this didn't happen every time. But often
when I switched into double wide mode before running my synchronization
test pattern the display would look corrupt. That should have been a
line of "0123456789" repeating which a few "1", "2", "3" markers helping
denote the 10's places. Instead only the first "1" in the lower row
made it out and the rest of the line filled up starting from character
0xF3 on up. On top of that, the display apparently started to use
fewer cycles per screen. Here's the loop that tried to put up the numbers.

There is a simple explanation for what happened here. Look what we get if
the first byte of the "ld (ix),a" instruction has a bit flipped
and changes from 0xDD to 0x9D. The 0x9D is a single byte instruction
"sbc a,l". The rest of the 3 byte "ld (ix),a"
would be another couple instructions. In all, the following sequence would
replace it.

nocarry:
sbc a,l
ld (hl),a
nop

The loop draws '0' through '9' are as expected (remember that only the even
digits are visible). Then we hit
"ld (ix+64),c" which draws the '1' on the second row.
However, for unknown reasons this write to video memory causes a bus
conflict. At this point the "ld (ix),a" instruction is corrupted as
described above. Due to earlier code, HL is loaded with 0x3C3F. Since
the carry is clear at this point the "sbc a,l" changes A from 0x30
to 0xF1 because 0x30 - 0x3F is 0xF1. And we don't write the '0' out
as was planned which is why the white block remains where the '0' was meant to be.

The "ld (hl),a" stores A on screen but the address of HL is odd
and the result is not visible. Afterwards the loop continues on writing the
values we see from 0xF3 on up. It never again writes to the second row because
A register will not equal 0x3A.

The theory fits the facts so well it must be correct. But why did that one
instruction get corrupted? Beats me, but it is not unreasonable to suspect
a problem as the previous instruction did access video memory and the fault
is related to being in a different video mode. There's never a problem in
normal, single-wide mode. I also did a few attempts to drop into BASIC
and gather more information. But I ran into machine lockups which points
in the direction of similar instruction zappings going on.

Those lockups have held back investigation. Given the odd things happening
I was starting to worry about damaging the hardware. I want to make my
Model 3 do cool things, not kill it! There are some ideas to follow
up on here what with trying to get the fault to happen consistently and
changing things a bit to prove the instruction corruption theory. One has
to wonder why these problems don't happen on the TRS-80 more often. My
program is writing to odd video addresses in double-wide mode which is not
something normal programs would do. Or perhaps the fact that double-wide
mode was practically never used is explanation enough.
At any rate the mystery remains unsolved. But as soon as it is you can bet I'll
get the emulator to operate the same way.

For the record, the story is a little better on the Model 1. It did not
exhibit any of the screen skewing when switching between video modes. But there
was some kind of timing variance that I didn't figure out how to make happen
programattically. Using a program that let you switch modes based on key
presses I could thrash a bit and get into a mode where the apparent number of
cycles per screen dropped by one. After that point there was a known procedure
to get it back into a stable configuration and it flipped easily between the
synced and "slipping" versions. In short, less weird but still weird.

The oddities with double-wide mode may seem a bit strange. They're not such
a surprise when you look closer at the video hardware. Double-wide mode
isn't something tacked on to the end which doubles the size of each character.
Instead it halves the driving video clock frequency which makes everything
stretch. And then doubles the frequency again at a few key points to have
it skip every second character and make sure the end of line and end of screen
signals go off at the right time. In other words, it's entirely reasonable
to expect the screen timing to go off for a bit when switching modes.

The End?

No way! I will get my emulator to support all the weird things that can
happen on the Model 3. And surely there will be more graphics demos.
And I'd love to see others join this mad game. Please contact me at the
e-mail address below if you're at all interested, would like to hear more
or would like to try a few things like this yourself. All you need is
right here:

An emulator to try out code. Necessary
if you don't have a real TRS-80, still very helpful if you do.