--- title: "Earth Attack" id: 70932 type: "computer_media" slug: "earth-attack" url: "http://localhost/computer_media/earth-attack/" markdown_url: "http://localhost/computer_media/earth-attack.md" published_at: "2026-08-24T11:52:41+00:00" modified_at: "2026-08-24T11:53:48+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/08/Earth-Attack.png" alt: "Earth Attack screen" excerpt: "Pilot a spacecraft across a scrolling cityscape, blasting enemies and deploying smart bombs in this machine-code-driven shoot-'em-up with high-score entry." 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/" indiv: - name: "Alvin Albrecht" slug: "albrecht-alvin" taxonomy: "indiv" url: "http://localhost/indiv/albrecht-alvin/" - name: "David Mold" slug: "david-mold" taxonomy: "indiv" url: "http://localhost/indiv/david-mold/" genre: - name: "Arcade" slug: "arcade" taxonomy: "genre" url: "http://localhost/type/arcade/" media_type: "Program" programmers: - name: "David Mold" slug: "david-mold" taxonomy: "indiv" url: "http://localhost/indiv/david-mold/" - name: "Alvin Albrecht" slug: "albrecht-alvin" taxonomy: "indiv" url: "http://localhost/indiv/albrecht-alvin/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Earth%20Attack%20%281983%29%28Mold%2C%20David%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "1983" images: - url: "http://localhost/wp-content/uploads/2026/08/Earth-Attack.png" alt: "Earth Attack screen" media_type_tags: "Arcade" --- # Earth Attack Earth Attack is a side-scrolling shoot-’em-up in which the player pilots a ship across a cityscape, firing lasers at enemy craft and deploying smart bombs while protecting a set of shield units. The game relies heavily on machine code routines POKEd into RAM from DATA statements, covering functions including side-scrolling, collision/firing detection, smart-bomb blasts, and city building. Six UDG characters (A–F) are defined for the ship, enemies, refueling station, city blocks, and explosion graphics. Laser ammunition is tracked numerically and displayed on-screen, with score bonuses awarded for hits and penalties for enemy collisions; a high-score entry routine prompts the player for three initials when a new record is set. The attract-mode loop cycles through a title screen, a scoring guide, and a high-score table before waiting for the “S” keypress to start a game. *** ### Program Structure The program is organized into three broad phases: initialization (lines 20–50), the attract/menu loop (lines 1140–1400), and the main game (lines 80–690). Subroutines are clearly demarcated with REM labels and occupy lines 280–690 for game logic and lines 700–1130 for setup. 1. **Lines 20–50:** Hardware setup — screen POKEs, beeps, and calls to UDG and machine-code loading subroutines. 2. **Lines 60–70:** Variable initialization, then jump to attract loop at 1140. 3. **Lines 80–270:** Main game loop — player movement, enemy spawning, collision, and firing. 4. **Lines 280–460:** Firing, hit detection, life loss, and game-over logic. 5. **Lines 470–550:** Smart-bomb subroutine with shield management. 6. **Lines 560–680:** High-score name entry. 7. **Lines 700–790:** UDG definition from DATA. 8. **Lines 800–1130:** Machine code loading from DATA into RAM. 9. **Lines 1140–1400:** Attract loop (title, scoring guide, high-score table). ### Machine Code Usage The game’s performance-critical routines are implemented as Z80 machine code, loaded from DATA statements into fixed RAM addresses. Five distinct routines are identified: | Label | Start Address | Purpose | | --- | --- | --- | | Smart Bomb | 62400 (approx) | Clears enemies from screen area | | Side Scroll | 62426 (approx) | Scrolls the playfield one step; called via `USR 62426` | | Build City | ~62450 | Draws city graphics at game start | | Check Firing | 62507 (approx) | Traces laser beam, returns hit count in A register | | Misc routines | 62300, 62350 | Loaded via `p1`/`p2` pairs at lines 1040–1100 | Machine code is loaded using a generalized loader subroutine at line 1110–1130: `p1` holds the byte count and `p2` the destination address; the loop READs and POKEs each byte. The value `-12`, `-18`, `-4` etc. appearing in the DATA are signed relative jump offsets for Z80 `DJNZ` and `JR` instructions. A variable `a` appears in several DATA lines (e.g. lines 730–780) where the literal value `0` is expected; this is likely a bug — `a` will have whatever numeric value it held at READ time rather than the intended constant. ### UDG Definitions Six UDGs (A–F) are defined at lines 700–790 by POKEing 8 bytes each starting at `USR "[UDG-A]"`. The loop structure has a minor anomaly: line 710 ends with `NEXT p` and line 720 also has a stray `NEXT p`, which would cause an error in most interpreters — this appears to be a listing artifact or typo. The UDG characters represent: - **[UDG-A]** — Player ship - **[UDG-B]** — Enemy craft (10 points) - **[UDG-C]** — Refueling station - **[UDG-D]** — Shield/city block - **[UDG-E]** — City pattern (inverse stripes) - **[UDG-F]** — Bonus enemy (20 points) ### Key BASIC Idioms Line 240 uses a conditional string expression to select which enemy graphic to print based on `rg` (a random value), using the Spectrum’s string AND idiom: `("string1" AND condition)+("string2" AND NOT condition)` — when a boolean condition is true it returns 1 (string kept) or 0 (empty string). This selects between UDG-C and a colored UDG-F character inline without branching. Line 200 uses a double-PEEK to read a two-byte system variable: `PEEK (PEEK 23684 + 256 * PEEK 23685)` retrieves the attribute of the character under the player sprite for collision detection via the ATTR system variable pointer. The `IN` keyword is used extensively (lines 190, 210, 230, 260) to read the keyboard matrix ports directly, which is faster than `INKEY$` and allows multiple keys to be detected each frame. Port values 64510, 63486, 61438, 32766, 65278 correspond to specific keyboard half-rows. Line 440 uses `PAUSE PI` — since PI ≈ 3.14159 and PAUSE takes an integer argument, this effectively pauses for 3/50 of a second, a compact way to insert a very brief delay. ### Game Logic and Scoring Laser count (`l`) starts at 20 and decreases by 1 per shot. A pickup (attribute value 60, detected at line 360) grants 20 extra lasers. The shield system uses variable `sb` (starting at 3), decremented by smart bomb use; shields regenerate every 1000 score points via the `bo` (bonus) counter. Score is modified by machine code return values multiplied by 10 in lines 330 and 500. ### Attract Loop The attract sequence at lines 1140–1400 cycles through three screens — title/controls, scoring guide, high-score table — each waiting up to a PAUSE period for the “s” keypress. The title screen animates the game title in all seven INK colors (line 1199 loop). The scoring guide at lines 1270–1300 prints item descriptions character-by-character with a BEEP per character for a teletype effect. ### Notable Anomalies - Variable `a` used as a literal `0` in DATA statements (lines 730–1000): BASIC’s `READ` will evaluate `a` as a numeric variable, so its value depends on prior computation — this is almost certainly a typographical error for the digit `0`. - The double `NEXT p` at lines 710–720 in the UDG loader would cause a NEXT without FOR error on a second pass; the inner FOR loop at line 700 uses `p`, so the extra NEXT is spurious. - Line 690 contains a bare `STOP` statement that is never reached in normal execution; it serves as a safety barrier between subroutines. - Line 260 calls `USR 62426` twice if a specific key is held, effectively double-scrolling — this appears intentional for the SHIFT “extra speed” feature mentioned in the instructions. ## Source Code ``` 10 REM >> EARTH ATTACK << © ZX COMPUTING, Oct/Nov 1983by David Mold, TS 2068 versionby Alvin Albrecht 20 POKE 23730,190:POKE 23731,243:BEEP .5,12:BEEP .5,24:CLS :PRINT AT 10,8;"STOP THE TAPE!!!" 30 GO SUB 700 40 GO SUB 800 50 BORDER 0 60 LET s$="...":LET s=0:LET t=s:LET hs=s:LET bo=s 70 GO TO 1140 80 PAPER 0:INK 7:CLS :FOR n=0 TO 20:BEEP .005,n:NEXT n 90 LET x=9:LET y=5:LET b=1 100 FOR n=0 TO 7:PRINT PAPER 1; AT n,0,,:NEXT n 110 LET s=0 120 PRINT AT 20,0;"SCORE:";s 130 LET a$="[UDG-A] [UDG-A] [UDG-A] [UDG-A] ":PRINT AT 20,15;a$ 140 FOR n=16 TO 19:PRINT AT n,0; PAPER 5,,:NEXT n 150 LET l=20 160 PRINT AT 0,0;"LASERS:";l;" " 170 PRINT AT 0,16;"HI-SCORE:";hs 180 PRINT AT 18,15; INK 2; PAPER 5;"[UDG-D][UDG-D][UDG-D]":LET sb=3 190 LET x=x+(IN 64510<31)-(IN 63486<31):PRINT AT x,y;"[UDG-A]"; 200 LET p= PEEK (PEEK 23684+256* PEEK 23685):IF p THEN GO SUB 360 210 IF IN 61438<31 THEN IF l THEN GO SUB 280 220 IF RND>.79 THEN PRINT AT RND*5+8,31; INK 6;"[UDG-B]" 230 IF IN 32766<31 THEN GO SUB 470 240 LET rg= RND:IF rg>.96 THEN PRINT AT 15-b,31; INK 4;("[UDG-C]" AND rg>.98)+(CHR$ 16+ CHR$ 6+"[UDG-F]" AND rg <=.98):BEEP .005,10:BEEP .005,20 250 LET b= INT (RND*3)+1 260 PRINT AT x,y;" ":POKE 62477,b:LET a= USR 62426:IF IN 65278<31 THEN LET a= USR 62426 270 GO TO 190 280 REM >>Firing Subroutine<< 290 LET l=l-1 300 BEEP .005,30:LET a= USR 62507:IF a THEN BEEP .01,7:BEEP .01,0:GO TO 330 310 PRINT AT 0,7;l;" " 320 RETURN 330 LET s=s+10*a 340 PRINT AT 20,6;s;" "; AT 0,7;l;" " 350 RETURN 360 IF p=60 THEN :LET l=l+20:BEEP .01,20:GO TO 340 370 FOR f=1 TO 4:BEEP .01,f*2:NEXT f:FOR f=4 TO 1 STEP -1:BEEP .01,f*2:NEXT f 380 PRINT AT x,y; OVER 1;"#":BEEP .01,0:BEEP .01,-.5:BEEP .01,-1 390 IF a$="!" THEN GO TO 440 400 LET a$=a$(3 TO ):IF a$="" THEN LET a$="!" 410 LET s=s-10:PRINT AT 20,15;a$;" " 420 PRINT AT x,y; INK 1;"█":LET a= USR 62426 430 LET x=9:BEEP .3,0:PRINT AT 20,6;s;" ":RETURN 440 PRINT AT 4,10;"GAME OVER":FOR n=1 TO 8:LET a= USR 62300:BEEP .1,n:NEXT n:PAUSE PI:IF hsbo THEN LET sb=3:PRINT AT 18,15; INK 2; PAPER 5;"[UDG-D][UDG-D][UDG-D]" 490 IF sb<0 THEN RETURN 500 LET s=s+10* USR 62400:BEEP .5,7:BEEP .5,0:PRINT AT 20,6;s;" ":PRINT AT 18,15+sb; INK 5;"█" 510 IF INT (s/1000)>bo THEN LET sb=3:PRINT AT 18,15; INK 2; PAPER 5;"[UDG-D][UDG-D][UDG-D]" 520 LET bo= INT (s/1000) 530 FOR n=0 TO 31:POKE 62477, INT (RND*3)+1:LET a= USR 62426 540 PRINT AT x,y-1; PAPER 8;" [UDG-A]":BEEP .01,n 550 NEXT n:RETURN 560 PAPER 0:INK 6:CLS 570 PRINT " EARTH ATTACK" 580 LET a$="WELL DONE, YOU HAVE BEATEN THE HIGH SCORE: PLEASE ENTER YOUR INITIALS NOW" 590 PRINT ''' 600 FOR n=1 TO LEN a$:PRINT a$(n);:BEEP .003,0:NEXT n 610 LET s$="" 620 PRINT ''" ---"; CHR$ 8; CHR$ 8; CHR$ 8; 630 FOR n=1 TO 3 640 PRINT "?"; 650 PAUSE 0:LET p$= INKEY$:IF LEN p$ <>1 THEN GO TO 650 660 PRINT CHR$ 8;p$;:LET s$=s$+p$ 670 BEEP .1,n:NEXT n 680 PAUSE 50:RETURN 690 STOP 700 FOR p=0 TO 47:READ a 710 POKE USR "[UDG-A]"+p,a:NEXT p 720 NEXT p 730 DATA 224,48,248,127,a,248,48,224 740 DATA 24,36,126,129,a,126,0,a 750 DATA 60,66,129,66,60,a,a,a 760 DATA 0,64,92,126,a,92,64,0 770 DATA 255,153,a,255,153,a,255,a 780 DATA 93,42,54,127,85,a,20,54 790 RETURN 800 REM >>SMART BOMB<< 810 DATA 33,255,88,14,0,6,255,35,126,254 820 DATA 6,32,7,12,62,8,119,16,-12,201 830 DATA 198,16,119,16,-18,201 840 REM >>SIDE SCROLL<< 850 DATA 6,64,33,0,72,17,32,0,62,0 860 DATA 119,25,16,252,33,0,89,6,8,17 870 DATA 32,0,62,7,119,25,16,-4,1,0 880 DATA 8,17,0,72,33,1,72,237,176,1 890 DATA 0,1,17,0,89,33,1,89,237,176 900 REM >>BUILD CITY<< 910 DATA 6,0,14,15,62,22,215,121,215,62 920 DATA 31,215,62,16,215,62,5,215,62,17 930 DATA 215,62,0,215,62,148,215,13,16,-26 940 DATA 201 950 REM >>CHECK FIRING<< 960 DATA 14,0,42,132,92,17,0,3,25,229,6,5,126,254,129,40,16,254,127,40,11,54,255,35,16,-14,118,118,118,118,24,47,12,197,237,82 970 DATA 229,205,142,243 980 DATA 0,66,36,24,24,36,66,0,118,118,225 990 DATA 229,205,142,243,153,90,16,199,227,8,90,153,118,a,225 1000 DATA 205,142,243,0,a,a,a,a,a,a 1010 DATA 0,193,12 1020 DATA 225,62,5,54,0,35,4,184,32,-7,6,0,201 1030 REM >> CODE DATA << 1040 LET p1=199:LET p2=62399 1050 GO SUB 1110 1060 DATA 62,7,33,0,89,6,255,119,35,16,-4,118,61,32,-13,6,1,33,255,79,14,32,175,126,203,63,119,43,13,32,-8,62,71,188,32,-16,16,-21,201 1070 LET p1=39:LET p2=62299 1080 GO SUB 1110 1090 DATA 6,8,209,26,19,213,119,17,0,1,25,16,-11,201 1100 LET p1=14:LET p2=62349 1110 FOR n=1 TO p1 1120 READ a:POKE p2+n,a:NEXT n 1130 RETURN 1140 INK 7:PAPER 0:CLS 1150 LET a$=" DAVID MOLD " 1160 FOR n=1 TO LEN a$ 1170 PRINT a$(n); 1180 NEXT n 1190 FOR n=0 TO 7:INK n:PRINT AT 3,9;"EARTH ATTACK":BEEP .1,n 1200 LET a$=" ":PRINT '"Use Keys:"'a$;"1-5......Up"''a$;"Q-T......Down"''a$;"6-0......Fire"''a$;"SHIFT....Extra Speed"''a$;"SPACE....Smart Bombs" 1210 PRINT '"PRESS 'S' TO START" 1220 NEXT n 1230 PAUSE 250 1240 IF INKEY$="s" THEN GO TO 80 1250 CLS 1260 PRINT "EARTH ATTACK"'''' 1270 LET a$= CHR$ 13+ CHR$ 13:LET a$="[UDG-B]........10 POINTS"+a$+"[UDG-F]........20 POINTS"+a$+"[UDG-C]........REFUELLING Stn"+a$+a$+"PRESS 'S' TO START" 1280 FOR n=1 TO LEN a$ 1290 PRINT a$(n);:BEEP .003,0:NEXT n 1300 PAUSE 250:IF INKEY$="s" THEN GO TO 80 1310 CLS 1320 PRINT "EARTH ATTACK" 1330 PRINT "------------" 1340 PAUSE 50 1350 PRINT '''"HIGH SCORE=";hs:BEEP .1,10:PAUSE 50 1360 PRINT '"LAST SCORE=";s:BEEP .1,9:PAUSE 50 1370 PRINT ''"HIGH SCORE BY ";s$:BEEP .1,8 1380 PRINT '''''"PRESS 'S' TO START" 1390 PAUSE 200:IF INKEY$="s" THEN GO TO 80 1400 GO TO 1140 ```