From 0b5b24050fb3016dc26f2224a5979b48a9f3d6c0 Mon Sep 17 00:00:00 2001 From: Franco Colmenarez Date: Sun, 21 Jan 2024 22:29:07 -0500 Subject: [PATCH] fix substraction issue --- snes-core/src/cpu/instructions/adc.rs | 19 +++++++++++++++ snes-core/src/cpu/instructions/cmp.rs | 1 + snes-core/src/cpu/instructions/comp_common.rs | 8 ++++--- snes-core/src/cpu/instructions/dec_common.rs | 2 +- snes-core/src/cpu/instructions/sbc.rs | 23 ++++++++++++++++++- snes-core/src/cpu/internal_registers.rs | 3 --- snes-core/src/utils/alu.rs | 18 +++++++-------- 7 files changed, 57 insertions(+), 17 deletions(-) diff --git a/snes-core/src/cpu/instructions/adc.rs b/snes-core/src/cpu/instructions/adc.rs index 906e961..056b790 100644 --- a/snes-core/src/cpu/instructions/adc.rs +++ b/snes-core/src/cpu/instructions/adc.rs @@ -147,6 +147,25 @@ mod cpu_instructions_tests { assert_eq!(registers.pc, 0x02); assert_eq!(registers.cycles, 2); assert!(!registers.get_carry_flag()); + + let mut registers = Registers::new(); + let mut bus = Bus::new(); + registers.emulation_mode = false; + registers.a = 0x007F; + registers.pbr = 0x00; + registers.pc = 0x0000; + registers.set_16bit_mode(false); + registers.set_carry_flag(true); + bus.write(0x000001, 0x7F); + let instruction = ADC8BIN{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); + assert_eq!(registers.a, 0xFF); + assert_eq!(registers.pc, 0x02); + assert_eq!(registers.cycles, 2); + assert!(registers.get_negative_flag()); + assert!(registers.get_overflow_flag()); + assert!(!registers.get_zero_flag()); + assert!(!registers.get_carry_flag()); } #[test] diff --git a/snes-core/src/cpu/instructions/cmp.rs b/snes-core/src/cpu/instructions/cmp.rs index 5dfbc24..0484a94 100644 --- a/snes-core/src/cpu/instructions/cmp.rs +++ b/snes-core/src/cpu/instructions/cmp.rs @@ -106,6 +106,7 @@ mod cpu_instructions_tests { registers.pc = 0x0000; registers.set_16bit_mode(false); registers.set_overflow_flag(false); + registers.set_carry_flag(true); bus.write(0x000001, 0xB0); let instruction = CMP16{addressing_mode: AddressingMode::Immediate}; instruction.execute(&mut registers, &mut bus); diff --git a/snes-core/src/cpu/instructions/comp_common.rs b/snes-core/src/cpu/instructions/comp_common.rs index 70f8cbe..d33ec93 100644 --- a/snes-core/src/cpu/instructions/comp_common.rs +++ b/snes-core/src/cpu/instructions/comp_common.rs @@ -2,11 +2,13 @@ use crate::{cpu::registers::Registers, utils::{num_trait::SnesNum, alu}, common: pub fn do_comp(registers: &mut Registers, target: T, value: T) { - let (_, affected_flags) = alu::sbc_bin(target, value, false); + let (_, affected_flags) = alu::sbc_bin(target, value, true); for flag in affected_flags { match flag { - Flags::Overflow(_) => {}, - _ => registers.set_flags(&[flag]), + Flags::Negative(_) | + Flags::Zero(_) | + Flags::Carry(_) => registers.set_flags(&[flag]), + _ => {}, } } } \ No newline at end of file diff --git a/snes-core/src/cpu/instructions/dec_common.rs b/snes-core/src/cpu/instructions/dec_common.rs index e9f39db..a68af73 100644 --- a/snes-core/src/cpu/instructions/dec_common.rs +++ b/snes-core/src/cpu/instructions/dec_common.rs @@ -1,7 +1,7 @@ use crate::{cpu::registers::Registers, utils::{num_trait::SnesNum, alu}, common::flags::Flags}; pub fn do_dec(registers: &mut Registers, target: T) -> T { - let (result, affected_flags) = alu::sbc_bin(target, T::from_u32(1), false); + let (result, affected_flags) = alu::sbc_bin(target, T::from_u32(1), true); for flag in affected_flags { match flag { Flags::Negative(_) | Flags::Zero(_) => registers.set_flags(&[flag]), diff --git a/snes-core/src/cpu/instructions/sbc.rs b/snes-core/src/cpu/instructions/sbc.rs index c69b733..d041fea 100644 --- a/snes-core/src/cpu/instructions/sbc.rs +++ b/snes-core/src/cpu/instructions/sbc.rs @@ -139,7 +139,8 @@ mod cpu_instructions_tests { registers.a = 0x0040; registers.pbr = 0x00; registers.pc = 0x0000; - registers.set_memory_select_flag(true); + registers.set_16bit_mode(false); + registers.set_carry_flag(true); bus.write(0x000001, 0x40); let instruction = SBC8BIN{addressing_mode: AddressingMode::Immediate}; instruction.execute(&mut registers, &mut bus); @@ -148,6 +149,25 @@ mod cpu_instructions_tests { assert_eq!(registers.cycles, 2); assert!(registers.get_zero_flag()); assert!(!registers.get_carry_flag()); + + let mut registers = Registers::new(); + let mut bus = Bus::new(); + registers.emulation_mode = false; + registers.a = 0x007F; + registers.pbr = 0x00; + registers.pc = 0x0000; + registers.set_16bit_mode(false); + registers.set_carry_flag(false); + bus.write(0x000001, 0x7E); + let instruction = SBC8BIN{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); + assert_eq!(registers.a, 0x00); + assert_eq!(registers.pc, 0x02); + assert_eq!(registers.cycles, 2); + assert!(!registers.get_negative_flag()); + assert!(!registers.get_overflow_flag()); + assert!(registers.get_zero_flag()); + assert!(registers.get_carry_flag()); } #[test] @@ -159,6 +179,7 @@ mod cpu_instructions_tests { registers.pbr = 0x00; registers.pc = 0x0000; registers.set_memory_select_flag(false); + registers.set_carry_flag(true); bus.write(0x000001, 0x00); bus.write(0x000002, 0x40); let instruction = SBC16BIN{addressing_mode: AddressingMode::Immediate}; diff --git a/snes-core/src/cpu/internal_registers.rs b/snes-core/src/cpu/internal_registers.rs index dd44fc3..306c94e 100644 --- a/snes-core/src/cpu/internal_registers.rs +++ b/snes-core/src/cpu/internal_registers.rs @@ -58,9 +58,6 @@ impl InternalRegisters { fn read_vblank_nmi_mut(&self, ppu_registers: &mut PPURegisters) -> u8 { let result = self.read_vblank_nmi(ppu_registers); - if result == 0x80 { - println!("nmi set"); - } // When register is read, bit 7 is cleared ppu_registers.vblank_nmi = false; result diff --git a/snes-core/src/utils/alu.rs b/snes-core/src/utils/alu.rs index f16db07..3897cc0 100644 --- a/snes-core/src/utils/alu.rs +++ b/snes-core/src/utils/alu.rs @@ -49,12 +49,12 @@ pub fn adc_bcd(target: T, value: T, carry: bool) -> (T, [Flags; 4]) } pub fn sbc_bin(target: T, value: T, carry: bool) -> (T, [Flags; 4]) { - let result = target.sbc_snes(value, carry); + let result = target.sbc_snes(value, !carry); (result, [ Negative(result.is_negative()), Overflow(target.is_overflow(value, result)), Zero(result.is_zero()), - Carry(target.sbc_will_carry(value, carry)), + Carry(!carry), ]) } @@ -274,33 +274,33 @@ mod alu_tests { #[test] fn test_dec_bin() { // 8 bit - let (result, affected_flags) = sbc_bin(1_u8, 1_u8, false); + let (result, affected_flags) = sbc_bin(1_u8, 1_u8, true); assert_eq!(result, 0); assert_eq!(affected_flags, [Negative(false), Overflow(false), Zero(true), Carry(false)]); - let (result, affected_flags) = sbc_bin(0_u8, 1_u8, false); + let (result, affected_flags) = sbc_bin(0_u8, 1_u8, true); assert_eq!(result, 0b11111111); assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(true)]); - let (result, affected_flags) = sbc_bin(0_u8, 1_u8, true); + let (result, affected_flags) = sbc_bin(0_u8, 1_u8, false); assert_eq!(result, 0b11111110); assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(true)]); // overflow - let (result, affected_flags) = sbc_bin(0x50_u8, 0xB0_u8, false); + let (result, affected_flags) = sbc_bin(0x50_u8, 0xB0_u8, true); assert_eq!(result, 0xA0); assert_eq!(affected_flags, [Negative(true), Overflow(false), Zero(false), Carry(true)]); // 16 bit - let (result, affected_flags) = sbc_bin(1_u16, 1_u16, false); + let (result, affected_flags) = sbc_bin(1_u16, 1_u16, true); assert_eq!(result, 0); assert_eq!(affected_flags, [Negative(false), Overflow(false), Zero(true), Carry(false)]); - let (result, affected_flags) = sbc_bin(0_u16, 1_u16, false); + let (result, affected_flags) = sbc_bin(0_u16, 1_u16, true); assert_eq!(result, 0b11111111_11111111); assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(true)]); - let (result, affected_flags) = sbc_bin(0_u16, 1_u16, true); + let (result, affected_flags) = sbc_bin(0_u16, 1_u16, false); assert_eq!(result, 0b11111111_11111110); assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(true)]); }