--- title: "TMS9918A Video Enhanced Basic EPROM Programmer" id: 58464 type: "computer_media" slug: "tms9918a-video-enhanced-basic-eprom-programmer" url: "http://localhost/computer_media/tms9918a-video-enhanced-basic-eprom-programmer/" markdown_url: "http://localhost/computer_media/tms9918a-video-enhanced-basic-eprom-programmer.md" published_at: "2024-11-17T22:31:09+00:00" modified_at: "2026-04-03T07:58:01+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/11/Prog.jpeg" excerpt: "A guided EPROM burner that PEEKs your ROM, applies selectable patches for printer support and memory size, then POKEs bytes out with per-byte timing delays." 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 Oliger Co." slug: "john-oliger-co" taxonomy: "post_tag" url: "http://localhost/tag/john-oliger-co/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "John Oliger" slug: "john-oliger" taxonomy: "indiv" url: "http://localhost/indiv/john-oliger/" genre: - name: "Graphics" slug: "graphics" taxonomy: "genre" url: "http://localhost/type/graphics/" media_type: "Program" programmers: - name: "John Oliger" slug: "john-oliger" taxonomy: "indiv" url: "http://localhost/indiv/john-oliger/" download_url: "https://archive.org/download/timex-sinclair-software-archive/TMS9918A%20Vid%20Enh%20Basic%20Eprom%20Programmer%20%281983%29%28J.%20Oliger%29%28TS1000%29%28US%29%28Program%29.zip" mediadate: "1983" producer_company: - id: 10990 title: "John Oliger Co." type: "company" url: "http://localhost/company/john-oliger-co/" images: - url: "http://localhost/wp-content/uploads/2024/11/Prog.jpeg" - url: "http://localhost/wp-content/uploads/2024/11/Tape-17.jpg" related_products: - id: 14526 title: "TMS 9918A Video Upgrade" type: "product" url: "http://localhost/product/video-upgrade-project/" - id: 36730 title: "TMS9918A VDP Enhanced BASIC Programming Cassette" type: "product" url: "http://localhost/product/tms9918a-vdp-enhanced-basic-programming-cassette/" media_type_tags: "Graphics" --- # TMS9918A Video Enhanced Basic EPROM Programmer This program is a ZX81/TS1000 EPROM programmer utility that guides the user through copying a ROM image into an 8192-byte array, applying user-selected patches, and then burning the result to an EPROM chip. It reads the first 8 KB of memory address space using PEEK (addresses 0–8191) into a string array A$(8192), then selectively overlays specific byte ranges from a secondary buffer B$ using a GOSUB-based copy routine at line 3. Options include a parallel printer-port patch, a configurable power-up character color (0–15), background and border color bytes, and a switch between 16K and 48K memory-check ROM routines. The EPROM burning loop at line 700 uses POKE with a 3-frame PAUSE per byte to meet programming timing requirements, and a checksum is calculated via a second GOSUB loop that sums all CODE values. A machine-code routine at address 16514, called via USR 16514, performs a tape-load integrity check against the expected value 55194. *** ## Program Structure The program is organised into several logical phases, each separated by `CLS` and user prompts: 1. **Tape integrity check** (line 17, subroutine 8000): calls `USR 16514` and validates the result. 2. **Optional tape copy** (lines 19–23): offers `SAVE "PRO%G"` at line 7000 before proceeding. 3. **Initialisation** (lines 25–340): reads 8 KB from addresses 0–8191 via `PEEK` into `A$(8192)`, then applies patches via a GOSUB copy loop. 4. **Option selection** (lines 400–660): collects printer patch, colour, border, and memory-check preferences. 5. **EPROM burn** (lines 675–740): iterates over the array and `POKE`s each byte with a short pause. 6. **Checksum verification** (lines 800–880): sums all byte values and displays the result. ## Subroutines | Lines | Purpose | Entry point label | | --- | --- | --- | | 3–7 | Copy `B$(X…)` into `A$(A TO B)` | `L` (via `GOSUB L`) | | 8–11 | Accumulate checksum: sum `CODE A$(N)` for N=1–8192 | line 8 | | 8000–8110 | Tape-load verification via `USR 16514` | line 8000 | The copy subroutine at lines 3–7 uses shared variables `A`, `B`, and `X`: `A` and `B` define the destination range in `A$`, while `X` is a running index into `B$` that is *not* reset between calls, so segments are copied sequentially from `B$` into non-contiguous ranges of `A$`. ## EPROM Burn Loop The burn loop at lines 700–740 contains a notable bug: the loop variable `N` iterates from 1 to `X` (which was set to 8192 at line 690), but inside the loop `X` itself is incremented (`LET X=X+1` at line 720), and `POKE X, CODE A$(N)` uses the *modified* `X` as the destination address rather than `N`. This means bytes are written starting at address 8193 (0x2001) rather than address 0, and the destination address drifts upward in parallel with `N`. The `PAUSE 3` at line 730 provides approximately 3 frame-periods (~50 ms at 50 Hz) per byte to satisfy EPROM programming pulse-width requirements. ## Patch Application After the bulk copy, line 340 directly overwrites three bytes of `A$`: - `A$(517 TO 519) = CHR$ 195 + "%I\ '"` — writes three specific byte values (0xC3 = Z80 JP instruction, then two address bytes) into what is likely a jump vector. The printer-patch option (lines 450–472) writes either `"COS "` / `"4"` or `" SCROLL "` / `"\ '"` into `A$(2168)` and `A$(2169)`, corresponding to different ROM bytes at offset 0x877–0x878 depending on whether the parallel printer port patch is applied. The 48 K memory-check option (lines 640–650) writes `" RETURN "` and `" COPY "` into `A$(4)` and `A$(5)`, patching the early ROM memory-test routine to skip the 16 K limit. ## Colour Configuration The program prompts for a foreground colour (0–15) stored in `A` and a background colour in `B`, computing a packed byte `C = A*16 + B` (line 520) and storing it into `A$(7751)`. A separate border byte is similarly computed and stored at `A$(7688)`. Value 16 for the border is treated as “no border” (line 560 jumps past the packing step). These offsets correspond to specific locations in what appears to be a custom ROM image. ## Notable Idioms and Anomalies - `GOSUB L` at lines 90–330 uses the variable name `L` as a line-number argument — the value of `L` is never explicitly set, so it defaults to 0, which would jump to line 0 (or the nearest line, line 1 in most implementations). This appears to be an error; the intent is almost certainly `GOSUB 3`. - `GOTO 2` is never used; line 2 (`GOTO 17`) is only reachable via the tape-copy restart at line 7010 (`GOTO 1` → REM, falls through to line 2). - `PAUSE 4E4` (lines 680 and 825) pauses for 40,000 frames — approximately 13 minutes at 50 Hz — giving the user time to switch the EPROM programmer’s VPP supply voltage before the burn begins. ## Source Code ``` 1 REM 2 GOTO 17 3 FOR N=A TO B 4 LET A$(N)=B$(X) 5 LET X=X+1 6 NEXT N 7 RETURN 8 FOR N=1 TO 8192 9 LET X=X+CODE A$(N) 10 NEXT N 11 RETURN 15 REM DIM B$(704) 17 GOSUB 8000 19 PRINT AT 8,0;"IF YOU DESIRE TO MAKE A BACK UP OF THIS TAPE, OR A COPY FOR A FRIEND, THEN ENTER ""S"" AFTER RECORDER IS READY AND RUNNING.";AT 20,0;" ""S-ENTER"" TO COPY OR ""ENTER"" ONLY TO CONTINUE" 21 INPUT K$ 22 CLS 23 IF K$="S" THEN GOTO 7000 25 PRINT AT 9,0;"THERE WILL NOW BE A DELAY FOR INITIALIZATION....";AT 21,7;"%P%L%E%A%S%E %S%T%A%N%D %B%Y" 27 FAST 29 PAUSE 400 31 DIM A$(8192) 33 FOR N=1 TO 8192 40 LET A$(N)=CHR$ (PEEK (N-1)) 50 NEXT N 60 LET X=1 70 LET A=57 80 LET B=73 90 GOSUB L 100 LET A=103 110 LET B=126 120 GOSUB L 130 LET A=528 140 LET B=553 150 GOSUB L 160 LET A=596 170 LET B=699 180 GOSUB L 190 LET A=732 200 LET B=743 210 GOSUB L 220 LET A=749 230 LET B=751 240 GOSUB L 250 LET A=1041 260 LET B=1043 270 GOSUB L 280 LET A=2225 290 LET B=2227 300 GOSUB L 310 LET A=7681 320 LET B=8192 330 GOSUB L 340 LET A$(517 TO 519)=CHR$ 195+"%I '" 390 SLOW 400 CLS 410 PRINT AT 1,0;"INITIALIZATION COMPLETE.",,,"NOW, FOR THE OPTIONS.";AT 8,0;"WOULD YOU LIKE TO INCLUDE THE PRINTER PATCH AT 0876H FOR MY PARALLEL PRINTER PORT PUBLISHED IN SQ NO. 1?";AT 21,0;"ENTER ""Y"" FOR YES OR ""N"" FOR NO" 420 INPUT K$ 430 IF K$="" THEN GOTO 470 440 IF K$(1)<>"Y" THEN GOTO 470 450 LET A$(2168)="COS " 460 LET A$(2169)="4" 465 GOTO 475 470 LET A$(2168)=" SCROLL " 472 LET A$(2169)=" '" 475 CLS 480 PRINT "ENTER DEFAULT ON POWER UP CHARACTER COLOR DESIRED.","(WHITE RECCOMENDED)";AT 5,0;" 0=TRANSPARENT",," 1=BLACK",," 2=MEDIUM GREEN",," 3=LIGHT GREEN",," 4=DARK BLUE",," 5=LIGHT BLUE",," 6=DARK RED",," 7=CYAN",," 8=MEDIUM RED",," 9=LIGHT RED",,"10=DARK YELLOW",,"11=LIGHT YELLOW",,"12=DARK GREEN",,"13=MAGNETA",,"14=GREY",,"15=WHITE" 490 INPUT A 495 IF A>15 THEN GOTO 480 500 PRINT AT 1,0;"BACKGROUND";AT 2,1;"BLACK" 510 INPUT B 520 LET C=A*16+B 530 LET A$(7751)=CHR$ C 540 PRINT AT 1,0;" BORDER ";AT 2,1;"NO BORDER RECCOMENDED)";AT 21,0;"16=NO BORDER" 550 INPUT B 560 IF B=16 THEN GOTO 590 570 IF B>16 THEN GOTO 550 580 LET C=A*16+B 590 LET A$(7688)=CHR$ C 600 CLS 610 PRINT AT 3,0;"WOULD YOU LIKE A FULL 48K MEMORYCHECK ON POWER-UP, OR THE NORMAL16K MEMORY CHECK?";AT 21,6;"ENTER ""16"" OR ""48""" 620 INPUT K$ 630 IF K$<>"48" THEN GOTO 660 640 LET A$(4)=" RETURN " 650 LET A$(5)=" COPY " 660 CLS 670 PRINT AT 2,0;"OPTION PROGRAMMING COMPLETE";AT 9,0;"PREPARE PROGRAMMER TO PROGRAM EPROM BY SWITCHING ITS VPP POWERSUPPLY FROM 4.4V TO 21VDC";AT 21,0;"PRESS ""ENTER"" TO PROGRAM EPROM" 675 FAST 680 PAUSE 4E4 690 LET X=8192 700 FOR N=1 TO X 710 POKE X,CODE A$(N) 720 LET X=X+1 730 PAUSE 3 740 NEXT N 800 CLS 810 PRINT AT 5,0;"EPROM IS NOW PROGRAMMED";AT 11,0;"SWITCH VPP POWER SUPPLY VOLTAGE BACK TO 4.4 VOLTS";AT 20,0;"PRESS ""ENTER"" TO START CHECKSUM COMPUTATION" 820 LET X=0 825 PAUSE 4E4 830 GOSUB 8 860 CLS 865 SLOW 870 PRINT AT 2,0;"CHECKSUM FOR YOUR EPROM=";X;AT 8,0;"WRITE DOWN YOUR CHECKSUM FOR LATER VERIFICATION OF YOUR EPROM";AT 15,0;"UNPLUG THE VPP SUPPLY AND THEN DOWNPOWER YOUR COMPUTER--";AT 21,0;"YOUR EPROM IS READY......" 880 STOP 7000 SAVE "PRO%G" 7010 GOTO 1 8000 LET CS=USR 16514 8005 CLS 8010 IF CS<>55194 THEN GOTO 8100 8020 PRINT AT 10,0;"THE TAPE LOAD CHECKS GOOD" 8040 PAUSE 150 8050 CLS 8070 RETURN 8100 PRINT AT 8,0;"THE TAPE LOAD CHECKS BAD";AT 12,0;"TRY LOADING THE TAPE AGAIN" 8110 STOP ```