c64bridge 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/.github/prompts/README.md +6 -0
  2. package/.github/prompts/assembly-routine-session.prompt.md +13 -0
  3. package/.github/prompts/basic-program-session.prompt.md +13 -0
  4. package/.github/prompts/drive-management-session.prompt.md +13 -0
  5. package/.github/prompts/petscii-art-session.prompt.md +13 -0
  6. package/.github/prompts/play-classic-game.prompt.md +13 -0
  7. package/.github/prompts/sid-music-session.prompt.md +13 -0
  8. package/AGENTS.md +173 -0
  9. package/LICENSE +339 -0
  10. package/README.md +582 -0
  11. package/data/README.md +16 -0
  12. package/data/api/basic-api-spec.md +154 -0
  13. package/data/api/kernal-api-spec.md +68 -0
  14. package/data/assembly/assembly-spec.md +196 -0
  15. package/data/assembly/examples/effects/sinewave.asm +5 -0
  16. package/data/assembly/examples/graphics/sprite/mover.asm +15 -0
  17. package/data/assembly/examples/sid-file-structure.md +8 -0
  18. package/data/assembly/examples/sid-overview.md +11 -0
  19. package/data/audio/examples/Biosphere.sid +0 -0
  20. package/data/audio/sid-file-structure.md +91 -0
  21. package/data/audio/sid-programming-best-practices.md +198 -0
  22. package/data/audio/sid-spec.md +166 -0
  23. package/data/audio/sidwave.md +131 -0
  24. package/data/audio/sidwave.schema.json +64 -0
  25. package/data/basic/basic-spec.md +230 -0
  26. package/data/basic/examples/audio/alle-meine-entchen-expressive.bas +41 -0
  27. package/data/basic/examples/audio/c-major-scale-pleasant.bas +29 -0
  28. package/data/basic/examples/io/joystick.bas +5 -0
  29. package/data/basic/examples/video/bounce.bas +8 -0
  30. package/data/basic/examples/video/entchen-petscii.bas +16 -0
  31. package/data/basic/examples/video/hello-world.bas +4 -0
  32. package/data/basic/examples/video/wave.bas +7 -0
  33. package/data/context/bootstrap.md +148 -0
  34. package/data/context/chat.md +36 -0
  35. package/data/drive/drive-spec.md +215 -0
  36. package/data/embeddings_asm.json +1 -0
  37. package/data/embeddings_basic.json +1 -0
  38. package/data/embeddings_hardware.json +1 -0
  39. package/data/embeddings_mixed.json +1 -0
  40. package/data/embeddings_other.json +1 -0
  41. package/data/io/cia-spec.md +115 -0
  42. package/data/io/io-spec.md +124 -0
  43. package/data/memory/kernal-memory-map.md +227 -0
  44. package/data/memory/low-memory-map.md +133 -0
  45. package/data/memory/memory-map.md +186 -0
  46. package/data/printer/printer-commodore-bitmap.md +31 -0
  47. package/data/printer/printer-commodore.md +28 -0
  48. package/data/printer/printer-epson-bitmap.md +29 -0
  49. package/data/printer/printer-epson.md +30 -0
  50. package/data/printer/printer-prompts.md +29 -0
  51. package/data/printer/printer-spec.md +180 -0
  52. package/data/video/character-set.csv +257 -0
  53. package/data/video/vic-spec.md +276 -0
  54. package/dist/assemblyConverter.js +1299 -0
  55. package/dist/audio/record_and_analyze_audio.js +292 -0
  56. package/dist/basicConverter.js +193 -0
  57. package/dist/bootstrap/stdio-logger.js +32 -0
  58. package/dist/c64Client.js +1052 -0
  59. package/dist/chargen.js +197 -0
  60. package/dist/config.js +142 -0
  61. package/dist/context.js +157 -0
  62. package/dist/device.js +413 -0
  63. package/dist/index.js +7 -0
  64. package/dist/knowledge.js +454 -0
  65. package/dist/logger.js +182 -0
  66. package/dist/loggingHttpClient.js +88 -0
  67. package/dist/mcp-server.js +426 -0
  68. package/dist/petscii.js +135 -0
  69. package/dist/petsciiArt.js +356 -0
  70. package/dist/platform.js +82 -0
  71. package/dist/prompts/registry.js +560 -0
  72. package/dist/rag/discover.config.json +41 -0
  73. package/dist/rag/discover.js +401 -0
  74. package/dist/rag/embeddings.js +60 -0
  75. package/dist/rag/externalFetcher.js +934 -0
  76. package/dist/rag/indexer.js +770 -0
  77. package/dist/rag/init.js +139 -0
  78. package/dist/rag/knowledgeIndex.js +361 -0
  79. package/dist/rag/loggingRetriever.js +46 -0
  80. package/dist/rag/rateLimiter.js +127 -0
  81. package/dist/rag/retriever.js +74 -0
  82. package/dist/rag/sources.csv +31 -0
  83. package/dist/rag/types.js +5 -0
  84. package/dist/rag/urlUtils.js +38 -0
  85. package/dist/sidplayRunner.js +240 -0
  86. package/dist/sidwave.js +101 -0
  87. package/dist/sidwaveCompiler.js +329 -0
  88. package/dist/tools/audio.js +944 -0
  89. package/dist/tools/developer.js +515 -0
  90. package/dist/tools/errors.js +59 -0
  91. package/dist/tools/graphics.js +469 -0
  92. package/dist/tools/machineControl.js +267 -0
  93. package/dist/tools/memory.js +224 -0
  94. package/dist/tools/printer.js +482 -0
  95. package/dist/tools/programRunners.js +315 -0
  96. package/dist/tools/rag.js +153 -0
  97. package/dist/tools/registry.js +58 -0
  98. package/dist/tools/responses.js +36 -0
  99. package/dist/tools/schema.js +304 -0
  100. package/dist/tools/storage.js +740 -0
  101. package/dist/tools/streaming.js +132 -0
  102. package/dist/tools/types.js +99 -0
  103. package/dist/viceRunner.js +239 -0
  104. package/doc/MCP_SETUP.md +153 -0
  105. package/doc/README.md +7 -0
  106. package/doc/developer.md +312 -0
  107. package/doc/img/logo.png +0 -0
  108. package/doc/img/prompts/duck_petscii.png +0 -0
  109. package/doc/img/prompts/duck_song.png +0 -0
  110. package/doc/img/vscode/vscode-copilot-c64-chat-mode.png +0 -0
  111. package/doc/img/vscode/vscode-copilot-hello-world.png +0 -0
  112. package/doc/prompts/README.md +96 -0
  113. package/doc/prompts/user-prompt-ideas.md +147 -0
  114. package/doc/rest/c64-openapi.yaml +979 -0
  115. package/doc/rest/c64-rest-api.md +106 -0
  116. package/doc/troubleshooting-mcp.md +177 -0
  117. package/generated/c64/index.js +857 -0
  118. package/mcp.json +106 -0
  119. package/package.json +79 -0
  120. package/scripts/c64-cli.mjs +142 -0
  121. package/scripts/c64-tool.sh +83 -0
  122. package/scripts/check-package.mjs +89 -0
  123. package/scripts/cli.js +61 -0
  124. package/scripts/fetch-external-sources.mjs +67 -0
  125. package/scripts/generate-changelog.mjs +131 -0
  126. package/scripts/postbuild.mjs +101 -0
  127. package/scripts/prepare-release.mjs +58 -0
  128. package/scripts/rag-rebuild.mjs +53 -0
  129. package/scripts/register-ts-node.mjs +6 -0
  130. package/scripts/run-mcp-check.sh +104 -0
  131. package/scripts/run-tests.mjs +195 -0
  132. package/scripts/sid2wav.sh +94 -0
  133. package/scripts/smoke-run.sh +65 -0
  134. package/scripts/start-mock-c64.mjs +51 -0
  135. package/scripts/start-mock.mjs +31 -0
  136. package/scripts/start.mjs +72 -0
  137. package/scripts/update-readme.ts +164 -0
  138. package/scripts/verify-package.mjs +147 -0
@@ -0,0 +1,115 @@
1
+ # Commodore 64 CIA Specification
2
+
3
+ > Purpose: Single source of truth for CIA hardware on the C64 (LLM/MCP).
4
+ > Companion specs: `io-spec.md` (system I/O topology, IEC/tape/ports), `data/printer/printer-spec.md` (printers).
5
+ > Notes: Do **not** duplicate I/O details here—refer to `io-spec.md`. This file defines *exact CIA semantics*. Where sources disagree, this merged spec defers to the attached “Mapping the C64 CIA” and the C64 Programmer’s Reference Guide.
6
+
7
+ ## Overview
8
+
9
+ - **Chips:** 2× MOS **6526/6526A/8521** (functionally equivalent for C64 use).
10
+ - **Address blocks:** **CIA1** `$DC00–$DC0F` (mirrored every 16 bytes to `$DCFF`), **CIA2** `$DD00–$DD0F` (mirrored to `$DDFF`).
11
+ - **Core units:** Ports **PA/PB (8+8)**, **Timers A/B (16‑bit)**, **TOD clock+alarm (BCD)**, **Serial shift (SDR)**, **ICR**.
12
+ - **System wiring:** CIA1 → **/IRQ**; CIA2 → **/NMI**. `FLAG` inputs: **CIA1** (cassette READ), **CIA2** (user port pin B).
13
+ - **Electrical:** Port bits are open‑collector with pull‑ups; CMOS‑compatible; CNT/SP serial pins present on user port.
14
+ - **Defaults after init:** CIA1 `DDRA=$FF` (PA out), `DDRB=$00` (PB in); CIA2 `DDRA=$3F` (bits 6–7 in), `DDRB=$00` (in).
15
+ - **Cross‑refs:** IEC bus, user port pins, datasette lines, VIC bank select, joystick/paddles/key scan → see `io-spec.md`.
16
+
17
+ ## CIA #1 Registers (`$DC00–$DC0F`) — Keyboard/Joysticks/Paddles/Lightpen/IRQ
18
+
19
+ | Address | Decimal | Name | Function / Bits (compact) |
20
+ |:-------:|:-------:|:-----|:---------------------------|
21
+ | `$DC00` | 56320 | **PRA** | Keyboard **column select** (write), **joy2** read, paddle mux/fire. **b7..b0** column sel; **b7/b6** paddle mux (`01`=Port1, `10`=Port2); **b4** joy2 fire (0=pressed); **b3..b0** joy2 dir; **b3..b2** paddle fires. |
22
+ | `$DC01` | 56321 | **PRB** | Keyboard **row read**, **joy1** read, timer outputs. **b7..b0** rows; **b7** Timer B out (toggle/pulse); **b6** Timer A out; **b4** joy1 fire (0=pressed); **b3..b0** joy1 dir; **b3..b2** paddle fires. |
23
+ | `$DC02` | 56322 | **DDRA** | Port A direction (0=in, 1=out). Default `$FF`. |
24
+ | `$DC03` | 56323 | **DDRB** | Port B direction (0=in, 1=out). Default `$00`. |
25
+ | `$DC04` | 56324 | **TALO** | Timer A **low**. **R:** counter; **W:** latch low. |
26
+ | `$DC05` | 56325 | **TAHI** | Timer A **high**. **R:** counter; **W:** latch high (if stopped, also loads). |
27
+ | `$DC06` | 56326 | **TBLO** | Timer B **low**. **R/W** as above. |
28
+ | `$DC07` | 56327 | **TBHI** | Timer B **high**. **R/W** as above. |
29
+ | `$DC08` | 56328 | **TOD10TH** | TOD tenths BCD (0–9). **CRB7=0:** writes set **time**; **=1:** set **alarm**. |
30
+ | `$DC09` | 56329 | **TODSEC** | TOD seconds BCD. |
31
+ | `$DC0A` | 56330 | **TODMIN** | TOD minutes BCD. |
32
+ | `$DC0B` | 56331 | **TODHR** | TOD hours BCD; **b7 AM/PM** (1=PM). **Write halts** TOD until `$DC08` read. |
33
+ | `$DC0C` | 56332 | **SDR** | Serial shift data. **CRA6:** 0=input (SP→SDR on CNT↑); 1=output (SDR→SP, CNT strobes). |
34
+ | `$DC0D` | 56333 | **ICR** | **R:** b0 TA UF, b1 TB UF, b2 TOD=ALARM, b3 serial byte, b4 FLAG; **b7**=any pending. **W:** b7=1 set mask bits0–4; b7=0 clear them. **Read clears** status bits. |
35
+ | `$DC0E` | 56334 | **CRA** | **Timer A ctrl**/**serial/TOD**: **b0** start; **b1** PB6 enable; **b2** PB6 mode (1 toggle / 0 pulse); **b3** one‑shot; **b4** force load; **b5** count src (1=CNT / 0=Φ2); **b6** SDR dir (1 out); **b7** TOD freq (1=50 Hz/0=60 Hz). |
36
+ | `$DC0F` | 56335 | **CRB** | **Timer B ctrl/TOD sel**: **b0** start; **b1** PB7 enable; **b2** PB7 mode; **b3** one‑shot; **b4** force load; **b6..b5** mode: `00`=Φ2, `01`=CNT, `10`=TA underflow, `11`=TA underflow gated by CNT; **b7** TOD write target (1=ALARM/0=TIME). |
37
+
38
+ **Notes (CIA1):** Keyboard matrix via column write (PRA) + row read (PRB), active‑low. Joystick‑keyboard contention on **Port 1** (PRB) exists; avoid or gate scanning accordingly. Paddle select uses **PRA b7/b6**; paddle *positions* read via SID POTX/POTY; paddle buttons via CIA (bits 2–3). Lightpen appears as fire on PRA b4 and via VIC `/LP`.
39
+
40
+ ## CIA #2 Registers (`$DD00–$DD0F`) — IEC/User Port/RS‑232/VIC Bank/NMI
41
+
42
+ | Address | Decimal | Name | Function / Bits (compact) |
43
+ |:-------:|:-------:|:-----|:---------------------------|
44
+ | `$DD00` | 56576 | **PRA** | **IEC** + **VIC bank** + RS‑232 TXD. **b7** DATA IN, **b6** CLOCK IN, **b5** DATA OUT, **b4** CLOCK OUT, **b3** ATN OUT (bus lines active‑low via drivers); **b2** RS‑232 TXD (user M); **b1..b0** VIC 16 KiB bank: `00=$C000–FFFF`, `01=$8000–BFFF`, `10=$4000–7FFF`, `11=$0000–3FFF` (power‑on `11`). |
45
+ | `$DD01` | 56577 | **PRB** | **User Port/RS‑232** lines (TTL). **b7** DSR (L), **b6** CTS (K), **b5** User‑J, **b4** DCD (H), **b3** RI (F), **b2** DTR (E), **b1** RTS (D), **b0** RXD (C). **Also:** PB7/PB6 timer outputs when enabled. |
46
+ | `$DD02` | 56578 | **DDRA** | Port A direction. Default `$3F` (b6–b7 in). |
47
+ | `$DD03` | 56579 | **DDRB** | Port B direction. Default `$00`; RS‑232 may set b1–b2 out when opened. |
48
+ | `$DD04` | 56580 | **TALO** | Timer A low (R counter / W latch low). |
49
+ | `$DD05` | 56581 | **TAHI** | Timer A high (R counter / W latch high). |
50
+ | `$DD06` | 56582 | **TBLO** | Timer B low. |
51
+ | `$DD07` | 56583 | **TBHI** | Timer B high. |
52
+ | `$DD08` | 56584 | **TOD10TH** | TOD tenths BCD. (OS typically unused here.) |
53
+ | `$DD09` | 56585 | **TODSEC** | TOD seconds BCD. |
54
+ | `$DD0A` | 56586 | **TODMIN** | TOD minutes BCD. |
55
+ | `$DD0B` | 56587 | **TODHR** | TOD hours BCD + AM/PM (b7). |
56
+ | `$DD0C` | 56588 | **SDR** | Serial shift data (rarely used by OS; available via user port SP2/CNT2). |
57
+ | `$DD0D` | 56589 | **ICR** | As CIA1, but flags drive **/NMI**. **b4**=FLAG (user‑port pin B). |
58
+ | `$DD0E` | 56590 | **CRA** | As CIA1 `$DC0E`. |
59
+ | `$DD0F` | 56591 | **CRB** | As CIA1 `$DC0F`. |
60
+
61
+ **Notes (CIA2):** Provides **IEC** master control (ATN/CLOCK/DATA), **User Port** digital I/O and RS‑232 signals, and **VIC bank** selection via `PRA[1:0]`. `/PC2` (handshake) pulses low for one cycle after **PRB** access—available on user port for external strobing.
62
+
63
+ ## Timers (A/B) — Operation
64
+
65
+ - **16‑bit down‑counters** with separate **latches** (write low→high). **Start** or **CRA/CRB b4** forces latch→counter.
66
+ - **Clock sources:** Φ2 (system cycles) or **CNT** pulses; **Timer B** can count **Timer A underflows**, gated by CNT if mode `11`.
67
+ - **Underflow:** Sets ICR bit (and asserts IRQ/NMI). Optional **PB6/PB7** **pulse** (b2=0) or **toggle** (b2=1). **b3=1** one‑shot; else auto‑reload.
68
+ - **Readback:** Reads return current counter; device internally manages proper two‑byte read behavior.
69
+ - **Typical OS setup:** CIA1 Timer A ≈ 1/60 s IRQ; tape I/O repurposes CIA1 timers; CIA2 timers often used by RS‑232.
70
+
71
+ ## Time‑of‑Day (TOD) Clock — BCD + Alarm
72
+
73
+ - **Regs:** `$xx08–$xx0B` (10th, sec, min, hr). **Hours b7**=AM/PM.
74
+ - **Write target:** **CRB7=0** write **time**; **CRB7=1** write **alarm**.
75
+ - **Halt rule:** Writing **TODHR** halts update until **TOD10TH** is read (for read‑latch/write‑latch coherency).
76
+ - **Tick source:** **CRA7** selects 60 Hz/50 Hz. **Alarm match** sets ICR bit2 (IRQ/NMI by CIA).
77
+
78
+ ## Serial Shift (SDR) — SP/CNT
79
+
80
+ - **Direction:** **CRA6** (0=in, 1=out).
81
+ - **Input:** On **CNT↑**, bit from **SP** shifts into SDR; byte complete → **ICR b3**.
82
+ - **Output:** With Timer A running (cont.), SDR shifts MSB→LSB out **SP** with **CNT** strobes; byte complete → **ICR b3**.
83
+ - **System:** OS uses port‑bit IEC more than SDR; SDR remains available on user port **SP1/CNT1** (CIA1) and **SP2/CNT2** (CIA2).
84
+
85
+ ## Interrupts (ICR) — Mask/Status
86
+
87
+ - **Status read (clears):** b0 TA UF, b1 TB UF, b2 TOD alarm, b3 serial, b4 FLAG; **b7**=any pending (ANDed with mask).
88
+ - **Mask write:** **b7=1** sets bits 0–4; **b7=0** clears bits 0–4; bits written as 0 are unchanged.
89
+ - **Wiring:** CIA1 ICR → **/IRQ**; CIA2 ICR → **/NMI** (not maskable by SEI).
90
+
91
+ ## Pinout (logical summary)
92
+
93
+ `PA0–PA7`, `PB0–PB7` (parallel I/O); `/PC` (handshake pulse after PB access; only CIA2 connected externally); `SP` (serial data), `CNT` (count/serial clock); `FLAG` (neg‑edge IRQ/NMI input); `/IRQ` (CIA1), `/NMI` (CIA2); `RS0–RS3` (reg select); `DB0–DB7`; `R/W`; `/CS`; `/RES`; `Φ2`; `Vcc`; `Vss`.
94
+ User‑port mapping for CIA2 PRB and PRA b2 is defined in `io-spec.md` (pin letters C..N).
95
+
96
+ ## Behavior Notes / Gotchas (LLM hints)
97
+
98
+ - **Keyboard scan vs Joystick 1:** Shared on **PRB**; keyscan can misread joystick state and vice‑versa. Gate scan or prefer **Port 2** for games.
99
+ - **Paddles:** Buttons via CIA **bits 2–3**; *positions* via **SID** POTX/POTY; select port with **PRA b7/b6**.
100
+ - **Mirroring:** Access any `$xx00–$xx0F` alias in the `$xx10–$xxFF` window; use base addresses for clarity.
101
+ - **VIC bank:** Use **CIA2 PRA[1:0]**; update VIC `$D018` pointers accordingly (see `io-spec.md`).
102
+ - **Datasette:** READ→CIA1 **FLAG** (ICR b4); MOTOR/WRITE/SENSE via CPU `$0001` (see `io-spec.md`).
103
+
104
+ ## Cross‑References
105
+
106
+ - **System I/O (IEC, tape, user/expansion ports, keyboard algorithm):** `io-spec.md`
107
+ - **Printers:** `data/printer/printer-spec.md`
108
+ - **KERNAL vector/entry points:** `data/memory/kernal-api-spec.md`
109
+
110
+ ---
111
+
112
+ **Provenance:**
113
+
114
+ - [C64 Programmer’s Reference Guide](https://www.zimmers.net/cbmpics/cbm/c64/c64prg.txt)
115
+ - [Mapping the C64](https://www.zimmers.net/anonftp/pub/cbm/c64/manuals/mapping-c64.txt)
@@ -0,0 +1,124 @@
1
+ # Commodore 64 I/O Specification
2
+
3
+ **Scope:** Single source of truth for C64 I/O architecture and programmer interfaces.
4
+
5
+ **Companion docs:**
6
+
7
+ - `data/io/cia-spec.md` (CIA registers/semantics)
8
+ - `data/drive/drive-spec.md` (printer details)
9
+ - `data/printer/printer-spec.md` (printer details)
10
+
11
+ ---
12
+
13
+ ## 1. I/O Topology (What connects where)
14
+
15
+ - **CIA1 (@ $DC00)** → Keyboard matrix, Joystick Port 1, Joystick Port 2 (via matrix), Paddles select, Lightpen flag, Datasette read IRQ flag, IRQ output.
16
+ - **CIA2 (@ $DD00)** → Serial IEC bus (ATN/CLOCK/DATA), User Port (PB0–PB7; RS‑232 lines), VIC bank select (PRA[1:0]), NMI output.
17
+ - **6510 CPU Port ($0000/$0001)** → Memory map control; **Datasette motor, sense, write** lines. Datasette **read** goes to **CIA1 FLAG**.
18
+ - **Expansion Port** → Direct 6510 bus (A/D/R/W/Φ2/IRQ/NMI/RESET); cartridges/REUs map registers/ROM, **bypassing CIAs**.
19
+ - **SID** → Paddles (analog) POTX/POTY; audio; not covered here.
20
+ - **VIC-II** → Lightpen latch; video; not covered here.
21
+
22
+ (For CIA registers and bit meanings, see `cia-spec.md`.)
23
+
24
+ ---
25
+
26
+ ## 2. Device Addressing & KERNAL I/O
27
+
28
+ - **Device numbers (IEC):** Printers **4–7** (convention: 4), Storage **8–30** (convention: first disk **8**). Keyboard=0, Tape=1, RS‑232=2, Screen=3. Secondary addresses distinguish channels on same device.
29
+ - **Bus role:** C64 is IEC **master**; commands: **LISTEN**, **TALK**, **UNLISTEN**, **UNTALK**, **OPEN/CLOSE channel**, with **ATN** controlling command vs data phases.
30
+ - **Key KERNAL entry points:** `OPEN`, `CLOSE`, `CHKIN`, `CHKOUT`, `CLRCHN`, `CHRIN`, `CHROUT`, `LOAD`, `SAVE` (see pagetable KERNAL reference for exact call vectors/regs).
31
+
32
+ ---
33
+
34
+ ## 3. Serial IEC Bus (Disk, Printers)
35
+
36
+ **Physical lines (on CIA2 PRA):**
37
+
38
+ - **b3 ATN OUT**, **b4 CLOCK OUT**, **b5 DATA OUT** (active‑low drivers via 7406), **b6 CLOCK IN**, **b7 DATA IN**. Use open‑collector semantics (0V=true/active). Bytes shift **LSB first**, valid on **CLK rising**.
39
+
40
+ **Protocol sketch:**
41
+
42
+ 1) Master asserts **ATN**, sends device **TALK/LISTEN** + (optional) **secondary address**.
43
+ 2) Data phase with **ATN released**; talker drives DATA, listeners ack. **EOI** marks last byte.
44
+ 3) Master sends **UNLISTEN/UNTALK** to end.
45
+
46
+ > Use KERNAL calls where possible; custom fastloaders may bit‑bang CIA2 lines for speed.
47
+
48
+ ---
49
+
50
+ ## 4. Datasette (Tape) I/O
51
+
52
+ - **CPU Port ($0001):** **bit5 MOTOR** (0=on), **bit4 SENSE** (0=key pressed), **bit3 WRITE** (tape out). Direction via $0000.
53
+ - **Read:** Cassette **READ → CIA1 /FLAG** (edge‑sensitive, falling only). **ICR bit4** set on edge; enable IRQ via ICR mask.
54
+ - **Implication:** Can **toggle** write/motor; **cannot level‑poll** read—only edges—so loaders measure inter‑edge timing (often with CIA timers).
55
+
56
+ ---
57
+
58
+ ## 5. Keyboard (Matrix Scan) — Detailed
59
+
60
+ **Hardware:** 8×8 matrix via **CIA1**: write **PRA ($DC00)** to select **column**, read **PRB ($DC01)** to sense **rows** (active‑low). Configure **DDRA=$FF**, **DDRB=$00**. Typical scan masks: `$FE,$FD,$FB,$F7,$EF,$DF,$BF,$7F`.
61
+ **Algorithm (debounce omitted):**
62
+
63
+ ```text
64
+ init: DDRA=$FF, DDRB=$00
65
+ for col in 0..7:
66
+ PRA = ~(1<<col) ; one column low, others high
67
+ rows = ~PRB & $7F/$FF ; read active rows (0=pressed)
68
+ record (col, rows) ; map to keys
69
+ ```
70
+
71
+ **Notes:**
72
+
73
+ - Joystick **Port 1** shares PRB bits; pressed directions can alias key bits: e.g. Right = “2” key. Prefer **Port 2** for games.
74
+ - **Shift/Ctrl/Commodore** are matrix keys; handle modifiers in lookup.
75
+ - KERNAL scan routine entry in ROM; custom code may be faster/leaner.
76
+
77
+ ---
78
+
79
+ ## 6. Joysticks, Lightpen, Paddles
80
+
81
+ - **Joysticks:** Digital switches, active‑low. **Port 1 → CIA1 PRB[0..4]**, **Port 2 → CIA1 PRA[0..4]** (see `cia-spec.md` mapping). Joystick‑keyboard contention exists on Port 1.
82
+ - **Lightpen:** Routed via VIC /LP; also appears as “fire” on CIA1. Use VIC registers for position latch. (Mapping note: see `cia-spec.md`.)
83
+ - **Paddles:** Analog via **SID POTX/POTY**; channel selection via **CIA1 PRA[6:7]** to choose control port.
84
+
85
+ ---
86
+
87
+ ## 7. User Port (Rear Edge Connector)
88
+
89
+ - **Logical:** **CIA2 PRB (PB0–PB7)** as general‑purpose digital I/O; configure with **DDRB**; read/write via **PRB**. KERNAL also provides RS‑232 routines mapping PB pins.
90
+ - **RS‑232:** TTL‑level via User Port; needs level shifting (e.g., MAX232). High‑speed bit‑bangers (e.g., UP9600) leverage CIA timing/interrupts.
91
+
92
+ ---
93
+
94
+ ## 8. Expansion Port (Cartridges/REU/Fastloaders)
95
+
96
+ - **Direct 6510 bus exposure:** A[15:0], D[7:0], R/W, Φ2, /IRQ, /NMI, /RESET, chip selects. Devices can map ROM/RAM/I/O and trap vectors. **No CIA mediation.**
97
+
98
+ ---
99
+
100
+ ## 9. VIC Bank Select (Memory Windows)
101
+
102
+ - **CIA2 PRA[1:0]:** **00=$C000–FFFF**, **01=$8000–BFFF**, **10=$4000–7FFF**, **11=$0000–3FFF (default)**. Controls VIC’s addressable 16 KiB bank. (Use with VIC memory pointers).
103
+
104
+ ---
105
+
106
+ ## 10. Recommended Access Patterns (Summary)
107
+
108
+ - **Prefer KERNAL** for disk/printer where compatibility matters; switch to custom IEC only for speed‑critical paths.
109
+ - **Keyboard:** CIA1 column‑by‑column scan; handle Port‑1 joystick aliasing.
110
+ - **Tape:** Control motor/write via $0001; measure **FLAG** edges via CIA1 ICR.
111
+ - **User Port:** Set DDRB and use PRB; add RS‑232 level shifting if interfacing to standard serial.
112
+ - **Expansion Port:** Memory‑mapped by cartridge; coordinate with bank switching and KERNAL vectors.
113
+
114
+ ---
115
+
116
+ ## 11. External References
117
+
118
+ - **CIA details:** `cia-spec.md` (this repo).
119
+ - **Printers:** `data/printer/printer-spec.md` (this repo).
120
+ - **KERNAL API (official lookup):** pagetable.com C64 KERNAL reference.
121
+ - **IEC protocol (electrical & byte‑level):** Derogee “IEC dissected”; pagetable Standard Serial overview; Wikipedia Commodore bus.
122
+ - **Keyboard matrix & scan masks:** C64 OS deep‑dive. citeturn0search0
123
+ - **Datasette lines:** C64‑Wiki Cassette Port; Luigi Di Fraia on FLAG edge; 6510 port overview.
124
+ - **User Port/RS‑232:** C64‑Wiki Serial Port; pagetable UP9600.
@@ -0,0 +1,227 @@
1
+ # C64 KERNAL Memory Map — Complete ($E000–$FFFF)
2
+
3
+ > Purpose: Exhaustive sequential map of KERNAL ROM: callable routines, internal subroutines, constants, tables, IRQ/NMI handlers, and vectors.
4
+ > Format: One table row per symbol; **bold** names indicate callable/public API (also present in `data/api/kernal-api-spec.md`).
5
+ > Conventions: A=Accumulator, X,Y=Index, C=Carry; “—” not applicable.
6
+
7
+ | Address | Decimal | Name | Function | Args | Input | Output | Notes |
8
+ |:--------|:--------|:-----|:---------|:-----|:------|:-------|:------|
9
+ | `$E000` | 57344 | EXP cont. | Continuation of BASIC EXP evaluation | — | Entered via BASIC JMP | — | Cross‑ROM linkage |
10
+ | `$E043` | 57411 | POLY1 | FP series evaluation helper 1 | — | FAC1 set | — | Calls POLY2 |
11
+ | `$E059` | 57433 | POLY2 | FP series evaluation helper 2 | — | FAC1 | FAC1 | Uses constant tables |
12
+ | `$E08D` | 57485 | RMULC | FP const for RND multiply (5‑byte) | — | — | — | Constant |
13
+ | `$E092` | 57490 | RADDC | FP const for RND add (5‑byte) | — | — | — | Constant |
14
+ | `$E097` | 57495 | RND | RND(X): seed ops / scramble | A=mode in FAC | X>0 next; X<0 seed; X=0 CIA/ToD mix | FAC1 | See CIA/BCD caveats |
15
+ | `$E0F9` | 57593 | BASIC↔KERNAL I/O | Bridge to CHRIN/CHROUT/CHKx/GETIN | — | — | — | Handles RS‑232 buffer |
16
+ | `$E12A` | 57642 | SYS | Perform SYS; register save/restore | — | Uses `$030C–$030F` | Stores back post‑RTS | JSR target from SYS |
17
+ | `$E156` | 57686 | SAVE (BASIC) | Prepare range; call KERNAL SAVE | — | Uses `$002B/$002D` | — | Can save arbitrary by ptr tweak |
18
+ | `$E165` | 57701 | VERIFY (BASIC) | Set verify flag then LOAD | — | — | — | Falls through LOAD |
19
+ | `$E168` | 57704 | LOAD (BASIC) | Prepare start; call KERNAL LOAD | — | Adjusts BASIC links | — | Retains variables; relinks |
20
+ | `$E1BE` | 57790 | OPEN (BASIC) | BASIC OPEN → KERNAL OPEN | — | — | — | — |
21
+ | `$E1C7` | 57799 | CLOSE (BASIC) | BASIC CLOSE → KERNAL CLOSE | — | — | — | — |
22
+ | `$E1D4` | 57812 | Param setup L/V/S | Set filename/LFN/dev/sec | — | Prior to LOAD/SAVE/VERIFY | — | — |
23
+ | `$E200` | 57856 | Get int to X | Comma skip, parse integer to X | — | Parsing context | X=integer | — |
24
+ | `$E206` | 57862 | Fetch/Endline | Fetch char; if 0, unwind caller | — | — | — | Control‑flow helper |
25
+ | `$E20E` | 57870 | Check comma | Require comma; advance text ptr | — | — | — | Error on missing comma |
26
+ | `$E219` | 57881 | Param setup O/C | Set filename/LFN/dev/sec for O/C | — | Before OPEN/CLOSE | — | — |
27
+ | `$E264` | 57956 | COS | COS(FAC1) via SIN | — | FAC1 | FAC1 | Adds PI/2 then SIN |
28
+ | `$E268` | 57960 | SIN | SIN(FAC1) | — | FAC1 | FAC1 | — |
29
+ | `$E2B4` | 58036 | TAN | TAN(FAC1)=SIN/COS | — | FAC1 | FAC1 | — |
30
+ | `$E2E0` | 58080 | PI2 | Const PI/2 (5‑byte) | — | — | — | Constant |
31
+ | `$E2E5` | 58085 | TWOPI | Const 2*PI (5‑byte) | — | — | — | Constant |
32
+ | `$E2EA` | 58090 | FR4 | Const 1/4 (5‑byte) | — | — | — | Constant |
33
+ | `$E2EF` | 58095 | SINCON | SIN/COS/TAN constants table | — | — | — | 6×5‑byte, count=5 |
34
+ | `$E30E` | 58126 | ATN | ATN(FAC1) | — | FAC1 | FAC1 | Uses table |
35
+ | `$E33E` | 58174 | ATNCON | ATN constants table | — | — | — | 12×5‑byte, count=11 |
36
+ | `$E37B` | 58235 | Warm BASIC | Warm start; CLRCHN; READY vector | — | From BRK | — | Vector `$0300` |
37
+ | `$E38B` | 58251 | Error msg | BASIC error/READY printing | X=index | Vector `$0302` next | — | — |
38
+ | `$E394` | 58260 | Cold BASIC | Power‑on BASIC init | — | — | — | Copies vectors to RAM |
39
+ | `$E3A2` | 58274 | INITAT | CHRGET text (to $0073) | — | — | — | Moved to ZP |
40
+ | `$E3BA` | 59298 | RND seed | Initial RND seed (5‑byte) | — | — | — | Constant |
41
+ | `$E3BF` | 58303 | INIT | BASIC ZP init; copy CHRGET | — | — | — | — |
42
+ | `$E422` | 58402 | Startup msgs | Print banner & BYTES FREE | — | — | — | — |
43
+ | `$E447` | 58439 | BASIC vec tbl | ROM vector table (→RAM $0300) | — | — | — | — |
44
+ | `$E453` | 58451 | Copy vec | Copy BASIC vectors to RAM | — | — | — | — |
45
+ | `$E460` | 58464 | WORDS | Text constants | — | — | — | — |
46
+ | `$E4AD` | 58541 | CHKOUT patch | Preserve A on BASIC→KERNAL CHKOUT | — | — | — | Later KERNAL patch |
47
+ | `$E4B7` | 58551 | Unused | 35 bytes of $AA | — | — | — | — |
48
+ | `$E4DA` | 58586 | Color RAM clr | Clear line color to background | — | Called by `$E9FF` | — | Patch; changes old behavior |
49
+ | `$E4E0` | 58592 | Tape pause | Pause after FOUND; auto‑continue | — | Cassette find | — | Newer KERNAL |
50
+ | `$E4EC` | 58604 | PAL baud tbl | PAL RS‑232 prescalers | — | — | — | Matches NTSC at `$FEC2` |
51
+ | `$E500` | 58624 | **IOBASE** | Return I/O base | — | — | X=lo,Y=hi | Default `$DC00` |
52
+ | `$E505` | 58629 | **SCREEN** | Return screen cols/rows | — | — | X=40,Y=25 | For compat layouts |
53
+ | `$E50A` | 58634 | **PLOT** | Read/Set cursor | C=1 read; C=0 set; Y=row,X=col | — | Read→X/Y | Uses PNTR/TBLX |
54
+ | `$E518` | 58648 | CINT (part) | Init screen/keyboard (orig) | — | — | — | Falls through |
55
+ | `$E544` | 58692 | Screen links | Init line link table; clear screen | — | — | — | — |
56
+ | `$E566` | 58726 | Home | Home cursor | — | — | — | Sets PNTR/TBLX=0 |
57
+ | `$E56C` | 58732 | PNT set | Pointer to current line | — | Uses links | `$00D1/$00D2` | — |
58
+ | `$E5A0` | 58784 | Defaults | Set default I/O; init VIC regs | — | — | — | Writes table at `$ECB9` |
59
+ | `$E5B4` | 58804 | LP2 | Pop from keyboard buffer | — | Buffer `$0277` | A=char | — |
60
+ | `$E5CA` | 58826 | KBD line | Line input; echo; handles SHIFT‑RUN/STOP | — | Keyboard CHKIN path | A=bytes of line | — |
61
+ | `$E632` | 58930 | CHRIN (kbd/scr) | Device handler for keyboard/screen | — | From CHRIN/GETIN | A=byte | — |
62
+ | `$E684` | 59012 | Quote test | Toggle quote flag | — | — | — | `$00D4` |
63
+ | `$E691` | 59025 | Add char | Put printable to screen | A=PETSCII | — | — | — |
64
+ | `$E6A8` | 59048 | Exit print | Common exit of screen output | — | — | — | — |
65
+ | `$E6B6` | 59062 | Advance cur | Advance cursor; scroll/insert as needed | — | — | — | — |
66
+ | `$E701` | 59137 | Back 40 | Move cursor back across 40‑col boundary | — | — | — | — |
67
+ | `$E716` | 59158 | Screen out | CHROUT screen device path | A=byte | — | — | Prints/control‑codes |
68
+ | `$E87C` | 59516 | Next line | Cursor to next line / scroll | — | — | — | — |
69
+ | `$E891` | 59537 | CR | Carriage return behavior | — | — | — | Reset modes; move line |
70
+ | `$E8A1` | 59553 | BOF prev | If at start of line, move up | — | — | — | — |
71
+ | `$E8B3` | 59571 | EOF next | If at end of line, move down | — | — | — | — |
72
+ | `$E8CB` | 59595 | Color chk | Detect color control | A=code | — | — | — |
73
+ | `$E8D1` | 59601 | Color tbl | PETSCII→color control map | — | — | — | 16 entries listed |
74
+ | `$E8EA` | 59626 | Scroll | Scroll screen | — | CTRL pauses | — | — |
75
+ | `$E965` | 59749 | Insert line | Insert blank physical line | — | — | — | — |
76
+ | `$E9C8` | 59848 | Move line | Move screen line (and color) | — | — | — | — |
77
+ | `$E9E0` | 59872 | Set color ptr | Temp color pointer for scrolling | — | — | `$00AE/$00AF` | — |
78
+ | `$E9F0` | 59888 | Set line start | Pointer to start of line by X | X=line# | — | `$00D1/$00D2` | — |
79
+ | `$E9FF` | 59903 | Clear line | Clear screen line & color | — | — | — | Uses `$E4DA` patch |
80
+ | `$EA13` | 59923 | Blink & color | Cursor blink timer & color RAM base | — | — | — | — |
81
+ | `$EA1C` | 59932 | Store to screen | Store A to screen, X to color | A=char,X=color | `$00D1`/`$00F3` set | — | — |
82
+ | `$EA24` | 59940 | Sync color ptr | Sync color ptr to screen line | — | `$00D1` | `$00F3` | — |
83
+ | `$EA31` | 59953 | IRQ | Standard IRQ entry | — | Via `$0314` | Updates jiffy clock; SCNKEY | Every 1/60 s |
84
+ | `$EA87` | 60039 | **SCNKEY** | Keyboard scan; buffer char | — | IRQ context | Keycode→`$00CB` | Sets shift/control flags |
85
+ | `$EAE0` | 60128 | Decode→buffer | Decode key; handle repeat; buf put | — | Keycode | Adds to `$0277` | — |
86
+ | `$EB48` | 60232 | Set decode tbl | Choose PETSCII table (shift/ctrl/logo) | — | Flags at `$028D` | `$00F5` ptr | Handles char set toggle |
87
+ | `$EB79` | 60281 | Tbl vectors | Addresses of decode tables | — | — | — | — |
88
+ | `$EB81` | 60289 | Std decode | Standard key decode table | — | — | — | 64+1 entries |
89
+ | `$EBC2` | 60354 | Shift decode | Shifted key decode table | — | — | — | 64+1 entries |
90
+ | `$EC03` | 60419 | Logo decode | Commodore‑logo decode table | — | — | — | 64+1 entries |
91
+ | `$EC44` | 60484 | Charset switch | Handle CHR$(14)/CHR$(142) | — | — | — | Writes `$D018` |
92
+ | `$EC5E` | 60510 | Toggle enable | Enable/disable charset toggle | — | — | — | Uses `$0291` |
93
+ | `$EC78` | 60536 | Ctrl decode | Control key decode table | — | — | — | 64+1 entries |
94
+ | `$ECB9` | 60601 | VIC defaults | VIC‑II register default table | — | — | — | 47 regs |
95
+ | `$ECE7` | 60647 | Shift‑RUN text | "LOAD\rRUN\r" buffer text | — | — | — | Injected on SHIFT‑RUN |
96
+ | `$ECF0` | 60656 | Screen low tbl | Low bytes of line addresses | — | — | — | High from links/`$0288` |
97
+ | `$ED09` | 60681 | **TALK** | Send TALK+dev | A=dev | — | — | — |
98
+ | `$ED0C` | 60684 | **LISTEN** | Send LISTEN+dev | A=dev | — | — | — |
99
+ | `$ED11` | 60689 | Serial cmd | Send serial command in A | A=cmd | — | — | Helper |
100
+ | `$ED40` | 60736 | Serial out | Send byte on serial bus | A=byte | `$0095` buffer used | — | — |
101
+ | `$EDB0` | 60848 | Serial timeout | TIMEOUT handler | — | — | Sets status | — |
102
+ | `$EDB9` | 60857 | **SECOND** | Send secondary after LISTEN | A=sec | LISTEN sent | — | — |
103
+ | `$EDC7` | 60871 | **TKSA** | Send secondary after TALK | A=sec | TALK sent | — | — |
104
+ | `$EDDD` | 60893 | **CIOUT** | Serial write byte | A=byte | LISTEN path active | — | Buffers until UNLSN |
105
+ | `$EDEF` | 60911 | **UNTLK** | Send UNTALK | — | — | — | — |
106
+ | `$EDFE` | 60926 | **UNLSN** | Send UNLISTEN | — | — | — | — |
107
+ | `$EE13` | 60947 | **ACPTR** | Serial read byte | — | TALK path active | A=byte | — |
108
+ | `$EE85` | 61061 | SCLK low | Serial clock low | — | — | — | CIA2 `$DD00`.4 |
109
+ | `$EE8E` | 61070 | SCLK high | Serial clock high | — | — | — | CIA2 `$DD00`.4 |
110
+ | `$EE97` | 61079 | SDATA low | Serial data low | — | — | — | CIA2 `$DD00`.5 |
111
+ | `$EEA9` | 61097 | Read SDATA/SCLK | Read serial input bits | — | — | C=data, N=clock | CIA2 `$DD00`.7/.6 |
112
+ | `$EEB3` | 61107 | Delay 1ms | Busy wait ~1 ms | — | — | — | Timing helper |
113
+ | `$EEBB` | 61115 | RS232 send bit | NMI bit‑send routine | — | NMI context | — | — |
114
+ | `$EF2E` | 61230 | RS232 errors | Set RS‑232 status bits | — | — | Status at `$0297` | — |
115
+ | `$EF4A` | 61258 | RS232 wordlen | Word length to X | — | Control reg | X=len | — |
116
+ | `$EF59` | 61273 | RS232 recv bit | NMI bit‑receive routine | — | NMI context | — | — |
117
+ | `$EF7E` | 61310 | RS232 setup rx | Setup to receive new byte | — | — | — | — |
118
+ | `$EF90` | 61328 | RS232 start? | Test start bit | — | — | — | — |
119
+ | `$EF97` | 61335 | RS232 store | Store received byte; check errors | — | — | — | Manage overrun/parity etc. |
120
+ | `$EFE1` | 61409 | RS232 CHKOUT | Device‑specific CHKOUT | — | After OPEN | — | — |
121
+ | `$F014` | 61460 | RS232 CHROUT | Device‑specific CHROUT | A=byte | After CHKOUT | — | — |
122
+ | `$F04D` | 61517 | RS232 CHKIN | Device‑specific CHKIN | — | After OPEN | — | — |
123
+ | `$F086` | 61574 | RS232 GETIN | Device‑specific GETIN | — | — | A=byte | Checks buffer empty |
124
+ | `$F0A4` | 61604 | Stop RS232 NMIs | Disable RS‑232 NMIs for tape/serial | — | Before cassette/serial ops | — | Timing safety |
125
+ | `$F0BD` | 61629 | Ctrl messages | Text: I/O ERROR, SEARCHING, … | — | — | — | High bit set on last char |
126
+ | `$F12B` | 61739 | Print error | Print KERNAL error if direct | Y=index | Message flag `$009D` | — | — |
127
+ | `$F13E` | 61758 | **GETIN** | Get next char | — | Device selected | A=byte | Vector `$032A` |
128
+ | `$F157` | 61783 | **CHRIN** | Read from current input | — | After CHKIN | A=byte | Keyboard path does line read |
129
+ | `$F1CA` | 61898 | **CHROUT** | Output to current device | A=byte | After CHKOUT | — | Screen handler at `$E716` |
130
+ | `$F20E` | 61966 | **CHKIN** | Select input channel | X=file# | After OPEN | — | Sends TALK/SA as needed |
131
+ | `$F250` | 62032 | **CHKOUT** | Select output channel | X=file# | After OPEN | — | Sends LISTEN/SA as needed |
132
+ | `$F291` | 62097 | **CLOSE** | Close logical file | A=file# | File open | — | Frees buffers; UNLSN |
133
+ | `$F30F` | 62223 | Find LFN | Find file in LFN table | A=file# | Tables at `$0259/$0263/$026D` | X=index | Helper |
134
+ | `$F31F` | 62239 | Set current | Set current LFN/dev/SA | — | — | `$00B8–$00BA` | Helper |
135
+ | `$F32F` | 62255 | **CLALL** | Close all channels | — | — | — | Vector `$032C` |
136
+ | `$F333` | 62259 | **CLRCHN** | Restore default I/O | — | — | — | Keyboard/screen |
137
+ | `$F34A` | 62282 | **OPEN** | Open logical file | — | After SETLFS/SETNAM | C=1 on error | Vector `$031A` |
138
+ | `$F49E` | 62622 | **LOAD** | Load/Verify RAM | A=0/1; X/Y=start | After SETLFS/SETNAM | X/Y=end addr | SA=1 uses header |
139
+ | `$F5A5` | 62885 | SEARCHING | Print SEARCHING (direct mode) | — | Direct mode | — | — |
140
+ | `$F5D2` | 62930 | LOAD/VERIFY msg | Print LOADING/VERIFYING | — | — | — | — |
141
+ | `$F5DD` | 62941 | **SAVE** | Save RAM to device | A=ZP ptr; X/Y=end addr | After SETLFS/SETNAM | — | Vector `$0332` |
142
+ | `$F68F` | 63119 | SAVING msg | Print SAVING and filename | — | Direct mode | — | — |
143
+ | `$F69B` | 63131 | **UDTIM** | Update clock; STOP scan | — | IRQ 60 Hz | `$00A0–$00A2`++ | STOP key to `$0091` |
144
+ | `$F6DD` | 63197 | **RDTIM** | Read clock | — | — | A=lo,X=mid,Y=hi | From `$00A0–$00A2` |
145
+ | `$F6E4` | 63204 | **SETTIM** | Set clock | A=lo,X=mid,Y=hi | — | Clock set | Disables IRQ during set |
146
+ | `$F6ED` | 63213 | **STOP** | Test STOP key | — | — | Z=1 if pressed | Also CLRCHN & clear queue |
147
+ | `$F6FB` | 63227 | I/O error | Handle KERNAL I/O errors | — | — | C=1, A=code | Prints if enabled |
148
+ | `$F72C` | 63276 | Tape: next header | Find next tape header; print FOUND | — | Cassette | — | — |
149
+ | `$F76A` | 63338 | Tape: write hdr | Write tape header block | — | — | — | — |
150
+ | `$F7D0` | 63440 | Tape: ptr→X/Y | Pointer to tape buffer | — | — | X/Y | — |
151
+ | `$F7D7` | 63447 | Tape: set IO area | I/O start/end to tape buffer | — | — | — | — |
152
+ | `$F7EA` | 63466 | Tape: search name | Search tape for filename | — | — | — | — |
153
+ | `$F817` | 63511 | Tape: buttons read | Press PLAY msg; wait / OK | — | Direct mode unaffected | — | — |
154
+ | `$F82E` | 63534 | Cassette sense | Check cassette switch | — | — | — | — |
155
+ | `$F838` | 63544 | Tape: buttons write | Press PLAY & RECORD msg; wait / OK | — | — | — | — |
156
+ | `$F841` | 63553 | Tape: start read | Init flags; start read | — | — | — | — |
157
+ | `$F864` | 63588 | Tape: start write | Init flags; start write | — | — | — | — |
158
+ | `$F875` | 63605 | Tape: common | Setup IRQ, blank screen, save/replace IRQ | — | — | — | Uses CIA1 Timer B |
159
+ | `$F8D0` | 63696 | Tape: STOP test | Test STOP during tape I/O | — | — | — | — |
160
+ | `$F8E2` | 63714 | Tape: TimerA tune | Adjust CIA1 Timer A for bit timing | — | — | — | — |
161
+ | `$F92C` | 63788 | Tape: read IRQ | IRQ handler for tape read | — | IRQ | — | Restores IRQ at end |
162
+ | `$FA60` | 64096 | Tape: get byte | Receive/store next cassette byte | — | IRQ | — | — |
163
+ | `$FB8E` | 64398 | Tape: addr→172 | Copy save/load address to `$00AC` | — | — | — | — |
164
+ | `$FB97` | 64407 | Tape: reset counters | For new byte R/W | — | — | — | — |
165
+ | `$FBA6` | 64422 | Tape: toggle out | Toggle 6510 port bit 3 for data | — | — | — | `$0001`.3 |
166
+ | `$FBC8` | 64456 | Tape: write IRQ 2 | Cassette write (part 2) | — | IRQ | — | — |
167
+ | `$FC6A` | 64618 | Tape: write IRQ 1 | Cassette write (part 1) | — | IRQ | — | — |
168
+ | `$FC93` | 64659 | IRQ restore | Restore default IRQ; stop motor | — | — | — | Re‑enable 60 Hz IRQ |
169
+ | `$FCB8` | 64696 | Tape I/O end | Terminate cassette I/O | — | — | — | RTS from IRQ |
170
+ | `$FCCA` | 64714 | Tape motor off | Turn off cassette motor | — | — | — | — |
171
+ | `$FCD1` | 64721 | Tape ptr chk | Compare R/W ptr vs end | — | — | — | — |
172
+ | `$FCDB` | 64731 | Tape ptr adv | Advance R/W pointer | — | — | — | — |
173
+ | `$FCE2` | 64738 | RESET | Power‑on reset entry | — | HW reset | — | Checks cartridge; calls IOINIT,RAMTAS,RESTOR,CINT |
174
+ | `$FD02` | 64770 | Cart detect | Check autostart cartridge | — | — | Z set on match | Compares `$8004–$8008` |
175
+ | `$FD10` | 64784 | Cart text | CBM+“80” text for detect (hi‑bit set) | — | — | — | — |
176
+ | `$FD15` | 64789 | **RESTOR** | Restore RAM vectors | — | — | — | Uses ROM table `$FD30` |
177
+ | `$FD1A` | 64794 | **VECTOR** | Read/Write vectors | C=1 read; C=0 write; X/Y=table | — | Copy vectors | Affect IRQ/NMI; SEI |
178
+ | `$FD30` | 64816 | Default vectors | ROM vector table (to `$0314–$0333`) | — | — | — | — |
179
+ | `$FD50` | 64848 | **RAMTAS** | RAM test; set pointers | — | — | `$0281–$0284` | Clears ZP, pages 2–3 |
180
+ | `$FD9B` | 64923 | IRQ vector tbl | Pointers to IRQ routines | — | — | — | Tape write1/2, standard IRQ, tape read |
181
+ | `$FDA3` | 64931 | **IOINIT** | Initialize CIAs/SID | — | — | — | Sets CIA1 Timer A |
182
+ | `$FDF9` | 65017 | **SETNAM** | Set filename pointer/len | A=len, X=lo, Y=hi | — | — | For OPEN/LOAD/SAVE |
183
+ | `$FE00` | 65024 | **SETLFS** | Set LFN/dev/SA | A=lfn, X=dev, Y=sa or `$FF` | — | — | For OPEN/LOAD/SAVE |
184
+ | `$FE07` | 65031 | **READST** | Read I/O status word | — | — | A=status | RS‑232 clears own |
185
+ | `$FE18` | 65048 | **SETMSG** | Control/error messages | A bits6–7 | — | — | — |
186
+ | `$FF81` | 65409 | **CINT** | Init screen/keyboard | — | — | — | Jump table |
187
+ | `$FF84` | 65412 | **IOINIT** | Initialize I/O | — | — | — | Jump table |
188
+ | `$FF87` | 65415 | **RAMTAS** | RAM test/setup | — | — | — | Jump table |
189
+ | `$FF8A` | 65418 | **RESTOR** | Restore vectors | — | — | — | Jump table |
190
+ | `$FF8D` | 65421 | **VECTOR** | Vectors R/W | C,X,Y | — | — | Jump table |
191
+ | `$FF90` | 65424 | **SETMSG** | Message flags | A | — | — | Jump table |
192
+ | `$FF93` | 65427 | **SECOND** | Serial SA after LISTEN | A | — | — | Jump table |
193
+ | `$FF96` | 65430 | **TKSA** | Serial SA after TALK | A | — | — | Jump table |
194
+ | `$FF99` | 65433 | **MEMTOP** | Get/Set top of RAM | C,X,Y | — | X/Y | Jump table |
195
+ | `$FF9C` | 65436 | **MEMBOT** | Get/Set bottom of RAM | C,X,Y | — | X/Y | Jump table |
196
+ | `$FF9F` | 65439 | **SCNKEY** | Keyboard scan | — | — | — | Jump table |
197
+ | `$FFA2` | 65442 | **SETTMO** | Timeout control | A | — | — | Jump table |
198
+ | `$FFA5` | 65445 | **ACPTR** | Serial read | — | — | A | Jump table |
199
+ | `$FFA8` | 65448 | **CIOUT** | Serial write | A | — | — | Jump table |
200
+ | `$FFAB` | 65451 | **UNTLK** | Serial UNTALK | — | — | — | Jump table |
201
+ | `$FFAE` | 65454 | **UNLSN** | Serial UNLISTEN | — | — | — | Jump table |
202
+ | `$FFB1` | 65457 | **LISTEN** | Serial LISTEN | A | — | — | Jump table |
203
+ | `$FFB4` | 65460 | **TALK** | Serial TALK | A | — | — | Jump table |
204
+ | `$FFB7` | 65463 | **READST** | Read status | — | — | A | Jump table |
205
+ | `$FFBA` | 65466 | **SETLFS** | Set LFN/dev/SA | A,X,Y | — | — | Jump table |
206
+ | `$FFBD` | 65469 | **SETNAM** | Set filename | A,X,Y | — | — | Jump table |
207
+ | `$FFC0` | 65472 | **OPEN** | Open | — | — | C on error | Jump table |
208
+ | `$FFC3` | 65475 | **CLOSE** | Close | A | — | — | Jump table |
209
+ | `$FFC6` | 65478 | **CHKIN** | Select input | X | — | — | Jump table |
210
+ | `$FFC9` | 65481 | **CHKOUT** | Select output | X | — | — | Jump table |
211
+ | `$FFCC` | 65484 | **CLRCHN** | Restore default I/O | — | — | — | Jump table |
212
+ | `$FFCF` | 65487 | **CHRIN** | Read byte | — | — | A | Jump table |
213
+ | `$FFD2` | 65490 | **CHROUT** | Write byte | A | — | — | Jump table |
214
+ | `$FFD5` | 65493 | **LOAD** | Load/Verify | A,X,Y | — | X/Y=end | Jump table |
215
+ | `$FFD8` | 65496 | **SAVE** | Save | A,X,Y | — | — | Jump table |
216
+ | `$FFDB` | 65499 | **SETTIM** | Set clock | A,X,Y | — | — | Jump table |
217
+ | `$FFDE` | 65502 | **RDTIM** | Read clock | — | — | A,X,Y | Jump table |
218
+ | `$FFE1` | 65505 | **STOP** | Test STOP | — | — | Z flag | Jump table |
219
+ | `$FFE4` | 65508 | **GETIN** | Get char | — | — | A | Jump table |
220
+ | `$FFE7` | 65511 | **CLALL** | Close all | — | — | — | Jump table |
221
+ | `$FFEA` | 65514 | **UDTIM** | Jiffy tick | — | — | — | Jump table |
222
+ | `$FFED` | 65517 | **SCREEN** | Screen size | — | — | X,Y | Jump table |
223
+ | `$FFF0` | 65520 | **PLOT** | Cursor read/set | C,X,Y | — | X,Y | Jump table |
224
+ | `$FFF3` | 65523 | **IOBASE** | I/O base | — | — | X,Y | Jump table |
225
+ | `$FFFA` | 65530 | NMI vec | NMI vector | — | HW | — | RAM at `$0318/9` |
226
+ | `$FFFC` | 65532 | RESET vec | RESET vector | — | HW | — | Points to `$FCE2` |
227
+ | `$FFFE` | 65534 | IRQ/BRK vec | IRQ/BRK vector | — | HW | — | RAM at `$0314/5` |
@@ -0,0 +1,133 @@
1
+ # Low Memory Pages 0–3 (Zero Page, Stack, System Work Areas)
2
+
3
+ > Scope: **$0000–$03FF (0–1023)**: Zero page (BASIC + KERNAL vars), page-1 stack, page-2 system buffers/tables, page-3 vectors + **cassette (tape) buffer**.
4
+
5
+ > Style: Same compact table schema used in your KERNAL/BASIC specs. **Hex + decimal** addresses. **Bold** = key/callable vectors.
6
+
7
+ > Hints: Zero page gives **1‑byte addressing** → faster code; keep ML temporaries in $FB–$FE. If **tape is unused**, the **cassette buffer $033C–$03FB (828–1019)** is ideal for **small ML helpers** or even **sprite/char data** (e.g., sprite blocks 13 @ $0340–$037F, 14 @ $0380–$03BF). Keyboard buffering enables **“dynamic keyboard”** input injection. Adjust **LORAM/HIRAM/CHAREN** via $0001 for ROM/RAM banking.
8
+
9
+ ## Legend
10
+
11
+ A=Accumulator, X,Y=index, C=Carry; “—” = not applicable. Pointers are little‑endian unless noted.
12
+
13
+ | Address | Decimal | Name | Function | Args | Input | Output | Notes |
14
+ |:--|:--|:--|:--|:--|:--|:--|:--|
15
+ | `$0000` | 0 | **D6510** | 6510 on‑chip I/O **Data Direction** | bitmask | — | — | Bits0–5 valid; default `$EF`. Configure port at $0001. |
16
+ | `$0001` | 1 | **R6510** | 6510 on‑chip **I/O Port** (banking + cassette) | bitmask | — | — | Bit0=LORAM,1=HIRAM,2=CHAREN; 3=data out; 4=switch sense; 5=motor. |
17
+ | `$0002` | 2 | — | Unused | — | — | — | Free (zero page). |
18
+ | `$0003–$0004` | 3–4 | **ADRAY1** | Vector: FP→signed **int** | — | FAC1 | A,Y or $64/65 | Points to `$B1AA`. |
19
+ | `$0005–$0006` | 5–6 | **ADRAY2** | Vector: **int→FP** | — | A,Y or $64/65 | FAC1 | Points to `$B391`. |
20
+ | `$0007` | 7 | CHARAC | Scanner work byte | — | — | — | Search char for tokeniser. |
21
+ | `$0008` | 8 | ENDCHR | Scanner work byte | — | — | — | Often 0 or 34 ("). |
22
+ | `$0009` | 9 | TRMPOS | Cursor col before TAB/SPC | — | — | — | 0–79 logical col. |
23
+ | `$000A` | 10 | VERCK | LOAD(0)/VERIFY(1) flag → KERNAL | — | — | — | Also copied to $0093. |
24
+ | `$000B` | 11 | COUNT | Input buffer index/array subscripts | — | — | — | Tokeniser & DIM/array helper. |
25
+ | `$000C` | 12 | DIMFLG | Array build/reference flags | — | — | — | Array state. |
26
+ | `$000D` | 13 | VALTYP | Type flag | — | — | — | 0=numeric, $FF=string. |
27
+ | `$000E` | 14 | INTFLG | Numeric kind flag | — | — | — | $80=int, 0=float. |
28
+ | `$000F` | 15 | GARBFL | LIST/GC/tokenize flag | — | — | — | GC tried; LIST in quotes. |
29
+ | `$0010` | 16 | SUBFLG | “(” seen → array/FN | — | — | — | PTRGET helper. |
30
+ | `$0011` | 17 | INPFLG | GET/READ/INPUT kind | — | — | — | 0=INPUT, $40=GET, $98=READ. |
31
+ | `$0012` | 18 | TANSGN | Sign/compare mask | — | — | — | Also holds compare result flags. |
32
+ | `$0013` | 19 | CHANNL | Current I/O **channel** (CMD LFN) | — | device state | — | 0=screen/keyboard; ≠0 alters prompts/tabs. |
33
+ | `$0014–$0015` | 20–21 | LINNUM | Target/line number | — | — | — | Also PEEK/POKE/WAIT/SYS address temp. |
34
+ | `$0016` | 22 | TEMPPT | Temp string stack ptr | — | — | — | 3 slots @ $19–$21; FORMULA TOO COMPLEX if full. |
35
+ | `$0017–$0018` | 23–24 | LASTPT | Temp string stack last | — | — | — | =TEMPPT−3. |
36
+ | `$0019–$0021` | 25–33 | TEMPST | Temp string descriptors | — | — | — | length/addr triples. |
37
+ | `$0022–$0025` | 34–37 | INDEX | Misc temp/save | — | — | — | Scratch. |
38
+ | `$0026–$002A` | 38–42 | RESHO | FP mult/div work | — | — | — | Also array-size calc. |
39
+ | `$002B–$002C` | 43–44 | **TXTTAB** | Ptr: start of BASIC text | — | — | — | Usually $0801; changing relocates program base. |
40
+ | `$002D–$002E` | 45–46 | **VARTAB** | Ptr: start of variables | — | — | — | 7‑byte descriptors; type via high bit(s). |
41
+ | `$002F–$0030` | 47–48 | **ARYTAB** | Ptr: start of arrays | — | — | — | Array header + dims + data. |
42
+ | `$0031–$0032` | 49–50 | **STREND** | Ptr: end of arrays (=start free RAM) | — | — | — | Moves up as vars grow. |
43
+ | `$0033–$0034` | 51–52 | **FREETOP** | Ptr: bottom of string text | — | — | — | CLR sets to MEMSIZ; strings grow downward. |
44
+ | `$0035–$0036` | 53–54 | FRESPC | Temp string ptr | — | — | — | Recent string. |
45
+ | `$0037–$0038` | 55–56 | **MEMSIZ** | Ptr: BASIC top (limit) | — | — | — | User‑lowerable to reserve safe area. |
46
+ | `$0039–$003A` | 57–58 | **CURLIN** | Current BASIC line # | — | — | — | $FF in $3A = immediate mode. |
47
+ | `$003B–$003C` | 59–60 | OLDLIN | Previous line # | — | — | — | For CONT. |
48
+ | `$003D–$003E` | 61–62 | OLDTXT | Ptr: current stmt text | — | — | — | Saved/restored by STOP/CONT. |
49
+ | `$003F–$0040` | 63–64 | DATLIN | DATA line # | — | — | — | Error context. |
50
+ | `$0041–$0042` | 65–66 | **DATPTR** | Ptr: current DATA item | — | — | — | RESTORE resets to TXTTAB. |
51
+ | `$0043–$0044` | 67–68 | INPPTR | Ptr: GET/READ/INPUT source | — | — | — | DATA or $0200 buffer. |
52
+ | `$0045–$0046` | 69–70 | VARNAM | Current var name (2 bytes) | — | — | — | High‑bit type tagging. |
53
+ | `$0047–$0048` | 71–72 | VARPNT | Ptr: current var value | — | — | — | Points past name bytes. |
54
+ | `$0049–$004A` | 73–74 | FORPNT | Temp FOR var ptr | — | — | — | Pushed to stack. |
55
+ | `$004B–$004C` | 75–76 | OPPTR | Operator table offset | — | — | — | Also text save. |
56
+ | `$004D` | 77 | OPMASK | Compare mask | — | — | — | 1/2/4 for </=/>. |
57
+ | `$004E–$004F` | 78–79 | DEFPNT | Ptr: current FN descriptor | — | — | — | DEF/FN. |
58
+ | `$0050–$0052` | 80–82 | DSCPNT | Temp string desc ptr/len | — | — | — | — |
59
+ | `$0053` | 83 | FOUR6 | GC format constant | — | — | — | 3 vs 7‑byte desc. |
60
+ | `$0054–$0056` | 84–86 | JMPER | `JMP` + addr for FN | — | — | — | Table @ $A052. |
61
+ | `$0057–$0060` | 87–96 | — | BASIC numeric work area | — | — | — | — |
62
+ | `$0061–$0066` | 97–102 | **FAC1** | FP accumulator #1 | — | — | FAC1 | Exp @ $61; mant $62–$65; sign $66. |
63
+ | `$0067–$0068` | 103–104 | SGNFLG/BITS | Series count/overflow | — | — | — | FP helper. |
64
+ | `$0069–$006E` | 105–110 | **FAC2** | FP accumulator #2 | — | — | FAC2 | Exp/mant/sign. |
65
+ | `$006F–$0072` | 111–114 | ARISGN/FACOV | Sign compare/rounding | — | — | — | — |
66
+ | `$0071–$0072` | 113–114 | FBUFPT | Series eval ptr | — | — | — | Multi‑use scratch. |
67
+ | `$0073–$008A` | 115–138 | **CHRGET** | Get/peek next BASIC char | — | TXTPTR | A=char; flags | Copied from ROM @ $E3A2 for speed. Entry **CHRGOT**=$0079. |
68
+ | `$008B–$008F` | 139–143 | RNDX | RND seed (5‑byte FP) | — | — | — | Init from ROM seed. |
69
+ | `$0090` | 144 | STATUS | **KERNAL ST** (I/O status) | — | device | — | Bits vary (EOF=bit6). |
70
+ | `$0091` | 145 | STKEY | STOP/row readback | — | keyboard | — | $7F when STOP pressed. |
71
+ | `$0092` | 146 | SVXT | Tape timing const | — | — | — | Adjustable. |
72
+ | `$0093` | 147 | VERCK | LOAD/VERIFY flag | — | — | — | Mirrors $000A usage. |
73
+ | `$0094–$0097` | 148–151 | C3PO/BSOUR/SYNO/XSAV | Serial/tape temporaries | — | — | — | Buffered char, etc. |
74
+ | `$0098` | 152 | LDTND | Open files count / table end | — | OPEN/CLOSE | — | Drives LAT/FAT/SAT mgmt. |
75
+ | `$0099` | 153 | DFLTN | Default input device | — | — | — | 0=keyboard; set by CHKIN. |
76
+ | `$009A` | 154 | DFLTO | Default output (CMD) | — | — | — | 3=screen; set by CHKOUT. |
77
+ | `$009B–$00A2` | 155–162 | Tape/serial state + **TIME** | — | IRQ | TIME ticks | TI/TI$ use RDTIM/SETTIM. |
78
+ | `$00A3–$00AD` | 163–173 | Temp + **SAL** | Load start (work) | — | — | — | Screen routines reuse. |
79
+ | `$00AE–$00AF` | 174–175 | **EAL** | Load end | — | — | — | Also SAVE limit. |
80
+ | `$00B0–$00B3` | 176–179 | CMP0/**TAPE1** | Tape timing / **tape buffer start ptr** | — | — | — | TAPE1→$033C. |
81
+ | `$00B4–$00B7` | 180–183 | BITTS/NXTBIT/RODATA/FNLEN | RS‑232/tape/fname len | — | — | — | Tape names up to 187 bytes. |
82
+ | `$00B8–$00BC` | 184–188 | **LA/SA/FA/FNADR** | LFN/SA/device/fname ptr | — | — | — | Device ids: 0,1,2,3,4–5,8–11. |
83
+ | `$00BD–$00C2` | 189–194 | ROPRTY/FSBLK/MYCH/**STAL** | RS‑232/tape start | — | — | — | STAL used by LOAD/SAVE. |
84
+ | `$00C5` | 197 | LSTX | Last key matrix code | — | — | — | 64 if none. |
85
+ | `$00C6` | 198 | NDX | Keyboard buffer count | — | — | — | Set to 0 to flush. |
86
+ | `$00C7` | 199 | RVS | Reverse‑video flag | — | — | — | CHR$(18)/CHR$(146) toggle; clears on CR. |
87
+ | `$00C8–$00CA` | 200–202 | INDX/LXSP | Input line end / start X,Y | — | — | — | Logical lines. |
88
+ | `$00CB` | 203 | SFDX | Current key matrix code | — | keyboard | — | Used with KEYTAB tables. |
89
+ | `$00D1` | 209 | — | Ptr: current screen line | — | — | — | USER ($F3) follows color RAM. |
90
+ | `$00D9` | 217 | SCRLLN | **Screen line link table index** | — | — | — | Logical line topology (hi‑bit marks head). |
91
+ | `$00F3–$00F6` | 243–246 | **USER/KEYTAB** | Color RAM ptr / keyboard table vector | — | — | — | KEYTAB→tables at $EB81/$EBC2/$EC03/$EC78. |
92
+ | `$00F7–$00FA` | 247–250 | **RIBUF/ROBUF** | RS‑232 input/output buffer ptrs | — | — | — | 256‑byte rings at top of RAM. |
93
+ | `$00FB–$00FE` | 251–254 | **FREEZP** | **Free zero‑page bytes** | — | — | — | Safe for ML use. |
94
+ | `$00FF` | 255 | BASZPT | FP→ASCII temp | — | — | — | — |
95
+
96
+ ### Page 1 — Stack / Tape Log
97
+
98
+ | Address | Decimal | Name | Function | Args | Input | Output | Notes |
99
+ |:--|:--|:--|:--|:--|:--|:--|:--|
100
+ | `$0100–$01FF` | 256–511 | **STACK** | 6510 **hardware stack** | pushes/pulls | JSR/IRQ | return addr/reg saves | BASIC also uses as work area; keep ≥62 bytes free; FOR frame = 18 bytes. |
101
+ | `$0100–$010A` | 256–266 | — | FP→string and scan work | — | — | — | — |
102
+ | `$0100–$013E` | 256–318 | **BAD** | Tape input error log | — | tape pass 1 | — | 62 bytes. |
103
+
104
+ ### Page 2 — Input Buffer, File Tables, Keyboard Queue
105
+
106
+ | Address | Decimal | Name | Function | Args | Input | Output | Notes |
107
+ |:--|:--|:--|:--|:--|:--|:--|:--|
108
+ | `$0200–$0258` | 512–600 | **INBUF** | Keyboard/direct‑mode & GET/INPUT/READ buffer | — | KERNAL CHRIN | — | 89 bytes; last ~8 free on C64. |
109
+ | `$0259–$0262` | 601–610 | **LAT** | Table: active **logical file #s** | — | OPEN/CLOSE | — | 10 entries. |
110
+ | `$0263–$026C` | 611–620 | **FAT** | Table: device # per LFN | — | — | — | 10 entries. |
111
+ | `$026D–$0276` | 621–630 | **SAT** | Table: secondary address per LFN | — | — | — | 10 entries. |
112
+ | `$0277–$0280` | 631–640 | **KEYD** | **Keyboard buffer (FIFO)** | — | IRQ keyboard | dequeued chars | Max length set by $0289 (649). Supports “dynamic keyboard”. |
113
+ | `$0281–$0284` | 641–644 | **BASBOT/BASTOP** | BASIC bottom/top pointers | — | RAMTAS | — | Set by RAM test; RS‑232 lowers by 512 for buffers. |
114
+ | `$0288–$0289` | 648–649 | SCRNPAGE/KEYMAX | Screen page base / max KEYD size | — | — | — | Screen base page used with $ECF0 low‑byte table. |
115
+
116
+ ### Page 3 — KERNAL/BASIC Vectors & **Cassette Buffer**
117
+
118
+ | Address | Decimal | Name | Function | Args | Input | Output | Notes |
119
+ |:--|:--|:--|:--|:--|:--|:--|:--|
120
+ | `$0300–$030B` | 768–779 | **BASIC RAM vectors** | Pointers to BASIC core routines (editable) | — | — | — | Copied from ROM @ $E447; used for wedges/overrides. |
121
+ | `$0314–$0333` | 788–819 | **KERNAL RAM vectors** | CHRIN/CHROUT/STOP/GETIN/etc. | — | — | — | IOPEN/ICLOSE/ICHKIN/ICKOUT/ICLRCH/IBASIN/IBSOUT/ISTOP/IGETIN/ICLALL/USRCMD/ILOAD/ISAVE. |
122
+ | `$0334–$033B` | 820–827 | — | Free vector slots | — | — | — | 8 bytes free. |
123
+ | `$033C–$03FB` | 828–1019 | **TBUFFER** | **Cassette buffer** (192 bytes) | — | tape I/O | — | Reusable if **no tape**: ML stash or VIC‑II data (sprites **13** @ $0340–$037F, **14** @ $0380–$03BF). Header/data block formats; id byte at $033C. |
124
+ | `$03FC–$03FF` | 1020–1023 | — | Unused | — | — | — | 4 free bytes. |
125
+
126
+ ---
127
+
128
+ ## Practical Tips (LLM prompts → actions)
129
+
130
+ - **Reserve safe RAM** above BASIC: lower `MEMSIZ` ($37/$38) then `CLR` to keep ML/sprite/charset. RS‑232 OPEN auto‑lowers top by 512 for 2×256‑byte buffers.
131
+ - **Dynamic keyboard**: preload KEYD ($0277–$0280), set NDX ($00C6), characters are consumed in order; handy for quoted INPUT.
132
+ - **ROM banking** via $0001: temporarily map out BASIC/KERNAL/CHAR for patching or ROM reads; remember to **disable IRQs** before switching out KERNAL.
133
+ - **Cassette buffer reuse**: if device 1 not active, use $033C–$03FB for short ML stubs or graphics data; keep header semantics in mind; **do not** run tape I/O concurrently.