Z-XLR8 is a two-part cassette tape accelerator system that records and plays back data at higher-than-standard speeds using machine code routines embedded in REM statements. The first program handles calibration: it records a timing signal to tape, plays it back into RAM at address 22001–22959, then analyzes the sampled waveform to compute average, low, and high byte values and assess signal quality. The second program is the actual Z-XLR8 loader/saver, which accepts user-supplied timing and calibration values plus a starting memory address, patches several machine code parameters via POKE, and then executes the fast-load/save routine via RAND USR. The machine code in the first program’s REM (line 1) begins at address 16384 and includes routines for tape I/O, delay loops, and byte sampling; the second program’s REM similarly contains a large Z80 routine starting at 16384 that implements the full accelerated tape protocol, including a disassembler-style jump table visible in the opcode data.
Program Analysis
Overall Architecture
Z-XLR8 consists of two independent BASIC programs. The first (lines 1–570) is a calibration utility that records a timing signal to tape, reads it back, analyzes the resulting byte values in RAM, and guides the user to an optimal timing constant. The second (lines 1 and 9000–9082) is the actual fast tape transfer loader, which takes the calibrated parameters and a starting address, patches the embedded machine code via POKE statements, and launches it with RAND USR 18141.
Machine Code Payloads
Both programs carry their Z80 machine code in line 1 REM statements. In the first program the REM at line 1 places code starting at address 16389 (the first byte after the REM token and length bytes). The routine at USR 16700 is called from line 7 as a load-verification check; it returns 65 on a good load. The second program’s REM similarly loads a much larger block; USR 18520 returns 33 as its integrity check (line 9001). The final byte (0x35, decimal 53) in each REM is used as a checksum or sentinel by the machine code.
Program 1 – Calibration Routine Structure
| Lines | Function |
|---|---|
| 1 | REM holding Z80 machine code payload |
| 5 | SAVE the program itself |
| 7–9 | Verify machine code loaded correctly via USR 16700 |
| 10–88 | Setup: POKEs to install the MC, prompt for timing value N, record to tape via RAND USR 16520 |
| 90–103 | User tape management prompts (stop, rewind, play) |
| 104–111 | Delay loop (GOSUB 420), then playback via RAND USR 16625 |
| 120–175 | Statistical analysis of bytes at addresses 22001–22959 |
| 180–205 | Quality assessment and display of calibration result |
| 207–265 | Selection menu: restart, recalibrate, or stop |
| 300–348 | Subroutine: center-print a prompt string and wait for keypress |
| 400–410 | Error handler: timing value out of range |
| 420–440 | Short delay loop (100 iterations) |
| 500–570 | Diagnostic/debug routine: scans for anomalous bytes and prints surrounding values |
Waveform Analysis Algorithm
After playback, 959 bytes are stored starting at address 22001. The calibration analysis at lines 120–175 computes the arithmetic mean (stored as AVG), then makes a second pass to find the highest value below the mean (L) and the lowest value above it (H). Line 181 tests three conditions simultaneously: the midpoint of H and L must be within 1.5 of AVG, and both half-amplitudes must exceed 2, ensuring a reasonably symmetric, well-separated waveform. Line 194 computes the average amplitude A and prints that many asterisks as a visual bar graph.
Lines 400–410 handle out-of-range timing: if a byte exceeds 249 (near the 8-bit ceiling) and N is already above 12, the user is told to decrease the timing value; if N is above 14 the decrease message is also triggered from line 182.
Machine Code Patching – Program 1
Lines 50–80 install the machine code into the system and patch one parameter:
POKE 23000,197— patches a byte in system RAM (possibly a USR vector or stack frame)POKE 16515,216/16516,89/16517,0/16518,64— patches four bytes inside the REM machine code (a 16-bit address pair, likely a destination pointer)POKE 16620,N— writes the user-supplied timing constant into the delay loop within the MC
Machine Code Patching – Program 2
Program 2’s setup (lines 9008–9082) performs more extensive patching:
POKE 16961,N— timing valuePOKE 17107,N— calibration (threshold) value- Lines 9030–9032: stores
TA = L + 1760(the tape-area end address) low/high bytes at addresses 16631/16630 - Lines 9040–9050: stores a four-byte address block at 16450–16455, encoding both a fixed pointer (0x4083 = 16515) and the user-supplied starting address
L RAND USR 18141launches the full fast-transfer routine;NEWclears BASIC afterward
Key BASIC Idioms
- The keypress-wait idiom at lines 319–320:
IF INKEY$<>"" THEN GOTO 319(flush any held key) followed byIF INKEY$="" THEN GOTO 320(wait for a new press). - The centering calculation at line 308:
TAB ((32-SL)/2)whereSL=LEN U$centers text on a 32-column display. - Low/high byte splitting via
INT(x/256)andx - 256*INT(x/256)is used at lines 9030–9032 and 9048–9050 to store 16-bit addresses as two separate POKEs. GOSUB 300withU$pre-set is used throughout as a parameterized message-and-wait subroutine, avoiding repetitive code.
Notable Techniques
The use of the area around address 22001 (0x55F1) as a sample buffer is deliberate: it sits in the display file on a 16K machine but above typical BASIC program space, making it a convenient scratch area for waveform data that does not need to persist. The large second-program REM block contains a sophisticated Z80 routine with what appears to be a jump table (multiple CA xx xx — JP Z,nn — instructions following byte comparisons), suggesting a command dispatcher for different tape operations. The embedded ASCII-encoded strings visible in the second REM (e.g., INPUT DIM NAME TYPE START STOP ERROR VARSAVE in XOR-shifted encoding) indicate the machine code implements a named-file fast tape filing system.
Anomalies and Notes
- Lines 350–365 define a FOR/NEXT loop that iterates 1–4 but does nothing, then returns. This appears to be an unused stub or leftover timing loop.
- Lines 500–570 are never called from the main flow and appear to be a debugging/diagnostic routine for inspecting anomalous sample data.
- The FAST/SLOW calls around the keypress subroutine (lines 310, 340) ensure the display is readable during the prompt but execution resumes at full speed afterward.
- Program 2 calls
NEWat line 9082 immediately afterRAND USR 18141, which would only execute if the machine code routine returns — suggesting the MC is expected to take over completely andNEWis a safety fallback.
Content
Source Code
1 REM 0D859 040 01E64CDB7401D20FA1E 23EFDCDD7401D20F82A8540EB2A83407ECDD7401B 07AB3C2A1401E 23EDDCDD7401D20F8C947DBFE78CDEB40D3FFCDEB40C947DBFE78CDEB40CD2F41D3FFCDEB40CD2F41C9CDC440 E 8 7DCC440D4B740 DC2DC40CDB740C9 619 520FDC9C5D5E5D9C5D5E51EFD21F055D91E78CD15411D 0 0 0 0 0 020F4D9E1D1C1D9E1D1C1C9D9 6 816 015DBFEA7F21A417BBADA184172 523 0C21841D9C9CDEB40CDEB40C9 0 0 0 0 0 03E 0 1B3 0218340865F B78B17B2320F7 6 04FC9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 035
5 SAVE "%C"
7 IF USR 16700=65 THEN GOTO 10
8 PRINT AT 10,11;"BAD LOAD"
9 STOP
10 CLS
25 PRINT AT 7,0
30 PRINT " REWIND AND REMOVE PROGRAM TAPE"
35 LET U$="THEN INSERT BLANK TAPE"
40 GOSUB 300
47 FAST
50 POKE 23000,197
55 POKE 16515,216
60 POKE 16516,89
65 POKE 16517,0
70 POKE 16518,64
75 PRINT AT 8,7;"INPUT TIMING VALUE"
78 INPUT N
79 CLS
80 POKE 16620,N
85 LET U$="START RECORDING TAPE"
86 GOSUB 300
88 RAND USR 16520
90 LET U$="STOP RECORDING TAPE"
91 GOSUB 300
95 LET U$="REWIND TAPE HALF WAY"
96 GOSUB 300
100 LET U$="START PLAYING TAPE"
101 GOSUB 300
104 GOSUB 420
105 RAND USR 16625
110 LET U$="STOP PLAYING TAPE"
111 GOSUB 300
120 LET S=0
125 FOR I=22001 TO 22959
126 IF PEEK I>249 THEN GOTO 400
130 LET S=S+PEEK I
135 NEXT I
140 LET AVG=INT (S/959+.5)
145 LET L=0
150 LET H=255
155 FOR I=22001 TO 22959
160 LET P=PEEK I
165 IF P<AVG AND P>L THEN LET L=P
170 IF P>AVG AND P<H THEN LET H=P
175 NEXT I
180 CLS
181 IF (ABS (AVG-(H+L)/2)<=1.5) AND (H-AVG>2) AND (AVG-L>2) THEN GOTO 190
182 IF N>14 THEN GOTO 402
183 PRINT AT 10,5;"INCREASE TIMING VALUE"
184 LET U$="BAD CALIBRATION"
186 GOSUB 300
188 GOTO 207
190 PRINT AT 3,8;"TIMING VALUE = ";N
192 PRINT AT 6,6;"CALIBRATION VALUE = ";AVG
194 LET A=INT (((H-AVG)+(AVG-L))/2+.5)
196 PRINT AT 10,13;
198 FOR I=1 TO A
200 PRINT "*";
202 NEXT I
204 LET U$="GOOD CALIBRATION"
205 GOSUB 300
207 CLS
208 PRINT AT 8,11;"%S%E%L%E%C%T%I%O%N"
209 PRINT ,,,,,,
210 PRINT TAB 8;"1. RESTART"
215 PRINT TAB 8;"2. RECALIBRATE"
225 PRINT TAB 8;"3. STOP"
230 PRINT AT 17,5;"INPUT SELECTION NUMBER"
235 INPUT X
237 CLS
240 IF X=1 THEN GOTO 75
245 IF X=2 THEN GOTO 100
250 IF X=3 THEN STOP
260 CLS
265 GOTO 207
300 LET SL=LEN U$
304 PRINT AT 8,0
308 PRINT TAB ((32-SL)/2);U$
309 PRINT
310 SLOW
318 PRINT AT 12,0;" : PRESS ANY KEY TO CONTINUE :"
319 IF INKEY$<>"" THEN GOTO 319
320 IF INKEY$="" THEN GOTO 320
340 FAST
345 CLS
348 RETURN
350 FOR I=1 TO 4
360 NEXT I
365 RETURN
400 IF N<13 THEN GOTO 130
402 CLS
405 PRINT AT 10,5;"DECREASE TIMING VALUE"
410 GOTO 184
420 FOR A=1 TO 100
430 NEXT A
440 RETURN
500 FOR I=22001 TO 22959
505 IF PEEK I>249 THEN GOTO 550
510 NEXT I
550 CLS
555 PRINT I
560 FOR J=I TO I+19
565 PRINT PEEK J,PEEK (J+20)
570 NEXT J
1 REM 0C3F540CDDD40CD2B F2A C40233680E5CDB840E1FE7620 4CD23 FC9FE7720 B36 02B7EFE7620 12B18E277237EFE7620DB2318D8CD2B F213B40CB7ECC29 2CB4628FCED4B2540CD4B FCDBD 77EFE77C8FE76C8FE4030DCC92A C4011D6 219 142 023 B78B1C87EFE7628F636 018F2216347227B40CDDD40 6 1CD D45CD9040CDFF44 1 7 0113E40EDB0CDDD40 6 2CD D45CD9040CDFF447E324540237EFE31CA4642FE38CA3241C311413A4540FE37CA 0 0FE27CA5341FE35CAA343FE29CAE343FE2CCA2B44FE2DCA3D44CDDD40 6 3CD7241ED534740CDDD40 6 4CD7241ED534940ED535840C38941CD7F417EFE DCC4E45C42B45C9CD D45CD9040CDFF44C9CDDD40 6 5CD7F413EFD213C40772377CD7745324B40CD8145324C40325B40C3AB41DBFECDD541CDE5411111 0213C40CDF141CDFD41ED5B49402A4740CDF141CDD944CDDD40 6 6CD7F41C9DBFE 6 611 0 01B7AB320FB 520F8C911E8 3CD 6421B7AB320F8C97ECD13421B237AB3C2F141C91EFFCD 6421D20FAC947DBFE78CD4042D3FFCD4042C9CD2742 E 8 7DC2742D4 642 DC21842CD 642C947DBFE78CD4042CD4042CD4042D3FFCD4042CD4042CD4042C9 6FF 520FDC9D9C5D5E53A4540FE2ECA9445FE27CA7142FE35CA4E44FE29CA7544FE2CCAC444FE2DCAD644 6 3C5C35B43CDDD40 6 3CD7241ED534740CDDD40 6 5CD7F41CD9E42CD36432A47407CB528 3225640CD4843CD6E43C39243CDD1421E F214D40CDE042FEFD20F9CDE042FEFD20F2CDE04277231DC2B442213E40114D40 E 71ABEC29E42 D2313C2C542C9D9 EFF1EFBD9C9D9E1E1E1D1C1D9C9D9CD46 FD2D842 6 016FF15DBFEA7F2EB427BBADAE9427A91781747D2E942D9C921 028118340 1F8 7EDB0C921834011E02E 1FA 0EDB0C92A7F40 1FF 0 9227F40218340CD9E 9 1FF 0EB36 02B B78B120F8C9214D401E D9786231D20FBBEC8 61DC35B432A5640ED5B5840CDE04277231B7AB3C24F43C9C5CDDD40 6 7CD D45C17023C1CD9040C392432BED5B584097862B1B477AB378C274433278372A5B40227937ED5B5B40BBC8 61EC35B43D9E1D1C1D9CDD944CDDD40 6 6CD7F41C911 040ED5347402A1440A7ED5223224940225840CDDD40 6 5CD7F413EFD213C40772377CD7745324B403E 0324C40325B40CD8145ED44324C40325B40C3AB41CDDD40 6 8CD7F41CD 444235E2356ED53783723224740ED534940324640C389417ED62047237EFE D3E8020 2CBF7B0472A10407EB8C8FE8020 5 61FC35B43C5CDF2 9C1EB18ECED5B C40ED53474011D7 2ED534940C3894111 020ED53474011 018ED534940C38941CD5A44CD4843CD6E43C39243CDDD40 6 5CD7F41CD9E42CD36432145403A5440BEC8 620C35B43CDDD40 6 8CD7F41CD 444235E235623224740ED534940324640CD5A442146403A554086CB7728 6 621C5C35B432A4940ED5B5840A7ED5230 6 622C5C35B432A4740225640CD4843CD6E43C39243CD5A442A C40225640CD4843CD6E43C39243C34E44DBFE 6 4C3D94150E52A7B40 1FF 03E18EDB11520FB4E 6 0EBE1 92B4713231AB8C87718F82A C4011F8 219237EFE 028FAC92A C4011D7 219E5CDE044E11130 019C9237EFE1C30FA2B2B11 0 0EBC9CD1E45 1 1 0CD6C45 1 A 0CD6C45 164 0CD6C45 1E8 3CD6C45 11027CD6C45EBC9CD1E45 1 1 0CD6C45 110 0CD6C45 1 0 1CD6C45 1 010CD6C45EB97C91A1BD61DD83C 93D20FCC9 6 D3E 02386 520FBC92A4740ED5B49403E 0861B23477AB378C818F6E1D1C1223C40ED533E40ED434040C5D5E5CDDD40 6 5CD7F41CDDD40 6 9CD D45CDC845 6 ACD D45CDC845CDDA45CD934618F52A C40EB132121 019 1F7 2EDB0CDDD40C9CDD1421E F214D40CDE042FEFD20F9CDE042FEFD20F2CDE04277231D20F8CDA746CD1D46CD5246CD304611 D 0193A544077FE2920 5CD39463E 0FE2720 3CDBC46C9CD3046 6 7114C4023131AFE80C877 5C818F32A C402311D6 219C9CD3046111C 0193A5540E63FC62077233A5540CB77C836 DC9CD30461113 019224D40111027CD7B4611E8 3CD7B461164 0CD7B4611 A 0CD7B4611 1 0CD7B46C92A58403E1B3CA7ED5230FA192258402A4D407723224D40C9D92A3C40ED5B3E40ED4B4040D9 1F0 0CD35 FC91E D214D403E 086231D20FB215A40BEC8E1C3DA452A5640225840CD3046111B 019C359462A4640E5ED5B4240A7ED52224840C31748CDCC467EFEC3CA 947FECDCA 947E6C7FEC2CA 947FEC4CA 9477E121323ED4B4440A7E5ED42E138DAC333477E1213234E234623E52A4240A7 3ED42 B30 E2A4440A7ED4238 62A4840 94D44E1EB71237023EB18C82A46401182 11936C9233647C351471936C923362A1117 019362B23362BED5B46402A1440A7ED52D01BED53 440C97618 92E33353A39 02B2E312A 03326322A18 A2E33353A39 02834323226332918 A2E33353A39 0262929372A383818 A2E33353A39 0312A332C392D18 B3839263739 03926352A18 C38393435 03926352A18 E2A3737343718 72E33353A39 0292E32 03B26372E2627312A18 12B2E312A 03326322A 0 0393E352A 0 0312A332C392D 0 03839263739 018 0 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 318 0ED5BB5421922B54222F145D12A4240C928263131 0311F1928263131 D1C2B1E27193129 02D311B101D221F252211192E3328 02D3119 E31213129 0102D31113E 0 194 7218340865F B78B17B2320F7 6 04FC9 0FF 0CF82 021 0 0EF 0BF80 082 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 035
9000 SAVE "%Z"
9001 IF USR 18520=33 THEN GOTO 9004
9002 PRINT AT 10,11;"BAD LOAD"
9003 STOP
9004 CLS
9005 PRINT AT 10,7;"INPUT TIMING VALUE"
9006 INPUT N
9008 POKE 16961,N
9010 CLS
9012 PRINT AT 10,4;"INPUT CALIBRATION VALUE"
9014 INPUT N
9016 POKE 17107,N
9018 CLS
9020 PRINT AT 10,2;"INPUT Z-XLR8 STARTING LOCATION"
9022 INPUT L
9023 IF L=0 THEN STOP
9024 LET TA=L+1760
9030 POKE 16631,INT (TA/256)
9032 POKE 16630,TA-256*INT (TA/256)
9040 POKE 16450,131
9042 POKE 16451,64
9044 POKE 16452,23
9046 POKE 16453,72
9048 POKE 16455,INT (L/256)
9050 POKE 16454,L-256*INT (L/256)
9080 RAND USR 18141
9082 NEW
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.


