--- title: "Rifle" id: 69505 type: "computer_media" slug: "rifle" url: "http://localhost/computer_media/rifle/" markdown_url: "http://localhost/computer_media/rifle.md" published_at: "2026-04-13T22:13:14+00:00" modified_at: "2026-04-13T22:15:25+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/04/SCR-20260413-pnyv.png" excerpt: "A scrolling shooting gallery game with machine code effects, six escalating target rounds, UDG sprites, and a bubble-sort high-score table tracking the top five players." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - 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/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/RIFLE%20%28198x%29%28Housley%2C%20Michael%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/04/SCR-20260413-pnyv.png" - url: "http://localhost/wp-content/uploads/2026/04/SCR-20260413-pnxd.png" media_type_tags: "Game" --- # Rifle Rifle is a shooting gallery game in which the player fires at a row of moving targets that scroll across the screen, with the gun position oscillating left and right along the bottom. The program uses multiple machine code routines POKEd into memory at address 60000, handling display effects including a border color-cycling routine and screen-copy operations. Six progressively harder rounds are defined at lines 1000–1050, each using a different set of User Defined Graphics characters to represent two-row sprite targets worth 100 to 600 points each; clearing all targets in a round awards bonus points and reduces available ammunition. A bubble-sort high-score table (lines 1610–1670) stores the top five names and scores, pre-initialized with placeholder entries, and persists across games within the same session. The graphical title screen at lines 40–300 is drawn entirely with PLOT, DRAW, CIRCLE, and PRINT statements to create a detailed rifle-range backdrop. *** ## Program Analysis ### Program Structure The program divides into several logical sections: 1. **Lines 10–30:** Initialization — defines helper functions, clears memory, and calls the machine code loader subroutine at line 1760. 2. **Lines 40–300:** Draws the static rifle-range backdrop using PLOT, DRAW, CIRCLE, and PRINT. 3. **Lines 310–320:** Launches the title animation via `RANDOMIZE USR 60000`, then jumps to the main menu. 4. **Lines 330–620:** Core gameplay loop — manages ammunition, moving gun, target hit detection, and round progression. 5. **Lines 990–1060:** Round-definition subroutines (lines 1000–1050), each setting target UDGs, point value, and ink color; line 1060 handles round-clear fanfare. 6. **Lines 1110–1210:** Title/menu screen with animated border and key selection. 7. **Lines 1220–1410:** Multi-page instruction screens. 8. **Lines 1420–1730:** End-of-game sequence, high-score entry, bubble sort, and leaderboard display. 9. **Lines 1760–1880:** Machine code loader — reads DATA bytes, POKEs them to addresses 60000–60134 and 60200–60266, initializes the high-score arrays, and relocates the UDG table. ### Machine Code Routines Three distinct machine code blocks are installed by the loader: | Address | Called via | Purpose | | --- | --- | --- | | 60000 | `RANDOMIZE USR 60000` | Title screen animation (copies/manipulates display memory) | | 60050 | `RANDOMIZE USR 60050` | Game-start screen setup (copies attribute or pixel area) | | 60100 | `RANDOMIZE USR 60100` | Used on instruction pages — likely a border or screen effect | | 60200 | `RANDOMIZE USR 60200` | Per-frame animation during menu loop (title scrolling/twinkle) | | 60250 | `RANDOMIZE USR 60250` | Border color cycling; driven by `POKE 59990,g` before the call | The loader at lines 1780–1850 applies two skip conditions: when the loop variable `F` equals 60012 or 60062 (first block) or 60242 (second block), it advances `F` by 38 or 8 bytes respectively, skipping those addresses — a technique used to leave certain memory locations unpopulated or to jump over self-modifying regions. The `RANDOMIZE USR` idiom is used throughout because the return value of a machine code routine is loaded into the RANDOMIZE seed, so it is a convenient way to call machine code without a numeric result interfering with the program flow. ### UDG Sprite System Each of the six target types is built from two rows of two UDG characters, giving a 2×2 character sprite. The UDGs used are `\a`–`\u` (the full set of 21 user-defined graphics). Line 1880 relocates the UDG table pointer (system variables at addresses 23675–23676) to point 6 bytes before the calculated UDG base, effectively remapping all UDG slots. The instruction screen (lines 1330–1380) uses the same UDG strings to illustrate each prize tier. ### Gameplay Mechanics The gun position is stored in variable `a` and oscillates between columns 7 and 23 using direction variable `x` (lines 450–470). Firing is detected by any key press setting `f=1` (line 420). Hit detection at line 480 checks whether the character in the bottom row of the target string `b$` at the gun’s column offset has a code greater than 32 (i.e., is not a space), providing a simple but effective 1D collision test. When a hit occurs, lines 540–570 clear both the hit character and its immediate neighbors in both `a$` and `b$`, simulating a two-character-wide target being destroyed. The variable `go` starts at 1000 and is incremented by 10 each time all five targets in a round are cleared (line 590), so successive rounds call GO SUB 1010, 1020, etc., cycling through progressively harder target types. The sixth round at line 1050 mixes all five target sprites together for maximum difficulty. ### High-Score Table The high-score system uses parallel arrays: `h(5)` for numeric scores and `h$(5,10)` for 10-character names (lines 1810–1830), pre-seeded with scores 5000 down to 1000 and the name “SPECTRUM”. Name entry at lines 1500–1570 supports backspace via `CHR$ 12` detection. After entry, a bubble sort (lines 1610–1670) uses a shrinking-range variable `zx` starting at 4 and decrementing each pass, correctly sorting both arrays in tandem. ### Helper Functions Line 20 defines two functions used for splitting 16-bit values into bytes: `FN h(x)` returns the high byte (`INT(x/256)`) and `FN l(x)` returns the low byte. These are applied in line 1880 to split the UDG table address for POKEing into the system variable pair at 23675–23676, and also in line 1430 where `h(5)` is used as a numeric array element — note that `h` is both a DEF FN name and a numeric array, which works in Spectrum BASIC because functions are called with `FN h(...)` syntax. ### Notable Techniques and Anomalies - The scrolling target strings use a rotate idiom: `LET a$=a$(2 TO )+a$(1)` (line 430), efficiently cycling the target row left by one character each frame without any loop. - Line 590 uses `LET go=go+10: GO TO 380` to advance the subroutine destination — since `go` starts at 1000 and each round subroutine is at 1000, 1010, 1020 …, this elegantly steps through round definitions using a numeric variable as the GO SUB target. - The backdrop drawing at lines 110–210 uses perspective-like diagonal lines and arcs to suggest a 3D shooting gallery booth, all in pure BASIC PLOT/DRAW commands. - Line 290 uses a `PAPER 0; INK 7` area for the ammo display in the attribute-colored title bar, exploiting attribute color to integrate the HUD into the static backdrop drawn at startup. - Line 1140 and line 1680 use long PRINT strings of block graphics characters to render multi-line pixel-art title text, a common technique to embed graphics in BASIC without a separate data-loading routine. - The variable name collision between array `h()` and function `FN h()` at line 1430 (`IF sc>h(5)`) accesses the array element, not the function — a valid distinction in Spectrum BASIC but potentially confusing to read. ## Source Code ``` 10 REM by Michael Housley of Bradford,Yorkshire 20 DEF FN h(x)=INT (x/256): DEF FN l(x)=x-256*FN h(x) 30 CLEAR 60000: GO SUB 1760 40 PAPER 4: INK 0: BRIGHT 1: BORDER 4: CLS 50 PRINT PAPER 5;AT 0,0,,,,,,,, 60 FOR f=1 TO 14 STEP .5: CIRCLE INK 6;235,160,f: NEXT f 70 INVERSE 1: PLOT PAPER 0; INK 6;225,156: DRAW INK 6; PAPER 0;20,0,1.5: DRAW PAPER 0; INK 6;-20,0,-.75 80 CIRCLE INK 6; PAPER 0;232,162,3: PLOT INK 6; PAPER 0;233,162 90 CIRCLE INK 6; PAPER 0;238,162,3: PLOT INK 6; PAPER 0;237,162 100 CIRCLE INK 6; PAPER 0;235,157,2: INVERSE 0 110 PLOT 0,0: FOR f=0 TO 15: PLOT f,f: DRAW 15-f,0: PLOT 255-f,-f: DRAW f-15,0: NEXT f 120 PLOT 0,0: DRAW 48,48: DRAW 159,0: DRAW 48,-48: DRAW 0,140: DRAW -255,0: DRAW 0,-140 130 PLOT 48,48: DRAW 0,92: PLOT 207,48: DRAW 0,92: PLOT 16,16: DRAW 223,0 140 PLOT 10,10: DRAW 0,130: PLOT 20,20: DRAW 0,120: PLOT 30,30: DRAW 0,110: PLOT 40,40: DRAW 0,100 150 PLOT 245,10: DRAW 0,130: PLOT 235,20: DRAW 0,120: PLOT 225,30: DRAW 0,110: PLOT 215,40: DRAW 0,100 160 PLOT 58,48: DRAW -24,-32: PLOT 68,48: DRAW -14,-32: PLOT 78,48: DRAW -9,-32: PLOT 88,48: DRAW -5,-32 170 PLOT 98,48: DRAW -4,-32: PLOT 108,48: DRAW -3,-32: PLOT 118,48: DRAW -2,-32: PLOT 128,48: DRAW 0,-32 180 PLOT 138,48: DRAW 2,-32: PLOT 148,48: DRAW 3,-32: PLOT 158,48: DRAW 4,-32: PLOT 168,48: DRAW 5,-32 190 PLOT 178,48: DRAW 9,-32: PLOT 188,48: DRAW 14,-32: PLOT 188,48: DRAW 14,-32: PLOT 198,48: DRAW 24,-32 200 PLOT 48,95: DRAW 159,0: DRAW 10,-3: DRAW -179,0: DRAW 8,3: PLOT 38,92: DRAW 0,-2: DRAW 179,0: DRAW 0,2 210 PLOT 0,140: DRAW 0,2: DRAW 255,0: DRAW 0,-2 220 FOR f=67 TO 187 STEP 20: CIRCLE INK 7;f,106,10: CIRCLE INK 7;f,106,7: NEXT f 230 PRINT PAPER 0; INK 7;AT 2,6;"YE OLDE RIFLE RANGE." 240 PLOT 45,149: DRAW 165,0: DRAW 0,13: DRAW -165,0: DRAW 0,-13 250 PLOT 80,149: DRAW 0,-6: PLOT 82,149: DRAW 0,-6: PLOT 175,149: DRAW 0,-6: PLOT 173,149: DRAW 0,-6 260 PLOT 80,142: PLOT 82,142: PLOT 175,142: PLOT 173,142 270 PRINT PAPER 2; INK 6;AT 5,8;"\c";AT 6,8;"\d\e";AT 5,22;"\c";AT 6,22;"\d\e" 280 PRINT PAPER 7;AT 5,11;"YE PRIZES.";AT 11,12;"YE SCORE"; PAPER 0;AT 12,13," ";AT 14,6," ";AT 15,6," " 290 PRINT PAPER 7;AT 0,11;"YE AMMO "; PAPER 0;" ": PRINT PAPER 0;AT 20,2," ";AT 21,1," " 300 PAUSE 160 310 RANDOMIZE USR 60000 320 GO TO 1110 330 BORDER 0 340 LET sc=0: LET bon=1000: LET tam=51 350 RANDOMIZE USR 60050 360 LET co=0: LET a=15: LET f=co: LET x=1: LET am=tam: LET go=1000 370 PRINT PAPER 0; INK 6;AT 0,19;am 380 GO SUB go 390 LET f=0: LET am=am-1 400 PRINT PAPER 0; INK 6;AT 0,19;am;" " 410 PRINT PAPER 0; INK in;AT 14,6;a$;AT 15,6;b$ 420 IF INKEY$<>"" THEN LET f=1: BEEP .01,-10 430 LET a$=a$(2 TO )+a$(1): LET b$=b$(2 TO )+b$(1) 440 PRINT INK 5; PAPER 0;AT 20,a;" \a ";AT 21,a;" \b " 450 LET a=a+x 460 IF a<7 THEN LET x=1 470 IF a>23 THEN LET x=-1 480 IF f=1 AND CODE (b$(a-5))>32 THEN GO TO 520 490 IF f=1 THEN LET f=0: LET am=am-1 500 IF am=0 THEN GO TO 1420 510 GO TO 400 520 BEEP .01,20 530 LET co=co+1 540 LET b$(a-5)=" " 550 IF CODE (b$(a-6))>32 THEN LET b$(a-6)=" " 560 IF CODE (b$(a-4))>32 THEN LET b$(a-4)=" " 570 LET a$(a-6 TO a-4)=" " 580 LET sc=sc+va: PRINT INK RND*6+1; PAPER 0;AT 12,13;sc;" " 590 IF co=5 THEN LET go=go+10: GO TO 380 600 IF am=0 THEN GO TO 1420 610 GO TO 490 990 REM go 1000 LET va=100: LET in=6: LET a$="\c \c \c \c \c ": LET b$="\d\e \d\e \d\e \d\e \d\e ": RETURN 1010 LET co=0: LET va=200: LET in=7: LET a$="\f\h \f\h \f\h \f\h \f\h ": LET b$="\g\i \g\i \g\i \g\i \g\i ": RETURN 1020 LET co=0: LET va=300: LET in=4: LET a$="\j\l \j\l \j\l \j\l \j\l ": LET b$="\k\m \k\m \k\m \k\m \k\m ": RETURN 1030 LET co=0: LET va=400: LET in=5: LET a$="\n\o \n\o \n\o \n\o \n\o ": LET b$="\p\q \p\q \p\q \p\q \p\q ": RETURN 1040 LET co=0: LET va=500: LET in=3: LET a$="\r\s \r\s \r\s \r\s \r\s ": LET b$="\t\u \t\u \t\u \t\u \t\u ": RETURN 1050 LET co=0: LET va=600: LET in=7: LET a$="\r\s \c \f\h \j\l \n\o ": LET b$="\t\u \d\e \g\i \k\m \p\q ": RETURN 1060 FOR f=0 TO 10: FOR g=7 TO 0 STEP -1: POKE 59990,g: RANDOMIZE USR 60250: BEEP .001,f*2+20: NEXT g: NEXT f 1070 RANDOMIZE USR 60050: BEEP .01,20 1080 PRINT AT 20,a;" ";AT 21,a;" ": LET sc=sc+bon: LET tam=tam-5 1090 IF tam<30 THEN LET sc=sc+10000: GO TO 1420 1100 GO TO 360 1110 BORDER 0: PAPER 0: INK 7: CLS 1120 LET ink=RND*5+1 1130 FOR f=4 TO 5: PRINT INK ink;AT f,0;"▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚";AT f+13,0;"▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜": NEXT f 1140 PRINT INK ink;AT 8,6;"▗▜▜▘▗▘▐ ▗▘ ▗▜▗▐▝▐▐▀▐▀ ▗▜▐ ▗ ▐ ▗ ▗▜▗▐▐▜▐▐▐▘ ▘▘▀▘▘ ▀▘▀▘ ▘▘▘▘▘▝▝▀▝▀" 1150 PRINT AT 12,0;"PRESS EITHER"''"1.FOR INSTRUCTIONS"'" OR 2.TO PLAY" 1160 FOR f=0 TO 500 1170 RANDOMIZE USR 60200 1180 IF INKEY$="1" THEN BEEP .01,10: GO TO 1220 1190 IF INKEY$="2" THEN BEEP .01,10: GO TO 330 1200 NEXT f 1210 CLS : GO TO 1680 1220 CLS : INK 0 1230 PRINT "USE ANY KEY TO SHOOT AT THE"''"TARGETS." 1240 PRINT '"THE GAME WILL END WHEN YOU HAVE"''"NO AMMUNITION LEFT." 1250 PRINT '"IF YOU SHOOT ALL THE TARGETS"''"THEN YOU WILL GET SOME BONUS"''"POINTS AND START AGAIN WITH LESS"''"AMMUNITION." 1260 PRINT ''"PRESS ANY KEY.": RANDOMIZE USR 60100: BORDER 0 1270 PAUSE 0: CLS 1280 PRINT "WHILST YOU ARE PLAYING THE GAME"''"YOUR GUN WILL MOVE BACKWARDS"''"AND FORWARDS ACROSS THE"''"BOTTOM OF THE SCREEN JUST TO "''"MAKE THINGS HARDER." 1290 PRINT '"REMEMBER TO ALLOW FOR THE DELAY"''"BEFORE THE BULLET REACHES THE"''"TARGET." 1300 PRINT ''"PRESS ANY KEY." 1310 RANDOMIZE USR 60100: BORDER 0 1320 PAUSE 0: CLS 1330 PRINT "\c \c \c \c \c 100 POINTS"'"\d\e \d\e \d\e \d\e \d\e EACH" 1340 PRINT '"\f\h \f\h \f\h \f\h \f\h 200 POINTS"'"\g\i \g\i \g\i \g\i \g\i EACH" 1350 PRINT '"\j\l \j\l \j\l \j\l \j\l 300 POINTS"'"\k\m \k\m \k\m \k\m \k\m EACH" 1360 PRINT '"\n\o \n\o \n\o \n\o \n\o 400 POINTS"'"\p\q \p\q \p\q \p\q \p\q EACH" 1370 PRINT '"\r\s \r\s \r\s \r\s \r\s 500 POINTS"'"\t\u \t\u \t\u \t\u \t\u EACH" 1380 PRINT '"\c \f\h \j\l \n\o \r\s 600 POINTS"'"\d\e \g\i \k\m \p\q \t\u EACH" 1390 PRINT ''"PRESS ANY KEY." 1400 RANDOMIZE USR 60100: BORDER 0 1410 PAUSE 0: INK 7: CLS : GO TO 1120 1420 FOR f=7 TO 0 STEP -1: POKE 59990,f: RANDOMIZE USR 60250: BEEP .01,f*2: PAUSE 10: NEXT f: BORDER 0: BEEP .2,-20: CLS 1430 IF sc>h(5) THEN GO TO 1470 1440 PRINT FLASH 1;AT 8,8;"YOU SCORED ";sc 1450 PRINT INK 7;AT 16,9;"PRESS ANY KEY." 1460 PAUSE 0: GO TO 1110 1470 LET h$(5)="": PRINT " PLEASE ENTER YOUR NAME" 1480 PRINT AT 10,10;"----------": PRINT AT 15,8;"YOU SCORED ";sc 1490 LET g=1 1500 PAUSE 0 1510 LET l$=INKEY$: BEEP .005,10 1520 IF l$=CHR$ 13 THEN GO TO 1580 1530 IF g>1 AND l$=CHR$ 12 THEN LET h$(5,g)="": PRINT CHR$ 8;"-";CHR$ 8;: LET g=g-1: GO TO 1500 1540 LET h$(5,g)=l$ 1550 PRINT AT 10,g+10;l$; 1560 LET g=g+1 1570 IF g<11 THEN GO TO 1500 1580 CLS 1590 LET h(5)=sc 1600 LET zx=4 1610 FOR f=1 TO zx 1620 IF h(f)>=h(f+1) THEN GO TO 1650 1630 LET v=h(f): LET h(f)=h(f+1): LET h(f+1)=v 1640 LET v$=h$(f): LET h$(f)=h$(f+1): LET h$(f+1)=v$ 1650 NEXT f 1660 LET zx=zx-1 1670 IF zx>0 THEN GO TO 1610 1680 PRINT AT 0,2; INK RND*6+1;"▐▐▗▘ ▐▐▗▐▐ ▐ ▗▐▗▘ ▗▘▗▐▗▗▐▗▘ ▜▘▗ ▗▐▗▐▐ ▐ ▐▐▗ ▗ ▗▐▐▐▐▗ ▝ ▀▘ ▘▘▘▘▀▘▀▘ ▀▘▘ ▘ ▘▘▘▘▘▀▘" 1690 FOR f=1 TO 5: PRINT INK f+2;AT (f*2)+3,0;f;"-------- ";h$(f);AT (f*2)+3,21;" ---- ";h(f): NEXT f 1700 PRINT AT 18,5;" PRESS ANY KEY. " 1710 FOR f=0 TO 1000 1720 IF INKEY$<>"" THEN GO TO 320 1730 NEXT f: GO TO 1110 1740 STOP 1750 SAVE /"RIFLE" LINE 10 1760 RESTORE 1760 1770 DATA 17,64,156,33,0,64,1,0,27,237,176,201,17,0,64,33,64,156,1,0,27,237,176,201,33,0,88,1,0,3,197,62,0,1,100,0,11,60,211,254,120,177,32,248,54,7,35,54,54,193,11,120,177,32,231,201,32,228,201 1780 FOR f=60000 TO 60134 1790 IF F=60012 OR F=60062 THEN LET F=F+38 1800 READ a: POKE f,a: NEXT f 1810 DIM h(5): DIM h$(5,10) 1820 FOR f=1 TO 5: LET h(f)=6000-(f*1000) 1830 LET h$(f)="SPECTRUM": NEXT f 1840 FOR f=60200 TO 60266: IF F=60242 THEN LET F=F+8 1850 READ a: POKE f,a: NEXT f 1860 DATA 1,2,0,197,33,0,64,1,0,4,126,15,119,35,126,7,119,35,11,120,177,32,243,193,11,120,177,32,1,201,33,0,80,120,177,197,1,0,4,32,225,201,33,0,88,1,0,3,58,86,234,119,35,11,120,177,32,246,201 1870 REM UDG's 1880 LET x=VAL "(PEEK 23637+PEEK 23638*256)+6": POKE 23675,FN l(x): POKE 23676,FN h(x): RETURN 1890 REM lACS ACS ACS ACS ACS ACS ACS ACS ACS ACS ACS ACS ACS ACS ACS .FREE <>STICK DRAW DRAW SAVE SAVE LIST LPRINT DH\b\c\c\bHD#USR 0BIN "II▞BIN 0USR COPY COPY USR USR USR SAVE COPY COPY SAVE USR USR USR *D@©@ LPRINT FN D DRAW 5I▝ COPY 0@USR 8$ RETURN COPY ? USR USR COPY DRAW LPRINT LPRINT LIST p8 ```