Machine code program that translates TS1000 programs into 2068 programs. The program translates input bytes from ZX/TS tapes to an equal number of output bytes in your 2068 that you must edit, and then save. Codes & program control structures differ in the two designs, making functionally identical programs use different numbers of bytes.
Program Analysis
Program Structure
The program is divided into several loosely coupled sections, navigated by GO TO rather than a clean menu:
- Lines 2–35: Machine code installation — READ bytes from
DATAand POKE them into addresses 24606–24628, then fall through toSTOPat line 40. - Lines 100–150: Interactive memory editor — accepts a base address, then allows the user to inspect and POKE values into 11 consecutive bytes.
- Lines 205–299: Memory inspector/hex dumper — prints 61 rows of 5 bytes each starting from a user-supplied address, with right-aligned decimal values.
- Lines 300–320: Memory comparison — scans 1235 bytes from address 44000, comparing each byte to its counterpart 6000 bytes higher, printing any mismatches.
- Lines 500–699: Tape loader and usage prompt — loads a CODE block, then instructs the user to
CLEAR 43999and runRANDOMIZE USR 45000. - Lines 700–799: Save section — saves the BASIC loader auto-running at line 500 and the CODE block starting at address 44000 for 1234 bytes.
Machine Code Payload (Lines 10–35)
The 23 bytes POKEd into addresses 24606–24628 are Z80 instructions. Disassembling the DATA values:
| Bytes (hex) | Z80 Mnemonic | Notes |
|---|---|---|
| 01 B5 00 | LD BC, 0x00B5 | Byte count = 181 for first LDIR |
| 11 00 5C | LD DE, 0x5C00 | Destination = 23552 |
| 21 88 6F | LD HL, 0x6F88 | Source = 28552 |
| ED B0 | LDIR | Block copy #1 |
| 01 7C 92 | LD BC, 0x927C | Byte count = 37500 for second LDIR |
| 11 3E 69 | LD DE, 0x693E | Destination = 26942 |
| 21 3E 70 | LD HL, 0x703E | Source = 28734 |
| ED B0 | LDIR | Block copy #2 |
| C9 | RET | Return to BASIC |
The routine copies a 181-byte block and then a large ~37KB block from upper RAM into lower RAM regions, consistent with a game or application relocation scheme. The entry point at address 45000 (referenced in the user prompt at line 610) suggests the actual main code is loaded separately by lines 500–510.
Memory Inspector (Lines 205–295)
This section implements a rudimentary memory dump. It prints 5-byte rows across a 300-byte range (61 iterations via STEP 5). The padding variable b$ is set to two spaces by default (line 207), then widened to three spaces for values under 100 (line 250) and four spaces for values under 10 (line 255), giving right-aligned columns for decimal byte values. The padding is reset to one space at line 270 after each byte is printed. Note that the default assignment at line 207 uses a single space (" ") while line 250 assigns two spaces and line 255 assigns three — the PRINT " ";b$;x; at line 260 prepends an additional space, achieving consistent column widths of 4 characters for all byte values.
Memory Comparison Utility (Lines 300–320)
Lines 300–320 iterate over addresses 44000–45234 and compare each byte to the byte 6000 addresses higher (50000–51234). Any mismatch prints the address and the byte value from the lower region. This is likely a verification tool to confirm that a block copy operation produced an exact duplicate, consistent with the LDIR-based relocation in the machine code payload.
Interactive Memory Editor (Lines 100–150)
The editor at lines 100–150 is a debugging aid. It accepts a start address v via INPUT, then loops through 11 addresses (v to v+10), printing each address, prompting for a new byte value t, printing it, and POKEing it in. The GO TO 207 at line 150 drops directly into the memory inspector after editing, allowing the user to verify the changes just made.
Notable Techniques and Anomalies
- Entry point via line 2:
GO TO 40skips theDATAand loop lines on normal RUN, preventing accidental re-execution of the POKE routine. The machine code is only installed once on first run (lines 15–35 are only reached if jumped to explicitly or run from line 15). - Default address fallback: Line 206 substitutes
v=45000if the user enters 0 at the inspector prompt, a convenient default pointing to the loaded code block. - Tape workflow: The save section (lines 700–710) pairs a BASIC auto-loader (saved with
LINE 500) and a raw CODE block under the same filename"firstloadr", a standard two-file tape distribution technique. - Unreachable sections by design: Sections starting at lines 100, 205, 300, and 600 are only reachable by manually typing
GO TOor by deliberate program flow, functioning as a toolkit of separate utilities within one listing. - Off-by-one in editor loop: The loop at line 110 runs from
vtov+10inclusive, editing 11 bytes rather than the 10 implied by the range label, which may or may not be intentional.
Content
Source Code
2 GO TO 40
10 DATA 1,181,0,17,0,92,33,136,111,237,176,1,124,146,17,62,105,33,62,112,237,176,201
15 FOR i=24606 TO 24628
25 READ v
30 POKE i,v
35 NEXT i
40 STOP
100 INPUT v
110 FOR i=v TO v+10
120 PRINT i,
130 INPUT t
135 PRINT t,
137 POKE i,t
140 NEXT i
150 GO TO 207
205 INPUT "start";v
206 IF v=0 THEN LET v=45000
207 LET b$=" "
210 FOR i=v TO (v+300) STEP 5
220 PRINT i;
230 FOR j=0 TO 4
240 LET x=PEEK (i+j)
250 IF x<100 THEN LET b$=" "
255 IF x<10 THEN LET b$=" "
260 PRINT " ";b$;x;
270 LET b$=" "
280 NEXT j
290 PRINT " ";
295 NEXT i
299 STOP
300 FOR i=44000 TO 45234
310 IF PEEK i<>PEEK (i+6000) THEN PRINT i,PEEK i
320 NEXT i
500 CLS
501 PRINT " Loading code... Please wait"
510 LOAD ""CODE
600 CLS
610 PRINT " Enter: CLEAR 43999 :NEW then: RANDOMIZE USR 45000"
699 STOP
700 SAVE "firstloadr" LINE 500
710 SAVE "firstloadr"CODE 44000,1234
799 STOP
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
