diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index 35d3cd5..4b0ec41 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -51,10 +51,13 @@ static void ld_rr_d16(GB_gameboy_t *gb, uint8_t opcode) { uint8_t register_id; uint16_t value; - GB_advance_cycles(gb, 12); - register_id = (GB_read_memory(gb, gb->pc++) >> 4) + 1; + GB_advance_cycles(gb, 4); + register_id = (opcode >> 4) + 1; + gb->pc++; value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); value |= GB_read_memory(gb, gb->pc++) << 8; + GB_advance_cycles(gb, 4); gb->registers[register_id] = value; } @@ -72,7 +75,8 @@ static void inc_rr(GB_gameboy_t *gb, uint8_t opcode) { uint8_t register_id; GB_advance_cycles(gb, 8); - register_id = (GB_read_memory(gb, gb->pc++) >> 4) + 1; + register_id = (opcode >> 4) + 1; + gb->pc++; gb->registers[register_id]++; } @@ -115,11 +119,12 @@ static void dec_hr(GB_gameboy_t *gb, uint8_t opcode) static void ld_hr_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t register_id; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; register_id = ((opcode >> 4) + 1) & 0x03; gb->registers[register_id] &= 0xFF; gb->registers[register_id] |= GB_read_memory(gb, gb->pc++) << 8; + GB_advance_cycles(gb, 4); } static void rlca(GB_gameboy_t *gb, uint8_t opcode) @@ -150,14 +155,20 @@ static void rla(GB_gameboy_t *gb, uint8_t opcode) } } -static void ld_da16_sp(GB_gameboy_t *gb, uint8_t opcode){ +static void ld_da16_sp(GB_gameboy_t *gb, uint8_t opcode) +{ + /* Todo: Verify order is correct */ uint16_t addr; - GB_advance_cycles(gb, 20); + GB_advance_cycles(gb, 4); gb->pc++; addr = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); addr |= GB_read_memory(gb, gb->pc++) << 8; + GB_advance_cycles(gb, 4); GB_write_memory(gb, addr, gb->registers[GB_REGISTER_SP] & 0xFF); + GB_advance_cycles(gb, 4); GB_write_memory(gb, addr+1, gb->registers[GB_REGISTER_SP] >> 8); + GB_advance_cycles(gb, 4); } static void add_hl_rr(GB_gameboy_t *gb, uint8_t opcode) @@ -197,7 +208,8 @@ static void dec_rr(GB_gameboy_t *gb, uint8_t opcode) { uint8_t register_id; GB_advance_cycles(gb, 8); - register_id = (GB_read_memory(gb, gb->pc++) >> 4) + 1; + register_id = (opcode >> 4) + 1; + gb->pc++; gb->registers[register_id]--; } @@ -206,7 +218,8 @@ static void inc_lr(GB_gameboy_t *gb, uint8_t opcode) uint8_t register_id; uint8_t value; GB_advance_cycles(gb, 4); - register_id = (GB_read_memory(gb, gb->pc++) >> 4) + 1; + register_id = (opcode >> 4) + 1; + gb->pc++; value = (gb->registers[register_id] & 0xFF) + 1; gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; @@ -226,7 +239,8 @@ static void dec_lr(GB_gameboy_t *gb, uint8_t opcode) uint8_t register_id; uint8_t value; GB_advance_cycles(gb, 4); - register_id = (GB_read_memory(gb, gb->pc++) >> 4) + 1; + register_id = (opcode >> 4) + 1; + gb->pc++; value = (gb->registers[register_id] & 0xFF) - 1; gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; @@ -246,10 +260,12 @@ static void dec_lr(GB_gameboy_t *gb, uint8_t opcode) static void ld_lr_d8(GB_gameboy_t *gb, uint8_t opcode) { uint8_t register_id; - GB_advance_cycles(gb, 8); - register_id = (GB_read_memory(gb, gb->pc++) >> 4) + 1; + GB_advance_cycles(gb, 4); + register_id = (opcode >> 4) + 1; + gb->pc++; gb->registers[register_id] &= 0xFF00; gb->registers[register_id] |= GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); } static void rrca(GB_gameboy_t *gb, uint8_t opcode) @@ -282,9 +298,11 @@ static void rra(GB_gameboy_t *gb, uint8_t opcode) static void jr_r8(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 12); + /* Todo: Verify cycles are not 8 and 4 instead */ + GB_advance_cycles(gb, 4); gb->pc++; gb->pc += (int8_t) GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 8); } static bool condition_code(GB_gameboy_t *gb, uint8_t opcode) @@ -305,9 +323,11 @@ static bool condition_code(GB_gameboy_t *gb, uint8_t opcode) static void jr_cc_r8(GB_gameboy_t *gb, uint8_t opcode) { - if (condition_code(gb, GB_read_memory(gb, gb->pc++))) { - GB_advance_cycles(gb, 12); + gb->pc++; + if (condition_code(gb, opcode)) { + GB_advance_cycles(gb, 4); gb->pc += (int8_t)GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 8); } else { GB_advance_cycles(gb, 8); @@ -395,42 +415,47 @@ static void ccf(GB_gameboy_t *gb, uint8_t opcode) static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; GB_write_memory(gb, gb->registers[GB_REGISTER_HL]++, gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); } static void ld_dhld_a(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; GB_write_memory(gb, gb->registers[GB_REGISTER_HL]--, gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); } static void ld_a_dhli(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; gb->registers[GB_REGISTER_AF] &= 0xFF; gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[GB_REGISTER_HL]++) << 8; + GB_advance_cycles(gb, 4); } static void ld_a_dhld(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; gb->registers[GB_REGISTER_AF] &= 0xFF; gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[GB_REGISTER_HL]--) << 8; + GB_advance_cycles(gb, 4); } static void inc_dhl(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]) + 1; GB_advance_cycles(gb, 4); GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value); + GB_advance_cycles(gb, 4); gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); if ((value & 0x0F) == 0) { @@ -445,11 +470,12 @@ static void inc_dhl(GB_gameboy_t *gb, uint8_t opcode) static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]) - 1; GB_advance_cycles(gb, 4); GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value); + GB_advance_cycles(gb, 4); gb->registers[GB_REGISTER_AF] &= ~( GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; @@ -464,9 +490,12 @@ static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode) static void ld_dhl_d8(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 12); + GB_advance_cycles(gb, 4); gb->pc++; - GB_write_memory(gb, gb->registers[GB_REGISTER_HL], GB_read_memory(gb, gb->pc++)); + uint8_t data = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_HL], data); + GB_advance_cycles(gb, 4); } uint8_t get_src_value(GB_gameboy_t *gb, uint8_t opcode) @@ -479,8 +508,9 @@ uint8_t get_src_value(GB_gameboy_t *gb, uint8_t opcode) if (src_low) { return gb->registers[GB_REGISTER_AF] >> 8; } + uint8_t ret = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]); GB_advance_cycles(gb, 4); - return GB_read_memory(gb, gb->registers[GB_REGISTER_HL]); + return ret; } if (src_low) { return gb->registers[src_register_id] & 0xFF; @@ -501,8 +531,8 @@ static void set_src_value(GB_gameboy_t *gb, uint8_t opcode, uint8_t value) gb->registers[GB_REGISTER_AF] |= value << 8; } else { - GB_advance_cycles(gb, 4); GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value); + GB_advance_cycles(gb, 4); } } else { @@ -529,16 +559,14 @@ static void ld_r_r(GB_gameboy_t *gb, uint8_t opcode) dst_low = opcode & 8; value = get_src_value(gb, opcode); - - if (dst_register_id == GB_REGISTER_AF) { if (dst_low) { gb->registers[GB_REGISTER_AF] &= 0xFF; gb->registers[GB_REGISTER_AF] |= value << 8; } else { - GB_advance_cycles(gb, 4); GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value); + GB_advance_cycles(gb, 4); } } else { @@ -702,11 +730,14 @@ static void halt(GB_gameboy_t *gb, uint8_t opcode) static void ret_cc(GB_gameboy_t *gb, uint8_t opcode) { + /* Todo: Verify timing */ if (condition_code(gb, GB_read_memory(gb, gb->pc++))) { GB_debugger_ret_hook(gb); - GB_advance_cycles(gb, 20); - gb->pc = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]) | - (GB_read_memory(gb, gb->registers[GB_REGISTER_SP] + 1) << 8); + GB_advance_cycles(gb, 8); + gb->pc = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]); + GB_advance_cycles(gb, 4); + gb->pc |= GB_read_memory(gb, gb->registers[GB_REGISTER_SP] + 1) << 8; + GB_advance_cycles(gb, 8); gb->registers[GB_REGISTER_SP] += 2; } else { @@ -720,10 +751,10 @@ static void pop_rr(GB_gameboy_t *gb, uint8_t opcode) GB_advance_cycles(gb, 4); register_id = ((opcode >> 4) + 1) & 3; gb->pc++; - GB_advance_cycles(gb, 4); gb->registers[register_id] = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]); GB_advance_cycles(gb, 4); gb->registers[register_id] |= GB_read_memory(gb, gb->registers[GB_REGISTER_SP] + 1) << 8; + GB_advance_cycles(gb, 4); gb->registers[GB_REGISTER_AF] &= 0xFFF0; // Make sure we don't set impossible flags on F! See Blargg's PUSH AF test. gb->registers[GB_REGISTER_SP] += 2; } @@ -796,9 +827,10 @@ 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; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = (a + value) << 8; if ((uint8_t) (a + value) == 0) { @@ -815,9 +847,10 @@ 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; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); 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; @@ -836,9 +869,10 @@ 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; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG; if (a == value) { @@ -855,9 +889,10 @@ 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; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); 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; @@ -876,9 +911,10 @@ 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; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = ((a & value) << 8) | GB_HALF_CARRY_FLAG; if ((a & value) == 0) { @@ -889,9 +925,10 @@ 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; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = (a ^ value) << 8; if ((a ^ value) == 0) { @@ -902,9 +939,10 @@ 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; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] = (a | value) << 8; if ((a | value) == 0) { @@ -915,9 +953,10 @@ 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; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; @@ -980,36 +1019,40 @@ static void call_a16(GB_gameboy_t *gb, uint8_t opcode) static void ld_da8_a(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; uint8_t temp = GB_read_memory(gb, gb->pc++); GB_advance_cycles(gb, 4); GB_write_memory(gb, 0xFF00 + temp, gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); } static void ld_a_da8(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->registers[GB_REGISTER_AF] &= 0xFF; gb->pc++; uint8_t temp = GB_read_memory(gb, gb->pc++); GB_advance_cycles(gb, 4); gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, 0xFF00 + temp) << 8; + GB_advance_cycles(gb, 4); } static void ld_dc_a(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; GB_write_memory(gb, 0xFF00 + (gb->registers[GB_REGISTER_BC] & 0xFF), gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); } static void ld_a_dc(GB_gameboy_t *gb, uint8_t opcode) { - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->registers[GB_REGISTER_AF] &= 0xFF; gb->pc++; gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, 0xFF00 + (gb->registers[GB_REGISTER_BC] & 0xFF)) << 8; + GB_advance_cycles(gb, 4); } static void add_sp_r8(GB_gameboy_t *gb, uint8_t opcode) @@ -1043,22 +1086,28 @@ 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; - GB_advance_cycles(gb, 16); + GB_advance_cycles(gb, 4); gb->pc++; addr = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); addr |= GB_read_memory(gb, gb->pc++) << 8; + GB_advance_cycles(gb, 4); GB_write_memory(gb, addr, gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); } static void ld_a_da16(GB_gameboy_t *gb, uint8_t opcode) { uint16_t addr; - GB_advance_cycles(gb, 16); + GB_advance_cycles(gb, 4); gb->registers[GB_REGISTER_AF] &= 0xFF; gb->pc++; addr = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); addr |= GB_read_memory(gb, gb->pc++) << 8 ; + GB_advance_cycles(gb, 4); gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, addr) << 8; + GB_advance_cycles(gb, 4); } static void di(GB_gameboy_t *gb, uint8_t opcode) @@ -1111,7 +1160,7 @@ static void rlc_r(GB_gameboy_t *gb, uint8_t opcode) { bool carry; uint8_t value; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = get_src_value(gb, opcode); carry = (value & 0x80) != 0; @@ -1129,7 +1178,7 @@ static void rrc_r(GB_gameboy_t *gb, uint8_t opcode) { bool carry; uint8_t value; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = get_src_value(gb, opcode); carry = (value & 0x01) != 0; @@ -1149,7 +1198,7 @@ static void rl_r(GB_gameboy_t *gb, uint8_t opcode) bool carry; uint8_t value; bool bit7; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = get_src_value(gb, opcode); carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; @@ -1172,7 +1221,7 @@ static void rr_r(GB_gameboy_t *gb, uint8_t opcode) uint8_t value; bool bit1; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = get_src_value(gb, opcode); carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; @@ -1193,7 +1242,7 @@ static void sla_r(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value; bool carry; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = get_src_value(gb, opcode); carry = (value & 0x80) != 0; @@ -1211,7 +1260,7 @@ static void sra_r(GB_gameboy_t *gb, uint8_t opcode) { uint8_t bit7; uint8_t value; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = get_src_value(gb, opcode); bit7 = value & 0x80; @@ -1229,7 +1278,7 @@ static void sra_r(GB_gameboy_t *gb, uint8_t opcode) static void srl_r(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = get_src_value(gb, opcode); gb->registers[GB_REGISTER_AF] &= 0xFF00; @@ -1245,7 +1294,7 @@ static void srl_r(GB_gameboy_t *gb, uint8_t opcode) static void swap_r(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = get_src_value(gb, opcode); gb->registers[GB_REGISTER_AF] &= 0xFF00; @@ -1259,7 +1308,7 @@ static void bit_r(GB_gameboy_t *gb, uint8_t opcode) { uint8_t value; uint8_t bit; - GB_advance_cycles(gb, 8); + GB_advance_cycles(gb, 4); gb->pc++; value = get_src_value(gb, opcode); bit = 1 << ((opcode >> 3) & 7); @@ -1280,6 +1329,7 @@ static void bit_r(GB_gameboy_t *gb, uint8_t opcode) static void cb_prefix(GB_gameboy_t *gb, uint8_t opcode) { + GB_advance_cycles(gb, 4); opcode = GB_read_memory(gb, ++gb->pc); switch (opcode >> 3) { case 0: