diff --git a/Cargo.lock b/Cargo.lock index d53ff5b..5fd00c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,12 +141,28 @@ dependencies = [ ] [[package]] -name = "gba-rust" +name = "gameboy-rust-desktop" version = "0.1.0" dependencies = [ + "gba-core", + "gba-demos", "minifb", ] +[[package]] +name = "gba-core" +version = "0.1.0" +dependencies = [ + "gba-demos", +] + +[[package]] +name = "gba-demos" +version = "0.1.0" +dependencies = [ + "gba-core", +] + [[package]] name = "instant" version = "0.1.13" diff --git a/Cargo.toml b/Cargo.toml index bec53f0..bba8f91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,8 @@ -[package] -name = "gba-rust" +[workspace] +resolver = "2" +members = ["crates/gba-core", "crates/gba-demos", "crates/desktop"] + +[workspace.package] version = "0.1.0" edition = "2021" publish = false - -[features] -default = ["desktop"] -desktop = ["dep:minifb"] - -[dependencies] -# Pinned because src/desktop.rs corrects a macOS focus bug in this version. -minifb = { version = "=0.28.0", optional = true, default-features = false, features = ["x11"] } - -[[bin]] -name = "gba-rust" -path = "src/main.rs" -required-features = ["desktop"] diff --git a/README.md b/README.md index 1364c53..07ee013 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ -# gba-rust +# gameboy-rust -A small Game Boy Advance (GBA) emulator foundation written in Rust. -The core has no external Rust dependencies when built with `--no-default-features`. -The default `desktop` feature adds minifb for a native window. +Game Boy family emulation in Rust. The Game Boy Advance (GBA) is the first and currently only system. +This is a small GBA emulator foundation, organized as a Cargo workspace: + +- `crates/gba-core`: the platform-independent emulator, with no external Rust dependencies. +- `crates/gba-demos`: original test programs that drive the core. +- `crates/desktop`: the native window frontend, built on minifb. It provides the `gameboy-rust` executable. **This cannot run Pokémon Emerald or other games yet.** The CPU-driven demos run original ARM code through emulated video RAM. @@ -279,7 +282,7 @@ From this project directory: direnv allow cargo run cargo test -cargo fmt --check +cargo fmt --all --check cargo clippy --all-targets -- -D warnings ``` @@ -303,7 +306,7 @@ The flake sets Darwin-only `CFLAGS` to correct two minifb 0.28 native-build issu Build through direnv or `nix develop` so these settings apply. The window runs on the main thread, as required by macOS AppKit. -`src/desktop.rs` also corrects the inverted macOS focus result in minifb 0.28.0. +`crates/desktop/src/desktop.rs` also corrects the inverted macOS focus result in minifb 0.28.0. The dependency is pinned to that exact version. Review this workaround before upgrading minifb. Intel macOS and Linux desktop builds are not verified. @@ -477,7 +480,7 @@ Neither constructor provides Nintendo BIOS services or initializes BIOS-managed ### Optional original BIOS replacement -`src/bios.rs` builds a deterministic 16 KiB image from original ARM instructions and mathematically generated data. +`crates/gba-core/src/bios.rs` builds a deterministic 16 KiB image from original ARM instructions and mathematically generated data. No Nintendo firmware bytes are included. A compile-time integer calculation generates the 512-byte sine table at `0x3e00..0x3fff`. The image builder checks that code and literal pools do not overlap this table. @@ -1632,100 +1635,102 @@ Important timing limits: | --- | --- | | `flake.nix`, `flake.lock` | Pinned development environment | | `.envrc` | Automatic environment loading through direnv | -| `src/cpu.rs` | Registers, flags, instruction-set state, and stepping | -| `src/cpu/arm.rs` | ARM decoding, data processing, transfers, branches, and multiply | -| `src/cpu/alu.rs` | Shared arithmetic and barrel shifter | -| `src/cpu/transfer.rs` | Shared ARM/Thumb block transfers and ARM swaps | -| `src/cpu/thumb.rs` | Thumb decoding and execution | -| `src/cpu/status.rs` | Processor modes, register banks, and status transfers | -| `src/cpu/exception.rs` | Reset state, exception entry, and interrupt sampling | -| `src/cpu/status_tests.rs`, `src/cpu/exception_tests.rs` | Status, banking, exception, and return tests | -| `src/cpu/thumb_tests.rs` | Thumb instructions, state switching, and decoder checks | -| `src/cpu/transfer_tests.rs` | Stack, addressing, overlap, empty-list, and swap tests | -| `src/cpu/tests.rs` | Condition truth tables and immediate arithmetic tests | -| `src/cpu/instruction_tests.rs` | Register operations, transfers, branches, and edge cases | -| `src/memory.rs` | Memory mapping, I/O routing, write validation, and device clock | -| `src/io.rs` | I/O registers, timers, HALT wake-up, next-event bounds, and IRQ latches | -| `src/display.rs` | Display clock, scanline status, comparison edges, and display IRQ events | -| `src/dma.rs` | DMA registers, internal pointers, trigger state, priority, and completion IRQs | -| `src/machine.rs` | Timed CPU/DMA/device stepping and IRQ delivery | -| `src/timing.rs` | Bus widths, wait-state costs, and timing breakdowns | -| `src/cpu/timing.rs` | ARM/Thumb cycle summaries and data-access accounting | -| `src/cpu/timing_tests.rs` | Instruction timing and semantic-equivalence checks | -| `src/timer_demo.rs` | Original timer-configuration program and IRQ handler | -| `src/lib.rs` | Core modules and original demo bytes | -| `src/bios.rs` | Original ARM BIOS image builder, minimal boot, IRQ dispatch, waits, and memory services | -| `src/bios/reset.rs` | Emitted ARM SoftReset and selective RegisterRamReset; CPU banks, RAM clearing, and supported device-register resets | -| `src/bios/arithmetic.rs` | Emitted ARM division and integer-square-root routines | -| `src/bios/affine.rs` | Emitted ARM background/sprite matrix services, range checks, and generated sine table | -| `src/bios/angles.rs` | Emitted ARM ArcTan polynomial, ArcTan2 ratio/quadrant handling, and input validation | -| `src/bios/lz77.rs` | Emitted ARM LZ77 decoder with byte and halfword output | -| `src/bios/run_length.rs` | Emitted ARM run-length decoder, header validation, and block bounds | -| `src/bios/bit_unpack.rs` | Emitted ARM packed-unit expansion, offsets, word stores, and validation | -| `src/bios/decompression.rs` | Shared emitted byte/halfword output routine for decompression and byte differential filters | -| `src/bios/differential.rs` | Emitted ARM byte/halfword differential filters, modular accumulation, and validation | -| `src/bios/huffman.rs` | Emitted ARM Huffman tree traversal, symbol packing, word output, and validation | -| `src/video.rs` | Presentation buffer, RGB555 conversion, and Mode 0–5 composition | -| `src/video/affine.rs` | Programmed registers, internal scanline origins, and tiled/bitmap sampling | -| `src/video/windows.rs` | Persistent vertical window edge flags and constant-time clock advancement | -| `src/video/windows/horizontal.rs` | Horizontal comparator flags, per-column history, and bounded bulk advancement | -| `src/video/mosaic.rs` | Live vertical mosaic phase and constant-time counter transitions | -| `src/video/capture.rs` | Drawing/completed frame buffers, row completeness, and deferred render diagnostics | -| `src/video/sprites.rs` | Sprite index preparation, priority metadata, mosaic, late palette lookup, and composition | -| `src/video/sprites/pipeline.rs` | Two prepared row buffers, cycle40 events, and bounded capture-disabled advancement | -| `src/video/sprites/budget.rs` | Nominal per-row work allowance, partial canvas prefixes, and independent arithmetic tests | -| `src/input.rs` | Platform-independent GBA button state | -| `src/graphics_demo.rs` | Original ARM bitmap program and shared bounded frame runner | -| `src/tile_demo.rs` | Original ARM tile/sprite program, palettes, tiles, maps, and OAM image | -| `src/affine_demo.rs` | Shared ARM background program builder and Mode 2 assets | -| `src/affine_raster_demo.rs` | CPU-driven HBlank DMA affine distortion demo | -| `src/bitmap_demo.rs` | Mode 4/5 demo runners, palettes, and original two-page images | -| `src/effects_demo.rs` | CPU-driven window and color-effects demo runner | -| `src/mosaic_demo.rs` | CPU-driven background/sprite mosaic demo runner | -| `src/raster_demo.rs` | Original ARM HBlank DMA raster program and color table | -| `src/video/effects.rs` | Region masks and RGB555 alpha/brightness arithmetic | -| `src/desktop.rs` | Native window, display test, and keyboard controls | -| `src/desktop/affine.rs` | Affine background window and smoke-test pixel checks | -| `src/desktop/affine_raster.rs` | Affine raster window and every-pixel smoke checks | -| `src/desktop/bitmap.rs` | Mode 4/5 windows and page-flipping smoke-test pixel checks | -| `src/desktop/effects.rs` | Window/effects demo and independent smoke-test pixel checks | -| `src/desktop/mosaic.rs` | Mosaic window and 128-frame independent pixel checks | -| `src/desktop/raster.rs` | Raster window and scanline color-band smoke test | -| `src/main.rs` | Command-line modes and fixed-length CPU demo | -| `tests/core.rs` | CPU integration tests and the complete demo | -| `tests/memory.rs` | Memory widths, alignment, errors, and mirrors | -| `tests/exceptions.rs` | Exception demo, BIOS mapping, and reset-vector execution | -| `tests/timers.rs` | Timer rules, interrupt registers, and a cycle-by-cycle reference | -| `tests/machine.rs` | Device IRQ entry/return, clock policy, and I/O failure atomicity | -| `tests/timing.rs` | WAITCNT fields, bus costs, and timer/IRQ timing integration | -| `tests/graphics.rs` | Video memory, rendering, KEYINPUT, and CPU-driven graphics integration | -| `tests/tiles.rs` | Mode 0 registers, maps, palettes, composition, diagnostics, and CPU tile/sprite demo | -| `tests/affine_backgrounds.rs` | Affine registers, maps, transforms, bitmap sampling, composition, and CPU demo | -| `tests/affine_tracking.rs` | Internal origins, mid-frame writes, reloads, mosaic, DMA, and affine raster demo | -| `tests/bitmap_modes.rs` | Mode 4/5 pages, formats, transforms, transparency, sprites, and CPU demos | -| `tests/effects.rs`, `tests/effects/` | Window masks, color arithmetic, target selection, OBJ effects, DMA, and CPU demo | -| `tests/window_tracking.rs`, `tests/window_tracking/` | Vertical/horizontal edges, mid-line writes, hidden positions, DMA, masks, and capture independence | -| `tests/mosaic.rs`, `tests/mosaic/` | Mosaic sizes, sampling, transparent metadata, windows, DMA, and CPU demo | -| `tests/mosaic_tracking.rs` | Size changes, counter wrap, text/affine/OBJ sampling, DMA, and frame resets | -| `tests/scanlines.rs`, `tests/scanlines/` | Capture boundaries, mid-frame changes, DMA ordering, diagnostics, and raster program | -| `tests/sprites.rs` | OAM, DMA, sprite sizes, mapping, palettes, flips, clipping, priorities, and diagnostics | -| `tests/sprite_pipeline.rs` | Preparation boundaries, OAM/VRAM history, late palette/effects, DMA, row0, and diagnostics | -| `tests/sprite_budget.rs` | Regular/affine costs, clipping policy, truncation, inspection, bit5 sampling, DMA, and diagnostics | -| `tests/sprites/affine.rs` | Affine matrices, drawing areas, signed sampling, shared groups, and floating-point reference tests | -| `tests/display.rs` | Display boundaries, register masks, IRQ handlers, and VBlank frame execution | -| `tests/dma.rs` | DMA widths, latches, priority, triggers, IRQs, timing, errors, and CPU integration | -| `tests/halt.rs` | HALT wake masks, idle timing, BIOS-only writes, DMA progress, and STOP diagnostics | -| `tests/bios.rs` | ARM/Thumb service calls, copy/fill boundaries, wait races, callback contracts, and boot | -| `tests/bios/ram_reset.rs` | Selective RAM boundaries, flag combinations, I/O reset, display rendering, DMA/timer latches, and diagnostics | -| `tests/bios/reset.rs` | All restart flags, exact RAM boundaries, CPU banks, restart execution, device continuity, and IRQ masking | -| `tests/bios/arithmetic.rs` | Arithmetic boundaries, wide-integer references, status restoration, and zero-division diagnostics | -| `tests/bios/affine.rs` | Matrix/origin references, all angle phases, strides, live rendering, register preservation, and diagnostics | -| `tests/bios/angles.rs` | Fixed-point references, axes/quadrants, rounding, caller flags, stack bounds, DMA, and diagnostics | -| `tests/bios/lz77.rs` | Token-reference tests, overlaps, output widths, malformed streams, and partial failures | -| `tests/bios/run_length.rs` | All block controls, mixed streams, output widths, status, diagnostics, DMA, and IRQ masking | -| `tests/bios/bit_unpack.rs` | Width pairs, bit references, offsets, maximum length, memory boundaries, status, DMA, and diagnostics | -| `tests/bios/differential.rs` | Round trips, wraparound, output widths, large lengths, partial failures, status, DMA, and diagnostics | -| `tests/bios/huffman.rs` | Independent path encoding, tree bounds, packing, large lengths, partial failures, status, and DMA | +| `crates/gba-core/src/cpu.rs` | Registers, flags, instruction-set state, and stepping | +| `crates/gba-core/src/cpu/arm.rs` | ARM decoding, data processing, transfers, branches, and multiply | +| `crates/gba-core/src/cpu/alu.rs` | Shared arithmetic and barrel shifter | +| `crates/gba-core/src/cpu/transfer.rs` | Shared ARM/Thumb block transfers and ARM swaps | +| `crates/gba-core/src/cpu/thumb.rs` | Thumb decoding and execution | +| `crates/gba-core/src/cpu/status.rs` | Processor modes, register banks, and status transfers | +| `crates/gba-core/src/cpu/exception.rs` | Reset state, exception entry, and interrupt sampling | +| `crates/gba-core/src/cpu/status_tests.rs`, `crates/gba-core/src/cpu/exception_tests.rs` | Status, banking, exception, and return tests | +| `crates/gba-core/src/cpu/thumb_tests.rs` | Thumb instructions, state switching, and decoder checks | +| `crates/gba-core/src/cpu/transfer_tests.rs` | Stack, addressing, overlap, empty-list, and swap tests | +| `crates/gba-core/src/cpu/tests.rs` | Condition truth tables and immediate arithmetic tests | +| `crates/gba-core/src/cpu/instruction_tests.rs` | Register operations, transfers, branches, and edge cases | +| `crates/gba-core/src/memory.rs` | Memory mapping, I/O routing, write validation, and device clock | +| `crates/gba-core/src/io.rs` | I/O registers, timers, HALT wake-up, next-event bounds, and IRQ latches | +| `crates/gba-core/src/display.rs` | Display clock, scanline status, comparison edges, and display IRQ events | +| `crates/gba-core/src/dma.rs` | DMA registers, internal pointers, trigger state, priority, and completion IRQs | +| `crates/gba-core/src/machine.rs` | Timed CPU/DMA/device stepping and IRQ delivery | +| `crates/gba-core/src/timing.rs` | Bus widths, wait-state costs, and timing breakdowns | +| `crates/gba-core/src/cpu/timing.rs` | ARM/Thumb cycle summaries and data-access accounting | +| `crates/gba-core/src/cpu/timing_tests.rs` | Instruction timing and semantic-equivalence checks | +| `crates/gba-demos/src/timer_demo.rs` | Original timer-configuration program and IRQ handler | +| `Cargo.toml` | Workspace members and shared package settings | +| `crates/gba-core/src/lib.rs` | Core modules | +| `crates/gba-demos/src/lib.rs` | Demo modules and original instruction/exception demo bytes | +| `crates/gba-core/src/bios.rs` | Original ARM BIOS image builder, minimal boot, IRQ dispatch, waits, and memory services | +| `crates/gba-core/src/bios/reset.rs` | Emitted ARM SoftReset and selective RegisterRamReset; CPU banks, RAM clearing, and supported device-register resets | +| `crates/gba-core/src/bios/arithmetic.rs` | Emitted ARM division and integer-square-root routines | +| `crates/gba-core/src/bios/affine.rs` | Emitted ARM background/sprite matrix services, range checks, and generated sine table | +| `crates/gba-core/src/bios/angles.rs` | Emitted ARM ArcTan polynomial, ArcTan2 ratio/quadrant handling, and input validation | +| `crates/gba-core/src/bios/lz77.rs` | Emitted ARM LZ77 decoder with byte and halfword output | +| `crates/gba-core/src/bios/run_length.rs` | Emitted ARM run-length decoder, header validation, and block bounds | +| `crates/gba-core/src/bios/bit_unpack.rs` | Emitted ARM packed-unit expansion, offsets, word stores, and validation | +| `crates/gba-core/src/bios/decompression.rs` | Shared emitted byte/halfword output routine for decompression and byte differential filters | +| `crates/gba-core/src/bios/differential.rs` | Emitted ARM byte/halfword differential filters, modular accumulation, and validation | +| `crates/gba-core/src/bios/huffman.rs` | Emitted ARM Huffman tree traversal, symbol packing, word output, and validation | +| `crates/gba-core/src/video.rs` | Presentation buffer, RGB555 conversion, and Mode 0–5 composition | +| `crates/gba-core/src/video/affine.rs` | Programmed registers, internal scanline origins, and tiled/bitmap sampling | +| `crates/gba-core/src/video/windows.rs` | Persistent vertical window edge flags and constant-time clock advancement | +| `crates/gba-core/src/video/windows/horizontal.rs` | Horizontal comparator flags, per-column history, and bounded bulk advancement | +| `crates/gba-core/src/video/mosaic.rs` | Live vertical mosaic phase and constant-time counter transitions | +| `crates/gba-core/src/video/capture.rs` | Drawing/completed frame buffers, row completeness, and deferred render diagnostics | +| `crates/gba-core/src/video/sprites.rs` | Sprite index preparation, priority metadata, mosaic, late palette lookup, and composition | +| `crates/gba-core/src/video/sprites/pipeline.rs` | Two prepared row buffers, cycle40 events, and bounded capture-disabled advancement | +| `crates/gba-core/src/video/sprites/budget.rs` | Nominal per-row work allowance, partial canvas prefixes, and independent arithmetic tests | +| `crates/gba-core/src/input.rs` | Platform-independent GBA button state | +| `crates/gba-demos/src/graphics_demo.rs` | Original ARM bitmap program and shared bounded frame runner | +| `crates/gba-demos/src/tile_demo.rs` | Original ARM tile/sprite program, palettes, tiles, maps, and OAM image | +| `crates/gba-demos/src/affine_demo.rs` | Shared ARM background program builder and Mode 2 assets | +| `crates/gba-demos/src/affine_raster_demo.rs` | CPU-driven HBlank DMA affine distortion demo | +| `crates/gba-demos/src/bitmap_demo.rs` | Mode 4/5 demo runners, palettes, and original two-page images | +| `crates/gba-demos/src/effects_demo.rs` | CPU-driven window and color-effects demo runner | +| `crates/gba-demos/src/mosaic_demo.rs` | CPU-driven background/sprite mosaic demo runner | +| `crates/gba-demos/src/raster_demo.rs` | Original ARM HBlank DMA raster program and color table | +| `crates/gba-core/src/video/effects.rs` | Region masks and RGB555 alpha/brightness arithmetic | +| `crates/desktop/src/desktop.rs` | Native window, display test, and keyboard controls | +| `crates/desktop/src/desktop/affine.rs` | Affine background window and smoke-test pixel checks | +| `crates/desktop/src/desktop/affine_raster.rs` | Affine raster window and every-pixel smoke checks | +| `crates/desktop/src/desktop/bitmap.rs` | Mode 4/5 windows and page-flipping smoke-test pixel checks | +| `crates/desktop/src/desktop/effects.rs` | Window/effects demo and independent smoke-test pixel checks | +| `crates/desktop/src/desktop/mosaic.rs` | Mosaic window and 128-frame independent pixel checks | +| `crates/desktop/src/desktop/raster.rs` | Raster window and scanline color-band smoke test | +| `crates/desktop/src/main.rs` | Command-line modes and fixed-length CPU demo | +| `crates/gba-core/tests/core.rs` | CPU integration tests and the complete demo | +| `crates/gba-core/tests/memory.rs` | Memory widths, alignment, errors, and mirrors | +| `crates/gba-core/tests/exceptions.rs` | Exception demo, BIOS mapping, and reset-vector execution | +| `crates/gba-core/tests/timers.rs` | Timer rules, interrupt registers, and a cycle-by-cycle reference | +| `crates/gba-core/tests/machine.rs` | Device IRQ entry/return, clock policy, and I/O failure atomicity | +| `crates/gba-core/tests/timing.rs` | WAITCNT fields, bus costs, and timer/IRQ timing integration | +| `crates/gba-core/tests/graphics.rs` | Video memory, rendering, KEYINPUT, and CPU-driven graphics integration | +| `crates/gba-core/tests/tiles.rs` | Mode 0 registers, maps, palettes, composition, diagnostics, and CPU tile/sprite demo | +| `crates/gba-core/tests/affine_backgrounds.rs` | Affine registers, maps, transforms, bitmap sampling, composition, and CPU demo | +| `crates/gba-core/tests/affine_tracking.rs` | Internal origins, mid-frame writes, reloads, mosaic, DMA, and affine raster demo | +| `crates/gba-core/tests/bitmap_modes.rs` | Mode 4/5 pages, formats, transforms, transparency, sprites, and CPU demos | +| `crates/gba-core/tests/effects.rs`, `crates/gba-core/tests/effects/` | Window masks, color arithmetic, target selection, OBJ effects, DMA, and CPU demo | +| `crates/gba-core/tests/window_tracking.rs`, `crates/gba-core/tests/window_tracking/` | Vertical/horizontal edges, mid-line writes, hidden positions, DMA, masks, and capture independence | +| `crates/gba-core/tests/mosaic.rs`, `crates/gba-core/tests/mosaic/` | Mosaic sizes, sampling, transparent metadata, windows, DMA, and CPU demo | +| `crates/gba-core/tests/mosaic_tracking.rs` | Size changes, counter wrap, text/affine/OBJ sampling, DMA, and frame resets | +| `crates/gba-core/tests/scanlines.rs`, `crates/gba-core/tests/scanlines/` | Capture boundaries, mid-frame changes, DMA ordering, diagnostics, and raster program | +| `crates/gba-core/tests/sprites.rs` | OAM, DMA, sprite sizes, mapping, palettes, flips, clipping, priorities, and diagnostics | +| `crates/gba-core/tests/sprite_pipeline.rs` | Preparation boundaries, OAM/VRAM history, late palette/effects, DMA, row0, and diagnostics | +| `crates/gba-core/tests/sprite_budget.rs` | Regular/affine costs, clipping policy, truncation, inspection, bit5 sampling, DMA, and diagnostics | +| `crates/gba-core/tests/sprites/affine.rs` | Affine matrices, drawing areas, signed sampling, shared groups, and floating-point reference tests | +| `crates/gba-core/tests/display.rs` | Display boundaries, register masks, IRQ handlers, and VBlank frame execution | +| `crates/gba-core/tests/dma.rs` | DMA widths, latches, priority, triggers, IRQs, timing, errors, and CPU integration | +| `crates/gba-core/tests/halt.rs` | HALT wake masks, idle timing, BIOS-only writes, DMA progress, and STOP diagnostics | +| `crates/gba-core/tests/bios.rs` | ARM/Thumb service calls, copy/fill boundaries, wait races, callback contracts, and boot | +| `crates/gba-core/tests/bios/ram_reset.rs` | Selective RAM boundaries, flag combinations, I/O reset, display rendering, DMA/timer latches, and diagnostics | +| `crates/gba-core/tests/bios/reset.rs` | All restart flags, exact RAM boundaries, CPU banks, restart execution, device continuity, and IRQ masking | +| `crates/gba-core/tests/bios/arithmetic.rs` | Arithmetic boundaries, wide-integer references, status restoration, and zero-division diagnostics | +| `crates/gba-core/tests/bios/affine.rs` | Matrix/origin references, all angle phases, strides, live rendering, register preservation, and diagnostics | +| `crates/gba-core/tests/bios/angles.rs` | Fixed-point references, axes/quadrants, rounding, caller flags, stack bounds, DMA, and diagnostics | +| `crates/gba-core/tests/bios/lz77.rs` | Token-reference tests, overlaps, output widths, malformed streams, and partial failures | +| `crates/gba-core/tests/bios/run_length.rs` | All block controls, mixed streams, output widths, status, diagnostics, DMA, and IRQ masking | +| `crates/gba-core/tests/bios/bit_unpack.rs` | Width pairs, bit references, offsets, maximum length, memory boundaries, status, DMA, and diagnostics | +| `crates/gba-core/tests/bios/differential.rs` | Round trips, wraparound, output widths, large lengths, partial failures, status, DMA, and diagnostics | +| `crates/gba-core/tests/bios/huffman.rs` | Independent path encoding, tree bounds, packing, large lengths, partial failures, status, and DMA | ## Deliberate limits @@ -1765,35 +1770,36 @@ Writes to cartridge addresses return errors instead of modeling cartridge hardwa Run native macOS validation from the project directory: ```sh -direnv exec . cargo fmt --check +direnv exec . cargo fmt --all --check direnv exec . cargo clippy --locked --all-targets -- -D warnings direnv exec . cargo test --locked direnv exec . cargo test --locked --release direnv exec . cargo build --locked --release -file target/release/gba-rust -./target/release/gba-rust --smoke-test -./target/release/gba-rust --graphics-smoke-test -./target/release/gba-rust --tile-smoke-test -./target/release/gba-rust --affine-smoke-test -./target/release/gba-rust --affine-raster-smoke-test -./target/release/gba-rust --bitmap4-smoke-test -./target/release/gba-rust --bitmap5-smoke-test -./target/release/gba-rust --effects-smoke-test -./target/release/gba-rust --mosaic-smoke-test -./target/release/gba-rust --raster-smoke-test -./target/release/gba-rust --cpu-demo -./target/release/gba-rust --timer-demo +file target/release/gameboy-rust +./target/release/gameboy-rust --smoke-test +./target/release/gameboy-rust --graphics-smoke-test +./target/release/gameboy-rust --tile-smoke-test +./target/release/gameboy-rust --affine-smoke-test +./target/release/gameboy-rust --affine-raster-smoke-test +./target/release/gameboy-rust --bitmap4-smoke-test +./target/release/gameboy-rust --bitmap5-smoke-test +./target/release/gameboy-rust --effects-smoke-test +./target/release/gameboy-rust --mosaic-smoke-test +./target/release/gameboy-rust --raster-smoke-test +./target/release/gameboy-rust --cpu-demo +./target/release/gameboy-rust --timer-demo ``` All ten window smoke tests need an active desktop session. Ordinary tests do not open windows. CPU-driven smoke tests supply scripted buttons; they do not validate physical keyboard events. -To test the core without building the window dependency: +To test the core and demo programs without building the window dependency: ```sh -direnv exec . cargo test --locked --no-default-features +direnv exec . cargo test --locked -p gba-core -p gba-demos ``` -This runs 709 core and integration tests; the eleven desktop and command-line tests are excluded. +This runs 709 core, demo, and integration tests; the eleven desktop and command-line tests are excluded. +The core's integration tests use `gba-demos` as a development dependency. On Apple Silicon, `file` must report a Mach-O `arm64` executable. Do not set a Linux cross-compilation target for this validation. diff --git a/crates/desktop/Cargo.toml b/crates/desktop/Cargo.toml new file mode 100644 index 0000000..15524ff --- /dev/null +++ b/crates/desktop/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "gameboy-rust-desktop" +version.workspace = true +edition.workspace = true +publish.workspace = true + +[[bin]] +name = "gameboy-rust" +path = "src/main.rs" + +[dependencies] +gba-core = { path = "../gba-core" } +gba-demos = { path = "../gba-demos" } +# Pinned because src/desktop.rs corrects a macOS focus bug in this version. +minifb = { version = "=0.28.0", default-features = false, features = ["x11"] } diff --git a/src/desktop.rs b/crates/desktop/src/desktop.rs similarity index 98% rename from src/desktop.rs rename to crates/desktop/src/desktop.rs index 34a685f..83cadbd 100644 --- a/src/desktop.rs +++ b/crates/desktop/src/desktop.rs @@ -19,13 +19,15 @@ use std::{ time::{Duration, Instant}, }; -use gba_rust::{ +use gba_core::{ display::{CPU_HZ, CYCLES_PER_FRAME, VISIBLE_LINES}, - graphics_demo::{GraphicsDemo, BACKGROUND, DEMO_STATE, SQUARE_SIZE}, input::{Button, Buttons}, - tile_demo::{TileDemo, TILE_STATE}, video::{rgb555_to_rgb888, Framebuffer, HEIGHT, WIDTH}, }; +use gba_demos::{ + graphics_demo::{GraphicsDemo, BACKGROUND, DEMO_STATE, SQUARE_SIZE}, + tile_demo::{TileDemo, TILE_STATE}, +}; use minifb::{Key, KeyRepeat, Scale, Window, WindowOptions}; const TITLE: &str = @@ -381,14 +383,14 @@ fn validate_tile_smoke( if memory.read32(TILE_STATE)? != index as u32 + 1 || memory.read32(TILE_STATE + 4)? != sx as u32 || memory.read32(TILE_STATE + 8)? != sy as u32 - || memory.read16(gba_rust::memory::OAM_START)? != if affine { 0x340 } else { 72 } - || memory.read16(gba_rust::memory::OAM_START + 2)? + || memory.read16(gba_core::memory::OAM_START)? != if affine { 0x340 } else { 72 } + || memory.read16(gba_core::memory::OAM_START + 2)? != if affine { 0x4068 } else { 0x4070 | if flipped { 0x1000 } else { 0 } } - || memory.read16(gba_rust::memory::OAM_START + 4)? != if behind { 0x400 } else { 0 } + || memory.read16(gba_core::memory::OAM_START + 4)? != if behind { 0x400 } else { 0 } || u32::from(position.scanline) != VISIBLE_LINES || u32::from(position.line_cycle) >= demo.machine().last_timing().total() { @@ -397,7 +399,7 @@ fn validate_tile_smoke( ); } for (i, value) in matrix.into_iter().enumerate() { - if memory.read16(gba_rust::memory::OAM_START + 6 + i as u32 * 8)? != value as u16 { + if memory.read16(gba_core::memory::OAM_START + 6 + i as u32 * 8)? != value as u16 { return Err(io::Error::other("tile smoke test: unexpected affine matrix").into()); } } diff --git a/src/desktop/affine.rs b/crates/desktop/src/desktop/affine.rs similarity index 97% rename from src/desktop/affine.rs rename to crates/desktop/src/desktop/affine.rs index 5654f81..73f63d7 100644 --- a/src/desktop/affine.rs +++ b/crates/desktop/src/desktop/affine.rs @@ -1,10 +1,10 @@ use super::{create_window, read_buttons}; -use gba_rust::{ - affine_demo::{AffineDemo, AFFINE_STATE}, +use gba_core::{ display::{CPU_HZ, CYCLES_PER_FRAME, VISIBLE_LINES}, input::{Button, Buttons}, video::{rgb555_to_rgb888, Framebuffer, HEIGHT, WIDTH}, }; +use gba_demos::affine_demo::{AffineDemo, AFFINE_STATE}; use minifb::Key; use std::{ error::Error, @@ -75,7 +75,7 @@ fn validate(demo: &AffineDemo, frame: &Framebuffer, index: usize) -> Result<(), if m.read32(AFFINE_STATE)? != index as u32 + 1 || m.read32(AFFINE_STATE + 4)? != pan_x as u32 || m.read32(AFFINE_STATE + 8)? != pan_y as u32 - || m.read16(gba_rust::io::BG2CNT)? != if clipped { 0x5000 } else { 0x7000 } + || m.read16(gba_core::io::BG2CNT)? != if clipped { 0x5000 } else { 0x7000 } || u32::from(position.scanline) != VISIBLE_LINES || u32::from(position.line_cycle) >= demo.machine().last_timing().total() { diff --git a/src/desktop/affine_raster.rs b/crates/desktop/src/desktop/affine_raster.rs similarity index 97% rename from src/desktop/affine_raster.rs rename to crates/desktop/src/desktop/affine_raster.rs index d5b2a68..7d925a0 100644 --- a/src/desktop/affine_raster.rs +++ b/crates/desktop/src/desktop/affine_raster.rs @@ -1,10 +1,10 @@ use super::{create_window, read_buttons}; -use gba_rust::{ - affine_raster_demo::{AffineRasterDemo, AFFINE_RASTER_STATE}, +use gba_core::{ display::{CPU_HZ, CYCLES_PER_FRAME, VISIBLE_LINES}, input::{Button, Buttons}, video::{rgb555_to_rgb888, Framebuffer, HEIGHT, WIDTH}, }; +use gba_demos::affine_raster_demo::{AffineRasterDemo, AFFINE_RASTER_STATE}; use minifb::Key; use std::{ error::Error, @@ -79,7 +79,7 @@ fn validate( if m.read32(AFFINE_RASTER_STATE)? != index as u32 + 1 || m.read32(AFFINE_RASTER_STATE + 4)? != pan_x as u32 || m.read32(AFFINE_RASTER_STATE + 8)? != pan_y as u32 - || m.read16(gba_rust::io::BG2CNT)? != 0x7000 + || m.read16(gba_core::io::BG2CNT)? != 0x7000 || u32::from(position.scanline) != VISIBLE_LINES || u32::from(position.line_cycle) >= demo.machine().last_timing().total() { diff --git a/src/desktop/bitmap.rs b/crates/desktop/src/desktop/bitmap.rs similarity index 98% rename from src/desktop/bitmap.rs rename to crates/desktop/src/desktop/bitmap.rs index 0ad6b33..448cc57 100644 --- a/src/desktop/bitmap.rs +++ b/crates/desktop/src/desktop/bitmap.rs @@ -1,11 +1,11 @@ use super::{create_window, read_buttons}; -use gba_rust::{ - bitmap_demo::{BitmapDemo, BitmapMode, BITMAP_STATE}, +use gba_core::{ display::{CPU_HZ, CYCLES_PER_FRAME, VISIBLE_LINES}, input::{Button, Buttons}, io::DISPCNT, video::{rgb555_to_rgb888, Framebuffer, HEIGHT, WIDTH}, }; +use gba_demos::bitmap_demo::{BitmapDemo, BitmapMode, BITMAP_STATE}; use minifb::Key; use std::{ error::Error, diff --git a/src/desktop/effects.rs b/crates/desktop/src/desktop/effects.rs similarity index 98% rename from src/desktop/effects.rs rename to crates/desktop/src/desktop/effects.rs index 8dd6a69..b1e71f1 100644 --- a/src/desktop/effects.rs +++ b/crates/desktop/src/desktop/effects.rs @@ -1,11 +1,11 @@ use super::{create_window, read_buttons}; -use gba_rust::{ +use gba_core::{ display::{CPU_HZ, CYCLES_PER_FRAME, VISIBLE_LINES}, - effects_demo::{EffectsDemo, EFFECTS_STATE}, input::{Button, Buttons}, io::{BLDALPHA, BLDCNT, DISPCNT, WININ, WINOUT}, video::{rgb555_to_rgb888, Framebuffer, HEIGHT, WIDTH}, }; +use gba_demos::effects_demo::{EffectsDemo, EFFECTS_STATE}; use minifb::Key; use std::{ error::Error, diff --git a/src/desktop/mosaic.rs b/crates/desktop/src/desktop/mosaic.rs similarity index 98% rename from src/desktop/mosaic.rs rename to crates/desktop/src/desktop/mosaic.rs index 963d723..2ec04af 100644 --- a/src/desktop/mosaic.rs +++ b/crates/desktop/src/desktop/mosaic.rs @@ -1,12 +1,12 @@ use super::{create_window, read_buttons}; -use gba_rust::{ +use gba_core::{ display::{CPU_HZ, CYCLES_PER_FRAME, VISIBLE_LINES}, input::{Button, Buttons}, io::{BG0CNT, BG1CNT, DISPCNT, MOSAIC}, memory::OAM_START, - mosaic_demo::{MosaicDemo, MOSAIC_STATE}, video::{rgb555_to_rgb888, Framebuffer, HEIGHT, WIDTH}, }; +use gba_demos::mosaic_demo::{MosaicDemo, MOSAIC_STATE}; use minifb::Key; use std::{ error::Error, diff --git a/src/desktop/raster.rs b/crates/desktop/src/desktop/raster.rs similarity index 97% rename from src/desktop/raster.rs rename to crates/desktop/src/desktop/raster.rs index 7e3f362..40e8cce 100644 --- a/src/desktop/raster.rs +++ b/crates/desktop/src/desktop/raster.rs @@ -1,11 +1,11 @@ use super::{create_window, read_buttons}; -use gba_rust::{ +use gba_core::{ display::{CPU_HZ, CYCLES_PER_FRAME}, dma::DMA_BASE, input::{Button, Buttons}, - raster_demo::{RasterDemo, RASTER_STATE}, video::{rgb555_to_rgb888, Framebuffer, HEIGHT, WIDTH}, }; +use gba_demos::raster_demo::{RasterDemo, RASTER_STATE}; use minifb::Key; use std::{ error::Error, diff --git a/src/main.rs b/crates/desktop/src/main.rs similarity index 95% rename from src/main.rs rename to crates/desktop/src/main.rs index 37a26ad..29b9188 100644 --- a/src/main.rs +++ b/crates/desktop/src/main.rs @@ -2,12 +2,14 @@ mod desktop; use std::{error::Error, ffi::OsString, io}; -use gba_rust::{ - bitmap_demo::BitmapMode, +use gba_core::{ cpu::Cpu, - demo_bios, demo_program, exception_demo_program, io::{IF, TIMER_BASE}, memory::{Memory, ROM_START}, +}; +use gba_demos::{ + bitmap_demo::BitmapMode, + demo_bios, demo_program, exception_demo_program, timer_demo::{timer_demo, TIMER_DEMO_STEPS}, DEMO_STEPS, EXCEPTION_DEMO_STEPS, }; @@ -64,7 +66,7 @@ fn parse_args(args: &[OsString]) -> Result { [arg] if arg == "--help" || arg == "-h" => Ok(RunMode::Help), _ => Err(io::Error::new( io::ErrorKind::InvalidInput, - "usage: gba-rust [--cpu-demo | --timer-demo | --graphics-demo | --smoke-test | --graphics-smoke-test | --raster-demo | --raster-smoke-test | --mosaic-demo | --mosaic-smoke-test | --effects-demo | --effects-smoke-test | --tile-demo | --tile-smoke-test | --affine-demo | --affine-smoke-test | --affine-raster-demo | --affine-raster-smoke-test | --bitmap4-demo | --bitmap5-demo | --bitmap4-smoke-test | --bitmap5-smoke-test | --help]; ROM loading is not supported yet", + "usage: gameboy-rust [--cpu-demo | --timer-demo | --graphics-demo | --smoke-test | --graphics-smoke-test | --raster-demo | --raster-smoke-test | --mosaic-demo | --mosaic-smoke-test | --effects-demo | --effects-smoke-test | --tile-demo | --tile-smoke-test | --affine-demo | --affine-smoke-test | --affine-raster-demo | --affine-raster-smoke-test | --bitmap4-demo | --bitmap5-demo | --bitmap4-smoke-test | --bitmap5-smoke-test | --help]; ROM loading is not supported yet", )), } } diff --git a/crates/gba-core/Cargo.toml b/crates/gba-core/Cargo.toml new file mode 100644 index 0000000..945bb75 --- /dev/null +++ b/crates/gba-core/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "gba-core" +version.workspace = true +edition.workspace = true +publish.workspace = true + +[dev-dependencies] +# Integration tests exercise the core through the original demo programs. +gba-demos = { path = "../gba-demos" } diff --git a/src/bios.rs b/crates/gba-core/src/bios.rs similarity index 100% rename from src/bios.rs rename to crates/gba-core/src/bios.rs diff --git a/src/bios/affine.rs b/crates/gba-core/src/bios/affine.rs similarity index 100% rename from src/bios/affine.rs rename to crates/gba-core/src/bios/affine.rs diff --git a/src/bios/angles.rs b/crates/gba-core/src/bios/angles.rs similarity index 100% rename from src/bios/angles.rs rename to crates/gba-core/src/bios/angles.rs diff --git a/src/bios/arithmetic.rs b/crates/gba-core/src/bios/arithmetic.rs similarity index 100% rename from src/bios/arithmetic.rs rename to crates/gba-core/src/bios/arithmetic.rs diff --git a/src/bios/bit_unpack.rs b/crates/gba-core/src/bios/bit_unpack.rs similarity index 100% rename from src/bios/bit_unpack.rs rename to crates/gba-core/src/bios/bit_unpack.rs diff --git a/src/bios/decompression.rs b/crates/gba-core/src/bios/decompression.rs similarity index 100% rename from src/bios/decompression.rs rename to crates/gba-core/src/bios/decompression.rs diff --git a/src/bios/differential.rs b/crates/gba-core/src/bios/differential.rs similarity index 100% rename from src/bios/differential.rs rename to crates/gba-core/src/bios/differential.rs diff --git a/src/bios/huffman.rs b/crates/gba-core/src/bios/huffman.rs similarity index 100% rename from src/bios/huffman.rs rename to crates/gba-core/src/bios/huffman.rs diff --git a/src/bios/lz77.rs b/crates/gba-core/src/bios/lz77.rs similarity index 100% rename from src/bios/lz77.rs rename to crates/gba-core/src/bios/lz77.rs diff --git a/src/bios/reset.rs b/crates/gba-core/src/bios/reset.rs similarity index 100% rename from src/bios/reset.rs rename to crates/gba-core/src/bios/reset.rs diff --git a/src/bios/run_length.rs b/crates/gba-core/src/bios/run_length.rs similarity index 100% rename from src/bios/run_length.rs rename to crates/gba-core/src/bios/run_length.rs diff --git a/src/cpu.rs b/crates/gba-core/src/cpu.rs similarity index 100% rename from src/cpu.rs rename to crates/gba-core/src/cpu.rs diff --git a/src/cpu/alu.rs b/crates/gba-core/src/cpu/alu.rs similarity index 100% rename from src/cpu/alu.rs rename to crates/gba-core/src/cpu/alu.rs diff --git a/src/cpu/arm.rs b/crates/gba-core/src/cpu/arm.rs similarity index 100% rename from src/cpu/arm.rs rename to crates/gba-core/src/cpu/arm.rs diff --git a/src/cpu/exception.rs b/crates/gba-core/src/cpu/exception.rs similarity index 100% rename from src/cpu/exception.rs rename to crates/gba-core/src/cpu/exception.rs diff --git a/src/cpu/exception_tests.rs b/crates/gba-core/src/cpu/exception_tests.rs similarity index 100% rename from src/cpu/exception_tests.rs rename to crates/gba-core/src/cpu/exception_tests.rs diff --git a/src/cpu/instruction_tests.rs b/crates/gba-core/src/cpu/instruction_tests.rs similarity index 100% rename from src/cpu/instruction_tests.rs rename to crates/gba-core/src/cpu/instruction_tests.rs diff --git a/src/cpu/status.rs b/crates/gba-core/src/cpu/status.rs similarity index 100% rename from src/cpu/status.rs rename to crates/gba-core/src/cpu/status.rs diff --git a/src/cpu/status_tests.rs b/crates/gba-core/src/cpu/status_tests.rs similarity index 100% rename from src/cpu/status_tests.rs rename to crates/gba-core/src/cpu/status_tests.rs diff --git a/src/cpu/tests.rs b/crates/gba-core/src/cpu/tests.rs similarity index 100% rename from src/cpu/tests.rs rename to crates/gba-core/src/cpu/tests.rs diff --git a/src/cpu/thumb.rs b/crates/gba-core/src/cpu/thumb.rs similarity index 100% rename from src/cpu/thumb.rs rename to crates/gba-core/src/cpu/thumb.rs diff --git a/src/cpu/thumb_tests.rs b/crates/gba-core/src/cpu/thumb_tests.rs similarity index 100% rename from src/cpu/thumb_tests.rs rename to crates/gba-core/src/cpu/thumb_tests.rs diff --git a/src/cpu/timing.rs b/crates/gba-core/src/cpu/timing.rs similarity index 100% rename from src/cpu/timing.rs rename to crates/gba-core/src/cpu/timing.rs diff --git a/src/cpu/timing_tests.rs b/crates/gba-core/src/cpu/timing_tests.rs similarity index 100% rename from src/cpu/timing_tests.rs rename to crates/gba-core/src/cpu/timing_tests.rs diff --git a/src/cpu/transfer.rs b/crates/gba-core/src/cpu/transfer.rs similarity index 100% rename from src/cpu/transfer.rs rename to crates/gba-core/src/cpu/transfer.rs diff --git a/src/cpu/transfer_tests.rs b/crates/gba-core/src/cpu/transfer_tests.rs similarity index 100% rename from src/cpu/transfer_tests.rs rename to crates/gba-core/src/cpu/transfer_tests.rs diff --git a/src/display.rs b/crates/gba-core/src/display.rs similarity index 100% rename from src/display.rs rename to crates/gba-core/src/display.rs diff --git a/src/dma.rs b/crates/gba-core/src/dma.rs similarity index 100% rename from src/dma.rs rename to crates/gba-core/src/dma.rs diff --git a/src/input.rs b/crates/gba-core/src/input.rs similarity index 100% rename from src/input.rs rename to crates/gba-core/src/input.rs diff --git a/src/io.rs b/crates/gba-core/src/io.rs similarity index 100% rename from src/io.rs rename to crates/gba-core/src/io.rs diff --git a/crates/gba-core/src/lib.rs b/crates/gba-core/src/lib.rs new file mode 100644 index 0000000..4498308 --- /dev/null +++ b/crates/gba-core/src/lib.rs @@ -0,0 +1,12 @@ +//! An educational GBA starting point, not a game-compatible emulator. + +pub mod bios; +pub mod cpu; +pub mod display; +pub mod dma; +pub mod input; +pub mod io; +pub mod machine; +pub mod memory; +pub mod timing; +pub mod video; diff --git a/src/machine.rs b/crates/gba-core/src/machine.rs similarity index 100% rename from src/machine.rs rename to crates/gba-core/src/machine.rs diff --git a/src/memory.rs b/crates/gba-core/src/memory.rs similarity index 100% rename from src/memory.rs rename to crates/gba-core/src/memory.rs diff --git a/src/timing.rs b/crates/gba-core/src/timing.rs similarity index 100% rename from src/timing.rs rename to crates/gba-core/src/timing.rs diff --git a/src/video.rs b/crates/gba-core/src/video.rs similarity index 100% rename from src/video.rs rename to crates/gba-core/src/video.rs diff --git a/src/video/affine.rs b/crates/gba-core/src/video/affine.rs similarity index 100% rename from src/video/affine.rs rename to crates/gba-core/src/video/affine.rs diff --git a/src/video/capture.rs b/crates/gba-core/src/video/capture.rs similarity index 100% rename from src/video/capture.rs rename to crates/gba-core/src/video/capture.rs diff --git a/src/video/effects.rs b/crates/gba-core/src/video/effects.rs similarity index 100% rename from src/video/effects.rs rename to crates/gba-core/src/video/effects.rs diff --git a/src/video/mosaic.rs b/crates/gba-core/src/video/mosaic.rs similarity index 100% rename from src/video/mosaic.rs rename to crates/gba-core/src/video/mosaic.rs diff --git a/src/video/sprites.rs b/crates/gba-core/src/video/sprites.rs similarity index 100% rename from src/video/sprites.rs rename to crates/gba-core/src/video/sprites.rs diff --git a/src/video/sprites/budget.rs b/crates/gba-core/src/video/sprites/budget.rs similarity index 100% rename from src/video/sprites/budget.rs rename to crates/gba-core/src/video/sprites/budget.rs diff --git a/src/video/sprites/pipeline.rs b/crates/gba-core/src/video/sprites/pipeline.rs similarity index 100% rename from src/video/sprites/pipeline.rs rename to crates/gba-core/src/video/sprites/pipeline.rs diff --git a/src/video/windows.rs b/crates/gba-core/src/video/windows.rs similarity index 100% rename from src/video/windows.rs rename to crates/gba-core/src/video/windows.rs diff --git a/src/video/windows/horizontal.rs b/crates/gba-core/src/video/windows/horizontal.rs similarity index 100% rename from src/video/windows/horizontal.rs rename to crates/gba-core/src/video/windows/horizontal.rs diff --git a/tests/affine_backgrounds.rs b/crates/gba-core/tests/affine_backgrounds.rs similarity index 99% rename from tests/affine_backgrounds.rs rename to crates/gba-core/tests/affine_backgrounds.rs index fd11dd9..2916312 100644 --- a/tests/affine_backgrounds.rs +++ b/crates/gba-core/tests/affine_backgrounds.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ io::*, memory::{Memory, MemoryError, OAM_START as OAM, PALETTE_START as PAL, VRAM_START as VRAM}, video::{rgb555_to_rgb888, Framebuffer, VideoError, WIDTH}, @@ -281,10 +281,8 @@ fn diagnostics_leave_output_unchanged_and_disabled_layers_skip_validation() { #[test] fn cpu_demo_pans_rotates_zooms_clips_cancels_opposites_and_resets() { - use gba_rust::{ - affine_demo::{AffineDemo, AFFINE_STATE}, - input::{Button, Buttons}, - }; + use gba_core::input::{Button, Buttons}; + use gba_demos::affine_demo::{AffineDemo, AFFINE_STATE}; let mut demo = AffineDemo::new().unwrap(); let mut f = Framebuffer::default(); assert_eq!(demo.machine().memory().read16(DISPCNT).unwrap(), 0); diff --git a/tests/affine_tracking.rs b/crates/gba-core/tests/affine_tracking.rs similarity index 98% rename from tests/affine_tracking.rs rename to crates/gba-core/tests/affine_tracking.rs index 7712b52..9c8ef36 100644 --- a/tests/affine_tracking.rs +++ b/crates/gba-core/tests/affine_tracking.rs @@ -1,5 +1,4 @@ -use gba_rust::{ - affine_raster_demo::{AffineRasterDemo, AFFINE_RASTER_STATE, AFFINE_RASTER_TABLE}, +use gba_core::{ cpu::Cpu, display::{CYCLES_PER_FRAME, CYCLES_PER_LINE as LINE, HBLANK_START as HB, VBLANK_START as VB}, dma::DMA_BASE, @@ -9,6 +8,7 @@ use gba_rust::{ memory::{Memory, PALETTE_START as PAL, ROM_START, VRAM_START as VRAM}, video::{rgb555_to_rgb888 as rgb, Framebuffer, HEIGHT, WIDTH}, }; +use gba_demos::affine_raster_demo::{AffineRasterDemo, AFFINE_RASTER_STATE, AFFINE_RASTER_TABLE}; fn color(x: u32, y: u32) -> u16 { ((x & 31) | ((y & 31) << 5) | (((x + y) & 31) << 10)) as u16 diff --git a/tests/bios.rs b/crates/gba-core/tests/bios.rs similarity index 99% rename from tests/bios.rs rename to crates/gba-core/tests/bios.rs index d6a1c04..c1e4f62 100644 --- a/tests/bios.rs +++ b/crates/gba-core/tests/bios.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ bios::{self, IRQ_FLAGS, IRQ_HANDLER, SYSTEM_STACK, UNSUPPORTED_TRAP}, cpu::{CpuError, InstructionSet, Mode}, display::VBLANK_START, diff --git a/tests/bios/affine.rs b/crates/gba-core/tests/bios/affine.rs similarity index 99% rename from tests/bios/affine.rs rename to crates/gba-core/tests/bios/affine.rs index 09b9f5e..5cd87ff 100644 --- a/tests/bios/affine.rs +++ b/crates/gba-core/tests/bios/affine.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::{ +use gba_core::{ bios::INVALID_ARGUMENT_TRAP, dma::DMA_BASE, io::{BG2PA, DISPCNT}, diff --git a/tests/bios/angles.rs b/crates/gba-core/tests/bios/angles.rs similarity index 99% rename from tests/bios/angles.rs rename to crates/gba-core/tests/bios/angles.rs index afe9513..3a43d01 100644 --- a/tests/bios/angles.rs +++ b/crates/gba-core/tests/bios/angles.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::{bios::INVALID_ARGUMENT_TRAP, dma::DMA_BASE}; +use gba_core::{bios::INVALID_ARGUMENT_TRAP, dma::DMA_BASE}; /// Wide-integer reference for signed low-word multiplication and floor division. /// This avoids both host signed overflow and the emitted instruction sequence. diff --git a/tests/bios/arithmetic.rs b/crates/gba-core/tests/bios/arithmetic.rs similarity index 99% rename from tests/bios/arithmetic.rs rename to crates/gba-core/tests/bios/arithmetic.rs index 65bcb91..7e7dced 100644 --- a/tests/bios/arithmetic.rs +++ b/crates/gba-core/tests/bios/arithmetic.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::bios::INVALID_ARGUMENT_TRAP; +use gba_core::bios::INVALID_ARGUMENT_TRAP; fn divide(number: i32, denominator: i32, thumb: bool, service: u8) { let inputs = if service == 6 { diff --git a/tests/bios/bit_unpack.rs b/crates/gba-core/tests/bios/bit_unpack.rs similarity index 99% rename from tests/bios/bit_unpack.rs rename to crates/gba-core/tests/bios/bit_unpack.rs index fd28350..0b62bb8 100644 --- a/tests/bios/bit_unpack.rs +++ b/crates/gba-core/tests/bios/bit_unpack.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::{ +use gba_core::{ bios::INVALID_ARGUMENT_TRAP, dma::DMA_BASE, memory::{OAM_START, PALETTE_START}, diff --git a/tests/bios/differential.rs b/crates/gba-core/tests/bios/differential.rs similarity index 99% rename from tests/bios/differential.rs rename to crates/gba-core/tests/bios/differential.rs index a27f14c..964e24a 100644 --- a/tests/bios/differential.rs +++ b/crates/gba-core/tests/bios/differential.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::{bios::INVALID_ARGUMENT_TRAP, dma::DMA_BASE, memory::OAM_START}; +use gba_core::{bios::INVALID_ARGUMENT_TRAP, dma::DMA_BASE, memory::OAM_START}; fn filtered(service: u8, samples: &[u16]) -> (Vec, Vec) { let halfword = service == 0x18; diff --git a/tests/bios/huffman.rs b/crates/gba-core/tests/bios/huffman.rs similarity index 99% rename from tests/bios/huffman.rs rename to crates/gba-core/tests/bios/huffman.rs index 8b84ad1..bf59c79 100644 --- a/tests/bios/huffman.rs +++ b/crates/gba-core/tests/bios/huffman.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::{ +use gba_core::{ bios::INVALID_ARGUMENT_TRAP, dma::DMA_BASE, memory::{OAM_START, PALETTE_START}, diff --git a/tests/bios/lz77.rs b/crates/gba-core/tests/bios/lz77.rs similarity index 99% rename from tests/bios/lz77.rs rename to crates/gba-core/tests/bios/lz77.rs index 440f1bd..f7617ab 100644 --- a/tests/bios/lz77.rs +++ b/crates/gba-core/tests/bios/lz77.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::bios::INVALID_ARGUMENT_TRAP; +use gba_core::bios::INVALID_ARGUMENT_TRAP; #[derive(Clone, Copy)] enum Token { diff --git a/tests/bios/ram_reset.rs b/crates/gba-core/tests/bios/ram_reset.rs similarity index 99% rename from tests/bios/ram_reset.rs rename to crates/gba-core/tests/bios/ram_reset.rs index 59fc1f5..a406959 100644 --- a/tests/bios/ram_reset.rs +++ b/crates/gba-core/tests/bios/ram_reset.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::{ +use gba_core::{ bios::INVALID_ARGUMENT_TRAP, dma::{DmaError, DMA_BASE, DMA_STRIDE}, input::Buttons, diff --git a/tests/bios/reset.rs b/crates/gba-core/tests/bios/reset.rs similarity index 99% rename from tests/bios/reset.rs rename to crates/gba-core/tests/bios/reset.rs index efcaa23..8338726 100644 --- a/tests/bios/reset.rs +++ b/crates/gba-core/tests/bios/reset.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::{ +use gba_core::{ dma::DMA_BASE, io::{BG0CNT, DISPCNT, WAITCNT}, memory::{OAM_START, PALETTE_START}, diff --git a/tests/bios/run_length.rs b/crates/gba-core/tests/bios/run_length.rs similarity index 99% rename from tests/bios/run_length.rs rename to crates/gba-core/tests/bios/run_length.rs index 0bc90de..6f3c5b4 100644 --- a/tests/bios/run_length.rs +++ b/crates/gba-core/tests/bios/run_length.rs @@ -1,5 +1,5 @@ use super::*; -use gba_rust::{bios::INVALID_ARGUMENT_TRAP, dma::DMA_BASE, memory::OAM_START}; +use gba_core::{bios::INVALID_ARGUMENT_TRAP, dma::DMA_BASE, memory::OAM_START}; #[derive(Clone)] enum Block { diff --git a/tests/bitmap_modes.rs b/crates/gba-core/tests/bitmap_modes.rs similarity index 97% rename from tests/bitmap_modes.rs rename to crates/gba-core/tests/bitmap_modes.rs index 338adff..c006718 100644 --- a/tests/bitmap_modes.rs +++ b/crates/gba-core/tests/bitmap_modes.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ io::{BG2CNT, BG2PA, BG2X, BG2Y, DISPCNT, GREENSWAP}, memory::{Memory, OAM_START as OAM, PALETTE_START as PAL, VRAM_START as VRAM}, video::{rgb555_to_rgb888, Framebuffer, VideoError, WIDTH}, @@ -293,13 +293,13 @@ fn bitmap_green_swap_disabled_bg_and_forced_blank_remain_consistent() { fn assert_demo_frame( f: &Framebuffer, - mode: gba_rust::bitmap_demo::BitmapMode, + mode: gba_demos::bitmap_demo::BitmapMode, pan: (i32, i32), rotated: bool, zoomed: bool, page: usize, ) { - use gba_rust::bitmap_demo::BitmapMode; + use gba_demos::bitmap_demo::BitmapMode; let (w, h) = if mode == BitmapMode::Mode4 { (240, 160) } else { @@ -346,10 +346,8 @@ fn assert_demo_frame( #[test] fn cpu_demos_copy_both_pages_and_flip_during_vblank_every_32_updates() { - use gba_rust::{ - bitmap_demo::{BitmapDemo, BitmapMode, BITMAP_STATE}, - input::Buttons, - }; + use gba_core::input::Buttons; + use gba_demos::bitmap_demo::{BitmapDemo, BitmapMode, BITMAP_STATE}; for mode in [BitmapMode::Mode4, BitmapMode::Mode5] { let mut demo = BitmapDemo::new(mode).unwrap(); let mut f = Framebuffer::default(); @@ -376,10 +374,8 @@ fn cpu_demos_copy_both_pages_and_flip_during_vblank_every_32_updates() { #[test] fn cpu_bitmap_controls_pan_rotate_zoom_force_page_and_reset() { - use gba_rust::{ - bitmap_demo::{BitmapDemo, BitmapMode, BITMAP_STATE}, - input::{Button, Buttons}, - }; + use gba_core::input::{Button, Buttons}; + use gba_demos::bitmap_demo::{BitmapDemo, BitmapMode, BITMAP_STATE}; for mode in [BitmapMode::Mode4, BitmapMode::Mode5] { let mut demo = BitmapDemo::new(mode).unwrap(); let mut f = Framebuffer::default(); diff --git a/tests/core.rs b/crates/gba-core/tests/core.rs similarity index 98% rename from tests/core.rs rename to crates/gba-core/tests/core.rs index 2c9bcad..c67d9a7 100644 --- a/tests/core.rs +++ b/crates/gba-core/tests/core.rs @@ -1,9 +1,8 @@ -use gba_rust::{ +use gba_core::{ cpu::{Cpu, CpuError, InstructionSet}, - demo_program, memory::{Memory, MemoryError, ROM_START}, - DEMO_STEPS, }; +use gba_demos::{demo_program, DEMO_STEPS}; fn program(words: &[u32]) -> Memory { Memory::new(words.iter().flat_map(|word| word.to_le_bytes()).collect()).unwrap() diff --git a/tests/display.rs b/crates/gba-core/tests/display.rs similarity index 99% rename from tests/display.rs rename to crates/gba-core/tests/display.rs index 5cba467..13ef94f 100644 --- a/tests/display.rs +++ b/crates/gba-core/tests/display.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ cpu::{Cpu, Mode}, display::{CYCLES_PER_FRAME, CYCLES_PER_LINE, HBLANK_START, LINES_PER_FRAME, VBLANK_START}, io::{DISPCNT, DISPSTAT, IE, IF, IME, TIMER_BASE, VCOUNT}, @@ -397,7 +397,7 @@ fn failed_block_store_does_not_change_window_controls_or_advance_display() { assert!(machine.step().is_err()); assert_eq!(machine.cpu(), &before); assert_eq!(machine.memory().display_position(), position); - assert_eq!(machine.memory().read32(gba_rust::io::WININ).unwrap(), 0); + assert_eq!(machine.memory().read32(gba_core::io::WININ).unwrap(), 0); assert_eq!(machine.memory().read16(DISPSTAT).unwrap(), 0); assert_eq!(machine.memory().read16(IF).unwrap(), 0); } diff --git a/tests/dma.rs b/crates/gba-core/tests/dma.rs similarity index 99% rename from tests/dma.rs rename to crates/gba-core/tests/dma.rs index 913e1c1..10c3403 100644 --- a/tests/dma.rs +++ b/crates/gba-core/tests/dma.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ cpu::{Cpu, Mode}, display::{CYCLES_PER_FRAME, CYCLES_PER_LINE, HBLANK_START, VBLANK_START}, dma::{DmaError, DMA_BASE, DMA_STRIDE}, diff --git a/tests/effects.rs b/crates/gba-core/tests/effects.rs similarity index 99% rename from tests/effects.rs rename to crates/gba-core/tests/effects.rs index b146b43..d51c99c 100644 --- a/tests/effects.rs +++ b/crates/gba-core/tests/effects.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ io::*, memory::{Memory, MemoryError, OAM_START as OAM, PALETTE_START as PAL, VRAM_START as VRAM}, video::{rgb555_to_rgb888 as rgb, Framebuffer, HEIGHT, WIDTH}, diff --git a/tests/effects/colors.rs b/crates/gba-core/tests/effects/colors.rs similarity index 100% rename from tests/effects/colors.rs rename to crates/gba-core/tests/effects/colors.rs diff --git a/tests/effects/demo.rs b/crates/gba-core/tests/effects/demo.rs similarity index 98% rename from tests/effects/demo.rs rename to crates/gba-core/tests/effects/demo.rs index d758778..feafb65 100644 --- a/tests/effects/demo.rs +++ b/crates/gba-core/tests/effects/demo.rs @@ -1,7 +1,7 @@ use super::*; -use gba_rust::{ +use gba_core::input::{Button, Buttons}; +use gba_demos::{ effects_demo::{EffectsDemo, EFFECTS_STATE}, - input::{Button, Buttons}, tile_demo::TileDemo, }; @@ -149,7 +149,7 @@ fn cpu_window_demo_retains_active_region_when_bottom_moves_beyond_vcount_range() #[test] fn dma_word_write_updates_selection_and_coefficients_together() { - use gba_rust::{ + use gba_core::{ cpu::Cpu, dma::DMA_BASE, machine::{Machine, StepKind}, diff --git a/tests/effects/windows.rs b/crates/gba-core/tests/effects/windows.rs similarity index 100% rename from tests/effects/windows.rs rename to crates/gba-core/tests/effects/windows.rs diff --git a/tests/exceptions.rs b/crates/gba-core/tests/exceptions.rs similarity index 97% rename from tests/exceptions.rs rename to crates/gba-core/tests/exceptions.rs index 0bbef68..9dd2d48 100644 --- a/tests/exceptions.rs +++ b/crates/gba-core/tests/exceptions.rs @@ -1,9 +1,8 @@ -use gba_rust::{ +use gba_core::{ cpu::{Cpu, InstructionSet, Mode}, - demo_bios, exception_demo_program, memory::{Memory, MemoryError, BIOS_SIZE, ROM_START}, - EXCEPTION_DEMO_STEPS, }; +use gba_demos::{demo_bios, exception_demo_program, EXCEPTION_DEMO_STEPS}; #[test] fn original_demo_enters_supervisor_and_returns_to_arm_and_thumb() { diff --git a/tests/graphics.rs b/crates/gba-core/tests/graphics.rs similarity index 98% rename from tests/graphics.rs rename to crates/gba-core/tests/graphics.rs index 09975ae..63f9bb5 100644 --- a/tests/graphics.rs +++ b/crates/gba-core/tests/graphics.rs @@ -1,11 +1,11 @@ -use gba_rust::{ - graphics_demo::{GraphicsDemo, BACKGROUND, DEMO_STATE, SQUARE_SIZE}, +use gba_core::{ input::{Button, Buttons}, io::{BG2PA, BG2PD, DISPCNT, GREENSWAP, KEYINPUT}, memory::{Memory, MemoryError, PALETTE_START, VRAM_START}, timing::{bus_cycles, AccessKind, AccessWidth}, video::{rgb555_to_rgb888, Framebuffer, VideoError, HEIGHT, WIDTH}, }; +use gba_demos::graphics_demo::{GraphicsDemo, BACKGROUND, DEMO_STATE, SQUARE_SIZE}; fn mode3() -> Memory { let mut memory = Memory::new(vec![]).unwrap(); @@ -65,7 +65,7 @@ fn cpu_program_draws_mode3_and_moves_from_keyinput_without_host_vram_writes() { assert_eq!(position.frames, previous.frames + 1); assert_eq!( demo.machine().cycles() - previous_cycles, - u64::from(gba_rust::display::CYCLES_PER_FRAME) + u64::from(position.line_cycle) + u64::from(gba_core::display::CYCLES_PER_FRAME) + u64::from(position.line_cycle) - u64::from(previous.line_cycle) ); assert_demo_frame(&demo, &frame, 114, 70, 0x7fff); diff --git a/tests/halt.rs b/crates/gba-core/tests/halt.rs similarity index 99% rename from tests/halt.rs rename to crates/gba-core/tests/halt.rs index 4863ab9..5579799 100644 --- a/tests/halt.rs +++ b/crates/gba-core/tests/halt.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ cpu::{Cpu, InstructionSet, Mode}, display::{CYCLES_PER_FRAME, CYCLES_PER_LINE, HBLANK_START, VBLANK_START}, dma::{DmaError, DMA_BASE}, diff --git a/tests/machine.rs b/crates/gba-core/tests/machine.rs similarity index 99% rename from tests/machine.rs rename to crates/gba-core/tests/machine.rs index f27ba59..4d3ac88 100644 --- a/tests/machine.rs +++ b/crates/gba-core/tests/machine.rs @@ -1,10 +1,10 @@ -use gba_rust::{ +use gba_core::{ cpu::{Cpu, CpuError, InstructionSet, Mode}, io::{IE, IF, IME, TIMER_BASE, WAITCNT}, machine::{Machine, MachineError, StepKind}, memory::{Memory, MemoryError, BIOS_SIZE, ROM_START}, - timer_demo::{timer_demo, TIMER_DEMO_STEPS}, }; +use gba_demos::timer_demo::{timer_demo, TIMER_DEMO_STEPS}; fn words(values: &[u32]) -> Vec { values diff --git a/tests/memory.rs b/crates/gba-core/tests/memory.rs similarity index 97% rename from tests/memory.rs rename to crates/gba-core/tests/memory.rs index 5e8b5a2..170b76d 100644 --- a/tests/memory.rs +++ b/crates/gba-core/tests/memory.rs @@ -1,4 +1,4 @@ -use gba_rust::memory::{Memory, MemoryError, ROM_START}; +use gba_core::memory::{Memory, MemoryError, ROM_START}; #[test] fn halfword_and_word_writes_are_little_endian() { diff --git a/tests/mosaic.rs b/crates/gba-core/tests/mosaic.rs similarity index 98% rename from tests/mosaic.rs rename to crates/gba-core/tests/mosaic.rs index f336fe2..e86141f 100644 --- a/tests/mosaic.rs +++ b/crates/gba-core/tests/mosaic.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ io::*, memory::{Memory, MemoryError, OAM_START as OAM, PALETTE_START as PAL, VRAM_START as VRAM}, video::{rgb555_to_rgb888 as rgb, Framebuffer, HEIGHT, WIDTH}, diff --git a/tests/mosaic/backgrounds.rs b/crates/gba-core/tests/mosaic/backgrounds.rs similarity index 100% rename from tests/mosaic/backgrounds.rs rename to crates/gba-core/tests/mosaic/backgrounds.rs diff --git a/tests/mosaic/demo.rs b/crates/gba-core/tests/mosaic/demo.rs similarity index 98% rename from tests/mosaic/demo.rs rename to crates/gba-core/tests/mosaic/demo.rs index 8a9c4ba..ade2885 100644 --- a/tests/mosaic/demo.rs +++ b/crates/gba-core/tests/mosaic/demo.rs @@ -1,6 +1,6 @@ use super::*; -use gba_rust::{ - input::{Button, Buttons}, +use gba_core::input::{Button, Buttons}; +use gba_demos::{ mosaic_demo::{MosaicDemo, MOSAIC_STATE}, tile_demo::TileDemo, }; @@ -72,7 +72,7 @@ fn both_bypasses_restore_original_scene_with_scroll_rotation_zoom_and_reset() { #[test] fn dma_word_write_sets_bg_and_obj_fields_while_unused_halfword_ignores_writes() { - use gba_rust::{ + use gba_core::{ cpu::Cpu, dma::DMA_BASE, machine::{Machine, StepKind}, diff --git a/tests/mosaic/objects.rs b/crates/gba-core/tests/mosaic/objects.rs similarity index 100% rename from tests/mosaic/objects.rs rename to crates/gba-core/tests/mosaic/objects.rs diff --git a/tests/mosaic_tracking.rs b/crates/gba-core/tests/mosaic_tracking.rs similarity index 99% rename from tests/mosaic_tracking.rs rename to crates/gba-core/tests/mosaic_tracking.rs index cbad859..104dadc 100644 --- a/tests/mosaic_tracking.rs +++ b/crates/gba-core/tests/mosaic_tracking.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ cpu::Cpu, display::{ CYCLES_PER_FRAME as FRAME, CYCLES_PER_LINE as LINE, HBLANK_START as HB, VBLANK_START as VB, diff --git a/tests/scanlines.rs b/crates/gba-core/tests/scanlines.rs similarity index 91% rename from tests/scanlines.rs rename to crates/gba-core/tests/scanlines.rs index d761b95..5359ff3 100644 --- a/tests/scanlines.rs +++ b/crates/gba-core/tests/scanlines.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ cpu::Cpu, display::{CYCLES_PER_FRAME, CYCLES_PER_LINE, HBLANK_START, VBLANK_START}, dma::DMA_BASE, @@ -6,9 +6,9 @@ use gba_rust::{ io::*, machine::{Machine, StepKind}, memory::{Memory, OAM_START as OAM, PALETTE_START as PAL, ROM_START, VRAM_START as VRAM}, - raster_demo::{RasterDemo, RASTER_STATE, RASTER_TABLE}, video::{rgb555_to_rgb888 as rgb, Framebuffer, VideoError, HEIGHT, WIDTH}, }; +use gba_demos::raster_demo::{RasterDemo, RASTER_STATE, RASTER_TABLE}; #[path = "scanlines/capture.rs"] mod capture; diff --git a/tests/scanlines/capture.rs b/crates/gba-core/tests/scanlines/capture.rs similarity index 100% rename from tests/scanlines/capture.rs rename to crates/gba-core/tests/scanlines/capture.rs diff --git a/tests/scanlines/machine.rs b/crates/gba-core/tests/scanlines/machine.rs similarity index 100% rename from tests/scanlines/machine.rs rename to crates/gba-core/tests/scanlines/machine.rs diff --git a/tests/scanlines/rendering.rs b/crates/gba-core/tests/scanlines/rendering.rs similarity index 100% rename from tests/scanlines/rendering.rs rename to crates/gba-core/tests/scanlines/rendering.rs diff --git a/tests/sprite_budget.rs b/crates/gba-core/tests/sprite_budget.rs similarity index 99% rename from tests/sprite_budget.rs rename to crates/gba-core/tests/sprite_budget.rs index 3d23679..31870fb 100644 --- a/tests/sprite_budget.rs +++ b/crates/gba-core/tests/sprite_budget.rs @@ -1,5 +1,5 @@ //! Regression tests for the nominal allowance, not hardware fetch cutoffs. -use gba_rust::{ +use gba_core::{ cpu::Cpu, display::{CYCLES_PER_LINE as LINE, VBLANK_START as VB}, dma::DMA_BASE, diff --git a/tests/sprite_pipeline.rs b/crates/gba-core/tests/sprite_pipeline.rs similarity index 99% rename from tests/sprite_pipeline.rs rename to crates/gba-core/tests/sprite_pipeline.rs index 56a39f2..010110a 100644 --- a/tests/sprite_pipeline.rs +++ b/crates/gba-core/tests/sprite_pipeline.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ cpu::Cpu, display::{CYCLES_PER_FRAME as FRAME, CYCLES_PER_LINE as LINE, VBLANK_START as VB}, dma::DMA_BASE, diff --git a/tests/sprites.rs b/crates/gba-core/tests/sprites.rs similarity index 99% rename from tests/sprites.rs rename to crates/gba-core/tests/sprites.rs index 923c6dc..933a952 100644 --- a/tests/sprites.rs +++ b/crates/gba-core/tests/sprites.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ io::{BG0CNT, BG2CNT, DISPCNT, GREENSWAP}, memory::{Memory, MemoryError, OAM_START as OAM, PALETTE_START as PAL, VRAM_START as VRAM}, video::{rgb555_to_rgb888, Framebuffer, VideoError, WIDTH}, @@ -339,7 +339,7 @@ fn green_swap_applies_after_sprite_composition() { #[test] fn oam_bus_uses_one_cycle_for_every_width() { - use gba_rust::timing::{bus_cycles, AccessKind, AccessWidth}; + use gba_core::timing::{bus_cycles, AccessKind, AccessWidth}; for kind in [AccessKind::Sequential, AccessKind::NonSequential] { for width in [AccessWidth::Byte, AccessWidth::Halfword, AccessWidth::Word] { assert_eq!(bus_cycles(0, OAM, width, kind), 1); @@ -349,7 +349,7 @@ fn oam_bus_uses_one_cycle_for_every_width() { #[test] fn dma_copies_words_to_oam_and_reads_them_back() { - use gba_rust::{ + use gba_core::{ cpu::Cpu, dma::DMA_BASE, machine::{Machine, StepKind}, diff --git a/tests/sprites/affine.rs b/crates/gba-core/tests/sprites/affine.rs similarity index 100% rename from tests/sprites/affine.rs rename to crates/gba-core/tests/sprites/affine.rs diff --git a/tests/tiles.rs b/crates/gba-core/tests/tiles.rs similarity index 98% rename from tests/tiles.rs rename to crates/gba-core/tests/tiles.rs index 45e4b2c..c23894d 100644 --- a/tests/tiles.rs +++ b/crates/gba-core/tests/tiles.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ io::*, memory::{Memory, MemoryError, PALETTE_START as PAL, VRAM_START as VRAM}, video::{rgb555_to_rgb888, Framebuffer, VideoError, WIDTH}, @@ -308,10 +308,8 @@ fn assert_scene( #[test] fn cpu_tile_demo_copies_assets_scrolls_wraps_cancels_opposites_and_resets() { - use gba_rust::{ - input::{Button, Buttons}, - tile_demo::{TileDemo, TILE_STATE}, - }; + use gba_core::input::{Button, Buttons}; + use gba_demos::tile_demo::{TileDemo, TILE_STATE}; let mut demo = TileDemo::new().unwrap(); let mut frame = Framebuffer::default(); assert_eq!(demo.machine().memory().read16(VRAM).unwrap(), 0); @@ -367,11 +365,11 @@ fn cpu_tile_demo_copies_assets_scrolls_wraps_cancels_opposites_and_resets() { #[test] fn cpu_sprite_controls_flip_and_change_priority_through_oam() { - use gba_rust::{ + use gba_core::{ input::{Button, Buttons}, memory::OAM_START, - tile_demo::TileDemo, }; + use gba_demos::tile_demo::TileDemo; let mut demo = TileDemo::new().unwrap(); let mut frame = Framebuffer::default(); for _ in 0..16 { @@ -411,11 +409,11 @@ fn cpu_sprite_controls_flip_and_change_priority_through_oam() { #[test] fn cpu_affine_controls_write_matrices_preserve_center_and_return_to_regular_mode() { - use gba_rust::{ + use gba_core::{ input::{Button, Buttons}, memory::OAM_START, - tile_demo::TileDemo, }; + use gba_demos::tile_demo::TileDemo; let mut demo = TileDemo::new().unwrap(); let mut frame = Framebuffer::default(); // Put foreground crosses over the sprite so X also tests affine composition. diff --git a/tests/timers.rs b/crates/gba-core/tests/timers.rs similarity index 99% rename from tests/timers.rs rename to crates/gba-core/tests/timers.rs index 600dc5d..56b975b 100644 --- a/tests/timers.rs +++ b/crates/gba-core/tests/timers.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ io::{IE, IF, IME, TIMER_BASE}, memory::{Memory, MemoryError}, }; diff --git a/tests/timing.rs b/crates/gba-core/tests/timing.rs similarity index 99% rename from tests/timing.rs rename to crates/gba-core/tests/timing.rs index bf698ce..0c7e6a2 100644 --- a/tests/timing.rs +++ b/crates/gba-core/tests/timing.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ cpu::Cpu, io::{IE, IF, IME, TIMER_BASE, WAITCNT}, machine::{Machine, StepKind}, diff --git a/tests/window_tracking.rs b/crates/gba-core/tests/window_tracking.rs similarity index 99% rename from tests/window_tracking.rs rename to crates/gba-core/tests/window_tracking.rs index 0e13e23..15be073 100644 --- a/tests/window_tracking.rs +++ b/crates/gba-core/tests/window_tracking.rs @@ -1,4 +1,4 @@ -use gba_rust::{ +use gba_core::{ cpu::Cpu, display::{ CYCLES_PER_FRAME as FRAME, CYCLES_PER_LINE as LINE, HBLANK_START as HB, VBLANK_START as VB, diff --git a/tests/window_tracking/horizontal.rs b/crates/gba-core/tests/window_tracking/horizontal.rs similarity index 100% rename from tests/window_tracking/horizontal.rs rename to crates/gba-core/tests/window_tracking/horizontal.rs diff --git a/crates/gba-demos/Cargo.toml b/crates/gba-demos/Cargo.toml new file mode 100644 index 0000000..45521ab --- /dev/null +++ b/crates/gba-demos/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "gba-demos" +version.workspace = true +edition.workspace = true +publish.workspace = true + +[dependencies] +gba-core = { path = "../gba-core" } diff --git a/src/affine_demo.rs b/crates/gba-demos/src/affine_demo.rs similarity index 99% rename from src/affine_demo.rs rename to crates/gba-demos/src/affine_demo.rs index acdcb72..5727562 100644 --- a/src/affine_demo.rs +++ b/crates/gba-demos/src/affine_demo.rs @@ -2,8 +2,8 @@ //! and writes affine coefficients/reference points during VBlank. //! The bitmap demos reuse this instruction builder with different assets and page control. -use crate::{ - graphics_demo::{GraphicsDemo, GraphicsError}, +use crate::graphics_demo::{GraphicsDemo, GraphicsError}; +use gba_core::{ input::Buttons, machine::Machine, memory::{MemoryError, ROM_START}, diff --git a/src/affine_raster_demo.rs b/crates/gba-demos/src/affine_raster_demo.rs similarity index 86% rename from src/affine_raster_demo.rs rename to crates/gba-demos/src/affine_raster_demo.rs index 5b9ad09..9f9cd0d 100644 --- a/src/affine_raster_demo.rs +++ b/crates/gba-demos/src/affine_raster_demo.rs @@ -1,13 +1,8 @@ //! CPU-driven affine raster distortion. HBlank DMA changes BG2PB for the next //! line transition; internal origins accumulate the resulting horizontal shifts. -use crate::{ - graphics_demo::{GraphicsDemo, GraphicsError}, - input::Buttons, - machine::Machine, - memory::MemoryError, - video::Framebuffer, -}; +use crate::graphics_demo::{GraphicsDemo, GraphicsError}; +use gba_core::{input::Buttons, machine::Machine, memory::MemoryError, video::Framebuffer}; /// Completed updates and signed pan X/Y, as three debug words. pub const AFFINE_RASTER_STATE: u32 = crate::affine_demo::AFFINE_STATE; diff --git a/src/bitmap_demo.rs b/crates/gba-demos/src/bitmap_demo.rs similarity index 96% rename from src/bitmap_demo.rs rename to crates/gba-demos/src/bitmap_demo.rs index 5e44035..431cd8f 100644 --- a/src/bitmap_demo.rs +++ b/crates/gba-demos/src/bitmap_demo.rs @@ -4,11 +4,8 @@ use crate::{ affine_demo, graphics_demo::{GraphicsDemo, GraphicsError}, - input::Buttons, - machine::Machine, - memory::MemoryError, - video::Framebuffer, }; +use gba_core::{input::Buttons, machine::Machine, memory::MemoryError, video::Framebuffer}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u16)] diff --git a/src/effects_demo.rs b/crates/gba-demos/src/effects_demo.rs similarity index 86% rename from src/effects_demo.rs rename to crates/gba-demos/src/effects_demo.rs index c241431..133a305 100644 --- a/src/effects_demo.rs +++ b/crates/gba-demos/src/effects_demo.rs @@ -1,13 +1,8 @@ //! Original CPU-driven window and color-effects scene, based on the tile demo. //! The CPU writes window bounds and effect registers during each VBlank. -use crate::{ - graphics_demo::{GraphicsDemo, GraphicsError}, - input::Buttons, - machine::Machine, - memory::MemoryError, - video::Framebuffer, -}; +use crate::graphics_demo::{GraphicsDemo, GraphicsError}; +use gba_core::{input::Buttons, machine::Machine, memory::MemoryError, video::Framebuffer}; /// Completed updates and nine-bit horizontal/vertical scroll, as three words. pub const EFFECTS_STATE: u32 = crate::tile_demo::TILE_STATE; diff --git a/src/graphics_demo.rs b/crates/gba-demos/src/graphics_demo.rs similarity index 99% rename from src/graphics_demo.rs rename to crates/gba-demos/src/graphics_demo.rs index 2ca215d..8917c06 100644 --- a/src/graphics_demo.rs +++ b/crates/gba-demos/src/graphics_demo.rs @@ -5,7 +5,7 @@ use std::{error::Error, fmt}; -use crate::{ +use gba_core::{ bios, cpu::CpuError, dma::DmaError, @@ -306,7 +306,7 @@ fn patch_branch(code: &mut [u32], index: usize, target: usize, condition: u32, l #[cfg(test)] mod tests { use super::*; - use crate::{cpu::Cpu, io::DISPSTAT, memory::Memory}; + use gba_core::{cpu::Cpu, io::DISPSTAT, memory::Memory}; #[test] fn frame_runner_does_not_require_a_ram_counter_update() { @@ -327,7 +327,7 @@ mod tests { #[test] fn arm_startup_uses_dma3_for_every_background_pixel() { - use crate::{ + use gba_core::{ dma::DMA_BASE, machine::StepKind, memory::VRAM_START, @@ -373,7 +373,7 @@ mod tests { #[test] fn dma_error_keeps_output_unchanged() { - use crate::dma::DMA_BASE; + use gba_core::dma::DMA_BASE; let mut demo = GraphicsDemo::new().unwrap(); // An unsupported special-mode request fails before any CPU instruction. @@ -393,7 +393,7 @@ mod tests { #[test] fn graphics_uses_bios_wait_and_irq_dispatch_before_each_redraw() { - use crate::{ + use gba_core::{ cpu::Mode, io::{IE, IF, IME}, machine::StepKind, diff --git a/src/lib.rs b/crates/gba-demos/src/lib.rs similarity index 92% rename from src/lib.rs rename to crates/gba-demos/src/lib.rs index 096f0e6..8c69ecb 100644 --- a/src/lib.rs +++ b/crates/gba-demos/src/lib.rs @@ -1,24 +1,14 @@ -//! An educational GBA starting point, not a game-compatible emulator. +//! Original GBA test programs that drive `gba-core`. No game or Nintendo code. pub mod affine_demo; pub mod affine_raster_demo; -pub mod bios; pub mod bitmap_demo; -pub mod cpu; -pub mod display; -pub mod dma; pub mod effects_demo; pub mod graphics_demo; -pub mod input; -pub mod io; -pub mod machine; -pub mod memory; pub mod mosaic_demo; pub mod raster_demo; pub mod tile_demo; pub mod timer_demo; -pub mod timing; -pub mod video; /// Steps needed to reach and execute the demo's final self-branch. pub const DEMO_STEPS: usize = 40; @@ -29,7 +19,7 @@ pub const EXCEPTION_DEMO_STEPS: usize = 11; /// Original test image, not a Nintendo BIOS or a BIOS-service replacement. /// The SWI vector branches to a handler that increments r10 and returns. pub fn demo_bios() -> Vec { - let mut bytes = vec![0; memory::BIOS_SIZE]; + let mut bytes = vec![0; gba_core::memory::BIOS_SIZE]; bytes[8..12].copy_from_slice(&0xea00_000c_u32.to_le_bytes()); // B 0x40 bytes[0x40..0x44].copy_from_slice(&0xe28a_a001_u32.to_le_bytes()); // ADD r10, r10, #1 bytes[0x44..0x48].copy_from_slice(&0xe1b0_f00e_u32.to_le_bytes()); // MOVS pc, lr diff --git a/src/mosaic_demo.rs b/crates/gba-demos/src/mosaic_demo.rs similarity index 86% rename from src/mosaic_demo.rs rename to crates/gba-demos/src/mosaic_demo.rs index 58507d8..f39a7f4 100644 --- a/src/mosaic_demo.rs +++ b/crates/gba-demos/src/mosaic_demo.rs @@ -1,12 +1,7 @@ //! Original tile scene with CPU-controlled background and sprite mosaic sizes. -use crate::{ - graphics_demo::{GraphicsDemo, GraphicsError}, - input::Buttons, - machine::Machine, - memory::MemoryError, - video::Framebuffer, -}; +use crate::graphics_demo::{GraphicsDemo, GraphicsError}; +use gba_core::{input::Buttons, machine::Machine, memory::MemoryError, video::Framebuffer}; /// Completed updates and nine-bit horizontal/vertical scroll, as three words. pub const MOSAIC_STATE: u32 = crate::tile_demo::TILE_STATE; diff --git a/src/raster_demo.rs b/crates/gba-demos/src/raster_demo.rs similarity index 98% rename from src/raster_demo.rs rename to crates/gba-demos/src/raster_demo.rs index 09aef42..8df06db 100644 --- a/src/raster_demo.rs +++ b/crates/gba-demos/src/raster_demo.rs @@ -1,8 +1,8 @@ //! Original ARM raster program. Repeated HBlank DMA changes the palette backdrop //! after each captured row. A whole-frame snapshot cannot reproduce these bands. -use crate::{ - graphics_demo::{GraphicsDemo, GraphicsError}, +use crate::graphics_demo::{GraphicsDemo, GraphicsError}; +use gba_core::{ input::Buttons, machine::Machine, memory::{MemoryError, ROM_START}, diff --git a/src/tile_demo.rs b/crates/gba-demos/src/tile_demo.rs similarity index 99% rename from src/tile_demo.rs rename to crates/gba-demos/src/tile_demo.rs index 2dcf0a8..1c1966d 100644 --- a/src/tile_demo.rs +++ b/crates/gba-demos/src/tile_demo.rs @@ -2,8 +2,8 @@ //! KEYINPUT, and updates scroll registers and a sprite once per VBlank. //! The host does not write VRAM or object attribute memory (OAM). -use crate::{ - graphics_demo::{GraphicsDemo, GraphicsError}, +use crate::graphics_demo::{GraphicsDemo, GraphicsError}; +use gba_core::{ input::Buttons, machine::Machine, memory::{MemoryError, ROM_START}, diff --git a/src/timer_demo.rs b/crates/gba-demos/src/timer_demo.rs similarity index 99% rename from src/timer_demo.rs rename to crates/gba-demos/src/timer_demo.rs index 694c35b..e0a8085 100644 --- a/src/timer_demo.rs +++ b/crates/gba-demos/src/timer_demo.rs @@ -1,7 +1,7 @@ //! Original code that configures a timer, handles one IRQ, and returns. //! Uses nominal instruction/bus costs; device updates occur at instruction boundaries. -use crate::{ +use gba_core::{ cpu::Cpu, machine::Machine, memory::{Memory, MemoryError, BIOS_SIZE, ROM_START}, diff --git a/flake.nix b/flake.nix index 6ee74da..b61b23c 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "A minimal GBA emulator written in Rust"; + description = "Game Boy family emulation in Rust, starting with the GBA"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";