--- title: "Stuntman" id: 71430 type: "computer_media" slug: "stuntman" url: "http://localhost/computer_media/stuntman/" markdown_url: "http://localhost/computer_media/stuntman.md" published_at: "2026-09-09T09:01:39+00:00" modified_at: "2026-09-09T09:01:39+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/stuntman-2.png" excerpt: "Hold a key to build speed, release at the right moment, and watch your stuntman attempt to clear a row of double-decker buses in this arcade jump game." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "1986" slug: "year-1986" taxonomy: "post_tag" url: "http://localhost/tag/year-1986/" - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" basic: - name: "User Defined Graphics (UDG)" slug: "user-defined-graphics-udg" taxonomy: "basic" url: "http://localhost/basic/user-defined-graphics-udg/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "David Ritchie" slug: "david-ritchie" taxonomy: "indiv" url: "http://localhost/indiv/david-ritchie/" genre: - name: "Arcade" slug: "arcade" taxonomy: "genre" url: "http://localhost/type/arcade/" media_type: "Program" programmers: - name: "David Ritchie" slug: "david-ritchie" taxonomy: "indiv" url: "http://localhost/indiv/david-ritchie/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Stuntman%20(1986)(Ritchie%2C%20David)(TS2068)(US)(Program).zip" tsrun_member: "Stuntman (1986)(Ritchie, David)(TS2068)(US)(Program).tap" mediadate: "1986" images: - url: "http://localhost/wp-content/uploads/2026/09/stuntman-2.png" - url: "http://localhost/wp-content/uploads/2026/09/stuntman-3.png" - url: "http://localhost/wp-content/uploads/2026/09/stuntman.png" media_type_tags: "Arcade" --- # Stuntman Stuntman is an arcade-style motorcycle jump game in which the player accelerates a bike and attempts to clear a row of double-decker buses. The program uses several blocks of machine code POKEd into memory starting at address 52000, handling screen scrolling and sprite animation routines called via RANDOMIZE USR. User-defined graphics (UDGs) are loaded through READ/DATA statements to render the bike, ramps, buses, and other game elements across characters A through L. Speed is simulated by having the player hold a key to build MPH, with a random braking component determining the jump arc calculated at line 170 using the formula `J=9+INT(M/7.5+.5)`. The game tracks score and lives, awards a bonus for clearing all buses, and includes a scrolling title sequence and instruction screen driven by machine code scroll routines. *** ### Program Structure The program is organized into several distinct sections: 1. **Lines 10–50:** Initialization — set up UDGs, machine code, and call the scene-drawing subroutine. 2. **Lines 60–140:** Speed-building loop — the player holds a key to accelerate, releasing to commit to a speed. 3. **Lines 150–310:** Jump sequence — calculate arc, animate bike up the ramp and across the screen. 4. **Lines 310–420:** Success branch — animate bus crossing, print result, award score and life, loop. 5. **Lines 440–590:** Scene setup subroutine — draws road, buses, ramps, score/lives display. 6. **Lines 600–740:** Crash/game-over handling — crash animation, life decrement, end-of-game sequence. 7. **Lines 750–860:** Loader section — POKEs UDG data and machine code into memory. 8. **Lines 860–1030:** Title/intro sequence — animated logo, credits, instructions screen. 9. **Lines 1040–1080:** Utility lines — SAVE, system POKEs, and a simple border/paper/CLS subroutine at 1080. ### Machine Code Usage Four machine code routines are POKEd into RAM starting at address 52000, loaded via READ/DATA statements at lines 810–850. They are called throughout the game using `RANDOMIZE USR` (to discard the return value) or `LET L=USR` (also discarding the value, but syntactically requiring an assignment). | Address | Approximate Function | Called At | | --- | --- | --- | | 52000 | Scroll or screen wipe routine | Lines 330, 700, 710, 720, 1020 | | 52022 | Screen clear/reset helper | Lines 340, 410, 610, 630, 950, 1020 | | 52044 | Parameterized effect (value in POKE 52046) | Lines 600, 630, 680, 690, 710, 720, 890 | | 52069 | Animated sprite/scroll driver (POKE 52071 sets parameter) | Lines 50, 320 | The parameter byte at address 52046 is set immediately before calling `USR 52044`, acting as a simple argument-passing mechanism. Similarly, address 52071 controls behavior of the `USR 52069` routine, set to `1` before bus-clearing animation and reset to `5` afterward at line 320. ### UDG Loading Lines 750–800 load custom characters into UDG slots A through L. A loop from `USR "A"` to `USR "I"+7` (covering nine 8-byte characters) reads from DATA at lines 760–770. Notably, the DATA at line 760 uses the variable `X` as a literal token inside the DATA statement — this is a known quirk where the BASIC tokenizer stores a numeric variable reference instead of a number, which resolves to 0 at runtime (since X has not yet been assigned). UDG “J” (lines 780) is filled with random bytes each run, likely to generate a randomized explosion or debris graphic. UDG “L” is loaded with a fixed wheel/tire pattern (line 800, DATA 124,130,170,130,84,68,56,254). ### Jump Arc Calculation The landing column `J` is computed at line 170 as `J=9+INT(M/7.5+.5)`, where `M` is the effective speed after subtracting a random braking factor (`Z-5`, range −5 to +5) and a fixed deceleration of 40. This means a higher release speed produces a larger `J`, moving the landing point further along the screen. Success requires `J=BUS+7` (line 310), where `BUS` is a random value from 2 to 18 (line 30), making the number of buses variable each round and requiring different speeds to clear different stacks. ### Speed Building Loop Lines 80–130 implement the throttle mechanic: line 80 waits for any key press, line 90 increments speed by `2+INT(RND*4)` each iteration (giving 2–5 MPH per loop), and line 130 exits when the key is released. Speed is capped at 170 MPH (line 110). The sound at line 100 uses two `BEEP` calls at low pitches to simulate engine noise during acceleration. ### Scrolling Title and Instruction Sequences The intro at lines 860–1030 draws a geometric pattern using `PLOT`/`DRAW` and then animates the game title scrolling in from the right using a `FOR Z=3 TO 23` loop at line 890. Each iteration prints a substring of a repeating UDG pattern, using the `(Z+1)` subscript on a string literal to truncate it — a compact horizontal scroll idiom in Sinclair BASIC. The instructions screen (lines 960–1030) uses UDG characters `\\k` and `\\j` to draw a decorative border around the “STUNTMAN” title. ### Score and Lives Management Score (`SC`) starts at 0 and increments by 100 per successful jump (line 390). Lives (`LI`) start at 3 (line 20) and gain one per successful jump (line 400), while a crash deducts one (line 640). When `LI<=0` the game-over sequence fires at line 670. The scene subroutine at line 440 redraws the score and lives on each new round via line 580. ### Notable Techniques and Idioms - `NOT PI` evaluates to 0 (since PI is non-zero, NOT returns 0), used throughout as a compact literal zero for `AT` row/column and INK color arguments. - `INT PI` evaluates to 3, used at line 200 as the loop limit and at line 240 as a column argument. - `VAL "number"` is not used here; `GO TO` targets are all explicit line numbers. - Line 1080 is a minimal utility subroutine: `BORDER 7:PAPER 7:INK NOT PI:CLS :RETURN`, called from multiple points to reset the display cleanly. - Line 630 uses `LET L=USR 52022` — assigning the machine code return value to an otherwise unused variable `L` purely to satisfy BASIC syntax, since `USR` cannot appear as a statement alone. - Lines 720 and 730 check `S$` for “N” and “Y” respectively after an INPUT, with a fallback `GO TO 700` at line 740 for invalid input — a standard validation loop. ### Anomalies and Notes - Line 760 DATA contains the token `X` as a numeric value in the DATA stream. At the time the loop at line 750 runs, `X` is uninitialized and will be 0, so all occurrences of `X` in the DATA effectively supply 0 bytes to the UDG patterns. - Line 1000 contains a typo in the PRINT statement: `"\\f\\f\\g\\f\\g\\g"` includes a stray extra character mid-sequence (`\\f\\f\\g`), likely a mistype of the repeating `\\f\\g` bus graphic pair. This would display a slightly malformed graphic on that row but is not a program-breaking bug. - Line 1050 contains a `REM IS (35)NORM.` comment referencing a system variable, suggesting the developer experimented with the `POKE 23561,12` setting (probably RAMTOP or a related pointer) during development. - Lines 1040 and 2000 are SAVE lines used for tape storage and are not part of normal program flow. ## Source Code ``` 10 POKE 23658,8:BEEP .1,10:GO SUB 750 20 LET SC=0:LET LI=3 30 RANDOMIZE :LET BUS= INT (RND*17)+2 40 GO SUB 440 50 RANDOMIZE USR 52069 60 LET M=0 70 PRINT AT 1,11;"0 M.P.H." 80 IF INKEY$="" THEN GO TO 80 90 LET M=M+2+ INT (RND*4) 100 BEEP .17,-50:BEEP .1,-55 110 IF M>170 THEN LET M=170 120 PRINT AT 1,11;M;" M.P.H." 130 IF INKEY$ <>"" THEN GO TO 90 140 LET MP=M 150 LET Z= INT (RND*11) 160 LET M=M+(Z-5)-40 170 LET J=9+ INT (M/7.5+.5) 180 FOR O=1 TO 120:NEXT O 190 IF M<-5 THEN LET J=6 200 FOR N=1 TO INT PI 210 PRINT PAPER 6; AT 10,N-1;""; AT 10,N-1;" \f\g" 220 BEEP .1,-50 230 NEXT N 240 FOR O=10 TO 15:BEEP .01,O:NEXT O:PRINT AT 10, PI;" "; AT 9,5;"IH"; AT 9,5;" "; AT 8,6;"\i\h":POKE 52046,10:RANDOMIZE USR 52044 250 IF J=6 THEN GO TO 300 260 FOR N=6 TO J 270 PRINT AT 8,N-1;" "; AT 8,N;" \i\h" 280 BEEP .1,-40:BEEP .1,-50:BEEP .1,-59 290 NEXT N 300 FOR O=1 TO 5:BEEP .01,J:NEXT O:PRINT AT 8,J;" "; AT 9,J+1;"\i\h"; AT 9,J+1;" "; AT 10,J+2;"\i\h" 310 IF J <>BUS+7 THEN GO TO 600 320 POKE 52071,1:RANDOMIZE USR 52069:FOR N=J+3 TO 29:PRINT AT 10,N-1;" "; AT 10,N;" \f\g":BEEP .1,-50:BEEP .01,45:BEEP .01,55:BEEP .1,-59:NEXT N:POKE 52071,5 330 PRINT AT 10,29;"\f\g ":RANDOMIZE USR 52000 340 RANDOMIZE USR 52022:GO SUB 1080 350 PRINT AT 8,11;"GREAT JUMP" 360 PRINT AT 10,2;"YOU CLEARED ALL ";BUS;" BUSSES AT" 370 PRINT AT 12,6;"A SPEED OF ";MP;" M.P.H." 380 FOR X=1 TO 600:NEXT X 390 LET SC=SC+100 400 LET LI=LI+1 410 RANDOMIZE USR 52022:CLS 420 GO TO 30 430 STOP 440 BORDER 5:PAPER 6:INK NOT PI:CLS 450 PRINT AT 11, NOT PI; INK 3;" \::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\:: " 460 PRINT AT 10,5;"\a\b" 470 FOR N=7 TO BUS+6 480 PRINT AT 10,N;"\e":NEXT N 490 PRINT AT 10,BUS+7;"\d\c" 500 PRINT AT 2, NOT PI;"\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''" 510 PRINT "\l\l\l\{16}\{1}\l\l\l\{16}\{2}\l\l\l\l\l\l\{16}\{0}\l\l\l\l\l\l\l\l\l\l\{16}\{2}\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\{16}\{1}\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\{16}\{4}\{16}\{2}\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\l\{16}\{9}" 520 PRINT INK 4; OVER 1;"\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::" 530 FOR J=12 TO 21:PRINT AT J, NOT PI; OVER 1; INK 4;"\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::":NEXT J 540 PLOT 0,152:DRAW 255,0 550 DRAW 0,-32:DRAW -255,0:DRAW 0,32 560 PLOT 0,128:DRAW 255,0:PLOT 0,120:DRAW 255,0 570 PRINT AT 6,0; PAPER 7;"\{20}\{1} \{19}\{1}S T U N T M A N\{19}\{0} \{20}\{0}" 580 PRINT AT 14,10; PAPER PI; INK 7;"SCORE:";SC;" "; AT 16,10; PAPER PI; INK 7;"LIVES:";LI;" " 590 RETURN 600 FOR N=1 TO 10:POKE 52046, INT (RND*10)+1:LET l= USR 52044:BEEP .1,-50:BEEP .1,-50:PRINT AT 10,j+2; OVER 1; BRIGHT 1; FLASH 1;"\j\k"; AT 10,j+2; OVER 1;"\k\j":NEXT N 610 RANDOMIZE USR 52022:GO SUB 1080 620 PRINT AT 10,6;"YOU HAVE CRASHED" 630 FOR J=1 TO 200:NEXT J:LET L= USR 52022 640 LET LI=LI-1 650 IF LI <=0 THEN GO TO 670 660 GO TO 40 670 BORDER 0:PAPER 0:INK 6:CLS 680 FOR Z=0 TO 8:POKE 52046,12:LET L= USR 52044:BEEP .1,-50:BEEP .1,-45:PRINT INK 6; AT 14,Z;" YOU SCORED ";SC:PRINT AT 14,Z+19;" \i\h":NEXT Z 690 FOR Z=0 TO 29:POKE 52046, INT (RND*5)+1:LET L= USR 52044:BEEP .1,-50:BEEP .1,-45:PRINT INK 7; AT 12,Z;"END OF GAME. NO LIVES LEFT "(Z+1);"\i\h":NEXT Z 700 RANDOMIZE USR 52000:INPUT "ANOTHER GAME(Y/N)? :";S$ 710 FOR J=30 TO 0 STEP -1:POKE 52046,2:LET L= USR 52044:PRINT AT 12,J;"\f\g "; AT 14,J;"\f\g ":NEXT J 720 IF S$="N" THEN FOR Z=0 TO 8:POKE 52046,12:LET L= USR 52044:BEEP .1,-50:BEEP .1,-45:PRINT INK 6; AT 14,Z;" GOOD BYE ":PRINT AT 14,Z+13;" \i\h":NEXT Z:PAUSE 300:NEW 730 IF S$="Y" THEN LET S=0:GO TO 20 740 GO TO 700 750 FOR I= USR "A" TO USR "I"+7:READ X:POKE I,X:NEXT I 760 DATA 0,X,3,12,48,64,255,0,31,97,129,1,X,X,255,0,X,X,128,96,24,6,255,0,248,134,129,128,X,X,255,0 770 DATA 62,85,127,X,85,127,X,34,3,X,1,X,27,38,37,26,128,136,249,40,88,228,X,24,136,220,178,210,204,128,0,X,X,1,13,18,45,19,18,12 780 FOR I=0 TO 15:POKE USR "J"+I, INT (RND*254)+1:NEXT I 790 FOR I=0 TO 7:READ A:POKE USR "L"+I,A:NEXT I 800 DATA 124,130,170,130,84,68,56,254 810 FOR X=52000 TO 52101:READ A:POKE X,A:NEXT X 820 DATA 33,0,60,58,120,92,71,62,24,211,254,62,0,211,254,16,254,43,188,32,238,201 830 DATA 22,0,33,0,64,126,203,63,119,35,62,88,188,32,246,20,62,9,186,32,237,201 840 DATA 33,200,21,6,40,0,17,0,0,197,229,205,181,3,225,193,43,43,43,43,43,43,16,238,201 850 DATA 33,4,5,6,128,17,1,0,197,229,205,181,3,225,193,35,35,35,35,35,35,16,238,37,37,37,37,62,255,188,32,227,201 860 BORDER 0:PAPER 5:INK NOT PI:CLS :FOR F=100 TO 1 STEP -1:PLOT 132-F/2,105+F/2:DRAW F,0:NEXT F:FOR F=0 TO 40:PLOT 132-F,165-F:DRAW F*2,0:NEXT F 870 PRINT AT PI,14; PAPER 0; INK 6;"\{19}\{1}DAVID"; AT 5,13; INK 7;"RITCHIE" ; AT 7,16; INK 7;"\*\{19}\{0}" 880 PRINT AT 10,11;"JAN 1985 \*" 890 FOR Z=3 TO 23:POKE 52046, INT (RND*5)+1:LET L= USR 52044: BEEP .1,-50:BEEP .1,-45:PRINT INK 1; AT 18,Z;" \i\g\i\g\i\g\i\g\i\g\i\g\i\g\i\g\i\g\i\g\i\g"(Z+1);"\i\h"; AT 19,Z;" \i\g S T U N T M A N \i\g"(Z+1);"\i\h"; AT 20,Z;" \i\g\i\g\i\g\i\g\i\g\i\g\i\g\i\g\i\g\i\g\i\g"(Z+1);"\i\h":NEXT Z 900 FOR J=24 TO 29:BEEP .1,-50:BEEP .1,-55:BEEP .1,-45:PRINT AT 18,J," \i\h"; AT 19,J;" \i\h"; AT 20,J;" \i\h":NEXT J 910 PRINT AT 12,8;"SINCLAIR PROGRAMS":PLOT 64,72:DRAW 136,0 920 PRINT AT 14,7;"INSTRUCTIONS? (Y/N)" 930 INPUT A$:IF A$="y" OR a$="Y" THEN GO TO 950 940 IF a$="n" OR a$="N" THEN LET L= USR 52022:GO TO 1080 950 FOR J=29 TO 1 STEP -1:PRINT AT 18,J;"\i\g "; AT 19,J;"\i\g "; AT 20,J;"\i\g ":BEEP .1,-50:BEEP .1,-55:BEEP .1,-59:BEEP .1,-45:NEXT J:RANDOMIZE USR 52022:GO SUB 1080 960 BORDER NOT PI:PAPER NOT PI:INK 7:CLS :PRINT TAB 10;"\k\k\k\k\k\k\k\k\k\k"; TAB 10;"\kSTUNTMAN\k"; TAB 10;"\j\j\j\j\j\j\j\j\j\j" 970 PRINT AT 5, NOT PI;"IN THIS GAME,IT'S ON WITH YOUR CRASH HELMET AND AWAY YOU GO. YOU MUST JUMP OVER A LINE OF BIGDOUBLE DECKER BUSES. TO DO THIS HOLD DOWN ANY KEY, WATCH YOUR" 980 PRINT "SPEED INCREASE, LET GO OF THE BRAKES (REMOVE FINGER), AND WATCH YOUR STUNTMAN FLY OVER THE RAMPS......" 990 PRINT AT 19, NOT PI;"\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g P R E S S A K E Y \f\g\f\g" 1000 PRINT AT 21, NOT PI;"\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\g\f\f\g\f\g\g\f\g\f\g\f\g\f\g\f\g" 1010 PAUSE NOT PI 1020 RANDOMIZE USR 52022:GO SUB 1080 1030 RETURN 1040 SAVE "BIKE/STUNT":VERIFY "":BEEP .1,7:BEEP .1,7:STOP 1050 POKE 23609,7:POKE 23658,8:POKE 23561,12:REM IS (35)NORM. 1060 STOP 1070 RETURN 1080 BORDER 7:PAPER 7:INK NOT PI:CLS :RETURN 2000 SAVE "BIKE/STUNT" LINE 1 ```