--- title: "Fortress Of Zorlac" id: 51883 type: "computer_media" slug: "fortress-of-zorlac" url: "http://localhost/computer_media/fortress-of-zorlac/" markdown_url: "http://localhost/computer_media/fortress-of-zorlac.md" published_at: "2023-08-16T01:42:21+00:00" modified_at: "2026-04-04T20:17:52+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2023/08/SCR-20260403-opnl.png" excerpt: "Pilot a spacecraft through five skill levels to blast an alien and its fortress apart, with all game logic driven by machine code packed into REM statements." 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: "Timex Computer Corporation" slug: "timex-computer-corporation" taxonomy: "post_tag" url: "http://localhost/tag/timex-computer-corporation/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/FortressOfZorlac (1982)(Timex)(US)(TS1000)(Cassette).zip" mediadate: "1982" producer_company: - id: 11401 title: "Timex Computer Corporation" type: "company" url: "http://localhost/company/timex-computer-corporation/" images: - url: "http://localhost/wp-content/uploads/2023/08/SCR-20260403-opnl.png" - url: "http://localhost/wp-content/uploads/2023/08/SCR-20260403-opkv.png" related_products: - id: 12619 title: "Fortress of Zorlac" type: "product" url: "http://localhost/product/fortress-of-zorlac/" media_type_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: | Address | Apparent Role | | --- | --- | | `17617` | Early init / display setup | | `17926` | Keyboard / title screen handler | | `18431` | Game field initialization / redraw | | `17968` | Alien movement | | `18526` | Fortress block rendering | | `16684` | Ship movement | | `17055` | Torpedo / firing logic | | `17224` | Collision / hit detection | | `18545` | Post-keypress processing | | `18769` | Score / status update | | `17860` | Per-block scoring loop body | | `17413` | Wave reset | | `18614` | Alien-death animation frame | | `18867` | End-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. ## 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 ```