Fix bugs with emulation mode flag

This commit is contained in:
2023-10-05 16:02:18 -05:00
parent 265da3470f
commit 8f05a21ebc
5 changed files with 50 additions and 78 deletions

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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));
});

View File

@@ -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) |