Skip to content

Commit 7a397de

Browse files
committed
Fix several CPU instruction bug. SMB now working perfectly - disappearing enemy bug is gone
1 parent dfbade6 commit 7a397de

File tree

3 files changed

+26
-17
lines changed

3 files changed

+26
-17
lines changed

lib/inc/nes_cpu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ private :
387387

388388
bool is_sign_overflow(uint8_t val1, int8_t val2, uint8_t new_value)
389389
{
390-
return ((val1 & 0x80) == (val2 & 0x80) &&
390+
return (((val1 & 0x80) == (val2 & 0x80)) &&
391391
((val1 & 0x80) != (new_value & 0x80)));
392392
}
393393

lib/src/nes_cpu.cpp

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -721,11 +721,23 @@ void nes_cpu::ADC(nes_addr_mode addr_mode)
721721
void nes_cpu::_ADC(uint8_t val)
722722
{
723723
uint8_t old_val = A();
724-
A() = val + A() + get_carry();
724+
uint8_t new_val = old_val;
725+
bool bit7_overflow = false;
726+
727+
// FF+FF+1=FF -> need to detect such case by checking for overflow in each step
728+
// However, for FF+80+1=80 -> the sign bit got "rescued" so we should just check final result
729+
new_val += val;
730+
if (new_val < old_val) bit7_overflow = true;
731+
732+
uint8_t old_val2 = new_val;
733+
new_val += get_carry();
734+
if (new_val < old_val2) bit7_overflow = true;
735+
736+
A() = new_val;
725737

726738
// flags
727-
set_overflow_flag(is_sign_overflow(old_val, val, A()));
728-
set_carry_flag(old_val > A() || val > A());
739+
set_overflow_flag(is_sign_overflow(old_val, val, new_val));
740+
set_carry_flag(bit7_overflow);
729741
calc_alu_flag(A());
730742
}
731743

@@ -803,15 +815,7 @@ void nes_cpu::SBC(nes_addr_mode addr_mode)
803815

804816
void nes_cpu::_SBC(uint8_t val)
805817
{
806-
val = ~val + 1; // turn it into a add operand
807-
val = val -(1 - get_carry()); // account for the carry
808-
uint8_t old_val = A();
809-
A() = A() + val;
810-
811-
// flags
812-
set_overflow_flag(is_sign_overflow(old_val, val, A()));
813-
set_carry_flag(A() <= old_val);
814-
calc_alu_flag(A());
818+
_ADC(~val);
815819
}
816820

817821
// Load Accumulator
@@ -1130,7 +1134,7 @@ void nes_cpu::LSR(nes_addr_mode addr_mode)
11301134
set_carry_flag(val & 0x1);
11311135

11321136
// @DOCBUG:
1133-
// http://obelisk.me.uk/6502/reference.html#ASL incorrectly states ASL detects A == 0
1137+
// http://obelisk.me.uk/6502/reference.html#LSR incorrectly states ASL detects A == 0
11341138
set_zero_flag(new_val == 0);
11351139
set_negative_flag(new_val & 0x80);
11361140

@@ -1208,7 +1212,9 @@ void nes_cpu::ROL(nes_addr_mode addr_mode)
12081212

12091213
// flags
12101214
set_carry_flag(val & 0x80);
1211-
set_zero_flag(A() == 0);
1215+
// @DOCBUG
1216+
// http://obelisk.me.uk/6502/reference.html#ROL incorrectly states zero is set if A == 0
1217+
set_zero_flag(new_val == 0);
12121218
set_negative_flag(new_val & 0x80);
12131219

12141220
// cycle count
@@ -1225,7 +1231,10 @@ void nes_cpu::ROR(nes_addr_mode addr_mode)
12251231

12261232
// flags
12271233
set_carry_flag(val & 0x1);
1228-
set_zero_flag(A() == 0);
1234+
1235+
// @DOCBUG
1236+
// http://obelisk.me.uk/6502/reference.html#ROR incorrectly states zero is set if A == 0
1237+
set_zero_flag(new_val == 0);
12291238
set_negative_flag(new_val & 0x80);
12301239

12311240
// cycle count

test/cpu_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,6 @@ TEST_CASE("CPU tests") {
125125
system.run_rom("./roms/instr_test-v5/rom_singles/06-absolute.nes", nes_rom_exec_mode_reset);
126126

127127
// Check the test is successful
128-
// CHECK(cpu->peek(0x6000) == 0);
128+
CHECK(cpu->peek(0x6000) == 0);
129129
}
130130
}

0 commit comments

Comments
 (0)