Retrochallenge: The last few details of Hac-ManPosted: July 30, 2012
There are just a few details left to explain. When I first thought of recreating my old BASIC game, I’d planned to have some bells and whistles like a high-score screen and an attract mode like in a real arcade game.
Very late in development, I ran out of time and memory to include all this in one executable, and I wasn’t sure if I would have a complete game for the contest.
Fortunately, fate went in the other direction; Hac-Man will have a front end with animation, a help screen and high scores. It will also have the “halftime show” that was in the original game—and in my original clone.
RSTS/E BASIC, like most BASICS, has a mechanism for starting other programs from within a program: The CHAIN statement.
23050 IF NOT DEBUG% THEN CHAIN "HACMAN.BAC" 9000
This code, if I’m not debugging will call HACMAN.BAC and start it at line 9000. The .BAC extension indicates a compiled program; CHAIN will fall back to the uncompiled program if the compiled program isn’t found, so it’s recommended practice to always specify .BAC.
(The DEBUG% variable is not part of RSTS/E BASIC, but is my own convention I’ve used for debugging in all my code.)
OK, but how do we pass information from one program to another. This line of code is run in the Hac-Man game engine when the player loses the game. The program should then pass the score back to the front end so it can be included in the high score list if possible.
RSTS/E has a feature it calls “core common”. This is a 128-byte area that the operating system keeps for each job, and it is shared amongst all the processes in each job. The RSTS/E command processor uses core common to pass parameters to system programs from the command line.
23010 GM$="HACMAN"+CVTF$(SCORE)+SPACE$(12-LEN(CVTF$(0)))+CVT%$(LEV%)+CVT%$(PLAY%) 23020 XX$=SYS(CHR$(8%))
We construct a string to pass back to our front end. The first characters of the string are “HACMAN”, our magic signature that the other program uses to verify that it’s valid.
Next, the function CVTF$(SCORE) adds the score as a binary string. Some explanation: In RSTS/E, BASIC can use either 2-word floating point or 4-word floating point values, determined at system generation. I generated my own RSTS/E system but I don’t remember which option I selected. (And in the era of emulation, there’s no saying I could not generate a system with 4-word FP.)
The string fragment SPACES$(12-LEN(CVTF$(0 ))) accounts for this possibility; it pads the string with spaces for the next two values.
CVT%$(LEV%) and CVT%(PLAY%) convert these integers to binary; integers are always 2 bytes so this is straightforward.
Here is the corresponding code on the front end:
8500 GM$=SYS(CHR$(7%)) ! Get string from core common 8509 !Validate string 8510 IF LEFT(GM$,6)<>"HACMAN" GOTO 1000 ! If no score passed, resume attract loop 8520 SCORE=CVT$F(MID(GM$,7,LEN(CVTF$(0)))) 8530 LEV%=CVT$%(MID(GM$,12,2))
This code is called from the Hac-Man game engine at game over. Line 8500 retrieves the string from core common. Line 8510 checks for a “HACMAN” signature that indicates a valid code. Line 8520 retrieves the score, and 8530 retrieves the ending level.
One last aside, this on memory: I had forgotten how little memory I had on RSTS. The memory in the BASIC interpreter, and the memory in my TECO screen editor more or less tracked together. The biggest program I could get in both the editor, and BASIC was about 19,000 bytes, just less than 20K.
That included white space. It isn’t free here, and that will surprise a lot of modern developers.
Several times, I had to back out of programming changes and refactor my code. Hac-Man likely represents the most complex programming in RSTS/E. In 1981, I was complimented on my work by a DEC field service engineer (“Wow, is that Pac-Man!?”) who told us that was the most ingenious program he had ever seen.
It is as good as I can possibly get it.
Next: Closing words, and a video.