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.
- package/.clangd +5 -0
- package/.mcp.json +12 -0
- package/CLAUDE.md +362 -0
- package/CMakeLists.txt +774 -0
- package/LICENSE +21 -0
- package/README.md +392 -0
- package/build-wasm/generated/roms.cpp +2447 -0
- package/docker-compose.staging.yml +9 -0
- package/docs/basic-rom-disassembly.md +6663 -0
- package/docs/softswitch-comparison.md +273 -0
- package/docs/thunderclock-debug.md +89 -0
- package/examples/cube.bas +72 -0
- package/examples/hello.s +55 -0
- package/examples/scroll.s +140 -0
- package/package.json +18 -0
- package/public/assets/apple-logo-old.png +0 -0
- package/public/assets/apple-logo.png +0 -0
- package/public/assets/drive-closed-light-on.png +0 -0
- package/public/assets/drive-closed.png +0 -0
- package/public/assets/drive-open-light-on.png +0 -0
- package/public/assets/drive-open.png +0 -0
- package/public/audio-worklet.js +82 -0
- package/public/disks/Apple DOS 3.3 January 1983.dsk +0 -0
- package/public/disks/ProDOS 2.4.3.po +0 -0
- package/public/disks/h32mb.2mg +0 -0
- package/public/disks/library.json +26 -0
- package/public/docs/llms/llm-assembler.txt +90 -0
- package/public/docs/llms/llm-basic-program.txt +256 -0
- package/public/docs/llms/llm-disk-drives.txt +72 -0
- package/public/docs/llms/llm-file-explorer.txt +50 -0
- package/public/docs/llms/llm-hard-drives.txt +80 -0
- package/public/docs/llms/llm-main.txt +51 -0
- package/public/docs/llms/llm-slot-configuration.txt +66 -0
- package/public/icons/icon-192.svg +4 -0
- package/public/icons/icon-512.svg +4 -0
- package/public/index.html +661 -0
- package/public/llms.txt +49 -0
- package/public/manifest.json +29 -0
- package/public/shaders/burnin.glsl +22 -0
- package/public/shaders/crt.glsl +706 -0
- package/public/shaders/edge.glsl +109 -0
- package/public/shaders/vertex.glsl +8 -0
- package/public/sw.js +186 -0
- package/roms/341-0027.bin +0 -0
- package/roms/341-0160-A-US-UK.bin +0 -0
- package/roms/341-0160-A.bin +0 -0
- package/roms/342-0273-A-US-UK.bin +0 -0
- package/roms/342-0349-B-C0-FF.bin +0 -0
- package/roms/Apple Mouse Interface Card ROM - 342-0270-C.bin +0 -0
- package/roms/Thunderclock Plus ROM.bin +0 -0
- package/scripts/generate_roms.sh +69 -0
- package/src/bindings/wasm_interface.cpp +1940 -0
- package/src/core/assembler/assembler.cpp +1239 -0
- package/src/core/assembler/assembler.hpp +115 -0
- package/src/core/audio/audio.cpp +160 -0
- package/src/core/audio/audio.hpp +81 -0
- package/src/core/basic/basic_detokenizer.cpp +436 -0
- package/src/core/basic/basic_detokenizer.hpp +41 -0
- package/src/core/basic/basic_tokenizer.cpp +286 -0
- package/src/core/basic/basic_tokenizer.hpp +26 -0
- package/src/core/basic/basic_tokens.hpp +295 -0
- package/src/core/cards/disk2_card.cpp +568 -0
- package/src/core/cards/disk2_card.hpp +316 -0
- package/src/core/cards/expansion_card.hpp +185 -0
- package/src/core/cards/mockingboard/ay8910.cpp +616 -0
- package/src/core/cards/mockingboard/ay8910.hpp +159 -0
- package/src/core/cards/mockingboard/via6522.cpp +530 -0
- package/src/core/cards/mockingboard/via6522.hpp +163 -0
- package/src/core/cards/mockingboard_card.cpp +312 -0
- package/src/core/cards/mockingboard_card.hpp +159 -0
- package/src/core/cards/mouse_card.cpp +654 -0
- package/src/core/cards/mouse_card.hpp +190 -0
- package/src/core/cards/smartport/block_device.cpp +202 -0
- package/src/core/cards/smartport/block_device.hpp +60 -0
- package/src/core/cards/smartport/smartport_card.cpp +603 -0
- package/src/core/cards/smartport/smartport_card.hpp +120 -0
- package/src/core/cards/thunderclock_card.cpp +237 -0
- package/src/core/cards/thunderclock_card.hpp +122 -0
- package/src/core/cpu/cpu6502.cpp +1609 -0
- package/src/core/cpu/cpu6502.hpp +203 -0
- package/src/core/debug/condition_evaluator.cpp +470 -0
- package/src/core/debug/condition_evaluator.hpp +87 -0
- package/src/core/disassembler/disassembler.cpp +552 -0
- package/src/core/disassembler/disassembler.hpp +171 -0
- package/src/core/disk-image/disk_image.hpp +267 -0
- package/src/core/disk-image/dsk_disk_image.cpp +827 -0
- package/src/core/disk-image/dsk_disk_image.hpp +204 -0
- package/src/core/disk-image/gcr_encoding.cpp +147 -0
- package/src/core/disk-image/gcr_encoding.hpp +78 -0
- package/src/core/disk-image/woz_disk_image.cpp +1049 -0
- package/src/core/disk-image/woz_disk_image.hpp +343 -0
- package/src/core/emulator.cpp +2126 -0
- package/src/core/emulator.hpp +434 -0
- package/src/core/filesystem/dos33.cpp +178 -0
- package/src/core/filesystem/dos33.hpp +66 -0
- package/src/core/filesystem/pascal.cpp +262 -0
- package/src/core/filesystem/pascal.hpp +87 -0
- package/src/core/filesystem/prodos.cpp +369 -0
- package/src/core/filesystem/prodos.hpp +119 -0
- package/src/core/input/keyboard.cpp +227 -0
- package/src/core/input/keyboard.hpp +111 -0
- package/src/core/mmu/mmu.cpp +1387 -0
- package/src/core/mmu/mmu.hpp +236 -0
- package/src/core/types.hpp +196 -0
- package/src/core/video/video.cpp +680 -0
- package/src/core/video/video.hpp +156 -0
- package/src/css/assembler-editor.css +1617 -0
- package/src/css/base.css +470 -0
- package/src/css/basic-debugger.css +791 -0
- package/src/css/basic-editor.css +792 -0
- package/src/css/controls.css +783 -0
- package/src/css/cpu-debugger.css +1413 -0
- package/src/css/debug-base.css +160 -0
- package/src/css/debug-windows.css +6455 -0
- package/src/css/disk-drives.css +406 -0
- package/src/css/documentation.css +392 -0
- package/src/css/file-explorer.css +867 -0
- package/src/css/hard-drive.css +180 -0
- package/src/css/layout.css +217 -0
- package/src/css/memory-windows.css +798 -0
- package/src/css/modals.css +510 -0
- package/src/css/monitor.css +425 -0
- package/src/css/release-notes.css +101 -0
- package/src/css/responsive.css +400 -0
- package/src/css/rule-builder.css +340 -0
- package/src/css/save-states.css +201 -0
- package/src/css/settings-windows.css +1231 -0
- package/src/css/window-switcher.css +150 -0
- package/src/js/agent/agent-manager.js +643 -0
- package/src/js/agent/agent-tools.js +293 -0
- package/src/js/agent/agent-version-tools.js +131 -0
- package/src/js/agent/assembler-tools.js +357 -0
- package/src/js/agent/basic-program-tools.js +894 -0
- package/src/js/agent/disk-tools.js +417 -0
- package/src/js/agent/file-explorer-tools.js +269 -0
- package/src/js/agent/index.js +13 -0
- package/src/js/agent/main-tools.js +222 -0
- package/src/js/agent/slot-tools.js +303 -0
- package/src/js/agent/smartport-tools.js +257 -0
- package/src/js/agent/window-tools.js +80 -0
- package/src/js/audio/audio-driver.js +417 -0
- package/src/js/audio/audio-worklet.js +85 -0
- package/src/js/audio/index.js +8 -0
- package/src/js/config/default-layout.js +34 -0
- package/src/js/config/version.js +8 -0
- package/src/js/data/apple2-rom-routines.js +577 -0
- package/src/js/debug/assembler-editor-window.js +2993 -0
- package/src/js/debug/basic-breakpoint-manager.js +529 -0
- package/src/js/debug/basic-program-parser.js +436 -0
- package/src/js/debug/basic-program-window.js +2594 -0
- package/src/js/debug/basic-variable-inspector.js +447 -0
- package/src/js/debug/breakpoint-manager.js +472 -0
- package/src/js/debug/cpu-debugger-window.js +2396 -0
- package/src/js/debug/index.js +22 -0
- package/src/js/debug/label-manager.js +238 -0
- package/src/js/debug/memory-browser-window.js +416 -0
- package/src/js/debug/memory-heat-map-window.js +481 -0
- package/src/js/debug/memory-map-window.js +206 -0
- package/src/js/debug/mockingboard-window.js +882 -0
- package/src/js/debug/mouse-card-window.js +355 -0
- package/src/js/debug/rule-builder-window.js +648 -0
- package/src/js/debug/soft-switch-window.js +458 -0
- package/src/js/debug/stack-viewer-window.js +221 -0
- package/src/js/debug/symbols.js +416 -0
- package/src/js/debug/trace-panel.js +291 -0
- package/src/js/debug/zero-page-watch-window.js +297 -0
- package/src/js/disk-manager/disk-drives-window.js +212 -0
- package/src/js/disk-manager/disk-operations.js +284 -0
- package/src/js/disk-manager/disk-persistence.js +301 -0
- package/src/js/disk-manager/disk-surface-renderer.js +388 -0
- package/src/js/disk-manager/drive-sounds.js +139 -0
- package/src/js/disk-manager/hard-drive-manager.js +481 -0
- package/src/js/disk-manager/hard-drive-persistence.js +187 -0
- package/src/js/disk-manager/hard-drive-window.js +57 -0
- package/src/js/disk-manager/index.js +890 -0
- package/src/js/display/display-settings-window.js +383 -0
- package/src/js/display/index.js +10 -0
- package/src/js/display/screen-window.js +342 -0
- package/src/js/display/webgl-renderer.js +705 -0
- package/src/js/file-explorer/disassembler.js +574 -0
- package/src/js/file-explorer/dos33.js +266 -0
- package/src/js/file-explorer/file-viewer.js +359 -0
- package/src/js/file-explorer/index.js +1261 -0
- package/src/js/file-explorer/prodos.js +549 -0
- package/src/js/file-explorer/utils.js +67 -0
- package/src/js/help/documentation-window.js +1096 -0
- package/src/js/help/index.js +10 -0
- package/src/js/help/release-notes-window.js +85 -0
- package/src/js/help/release-notes.js +612 -0
- package/src/js/input/gamepad-handler.js +176 -0
- package/src/js/input/index.js +12 -0
- package/src/js/input/input-handler.js +396 -0
- package/src/js/input/joystick-window.js +404 -0
- package/src/js/input/mouse-handler.js +99 -0
- package/src/js/input/text-selection.js +462 -0
- package/src/js/main.js +653 -0
- package/src/js/state/index.js +15 -0
- package/src/js/state/save-states-window.js +393 -0
- package/src/js/state/state-manager.js +409 -0
- package/src/js/state/state-persistence.js +218 -0
- package/src/js/ui/confirm.js +43 -0
- package/src/js/ui/disk-drive-positioner.js +347 -0
- package/src/js/ui/reminder-controller.js +129 -0
- package/src/js/ui/slot-configuration-window.js +560 -0
- package/src/js/ui/theme-manager.js +61 -0
- package/src/js/ui/toast.js +44 -0
- package/src/js/ui/ui-controller.js +897 -0
- package/src/js/ui/window-switcher.js +275 -0
- package/src/js/utils/basic-autocomplete.js +832 -0
- package/src/js/utils/basic-highlighting.js +473 -0
- package/src/js/utils/basic-tokenizer.js +153 -0
- package/src/js/utils/basic-tokens.js +117 -0
- package/src/js/utils/constants.js +28 -0
- package/src/js/utils/indexeddb-helper.js +225 -0
- package/src/js/utils/merlin-editor-support.js +905 -0
- package/src/js/utils/merlin-highlighting.js +551 -0
- package/src/js/utils/storage.js +125 -0
- package/src/js/utils/string-utils.js +19 -0
- package/src/js/utils/wasm-memory.js +54 -0
- package/src/js/windows/base-window.js +690 -0
- package/src/js/windows/index.js +9 -0
- package/src/js/windows/window-manager.js +375 -0
- package/tests/catch2/catch.hpp +17976 -0
- package/tests/common/basic_program_builder.cpp +119 -0
- package/tests/common/basic_program_builder.hpp +209 -0
- package/tests/common/disk_image_builder.cpp +444 -0
- package/tests/common/disk_image_builder.hpp +141 -0
- package/tests/common/test_helpers.hpp +118 -0
- package/tests/gcr/gcr-test.cpp +142 -0
- package/tests/integration/check-rom.js +70 -0
- package/tests/integration/compare-boot.js +239 -0
- package/tests/integration/crash-trace.js +102 -0
- package/tests/integration/disk-boot-test.js +264 -0
- package/tests/integration/memory-crash.js +108 -0
- package/tests/integration/nibble-read-test.js +249 -0
- package/tests/integration/phase-test.js +159 -0
- package/tests/integration/test_emulator.cpp +291 -0
- package/tests/integration/test_emulator_basic.cpp +91 -0
- package/tests/integration/test_emulator_debug.cpp +344 -0
- package/tests/integration/test_emulator_disk.cpp +153 -0
- package/tests/integration/test_emulator_state.cpp +163 -0
- package/tests/klaus/6502_functional_test.bin +0 -0
- package/tests/klaus/65C02_extended_opcodes_test.bin +0 -0
- package/tests/klaus/klaus_6502_test.cpp +184 -0
- package/tests/klaus/klaus_65c02_test.cpp +197 -0
- package/tests/thunderclock/thunderclock_mmu_test.cpp +304 -0
- package/tests/thunderclock/thunderclock_test.cpp +550 -0
- package/tests/unit/test_assembler.cpp +521 -0
- package/tests/unit/test_audio.cpp +196 -0
- package/tests/unit/test_ay8910.cpp +311 -0
- package/tests/unit/test_basic_detokenizer.cpp +265 -0
- package/tests/unit/test_basic_tokenizer.cpp +382 -0
- package/tests/unit/test_block_device.cpp +259 -0
- package/tests/unit/test_condition_evaluator.cpp +219 -0
- package/tests/unit/test_cpu6502.cpp +1301 -0
- package/tests/unit/test_cpu_addressing.cpp +361 -0
- package/tests/unit/test_cpu_cycle_counts.cpp +409 -0
- package/tests/unit/test_cpu_decimal.cpp +166 -0
- package/tests/unit/test_cpu_interrupts.cpp +285 -0
- package/tests/unit/test_disassembler.cpp +323 -0
- package/tests/unit/test_disk2_card.cpp +330 -0
- package/tests/unit/test_dos33.cpp +273 -0
- package/tests/unit/test_dsk_disk_image.cpp +315 -0
- package/tests/unit/test_expansion_card.cpp +178 -0
- package/tests/unit/test_gcr_encoding.cpp +232 -0
- package/tests/unit/test_keyboard.cpp +262 -0
- package/tests/unit/test_mmu.cpp +555 -0
- package/tests/unit/test_mmu_slots.cpp +323 -0
- package/tests/unit/test_mockingboard.cpp +352 -0
- package/tests/unit/test_mouse_card.cpp +386 -0
- package/tests/unit/test_pascal.cpp +248 -0
- package/tests/unit/test_prodos.cpp +259 -0
- package/tests/unit/test_smartport_card.cpp +321 -0
- package/tests/unit/test_thunderclock.cpp +354 -0
- package/tests/unit/test_via6522.cpp +323 -0
- package/tests/unit/test_video.cpp +319 -0
- package/tests/unit/test_woz_disk_image.cpp +257 -0
- package/vite.config.js +96 -0
- package/wiki/AI-Agent.md +372 -0
- package/wiki/Architecture-Overview.md +303 -0
- package/wiki/Audio-System.md +449 -0
- package/wiki/CPU-Emulation.md +477 -0
- package/wiki/Debugger.md +516 -0
- package/wiki/Disk-Drives.md +161 -0
- package/wiki/Disk-System-Internals.md +547 -0
- package/wiki/Display-Settings.md +88 -0
- package/wiki/Expansion-Slots.md +187 -0
- package/wiki/File-Explorer.md +259 -0
- package/wiki/Getting-Started.md +156 -0
- package/wiki/Home.md +69 -0
- package/wiki/Input-Devices.md +183 -0
- package/wiki/Keyboard-Shortcuts.md +158 -0
- package/wiki/Memory-System.md +364 -0
- package/wiki/Save-States.md +172 -0
- 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
|