EPSON COPY is a machine code screen dump utility that sends display data to Epson-compatible dot-matrix printers. The BASIC loader POKEs 240 bytes of Z80 machine code into memory starting at address 23296, verifying each 16-byte block against a checksum before saving. The routine interfaces with the printer via port 12 (0Ch), using Z80 instructions such as IN, OUT, and bit manipulation to convert screen pixel data into Epson graphics escape sequences (ESC “A”, ESC “L”). The program is designed to be loaded alongside a companion file called “DRAW DX-85” and saved back as a combined binary for screen dump functionality.
Program Structure
The program is a two-phase BASIC loader. Lines 20–30 handle the installation and verification of machine code, while lines 40–180 contain the raw data. Line 190 acts as a safety STOP, and line 200 saves the BASIC loader itself under the name “EPSON COPY”.
- Lines 10–30: Install and checksum-verify 15 blocks of 16 bytes each into RAM starting at address 23296 (0x5B00), then save the result.
- Lines 40–180: Fifteen
DATAstatements, each containing 16 machine code bytes followed by a checksum (sum of the 16 bytes). - Line 200: Saves the BASIC loader program itself.
Machine Code Installation
The loader uses a pointer variable a initialized to 23296 and increments it with each POKE. After reading each group of 16 bytes, it reads a 17th value and compares it to the running sum s. A mismatch triggers an informative error message indicating the faulty DATA line (20+10*t), then halts with STOP. This is a robust integrity check for typed-in listings.
Save Mechanism
Line 30 uses SAVE *"draw dx-85",23296,256,23298. The asterisk form of SAVE appends a CODE block to an existing microdrive or device file named “draw dx-85”, saving 256 bytes from address 23296 with an autostart address of 23298. This merges the screen dump routine into the companion program rather than creating a standalone file.
Z80 Machine Code Analysis
Disassembling the 240 bytes of payload (15 × 16 bytes, noting the final block is padded with zeros) reveals the following functional areas:
- Entry and setup (block 1, DATA line 40): Loads register pairs and begins iterating over the screen memory region (0x5CB7 = 23735, within display file territory).
- Printer output (blocks 2–3): Uses
RST 16(byte 0xD7) for character output and interfaces with port 0x0C (12 decimal) viaIN A,(12)(0xDB, 0x0C) to poll printer status. - Epson escape sequences (blocks 6–8, DATA lines 90–110): Sends ESC (0x1B), followed by “A” (0x41), byte value 8, and CR (0x0D) — this is the Epson
ESC A nline spacing command. Also sends ESC “L” (0x4C) for graphics mode entry. - Pixel-to-dot conversion (blocks 10–12, DATA lines 140–160): Performs four right-shifts (
SRL= 0xCB 0x1F series) to repack pixel nibbles, consistent with converting Spectrum pixel rows into Epson single-density graphics bytes. - Line termination (block 13, DATA line 160): Sends LF (0x0A) and CR (0x0D) after each graphics row.
- Form-feed and reset logic (blocks 14–15, DATA lines 170–180): Includes conditional bit-set (
SET 7,B= 0xCB 0xFB or similar) and a check against 0xC0, with a finalRET(0xC9) and zero padding.
Checksum Table
| DATA Line | Block | Declared Checksum |
|---|---|---|
| 40 | 1 | 1605 |
| 50 | 2 | 1650 |
| 60 | 3 | 2160 |
| 70 | 4 | 1744 |
| 80 | 5 | 1107 |
| 90 | 6 | 1362 |
| 100 | 7 | 1429 |
| 110 | 8 | 1291 |
| 120 | 9 | 1286 |
| 130 | 10 | 1525 |
| 140 | 11 | 1367 |
| 150 | 12 | 1512 |
| 160 | 13 | 1593 |
| 170 | 14 | 1518 |
| 180 | 15 | 849 |
Notable Techniques
- The
20+10*texpression in the error message dynamically reconstructs the offendingDATAline number, giving the typist precise feedback without storing line numbers separately. - Placement at address 23296 (0x5B00) uses the area just below the system variables at 23552 (0x5C00), a common location for short machine code routines that avoids disturbing RAMTOP or the BASIC program.
- The 17th value in each
DATAgroup is an arithmetic checksum (simple byte sum, not modular), which catches both transcription errors and off-by-one data shifts. - The final
DATAblock (line 180) contains six trailing zero bytes, indicating the actual machine code is shorter than the full 240 bytes allocated — padding is used to maintain uniform block structure for the checksum loop.
Potential Anomalies
The SAVE * syntax (line 30) targets a Microdrive or Interface 1 device; the program will error on a standard tape interface without modification. Additionally, the companion file “draw dx-85” must already exist on the target device before line 30 executes, as the asterisk-form save appends rather than creates.
Source Code
10 REM SCREEN COPY ON EPSON PRINTERS "COPY.EPSON"...LOAD WITH "DRAW DX-85"...FOR SCREEN DUMP
20 LET a=23296:FOR t=1 TO 15:LET s=0:FOR n=1 TO 16:READ b:POKE a,b:LET s=s+b:LET a=a+1:NEXT n: READ b:IF b <>s THEN PRINT "Error in line";20+10*t:STOP
30 NEXT t:SAVE *"draw dx-85",23296,256,23298:STOP
40 DATA 2,6,33,183,92,1,60,91,113,35,112,219,12,225,195,226,1605
50 DATA 1,197,197,22,8,120,215,176,34,71,4,126,7,16,253,203,1650
60 DATA 19,193,4,197,21,32,238,193,193,201,213,95,205,121,26,209,2160
70 DATA 201,58,0,91,61,200,62,3,50,0,91,201,254,252,194,26,1744
80 DATA 1,33,71,91,195,9,1,205,65,10,205,219,1,1,0,0,1107
90 DATA 62,27,205,42,91,62,65,205,42,91,62,8,205,42,91,62,1362
100 DATA 13,205,42,91,205,62,12,40,21,246,32,254,97,32,15,62,1429
110 DATA 27,205,42,91,62,65,205,42,91,62,12,195,42,91,58,1,1291
120 DATA 91,95,28,29,40,7,62,32,205,42,91,24,246,62,27,205,1286
130 DATA 42,91,62,76,205,42,91,175,205,42,91,205,49,91,58,0,1525
140 DATA 91,205,42,91,205,17,91,205,49,91,123,40,24,31,31,31,1367
150 DATA 31,22,4,203,15,203,27,203,43,21,32,247,123,205,42,91,1512
160 DATA 123,205,42,91,123,205,42,91,12,32,217,62,10,205,42,91,1593
170 DATA 62,13,205,42,91,205,49,91,62,8,40,2,203,63,128,254,1518
180 DATA 192,200,71,195,100,91,0,0,0,0,0,0,0,0,0,0,849
190 STOP
200 SAVE "EPSON COPY"Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.