--- title: "KAPKIT 1000" id: 58404 type: "computer_media" slug: "kapkit-1000" url: "http://localhost/computer_media/kapkit-1000/" markdown_url: "http://localhost/computer_media/kapkit-1000.md" published_at: "2024-11-17T12:42:17+00:00" modified_at: "2026-04-03T07:58:03+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/11/KK-2.jpeg" excerpt: "A self-relocating Z80 machine code toolkit with ten callable routines — including REM generation, memory copy, port I/O, and RAMTOP control — all packed into REM lines." 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: "LST Software" slug: "lst-software" taxonomy: "post_tag" url: "http://localhost/tag/lst-software/" - 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: "Charles Peterson" slug: "charles-peterson" taxonomy: "indiv" url: "http://localhost/indiv/charles-peterson/" genre: - name: "Programming" slug: "programming" taxonomy: "genre" url: "http://localhost/type/programming/" media_type: "Program" programmers: - name: "Charles Peterson" slug: "charles-peterson" taxonomy: "indiv" url: "http://localhost/indiv/charles-peterson/" download_url: "https://archive.org/download/timex-sinclair-software-archive/KAPKIT%201000%20%281987%29%28LST%20Software%29%28TS1000%29%28US%29%28Program%29.zip" mediadate: "1987" producer_company: - id: 54587 title: "LST Software" type: "company" url: "http://localhost/company/lst-software/" images: - url: "http://localhost/wp-content/uploads/2024/11/KK-2.jpeg" - url: "http://localhost/wp-content/uploads/2024/11/KK.jpeg" - url: "http://localhost/wp-content/uploads/2024/11/TapeA-Label.jpg" - url: "http://localhost/wp-content/uploads/2024/11/TapeB-Label-scaled.jpg" - url: "http://localhost/wp-content/uploads/2024/11/TapeA-Side1.jpg" - url: "http://localhost/wp-content/uploads/2024/11/TapeA-Side2.jpg" - url: "http://localhost/wp-content/uploads/2024/11/TapeB-Side1-scaled.jpg" - url: "http://localhost/wp-content/uploads/2024/11/TapeB-Side2-scaled.jpg" related_products: - id: 54588 title: "KAPKIT 1000" type: "product" url: "http://localhost/product/kapkit-1000/" media_type_tags: "Programming" --- KAPKIT 1000 is a machine language toolkit stored in REM lines that provides a suite of Z80 utility routines callable from BASIC. The package includes routines for REM line generation, line deletion, memory copy (LDIR and LDDR), line address lookup, line length calculation, IN/OUT port access, RAMTOP adjustment, and RAM save/load operations. Each routine is invoked via USR calls with arguments passed using the exponentiation operator as a parameter-passing idiom. The main menu allows the user to list the documentation, save the program, or relocate the entire machine code block to a new address using the built-in LDIR copy routine. A supplementary section at line 3000 computes the hexadecimal offset between two addresses and prints the corresponding Z80 LD HL and CALL opcodes in decimal form for manual patching. *** ## Program Analysis ### Program Structure The program is divided into four logical sections: 1. **Lines 1–2:** REM lines storing the machine code payload. Line 1 contains 597 bytes of Z80 opcodes; line 2 is an empty separator. 2. **Lines 100–910:** Pure REM documentation describing each routine’s offset, calling convention, and parameter syntax. 3. **Lines 1000–1310:** The interactive menu — list docs, save, or relocate the code block and display a formatted routine address table. 4. **Lines 2000–2050 and 3000–3150:** A SAVE subroutine and a decimal-offset calculator for manual Z80 patching. ### Machine Code Storage All 597 bytes of Z80 machine code are stored in the body of REM line 1, beginning at address 16514 (the standard location immediately after the system variables on a 1K/16K machine). The comment at line 130 confirms `S = 16514` as the canonical base address. Each routine is referenced by an offset from `S`, documented in lines 250–910 and printed dynamically in lines 1190–1300. ### Routine Entry Points | Routine | Offset from S | USR Address (default) | | --- | --- | --- | | REM Generator | +158 | 16672 | | Delete Line(s) | +243 | 16757 | | LDIR (copy bottom-up) | +309 | 16823 | | LDDR (copy top-down) | +327 | 16841 | | Line Address | +345 | 16859 | | Line Length | +358 | 16872 | | IN | +402 | 16916 | | OUT | +414 | 16928 | | Change RAMTOP | +426 | 16940 | | RAMSAVE | +465 | 16979 | | RAMLOAD | +529 | 17043 | ### Parameter-Passing Idiom Parameters are passed to machine code routines using the exponentiation operator (`**`, SHIFT-H), noted in lines 210–230. For example, `RAND USR 16823**SOURCE**DEST**NO. OF BYTES` chains multiple numeric arguments. The Z80 routines retrieve these from the BASIC calculator stack. This is a well-established technique for passing multiple values to USR routines without needing additional PEEK/POKE setup. ### Self-Relocation Line 1090 uses the LDIR routine itself to copy the 597-byte code block to a new user-supplied address `S`: `RAND USR 16823**16514**S**597` After relocation, lines 1190–1300 compute and display the new absolute USR addresses by adding the documented offsets to `S` at runtime, using expressions like `S+158`, `S+243`, etc. This makes the toolkit fully position-independent from the user’s perspective. ### Menu and Display Logic Line 1005 clears the screen; line 1015 switches to SLOW mode before printing the menu. The key-polling loop at lines 1030–1050 uses `INKEY$` in a tight loop rather than INPUT, allowing instant response without an ENTER keypress. The address table printed from line 1190 uses `TAB C` with `C=25` to right-align USR addresses in a fixed column, producing a neat two-column layout despite the limited display width. ### SAVE Routine Lines 2000–2050 prompt the user, pause, save the program, then immediately `RUN` to restart. The SAVE filename at line 2040 uses inverse-video characters for the letters `KK`, which serves as an auto-run marker. ### Decimal Offset Calculator (Lines 3000–3150) This standalone utility helps users manually patch Z80 code after relocation. It accepts two addresses, computes their difference as `OFFSET = A - B`, and applies a two’s-complement correction at line 3090: `LET OFFSET=OFFSET+(65536 AND SGN OFFSET=-1)` This idiom adds 65536 if the offset is negative, yielding the correct unsigned 16-bit representation. Lines 3120–3140 then print the corresponding Z80 opcode bytes in decimal: `LD HL, offset` (opcode 33 followed by low and high bytes peeked from system variables 16434–16435 after `RAND OFFSET` loads the value), followed by opcode 9 (`ADD HL, BC`) and the three-byte sequence for `CALL 2762` which is the ROM’s `JP (HL)` dispatch. The use of `RAND OFFSET` at line 3110 to load the offset value into the BASIC random-number register is a side-effect trick to make the low/high byte split available via PEEK on system variable addresses 16434–16435. ### Notable Anomaly Line 3020 contains a double-I typo: `PRINT "IIS STARTING ADDRESS? "`. This appears to be a BASIC listing artifact where an intended prompt string was entered with an accidental leading `I`, likely a keystroke error. It does not affect functionality since the line is purely a PRINT statement. ### Key BASIC Idioms Summary - `USR addr**arg1**arg2` — multi-parameter USR call via exponentiation chaining - `INKEY$` polling loop — non-blocking single-key menu selection - `65536 AND SGN x=-1` — two’s-complement unsigned wrap for 16-bit arithmetic - `RAND value` then `PEEK 16434/16435` — extract low/high bytes of a 16-bit value via the random seed system variable - `TAB C` with a pre-set constant — consistent column alignment in tabular output ## Source Code ``` 1 REM 2A1A40E5DF23E5FED82060D6624FE7CDB47221640B9284FED820F27923D1CD17AE5F7E1EDB02BBE2861B1223E518DCCF777571E1E1221640DFFE2DD5202C16415E7D61C3822FE10301ECB4228CA7CB17CB17CB17CB175F18E683CB4A2834718DE4FE7D1BA289CFDCD92DCDA7ED1E71CCB53206C5BA28F718BC2A2402B3EABE20FA3EC62BBE20F53E102BBE20EF2336C323360D1E1C9CDE722162FF9CDCAAE5C5EB21F0D819302CFBEBCDD892BC133C53333CD9E9C1D12323E5722373237123702336EABB2336078B120F83675342A740CB74282262823CDD89222940CD72C1C9CDE7221DFF9CDCAAEB21F0D89385ED4219302CFB6069CD17A38FB13D5CDD89D1E5EBCDD89D1CD5DA2A740CB74282262823CDD89222940CD72C9CDE7221CBFE9CDCAAEDB0D5CD72C1C9CDE7221B9FE9CDCAAEDB8D5CD72C1C921A7FE9CDCAACDD89444DC9219AFE9CDCAAEB21F0D89385ED4219302CFB6069CD17A38FB13D5CDD89D1E5EBCDD89D1CD17AC9216EFE9CDCAAED4860C92162FE9CDCAA444DED59C92156FE9CDCAA2A440A7ED72E5C12A440EB22440ED42F9EBED42EDB01B1B1B1BED53240C9CDE72DFFED8282CFDE72A1440FE352051194018AFE3B282CFEED5B1040D5ED52E5F5E7212FFE9CDCAAF17723C171237023EBE1EDB0D5CD72C1C9CDE72DFFED8282CFDE7F5E721EFFD9CDCAAF1FE35208BE20C1194018DFE3B203BE282CFEED5B1040234E234623E5D5EBCDC8ED1E1EDB0ED531440C35B0 2 REM 100 REM .....KAPKIT (KK)..... 110 REM 120 REM S = KK STARTING ADDRESS 130 REM S = 16514 140 REM 150 REM ADDR = ADDRESS 160 REM SOURCE = SOURCE ADDR 170 REM DEST = DESTINATION ADDR 180 REM 190 REM KK TOTAL BYTES = 597 200 REM 210 REM DOUBLE ASTERISKS (**) 220 REM ARE "RAISED TO THE 230 REM POWER OF" (SHIFT-"H") 235 REM 240 REM ...HOW TO USE KK... 245 REM 250 REM --REM GEN-- (S + 158) 260 REM 270 REM LET ADDR=5+USR 16672** 280 REM LINE NO.**SPACES 290 REM 300 REM --DELETE-- (S + 243) 310 REM 320 REM RAND USR 16757**LINE 330 REM NO. 340 REM 350 REM RAND USR 16757**1ST 360 REM LINE NO.**2ND LINE NO. 370 REM 380 REM --LDIR-- (S + 309) 390 REM 400 REM RAND USR 16823**SOURCE 410 REM **DEST**NO. OF BYTES 420 REM 430 REM --LDDR-- (S + 327) 440 REM 450 REM RAND USR 16841**SOURCE 460 REM **DEST**NO. OF BYTES 470 REM 480 REM --LINADDR-- (S + 345) 490 REM 500 REM LET ADDR=USR 16859** 510 REM LINE NO. 520 REM 530 REM --LINLEN-- (S + 358) 540 REM 550 REM LET LENGTH=USR 16872** 560 REM LINE NO. 570 REM 580 REM LET LENGTH=USR 16872** 590 REM 1ST LINE NO.**2ND LINE 600 REM NO. 610 REM 620 REM --IN-- (S + 402) 630 REM 640 REM LET A=USR 16916**PORT 650 REM 660 REM --OUT-- (S + 414) 670 REM 680 REM RAND USR 16928**PORT** 690 REM DATA 700 REM 710 REM --RAMTOP-- (S + 426) 720 REM 730 REM RAND USR 16940**NEW 740 REM RAMTOP 750 REM 760 REM --RAMSAVE-- (S + 465) 770 REM 780 REM (PROGRAM): RAND USR 790 REM 16979**P**DEST 800 REM 810 REM (VARIABLES): RAND USR 820 REM 16979**V**DEST 830 REM 840 REM --RAMLOAD-- (S + 529) 850 REM 860 REM (PROGRAM): RAND USR 870 REM 17043**P**SOURCE 880 REM 890 REM (VARIABLES): RAND USR 900 REM 17043**V**SOURCE 910 REM 1000 REM ..LIST/SAVE/RELOCATE.. 1005 CLS 1010 PRINT TAB 11;"KAPKIT 1000",,, 1015 SLOW 1020 PRINT "1. LIST",,,,"2. SAVE",,,,"3. RELOCATE",,,, 1030 LET A$=INKEY$ 1040 IF A$="1" THEN LIST 100 1045 IF A$="2" THEN GOTO 2000 1050 IF A$<>"3" THEN GOTO 1030 1060 PRINT AT 21,3;"INPUT NEW STARTING ADDRESS" 1070 INPUT S 1080 FAST 1090 RAND USR 16823**16514**S**597 1100 LET C=25 1110 CLS 1190 PRINT "R O U T I N E";TAB C;"U S R" 1200 PRINT ,,"REM GENERATOR";TAB C;S+158 1210 PRINT ,,"DELETE LINE(S)";TAB C;S+243 1220 PRINT ,,"LDIR (COPY BOTTOM-UP)";TAB C;S+309 1230 PRINT "LDDR (COPY TOP-DOWN)";TAB C;S+327 1240 PRINT ,,"LINE ADDRESS";TAB C;S+345 1250 PRINT ,,"LINE(S) LENGTH";TAB C;S+358 1260 PRINT ,,"IN";TAB C;S+402 1270 PRINT "OUT";TAB C;S+414 1280 PRINT ,,"CHANGE RAMTOP";TAB C;S+426 1290 PRINT ,,"RAMSAVE";TAB C;S+465 1300 PRINT "RAMLOAD";TAB C;S+529 1310 STOP 2000 REM ......SAVE...... 2010 CLS 2020 PRINT "PRESS ANY KEY TO SAVE ""KK""" 2030 PAUSE 4E4 2040 SAVE "K%K" 2050 RUN 3000 REM ...DECIMAL OFFSET... 3010 REM 3020 PRINT "IIS STARTING ADDRESS? "; 3030 INPUT A 3040 PRINT A 3050 PRINT ,,"ROUTINES STARTING ADDRESS? "; 3060 INPUT B 3070 PRINT B 3080 LET OFFSET=A-B 3090 LET OFFSET=OFFSET+(65536 AND SGN OFFSET=-1) 3100 PRINT ,,"OFFSET = ";OFFSET 3110 RAND OFFSET 3120 PRINT ,,"33,";PEEK 16434;",";PEEK 16435,"LD HL, ";OFFSET 3130 PRINT "9","ADD HL,BC" 3140 PRINT "205,202,10","CALL 2762;JP(HL)" 3150 STOP ```