web-a2e 1.0.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 (295) hide show
  1. package/.clangd +5 -0
  2. package/.mcp.json +12 -0
  3. package/CLAUDE.md +362 -0
  4. package/CMakeLists.txt +774 -0
  5. package/LICENSE +21 -0
  6. package/README.md +392 -0
  7. package/build-wasm/generated/roms.cpp +2447 -0
  8. package/docker-compose.staging.yml +9 -0
  9. package/docs/basic-rom-disassembly.md +6663 -0
  10. package/docs/softswitch-comparison.md +273 -0
  11. package/docs/thunderclock-debug.md +89 -0
  12. package/examples/cube.bas +72 -0
  13. package/examples/hello.s +55 -0
  14. package/examples/scroll.s +140 -0
  15. package/package.json +18 -0
  16. package/public/assets/apple-logo-old.png +0 -0
  17. package/public/assets/apple-logo.png +0 -0
  18. package/public/assets/drive-closed-light-on.png +0 -0
  19. package/public/assets/drive-closed.png +0 -0
  20. package/public/assets/drive-open-light-on.png +0 -0
  21. package/public/assets/drive-open.png +0 -0
  22. package/public/audio-worklet.js +82 -0
  23. package/public/disks/Apple DOS 3.3 January 1983.dsk +0 -0
  24. package/public/disks/ProDOS 2.4.3.po +0 -0
  25. package/public/disks/h32mb.2mg +0 -0
  26. package/public/disks/library.json +26 -0
  27. package/public/docs/llms/llm-assembler.txt +90 -0
  28. package/public/docs/llms/llm-basic-program.txt +256 -0
  29. package/public/docs/llms/llm-disk-drives.txt +72 -0
  30. package/public/docs/llms/llm-file-explorer.txt +50 -0
  31. package/public/docs/llms/llm-hard-drives.txt +80 -0
  32. package/public/docs/llms/llm-main.txt +51 -0
  33. package/public/docs/llms/llm-slot-configuration.txt +66 -0
  34. package/public/icons/icon-192.svg +4 -0
  35. package/public/icons/icon-512.svg +4 -0
  36. package/public/index.html +661 -0
  37. package/public/llms.txt +49 -0
  38. package/public/manifest.json +29 -0
  39. package/public/shaders/burnin.glsl +22 -0
  40. package/public/shaders/crt.glsl +706 -0
  41. package/public/shaders/edge.glsl +109 -0
  42. package/public/shaders/vertex.glsl +8 -0
  43. package/public/sw.js +186 -0
  44. package/roms/341-0027.bin +0 -0
  45. package/roms/341-0160-A-US-UK.bin +0 -0
  46. package/roms/341-0160-A.bin +0 -0
  47. package/roms/342-0273-A-US-UK.bin +0 -0
  48. package/roms/342-0349-B-C0-FF.bin +0 -0
  49. package/roms/Apple Mouse Interface Card ROM - 342-0270-C.bin +0 -0
  50. package/roms/Thunderclock Plus ROM.bin +0 -0
  51. package/scripts/generate_roms.sh +69 -0
  52. package/src/bindings/wasm_interface.cpp +1940 -0
  53. package/src/core/assembler/assembler.cpp +1239 -0
  54. package/src/core/assembler/assembler.hpp +115 -0
  55. package/src/core/audio/audio.cpp +160 -0
  56. package/src/core/audio/audio.hpp +81 -0
  57. package/src/core/basic/basic_detokenizer.cpp +436 -0
  58. package/src/core/basic/basic_detokenizer.hpp +41 -0
  59. package/src/core/basic/basic_tokenizer.cpp +286 -0
  60. package/src/core/basic/basic_tokenizer.hpp +26 -0
  61. package/src/core/basic/basic_tokens.hpp +295 -0
  62. package/src/core/cards/disk2_card.cpp +568 -0
  63. package/src/core/cards/disk2_card.hpp +316 -0
  64. package/src/core/cards/expansion_card.hpp +185 -0
  65. package/src/core/cards/mockingboard/ay8910.cpp +616 -0
  66. package/src/core/cards/mockingboard/ay8910.hpp +159 -0
  67. package/src/core/cards/mockingboard/via6522.cpp +530 -0
  68. package/src/core/cards/mockingboard/via6522.hpp +163 -0
  69. package/src/core/cards/mockingboard_card.cpp +312 -0
  70. package/src/core/cards/mockingboard_card.hpp +159 -0
  71. package/src/core/cards/mouse_card.cpp +654 -0
  72. package/src/core/cards/mouse_card.hpp +190 -0
  73. package/src/core/cards/smartport/block_device.cpp +202 -0
  74. package/src/core/cards/smartport/block_device.hpp +60 -0
  75. package/src/core/cards/smartport/smartport_card.cpp +603 -0
  76. package/src/core/cards/smartport/smartport_card.hpp +120 -0
  77. package/src/core/cards/thunderclock_card.cpp +237 -0
  78. package/src/core/cards/thunderclock_card.hpp +122 -0
  79. package/src/core/cpu/cpu6502.cpp +1609 -0
  80. package/src/core/cpu/cpu6502.hpp +203 -0
  81. package/src/core/debug/condition_evaluator.cpp +470 -0
  82. package/src/core/debug/condition_evaluator.hpp +87 -0
  83. package/src/core/disassembler/disassembler.cpp +552 -0
  84. package/src/core/disassembler/disassembler.hpp +171 -0
  85. package/src/core/disk-image/disk_image.hpp +267 -0
  86. package/src/core/disk-image/dsk_disk_image.cpp +827 -0
  87. package/src/core/disk-image/dsk_disk_image.hpp +204 -0
  88. package/src/core/disk-image/gcr_encoding.cpp +147 -0
  89. package/src/core/disk-image/gcr_encoding.hpp +78 -0
  90. package/src/core/disk-image/woz_disk_image.cpp +1049 -0
  91. package/src/core/disk-image/woz_disk_image.hpp +343 -0
  92. package/src/core/emulator.cpp +2126 -0
  93. package/src/core/emulator.hpp +434 -0
  94. package/src/core/filesystem/dos33.cpp +178 -0
  95. package/src/core/filesystem/dos33.hpp +66 -0
  96. package/src/core/filesystem/pascal.cpp +262 -0
  97. package/src/core/filesystem/pascal.hpp +87 -0
  98. package/src/core/filesystem/prodos.cpp +369 -0
  99. package/src/core/filesystem/prodos.hpp +119 -0
  100. package/src/core/input/keyboard.cpp +227 -0
  101. package/src/core/input/keyboard.hpp +111 -0
  102. package/src/core/mmu/mmu.cpp +1387 -0
  103. package/src/core/mmu/mmu.hpp +236 -0
  104. package/src/core/types.hpp +196 -0
  105. package/src/core/video/video.cpp +680 -0
  106. package/src/core/video/video.hpp +156 -0
  107. package/src/css/assembler-editor.css +1617 -0
  108. package/src/css/base.css +470 -0
  109. package/src/css/basic-debugger.css +791 -0
  110. package/src/css/basic-editor.css +792 -0
  111. package/src/css/controls.css +783 -0
  112. package/src/css/cpu-debugger.css +1413 -0
  113. package/src/css/debug-base.css +160 -0
  114. package/src/css/debug-windows.css +6455 -0
  115. package/src/css/disk-drives.css +406 -0
  116. package/src/css/documentation.css +392 -0
  117. package/src/css/file-explorer.css +867 -0
  118. package/src/css/hard-drive.css +180 -0
  119. package/src/css/layout.css +217 -0
  120. package/src/css/memory-windows.css +798 -0
  121. package/src/css/modals.css +510 -0
  122. package/src/css/monitor.css +425 -0
  123. package/src/css/release-notes.css +101 -0
  124. package/src/css/responsive.css +400 -0
  125. package/src/css/rule-builder.css +340 -0
  126. package/src/css/save-states.css +201 -0
  127. package/src/css/settings-windows.css +1231 -0
  128. package/src/css/window-switcher.css +150 -0
  129. package/src/js/agent/agent-manager.js +643 -0
  130. package/src/js/agent/agent-tools.js +293 -0
  131. package/src/js/agent/agent-version-tools.js +131 -0
  132. package/src/js/agent/assembler-tools.js +357 -0
  133. package/src/js/agent/basic-program-tools.js +894 -0
  134. package/src/js/agent/disk-tools.js +417 -0
  135. package/src/js/agent/file-explorer-tools.js +269 -0
  136. package/src/js/agent/index.js +13 -0
  137. package/src/js/agent/main-tools.js +222 -0
  138. package/src/js/agent/slot-tools.js +303 -0
  139. package/src/js/agent/smartport-tools.js +257 -0
  140. package/src/js/agent/window-tools.js +80 -0
  141. package/src/js/audio/audio-driver.js +417 -0
  142. package/src/js/audio/audio-worklet.js +85 -0
  143. package/src/js/audio/index.js +8 -0
  144. package/src/js/config/default-layout.js +34 -0
  145. package/src/js/config/version.js +8 -0
  146. package/src/js/data/apple2-rom-routines.js +577 -0
  147. package/src/js/debug/assembler-editor-window.js +2993 -0
  148. package/src/js/debug/basic-breakpoint-manager.js +529 -0
  149. package/src/js/debug/basic-program-parser.js +436 -0
  150. package/src/js/debug/basic-program-window.js +2594 -0
  151. package/src/js/debug/basic-variable-inspector.js +447 -0
  152. package/src/js/debug/breakpoint-manager.js +472 -0
  153. package/src/js/debug/cpu-debugger-window.js +2396 -0
  154. package/src/js/debug/index.js +22 -0
  155. package/src/js/debug/label-manager.js +238 -0
  156. package/src/js/debug/memory-browser-window.js +416 -0
  157. package/src/js/debug/memory-heat-map-window.js +481 -0
  158. package/src/js/debug/memory-map-window.js +206 -0
  159. package/src/js/debug/mockingboard-window.js +882 -0
  160. package/src/js/debug/mouse-card-window.js +355 -0
  161. package/src/js/debug/rule-builder-window.js +648 -0
  162. package/src/js/debug/soft-switch-window.js +458 -0
  163. package/src/js/debug/stack-viewer-window.js +221 -0
  164. package/src/js/debug/symbols.js +416 -0
  165. package/src/js/debug/trace-panel.js +291 -0
  166. package/src/js/debug/zero-page-watch-window.js +297 -0
  167. package/src/js/disk-manager/disk-drives-window.js +212 -0
  168. package/src/js/disk-manager/disk-operations.js +284 -0
  169. package/src/js/disk-manager/disk-persistence.js +301 -0
  170. package/src/js/disk-manager/disk-surface-renderer.js +388 -0
  171. package/src/js/disk-manager/drive-sounds.js +139 -0
  172. package/src/js/disk-manager/hard-drive-manager.js +481 -0
  173. package/src/js/disk-manager/hard-drive-persistence.js +187 -0
  174. package/src/js/disk-manager/hard-drive-window.js +57 -0
  175. package/src/js/disk-manager/index.js +890 -0
  176. package/src/js/display/display-settings-window.js +383 -0
  177. package/src/js/display/index.js +10 -0
  178. package/src/js/display/screen-window.js +342 -0
  179. package/src/js/display/webgl-renderer.js +705 -0
  180. package/src/js/file-explorer/disassembler.js +574 -0
  181. package/src/js/file-explorer/dos33.js +266 -0
  182. package/src/js/file-explorer/file-viewer.js +359 -0
  183. package/src/js/file-explorer/index.js +1261 -0
  184. package/src/js/file-explorer/prodos.js +549 -0
  185. package/src/js/file-explorer/utils.js +67 -0
  186. package/src/js/help/documentation-window.js +1096 -0
  187. package/src/js/help/index.js +10 -0
  188. package/src/js/help/release-notes-window.js +85 -0
  189. package/src/js/help/release-notes.js +612 -0
  190. package/src/js/input/gamepad-handler.js +176 -0
  191. package/src/js/input/index.js +12 -0
  192. package/src/js/input/input-handler.js +396 -0
  193. package/src/js/input/joystick-window.js +404 -0
  194. package/src/js/input/mouse-handler.js +99 -0
  195. package/src/js/input/text-selection.js +462 -0
  196. package/src/js/main.js +653 -0
  197. package/src/js/state/index.js +15 -0
  198. package/src/js/state/save-states-window.js +393 -0
  199. package/src/js/state/state-manager.js +409 -0
  200. package/src/js/state/state-persistence.js +218 -0
  201. package/src/js/ui/confirm.js +43 -0
  202. package/src/js/ui/disk-drive-positioner.js +347 -0
  203. package/src/js/ui/reminder-controller.js +129 -0
  204. package/src/js/ui/slot-configuration-window.js +560 -0
  205. package/src/js/ui/theme-manager.js +61 -0
  206. package/src/js/ui/toast.js +44 -0
  207. package/src/js/ui/ui-controller.js +897 -0
  208. package/src/js/ui/window-switcher.js +275 -0
  209. package/src/js/utils/basic-autocomplete.js +832 -0
  210. package/src/js/utils/basic-highlighting.js +473 -0
  211. package/src/js/utils/basic-tokenizer.js +153 -0
  212. package/src/js/utils/basic-tokens.js +117 -0
  213. package/src/js/utils/constants.js +28 -0
  214. package/src/js/utils/indexeddb-helper.js +225 -0
  215. package/src/js/utils/merlin-editor-support.js +905 -0
  216. package/src/js/utils/merlin-highlighting.js +551 -0
  217. package/src/js/utils/storage.js +125 -0
  218. package/src/js/utils/string-utils.js +19 -0
  219. package/src/js/utils/wasm-memory.js +54 -0
  220. package/src/js/windows/base-window.js +690 -0
  221. package/src/js/windows/index.js +9 -0
  222. package/src/js/windows/window-manager.js +375 -0
  223. package/tests/catch2/catch.hpp +17976 -0
  224. package/tests/common/basic_program_builder.cpp +119 -0
  225. package/tests/common/basic_program_builder.hpp +209 -0
  226. package/tests/common/disk_image_builder.cpp +444 -0
  227. package/tests/common/disk_image_builder.hpp +141 -0
  228. package/tests/common/test_helpers.hpp +118 -0
  229. package/tests/gcr/gcr-test.cpp +142 -0
  230. package/tests/integration/check-rom.js +70 -0
  231. package/tests/integration/compare-boot.js +239 -0
  232. package/tests/integration/crash-trace.js +102 -0
  233. package/tests/integration/disk-boot-test.js +264 -0
  234. package/tests/integration/memory-crash.js +108 -0
  235. package/tests/integration/nibble-read-test.js +249 -0
  236. package/tests/integration/phase-test.js +159 -0
  237. package/tests/integration/test_emulator.cpp +291 -0
  238. package/tests/integration/test_emulator_basic.cpp +91 -0
  239. package/tests/integration/test_emulator_debug.cpp +344 -0
  240. package/tests/integration/test_emulator_disk.cpp +153 -0
  241. package/tests/integration/test_emulator_state.cpp +163 -0
  242. package/tests/klaus/6502_functional_test.bin +0 -0
  243. package/tests/klaus/65C02_extended_opcodes_test.bin +0 -0
  244. package/tests/klaus/klaus_6502_test.cpp +184 -0
  245. package/tests/klaus/klaus_65c02_test.cpp +197 -0
  246. package/tests/thunderclock/thunderclock_mmu_test.cpp +304 -0
  247. package/tests/thunderclock/thunderclock_test.cpp +550 -0
  248. package/tests/unit/test_assembler.cpp +521 -0
  249. package/tests/unit/test_audio.cpp +196 -0
  250. package/tests/unit/test_ay8910.cpp +311 -0
  251. package/tests/unit/test_basic_detokenizer.cpp +265 -0
  252. package/tests/unit/test_basic_tokenizer.cpp +382 -0
  253. package/tests/unit/test_block_device.cpp +259 -0
  254. package/tests/unit/test_condition_evaluator.cpp +219 -0
  255. package/tests/unit/test_cpu6502.cpp +1301 -0
  256. package/tests/unit/test_cpu_addressing.cpp +361 -0
  257. package/tests/unit/test_cpu_cycle_counts.cpp +409 -0
  258. package/tests/unit/test_cpu_decimal.cpp +166 -0
  259. package/tests/unit/test_cpu_interrupts.cpp +285 -0
  260. package/tests/unit/test_disassembler.cpp +323 -0
  261. package/tests/unit/test_disk2_card.cpp +330 -0
  262. package/tests/unit/test_dos33.cpp +273 -0
  263. package/tests/unit/test_dsk_disk_image.cpp +315 -0
  264. package/tests/unit/test_expansion_card.cpp +178 -0
  265. package/tests/unit/test_gcr_encoding.cpp +232 -0
  266. package/tests/unit/test_keyboard.cpp +262 -0
  267. package/tests/unit/test_mmu.cpp +555 -0
  268. package/tests/unit/test_mmu_slots.cpp +323 -0
  269. package/tests/unit/test_mockingboard.cpp +352 -0
  270. package/tests/unit/test_mouse_card.cpp +386 -0
  271. package/tests/unit/test_pascal.cpp +248 -0
  272. package/tests/unit/test_prodos.cpp +259 -0
  273. package/tests/unit/test_smartport_card.cpp +321 -0
  274. package/tests/unit/test_thunderclock.cpp +354 -0
  275. package/tests/unit/test_via6522.cpp +323 -0
  276. package/tests/unit/test_video.cpp +319 -0
  277. package/tests/unit/test_woz_disk_image.cpp +257 -0
  278. package/vite.config.js +96 -0
  279. package/wiki/AI-Agent.md +372 -0
  280. package/wiki/Architecture-Overview.md +303 -0
  281. package/wiki/Audio-System.md +449 -0
  282. package/wiki/CPU-Emulation.md +477 -0
  283. package/wiki/Debugger.md +516 -0
  284. package/wiki/Disk-Drives.md +161 -0
  285. package/wiki/Disk-System-Internals.md +547 -0
  286. package/wiki/Display-Settings.md +88 -0
  287. package/wiki/Expansion-Slots.md +187 -0
  288. package/wiki/File-Explorer.md +259 -0
  289. package/wiki/Getting-Started.md +156 -0
  290. package/wiki/Home.md +69 -0
  291. package/wiki/Input-Devices.md +183 -0
  292. package/wiki/Keyboard-Shortcuts.md +158 -0
  293. package/wiki/Memory-System.md +364 -0
  294. package/wiki/Save-States.md +172 -0
  295. package/wiki/Video-Rendering.md +658 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Mike Daley
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,392 @@
1
+ # Apple //e Browser Based Emulator
2
+
3
+ A cycle-accurate Apple //e Enhanced emulator running in the browser using WebAssembly and WebGL. No JavaScript frameworks — vanilla ES6 modules with Vite for bundling. Having built native emulators in the past, this is my first attempt at a browser-based emulator, hopefully making it easier to allow cross platform users from making use of it :)
4
+
5
+ ## Features
6
+
7
+ - **Cycle-accurate 65C02 CPU** — All legal 6502 opcodes plus 65C02 extensions at 1.023 MHz
8
+ - **Full Apple //e memory architecture** — 128KB RAM (64KB main + 64KB auxiliary), language card, soft switches
9
+ - **Multiple display modes** — Text (40/80 col), LoRes, Double LoRes, HiRes, Double HiRes, monochrome
10
+ - **WebGL rendering** — Hardware-accelerated display with configurable CRT shader effects
11
+ - **Audio-driven timing** — Web Audio API AudioWorklet drives frame timing at 48kHz
12
+ - **Disk II controller** — DSK, DO, PO, and WOZ format support with write capability
13
+ - **Expansion cards** — Mockingboard sound card, Thunderclock Plus, Apple Mouse Interface Card, SmartPort hard drive
14
+ - **File explorer** — Browse DOS 3.3 and ProDOS disk contents with BASIC detokenizer and disassembler
15
+ - **Save states** — Autosave slot plus 5 manual save slots, stored in IndexedDB
16
+ - **Built-in debugger** — CPU debugger, memory browser, heat map, soft switch monitor, BASIC conditional breakpoints, and more
17
+ - **Light/Dark/System themes** — Switchable colour scheme with Apple rainbow logo accent palette
18
+ - **PWA support** — Install as a standalone app with offline functionality
19
+
20
+ ## Prerequisites
21
+
22
+ - [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html) (3.0+)
23
+ - CMake 3.20+
24
+ - Node.js 18+
25
+
26
+ ## ROM Files
27
+
28
+ Place the following ROM files in the `roms/` directory before building. ROMs are embedded into the WASM binary at compile time via `scripts/generate_roms.sh`.
29
+
30
+ | File | Size | Description |
31
+ |------|------|-------------|
32
+ | `342-0349-B-C0-FF.bin` | 16KB | Apple IIe system ROM |
33
+ | `342-0273-A-US-UK.bin` | 4KB | Character generator ROM (US/UK enhanced) |
34
+ | `341-0027.bin` | 256 bytes | Disk II controller ROM |
35
+ | `Thunderclock Plus ROM.bin` | 2KB | Thunderclock card ROM |
36
+ | `Apple Mouse Interface Card ROM - 342-0270-C.bin` | 2KB | Mouse Interface Card ROM |
37
+
38
+ An alternate character ROM variant `341-0160-A-US-UK.bin` (8KB) is also supported.
39
+
40
+ ## Building
41
+
42
+ ### Install Emscripten
43
+
44
+ ```bash
45
+ git clone https://github.com/emscripten-core/emsdk.git
46
+ cd emsdk
47
+ ./emsdk install latest
48
+ ./emsdk activate latest
49
+ source ./emsdk_env.sh
50
+ ```
51
+
52
+ ### Build and Run
53
+
54
+ ```bash
55
+ npm install # Install dependencies
56
+ npm run build:wasm # Build WASM module (required first time and after C++ changes)
57
+ npm run dev # Start dev server at localhost:3000 (hot-reload for JS only)
58
+ ```
59
+
60
+ Open http://localhost:3000 in your browser.
61
+
62
+ ### Other Commands
63
+
64
+ ```bash
65
+ npm run build # Full production build (WASM + Vite bundle)
66
+ npm run clean # Clean build artifacts
67
+ npm run deploy # Deploy to VPS via rsync
68
+ ```
69
+
70
+ ## Usage
71
+
72
+ ### Quick Start
73
+
74
+ 1. Click **Power** to start the emulator
75
+ 2. Click on the screen to give it keyboard focus
76
+ 3. Use **Insert** buttons to load disk images (DSK, DO, PO, WOZ)
77
+ 4. Type `PR#6` and press Return to boot from drive 1
78
+ 5. Or press **Ctrl+Reset** to enter Applesoft BASIC
79
+
80
+ ### Keyboard Mapping
81
+
82
+ | PC Key | Apple II |
83
+ |--------|----------|
84
+ | Backspace | Delete (left arrow) |
85
+ | Arrow Keys | Arrow Keys |
86
+ | Left Alt | Open Apple (joystick button 0) |
87
+ | Right Alt / Win | Closed Apple (joystick button 1) |
88
+ | Ctrl+Letter | Control characters |
89
+ | Escape | ESC |
90
+ | Enter | Return |
91
+ | Ctrl+Break | Reset (Ctrl+Reset) |
92
+
93
+ ### Keyboard Shortcuts
94
+
95
+ | Shortcut | Action |
96
+ |----------|--------|
97
+ | F1 | Open help and documentation |
98
+ | Ctrl+Escape | Toggle full-page mode |
99
+ | Ctrl+V | Paste text into keyboard buffer |
100
+ | Ctrl+` | Open window switcher |
101
+ | Option+Tab | Cycle to next window |
102
+ | Option+Shift+Tab | Cycle to previous window |
103
+
104
+ ### Text Selection
105
+
106
+ Click and drag on the screen to select text. The selection is automatically copied to the clipboard when you release the mouse.
107
+
108
+ ### Disk Drives
109
+
110
+ Each drive supports:
111
+ - **Insert** — Load a disk image from file
112
+ - **Recent** — Quick access to last 20 used disks (tracked per drive)
113
+ - **Blank** — Create a new formatted blank disk
114
+ - **Eject** — Remove disk (prompts to save if modified)
115
+
116
+ Drag and drop disk files directly onto drives. Drive seek and motor sounds can be toggled on or off.
117
+
118
+ ### File Explorer
119
+
120
+ Browse the contents of inserted disks:
121
+ - **DOS 3.3** — Catalog listing with file type icons (Text, Integer BASIC, Applesoft BASIC, Binary, etc.)
122
+ - **ProDOS** — Folder navigation with full ProDOS file type support
123
+ - **File viewer** — View files as hex, BASIC listing (detokenized), or disassembly
124
+ - **Disassembler** — Recursive descent flow analysis with symbol resolution
125
+
126
+ ### Save States
127
+
128
+ - **Autosave** — Saves every 5 seconds while running (enabled by default)
129
+ - **5 manual slots** — Save and restore at any time from the Save States window
130
+ - State includes CPU registers, 128KB RAM, language card, soft switches, disk images with modifications, filenames, and debugger state
131
+ - Stored in browser IndexedDB
132
+
133
+ ### Display Settings
134
+
135
+ The display settings window provides configurable CRT shader effects:
136
+
137
+ - Screen curvature, scanlines, shadow mask
138
+ - Phosphor glow, vignette, NTSC fringing
139
+ - Flicker, static noise, jitter, horizontal sync lines
140
+ - Brightness, contrast, saturation
141
+ - Sharp pixels toggle, overscan/border control
142
+ - Monochrome modes: Green, Amber, White
143
+
144
+ ### Expansion Cards
145
+
146
+ Cards are configured via **View > Expansion Slots**.
147
+
148
+ | Slot | Default | Available Cards |
149
+ |------|---------|-----------------|
150
+ | 1 | Empty | — |
151
+ | 2 | Empty | — |
152
+ | 3 | 80-Column | Built-in (fixed) |
153
+ | 4 | Mockingboard | Mouse Card, Empty |
154
+ | 5 | Thunderclock Plus | Empty |
155
+ | 6 | Disk II | Empty |
156
+ | 7 | Empty | Thunderclock Plus |
157
+
158
+ **Mockingboard** — Dual AY-3-8910 sound chips with VIA 6522 timers. Stereo output with per-channel mute controls. All audio (speaker, Mockingboard, drive sounds) is unified under a single volume slider and mute toggle.
159
+
160
+ **Thunderclock Plus** — ProDOS-compatible real-time clock card.
161
+
162
+ **Apple Mouse Interface Card** — Mouse input via MC6821 PIA command protocol.
163
+
164
+ ### Joystick & Game Controllers
165
+
166
+ A floating joystick window provides visual paddle/joystick controls that map to the Apple II game ports ($C064-$C067). Physical game controllers are supported via the Gamepad API — the left stick maps to paddle values and buttons A/B map to Apple II buttons 0/1, with a configurable deadzone.
167
+
168
+ ## Architecture
169
+
170
+ ```
171
+ +---------------------------------------------+
172
+ | Browser Environment |
173
+ |---------------------------------------------|
174
+ | WebGL Renderer | Web Audio | IndexedDB |
175
+ |---------------------------------------------|
176
+ | JavaScript Layer (ES6) |
177
+ | +-------------------------------------+ |
178
+ | | Emulator | DiskManager | Debugger | |
179
+ | | Display | FileExplorer| SaveStates | |
180
+ | +-------------------------------------+ |
181
+ |---------------------------------------------|
182
+ | WebAssembly Module (C++) |
183
+ | +------+-----+-------+------+--------+ |
184
+ | | CPU | MMU | Video | Audio| Disk II| |
185
+ | |65C02 |128KB| | | | |
186
+ | +------+-----+-------+------+--------+ |
187
+ | |
188
+ | +-------+------------+-------+-------+ |
189
+ | | Cards | Filesystem | BASIC | Disasm| |
190
+ | +-------+------------+-------+-------+ |
191
+ +---------------------------------------------+
192
+ ```
193
+
194
+ ### Audio-Driven Timing
195
+
196
+ The emulator uses Web Audio API to drive timing:
197
+
198
+ 1. AudioWorklet requests samples at 48kHz
199
+ 2. WASM runs CPU for ~21.3 cycles per audio sample
200
+ 3. Speaker toggle events ($C030) generate the audio waveform
201
+ 4. Video frame rendered when cycle count crosses ~17,030 cycles (60 Hz)
202
+
203
+ This ensures consistent emulation speed, no audio drift, and operation even when the browser tab is backgrounded.
204
+
205
+ ### WASM Interface
206
+
207
+ Single global `Emulator` instance in C++ (`wasm_interface.cpp`). JavaScript allocates WASM heap memory with `_malloc`/`_free` and uses `stringToUTF8()`/`UTF8ToString()` for string conversion. New WASM exports must be added to the `EXPORTED_FUNCTIONS` list in `CMakeLists.txt`.
208
+
209
+ ## Debug Tools
210
+
211
+ All debug windows are accessible from the **Debug** menu.
212
+
213
+ | Tool | Description |
214
+ |------|-------------|
215
+ | **CPU Debugger** | Registers (REGS, FLAGS, TIMING, BEAM sections), breakpoints, step/over/out, disassembly with symbols |
216
+ | **Memory Browser** | Full 128KB hex/ASCII view with search |
217
+ | **Memory Heat Map** | Real-time memory access visualization (read/write/combined) |
218
+ | **Memory Map** | Address space layout overview |
219
+ | **Stack Viewer** | Monitor stack page ($0100-$01FF) |
220
+ | **Zero Page Watch** | Monitor zero page locations with predefined and custom watches |
221
+ | **Soft Switch Monitor** | Apple II soft switch states ($C000-$C0FF) |
222
+ | **Mockingboard** | Unified channel-centric view: AY-3-8910 and VIA registers, inline waveforms, level meters, per-channel mute controls |
223
+ | **Mouse Card** | PIA registers, position, mode, interrupt state |
224
+ | **Rule Builder** | Complex conditional breakpoints with C-style expressions |
225
+
226
+ The CPU debugger supports breakpoints (conditional with expression evaluation), watchpoints, beam breakpoints (video position with wildcard-scanline support), execution tracing, and a call stack viewer. Labels and symbols are supported for both system routines and user-defined addresses. Debugger state (breakpoints, watches, settings) persists across save/load.
227
+
228
+ ## Dev Tools
229
+
230
+ Development tools are accessible from the **Dev** menu.
231
+
232
+ | Tool | Description |
233
+ |------|-------------|
234
+ | **BASIC Program** | Write, edit, and paste Applesoft BASIC programs with syntax highlighting, autocomplete, line heat map, trace toggle, statement-level breakpoints, variable inspector, and run/stop/pause/step controls |
235
+ | **Assembler** | Full 65C02 assembler with Merlin-style syntax, live validation, ROM routines reference, breakpoint support, and file save/load |
236
+
237
+ ### Assembler Features
238
+
239
+ - **Syntax highlighting** for opcodes, directives, labels, operands, and comments
240
+ - **Column guides** for Merlin's column-based format (Label, Opcode, Operand, Comment)
241
+ - **Live validation** with inline error messages
242
+ - **ROM Routines Reference** (F2) — searchable database of Apple II ROM routines with insert capability
243
+ - **Breakpoints** — click gutter or press F9 to toggle breakpoints on instruction lines
244
+ - **File operations** — New, Open, Save with Ctrl/Cmd+N/O/S shortcuts
245
+ - **Symbols panel** — view all defined labels and their addresses
246
+ - **Hex output** — view assembled machine code bytes
247
+
248
+ ## Testing
249
+
250
+ ### CPU Compliance Tests
251
+
252
+ Klaus Dormann's 6502/65C02 functional test suites:
253
+
254
+ ```bash
255
+ mkdir -p build-native && cd build-native
256
+ cmake ..
257
+ make -j$(sysctl -n hw.ncpu)
258
+ ctest --verbose
259
+ ```
260
+
261
+ Test executables: `klaus_6502_test` (NMOS 6502), `klaus_65c02_test` (65C02 extended opcodes).
262
+
263
+ ### Thunderclock Tests
264
+
265
+ Native C++ tests for Thunderclock card emulation, including MMU integration:
266
+
267
+ ```bash
268
+ # Built and run via the same native CMake build above
269
+ ```
270
+
271
+ ### GCR Encoding Tests
272
+
273
+ Native C++ tests for Group Code Recording disk encoding logic.
274
+
275
+ ### Integration Tests
276
+
277
+ JavaScript tests for disk boot, memory, and debugging:
278
+
279
+ ```bash
280
+ node tests/integration/disk-boot-test.js
281
+ ```
282
+
283
+ ## Project Structure
284
+
285
+ ```
286
+ web-a2e/
287
+ ├── src/
288
+ │ ├── core/ # C++ emulator core (namespace a2e::)
289
+ │ │ ├── cpu/ # 65C02 CPU emulation
290
+ │ │ ├── mmu/ # Memory management, soft switches
291
+ │ │ ├── video/ # Per-scanline video rendering
292
+ │ │ ├── audio/ # Speaker emulation
293
+ │ │ ├── disk-image/ # Disk formats (DSK/DO/PO/WOZ), GCR encoding
294
+ │ │ ├── disassembler/ # 65C02 disassembler
295
+ │ │ ├── input/ # Keyboard handling
296
+ │ │ ├── cards/ # Expansion card system
297
+ │ │ │ └── mockingboard/ # AY-3-8910 + VIA 6522
298
+ │ │ ├── filesystem/ # DOS 3.3 and ProDOS parsers
299
+ │ │ ├── basic/ # BASIC detokenizer
300
+ │ │ ├── assembler/ # 65C02 assembler (Merlin-style syntax)
301
+ │ │ ├── debug/ # Condition evaluator
302
+ │ │ ├── emulator.cpp # Core coordinator, state serialization
303
+ │ │ └── types.hpp # Shared constants
304
+ │ ├── bindings/ # wasm_interface.cpp (WASM exports)
305
+ │ └── js/ # ES6 modules
306
+ │ ├── main.js # AppleIIeEmulator entry point
307
+ │ ├── audio/ # Web Audio API driver and AudioWorklet
308
+ │ ├── config/ # App version
309
+ │ ├── debug/ # Debug window implementations
310
+ │ ├── disk-manager/ # Drive UI, persistence, surface renderer, sounds
311
+ │ ├── display/ # WebGL renderer, CRT shaders, display settings
312
+ │ ├── file-explorer/ # DOS 3.3/ProDOS browser, file viewer, disassembler
313
+ │ ├── help/ # Documentation and release notes
314
+ │ ├── input/ # Keyboard, text selection, joystick, mouse
315
+ │ ├── state/ # Save state manager and persistence
316
+ │ ├── ui/ # Menu wiring, reminders, slot configuration
317
+ │ ├── utils/ # Storage, string, BASIC utilities
318
+ │ └── windows/ # Base window class and window manager
319
+ ├── public/ # Static assets, built WASM, shaders
320
+ │ ├── css/ # Stylesheets
321
+ │ ├── shaders/ # CRT vertex/fragment shaders
322
+ │ ├── assets/ # Images and sounds
323
+ │ └── index.html # Main HTML entry point
324
+ ├── roms/ # ROM files (not included)
325
+ ├── tests/
326
+ │ ├── klaus/ # Klaus Dormann CPU compliance tests
327
+ │ ├── thunderclock/ # Thunderclock card tests
328
+ │ ├── integration/ # JS integration tests
329
+ │ └── gcr/ # GCR encoding tests
330
+ ├── scripts/ # Build scripts (generate_roms.sh)
331
+ ├── CMakeLists.txt # C++ build configuration
332
+ ├── vite.config.js # Vite bundler configuration
333
+ └── package.json
334
+ ```
335
+
336
+ ## Development Workflow
337
+
338
+ **C++ changes** require rebuilding WASM: `npm run build:wasm`
339
+
340
+ **JavaScript changes** auto-reload via the Vite dev server.
341
+
342
+ **Full build** for production: `npm run build` (outputs to `dist/`).
343
+
344
+ ## Browser Compatibility
345
+
346
+ Requires WebAssembly, WebGL 2.0, Web Audio API (AudioWorklet), IndexedDB, and Service Worker support. Works in current versions of Chrome, Firefox, Safari, and Edge.
347
+
348
+ ## TODO
349
+
350
+ ### Expansion Cards
351
+ - **Microsoft Softcard (Z80)** — Z80 co-processor card for running CP/M software
352
+ - **Super Serial Card** — RS-232 serial interface for printer and modem emulation
353
+ - **Parallel Printer Card** — Centronics parallel port for printing to file/PDF
354
+
355
+ ### Input
356
+ - **Configurable key bindings** — Allow remapping of Apple II keys and shortcuts
357
+
358
+ ### Disk & Storage
359
+ - **Improved WOZ copy protection compatibility** — Better support for timing-sensitive copy protection schemes (quarter-track stepping, weak/flux bits, cross-track sync)
360
+ - **2IMG format support** — Universal disk image format with metadata
361
+
362
+ ### Development Tools
363
+ - **Source-level debugging** — Step through assembly source with symbol mapping from assembler
364
+ - **Profiler** — Cycle-accurate performance profiling with per-routine breakdown and heat maps
365
+ - **I/O trace log** — Record and replay soft switch and card I/O activity
366
+
367
+ ### Audio
368
+ - **Mockingboard speech synthesis** — SC-01 Votrax speech chip emulation
369
+ - **SAM speech synthesizer** — Software Automatic Mouth support
370
+
371
+ ### Display
372
+ - **Video recording** — Capture emulator screen to video file
373
+ - **Screenshot export** — Save screen contents as PNG
374
+
375
+ ### Networking
376
+ - **Uthernet / Ethernet emulation** — TCP/IP networking via WebSocket bridge for Contiki, etc.
377
+
378
+ ### Platform
379
+ - **Disk image library** — Browse and load from a curated online software archive
380
+ - **URL disk loading** — Load disk images directly from a URL parameter
381
+ - **Mobile touch controls** — On-screen keyboard and virtual joystick optimized for touch devices
382
+
383
+ ## License
384
+
385
+ MIT License. See [LICENSE](LICENSE) for details.
386
+
387
+ ## Acknowledgments
388
+
389
+ - Based on the native [a2e](https://github.com/mikedaley/a2e) emulator
390
+ - CPU emulation derived from [MOS6502](https://github.com/mikedaley/MOS6502)
391
+ - Klaus Dormann's [6502 functional tests](https://github.com/Klaus2m5/6502_65C02_functional_tests)
392
+ - Inspired by [AppleWin](https://github.com/AppleWin/AppleWin) and [Apple2TS](https://github.com/nickmcummins/apple2ts), both outstanding Apple II emulators that have been invaluable references for hardware accuracy and feature direction