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.
Files changed (295) hide show
  1. package/.clangd +5 -0
  2. package/.mcp.json +12 -0
  3. package/CLAUDE.md +362 -0
  4. package/CMakeLists.txt +774 -0
  5. package/LICENSE +21 -0
  6. package/README.md +392 -0
  7. package/build-wasm/generated/roms.cpp +2447 -0
  8. package/docker-compose.staging.yml +9 -0
  9. package/docs/basic-rom-disassembly.md +6663 -0
  10. package/docs/softswitch-comparison.md +273 -0
  11. package/docs/thunderclock-debug.md +89 -0
  12. package/examples/cube.bas +72 -0
  13. package/examples/hello.s +55 -0
  14. package/examples/scroll.s +140 -0
  15. package/package.json +18 -0
  16. package/public/assets/apple-logo-old.png +0 -0
  17. package/public/assets/apple-logo.png +0 -0
  18. package/public/assets/drive-closed-light-on.png +0 -0
  19. package/public/assets/drive-closed.png +0 -0
  20. package/public/assets/drive-open-light-on.png +0 -0
  21. package/public/assets/drive-open.png +0 -0
  22. package/public/audio-worklet.js +82 -0
  23. package/public/disks/Apple DOS 3.3 January 1983.dsk +0 -0
  24. package/public/disks/ProDOS 2.4.3.po +0 -0
  25. package/public/disks/h32mb.2mg +0 -0
  26. package/public/disks/library.json +26 -0
  27. package/public/docs/llms/llm-assembler.txt +90 -0
  28. package/public/docs/llms/llm-basic-program.txt +256 -0
  29. package/public/docs/llms/llm-disk-drives.txt +72 -0
  30. package/public/docs/llms/llm-file-explorer.txt +50 -0
  31. package/public/docs/llms/llm-hard-drives.txt +80 -0
  32. package/public/docs/llms/llm-main.txt +51 -0
  33. package/public/docs/llms/llm-slot-configuration.txt +66 -0
  34. package/public/icons/icon-192.svg +4 -0
  35. package/public/icons/icon-512.svg +4 -0
  36. package/public/index.html +661 -0
  37. package/public/llms.txt +49 -0
  38. package/public/manifest.json +29 -0
  39. package/public/shaders/burnin.glsl +22 -0
  40. package/public/shaders/crt.glsl +706 -0
  41. package/public/shaders/edge.glsl +109 -0
  42. package/public/shaders/vertex.glsl +8 -0
  43. package/public/sw.js +186 -0
  44. package/roms/341-0027.bin +0 -0
  45. package/roms/341-0160-A-US-UK.bin +0 -0
  46. package/roms/341-0160-A.bin +0 -0
  47. package/roms/342-0273-A-US-UK.bin +0 -0
  48. package/roms/342-0349-B-C0-FF.bin +0 -0
  49. package/roms/Apple Mouse Interface Card ROM - 342-0270-C.bin +0 -0
  50. package/roms/Thunderclock Plus ROM.bin +0 -0
  51. package/scripts/generate_roms.sh +69 -0
  52. package/src/bindings/wasm_interface.cpp +1940 -0
  53. package/src/core/assembler/assembler.cpp +1239 -0
  54. package/src/core/assembler/assembler.hpp +115 -0
  55. package/src/core/audio/audio.cpp +160 -0
  56. package/src/core/audio/audio.hpp +81 -0
  57. package/src/core/basic/basic_detokenizer.cpp +436 -0
  58. package/src/core/basic/basic_detokenizer.hpp +41 -0
  59. package/src/core/basic/basic_tokenizer.cpp +286 -0
  60. package/src/core/basic/basic_tokenizer.hpp +26 -0
  61. package/src/core/basic/basic_tokens.hpp +295 -0
  62. package/src/core/cards/disk2_card.cpp +568 -0
  63. package/src/core/cards/disk2_card.hpp +316 -0
  64. package/src/core/cards/expansion_card.hpp +185 -0
  65. package/src/core/cards/mockingboard/ay8910.cpp +616 -0
  66. package/src/core/cards/mockingboard/ay8910.hpp +159 -0
  67. package/src/core/cards/mockingboard/via6522.cpp +530 -0
  68. package/src/core/cards/mockingboard/via6522.hpp +163 -0
  69. package/src/core/cards/mockingboard_card.cpp +312 -0
  70. package/src/core/cards/mockingboard_card.hpp +159 -0
  71. package/src/core/cards/mouse_card.cpp +654 -0
  72. package/src/core/cards/mouse_card.hpp +190 -0
  73. package/src/core/cards/smartport/block_device.cpp +202 -0
  74. package/src/core/cards/smartport/block_device.hpp +60 -0
  75. package/src/core/cards/smartport/smartport_card.cpp +603 -0
  76. package/src/core/cards/smartport/smartport_card.hpp +120 -0
  77. package/src/core/cards/thunderclock_card.cpp +237 -0
  78. package/src/core/cards/thunderclock_card.hpp +122 -0
  79. package/src/core/cpu/cpu6502.cpp +1609 -0
  80. package/src/core/cpu/cpu6502.hpp +203 -0
  81. package/src/core/debug/condition_evaluator.cpp +470 -0
  82. package/src/core/debug/condition_evaluator.hpp +87 -0
  83. package/src/core/disassembler/disassembler.cpp +552 -0
  84. package/src/core/disassembler/disassembler.hpp +171 -0
  85. package/src/core/disk-image/disk_image.hpp +267 -0
  86. package/src/core/disk-image/dsk_disk_image.cpp +827 -0
  87. package/src/core/disk-image/dsk_disk_image.hpp +204 -0
  88. package/src/core/disk-image/gcr_encoding.cpp +147 -0
  89. package/src/core/disk-image/gcr_encoding.hpp +78 -0
  90. package/src/core/disk-image/woz_disk_image.cpp +1049 -0
  91. package/src/core/disk-image/woz_disk_image.hpp +343 -0
  92. package/src/core/emulator.cpp +2126 -0
  93. package/src/core/emulator.hpp +434 -0
  94. package/src/core/filesystem/dos33.cpp +178 -0
  95. package/src/core/filesystem/dos33.hpp +66 -0
  96. package/src/core/filesystem/pascal.cpp +262 -0
  97. package/src/core/filesystem/pascal.hpp +87 -0
  98. package/src/core/filesystem/prodos.cpp +369 -0
  99. package/src/core/filesystem/prodos.hpp +119 -0
  100. package/src/core/input/keyboard.cpp +227 -0
  101. package/src/core/input/keyboard.hpp +111 -0
  102. package/src/core/mmu/mmu.cpp +1387 -0
  103. package/src/core/mmu/mmu.hpp +236 -0
  104. package/src/core/types.hpp +196 -0
  105. package/src/core/video/video.cpp +680 -0
  106. package/src/core/video/video.hpp +156 -0
  107. package/src/css/assembler-editor.css +1617 -0
  108. package/src/css/base.css +470 -0
  109. package/src/css/basic-debugger.css +791 -0
  110. package/src/css/basic-editor.css +792 -0
  111. package/src/css/controls.css +783 -0
  112. package/src/css/cpu-debugger.css +1413 -0
  113. package/src/css/debug-base.css +160 -0
  114. package/src/css/debug-windows.css +6455 -0
  115. package/src/css/disk-drives.css +406 -0
  116. package/src/css/documentation.css +392 -0
  117. package/src/css/file-explorer.css +867 -0
  118. package/src/css/hard-drive.css +180 -0
  119. package/src/css/layout.css +217 -0
  120. package/src/css/memory-windows.css +798 -0
  121. package/src/css/modals.css +510 -0
  122. package/src/css/monitor.css +425 -0
  123. package/src/css/release-notes.css +101 -0
  124. package/src/css/responsive.css +400 -0
  125. package/src/css/rule-builder.css +340 -0
  126. package/src/css/save-states.css +201 -0
  127. package/src/css/settings-windows.css +1231 -0
  128. package/src/css/window-switcher.css +150 -0
  129. package/src/js/agent/agent-manager.js +643 -0
  130. package/src/js/agent/agent-tools.js +293 -0
  131. package/src/js/agent/agent-version-tools.js +131 -0
  132. package/src/js/agent/assembler-tools.js +357 -0
  133. package/src/js/agent/basic-program-tools.js +894 -0
  134. package/src/js/agent/disk-tools.js +417 -0
  135. package/src/js/agent/file-explorer-tools.js +269 -0
  136. package/src/js/agent/index.js +13 -0
  137. package/src/js/agent/main-tools.js +222 -0
  138. package/src/js/agent/slot-tools.js +303 -0
  139. package/src/js/agent/smartport-tools.js +257 -0
  140. package/src/js/agent/window-tools.js +80 -0
  141. package/src/js/audio/audio-driver.js +417 -0
  142. package/src/js/audio/audio-worklet.js +85 -0
  143. package/src/js/audio/index.js +8 -0
  144. package/src/js/config/default-layout.js +34 -0
  145. package/src/js/config/version.js +8 -0
  146. package/src/js/data/apple2-rom-routines.js +577 -0
  147. package/src/js/debug/assembler-editor-window.js +2993 -0
  148. package/src/js/debug/basic-breakpoint-manager.js +529 -0
  149. package/src/js/debug/basic-program-parser.js +436 -0
  150. package/src/js/debug/basic-program-window.js +2594 -0
  151. package/src/js/debug/basic-variable-inspector.js +447 -0
  152. package/src/js/debug/breakpoint-manager.js +472 -0
  153. package/src/js/debug/cpu-debugger-window.js +2396 -0
  154. package/src/js/debug/index.js +22 -0
  155. package/src/js/debug/label-manager.js +238 -0
  156. package/src/js/debug/memory-browser-window.js +416 -0
  157. package/src/js/debug/memory-heat-map-window.js +481 -0
  158. package/src/js/debug/memory-map-window.js +206 -0
  159. package/src/js/debug/mockingboard-window.js +882 -0
  160. package/src/js/debug/mouse-card-window.js +355 -0
  161. package/src/js/debug/rule-builder-window.js +648 -0
  162. package/src/js/debug/soft-switch-window.js +458 -0
  163. package/src/js/debug/stack-viewer-window.js +221 -0
  164. package/src/js/debug/symbols.js +416 -0
  165. package/src/js/debug/trace-panel.js +291 -0
  166. package/src/js/debug/zero-page-watch-window.js +297 -0
  167. package/src/js/disk-manager/disk-drives-window.js +212 -0
  168. package/src/js/disk-manager/disk-operations.js +284 -0
  169. package/src/js/disk-manager/disk-persistence.js +301 -0
  170. package/src/js/disk-manager/disk-surface-renderer.js +388 -0
  171. package/src/js/disk-manager/drive-sounds.js +139 -0
  172. package/src/js/disk-manager/hard-drive-manager.js +481 -0
  173. package/src/js/disk-manager/hard-drive-persistence.js +187 -0
  174. package/src/js/disk-manager/hard-drive-window.js +57 -0
  175. package/src/js/disk-manager/index.js +890 -0
  176. package/src/js/display/display-settings-window.js +383 -0
  177. package/src/js/display/index.js +10 -0
  178. package/src/js/display/screen-window.js +342 -0
  179. package/src/js/display/webgl-renderer.js +705 -0
  180. package/src/js/file-explorer/disassembler.js +574 -0
  181. package/src/js/file-explorer/dos33.js +266 -0
  182. package/src/js/file-explorer/file-viewer.js +359 -0
  183. package/src/js/file-explorer/index.js +1261 -0
  184. package/src/js/file-explorer/prodos.js +549 -0
  185. package/src/js/file-explorer/utils.js +67 -0
  186. package/src/js/help/documentation-window.js +1096 -0
  187. package/src/js/help/index.js +10 -0
  188. package/src/js/help/release-notes-window.js +85 -0
  189. package/src/js/help/release-notes.js +612 -0
  190. package/src/js/input/gamepad-handler.js +176 -0
  191. package/src/js/input/index.js +12 -0
  192. package/src/js/input/input-handler.js +396 -0
  193. package/src/js/input/joystick-window.js +404 -0
  194. package/src/js/input/mouse-handler.js +99 -0
  195. package/src/js/input/text-selection.js +462 -0
  196. package/src/js/main.js +653 -0
  197. package/src/js/state/index.js +15 -0
  198. package/src/js/state/save-states-window.js +393 -0
  199. package/src/js/state/state-manager.js +409 -0
  200. package/src/js/state/state-persistence.js +218 -0
  201. package/src/js/ui/confirm.js +43 -0
  202. package/src/js/ui/disk-drive-positioner.js +347 -0
  203. package/src/js/ui/reminder-controller.js +129 -0
  204. package/src/js/ui/slot-configuration-window.js +560 -0
  205. package/src/js/ui/theme-manager.js +61 -0
  206. package/src/js/ui/toast.js +44 -0
  207. package/src/js/ui/ui-controller.js +897 -0
  208. package/src/js/ui/window-switcher.js +275 -0
  209. package/src/js/utils/basic-autocomplete.js +832 -0
  210. package/src/js/utils/basic-highlighting.js +473 -0
  211. package/src/js/utils/basic-tokenizer.js +153 -0
  212. package/src/js/utils/basic-tokens.js +117 -0
  213. package/src/js/utils/constants.js +28 -0
  214. package/src/js/utils/indexeddb-helper.js +225 -0
  215. package/src/js/utils/merlin-editor-support.js +905 -0
  216. package/src/js/utils/merlin-highlighting.js +551 -0
  217. package/src/js/utils/storage.js +125 -0
  218. package/src/js/utils/string-utils.js +19 -0
  219. package/src/js/utils/wasm-memory.js +54 -0
  220. package/src/js/windows/base-window.js +690 -0
  221. package/src/js/windows/index.js +9 -0
  222. package/src/js/windows/window-manager.js +375 -0
  223. package/tests/catch2/catch.hpp +17976 -0
  224. package/tests/common/basic_program_builder.cpp +119 -0
  225. package/tests/common/basic_program_builder.hpp +209 -0
  226. package/tests/common/disk_image_builder.cpp +444 -0
  227. package/tests/common/disk_image_builder.hpp +141 -0
  228. package/tests/common/test_helpers.hpp +118 -0
  229. package/tests/gcr/gcr-test.cpp +142 -0
  230. package/tests/integration/check-rom.js +70 -0
  231. package/tests/integration/compare-boot.js +239 -0
  232. package/tests/integration/crash-trace.js +102 -0
  233. package/tests/integration/disk-boot-test.js +264 -0
  234. package/tests/integration/memory-crash.js +108 -0
  235. package/tests/integration/nibble-read-test.js +249 -0
  236. package/tests/integration/phase-test.js +159 -0
  237. package/tests/integration/test_emulator.cpp +291 -0
  238. package/tests/integration/test_emulator_basic.cpp +91 -0
  239. package/tests/integration/test_emulator_debug.cpp +344 -0
  240. package/tests/integration/test_emulator_disk.cpp +153 -0
  241. package/tests/integration/test_emulator_state.cpp +163 -0
  242. package/tests/klaus/6502_functional_test.bin +0 -0
  243. package/tests/klaus/65C02_extended_opcodes_test.bin +0 -0
  244. package/tests/klaus/klaus_6502_test.cpp +184 -0
  245. package/tests/klaus/klaus_65c02_test.cpp +197 -0
  246. package/tests/thunderclock/thunderclock_mmu_test.cpp +304 -0
  247. package/tests/thunderclock/thunderclock_test.cpp +550 -0
  248. package/tests/unit/test_assembler.cpp +521 -0
  249. package/tests/unit/test_audio.cpp +196 -0
  250. package/tests/unit/test_ay8910.cpp +311 -0
  251. package/tests/unit/test_basic_detokenizer.cpp +265 -0
  252. package/tests/unit/test_basic_tokenizer.cpp +382 -0
  253. package/tests/unit/test_block_device.cpp +259 -0
  254. package/tests/unit/test_condition_evaluator.cpp +219 -0
  255. package/tests/unit/test_cpu6502.cpp +1301 -0
  256. package/tests/unit/test_cpu_addressing.cpp +361 -0
  257. package/tests/unit/test_cpu_cycle_counts.cpp +409 -0
  258. package/tests/unit/test_cpu_decimal.cpp +166 -0
  259. package/tests/unit/test_cpu_interrupts.cpp +285 -0
  260. package/tests/unit/test_disassembler.cpp +323 -0
  261. package/tests/unit/test_disk2_card.cpp +330 -0
  262. package/tests/unit/test_dos33.cpp +273 -0
  263. package/tests/unit/test_dsk_disk_image.cpp +315 -0
  264. package/tests/unit/test_expansion_card.cpp +178 -0
  265. package/tests/unit/test_gcr_encoding.cpp +232 -0
  266. package/tests/unit/test_keyboard.cpp +262 -0
  267. package/tests/unit/test_mmu.cpp +555 -0
  268. package/tests/unit/test_mmu_slots.cpp +323 -0
  269. package/tests/unit/test_mockingboard.cpp +352 -0
  270. package/tests/unit/test_mouse_card.cpp +386 -0
  271. package/tests/unit/test_pascal.cpp +248 -0
  272. package/tests/unit/test_prodos.cpp +259 -0
  273. package/tests/unit/test_smartport_card.cpp +321 -0
  274. package/tests/unit/test_thunderclock.cpp +354 -0
  275. package/tests/unit/test_via6522.cpp +323 -0
  276. package/tests/unit/test_video.cpp +319 -0
  277. package/tests/unit/test_woz_disk_image.cpp +257 -0
  278. package/vite.config.js +96 -0
  279. package/wiki/AI-Agent.md +372 -0
  280. package/wiki/Architecture-Overview.md +303 -0
  281. package/wiki/Audio-System.md +449 -0
  282. package/wiki/CPU-Emulation.md +477 -0
  283. package/wiki/Debugger.md +516 -0
  284. package/wiki/Disk-Drives.md +161 -0
  285. package/wiki/Disk-System-Internals.md +547 -0
  286. package/wiki/Display-Settings.md +88 -0
  287. package/wiki/Expansion-Slots.md +187 -0
  288. package/wiki/File-Explorer.md +259 -0
  289. package/wiki/Getting-Started.md +156 -0
  290. package/wiki/Home.md +69 -0
  291. package/wiki/Input-Devices.md +183 -0
  292. package/wiki/Keyboard-Shortcuts.md +158 -0
  293. package/wiki/Memory-System.md +364 -0
  294. package/wiki/Save-States.md +172 -0
  295. package/wiki/Video-Rendering.md +658 -0
@@ -0,0 +1,171 @@
1
+ /*
2
+ * disassembler.hpp - 65C02 instruction disassembler interface
3
+ *
4
+ * Written by
5
+ * Mike Daley <michael_daley@icloud.com>
6
+ */
7
+
8
+ #pragma once
9
+
10
+ #include <cstdint>
11
+ #include <vector>
12
+
13
+ namespace a2e {
14
+
15
+ /**
16
+ * Standalone 6502/65C02 disassembler
17
+ *
18
+ * Returns raw structured data for frontend rendering.
19
+ */
20
+
21
+ // Addressing modes
22
+ enum class AddrMode : uint8_t {
23
+ IMP = 0, // Implied
24
+ ACC = 1, // Accumulator
25
+ IMM = 2, // Immediate #$nn
26
+ ZP = 3, // Zero Page $nn
27
+ ZPX = 4, // Zero Page,X $nn,X
28
+ ZPY = 5, // Zero Page,Y $nn,Y
29
+ ABS = 6, // Absolute $nnnn
30
+ ABX = 7, // Absolute,X $nnnn,X
31
+ ABY = 8, // Absolute,Y $nnnn,Y
32
+ IND = 9, // Indirect ($nnnn)
33
+ IZX = 10, // Indexed Indirect ($nn,X)
34
+ IZY = 11, // Indirect Indexed ($nn),Y
35
+ REL = 12, // Relative (branches)
36
+ ZPI = 13, // Zero Page Indirect ($nn) - 65C02
37
+ AIX = 14, // Absolute Indexed Indirect ($nnnn,X) - 65C02
38
+ ZPR = 15 // Zero Page Relative (BBR/BBS) - 65C02
39
+ };
40
+
41
+ // Instruction categories for syntax highlighting
42
+ enum class InstrCategory : uint8_t {
43
+ BRANCH = 0, // Jumps and branches
44
+ LOAD = 1, // Load/store
45
+ MATH = 2, // Math and logic
46
+ STACK = 3, // Stack and register operations
47
+ FLAG = 4, // Flag operations
48
+ UNKNOWN = 5 // Unknown/illegal opcodes
49
+ };
50
+
51
+ // Opcode info structure (maps opcode byte to mnemonic, mode, category)
52
+ struct OpcodeInfo {
53
+ uint8_t mnemonicIndex;
54
+ uint8_t mode; // AddrMode enum value
55
+ uint8_t category; // InstrCategory enum value
56
+ };
57
+
58
+ /**
59
+ * Get pointer to the 256-entry opcode table
60
+ */
61
+ const OpcodeInfo* getOpcodeTable();
62
+
63
+ /**
64
+ * Get the number of mnemonics in the mnemonic table
65
+ */
66
+ int getMnemonicCount();
67
+
68
+ // Disassembled instruction data - 16 bytes per instruction
69
+ // Layout: [address:2][target:2][length:1][opcode:1][op1:1][op2:1][mode:1][cat:1][mnem:4][pad:2]
70
+ struct DisasmInstruction {
71
+ uint16_t address; // offset 0-1: Memory address
72
+ uint16_t target; // offset 2-3: Branch/jump target address
73
+ uint8_t length; // offset 4: Instruction length (1-3)
74
+ uint8_t opcode; // offset 5: Opcode byte
75
+ uint8_t operand1; // offset 6: First operand byte
76
+ uint8_t operand2; // offset 7: Second operand byte
77
+ uint8_t mode; // offset 8: AddrMode enum value
78
+ uint8_t category; // offset 9: InstrCategory enum value
79
+ char mnemonic[4]; // offset 10-13: Mnemonic (null-padded)
80
+ uint8_t padding[2]; // offset 14-15: Alignment padding
81
+ };
82
+
83
+ // Result structure for disassembly
84
+ struct DisasmResult {
85
+ std::vector<DisasmInstruction> instructions;
86
+ };
87
+
88
+ /**
89
+ * Get the length of an instruction given its opcode
90
+ */
91
+ int getInstructionLength(uint8_t opcode);
92
+
93
+ /**
94
+ * Get mnemonic string for an opcode
95
+ */
96
+ const char* getMnemonic(uint8_t opcode);
97
+
98
+ /**
99
+ * Get mnemonic string by index (for use with DisasmInstruction.mnemonicIndex)
100
+ */
101
+ const char* getMnemonicByIndex(uint8_t index);
102
+
103
+ /**
104
+ * Get addressing mode for an opcode
105
+ */
106
+ AddrMode getAddressingMode(uint8_t opcode);
107
+
108
+ /**
109
+ * Get instruction category for an opcode
110
+ */
111
+ InstrCategory getInstructionCategory(uint8_t opcode);
112
+
113
+ /**
114
+ * Disassemble a single instruction from raw data
115
+ */
116
+ DisasmInstruction disassembleInstruction(const uint8_t *data, size_t size,
117
+ uint16_t address);
118
+
119
+ /**
120
+ * Disassemble a block of raw binary data (linear)
121
+ */
122
+ DisasmResult disassembleBlock(const uint8_t *data, size_t size,
123
+ uint16_t baseAddress);
124
+
125
+ /**
126
+ * Instruction flow classification
127
+ */
128
+ enum class FlowType : uint8_t {
129
+ SEQUENTIAL = 0, // Continue to next instruction
130
+ CONDITIONAL = 1, // Branch may or may not be taken (Bxx, BBRx, BBSx)
131
+ UNCONDITIONAL = 2, // Always transfers control (JMP abs, BRA)
132
+ CALL = 3, // Subroutine call (JSR) - returns to next instruction
133
+ RETURN = 4, // Returns via stack (RTS, RTI)
134
+ INDIRECT = 5, // Indirect jump - target unknown (JMP indirect)
135
+ HALT = 6 // Stops execution (BRK, STP, WAI)
136
+ };
137
+
138
+ /**
139
+ * Get the flow type of an instruction
140
+ */
141
+ FlowType getFlowType(uint8_t opcode);
142
+
143
+ /**
144
+ * Disassemble using recursive descent / control flow analysis
145
+ *
146
+ * This approach traces execution paths from entry points to better
147
+ * distinguish code from data:
148
+ * 1. Decode instruction at entry point
149
+ * 2. If sequential, continue to next instruction
150
+ * 3. If branch/jump, add target to visit list
151
+ * 4. If JSR, add target AND return address
152
+ * 5. If RTS/RTI/indirect jump, stop this path
153
+ * 6. Repeat until no more addresses to visit
154
+ *
155
+ * @param data Raw binary data
156
+ * @param size Size of data in bytes
157
+ * @param baseAddress Memory address of first byte
158
+ * @param entryPoints List of known entry points to start tracing from
159
+ * @return Disassembly result with instructions sorted by address
160
+ */
161
+ DisasmResult disassembleWithFlowAnalysis(const uint8_t *data, size_t size,
162
+ uint16_t baseAddress,
163
+ const std::vector<uint16_t> &entryPoints);
164
+
165
+ /**
166
+ * Convenience overload with single entry point (defaults to baseAddress)
167
+ */
168
+ DisasmResult disassembleWithFlowAnalysis(const uint8_t *data, size_t size,
169
+ uint16_t baseAddress);
170
+
171
+ } // namespace a2e
@@ -0,0 +1,267 @@
1
+ /*
2
+ * disk_image.hpp - Abstract base class for disk image formats
3
+ *
4
+ * Written by
5
+ * Mike Daley <michael_daley@icloud.com>
6
+ */
7
+
8
+ #pragma once
9
+
10
+ #include <cstdint>
11
+ #include <string>
12
+
13
+ namespace a2e {
14
+
15
+ /**
16
+ * DiskImage - Abstract base class for disk image formats
17
+ *
18
+ * This interface defines the contract for disk image implementations.
19
+ * The disk controller uses this interface to access disk data without
20
+ * needing to know the specific format details.
21
+ *
22
+ * The disk image manages head positioning internally based on stepper
23
+ * motor phase changes. The controller only knows about phases (0-3),
24
+ * not tracks. The disk image translates phase sequences into head
25
+ * movement using 4-phase stepper motor physics.
26
+ *
27
+ * Data access is nibble-based. The controller reads nibbles sequentially
28
+ * as the virtual disk spins. Each track contains a stream of nibbles
29
+ * that encode the sector data using GCR (Group Coded Recording).
30
+ */
31
+ class DiskImage {
32
+ public:
33
+ /**
34
+ * Disk image format types
35
+ */
36
+ enum class Format {
37
+ Unknown,
38
+ WOZ1,
39
+ WOZ2,
40
+ DSK, // Raw sector format (140KB, 35 tracks x 16 sectors x 256 bytes)
41
+ DO, // DOS-order DSK (same as DSK)
42
+ PO // ProDOS-order DSK
43
+ };
44
+
45
+ virtual ~DiskImage() = default;
46
+
47
+ // Non-copyable
48
+ DiskImage(const DiskImage &) = delete;
49
+ DiskImage &operator=(const DiskImage &) = delete;
50
+
51
+ // Movable
52
+ DiskImage(DiskImage &&) = default;
53
+ DiskImage &operator=(DiskImage &&) = default;
54
+
55
+ // ===== Loading =====
56
+
57
+ /**
58
+ * Load a disk image from raw data
59
+ * @param data Pointer to disk image data
60
+ * @param size Size of the data
61
+ * @param filename Original filename (for format detection)
62
+ * @return true on success, false on failure
63
+ */
64
+ virtual bool load(const uint8_t *data, size_t size,
65
+ const std::string &filename) = 0;
66
+
67
+ /**
68
+ * Check if a disk image is currently loaded
69
+ * @return true if a valid disk image is loaded
70
+ */
71
+ virtual bool isLoaded() const = 0;
72
+
73
+ /**
74
+ * Get the format of the loaded disk image
75
+ * @return Format enum value
76
+ */
77
+ virtual Format getFormat() const = 0;
78
+
79
+ // ===== Head Positioning =====
80
+
81
+ /**
82
+ * Notify the disk of a phase magnet state change
83
+ * The disk image tracks phase states and moves the head accordingly
84
+ * using 4-phase stepper motor physics.
85
+ *
86
+ * @param phase Phase number (0-3)
87
+ * @param on true if phase is being activated, false if deactivated
88
+ */
89
+ virtual void setPhase(int phase, bool on) = 0;
90
+
91
+ /**
92
+ * Get the current quarter-track position (0-139)
93
+ * This is for display/debugging purposes only.
94
+ * @return Current quarter-track position
95
+ */
96
+ virtual int getQuarterTrack() const = 0;
97
+
98
+ /**
99
+ * Get the current track position (0-34)
100
+ * This is for display/debugging purposes only.
101
+ * @return Current track number (quarter_track / 4)
102
+ */
103
+ virtual int getTrack() const = 0;
104
+
105
+ /**
106
+ * Set the quarter-track position directly (for state restoration)
107
+ * @param quarter_track Quarter-track position (0-139)
108
+ */
109
+ virtual void setQuarterTrack(int quarter_track) = 0;
110
+
111
+ // ===== Geometry =====
112
+
113
+ /**
114
+ * Get the number of tracks on the disk
115
+ * Standard 5.25" disks have 35 tracks (0-34)
116
+ * @return Number of tracks
117
+ */
118
+ virtual int getTrackCount() const = 0;
119
+
120
+ /**
121
+ * Check if current head position has data
122
+ * @return true if the current position has data
123
+ */
124
+ virtual bool hasData() const = 0;
125
+
126
+ // ===== Data Access =====
127
+
128
+ /**
129
+ * Advance the bit position based on elapsed CPU cycles
130
+ * This simulates the disk rotating while the motor is on.
131
+ * Call this before reading to account for disk rotation during
132
+ * the time since the last read.
133
+ *
134
+ * @param current_cycles Current total CPU cycle count
135
+ */
136
+ virtual void advanceBitPosition(uint64_t current_cycles) = 0;
137
+
138
+ /**
139
+ * Read a nibble from the disk at the current position
140
+ * This simulates the disk read head reading data.
141
+ * The bit position advances as bits are read until a complete
142
+ * nibble (byte with high bit set) is assembled.
143
+ *
144
+ * @return The nibble read (high bit set for valid data)
145
+ */
146
+ virtual uint8_t readNibble() = 0;
147
+
148
+ // ===== Write Operations =====
149
+
150
+ /**
151
+ * Write a nibble to the disk at the current position
152
+ * This simulates the disk write head writing data.
153
+ * The bit position advances as bits are written.
154
+ *
155
+ * @param nibble The nibble to write (should have high bit set for valid GCR
156
+ * data)
157
+ */
158
+ virtual void writeNibble(uint8_t nibble) = 0;
159
+
160
+ /**
161
+ * Read a single bit from the disk at the current position
162
+ * Advances the bit position by one.
163
+ * Used by the Logic State Sequencer for cycle-accurate disk access.
164
+ *
165
+ * @return 0 or 1
166
+ */
167
+ virtual uint8_t readBit() = 0;
168
+
169
+ /**
170
+ * Write a single bit to the disk at the current position
171
+ * Advances the bit position by one.
172
+ * Used by the Logic State Sequencer for cycle-accurate disk access.
173
+ *
174
+ * @param bit The bit value (0 or 1)
175
+ */
176
+ virtual void writeBit(uint8_t bit) = 0;
177
+
178
+ // ===== Status =====
179
+
180
+ /**
181
+ * Check if the disk is write-protected
182
+ * @return true if write-protected
183
+ */
184
+ virtual bool isWriteProtected() const = 0;
185
+
186
+ /**
187
+ * Check if the disk has been modified
188
+ * @return true if modified since load
189
+ */
190
+ virtual bool isModified() const = 0;
191
+
192
+ /**
193
+ * Get a human-readable format name
194
+ * @return Format name string (e.g., "WOZ 2.0")
195
+ */
196
+ virtual std::string getFormatName() const = 0;
197
+
198
+ /**
199
+ * Get the raw sector data for saving (DSK format)
200
+ * @param size Output: size of the data
201
+ * @return Pointer to sector data, or nullptr if not available
202
+ */
203
+ virtual const uint8_t *getSectorData(size_t *size) const = 0;
204
+
205
+ /**
206
+ * Export disk data in its native format for saving
207
+ * This reconstructs the disk image file that can be saved to disk.
208
+ * The returned pointer is valid until the next call to exportData()
209
+ * or until the disk image is destroyed.
210
+ *
211
+ * @param size Output: size of the exported data
212
+ * @return Pointer to exported data, or nullptr if export not supported
213
+ */
214
+ virtual const uint8_t *exportData(size_t *size) = 0;
215
+
216
+ // ===== Debug Methods =====
217
+
218
+ /**
219
+ * Get a nibble at a specific track and position (debug only)
220
+ * @param track Track number (0-34)
221
+ * @param position Position in nibble stream
222
+ * @return Nibble value at that position
223
+ */
224
+ virtual uint8_t getNibbleAt(int track, int position) const = 0;
225
+
226
+ /**
227
+ * Get the number of nibbles in a track (debug only)
228
+ * @param track Track number (0-34)
229
+ * @return Number of nibbles in the track
230
+ */
231
+ virtual int getTrackNibbleCount(int track) const = 0;
232
+
233
+ /**
234
+ * Get the current nibble position within the track (debug only)
235
+ * @return Current nibble position
236
+ */
237
+ virtual size_t getCurrentNibblePosition() const = 0;
238
+
239
+ // ===== Reset =====
240
+
241
+ /**
242
+ * Reset runtime positioning state while preserving loaded disk data.
243
+ * Resets head position, phase states, bit position, and cycle counters
244
+ * back to initial values as if the disk was freshly inserted.
245
+ */
246
+ virtual void resetState() = 0;
247
+
248
+ // ===== Filename Tracking =====
249
+
250
+ /**
251
+ * Get the filename associated with this disk image
252
+ * @return Filename string
253
+ */
254
+ const std::string &getFilename() const { return filename_; }
255
+
256
+ /**
257
+ * Set the filename associated with this disk image
258
+ * @param filename The filename to set
259
+ */
260
+ void setFilename(const std::string &filename) { filename_ = filename; }
261
+
262
+ protected:
263
+ DiskImage() = default;
264
+ std::string filename_;
265
+ };
266
+
267
+ } // namespace a2e