Night Gunner

Products: Night Gunner
Date: 1982
Type: Cassette
Platform(s): TS 1000
Tags: Arcade, Game

Night Gunner is a shooting game that uses machine code (invoked via RAND USR 20337) for its core gameplay loop, with BASIC handling initialization, display setup, and high-score management. The program uses LPRINT and AT/TAN/FAST/SLOW idioms embedded within REM statements to store and execute encoded data and machine code routines. Block graphics characters are used extensively to render the game’s visual elements, including the playfield and aircraft graphics. The BASIC loader REMs at lines 5, 10, 15, and 20 contain densely packed tokenized data that serves as both the machine code payload and display rendering instructions. A high-score table with named entries is maintained and displayed using formatted LPRINT output.


Program Analysis

Program Structure

The program consists of five lines: four large REM blocks (lines 5, 10, 15, 20), a SAVE command at line 25, and the machine code entry point at line 30. The actual game engine resides entirely within machine code that is stored as tokenized data inside the REM statements. The BASIC program’s sole runtime purpose is to invoke that machine code via RAND USR 20337 at line 30.

REM-as-Data Technique

This is a classic loader pattern: the four REM lines (5, 10, 15, 20) hold raw bytes — machine code, lookup tables, sprite data, and string resources — in positions immediately following each REM token in memory. Because the ZX81/TS1000 stores the entire line including REM body verbatim in RAM, arbitrary byte sequences can be embedded there and accessed by absolute address. The RAND USR 20337 call jumps directly into this binary payload.

Key BASIC Idioms

  • RAND USR 20337 — transfers control to machine code at the fixed RAM address where the REM data begins; this is the canonical ZX81/TS1000 machine-code launch technique.
  • VAL "number" used in GO TO / GO SUB targets within the encoded data — a standard memory-saving idiom.
  • Block graphics characters (▘▝▖▗▌▐▀▄▛▜▙▚▟█) are embedded directly in the REM data to represent sprite and playfield tiles.
  • FAST / SLOW tokens appear inside the REM data, consistent with the machine code using them as byte values rather than executed BASIC commands.
  • LPRINT, AT, TAN, COPY, and SAVE tokens visible in the disassembly are tokenized bytes being repurposed as data, not executed BASIC statements.

Display and Graphics

The title screen text visible in the REM data includes the strings [P][R][E][S][S], [R][U][N], [T][O], [P][L][A][Y], [B][E][S][T][S][C][O][R][E][O][F][T][H][E][D][A][Y], and a mission identifier [-][M][I][S][S][I][O][N][-][-][-][-][1]. These are rendered by the machine code using direct screen writes. The dense block-graphic sequences in line 5’s REM body represent the game’s visual scenery or sprite frames for the night sky and gun/aircraft imagery.

High Score System

Evidence within the REM data shows variables named M[O], M[P], M[Q] used alongside LPRINT tokens and ACS/LN arithmetic sequences, consistent with a three-entry high-score table. Score comparison and conditional branching sequences (visible as IF, GOSUB, RETURN tokens) manage table updates. The SAVE "NG" at line 25 persists the program (including any modified REM data holding scores) back to tape.

Notable Techniques

  • Scores and game state are preserved between sessions by saving the entire program — modified REM bytes act as non-volatile storage without a separate data file.
  • The use of GOSUB PI, GOSUB [K], GOSUB [R] patterns in the REM data are BASIC tokens whose numeric values serve as operands or subroutine-vector bytes in the machine code, not actual BASIC subroutine calls.
  • Sprite movement and collision detection are handled entirely in Z80 machine code, keeping gameplay fast despite the inherently slow BASIC interpreter.
  • Multiple COPY tokens in sequence within the data (e.g., COPY3> COPY3> COPY$+) suggest screen-copy or buffer-flip operations driven by the machine code.

Anomalies and Observations

  • The trailing 00000000000 sequences at the end of lines 10 and 20 are padding bytes (zero is the FORMAT token on ZX81, harmless as data) used to align or fill the REM block to a required length.
  • Line 5’s REM contains what appears to be a copyright notice: (C)DIGITAL INTEGRATION 1982 — confirming commercial authorship and dating the binary.
  • The DIM Y token sequence in line 10’s data suggests the machine code sets up array storage for game variables at runtime.

Content

Appears On

Related Products

You peer into the inky black sky from your position as tail gunner in a bomber plane, searching for enemy...

Related Articles

Related Content

Image Gallery

Source Code

   5 REM (C)DIGITAL INTEGRATION 1982##Y█LN 7#LN  GOSUB PILN CHR$ RNDE£RND▘▞ \,, FOR ▘= 5[M]INKEY$  GOSUB [K]E£RND▘[T]▝\,, FOR ▘+ 5LEN INKEY$  GOSUB [K]E▐#6#RND FOR 7LN [-]#TAN E£RND▘# \,,##▘) 5TINKEY$  GOSUB [K]##▘( \,,##▘) 5#INKEY$  GOSUB [K]##▘( \,,##▘) 5#INKEY$  GOSUB [K]E£RND▘+▝\,,##▘* 5#INKEY$  GOSUB [K]##▘\~~ \,,##▘* 5▄INKEY$  GOSUB [K]##▘\~~ \,,##▘* 5[,]INKEY$  GOSUB [K]TAN ▌▜▌█▌█▌▄▟█▌█▐█▙▖▄▌▙▘█▌█▌▙▐█▌▄▐██▌█▙█▙█▙█▙▄▟█▙█▟██▙█▀▀██▜▛██▜█▜█▛█▛██▀▀██▀▜▐▀██▐▌██▗▜▐█▌▞▌██▝███▝▟▝▘██▞▚██▐▙▐█▌█▖██▝▀██▐▞ [P][R][E][S][S]██[R][U][N]██[T][O]██[P][L][A][Y][B][E][S][T]█[S][C][O][R][E]█[O][F]█[T][H][E]█[D][A][Y] FASTVAL Y[-]#7Y[O]#7Y[-]#▘6 [R] GOSUB PIY[.]#\,,FF▞ COPY:=$4 CLEAR( RAND Y█#7#7#▘6 [R] GOSUB PI#LN  GOSUB PIAT  LPRINT U9RNDACS #"" LPRINT  TAN LN [3]RNDE£RND▘# \,,▞0)5 LN <=INKEY$ 7( IF ▞▞LN <=INKEY$ ;( IF ▞.LN <=INKEY$ F( IF ▞£LN <=INKEY$ ;( IF ▞.LN <=INKEY$ 7( IF ▞$LN <=INKEY$ [R] GOSUB #( SAVE ▞/LN <=INKEY$ F( IF ▞▌LN <=INKEY$ [R] GOSUB #( SAVE ▞"LN <=INKEY$ 7( IF FY[-]#7Y[O]#7Y[-]#▘6 [R] GOSUB PIY[.]#Y:MQRNDY▝MRRNDLN  UNPLOT #   LN [3]RNDE£RND▘# \,,)5 ▞/LN <=INKEY$ F( IF ▞▒LN <=INKEY$ ;( IF ▞;LN <=INKEY$ 7( IF ▞\~~LN <=INKEY$ ;( IF ▞.LN <=INKEY$ F( IF ▞\~~LN <=INKEY$ [R] GOSUB #( SAVE ▞:LN <=INKEY$ 7( IF Y[O]#LN ABS #LN  GOSUB PI   #;PI FASTVAL E£RND▘ RUN  Y[.]\,,#▘5 \,,#\,,#\,,\,,#\,,#\,,#▘# [R] GOSUB PIY[-]#7#7#7Y[+]#7Y[-]#7#7#AT  LPRINT TAN  FASTVAL E£RND7▞-:4#7$4 CLS7( PLOT AT  LPRINT TAN  FASTVAL E▄# GOSUB #▟#▞ \,, GOSUB #▙#▞ [R] GOSUB PI▘# \,,6▄#LN ##Y#   AT  LPRINT TAN  FASTE▄#6#RNDE£RND7LN [-]# LPRINT TAN  FASTSTR$ E▐#6#RNDE£RND): ;LN [-]#SGN  LPRINT TAN  FASTSTR$ E£RND)0 ;U[R]#LEN [0]#SGN  LPRINT TAN STR$ VAL  FAST[J]M[O]#M[P]#M[Q]#5## GOSUB ##RND▞(ACS #CA# FAST5[Q]#▚B LPRINT M[Q]#7# FAST5[P]#[:]B LPRINT M[P]#7# FAST5[O]#[:]B LPRINT M[O]#7/▀777ACS 7ACS >(LN U[O]# NEW?4OY█ LPRINT #7U[P]#ACS ZACS ZACS ZACS Z4MY█#7U[P]# NEW?4KY█#7U[Q]#ACS ZACS ZACS ZACS Z4IY█#7/GLEN [0] LPRINT #7U[P]#ACS ZACS ZACS ZACS ZLEN [0]#7U[P]# NEW?LEN [0]#7U[Q]#ACS ZACS ZACS ZACS ZLEN [0]#7U[Q]# NEW?LEN [0]#AT SGN TAN #B▀▜#▘[>]▟ [-]RND #4 8( >▌ #▝ C▘ #  M  -  ▒  ▖  ▝  ▘  ##     3 "\,,::\~~£." COPY3> COPY3> COPY$+ COPY3+)4+████[3]▘ #(9 ▀▒▞▀ :▖▛   ▀ UNPLOT #,[S]###TAN 00000000000
  10 REM ## FASTLN 9#LN  PLOT #LN  TO # LPRINT TAN  FASTURRNDLN ▖#UQRNDLN 2#Y[-]#7Y[O]#7Y[-]#VAL ▘6 [R] GOSUB PIAT Y[.]# LPRINT TAN VAL STR$ E£RND7#- ▞▌ACS 7ACS >( IF #▞ \,, GOSUB #SGN AT TAN STR$ #- ;SGN TAN  FAST# RETURN 4\~~5RRNDOLN INT ##[K]# RETURN▘4\~~5RRNDPLN SIN ##[K]# RETURN▝4\~~5QRNDOLN [Z]##[K]# RETURN▀4\~~5QRNDPLN [Q]##[K]# RETURN▖4)5QRNDPLN [Q]#5RRNDPLN SIN ##[K]# RETURN▌4)5QRNDOLN [Z]#5RRNDOLN INT ##[K]# RETURN▞4)5QRNDOLN [Z]#5RRNDPLN SIN ##[K]# RETURN▛4:5QRNDPLN [Q]#5RRNDOLN INT # LPRINT ▌ATN NOT #TAN ACS #COS Q LN NOT #TAN #CHR$ 2 SAVE Q1/ POKE #CHR$ ▝ LIST Q▝/ GOTO #CHR$ + SAVE Q=/ SLOWUORNDACS Z FAST5[E]#[I]▞▌ACS ?( UNPLOT # NEW?LEN ▀# GOSUB #ACS ? NEW▛# LPRINT TAN  FASTVAL  GOSUB #9RND5 COPY COPY[R] GOSUB PIASN L#5 LOAD  TO [R] GOSUB PI4?5RRNDAT PPLN O#LN SIN ##M#5 LOAD  LOAD [R] GOSUB PI4?5RRNDAT OOLN RND#LN INT ##M#5 LOAD  RUN [R] GOSUB PI4?5QRNDAT PPLN ##LN [Q]##M#5 RUN  TO [R] GOSUB PI4?5QRNDAT OOLN ##LN [Z]##M#5 SCROLLINT [R] GOSUB PI4,5QRNDAT OOLN ##LN [Z]#5RRNDOOLN RND#LN INT ##M#5 LOAD NOT [R] GOSUB PI4,5QRNDAT PPLN ##LN [Q]#5RRNDPPLN O#LN SIN ##M#5 LOAD  SCROLL[R] GOSUB PI4,5QRNDAT PPLN ##LN [Q]#5RRNDOOLN RND#LN INT ##M#5 SCROLL TO [B] GOSUB PI4,5QRNDAT OOLN ##LN [Z]#5RRNDPPLN O#LN SIN ##M#5 FOR <>[B] GOSUB PIASN $#5 FOR  GOSUB [B] GOSUB PIASN 8#5 FOR  PRINT [B] GOSUB PIASN V#5 NEXT <>[B] GOSUB PIASN ##5 STOPLN [B] GOSUB PIASN ##5 FOR STR$ [B] GOSUB PIASN ["]#5 FOR  FAST[B] GOSUB PIASN [H]#5 STOP<>[B] GOSUB PIASN INT #AT  LPRINT TAN # RETURN▛COS  RETURN COS  RETURN▌COS OTAN # RETURN▖COS  RETURN▘COS  RETURN▞COS PTAN # RETURN▞COS  RETURN▝COS  RETURN▌COS OTAN # RETURN▖COS  RETURN▀COS  RETURN▛COS PTAN VAL ▞COS :$$4 CLEAR( RAND AT TAN VAL ▞ COPY:M$4 CLEAR( RAND AT TAN VAL ▞▞[J]LN 7#Y█LN [.]#LN ##Y█LN 7#[J]LN [.]#LN ##( NEWAT TAN  FASTVAL STR$ E£RND▘[C] \,,LN £#E£RND▘[H] \,,LN £#E£RND▘[M] \,,LN £#E£RND▘[U] \,,LN £#E£RND▘TAB  \,,▞£LN :#E£RND▘[R] \,,▞▒#7( UNPLOT ▘4 \,,▞▒#F( UNPLOT E£RND▘#▘\,,#7#7#▘5 \,,#F#F#E£RND▘#▝\,,#7#SGN AT  LPRINT TAN ▞:)4 #7#;( IF TAN 5[<]#▞▖# RETURN█4▀Q[-]7( PLOT Y>E£RND)#▘; FOR 5▗#▘▘ STR$  FASTVAL  GOSUB [K]AT  LPRINT SGN ▀ RETURN>ATN [T]# RETURN>CODE [;]#.X4 DIM Y:▘> STR$  FASTVAL  GOSUB [K]AT  LPRINT SGN  RETURN▒ATN ##LN [;]#.X4 GOTO Y)▘) <7STR$  FASTVAL  GOSUB [K]AT  LPRINT SGN ". RETURN)ATN [;]#< RETURN)CODE [T]#X4 SCROLLTAN [(]O▘[<][-][M][I][S][S][I][O][N][-][-][-][-][1]█ FASTVAL ##▘4 [R] GOSUB PI▞▝:[X]#LN ##:[+]#LN ##( PAUSE :█#AT  LPRINT TAN VAL ▞▖LN ##( CLSAT TAN VAL ▞▌LN [;]#( CLSAT TAN LN ▄#( PAUSE :█#AT  LPRINT TAN VAL ▞▖LN ▄#( CLSAT TAN VAL ▞▌LN [S]#( CLSAT TAN Y▞M>=ZMRRND##Y█XXMT##MYPU#MPTAN 
  15 REM ## FASTVAL STR$ 5[▒]#ACS #C\,,E[~~]#6QRNDLN ##5[▒]#ACS #C\,,E[£]#6QRNDLN ##5[▒]#ACS #C\,,E[:]#6QRNDLN ##5[▒]#ACS #C\,,E[(]#6QRNDLN ##LN  GOSUB PI5[▒]#ACS #CYE[~~]#6QRND GOSUB #[G]##LN PEEK #EQRND6[~~]## GOSUB #[G]# FAST5▗#ACS # LPRINT 40#CHR$ < PAUSE [;]## RETURN▘4)G#M[+]#M[-]##M[*]#5▗#ACS EXP 5[▒]#ACS #CYE[£]#6QRND GOSUB #[I]##LN PEEK #EQRND6[£]## GOSUB #[I]# FAST5▗#ACS # LPRINT 40#CHR$ < PAUSE  THEN## RETURN▘4)G#M[/]#M[;]##M[,]#5▗#ACS CHR$ 5[▒]#ACS #CYE[:]#6QRND GOSUB #[K]##LN PEEK #EQRND6[:]## GOSUB #[K]# FAST5▗#ACS # LPRINT 40#CHR$ < PAUSE 7## RETURN▘4)G#M[.]#M[0]##M[1]#5▗#ACS  THEN5[▒]#ACS #CYE[(]#6QRND GOSUB #[M]##LN PEEK #EQRND6[(]## GOSUB #[M]# FAST5▗#ACS # LPRINT 40#CHR$ < PAUSE ### RETURN▘4)G#M[2]#M[3]##M[4]#5▗#ACS  NEWSGN AT  LPRINT TAN URRNDLN ▖#UQRNDLN 2#Y█#7#7#▘6 [R] GOSUB PI#TAN  FASTVAL  GOSUB #9RND      5 FOR <>LN ATN #5 FOR  GOSUB LN ATN #5 FOR  PRINT LN ATN #5 NEXT <>LN ATN #5 STOPLN LN ATN #5 FOR STR$ LN ATN #5 FOR  FASTLN ATN #5 STOP<>LN ATN #5 CLS CLEARLN ATN #AT  LPRINT TAN [R] GOSUB PI""U[C]#[R]COS 5▗#ACS #""CHR$ ▝M[C]#ACS LEN LN  NEW#TAN  FASTVAL E£RND▘[Q]▝\,,Y[A]#7Y[M]#7#7Y[O]#U[C]#[R]C£ACS JACS JW#Y[▒]7#( UNPLOT U[C]#ACS JACS JW#Y0[(]#Y█7#( UNPLOT AT  LPRINT TAN  FASTVAL STR$ E[S]# GOSUB #[U]#-  GOSUB #[V]#[R] GOSUB PI PAUSE PI#E[S]#LN [F]#/▞E[S]#[R] GOSUB #▘6 [R] GOSUB PI;..6[S]##M[U]# GOSUB #[X]#[R] GOSUB PI PAUSE ##LN [N]#5▗#ACS ▚/VE[S]#▘# [R] GOSUB PI FAST GOSUB #[X]#[R] GOSUB PI LPRINT  IF [-]#Y▞# GOSUB #[U]#- ....[R] GOSUB #Y▚#/)E£RND)#▘;# RETURN[+]C▌5▗#ACS  INPUT SGN AT  LPRINT TAN [R]Y█# GOSUB ##TAN  FASTVAL E£RND▘=▀\,,6[S]#▘# [R] GOSUB PI6[V]#Y,M[U]#E£RND▘#▘\,,6[X]#5▗#ACS ▚AT  LPRINT TAN  FASTVAL E£RND▘T▘\,,#▘4 \,,#77#\,,#AT  LPRINT TAN  FASTVAL E£RND▘ RUN  \,,#▘3 \,,#▘▖ \,,#▘X \,,#▘▞ \,,#▘X \,,#▘▖ \,,#▘3 \,,#AT  LPRINT TAN  FASTVAL E£RND▘[=] \,,#▘2 \,,#▘▞ \,,#▘U \,,#▘\~~ \,,#▘# \,,#▘£ \,,#▘# \,,#▘\~~ \,,#▘U \,,#▘▞ \,,#▘2 \,,#AT  LPRINT TAN  \,,#▘▞ \,,#▘2 \,,#AT  LPRINT TAN 00
  20 REM ##VAL  FAST)[>]#▘▀  GOSUB [K]U[>]##U[<]#[G]CEU[=]#CHR$ + PAUSE  TO #U[=]#LN ▖# FASTU[>]#ACS #4▞LN 2#Y█# LPRINT U[<]# RETURN4C▞LN 2#Y█#5[>]#PLN 6#5[<]#OLN C#5[=]#O#5▗#ACS [Y]CHR$ + IF  PRINT #5▗#ACS  RETURNU[C]#[R]C▛U▟#ACS #CAACS  PLOT /6U[=]#LN ▖# FASTU[>]#ACS #4▞LN 2#Y▚# LPRINT U[<]# RETURN4C▞LN 2#Y▞#5[>]#SGN ▘▀  GOSUB [K]AT TAN ACS #COS Q COPYTAN #CHR$ 4 SAVE Q4TAN  FASTSTR$ U[,,]#[R]TAB ▘#5[▒]#U["]# RETURN\~~C▞ RETURN"40/"U[~~]# RETURN$C" RETURN?C▛U[~~]# RETURN:4▒ACS [:][J]M[~~]#/#U[$]# RETURN\~~C▞ RETURN"40/"U[£]# RETURN$C" RETURN?C▛U[£]# RETURN:4▒ACS [-][J]M[£]#/#U[?]# RETURN\~~C▞ RETURN"40/"U[:]# RETURN$C" RETURN?C▛U[:]# RETURN:4▒ACS [2][J]M[:]#/IU[)]# RETURN\~~C▞ RETURN"40/"U[(]# RETURN$C" RETURN?C▛U[(]# RETURN:4▒ACS [A][J]M[(]#/▛5▗#ACS [I]/#U[,,]# RETURN 40E£RND)S▘;Y█#77#LN  GOSUB PIY[*]LN  TO #5[,,]#ACS EXP /#ACS #4£Y[*]LN  PLOT #5[,,]#ACS CHR$ /RNDACS #4£Y[*]LN A#5[,,]#ACS  THEN/KY█LN  TO #LN  PLOT #LN A#LN  GOSUB PI5▗#ACS [I]5[,,]#Q 5[▒]#ACS #ATN S#Y#M▟#U[▒]# RETURN▘4▖[J]M[▒]#SGN  LPRINT TAN  FASTVAL STR$ U[D]##5▗#ACS #CODE 8#5▗#ACS #C▀LN J#ACS #C)5[+]#LN ▜#5▗#ACS #C▖ACS [Y]ACS [:]ACS #C)5[/]#LN ▜#5▗#ACS #C▖ACS [Y]ACS [-]ACS #C)5[.]#LN ▜#5▗#ACS #C▖ACS [Y]ACS [2]ACS #C)5[2]#LN ▜#5▗#ACS #C▖ACS [Y]ACS [A]VAL ▞ COPYY▞X4 CLEAR( RAND AT ([$]SGN AT  LPRINT TAN  FASTVAL LN [N]#▞$LN 8#LN ##( SAVE ▞▖Y?M[~~]#Y\~~M["]#[J]M[,,]#LN J#LN ##( SAVE AT  LPRINT TAN  FASTVAL Y?M[+]#M[-]#Y▝M[*]#▞(5[+]#LN ▜#LN ##( PRINT LN ##AT  LPRINT TAN LN NOT ## GOSUB #[G]#LN ## GOSUB #[~~]#LN NOT ## GOSUB #[I]#LN ###LEN ▀# GOSUB #[£]#LN NOT ## GOSUB #[K]#LN ###LEN ▝# GOSUB #[:]#LN NOT ## GOSUB #[M]#LN ###CHR$ ▝# GOSUB #[:]#TAN #▙##ACS BLEN ▀#TAN 5  6▐#5  6▄#6[A]#5[▒]#ACS  RETURNY#M▙#Y)M[D]#Y▀M[R]#LN [N]#LN ;PIY3M[▒]#U▙# RETURN+C$CHR$ ▛M▙#U[D]#CHR$ ▘M[D]#Y#M▟#E[A]#76[A]#6#RND5[<]#LN [-]#LN ##Y#M[C]#[J]M▗#M[,,]#Y█LN 7#LN  GOSUB PILN ##LN ##LN ▜#LN  NEW#LN 2#LN ▗#U▗# RETURN C▌LN ##/\~~▞ COPYU▙#X4 CLEAR( SAVE U[▒]# RETURN C[£]5▗#ACS #435▟#PLN :# GOSUB #9RND5[U]<=[R] GOSUB PI4▘TAN 5 RETURN NEXT [R] GOSUB PI4[X]###LN ##U[R]#XC"M[R]#Y#M▟##ACS #E▐# GOSUB #▄##[G] IF ##[R] GOSUB # PAUSE ##E▄#6▐####Y█LN 7#LN ##LN ##LN ▜#LN /#TAN ▒  ▖  ▝  ▘    ▞   42 ;=▀=▌▝\~~"   ;;£??)▖▖▒               ▒▀▝▝▒▀▒    [9]#,##"#TAN 00000000000
  25 SAVE "N[G]"
  30 RAND USR 20337

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top