feat: implement more accurate memory bus conflicts with DMA
This commit is contained in:
parent
a2156ec7f4
commit
9ecfdc9db3
19 changed files with 189 additions and 22 deletions
|
@ -30,6 +30,10 @@ jobs:
|
||||||
if: always()
|
if: always()
|
||||||
run: ./target/release/meowgb-tests 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 add_sp_e_timing)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/add_sp_e_timing.gb test -m 100000000 -s meowgb-tests/expected_output/add_sp_e_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite basic)
|
- name: Run test ROM (mooneye-test-suite basic)
|
||||||
if: always()
|
if: always()
|
||||||
run: ./target/release/meowgb-tests 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
|
||||||
|
@ -42,6 +46,22 @@ jobs:
|
||||||
if: always()
|
if: always()
|
||||||
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
|
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 call_cc_timing)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_cc_timing.gb test -m 100000000 -s meowgb-tests/expected_output/call_cc_timing.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite call_cc_timing2)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_cc_timing2.gb test -m 100000000 -s meowgb-tests/expected_output/call_cc_timing2.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite call_timing)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_timing.gb test -m 100000000 -s meowgb-tests/expected_output/call_timing.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite call_timing2)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_timing2.gb test -m 100000000 -s meowgb-tests/expected_output/call_timing2.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite daa)
|
- name: Run test ROM (mooneye-test-suite daa)
|
||||||
if: always()
|
if: always()
|
||||||
run: ./target/release/meowgb-tests 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
|
||||||
|
|
20
.github/workflows/action.yml
vendored
20
.github/workflows/action.yml
vendored
|
@ -30,6 +30,10 @@ jobs:
|
||||||
if: always()
|
if: always()
|
||||||
run: ./target/release/meowgb-tests 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 add_sp_e_timing)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/add_sp_e_timing.gb test -m 100000000 -s meowgb-tests/expected_output/add_sp_e_timing.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite basic)
|
- name: Run test ROM (mooneye-test-suite basic)
|
||||||
if: always()
|
if: always()
|
||||||
run: ./target/release/meowgb-tests 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
|
||||||
|
@ -42,6 +46,22 @@ jobs:
|
||||||
if: always()
|
if: always()
|
||||||
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
|
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 call_cc_timing)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_cc_timing.gb test -m 100000000 -s meowgb-tests/expected_output/call_cc_timing.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite call_cc_timing2)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_cc_timing2.gb test -m 100000000 -s meowgb-tests/expected_output/call_cc_timing2.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite call_timing)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_timing.gb test -m 100000000 -s meowgb-tests/expected_output/call_timing.bin
|
||||||
|
|
||||||
|
- name: Run test ROM (mooneye-test-suite call_timing2)
|
||||||
|
if: always()
|
||||||
|
run: ./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_timing2.gb test -m 100000000 -s meowgb-tests/expected_output/call_timing2.bin
|
||||||
|
|
||||||
- name: Run test ROM (mooneye-test-suite daa)
|
- name: Run test ROM (mooneye-test-suite daa)
|
||||||
if: always()
|
if: always()
|
||||||
run: ./target/release/meowgb-tests 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
|
||||||
|
|
|
@ -106,7 +106,7 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
pub fn tick(&mut self) -> bool {
|
pub fn tick(&mut self) -> bool {
|
||||||
if self.tick_count == 0 {
|
if self.tick_count == 0 {
|
||||||
cpu::tick_cpu(self);
|
cpu::tick_cpu(self);
|
||||||
let redraw_requested = self.ppu.tick(&mut self.interrupts);
|
let redraw_requested = self.ppu.tick(&self.dma, &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());
|
||||||
self.serial.tick(&mut self.interrupts);
|
self.serial.tick(&mut self.interrupts);
|
||||||
self.timer.tick(&mut self.interrupts);
|
self.timer.tick(&mut self.interrupts);
|
||||||
|
@ -114,7 +114,7 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
self.tick_count += 1;
|
self.tick_count += 1;
|
||||||
redraw_requested
|
redraw_requested
|
||||||
} else {
|
} else {
|
||||||
let redraw_requested = self.ppu.tick(&mut self.interrupts);
|
let redraw_requested = self.ppu.tick(&self.dma, &mut self.interrupts);
|
||||||
self.timer.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;
|
||||||
|
@ -328,7 +328,7 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
assert!(!self.registers.mem_op_happened);
|
assert!(!self.registers.mem_op_happened);
|
||||||
assert!(self.registers.mem_read_hold.is_none());
|
assert!(self.registers.mem_read_hold.is_none());
|
||||||
self.registers.mem_op_happened = true;
|
self.registers.mem_op_happened = true;
|
||||||
let value = match self.ppu.dma_occuring {
|
let value = match self.dma.is_conflict(address) {
|
||||||
true => match address {
|
true => match address {
|
||||||
0..=0xFEFF => 0xFF,
|
0..=0xFEFF => 0xFF,
|
||||||
0xFF00..=0xFF7F => self.cpu_read_io(address),
|
0xFF00..=0xFF7F => self.cpu_read_io(address),
|
||||||
|
@ -366,7 +366,7 @@ impl<S: SerialWriter> Gameboy<S> {
|
||||||
self.registers.mem_op_happened = true;
|
self.registers.mem_op_happened = true;
|
||||||
self.last_write = Some((address, value));
|
self.last_write = Some((address, value));
|
||||||
|
|
||||||
match self.ppu.dma_occuring {
|
match self.dma.is_conflict(address) {
|
||||||
true => match address {
|
true => match address {
|
||||||
0..=0xFEFF => {}
|
0..=0xFEFF => {}
|
||||||
0xFF00..=0xFF7F => self.cpu_write_io(address, value),
|
0xFF00..=0xFF7F => self.cpu_write_io(address, value),
|
||||||
|
|
|
@ -1,16 +1,64 @@
|
||||||
use super::{mapper::Mapper, memory::Memory, ppu::Ppu};
|
use super::{mapper::Mapper, memory::Memory, ppu::Ppu};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum DmaMemoryBus {
|
||||||
|
External,
|
||||||
|
Video,
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DmaMemoryBus {
|
||||||
|
pub fn from_base(base: u8) -> Self {
|
||||||
|
match base {
|
||||||
|
0..=0x7F
|
||||||
|
| 0xA0..=0xFD => Self::External,
|
||||||
|
0x80..=0x9F => Self::Video,
|
||||||
|
_ => Self::Other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn conflict_in_range(self, address: u16) -> bool {
|
||||||
|
let base = (address >> 8) as u8;
|
||||||
|
|
||||||
|
if base == 0xFE {
|
||||||
|
true
|
||||||
|
} else if base == 0xFF {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
match self {
|
||||||
|
DmaMemoryBus::External => base < 0x7F || (base >= 0xA0 && base <= 0xFD),
|
||||||
|
DmaMemoryBus::Video => base >= 0x80 && base <= 0x9F,
|
||||||
|
DmaMemoryBus::Other => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct DmaState {
|
pub struct DmaState {
|
||||||
original_base: u8,
|
original_base: u8,
|
||||||
|
pub dma_in_progress: bool,
|
||||||
pub base: u8,
|
pub base: u8,
|
||||||
pub remaining_cycles: u8,
|
pub remaining_cycles: u8,
|
||||||
restarting: Option<(u8, bool)>,
|
restarting: Option<(u8, bool)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DmaState {
|
impl DmaState {
|
||||||
|
pub fn is_conflict(&self, address: u16) -> bool {
|
||||||
|
self.in_progress().map(|bus| {
|
||||||
|
bus.conflict_in_range(address)
|
||||||
|
}).unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn in_progress(&self) -> Option<DmaMemoryBus> {
|
||||||
|
match self.dma_in_progress {
|
||||||
|
true => Some(DmaMemoryBus::from_base(self.original_base)),
|
||||||
|
false => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { original_base: 0, base: 0, remaining_cycles: 0, restarting: None }
|
Self { dma_in_progress: false, original_base: 0, base: 0, remaining_cycles: 0, restarting: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_request(&mut self, base: u8) {
|
pub fn init_request(&mut self, base: u8) {
|
||||||
|
@ -34,7 +82,7 @@ impl DmaState {
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu.dma_occuring = self.remaining_cycles > 0;
|
self.dma_in_progress = self.remaining_cycles > 0;
|
||||||
|
|
||||||
if self.remaining_cycles > 0 {
|
if self.remaining_cycles > 0 {
|
||||||
let offset = 0xA0 - self.remaining_cycles;
|
let offset = 0xA0 - self.remaining_cycles;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::interrupts::Interrupts;
|
use super::{interrupts::Interrupts, dma::DmaState};
|
||||||
|
|
||||||
pub const FB_HEIGHT: u32 = 144;
|
pub const FB_HEIGHT: u32 = 144;
|
||||||
pub const FB_WIDTH: u32 = 160;
|
pub const FB_WIDTH: u32 = 160;
|
||||||
|
@ -298,8 +298,6 @@ pub struct Ppu {
|
||||||
sprite_buffer: [Option<OAMEntry>; 10],
|
sprite_buffer: [Option<OAMEntry>; 10],
|
||||||
sprite_count: usize,
|
sprite_count: usize,
|
||||||
|
|
||||||
pub dma_occuring: bool,
|
|
||||||
|
|
||||||
current_draw_state: Option<LineDrawingState>,
|
current_draw_state: Option<LineDrawingState>,
|
||||||
wy_match: bool,
|
wy_match: bool,
|
||||||
|
|
||||||
|
@ -355,7 +353,6 @@ impl Ppu {
|
||||||
dot_target: 0,
|
dot_target: 0,
|
||||||
sprite_buffer: [None; 10],
|
sprite_buffer: [None; 10],
|
||||||
sprite_count: 0,
|
sprite_count: 0,
|
||||||
dma_occuring: false,
|
|
||||||
current_draw_state: None,
|
current_draw_state: None,
|
||||||
wy_match: false,
|
wy_match: false,
|
||||||
first_frame: true,
|
first_frame: true,
|
||||||
|
@ -452,15 +449,14 @@ impl Ppu {
|
||||||
((high & 0b1) << 1) | low & 0b1
|
((high & 0b1) << 1) | low & 0b1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn internal_read_oam(&mut self, offset: usize) -> u8 {
|
fn internal_read_oam(&mut self, dma_state: &DmaState, offset: usize) -> u8 {
|
||||||
match self.dma_occuring && !OVERRIDE_PPU_MEMORY_ACCESS {
|
match dma_state.in_progress().is_some() && !OVERRIDE_PPU_MEMORY_ACCESS {
|
||||||
true => 0xFF,
|
true => 0xFF,
|
||||||
false => self.oam[offset as usize],
|
false => self.oam[offset as usize],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dma_write_oam(&mut self, offset: u8, value: u8) {
|
pub fn dma_write_oam(&mut self, offset: u8, value: u8) {
|
||||||
assert!(self.dma_occuring);
|
|
||||||
self.oam[offset as usize] = value;
|
self.oam[offset as usize] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,7 +565,7 @@ impl Ppu {
|
||||||
self.registers.ly_lyc = self.registers.ly == self.registers.lyc;
|
self.registers.ly_lyc = self.registers.ly == self.registers.lyc;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self, interrupts: &mut Interrupts) -> bool {
|
pub fn tick(&mut self, dma_state: &DmaState, interrupts: &mut Interrupts) -> bool {
|
||||||
if self.enabled() {
|
if self.enabled() {
|
||||||
self.registers.cycles_since_last_ly_increment += 1;
|
self.registers.cycles_since_last_ly_increment += 1;
|
||||||
match self.mode() {
|
match self.mode() {
|
||||||
|
@ -587,10 +583,10 @@ impl Ppu {
|
||||||
let oam_item_idx: usize = (self.current_dot as usize / 2) * 4;
|
let oam_item_idx: usize = (self.current_dot as usize / 2) * 4;
|
||||||
|
|
||||||
let oam_entry = OAMEntry::parse([
|
let oam_entry = OAMEntry::parse([
|
||||||
self.internal_read_oam(oam_item_idx),
|
self.internal_read_oam(dma_state, oam_item_idx),
|
||||||
self.internal_read_oam(oam_item_idx + 1),
|
self.internal_read_oam(dma_state, oam_item_idx + 1),
|
||||||
self.internal_read_oam(oam_item_idx + 2),
|
self.internal_read_oam(dma_state, oam_item_idx + 2),
|
||||||
self.internal_read_oam(oam_item_idx + 3),
|
self.internal_read_oam(dma_state, oam_item_idx + 3),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let sprite_height = self.sprite_height();
|
let sprite_height = self.sprite_height();
|
||||||
|
|
1
meowgb-tests/expected_output/add_sp_e_timing.bin
Normal file
1
meowgb-tests/expected_output/add_sp_e_timing.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/call_cc_timing.bin
Normal file
1
meowgb-tests/expected_output/call_cc_timing.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/call_cc_timing2.bin
Normal file
1
meowgb-tests/expected_output/call_cc_timing2.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/call_timing.bin
Normal file
1
meowgb-tests/expected_output/call_timing.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
1
meowgb-tests/expected_output/call_timing2.bin
Normal file
1
meowgb-tests/expected_output/call_timing2.bin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"
|
|
@ -193,8 +193,6 @@ pub fn run_gameboy(
|
||||||
gameboy.debugging |= bp_triggered;
|
gameboy.debugging |= bp_triggered;
|
||||||
|
|
||||||
if bp_triggered || step {
|
if bp_triggered || step {
|
||||||
gameboy.debugging = bp_triggered;
|
|
||||||
|
|
||||||
let now = time::OffsetDateTime::now_utc();
|
let now = time::OffsetDateTime::now_utc();
|
||||||
|
|
||||||
if let Some(debugging_tbf) = debugging_tbf {
|
if let Some(debugging_tbf) = debugging_tbf {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/// Provides an [egui] based overlay for debugigng the emulator whilst it is
|
/// Provides an [egui] based overlay for debugigng the emulator whilst it is
|
||||||
/// running
|
/// running
|
||||||
use egui::{ClippedPrimitive, Context, Grid, TexturesDelta};
|
use egui::{ClippedPrimitive, Context, Grid, TexturesDelta, RichText, Color32};
|
||||||
use egui_wgpu::renderer::{Renderer, ScreenDescriptor};
|
use egui_wgpu::renderer::{Renderer, ScreenDescriptor};
|
||||||
use meowgb_core::gameboy::serial::SerialWriter;
|
use meowgb_core::gameboy::serial::SerialWriter;
|
||||||
use pixels::{wgpu, PixelsContext};
|
use pixels::{wgpu, PixelsContext};
|
||||||
|
@ -28,6 +28,7 @@ pub struct GuiWindowState {
|
||||||
pub wram_window_open: bool,
|
pub wram_window_open: bool,
|
||||||
pub oam_window_open: bool,
|
pub oam_window_open: bool,
|
||||||
pub hram_window_open: bool,
|
pub hram_window_open: bool,
|
||||||
|
pub dma_window_open: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuiWindowState {
|
impl GuiWindowState {
|
||||||
|
@ -39,6 +40,7 @@ impl GuiWindowState {
|
||||||
self.wram_window_open = false;
|
self.wram_window_open = false;
|
||||||
self.oam_window_open = false;
|
self.oam_window_open = false;
|
||||||
self.hram_window_open = false;
|
self.hram_window_open = false;
|
||||||
|
self.dma_window_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn any_open(&self) -> bool {
|
pub fn any_open(&self) -> bool {
|
||||||
|
@ -49,6 +51,7 @@ impl GuiWindowState {
|
||||||
|| self.wram_window_open
|
|| self.wram_window_open
|
||||||
|| self.oam_window_open
|
|| self.oam_window_open
|
||||||
|| self.hram_window_open
|
|| self.hram_window_open
|
||||||
|
|| self.dma_window_open
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +71,7 @@ pub struct Gui {
|
||||||
pub is_debugging: bool,
|
pub is_debugging: bool,
|
||||||
pub breakpoints: [[bool; 3]; 0x10000],
|
pub breakpoints: [[bool; 3]; 0x10000],
|
||||||
pub sender: std::sync::mpsc::Sender<EmulatorWindowEvent>,
|
pub sender: std::sync::mpsc::Sender<EmulatorWindowEvent>,
|
||||||
|
pub dma: meowgb_core::gameboy::dma::DmaState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Framework {
|
impl Framework {
|
||||||
|
@ -124,6 +128,7 @@ impl Framework {
|
||||||
self.gui.oam = gameboy.gameboy.ppu.oam;
|
self.gui.oam = gameboy.gameboy.ppu.oam;
|
||||||
self.gui.hram = gameboy.gameboy.memory.hram;
|
self.gui.hram = gameboy.gameboy.memory.hram;
|
||||||
self.gui.wram = gameboy.gameboy.memory.wram;
|
self.gui.wram = gameboy.gameboy.memory.wram;
|
||||||
|
self.gui.dma = gameboy.gameboy.dma;
|
||||||
|
|
||||||
// Run the egui frame and create all paint jobs to prepare for rendering.
|
// Run the egui frame and create all paint jobs to prepare for rendering.
|
||||||
let raw_input = self.egui_state.take_egui_input(window);
|
let raw_input = self.egui_state.take_egui_input(window);
|
||||||
|
@ -189,6 +194,7 @@ impl Gui {
|
||||||
wram_window_open: false,
|
wram_window_open: false,
|
||||||
oam_window_open: false,
|
oam_window_open: false,
|
||||||
hram_window_open: false,
|
hram_window_open: false,
|
||||||
|
dma_window_open: false,
|
||||||
},
|
},
|
||||||
state_restore: None,
|
state_restore: None,
|
||||||
registers: gameboy.gameboy.registers,
|
registers: gameboy.gameboy.registers,
|
||||||
|
@ -203,6 +209,7 @@ impl Gui {
|
||||||
wram: gameboy.gameboy.memory.wram,
|
wram: gameboy.gameboy.memory.wram,
|
||||||
hram: gameboy.gameboy.memory.hram,
|
hram: gameboy.gameboy.memory.hram,
|
||||||
oam: gameboy.gameboy.ppu.oam,
|
oam: gameboy.gameboy.ppu.oam,
|
||||||
|
dma: gameboy.gameboy.dma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +242,10 @@ impl Gui {
|
||||||
if ui.button("Toggle OAM Window").clicked() {
|
if ui.button("Toggle OAM Window").clicked() {
|
||||||
self.state.oam_window_open = !self.state.oam_window_open;
|
self.state.oam_window_open = !self.state.oam_window_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ui.button("Toggle DMA Window").clicked() {
|
||||||
|
self.state.dma_window_open = !self.state.dma_window_open;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
egui::Window::new("Register State").open(&mut self.state.register_window_open).show(
|
egui::Window::new("Register State").open(&mut self.state.register_window_open).show(
|
||||||
|
@ -336,6 +347,20 @@ impl Gui {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
egui::Window::new("DMA").vscroll(true).open(&mut self.state.dma_window_open).show(ctx, |ui| {
|
||||||
|
if let Some(bus) = self.dma.in_progress() {
|
||||||
|
ui.heading(RichText::new(format!("Active ({:#?} Bus)", bus)).color(Color32::LIGHT_GREEN));
|
||||||
|
} else {
|
||||||
|
ui.heading(RichText::new("Inactive").color(Color32::LIGHT_RED));
|
||||||
|
}
|
||||||
|
|
||||||
|
let offset = (0xA0 - self.dma.remaining_cycles) as u16;
|
||||||
|
ui.label(format!("Read Address: {:#04X}", ((self.dma.base as u16) << 8) | offset));
|
||||||
|
ui.label(format!("Write Address: {:#04X}", 0xFE00 | offset));
|
||||||
|
ui.label(format!("Base: {:#04X}", (self.dma.base as u16) << 8));
|
||||||
|
ui.label(format!("Remaining Bytes: {:#02X}", self.dma.remaining_cycles));
|
||||||
|
});
|
||||||
|
|
||||||
egui::Window::new("HRAM").vscroll(true).open(&mut self.state.hram_window_open).show(ctx, |ui| {
|
egui::Window::new("HRAM").vscroll(true).open(&mut self.state.hram_window_open).show(ctx, |ui| {
|
||||||
egui::Grid::new("memory_ov_hram").show(ui, |ui| {
|
egui::Grid::new("memory_ov_hram").show(ui, |ui| {
|
||||||
ui.label("ROW: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
|
ui.label("ROW: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
|
||||||
|
|
|
@ -37,6 +37,16 @@ else
|
||||||
echo "Failed: $res"
|
echo "Failed: $res"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/add_sp_e_timing.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/add_sp_e_timing.gb test -m 100000000 -s meowgb-tests/expected_output/add_sp_e_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"
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/basic.gb"
|
||||||
|
|
||||||
TEST_TOTAL=$((TEST_TOTAL + 1))
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
@ -67,6 +77,46 @@ else
|
||||||
echo "Failed: $res"
|
echo "Failed: $res"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/call_cc_timing.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_cc_timing.gb test -m 100000000 -s meowgb-tests/expected_output/call_cc_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/call_cc_timing2.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_cc_timing2.gb test -m 100000000 -s meowgb-tests/expected_output/call_cc_timing2.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/call_timing.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_timing.gb test -m 100000000 -s meowgb-tests/expected_output/call_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/call_timing2.gb"
|
||||||
|
|
||||||
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
||||||
|
if res=$(./target/release/meowgb-tests test-roms/mooneye-test-suite/roms/call_timing2.gb test -m 100000000 -s meowgb-tests/expected_output/call_timing2.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"
|
echo "Running test ROM ./test-roms/mooneye-test-suite/roms/daa.gb"
|
||||||
|
|
||||||
TEST_TOTAL=$((TEST_TOTAL + 1))
|
TEST_TOTAL=$((TEST_TOTAL + 1))
|
||||||
|
|
BIN
test-roms/mooneye-test-suite/roms/add_sp_e_timing.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/add_sp_e_timing.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/call_cc_timing.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/call_cc_timing.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/call_cc_timing2.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/call_cc_timing2.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/call_timing.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/call_timing.gb
Normal file
Binary file not shown.
BIN
test-roms/mooneye-test-suite/roms/call_timing2.gb
Normal file
BIN
test-roms/mooneye-test-suite/roms/call_timing2.gb
Normal file
Binary file not shown.
5
tests.md
5
tests.md
|
@ -8,9 +8,14 @@
|
||||||
|
|
||||||
## Mooneye Test Suite
|
## Mooneye Test Suite
|
||||||
|
|
||||||
|
* add_sp_e_timing.gb - [ROM](./test-roms/mooneye-test-suite/roms/add_sp_e_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/add_sp_e_timing.bin)
|
||||||
* basic.gb - [ROM](./test-roms/mooneye-test-suite/roms/basic.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/basic.bin)
|
* basic.gb - [ROM](./test-roms/mooneye-test-suite/roms/basic.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/basic.bin)
|
||||||
* boot_hwio-dmgABCmgb.gb - [ROM](./test-roms/mooneye-test-suite/roms/boot_hwio-dmgABCmgb.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/boot_hwio-dmgABCmgb.bin)
|
* boot_hwio-dmgABCmgb.gb - [ROM](./test-roms/mooneye-test-suite/roms/boot_hwio-dmgABCmgb.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/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/MBC1/boot_regs-dmgABC.bin)
|
* boot_regs-dmgABC.gb - [ROM](./test-roms/mooneye-test-suite/roms/boot_regs-dmgABC.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/boot_regs-dmgABC.bin)
|
||||||
|
* call_cc_timing.gb - [ROM](./test-roms/mooneye-test-suite/roms/call_cc_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/call_cc_timing.bin)
|
||||||
|
* call_cc_timing2.gb - [ROM](./test-roms/mooneye-test-suite/roms/call_cc_timing2.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/call_cc_timing2.bin)
|
||||||
|
* call_timing.gb - [ROM](./test-roms/mooneye-test-suite/roms/call_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/call_timing.bin)
|
||||||
|
* call_timing2.gb - [ROM](./test-roms/mooneye-test-suite/roms/call_timing2.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/call_timing2.bin)
|
||||||
* daa.gb - [ROM](./test-roms/mooneye-test-suite/roms/daa.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/daa.bin)
|
* daa.gb - [ROM](./test-roms/mooneye-test-suite/roms/daa.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/daa.bin)
|
||||||
* di_timing-GS.gb - [ROM](./test-roms/mooneye-test-suite/roms/di_timing-GS.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/di_timing-GS.bin)
|
* di_timing-GS.gb - [ROM](./test-roms/mooneye-test-suite/roms/di_timing-GS.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/di_timing-GS.bin)
|
||||||
* div_timing.gb - [ROM](./test-roms/mooneye-test-suite/roms/div_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/div_timing.bin)
|
* div_timing.gb - [ROM](./test-roms/mooneye-test-suite/roms/div_timing.gb) - [Expected Serial Output](./meowgb-tests/expected_output/MBC1/div_timing.bin)
|
||||||
|
|
Loading…
Reference in a new issue