Close

The 592x384 display

A project log for Running code on the HP 1653B Logic Analyzer

I ported a falling blocks game to my logic analyzer.

alexander-r-prussAlexander R Pruss 02/28/2026 at 18:350 Comments

Early disassembly of the self-test, together with the MAME 16500 emulation code, revealed that the screen is 592x384 and the memory is at 0x600000. But writing to the memory is tricky. There is a screen memory control register at 0x201000. Writing certain "magic" values (discovered by disassembly) to the screen memory control register (e.g., 0xE00) allow one to draw a black pixel and other values (e.g., 0xF00) allow one to draw a white pixel. Specifically, to write a pixel--regardless of color--you write a one to the right bit in screen memory. Zeroes are completely ignored.

The pixels are stored in the low nibble of each word of logical memory, with the high bit of the nibble being the left-most byte. The rest of the memory map is straightfoward. Each scanline is 592/4=148 words long, and they are stored in sequence from top to bottom, with no padding.

This was enough information for me to make my Wiztris port.

But the mysteries were not finished. I tried very hard, with lots of test code, to figure out how the screen memory control register worked. I also found some strange things. Sometimes I was able to draw a pixel with two different screen modes. The pixel looked the same, but behaved differently when I wrote to it in a different mode. This was very puzzling--it was as if the system remembered how I wrote the pixel. But at the same time the service manual clearly stated that there was 64K of 4bit memory for the display, which was only slightly more than 4 bits per pixel times 592 times 384, so there was no way for the system to remember the mode in which I wrote the pixel, or so I thought.

This was very frustrating. Finally, I did some reproducible experiments and wrote up a detailed stackexchange query about the mystery. But before posting, I decided to ask the query of Gemini Pro. I never some Gemini work this long--it felt like 5-10 minutes--but then it came up with something I hadn't thought of. It concluded that the display had two bitplanes, which were XOR'ed together to produce the output. One of the bitplanes was for data and the other for an attribute, used for inverted video cursors. This would, of course, require twice as much screen memory as the service manual seemed to say. Gemini's explanation was that the service manual was only stating the capacity of each video RAM chip, and there was more than one. 

This explanation made sense, and I was able to identify screen display modes that fit with the hypotheses. Indeed, it was possible to write separately to a data plane and an attribute plane. Both writes go to the same 68000 logical address, but the screen memory control register selects which plane they go to. 

I did some more experimentation, but I was still getting results that didn't fit with the two-plane hypothesis. Finally, I guessed that maybe there are more than two bitplanes (the 16500 units, which have color displays, have four). With some experimentation, I was able to confirm the hypothesis. There are four bitplanes, which one can label:

There is a complicated function that combines these to the final display. One nice feature of this function is that if you keep attribute at 0, and set overlay to 1, then the screen shows overlay-data instead of data. This allows for pop-up windows without having to save what's in the background: one just draws the pop-up in overlay mode. I haven't checked empirically, but this has got to be how the system software does its display.

The memory control register works as follows. It is a binary word of the form:

The four low bits of the low byte (dcba) control which planes are active for a write, with a clear bit indicating an active plane. Thus, 0000zyxw00001111 results in no-functionality, while 0000zyxw00000000 writes to all four planes at once. The four low bits of the upper byte (zyxw) control what value is written when the 68000 writes a 1 to a logical memory bit. These are reversed: if the value bit in the control register is 1, a 0 is written, and if it's a 0, a 1 is written.

almost had everything. But not quite! One day I turned up the adjustment pot in the back of the scope for the screen brightness. And then to my surprise I saw that while I had previously thought there were two screen colors--black and white--there is actually a third, namely gray. (If I had read all of the service manual, I would have seen on page 6C-13 that the display connector had both a half-bright and a full-bright pin.) So I had to experiment again and revise what I thought was the function combining the four bitplanes into a single screen pixel. Here is the final function, since then double-checked by finding in the ROM where it's loaded as a screen palette:

0000: 0
0001: 1 
0010: 0.5 
0011: 0.5 
0100: 0
0101: 0
0110: 1
0111: 1
1000: 1
1001: 0
1010: 0
1011: 0
1100: 1
1101: 1
1110: 0
1111: 0 

 The planes, left-to-right, are: attribute, overlay-data, overlay, data. The outputs are 0 (black), 0.5 (gray) and 1 (white). (In the actual palette registers, these are written as 0, 1 and 2. Sadly, there is only one shade of gray.)

Discussions