From 0ccabda71ee3d2f94c517ba5d4d9a01b3e6e4931 Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Fri, 30 Mar 2018 20:07:24 -0500 Subject: [PATCH] Rewrite SBC logic The carry handling was incorrect; carry is set if we went below zero, but bit 7 is not enough to determine that. It follows that negative handling needed to be modified accordingly. Overflow handling was also incorrect. --- src/mos6502.arith.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/mos6502.arith.c b/src/mos6502.arith.c index 0d458b4..0eaf389 100644 --- a/src/mos6502.arith.c +++ b/src/mos6502.arith.c @@ -225,18 +225,30 @@ DEFINE_INST(sbc) MOS_CARRY_BIT(); - vm_8bit result = cpu->A - oper - (carry ? 0 : 1); - MOS_CHECK_NVZ(cpu->A, result); + int result32 = cpu->A - oper - (carry ? 0 : 1); + vm_8bit result8 = cpu->A - oper - (carry ? 0 : 1); + + MOS_CHECK_Z(result8); // Carry is handled slightly differently in SBC; it's set if the // value is non-negative, and unset if negative. (It's essentially a // mirror of the N flag in that sense.) cpu->P |= MOS_CARRY; - if (result >= 0x80) { + cpu->P &= ~MOS_NEGATIVE; + + if (result32 < 0) { cpu->P &= ~MOS_CARRY; + cpu->P |= MOS_NEGATIVE; } - cpu->A = result; + cpu->P &= ~MOS_OVERFLOW; + if ((cpu->A & 0x80) != (oper & 0x80) && + (cpu->A & 0x80) != (result8 & 0x80) + ) { + cpu->P |= MOS_OVERFLOW; + } + + cpu->A = result8; } /*