(28S) Space Chase game

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (https://www.hpmuseum.org/forum/forum-10.html)
+--- Forum: General Software Library (https://www.hpmuseum.org/forum/forum-13.html)
+--- Thread: (28S) Space Chase game (/thread-25430.html)



(28S) Space Chase game - mmorrison - 2026-09-10 08:22

A three-ship dodging game for the HP-28S, written in 1989 at Tennessee Tech by Randy Weems, Shawn Yeager and me, for an algorithm design course taught by John Selden. The listing below is the version Selden published in 1990:

Selden, J., Selden, A., Morrison, M., Weems, R. & Yeager, S. "The HP-28S, Calculus, and Programming." Proc. 2nd Annual Ohio State University Conference on Technology in Collegiate Mathematics, Addison-Wesley (1990), pp. 285-286.

Two ships move at random across the 137x32 display over a thirty-pixel starfield. The third is yours. The game ends the moment they touch. Score is time survived in tenths of a second, and there is a hyperspace jump good for three uses.

The whole design is one idea. The display is 548 bytes and ->LCD takes a plain character string, so the screen is a string. Each ship is a 548-byte string with the sprite in it, and moving a ship rotates that string: UP by 137 bytes, one page exactly, LEFT and RIGHT by six. Compositing the frame is OR. Collision is XOR against what should be there, so there is no collision routine in the program at all. Input is one line, IF KEY THEN STR-> END, because KEY returns the name of the key you pressed and the six control programs are named for the keys they serve.

TO RUN Key in all ten programs. Run SETUP once. It builds SHIP1, SHIP2, SHIP3, the starfield in BACK, and the high score in HI. Then run SPACE.

Cursor keys steer. SHIFT is hyperspace, three uses per game. HISCR recalls the high-score screen.

REQUIRES An HP-28S. Four 548-byte strings live in memory, so the 28C's two kilobytes will not do it.

@ SPACE CHASE as published, 1990. @ Selden, J., Selden, A., Morrison, M., Weems, R. & Yeager, S. @ "The HP-28S, Calculus, and Programming." @ Proc. 2nd Annual Ohio State University Conference on Technology in @ Collegiate Mathematics, Addison-Wesley (1990), pp. 285-286. @ Transcribed from the printed paper. Note MAKE is named L→LCD here.

SETUP « { 255 24 24 36 102 90 90 102 36 24 24 255 } 137 L→LCD 'SHIP1' STO { 64 97 250 228 228 228 228 228 250 97 64 } 200 L→LCD 'SHIP2' STO { 16 24 24 30 57 57 63 57 57 30 24 24 16 } 261 L→LCD 'SHIP3' STO CLLCD { (0,0) (136,31) X 1 (0,0) } 'PPAR' STO 1 30 START RAND 137 * FLOOR RAND 32 * FLOOR R→C PIXEL NEXT 'PPAR' PURGE LCD→ 'BACK' STO { 0 "" } 'HI' STO »

L→LCD « 0 CHR 1 9 START DUP + NEXT 1 ROT SUB SWAP LIST→ "" 1 ROT START SWAP CHR + NEXT + CLLCD →LCD LCD→ »

SPACE « # 11CAh SYSEVAL 0 SHIP2 SHIP1 SHIP3 WHILE 3 DUPN OR DUP2 OR DUP BACK OR →LCD XOR == REPEAT { UP DOWN LEFT RIGHT LEFT } RAND 5 * CEIL GET EVAL ROT IF KEY THEN STR→ IF DUP TYPE 2 ≠ THEN DROP END END 512 .01 BEEP ROT { UP DOWN LEFT RIGHT RIGHT } RAND 5 * CEIL GET EVAL ROT END 1 4 START LCD→ NOT →LCD NEXT 4 DROPN 50 1 BEEP WHILE KEY REPEAT DROP END # 11CAh SYSEVAL SWAP - B→R 819.2 / IP DUP LCD→ CLLCD SWAP 4 DISP LCD→ OR →LCD IF DUP HI 1 GET ≥ THEN LCD→ 2 →LIST 'HI' STO ELSE DROP END »

HISCR « HI 2 GET →LCD »

UP « DUP 138 548 SUB SWAP 1 137 SUB + »

DOWN « DUP 412 548 SUB SWAP 1 411 SUB + »

RIGHT « DUP 543 548 SUB SWAP 1 542 SUB + »

LEFT « DUP 7 548 SUB SWAP 1 6 SUB + »

SHIFT « 4 ROLL 1 + DUP 5 ROLLD IF 3 ≤ THEN DUP RAND 547 * SWAP OVER CEIL 548 SUB 3 ROLLD 1 SWAP FLOOR SUB + 512 1500 FOR x x .015 BEEP 50 STEP END »

INS « # 11CAh SYSEVAL DEPTH → d « DGTIZ WHILE DEPTH d ≠ REPEAT DROP END # 11CAh SYSEVAL SWAP - 6 ROLL + 5 ROLLD » »

NOTES

L->LCD is a helper that turns a list of column bytes into a full-screen string. In my notebook it is called MAKE; the name in the paper is the one used here.

The notebook version differs slightly from the published one. LEFT and RIGHT shift eight and nine bytes rather than six and six, and the key handler has no TYPE guard. Which of us added the guard between 1989 and 1990 is not recorded.

The scans, both listings transcribed token for token, and a small interpreter that runs this listing in a browser: https://michaelmorrison.com/vault/games/space-chase/

Background, plus two pages of hand-assembly with some ROM addresses I cannot account for: https://www.hpmuseum.org/forum/thread-25429-post-223008.html


RE: A 1989 HP-28S game recovered from paper, and two pages of hand-assembly I can't fully - Giuseppe Donnini - 2026-09-10 17:02

You lucked out! I've been spending a lot of time reverse-engineering the HP-28S (to the point of writing my own custom decompiler and disassembler for it). So your cuneiforms instantly felt very familiar to me.

Here is my deciphering proposal.

To make sure we are reading these clay tablets correctly, here is a quick key to the columns:
M: Address in memory (i.e. little-endian) order.
A: Address in standard human-readable form.
HP SYMBOLS: I updated the nomenclature to official HP terminology.
COMMENTARY: My personal notes and suggestions.

CH1
+-------+-------+------------+------------------------------------------------+
|   M   |   A   | HP SYMBOLS |                   COMMENTARY                   |
+-------+-------+------------+------------------------------------------------+
| 76C20 | 02C67 | ::         |                                                |
| 7C170 | 071C7 |   THREE    | Pointer to built-in binary integer # 00003.    |
| B9020 | 0209B |   NDUP     |                                                |
| 92282 | 28229 |   OR$      | Logical OR of two character strings.           |
| E6020 | 0206E |   2DUP     |                                                |
| 92282 | 28229 |   OR$      |                                                |
| A4020 | 0204A |   DUP      |                                                |
| 9F170 | 071F9 |   EIGHT    | Pointer to built-in binary integer # 00008.    |
| 7E120 | 021E7 |   ROLL     |                                                |
| 21D20 | 02D12 |   ID RIGHT | DOIDNT ( Ordinary Identifier Object )          |
| 50    | 05    |            |   Length Field: 5                              |
| 25    | 52    |            |   Data: ASCII 0x52 = 82 = 'R'                  |
| 94    | 49    |            |         ASCII 0x49 = 73 = 'I'                  |
| 74    | 47    |            |         ASCII 0x47 = 71 = 'G'                  |
| 84    | 48    |            |         ASCII 0x48 = 72 = 'H'                  |
| 45    | 54    |            |         ASCII 0x54 = 84 = 'T'                  |
| A4020 | 0204A |   DUP      |                                                |
| 30270 | 07203 |   NINE     | Pointer to built-in binary integer # 00009.    |
| 13220 | 02231 |   UNROLL   | ! TYPO IN SOURCE: Should be 13220, not 13320 ! |
| 92282 | 28229 |   OR$      |                               ^          ^     |
| D8152 | 2518D |   DO>LCD   |                                                |
| D3282 | 2823D |   XOR$     | Logical XOR of two character strings.          |
| 5D980 | 089D5 |   x==      | User Keyword; better to use XEQ=? at #08A2Fh.  |
| 09F20 | 02F90 | ;          |                                                |
+-------+-------+------------+------------------------------------------------+


CH2
+-------+-------+------------+------------------------------------------------+
|   M   |   A   | HP SYMBOLS |                   COMMENTARY                   |
+-------+-------+------------+------------------------------------------------+
| 76C20 | 02C67 | ::         |                                                |
| 3C0A0 | 0A0C3 |   xRAND    | User Keyword; better to use %RAN at #124E6h.   |
| D1311 | 1131D |   %5       | Pointer to built-in float % 5.                 |
| 84D11 | 11D48 |   %*       | Floating-point multiplication.                 |
| 58421 | 12485 |   %CEIL    | Floating-point ceiling function.               |
| 35280 | 08253 |   XEQGET5  | xGET dispatchee for the combination 2:{} 1:%   |
| 8E450 | 054E8 |   EVAL     |                                                |
| 75120 | 02157 |   ROT      |                                                |
| 09F20 | 02F90 | ;          |                                                |
+-------+-------+------------+------------------------------------------------+


UP
+-------+-------+------------+------------------------------------------------+
|   M   |   A   | HP SYMBOLS |                   COMMENTARY                   |
+-------+-------+------------+------------------------------------------------+
| 76C20 | 02C67 | ::         |                                                |
| CD570 | 075DC |   xDUP     | User Keyword, better to use DUP at #0204Ah.    |
| 11920 | 02911 |   138      | DOBINT ( System Binary Integer Object )        |
| A8000 | 0008A |            |   Value: # 0008A = 138                         |
| 11920 | 02911 |   548      | DOBINT ( System Binary Integer Object )        |
| 42200 | 00224 |            |   Value: # 00224 = 548                         |
| FC140 | 041CF |   SUB$     | Subset of a character string.                  |
| 5E020 | 020E5 |   SWAP     |                                                |
| 3B170 | 071B3 |   ONE      | Pointer to built-in binary integer # 00001.    |
| 11920 | 02911 |   137      | DOBINT ( System Binary Integer Object )        |
| 98000 | 00089 |            |   Value: # 00089 = 137                         |
| FC140 | 041CF |   SUB$     |                                                |
| 28B30 | 03B82 |   &$       | Concatenation of two character strings.        |
| 09F20 | 02F90 | ;          |                                                |
+-------+-------+------------+------------------------------------------------+


DOWN
+-------+-------+------------+------------------------------------------------+
|   M   |   A   | HP SYMBOLS |                   COMMENTARY                   |
+-------+-------+------------+------------------------------------------------+
| 76C20 | 02C67 | ::         |                                                |
| CD570 | 075DC |   xDUP     | User Keyword, better to use DUP at #0204Ah.    |
| 3B170 | 071B3 |   ONE      | Pointer to built-in binary integer # 00001.    |
| 11920 | 02911 |   411      | DOBINT ( System Binary Integer Object )        |
| B9100 | 0019B |            |   Value: # 0019B = 411                         |
| FC140 | 041CF |   SUB$     | Subset of a character string.                  |
| 5E020 | 020E5 |   SWAP     |                                                |
| 11920 | 02911 |   412      | DOBINT ( System Binary Integer Object )        |
| C9100 | 0019C |            |   Value: # 0019C = 412                         |
| 11920 | 02911 |   548      | DOBINT ( System Binary Integer Object )        |
| 42200 | 00224 |            |   Value: # 00224 = 548                         |
| FC140 | 041CF |   SUB$     |                                                |
| 5E020 | 020E5 |   SWAP     |                                                |
| 28B30 | 03B82 |   &$       | Concatenation of two character strings.        |
| 09F20 | 02F90 | ;          |                                                |
+-------+-------+------------+------------------------------------------------+


LEFT
+-------+-------+------------+------------------------------------------------+
|   M   |   A   | HP SYMBOLS |                   COMMENTARY                   |
+-------+-------+------------+------------------------------------------------+
| 76C20 | 02C67 | ::         |                                                |
| CD570 | 075DC |   xDUP     | User Keyword, better to use DUP at #0204Ah.    |
| 30270 | 07203 |   NINE     | Pointer to built-in binary integer # 00009.    |
| 11920 | 02911 |   548      | DOBINT ( System Binary Integer Object )        |
| 42200 | 00224 |            |   Value: # 00224 = 548                         |
| FC140 | 041CF |   SUB$     | Subset of a character string.                  |
| 5E020 | 020E5 |   SWAP     |                                                |
| 3B170 | 071B3 |   ONE      | Pointer to built-in binary integer # 00001.    |
| 9F170 | 071F9 |   EIGHT    | Pointer to built-in binary integer # 00008.    |
| FC140 | 041CF |   SUB$     |                                                |
| 28B30 | 03B82 |   &$       | Concatenation of two character strings.        |
| 09F20 | 02F90 | ;          |                                                |
+-------+-------+------------+------------------------------------------------+


RIGHT
+-------+-------+------------+------------------------------------------------+
|   M   |   A   | HP SYMBOLS |                   COMMENTARY                   |
+-------+-------+------------+------------------------------------------------+
| 76C20 | 02C67 | ::         |                                                |
| CD570 | 075DC |   xDUP     | User Keyword, better to use DUP at #0204Ah.    |
| 11920 | 02911 |   540      | DOBINT ( System Binary Integer Object )        |
| C1200 | 0021C |            |   Value: # 0021C = 540                         |
| 11920 | 02911 |   548      | DOBINT ( System Binary Integer Object )        |
| 42200 | 00224 |            |   Value: # 00224 = 548                         |
| FC140 | 041CF |   SUB$     | Subset of a character string.                  |
| 5E020 | 020E5 |   SWAP     |                                                |
| 3B170 | 071B3 |   ONE      |                                                |
| 11920 | 02911 |   539      | DOBINT ( System Binary Integer Object )        |
| B1200 | 0021B |            |   Value: # 0021B = 539                         |
| FC140 | 041CF |   SUB$     |                                                |
| 28B30 | 03B82 |   &$       | Concatenation of two character strings.        |
| 09F20 | 02F90 | ;          |                                                |
+-------+-------+------------+------------------------------------------------+



RE: A 1989 HP-28S game recovered from paper, and two pages of hand-assembly I can't fully - Christoph Giesselink - 2026-09-11 13:05

Attached a state file for Emu42.

The HP28S state file has three directories FAST, SPACE, TOOLS.

FAST contains the fast version of the game. I had to adjust the SHIFT program to the fast SPACE program.

SPACE contains the original UserRPL game.

TOOLS contains helper programs to compile the SysRPL programs of the fast version.

MMorrison: You may add the state file to your page.

The sources for ASS:

Code:
MCHI1 Checksum [5174] "76C207C170B902092282E602092282A40209F1707E12021D20502594748445A4020302701322092282D8152D32825D98009F20" MCHI2 Checksum [EEB0] "76C203C0A0D131184D1158421352808E4507512009F20" MUP Checksum [D5F0] "76C20CD57011920A80001192042200FC1405E0203B1701192098000FC14028B3009F20" MDOWN Checksum [0B5B] "76C20CD5703B17011920B9100FC1405E02011920C91001192042200FC1405E02028B3009F20" MLEFT Checksum [156E] "76C20CD570302701192042200FC1405E0203B1709F170FC14028B3009F20" MRIGHT Checksum [D100] "76C20CD57011920C12001192042200FC1405E0203B17011920B1200FC14028B3009F20"


.zip   SpaceChase.zip (Size: 3.78 KB / Downloads: 4)