mirror of
https://github.com/FranLMSP/snes.git
synced 2026-08-03 08:30:01 -04:00
Fix bugs related to 16bit mode, emulation mode and REP instruction
This commit is contained in:
@@ -51,7 +51,7 @@ impl CPU {
|
||||
match condition {
|
||||
// Add 1 byte and 1 cycle if m = 0 (16-bit memory/accumulator)
|
||||
Condition::MemorySelectFlag => {
|
||||
if !self.registers.get_memory_select_flag() {
|
||||
if self.registers.is_16bit_mode() {
|
||||
cycles += 1;
|
||||
match addressing_mode {
|
||||
A::Immediate => bytes += 1,
|
||||
@@ -441,6 +441,7 @@ mod cpu_instructions_tests {
|
||||
#[test]
|
||||
fn test_common_conditions() {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
|
||||
// 16-bit Memory/accumulator flag condition
|
||||
cpu.registers.pc = 0;
|
||||
|
||||
@@ -760,7 +760,8 @@ impl CPU {
|
||||
}
|
||||
|
||||
fn rep(&mut self, bus: &Bus) {
|
||||
self.registers.p = self.get_8bit_from_address(bus, AddressingMode::Immediate);
|
||||
let byte = self.get_8bit_from_address(bus, AddressingMode::Immediate);
|
||||
self.registers.reset_rep_byte(byte);
|
||||
self.increment_cycles_rep();
|
||||
}
|
||||
|
||||
@@ -1506,6 +1507,7 @@ mod cpu_instructions_tests {
|
||||
fn test_adc() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.a = 0x0000;
|
||||
cpu.registers.pbr = 0x00;
|
||||
cpu.registers.pc = 0x0000;
|
||||
@@ -1539,6 +1541,7 @@ mod cpu_instructions_tests {
|
||||
fn test_sbc() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.a = 0x0001;
|
||||
cpu.registers.pbr = 0x00;
|
||||
cpu.registers.pc = 0x0000;
|
||||
@@ -1556,6 +1559,7 @@ mod cpu_instructions_tests {
|
||||
fn test_and() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.a = 0x0101;
|
||||
cpu.registers.pbr = 0x00;
|
||||
cpu.registers.pc = 0x0000;
|
||||
@@ -1591,6 +1595,7 @@ mod cpu_instructions_tests {
|
||||
fn test_asl() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.a = 0b01010000_00000000;
|
||||
cpu.registers.pbr = 0x00;
|
||||
cpu.registers.pc = 0x0000;
|
||||
@@ -1608,6 +1613,8 @@ mod cpu_instructions_tests {
|
||||
fn test_lsr() {
|
||||
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;
|
||||
@@ -1627,6 +1634,7 @@ mod cpu_instructions_tests {
|
||||
fn test_bit() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.a = 0b1111_0000;
|
||||
cpu.registers.pbr = 0x00;
|
||||
cpu.registers.pc = 0x0000;
|
||||
@@ -2041,6 +2049,7 @@ mod cpu_instructions_tests {
|
||||
// store the result nor it affects the overflow flag
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.x = 0x01;
|
||||
cpu.registers.pbr = 0x00;
|
||||
cpu.registers.pc = 0x0000;
|
||||
@@ -2058,6 +2067,8 @@ mod cpu_instructions_tests {
|
||||
cpu.registers.x = 0x50;
|
||||
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);
|
||||
@@ -2077,6 +2088,8 @@ mod cpu_instructions_tests {
|
||||
// store the result nor it affects the overflow flag
|
||||
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;
|
||||
@@ -2432,6 +2445,7 @@ mod cpu_instructions_tests {
|
||||
fn test_phx() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.x = 0x1234;
|
||||
cpu.registers.sp = 0x1FC;
|
||||
@@ -2447,6 +2461,7 @@ mod cpu_instructions_tests {
|
||||
fn test_phy() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.y = 0x1234;
|
||||
cpu.registers.sp = 0x1FC;
|
||||
@@ -2462,6 +2477,7 @@ mod cpu_instructions_tests {
|
||||
fn test_pla() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.y = 0x1234;
|
||||
cpu.registers.set_16bit_mode(true);
|
||||
@@ -2537,6 +2553,7 @@ mod cpu_instructions_tests {
|
||||
fn test_plx() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.x = 0x1234;
|
||||
cpu.registers.set_16bit_index(true);
|
||||
@@ -2558,6 +2575,7 @@ mod cpu_instructions_tests {
|
||||
fn test_ply() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.y = 0x1234;
|
||||
cpu.registers.set_16bit_index(true);
|
||||
@@ -2579,11 +2597,12 @@ mod cpu_instructions_tests {
|
||||
fn test_rep() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.p = 0x00;
|
||||
cpu.registers.p = 0xFF;
|
||||
bus.write(0x0001, 0xFF);
|
||||
cpu.rep(&mut bus);
|
||||
assert_eq!(cpu.registers.p, 0xFF);
|
||||
assert_eq!(cpu.registers.p, 0x00);
|
||||
assert_eq!(cpu.registers.pc, 0x0002);
|
||||
assert_eq!(cpu.cycles, 3);
|
||||
}
|
||||
@@ -2592,6 +2611,7 @@ mod cpu_instructions_tests {
|
||||
fn test_rol() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.set_16bit_mode(false);
|
||||
cpu.registers.a = 0b0100_0000;
|
||||
cpu.registers.pc = 0x0000;
|
||||
@@ -2607,6 +2627,7 @@ mod cpu_instructions_tests {
|
||||
fn test_ror() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.set_16bit_mode(false);
|
||||
cpu.registers.set_carry_flag(true);
|
||||
cpu.registers.a = 0x00;
|
||||
@@ -2770,6 +2791,7 @@ mod cpu_instructions_tests {
|
||||
#[test]
|
||||
fn test_tax() {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.a = 0xF0F0;
|
||||
cpu.registers.x = 0x0000;
|
||||
@@ -2786,6 +2808,7 @@ mod cpu_instructions_tests {
|
||||
#[test]
|
||||
fn test_tay() {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.a = 0xF0F0;
|
||||
cpu.registers.y = 0x0000;
|
||||
@@ -2850,6 +2873,7 @@ mod cpu_instructions_tests {
|
||||
#[test]
|
||||
fn test_tsx() {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.x = 0x0000;
|
||||
cpu.registers.sp = 0xF0F0;
|
||||
@@ -2863,6 +2887,7 @@ mod cpu_instructions_tests {
|
||||
#[test]
|
||||
fn test_txa() {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.a = 0x0000;
|
||||
cpu.registers.x = 0xF0F0;
|
||||
@@ -2876,6 +2901,7 @@ mod cpu_instructions_tests {
|
||||
#[test]
|
||||
fn test_txs() {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.sp = 0x0000;
|
||||
cpu.registers.x = 0xF0F0;
|
||||
@@ -2889,6 +2915,7 @@ mod cpu_instructions_tests {
|
||||
#[test]
|
||||
fn test_txy() {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.y = 0x0000;
|
||||
cpu.registers.x = 0xF0F0;
|
||||
@@ -2902,6 +2929,7 @@ mod cpu_instructions_tests {
|
||||
#[test]
|
||||
fn test_tya() {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.a = 0x0000;
|
||||
cpu.registers.y = 0xF0F0;
|
||||
@@ -2915,6 +2943,7 @@ mod cpu_instructions_tests {
|
||||
#[test]
|
||||
fn test_tyx() {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.registers.emulation_mode = false;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.x = 0x0000;
|
||||
cpu.registers.y = 0xF0F0;
|
||||
|
||||
@@ -27,8 +27,8 @@ impl Registers {
|
||||
pbr: 0,
|
||||
dbr: 0,
|
||||
pc: 0,
|
||||
exposed_bit_zero: ModeFlag::Carry,
|
||||
emulation_mode: false,
|
||||
exposed_bit_zero: ModeFlag::EmulationMode,
|
||||
emulation_mode: true,
|
||||
carry: false,
|
||||
}
|
||||
}
|
||||
@@ -154,10 +154,16 @@ impl Registers {
|
||||
}
|
||||
|
||||
pub fn is_16bit_index(&self) -> bool {
|
||||
if self.emulation_mode {
|
||||
return false
|
||||
}
|
||||
!self.get_index_register_select_flag()
|
||||
}
|
||||
|
||||
pub fn is_16bit_mode(&self) -> bool {
|
||||
if self.emulation_mode {
|
||||
return false
|
||||
}
|
||||
!self.get_memory_select_flag()
|
||||
}
|
||||
|
||||
@@ -223,6 +229,15 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -232,6 +247,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_is_16bit_mode() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
registers.set_memory_select_flag(false);
|
||||
assert!(registers.is_16bit_mode());
|
||||
registers.set_memory_select_flag(true);
|
||||
@@ -241,6 +257,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_set_16bit_mode() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
registers.set_16bit_mode(true);
|
||||
assert!(registers.is_16bit_mode());
|
||||
registers.set_16bit_mode(false);
|
||||
@@ -250,6 +267,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_is_16bit_index() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
registers.set_index_register_select_flag(false);
|
||||
assert!(registers.is_16bit_index());
|
||||
registers.set_index_register_select_flag(true);
|
||||
@@ -259,6 +277,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_set_16bit_index() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
registers.set_16bit_index(true);
|
||||
assert!(registers.is_16bit_index());
|
||||
registers.set_16bit_index(false);
|
||||
@@ -268,6 +287,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_set_low_a() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
registers.a = 0xA1A1;
|
||||
registers.set_low_a(0xFF);
|
||||
assert_eq!(registers.a, 0xA1FF);
|
||||
@@ -276,6 +296,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_set_low_x() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
registers.x = 0xA1A1;
|
||||
registers.set_low_x(0xFF);
|
||||
assert_eq!(registers.x, 0xA1FF);
|
||||
@@ -284,6 +305,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_set_low_y() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
registers.y = 0xA1A1;
|
||||
registers.set_low_y(0xFF);
|
||||
assert_eq!(registers.y, 0xA1FF);
|
||||
@@ -292,6 +314,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_set_low_sp() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
registers.sp = 0xA1A1;
|
||||
registers.set_low_sp(0xFF);
|
||||
assert_eq!(registers.sp, 0xA1FF);
|
||||
@@ -319,6 +342,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_status_registers() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
registers.p = 0x00;
|
||||
|
||||
registers.set_carry_flag(true);
|
||||
@@ -388,6 +412,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
fn test_set_flags() {
|
||||
let mut registers = Registers::new();
|
||||
registers.emulation_mode = false;
|
||||
|
||||
registers.p = 0x00;
|
||||
registers .set_flags(&[
|
||||
@@ -411,6 +436,7 @@ mod registers_tests {
|
||||
#[test]
|
||||
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;
|
||||
@@ -433,4 +459,40 @@ mod registers_tests {
|
||||
registers.exchange_carry_and_emulation();
|
||||
assert_eq!(registers.get_emulation_mode_flag(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reset_rep_byte() {
|
||||
let mut registers = Registers::new();
|
||||
registers.p = 0xFF;
|
||||
registers.reset_rep_byte(0b0000_0001);
|
||||
assert_eq!(registers.p, 0b1111_1110);
|
||||
|
||||
registers.p = 0xFF;
|
||||
registers.reset_rep_byte(0b0000_0010);
|
||||
assert_eq!(registers.p, 0b1111_1101);
|
||||
|
||||
registers.p = 0xFF;
|
||||
registers.reset_rep_byte(0b0010_0010);
|
||||
assert_eq!(registers.p, 0b1101_1101);
|
||||
|
||||
registers.p = 0xFF;
|
||||
registers.reset_rep_byte(0b1111_1111);
|
||||
assert_eq!(registers.p, 0b0000_0000);
|
||||
|
||||
registers.p = 0b0000_0010;
|
||||
registers.reset_rep_byte(0b0000_0001);
|
||||
assert_eq!(registers.p, 0b0000_0010);
|
||||
|
||||
registers.p = 0b0000_0010;
|
||||
registers.reset_rep_byte(0b0000_0010);
|
||||
assert_eq!(registers.p, 0b0000_0000);
|
||||
|
||||
registers.p = 0x38;
|
||||
registers.reset_rep_byte(0x38);
|
||||
assert_eq!(registers.p, 0x00);
|
||||
|
||||
registers.p = 0x86;
|
||||
registers.reset_rep_byte(0x38);
|
||||
assert_eq!(registers.p, 0b10000110);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ fn main() {
|
||||
emulator.tick();
|
||||
}
|
||||
});
|
||||
if ui.button("Reset") {
|
||||
if ui.button("Reset Vector") {
|
||||
emulator.reset();
|
||||
}
|
||||
ui.separator();
|
||||
|
||||
Reference in New Issue
Block a user