Fortress Of Zorlac

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

Fortress Of Zorlac is a space shooter game in which the player pilots a ship to destroy an alien and the blocks of its fortress across multiple waves of increasing difficulty. The game uses extensive machine code stored across REM statements in lines 2 through 29, with USR calls throughout the main loop to drive all gameplay mechanics including movement, torpedo firing, collision detection, and rendering. Skill level (1–5) is selected at startup and affects the game speed via POKEs to timing variables as well as the point multiplier (F = 50*V). The score is stored as a two-byte value split across two memory locations and reconstructed with PEEK 18210 + 256*PEEK 18211. A wave counter (W) runs from 29 to 33, triggering a “Game Over” screen at W=34.


Program Analysis

Program Structure

The program is divided into several logical sections:

  1. Lines 1–29: REM statements holding machine code routines and data tables. Line 1 also encodes a title/banner graphic. Lines 2–29 contain Z80 machine code in hex byte sequences.
  2. Lines 30–110: Title screen setup — CLS, screen POKEs, welcome text with block-graphic logo, and a prompt for instructions.
  3. Lines 140–190: Initialization USR calls and branch to instructions or game setup.
  4. Lines 190–510 (main game loop): Wave management, USR calls for all gameplay mechanics, scoring, and wave progression.
  5. Lines 520–630: Alien-destroyed branch — score update, speed increase, and loop back.
  6. Lines 640–740: End-of-game (wave 34) screen and play-again prompt.
  7. Lines 1000–1140: Instructions subroutine (two pages of text with key layout).
  8. Lines 2000–2200: Skill level selection subroutine.
  9. Lines 3000–3100: SAVE and restart.

Machine Code Storage in REM Statements

All game logic is implemented in Z80 machine code, stored as raw bytes embedded in REM statements (lines 2–29). This is a common technique: the BASIC interpreter ignores REM content, so arbitrary binary data can be placed there and executed via USR with the appropriate address. The machine code spans many hundreds of bytes across 28 REM lines, covering routines for rendering, movement, collision detection, torpedo logic, alien AI, fortress block management, and scoring.

USR Call Dispatch

The main game loop invokes machine code exclusively through LET L=USR address. The return value is assigned to L but is generally discarded; the USR idiom is used purely for its side effects. Key USR entry points include:

AddressApparent Role
17617Early init / display setup
17926Keyboard / title screen handler
18431Game field initialization / redraw
17968Alien movement
18526Fortress block rendering
16684Ship movement
17055Torpedo / firing logic
17224Collision / hit detection
18545Post-keypress processing
18769Score / status update
17860Per-block scoring loop body
17413Wave reset
18614Alien-death animation frame
18867End-of-wave / end-of-game handler

Key BASIC Idioms

  • Two-byte score storage: The score S is stored across two adjacent memory bytes. It is read as PEEK 18210 + 256*PEEK 18211 and written back by splitting on INT(S/256). This supports scores up to 65535.
  • Skill-level configuration via POKE: Lines 2110–2190 patch the machine code directly: POKE 18767,1 and POKE 18768,5-V set speed parameters; a loop POKEs ship-count values into addresses 18354–18358 based on the chosen level.
  • Speed escalation: Each time the alien is destroyed, R is decremented by 20 (down to a floor of 20) and POKEd to address 18146, tightening the game loop timing.
  • Point multiplier: F = 50*V where V is the skill level (1–5). Scoring in lines 560–590 adds F * (PEEK 17455 - 3), rewarding players who fire from farther left with a higher multiplier.
  • Wave counter: W starts at 28 (line 195), increments each loop, and is POKEd to three addresses (17158, 17183, 17208) for the machine code to use. At W=34, the game ends.
  • Keyboard wait: Line 155 uses IF INKEY$="" THEN GOTO 140 as a spin-wait for a keypress after the title USR calls complete.

Scoring Loop

Lines 430–460 iterate N from 1 to 32, calling USR 17860 each time and adding N to the result. This loop walks through all 32 possible fortress block positions; the machine code routine presumably checks and scores each surviving block. The accumulation of L=L+N within the loop has no meaningful effect on gameplay since L is a scratch variable, but it may be a stylistic artifact.

Graphics and Display

The title logo at lines 50–70 is constructed from ZX81 block graphics characters arranged to spell out the game title in a large font. Lines 660–690 use similar block graphics to render a “GAME OVER” box. The instruction screens (lines 1100–1110) use block graphics to draw a representation of a keyboard layout showing all control keys.

Skill Level Selection

The skill level subroutine (lines 2000–2200) reads a keypress, converts it to a numeric value with LET V=CODE INKEY$-28 (mapping digit characters ‘1’–’5′ to values 1–5 by subtracting the ZX81 character code offset), validates the range, and applies the result via POKEs and the F multiplier variable.

Notable Techniques and Observations

  • The machine code at line 2 begins with LD HL,(nn) and LD (nn),HL pairs, suggesting it copies pointers or initializes display addresses at startup.
  • Line 3 contains LDIR and LDDR (block copy/move) opcodes, used for scrolling or copying screen regions.
  • Line 8’s machine code includes keyboard port reads (3E F7, 3E EF, 3E DF — the standard ZX81 keyboard row port values) and compares against register C for keypress detection.
  • Lines 545–547 with LET L=L+0 appearing twice in the alien-death loop are effectively no-ops, likely serving as timing delays or placeholders left from development.
  • The SAVE "ATTAC%K" at line 3000 uses an inverse-video K in the filename.
  • There is no apparent protection against V=0 at line 2090 if a non-digit is pressed and then INKEY$ changes between lines 2080 and 2090, but the validation at line 2100 catches out-of-range values and loops back safely.

Content

Appears On

Related Products

You are commander of a fleet of spaceships. Your mission is to rid the galaxy of the dreaded alien, Zorlac....

Related Articles

Related Content

Image Gallery

Source Code

   1 REM % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % ####################################################################################################% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %  INPUT RND*INKEY$+ '(: D     
   2 REM 21BB40221A412182402218413E14321E413E9321F413E39322041CD9141CD5B41CD5B4155DDED431C41C38A414CED431C41ED5318413A2041D683220412606F19221A413A1E41D62321E413A1F41D62321F41000CD9141C9
   3 REM ED5B1A411A2A1A412B60F53A20414FF1EDB82A184177E5ED4B1C41CD1242EBE1C53A1E411200EDA033DFE0285EB9EB18F3ED4B1F4160EDB03A1E411220EDA033DFE0287EBA7ED42EB18F13A1F411B1BEDA03DFE020F7C1EBC93EF7BC28D3EEFBC2883EDFBC283C3F543AFB9CAF543C3EA43
   4 REM D5F52AC4023AF11210B8284193C18F9791E0BB2841C2318F9F1D1C900
   5 REM 218240ED5B1C41D578921605F19D17993FE128530D360C91603E3905F19360C91603E39087D685F19360C900000
   6 REM 18700000087780844084370028010078084008780400810820000002A1C417DC63327442ED4B7442C53AEF42FE028E5CDD142C178FE6C0AF32EF42C94CDD142C178FEAC03E118EF00ED437442CD1242EB2177423E8150EDB03DFE0C8EB11C09EB18EF10000
   7 REM 8180808082828281838008020800778438084808080781808080828281838281080208007843784848080807818080808280838281810802080080378484848080807209ED4B4643CD1242EB2145433E1BE2093C32454321FA4218163E2BE2093C3245432113431883E1324543212C433E5150EDB03DFE0C8EB11C09EB18EF00000
   8 REM CDBB2ED4B46433EFFBD28543DBD282B3DBD28273D3DBD282D3EF7BD28283EEFBD28383EDFBD28333EF79430243A1C41D68B9282BCD544C18253E10B82820CD5444181A3E3B82815CD544518FAFB928BCD544D185C5CD3144C1ED434643CD4843C900
   9 REM C5ED4B4643CD12423E5111C0653602310FB193DFE020F3C1C900000
  10 REM 01112A123A2C44FE1C82A464324242C2C2C2C222D44222F44444DCD124236343E1322C44C900000
  11 REM 00AF325E44325F443A2C44FE0C8ED4B2D44CD12423E34BE202360ED5B1C417B3D9128B389233634CED432D44C9237BC64912820AFBE28ED3E80BE28C3E8BE2873E1325F4418BC360CD38423E1325E44AF322C44C9000000000
  12 REM 808000000113CD1242EB6B21CA44EDA0EDA0EDA010F53E56321CA44C51200EB9C1EBEDA010F43DFE020EA1200EB9EB6A21CA447E12231B7E12231B7E1201B10EF1200EBA7ED42EB3E56321CA44F57E12F1C51210EBA7ED42C1EB2310EF3DFE020E53ACA4432CD443ACB4432CA443ACC4432CB443ACD4432CC441DBC34C43
  13 REM 081847081867828182708184784818670818270818007828081807808081078080818078084810807084782082818468278208481846827840848182081808080828282828280080080080848484848480808074111903AC3453CFE52023E132C345214645471910FDE5ED4B4643CD1242EBE1C3774300000
  14 REM 000000003400000000FB452A4462B1F345A7ED4230521FB451819E522446112DCD1242D1EB180EDB0C9
  15 REM 3A1C41D624F65CD47460CD4746CD47460CD4746C9CD1242368111210193624444C9000
  16 REM 0D03A6246FE1C83A1C41D636F3A4743673E59438426518143E99438426918B3ED9438426D18226112260463E1326246C9
  17 REM 0AF329F46ED4B6046CD1242360AFB9204326246C9D2BBE2853E34BE207364ED436046C93432C6463E1329F46C900000
  18 REM 2D02ADB462311C80A7ED522851922DB46C9210022DB46CDE147ED4B1C41DED431C41DDCD12423E141D0545D23EDB02B360114093DFE020ECC9
  19 REM 0001D1C241C1027E83640A010001AF3235472A224722334712447212947E5AFE15E23562BE52A3347A7ED522233473833C18F219FE02093A3547FE03E0289C61CF53E1323547F122334723E12323E57BFE120C6E1C90000000000
  20 REM 3A5F44FE1C83A5E44FE0C8AF325E4411302A2F44260A7ED52EB2A2247190000222247CD36472AC401112019EB212447657EFE0286EDA0310F6C92310F2C900
  21 REM ED4B2D44CD12423E34BEC0360C9EDA06046CD1242360C9
  22 REM 63A21824036802310FB6323682310FB62A36802310FB21152221C41210022DB46225E4421092246432101226046AF322C44326246329F46C900
  23 REM 2D2E39026333E0312A39392A3703C2D2A330372A26293E1317CD1242EB2145481190EDB0C90001317CD12426193602310FBC9000
  24 REM 0851850028030087804008108200000087780844084370028010000001ED4B1C41CCC65CD1242111C03EEF5657EEE80772310F919F13DFE020EFC9EB219C48C377433E2BE201F3C32B548EB233652336223365111F019363232336111A30193680C93E132B548EB2323360233685112101936311A50193680C9000
  25 REM ED4B1C41CCC65ED434643CD5446EED434643CD544C900000000
  26 REM 14CDDD46CDD149CD9F42CD2C41CD6044CD93473A5F44FE1C8CD3046CDA0463A9F46FE1C8CD63462A4F49110013A7ED52CA51491918F60000000
  27 REM 3EBFBD2863E7FBDC2F0433A1C41C3C5430000000
  28 REM '   'LN >PIY=.'4Q 7( CLS 7X RETURN  4 NEXT TAN 
  29 REM FFFFCDBB2ED4B464322CF4911FFFFA7ED52C82ACF49CB65CC31442ACF49ED4B4643CB6DCC31442ACF49ED4B4643CB5DCADB43CB55CADB43CB45CAD043CB4DCAD043CB75283CB7DC000000CB6CCAE643CB64CAE643CB5CCAE643CB54CAC243CB4CCAC243C9000000
  30 CLS 
  34 POKE 17924,252
  35 POKE 17925,69
  40 PRINT AT 5,11;"WELCOME TO";
  50 PRINT AT 7,5;".''''. '':''  '':'' .''''. .''''. :  .' ";
  60 PRINT AT 8,5;":....:  :    :  :....: :    :''.";
  70 PRINT AT 9,5;":   :  :    :  :   : '....' :  '."; 
  80 PRINT AT 17,3;"COPR., PAUL CARLSON, 1982";
  90 PRINT AT 21,0;"DO YOU WANT INSTRUCTIONS? (Y/N)";
 100 POKE 17158,128
 110 POKE 17183,128
 120 POKE 17208,128
 140 LET L=USR 17617
 150 LET L=USR 17926
 155 IF INKEY$="" THEN GOTO 140
 160 IF INKEY$="N" THEN GOTO 190
 170 IF INKEY$<>"Y" THEN GOTO 140
 180 GOSUB 1000
 190 GOSUB 2000
 195 LET W=28
 200 LET S=0
 202 LET R=200
 205 POKE 18146,R
 210 POKE 18210,0
 220 POKE 18211,0
 230 LET L=USR 18431
 250 PRINT AT 0,10;"SCORE: 0"
 260 LET W=W+1
 270 IF W=34 THEN GOTO 640
 280 POKE 17158,W
 290 POKE 17183,W
 300 POKE 17208,W
 310 LET L=USR 17968
 320 LET L=USR 18526
 340 LET L=USR 16684
 350 LET L=USR 17055
 360 LET L=USR 17224
 370 IF INKEY$="" THEN GOTO 340
 380 LET L=USR 18545
 390 LET L=USR 18769
 400 LET L=USR 18401
 410 LET L=USR 18415
 420 IF PEEK 17503=1 THEN GOTO 520
 430 FOR N=1 TO 32
 440 LET L=USR 17860
 450 LET L=L+N
 460 NEXT N
 470 LET L=USR 17413
 475 POKE 18016,0
 480 POKE 17452,0
 485 POKE 18018,0
 490 POKE 17222,0
 500 POKE 17223,9
 505 POKE 18079,0
 510 GOTO 260
 520 FOR N=1 TO 50
 540 LET L=USR 18614
 545 LET L=L+0
 547 LET L=L+0
 550 NEXT N
 560 LET S=PEEK 18210+256*PEEK 18211
 570 LET S=S+F*((PEEK 17455)-3)
 575 PRINT AT 0,17;S
 580 POKE 18211,INT (S/256)
 590 POKE 18210,(S-256*PEEK 18211)
 592 IF R>20 THEN LET R=R-20
 595 POKE 18146,R
 600 LET L=USR 18867
 620 LET L=USR 18431
 630 GOTO 310
 640 LET L=USR 18867
 650 PRINT AT 0,4;"FINAL";
 660 PRINT AT 10,13;":'''''''''':"
 670 PRINT AT 11,13;": GAME :"
 680 PRINT AT 12,13;": OVER :"
 690 PRINT AT 13,13;":..........:"
 700 PRINT AT 16,6;"PLAY AGAIN? (Y OR N)"
 720 IF INKEY$="N" THEN STOP 
 730 IF INKEY$="Y" THEN GOTO 190
 740 GOTO 720
 1000 CLS 
 1010 PRINT AT 0,10;"YOUR GOAL:"
 1020 PRINT AT 2,0;"TO SCORE AS MANY POINTS AS YOU   CAN BY DESTROYING THE ALIEN AND BLOCKS OF HIS FORTRESS."
 1030 PRINT AT 6,0;"YOU HAVE FIVE SHIPS TO DESTROY   THE ALIEN AS MANY TIMES AS YOU  CAN.  WARNING - THE ALIEN GUNS  ARE INDESTRUCTIBLE."
 1040 PRINT AT 11,0;"POINTS ARE AWARDED BASED ON      SKILL LEVEL AND THE DISTANCE    YOUR SHIP IS FROM THE LEFT EDGE OF THE SCREEN WHEN IT FIRES."
 1050 PRINT AT 16,0;"DESTROYING THE ALIEN IS WORTH    FIFTY TIMES THE POINTS AWARDED  FOR DESTROYING A BLOCK OF HIS   FORTRESS."
 1060 PRINT AT 21,1;"HIT ANY LETTER TO CONTINUE..."
 1070 IF INKEY$="" THEN GOTO 1070
 1080 CLS 
 1090 PRINT AT 0,3;"YOUR SHIPS CONTROL PANEL:"
 1100 PRINT AT 3,2;":'''''''''''''''''''''':    :'''''''''''''''''''''':    : 1 2 3 4 5  :    : 6 7 8 9 0  :    :  Q W E R T :    :  Y U I O P :    :......................:    :......................:    MOVE SHIP UP    FIRE TORPEDO" 
 1110 PRINT AT 11,0;":'''''''''''''''''''':  :'''''''''''''': :'''''''''''''''''':: A S D F G :  :  H J K : :  L ENTER ::  Z X C V  :  : B N M  : : . SPACE  ::....................:  :..............: :..................: MOVE SHIP     MOVE      MOVE      DOWN        SHIP      SHIP                  LEFT      RIGHT"
 1120 PRINT AT 21,1;"HIT ANY LETTER TO CONTINUE..."
 1130 IF INKEY$="" THEN GOTO 1130
 1140 RETURN 
 2000 CLS 
 2010 PRINT AT 2,1;"SKILL LEVELS:"
 2020 PRINT AT 4,15;"1 = SLOW"
 2030 PRINT AT 6,15;"2 = AVERAGE"
 2040 PRINT AT 8,15;"3 = FAST"
 2050 PRINT AT 10,15;"4 = VERY FAST"
 2060 PRINT AT 12,15;"5 = SUICIDAL"
 2070 PRINT AT 16,6;"PRESS SKILL LEVEL..."
 2080 IF INKEY$="" THEN GOTO 2080
 2090 LET V=CODE INKEY$-28
 2100 IF V<1 OR V>5 THEN GOTO 2080
 2105 CLS 
 2110 POKE 18767,1
 2120 POKE 18768,5-V
 2130 LET F=50*V
 2150 FOR N=1 TO 5
 2160 LET A=18353+N
 2170 POKE A,0
 2180 IF N<=V THEN POKE A,25
 2190 NEXT N
 2200 RETURN 
 3000 SAVE "ATTAC%K"
 3100 GOTO 30

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

People

No people associated with this content.

Scroll to Top