This BASIC program is a configuration and management utility for the AERCO Relocatable Centronics Print Driver, a 800-byte machine code block that is loaded into high RAM (default base address 64000) to provide printer output support. The program allows the user to customize the driver for eight different dot-matrix printers—including the Seikosha GP-100, Prowriter 8510, Star Gemini, Epson models, Olivetti PR2300, Seikosha 250, and MT Spirit 80—by POKEing printer-specific escape-code sequences and control bytes into the machine code block at calculated offsets from the base address. A key design feature is that the driver remains relocatable (loadable at any base address) until it is activated via RANDOMIZE USR, after which its internal addresses are fixed. The program also manages linefeed auto-switching, print width, a COPY screen-dump function, tape backup and verification, and includes a multi-page help system. Control bytes for features such as line width and linefeed are stored at fixed offsets (BASE+4 and BASE+5), and printer-type configuration data is written to offset regions TA (BASE+388), TG (BASE+405), and TT (BASE+440) using DATA statements and FOR/NEXT POKE loops.
Program Analysis
Program Structure
The program is organized into high-numbered line ranges, all above 8000, making it suitable for appending to a user’s own BASIC program. The major functional sections are:
- Lines 8000–8038: Entry point and REMs including fairware notice and author contact.
- Lines 8090–8212: Tape load, backup, and verify routines.
- Lines 8900–8954: Initialization — computes all key offsets from the base address
Binto named variables. - Lines 9000–9150: Main menu — displays options and dispatches on keypress.
- Lines 9220–9236: Linefeed toggle and width input handlers.
- Lines 9400–9498: Printer type configuration routines (types 1–8) using DATA and POKE.
- Lines 9500–9692: Test menu — exercises LPRINT, LLIST, and two COPY variants including a graphics pattern generator.
- Lines 9700–9798: Multi-page help system with menu-driven pagination.
- Lines 9900–9920: Save and verify routine, with a guard check to prevent saving a driver that has already been activated.
Machine Code Driver Interface
The program does not contain machine code directly; instead it loads a separate 800-byte binary file (RADRIVER) and configures it by POKEing values at well-defined offsets from the base address B (default 64000). All offset variables are computed once at line 8910–8912:
| Variable | Offset | Purpose |
|---|---|---|
TA | BASE+388 | Initialization escape sequence bytes |
TG | BASE+405 | Graphics/bit-image escape sequence |
TT | BASE+440 | Tab/line termination sequence |
L1–L7 | Various | Jump targets and control flow patches inside the MC |
c1 | BASE+450 | Standard COPY entry point |
c2 | BASE+612 | Olivetti PR2300-specific COPY entry point |
| BASE+4 | — | Print width (stored as width−1) |
| BASE+5 | — | Linefeed switch (10 = ON, 0 = OFF) |
The relocatability guard is implemented by checking PEEK 64040 and PEEK 64041 for values 8 and 0 respectively (lines 8204, 9902). Once the driver is activated with RANDOMIZE USR BASE, these bytes change, and the program refuses to save or back up the now-fixed driver, printing an error message instead.
Printer Type Configuration
Eight printer types are supported. Each type handler POKEs a sequence of bytes read from DATA statements into the TA, TG, and TT regions, followed by individual POKEs to L1–L5 for internal jump address bytes. The two DATA lines used are:
- Line 9438: For types 3, 4, and 8 (Star Gemini / Epson family):
3,27,51,16,4,27,75,0,1,2,27,64 - Line 9498: For type 2 (Prowriter 8510, also used as default init):
6,27,84,49,54,27,62,6,27,83,48,50,53,54,4,27,60,27,65 - Line 9478: For type 7 (Seikosha 250):
3,27,76,2,8,27,16,0,111,27,71,1,0,3,27,76,3
Types 4 and 8 reuse the type 3 subroutine (GO SUB 9435) and then patch a single byte at TA+3 to differentiate them (24 for type 4, 21 for type 8). The Olivetti PR2300 (types 5 and 6) shares most configuration with type 2 but additionally writes to L6 (BASE+586) and L7 (BASE+587) to set zoom or normal mode.
Key BASIC Idioms and Techniques
- Keypress debounce: The idiom at lines 9110–9114 (and mirrored at 9791–9793) first waits for the previously-seen key to be released, then waits for any new keypress — preventing key repeat and double-firing.
- Lowercase normalization: Line 9116 converts lowercase input to uppercase using
CHR$ (CODE k$-32)whenk$>"`"(i.e., ASCII > 96), avoiding duplicate IF branches for each letter. - RESTORE before READ in loops: Each printer-type routine calls
RESTOREto its ownDATAline before reading, ensuring correct data is used regardless of priorREADstate. - Paginated help: The help system (lines 9700–9798) uses a
retvariable to track which help page to display next, withGO TO retvia a shared input-check subroutine at line 9790. This implements a simple state machine for multi-page display. - Input validation loop: The width input at lines 9231–9233 iterates over each character of the input string to confirm all are digits before calling
VAL, avoiding a crash on non-numeric input.
Graphics Test Pattern
The COPY test routine at lines 9680–9692 generates a geometric test image before printing. It draws two families of diagonal lines using DRAW OVER 1 (XOR mode) to create a crossed pattern, then adds a border rectangle and a series of concentric circles (CIRCLE 127,87,i for i from 20 to 70 in steps of 10). This provides a visually rich but programmatically compact screen to verify the printer’s bit-image graphics capability.
Bugs and Anomalies
- Line 8114 uses lowercase
q$instead of the uppercaseQ$used in line 8110 and 8112. On most Sinclair BASIC interpreters, variable names are case-sensitive for string variables, soq$andQ$are distinct variables. The value entered by the user is stored inQ$, so the test at 8114 againstq$(which is empty) will always be false. The program falls through to line 8116 regardless of input, but since 8112 handles “Y”/”y” first and 8116 loops back, the only practical effect is that “n”/”N” is not caught at 8114 and instead loops back through 8116 to re-prompt — a minor but real bug. - Line 9415 is defined as a shared “update type indicator” stub but is also the fall-through target from lines that
GO TO 9415after configuration. Since line 9416 (GO TO 9100) is immediately after and also goes to the main menu, line 9416 is redundant dead code. - The test menu at line 9515 uses
INPUT Q$withoutLINE, meaning single-character entry requires ENTER to be pressed, making the UX inconsistent with the main menu’s direct INKEY$ approach.
Content
Image Gallery
Source Code
8000 LET B=64000: LET BASE=B: GO TO 8900
8010 REM RELOCATABLE AERCO
8014 REM CENTRONICS PRINT DRIVER
8016 REM VERSION 4T (7-26-85)
8018
8020 REM **A FAIRWARE PROGRAM**
8022 REM **COPYING IS WELCOME**
8024
8026 REM IF YOU LIKE THIS PROGRAM, PLEASE SEND $5.00 TO THE AUTHOR:
8028
8030 REM JACK DOHANY
8032 REM 325 O'CONNOR ST.
8034 REM MENLO PARK, CA 94025
8036 REM (415) 321-7684
8038
8040
8090 CLS : PRINT "**RELOCATABLE AERCO DRIVER V4**": RETURN
8100 REM LOAD MC
8101 CLEAR 63999
8102 BORDER 0: PAPER 0: INK 7: GO SUB 8090: PRINT AT 10,0;"LOADING 800-BYTE DRIVER CODE"'" AT LOC 64000 FOR CUSTOMIZING."
8104 LOAD "RADRIVER"CODE 64000
8106 LET B=64000: LET BASE=B
8108 GO SUB 8090
8110 INPUT "MAKE BACKUP? (Y/N): ";Q$: IF Q$="" THEN GO TO 8110
8112 IF Q$="Y" OR Q$="y" THEN GO TO 8200
8114 IF q$="n" OR q$="N" THEN GO TO 8900
8116 GO TO 8110
8200 REM BACKUP
8204 IF PEEK 64040<>8 OR PEEK 64041<>0 THEN GO TO 9920
8208 GO SUB 8090: PRINT AT 10,0;"MAKING TWO-PART BACKUP": SAVE "RALOADER" LINE 8100: BEEP .1,10: SAVE "RADRIVER"CODE 64000,800
8210 GO SUB 8090: PRINT AT 10,0;"REWIND and PLAY to VERIFY"''"or BREAK and RUN."
8212 VERIFY "": VERIFY ""CODE : GO TO 8108
8900 REM INITIALIZE
8905 LET k$=""
8906 LET L$="OFF": IF PEEK (B+5)=10 THEN LET L$="ON "
8908 LET width=1+PEEK (B+4)
8910 LET TA=B+388: LET TG=B+405: LET TT=B+440
8912 LET l1=b+456: LET l2=b+480: LET l3=b+492: LET l4=b+494: LET l5=b+500: LET l6=b+586: LET l7=b+587
8914 LET c1=b+450: LET c2=b+612
8920 GO SUB 9490: LET typ=2
8954 GO TO 9000
9000 REM MAIN MENU
9050 CLS : PRINT TAB 6;"*** MAIN MENU ***"
9052 PRINT '"H: HELP (INSTRUCTIONS)"''"W: SET WIDTH";TAB 20;"-NOW ";width;'"L: LINEFEED SWITCH";TAB 20;"-NOW": GO SUB 9226
9060 PRINT "S: SAVE CUSTOMIZED DRIVER"'"T: TEST CUSTOMIZED DRIVER"'"Q: QUIT"
9070 PRINT AT 10,5;" TO CUSTOMISE DRIVER "'"PLEASE SELECT YOUR PRINTER TYPE:"''" 1: Seikosha GP100"'" 2: Prowriter 8510"'" 3: Star Gemini, older Epsons"'" 4: Newer Epsons"'" 5: Olivetti PR2300 Zoom"'" 6: Olivetti PR2300 Normal"'" 7: Seikosha 250"
9073 PRINT " 8: MT Spirit 80"
9074 PRINT AT 12+typ,1; INVERSE 1;typ
9100 PRINT #1;AT 1,4;"** Please press a key ** "
9110 IF k$=INKEY$ THEN GO TO 9110
9112 IF INKEY$="" THEN GO TO 9112
9114 LET k$=INKEY$: BEEP .01,25
9116 IF k$>"`" THEN LET k$=CHR$ (CODE k$-32)
9120 IF K$="H" THEN GO TO 9700
9122 IF k$="W" THEN GO TO 9230
9124 IF k$="L" THEN GO TO 9220
9128 IF k$="S" THEN GO TO 9900
9130 IF K$="T" THEN GO TO 9500
9132 IF k$="Q" THEN CLS : PRINT AT 10,9;" OK TO RUN ": STOP
9134 IF k$="1" THEN GO TO 9410
9135 IF k$="2" THEN GO TO 9420
9136 IF k$="3" THEN GO TO 9430
9137 IF k$="4" THEN GO TO 9440
9138 IF k$="5" THEN GO TO 9450
9139 IF k$="6" THEN GO TO 9460
9140 IF k$="7" THEN GO TO 9470
9141 IF k$="8" THEN GO TO 9480
9150 GO TO 9110
9220 IF PEEK (b+5)=0 THEN POKE b+5,10: GO TO 9224
9222 POKE b+5,0
9224 GO SUB 9226: GO TO 9110
9226 LET L$="OFF": IF PEEK (b+5)=10 THEN LET L$="ON "
9228 PRINT AT 5,25; INVERSE 1;L$: RETURN
9230 INPUT "WIDTH: "; LINE q$: IF q$="" THEN GO TO 9100
9231 FOR i=1 TO LEN q$
9232 IF q$(i)<"0" OR q$(i)>"9" THEN GO TO 9230
9233 NEXT i
9235 IF VAL q$<2 OR VAL q$>255 THEN GO TO 9230
9236 LET width=VAL q$: POKE b+4,width-1: PRINT AT 4,25;width;" ": GO TO 9100
9400 REM TYPES
9402 LET copy=c1: RETURN
9404 LET copy=c2: RETURN
9410 REM type 1
9412 GO SUB 9402: POKE TA,1: POKE TA+1,8: POKE TG,0: POKE TT,1: POKE TT+1,15: POKE L1,25: POKE L2,64: POKE L3,251: POKE L4,11: POKE L5,11
9415 PRINT AT 12+typ,1;typ: LET typ=CODE k$-48: PRINT AT 12+typ,1; INVERSE 1;typ: GO TO 9100
9416 GO TO 9100
9420 REM type 2
9422 GO SUB 9490: GO TO 9415
9430 REM type 3
9432 GO SUB 9435: GO TO 9415
9435 GO SUB 9402: RESTORE 9438: FOR i=TA TO TA+3: READ by: POKE i,by: NEXT i: FOR i=TG TO TG+4: READ by: POKE i,by: NEXT i: FOR i=TT TO TT+2: READ by: POKE i,by: NEXT i
9436 POKE L1,24: POKE L2,1: POKE L3,35: POKE L4,195: POKE L5,35: RETURN
9438 DATA 3,27,51,16,4,27,75,0,1,2,27,64
9440 REM type 4
9442 GO SUB 9435: POKE TA+3,24
9446 GO TO 9415
9450 REM type 5
9452 GO SUB 9404: POKE L6,27: POKE L7,47: GO TO 9415
9460 REM type 6
9462 GO SUB 9404: POKE L6,0: POKE L7,0: GO TO 9415
9470 REM type 7
9471 GO SUB 9402
9472 RESTORE 9478: FOR i=TA TO TA+3: READ by: POKE i,by: NEXT i: FOR i=TG TO TG+8: READ by: POKE i,by: NEXT i: FOR i=TT TO TT+3: READ by: POKE i,by: NEXT i
9474 POKE L1,24: POKE L2,128: POKE L3,59: POKE L4,251: POKE L5,59
9476 GO TO 9415
9478 DATA 3,27,76,2,8,27,16,0,111,27,71,1,0,3,27,76,3
9480 REM TYPE 8
9482 GO SUB 9435: POKE TA+3,21
9484 GO TO 9415
9490 REM initialize (type 2)
9491 GO SUB 9402
9493 RESTORE 9498: FOR i=TA TO TA+6: READ by: POKE i,by: NEXT i: FOR i=TG TO TG+6: READ by: POKE i,by: NEXT i: FOR i=TT TO TT+4: READ by: POKE i,by: NEXT i
9494 POKE L1,24: POKE L2,128: POKE L3,59: POKE L4,251: POKE L5,59
9495 RETURN
9498 DATA 6,27,84,49,54,27,62,6,27,83,48,50,53,54,4,27,60,27,65
9500 REM TEST
9510 CLS : PRINT TAB 10;"** TEST **"''"1: LPRINT"''"2: LLIST"''"3: COPY (to T/S 2040)"''"4: COPY (RANDOMIZE USR ";copy;")"''"0: RETURN TO MAIN MENU"
9512 PRINT '"NOTE: TESTING WILL TURN THE"'"DRIVER ON AND MAKE IT NO LONGER"'"RELOCATABLE."
9515 INPUT Q$: IF Q$="" THEN GO TO 9515
9520 IF Q$="0" THEN GO TO 9000
9522 IF Q$="1" OR Q$="2" OR Q$="4" THEN RANDOMIZE USR BASE
9523 IF Q$="1" THEN GO TO 9610
9524 IF Q$="2" THEN GO TO 9620
9525 IF Q$="3" THEN GO TO 9630
9526 IF Q$="4" THEN GO TO 9640
9530 GO TO 9515
9610 REM LPRINT
9612 CLS : LET Q$="This is a test."+CHR$ 13+"Linefeed Switch is "+L$+"."+CHR$ 13+"End of test."
9614 PRINT q$: LPRINT q$
9616 PAUSE 200: GO TO 9500
9620 REM LLIST
9624 LLIST 9700: GO TO 9500
9630 REM COPY 2040
9632 GO SUB 9680: COPY : GO TO 9616
9640 REM COPY AERCO
9644 GO SUB 9680: RANDOMIZE USR copy: PAUSE 200: GO TO 9500
9680 CLS : FOR f=0 TO 174 STEP 2: PLOT 0,f: DRAW OVER 1;f,174-f: PLOT 255,f: DRAW OVER 1;-f,174-f: NEXT f
9682 FOR f=0 TO 174 STEP 2: PLOT 0,f: DRAW OVER 1;174-f,-f: PLOT 255,f: DRAW OVER 1;-174+f,-f: NEXT f
9690 PLOT 0,0: DRAW 0,175: DRAW 255,0: DRAW 0,-175: DRAW -255,0: FOR i=20 TO 70 STEP 10: CIRCLE 127,87,i: NEXT i
9692 RETURN
9700 REM HELP
9701 LET q$="": GO SUB 8090
9702 PRINT '"PLEASE FOLLOW THIS SEQUENCE:"''"1. CUSTOMIZE DRIVER."'"2. SAVE IT."'"3. THEN TEST IT."
9703 PRINT '"TO USE YOUR CUSTOMIZED DRIVER,"'"SIMPLY LOAD IT TO ANY REASONABLE"'"BASE ADDRESS WITH THIS COMMAND:"''"LOAD ""NAME"" CODE base"''"WHERE base IS THE BASE ADDRESS"'"OF YOUR CHOICE."''"THEN TURN THE DRIVER ON WITH:"''"RANDOMISE USR base"
9704 LET ret=9705: GO TO 9790
9705 PRINT '"The driver is 800 bytes long."''"The driver will work with either"'"ROM, 2068 or Spectrum."''"NOTE: THE CUSTOMIZED DRIVER IS"'"RELOCATABLE, BUT ONLY UNTIL IT"'"HAS BEEN TURNED ON."
9706 PRINT '"THE DRIVER MAY BE TURNED ON AND"'"OFF REPEATEDLY, BUT TURNING IT"'"OFF DOES NOT RESTORE ITS"'"RELOCATABILITY."
9707 LET ret=9708: GO TO 9790
9708 PRINT '"The print driver shouldn't be"'"turned on until after it's been"'"CUSTOMIZED and SAVED from"'"the MENU."
9709 PRINT '"You can then leave it where it"'"is (64000-64799) or load it to"'"another base address with:"''"CLEAR base-1 e.g.62999"'"LOAD ""NAME"" CODE base e.g.63000"
9710 PRINT '"To turn the driver ON:"''"RANDOMIZE USR base e.g.63000"''"Note that the driver is now at"'"64000, so you'd turn it on with"'"RANDOMIZE USR 64000"
9714 LET RET=9720: GO TO 9790
9720 PRINT '" IMPORTANT DRIVER CONTROLS: "''"POKE (BASE+4),WIDTH-1"''"POKE (BASE+5),10 = LINEFEED ON"'"POKE (BASE+5),0 = LINEFEED OFF"
9722 PRINT '"RANDOMIZE USR BASE = TURN ON"''"RANDOMIZE USR (BASE+2)= TURN OFF"
9724 PRINT '"RANDOMIZE USR (BASE+450) = COPY"'"(EXCEPT PR2300 PRINTER)"
9730 LET RET=9731: GO TO 9790
9731 PRINT '"The OLIVETTI PR2300 printer"'"uses a unique copy function:"''"TO SET NORMAL MODE:"'"POKE (base+586),0"'"POKE (base+587),0"
9732 PRINT '"TO SET ZOOM MODE:"'"POKE (base+586),27"'"POKE (base+587),47"''"TO COPY SCREEN TO PR2300:"'"RANDOMIZE USR (base+612)"
9735 LET RET=9736: GO TO 9790
9736 PRINT '"The menu can be used to set the"'"two print parameters:"'"WIDTH and LINEFEED SWITCH."
9737 PRINT '"These can also be changed"'"directly as follows:"''"TO SET WIDTH:"'"POKE base+4, width-1"
9738 PRINT ''"TO TURN LINEFEED SWITCH ON/OFF:"'"POKE base+5, 10 (ON) or 0 (OFF)"
9739 PRINT ''"EXAMPLE: say the driver is"'"loaded at 60000 and you want the"'"printing width to be 80 columns:"'"POKE 60004,79 will do it."
9740 LET RET=9742: GO TO 9790
9742 PRINT '"NOTE: If the Auto-Linefeed DIP"'"switch on your printer is OFF"'"then the driver's linefeed"'"switch should be ON, and vice-"'"versa."
9743 PRINT ''"NOTE RE COPY FUNCTION:"'"If your printer doesn't have"'"BIT-IMAGE GRAPHICS CAPABILITY,"'"then it cannot copy the screen."
9744 PRINT '"If your dot-matrix printer is"'"not among the types listed, you"'"can try various types."'"For further assistance, contact"'"AERCO (512)451-5874"
9746 LET ret=9748: GO TO 9790
9748 PRINT '"For further help in using the"'"Relocatable Print Driver, call"'"or write:"''"Jack Dohany (415) 321-7684"'"325 O'Connor St"'"Menlo Park, CA 94025"
9749 PRINT '"Note that Version 5 is now being"'"worked on. Features:"'". Set Left Margin"'". Set Lines Per Page"'". Word Wrap"'". Constant Relocatability"''"Enquire re price/availability."
9750 LET RET=9700: GO TO 9790
9790 PRINT #1;AT 0,0;"menu copy(2040) ENT=next pg"
9791 IF q$=INKEY$ THEN GO TO 9791
9792 IF INKEY$="" THEN GO TO 9792
9793 LET q$=INKEY$
9795 IF q$="c" OR q$="C" THEN COPY : GO TO 9790
9796 IF q$=CHR$ 13 THEN GO SUB 8090: GO TO ret
9797 IF q$="M" OR q$="m" THEN GO TO 9000
9798 GO TO 9790
9900 REM SAVE
9902 IF PEEK 64040<>8 OR PEEK 64041<>0 THEN GO TO 9920
9905 INPUT "FILE NAME: ";f$: IF f$="" THEN GO TO 9905
9906 SAVE f$CODE 64000,800
9908 INPUT "VERIFY? (y/n): ";q$: IF q$="" THEN GO TO 9908
9910 IF q$="y" OR q$="Y" THEN VERIFY ""CODE : GO TO 9000
9912 IF q$="n" OR q$="N" THEN GO TO 9000
9914 GO TO 9908
9920 CLS : PRINT AT 10,0;"DRIVER HAS BEEN TURNED ON AND IS"'"NO LONGER RELOCATABLE."''"PLEASE RELOAD ORIGINAL DRIVER,"'"CUSTOMIZE, SAVE, AND RELOAD": STOP
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.