feat: timer works much better
This commit is contained in:
parent
99eb507cf1
commit
8ae96ec880
42 changed files with 1032 additions and 617 deletions
|
@ -15,102 +15,149 @@ jobs:
|
||||||
- name: Run cargo tests (meowgb-core)
|
- name: Run cargo tests (meowgb-core)
|
||||||
run: cargo test -p meowgb-core
|
run: cargo test -p meowgb-core
|
||||||
|
|
||||||
|
- name: Build release (meowgb-tests)
|
||||||
|
run: cargo build -p meowgb-tests --release
|
||||||
|
|
||||||
- name: Run test ROM (blargg cpu_instrs)
|
- name: Run test ROM (blargg cpu_instrs)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/blargg/roms/cpu_instrs.gb test -m 100000000 -s meowgb-tests/expected_output/cpu_instrs.bin
|
run: ./target/release/meowgb-tests test-roms/blargg/roms/cpu_instrs.gb test -m 100000000 -s meowgb-tests/expected_output/cpu_instrs.bin
|
||||||
|
|
||||||
- name: Run test ROM (blargg instr_timing)
|
- name: Run test ROM (blargg instr_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/blargg/roms/instr_timing.gb test -m 100000000 -s meowgb-tests/expected_output/instr_timing.bin
|
run: ./target/release/meowgb-tests test-roms/blargg/roms/instr_timing.gb test -m 100000000 -s meowgb-tests/expected_output/instr_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (blargg mem_timing)
|
- name: Run test ROM (blargg mem_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/blargg/roms/mem_timing.gb test -m 100000000 -s meowgb-tests/expected_output/mem_timing.bin
|
run: ./target/release/meowgb-tests test-roms/blargg/roms/mem_timing.gb test -m 100000000 -s meowgb-tests/expected_output/mem_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite basic)
|
- name: Run test ROM (mooneye-test-suite basic)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/basic.gb test -m 100000000 -s meowgb-tests/expected_output/basic.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/basic.gb test -m 100000000 -s meowgb-tests/expected_output/basic.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite boot_hwio-dmgABCmgb)
|
- name: Run test ROM (mooneye-test-suite boot_hwio-dmgABCmgb)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/boot_hwio-dmgABCmgb.gb test -m 100000000 -s meowgb-tests/expected_output/boot_hwio-dmgABCmgb.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/boot_hwio-dmgABCmgb.gb test -m 100000000 -s meowgb-tests/expected_output/boot_hwio-dmgABCmgb.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite boot_regs-dmgABC)
|
- name: Run test ROM (mooneye-test-suite boot_regs-dmgABC)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/boot_regs-dmgABC.gb test -m 100000000 -s meowgb-tests/expected_output/boot_regs-dmgABC.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/boot_regs-dmgABC.gb test -m 100000000 -s meowgb-tests/expected_output/boot_regs-dmgABC.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite daa)
|
- name: Run test ROM (mooneye-test-suite daa)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/daa.gb test -m 100000000 -s meowgb-tests/expected_output/daa.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/daa.gb test -m 100000000 -s meowgb-tests/expected_output/daa.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite div_timing)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/div_timing.gb test -m 100000000 -s meowgb-tests/expected_output/div_timing.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite div_write)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/div_write.gb test -m 100000000 -s meowgb-tests/expected_output/div_write.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite ei_sequence)
|
- name: Run test ROM (mooneye-test-suite ei_sequence)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/ei_sequence.gb test -m 100000000 -s meowgb-tests/expected_output/ei_sequence.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/ei_sequence.gb test -m 100000000 -s meowgb-tests/expected_output/ei_sequence.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite ei_timing)
|
- name: Run test ROM (mooneye-test-suite ei_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/ei_timing.gb test -m 100000000 -s meowgb-tests/expected_output/ei_timing.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/ei_timing.gb test -m 100000000 -s meowgb-tests/expected_output/ei_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite halt_ime0_ei)
|
- name: Run test ROM (mooneye-test-suite halt_ime0_ei)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/halt_ime0_ei.gb test -m 100000000 -s meowgb-tests/expected_output/halt_ime0_ei.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/halt_ime0_ei.gb test -m 100000000 -s meowgb-tests/expected_output/halt_ime0_ei.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite intr_1_2_timing-GS)
|
- name: Run test ROM (mooneye-test-suite intr_1_2_timing-GS)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/intr_1_2_timing-GS.gb test -m 100000000 -s meowgb-tests/expected_output/intr_1_2_timing-GS.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/intr_1_2_timing-GS.gb test -m 100000000 -s meowgb-tests/expected_output/intr_1_2_timing-GS.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite intr_2_0_timing)
|
- name: Run test ROM (mooneye-test-suite intr_2_0_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/intr_2_0_timing.gb test -m 100000000 -s meowgb-tests/expected_output/intr_2_0_timing.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/intr_2_0_timing.gb test -m 100000000 -s meowgb-tests/expected_output/intr_2_0_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite mem_oam)
|
- name: Run test ROM (mooneye-test-suite mem_oam)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/mem_oam.gb test -m 100000000 -s meowgb-tests/expected_output/mem_oam.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/mem_oam.gb test -m 100000000 -s meowgb-tests/expected_output/mem_oam.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite oam_dma_restart)
|
- name: Run test ROM (mooneye-test-suite oam_dma_restart)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/oam_dma_restart.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_restart.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/oam_dma_restart.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_restart.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite oam_dma_start)
|
- name: Run test ROM (mooneye-test-suite oam_dma_start)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/oam_dma_start.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_start.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/oam_dma_start.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_start.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite oam_dma_timing)
|
- name: Run test ROM (mooneye-test-suite oam_dma_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/oam_dma_timing.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_timing.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/oam_dma_timing.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite rapid_di_ei)
|
- name: Run test ROM (mooneye-test-suite rapid_di_ei)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/rapid_di_ei.gb test -m 100000000 -s meowgb-tests/expected_output/rapid_di_ei.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/rapid_di_ei.gb test -m 100000000 -s meowgb-tests/expected_output/rapid_di_ei.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite rapid_toggle)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/rapid_toggle.gb test -m 100000000 -s meowgb-tests/expected_output/rapid_toggle.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite reg_f)
|
- name: Run test ROM (mooneye-test-suite reg_f)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/reg_f.gb test -m 100000000 -s meowgb-tests/expected_output/reg_f.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/reg_f.gb test -m 100000000 -s meowgb-tests/expected_output/reg_f.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite reg_read)
|
- name: Run test ROM (mooneye-test-suite reg_read)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/reg_read.gb test -m 100000000 -s meowgb-tests/expected_output/reg_read.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/reg_read.gb test -m 100000000 -s meowgb-tests/expected_output/reg_read.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite stat_irq_blocking)
|
- name: Run test ROM (mooneye-test-suite stat_irq_blocking)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/stat_irq_blocking.gb test -m 100000000 -s meowgb-tests/expected_output/stat_irq_blocking.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/stat_irq_blocking.gb test -m 100000000 -s meowgb-tests/expected_output/stat_irq_blocking.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite stat_lyc_onoff)
|
- name: Run test ROM (mooneye-test-suite stat_lyc_onoff)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/stat_lyc_onoff.gb test -m 100000000 -s meowgb-tests/expected_output/stat_lyc_onoff.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/stat_lyc_onoff.gb test -m 100000000 -s meowgb-tests/expected_output/stat_lyc_onoff.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim00)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim00.gb test -m 100000000 -s meowgb-tests/expected_output/tim00.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite tim00_div_trigger)
|
- name: Run test ROM (mooneye-test-suite tim00_div_trigger)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/tim00_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim00_div_trigger.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim00_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim00_div_trigger.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite tim01)
|
- name: Run test ROM (mooneye-test-suite tim01)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/tim01.gb test -m 100000000 -s meowgb-tests/expected_output/tim01.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim01.gb test -m 100000000 -s meowgb-tests/expected_output/tim01.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim01_div_trigger)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim01_div_trigger.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim10)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim10.gb test -m 100000000 -s meowgb-tests/expected_output/tim10.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim10_div_trigger)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim10_div_trigger.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim11)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim11.gb test -m 100000000 -s meowgb-tests/expected_output/tim11.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite tim11_div_trigger)
|
- name: Run test ROM (mooneye-test-suite tim11_div_trigger)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/tim11_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim11_div_trigger.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim11_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim11_div_trigger.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tima_reload)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tima_reload.gb test -m 100000000 -s meowgb-tests/expected_output/tima_reload.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tima_write_reloading)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tima_write_reloading.gb test -m 100000000 -s meowgb-tests/expected_output/tima_write_reloading.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tma_write_reloading)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tma_write_reloading.gb test -m 100000000 -s meowgb-tests/expected_output/tma_write_reloading.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite unused_hwio-GS)
|
- name: Run test ROM (mooneye-test-suite unused_hwio-GS)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/unused_hwio-GS.gb test -m 100000000 -s meowgb-tests/expected_output/unused_hwio-GS.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/unused_hwio-GS.gb test -m 100000000 -s meowgb-tests/expected_output/unused_hwio-GS.bin
|
||||||
|
|
97
.github/workflows/action.yml
vendored
97
.github/workflows/action.yml
vendored
|
@ -15,102 +15,149 @@ jobs:
|
||||||
- name: Run cargo tests (meowgb-core)
|
- name: Run cargo tests (meowgb-core)
|
||||||
run: cargo test -p meowgb-core
|
run: cargo test -p meowgb-core
|
||||||
|
|
||||||
|
- name: Build release (meowgb-tests)
|
||||||
|
run: cargo build -p meowgb-tests --release
|
||||||
|
|
||||||
- name: Run test ROM (blargg cpu_instrs)
|
- name: Run test ROM (blargg cpu_instrs)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/blargg/roms/cpu_instrs.gb test -m 100000000 -s meowgb-tests/expected_output/cpu_instrs.bin
|
run: ./target/release/meowgb-tests test-roms/blargg/roms/cpu_instrs.gb test -m 100000000 -s meowgb-tests/expected_output/cpu_instrs.bin
|
||||||
|
|
||||||
- name: Run test ROM (blargg instr_timing)
|
- name: Run test ROM (blargg instr_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/blargg/roms/instr_timing.gb test -m 100000000 -s meowgb-tests/expected_output/instr_timing.bin
|
run: ./target/release/meowgb-tests test-roms/blargg/roms/instr_timing.gb test -m 100000000 -s meowgb-tests/expected_output/instr_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (blargg mem_timing)
|
- name: Run test ROM (blargg mem_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/blargg/roms/mem_timing.gb test -m 100000000 -s meowgb-tests/expected_output/mem_timing.bin
|
run: ./target/release/meowgb-tests test-roms/blargg/roms/mem_timing.gb test -m 100000000 -s meowgb-tests/expected_output/mem_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite basic)
|
- name: Run test ROM (mooneye-test-suite basic)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/basic.gb test -m 100000000 -s meowgb-tests/expected_output/basic.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/basic.gb test -m 100000000 -s meowgb-tests/expected_output/basic.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite boot_hwio-dmgABCmgb)
|
- name: Run test ROM (mooneye-test-suite boot_hwio-dmgABCmgb)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/boot_hwio-dmgABCmgb.gb test -m 100000000 -s meowgb-tests/expected_output/boot_hwio-dmgABCmgb.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/boot_hwio-dmgABCmgb.gb test -m 100000000 -s meowgb-tests/expected_output/boot_hwio-dmgABCmgb.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite boot_regs-dmgABC)
|
- name: Run test ROM (mooneye-test-suite boot_regs-dmgABC)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/boot_regs-dmgABC.gb test -m 100000000 -s meowgb-tests/expected_output/boot_regs-dmgABC.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/boot_regs-dmgABC.gb test -m 100000000 -s meowgb-tests/expected_output/boot_regs-dmgABC.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite daa)
|
- name: Run test ROM (mooneye-test-suite daa)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/daa.gb test -m 100000000 -s meowgb-tests/expected_output/daa.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/daa.gb test -m 100000000 -s meowgb-tests/expected_output/daa.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite div_timing)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/div_timing.gb test -m 100000000 -s meowgb-tests/expected_output/div_timing.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite div_write)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/div_write.gb test -m 100000000 -s meowgb-tests/expected_output/div_write.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite ei_sequence)
|
- name: Run test ROM (mooneye-test-suite ei_sequence)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/ei_sequence.gb test -m 100000000 -s meowgb-tests/expected_output/ei_sequence.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/ei_sequence.gb test -m 100000000 -s meowgb-tests/expected_output/ei_sequence.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite ei_timing)
|
- name: Run test ROM (mooneye-test-suite ei_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/ei_timing.gb test -m 100000000 -s meowgb-tests/expected_output/ei_timing.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/ei_timing.gb test -m 100000000 -s meowgb-tests/expected_output/ei_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite halt_ime0_ei)
|
- name: Run test ROM (mooneye-test-suite halt_ime0_ei)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/halt_ime0_ei.gb test -m 100000000 -s meowgb-tests/expected_output/halt_ime0_ei.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/halt_ime0_ei.gb test -m 100000000 -s meowgb-tests/expected_output/halt_ime0_ei.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite intr_1_2_timing-GS)
|
- name: Run test ROM (mooneye-test-suite intr_1_2_timing-GS)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/intr_1_2_timing-GS.gb test -m 100000000 -s meowgb-tests/expected_output/intr_1_2_timing-GS.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/intr_1_2_timing-GS.gb test -m 100000000 -s meowgb-tests/expected_output/intr_1_2_timing-GS.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite intr_2_0_timing)
|
- name: Run test ROM (mooneye-test-suite intr_2_0_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/intr_2_0_timing.gb test -m 100000000 -s meowgb-tests/expected_output/intr_2_0_timing.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/intr_2_0_timing.gb test -m 100000000 -s meowgb-tests/expected_output/intr_2_0_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite mem_oam)
|
- name: Run test ROM (mooneye-test-suite mem_oam)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/mem_oam.gb test -m 100000000 -s meowgb-tests/expected_output/mem_oam.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/mem_oam.gb test -m 100000000 -s meowgb-tests/expected_output/mem_oam.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite oam_dma_restart)
|
- name: Run test ROM (mooneye-test-suite oam_dma_restart)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/oam_dma_restart.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_restart.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/oam_dma_restart.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_restart.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite oam_dma_start)
|
- name: Run test ROM (mooneye-test-suite oam_dma_start)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/oam_dma_start.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_start.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/oam_dma_start.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_start.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite oam_dma_timing)
|
- name: Run test ROM (mooneye-test-suite oam_dma_timing)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/oam_dma_timing.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_timing.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/oam_dma_timing.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite rapid_di_ei)
|
- name: Run test ROM (mooneye-test-suite rapid_di_ei)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/rapid_di_ei.gb test -m 100000000 -s meowgb-tests/expected_output/rapid_di_ei.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/rapid_di_ei.gb test -m 100000000 -s meowgb-tests/expected_output/rapid_di_ei.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite rapid_toggle)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/rapid_toggle.gb test -m 100000000 -s meowgb-tests/expected_output/rapid_toggle.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite reg_f)
|
- name: Run test ROM (mooneye-test-suite reg_f)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/reg_f.gb test -m 100000000 -s meowgb-tests/expected_output/reg_f.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/reg_f.gb test -m 100000000 -s meowgb-tests/expected_output/reg_f.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite reg_read)
|
- name: Run test ROM (mooneye-test-suite reg_read)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/reg_read.gb test -m 100000000 -s meowgb-tests/expected_output/reg_read.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/reg_read.gb test -m 100000000 -s meowgb-tests/expected_output/reg_read.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite stat_irq_blocking)
|
- name: Run test ROM (mooneye-test-suite stat_irq_blocking)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/stat_irq_blocking.gb test -m 100000000 -s meowgb-tests/expected_output/stat_irq_blocking.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/stat_irq_blocking.gb test -m 100000000 -s meowgb-tests/expected_output/stat_irq_blocking.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite stat_lyc_onoff)
|
- name: Run test ROM (mooneye-test-suite stat_lyc_onoff)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/stat_lyc_onoff.gb test -m 100000000 -s meowgb-tests/expected_output/stat_lyc_onoff.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/stat_lyc_onoff.gb test -m 100000000 -s meowgb-tests/expected_output/stat_lyc_onoff.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim00)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim00.gb test -m 100000000 -s meowgb-tests/expected_output/tim00.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite tim00_div_trigger)
|
- name: Run test ROM (mooneye-test-suite tim00_div_trigger)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/tim00_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim00_div_trigger.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim00_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim00_div_trigger.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite tim01)
|
- name: Run test ROM (mooneye-test-suite tim01)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/tim01.gb test -m 100000000 -s meowgb-tests/expected_output/tim01.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim01.gb test -m 100000000 -s meowgb-tests/expected_output/tim01.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim01_div_trigger)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim01_div_trigger.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim10)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim10.gb test -m 100000000 -s meowgb-tests/expected_output/tim10.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim10_div_trigger)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim10_div_trigger.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tim11)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim11.gb test -m 100000000 -s meowgb-tests/expected_output/tim11.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite tim11_div_trigger)
|
- name: Run test ROM (mooneye-test-suite tim11_div_trigger)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/tim11_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim11_div_trigger.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim11_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim11_div_trigger.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tima_reload)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tima_reload.gb test -m 100000000 -s meowgb-tests/expected_output/tima_reload.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tima_write_reloading)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tima_write_reloading.gb test -m 100000000 -s meowgb-tests/expected_output/tima_write_reloading.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite tma_write_reloading)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tma_write_reloading.gb test -m 100000000 -s meowgb-tests/expected_output/tma_write_reloading.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite unused_hwio-GS)
|
- name: Run test ROM (mooneye-test-suite unused_hwio-GS)
|
||||||
if: always()
|
if: always()
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/unused_hwio-GS.gb test -m 100000000 -s meowgb-tests/expected_output/unused_hwio-GS.bin
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/unused_hwio-GS.gb test -m 100000000 -s meowgb-tests/expected_output/unused_hwio-GS.bin
|
||||||
|
|
122
generate-action-and-tests.sh
Executable file
122
generate-action-and-tests.sh
Executable file
|
@ -0,0 +1,122 @@
|
||||||
|
#!/bin/bash
|
||||||
|
GH_ACTION_OUTPUT_FILE=./.github/workflows/action.yml
|
||||||
|
FJ_ACTION_OUTPUT_FILE=./.forgejo/workflows/action.yml
|
||||||
|
TEST_SCRIPT_OUTPUT_FILE=./run-test-roms.sh
|
||||||
|
TEST_MD_FILE=./tests.md
|
||||||
|
|
||||||
|
cat >$TEST_MD_FILE << EOF
|
||||||
|
# Passing Tests
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >$TEST_SCRIPT_OUTPUT_FILE << EOF
|
||||||
|
echo "Running Test Roms..."
|
||||||
|
|
||||||
|
if ! cargo build -p meowgb-tests --release ; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
TEST_TOTAL=0
|
||||||
|
TEST_SUCCESS=0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x $TEST_SCRIPT_OUTPUT_FILE
|
||||||
|
|
||||||
|
|
||||||
|
tee $GH_ACTION_OUTPUT_FILE $FJ_ACTION_OUTPUT_FILE >/dev/null << EOF
|
||||||
|
on:
|
||||||
|
- push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
main_test:
|
||||||
|
name: Test changes to main
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install toolchain
|
||||||
|
run: curl https://sh.rustup.rs -sSf | sh -s -- --profile minimal --default-toolchain stable -y && echo "\$HOME/.cargo/bin" >> \$GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Run cargo tests (meowgb-core)
|
||||||
|
run: cargo test -p meowgb-core
|
||||||
|
|
||||||
|
- name: Build release (meowgb-tests)
|
||||||
|
run: cargo build -p meowgb-tests --release
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >>$TEST_MD_FILE << EOF
|
||||||
|
## Blargg's Test ROMs
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
for full_f in ./test-roms/blargg/roms/*
|
||||||
|
do
|
||||||
|
f="${full_f##*/}"; f="${f%.*}";
|
||||||
|
TEST_CMD="./target/release/meowgb-tests test-roms/blargg/roms/$f.gb test -m 100000000 -s meowgb-tests/expected_output/$f.bin"
|
||||||
|
|
||||||
|
cat >>$TEST_SCRIPT_OUTPUT_FILE << EOF
|
||||||
|
|
||||||
|
echo "Running test ROM $full_f"
|
||||||
|
|
||||||
|
TEST_TOTAL=\$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=\$($TEST_CMD 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=\$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: \$res"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >>$TEST_MD_FILE << EOF
|
||||||
|
* $f.gb - [ROM]($full_f) - [Expected Serial Output](./meowgb-tests/expected_output/$f.bin)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
tee -a $GH_ACTION_OUTPUT_FILE $FJ_ACTION_OUTPUT_FILE >/dev/null << EOF
|
||||||
|
|
||||||
|
- name: Run test ROM (blargg $f)
|
||||||
|
if: always()
|
||||||
|
run: $TEST_CMD
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
|
||||||
|
cat >>$TEST_MD_FILE << EOF
|
||||||
|
|
||||||
|
## Mooneye Test Suite
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
for full_f in ./test-roms/mooneye-test-suite/roms/*
|
||||||
|
do
|
||||||
|
f="${full_f##*/}"; f="${f%.*}";
|
||||||
|
TEST_CMD="./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/$f.gb test -m 100000000 -s meowgb-tests/expected_output/$f.bin"
|
||||||
|
|
||||||
|
cat >>$TEST_SCRIPT_OUTPUT_FILE << EOF
|
||||||
|
|
||||||
|
echo "Running test ROM $full_f"
|
||||||
|
|
||||||
|
TEST_TOTAL=\$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=\$($TEST_CMD 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=\$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: \$res"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >>$TEST_MD_FILE << EOF
|
||||||
|
* $f.gb - [ROM]($full_f) - [Expected Serial Output](./meowgb-tests/expected_output/$f.bin)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
tee -a $GH_ACTION_OUTPUT_FILE $FJ_ACTION_OUTPUT_FILE >/dev/null << EOF
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite $f)
|
||||||
|
if: always()
|
||||||
|
run: $TEST_CMD
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
|
||||||
|
cat >>$TEST_SCRIPT_OUTPUT_FILE << EOF
|
||||||
|
|
||||||
|
echo "Succeeded in running \$TEST_SUCCESS/\$TEST_TOTAL"
|
||||||
|
EOF
|
|
@ -1,57 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
OUTPUT_FILE=./.github/workflows/action.yml
|
|
||||||
|
|
||||||
cat >$OUTPUT_FILE << EOF
|
|
||||||
on:
|
|
||||||
- push
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
main_test:
|
|
||||||
name: Test changes to main
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Install toolchain
|
|
||||||
run: curl https://sh.rustup.rs -sSf | sh -s -- --profile minimal --default-toolchain stable -y && echo "\$HOME/.cargo/bin" >> \$GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Run cargo tests (meowgb-core)
|
|
||||||
run: cargo test -p meowgb-core
|
|
||||||
EOF
|
|
||||||
|
|
||||||
|
|
||||||
for f in ./test-roms/blargg/roms/*
|
|
||||||
do
|
|
||||||
f="${f##*/}"; f="${f%.*}";
|
|
||||||
cat >>$OUTPUT_FILE << EOF
|
|
||||||
|
|
||||||
- name: Run test ROM (blargg $f)
|
|
||||||
if: always()
|
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/blargg/roms/$f.gb test -m 100000000 -s meowgb-tests/expected_output/$f.bin
|
|
||||||
EOF
|
|
||||||
done
|
|
||||||
|
|
||||||
# for f in ./test-roms/mealybug-tearoom-tests/roms/*
|
|
||||||
# do
|
|
||||||
# f="${f##*/}"; f="${f%.*}";
|
|
||||||
# cat >>$OUTPUT_FILE << EOF
|
|
||||||
|
|
||||||
# - name: Run test ROM (mealybug-tearoom-tests $f)
|
|
||||||
# if: always()
|
|
||||||
# run: cargo run -p meowgb-tests --release -- test-roms/mealybug-tearoom-tests/roms/$f.gb test -m 100000000 -s meowgb-tests/expected_output/$f.bin
|
|
||||||
# EOF
|
|
||||||
# done
|
|
||||||
|
|
||||||
for f in ./test-roms/mooneye-test-suite/roms/*
|
|
||||||
do
|
|
||||||
f="${f##*/}"; f="${f%.*}";
|
|
||||||
cat >>$OUTPUT_FILE << EOF
|
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite $f)
|
|
||||||
if: always()
|
|
||||||
run: cargo run -p meowgb-tests --release -- test-roms/mooneye-test-suite/roms/$f.gb test -m 100000000 -s meowgb-tests/expected_output/$f.bin
|
|
||||||
EOF
|
|
||||||
done
|
|
||||||
|
|
||||||
cp .github/workflows/action.yml .forgejo/workflows/action.yml
|
|
|
@ -10,8 +10,6 @@ pub mod serial;
|
||||||
pub mod sound;
|
pub mod sound;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
|
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
|
|
||||||
use interrupts::Interrupts;
|
use interrupts::Interrupts;
|
||||||
use joypad::Joypad;
|
use joypad::Joypad;
|
||||||
use mapper::Mapper;
|
use mapper::Mapper;
|
||||||
|
@ -21,82 +19,12 @@ use timer::Timer;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
cpu::Registers,
|
cpu::Registers,
|
||||||
|
dma::DmaState,
|
||||||
mapper::{mbc1::MBC1, NoMBC},
|
mapper::{mbc1::MBC1, NoMBC},
|
||||||
serial::{Serial, SerialWriter},
|
serial::{Serial, SerialWriter},
|
||||||
sound::Sound, dma::DmaState,
|
sound::Sound,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RingBuffer<T: std::fmt::Debug + Copy + Default, const SIZE: usize> {
|
|
||||||
buffer: [T; SIZE],
|
|
||||||
size: usize,
|
|
||||||
write_ptr: usize,
|
|
||||||
read_ptr: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: std::fmt::Debug + Copy + Default, const SIZE: usize> RingBuffer<T, SIZE> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
RingBuffer { buffer: [T::default(); SIZE], size: 0, write_ptr: 0, read_ptr: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, value: T) {
|
|
||||||
self.buffer[self.write_ptr] = value;
|
|
||||||
if self.size < SIZE {
|
|
||||||
self.size += 1;
|
|
||||||
} else {
|
|
||||||
self.read_ptr += 1;
|
|
||||||
self.read_ptr %= SIZE;
|
|
||||||
}
|
|
||||||
self.write_ptr += 1;
|
|
||||||
self.write_ptr %= SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_vec(&self) -> Vec<T> {
|
|
||||||
let mut out = Vec::new();
|
|
||||||
let mut offset = self.read_ptr;
|
|
||||||
|
|
||||||
for _ in 0..self.size {
|
|
||||||
out.push(self.buffer[offset]);
|
|
||||||
|
|
||||||
offset += 1;
|
|
||||||
offset %= SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_ringbuffer() {
|
|
||||||
let mut ringbuffer: RingBuffer<u8, 16> = RingBuffer::new();
|
|
||||||
|
|
||||||
for x in 0..16 {
|
|
||||||
ringbuffer.push(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
ringbuffer.to_vec().as_slice(),
|
|
||||||
&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
|
||||||
);
|
|
||||||
ringbuffer.push(16);
|
|
||||||
assert_eq!(
|
|
||||||
ringbuffer.to_vec().as_slice(),
|
|
||||||
&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
|
||||||
);
|
|
||||||
ringbuffer.push(17);
|
|
||||||
assert_eq!(
|
|
||||||
ringbuffer.to_vec().as_slice(),
|
|
||||||
&[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
|
|
||||||
);
|
|
||||||
|
|
||||||
for x in 18..32 {
|
|
||||||
ringbuffer.push(x);
|
|
||||||
}
|
|
||||||
assert_eq!(
|
|
||||||
ringbuffer.to_vec().as_slice(),
|
|
||||||
&[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Gameboy<S: SerialWriter> {
|
pub struct Gameboy<S: SerialWriter> {
|
||||||
pub ppu: Ppu,
|
pub ppu: Ppu,
|
||||||
pub memory: Memory,
|
pub memory: Memory,
|
||||||
|
@ -109,19 +37,11 @@ pub struct Gameboy<S: SerialWriter> {
|
||||||
pub dma: DmaState,
|
pub dma: DmaState,
|
||||||
pub sound: Sound,
|
pub sound: Sound,
|
||||||
|
|
||||||
pub single_step: bool,
|
|
||||||
pub breakpoints: [bool; u16::MAX as usize + 1],
|
|
||||||
pub mem_read_breakpoints: [bool; u16::MAX as usize + 1],
|
|
||||||
pub mem_write_breakpoints: [bool; u16::MAX as usize + 1],
|
|
||||||
trigger_bp: bool,
|
|
||||||
pub log_instructions: bool,
|
|
||||||
pub halt: bool,
|
pub halt: bool,
|
||||||
pub halt_bug: bool,
|
pub halt_bug: bool,
|
||||||
pub used_halt_bug: bool,
|
pub used_halt_bug: bool,
|
||||||
pub stop: bool,
|
pub stop: bool,
|
||||||
|
|
||||||
pub pc_history: RingBuffer<u16, 0x200>,
|
|
||||||
|
|
||||||
pub tick_count: u8,
|
pub tick_count: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,41 +61,14 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
false => Registers::post_rom(),
|
false => Registers::post_rom(),
|
||||||
},
|
},
|
||||||
sound: Sound::new(),
|
sound: Sound::new(),
|
||||||
single_step: false,
|
|
||||||
breakpoints: [false; u16::MAX as usize + 1],
|
|
||||||
mem_read_breakpoints: [false; u16::MAX as usize + 1],
|
|
||||||
mem_write_breakpoints: [false; u16::MAX as usize + 1],
|
|
||||||
trigger_bp: false,
|
|
||||||
log_instructions: false,
|
|
||||||
halt: false,
|
halt: false,
|
||||||
halt_bug: false,
|
halt_bug: false,
|
||||||
used_halt_bug: false,
|
used_halt_bug: false,
|
||||||
stop: false,
|
stop: false,
|
||||||
pc_history: RingBuffer::new(),
|
|
||||||
tick_count: 0,
|
tick_count: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log_next_opcode(&self) {
|
|
||||||
let op = self.internal_cpu_read_u8(self.registers.pc);
|
|
||||||
if op == 0xCB {
|
|
||||||
let op = self.internal_cpu_read_u8(self.registers.pc.overflowing_add(1).0);
|
|
||||||
log::info!(
|
|
||||||
"Executing opcode @ {:#X} (prefixed) (cycle {}): {:#X}",
|
|
||||||
self.registers.pc,
|
|
||||||
self.registers.cycle,
|
|
||||||
op
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
log::info!(
|
|
||||||
"Executing opcode @ {:#X} (cycle {}): {:#X}",
|
|
||||||
self.registers.pc,
|
|
||||||
self.registers.cycle,
|
|
||||||
op
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_cartridge(&mut self, bytes: Vec<u8>) {
|
pub fn load_cartridge(&mut self, bytes: Vec<u8>) {
|
||||||
if bytes.len() < 0x150 {
|
if bytes.len() < 0x150 {
|
||||||
panic!("Bad cartridge (len < 0x150)");
|
panic!("Bad cartridge (len < 0x150)");
|
||||||
|
@ -189,215 +82,31 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log_state(&self) {
|
pub fn tick_4(&mut self) -> bool {
|
||||||
log::info!("\n-- Registers --\nAF: {:04X}\nBC: {:04X}\nDE: {:04X}\nHL: {:04X}\nSP: {:04X}\nPC: {:04X}\nZero: {}\nSubtract: {}\nHalf-Carry: {}\nCarry: {}\n-- Interrupts --\nIME: {}\nIE VBlank: {}\nIE LCD Stat: {}\nIE Timer: {}\nIE Serial: {}\nIE Joypad: {}\nIF VBlank: {}\nIF LCD Stat: {}\nIF Timer: {}\nIF Serial: {}\nIF Joypad: {}\n", self.registers.get_af(), self.registers.get_bc(), self.registers.get_de(), self.registers.get_hl(), self.registers.get_sp(), self.registers.pc, self.registers.get_zero(), self.registers.get_subtract(), self.registers.get_half_carry(), self.registers.get_carry(), self.interrupts.ime, self.interrupts.read_ie_vblank(), self.interrupts.read_ie_lcd_stat(), self.interrupts.read_ie_timer(), self.interrupts.read_ie_serial(), self.interrupts.read_ie_joypad(), self.interrupts.read_if_vblank(), self.interrupts.read_if_lcd_stat(), self.interrupts.read_if_timer(), self.interrupts.read_if_serial(), self.interrupts.read_if_joypad());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tick_4(&mut self) -> (bool, Option<Duration>) {
|
|
||||||
let mut request_redraw = false;
|
let mut request_redraw = false;
|
||||||
let mut debug_time = None;
|
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
let (t_request_redraw, t_debug_time) = self.tick();
|
let t_request_redraw = self.tick();
|
||||||
request_redraw |= t_request_redraw;
|
request_redraw |= t_request_redraw;
|
||||||
if t_debug_time.is_some() {
|
|
||||||
assert!(debug_time.is_none());
|
|
||||||
debug_time = t_debug_time;
|
|
||||||
}
|
}
|
||||||
|
request_redraw
|
||||||
}
|
}
|
||||||
|
|
||||||
(request_redraw, debug_time)
|
pub fn tick(&mut self) -> bool {
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tick(&mut self) -> (bool, Option<Duration>) {
|
|
||||||
if self.tick_count == 0 {
|
if self.tick_count == 0 {
|
||||||
if self.breakpoints[self.registers.pc as usize] && !self.single_step {
|
|
||||||
self.single_step = true;
|
|
||||||
log::info!("Breakpoint hit @ {:#X}", self.registers.pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut diff = None;
|
|
||||||
|
|
||||||
if self.trigger_bp || (self.single_step && self.registers.cycle == 0) {
|
|
||||||
let entered_step = Instant::now();
|
|
||||||
self.trigger_bp = false;
|
|
||||||
self.single_step = true;
|
|
||||||
let mut input = String::new();
|
|
||||||
let mut exit = true;
|
|
||||||
match std::io::stdin().read_line(&mut input) {
|
|
||||||
Ok(_) => {
|
|
||||||
let lower = input.trim_end().to_lowercase();
|
|
||||||
let (lhs, rhs) =
|
|
||||||
lower.split_once(' ').unwrap_or_else(|| (lower.as_str(), ""));
|
|
||||||
match lhs {
|
|
||||||
"read" => match u16::from_str_radix(rhs, 16) {
|
|
||||||
Ok(address) => {
|
|
||||||
let res = self.internal_cpu_read_u8(address);
|
|
||||||
log::info!("{:#X}: {:#X} ({:#b})", address, res, res);
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("Failed to parse input as hex u16 (f.ex 420C)")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"regs" => self.log_state(),
|
|
||||||
"op" => {
|
|
||||||
self.log_next_opcode();
|
|
||||||
}
|
|
||||||
"bp" => match u16::from_str_radix(rhs, 16) {
|
|
||||||
Ok(address) => {
|
|
||||||
let bp = &mut self.breakpoints[address as usize];
|
|
||||||
*bp = !*bp;
|
|
||||||
match *bp {
|
|
||||||
true => log::info!("Set breakpoint @ {:#X}", address),
|
|
||||||
false => log::info!("Cleared breakpoint @ {:#X}", address),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("Failed to parse input as hex u16 (f.ex 420C)")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"bpr" => match u16::from_str_radix(rhs, 16) {
|
|
||||||
Ok(address) => {
|
|
||||||
let bp = &mut self.mem_read_breakpoints[address as usize];
|
|
||||||
*bp = !*bp;
|
|
||||||
match *bp {
|
|
||||||
true => {
|
|
||||||
log::info!("Set breakpoint on read @ {:#X}", address)
|
|
||||||
}
|
|
||||||
false => {
|
|
||||||
log::info!(
|
|
||||||
"Cleared breakpoint on read @ {:#X}",
|
|
||||||
address
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("Failed to parse input as hex u16 (f.ex 420C)")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"bpw" => match u16::from_str_radix(rhs, 16) {
|
|
||||||
Ok(address) => {
|
|
||||||
let bp = &mut self.mem_write_breakpoints[address as usize];
|
|
||||||
*bp = !*bp;
|
|
||||||
match *bp {
|
|
||||||
true => {
|
|
||||||
log::info!("Set breakpoint on write @ {:#X}", address)
|
|
||||||
}
|
|
||||||
false => {
|
|
||||||
log::info!(
|
|
||||||
"Cleared breakpoint on write @ {:#X}",
|
|
||||||
address
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
log::error!("Failed to parse input as hex u16 (f.ex 420C)")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c" => {
|
|
||||||
self.single_step = false;
|
|
||||||
log::info!("Continuing");
|
|
||||||
exit = false;
|
|
||||||
}
|
|
||||||
"timer" => {
|
|
||||||
println!(
|
|
||||||
"-- Timer Info --\n{:#?}\n-- End of Timer Info --",
|
|
||||||
self.timer
|
|
||||||
)
|
|
||||||
}
|
|
||||||
"p" | "pause" => {
|
|
||||||
self.single_step = true;
|
|
||||||
log::info!("Single step activated");
|
|
||||||
exit = false;
|
|
||||||
}
|
|
||||||
"pch" => {
|
|
||||||
println!("-- Start of PC History (new to old) --");
|
|
||||||
for (idx, pc) in self.pc_history.to_vec().iter().rev().enumerate() {
|
|
||||||
println!("{}: {:#04X}", idx + 1, pc);
|
|
||||||
}
|
|
||||||
println!("-- End of PC History --");
|
|
||||||
}
|
|
||||||
"s" | "step" | "" => {
|
|
||||||
self.log_next_opcode();
|
|
||||||
exit = false;
|
|
||||||
}
|
|
||||||
"ls" => {
|
|
||||||
self.log_state();
|
|
||||||
exit = false;
|
|
||||||
}
|
|
||||||
"dumpbgtiles" => {
|
|
||||||
self.ppu.dump_bg_tiles();
|
|
||||||
}
|
|
||||||
"dumpfb" => {
|
|
||||||
println!("Written to: {}", self.ppu.dump_fb_to_file());
|
|
||||||
}
|
|
||||||
"dumpoam" => {
|
|
||||||
for x in 0..self.ppu.oam.len() {
|
|
||||||
if x % 0x10 == 0 {
|
|
||||||
print!("\n{:X}: ", 0xFE00 + x)
|
|
||||||
}
|
|
||||||
|
|
||||||
let mem_val = self.ppu.oam[x];
|
|
||||||
print!("{:02X} ", mem_val);
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
}
|
|
||||||
"dumpvram" => {
|
|
||||||
for x in 0..0x200 {
|
|
||||||
if x % 0x10 == 0 {
|
|
||||||
print!("\n{:X}: ", 0x8000 + x)
|
|
||||||
}
|
|
||||||
|
|
||||||
let mem_val = self.ppu.vram[x];
|
|
||||||
print!("{:02X} ", mem_val);
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
}
|
|
||||||
"dumptilemap" => {
|
|
||||||
let base = match (self.ppu.registers.lcdc >> 3) & 0b1 == 1 {
|
|
||||||
true => 0x1C00,
|
|
||||||
false => 0x1800,
|
|
||||||
};
|
|
||||||
|
|
||||||
for x in 0..0x400 {
|
|
||||||
if x % 0x10 == 0 {
|
|
||||||
print!("\n{:X}: ", 0x8000 + base + x)
|
|
||||||
}
|
|
||||||
|
|
||||||
let mem_val = self.ppu.vram[base + x];
|
|
||||||
print!("{:02X} ", mem_val);
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(stdin_err) => panic!("Failed to lock stdin: {:?}", stdin_err),
|
|
||||||
}
|
|
||||||
|
|
||||||
diff = Some(entered_step.elapsed());
|
|
||||||
if exit {
|
|
||||||
return (false, diff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if self.timer.tick() {
|
|
||||||
self.interrupts.write_if_timer(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu::tick_cpu(self);
|
cpu::tick_cpu(self);
|
||||||
let redraw_requested = self.ppu.tick(&mut self.interrupts);
|
let redraw_requested = self.ppu.tick(&mut self.interrupts);
|
||||||
self.dma.tick_dma(&mut self.ppu, &self.memory, self.cartridge.as_deref());
|
self.dma.tick_dma(&mut self.ppu, &self.memory, self.cartridge.as_deref());
|
||||||
if self.serial.tick() {
|
self.serial.tick(&mut self.interrupts);
|
||||||
self.interrupts.write_if_serial(true);
|
self.timer.tick(&mut self.interrupts);
|
||||||
}
|
|
||||||
self.tick_count += 1;
|
self.tick_count += 1;
|
||||||
(redraw_requested, diff)
|
redraw_requested
|
||||||
} else {
|
} else {
|
||||||
let redraw_requested = self.ppu.tick(&mut self.interrupts);
|
let redraw_requested = self.ppu.tick(&mut self.interrupts);
|
||||||
|
self.timer.tick(&mut self.interrupts);
|
||||||
self.tick_count += 1;
|
self.tick_count += 1;
|
||||||
self.tick_count %= 4;
|
self.tick_count %= 4;
|
||||||
(redraw_requested, None)
|
redraw_requested
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,9 +116,9 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
0xFF01 => self.serial.sb,
|
0xFF01 => self.serial.sb,
|
||||||
0xFF02 => self.serial.get_sc(),
|
0xFF02 => self.serial.get_sc(),
|
||||||
0xFF03 => 0xFF, // Unused
|
0xFF03 => 0xFF, // Unused
|
||||||
0xFF04 => self.timer.div,
|
0xFF04 => self.timer.read_div(),
|
||||||
0xFF05 => self.timer.tima,
|
0xFF05 => self.timer.read_tima(),
|
||||||
0xFF06 => self.timer.tma,
|
0xFF06 => self.timer.read_tma(),
|
||||||
0xFF07 => self.timer.read_tac(),
|
0xFF07 => self.timer.read_tac(),
|
||||||
0xFF08..=0xFF0E => 0xFF, // Unused
|
0xFF08..=0xFF0E => 0xFF, // Unused
|
||||||
0xFF0F => self.interrupts.interrupt_flag,
|
0xFF0F => self.interrupts.interrupt_flag,
|
||||||
|
@ -469,9 +178,9 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
0xFF01 => self.serial.sb = value,
|
0xFF01 => self.serial.sb = value,
|
||||||
0xFF02 => self.serial.set_sc(value),
|
0xFF02 => self.serial.set_sc(value),
|
||||||
0xFF03 => {} // Unused
|
0xFF03 => {} // Unused
|
||||||
0xFF04 => self.timer.div = 0,
|
0xFF04 => self.timer.write_div(),
|
||||||
0xFF05 => self.timer.tima = value,
|
0xFF05 => self.timer.write_tima(value),
|
||||||
0xFF06 => self.timer.tma = value,
|
0xFF06 => self.timer.write_tma(value),
|
||||||
0xFF07 => self.timer.write_tac(value),
|
0xFF07 => self.timer.write_tac(value),
|
||||||
0xFF08..=0xFF0E => {} // Unused
|
0xFF08..=0xFF0E => {} // Unused
|
||||||
0xFF0F => self.interrupts.interrupt_flag = value | !0b1_1111,
|
0xFF0F => self.interrupts.interrupt_flag = value | !0b1_1111,
|
||||||
|
@ -485,19 +194,19 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
0xFF17 => self.sound.nr22 = value,
|
0xFF17 => self.sound.nr22 = value,
|
||||||
0xFF18 => self.sound.nr23 = value,
|
0xFF18 => self.sound.nr23 = value,
|
||||||
0xFF19 => self.sound.nr24 = value,
|
0xFF19 => self.sound.nr24 = value,
|
||||||
0xFF1A => {}, //self.sound.nr30 = value, - Unwritable on DMG
|
0xFF1A => {} //self.sound.nr30 = value, - Unwritable on DMG
|
||||||
0xFF1B => self.sound.nr31 = value,
|
0xFF1B => self.sound.nr31 = value,
|
||||||
0xFF1C => {}, //self.sound.nr32 = value, - Unwritable on DMG
|
0xFF1C => {} //self.sound.nr32 = value, - Unwritable on DMG
|
||||||
0xFF1D => self.sound.nr33 = value,
|
0xFF1D => self.sound.nr33 = value,
|
||||||
0xFF1E => self.sound.nr34 = value,
|
0xFF1E => self.sound.nr34 = value,
|
||||||
0xFF1F => {}
|
0xFF1F => {}
|
||||||
0xFF20 => {}, //self.sound.nr41 = value, - Unwritable on DMG
|
0xFF20 => {} //self.sound.nr41 = value, - Unwritable on DMG
|
||||||
0xFF21 => self.sound.nr42 = value,
|
0xFF21 => self.sound.nr42 = value,
|
||||||
0xFF22 => self.sound.nr43 = value,
|
0xFF22 => self.sound.nr43 = value,
|
||||||
0xFF23 => {}, //self.sound.nr44 = value, - Unwritable on DMG
|
0xFF23 => {} //self.sound.nr44 = value, - Unwritable on DMG
|
||||||
0xFF24 => self.sound.nr50 = value,
|
0xFF24 => self.sound.nr50 = value,
|
||||||
0xFF25 => self.sound.nr51 = value,
|
0xFF25 => self.sound.nr51 = value,
|
||||||
0xFF26 => {}, //self.sound.nr52 = value, - Unwritable on DMG
|
0xFF26 => {} //self.sound.nr52 = value, - Unwritable on DMG
|
||||||
0xFF27..=0xFF2F => {}
|
0xFF27..=0xFF2F => {}
|
||||||
0xFF30..=0xFF3F => self.sound.wave_pattern_ram[address as usize - 0xFF30] = value,
|
0xFF30..=0xFF3F => self.sound.wave_pattern_ram[address as usize - 0xFF30] = value,
|
||||||
0xFF40 => {
|
0xFF40 => {
|
||||||
|
@ -555,12 +264,12 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
0..=0xFF if !self.memory.bootrom_disabled => self.memory.bootrom[address as usize],
|
0..=0xFF if !self.memory.bootrom_disabled => self.memory.bootrom[address as usize],
|
||||||
0..=0x7FFF => match self.cartridge.as_ref() {
|
0..=0x7FFF => match self.cartridge.as_ref() {
|
||||||
Some(mapper) => mapper.read_rom_u8(address),
|
Some(mapper) => mapper.read_rom_u8(address),
|
||||||
None => 0,
|
None => 0xFF,
|
||||||
},
|
},
|
||||||
0x8000..=0x9FFF => self.ppu.cpu_read_vram(address),
|
0x8000..=0x9FFF => self.ppu.cpu_read_vram(address),
|
||||||
0xA000..=0xBFFF => match self.cartridge.as_ref() {
|
0xA000..=0xBFFF => match self.cartridge.as_ref() {
|
||||||
Some(mapper) => mapper.read_eram_u8(address),
|
Some(mapper) => mapper.read_eram_u8(address - 0xA000),
|
||||||
None => 0,
|
None => 0xFF,
|
||||||
},
|
},
|
||||||
0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000],
|
0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000],
|
||||||
0xE000..=0xFDFF => self.memory.wram[address as usize - 0xE000],
|
0xE000..=0xFDFF => self.memory.wram[address as usize - 0xE000],
|
||||||
|
@ -586,7 +295,7 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
0x8000..=0x9FFF => self.ppu.cpu_write_vram(address, value),
|
0x8000..=0x9FFF => self.ppu.cpu_write_vram(address, value),
|
||||||
0xA000..=0xBFFF => {
|
0xA000..=0xBFFF => {
|
||||||
if let Some(mapper) = self.cartridge.as_mut() {
|
if let Some(mapper) = self.cartridge.as_mut() {
|
||||||
mapper.write_eram_u8(address, value)
|
mapper.write_eram_u8(address - 0xA000, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000] = value,
|
0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000] = value,
|
||||||
|
@ -599,18 +308,27 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn internal_cpu_read_u8(&self, address: u16) -> u8 {
|
pub fn cpu_read_u8(&mut self, address: u16) {
|
||||||
if !self.ppu.dma_occuring {
|
assert!(!self.registers.mem_op_happened);
|
||||||
match address {
|
assert!(self.registers.mem_read_hold.is_none());
|
||||||
|
self.registers.mem_op_happened = true;
|
||||||
|
let value = match self.ppu.dma_occuring {
|
||||||
|
true => match address {
|
||||||
|
0..=0xFEFF => 0xFF,
|
||||||
|
0xFF00..=0xFF7F => self.cpu_read_io(address),
|
||||||
|
0xFF80..=0xFFFE => self.memory.hram[address as usize - 0xFF80],
|
||||||
|
0xFFFF => self.interrupts.interrupt_enable,
|
||||||
|
},
|
||||||
|
false => match address {
|
||||||
0..=0xFF if !self.memory.bootrom_disabled => self.memory.bootrom[address as usize],
|
0..=0xFF if !self.memory.bootrom_disabled => self.memory.bootrom[address as usize],
|
||||||
0..=0x7FFF => match self.cartridge.as_ref() {
|
0..=0x7FFF => match self.cartridge.as_ref() {
|
||||||
Some(mapper) => mapper.read_rom_u8(address),
|
Some(mapper) => mapper.read_rom_u8(address),
|
||||||
None => 0,
|
None => 0xFF,
|
||||||
},
|
},
|
||||||
0x8000..=0x9FFF => self.ppu.cpu_read_vram(address),
|
0x8000..=0x9FFF => self.ppu.cpu_read_vram(address),
|
||||||
0xA000..=0xBFFF => match self.cartridge.as_ref() {
|
0xA000..=0xBFFF => match self.cartridge.as_ref() {
|
||||||
Some(mapper) => mapper.read_eram_u8(address),
|
Some(mapper) => mapper.read_eram_u8(address - 0xA000),
|
||||||
None => 0,
|
None => 0xFF,
|
||||||
},
|
},
|
||||||
0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000],
|
0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000],
|
||||||
0xE000..=0xFDFF => self.memory.wram[address as usize - 0xE000],
|
0xE000..=0xFDFF => self.memory.wram[address as usize - 0xE000],
|
||||||
|
@ -619,41 +337,23 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
0xFF00..=0xFF7F => self.cpu_read_io(address),
|
0xFF00..=0xFF7F => self.cpu_read_io(address),
|
||||||
0xFF80..=0xFFFE => self.memory.hram[address as usize - 0xFF80],
|
0xFF80..=0xFFFE => self.memory.hram[address as usize - 0xFF80],
|
||||||
0xFFFF => self.interrupts.interrupt_enable,
|
0xFFFF => self.interrupts.interrupt_enable,
|
||||||
}
|
},
|
||||||
} else {
|
};
|
||||||
match address {
|
self.registers.mem_read_hold = Some(value);
|
||||||
0..=0xFEFF => 0xFF,
|
|
||||||
0xFF00..=0xFF7F => self.cpu_read_io(address),
|
|
||||||
0xFF80..=0xFFFE => self.memory.hram[address as usize - 0xFF80],
|
|
||||||
0xFFFF => self.interrupts.interrupt_enable,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cpu_read_u8(&mut self, address: u16) {
|
|
||||||
assert!(!self.registers.mem_op_happened);
|
|
||||||
assert!(self.registers.mem_read_hold.is_none());
|
|
||||||
self.registers.mem_op_happened = true;
|
|
||||||
|
|
||||||
if self.mem_read_breakpoints[address as usize] {
|
|
||||||
self.trigger_bp = true;
|
|
||||||
log::info!("Triggered read bp @ {:#X}", address);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.registers.mem_read_hold = Some(self.internal_cpu_read_u8(address));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cpu_write_u8(&mut self, address: u16, value: u8) {
|
pub fn cpu_write_u8(&mut self, address: u16, value: u8) {
|
||||||
assert!(!self.registers.mem_op_happened);
|
assert!(!self.registers.mem_op_happened);
|
||||||
self.registers.mem_op_happened = true;
|
self.registers.mem_op_happened = true;
|
||||||
|
|
||||||
if self.mem_write_breakpoints[address as usize] {
|
match self.ppu.dma_occuring {
|
||||||
self.trigger_bp = true;
|
true => match address {
|
||||||
log::info!("Triggered write bp @ {:#X} (value: {:#02X})", address, value);
|
0..=0xFEFF => {}
|
||||||
}
|
0xFF00..=0xFF7F => self.cpu_write_io(address, value),
|
||||||
|
0xFF80..=0xFFFE => self.memory.hram[address as usize - 0xFF80] = value,
|
||||||
if !self.ppu.dma_occuring {
|
0xFFFF => self.interrupts.cpu_set_interrupt_enable(value),
|
||||||
match address {
|
},
|
||||||
|
false => match address {
|
||||||
0..=0xFF if !self.memory.bootrom_disabled => {}
|
0..=0xFF if !self.memory.bootrom_disabled => {}
|
||||||
0..=0x7FFF => {
|
0..=0x7FFF => {
|
||||||
if let Some(mapper) = self.cartridge.as_mut() {
|
if let Some(mapper) = self.cartridge.as_mut() {
|
||||||
|
@ -663,7 +363,7 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
0x8000..=0x9FFF => self.ppu.cpu_write_vram(address, value),
|
0x8000..=0x9FFF => self.ppu.cpu_write_vram(address, value),
|
||||||
0xA000..=0xBFFF => {
|
0xA000..=0xBFFF => {
|
||||||
if let Some(mapper) = self.cartridge.as_mut() {
|
if let Some(mapper) = self.cartridge.as_mut() {
|
||||||
mapper.write_eram_u8(address, value)
|
mapper.write_eram_u8(address - 0xA000, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000] = value,
|
0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000] = value,
|
||||||
|
@ -673,14 +373,7 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
0xFF00..=0xFF7F => self.cpu_write_io(address, value),
|
0xFF00..=0xFF7F => self.cpu_write_io(address, value),
|
||||||
0xFF80..=0xFFFE => self.memory.hram[address as usize - 0xFF80] = value,
|
0xFF80..=0xFFFE => self.memory.hram[address as usize - 0xFF80] = value,
|
||||||
0xFFFF => self.interrupts.cpu_set_interrupt_enable(value),
|
0xFFFF => self.interrupts.cpu_set_interrupt_enable(value),
|
||||||
}
|
},
|
||||||
} else {
|
|
||||||
match address {
|
|
||||||
0..=0xFEFF => {}
|
|
||||||
0xFF00..=0xFF7F => self.cpu_write_io(address, value),
|
|
||||||
0xFF80..=0xFFFE => self.memory.hram[address as usize - 0xFF80] = value,
|
|
||||||
0xFFFF => self.interrupts.cpu_set_interrupt_enable(value),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,9 +238,7 @@ pub fn tick_cpu(state: &mut Gameboy<impl SerialWriter>) {
|
||||||
} else {
|
} else {
|
||||||
let opcode = match state.registers.current_opcode {
|
let opcode = match state.registers.current_opcode {
|
||||||
Some(opcode) => opcode,
|
Some(opcode) => opcode,
|
||||||
None => {
|
None => match state.registers.mem_read_hold.take() {
|
||||||
state.pc_history.push(state.registers.pc);
|
|
||||||
match state.registers.mem_read_hold.take() {
|
|
||||||
Some(opcode) => {
|
Some(opcode) => {
|
||||||
state.registers.current_opcode = Some(opcode);
|
state.registers.current_opcode = Some(opcode);
|
||||||
opcode
|
opcode
|
||||||
|
@ -249,8 +247,7 @@ pub fn tick_cpu(state: &mut Gameboy<impl SerialWriter>) {
|
||||||
state.cpu_read_u8(state.registers.pc);
|
state.cpu_read_u8(state.registers.pc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let result: CycleResult = match opcode {
|
let result: CycleResult = match opcode {
|
||||||
|
|
|
@ -56,12 +56,12 @@ opcode!(stop, 0x10, "STOP", false, 1, {
|
||||||
true => {
|
true => {
|
||||||
state.registers.pc = state.registers.pc.wrapping_add(1);
|
state.registers.pc = state.registers.pc.wrapping_add(1);
|
||||||
state.stop = true;
|
state.stop = true;
|
||||||
state.timer.div = 0;
|
state.timer.write_div();
|
||||||
},
|
},
|
||||||
false => {
|
false => {
|
||||||
state.registers.pc = state.registers.pc.wrapping_add(2);
|
state.registers.pc = state.registers.pc.wrapping_add(2);
|
||||||
state.stop = true;
|
state.stop = true;
|
||||||
state.timer.div = 0;
|
state.timer.write_div();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{ppu::Ppu, memory::Memory, mapper::Mapper};
|
use super::{mapper::Mapper, memory::Memory, ppu::Ppu};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DmaState {
|
pub struct DmaState {
|
||||||
|
@ -18,7 +18,12 @@ impl DmaState {
|
||||||
self.restarting = Some((base, false));
|
self.restarting = Some((base, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick_dma(&mut self, ppu: &mut Ppu, memory: &Memory, cartridge: Option<&(dyn Mapper + Send + Sync)>) {
|
pub fn tick_dma(
|
||||||
|
&mut self,
|
||||||
|
ppu: &mut Ppu,
|
||||||
|
memory: &Memory,
|
||||||
|
cartridge: Option<&(dyn Mapper + Send + Sync)>,
|
||||||
|
) {
|
||||||
match self.restarting {
|
match self.restarting {
|
||||||
Some((base, false)) => self.restarting = Some((base, true)),
|
Some((base, false)) => self.restarting = Some((base, true)),
|
||||||
Some((base, true)) => {
|
Some((base, true)) => {
|
||||||
|
@ -26,7 +31,7 @@ impl DmaState {
|
||||||
self.remaining_cycles = 0xA0;
|
self.remaining_cycles = 0xA0;
|
||||||
self.restarting = None;
|
self.restarting = None;
|
||||||
}
|
}
|
||||||
None => {},
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu.dma_occuring = self.remaining_cycles > 0;
|
ppu.dma_occuring = self.remaining_cycles > 0;
|
||||||
|
@ -55,7 +60,5 @@ impl DmaState {
|
||||||
ppu.dma_write_oam(offset, value);
|
ppu.dma_write_oam(offset, value);
|
||||||
self.remaining_cycles -= 1;
|
self.remaining_cycles -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -57,13 +57,13 @@ impl Joypad {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cpu_read(&self) -> u8 {
|
pub fn cpu_read(&self) -> u8 {
|
||||||
(0b11 << 6) | match self.mode {
|
(0b11 << 6)
|
||||||
|
| match self.mode {
|
||||||
JoypadMode::Action => {
|
JoypadMode::Action => {
|
||||||
(1 << 4)
|
(1 << 4)
|
||||||
| ((!self.start as u8) << 3)
|
| ((!self.start as u8) << 3)
|
||||||
| ((!self.select as u8) << 2)
|
| ((!self.select as u8) << 2)
|
||||||
| ((!self.b as u8) << 1)
|
| ((!self.b as u8) << 1) | (!self.a as u8)
|
||||||
| (!self.a as u8)
|
|
||||||
}
|
}
|
||||||
JoypadMode::Direction => {
|
JoypadMode::Direction => {
|
||||||
(1 << 5)
|
(1 << 5)
|
||||||
|
|
|
@ -4,7 +4,9 @@ pub trait Mapper {
|
||||||
fn read_rom_u8(&self, address: u16) -> u8;
|
fn read_rom_u8(&self, address: u16) -> u8;
|
||||||
fn write_rom_u8(&mut self, address: u16, value: u8);
|
fn write_rom_u8(&mut self, address: u16, value: u8);
|
||||||
|
|
||||||
|
/// The address passed into this function MUST be zero indexed
|
||||||
fn read_eram_u8(&self, address: u16) -> u8;
|
fn read_eram_u8(&self, address: u16) -> u8;
|
||||||
|
/// The address passed into this function MUST be zero indexed
|
||||||
fn write_eram_u8(&mut self, address: u16, value: u8);
|
fn write_eram_u8(&mut self, address: u16, value: u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,16 +99,23 @@ impl Mapper for MBC1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_eram_u8(&self, _address: u16) -> u8 {
|
fn read_eram_u8(&self, address: u16) -> u8 {
|
||||||
match self.ram.as_ref() {
|
match self.ram.as_ref() {
|
||||||
Some(_ram) => 0,
|
Some(ram) => match self.is_large_rom() {
|
||||||
None => 0,
|
true => ram[address as usize],
|
||||||
|
false => ram[(self.extra_2_bit_reg as usize * 0x2000) + address as usize],
|
||||||
|
},
|
||||||
|
None => 0xFF,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_eram_u8(&mut self, _address: u16, _value: u8) {
|
fn write_eram_u8(&mut self, address: u16, value: u8) {
|
||||||
match self.ram.as_ref() {
|
let is_large_rom = self.is_large_rom();
|
||||||
Some(_ram) => {}
|
match self.ram.as_mut() {
|
||||||
|
Some(ram) => match is_large_rom {
|
||||||
|
true => ram[address as usize] = value,
|
||||||
|
false => ram[(self.extra_2_bit_reg as usize * 0x2000) + address as usize] = value,
|
||||||
|
},
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
use super::interrupts::Interrupts;
|
||||||
|
|
||||||
pub trait SerialWriter {
|
pub trait SerialWriter {
|
||||||
fn write_byte(&mut self, byte: u8);
|
fn write_byte(&mut self, byte: u8);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +55,7 @@ impl<S: SerialWriter> Serial<S> {
|
||||||
self.sc |= conductor as u8;
|
self.sc |= conductor as u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self) -> bool {
|
pub fn tick(&mut self, interrupts: &mut Interrupts) {
|
||||||
if self.get_transfer_in_process() && self.is_conductor() {
|
if self.get_transfer_in_process() && self.is_conductor() {
|
||||||
if self.internal_tick < 128 {
|
if self.internal_tick < 128 {
|
||||||
self.internal_tick += 1;
|
self.internal_tick += 1;
|
||||||
|
@ -62,9 +64,8 @@ impl<S: SerialWriter> Serial<S> {
|
||||||
self.sb = 0;
|
self.sb = 0;
|
||||||
self.set_transfer_in_process(false);
|
self.set_transfer_in_process(false);
|
||||||
self.internal_tick = 0;
|
self.internal_tick = 0;
|
||||||
return true;
|
interrupts.write_if_serial(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl Sound {
|
||||||
nr50: 0b0111_0111,
|
nr50: 0b0111_0111,
|
||||||
nr51: 0b1111_0011,
|
nr51: 0b1111_0011,
|
||||||
nr52: 0b1111_0001,
|
nr52: 0b1111_0001,
|
||||||
wave_pattern_ram: [0u8;16],
|
wave_pattern_ram: [0u8; 16],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
|
use super::interrupts::Interrupts;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Timer {
|
pub struct Timer {
|
||||||
pub enable: bool,
|
enable: bool,
|
||||||
pub clock: TimerClock,
|
clock: TimerClock,
|
||||||
pub div: u8,
|
div: u16,
|
||||||
pub div_counter: u8,
|
tima: u8,
|
||||||
pub tima: u8,
|
tma: u8,
|
||||||
pub tima_counter: u16,
|
overflow_begin_div: u16,
|
||||||
pub tma: u8,
|
overflow: u8,
|
||||||
overflow: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Timer {
|
impl Timer {
|
||||||
|
@ -17,36 +18,83 @@ impl Timer {
|
||||||
clock: TimerClock::C1024,
|
clock: TimerClock::C1024,
|
||||||
tima: 0,
|
tima: 0,
|
||||||
tma: 0,
|
tma: 0,
|
||||||
div: 0xAD,
|
div: 0xAC << 8,
|
||||||
div_counter: 0,
|
overflow_begin_div: 0,
|
||||||
tima_counter: 0,
|
overflow: 0u8,
|
||||||
overflow: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self) -> bool {
|
pub fn tick(&mut self, interrupts: &mut Interrupts) {
|
||||||
self.div_counter = self.div_counter.wrapping_add(1);
|
self.overflow %= 4;
|
||||||
if self.div_counter == 0 {
|
let old_div = self.div;
|
||||||
self.div = self.div.wrapping_add(1);
|
self.div = self.div.wrapping_add(1);
|
||||||
}
|
|
||||||
|
|
||||||
if self.enable {
|
if self.enable {
|
||||||
self.tima_counter = self.tima_counter.wrapping_add(4);
|
if self.div & self.clock.div_falling_edge_bit() == 0
|
||||||
if self.tima_counter >= self.clock.cycles() {
|
&& old_div & self.clock.div_falling_edge_bit() != 0
|
||||||
self.tima_counter = 0;
|
{
|
||||||
self.tima = self.tima.wrapping_add(1);
|
self.increment_tima();
|
||||||
|
return;
|
||||||
self.overflow = self.tima == 0;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.overflow {
|
match self.overflow {
|
||||||
|
0 => {}
|
||||||
|
1..=2 => {
|
||||||
|
if self.overflow_begin_div != old_div {
|
||||||
|
self.overflow += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
self.tima = self.tma;
|
self.tima = self.tma;
|
||||||
self.overflow = false;
|
self.overflow += 1;
|
||||||
return true;
|
interrupts.write_if_timer(true);
|
||||||
}
|
}
|
||||||
false
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_div(&self) -> u8 {
|
||||||
|
(self.div >> 8) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_tima(&self) -> u8 {
|
||||||
|
self.tima
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_tma(&self) -> u8 {
|
||||||
|
self.tma
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_tma(&mut self, value: u8) {
|
||||||
|
self.tma = value;
|
||||||
|
if self.overflow == 4 {
|
||||||
|
self.tima = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_tima(&mut self, value: u8) {
|
||||||
|
if self.overflow < 3 {
|
||||||
|
self.tima = value;
|
||||||
|
self.overflow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn increment_tima(&mut self) {
|
||||||
|
let (new_tima, overflowed) = self.tima.overflowing_add(1);
|
||||||
|
self.tima = new_tima;
|
||||||
|
if overflowed {
|
||||||
|
self.overflow = 1;
|
||||||
|
self.overflow_begin_div = self.div;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_div(&mut self) {
|
||||||
|
if self.div & self.clock.div_falling_edge_bit() != 0 {
|
||||||
|
self.increment_tima();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.div = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_tac(&self) -> u8 {
|
pub fn read_tac(&self) -> u8 {
|
||||||
|
@ -54,28 +102,38 @@ impl Timer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_tac(&mut self, value: u8) {
|
pub fn write_tac(&mut self, value: u8) {
|
||||||
self.enable = (value >> 2) & 0b1 == 1;
|
let new_enable = (value >> 2) & 0b1 == 1;
|
||||||
self.tima_counter = 0;
|
|
||||||
let new_clock = TimerClock::from_tac_clock(value);
|
let new_clock = TimerClock::from_tac_clock(value);
|
||||||
if self.clock == TimerClock::C16 && new_clock == TimerClock::C1024 && self.enable {
|
|
||||||
self.tima = self.tima.wrapping_add(1);
|
|
||||||
|
|
||||||
self.overflow = self.tima == 0;
|
if self.enable {
|
||||||
|
let should_increment = match new_enable {
|
||||||
|
true => {
|
||||||
|
self.div & self.clock.div_falling_edge_bit() != 0
|
||||||
|
&& self.div & new_clock.div_falling_edge_bit() == 0
|
||||||
}
|
}
|
||||||
|
false => self.div & self.clock.div_falling_edge_bit() != 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
if should_increment {
|
||||||
|
self.increment_tima();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.enable = new_enable;
|
||||||
self.clock = new_clock;
|
self.clock = new_clock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum TimerClock {
|
pub enum TimerClock {
|
||||||
C16,
|
C16 = 1,
|
||||||
C64,
|
C64 = 2,
|
||||||
C256,
|
C256 = 3,
|
||||||
C1024,
|
C1024 = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimerClock {
|
impl TimerClock {
|
||||||
pub fn cycles(&self) -> u16 {
|
pub const fn cycles(self) -> u16 {
|
||||||
match self {
|
match self {
|
||||||
Self::C16 => 16,
|
Self::C16 => 16,
|
||||||
Self::C64 => 64,
|
Self::C64 => 64,
|
||||||
|
@ -84,7 +142,7 @@ impl TimerClock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tac_clock(&self) -> u8 {
|
pub const fn tac_clock(self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
Self::C16 => 1,
|
Self::C16 => 1,
|
||||||
Self::C64 => 2,
|
Self::C64 => 2,
|
||||||
|
@ -93,7 +151,7 @@ impl TimerClock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_tac_clock(value: u8) -> Self {
|
pub const fn from_tac_clock(value: u8) -> Self {
|
||||||
match value & 0b11 {
|
match value & 0b11 {
|
||||||
1 => Self::C16,
|
1 => Self::C16,
|
||||||
2 => Self::C64,
|
2 => Self::C64,
|
||||||
|
@ -102,4 +160,8 @@ impl TimerClock {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn div_falling_edge_bit(self) -> u16 {
|
||||||
|
self.cycles() / 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
pub mod gameboy;
|
pub mod gameboy;
|
||||||
|
pub mod ringbuffer;
|
||||||
|
|
||||||
|
/// A helper for writing CPU tests in Rust, the emulator returned by this
|
||||||
|
/// function has already fetched the first instruction. The next tick will be
|
||||||
|
/// the first tick of the instruction
|
||||||
pub fn setup_test_emulator<const ROM_LENGTH: usize>(
|
pub fn setup_test_emulator<const ROM_LENGTH: usize>(
|
||||||
test_opcodes: [u8; ROM_LENGTH],
|
test_opcodes: [u8; ROM_LENGTH],
|
||||||
) -> gameboy::Gameboy<std::io::Stdout> {
|
) -> gameboy::Gameboy<std::io::Stdout> {
|
||||||
|
|
70
meowgb-core/src/ringbuffer.rs
Normal file
70
meowgb-core/src/ringbuffer.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
pub struct RingBuffer<T: std::fmt::Debug + Copy + Default, const SIZE: usize> {
|
||||||
|
buffer: [T; SIZE],
|
||||||
|
size: usize,
|
||||||
|
write_ptr: usize,
|
||||||
|
read_ptr: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: std::fmt::Debug + Copy + Default, const SIZE: usize> RingBuffer<T, SIZE> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
RingBuffer { buffer: [T::default(); SIZE], size: 0, write_ptr: 0, read_ptr: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, value: T) {
|
||||||
|
self.buffer[self.write_ptr] = value;
|
||||||
|
if self.size < SIZE {
|
||||||
|
self.size += 1;
|
||||||
|
} else {
|
||||||
|
self.read_ptr += 1;
|
||||||
|
self.read_ptr %= SIZE;
|
||||||
|
}
|
||||||
|
self.write_ptr += 1;
|
||||||
|
self.write_ptr %= SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_vec(&self) -> Vec<T> {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
let mut offset = self.read_ptr;
|
||||||
|
|
||||||
|
for _ in 0..self.size {
|
||||||
|
out.push(self.buffer[offset]);
|
||||||
|
|
||||||
|
offset += 1;
|
||||||
|
offset %= SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ringbuffer() {
|
||||||
|
let mut ringbuffer: RingBuffer<u8, 16> = RingBuffer::new();
|
||||||
|
|
||||||
|
for x in 0..16 {
|
||||||
|
ringbuffer.push(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
ringbuffer.to_vec().as_slice(),
|
||||||
|
&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
||||||
|
);
|
||||||
|
ringbuffer.push(16);
|
||||||
|
assert_eq!(
|
||||||
|
ringbuffer.to_vec().as_slice(),
|
||||||
|
&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
||||||
|
);
|
||||||
|
ringbuffer.push(17);
|
||||||
|
assert_eq!(
|
||||||
|
ringbuffer.to_vec().as_slice(),
|
||||||
|
&[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
|
||||||
|
);
|
||||||
|
|
||||||
|
for x in 18..32 {
|
||||||
|
ringbuffer.push(x);
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
ringbuffer.to_vec().as_slice(),
|
||||||
|
&[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
|
||||||
|
);
|
||||||
|
}
|
|
@ -67,17 +67,23 @@ pub fn opcode(item: TokenStream) -> TokenStream {
|
||||||
block.push(op_impl.block);
|
block.push(op_impl.block);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if !cycle.is_empty() {
|
// let regs = quote::quote! {
|
||||||
if cycle[0].base10_parse::<u8>().expect("Expected u8") == 0u8 {
|
// log::debug!("\nSTART OF {}\n-- Registers --\nAF: {:04X}\nBC: {:04X}\nDE:
|
||||||
block[0].stmts.insert(0, Stmt::Semi(Expr::Macro(ExprMacro::)))
|
// {:04X}\nHL: {:04X}\nSP: {:04X}\nPC: {:04X}\nZero: {}\nSubtract:
|
||||||
} else {
|
// {}\nHalf-Carry: {}\nCarry: {}\n-- Interrupts --\nIME: {}\nIE VBlank: {}\nIE
|
||||||
|
// LCD Stat: {}\nIE Timer: {}\nIE Serial: {}\nIE Joypad: {}\nIF VBlank: {}\nIF
|
||||||
}
|
// LCD Stat: {}\nIF Timer: {}\nIF Serial: {}\nIF Joypad: {}\nEND OF {}",
|
||||||
}*/
|
// #name_s, state.registers.get_af(), state.registers.get_bc(),
|
||||||
|
// state.registers.get_de(), state.registers.get_hl(), state.registers.get_sp(),
|
||||||
let regs = quote::quote! {
|
// state.registers.pc, state.registers.get_zero(),
|
||||||
log::debug!("\nSTART OF {}\n-- Registers --\nAF: {:04X}\nBC: {:04X}\nDE: {:04X}\nHL: {:04X}\nSP: {:04X}\nPC: {:04X}\nZero: {}\nSubtract: {}\nHalf-Carry: {}\nCarry: {}\n-- Interrupts --\nIME: {}\nIE VBlank: {}\nIE LCD Stat: {}\nIE Timer: {}\nIE Serial: {}\nIE Joypad: {}\nIF VBlank: {}\nIF LCD Stat: {}\nIF Timer: {}\nIF Serial: {}\nIF Joypad: {}\nEND OF {}", #name_s, state.registers.get_af(), state.registers.get_bc(), state.registers.get_de(), state.registers.get_hl(), state.registers.get_sp(), state.registers.pc, state.registers.get_zero(), state.registers.get_subtract(), state.registers.get_half_carry(), state.registers.get_carry(), state.interrupts.ime, state.interrupts.read_ie_vblank(), state.interrupts.read_ie_lcd_stat(), state.interrupts.read_ie_timer(), state.interrupts.read_ie_serial(), state.interrupts.read_ie_joypad(), state.interrupts.read_if_vblank(), state.interrupts.read_if_lcd_stat(), state.interrupts.read_if_timer(), state.interrupts.read_if_serial(), state.interrupts.read_if_joypad(), #name_s);
|
// state.registers.get_subtract(), state.registers.get_half_carry(),
|
||||||
};
|
// state.registers.get_carry(), state.interrupts.ime,
|
||||||
|
// state.interrupts.read_ie_vblank(), state.interrupts.read_ie_lcd_stat(),
|
||||||
|
// state.interrupts.read_ie_timer(), state.interrupts.read_ie_serial(),
|
||||||
|
// state.interrupts.read_ie_joypad(), state.interrupts.read_if_vblank(),
|
||||||
|
// state.interrupts.read_if_lcd_stat(), state.interrupts.read_if_timer(),
|
||||||
|
// state.interrupts.read_if_serial(), state.interrupts.read_if_joypad(),
|
||||||
|
// #name_s); };
|
||||||
|
|
||||||
let match_statement = quote::quote! {
|
let match_statement = quote::quote! {
|
||||||
match state.registers.cycle {
|
match state.registers.cycle {
|
||||||
|
@ -88,26 +94,34 @@ pub fn opcode(item: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let log = if extended.value {
|
// let log = if extended.value {
|
||||||
quote::quote! {
|
// quote::quote! {
|
||||||
if state.registers.cycle == 1 && state.log_instructions {
|
// if state.registers.cycle == 1 && state.log_instructions {
|
||||||
log::debug!("(PC: {:#02X}) Prefixed OP {} ({:#02X})", state.registers.pc, #readable, #opcode);
|
// log::debug!("(PC: {:#02X}) Prefixed OP {} ({:#02X})", state.registers.pc,
|
||||||
#regs
|
// #readable, #opcode); #regs
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
quote::quote! {
|
// quote::quote! {
|
||||||
if state.registers.cycle == 0 && state.log_instructions {
|
// if state.registers.cycle == 0 && state.log_instructions {
|
||||||
log::debug!("(PC: {:#02X}) OP {} ({:#02X})", state.registers.pc, #readable, #opcode);
|
// log::debug!("(PC: {:#02X}) OP {} ({:#02X})", state.registers.pc, #readable,
|
||||||
#regs
|
// #opcode); #regs
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
let check_opcode = match extended.value {
|
||||||
|
true => quote::quote! {
|
||||||
|
assert_eq!(state.registers.current_prefixed_opcode, Some(#opcode), std::concat!("Prefixed instruction ", #name_s, " handler was called with the wrong opcode"));
|
||||||
|
},
|
||||||
|
false => quote::quote! {
|
||||||
|
assert_eq!(state.registers.current_opcode, Some(#opcode), std::concat!("Instruction \"", #name_s, "\" handler was called with the wrong opcode"));
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let out = quote::quote! {
|
let out = quote::quote! {
|
||||||
#fn_sig {
|
#fn_sig {
|
||||||
#log
|
#check_opcode
|
||||||
|
|
||||||
let res: CycleResult = #match_statement;
|
let res: CycleResult = #match_statement;
|
||||||
|
|
||||||
if res != CycleResult::NeedsMore {
|
if res != CycleResult::NeedsMore {
|
||||||
|
|
1
meowgb-tests/expected_output/div_timing.bin
Normal file
1
meowgb-tests/expected_output/div_timing.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/div_write.bin
Normal file
1
meowgb-tests/expected_output/div_write.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/rapid_toggle.bin
Normal file
1
meowgb-tests/expected_output/rapid_toggle.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/tim00.bin
Normal file
1
meowgb-tests/expected_output/tim00.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/tim01_div_trigger.bin
Normal file
1
meowgb-tests/expected_output/tim01_div_trigger.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/tim10.bin
Normal file
1
meowgb-tests/expected_output/tim10.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/tim10_div_trigger.bin
Normal file
1
meowgb-tests/expected_output/tim10_div_trigger.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/tim11.bin
Normal file
1
meowgb-tests/expected_output/tim11.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/tima_reload.bin
Normal file
1
meowgb-tests/expected_output/tima_reload.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/tima_write_reloading.bin
Normal file
1
meowgb-tests/expected_output/tima_write_reloading.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/tma_write_reloading.bin
Normal file
1
meowgb-tests/expected_output/tma_write_reloading.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
|
@ -28,9 +28,6 @@ pub struct CliArgs {
|
||||||
/// game path
|
/// game path
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub rom: Option<PathBuf>,
|
pub rom: Option<PathBuf>,
|
||||||
// enter in debu g mode
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub debug: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
@ -99,11 +96,6 @@ pub fn run_gameboy(
|
||||||
) -> Result<(), MeowGBError> {
|
) -> Result<(), MeowGBError> {
|
||||||
let mut gameboy = gameboy_arc.write().unwrap();
|
let mut gameboy = gameboy_arc.write().unwrap();
|
||||||
|
|
||||||
if args.debug {
|
|
||||||
gameboy.single_step = true;
|
|
||||||
tx.send(GameboyEvent::Framebuffer(gameboy.ppu.write_fb())).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(rom) = args.rom {
|
if let Some(rom) = args.rom {
|
||||||
if !rom.is_file() {
|
if !rom.is_file() {
|
||||||
return Err(MeowGBError::GameNotFound);
|
return Err(MeowGBError::GameNotFound);
|
||||||
|
@ -132,19 +124,15 @@ pub fn run_gameboy(
|
||||||
EmulatorWindowEvent::DownToggle => gameboy.joypad.invert_down(),
|
EmulatorWindowEvent::DownToggle => gameboy.joypad.invert_down(),
|
||||||
EmulatorWindowEvent::LeftToggle => gameboy.joypad.invert_left(),
|
EmulatorWindowEvent::LeftToggle => gameboy.joypad.invert_left(),
|
||||||
EmulatorWindowEvent::RightToggle => gameboy.joypad.invert_right(),
|
EmulatorWindowEvent::RightToggle => gameboy.joypad.invert_right(),
|
||||||
EmulatorWindowEvent::PauseToggle => gameboy.single_step = !gameboy.single_step,
|
EmulatorWindowEvent::PauseToggle => unimplemented!(),
|
||||||
EmulatorWindowEvent::Exit => break 'outer,
|
EmulatorWindowEvent::Exit => break 'outer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (redraw_needed, time_spent_debugging) = gameboy.tick_4();
|
let redraw_needed = gameboy.tick_4();
|
||||||
|
|
||||||
drop(gameboy);
|
drop(gameboy);
|
||||||
|
|
||||||
if let Some(diff) = time_spent_debugging {
|
|
||||||
goal = goal + diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
if redraw_needed {
|
if redraw_needed {
|
||||||
let now = time::OffsetDateTime::now_utc();
|
let now = time::OffsetDateTime::now_utc();
|
||||||
frame_counter += 1;
|
frame_counter += 1;
|
||||||
|
|
370
run-test-roms.sh
Executable file
370
run-test-roms.sh
Executable file
|
@ -0,0 +1,370 @@
|
||||||
|
echo "Running Test Roms..."
|
||||||
|
|
||||||
|
if ! cargo build -p meowgb-tests --release ; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
TEST_TOTAL=0
|
||||||
|
TEST_SUCCESS=0
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/blargg/roms/cpu_instrs.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/blargg/roms/cpu_instrs.gb test -m 100000000 -s meowgb-tests/expected_output/cpu_instrs.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/blargg/roms/instr_timing.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/blargg/roms/instr_timing.gb test -m 100000000 -s meowgb-tests/expected_output/instr_timing.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/blargg/roms/mem_timing.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/blargg/roms/mem_timing.gb test -m 100000000 -s meowgb-tests/expected_output/mem_timing.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/basic.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/basic.gb test -m 100000000 -s meowgb-tests/expected_output/basic.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/boot_hwio-dmgABCmgb.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/boot_hwio-dmgABCmgb.gb test -m 100000000 -s meowgb-tests/expected_output/boot_hwio-dmgABCmgb.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/boot_regs-dmgABC.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/boot_regs-dmgABC.gb test -m 100000000 -s meowgb-tests/expected_output/boot_regs-dmgABC.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/daa.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/daa.gb test -m 100000000 -s meowgb-tests/expected_output/daa.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/div_timing.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/div_timing.gb test -m 100000000 -s meowgb-tests/expected_output/div_timing.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/div_write.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/div_write.gb test -m 100000000 -s meowgb-tests/expected_output/div_write.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/ei_sequence.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/ei_sequence.gb test -m 100000000 -s meowgb-tests/expected_output/ei_sequence.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/ei_timing.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/ei_timing.gb test -m 100000000 -s meowgb-tests/expected_output/ei_timing.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/halt_ime0_ei.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/halt_ime0_ei.gb test -m 100000000 -s meowgb-tests/expected_output/halt_ime0_ei.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/intr_1_2_timing-GS.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/intr_1_2_timing-GS.gb test -m 100000000 -s meowgb-tests/expected_output/intr_1_2_timing-GS.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/intr_2_0_timing.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/intr_2_0_timing.gb test -m 100000000 -s meowgb-tests/expected_output/intr_2_0_timing.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/mem_oam.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/mem_oam.gb test -m 100000000 -s meowgb-tests/expected_output/mem_oam.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/oam_dma_restart.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/oam_dma_restart.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_restart.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/oam_dma_start.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/oam_dma_start.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_start.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/oam_dma_timing.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/oam_dma_timing.gb test -m 100000000 -s meowgb-tests/expected_output/oam_dma_timing.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/rapid_di_ei.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/rapid_di_ei.gb test -m 100000000 -s meowgb-tests/expected_output/rapid_di_ei.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/rapid_toggle.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/rapid_toggle.gb test -m 100000000 -s meowgb-tests/expected_output/rapid_toggle.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/reg_f.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/reg_f.gb test -m 100000000 -s meowgb-tests/expected_output/reg_f.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/reg_read.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/reg_read.gb test -m 100000000 -s meowgb-tests/expected_output/reg_read.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/stat_irq_blocking.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/stat_irq_blocking.gb test -m 100000000 -s meowgb-tests/expected_output/stat_irq_blocking.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/stat_lyc_onoff.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/stat_lyc_onoff.gb test -m 100000000 -s meowgb-tests/expected_output/stat_lyc_onoff.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tim00.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim00.gb test -m 100000000 -s meowgb-tests/expected_output/tim00.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tim00_div_trigger.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim00_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim00_div_trigger.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tim01.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim01.gb test -m 100000000 -s meowgb-tests/expected_output/tim01.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim01_div_trigger.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tim10.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim10.gb test -m 100000000 -s meowgb-tests/expected_output/tim10.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim10_div_trigger.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tim11.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim11.gb test -m 100000000 -s meowgb-tests/expected_output/tim11.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tim11_div_trigger.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tim11_div_trigger.gb test -m 100000000 -s meowgb-tests/expected_output/tim11_div_trigger.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tima_reload.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tima_reload.gb test -m 100000000 -s meowgb-tests/expected_output/tima_reload.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tima_write_reloading.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tima_write_reloading.gb test -m 100000000 -s meowgb-tests/expected_output/tima_write_reloading.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/tma_write_reloading.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/tma_write_reloading.gb test -m 100000000 -s meowgb-tests/expected_output/tma_write_reloading.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/unused_hwio-GS.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/unused_hwio-GS.gb test -m 100000000 -s meowgb-tests/expected_output/unused_hwio-GS.bin 2>&1 > /dev/null) ; then
|
||||||
|
TEST_SUCCESS=$((TEST_SUCCESS + 1))
|
||||||
|
else
|
||||||
|
echo "Failed: $res"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Succeeded in running $TEST_SUCCESS/$TEST_TOTAL"
|
BIN
test-roms/mooneye-test-suite/roms/div_timing.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/div_timing.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/div_write.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/div_write.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/rapid_toggle.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/rapid_toggle.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/tim00.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/tim00.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/tim10.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/tim10.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/tim11.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/tim11.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/tima_reload.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/tima_reload.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/tima_write_reloading.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/tima_write_reloading.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/tma_write_reloading.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/tma_write_reloading.gb
Normal file
Binary file not shown.
48
tests.md
48
tests.md
|
@ -1,9 +1,43 @@
|
||||||
# Passing Tests
|
# Passing Tests
|
||||||
|
|
||||||
* blargg/cpu_instrs.gb
|
## Blargg's Test ROMs
|
||||||
* blargg/instr_timing.gb
|
|
||||||
* blargg/mem_timing.gb
|
* cpu_instrs.gb - [ROM](./test-roms/blargg/roms/cpu_instrs.gb) - [Expected Serial Output](./meowgb-tests/expected_output/cpu_instrs.bin)
|
||||||
* mts/acceptance/ppu/intr_1_2_timing-GS.gb (VBlank intr -> OAM intr timing)
|
* instr_timing.gb - [ROM](./test-roms/blargg/roms/instr_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/instr_timing.bin)
|
||||||
* mts/acceptance/ppu/intr_2_0_timing.gb (VBlank intr -> HBlank intr timing) (I think this shouldn't pass, i believe i'm triggering the HBlank IRQ one CPU cycle late)
|
* mem_timing.gb - [ROM](./test-roms/blargg/roms/mem_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/mem_timing.bin)
|
||||||
* mts/acceptance/ppu/stat_lyc_onoff.gb (LY==LYC handling with PPU being enabled and disabled)
|
|
||||||
* mts/acceptance/ppu/stat_irq_blocking.gb (LCD status IRQ blocking)
|
## Mooneye Test Suite
|
||||||
|
|
||||||
|
* basic.gb - [ROM](./test-roms/mooneye-test-suite/roms/basic.gb) - [Expected Serial Output](./meowgb-tests/expected_output/basic.bin)
|
||||||
|
* boot_hwio-dmgABCmgb.gb - [ROM](./test-roms/mooneye-test-suite/roms/boot_hwio-dmgABCmgb.gb) - [Expected Serial Output](./meowgb-tests/expected_output/boot_hwio-dmgABCmgb.bin)
|
||||||
|
* boot_regs-dmgABC.gb - [ROM](./test-roms/mooneye-test-suite/roms/boot_regs-dmgABC.gb) - [Expected Serial Output](./meowgb-tests/expected_output/boot_regs-dmgABC.bin)
|
||||||
|
* daa.gb - [ROM](./test-roms/mooneye-test-suite/roms/daa.gb) - [Expected Serial Output](./meowgb-tests/expected_output/daa.bin)
|
||||||
|
* div_timing.gb - [ROM](./test-roms/mooneye-test-suite/roms/div_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/div_timing.bin)
|
||||||
|
* div_write.gb - [ROM](./test-roms/mooneye-test-suite/roms/div_write.gb) - [Expected Serial Output](./meowgb-tests/expected_output/div_write.bin)
|
||||||
|
* ei_sequence.gb - [ROM](./test-roms/mooneye-test-suite/roms/ei_sequence.gb) - [Expected Serial Output](./meowgb-tests/expected_output/ei_sequence.bin)
|
||||||
|
* ei_timing.gb - [ROM](./test-roms/mooneye-test-suite/roms/ei_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/ei_timing.bin)
|
||||||
|
* halt_ime0_ei.gb - [ROM](./test-roms/mooneye-test-suite/roms/halt_ime0_ei.gb) - [Expected Serial Output](./meowgb-tests/expected_output/halt_ime0_ei.bin)
|
||||||
|
* intr_1_2_timing-GS.gb - [ROM](./test-roms/mooneye-test-suite/roms/intr_1_2_timing-GS.gb) - [Expected Serial Output](./meowgb-tests/expected_output/intr_1_2_timing-GS.bin)
|
||||||
|
* intr_2_0_timing.gb - [ROM](./test-roms/mooneye-test-suite/roms/intr_2_0_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/intr_2_0_timing.bin)
|
||||||
|
* mem_oam.gb - [ROM](./test-roms/mooneye-test-suite/roms/mem_oam.gb) - [Expected Serial Output](./meowgb-tests/expected_output/mem_oam.bin)
|
||||||
|
* oam_dma_restart.gb - [ROM](./test-roms/mooneye-test-suite/roms/oam_dma_restart.gb) - [Expected Serial Output](./meowgb-tests/expected_output/oam_dma_restart.bin)
|
||||||
|
* oam_dma_start.gb - [ROM](./test-roms/mooneye-test-suite/roms/oam_dma_start.gb) - [Expected Serial Output](./meowgb-tests/expected_output/oam_dma_start.bin)
|
||||||
|
* oam_dma_timing.gb - [ROM](./test-roms/mooneye-test-suite/roms/oam_dma_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/oam_dma_timing.bin)
|
||||||
|
* rapid_di_ei.gb - [ROM](./test-roms/mooneye-test-suite/roms/rapid_di_ei.gb) - [Expected Serial Output](./meowgb-tests/expected_output/rapid_di_ei.bin)
|
||||||
|
* rapid_toggle.gb - [ROM](./test-roms/mooneye-test-suite/roms/rapid_toggle.gb) - [Expected Serial Output](./meowgb-tests/expected_output/rapid_toggle.bin)
|
||||||
|
* reg_f.gb - [ROM](./test-roms/mooneye-test-suite/roms/reg_f.gb) - [Expected Serial Output](./meowgb-tests/expected_output/reg_f.bin)
|
||||||
|
* reg_read.gb - [ROM](./test-roms/mooneye-test-suite/roms/reg_read.gb) - [Expected Serial Output](./meowgb-tests/expected_output/reg_read.bin)
|
||||||
|
* stat_irq_blocking.gb - [ROM](./test-roms/mooneye-test-suite/roms/stat_irq_blocking.gb) - [Expected Serial Output](./meowgb-tests/expected_output/stat_irq_blocking.bin)
|
||||||
|
* stat_lyc_onoff.gb - [ROM](./test-roms/mooneye-test-suite/roms/stat_lyc_onoff.gb) - [Expected Serial Output](./meowgb-tests/expected_output/stat_lyc_onoff.bin)
|
||||||
|
* tim00.gb - [ROM](./test-roms/mooneye-test-suite/roms/tim00.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tim00.bin)
|
||||||
|
* tim00_div_trigger.gb - [ROM](./test-roms/mooneye-test-suite/roms/tim00_div_trigger.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tim00_div_trigger.bin)
|
||||||
|
* tim01.gb - [ROM](./test-roms/mooneye-test-suite/roms/tim01.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tim01.bin)
|
||||||
|
* tim01_div_trigger.gb - [ROM](./test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tim01_div_trigger.bin)
|
||||||
|
* tim10.gb - [ROM](./test-roms/mooneye-test-suite/roms/tim10.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tim10.bin)
|
||||||
|
* tim10_div_trigger.gb - [ROM](./test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tim10_div_trigger.bin)
|
||||||
|
* tim11.gb - [ROM](./test-roms/mooneye-test-suite/roms/tim11.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tim11.bin)
|
||||||
|
* tim11_div_trigger.gb - [ROM](./test-roms/mooneye-test-suite/roms/tim11_div_trigger.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tim11_div_trigger.bin)
|
||||||
|
* tima_reload.gb - [ROM](./test-roms/mooneye-test-suite/roms/tima_reload.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tima_reload.bin)
|
||||||
|
* tima_write_reloading.gb - [ROM](./test-roms/mooneye-test-suite/roms/tima_write_reloading.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tima_write_reloading.bin)
|
||||||
|
* tma_write_reloading.gb - [ROM](./test-roms/mooneye-test-suite/roms/tma_write_reloading.gb) - [Expected Serial Output](./meowgb-tests/expected_output/tma_write_reloading.bin)
|
||||||
|
* unused_hwio-GS.gb - [ROM](./test-roms/mooneye-test-suite/roms/unused_hwio-GS.gb) - [Expected Serial Output](./meowgb-tests/expected_output/unused_hwio-GS.bin)
|
||||||
|
|
Loading…
Reference in a new issue