The C64 status bar challenge


Clicca qui per la versione italiana. ;-)

When I chose to make an interactive fiction game, I knew I wanted a nice status bar at the top of the screen. Easy peasy? Nah. I needed a "logical window", i.e. a zone of the screen you can update, without interfering with everything else outside that zone. Think of logical windows as your average Windows/Mac/Linux windows, minus frames and borders.  ;-)


Now, my SKU was the C64 and I was using XC-Basic, that relies on the original Commodore Kernal. Turns out that Kernal doesn't feature logical windows, which I created with QuickBasic (Dos) or QB64 (Windows) via the "VIEW / VIEW PRINT" commands. The status bar routine in the Amiga port was even easier, because the Amos language offers a multi-tasking "Window" statement, issued after a specific "Wind Open" command. 

But what about the poor C64? Zork's first C64 version features a rough disappearing status bar, displaying locations and score: when the text scrolls up, the status bar vanishes from sight. When the scrolling stops, the updated status bar reappears. That's pretty functional and I could replicate that easily by plotting the text in a precise location of the screen, but I didn't like to see the status bar pushed out of the screen area. Did I have other options, considering I didn't know any Assembly and I was working in BASIC?

My first attempt was based on an XC-Basic 2.3 extension: I activated a raster interrupt to split the screen. I put the status bar in one 1Kb screen memory area,  and I used another Kb to allocate the gameplay text screen. The result looked clumsy to me, and getting a precise raster screen split isn't easy. Moreover, I use colored text in my game, so the colors in the raster status bar clashed with the colors in the scrolling text (C64 has a single Color RAM for all the screens, so you'd need Assembly to update colors by frame: that was outside my league). 

Just when I was about to give up, I stumbled across an "unscrollable lines" BASICV2 routine, published on Compute Gazette #74. That article looked like the real deal, but... what did it do? I was a newbie programmer and I couldn't make head or tail of those lines: a bunch of "DATA" commands contained a machine code routine! Ouch. I had to understand that, in order to translate the code to XC-Basic.
I converted DATA numbers to hexadecimal values, and I ran these values in an online 6502 disassembler: I got an Assembly version of my craved routine, and I learnt a bit of essential Assembly to understand what it did. :-)


Sean Ganess' "unscrollable lines" routine copies Kernal and Basic ROMS in the underlying RAM, then it banks them out. The point of this process is poking ONE SINGLE BYTE in the "scroll-up" Kernal routine (which would normally be inaccessible in ROM). The original "FF" value is swapped with a "1", so when the routine makes the text scroll up, it's tricked into believing the screen is ending two rows before the real top border. So, this Kernal line

E8F6-E8F7    A2 FF    LDX #$FF

becomes

E8F6-E8F7    A2 01   LDX #$01

Once I understood what Ganess' routine did, I modified the code to copy just the Kernal, because BASICV2 ROM is automatically banked out by the XC-Basic compiler. The downside of this method is that letting VIC-II use the 8KB RAM space "under" the Kernal becomes risky, because it's now occupied by the Kernal itself. I was forced to swap my custom fonts and the credits tilesets in the same 2Kb of user RAM space, and the disk access increased during boot and intro.

After each player's input, my Pacuvia C64 code stores the current cursor position, then sends the cursor to update the status bar. When the update is complete, the cursor is restored in the position it held before ENTER was pressed. By the way, that's the same cursor behaviour I programmed for DOS and Windows versions. The Amiga multi-tasking environment is different: I just needed to specify which window any following command was addressing, and Amos automatically jumped from window to window!

Was this worth all the time I spent on it? Maybe. Finding a solution was a great learning process, and I understood several core concepts regarding memory, ROMs and Assembly. The irony is that not all the players enjoy the status bar up there! Pacuvia's Tandy Model 100 version simply displays the status before each players' input, and I bet someone would've liked that solution in all the other versions!


THE PUNCHLINE
The funny thing is that Commodore introduced commands to create logical windows in their next TED series of home computers (C16 / Plus-4 / C116), through a combination of keystrokes. Commodore 128 even featured a BASICV7 command "WINDOW" to do the same thing! If only my "sentimental research project" allowed me to code on the machines I've never owned or used!
But, you know... rules are rules.
:-D

Get The Daring Rescue of Pacuvia the Sheep

Comments

Log in with itch.io to leave a comment.

Thank you so much for taking the time to write this article twice (English and Italian)and then making the effort to get it out of moderation-lock :)
It was an interesting read, it shows how really deep you went in the machine internals to reach your goal (including learning a bit of Assembly!).
That's very honourable of you, especially considering that the C64 wasn't the only machine you were developing for!

The solution you ended up using could be overkill, and also limiting since you're sacrificing quite a bit of RAM just for the purpose. There's another trick (that I haven't tested yet, alas) in one of the old C64 books, "Mastering Machine Code on your Commodore 64", that involves modifying a 1D table kept in lower RAM and used by the KERNAL; it's still about modifying one byte in there, but without having to copy anything from ROM.
In that case, it explains how to scroll one line down but, as far as I understand it, it should be even easier to scroll up.
Since the book has been recently republished, it's a bit hard to find: here's the italian translation of it, the trick is described on the right page towards the bottom.
The original English book can still be found on commodore.bombjack.org, under C64/Books.

If you're curious, I can update you once I manage to test & understand that trick myself (as I'm going to need it for my next project, wink wink, nudge nudge :)

Thanks, JJ! I'll study the trick you mentioned, although I'm not sure about what I'll work on in the future. But the curiosity will always be there. :-D
Yeah, both the raster split and this method are memory hungry (albeit in a different way).