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,357 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* assembler-tools.js - Assembler window tools
|
|
3
|
+
*
|
|
4
|
+
* Written by
|
|
5
|
+
* Shawn Bullock <shawn@agenticexpert.ai>
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const assemblerTools = {
|
|
9
|
+
/**
|
|
10
|
+
* Assemble the current source code
|
|
11
|
+
*/
|
|
12
|
+
asmAssemble: async (args) => {
|
|
13
|
+
const windowManager = window.emulator?.windowManager;
|
|
14
|
+
if (!windowManager) {
|
|
15
|
+
throw new Error("Window manager not available");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const asmWindow = windowManager.getWindow("assembler-editor");
|
|
19
|
+
if (!asmWindow) {
|
|
20
|
+
throw new Error("Assembler window not found");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
asmWindow.doAssemble();
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
success: true,
|
|
27
|
+
message: "Assembly completed",
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Write assembled code into emulator memory
|
|
33
|
+
*/
|
|
34
|
+
asmWrite: async (args) => {
|
|
35
|
+
const windowManager = window.emulator?.windowManager;
|
|
36
|
+
if (!windowManager) {
|
|
37
|
+
throw new Error("Window manager not available");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const asmWindow = windowManager.getWindow("assembler-editor");
|
|
41
|
+
if (!asmWindow) {
|
|
42
|
+
throw new Error("Assembler window not found");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
asmWindow.doLoad();
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
success: true,
|
|
49
|
+
message: "Assembled code written to memory",
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Load example program into the editor
|
|
55
|
+
*/
|
|
56
|
+
asmLoadExample: async (args) => {
|
|
57
|
+
const windowManager = window.emulator?.windowManager;
|
|
58
|
+
if (!windowManager) {
|
|
59
|
+
throw new Error("Window manager not available");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const asmWindow = windowManager.getWindow("assembler-editor");
|
|
63
|
+
if (!asmWindow) {
|
|
64
|
+
throw new Error("Assembler window not found");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
asmWindow.loadExample();
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
success: true,
|
|
71
|
+
message: "Example program loaded into editor",
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Clear editor and start new file
|
|
77
|
+
* Emulates the newFile() method without confirmation dialog
|
|
78
|
+
*/
|
|
79
|
+
asmNew: async (args) => {
|
|
80
|
+
const windowManager = window.emulator?.windowManager;
|
|
81
|
+
if (!windowManager) {
|
|
82
|
+
throw new Error("Window manager not available");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const asmWindow = windowManager.getWindow("assembler-editor");
|
|
86
|
+
if (!asmWindow) {
|
|
87
|
+
throw new Error("Assembler window not found");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Emulate newFile() behavior without confirmation
|
|
91
|
+
if (asmWindow.textarea) {
|
|
92
|
+
asmWindow.textarea.value = "";
|
|
93
|
+
asmWindow.currentFileName = null;
|
|
94
|
+
asmWindow._fileHandle = null;
|
|
95
|
+
asmWindow.updateTitle("Assembler");
|
|
96
|
+
asmWindow.updateHighlighting();
|
|
97
|
+
asmWindow.updateGutter();
|
|
98
|
+
asmWindow.errors.clear();
|
|
99
|
+
asmWindow.syntaxErrors.clear();
|
|
100
|
+
asmWindow.clearOutputPanels();
|
|
101
|
+
asmWindow.setStatus("", true);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
success: true,
|
|
106
|
+
message: "Assembler editor cleared",
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get current assembly source code from editor
|
|
112
|
+
*/
|
|
113
|
+
asmGet: async (args) => {
|
|
114
|
+
const windowManager = window.emulator?.windowManager;
|
|
115
|
+
if (!windowManager) {
|
|
116
|
+
throw new Error("Window manager not available");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const asmWindow = windowManager.getWindow("assembler-editor");
|
|
120
|
+
if (!asmWindow) {
|
|
121
|
+
throw new Error("Assembler window not found");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const text = asmWindow.textarea ? asmWindow.textarea.value : "";
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
success: true,
|
|
128
|
+
source: text,
|
|
129
|
+
lines: text ? text.split("\n").length : 0,
|
|
130
|
+
message: "Assembly source retrieved",
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Set assembly source code in editor (replace entire content)
|
|
136
|
+
*/
|
|
137
|
+
asmSet: async (args) => {
|
|
138
|
+
const { source } = args;
|
|
139
|
+
|
|
140
|
+
if (source === undefined) {
|
|
141
|
+
throw new Error("source parameter is required");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const windowManager = window.emulator?.windowManager;
|
|
145
|
+
if (!windowManager) {
|
|
146
|
+
throw new Error("Window manager not available");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const asmWindow = windowManager.getWindow("assembler-editor");
|
|
150
|
+
if (!asmWindow) {
|
|
151
|
+
throw new Error("Assembler window not found");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (asmWindow.textarea) {
|
|
155
|
+
asmWindow.textarea.value = source;
|
|
156
|
+
asmWindow.updateHighlighting();
|
|
157
|
+
asmWindow.validateAllLines();
|
|
158
|
+
asmWindow.encodeAllLineBytes();
|
|
159
|
+
asmWindow.updateGutter();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
success: true,
|
|
164
|
+
message: "Assembly source set",
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get assembly source content from editor (used with save file MCP tool)
|
|
170
|
+
*/
|
|
171
|
+
saveAsmInEditorToLocal: async (args) => {
|
|
172
|
+
const windowManager = window.emulator?.windowManager;
|
|
173
|
+
if (!windowManager) {
|
|
174
|
+
throw new Error("Window manager not available");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const asmWindow = windowManager.getWindow("assembler-editor");
|
|
178
|
+
if (!asmWindow) {
|
|
179
|
+
throw new Error("Assembler window not found");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const content = asmWindow.textarea ? asmWindow.textarea.value : "";
|
|
183
|
+
if (!content.trim()) {
|
|
184
|
+
throw new Error("No source code in editor to save");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
success: true,
|
|
189
|
+
content: content,
|
|
190
|
+
lines: content.split("\n").length,
|
|
191
|
+
message: "Assembly source content retrieved from editor",
|
|
192
|
+
};
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Get assembly status, origin address, and size
|
|
197
|
+
*/
|
|
198
|
+
asmGetStatus: async (args) => {
|
|
199
|
+
const windowManager = window.emulator?.windowManager;
|
|
200
|
+
if (!windowManager) {
|
|
201
|
+
throw new Error("Window manager not available");
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const asmWindow = windowManager.getWindow("assembler-editor");
|
|
205
|
+
if (!asmWindow) {
|
|
206
|
+
throw new Error("Assembler window not found");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const statusText = asmWindow.statusSpan
|
|
210
|
+
? asmWindow.statusSpan.textContent
|
|
211
|
+
: "";
|
|
212
|
+
const statusClass = asmWindow.statusSpan
|
|
213
|
+
? asmWindow.statusSpan.className
|
|
214
|
+
: "";
|
|
215
|
+
const isError = statusClass.includes("asm-status-error");
|
|
216
|
+
const origin = asmWindow.lastOrigin || 0;
|
|
217
|
+
const size = asmWindow.lastAssembledSize || 0;
|
|
218
|
+
|
|
219
|
+
// Determine status: none if no assembly, error if failed, ok if successful
|
|
220
|
+
let status;
|
|
221
|
+
if (!statusText.trim() || size === 0) {
|
|
222
|
+
status = "none";
|
|
223
|
+
} else if (isError) {
|
|
224
|
+
status = "error";
|
|
225
|
+
} else {
|
|
226
|
+
status = "ok";
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
success: true,
|
|
231
|
+
status: status,
|
|
232
|
+
statusText: statusText,
|
|
233
|
+
origin: origin,
|
|
234
|
+
originHex: "$" + origin.toString(16).toUpperCase().padStart(4, "0"),
|
|
235
|
+
size: size,
|
|
236
|
+
message: "Assembly status retrieved",
|
|
237
|
+
};
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Execute code at a specific address (like monitor's G command)
|
|
242
|
+
* Sets PC to address and optionally resumes execution
|
|
243
|
+
*/
|
|
244
|
+
directExecuteAssemblyAt: async (args) => {
|
|
245
|
+
const { paused = false, addr } = args;
|
|
246
|
+
|
|
247
|
+
const emulator = window.emulator;
|
|
248
|
+
if (!emulator) {
|
|
249
|
+
throw new Error("Emulator not available");
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const windowManager = emulator.windowManager;
|
|
253
|
+
if (!windowManager) {
|
|
254
|
+
throw new Error("Window manager not available");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const wasmModule = emulator.wasmModule;
|
|
258
|
+
if (!wasmModule) {
|
|
259
|
+
throw new Error("WASM module not available");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Determine address to execute
|
|
263
|
+
let address;
|
|
264
|
+
if (addr !== undefined) {
|
|
265
|
+
// Support hex ($xxxx or 0xXXXX) or decimal
|
|
266
|
+
if (typeof addr === "string") {
|
|
267
|
+
const trimmed = addr.trim();
|
|
268
|
+
if (trimmed.startsWith("$")) {
|
|
269
|
+
address = parseInt(trimmed.substring(1), 16);
|
|
270
|
+
} else if (trimmed.toLowerCase().startsWith("0x")) {
|
|
271
|
+
address = parseInt(trimmed, 16);
|
|
272
|
+
} else {
|
|
273
|
+
address = parseInt(trimmed, 10);
|
|
274
|
+
}
|
|
275
|
+
} else {
|
|
276
|
+
address = addr;
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
// Use origin from last successful assembly
|
|
280
|
+
const asmWindow = windowManager.getWindow("assembler-editor");
|
|
281
|
+
if (!asmWindow) {
|
|
282
|
+
throw new Error("Assembler window not found");
|
|
283
|
+
}
|
|
284
|
+
address = asmWindow.lastOrigin || 0;
|
|
285
|
+
if (address === 0) {
|
|
286
|
+
throw new Error(
|
|
287
|
+
"No address specified and no assembled program origin available",
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Pause first to ensure clean state
|
|
293
|
+
wasmModule._setPaused(true);
|
|
294
|
+
|
|
295
|
+
// Push return address onto stack if specified
|
|
296
|
+
const { returnTo = "auto" } = args;
|
|
297
|
+
let returnAddr = null;
|
|
298
|
+
if (returnTo !== undefined) {
|
|
299
|
+
const NAMED_RETURNS = {
|
|
300
|
+
"monitor": 0xFF69,
|
|
301
|
+
"basic": 0xE003,
|
|
302
|
+
"auto": wasmModule._getPC(),
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
if (typeof returnTo === "string") {
|
|
306
|
+
const lower = returnTo.trim().toLowerCase();
|
|
307
|
+
if (NAMED_RETURNS[lower] !== undefined) {
|
|
308
|
+
returnAddr = NAMED_RETURNS[lower];
|
|
309
|
+
} else if (returnTo.trim().startsWith("$")) {
|
|
310
|
+
returnAddr = parseInt(returnTo.trim().substring(1), 16);
|
|
311
|
+
} else if (returnTo.trim().toLowerCase().startsWith("0x")) {
|
|
312
|
+
returnAddr = parseInt(returnTo.trim(), 16);
|
|
313
|
+
} else {
|
|
314
|
+
returnAddr = parseInt(returnTo.trim(), 10);
|
|
315
|
+
}
|
|
316
|
+
} else {
|
|
317
|
+
returnAddr = returnTo;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (isNaN(returnAddr)) {
|
|
321
|
+
throw new Error(`Invalid returnTo address: ${returnTo}`);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// RTS pops address and adds 1, so push (returnAddr - 1)
|
|
325
|
+
const rtsAddr = (returnAddr - 1) & 0xFFFF;
|
|
326
|
+
const sp = wasmModule._getSP();
|
|
327
|
+
wasmModule._writeMemory(0x0100 + sp, (rtsAddr >> 8) & 0xFF);
|
|
328
|
+
wasmModule._writeMemory(0x0100 + ((sp - 1) & 0xFF), rtsAddr & 0xFF);
|
|
329
|
+
wasmModule._setRegSP((sp - 2) & 0xFF);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Set PC to target address
|
|
333
|
+
wasmModule._setRegPC(address);
|
|
334
|
+
|
|
335
|
+
// Set final paused state: true = stay paused, false = resume execution
|
|
336
|
+
wasmModule._setPaused(paused);
|
|
337
|
+
|
|
338
|
+
const addrHex = "$" + address.toString(16).toUpperCase().padStart(4, "0");
|
|
339
|
+
const returnHex = returnAddr !== null
|
|
340
|
+
? "$" + returnAddr.toString(16).toUpperCase().padStart(4, "0")
|
|
341
|
+
: null;
|
|
342
|
+
const returnMsg = returnHex ? `, return to ${returnHex}` : "";
|
|
343
|
+
const statusMsg = paused
|
|
344
|
+
? `PC set to ${addrHex} (paused${returnMsg})`
|
|
345
|
+
: `Executing at ${addrHex}${returnMsg}`;
|
|
346
|
+
|
|
347
|
+
return {
|
|
348
|
+
success: true,
|
|
349
|
+
address: address,
|
|
350
|
+
addressHex: addrHex,
|
|
351
|
+
returnTo: returnAddr,
|
|
352
|
+
returnToHex: returnHex,
|
|
353
|
+
paused: paused,
|
|
354
|
+
message: statusMsg,
|
|
355
|
+
};
|
|
356
|
+
},
|
|
357
|
+
};
|