--- title: "Effects" id: 71032 type: "computer_media" slug: "effects" url: "http://localhost/computer_media/effects/" markdown_url: "http://localhost/computer_media/effects.md" published_at: "2026-08-26T01:39:07+00:00" modified_at: "2026-08-26T01:40:47+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/08/effects-2.png" alt: "Effects screen" excerpt: "Two showpiece effects in one program: a relocatable Z80 machine code screen-shaker and a BASIC text animation that explodes a line outward from its center." 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: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Effects%20%28198x%29%28-%29%28TS2068%29%28US%29%28Program%29.zip" tsrun_member: "Effects (198x)(-)(TS2068)(US)(Program).tap" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/08/effects-2.png" alt: "Effects screen" - url: "http://localhost/wp-content/uploads/2026/08/effects.png" alt: "Effects screen" media_type_tags: "Demo" --- # Effects Effects is a two-part demonstration program offering a Z80 machine code screen-shake (“Earthquake”) effect and a BASIC text “bursting line” animation. The machine code routine, stored at address 40000 and loaded via DATA statements at line 3000, occupies approximately 80 bytes and is described as relocatable, making it suitable for placement in a REM statement, the printer buffer, or any free memory area. The earthquake effect works by calling USR 40000 repeatedly in a loop, with optional PAUSE delays between calls controlled by 118 (HALT) bytes in the machine code that can be replaced with zeroes for a faster shake. The bursting-line subroutine at line 570 uses string slicing to progressively reveal characters from both ends of a string toward the center, combined with BEEP tones that rise in pitch with each iteration. *** ### Program Structure The program begins with a menu at line 1000 that lets the user choose between two self-contained demonstrations. Effect 1 (Quake) starts at line 10; Effect 2 (Bursting Line) starts at line 500. Lines 1020–1040 branch accordingly via `RUN 10` or `RUN 500`, which restarts the interpreter and clears variables — a common Spectrum idiom for jumping cleanly between major sections without GOTO spaghetti. | Line range | Purpose | | --- | --- | | 1–5 | REM header / GO TO menu | | 10–90 | Quake intro: colour-striped title screen, keypress wait, credit screen | | 100–140 | Mountain PLOT/DRAW scene; calls machine code loader | | 150–290 | Main Quake demo loop, volcano animation, explanatory text, single-shake demo | | 300–360 | Menu: repeat / quit / SAVE CODE | | 370–420 | Machine code DATA, loader subroutine, notes | | 500–590 | Bursting Line demo and subroutine | | 1000–1040 | Top-level selector menu | ### Machine Code Loader The subroutine at line 380 uses `RESTORE 400` followed by a `FOR` loop that READs 77 bytes and POKEs them into memory starting at address 40000. This is the standard Spectrum technique for embedding machine code in a BASIC program without a separate binary file. The routine is explicitly described as relocatable, meaning the target address can be changed to suit available RAM — possibilities mentioned include a REM statement, the printer buffer, or other free areas. The DATA is split across lines 400 and 410. Notable within the byte sequence are multiple occurrences of the value `118`, which is the opcode for the Z80 `HALT` instruction. In this context HALT suspends the CPU until the next interrupt (effectively a ~20 ms pause per occurrence), providing the timing delays that give the shake its character. The comments note these can be replaced with `0` (`NOP`) for a faster effect. ### Quake Effect Invocation The earthquake is triggered by assigning the result of `USR 40000` to a dummy variable `a` (lines 160, 180). Using `LET a= USR …` rather than `RANDOMIZE USR …` is slightly unusual; both call the routine, but `RANDOMIZE USR` is the more conventional idiom when the return value is irrelevant. Here it works correctly because BASIC discards the value into `a`. Multiple calls in a `FOR` loop (1–3 or 1–20 iterations) produce the earthquake intensity variation, with `PAUSE (RND*10)+1` between calls for irregular timing. ### Volcano Animation Line 170 uses `FLASH 1` together with block-graphic characters (▚, ▞) placed with `AT` to simulate an erupting volcano over the mountain scene. The comment explicitly labels this as “Turns on volcano!” Line 190 clears the same screen positions with spaces to extinguish it. The use of `AT PI` (which evaluates to `AT 3` since INT(PI)=3 on the Spectrum) is a compact way to reference row 3 without a literal digit — a memory-saving trick also used in `PAUSE NOT PI` (= `PAUSE 0`, the standard indefinite-pause idiom) and `NOT PI` used as a coordinate (evaluates to 0). ### Colour-Striped Title Screen Lines 20–40 create an alternating two-colour striped display by swapping INK colour `a` and PAPER colour `b` each iteration using the temporary variable `c`. Starting values are INK 2 (red) and PAPER 7 (white), swapping on each of the 22 rows to produce a barber-pole striped “STOP THE TAPE” banner. ### Bursting Line Subroutine The subroutine at line 570 implements a symmetric text reveal: starting from the midpoint of string `B$`, each iteration of the `FOR N` loop prints a slice that grows one character inward from the left and one from the right simultaneously. The key expression is: - `B$(TO N)` — the first N characters (left portion) - `B$(M-N+1 TO)` — the last N characters (right portion) - Both are concatenated implicitly by adjacent PRINT items and positioned with `AT VT, 16-N` so the left edge moves left as N grows Line 570 pads `B$` with a trailing space if its length is odd, ensuring `M/2` is always an integer. A `BEEP .02, 2*N` call rises in pitch with each step, giving an ascending “whoosh” sound effect synchronized to the animation. ### Menu and Flow Control The top-level menu (line 1000) uses `INPUT` to read a numeric choice, then branches with `IF a=1 THEN RUN 10` and `IF a=2 THEN RUN 500`. `RUN 1040` at the end restarts the menu if an invalid value is entered. The Quake section’s own menu (lines 300–360) uses a debounce pattern: line 310 loops while `INKEY$<>""` to flush any held key before `PAUSE NOT PI` waits for a fresh keypress — a robust technique to avoid spurious key repeats. ### Notable Techniques and Observations - `NOT PI` evaluates to 0 and `INT(PI)` = 3; using `AT PI` as `AT 3` and `AT NOT PI, NOT PI` as `AT 0,0` saves bytes versus literal digits. - `PAUSE NOT PI` (= `PAUSE 0`) is the standard indefinite-wait-for-keypress idiom. - Line 350 demonstrates an in-program SAVE: it prints the command for user reference before executing `SAVE "QUAKE" CODE 40000,80`, which writes just the machine code bytes to tape, independent of the BASIC. - The program’s REM at line 1 contains non-printing control characters that appear to be a self-listing or menu artifact rather than functional code. - Line 60 calls `RANDOMIZE USR 26727` — address 26727 is inside the Spectrum ROM and is commonly used to produce a key-click sound or a specific ROM routine call; its exact effect here is context-dependent on the ROM version. - The `DRAW 7, NOT PI` at line 130 draws a horizontal line of 7 pixels (dy=0), another use of `NOT PI` = 0 as a coordinate argument. ## Source Code ``` 1 REM USE LIST 2ddRETURN :H\NEW o AND gGO SUB i{= CLEAR GO SUB a{= CLEAR LIST d RETURN :H\NEW o AND gGO SUB i{= CLEAR GO SUB a{= CLEAR LIST <>oo 5 GO TO 1000 10 BORDER 5:PAPER 5:LET a=2:LET b=7:CLS 20 FOR i=0 TO 21 30 PRINT AT i,8; INK a; PAPER b;"STOP THE TAPE " 40 LET c=a:LET a=b:LET b=c:NEXT i 50 PRINT #1; INK 9;" PRESS ANY KEY TO TURN PAGE " 60 RANDOMIZE USR 26727 70 IF INKEY$="" THEN GO TO 60 80 BORDER 7:PAPER 7:INK 9:BRIGHT 0:CLS :BORDER 5 90 PRINT AT 18,0; INK 2;" Wizard Prang "; INK 1;"presents-"' TAB 9; PAPER 6;" EARTHQUAKE "; PAPER 7'" another world shattering Z80 machine code effect routine." 100 REM DRAW MOUNTAINS 110 PLOT 8,40:DRAW 24, NOT PI:DRAW 37,48:DRAW 24,-40:PLOT 86,60:DRAW 50,64 120 DRAW 5,-6:DRAW 5,4:DRAW 4,-7:DRAW 5,8:DRAW 48,-88:PLOT 182,75:DRAW 24,24:DRAW 31,-40 130 DRAW 7, NOT PI:PLOT 116,98:DRAW 13,1:DRAW 7,-5:DRAW 11,5:DRAW 10,-4:DRAW 4,5:DRAW 9,-5 140 GO SUB 380:REM CODE POKER 150 REM SHAKE IT UP 160 FOR i=1 TO 3:LET a= USR 40000:PAUSE (RND*10)+1:NEXT i 170 PRINT AT 1,17; FLASH 1;"▚▚"; AT 2,16;"▞▚▚▞"; AT PI,17;"▞▚"; FLASH 0; AT 4,17;"!!!"; AT 5,17;"!!!":REM Turns on volcano! 180 FOR i=1 TO 20:LET a= USR 40000:PAUSE (RND*10)+1:NEXT i 190 PRINT AT 1,17;" "; AT 2,16;" "; AT PI,17;" "; AT 4,17;" "; AT 5,17;" ":REM Turns off volcano! 200 PRINT AT NOT PI, NOT PI; INK 2;" R to REPEAT- Other to CONTINUE " 210 PAUSE NOT PI 220 IF INKEY$="r" OR INKEY$="R" THEN PRINT AT NOT PI, NOT PI;" "; TAB 1:GO TO 150 230 CLS :PRINT " This routine is relocatable and requires about 80 bytes of memory, so you could stick it in a REM like we do with our 'STOP TAPE' siren, or in the printer buffer or wherever." 240 PRINT " At the moment, the code is at address 40000, and also in DATA statements in BASIC, at line 3000, in decimal form. Each time the code is called the screen shakes once, so a single call gives a 'hit by a missile' effect, and multiple calls give an earthquake." 250 PRINT " You will be able to SAVE the code on its own via the menu on the next page, or just edit the BASIC to suit yourself. There are lots of REMs. "'" Press Q to turn page, or any other to see a single shake." 260 PAUSE NOT PI 270 IF INKEY$="q" OR INKEY$="Q" THEN GO TO 300 280 RANDOMIZE USR 40000:GO TO 260:REM SINGLE SHAKE 290 REM MENU 300 CLS :PRINT '''''" Press R to Read Again"''" Press Q to Quit"''" Press S to SAVE CODE " 310 IF INKEY$ <>"" THEN GO TO 310 320 PAUSE NOT PI 330 IF INKEY$="r" OR INKEY$="R" THEN RUN 80 340 IF INKEY$="q" OR INKEY$="Q" THEN BORDER 7:CLS :PRINT AT 10,8;"START THE TAPE":LOAD "" 350 IF INKEY$="s" OR INKEY$="S" THEN CLS :PRINT AT 10,4;"SAVE ""QUAKE""CODE 40000,80":SAVE "QUAKE"CODE 40000,80 360 GO TO 300 370 REM QUAKE code in decimal data form, with loader. Locates code at 40000, change to suit. 380 RESTORE 400:FOR i=0 TO 76:READ code:POKE 40000+i,code:NEXT i:RETURN 390 REM The '118's are machine code equivalents of 'PAUSE 1'. Replace with zeroes for faster shake. 400 DATA 58,0,64,245,58,255,90,245,58,255,87,245,33,0,64,84,93,1,254,26,35,237,176,251,118,118,118,118,58,255,87,50,254,87,33,255,90,84,93,1,253,26,43,43 410 DATA 237,184,251,118,118,118,118,118,118,33,0,64,84,93,1,254,26,35,237,176,241,50,255,87,241,50,255,90,241,50,0,64,201 420 REM SAVE /"QUAKE" LINE 1:REM PRINT "Verify...":VERIFY /"QUAKE" 500 REM To use as a subroutine, Define b$: <=32 char, Define vt: PRINT Line, Gosub 80 510 LET b$="DEMONSTRATION OF LINE EXPLOSION" 520 LET vt=0 530 LET vt=vt+1 540 GO SUB 570 550 IF vt=21 THEN STOP 560 GO TO 530 570 LET M= LEN B$:IF M/2 <> INT (M/2) THEN LET B$=B$+" ":LET M=M+1 580 FOR N=1 TO M/2:PRINT AT VT,16-N;B$( TO N);B$(M-N+1 TO ):BEEP .02,2*n:NEXT N:RETURN 590 REM SAVE /"BURSTLINE" LINE 130 1000 CLS :PRINT '''' TAB 12;"Effects" 1010 PRINT ''''" 1 Quake"''" 2 Bursting line" 1020 INPUT "Select 1, 2, ";a:IF a=1 THEN RUN 10 1030 IF a=2 THEN RUN 500 1040 RUN ```