From 2c6f7906c5d19897ca3c15b0b749ca4832e1a404 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 14 Apr 2018 15:32:55 +0300 Subject: [PATCH] Make multi-byte opcodes trigger the OAM bug when they increase PC --- Core/z80_cpu.c | 92 ++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 52 deletions(-) diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index 90f935a..78fa3ff 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -82,7 +82,7 @@ static void flush_pending_cycles(GB_gameboy_t *gb) gb->pending_cycles = 0; } -/* Todo: all multi-byte opcodes probably trigger the OAM bug when they increase pc */ +/* Todo: test if multi-byte opcodes trigger the OAM bug correctly */ static void ill(GB_gameboy_t *gb, uint8_t opcode) { @@ -110,6 +110,8 @@ static void stop(GB_gameboy_t *gb, uint8_t opcode) else { gb->stopped = true; } + + /* Todo: is PC being actually read? */ gb->pc++; } @@ -129,8 +131,8 @@ static void ld_rr_d16(GB_gameboy_t *gb, uint8_t opcode) uint8_t register_id; uint16_t value; register_id = (opcode >> 4) + 1; - value = cycle_read(gb, gb->pc++); - value |= cycle_read(gb, gb->pc++) << 8; + value = cycle_read_inc_oam_bug(gb, gb->pc++); + value |= cycle_read_inc_oam_bug(gb, gb->pc++) << 8; gb->registers[register_id] = value; } @@ -185,7 +187,7 @@ static void ld_hr_d8(GB_gameboy_t *gb, uint8_t opcode) uint8_t register_id; register_id = ((opcode >> 4) + 1) & 0x03; gb->registers[register_id] &= 0xFF; - gb->registers[register_id] |= cycle_read(gb, gb->pc++) << 8; + gb->registers[register_id] |= cycle_read_inc_oam_bug(gb, gb->pc++) << 8; } static void rlca(GB_gameboy_t *gb, uint8_t opcode) @@ -216,8 +218,8 @@ static void ld_da16_sp(GB_gameboy_t *gb, uint8_t opcode) { /* Todo: Verify order is correct */ uint16_t addr; - addr = cycle_read(gb, gb->pc++); - addr |= cycle_read(gb, gb->pc++) << 8; + addr = cycle_read_inc_oam_bug(gb, gb->pc++); + addr |= cycle_read_inc_oam_bug(gb, gb->pc++) << 8; cycle_write(gb, addr, gb->registers[GB_REGISTER_SP] & 0xFF); cycle_write(gb, addr+1, gb->registers[GB_REGISTER_SP] >> 8); } @@ -303,7 +305,7 @@ static void ld_lr_d8(GB_gameboy_t *gb, uint8_t opcode) uint8_t register_id; register_id = (opcode >> 4) + 1; gb->registers[register_id] &= 0xFF00; - gb->registers[register_id] |= cycle_read(gb, gb->pc++); + gb->registers[register_id] |= cycle_read_inc_oam_bug(gb, gb->pc++); } static void rrca(GB_gameboy_t *gb, uint8_t opcode) @@ -333,7 +335,7 @@ static void rra(GB_gameboy_t *gb, uint8_t opcode) static void jr_r8(GB_gameboy_t *gb, uint8_t opcode) { /* Todo: Verify timing */ - gb->pc += (int8_t)cycle_read(gb, gb->pc) + 1; + gb->pc += (int8_t)cycle_read_inc_oam_bug(gb, gb->pc) + 1; cycle_no_access(gb); } @@ -355,13 +357,11 @@ static bool condition_code(GB_gameboy_t *gb, uint8_t opcode) static void jr_cc_r8(GB_gameboy_t *gb, uint8_t opcode) { + int8_t offset = cycle_read_inc_oam_bug(gb, gb->pc++); if (condition_code(gb, opcode)) { - gb->pc += (int8_t)cycle_read(gb, gb->pc) + 1; + gb->pc += offset; + cycle_no_access(gb); } - else { - gb->pc += 1; - } - cycle_no_access(gb); } static void daa(GB_gameboy_t *gb, uint8_t opcode) @@ -491,7 +491,7 @@ static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode) static void ld_dhl_d8(GB_gameboy_t *gb, uint8_t opcode) { - uint8_t data = cycle_read(gb, gb->pc++); + uint8_t data = cycle_read_inc_oam_bug(gb, gb->pc++); cycle_write(gb, gb->registers[GB_REGISTER_HL], data); } @@ -718,24 +718,18 @@ static void pop_rr(GB_gameboy_t *gb, uint8_t opcode) static void jp_cc_a16(GB_gameboy_t *gb, uint8_t opcode) { + uint16_t addr = cycle_read_inc_oam_bug(gb, gb->pc++); + addr |= (cycle_read_inc_oam_bug(gb, gb->pc++) << 8); if (condition_code(gb, opcode)) { - uint16_t addr = cycle_read(gb, gb->pc); - addr |= (cycle_read(gb, gb->pc + 1) << 8); cycle_no_access(gb); gb->pc = addr; - - } - else { - cycle_no_access(gb); - cycle_no_access(gb); - gb->pc += 2; } } static void jp_a16(GB_gameboy_t *gb, uint8_t opcode) { - uint16_t addr = cycle_read(gb, gb->pc); - addr |= (cycle_read(gb, gb->pc + 1) << 8); + uint16_t addr = cycle_read_inc_oam_bug(gb, gb->pc); + addr |= (cycle_read_inc_oam_bug(gb, gb->pc + 1) << 8); cycle_no_access(gb); gb->pc = addr; @@ -744,9 +738,9 @@ static void jp_a16(GB_gameboy_t *gb, uint8_t opcode) static void call_cc_a16(GB_gameboy_t *gb, uint8_t opcode) { uint16_t call_addr = gb->pc - 1; + uint16_t addr = cycle_read_inc_oam_bug(gb, gb->pc++); + addr |= (cycle_read_inc_oam_bug(gb, gb->pc++) << 8); if (condition_code(gb, opcode)) { - uint16_t addr = cycle_read(gb, gb->pc++); - addr |= (cycle_read(gb, gb->pc++) << 8); cycle_oam_bug(gb, GB_REGISTER_SP); cycle_write(gb, --gb->registers[GB_REGISTER_SP], (gb->pc) >> 8); cycle_write(gb, --gb->registers[GB_REGISTER_SP], (gb->pc) & 0xFF); @@ -754,11 +748,6 @@ static void call_cc_a16(GB_gameboy_t *gb, uint8_t opcode) GB_debugger_call_hook(gb, call_addr); } - else { - cycle_no_access(gb); - cycle_no_access(gb); - gb->pc += 2; - } } static void push_rr(GB_gameboy_t *gb, uint8_t opcode) @@ -773,7 +762,7 @@ static void push_rr(GB_gameboy_t *gb, uint8_t opcode) static void add_a_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value, a; - value = cycle_read(gb, gb->pc++); + value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = (a + value) << 8; if ((uint8_t) (a + value) == 0) { @@ -790,7 +779,7 @@ static void add_a_d8(GB_gameboy_t *gb, uint8_t opcode) static void adc_a_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value, a, carry; - value = cycle_read(gb, gb->pc++); + value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; gb->registers[GB_REGISTER_AF] = (a + value + carry) << 8; @@ -809,7 +798,7 @@ static void adc_a_d8(GB_gameboy_t *gb, uint8_t opcode) static void sub_a_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value, a; - value = cycle_read(gb, gb->pc++); + value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG; if (a == value) { @@ -826,7 +815,7 @@ static void sub_a_d8(GB_gameboy_t *gb, uint8_t opcode) static void sbc_a_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value, a, carry; - value = cycle_read(gb, gb->pc++); + value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBSTRACT_FLAG; @@ -845,7 +834,7 @@ static void sbc_a_d8(GB_gameboy_t *gb, uint8_t opcode) static void and_a_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value, a; - value = cycle_read(gb, gb->pc++); + value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = ((a & value) << 8) | GB_HALF_CARRY_FLAG; if ((a & value) == 0) { @@ -856,7 +845,7 @@ static void and_a_d8(GB_gameboy_t *gb, uint8_t opcode) static void xor_a_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value, a; - value = cycle_read(gb, gb->pc++); + value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = (a ^ value) << 8; if ((a ^ value) == 0) { @@ -867,7 +856,7 @@ static void xor_a_d8(GB_gameboy_t *gb, uint8_t opcode) static void or_a_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value, a; - value = cycle_read(gb, gb->pc++); + value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = (a | value) << 8; if ((a | value) == 0) { @@ -878,7 +867,7 @@ static void or_a_d8(GB_gameboy_t *gb, uint8_t opcode) static void cp_a_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value, a; - value = cycle_read(gb, gb->pc++); + value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; @@ -931,8 +920,8 @@ static void ret_cc(GB_gameboy_t *gb, uint8_t opcode) static void call_a16(GB_gameboy_t *gb, uint8_t opcode) { uint16_t call_addr = gb->pc - 1; - uint16_t addr = cycle_read(gb, gb->pc++); - addr |= (cycle_read(gb, gb->pc++) << 8); + uint16_t addr = cycle_read_inc_oam_bug(gb, gb->pc++); + addr |= (cycle_read_inc_oam_bug(gb, gb->pc++) << 8); cycle_oam_bug(gb, GB_REGISTER_SP); cycle_write(gb, --gb->registers[GB_REGISTER_SP], (gb->pc) >> 8); cycle_write(gb, --gb->registers[GB_REGISTER_SP], (gb->pc) & 0xFF); @@ -942,14 +931,14 @@ static void call_a16(GB_gameboy_t *gb, uint8_t opcode) static void ld_da8_a(GB_gameboy_t *gb, uint8_t opcode) { - uint8_t temp = cycle_read(gb, gb->pc++); + uint8_t temp = cycle_read_inc_oam_bug(gb, gb->pc++); cycle_write(gb, 0xFF00 + temp, gb->registers[GB_REGISTER_AF] >> 8); } static void ld_a_da8(GB_gameboy_t *gb, uint8_t opcode) { gb->registers[GB_REGISTER_AF] &= 0xFF; - uint8_t temp = cycle_read(gb, gb->pc++); + uint8_t temp = cycle_read_inc_oam_bug(gb, gb->pc++); gb->registers[GB_REGISTER_AF] |= cycle_read(gb, 0xFF00 + temp) << 8; } @@ -968,7 +957,7 @@ static void add_sp_r8(GB_gameboy_t *gb, uint8_t opcode) { int16_t offset; uint16_t sp = gb->registers[GB_REGISTER_SP]; - offset = (int8_t) cycle_read(gb, gb->pc++); + offset = (int8_t) cycle_read_inc_oam_bug(gb, gb->pc++); cycle_no_access(gb); cycle_no_access(gb); gb->registers[GB_REGISTER_SP] += offset; @@ -993,8 +982,8 @@ static void jp_hl(GB_gameboy_t *gb, uint8_t opcode) static void ld_da16_a(GB_gameboy_t *gb, uint8_t opcode) { uint16_t addr; - addr = cycle_read(gb, gb->pc++); - addr |= cycle_read(gb, gb->pc++) << 8; + addr = cycle_read_inc_oam_bug(gb, gb->pc++); + addr |= cycle_read_inc_oam_bug(gb, gb->pc++) << 8; cycle_write(gb, addr, gb->registers[GB_REGISTER_AF] >> 8); } @@ -1002,8 +991,8 @@ static void ld_a_da16(GB_gameboy_t *gb, uint8_t opcode) { uint16_t addr; gb->registers[GB_REGISTER_AF] &= 0xFF; - addr = cycle_read(gb, gb->pc++); - addr |= cycle_read(gb, gb->pc++) << 8 ; + addr = cycle_read_inc_oam_bug(gb, gb->pc++); + addr |= cycle_read_inc_oam_bug(gb, gb->pc++) << 8 ; gb->registers[GB_REGISTER_AF] |= cycle_read(gb, addr) << 8; } @@ -1026,7 +1015,7 @@ static void ld_hl_sp_r8(GB_gameboy_t *gb, uint8_t opcode) { int16_t offset; gb->registers[GB_REGISTER_AF] &= 0xFF00; - offset = (int8_t) cycle_read(gb, gb->pc++); + offset = (int8_t) cycle_read_inc_oam_bug(gb, gb->pc++); cycle_no_access(gb); gb->registers[GB_REGISTER_HL] = gb->registers[GB_REGISTER_SP] + offset; @@ -1200,7 +1189,7 @@ static void bit_r(GB_gameboy_t *gb, uint8_t opcode) static void cb_prefix(GB_gameboy_t *gb, uint8_t opcode) { - opcode = cycle_read(gb, gb->pc++); + opcode = cycle_read_inc_oam_bug(gb, gb->pc++); switch (opcode >> 3) { case 0: rlc_r(gb, opcode); @@ -1334,8 +1323,7 @@ void GB_cpu_run(GB_gameboy_t *gb) } /* Run mode */ else if(!gb->halted) { - GB_trigger_oam_bug_read_increase(gb, gb->pc); /* Todo: test T-cycle timing */ - gb->last_opcode_read = cycle_read(gb, gb->pc++); + gb->last_opcode_read = cycle_read_inc_oam_bug(gb, gb->pc++); if (gb->halt_bug) { gb->pc--; gb->halt_bug = false;