Wednesday, 20 May 2020

Apple /// Horses Demo

The most widely known demo for the Apple /// is the 'Running Horses' demo. The Horses demo is one of a suite of demos included on the 'Apple3 System Demonstration' disk. Here is a screenshot of it running in MAME:
 

You can grab the original demo disk image from here: Apple3SystemDemo

And you can run it here on the Internet Archive: Apple_3_Systems_Demonstration_Disk
(You'll need to be patient, the horses part is after all the graphs)
 

This was written by Andy Hertzfeld, and used the downloadable fonts of the Apple /// to help do the heavy lifting. The main code is contained in an 'invokable module' that can be loaded in with Business Basic and called by Basic programs. I have been interested to see how it was done, so decided to dig into the demo and see what makes it tick. Lets see what we find.


The first part was to look into the basic program side of the demo. The Invokable module is loaded in by the 'HELLO' Basic program which contains this line:
  95   INVOKE "bgraf.inv","Horses.inv"

This tells Business basic to load these files from disk into memory, relocate the code, and setup the entry points for each of the procedures/functions included in each of them. The "Horses.inv" is the one that includes the main code for the demo.

Next, the actual basic code that creates and runs the demo, is included in the 'SHOW' file:

  9000   REM ---  Now run the horse race! ---   
  9005   PRINT CHR$(16);CHR$(1);
  9010   PERFORM hinit
  9020   PRINT CHR$(15);
  9030   FOR a=1 TO 20
  9050     FOR i=0 TO 4
  9070       PERFORM hframe(%i)
  9090       NEXT i
  9110     NEXT a
  9120   FOR lap=1 TO 40
  9125     secs=.007*(20-lap)+.01
  9130     FOR i=0 TO 4
  9150       PERFORM hframe(%i)
  9170       PERFORM hscroll
  9190       IF secs>0 THEN GOSUB 350
  9210       NEXT i
  9250     NEXT lap
  10000   TEXT:HOME

 
The line 'PRINT CHR$(16);CHR$(1);' is the .CONSOLE drivers code for setting the display mode to 40x24 color. This is a 40 column text mode that each character can have its foreground and background colors set from any of 16 colors.

Next we need to look into the 'Horses.inv' module. This must have the code for the three functions, hinit, hframe and hscroll that the basic program uses. The first thing I did was to extract the horses.inv file from the demo disk and have a look with a hex editor. This led to an interesting find, there was some text in there that looked like the initial part of the source code:



Here it is taken out, looks like the source code has the date of 9/4/1980 on it, so just over 40 years ago!!

     .PAGE
 ;
 ;-----------------------------------------------------------------------
 ;
 ;    "Horse Demo"  Invokable Module for Business Basic
 ;
 ;           by Andy Hertzfeld  09/04/80
 ;
 ;----------------------------------------------------------------------
 ;
     .PROC   HINIT
 ;
 ; First get the device number of the console
 ;
     BRK
     .BYTE   084             ;GETDEVNUM SOS call
     .WORD   DEVBLOCK
 ;
     LDA     CDEVNUM
     STA     WDEVNUM         ;Update the device number
 ;


Next step was to disassemble the code. This proved somewhat difficult as the modules are assembled into a Pascal PCD file which also includes relocation and linker info. I tried to decode that, but will need some more work before I understand that fully. I ended up extracting the code block and disassembling with SourceGen (That Fantastic Disassembler from Andy McFadden). Using that as a start, I was able to trap it in Mame and then dump it from memory after it had been relocated and loaded by BusinessBasic. After quite a bit more work, I was able to take the reconstructed source, assemble it with the A3 Pascal assembler, and successfully use it to run the demo!


Here is a summary of the functions included the Horses.inv invokable module.

HINIT
Loads the text screen memory with the grid of character codes for the horses and loads the colorful foreground/background colors. Each horse consists of 8 characters wide x 4 lines. Codes 00 - 31 are used with the high bit set, so $80 to $9F.

HFRAME(frame)
Takes the frame number as input and then downloads updated font data based on this. Frame=0 is the only frame with all 32 characters included and is the first frame set. The others only update the required characters that change for each animation frame. See pictures below for each frame (8 x 4).
This uses a SOS Device Control call to the .CONSOLE device to load up to eight characters font data at a time.









HSCROLL
Moves the text screen bytes across one character with wrap around. Steps through each line from 1 to 24.



Now we have the source code rebuilt and preserved for this classic Apple /// demo. I have tried to add enough comments to understand the code. Let me know if you have any feedback.


You can grab the disassembled source code from github here:
https://github.com/robjustice/Apple3/tree/master/horses

There is also a bootable disk image on there with the source code included, the assembled invokable module, and the basic program to run the Horses demo. Boot it up, and then type 'run horsedemo'

Enjoy!