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:
- Lines 1–2: REM lines storing the machine code payload. Line 1 contains 597 bytes of Z80 opcodes; line 2 is an empty separator.
- Lines 100–910: Pure REM documentation describing each routine’s offset, calling convention, and parameter syntax.
- Lines 1000–1310: The interactive menu — list docs, save, or relocate the code block and display a formatted routine address table.
- 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 chainingINKEY$polling loop — non-blocking single-key menu selection65536 AND SGN x=-1— two’s-complement unsigned wrap for 16-bit arithmeticRAND valuethenPEEK 16434/16435— extract low/high bytes of a 16-bit value via the random seed system variableTAB Cwith a pre-set constant — consistent column alignment in tabular output
Content
Source Code
1 REM 2A1A40E5DF23E5FED82060D6624FE7CDB4 7221640B928 4FED820F27923D1CD17 AE5F7E1EDB02BBE28 61B1223E518DC CF777571E 1E1221640DFFE2DD5202C16 415E7D61C3822FE10301ECB4228 CA7CB17CB17CB17CB175F18E683CB4A28 34718DE4FE7D1BA28 9CF DCD92 DCDA7 ED1E71CCB5320 6C5BA28F718BC2A 2402B3E ABE20FA3EC62BBE20F53E102BBE20EF2336C32336 0D1E1C9CDE7 22162FF 9CDCA AE5C5EB21F0D81930 2CF BEBCDD8 92BC1 3 3C5 3 3 3 3CD9E 9C1D12323E5722373237123702336EA B B2336 078B120F83675342A 740CB7428 2262823CDD8 9222940CD 7 2C1C9CDE7 221 DFF 9CDCA AEB21F0D8 938 5ED421930 2CF B6069CD17 A38FB13D5CDD8 9D1E5EBCDD8 9D1CD5D A2A 740CB7428 2262823CDD8 9222940CD 7 2C9CDE7 221CBFE 9CDCA AEDB0D5CD 7 2C1C9CDE7 221B9FE 9CDCA AEDB8D5CD 7 2C1C921A7FE 9CDCA ACDD8 9444DC9219AFE 9CDCA AEB21F0D8 938 5ED421930 2CF B6069CD17 A38FB13D5CDD8 9D1E5EBCDD8 9D1CD17 AC9216EFE 9CDCA AED48 6 0C92162FE 9CDCA A444DED59C92156FE 9CDCA A2A 440A7ED72E5C12A 440EB22 440ED42F9EBED42EDB01B1B1B1BED53 240C9CDE7 2DFFED828 2CF DE72A1440FE3520 511 94018 AFE3B28 2CF EED5B1040D5ED52E5F5E7212FFE 9CDCA AF17723C171237023EBE1EDB0D5CD 7 2C1C9CDE7 2DFFED828 2CF DE7F5E721EFFD 9CDCA AF1FE3520 8BE20 C11 94018 DFE3B20 3BE28 2CF EED5B1040234E234623E5D5EBCDC8 ED1E1EDB0ED531440C35B 0
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
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.







