Move the emulator into crates/gba-core, the original demo programs into crates/gba-demos, and the minifb frontend into crates/desktop. The binary is now gameboy-rust. Imports change from gba_rust to gba_core/gba_demos; no behavior changes. gba-core has no dependencies. Its integration tests use gba-demos as a development dependency. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
100 lines
4.1 KiB
Rust
100 lines
4.1 KiB
Rust
use super::*;
|
|
use gba_core::input::{Button, Buttons};
|
|
use gba_demos::{
|
|
mosaic_demo::{MosaicDemo, MOSAIC_STATE},
|
|
tile_demo::TileDemo,
|
|
};
|
|
|
|
#[test]
|
|
fn cpu_demo_cycles_all_sizes_and_wraps_without_host_video_writes() {
|
|
let mut demo = MosaicDemo::new().unwrap();
|
|
let mut frame = Framebuffer::default();
|
|
assert_eq!(demo.machine().memory().read16(DISPCNT).unwrap(), 0);
|
|
assert_eq!(demo.machine().memory().read16(VRAM).unwrap(), 0);
|
|
for update in 1..=129 {
|
|
demo.frame(Buttons::default(), &mut frame).unwrap();
|
|
let m = demo.machine().memory();
|
|
assert_eq!(m.read32(MOSAIC_STATE).unwrap(), update);
|
|
assert_eq!(m.read16(DISPCNT).unwrap(), 0x1340);
|
|
assert_eq!(m.read16(BG0CNT).unwrap(), 0x1844);
|
|
assert_eq!(m.read16(BG1CNT).unwrap(), 0xd0c1);
|
|
assert_eq!(m.read16(OAM).unwrap(), 0x1048);
|
|
assert_eq!(m.read32(MOSAIC).unwrap(), 0);
|
|
assert_eq!(m.display_position().scanline, 160);
|
|
let size = (1 + (update / 8) % 16) as usize;
|
|
// Check terrain and foreground away from the sprite for every size.
|
|
for y in 0..48 {
|
|
for x in 0..WIDTH {
|
|
let sx = x / size * size;
|
|
let sy = y / size * size;
|
|
let cross = sx / 8 % 4 == 1 && sy / 8 % 4 == 1 && (sx % 8 == 3 || sy % 8 == 3);
|
|
let color = if cross {
|
|
0x3ff
|
|
} else {
|
|
[0x260, 0x3a0, 0x7d20, 0x7e80]
|
|
[((sx / 32 + sy / 32) % 2) * 2 + (sx / 2 + sy / 2) % 2]
|
|
};
|
|
assert_eq!(at(&frame, x, y), rgb(color), "update={update} at={x},{y}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn both_bypasses_restore_original_scene_with_scroll_rotation_zoom_and_reset() {
|
|
let mut demo = MosaicDemo::new().unwrap();
|
|
let mut base = TileDemo::new().unwrap();
|
|
let mut f = Framebuffer::default();
|
|
let mut reference = Framebuffer::default();
|
|
for i in 0..32 {
|
|
let buttons = Buttons::default()
|
|
.with(Button::Left, i < 16)
|
|
.with(Button::Down, true)
|
|
.with(Button::Start, i == 31)
|
|
.with(Button::L, (8..24).contains(&i))
|
|
.with(Button::R, (16..28).contains(&i));
|
|
base.frame(buttons, &mut reference).unwrap();
|
|
demo.frame(buttons.with(Button::A, true).with(Button::B, true), &mut f)
|
|
.unwrap();
|
|
assert_eq!(f.pixels(), reference.pixels());
|
|
let m = demo.machine().memory();
|
|
assert_ne!(m.read16(OAM).unwrap() & 0x1000, 0);
|
|
assert_eq!(m.read16(OAM + 2).unwrap() & 0x1000, 0); // Z no longer flips.
|
|
assert_eq!(m.read16(OAM + 4).unwrap() & 0xc00, 0); // X no longer lowers priority.
|
|
assert_eq!(
|
|
m.read32(MOSAIC_STATE + 4).unwrap(),
|
|
base.machine().memory().read32(MOSAIC_STATE + 4).unwrap()
|
|
);
|
|
}
|
|
assert_eq!(demo.machine().memory().read32(MOSAIC_STATE + 4).unwrap(), 0);
|
|
assert_eq!(demo.machine().memory().read32(MOSAIC_STATE + 8).unwrap(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn dma_word_write_sets_bg_and_obj_fields_while_unused_halfword_ignores_writes() {
|
|
use gba_core::{
|
|
cpu::Cpu,
|
|
dma::DMA_BASE,
|
|
machine::{Machine, StepKind},
|
|
};
|
|
let mut m = memory();
|
|
m.write16(DISPCNT, 0x1140).unwrap();
|
|
m.write16(BG0CNT, 0x1040).unwrap();
|
|
fill(&mut m, VRAM, 32, 0x1212);
|
|
m.write16(PAL + 4, 31).unwrap();
|
|
m.write16(PAL + 2, 0x3e0).unwrap();
|
|
object(&mut m, 0, 0x1000, 0, 0);
|
|
fill(&mut m, VRAM + 0x10000, 32, 0x0101);
|
|
m.write16(PAL + 0x202, 0x7c00).unwrap();
|
|
m.write32(0x0200_0000, 0xffff_0302).unwrap(); // BG3x1, OBJ4x1.
|
|
m.write32(DMA_BASE + 36, 0x0200_0000).unwrap();
|
|
m.write32(DMA_BASE + 40, MOSAIC).unwrap();
|
|
m.write32(DMA_BASE + 44, 0x8400_0001).unwrap();
|
|
let mut machine = Machine::new(Cpu::new(0x0300_0000), m);
|
|
assert_eq!(machine.step().unwrap(), StepKind::Dma { channel: 3 });
|
|
let f = render(machine.memory());
|
|
assert_eq!(at(&f, 3, 0), rgb(0x7c00));
|
|
assert_eq!(at(&f, 8, 0), rgb(31)); // BG samples x6, not x8's independent phase.
|
|
assert_eq!(at(&f, 9, 0), rgb(0x3e0));
|
|
assert_eq!(machine.memory().read32(MOSAIC).unwrap(), 0);
|
|
}
|