[Z-MACHINE] Statusline printing

8.2.4 in Z-machine standard 1.1 states:

The status line is updated in exactly two circumstances: when a show_status opcode is executed, and just before the keyboard is read by read . (It is not displayed when the game begins.)

However, Infocom’s v3 interpreters for the C64 (at least the old one used for Enchanter and the newer used for Hollywood Hijinx and Ballyhoo) prints the statusline when the game hits the first MORE prompt.

Is this incorrect behaviour on behalf of these interpreters? Were there other Infocom terps for computers with small screens which behaved differently? I believe the C64 terp was based on the code for the Apple II terp, so I would think they act the same, but what about other home computers of the era?

In the CoCo source code mentioned in another thread [1], it looks to me like it updates the status line when a MORE prompt is displayed, with the caveat that I know little to nothing about CoCo assembly language:

        ; ---------------
        ; CARRIAGE RETURN
        ; ---------------

ZCRLF:  INC     LINCNT          ; NEW LINE GOING OUT
        LDA     LINCNT
        CMPA    #13             ; 13 LINES SENT YET?
        BLO     CR1             ; NO, KEEP GOING

        BSR     ZUSL            ; UPDATE STATUS LINE

        LDD     CURSOR          ; GET CURSOR POSITION
        STD     TEMP2           ; AND SAVE IT

        LDX     #MORES          ; "[MORE]"
        LDB     #MOREL
        JSR     DLINE

        CLR     CFLAG           ; NO CURSOR!
        JSR     GETKEY          ; GET A KEYPRESS

[1] Z-machine stack size?

1 Like

Sure looks like the statusline is updated.

(BSR is a regular jump to a subroutine - just like JSR but with relative addressing)

As it turns out, it will make the statusline code a bit more complicated if the statusline is to be printed at a MORE prompt, since the game may be in the middle of printing a string, and maybe even in the middle of printing an abbreviation within a string. The statusline will need to save the state of string printing including abbreviation printing and restore this state afterwards. On a platform where every byte of RAM matters, I would rather not do this.

When we say “update the status line”, it doesn’t mean invoking any Z-code, right? It’s copying the logical contents of the status line to the hardware display.

(Or is this a platform where there’s no “backing store” for the status line because that would be too many bytes?)

It doesn’t involve invoking any Z-code, but it does involve printing the short name of the object held in the first global. Note that this whole issue is only about z1-z3 games.

Just copying the last contents of the status line to the screen again doesn’t do anything, unless the status line has scrolled off the screen. For the C64 platform, I believe this only happens in Infocoms old z3 interpreter. In Infocoms later z3 interpreter, in Ozmoo and in Zeugma, the status line stays on screen at all times.

Also, Infocom’s interpreters update the status line at the first MORE prompt, even if it comes before any of the two circumstances where the status line should be updated according to the specification.

Actually, saving the state of printing would not take up a crazy amount of bytes. It’s just that it’s spread out over a number of different zeropage addresses and non-zeropage addresses. But yeah, we do care about using up 50 or 100 bytes here. The whole Ozmoo terp built for z3 is currently 9919 bytes. Every page that the terp uses is one page less for virtual memory, and with a maddeningly slow diskdrive, that matters.

Are you also low on stack space? Perhaps it’s possible to generalize the code for dealing with abbreviations (where you must already save the state of printing) to be reentrant, i.e. to save the state on the processor stack. Then, if you have to print an object name in the middle of that, you just call the same routine to push the state a second time.

Another trick could be to use the last row of the display buffer (starting at column 7) as temporary storage, since that row only contains “[more]” when this happens. But this approach would probably make the terp larger.

We’re using the first 41 bytes of the processor stack as our display buffer, just trusting that the CPU will never need them (and it has worked this far). I’m not sure how much we want to push onto the stack though. Anyway, it’s more a question of code size, since the state is spread out over different addresses on zero page and some not on zero page. I should first have a look to see if it’s possible to bring them all together.

Our MORE prompt doesn’t generate any text in the display buffer. It puts a flashing asterisk at the bottom right corner of the screen, while the first 39 characters of that row are used for displaying game text. When the MORE prompt is displayed, the display buffer may hold up to 38 characters that should go on the next line, so there’s only three bytes that can be safely used there…

Is this incorrect behaviour on behalf of these interpreters?

I don’t think you could call Infocom’s original interpreters incorrect for not following a standard that didn’t exist at the time. :slight_smile:

The standard has some deviations from Infocom interpreter behavior by necessity since not all of Infocom’s interpreters behaved equally, as you have pointed out.

I can see that updating the status line at a [MORE] prompt might be nice, but is hardly necessary, since it will definitely get updated before the player can enter any input. I’m curious how the early interpreters handled this in code, but I wouldn’t stress over following the behavior that exactly.