mirror of
https://github.com/FranLMSP/snes.git
synced 2026-01-01 07:21:35 -05:00
Fix bugs with emulation mode flag
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
|
||||
@@ -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) |
|
||||
|
||||
Reference in New Issue
Block a user