--- title: "Demolition" id: 71014 type: "computer_media" slug: "demolition-2" url: "http://localhost/computer_media/demolition-2/" markdown_url: "http://localhost/computer_media/demolition-2.md" published_at: "2026-08-26T01:11:18+00:00" modified_at: "2026-08-26T01:15:29+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/08/demolition-1.png" alt: "Demolition screen" excerpt: "Launch a bouncing ball to demolish an advancing brick wall across five difficulty levels, with a ten-entry high-score table to chase." 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/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Demolition%20%28198x%29%28-%29%28TS2068%29%28US%29%28Program%29.zip" tsrun_member: "Demolition (198x)(-)(TS2068)(US)(Program).tap" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/08/demolition-1.png" alt: "Demolition screen" - url: "http://localhost/wp-content/uploads/2026/08/demolition-2.png" alt: "Demolition screen" media_type_tags: "Game" --- # Demolition Demolition is a single-player arcade game in which the player launches a ball from the top of the screen to demolish a scrolling brick wall advancing from the bottom. The game supports five selectable difficulty levels, controlled by the variable `d`, which affects how many button presses are required before the wall advances. A high-score table stores the top ten entries across five difficulty levels using parallel string and numeric arrays (`s$` and `s`), with names entered via LINE input. User-defined graphics (UDGs A, B, and C) are used for the brick, ball-trail, and ball characters respectively, and a machine code routine is POKEd into low memory at startup (addresses 0–41) to perform collision detection, with its result read via `USR USR “d”`. The program uses `ATTR` reads at lines 380–390 to detect when the ball contacts the wall, awarding points by calculating the blast radius left and right of the impact column. *** ## Program Analysis ### Program Structure The program is organized into clearly separated functional blocks: 1. **Lines 10–80:** Initialization — sound, system setup, subroutine calls, and jump to title/difficulty screen. 2. **Lines 90–130:** Game setup — screen colors, wall drawing, score display, and random ball start direction. 3. **Lines 140–200:** Ball movement loop — bouncing the ball across the top row, waiting for a keypress to launch. 4. **Lines 210–270:** Wall advance logic — incrementing the wall counter `c` and updating the wall display, then checking for collision via machine code. 5. **Lines 280–470:** Ball drop and demolition — the ball falls from the top, hits the wall, and the blast radius is calculated left and right to award points. 6. **Lines 480–530:** Game-over sequence — the wall reaches the player; an animated sweep plays across row 0. 7. **Lines 540–600:** High-score table insertion — comparison and sorting into the parallel arrays. 8. **Lines 610–690:** High-score display — scores shown interleaved by difficulty level. 9. **Lines 700–730:** Wall-draw subroutine — prints five rows of UDG-A bricks in random ink colors on a black paper background. 10. **Lines 740–840:** Title and difficulty selection screen. 11. **Lines 850–880:** One-time initialization subroutine — POKEs machine code, dimensions score arrays, and sets default name strings. 12. **Lines 890–920:** Machine code DATA. 13. **Line 930:** CLEAR and SAVE with auto-run. ### Machine Code Usage Lines 850 and 890–920 load 42 bytes of machine code into addresses 0–41 via a `READ`/`POKE` loop. The routine is invoked at line 270 with the idiom `USR USR "d"`. The inner `USR "d"` returns the address of UDG “D” in the UDG table, and the outer `USR` calls the machine code at that address. The return value is compared to 65535 (`t<>65535`) to detect a collision condition — when the wall has reached the ball’s row. The DATA at line 920 includes a Z80 loop: `LD HL,nn`, `LD BC,nn`, `AND A`, `SBC HL,BC`, `JR NZ`, `LD BC,0FFFFh`, `RET` — a countdown-style scan returning a sentinel value. Note: the DATA lines use `x` as a variable in the DATA statements (lines 890–920), which at runtime holds the last value assigned to `x` in the ball-movement loop. This is an unusual technique — the machine code bytes that happen to coincide with `x`‘s current value are inserted dynamically rather than being fixed constants. This could cause subtle bugs if `x` has an unexpected value during initialization, since `GO SUB 850` is called before the game loop sets `x`. ### Difficulty and Wall Mechanics The difficulty value `d` (1–5, where 1 is hardest) is selected at line 820. The counter `b` is incremented each time the player fires (line 190), and the wall only advances when `b >= d` (line 210). A lower `d` means the wall advances more frequently. The wall position counter `c` runs from 0 to 9, wrapping back to 0 at 10 (line 220). When `c=5`, the wall string `w$` is set to a full row of UDG-A bricks; when `c=0`, it is reset to a color-control-character sequence (line 240), producing a new randomly colored wall row. ### Ball Movement and ATTR-Based Collision The ball bounces horizontally across row 0 using `dx` (+1 or -1) and reflects at the screen edges (line 170). On a keypress, the ball drops vertically in a loop (lines 300–350), checking `ATTR(y,x)` at each row. The attribute value `a=48` (PAPER 6, INK 0 — the wall’s attribute) is used as the wall-detection sentinel. When the ball lands on the wall, the blast radius is expanded left (`lx`) and right (`rx`) simultaneously (lines 380–470), awarding 5 points per brick destroyed and playing a tone pitched by distance from center. ### High Score Table The score table uses two parallel arrays: `s$(10,10)` for names (10 entries of up to 10 characters) and `s(10)` for numeric scores. Odd indices (1,3,5,7,9) store the top score for each of the five difficulty levels; even indices store the second score per level. Insertion at lines 590–600 performs a simple two-slot comparison. The display at lines 630–680 uses two interleaved `FOR` loops with `OVER 1` printing to overlay the level labels printed earlier. ### Key BASIC Idioms - `LET dx=(r>5)-(r<=5)` — Boolean arithmetic to set direction: evaluates to +1 or -1 depending on the random value of `r`. - `POKE 23692,255` — Disables the scroll prompt by setting the system variable SCRCT to 255, preventing “scroll?” interruptions during wall updates. - `POKE 23658,8` / `POKE 23658,0` — Enables and disables CAPS LOCK for name entry. - `LET lx=lx-(lx>0)` and `LET rx=rx+(rx<31)` — Boundary-clamped left/right expansion using Boolean expressions as increments. - `PRINT AT PI,0` at line 650 — `PI` truncates to 3, so this positions the cursor at row 3. An unconventional but valid use of a floating-point constant as a row index. - `LINE w$` in the `INPUT` at line 560 — accepts the entire line including spaces without requiring quotes. ### UDG Usage | UDG | Role | | --- | --- | | `[UDG-A]` | Brick tile, used to fill the wall rows | | `[UDG-B]` | Ball-trail or sweep graphic used in the game-over animation | | `[UDG-C]` | Ball character, displayed moving along row 0 and dropping | | `[UDG-D]` | Not displayed; its USR address is used to call the machine code routine | ### Bugs and Anomalies - The DATA statements at lines 890–920 use the variable `x` for several byte values. Since `GO SUB 850` is called at line 30 before `x` is ever assigned in the game loop, `x` will be 0 at that point, so those bytes are written as 0. This is likely intentional — 0 is a valid Z80 NOP or padding byte in those positions — but it is fragile and not self-documenting. - At line 220, when `c>=10`, it is set to `b`, which was just reset to 0. This is equivalent to `LET c=0` but is an indirect and potentially confusing assignment. - Line 570 checks `LEN w$ > 10` and displays an error at row 7, column 4. However, the `INPUT` at line 560 uses `LINE` input which can accept any length; the error message instructs the user to re-enter, but the `GO TO 560` loops back to the full INPUT prompt correctly. ## Source Code ``` 10 BEEP .5,10 20 POKE 23658,0 30 GO SUB 850 40 PAPER 7:INK 0:BORDER 7:CLS 50 PRINT #1; AT 0,0; TAB 8;"PRESS ANY KEY", 60 PAUSE 0 70 LET s=0:LET b=s:LET c=-1:LET a=48 80 GO TO 740 90 INK 0:PAPER 6:BORDER 7:CLS 100 GO SUB 700 110 PRINT #1; AT 0,0;"SCORE:0","HIGH SCORE:";s(d*2-1) 120 LET r= INT (RND*10+1) 130 LET dx=(r>5)-(r <=5):LET x=31*(r <=5) 140 LET x1=x 150 LET k$= INKEY$ 160 LET x=x+dx 170 IF x>31 OR x<0 THEN LET dx=-dx:GO TO 160 180 PRINT AT 0,x;"[UDG-C]"; AT 0,x1;" " 190 IF k$ <>"" THEN LET b=b+1:GO TO 210 200 GO TO 140 210 IF b=10 THEN LET c=b 230 IF c=5 THEN LET w$="[UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A]" 240 IF c=0 THEN LET w$= CHR$ 17+ CHR$ 6+ CHR$ 16+ CHR$ 0+ CHR$ 6+ CHR$ 6 250 POKE 23692,255:PRINT #1; AT 0,0,,#2; AT 21,0' PAPER 0; INK INT (RND*6+1);w$;#1; AT 0,0;"SCORE:";s,"HIGH SCORE:";s(d*2-1) 260 PRINT AT 0,x;"[UDG-C]" 270 LET t= USR USR "d":IF t <>65535 THEN GO TO 480 280 BEEP .03,12 290 LET y=0 300 LET y1=y 310 LET y=y+1 320 IF y>21 THEN PRINT AT y1,x;" ":GO TO 120 330 IF ATTR (y,x) <>a THEN GO TO 360 340 PRINT AT y,x;"[UDG-C]"; AT y1,x;" " 350 GO TO 300 360 PRINT AT y1,x;" " 370 LET lx=x:LET rx=x 380 LET l= ATTR (y,lx) 390 LET r= ATTR (y,rx) 400 IF l=a AND r=a THEN GO TO 120 410 IF l <>a AND lx <>rx THEN LET s=s+5:BEEP .01,10+x-lx 420 IF r <>a THEN LET s=s+5:BEEP .01,10+rx-x 430 PRINT #1; AT 0,6;s 440 PRINT AT y,lx;" "; AT y,rx;" " 450 LET lx=lx-(lx>0):LET rx=rx+(rx<31):LET y=y-1 460 IF y<0 THEN GO TO 120 470 GO TO 380 480 FOR i=0 TO 31-t 490 PRINT INK 0; PAPER 7; AT 0,i; OVER 0;"[UDG-B]" 500 BEEP .05,31-i 510 NEXT i 520 PRINT AT 0,i; OVER 1; INK 8;" " 530 LET x=d*2:LET y=x-1 540 IF s10 THEN PRINT AT 7,4;"ONLY 10 Letters PLEASE!":GO TO 560 580 POKE 23658,0 590 IF s >=s(y) THEN LET s$(x)=s$(y):LET s(x)=s(y):LET s$(y)=w$:LET s(y)=s:GO TO 610 600 IF s >=s(x) THEN LET s$(x)=w$:LET s(x)=s 610 CLS 620 PRINT AT 1,10;"HIGH SCORES:" 630 PRINT AT 4,0; 640 FOR i=1 TO 5:PRINT TAB 5;"LEVEL ";i''':NEXT i 650 PRINT AT PI,0 660 FOR i=1 TO 10 STEP 2:PRINT OVER 1; TAB 14; BRIGHT 1;s$(i); TAB 25;s(i)''':NEXT i 670 PRINT AT 4,0 680 FOR i=2 TO 10 STEP 2:PRINT OVER 1; TAB 14;s$(i); TAB 25;s(i)''':NEXT i 690 GO TO 50 700 LET w$="[UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A]" 710 FOR i=17 TO 21 720 PRINT PAPER 0; INK INT (RND*6+1); AT i,0;w$ 730 NEXT i:RETURN 740 PAPER 7:INK 0:BORDER 7:CLS 750 PRINT AT 1,11; INK 0; PAPER 7;"DEMOLITION" 760 PRINT ''" Try to gain points as you"''" DEMOLISH the advancing wall"''" before it reaches you." 770 PRINT '''" To launch the ball-" 780 PRINT '" PRESS the SPACEBAR" 790 PRINT #1; AT 0,0; INK 0; PAPER 6;"SELECT DIFFICULTY ? (1-5):1=HARD" 800 LET w$= INKEY$ 810 IF w$<"1" OR w$>"5" THEN GO TO 790 820 LET d= VAL w$(1) 830 PRINT #1; AT 0,0; INK 0; PAPER 6;" PRESS ANY KEY TO START GAME ":PAUSE 0 840 GO TO 90 850 RESTORE 890:FOR i=0 TO 41:READ x:POKE i,x:NEXT i 860 DIM s$(10,10):DIM s(10) 870 FOR i=1 TO 10:LET s$(i)="..........":NEXT i 880 RETURN 890 DATA 0,126,x,x,x,x,x,0 900 DATA 96,24,06,255,x,06,24,96 910 DATA 24,36,24,60,126,x,60,24 920 DATA 33,0,65,1,32,0,126,254,126,200,35,13,32,-8,1,255,x,201 930 CLEAR :SAVE "Demolition" LINE 10:BEEP .2,15 ```