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,257 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* smartport-tools.js - SmartPort hard drive operation tools
|
|
3
|
+
*
|
|
4
|
+
* Written by
|
|
5
|
+
* Shawn Bullock <shawn@agenticexpert.ai>
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
getRecentImages,
|
|
10
|
+
loadRecentImage,
|
|
11
|
+
clearRecentImages,
|
|
12
|
+
saveImageToStorage,
|
|
13
|
+
addToRecentImages,
|
|
14
|
+
} from "../disk-manager/hard-drive-persistence.js";
|
|
15
|
+
|
|
16
|
+
function requireSmartPort() {
|
|
17
|
+
const wasmModule = window.emulator?.wasmModule;
|
|
18
|
+
if (!wasmModule) {
|
|
19
|
+
throw new Error("WASM module not available");
|
|
20
|
+
}
|
|
21
|
+
if (!wasmModule._isSmartPortCardInstalled ||
|
|
22
|
+
!wasmModule._isSmartPortCardInstalled()) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
"SmartPort card is not installed. Use slotsInstallCard to install it in a compatible slot."
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return wasmModule;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const smartportTools = {
|
|
31
|
+
/**
|
|
32
|
+
* Insert a SmartPort image into a device by path
|
|
33
|
+
*/
|
|
34
|
+
smartportInsertImage: async (args) => {
|
|
35
|
+
const { deviceNum = 1, path } = args;
|
|
36
|
+
|
|
37
|
+
if (!path) {
|
|
38
|
+
throw new Error("path parameter is required");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (deviceNum !== 1 && deviceNum !== 2) {
|
|
42
|
+
throw new Error("deviceNum must be 1 or 2");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const supportedFormats = [".hdv", ".po", ".2mg"];
|
|
46
|
+
const extension = path.toLowerCase().match(/\.(hdv|po|2mg)$/);
|
|
47
|
+
|
|
48
|
+
if (!extension) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Unsupported SmartPort format. Supported formats: ${supportedFormats.join(", ")}`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const deviceIndex = deviceNum - 1;
|
|
55
|
+
|
|
56
|
+
requireSmartPort();
|
|
57
|
+
|
|
58
|
+
const hardDriveManager = window.emulator?.hardDriveManager;
|
|
59
|
+
if (!hardDriveManager) {
|
|
60
|
+
throw new Error("Hard drive manager not available");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const agentManager = window.emulator?.agentManager;
|
|
65
|
+
if (!agentManager) {
|
|
66
|
+
throw new Error("Agent manager not available");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const result = await agentManager.callMCPTool("load_smartport_image", { path });
|
|
70
|
+
|
|
71
|
+
if (!result || !result.success) {
|
|
72
|
+
throw new Error(result?.error || "Failed to load SmartPort image");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const binaryString = atob(result.data);
|
|
76
|
+
const data = new Uint8Array(binaryString.length);
|
|
77
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
78
|
+
data[i] = binaryString.charCodeAt(i);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const filename = result.filename;
|
|
82
|
+
|
|
83
|
+
const success = hardDriveManager.loadImageFromData(deviceIndex, filename, data);
|
|
84
|
+
if (!success) {
|
|
85
|
+
throw new Error("Failed to insert SmartPort image into emulator");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await saveImageToStorage(deviceIndex, filename, data);
|
|
89
|
+
await addToRecentImages(deviceIndex, filename, data);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
success: true,
|
|
93
|
+
device: deviceNum,
|
|
94
|
+
filename: filename,
|
|
95
|
+
size: data.length,
|
|
96
|
+
message: `SmartPort image inserted into device ${deviceNum}: ${filename}`,
|
|
97
|
+
};
|
|
98
|
+
} catch (error) {
|
|
99
|
+
throw new Error(`Error loading SmartPort image: ${error.message}`);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Get list of recent images for a device
|
|
105
|
+
*/
|
|
106
|
+
smartportRecentsList: async (args) => {
|
|
107
|
+
const { deviceNum = 1 } = args;
|
|
108
|
+
|
|
109
|
+
if (deviceNum !== 1 && deviceNum !== 2) {
|
|
110
|
+
throw new Error("deviceNum must be 1 or 2");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const deviceIndex = deviceNum - 1;
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const recentImages = await getRecentImages(deviceIndex);
|
|
117
|
+
|
|
118
|
+
const imageList = recentImages.map(img => ({
|
|
119
|
+
filename: img.filename,
|
|
120
|
+
accessedAt: img.accessedAt,
|
|
121
|
+
id: img.id,
|
|
122
|
+
}));
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
success: true,
|
|
126
|
+
device: deviceNum,
|
|
127
|
+
count: imageList.length,
|
|
128
|
+
images: imageList,
|
|
129
|
+
message: `Found ${imageList.length} recent image(s) for device ${deviceNum}`,
|
|
130
|
+
};
|
|
131
|
+
} catch (error) {
|
|
132
|
+
throw new Error(`Error getting recent images: ${error.message}`);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Insert a recent image by name
|
|
138
|
+
*/
|
|
139
|
+
smartportInsertRecent: async (args) => {
|
|
140
|
+
const { deviceNum = 1, name } = args;
|
|
141
|
+
|
|
142
|
+
if (!name) {
|
|
143
|
+
throw new Error("name parameter is required");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (deviceNum !== 1 && deviceNum !== 2) {
|
|
147
|
+
throw new Error("deviceNum must be 1 or 2");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const deviceIndex = deviceNum - 1;
|
|
151
|
+
|
|
152
|
+
requireSmartPort();
|
|
153
|
+
|
|
154
|
+
const hardDriveManager = window.emulator?.hardDriveManager;
|
|
155
|
+
if (!hardDriveManager) {
|
|
156
|
+
throw new Error("Hard drive manager not available");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
const recentImages = await getRecentImages(deviceIndex);
|
|
161
|
+
|
|
162
|
+
const imageEntry = recentImages.find(img => img.filename === name);
|
|
163
|
+
if (!imageEntry) {
|
|
164
|
+
throw new Error(`Image "${name}" not found in recent list for device ${deviceNum}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const imageData = await loadRecentImage(imageEntry.id);
|
|
168
|
+
if (!imageData) {
|
|
169
|
+
throw new Error(`Failed to load image data for "${name}"`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const success = hardDriveManager.loadImageFromData(deviceIndex, imageData.filename, imageData.data);
|
|
173
|
+
if (!success) {
|
|
174
|
+
throw new Error("Failed to insert SmartPort image into emulator");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
await saveImageToStorage(deviceIndex, imageData.filename, imageData.data);
|
|
178
|
+
await addToRecentImages(deviceIndex, imageData.filename, imageData.data);
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
success: true,
|
|
182
|
+
device: deviceNum,
|
|
183
|
+
filename: imageData.filename,
|
|
184
|
+
size: imageData.data.length,
|
|
185
|
+
message: `Recent image inserted into device ${deviceNum}: ${imageData.filename}`,
|
|
186
|
+
};
|
|
187
|
+
} catch (error) {
|
|
188
|
+
throw new Error(`Error inserting recent image: ${error.message}`);
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Clear all recent images for a device
|
|
194
|
+
*/
|
|
195
|
+
smartportClearRecent: async (args) => {
|
|
196
|
+
const { deviceNum = 1 } = args;
|
|
197
|
+
|
|
198
|
+
if (deviceNum !== 1 && deviceNum !== 2) {
|
|
199
|
+
throw new Error("deviceNum must be 1 or 2");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const deviceIndex = deviceNum - 1;
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
await clearRecentImages(deviceIndex);
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
success: true,
|
|
209
|
+
device: deviceNum,
|
|
210
|
+
message: `Cleared all recent images for device ${deviceNum}`,
|
|
211
|
+
};
|
|
212
|
+
} catch (error) {
|
|
213
|
+
throw new Error(`Error clearing recent images: ${error.message}`);
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Eject a SmartPort image from a device
|
|
219
|
+
*/
|
|
220
|
+
smartportEject: async (args) => {
|
|
221
|
+
const { deviceNum = 1 } = args;
|
|
222
|
+
|
|
223
|
+
if (deviceNum !== 1 && deviceNum !== 2) {
|
|
224
|
+
throw new Error("deviceNum must be 1 or 2");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const deviceIndex = deviceNum - 1;
|
|
228
|
+
|
|
229
|
+
const wasmModule = requireSmartPort();
|
|
230
|
+
|
|
231
|
+
const hardDriveManager = window.emulator?.hardDriveManager;
|
|
232
|
+
if (!hardDriveManager) {
|
|
233
|
+
throw new Error("Hard drive manager not available");
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
// Eject image via WASM
|
|
238
|
+
wasmModule._ejectSmartPortImage(deviceIndex);
|
|
239
|
+
|
|
240
|
+
// Update UI
|
|
241
|
+
hardDriveManager.setImageName(deviceIndex, null);
|
|
242
|
+
|
|
243
|
+
// Notify if callback exists
|
|
244
|
+
if (hardDriveManager.onImageEjected) {
|
|
245
|
+
hardDriveManager.onImageEjected(deviceIndex);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
success: true,
|
|
250
|
+
device: deviceNum,
|
|
251
|
+
message: `SmartPort image ejected from device ${deviceNum}`,
|
|
252
|
+
};
|
|
253
|
+
} catch (error) {
|
|
254
|
+
throw new Error(`Error ejecting SmartPort image: ${error.message}`);
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* window-tools.js - Window management tools
|
|
3
|
+
*
|
|
4
|
+
* Written by
|
|
5
|
+
* Shawn Bullock <shawn@agenticexpert.ai>
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const windowTools = {
|
|
9
|
+
/**
|
|
10
|
+
* Show or focus a window
|
|
11
|
+
*/
|
|
12
|
+
showWindow: async (args) => {
|
|
13
|
+
const { windowId } = args;
|
|
14
|
+
|
|
15
|
+
if (!windowId) {
|
|
16
|
+
throw new Error("windowId parameter is required");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const windowManager = window.emulator?.windowManager;
|
|
20
|
+
if (!windowManager) {
|
|
21
|
+
throw new Error("Window manager not available");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
windowManager.showWindow(windowId);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
success: true,
|
|
28
|
+
windowId: windowId,
|
|
29
|
+
message: `Window '${windowId}' is now visible`,
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Hide a window
|
|
35
|
+
*/
|
|
36
|
+
hideWindow: async (args) => {
|
|
37
|
+
const { windowId } = args;
|
|
38
|
+
|
|
39
|
+
if (!windowId) {
|
|
40
|
+
throw new Error("windowId parameter is required");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const windowManager = window.emulator?.windowManager;
|
|
44
|
+
if (!windowManager) {
|
|
45
|
+
throw new Error("Window manager not available");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
windowManager.hideWindow(windowId);
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
success: true,
|
|
52
|
+
windowId: windowId,
|
|
53
|
+
message: `Window '${windowId}' is now hidden`,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Focus a window (bring to front)
|
|
59
|
+
*/
|
|
60
|
+
focusWindow: async (args) => {
|
|
61
|
+
const { windowId } = args;
|
|
62
|
+
|
|
63
|
+
if (!windowId) {
|
|
64
|
+
throw new Error("windowId parameter is required");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const windowManager = window.emulator?.windowManager;
|
|
68
|
+
if (!windowManager) {
|
|
69
|
+
throw new Error("Window manager not available");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
windowManager.bringToFront(windowId);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
success: true,
|
|
76
|
+
windowId: windowId,
|
|
77
|
+
message: `Window '${windowId}' is now focused`,
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
};
|