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,259 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* test_prodos.cpp - Unit tests for ProDOS filesystem parser
|
|
3
|
+
*
|
|
4
|
+
* Tests the ProDOS filesystem reader including:
|
|
5
|
+
* - Format detection (isProDOS)
|
|
6
|
+
* - Volume information parsing
|
|
7
|
+
* - Catalog reading
|
|
8
|
+
* - File data retrieval
|
|
9
|
+
* - File type mapping for viewer
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#define CATCH_CONFIG_MAIN
|
|
13
|
+
#include "catch.hpp"
|
|
14
|
+
|
|
15
|
+
#include "prodos.hpp"
|
|
16
|
+
#include "disk_image_builder.hpp"
|
|
17
|
+
|
|
18
|
+
#include <array>
|
|
19
|
+
#include <cstring>
|
|
20
|
+
#include <vector>
|
|
21
|
+
|
|
22
|
+
using namespace a2e;
|
|
23
|
+
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// isProDOS - Format detection
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
TEST_CASE("isProDOS returns true for valid ProDOS image", "[prodos][detection]") {
|
|
29
|
+
test::ProDOSDiskBuilder builder("TESTDISK");
|
|
30
|
+
REQUIRE(ProDOS::isProDOS(builder.data(), builder.size()));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
TEST_CASE("isProDOS returns false for zeroed data", "[prodos][detection]") {
|
|
34
|
+
std::vector<uint8_t> zeroed(143360, 0x00);
|
|
35
|
+
REQUIRE_FALSE(ProDOS::isProDOS(zeroed.data(), zeroed.size()));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
TEST_CASE("isProDOS returns false for too-small data", "[prodos][detection]") {
|
|
39
|
+
std::vector<uint8_t> small(512, 0x00);
|
|
40
|
+
REQUIRE_FALSE(ProDOS::isProDOS(small.data(), small.size()));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
TEST_CASE("isProDOS returns false for null pointer", "[prodos][detection]") {
|
|
44
|
+
REQUIRE_FALSE(ProDOS::isProDOS(nullptr, 0));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// parseVolumeInfo - Volume information
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
TEST_CASE("parseVolumeInfo returns correct volume name", "[prodos][volume]") {
|
|
52
|
+
test::ProDOSDiskBuilder builder("MYVOLUME");
|
|
53
|
+
|
|
54
|
+
ProDOSVolumeInfo info;
|
|
55
|
+
bool result = ProDOS::parseVolumeInfo(builder.data(), builder.size(), &info);
|
|
56
|
+
REQUIRE(result);
|
|
57
|
+
CHECK(std::string(info.volumeName) == "MYVOLUME");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
TEST_CASE("parseVolumeInfo returns correct total blocks", "[prodos][volume]") {
|
|
61
|
+
test::ProDOSDiskBuilder builder("TEST");
|
|
62
|
+
|
|
63
|
+
ProDOSVolumeInfo info;
|
|
64
|
+
bool result = ProDOS::parseVolumeInfo(builder.data(), builder.size(), &info);
|
|
65
|
+
REQUIRE(result);
|
|
66
|
+
CHECK(info.totalBlocks == 280);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
TEST_CASE("parseVolumeInfo file count reflects added files", "[prodos][volume]") {
|
|
70
|
+
test::ProDOSDiskBuilder builder("TEST");
|
|
71
|
+
|
|
72
|
+
const uint8_t data1[] = "FIRST FILE";
|
|
73
|
+
const uint8_t data2[] = "SECOND FILE";
|
|
74
|
+
builder.addFile("FILE1", 0x04, 0x0000, data1, sizeof(data1));
|
|
75
|
+
builder.addFile("FILE2", 0x04, 0x0000, data2, sizeof(data2));
|
|
76
|
+
|
|
77
|
+
ProDOSVolumeInfo info;
|
|
78
|
+
bool result = ProDOS::parseVolumeInfo(builder.data(), builder.size(), &info);
|
|
79
|
+
REQUIRE(result);
|
|
80
|
+
CHECK(info.fileCount == 2);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
TEST_CASE("parseVolumeInfo returns false for zeroed data", "[prodos][volume]") {
|
|
84
|
+
std::vector<uint8_t> zeroed(143360, 0x00);
|
|
85
|
+
ProDOSVolumeInfo info;
|
|
86
|
+
REQUIRE_FALSE(ProDOS::parseVolumeInfo(zeroed.data(), zeroed.size(), &info));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// readCatalog - Catalog reading
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
TEST_CASE("readCatalog returns correct file count", "[prodos][catalog]") {
|
|
94
|
+
test::ProDOSDiskBuilder builder("TEST");
|
|
95
|
+
|
|
96
|
+
const uint8_t data[] = "HELLO";
|
|
97
|
+
builder.addFile("GREETING", 0x04, 0x0000, data, sizeof(data));
|
|
98
|
+
|
|
99
|
+
ProDOSCatalogEntry entries[32];
|
|
100
|
+
int count = ProDOS::readCatalog(builder.data(), builder.size(), entries, 32);
|
|
101
|
+
REQUIRE(count == 1);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
TEST_CASE("Catalog entry has correct filename", "[prodos][catalog]") {
|
|
105
|
+
test::ProDOSDiskBuilder builder("TEST");
|
|
106
|
+
|
|
107
|
+
const uint8_t data[] = "DATA";
|
|
108
|
+
builder.addFile("MYPROGRAM", 0xFC, 0x0801, data, sizeof(data));
|
|
109
|
+
|
|
110
|
+
ProDOSCatalogEntry entries[32];
|
|
111
|
+
int count = ProDOS::readCatalog(builder.data(), builder.size(), entries, 32);
|
|
112
|
+
REQUIRE(count == 1);
|
|
113
|
+
CHECK(std::string(entries[0].filename) == "MYPROGRAM");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
TEST_CASE("Catalog entry has correct file type", "[prodos][catalog]") {
|
|
117
|
+
test::ProDOSDiskBuilder builder("TEST");
|
|
118
|
+
|
|
119
|
+
const uint8_t data[] = "CONTENT";
|
|
120
|
+
builder.addFile("TEXTFILE", 0x04, 0x0000, data, sizeof(data)); // TXT
|
|
121
|
+
|
|
122
|
+
ProDOSCatalogEntry entries[32];
|
|
123
|
+
int count = ProDOS::readCatalog(builder.data(), builder.size(), entries, 32);
|
|
124
|
+
REQUIRE(count == 1);
|
|
125
|
+
CHECK(entries[0].fileType == 0x04);
|
|
126
|
+
CHECK(std::string(entries[0].fileTypeName) == "TXT");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
TEST_CASE("Catalog entry has correct auxType for binary", "[prodos][catalog]") {
|
|
130
|
+
test::ProDOSDiskBuilder builder("TEST");
|
|
131
|
+
|
|
132
|
+
const uint8_t data[] = {0xEA, 0x60}; // NOP RTS
|
|
133
|
+
builder.addFile("CODE", 0x06, 0x2000, data, sizeof(data)); // BIN at $2000
|
|
134
|
+
|
|
135
|
+
ProDOSCatalogEntry entries[32];
|
|
136
|
+
int count = ProDOS::readCatalog(builder.data(), builder.size(), entries, 32);
|
|
137
|
+
REQUIRE(count == 1);
|
|
138
|
+
CHECK(entries[0].fileType == 0x06);
|
|
139
|
+
CHECK(entries[0].auxType == 0x2000);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
TEST_CASE("readCatalog with empty disk returns zero", "[prodos][catalog]") {
|
|
143
|
+
test::ProDOSDiskBuilder builder("EMPTY");
|
|
144
|
+
|
|
145
|
+
ProDOSCatalogEntry entries[32];
|
|
146
|
+
int count = ProDOS::readCatalog(builder.data(), builder.size(), entries, 32);
|
|
147
|
+
REQUIRE(count == 0);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
TEST_CASE("Multiple files in ProDOS catalog", "[prodos][catalog]") {
|
|
151
|
+
test::ProDOSDiskBuilder builder("MULTI");
|
|
152
|
+
|
|
153
|
+
const uint8_t d1[] = "AAA";
|
|
154
|
+
const uint8_t d2[] = "BBB";
|
|
155
|
+
const uint8_t d3[] = "CCC";
|
|
156
|
+
builder.addFile("ALPHA", 0x04, 0x0000, d1, sizeof(d1));
|
|
157
|
+
builder.addFile("BETA", 0x06, 0x2000, d2, sizeof(d2));
|
|
158
|
+
builder.addFile("GAMMA", 0xFC, 0x0801, d3, sizeof(d3));
|
|
159
|
+
|
|
160
|
+
ProDOSCatalogEntry entries[32];
|
|
161
|
+
int count = ProDOS::readCatalog(builder.data(), builder.size(), entries, 32);
|
|
162
|
+
REQUIRE(count == 3);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
TEST_CASE("Catalog entry EOF matches data length", "[prodos][catalog]") {
|
|
166
|
+
test::ProDOSDiskBuilder builder("TEST");
|
|
167
|
+
|
|
168
|
+
std::vector<uint8_t> data(100, 0x42);
|
|
169
|
+
builder.addFile("HUNDRED", 0x04, 0x0000, data.data(), static_cast<int>(data.size()));
|
|
170
|
+
|
|
171
|
+
ProDOSCatalogEntry entries[32];
|
|
172
|
+
int count = ProDOS::readCatalog(builder.data(), builder.size(), entries, 32);
|
|
173
|
+
REQUIRE(count == 1);
|
|
174
|
+
CHECK(entries[0].eof == 100);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// readFile - File data retrieval
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
|
|
181
|
+
TEST_CASE("readFile retrieves correct data for seedling file", "[prodos][readFile]") {
|
|
182
|
+
test::ProDOSDiskBuilder builder("TEST");
|
|
183
|
+
|
|
184
|
+
std::vector<uint8_t> fileData(64);
|
|
185
|
+
for (int i = 0; i < 64; i++) {
|
|
186
|
+
fileData[i] = static_cast<uint8_t>(i);
|
|
187
|
+
}
|
|
188
|
+
builder.addFile("SEQDATA", 0x06, 0x0300, fileData.data(),
|
|
189
|
+
static_cast<int>(fileData.size()));
|
|
190
|
+
|
|
191
|
+
ProDOSCatalogEntry entries[32];
|
|
192
|
+
int count = ProDOS::readCatalog(builder.data(), builder.size(), entries, 32);
|
|
193
|
+
REQUIRE(count == 1);
|
|
194
|
+
|
|
195
|
+
std::vector<uint8_t> outBuf(512, 0);
|
|
196
|
+
int bytesRead = ProDOS::readFile(builder.data(), builder.size(),
|
|
197
|
+
&entries[0], outBuf.data(),
|
|
198
|
+
static_cast<int>(outBuf.size()));
|
|
199
|
+
REQUIRE(bytesRead == 64);
|
|
200
|
+
|
|
201
|
+
// Verify first bytes match
|
|
202
|
+
for (int i = 0; i < 64; i++) {
|
|
203
|
+
INFO("Byte at offset " << i);
|
|
204
|
+
CHECK(outBuf[i] == static_cast<uint8_t>(i));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
TEST_CASE("readFile returns zero for empty entry", "[prodos][readFile]") {
|
|
209
|
+
test::ProDOSDiskBuilder builder("TEST");
|
|
210
|
+
|
|
211
|
+
ProDOSCatalogEntry emptyEntry;
|
|
212
|
+
memset(&emptyEntry, 0, sizeof(emptyEntry));
|
|
213
|
+
|
|
214
|
+
std::vector<uint8_t> outBuf(512, 0);
|
|
215
|
+
int bytesRead = ProDOS::readFile(builder.data(), builder.size(),
|
|
216
|
+
&emptyEntry, outBuf.data(),
|
|
217
|
+
static_cast<int>(outBuf.size()));
|
|
218
|
+
CHECK(bytesRead == 0);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
// mapFileTypeForViewer - File type mapping
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
|
|
225
|
+
TEST_CASE("mapFileTypeForViewer maps TXT to text viewer", "[prodos][fileType]") {
|
|
226
|
+
// TXT (0x04) should map to text viewer type (0)
|
|
227
|
+
int viewerType = ProDOS::mapFileTypeForViewer(0x04);
|
|
228
|
+
CHECK(viewerType == 0);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
TEST_CASE("mapFileTypeForViewer maps BIN to hex viewer", "[prodos][fileType]") {
|
|
232
|
+
// BIN (0x06) should map to hex/binary viewer type (4)
|
|
233
|
+
int viewerType = ProDOS::mapFileTypeForViewer(0x06);
|
|
234
|
+
CHECK(viewerType == 4);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
TEST_CASE("mapFileTypeForViewer maps BAS to BASIC viewer", "[prodos][fileType]") {
|
|
238
|
+
// BAS (0xFC) should map to BASIC viewer type (2)
|
|
239
|
+
int viewerType = ProDOS::mapFileTypeForViewer(0xFC);
|
|
240
|
+
CHECK(viewerType == 2);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
TEST_CASE("mapFileTypeForViewer returns -1 for unknown type", "[prodos][fileType]") {
|
|
244
|
+
// Unknown/unmapped type should return -1
|
|
245
|
+
int viewerType = ProDOS::mapFileTypeForViewer(0x0F);
|
|
246
|
+
CHECK(viewerType == -1);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
TEST_CASE("mapFileTypeForViewer maps SYS to binary viewer", "[prodos][fileType]") {
|
|
250
|
+
// SYS (0xFF) should map to binary viewer type (4)
|
|
251
|
+
int sysType = ProDOS::mapFileTypeForViewer(0xFF);
|
|
252
|
+
CHECK(sysType == 4);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
TEST_CASE("mapFileTypeForViewer maps INT to Integer BASIC viewer", "[prodos][fileType]") {
|
|
256
|
+
// INT (0xFA) -> Integer BASIC viewer (1)
|
|
257
|
+
int intType = ProDOS::mapFileTypeForViewer(0xFA);
|
|
258
|
+
CHECK(intType == 1);
|
|
259
|
+
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* test_smartport_card.cpp - Unit tests for SmartPortCard
|
|
3
|
+
*
|
|
4
|
+
* Tests the SmartPort hard drive controller card including:
|
|
5
|
+
* - Construction
|
|
6
|
+
* - Card metadata (name, preferred slot)
|
|
7
|
+
* - No device initially: hasROM false, no images inserted
|
|
8
|
+
* - Image insert/eject operations
|
|
9
|
+
* - Filename tracking
|
|
10
|
+
* - Slot number configuration
|
|
11
|
+
* - Activity tracking
|
|
12
|
+
* - hasROM becomes true when a device is present
|
|
13
|
+
* - Serialization round-trip
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
#define CATCH_CONFIG_MAIN
|
|
17
|
+
#include "catch.hpp"
|
|
18
|
+
|
|
19
|
+
#include "smartport_card.hpp"
|
|
20
|
+
|
|
21
|
+
#include <cstring>
|
|
22
|
+
#include <vector>
|
|
23
|
+
|
|
24
|
+
using namespace a2e;
|
|
25
|
+
|
|
26
|
+
// Helper: create minimal block data (one block = 512 bytes minimum)
|
|
27
|
+
static std::vector<uint8_t> createMinimalImage(size_t blocks = 280) {
|
|
28
|
+
return std::vector<uint8_t>(blocks * 512, 0x00);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Construction
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
TEST_CASE("SmartPortCard constructor creates valid instance", "[smartport]") {
|
|
36
|
+
SmartPortCard card;
|
|
37
|
+
REQUIRE(card.getName() != nullptr);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Card metadata
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
TEST_CASE("SmartPortCard getName returns SmartPort", "[smartport]") {
|
|
45
|
+
SmartPortCard card;
|
|
46
|
+
REQUIRE(std::string(card.getName()) == "SmartPort");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
TEST_CASE("SmartPortCard getPreferredSlot returns 7", "[smartport]") {
|
|
50
|
+
SmartPortCard card;
|
|
51
|
+
REQUIRE(card.getPreferredSlot() == 7);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// No device initially
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
TEST_CASE("SmartPortCard hasROM false when no device present", "[smartport]") {
|
|
59
|
+
SmartPortCard card;
|
|
60
|
+
// hasROM() depends on hasAnyDevice() which should be false with no images
|
|
61
|
+
REQUIRE_FALSE(card.hasROM());
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
TEST_CASE("SmartPortCard no images inserted initially", "[smartport]") {
|
|
65
|
+
SmartPortCard card;
|
|
66
|
+
REQUIRE_FALSE(card.isImageInserted(0));
|
|
67
|
+
REQUIRE_FALSE(card.isImageInserted(1));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Image insert
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
TEST_CASE("SmartPortCard insertImage makes isImageInserted true", "[smartport]") {
|
|
75
|
+
SmartPortCard card;
|
|
76
|
+
auto data = createMinimalImage();
|
|
77
|
+
|
|
78
|
+
bool result = card.insertImage(0, data.data(), data.size(), "test.hdv");
|
|
79
|
+
REQUIRE(result);
|
|
80
|
+
REQUIRE(card.isImageInserted(0));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
TEST_CASE("SmartPortCard insertImage into device 1", "[smartport]") {
|
|
84
|
+
SmartPortCard card;
|
|
85
|
+
auto data = createMinimalImage();
|
|
86
|
+
|
|
87
|
+
bool result = card.insertImage(1, data.data(), data.size(), "disk2.hdv");
|
|
88
|
+
REQUIRE(result);
|
|
89
|
+
REQUIRE(card.isImageInserted(1));
|
|
90
|
+
REQUIRE_FALSE(card.isImageInserted(0)); // device 0 still empty
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
TEST_CASE("SmartPortCard hasROM becomes true after insertImage", "[smartport]") {
|
|
94
|
+
SmartPortCard card;
|
|
95
|
+
REQUIRE_FALSE(card.hasROM());
|
|
96
|
+
|
|
97
|
+
auto data = createMinimalImage();
|
|
98
|
+
card.insertImage(0, data.data(), data.size(), "prodos.hdv");
|
|
99
|
+
|
|
100
|
+
REQUIRE(card.hasROM());
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Image filename
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
TEST_CASE("SmartPortCard getImageFilename returns inserted filename", "[smartport]") {
|
|
108
|
+
SmartPortCard card;
|
|
109
|
+
auto data = createMinimalImage();
|
|
110
|
+
|
|
111
|
+
card.insertImage(0, data.data(), data.size(), "myvolume.po");
|
|
112
|
+
REQUIRE(card.getImageFilename(0) == "myvolume.po");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
TEST_CASE("SmartPortCard getImageFilename returns empty when no image", "[smartport]") {
|
|
116
|
+
SmartPortCard card;
|
|
117
|
+
REQUIRE(card.getImageFilename(0).empty());
|
|
118
|
+
REQUIRE(card.getImageFilename(1).empty());
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Image eject
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
TEST_CASE("SmartPortCard ejectImage makes isImageInserted false", "[smartport]") {
|
|
126
|
+
SmartPortCard card;
|
|
127
|
+
auto data = createMinimalImage();
|
|
128
|
+
|
|
129
|
+
card.insertImage(0, data.data(), data.size(), "test.hdv");
|
|
130
|
+
REQUIRE(card.isImageInserted(0));
|
|
131
|
+
|
|
132
|
+
card.ejectImage(0);
|
|
133
|
+
REQUIRE_FALSE(card.isImageInserted(0));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
TEST_CASE("SmartPortCard ejectImage clears filename", "[smartport]") {
|
|
137
|
+
SmartPortCard card;
|
|
138
|
+
auto data = createMinimalImage();
|
|
139
|
+
|
|
140
|
+
card.insertImage(0, data.data(), data.size(), "test.hdv");
|
|
141
|
+
card.ejectImage(0);
|
|
142
|
+
REQUIRE(card.getImageFilename(0).empty());
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
TEST_CASE("SmartPortCard hasROM becomes false after ejecting all devices", "[smartport]") {
|
|
146
|
+
SmartPortCard card;
|
|
147
|
+
auto data = createMinimalImage();
|
|
148
|
+
|
|
149
|
+
card.insertImage(0, data.data(), data.size(), "test.hdv");
|
|
150
|
+
REQUIRE(card.hasROM());
|
|
151
|
+
|
|
152
|
+
card.ejectImage(0);
|
|
153
|
+
REQUIRE_FALSE(card.hasROM());
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
// Slot number
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
|
|
160
|
+
TEST_CASE("SmartPortCard default slot number is 7", "[smartport]") {
|
|
161
|
+
SmartPortCard card;
|
|
162
|
+
REQUIRE(card.getSlotNumber() == 7);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
TEST_CASE("SmartPortCard setSlotNumber changes slot", "[smartport]") {
|
|
166
|
+
SmartPortCard card;
|
|
167
|
+
|
|
168
|
+
card.setSlotNumber(5);
|
|
169
|
+
REQUIRE(card.getSlotNumber() == 5);
|
|
170
|
+
|
|
171
|
+
card.setSlotNumber(2);
|
|
172
|
+
REQUIRE(card.getSlotNumber() == 2);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// Activity tracking
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
|
|
179
|
+
TEST_CASE("SmartPortCard hasActivity is false initially", "[smartport]") {
|
|
180
|
+
SmartPortCard card;
|
|
181
|
+
REQUIRE_FALSE(card.hasActivity());
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
TEST_CASE("SmartPortCard clearActivity does not crash when no activity", "[smartport]") {
|
|
185
|
+
SmartPortCard card;
|
|
186
|
+
card.clearActivity();
|
|
187
|
+
REQUIRE_FALSE(card.hasActivity());
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
// Reset
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
|
|
194
|
+
TEST_CASE("SmartPortCard reset does not crash", "[smartport]") {
|
|
195
|
+
SmartPortCard card;
|
|
196
|
+
auto data = createMinimalImage();
|
|
197
|
+
card.insertImage(0, data.data(), data.size(), "test.hdv");
|
|
198
|
+
|
|
199
|
+
card.reset();
|
|
200
|
+
// Image should still be inserted after reset (reset clears state, not images)
|
|
201
|
+
REQUIRE(card.isImageInserted(0));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
// I/O space
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
|
|
208
|
+
TEST_CASE("SmartPortCard readIO returns a value without crash", "[smartport]") {
|
|
209
|
+
SmartPortCard card;
|
|
210
|
+
uint8_t val = card.readIO(0x00);
|
|
211
|
+
(void)val;
|
|
212
|
+
REQUIRE(true);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
TEST_CASE("SmartPortCard writeIO does not crash", "[smartport]") {
|
|
216
|
+
SmartPortCard card;
|
|
217
|
+
card.writeIO(0x00, 0x55);
|
|
218
|
+
REQUIRE(true);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
TEST_CASE("SmartPortCard peekIO returns 0xFF", "[smartport]") {
|
|
222
|
+
SmartPortCard card;
|
|
223
|
+
REQUIRE(card.peekIO(0x00) == 0xFF);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
// Serialization round-trip
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
|
|
230
|
+
TEST_CASE("SmartPortCard getStateSize is greater than zero when image loaded", "[smartport]") {
|
|
231
|
+
SmartPortCard card;
|
|
232
|
+
auto data = createMinimalImage();
|
|
233
|
+
card.insertImage(0, data.data(), data.size(), "test.hdv");
|
|
234
|
+
|
|
235
|
+
REQUIRE(card.getStateSize() > 0);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
TEST_CASE("SmartPortCard serialize/deserialize round-trip", "[smartport]") {
|
|
239
|
+
SmartPortCard card1;
|
|
240
|
+
auto data = createMinimalImage();
|
|
241
|
+
card1.insertImage(0, data.data(), data.size(), "saved.hdv");
|
|
242
|
+
card1.setSlotNumber(5);
|
|
243
|
+
|
|
244
|
+
// Serialize
|
|
245
|
+
size_t stateSize = card1.getStateSize();
|
|
246
|
+
std::vector<uint8_t> buffer(stateSize);
|
|
247
|
+
size_t written = card1.serialize(buffer.data(), buffer.size());
|
|
248
|
+
REQUIRE(written > 0);
|
|
249
|
+
REQUIRE(written <= stateSize);
|
|
250
|
+
|
|
251
|
+
// Deserialize
|
|
252
|
+
SmartPortCard card2;
|
|
253
|
+
size_t consumed = card2.deserialize(buffer.data(), written);
|
|
254
|
+
REQUIRE(consumed > 0);
|
|
255
|
+
|
|
256
|
+
// Verify image and filename were preserved
|
|
257
|
+
REQUIRE(card2.isImageInserted(0));
|
|
258
|
+
REQUIRE(card2.getImageFilename(0) == "saved.hdv");
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ---------------------------------------------------------------------------
|
|
262
|
+
// Multiple devices
|
|
263
|
+
// ---------------------------------------------------------------------------
|
|
264
|
+
|
|
265
|
+
TEST_CASE("SmartPortCard supports two devices simultaneously", "[smartport]") {
|
|
266
|
+
SmartPortCard card;
|
|
267
|
+
auto data1 = createMinimalImage(280);
|
|
268
|
+
auto data2 = createMinimalImage(560);
|
|
269
|
+
|
|
270
|
+
card.insertImage(0, data1.data(), data1.size(), "disk1.hdv");
|
|
271
|
+
card.insertImage(1, data2.data(), data2.size(), "disk2.hdv");
|
|
272
|
+
|
|
273
|
+
REQUIRE(card.isImageInserted(0));
|
|
274
|
+
REQUIRE(card.isImageInserted(1));
|
|
275
|
+
REQUIRE(card.getImageFilename(0) == "disk1.hdv");
|
|
276
|
+
REQUIRE(card.getImageFilename(1) == "disk2.hdv");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
TEST_CASE("SmartPortCard eject one device keeps the other", "[smartport]") {
|
|
280
|
+
SmartPortCard card;
|
|
281
|
+
auto data1 = createMinimalImage();
|
|
282
|
+
auto data2 = createMinimalImage();
|
|
283
|
+
|
|
284
|
+
card.insertImage(0, data1.data(), data1.size(), "disk1.hdv");
|
|
285
|
+
card.insertImage(1, data2.data(), data2.size(), "disk2.hdv");
|
|
286
|
+
|
|
287
|
+
card.ejectImage(0);
|
|
288
|
+
|
|
289
|
+
REQUIRE_FALSE(card.isImageInserted(0));
|
|
290
|
+
REQUIRE(card.isImageInserted(1));
|
|
291
|
+
// hasROM should still be true because device 1 is present
|
|
292
|
+
REQUIRE(card.hasROM());
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
// MAX_DEVICES constant
|
|
297
|
+
// ---------------------------------------------------------------------------
|
|
298
|
+
|
|
299
|
+
TEST_CASE("SmartPortCard MAX_DEVICES is 2", "[smartport]") {
|
|
300
|
+
REQUIRE(SmartPortCard::MAX_DEVICES == 2);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ---------------------------------------------------------------------------
|
|
304
|
+
// ROM access with device loaded
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
|
|
307
|
+
TEST_CASE("SmartPortCard readROM returns valid data when device loaded", "[smartport]") {
|
|
308
|
+
SmartPortCard card;
|
|
309
|
+
auto data = createMinimalImage();
|
|
310
|
+
card.insertImage(0, data.data(), data.size(), "test.hdv");
|
|
311
|
+
|
|
312
|
+
// The self-built ROM should not be all zeros
|
|
313
|
+
bool allZero = true;
|
|
314
|
+
for (int i = 0; i < 256; ++i) {
|
|
315
|
+
if (card.readROM(static_cast<uint8_t>(i)) != 0x00) {
|
|
316
|
+
allZero = false;
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
REQUIRE_FALSE(allZero);
|
|
321
|
+
}
|