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,109 @@
|
|
|
1
|
+
// Edge overlay fragment shader
|
|
2
|
+
// Renders the screen edge highlight as a separate pass so it is
|
|
3
|
+
// completely unaffected by CRT effects (scanlines, shadow mask, etc.).
|
|
4
|
+
// Uses stable coordinates (no jitter / horizontal sync distortion).
|
|
5
|
+
|
|
6
|
+
precision highp float;
|
|
7
|
+
|
|
8
|
+
uniform float u_curvature;
|
|
9
|
+
uniform float u_cornerRadius;
|
|
10
|
+
uniform float u_edgeHighlight;
|
|
11
|
+
uniform vec2 u_textureSize;
|
|
12
|
+
uniform vec2 u_resolution;
|
|
13
|
+
|
|
14
|
+
varying vec2 v_texCoord;
|
|
15
|
+
|
|
16
|
+
// Screen curvature (must match crt.glsl)
|
|
17
|
+
vec2 curveUV(vec2 uv) {
|
|
18
|
+
if (u_curvature < 0.001) return uv;
|
|
19
|
+
|
|
20
|
+
vec2 cc = uv - 0.5;
|
|
21
|
+
float dist = dot(cc, cc);
|
|
22
|
+
float distortion = dist * u_curvature * 0.5;
|
|
23
|
+
return uv + cc * distortion;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Rounded rectangle alpha (must match crt.glsl)
|
|
27
|
+
float roundedRectAlpha(vec2 uv, float radius) {
|
|
28
|
+
if (radius < 0.001) return 1.0;
|
|
29
|
+
|
|
30
|
+
vec2 centered = abs(uv - 0.5);
|
|
31
|
+
vec2 cornerDist = centered - (0.5 - radius);
|
|
32
|
+
|
|
33
|
+
if (cornerDist.x < 0.0 || cornerDist.y < 0.0) {
|
|
34
|
+
return 1.0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
float dist = length(cornerDist);
|
|
38
|
+
return 1.0 - smoothstep(radius - 0.005, radius + 0.005, dist);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Edge highlight with uniform screen-pixel width and anti-aliasing.
|
|
42
|
+
// Computes the gradient direction of the distance field so that line
|
|
43
|
+
// width and AA are expressed in output pixels regardless of whether
|
|
44
|
+
// the fragment sits on a straight edge or a corner arc.
|
|
45
|
+
float edgeHighlightIntensity(vec2 uv, float radius) {
|
|
46
|
+
if (u_edgeHighlight < 0.001) return 0.0;
|
|
47
|
+
|
|
48
|
+
vec2 centered = abs(uv - 0.5);
|
|
49
|
+
vec2 cornerDist = centered - (0.5 - radius);
|
|
50
|
+
|
|
51
|
+
float distFromEdge;
|
|
52
|
+
vec2 gradDir; // unit-length gradient direction in UV space
|
|
53
|
+
|
|
54
|
+
if (cornerDist.x > 0.0 && cornerDist.y > 0.0) {
|
|
55
|
+
// Corner arc
|
|
56
|
+
float d = length(cornerDist);
|
|
57
|
+
distFromEdge = radius - d;
|
|
58
|
+
gradDir = cornerDist / d;
|
|
59
|
+
} else if (0.5 - centered.x < 0.5 - centered.y) {
|
|
60
|
+
// Nearest to a vertical edge (left / right)
|
|
61
|
+
distFromEdge = 0.5 - centered.x;
|
|
62
|
+
gradDir = vec2(1.0, 0.0);
|
|
63
|
+
} else {
|
|
64
|
+
// Nearest to a horizontal edge (top / bottom)
|
|
65
|
+
distFromEdge = 0.5 - centered.y;
|
|
66
|
+
gradDir = vec2(0.0, 1.0);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Convert pixel counts to UV-space distances along the gradient.
|
|
70
|
+
// length(gradDir / u_resolution) gives UV units per output pixel
|
|
71
|
+
// in the direction perpendicular to the edge.
|
|
72
|
+
float uvPerPixel = length(gradDir / u_resolution);
|
|
73
|
+
float lineWidth = 2.5 * uvPerPixel;
|
|
74
|
+
float aa = 0.75 * uvPerPixel;
|
|
75
|
+
|
|
76
|
+
// Anti-aliased line: smoothstep at both inner and outer boundaries
|
|
77
|
+
float outer = smoothstep(-aa, aa, distFromEdge);
|
|
78
|
+
float inner = smoothstep(lineWidth + aa, lineWidth - aa, distFromEdge);
|
|
79
|
+
|
|
80
|
+
return outer * inner * u_edgeHighlight;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void main() {
|
|
84
|
+
// Use raw texture coordinates with only curvature applied.
|
|
85
|
+
// No jitter or horizontal sync — the edge stays perfectly stable.
|
|
86
|
+
vec2 curvedUV = curveUV(v_texCoord);
|
|
87
|
+
|
|
88
|
+
// Outside the rounded rectangle — fully transparent
|
|
89
|
+
float cornerAlpha = roundedRectAlpha(curvedUV, u_cornerRadius);
|
|
90
|
+
if (cornerAlpha < 0.001) {
|
|
91
|
+
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Edge highlight
|
|
96
|
+
float edgeGlow = edgeHighlightIntensity(curvedUV, u_cornerRadius);
|
|
97
|
+
if (edgeGlow < 0.001) {
|
|
98
|
+
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Separate the line shape (0–1) from the brightness.
|
|
103
|
+
// Use the shape as alpha so the line is fully opaque where it exists
|
|
104
|
+
// and fades only at its own anti-aliased boundaries — not at the
|
|
105
|
+
// rounded-rect corner alpha which would dim the corner arcs.
|
|
106
|
+
float lineAlpha = edgeGlow / u_edgeHighlight;
|
|
107
|
+
vec3 highlightColor = vec3(0.55, 0.55, 0.5) * u_edgeHighlight;
|
|
108
|
+
gl_FragColor = vec4(highlightColor, lineAlpha);
|
|
109
|
+
}
|
package/public/sw.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// Service Worker for Apple //e Emulator
|
|
2
|
+
// Enables offline functionality by caching app assets
|
|
3
|
+
|
|
4
|
+
// IMPORTANT: Bump this version when WASM or core JS files change
|
|
5
|
+
const CACHE_VERSION = 3.3;
|
|
6
|
+
const CACHE_NAME = `a2e-cache-v${CACHE_VERSION}`;
|
|
7
|
+
|
|
8
|
+
// Files that should always be fetched fresh (network-first)
|
|
9
|
+
const NETWORK_FIRST_FILES = ["/a2e.js", "/a2e.wasm"];
|
|
10
|
+
|
|
11
|
+
// Assets to cache on install
|
|
12
|
+
const PRECACHE_ASSETS = [
|
|
13
|
+
"/",
|
|
14
|
+
"/index.html",
|
|
15
|
+
"/manifest.json",
|
|
16
|
+
"/a2e.js",
|
|
17
|
+
"/a2e.wasm",
|
|
18
|
+
"/audio-worklet.js",
|
|
19
|
+
"/css/base.css",
|
|
20
|
+
"/css/layout.css",
|
|
21
|
+
"/css/monitor.css",
|
|
22
|
+
"/css/disk-drives.css",
|
|
23
|
+
"/css/controls.css",
|
|
24
|
+
"/css/modals.css",
|
|
25
|
+
"/css/debug-windows.css",
|
|
26
|
+
"/css/file-explorer.css",
|
|
27
|
+
"/css/documentation.css",
|
|
28
|
+
"/css/responsive.css",
|
|
29
|
+
"/images/drive-open.png",
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// Install event - cache core assets
|
|
33
|
+
self.addEventListener("install", (event) => {
|
|
34
|
+
event.waitUntil(
|
|
35
|
+
caches
|
|
36
|
+
.open(CACHE_NAME)
|
|
37
|
+
.then((cache) => {
|
|
38
|
+
console.log("[SW] Precaching app assets");
|
|
39
|
+
return cache.addAll(PRECACHE_ASSETS);
|
|
40
|
+
})
|
|
41
|
+
.then(() => {
|
|
42
|
+
// Activate immediately without waiting
|
|
43
|
+
return self.skipWaiting();
|
|
44
|
+
})
|
|
45
|
+
.catch((error) => {
|
|
46
|
+
console.error("[SW] Precache failed:", error);
|
|
47
|
+
}),
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Activate event - clean up old caches
|
|
52
|
+
self.addEventListener("activate", (event) => {
|
|
53
|
+
event.waitUntil(
|
|
54
|
+
caches
|
|
55
|
+
.keys()
|
|
56
|
+
.then((cacheNames) => {
|
|
57
|
+
return Promise.all(
|
|
58
|
+
cacheNames
|
|
59
|
+
.filter((name) => name !== CACHE_NAME)
|
|
60
|
+
.map((name) => {
|
|
61
|
+
console.log("[SW] Deleting old cache:", name);
|
|
62
|
+
return caches.delete(name);
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
})
|
|
66
|
+
.then(() => {
|
|
67
|
+
// Take control of all pages immediately
|
|
68
|
+
return self.clients.claim();
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Check if URL should use network-first strategy
|
|
74
|
+
function isNetworkFirst(url) {
|
|
75
|
+
// Explicit network-first files
|
|
76
|
+
if (
|
|
77
|
+
NETWORK_FIRST_FILES.some(
|
|
78
|
+
(file) => url.pathname === file || url.pathname.endsWith(file),
|
|
79
|
+
)
|
|
80
|
+
) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
// Also use network-first for Vite JS bundles (they have hashed names)
|
|
84
|
+
if (url.pathname.includes("/assets/") && url.pathname.endsWith(".js")) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Fetch event - serve from cache, fall back to network
|
|
91
|
+
self.addEventListener("fetch", (event) => {
|
|
92
|
+
const url = new URL(event.request.url);
|
|
93
|
+
|
|
94
|
+
// Skip non-GET requests
|
|
95
|
+
if (event.request.method !== "GET") {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Skip cross-origin requests (fonts, etc.)
|
|
100
|
+
if (url.origin !== self.location.origin) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Use network-first for critical files (WASM, core JS)
|
|
105
|
+
if (isNetworkFirst(url)) {
|
|
106
|
+
event.respondWith(
|
|
107
|
+
fetch(event.request)
|
|
108
|
+
.then((networkResponse) => {
|
|
109
|
+
if (networkResponse && networkResponse.status === 200) {
|
|
110
|
+
// Update cache with fresh response
|
|
111
|
+
const responseToCache = networkResponse.clone();
|
|
112
|
+
caches.open(CACHE_NAME).then((cache) => {
|
|
113
|
+
cache.put(event.request, responseToCache);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return networkResponse;
|
|
117
|
+
})
|
|
118
|
+
.catch(() => {
|
|
119
|
+
// Network failed, try cache as fallback
|
|
120
|
+
return caches.match(event.request);
|
|
121
|
+
}),
|
|
122
|
+
);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Cache-first for other assets
|
|
127
|
+
event.respondWith(
|
|
128
|
+
caches.match(event.request).then((cachedResponse) => {
|
|
129
|
+
if (cachedResponse) {
|
|
130
|
+
// Return cached response
|
|
131
|
+
return cachedResponse;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Not in cache - fetch from network
|
|
135
|
+
return fetch(event.request)
|
|
136
|
+
.then((networkResponse) => {
|
|
137
|
+
// Don't cache non-successful responses
|
|
138
|
+
if (!networkResponse || networkResponse.status !== 200) {
|
|
139
|
+
return networkResponse;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Cache the new response for future use
|
|
143
|
+
// Clone because response can only be consumed once
|
|
144
|
+
const responseToCache = networkResponse.clone();
|
|
145
|
+
|
|
146
|
+
caches.open(CACHE_NAME).then((cache) => {
|
|
147
|
+
// Cache JS bundles and other assets dynamically
|
|
148
|
+
if (shouldCache(event.request.url)) {
|
|
149
|
+
cache.put(event.request, responseToCache);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
return networkResponse;
|
|
154
|
+
})
|
|
155
|
+
.catch((error) => {
|
|
156
|
+
console.error("[SW] Fetch failed:", error);
|
|
157
|
+
// Could return an offline fallback page here
|
|
158
|
+
throw error;
|
|
159
|
+
});
|
|
160
|
+
}),
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Determine if a URL should be cached dynamically
|
|
165
|
+
function shouldCache(url) {
|
|
166
|
+
// Cache JS bundles (Vite generates hashed names)
|
|
167
|
+
if (url.includes("/assets/") && url.endsWith(".js")) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
// Cache images
|
|
171
|
+
if (url.match(/\.(png|jpg|jpeg|gif|svg|webp)$/)) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
// Cache WASM
|
|
175
|
+
if (url.endsWith(".wasm")) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Listen for messages from the main app
|
|
182
|
+
self.addEventListener("message", (event) => {
|
|
183
|
+
if (event.data === "skipWaiting") {
|
|
184
|
+
self.skipWaiting();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Generate C++ source file containing ROM data as byte arrays
|
|
4
|
+
# Usage: generate_roms.sh <rom_directory> <output_file>
|
|
5
|
+
|
|
6
|
+
ROM_DIR="$1"
|
|
7
|
+
OUTPUT_FILE="$2"
|
|
8
|
+
|
|
9
|
+
if [ -z "$ROM_DIR" ] || [ -z "$OUTPUT_FILE" ]; then
|
|
10
|
+
echo "Usage: $0 <rom_directory> <output_file>"
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
# Start the output file
|
|
15
|
+
cat > "$OUTPUT_FILE" << 'EOF'
|
|
16
|
+
// Auto-generated ROM data - DO NOT EDIT
|
|
17
|
+
// Generated by generate_roms.sh
|
|
18
|
+
|
|
19
|
+
#include <cstdint>
|
|
20
|
+
#include <cstddef>
|
|
21
|
+
|
|
22
|
+
namespace roms {
|
|
23
|
+
|
|
24
|
+
EOF
|
|
25
|
+
|
|
26
|
+
# Function to convert a binary file to a C array
|
|
27
|
+
generate_array() {
|
|
28
|
+
local file="$1"
|
|
29
|
+
local name="$2"
|
|
30
|
+
|
|
31
|
+
if [ ! -f "$file" ]; then
|
|
32
|
+
echo "// ROM file not found: $file" >> "$OUTPUT_FILE"
|
|
33
|
+
echo "const uint8_t ${name}[] = {};" >> "$OUTPUT_FILE"
|
|
34
|
+
echo "const size_t ${name}_SIZE = 0;" >> "$OUTPUT_FILE"
|
|
35
|
+
echo "" >> "$OUTPUT_FILE"
|
|
36
|
+
return
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
local size=$(wc -c < "$file" | tr -d ' ')
|
|
40
|
+
|
|
41
|
+
echo "// $(basename "$file")" >> "$OUTPUT_FILE"
|
|
42
|
+
echo "const uint8_t ${name}[] = {" >> "$OUTPUT_FILE"
|
|
43
|
+
|
|
44
|
+
xxd -i < "$file" | sed 's/^/ /' >> "$OUTPUT_FILE"
|
|
45
|
+
|
|
46
|
+
echo "};" >> "$OUTPUT_FILE"
|
|
47
|
+
echo "const size_t ${name}_SIZE = $size;" >> "$OUTPUT_FILE"
|
|
48
|
+
echo "" >> "$OUTPUT_FILE"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Generate arrays for each ROM
|
|
52
|
+
# Prefer combined ROM if available
|
|
53
|
+
if [ -f "$ROM_DIR/342-0349-B-C0-FF.bin" ]; then
|
|
54
|
+
generate_array "$ROM_DIR/342-0349-B-C0-FF.bin" "ROM_SYSTEM"
|
|
55
|
+
elif [ -f "$ROM_DIR/342-0135-A-CD.bin" ] && [ -f "$ROM_DIR/342-0134-A-EF.bin" ]; then
|
|
56
|
+
# Fallback to separate CD/EF ROMs - combine them
|
|
57
|
+
generate_array "$ROM_DIR/342-0135-A-CD.bin" "ROM_CD"
|
|
58
|
+
generate_array "$ROM_DIR/342-0134-A-EF.bin" "ROM_EF"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
generate_array "$ROM_DIR/342-0273-A-US-UK.bin" "ROM_CHAR"
|
|
62
|
+
generate_array "$ROM_DIR/341-0027.bin" "ROM_DISK2"
|
|
63
|
+
generate_array "$ROM_DIR/Thunderclock Plus ROM.bin" "ROM_THUNDERCLOCK"
|
|
64
|
+
generate_array "$ROM_DIR/Apple Mouse Interface Card ROM - 342-0270-C.bin" "ROM_MOUSE"
|
|
65
|
+
|
|
66
|
+
# Close namespace
|
|
67
|
+
echo "} // namespace roms" >> "$OUTPUT_FILE"
|
|
68
|
+
|
|
69
|
+
echo "Generated $OUTPUT_FILE"
|