diff --git a/.forgejo/workflows/action.yml b/.forgejo/workflows/action.yml index 191224b..911fbec 100644 --- a/.forgejo/workflows/action.yml +++ b/.forgejo/workflows/action.yml @@ -14,103 +14,150 @@ jobs: - name: Run cargo tests (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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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 diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 191224b..911fbec 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -14,103 +14,150 @@ jobs: - name: Run cargo tests (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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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 diff --git a/generate-action-and-tests.sh b/generate-action-and-tests.sh new file mode 100755 index 0000000..c2ce06b --- /dev/null +++ b/generate-action-and-tests.sh @@ -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 diff --git a/generate-action.sh b/generate-action.sh deleted file mode 100755 index d8dfbba..0000000 --- a/generate-action.sh +++ /dev/null @@ -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 diff --git a/meowgb-core/src/gameboy.rs b/meowgb-core/src/gameboy.rs index 4177cbe..5fb54a4 100644 --- a/meowgb-core/src/gameboy.rs +++ b/meowgb-core/src/gameboy.rs @@ -10,8 +10,6 @@ pub mod serial; pub mod sound; pub mod timer; -use std::time::{Duration, Instant}; - use interrupts::Interrupts; use joypad::Joypad; use mapper::Mapper; @@ -21,82 +19,12 @@ use timer::Timer; use self::{ cpu::Registers, + dma::DmaState, mapper::{mbc1::MBC1, NoMBC}, serial::{Serial, SerialWriter}, - sound::Sound, dma::DmaState, + sound::Sound, }; -pub struct RingBuffer { - buffer: [T; SIZE], - size: usize, - write_ptr: usize, - read_ptr: usize, -} - -impl RingBuffer { - 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 { - 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 = 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 { pub ppu: Ppu, pub memory: Memory, @@ -109,19 +37,11 @@ pub struct Gameboy { pub dma: DmaState, 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_bug: bool, pub used_halt_bug: bool, pub stop: bool, - pub pc_history: RingBuffer, - pub tick_count: u8, } @@ -141,41 +61,14 @@ impl Gameboy { false => Registers::post_rom(), }, 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_bug: false, used_halt_bug: false, stop: false, - pc_history: RingBuffer::new(), 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) { if bytes.len() < 0x150 { panic!("Bad cartridge (len < 0x150)"); @@ -189,215 +82,31 @@ impl Gameboy { } } - fn log_state(&self) { - 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) { + pub fn tick_4(&mut self) -> bool { let mut request_redraw = false; - let mut debug_time = None; for _ in 0..4 { - let (t_request_redraw, t_debug_time) = self.tick(); + let t_request_redraw = self.tick(); request_redraw |= t_request_redraw; - if t_debug_time.is_some() { - assert!(debug_time.is_none()); - debug_time = t_debug_time; - } } - - (request_redraw, debug_time) + request_redraw } - pub fn tick(&mut self) -> (bool, Option) { + pub fn tick(&mut self) -> bool { 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); let redraw_requested = self.ppu.tick(&mut self.interrupts); self.dma.tick_dma(&mut self.ppu, &self.memory, self.cartridge.as_deref()); - if self.serial.tick() { - self.interrupts.write_if_serial(true); - } + self.serial.tick(&mut self.interrupts); + self.timer.tick(&mut self.interrupts); + self.tick_count += 1; - (redraw_requested, diff) + redraw_requested } else { let redraw_requested = self.ppu.tick(&mut self.interrupts); + self.timer.tick(&mut self.interrupts); self.tick_count += 1; self.tick_count %= 4; - (redraw_requested, None) + redraw_requested } } @@ -407,9 +116,9 @@ impl Gameboy { 0xFF01 => self.serial.sb, 0xFF02 => self.serial.get_sc(), 0xFF03 => 0xFF, // Unused - 0xFF04 => self.timer.div, - 0xFF05 => self.timer.tima, - 0xFF06 => self.timer.tma, + 0xFF04 => self.timer.read_div(), + 0xFF05 => self.timer.read_tima(), + 0xFF06 => self.timer.read_tma(), 0xFF07 => self.timer.read_tac(), 0xFF08..=0xFF0E => 0xFF, // Unused 0xFF0F => self.interrupts.interrupt_flag, @@ -469,9 +178,9 @@ impl Gameboy { 0xFF01 => self.serial.sb = value, 0xFF02 => self.serial.set_sc(value), 0xFF03 => {} // Unused - 0xFF04 => self.timer.div = 0, - 0xFF05 => self.timer.tima = value, - 0xFF06 => self.timer.tma = value, + 0xFF04 => self.timer.write_div(), + 0xFF05 => self.timer.write_tima(value), + 0xFF06 => self.timer.write_tma(value), 0xFF07 => self.timer.write_tac(value), 0xFF08..=0xFF0E => {} // Unused 0xFF0F => self.interrupts.interrupt_flag = value | !0b1_1111, @@ -485,19 +194,19 @@ impl Gameboy { 0xFF17 => self.sound.nr22 = value, 0xFF18 => self.sound.nr23 = 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, - 0xFF1C => {}, //self.sound.nr32 = value, - Unwritable on DMG + 0xFF1C => {} //self.sound.nr32 = value, - Unwritable on DMG 0xFF1D => self.sound.nr33 = value, 0xFF1E => self.sound.nr34 = value, 0xFF1F => {} - 0xFF20 => {}, //self.sound.nr41 = value, - Unwritable on DMG + 0xFF20 => {} //self.sound.nr41 = value, - Unwritable on DMG 0xFF21 => self.sound.nr42 = 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, 0xFF25 => self.sound.nr51 = value, - 0xFF26 => {}, //self.sound.nr52 = value, - Unwritable on DMG + 0xFF26 => {} //self.sound.nr52 = value, - Unwritable on DMG 0xFF27..=0xFF2F => {} 0xFF30..=0xFF3F => self.sound.wave_pattern_ram[address as usize - 0xFF30] = value, 0xFF40 => { @@ -555,12 +264,12 @@ impl Gameboy { 0..=0xFF if !self.memory.bootrom_disabled => self.memory.bootrom[address as usize], 0..=0x7FFF => match self.cartridge.as_ref() { Some(mapper) => mapper.read_rom_u8(address), - None => 0, + None => 0xFF, }, 0x8000..=0x9FFF => self.ppu.cpu_read_vram(address), 0xA000..=0xBFFF => match self.cartridge.as_ref() { - Some(mapper) => mapper.read_eram_u8(address), - None => 0, + Some(mapper) => mapper.read_eram_u8(address - 0xA000), + None => 0xFF, }, 0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000], 0xE000..=0xFDFF => self.memory.wram[address as usize - 0xE000], @@ -586,7 +295,7 @@ impl Gameboy { 0x8000..=0x9FFF => self.ppu.cpu_write_vram(address, value), 0xA000..=0xBFFF => { 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, @@ -599,18 +308,27 @@ impl Gameboy { } } - fn internal_cpu_read_u8(&self, address: u16) -> u8 { - if !self.ppu.dma_occuring { - match address { + 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; + 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..=0x7FFF => match self.cartridge.as_ref() { Some(mapper) => mapper.read_rom_u8(address), - None => 0, + None => 0xFF, }, 0x8000..=0x9FFF => self.ppu.cpu_read_vram(address), 0xA000..=0xBFFF => match self.cartridge.as_ref() { - Some(mapper) => mapper.read_eram_u8(address), - None => 0, + Some(mapper) => mapper.read_eram_u8(address - 0xA000), + None => 0xFF, }, 0xC000..=0xDFFF => self.memory.wram[address as usize - 0xC000], 0xE000..=0xFDFF => self.memory.wram[address as usize - 0xE000], @@ -619,41 +337,23 @@ impl Gameboy { 0xFF00..=0xFF7F => self.cpu_read_io(address), 0xFF80..=0xFFFE => self.memory.hram[address as usize - 0xFF80], 0xFFFF => self.interrupts.interrupt_enable, - } - } else { - 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, - } - } - } - - 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)); + }, + }; + self.registers.mem_read_hold = Some(value); } pub fn cpu_write_u8(&mut self, address: u16, value: u8) { assert!(!self.registers.mem_op_happened); self.registers.mem_op_happened = true; - if self.mem_write_breakpoints[address as usize] { - self.trigger_bp = true; - log::info!("Triggered write bp @ {:#X} (value: {:#02X})", address, value); - } - - if !self.ppu.dma_occuring { - match address { + match self.ppu.dma_occuring { + true => 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), + }, + false => match address { 0..=0xFF if !self.memory.bootrom_disabled => {} 0..=0x7FFF => { if let Some(mapper) = self.cartridge.as_mut() { @@ -663,7 +363,7 @@ impl Gameboy { 0x8000..=0x9FFF => self.ppu.cpu_write_vram(address, value), 0xA000..=0xBFFF => { 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, @@ -673,14 +373,7 @@ impl Gameboy { 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), - } - } 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), - } + }, } } diff --git a/meowgb-core/src/gameboy/cpu.rs b/meowgb-core/src/gameboy/cpu.rs index 5c61372..0ebe4d2 100644 --- a/meowgb-core/src/gameboy/cpu.rs +++ b/meowgb-core/src/gameboy/cpu.rs @@ -238,19 +238,16 @@ pub fn tick_cpu(state: &mut Gameboy) { } else { let opcode = match state.registers.current_opcode { Some(opcode) => opcode, - None => { - state.pc_history.push(state.registers.pc); - match state.registers.mem_read_hold.take() { - Some(opcode) => { - state.registers.current_opcode = Some(opcode); - opcode - } - None => { - state.cpu_read_u8(state.registers.pc); - return; - } + None => match state.registers.mem_read_hold.take() { + Some(opcode) => { + state.registers.current_opcode = Some(opcode); + opcode } - } + None => { + state.cpu_read_u8(state.registers.pc); + return; + } + }, }; let result: CycleResult = match opcode { diff --git a/meowgb-core/src/gameboy/cpu/misc.rs b/meowgb-core/src/gameboy/cpu/misc.rs index 5c33229..550f5c2 100644 --- a/meowgb-core/src/gameboy/cpu/misc.rs +++ b/meowgb-core/src/gameboy/cpu/misc.rs @@ -56,12 +56,12 @@ opcode!(stop, 0x10, "STOP", false, 1, { true => { state.registers.pc = state.registers.pc.wrapping_add(1); state.stop = true; - state.timer.div = 0; + state.timer.write_div(); }, false => { state.registers.pc = state.registers.pc.wrapping_add(2); state.stop = true; - state.timer.div = 0; + state.timer.write_div(); } }, } diff --git a/meowgb-core/src/gameboy/dma.rs b/meowgb-core/src/gameboy/dma.rs index c419e98..b774e35 100644 --- a/meowgb-core/src/gameboy/dma.rs +++ b/meowgb-core/src/gameboy/dma.rs @@ -1,11 +1,11 @@ -use super::{ppu::Ppu, memory::Memory, mapper::Mapper}; +use super::{mapper::Mapper, memory::Memory, ppu::Ppu}; #[derive(Debug)] pub struct DmaState { original_base: u8, pub base: u8, pub remaining_cycles: u8, - restarting: Option<(u8, bool)>, + restarting: Option<(u8, bool)>, } impl DmaState { @@ -14,22 +14,27 @@ impl DmaState { } pub fn init_request(&mut self, base: u8) { - self.base = base; - self.restarting = Some((base, false)); + self.base = base; + self.restarting = Some((base, false)); } - pub fn tick_dma(&mut self, ppu: &mut Ppu, memory: &Memory, cartridge: Option<&(dyn Mapper + Send + Sync)>) { - match self.restarting { - Some((base, false)) => self.restarting = Some((base, true)), - Some((base, true)) => { - self.original_base = base; - self.remaining_cycles = 0xA0; - self.restarting = None; - } - None => {}, - } + pub fn tick_dma( + &mut self, + ppu: &mut Ppu, + memory: &Memory, + cartridge: Option<&(dyn Mapper + Send + Sync)>, + ) { + match self.restarting { + Some((base, false)) => self.restarting = Some((base, true)), + Some((base, true)) => { + self.original_base = base; + self.remaining_cycles = 0xA0; + self.restarting = None; + } + None => {} + } - ppu.dma_occuring = self.remaining_cycles > 0; + ppu.dma_occuring = self.remaining_cycles > 0; if self.remaining_cycles > 0 { let offset = 0xA0 - self.remaining_cycles; @@ -55,7 +60,5 @@ impl DmaState { ppu.dma_write_oam(offset, value); self.remaining_cycles -= 1; } - } - -} \ No newline at end of file +} diff --git a/meowgb-core/src/gameboy/joypad.rs b/meowgb-core/src/gameboy/joypad.rs index 4b5e613..ffc048e 100644 --- a/meowgb-core/src/gameboy/joypad.rs +++ b/meowgb-core/src/gameboy/joypad.rs @@ -57,23 +57,23 @@ impl Joypad { } pub fn cpu_read(&self) -> u8 { - (0b11 << 6) | match self.mode { - JoypadMode::Action => { - (1 << 4) - | ((!self.start as u8) << 3) - | ((!self.select as u8) << 2) - | ((!self.b as u8) << 1) - | (!self.a as u8) + (0b11 << 6) + | match self.mode { + JoypadMode::Action => { + (1 << 4) + | ((!self.start as u8) << 3) + | ((!self.select as u8) << 2) + | ((!self.b as u8) << 1) | (!self.a as u8) + } + JoypadMode::Direction => { + (1 << 5) + | ((!self.down as u8) << 3) + | ((!self.up as u8) << 2) + | ((!self.left as u8) << 1) + | (!self.right as u8) + } + JoypadMode::Both => 0b1111, } - JoypadMode::Direction => { - (1 << 5) - | ((!self.down as u8) << 3) - | ((!self.up as u8) << 2) - | ((!self.left as u8) << 1) - | (!self.right as u8) - } - JoypadMode::Both => 0b1111, - } } joypad_input!(a, Action); diff --git a/meowgb-core/src/gameboy/mapper.rs b/meowgb-core/src/gameboy/mapper.rs index 657b29c..a762fc1 100644 --- a/meowgb-core/src/gameboy/mapper.rs +++ b/meowgb-core/src/gameboy/mapper.rs @@ -4,7 +4,9 @@ pub trait Mapper { fn read_rom_u8(&self, address: u16) -> 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; + /// The address passed into this function MUST be zero indexed fn write_eram_u8(&mut self, address: u16, value: u8); } diff --git a/meowgb-core/src/gameboy/mapper/mbc1.rs b/meowgb-core/src/gameboy/mapper/mbc1.rs index 3bfa739..f257a6d 100644 --- a/meowgb-core/src/gameboy/mapper/mbc1.rs +++ b/meowgb-core/src/gameboy/mapper/mbc1.rs @@ -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() { - Some(_ram) => 0, - None => 0, + Some(ram) => match self.is_large_rom() { + 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) { - match self.ram.as_ref() { - Some(_ram) => {} + fn write_eram_u8(&mut self, address: u16, value: u8) { + let is_large_rom = self.is_large_rom(); + 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 => {} } } diff --git a/meowgb-core/src/gameboy/serial.rs b/meowgb-core/src/gameboy/serial.rs index a4eca9e..bbee6a3 100644 --- a/meowgb-core/src/gameboy/serial.rs +++ b/meowgb-core/src/gameboy/serial.rs @@ -1,5 +1,7 @@ use std::io::Write; +use super::interrupts::Interrupts; + pub trait SerialWriter { fn write_byte(&mut self, byte: u8); } @@ -53,7 +55,7 @@ impl Serial { 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.internal_tick < 128 { self.internal_tick += 1; @@ -62,9 +64,8 @@ impl Serial { self.sb = 0; self.set_transfer_in_process(false); self.internal_tick = 0; - return true; + interrupts.write_if_serial(true); } } - false } } diff --git a/meowgb-core/src/gameboy/sound.rs b/meowgb-core/src/gameboy/sound.rs index 191b71d..714a31d 100644 --- a/meowgb-core/src/gameboy/sound.rs +++ b/meowgb-core/src/gameboy/sound.rs @@ -53,7 +53,7 @@ impl Sound { nr50: 0b0111_0111, nr51: 0b1111_0011, nr52: 0b1111_0001, - wave_pattern_ram: [0u8;16], + wave_pattern_ram: [0u8; 16], } } } diff --git a/meowgb-core/src/gameboy/timer.rs b/meowgb-core/src/gameboy/timer.rs index 00d19bf..4d62165 100644 --- a/meowgb-core/src/gameboy/timer.rs +++ b/meowgb-core/src/gameboy/timer.rs @@ -1,13 +1,14 @@ +use super::interrupts::Interrupts; + #[derive(Debug)] pub struct Timer { - pub enable: bool, - pub clock: TimerClock, - pub div: u8, - pub div_counter: u8, - pub tima: u8, - pub tima_counter: u16, - pub tma: u8, - overflow: bool, + enable: bool, + clock: TimerClock, + div: u16, + tima: u8, + tma: u8, + overflow_begin_div: u16, + overflow: u8, } impl Timer { @@ -17,36 +18,83 @@ impl Timer { clock: TimerClock::C1024, tima: 0, tma: 0, - div: 0xAD, - div_counter: 0, - tima_counter: 0, - overflow: false, + div: 0xAC << 8, + overflow_begin_div: 0, + overflow: 0u8, } } - pub fn tick(&mut self) -> bool { - self.div_counter = self.div_counter.wrapping_add(1); - if self.div_counter == 0 { - self.div = self.div.wrapping_add(1); - } + pub fn tick(&mut self, interrupts: &mut Interrupts) { + self.overflow %= 4; + let old_div = self.div; + self.div = self.div.wrapping_add(1); if self.enable { - self.tima_counter = self.tima_counter.wrapping_add(4); - if self.tima_counter >= self.clock.cycles() { - self.tima_counter = 0; - self.tima = self.tima.wrapping_add(1); - - self.overflow = self.tima == 0; - return false; + if self.div & self.clock.div_falling_edge_bit() == 0 + && old_div & self.clock.div_falling_edge_bit() != 0 + { + self.increment_tima(); + return; } } - if self.overflow { - self.tima = self.tma; - self.overflow = false; - return true; + match self.overflow { + 0 => {} + 1..=2 => { + if self.overflow_begin_div != old_div { + self.overflow += 1; + } + } + 3 => { + self.tima = self.tma; + self.overflow += 1; + interrupts.write_if_timer(true); + } + _ => unreachable!(), } - false + } + + 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 { @@ -54,28 +102,38 @@ impl Timer { } pub fn write_tac(&mut self, value: u8) { - self.enable = (value >> 2) & 0b1 == 1; - self.tima_counter = 0; + let new_enable = (value >> 2) & 0b1 == 1; 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; } } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TimerClock { - C16, - C64, - C256, - C1024, + C16 = 1, + C64 = 2, + C256 = 3, + C1024 = 0, } impl TimerClock { - pub fn cycles(&self) -> u16 { + pub const fn cycles(self) -> u16 { match self { Self::C16 => 16, Self::C64 => 64, @@ -84,7 +142,7 @@ impl TimerClock { } } - pub fn tac_clock(&self) -> u8 { + pub const fn tac_clock(self) -> u8 { match self { Self::C16 => 1, 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 { 1 => Self::C16, 2 => Self::C64, @@ -102,4 +160,8 @@ impl TimerClock { _ => unreachable!(), } } + + pub const fn div_falling_edge_bit(self) -> u16 { + self.cycles() / 2 + } } diff --git a/meowgb-core/src/lib.rs b/meowgb-core/src/lib.rs index 9e0a2bb..06dd4a4 100644 --- a/meowgb-core/src/lib.rs +++ b/meowgb-core/src/lib.rs @@ -1,5 +1,9 @@ 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( test_opcodes: [u8; ROM_LENGTH], ) -> gameboy::Gameboy { diff --git a/meowgb-core/src/ringbuffer.rs b/meowgb-core/src/ringbuffer.rs new file mode 100644 index 0000000..8442ce3 --- /dev/null +++ b/meowgb-core/src/ringbuffer.rs @@ -0,0 +1,70 @@ +pub struct RingBuffer { + buffer: [T; SIZE], + size: usize, + write_ptr: usize, + read_ptr: usize, +} + +impl RingBuffer { + 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 { + 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 = 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] + ); +} diff --git a/meowgb-opcode/src/lib.rs b/meowgb-opcode/src/lib.rs index ffc8653..bdaa390 100644 --- a/meowgb-opcode/src/lib.rs +++ b/meowgb-opcode/src/lib.rs @@ -67,17 +67,23 @@ pub fn opcode(item: TokenStream) -> TokenStream { block.push(op_impl.block); } - /*if !cycle.is_empty() { - if cycle[0].base10_parse::().expect("Expected u8") == 0u8 { - block[0].stmts.insert(0, Stmt::Semi(Expr::Macro(ExprMacro::))) - } else { - - } - }*/ - - let regs = quote::quote! { - 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); - }; + // let regs = quote::quote! { + // 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); }; let match_statement = quote::quote! { match state.registers.cycle { @@ -88,26 +94,34 @@ pub fn opcode(item: TokenStream) -> TokenStream { } }; - let log = if extended.value { - quote::quote! { - if state.registers.cycle == 1 && state.log_instructions { - log::debug!("(PC: {:#02X}) Prefixed OP {} ({:#02X})", state.registers.pc, #readable, #opcode); - #regs - } - } - } else { - quote::quote! { - if state.registers.cycle == 0 && state.log_instructions { - log::debug!("(PC: {:#02X}) OP {} ({:#02X})", state.registers.pc, #readable, #opcode); - #regs - } - } + // let log = if extended.value { + // quote::quote! { + // if state.registers.cycle == 1 && state.log_instructions { + // log::debug!("(PC: {:#02X}) Prefixed OP {} ({:#02X})", state.registers.pc, + // #readable, #opcode); #regs + // } + // } + // } else { + // quote::quote! { + // if state.registers.cycle == 0 && state.log_instructions { + // log::debug!("(PC: {:#02X}) OP {} ({:#02X})", state.registers.pc, #readable, + // #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! { #fn_sig { - #log - + #check_opcode let res: CycleResult = #match_statement; if res != CycleResult::NeedsMore { diff --git a/meowgb-tests/expected_output/div_timing.bin b/meowgb-tests/expected_output/div_timing.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/div_timing.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/div_write.bin b/meowgb-tests/expected_output/div_write.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/div_write.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/rapid_toggle.bin b/meowgb-tests/expected_output/rapid_toggle.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/rapid_toggle.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/tim00.bin b/meowgb-tests/expected_output/tim00.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/tim00.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/tim01_div_trigger.bin b/meowgb-tests/expected_output/tim01_div_trigger.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/tim01_div_trigger.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/tim10.bin b/meowgb-tests/expected_output/tim10.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/tim10.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/tim10_div_trigger.bin b/meowgb-tests/expected_output/tim10_div_trigger.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/tim10_div_trigger.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/tim11.bin b/meowgb-tests/expected_output/tim11.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/tim11.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/tima_reload.bin b/meowgb-tests/expected_output/tima_reload.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/tima_reload.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/tima_write_reloading.bin b/meowgb-tests/expected_output/tima_write_reloading.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/tima_write_reloading.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb-tests/expected_output/tma_write_reloading.bin b/meowgb-tests/expected_output/tma_write_reloading.bin new file mode 100644 index 0000000..2a02163 --- /dev/null +++ b/meowgb-tests/expected_output/tma_write_reloading.bin @@ -0,0 +1 @@ + " \ No newline at end of file diff --git a/meowgb/src/main.rs b/meowgb/src/main.rs index 9287a2f..e6a2f29 100644 --- a/meowgb/src/main.rs +++ b/meowgb/src/main.rs @@ -28,9 +28,6 @@ pub struct CliArgs { /// game path #[clap(long)] pub rom: Option, - // enter in debu g mode - #[clap(short, long)] - pub debug: bool, } #[derive(Debug, thiserror::Error)] @@ -99,11 +96,6 @@ pub fn run_gameboy( ) -> Result<(), MeowGBError> { 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 !rom.is_file() { return Err(MeowGBError::GameNotFound); @@ -132,19 +124,15 @@ pub fn run_gameboy( EmulatorWindowEvent::DownToggle => gameboy.joypad.invert_down(), EmulatorWindowEvent::LeftToggle => gameboy.joypad.invert_left(), EmulatorWindowEvent::RightToggle => gameboy.joypad.invert_right(), - EmulatorWindowEvent::PauseToggle => gameboy.single_step = !gameboy.single_step, + EmulatorWindowEvent::PauseToggle => unimplemented!(), EmulatorWindowEvent::Exit => break 'outer, } } - let (redraw_needed, time_spent_debugging) = gameboy.tick_4(); + let redraw_needed = gameboy.tick_4(); drop(gameboy); - if let Some(diff) = time_spent_debugging { - goal = goal + diff; - } - if redraw_needed { let now = time::OffsetDateTime::now_utc(); frame_counter += 1; diff --git a/run-test-roms.sh b/run-test-roms.sh new file mode 100755 index 0000000..f949bb6 --- /dev/null +++ b/run-test-roms.sh @@ -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" diff --git a/test-roms/mooneye-test-suite/roms/div_timing.gb b/test-roms/mooneye-test-suite/roms/div_timing.gb new file mode 100644 index 0000000..f72f194 Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/div_timing.gb differ diff --git a/test-roms/mooneye-test-suite/roms/div_write.gb b/test-roms/mooneye-test-suite/roms/div_write.gb new file mode 100644 index 0000000..c39366b Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/div_write.gb differ diff --git a/test-roms/mooneye-test-suite/roms/rapid_toggle.gb b/test-roms/mooneye-test-suite/roms/rapid_toggle.gb new file mode 100644 index 0000000..387bf0b Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/rapid_toggle.gb differ diff --git a/test-roms/mooneye-test-suite/roms/tim00.gb b/test-roms/mooneye-test-suite/roms/tim00.gb new file mode 100644 index 0000000..4e56d07 Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/tim00.gb differ diff --git a/test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb b/test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb new file mode 100644 index 0000000..53092c9 Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/tim01_div_trigger.gb differ diff --git a/test-roms/mooneye-test-suite/roms/tim10.gb b/test-roms/mooneye-test-suite/roms/tim10.gb new file mode 100644 index 0000000..fcd5d98 Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/tim10.gb differ diff --git a/test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb b/test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb new file mode 100644 index 0000000..1148f6f Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/tim10_div_trigger.gb differ diff --git a/test-roms/mooneye-test-suite/roms/tim11.gb b/test-roms/mooneye-test-suite/roms/tim11.gb new file mode 100644 index 0000000..2d0396e Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/tim11.gb differ diff --git a/test-roms/mooneye-test-suite/roms/tima_reload.gb b/test-roms/mooneye-test-suite/roms/tima_reload.gb new file mode 100644 index 0000000..c6e0aee Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/tima_reload.gb differ diff --git a/test-roms/mooneye-test-suite/roms/tima_write_reloading.gb b/test-roms/mooneye-test-suite/roms/tima_write_reloading.gb new file mode 100644 index 0000000..d8a3bbf Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/tima_write_reloading.gb differ diff --git a/test-roms/mooneye-test-suite/roms/tma_write_reloading.gb b/test-roms/mooneye-test-suite/roms/tma_write_reloading.gb new file mode 100644 index 0000000..1a39d78 Binary files /dev/null and b/test-roms/mooneye-test-suite/roms/tma_write_reloading.gb differ diff --git a/tests.md b/tests.md index c756af7..f05fe0c 100644 --- a/tests.md +++ b/tests.md @@ -1,9 +1,43 @@ # Passing Tests -* blargg/cpu_instrs.gb -* blargg/instr_timing.gb -* blargg/mem_timing.gb -* mts/acceptance/ppu/intr_1_2_timing-GS.gb (VBlank intr -> OAM intr timing) -* 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) -* 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) \ No newline at end of file +## Blargg's Test ROMs + +* cpu_instrs.gb - [ROM](./test-roms/blargg/roms/cpu_instrs.gb) - [Expected Serial Output](./meowgb-tests/expected_output/cpu_instrs.bin) +* instr_timing.gb - [ROM](./test-roms/blargg/roms/instr_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/instr_timing.bin) +* mem_timing.gb - [ROM](./test-roms/blargg/roms/mem_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/mem_timing.bin) + +## 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)