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
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* mmu.hpp - Memory management unit with soft switches
|
|
3
|
+
*
|
|
4
|
+
* Written by
|
|
5
|
+
* Mike Daley <michael_daley@icloud.com>
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "../types.hpp"
|
|
11
|
+
#include <array>
|
|
12
|
+
#include <cstdint>
|
|
13
|
+
#include <functional>
|
|
14
|
+
#include <memory>
|
|
15
|
+
|
|
16
|
+
namespace a2e {
|
|
17
|
+
|
|
18
|
+
// Forward declaration
|
|
19
|
+
class ExpansionCard;
|
|
20
|
+
|
|
21
|
+
class MMU {
|
|
22
|
+
public:
|
|
23
|
+
using KeyboardCallback = std::function<uint8_t()>;
|
|
24
|
+
using KeyStrobeCallback = std::function<void()>;
|
|
25
|
+
using AnyKeyDownCallback = std::function<bool()>; // Returns true if any key is currently held
|
|
26
|
+
using SpeakerCallback = std::function<void()>;
|
|
27
|
+
using ButtonCallback = std::function<uint8_t(int)>; // Returns button state for button 0-2
|
|
28
|
+
using CycleCallback = std::function<uint64_t()>; // Returns current CPU cycle count
|
|
29
|
+
using VideoSwitchCallback = std::function<void()>; // Called when video-relevant switches change
|
|
30
|
+
using WatchpointReadCallback = std::function<void(uint16_t, uint8_t)>;
|
|
31
|
+
using WatchpointWriteCallback = std::function<void(uint16_t, uint8_t)>;
|
|
32
|
+
|
|
33
|
+
MMU();
|
|
34
|
+
~MMU(); // Defined in mmu.cpp (needed for unique_ptr<ExpansionCard>)
|
|
35
|
+
|
|
36
|
+
// Memory access
|
|
37
|
+
uint8_t read(uint16_t address);
|
|
38
|
+
void write(uint16_t address, uint8_t value);
|
|
39
|
+
|
|
40
|
+
// Non-side-effecting read for debugger/memory viewer
|
|
41
|
+
uint8_t peek(uint16_t address) const;
|
|
42
|
+
|
|
43
|
+
// Non-side-effecting read of auxiliary memory (for text selection in 80-col mode)
|
|
44
|
+
uint8_t peekAux(uint16_t address) const;
|
|
45
|
+
|
|
46
|
+
// Direct memory access (bypasses soft switches)
|
|
47
|
+
uint8_t readRAM(uint16_t address, bool aux = false) const;
|
|
48
|
+
void writeRAM(uint16_t address, uint8_t value, bool aux = false);
|
|
49
|
+
|
|
50
|
+
// Language card RAM access (for state serialization)
|
|
51
|
+
const uint8_t *getLCBank1(bool aux = false) const {
|
|
52
|
+
return aux ? auxLcBank1_.data() : lcBank1_.data();
|
|
53
|
+
}
|
|
54
|
+
const uint8_t *getLCBank2(bool aux = false) const {
|
|
55
|
+
return aux ? auxLcBank2_.data() : lcBank2_.data();
|
|
56
|
+
}
|
|
57
|
+
const uint8_t *getLCHighRAM(bool aux = false) const {
|
|
58
|
+
return aux ? auxLcHighRAM_.data() : lcHighRAM_.data();
|
|
59
|
+
}
|
|
60
|
+
void setLCBank1(const uint8_t *data, bool aux = false) {
|
|
61
|
+
auto &bank = aux ? auxLcBank1_ : lcBank1_;
|
|
62
|
+
std::copy(data, data + bank.size(), bank.begin());
|
|
63
|
+
}
|
|
64
|
+
void setLCBank2(const uint8_t *data, bool aux = false) {
|
|
65
|
+
auto &bank = aux ? auxLcBank2_ : lcBank2_;
|
|
66
|
+
std::copy(data, data + bank.size(), bank.begin());
|
|
67
|
+
}
|
|
68
|
+
void setLCHighRAM(const uint8_t *data, bool aux = false) {
|
|
69
|
+
auto &bank = aux ? auxLcHighRAM_ : lcHighRAM_;
|
|
70
|
+
std::copy(data, data + bank.size(), bank.begin());
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ROM loading - combined 16KB system ROM ($C000-$FFFF)
|
|
74
|
+
void loadROM(const uint8_t *systemRom, size_t systemSize,
|
|
75
|
+
const uint8_t *charRom, size_t charSize);
|
|
76
|
+
|
|
77
|
+
// Character ROM access (for video)
|
|
78
|
+
uint8_t readCharROM(uint16_t address) const;
|
|
79
|
+
|
|
80
|
+
// Soft switch state
|
|
81
|
+
const SoftSwitches &getSoftSwitches() const { return switches_; }
|
|
82
|
+
|
|
83
|
+
// Callbacks
|
|
84
|
+
void setKeyboardCallback(KeyboardCallback cb) {
|
|
85
|
+
keyboardCallback_ = std::move(cb);
|
|
86
|
+
}
|
|
87
|
+
void setKeyStrobeCallback(KeyStrobeCallback cb) {
|
|
88
|
+
keyStrobeCallback_ = std::move(cb);
|
|
89
|
+
}
|
|
90
|
+
void setAnyKeyDownCallback(AnyKeyDownCallback cb) {
|
|
91
|
+
anyKeyDownCallback_ = std::move(cb);
|
|
92
|
+
}
|
|
93
|
+
void setSpeakerCallback(SpeakerCallback cb) {
|
|
94
|
+
speakerCallback_ = std::move(cb);
|
|
95
|
+
}
|
|
96
|
+
void setButtonCallback(ButtonCallback cb) { buttonCallback_ = std::move(cb); }
|
|
97
|
+
void setCycleCallback(CycleCallback cb) { cycleCallback_ = std::move(cb); }
|
|
98
|
+
void setVideoSwitchCallback(VideoSwitchCallback cb) { videoSwitchCallback_ = std::move(cb); }
|
|
99
|
+
void setWatchpointCallbacks(WatchpointReadCallback readCb, WatchpointWriteCallback writeCb) {
|
|
100
|
+
watchpointReadCallback_ = std::move(readCb);
|
|
101
|
+
watchpointWriteCallback_ = std::move(writeCb);
|
|
102
|
+
}
|
|
103
|
+
void setWatchpointsActive(bool active) { watchpointsActive_ = active; }
|
|
104
|
+
|
|
105
|
+
// Paddle/joystick input
|
|
106
|
+
void setPaddleValue(int paddle, uint8_t value) {
|
|
107
|
+
if (paddle >= 0 && paddle < 4) {
|
|
108
|
+
paddleValues_[paddle] = value;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
uint8_t getPaddleValue(int paddle) const {
|
|
112
|
+
return (paddle >= 0 && paddle < 4) ? paddleValues_[paddle] : 128;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
// ===== Expansion Slot Management =====
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Insert a card into an expansion slot
|
|
120
|
+
* @param slot Slot number (1-7)
|
|
121
|
+
* @param card Card to insert (ownership transferred)
|
|
122
|
+
* @return Previously installed card, or nullptr if slot was empty
|
|
123
|
+
*/
|
|
124
|
+
std::unique_ptr<ExpansionCard> insertCard(uint8_t slot, std::unique_ptr<ExpansionCard> card);
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Remove a card from an expansion slot
|
|
128
|
+
* @param slot Slot number (1-7)
|
|
129
|
+
* @return The removed card, or nullptr if slot was empty
|
|
130
|
+
*/
|
|
131
|
+
std::unique_ptr<ExpansionCard> removeCard(uint8_t slot);
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get a card from a slot (non-owning)
|
|
135
|
+
* @param slot Slot number (1-7)
|
|
136
|
+
* @return Pointer to card, or nullptr if slot is empty
|
|
137
|
+
*/
|
|
138
|
+
ExpansionCard* getCard(uint8_t slot) const;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Check if a slot is empty
|
|
142
|
+
* @param slot Slot number (1-7)
|
|
143
|
+
* @return true if no card is installed
|
|
144
|
+
*/
|
|
145
|
+
bool isSlotEmpty(uint8_t slot) const;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Get which slot's expansion ROM is active
|
|
149
|
+
* @return Active slot (1-7), or 0 if none
|
|
150
|
+
*/
|
|
151
|
+
uint8_t getActiveExpansionSlot() const { return activeExpansionSlot_; }
|
|
152
|
+
|
|
153
|
+
// Reset
|
|
154
|
+
void reset();
|
|
155
|
+
void warmReset(); // Reset soft switches and cards, preserve RAM
|
|
156
|
+
|
|
157
|
+
// Memory access tracking for debugger heat map
|
|
158
|
+
void enableTracking(bool enable) { trackingEnabled_ = enable; }
|
|
159
|
+
bool isTrackingEnabled() const { return trackingEnabled_; }
|
|
160
|
+
void clearTracking();
|
|
161
|
+
void decayTracking(uint8_t amount = 1); // Reduce all counts for real-time visualization
|
|
162
|
+
const uint8_t* getReadCounts() const { return readCounts_.data(); }
|
|
163
|
+
const uint8_t* getWriteCounts() const { return writeCounts_.data(); }
|
|
164
|
+
|
|
165
|
+
// Direct memory array access for heat map visualization
|
|
166
|
+
const uint8_t* getMainRAM() const { return mainRAM_.data(); }
|
|
167
|
+
const uint8_t* getAuxRAM() const { return auxRAM_.data(); }
|
|
168
|
+
const uint8_t* getSystemROM() const { return systemROM_.data(); }
|
|
169
|
+
|
|
170
|
+
private:
|
|
171
|
+
// Soft switch handling
|
|
172
|
+
uint8_t readSoftSwitch(uint16_t address);
|
|
173
|
+
uint8_t peekSoftSwitch(uint16_t address) const;
|
|
174
|
+
void writeSoftSwitch(uint16_t address, uint8_t value);
|
|
175
|
+
|
|
176
|
+
// Floating bus - returns value video hardware is currently reading
|
|
177
|
+
uint8_t getFloatingBusValue();
|
|
178
|
+
|
|
179
|
+
// Language card logic
|
|
180
|
+
uint8_t readLanguageCard(uint16_t address);
|
|
181
|
+
void writeLanguageCard(uint16_t address, uint8_t value);
|
|
182
|
+
uint8_t handleLanguageCardSwitch(uint8_t reg);
|
|
183
|
+
void handleLanguageCardSwitchWrite(uint8_t reg);
|
|
184
|
+
|
|
185
|
+
// Memory banks
|
|
186
|
+
std::array<uint8_t, MAIN_RAM_SIZE> mainRAM_{};
|
|
187
|
+
std::array<uint8_t, AUX_RAM_SIZE> auxRAM_{};
|
|
188
|
+
|
|
189
|
+
// Language card RAM banks
|
|
190
|
+
std::array<uint8_t, 0x1000> lcBank1_{}; // $D000-$DFFF bank 1
|
|
191
|
+
std::array<uint8_t, 0x1000> lcBank2_{}; // $D000-$DFFF bank 2
|
|
192
|
+
std::array<uint8_t, 0x2000> lcHighRAM_{}; // $E000-$FFFF
|
|
193
|
+
|
|
194
|
+
// Auxiliary language card banks
|
|
195
|
+
std::array<uint8_t, 0x1000> auxLcBank1_{};
|
|
196
|
+
std::array<uint8_t, 0x1000> auxLcBank2_{};
|
|
197
|
+
std::array<uint8_t, 0x2000> auxLcHighRAM_{};
|
|
198
|
+
|
|
199
|
+
// ROM - combined 16KB system ROM ($C000-$FFFF)
|
|
200
|
+
std::array<uint8_t, 0x4000> systemROM_{}; // $C000-$FFFF (16KB)
|
|
201
|
+
std::array<uint8_t, CHAR_ROM_SIZE> charROM_{};
|
|
202
|
+
|
|
203
|
+
// Soft switches
|
|
204
|
+
SoftSwitches switches_;
|
|
205
|
+
|
|
206
|
+
// Keyboard state
|
|
207
|
+
uint8_t keyboardLatch_ = 0;
|
|
208
|
+
|
|
209
|
+
// Paddle/joystick state
|
|
210
|
+
std::array<uint8_t, 4> paddleValues_ = {128, 128, 128, 128}; // Centered by default
|
|
211
|
+
uint64_t paddleTriggerCycle_ = 0;
|
|
212
|
+
static constexpr int PADDLE_CYCLES_PER_UNIT = 11; // ~11 cycles per paddle unit
|
|
213
|
+
|
|
214
|
+
// Callbacks
|
|
215
|
+
KeyboardCallback keyboardCallback_;
|
|
216
|
+
KeyStrobeCallback keyStrobeCallback_;
|
|
217
|
+
AnyKeyDownCallback anyKeyDownCallback_;
|
|
218
|
+
SpeakerCallback speakerCallback_;
|
|
219
|
+
ButtonCallback buttonCallback_;
|
|
220
|
+
CycleCallback cycleCallback_;
|
|
221
|
+
VideoSwitchCallback videoSwitchCallback_;
|
|
222
|
+
WatchpointReadCallback watchpointReadCallback_;
|
|
223
|
+
WatchpointWriteCallback watchpointWriteCallback_;
|
|
224
|
+
bool watchpointsActive_ = false;
|
|
225
|
+
|
|
226
|
+
// Expansion slots (1-7, index 0-6)
|
|
227
|
+
std::array<std::unique_ptr<ExpansionCard>, 7> slots_;
|
|
228
|
+
uint8_t activeExpansionSlot_ = 0; // Which card owns $C800-$CFFF (0 = none)
|
|
229
|
+
|
|
230
|
+
// Memory access tracking for debugger heat map
|
|
231
|
+
bool trackingEnabled_ = false;
|
|
232
|
+
std::array<uint8_t, 65536> readCounts_{};
|
|
233
|
+
std::array<uint8_t, 65536> writeCounts_{};
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
} // namespace a2e
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* types.hpp - Shared constants, types, and color palettes for the Apple IIe emulator
|
|
3
|
+
*
|
|
4
|
+
* Written by
|
|
5
|
+
* Mike Daley <michael_daley@icloud.com>
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <array>
|
|
11
|
+
#include <cstddef>
|
|
12
|
+
#include <cstdint>
|
|
13
|
+
#include <functional>
|
|
14
|
+
|
|
15
|
+
namespace a2e {
|
|
16
|
+
|
|
17
|
+
// Memory size constants
|
|
18
|
+
constexpr size_t MAIN_RAM_SIZE = 64 * 1024; // 64KB main RAM
|
|
19
|
+
constexpr size_t AUX_RAM_SIZE = 64 * 1024; // 64KB auxiliary RAM
|
|
20
|
+
constexpr size_t ROM_SIZE = 16 * 1024; // 16KB ROM ($C000-$FFFF)
|
|
21
|
+
constexpr size_t CHAR_ROM_SIZE = 8 * 1024; // 8KB character ROM (US + UK sets)
|
|
22
|
+
constexpr size_t DISK_ROM_SIZE = 256; // 256 bytes Disk II ROM
|
|
23
|
+
|
|
24
|
+
// Display constants
|
|
25
|
+
constexpr int SCREEN_WIDTH = 560; // 280 * 2 for double-width pixels
|
|
26
|
+
constexpr int SCREEN_HEIGHT = 384; // 192 * 2 for double-height pixels
|
|
27
|
+
constexpr int FRAMEBUFFER_SIZE = SCREEN_WIDTH * SCREEN_HEIGHT * 4; // RGBA
|
|
28
|
+
|
|
29
|
+
// Timing constants
|
|
30
|
+
constexpr double CPU_CLOCK_HZ = 1023000.0; // 1.023 MHz
|
|
31
|
+
constexpr int AUDIO_SAMPLE_RATE = 48000;
|
|
32
|
+
constexpr double CYCLES_PER_SAMPLE =
|
|
33
|
+
CPU_CLOCK_HZ / AUDIO_SAMPLE_RATE; // ~21.3125
|
|
34
|
+
|
|
35
|
+
constexpr int CYCLES_PER_SCANLINE = 65;
|
|
36
|
+
constexpr int SCANLINES_PER_FRAME = 262;
|
|
37
|
+
constexpr int CYCLES_PER_FRAME =
|
|
38
|
+
CYCLES_PER_SCANLINE * SCANLINES_PER_FRAME; // 17030
|
|
39
|
+
|
|
40
|
+
// Video mode flags
|
|
41
|
+
enum class VideoMode : uint8_t {
|
|
42
|
+
TEXT_40 = 0,
|
|
43
|
+
TEXT_80,
|
|
44
|
+
LORES,
|
|
45
|
+
HIRES,
|
|
46
|
+
DOUBLE_LORES,
|
|
47
|
+
DOUBLE_HIRES
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Soft switch state - comprehensive Apple IIe soft switches
|
|
51
|
+
struct SoftSwitches {
|
|
52
|
+
// Display switches ($C050-$C057)
|
|
53
|
+
bool text = true; // $C050/$C051: TEXT/GRAPHICS mode
|
|
54
|
+
bool mixed = false; // $C052/$C053: Mixed mode (4 lines text at bottom)
|
|
55
|
+
bool page2 = false; // $C054/$C055: PAGE1/PAGE2
|
|
56
|
+
bool hires = false; // $C056/$C057: LORES/HIRES
|
|
57
|
+
|
|
58
|
+
// 80-column switches ($C00C-$C00F)
|
|
59
|
+
bool col80 = false; // $C00C/$C00D: 40/80 column mode
|
|
60
|
+
bool altCharSet = false; // $C00E/$C00F: Primary/alternate character set
|
|
61
|
+
|
|
62
|
+
// Memory switches ($C000-$C00B)
|
|
63
|
+
bool store80 = false; // $C000/$C001: 80STORE
|
|
64
|
+
bool ramrd = false; // $C002/$C003: RAMRD - aux RAM read
|
|
65
|
+
bool ramwrt = false; // $C004/$C005: RAMWRT - aux RAM write
|
|
66
|
+
bool intcxrom = false; // $C006/$C007: INTCXROM - internal slot ROM
|
|
67
|
+
bool altzp = false; // $C008/$C009: ALTZP - aux zero page/stack
|
|
68
|
+
bool slotc3rom = false; // $C00A/$C00B: SLOTC3ROM - slot 3 ROM
|
|
69
|
+
bool intc8rom = false; // Internal $C800-$CFFF ROM active
|
|
70
|
+
|
|
71
|
+
// Language card ($C080-$C08F)
|
|
72
|
+
bool lcram = false; // LC RAM enabled for read
|
|
73
|
+
bool lcram2 = false; // LC RAM bank 2
|
|
74
|
+
bool lcwrite = false; // LC RAM write-enabled
|
|
75
|
+
bool lcprewrite = false; // LC pre-write state
|
|
76
|
+
|
|
77
|
+
// Annunciators ($C058-$C05F)
|
|
78
|
+
bool an0 = false; // $C058/$C059: Annunciator 0
|
|
79
|
+
bool an1 = false; // $C05A/$C05B: Annunciator 1
|
|
80
|
+
bool an2 = false; // $C05C/$C05D: Annunciator 2
|
|
81
|
+
bool an3 = false; // $C05E/$C05F: Annunciator 3 (DHIRES control)
|
|
82
|
+
|
|
83
|
+
// I/O state (read-only status)
|
|
84
|
+
bool vblBar = false; // $C019: Vertical blank (true = in VBL)
|
|
85
|
+
|
|
86
|
+
// Button states ($C061-$C063)
|
|
87
|
+
bool button0 = false; // $C061: Open Apple / Button 0
|
|
88
|
+
bool button1 = false; // $C062: Closed Apple / Button 1
|
|
89
|
+
bool button2 = false; // $C063: Button 2 / Shift key state
|
|
90
|
+
|
|
91
|
+
// Keyboard
|
|
92
|
+
uint8_t keyLatch = 0; // $C000: Keyboard latch (bit 7 = key available)
|
|
93
|
+
bool keyStrobe = false; // $C010: Keyboard strobe (key available)
|
|
94
|
+
|
|
95
|
+
// Paddle/Joystick
|
|
96
|
+
uint8_t paddle0 = 128; // $C064: PDL0 value (0-255, 128 = center)
|
|
97
|
+
uint8_t paddle1 = 128; // $C065: PDL1 value
|
|
98
|
+
uint8_t paddle2 = 128; // $C066: PDL2 value
|
|
99
|
+
uint8_t paddle3 = 128; // $C067: PDL3 value
|
|
100
|
+
|
|
101
|
+
// Cassette (stub)
|
|
102
|
+
bool cassetteOut = false; // $C020: Cassette output
|
|
103
|
+
bool cassetteIn = false; // $C060: Cassette input
|
|
104
|
+
|
|
105
|
+
// IOU / DHIRES
|
|
106
|
+
bool ioudis = false; // $C07E/$C07F: IOU disable (IIc specific)
|
|
107
|
+
bool dhires = false; // Double hi-res mode (AN3 off + 80COL + HIRES)
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Disk drive state
|
|
111
|
+
struct DriveState {
|
|
112
|
+
bool motorOn = false;
|
|
113
|
+
bool writeMode = false;
|
|
114
|
+
int currentTrack = 0; // 0-34
|
|
115
|
+
int currentPhase = 0; // Stepper motor phase
|
|
116
|
+
int headPosition = 0; // Bit position on track
|
|
117
|
+
uint8_t dataLatch = 0;
|
|
118
|
+
bool diskInserted = false;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// CPU status flags are defined in cpu/cpu6502.hpp
|
|
122
|
+
|
|
123
|
+
// Color palette for Apple II
|
|
124
|
+
constexpr std::array<uint32_t, 16> LORES_COLORS = {{
|
|
125
|
+
0xFF000000, // 0: Black
|
|
126
|
+
0xFFE31E60, // 1: Magenta
|
|
127
|
+
0xFF604EBD, // 2: Dark Blue
|
|
128
|
+
0xFFFF44FD, // 3: Purple
|
|
129
|
+
0xFF00A360, // 4: Dark Green
|
|
130
|
+
0xFF9C9C9C, // 5: Grey 1
|
|
131
|
+
0xFF14CFFD, // 6: Medium Blue
|
|
132
|
+
0xFFD0C3FF, // 7: Light Blue
|
|
133
|
+
0xFF607203, // 8: Brown
|
|
134
|
+
0xFFFF6A3C, // 9: Orange
|
|
135
|
+
0xFF9C9C9C, // 10: Grey 2
|
|
136
|
+
0xFFFFA0D0, // 11: Pink
|
|
137
|
+
0xFF14F53C, // 12: Light Green
|
|
138
|
+
0xFFD0DD8D, // 13: Yellow
|
|
139
|
+
0xFF72FFD0, // 14: Aqua
|
|
140
|
+
0xFFFFFFFF // 15: White
|
|
141
|
+
}};
|
|
142
|
+
|
|
143
|
+
// HiRes artifact colors (NTSC-accurate values)
|
|
144
|
+
// Group 1 (high bit = 0): Black, Green, Violet, White
|
|
145
|
+
// Group 2 (high bit = 1): Black, Orange, Blue, White
|
|
146
|
+
constexpr std::array<uint32_t, 6> HIRES_COLORS = {{
|
|
147
|
+
0xFF000000, // 0: Black
|
|
148
|
+
0xFF14F53C, // 1: Green (odd pixels, high bit = 0)
|
|
149
|
+
0xFFFF44FD, // 2: Violet (even pixels, high bit = 0)
|
|
150
|
+
0xFFFFFFFF, // 3: White
|
|
151
|
+
0xFF14CFFD, // 4: Blue (even pixels, high bit = 1)
|
|
152
|
+
0xFFFF6A3C // 5: Orange (odd pixels, high bit = 1)
|
|
153
|
+
}};
|
|
154
|
+
|
|
155
|
+
// Double Lo-Res / Double Hi-Res color palette
|
|
156
|
+
// Different from Lo-Res due to 14MHz dot rate vs 7MHz (changes NTSC phase
|
|
157
|
+
// relationship) Based on AppleWin's DoubleHiresPalIndex mapping See:
|
|
158
|
+
// https://github.com/AppleWin/AppleWin/blob/master/source/RGBMonitor.cpp
|
|
159
|
+
constexpr std::array<uint32_t, 16> DLGR_COLORS = {{
|
|
160
|
+
0xFF000000, // 0: Black (LORES[0])
|
|
161
|
+
0xFF604EBD, // 1: Dark Blue (LORES[2])
|
|
162
|
+
0xFF00A360, // 2: Dark Green (LORES[4])
|
|
163
|
+
0xFF14CFFD, // 3: Medium Blue (LORES[6])
|
|
164
|
+
0xFF607203, // 4: Brown (LORES[8])
|
|
165
|
+
0xFF9C9C9C, // 5: Grey (LORES[10])
|
|
166
|
+
0xFF14F53C, // 6: Light Green (LORES[12])
|
|
167
|
+
0xFF72FFD0, // 7: Aqua (LORES[14])
|
|
168
|
+
0xFFE31E60, // 8: Magenta (LORES[1])
|
|
169
|
+
0xFFFF44FD, // 9: Purple (LORES[3])
|
|
170
|
+
0xFF9C9C9C, // 10: Grey (LORES[5])
|
|
171
|
+
0xFFD0C3FF, // 11: Light Blue (LORES[7])
|
|
172
|
+
0xFFFF6A3C, // 12: Orange (LORES[9])
|
|
173
|
+
0xFFFFA0D0, // 13: Pink (LORES[11])
|
|
174
|
+
0xFFD0DD8D, // 14: Yellow (LORES[13])
|
|
175
|
+
0xFFFFFFFF // 15: White (LORES[15])
|
|
176
|
+
}};
|
|
177
|
+
|
|
178
|
+
// Snapshot of video-relevant soft switch state for per-scanline rendering
|
|
179
|
+
struct VideoSwitchState {
|
|
180
|
+
bool text;
|
|
181
|
+
bool mixed;
|
|
182
|
+
bool page2;
|
|
183
|
+
bool hires;
|
|
184
|
+
bool col80;
|
|
185
|
+
bool altCharSet;
|
|
186
|
+
bool store80;
|
|
187
|
+
bool an3;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Records a video switch change at a specific cycle within a frame
|
|
191
|
+
struct VideoSwitchChange {
|
|
192
|
+
uint32_t cycleOffset; // Cycle offset from frame start
|
|
193
|
+
VideoSwitchState state; // Full snapshot after the change
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
} // namespace a2e
|