From 8f05a21ebccc37b8a4f654f34c22603286cfeabc Mon Sep 17 00:00:00 2001 From: Franco Colmenarez Date: Thu, 5 Oct 2023 16:02:18 -0500 Subject: [PATCH] Fix bugs with emulation mode flag --- snes-core/src/cpu/cycles.rs | 8 +-- snes-core/src/cpu/instructions.rs | 23 ++++---- snes-core/src/cpu/registers.rs | 89 ++++++++++++------------------- snes-frontend/src/main.rs | 2 - snes-frontend/src/ppu.rs | 6 +-- 5 files changed, 50 insertions(+), 78 deletions(-) diff --git a/snes-core/src/cpu/cycles.rs b/snes-core/src/cpu/cycles.rs index 96aec21..72a39c3 100644 --- a/snes-core/src/cpu/cycles.rs +++ b/snes-core/src/cpu/cycles.rs @@ -349,6 +349,10 @@ impl CPU { self.registers.increment_pc(2); self.cycles += 3; } + pub fn increment_cycles_sep(&mut self) { + self.registers.increment_pc(2); self.cycles += 3; + } + pub fn increment_cycles_return_subroutine(&mut self) { self.cycles += 6; } @@ -364,10 +368,6 @@ impl CPU { self.registers.increment_pc(1); self.cycles += 2; } - pub fn increment_cycles_sep(&mut self) { - self.registers.increment_pc(2); self.cycles += 3; - } - pub fn increment_cycles_sta(&mut self, addressing_mode: AddressingMode) { let (bytes, cycles) = CPU::common_bytes_cycles_arithmetic(addressing_mode); self.registers.increment_pc(bytes); self.cycles += cycles; diff --git a/snes-core/src/cpu/instructions.rs b/snes-core/src/cpu/instructions.rs index 9b7119b..14da111 100644 --- a/snes-core/src/cpu/instructions.rs +++ b/snes-core/src/cpu/instructions.rs @@ -672,7 +672,7 @@ impl CPU { IndexRegister::Y => self.registers.y = value, } self.registers.set_flags(&[ - Flags::Negative(value >> 7 == 1), + Flags::Negative(value >> 15 == 1), Flags::Zero(value == 0), ]); } else { @@ -844,7 +844,8 @@ impl CPU { } fn sep(&mut self, bus: &mut Bus) { - self.registers.p = self.get_8bit_from_address(bus, AddressingMode::Immediate); + let byte = self.get_8bit_from_address(bus, AddressingMode::Immediate); + self.registers.set_sep_byte(byte); self.increment_cycles_sep(); } @@ -979,7 +980,7 @@ impl CPU { } fn txs(&mut self) { - if self.registers.is_16bit_mode() { + if self.registers.is_16bit_index() { self.registers.sp = self.registers.x; self.registers.set_negative_flag((self.registers.a >> 15) == 1); self.registers.set_zero_flag(self.registers.a == 0); @@ -993,7 +994,7 @@ impl CPU { } fn txy(&mut self) { - if self.registers.is_16bit_mode() { + if self.registers.is_16bit_index() { self.registers.y = self.registers.x; self.registers.set_negative_flag((self.registers.x >> 15) == 1); self.registers.set_zero_flag(self.registers.x == 0); @@ -1021,7 +1022,7 @@ impl CPU { } fn tyx(&mut self) { - if self.registers.is_16bit_mode() { + if self.registers.is_16bit_index() { self.registers.x = self.registers.y; self.registers.set_negative_flag((self.registers.y >> 15) == 1); self.registers.set_zero_flag(self.registers.y == 0); @@ -1510,7 +1511,6 @@ impl CPU { #[cfg(test)] mod cpu_instructions_tests { use super::*; - use crate::common::flags::ModeFlag; #[test] fn test_adc() { @@ -1623,7 +1623,6 @@ mod cpu_instructions_tests { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.emulation_mode = false; - cpu.registers.exposed_bit_zero = ModeFlag::Carry; cpu.registers.a = 0b00000000_00000011; cpu.registers.pbr = 0x00; cpu.registers.pc = 0x0000; @@ -2077,7 +2076,6 @@ mod cpu_instructions_tests { cpu.registers.pbr = 0x00; cpu.registers.pc = 0x0000; cpu.registers.emulation_mode = false; - cpu.registers.exposed_bit_zero = ModeFlag::Carry; cpu.registers.set_16bit_index(true); cpu.registers.set_overflow_flag(false); bus.write(0x000002, 0xB0); @@ -2098,7 +2096,6 @@ mod cpu_instructions_tests { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.emulation_mode = false; - cpu.registers.exposed_bit_zero = ModeFlag::Carry; cpu.registers.y = 0x01; cpu.registers.pbr = 0x00; cpu.registers.pc = 0x0000; @@ -2455,6 +2452,7 @@ mod cpu_instructions_tests { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.emulation_mode = false; + cpu.registers.set_16bit_index(true); cpu.registers.pc = 0x0000; cpu.registers.x = 0x1234; cpu.registers.sp = 0x1FC; @@ -2471,6 +2469,7 @@ mod cpu_instructions_tests { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.emulation_mode = false; + cpu.registers.set_16bit_index(true); cpu.registers.pc = 0x0000; cpu.registers.y = 0x1234; cpu.registers.sp = 0x1FC; @@ -2900,7 +2899,7 @@ mod cpu_instructions_tests { cpu.registers.pc = 0x0000; cpu.registers.a = 0x0000; cpu.registers.x = 0xF0F0; - cpu.registers.set_16bit_index(true); + cpu.registers.set_16bit_mode(true); cpu.txa(); assert_eq!(cpu.registers.a, 0xF0F0); assert_eq!(cpu.registers.pc, 0x0001); @@ -2942,7 +2941,7 @@ mod cpu_instructions_tests { cpu.registers.pc = 0x0000; cpu.registers.a = 0x0000; cpu.registers.y = 0xF0F0; - cpu.registers.set_16bit_index(true); + cpu.registers.set_16bit_mode(true); cpu.tya(); assert_eq!(cpu.registers.a, 0xF0F0); assert_eq!(cpu.registers.pc, 0x0001); @@ -2998,9 +2997,7 @@ mod cpu_instructions_tests { fn test_xce() { let mut cpu = CPU::new(); cpu.registers.pc = 0x0000; - cpu.registers.exposed_bit_zero = ModeFlag::Carry; cpu.xce(); - assert_eq!(cpu.registers.exposed_bit_zero, ModeFlag::EmulationMode); assert_eq!(cpu.registers.pc, 0x0001); assert_eq!(cpu.cycles, 2); } diff --git a/snes-core/src/cpu/registers.rs b/snes-core/src/cpu/registers.rs index 223e670..78bd177 100644 --- a/snes-core/src/cpu/registers.rs +++ b/snes-core/src/cpu/registers.rs @@ -1,4 +1,4 @@ -use crate::common::flags::{Flags, ModeFlag}; +use crate::common::flags::Flags; pub struct Registers { pub sp: u16, // Stack pointer @@ -10,26 +10,22 @@ pub struct Registers { pub pbr: u8, // Program bank register pub dbr: u8, // Data bank register pub pc: u16, // Program counter - pub exposed_bit_zero: ModeFlag, pub emulation_mode: bool, - pub carry: bool, } impl Registers { pub fn new() -> Self { Self { - sp: 0x01FC, + sp: 0x01FF, x: 0, y: 0, a: 0, - p: 0, + p: 0b00110100, d: 0, pbr: 0, dbr: 0, pc: 0, - exposed_bit_zero: ModeFlag::EmulationMode, emulation_mode: true, - carry: false, } } @@ -50,19 +46,12 @@ impl Registers { } pub fn get_carry_flag(&self) -> bool { - match self.exposed_bit_zero { - ModeFlag::Carry => self.carry, - ModeFlag::EmulationMode => self.emulation_mode, - } + (self.p & 0b0000_0001) == 1 } pub fn set_carry_flag(&mut self, val: bool) { self.p = self.p & 0b1111_1110; self.p = self.p | (val as u8); - match self.exposed_bit_zero { - ModeFlag::Carry => self.carry = val, - ModeFlag::EmulationMode => self.emulation_mode = val, - }; } pub fn get_emulation_mode_flag(&self) -> bool { @@ -191,26 +180,10 @@ impl Registers { self.d as u8 } - pub fn is_emu_mode_flag_exposed(&self) -> bool { - match self.exposed_bit_zero { - ModeFlag::Carry => false, - ModeFlag::EmulationMode => true, - } - } - pub fn exchange_carry_and_emulation(&mut self) { - match self.exposed_bit_zero { - ModeFlag::Carry => { - self.carry = self.get_carry_flag(); - self.exposed_bit_zero = ModeFlag::EmulationMode; - self.set_emulation_mode_flag(self.emulation_mode); - }, - ModeFlag::EmulationMode => { - self.emulation_mode = self.get_carry_flag(); - self.exposed_bit_zero = ModeFlag::Carry; - self.set_carry_flag(self.carry); - }, - } + let temp_carry_flag_value = self.get_carry_flag(); + self.set_carry_flag(self.emulation_mode); + self.emulation_mode = temp_carry_flag_value; } pub fn set_flags(&mut self, flags: &[Flags]) { @@ -232,11 +205,10 @@ impl Registers { pub fn reset_rep_byte(&mut self, byte: u8) { self.p = self.p & !byte; - // Avoid messing up exposed emu mode flag logic - let reset_carry_flag = (byte & 0x01) == 1; - if reset_carry_flag { - self.set_carry_flag(false); - } + } + + pub fn set_sep_byte(&mut self, byte: u8) { + self.p = self.p | byte; } } @@ -437,27 +409,16 @@ mod registers_tests { fn test_exchange_carry_and_emulation() { let mut registers = Registers::new(); registers.emulation_mode = false; - registers.exposed_bit_zero = ModeFlag::Carry; - registers .set_flags(&[Flags::Carry(false)]); - registers.exposed_bit_zero = ModeFlag::EmulationMode; - registers .set_flags(&[Flags::EmulationMode(false)]); - - registers.exposed_bit_zero = ModeFlag::Carry; - registers.set_carry_flag(true); - assert_eq!(registers.get_carry_flag(), true); + registers.set_flags(&[Flags::Carry(true)]); registers.exchange_carry_and_emulation(); assert_eq!(registers.get_carry_flag(), false); + assert_eq!(registers.emulation_mode, true); - registers.exposed_bit_zero = ModeFlag::Carry; - registers .set_flags(&[Flags::Carry(false)]); - registers.exposed_bit_zero = ModeFlag::EmulationMode; - registers .set_flags(&[Flags::EmulationMode(false)]); - - registers.exposed_bit_zero = ModeFlag::EmulationMode; - registers.set_emulation_mode_flag(true); - assert_eq!(registers.get_emulation_mode_flag(), true); + registers.emulation_mode = true; + registers.set_flags(&[Flags::Carry(false)]); registers.exchange_carry_and_emulation(); - assert_eq!(registers.get_emulation_mode_flag(), false); + assert_eq!(registers.get_carry_flag(), true); + assert_eq!(registers.emulation_mode, false); } #[test] @@ -495,4 +456,20 @@ mod registers_tests { registers.reset_rep_byte(0x38); assert_eq!(registers.p, 0b10000110); } + + #[test] + fn test_set_rep_byte() { + let mut registers = Registers::new(); + registers.p = 0xFF; + registers.set_sep_byte(0b0000_0001); + assert_eq!(registers.p, 0xFF); + + registers.p = 0b10101010; + registers.set_sep_byte(0b0000_0000); + assert_eq!(registers.p, 0b10101010); + + registers.p = 0b10100000; + registers.set_sep_byte(0b0000_1111); + assert_eq!(registers.p, 0b10101111); + } } diff --git a/snes-frontend/src/main.rs b/snes-frontend/src/main.rs index 420a71f..c97799e 100644 --- a/snes-frontend/src/main.rs +++ b/snes-frontend/src/main.rs @@ -370,10 +370,8 @@ fn main() { ui.text(format!("DBR: | {:#04X}", emulator.cpu.registers.dbr)); ui.text(format!("PC: | {:#06X}", emulator.cpu.registers.pc)); ui.text(format!("EMU MODE: | {}", emulator.cpu.registers.emulation_mode)); - ui.text(format!("CARRY: | {}", emulator.cpu.registers.carry)); ui.separator(); ui.text("Status flags:"); - ui.text(format!(" E (exposed: {})", emulator.cpu.registers.is_emu_mode_flag_exposed())); ui.text("NVMXDIZC"); ui.text(format!("{:08b}", emulator.cpu.registers.p)); }); diff --git a/snes-frontend/src/ppu.rs b/snes-frontend/src/ppu.rs index d3ed4ed..cc47240 100644 --- a/snes-frontend/src/ppu.rs +++ b/snes-frontend/src/ppu.rs @@ -71,13 +71,13 @@ fn render_background_char_2bpp(bgdebug: &mut BgDebug, registers: &PPURegisters) // 8x8 pixels, 2 bitplanes, each word (16bit) holds 8 pixels // so 1 char is 8 bytes x 2 let char_base_vram_address = current_char * 8 * 2; - let vram_address = vram_base_address + ( + let effective_vram_address = vram_base_address + ( char_base_vram_address + (current_char_row * 2) ); let current_pixel = x + (y * width); - let lsb_bitplane= vram[vram_address]; - let msb_bitplane= vram[vram_address + 1]; + let lsb_bitplane= vram[effective_vram_address]; + let msb_bitplane= vram[effective_vram_address + 1]; let pixels = [ ( (lsb_bitplane >> 7) |