--- title: "EPSON COPY" id: 71028 type: "computer_media" slug: "epson-copy" url: "http://localhost/computer_media/epson-copy/" markdown_url: "http://localhost/computer_media/epson-copy.md" published_at: "2026-08-26T01:41:22+00:00" modified_at: "2026-08-26T01:44:59+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "A verified machine code loader that POKEs a Z80 screen dump routine into memory, sending Spectrum display data directly to Epson dot-matrix printers." 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: "Printer" slug: "printer" taxonomy: "genre" url: "http://localhost/type/printer/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/EPSON%20COPY%20%28198x%29%28-%29%28TS2068%29%28US%29%28Program%29.zip" tsrun_member: "EPSON COPY (198x)(-)(TS2068)(US)(Program).tap" mediadate: "198x" media_type_tags: "Printer" --- # EPSON COPY 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”. 1. **Lines 10–30:** Install and checksum-verify 15 blocks of 16 bytes each into RAM starting at address 23296 (0x5B00), then save the result. 2. **Lines 40–180:** Fifteen `DATA` statements, each containing 16 machine code bytes followed by a checksum (sum of the 16 bytes). 3. **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) via `IN 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 n` line 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 final `RET` (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*t` expression in the error message dynamically reconstructs the offending `DATA` line 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 `DATA` group is an arithmetic checksum (simple byte sum, not modular), which catches both transcription errors and off-by-one data shifts. - The final `DATA` block (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" ```