Marine Rescue

Products: Marine Rescue
Date: 1982
Type: Cassette
Platform(s): TS 1000
Tags: Game

Marine Rescue is an action game in which the player dives underwater to rescue sailors from a sunken submarine while avoiding sharks and managing an oxygen supply. The game uses six REM lines at the start (lines 1–6) to store Z80 machine code routines that handle movement, collision detection, scoring, and shark behavior, accessed via USR calls to specific memory addresses such as 16531, 16676, and 16914. A DIM array M$(38,62) holds 37 humorous taunt and congratulation messages that are randomly selected based on the player’s score range at game over. The score is tracked by reading two consecutive memory locations (PEEK 16518 and PEEK 16519) to reconstruct a 16-bit value, while the oxygen countdown is maintained in PEEK 16521 and displayed in real time. Block graphics characters are used to render the underwater scene, safety zone, oxygen tank, submarine, and seabed decorations entirely within PRINT AT statements.


Program Analysis

Program Structure

The program is organized into several distinct functional regions:

  1. Lines 1–6: REM lines storing Z80 machine code routines (~200 bytes total).
  2. Lines 7–35: Initialization — variables, screen setup, POKE configuration of machine code parameters.
  3. Lines 40–450: Main game loop in two phases (200 iterations then 100 iterations), with increasing shark frequency.
  4. Lines 452–499: Time-expired and stop handlers.
  5. Lines 500–699: Scene-drawing subroutine.
  6. Lines 800–870: Diagnostic/development utilities (POKE loop and memory dump), left in the final listing.
  7. Lines 900–1099: Death/end-of-game handling, score display, and play-again logic.
  8. Lines 1100–1199: Message array initialization (M$) and flag reset.
  9. Lines 1600–1650: Unused collision-test stub.
  10. Lines 3000–3690: Title screen, instructions, and scrolling intro sequence.
  11. Lines 4000–5020: Delay and keypress wait subroutines.
  12. Line 9000: SAVE and restart.

Machine Code Usage

Six REM lines (1–6) hold Z80 machine code, loaded into the system RAM area starting around address 16384 (the start of the ZX81 display file region offset). The routines are invoked via USR calls throughout the main loop:

USR AddressApparent Role
16531Shark collision / player movement handler (returns 45 on hit)
16676Secondary event check (returns 41 on trigger)
16914Oxygen depletion check (returns 40 when empty)
16557Collision test stub called from line 1610

The machine code uses POKE’d parameters before each USR call: POKE 16514,C and POKE 16515,R pass the player’s column and row coordinates; POKE 16521,60 sets the initial oxygen count; POKE 16783,38 and related POKEs configure sprite or movement data. The score is maintained as a 16-bit value by the machine code at addresses 16518–16519.

Key BASIC Idioms

  • Score reconstruction: LET SC=PEEK 16518+256*PEEK 16519 reads a little-endian 16-bit integer maintained by the machine code.
  • Decade display filter: IF PEEK 16521=(INT (PEEK 16521/10))*10 updates the oxygen counter display only on multiples of 10, reducing flicker.
  • Keypress wait: Lines 5000–5020 implement a two-stage INKEY$ debounce: first wait for the key to be released, then wait for a new press.
  • Random positioning: Shark print positions use INT (RND*10)+5 and similar expressions; in phase 2 (lines 310–450) positions are snapped to even rows with (INT (RND*5))*2+6.
  • Z$ padding string: LET Z$=" " (32 spaces) is reused throughout for clearing screen lines.
  • High-score persistence: HS is never reset between games within a session; it survives replays via the GOTO 11 branch.

Message System

DIM M$(38,62) allocates a 38-row by 62-character string array. Rows 1–5 are oxygen-death taunts, rows 6–10 are low-score insults, rows 11–32 are score-tier messages, and rows 33–37 are shark-death messages. Row 38 is allocated but never explicitly assigned. Score tiers are:

Score RangeMessage Rows
0–1006–10 (random 5)
101–50011–15 (random 5)
501–100016–20 (random 5)
1001–200021–25 (random 5)
2001+26–33 (random 8)

Notable Techniques

  • The submarine’s horizontal position is randomized at startup via LET Z=(INT (RND*17))+1 and passed to the scene-drawing subroutine at line 500, making the rescue target appear at a different column each game.
  • The two-phase loop structure (200 then 100 iterations at lines 90 and 310) increases game pressure: phase 2 adds sharks on the left side (PRINT AT ... ,0) and checks a different USR address (16939 vs. 16531), suggesting a second machine code scan path for phase 2.
  • SLOW at line 40 and FAST at line 1067 are used deliberately: the game runs in SLOW mode for display sync during play, then switches to FAST for the title/intro sequence after a replay.
  • Lines 800–870 are clearly development artifacts — a POKEing INPUT loop and a PEEK memory dump with PAUSE 40000 — left in the shipped listing.
  • Line 135 is an exact duplicate of line 134 (IF USR 16531=45 THEN GOTO 950), which appears to be an unintentional copy.
  • Line 1038 (M$(38)) is dimensioned but its slot is never assigned, leaving it as blank padding.
  • The GOSUB at line 3575 calls line 1100 mid-intro solely to initialize the M$ array, then returns to continue the instructions sequence — a deferred data-initialization pattern.

Bugs and Anomalies

  • Duplicate line 134/135: The shark-collision check is issued twice in succession with identical conditions, meaning a hit at that point triggers two GOTOs (the first fires). This is harmless but redundant.
  • Line 1038 dead slot: M$(38) is allocated in the DIM but never populated; if somehow selected, it prints 62 spaces.
  • Developer utilities in release: Lines 800–870 provide full memory inspection and POKE-entry tools with no protection, accessible simply by RUNning from line 800.
  • Line 1600–1650 unreachable stub: The subroutine starting at 1600 is never called from the main game flow, and likely represents an earlier collision-detection approach superseded by the machine code.
  • M$(37) is the last assigned row but the array is DIM’d to 38 rows; the shark-death random picker uses INT (RND*5+33) which can return values 33–37, safely within bounds.

Content

Appears On

Related Products

Your ZX81 becomes the command console as a diver descends to the sunken submarine Nautilus to rescue as many of...

Related Articles

Related Content

Image Gallery

Marine Rescue

Source Code

   1 REM 1C41650000002AE404E60C9ED4B8240CCDF58CD8C403E13B920412D0C903A8F415F176A2A10402B7EB928218F910F7176A1602B7EBB28FBB9284725718F410F0C924251C
   2 REM ED4B8440C3E4B8381C93EFB8301C9ED43844079FE1D281FCDF58AFD7CD8C40B92053E17D718D6111902A864019228640AFD7D7D7C9CDF58AFD7D7C9C9222324251C
   3 REM CDBB27DFEFF201C9444DCDBD77EED4B8240FE33208ED438440CDD840C9FE3B208ED438440CDB142C9FE21208AFB9201C9D181AFE242093E1FB9201C9C18DFE222034186FE23281C95C5CDF58CD8C40AFB9205FED4B8240CDF58AFD7C1C5CDF583E26D7C1ED4382403E4B8202E3E7B93853E3C3289403E18B9301F3A8F41573E32BA2016119602A8640192286403E26328F413A88403C3288403E11B820F3ECB92853EDB92053E32328F41C93E12B928B3CB92873E38B9282C1C9C1AF473E294FC92020202020202021212121212121212121212121212121
   4 REM 3A89403D32894057AFBA2031280C9232425
   5 REM ED4B8240C5CCDF58CD8C403E13B928FC1DCDF58CD8C403E12B9283185C112D0C93A8F415F17652AC40237EB928218F910F7176A160237EBB28FBB9284725718F45237EB928218F910E8176A2A10402B7EB928218F910F7176A1602B7EBB28FBB9284725718F452B7EB928218F910E8C91F1F1F
   6 REM ED4B8440D3E4B8381C93EFB8301C9ED438440D79FE2281BCDF58CD8C40AFB92073E17D7AFD718D4111902A864019228640ED4B8440DDDCDF58AFD7D7D7D7D7C91E1F2021222324251C1D1E1F2021222324251C
   7 LET HS=0
   8 LET Z$="                                "
   9 GOSUB 3000
  11 IF F=1 THEN GOSUB 3640
  13 LET Z=(INT (RND*17))+1
  14 GOSUB 500
  15 LET C=28
  16 LET R=4
  17 LET X=26
  18 LET Y=15
  20 PRINT AT R,C;"A"
  22 POKE 16783,38
  23 POKE 16519,0
  24 POKE 16518,0
  25 POKE 16514,C
  26 POKE 16515,R
  29 POKE 16852,Z+7
  30 POKE 16521,60
  31 POKE 16847,Z+6
  34 POKE 16520,0
  35 PRINT AT 3,3;"60";AT 3,27;"0"
  40 SLOW 
  90 FOR I=1 TO 200
  93 IF PEEK 16521=(INT (PEEK 16521/10))*10 THEN PRINT AT 3,3;"  ";AT 3,3;PEEK 16521
  95 IF USR 16676=41 THEN GOSUB 950
 110 IF USR 16914=40 THEN GOTO 900
 134 IF USR 16531=45 THEN GOTO 950
 135 IF USR 16531=45 THEN GOTO 950
 137 IF USR 16676=41 THEN GOSUB 950
 145 PRINT AT INT (RND*10)+5,29;"<S>"
 151 IF USR 16531=45 THEN GOTO 950
 165 PRINT AT 3,27;PEEK 16520
 170 IF USR 16676=41 THEN GOSUB 950
 180 IF I>100 THEN PRINT AT INT (RND*10)+5,29;"<S>"
 210 IF USR 16531=45 THEN GOTO 950
 230 IF USR 16676=41 THEN GOSUB 950
 260 IF USR 16531=45 THEN GOTO 950
 290 IF USR 16676=41 THEN GOSUB 950
 300 NEXT I
 310 FOR I=1 TO 100
 315 IF PEEK 16521=(INT (PEEK 16521/10))*10 THEN PRINT AT 3,3;"  ";AT 3,3;PEEK 16521
 320 IF USR 16676=41 THEN GOTO 950
 322 IF USR 16914=40 THEN GOTO 900
 333 IF USR 16939=45 THEN GOTO 950
 340 PRINT AT (INT (RND*5))*2+6,29;"<S>"
 345 IF USR 16676=41 THEN GOTO 950
 360 IF USR 16939=45 THEN GOTO 950
 400 PRINT AT (INT (RND*5))*2+5,0;"<S>"
 410 IF USR 16676=41 THEN GOTO 950
 417 IF USR 16939=45 THEN GOTO 950
 420 PRINT AT 3,27;PEEK 16520
 450 NEXT I
 452 CLS 
 455 PRINT AT 0,0;"YOUR TIME HAS EXPIRED."
 460 GOTO 1005
 499 STOP 
 500 PRINT AT 0,24;" .% % % % % % . ";AT 1,24;"%       % ";AT 2,24;"%       % "
 510 PRINT AT 1,25;"SAFETY";AT 3,24;"%       % ";AT 4,24;"%       % "
 520 PRINT AT 0,0;" .############. ";AT 1,0;"##      ##";AT 2,0;"##      ##";AT 3,0;"##      ##";AT 4,0;"##      ##";AT 1,1;"OXYGEN"
 540 PRINT AT 4,8;"................"
 550 PRINT AT 21,0;"% % ####,,@@!!,,!!##:..:..,,..% % % ..,,.::.% % % % % ##,,@@..,,"
 600 PRINT AT 20,Z+1;"% % % % % % % % % :'"
 610 PRINT AT 19,Z;" :";AT 18,Z+1;".:";AT 17,Z+2;".......:  :...... "
 620 PRINT AT 16,Z+5;" :  : ";AT 18,Z+11;":.";AT 19,Z+11;":'"
 630 PRINT AT 19,Z+1;"SUB"
 699 RETURN 
 799 STOP 
 800 FOR I=16642 TO 17050
 810 INPUT A
 820 POKE I,A
 830 IF I=(INT (I/20))*20 THEN CLS 
 835 PRINT I,A
 840 NEXT I
 850 STOP 
 860 FOR I=16600 TO 17100
 863 PRINT PEEK I,I
 864 IF I<>(INT (I/20))*20 THEN GOTO 869
 865 PAUSE 40000
 867 CLS 
 869 NEXT I
 870 STOP 
 900 CLS 
 905 PRINT AT 2,0;"YOUR OXYGEN IS GONE."
 908 LET N=INT (RND*5+1)
 910 PRINT AT 4,0;M$(N)
 920 GOTO 1002
 950 CLS 
 955 PRINT AT 2,0;"YOU WERE A SHARKS DINNER."
 958 LET N=INT (RND*5+33)
 960 PRINT AT 4,0;M$(N)
 970 GOTO 1002
 1000 CLS 
 1002 PRINT AT 0,0;"SORRY, YOU ARE DEAD."
 1005 LET SC=PEEK 16518+256*PEEK 16519
 1008 IF SC>HS THEN LET HS=SC
 1009 PRINT AT 7,5;"% % % % % % % % % % % % % % % % % % % % % % "
 1010 PRINT AT 8,5;"% % % % % % % % % % % % % % % % % % % % % % ";AT 9,5;"% %  SCORE: ";SC;AT 9,25;"% % ";AT 10,5;"% % ";AT 10,25;"% % ";AT 11,5;"% %  HIGH SCORE: ";HS;AT 11,25;"% % ";AT 12,5;"% % % % % % % % % % % % % % % % % % % % % % "
 1011 PRINT AT 13,5;"% % % % % % % % % % % % % % % % % % % % % % "
 1020 IF SC<101 THEN PRINT AT 18,0;M$((INT (RND*5))+6)
 1025 IF SC>=101 AND SC<=500 THEN PRINT AT 18,0;M$((INT (RND*5))+11)
 1027 IF SC>=501 AND SC<=1000 THEN PRINT AT 18,0;M$((INT (RND*5))+16)
 1029 IF SC>=1001 AND SC<=2000 THEN PRINT AT 18,0;M$((INT (RND*5))+21)
 1031 IF SC>=2001 THEN PRINT AT 18,0;M$((INT (RND*8))+26)
 1035 FOR I=1 TO 25
 1036 NEXT I
 1037 PRINT AT 18,0;Z$;Z$
 1040 FOR I=1 TO 6
 1043 SCROLL 
 1045 NEXT I
 1050 PRINT AT 12,2;"I HAVE DECIDED TO GIVE YOU ";AT 14,2;"ANOTHER CHANCE."
 1055 PRINT AT 17,2;"TYPE ""Y"" TO PLAY AGAIN";AT 19,2;"OR ""N"" IF YOU GIVE UP."
 1060 LET L$=INKEY$
 1065 IF L$="" THEN GOTO 1060
 1067 IF L$="Y" THEN FAST 
 1070 IF L$(1)="Y" THEN CLS 
 1073 LET F=1
 1075 IF L$(1)="Y" THEN GOTO 11
 1080 PRINT AT 12,2;"GOOD-BYE SHARK-KILLER.         ";AT 14,0;Z$;AT 17,2;"MAY THE WAVES BE WITH YOU.    ";AT 19,0;Z$
 1099 STOP 
 1100 DIM M$(38,62)
 1101 LET M$(1)="DID YOU THINK YOU COULD HOLD    YOUR BREATH FOREVER?"
 1102 LET M$(2)="YOU ARE NOT A SHARK YOU KNOW.  "
 1103 LET M$(3)="HOW DID YOU EVER BECOME         A DIVER?"
 1104 LET M$(4)="ARE YOU TRYING TO GROW GILLS?  "
 1105 LET M$(5)="YOU DRINK WATER,                YOU DO NOT BREATHE IT."
 1106 LET M$(6)="WERE YOU PLAYING WITH YOUR      EYES CLOSED?"
 1107 LET M$(7)="NEXT TIME TRY THE GAME WHEN     YOU ARE AWAKE."
 1108 LET M$(8)="WITH THIS SCORE, MAYBE YOU      SHOULD TRY TIDDLY-WINKS." 
 1109 LET M$(9)="PERHAPS IT IS PAST YOUR BEDTIME."
 1110 LET M$(10)="I DO NOT THINK I SHOULD LET     YOU PLAY AGAIN."
 1111 LET M$(11)="NOT BAD, NOT GOOD, BUT NOT BAD."
 1112 LET M$(12)="ARE YOU REALLY TRYING?"
 1113 LET M$(13)="MAYBE YOU SHOULD READ THE       RULES OF THE GAME."
 1114 LET M$(14)="ON A SCALE OF 1 TO 10,          I WILL GIVE YOU A 0."
 1115 LET M$(15)="IT IS OBVIOUS THAT YOU DO NOT   DO THIS FOR A LIVING."
 1116 LET M$(16)="YOU ARE PRETTY GOOD AT THIS     GAME."
 1117 LET M$(17)="DOES YOUR BOSS KNOW HOW MUCH    TIME YOU SPEND PLAYING GAMES."
 1118 LET M$(18)="DO NOT QUIT YOUR REGULAR        JOB YET."
 1119 LET M$(19)="NOT BAD FOR A FIRST TRY.        WAS THIS YOUR FIRST TRY?"
 1120 LET M$(20)="ARE YOU REALLY PROUD OF THIS    SCORE?"
 1121 LET M$(21)="THERE IS NO HOPE FOR YOU YET."
 1122 LET M$(22)="SINCE ALL ELSE IS FAILING, WHY  NOT READ THE INSTRUCTIONS?"
 1123 LET M$(23)="IS THIS SCORE A REFECTION OF    YOU OR A BAD TV?"
 1124 LET M$(24)="I DARE YOU TO TRY AGAIN."
 1125 LET M$(25)="HAVE YOU CONSIDERED FISHING     INSTEAD OF PLAYING THIS GAME?"
 1126 LET M$(26)="FANTASTIC RESCUE OPERATION,     WELL DONE."
 1127 LET M$(27)="THIS IS  GOOD SCORE.  I BET     YOU CAN NOT BEAT IT."
 1128 LET M$(28)="THAT IS A GREAT SCORE.  ARE YOU A VIDEO GAME HUSTLER?"
 1129 LET M$(29)="THIS IS A HIGH SCORE.  DID YOU  HAVE A PARTNER HELPING YOU?"
 1130 LET M$(30)="IF YOU KEEP SCORING THIS HIGH,  I WILL QUIT."
 1131 LET M$(31)="I AM LUCKY THE GAME ENDED       BEFORE YOU KILLED ALL MY SHARKS."
 1132 LET M$(32)="NOTHING ""SUB""-NORMAL            ABOUT THIS SCORE."
 1133 LET M$(33)="YOU HAVE TO SWIM FASTER THAN    THAT."
 1134 LET M$(34)="DID YOU REALLY GRADUATE FROM    THE SCHOOL OF DIVING?"
 1135 LET M$(35)="NEXT TIME TRY SHOOTING THE      SHARK BEFORE IT EATS YOU."
 1136 LET M$(36)="I HOPE YOU DO NOT GIVE MY PET   INDIGESTION."
 1137 LET M$(37)="YOU SHOULD NEVER TAKE A SHARK   TO DINNER."
 1160 LET F=0
 1199 RETURN 
 1600 POKE 16553,C+1
 1605 POKE 16554,R
 1607 PRINT AT 6,29;"<S>"
 1610 LET L=USR 16557
 1650 RETURN 
 3000 PRINT AT 0,2;"INTERNATIONAL PUBLISHING             AND SOFTWARE";AT 3,10;"PRESENTS"
 3005 FOR I=1 TO 10
 3006 NEXT I
 3010 PRINT AT 9,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ";AT 10,0;"% % %M% %A% %R% %I% %N% %E% % % % %R% %E% %S% %C% %U% %E% % % % ";AT 11,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
 3015 PRINT AT 17,2;"COPYRIGHT 1982 BY";AT 18,2;"INTERNATIONAL PUBLISHING";AT 19,2;"AND SOFTWARE.";AT 20,2;"ALL RIGHTS RESERVED."
 3020 GOSUB 4000
 3025 PRINT AT 17,0;Z$;Z$;Z$;Z$
 3030 FOR I=1 TO 9
 3035 SCROLL 
 3040 NEXT I
 3050 PRINT AT 4,4;"A SUB HAS GONE DOWN.";AT 6,0;"YOU MUST SAVE THE CREW.";AT 8,0;"YOU MUST DIVE DOWN TO THE";AT 10,0;"SUB AND RESCUE THE SAILORS."
 3055 PRINT AT 12,0;"YOU MUST CARRY EACH SAILOR";AT 14,0;"BACK TO SAFETY."
 3520 PRINT AT 21,0;"PRESS ANY KEY TO GO ON."
 3530 GOSUB 5000
 3550 PRINT AT 4,4;"YOU WIN 150 POINTS            ";AT 6,0;Z$;AT 8,0;"    FOR EVERY SAILOR          "
 3560 PRINT AT 10,0;Z$;AT 12,0;"    YOU SAVE.                ";AT 14,0;Z$;AT 16,4;"GOOD LUCK.....";AT 21,0;Z$
 3570 GOSUB 4000
 3575 GOSUB 1100
 3580 PRINT AT 4,0;"OH, I FORGOT TO TELL YOU.    ";AT 8,0;"YOU CAN BE EATEN BY SHARKS    ";AT 12,0;"OR YOU CAN RUN OUT OF OXYGEN";AT 16,0;"AND DROWN.           "
 3590 PRINT AT 21,0;"PRESS ANY KEY TO GO ON."
 3600 GOSUB 5000
 3610 PRINT AT 4,0;"YOU CAN SHOOT THE SHARKS.     ";AT 6,0;"FOR EVERY SHARK YOU KILL";AT 8,0;"YOU SCORE 25 POINTS.        ";
 3620 PRINT AT 10,0;"YOU CAN GET MORE             ";AT 12,0;"OXYGEN BY GOING TO THE        ";AT 14,0;"OXYGEN TANK BEFORE YOURS   ";AT 16,0;"RUNS OUT.                    "
 3636 GOSUB 5000
 3640 PRINT AT 4,0;Z$;AT 6,0;"MOVE LEFT:  5     FIRE LEFT:  V";AT 8,0;"MOVE RIGHT: 8     FIRE RIGHT: N"
 3650 PRINT AT 10,0;"MOVE UP:    7                ";AT 12,0;"MOVE DOWN:  6               ";AT 14,0;Z$;AT 16,0;Z$;AT 21,0;"PRESS ANY KEY TO START THE GAME."
 3655 SLOW 
 3660 GOSUB 5000
 3670 FAST 
 3680 CLS 
 3690 RETURN 
 4000 FOR Q=1 TO 15
 4010 NEXT Q
 4020 RETURN 
 5000 IF INKEY$<>"" THEN GOTO 5000
 5010 IF INKEY$="" THEN GOTO 5010
 5020 RETURN 
 9000 SAVE "MARIN%E"
 9010 GOTO 1

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

People

No people associated with this content.

Scroll to Top