--- title: "ColorCopy" id: 51976 type: "computer_media" slug: "colorcopy" url: "http://localhost/computer_media/colorcopy/" markdown_url: "http://localhost/computer_media/colorcopy.md" published_at: "2023-08-28T01:08:08+00:00" modified_at: "2026-03-30T22:34:48+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2023/08/Color-Copy-IBM-opening.png" excerpt: "A tape-loaded machine code driver lets you configure color, size, and position settings before sending screens to an Okidata dot-matrix printer." 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: "John McMichael" slug: "john-mcmichael" taxonomy: "post_tag" url: "http://localhost/tag/john-mcmichael/" - 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/" indiv: - name: "John McMichael" slug: "john-mcmichael" taxonomy: "indiv" url: "http://localhost/indiv/john-mcmichael/" genre: - name: "Printer" slug: "printer" taxonomy: "genre" url: "http://localhost/type/printer/" media_type: "Program" programmers: - name: "John McMichael" slug: "john-mcmichael" taxonomy: "indiv" url: "http://localhost/indiv/john-mcmichael/" download_url: "https://archive.org/download/timex-sinclair-software-archive/ColorCopy%20%281988%29%28John%20McMichael%29%28US%29%28TS2068%29%28Cassette%29.zip" producer_company: - id: 10989 title: "John McMichael" type: "company" url: "http://localhost/company/john-mcmichael/" images: - url: "http://localhost/wp-content/uploads/2023/08/Color-Copy-IBM-opening.png" - url: "http://localhost/wp-content/uploads/2023/08/Color-Copy-IBM-main.png" - url: "http://localhost/wp-content/uploads/2023/08/McMichael-Color-Copy-IBM-Version.jpg" related_products: - id: 25194 title: "ColorCopy" type: "product" url: "http://localhost/product/colorcopy/" media_type_tags: "Printer" --- This program is a menu-driven front-end for printing screen captures on an Okidata OKI 20 dot-matrix printer using a machine code driver loaded from tape. It lets the user choose between black-and-white or color output, small or large size, and left/center/right/variable horizontal position, then loops for a specified number of copies. The machine code routines are stored at addresses starting around 64440 and are called via RANDOMIZE USR; different entry points handle header display, screen setup, and the four copy-mode combinations (B/W small, B/W large, color small, color large). Position values are patched directly into the machine code at runtime using POKE statements targeting four separate addresses (poka, pokb, pokc, pokd), one for each copy-mode routine. The program loads a SCREEN$ file by name from tape and supports reusing the last loaded screen for subsequent copy runs without reloading. *** ## Program Analysis ### Program Structure The program is split across two BASIC line-10 entries (a loader and the main program), suggesting the listing represents two separately saved programs or program segments. The first line 10 bootstraps the system: it clears memory to 54711, loads a machine code block, and executes it. The second line 10 begins the interactive session after the machine code is resident. The main program then flows through parameter collection, screen loading, and the print loop. 1. **Lines 10–20:** Initialization — stop-recorder prompt, variable setup mapping friendly names to machine code entry points. 2. **Lines 30–40:** Wait for keypress release, then call the header-display routine at `hdld` (64440) and set caps-lock off via `POKE 23658,8`. 3. **Lines 50–330:** Full parameter menu — mode, size, position, number of copies, confirmation. 4. **Lines 340–410:** Screen$ load logic, with option to reuse the previously loaded screen. 5. **Lines 420–510:** Printer-ready prompt, copy execution loop calling `RANDOMIZE USR copy` for each copy. 6. **Line 520:** Loops back to line 30 for another run. ### Machine Code Entry Points All machine code interaction is via `RANDOMIZE USR`. Ten named entry points are stored in variables at initialization: | Variable | Address | Purpose | | --- | --- | --- | | `hdld` | 64440 | Header/title display routine | | `scld` | 64460 | Screen load/preparation routine | | `scst` | 64468 | Post-load screen setup routine | | `poka` | 64485 | Position byte for B/W small copy | | `bwca` | 64505 | B/W small copy routine | | `pokb` | 64586 | Position byte for B/W large copy | | `bwcb` | 64610 | B/W large copy routine | | `pokc` | 64759 | Position byte for color small copy | | `clcc` | 64782 | Color small copy routine | | `pokd` | 65002 | Position byte for color large copy | | `clcd` | 65029 | Color large copy routine | The `poka`–`pokd` addresses are not entry points but operand bytes within the machine code. The program patches all four simultaneously with `POKE` regardless of which copy mode is selected, keeping all routines consistent. ### Key BASIC Idioms - **Boolean arithmetic for positions:** Line 220 uses `9+(16 AND s$="S")` and line 230 uses `16+(32 AND s$="S")` to compute center and right positions differently for small vs. large output — a compact alternative to nested IF statements. - **`INPUT #0`:** Used throughout for all user prompts, which directs input through stream 0 (keyboard) and allows `AT` positioning of the prompt text on screen without disturbing the parameter display area. - **Debounce pattern:** Lines 30 and 480 wait for INKEY$ to clear before proceeding, preventing spurious keypresses from carrying over. - **`POKE 23658,8`:** Enables extended mode / caps-lock suppression by writing to the FLAGS2 system variable, ensuring clean keyboard behavior during INPUT prompts. ### Position Validation When variable positioning is selected (line 240–270), the program computes a `max` value of 16 (large) or 48 (small) using the same boolean arithmetic idiom, then validates the entered position with `IF pos>max THEN GO TO 250`. Note that line 270 always branches back to line 250 on out-of-range input even when the large-size prompt was at line 260 — this is a minor anomaly but functionally acceptable since both prompts accept the same variable `pos`. ### Screen Reuse Logic A flag variable `scr` is set to 1 at startup and on the first pass forces the screen-load path (line 340). Once a screen has been loaded, `scr` is cleared to 0 (line 470), and on subsequent copy runs the user is offered the choice to reuse the loaded screen or load a fresh one (lines 350–370). The screen filename is entered with caps-lock disabled and validated to a maximum of 10 characters (line 390). ### Copy Loop Lines 500–510 implement a simple counted loop: `RANDOMIZE USR copy` calls the selected machine code print routine, decrements `num`, and repeats until the count reaches zero. The screen-setup call at line 490 (`RANDOMIZE USR scld`) is made once before the loop begins, preparing the screen data for repeated printing without reloading it each pass. ### Notable Techniques - All four position-patch POKEs (line 280) are executed unconditionally, keeping all copy routines synchronized to the same position value regardless of which will be called. - The use of named numeric variables (`hdld`, `bwca`, etc.) instead of literal addresses throughout the copy loop and POKEs makes the code significantly more readable and maintainable than embedding raw numbers. - The `BEEP` triplet on line 10 provides an audible stop-recorder signal after the machine code loads, followed by `PAUSE 150` to give the user time to react. ## Source Code ``` 10 BORDER 7: PAPER 7: INK 7: CLEAR 54711: PRINT AT 11,7; INK 0;"LEAVE RECORDER ON.": PRINT AT 7,0;: LOAD ""CODE : RANDOMIZE USR 64440: PRINT AT 7,0;: LOAD "" 10 INK 0: PRINT AT 11,7; FLASH 1; INK 2;"STOP THE RECORDER.": BEEP .03,20: BEEP .03,20: BEEP .03,20: PAUSE 150: PRINT AT 18,3;"PRESS ANY KEY TO CONTINUE.": PAUSE 0: LET scr=1 20 LET hdld=64440: LET scld=64460: LET scst=64468: LET poka=64485: LET bwca=64505: LET pokb=64586: LET bwcb=64610: LET pokc=64759: LET clcc=64782: LET pokd=65002: LET clcd=65029: LET scr=1 30 IF INKEY$<>"" THEN GO TO 30 40 CLS : RANDOMIZE USR hdld: POKE 23658,8 50 PRINT AT 9,8; INK 7; PAPER 1;"COPY PARAMETERS" 60 PRINT AT 11,2;"MODE = ";AT 13,2;"SIZE = ";AT 15,2;"POS. = ";AT 17,2;"COPIES = "'' 70 INPUT #0;AT 0,8;"ENTER COPY MODE:";AT 1,3;"LACK/WHITE OLOR? ";m$ 80 IF m$<>"B" AND m$<>"C" THEN GO TO 70 90 IF m$="B" THEN PRINT AT 11,11; INVERSE 1;"BLACK/WHITE": GO TO 110 100 PRINT AT 11,11; INVERSE 1;"COLOR" 110 INPUT #0;AT 0,8;"ENTER COPY SIZE:";AT 1,6;"MALL ARGE? ";s$ 120 IF s$<>"S" AND s$<>"L" THEN GO TO 110 130 IF s$="S" AND m$="B" THEN LET copy=bwca: GO TO 180 140 IF s$="S" AND m$="C" THEN LET copy=clcc: GO TO 180 150 IF s$="L" AND m$="B" THEN LET copy=bwcb: GO TO 170 160 LET copy=clcd 170 PRINT AT 13,11; INVERSE 1;"LARGE": GO TO 190 180 PRINT AT 13,11; INVERSE 1;"SMALL" 190 INPUT #0;AT 0,6;"ENTER COPY POSITION:";AT 1,0;"EFT NTR IGHT AR ";p$ 200 IF p$<>"L" AND p$<>"C" AND p$<>"R" AND p$<>"V" THEN GO TO 190 210 IF p$="L" THEN LET pos=0: LET a$="LEFT": GO TO 280 220 IF p$="C" THEN LET pos=9+(16 AND s$="S"): LET a$="CENTER": GO TO 280 230 IF p$="R" THEN LET pos=16+(32 AND s$="S"): LET a$="RIGHT": GO TO 280 240 LET max=16+(32 AND s$="S"): LET a$="VARIABLE SET TO " 250 IF s$="S" THEN INPUT #0;AT 0,2;"ENTER POSITION # (0-48) ";pos: GO TO 270 260 INPUT #0;AT 0,2;"ENTER POSITION # (0-16) ";pos 270 LET pos=INT pos: IF pos>max THEN GO TO 250 280 POKE poka,pos: POKE pokb,pos: POKE pokc,pos: POKE pokd,pos: PRINT AT 15,11; INVERSE 1;a$;: IF p$="V" THEN PRINT INVERSE 1;pos 290 INPUT #0;AT 0,6;"NUMBER OF COPIES? ";num: IF num=0 THEN GO TO 290 300 LET num=INT num: PRINT AT 17,11; INVERSE 1;num 310 INPUT #0;AT 0,4;"ARE THE ABOVE PARAMETERS";AT 1,3;"CORRECT? ES OR O ";a$ 320 IF a$<>"Y" AND a$<>"N" THEN GO TO 310 330 IF a$="N" THEN GO TO 60 340 IF scr=1 THEN GO TO 380 350 INPUT #0;AT 0,4;"OAD A NEW SCREEN$ OR";AT 1,4;"SE LAST SCREEN$? ";a$ 360 IF a$="U" THEN GO TO 420 370 IF a$<>"L" THEN GO TO 350 380 POKE 23658,0: INPUT #0;AT 0,1;"NAME OF SCREEN$ TO BE LOADED?";AT 1,10;n$: POKE 23658,8 390 IF LEN n$>10 THEN GO TO 380 400 CLS : RANDOMIZE USR hdld: PRINT AT 14,5; FLASH 1;"LOAD THE SCREEN$ NOW." 410 LOAD n$SCREEN$ : RANDOMIZE USR scst 420 CLS : RANDOMIZE USR hdld 430 PRINT AT 9,9; INK 7; PAPER 1;"PRINTER READY?" 440 IF m$="B" THEN PRINT AT 11,3;"VERIFY BLACK RIBBON+SMOOTH";AT 12,2;"PAPER -OR- NO RIBBON+THERMAL": GO TO 460 450 PRINT AT 12,3;"VERIFY COLOR RIBBON+SMOOTH" 460 PRINT AT 13,6;"PAPER ARE INSTALLED.";AT 15,4;"VERIFY OKI 20 IS ON, AND";AT 17,5;"PRESS ANY KEY TO COPY." 470 IF scr=1 THEN LET scr=0 480 IF INKEY$<>"" THEN GO TO 480 490 PAUSE 0: RANDOMIZE USR scld 500 RANDOMIZE USR copy: LET num=num-1 510 IF num>0 THEN GO TO 500 520 GO TO 30 ```