Effects

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Demo

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 rangePurpose
1–5REM header / GO TO menu
10–90Quake intro: colour-striped title screen, keypress wait, credit screen
100–140Mountain PLOT/DRAW scene; calls machine code loader
150–290Main Quake demo loop, volcano animation, explanatory text, single-shake demo
300–360Menu: repeat / quit / SAVE CODE
370–420Machine code DATA, loader subroutine, notes
500–590Bursting Line demo and subroutine
1000–1040Top-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.

Image Gallery

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 

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