13

The Apple I Operation Manual includes a full listing of Steve Wozniak's amazing 256 byte 6502 Hex Monitor, aka Wozmon, as well as some explanation of how to interact with the Apple I hardware. My question is with regards to outputting a character to the display. On page 8, it says:

The sequences listed below are the routines used to read the keyboard or output to the display (the text uses an arrow to indicate the BPL will branch to the prior LDA).

Read key from KBD:

  LDA KBD CR (D0111)
⤤ BPL
  LDA KBD DATA (D010)

Output to Display:

  BIT DSP (D012)
⤤ BPL
  STA DSP (D012)

And later:

DSP DATA D012

Lower seven bits are data output, high order bit is "display ready" input (1 equals ready, 0 equals busy)

So the output logic is: use BIT to check bit 7 of the value in the Display Data address (This is the PIA's PB7 line), and if that bit is 0 (BPL branches when flag N is not set), go back and read it again. Stay in this loop until the display is ready (bit 7 of DSP Data is 1, so BIT sets N to 1, and BPL does not branch), the proceed to push the byte to the DSP Data address.

So far so good. However, at the top of page 7, the Wozmon listing includes this:

FFEF 2C 12 D0    ECHO      BIT DSP        DA bit (B7) cleared yet?
FFF2 30 FB                 BMI ECHO       No, wait for display
FFF4 8D 12 D0              STA DSP        Output character.  Sets DA.

This seems to follow the explanation from page 8, except that it uses BMI (branch when N is set) instead of BPL (branch when N is NOT set), and the comment even indicates that it is waiting for bit 7 of DSP Data to be cleared, not set.

By comparison, the Wozmon code to read a character from the keyboard from Page 5 matches the description above:

FF29 AD 11 D0    NEXTCHAR  LDA KBD_CR     Key Ready?
FF2C 10 FB                 BPL NEXTCHAR   Loop until ready
FF2E AD 10 D0              LDA KBD        Load character. B7 should be '1'.

Here, Wozmon uses BPL just as the explanation says.

As San Bergmans notes in his excellent explanation of Wozmon,

Only upper case ASCII characters are accepted. Lower case characters are not recognized and are considered an error. Also bit b7 of every ASCII character is always set, whereas officially it should be cleared.

It would seem that Woz was using b7 as a flag, outputting it high and waiting for the display hardware to clear the flag, indicating that the next character could be output. This makes me think that the Wozmon listing must be correct, and the description of the output logic and DSP Data address must be incorrect, but I have not been able to find confirmation of this.

3
  • 2
    I don't know the Apple hardware particularly well, but I do know Woz's code, and I'd trust that over descriptive documentation. ;) Have you tried this code in an emulator (or even on hardware if you're lucky enough to own it)? Commented Jun 30, 2023 at 15:18
  • 4
    I'm currently writing my own emulator, which is how I found this issue. I agree that the code must be right, but I was surprised to find no other description online of the issue, and my 6502 (and Apple 1) experience is still limited, so I thought it would be worth asking here. Looking at another emulator is a good idea though. Commented Jun 30, 2023 at 16:11
  • 4
    The use of BPL in the "Output to Display:" quote, certainly looks like either: a copy/paste (or, given that copy and paste didn't exist back then, code duplication) error, or; (more likely) it was written upon the incorrect false premise stated under the definition of DSP (i.e. the logic is inverted). It is surprising that no one seems to have seen this before, or if they have, then it really doesn't seem to be mentioned, or documented, anywhere. After Googling many many variations of "Apple I Operation Manual errata/error", I couldn't find anything. Nice catch..! Commented Jun 30, 2023 at 21:29

1 Answer 1

6

Partial answer:

If you look at the schematics, both on page 7 and the very last page, you'll see that the PIA actual gets a pair of signals for the display, /RDA via a one-shot trigger to CB1 as an input, and CB2 as an output negated to DA. The latter is also looped back to PB7. The value $A7 in the DSP CR display control register sets up the PIA to generate a pulse whenever the DSP register is read by the CPU.

On the second last page, you can see that DA is looped back to /RDA via a 74174 D-Flip-Flip C7, which has MEM0 as a clock.

My interpretation of this is that originally the handshake with the display was intended to work in the same way as for the keyboard: /RDA would set bit 7 in the control register, so just like the keyboard loop

LOOP:   BIT KBD_CR
        BPL LOOP
        LDA KBD

the display loop would have been

LOOP:   BIT DSP_CR
        BPL LOOP
        STA DSP

waiting on the /RDA signal to be set in C7 after the MEM0 pulse.

However, for whatever reason, that then got changed: Instead of reading the control register /RDA signal, they found that it is sufficient (and maybe faster?) or necessary (because something else did not work?) to just wait on the triggered pulse of the PIA. So they corrected the code in the main text to use DSP instead of DSP_CR

LOOP:   BIT DSP
        BPL LOOP
        STA DSP

but forgot to change the BPL to BMI. Which they did do in the actual ROM code.

At least that's my reading. If someone has the Apple I hardware (or a re-creation), maybe they can check the signals and verify.

And if your intent is to write a faithful emulator, I guess you'll have to include PIA emulation including the /RDA signal, in case there is some Apple I program that uses that directly.

1
  • 1
    Excellent answer, that seems quite likely. Accepted. And there are a couple of other places where the code comments don't quite match the code, which I'll record in a separate answer, once Ben Eater releases his Wozmon video that documents one of them (available on Patreon now, on YouTube in a week). Commented Jul 2, 2023 at 22:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .