Merge branch 'master' into rateless_apu

This commit is contained in:
Lior Halphon 2016-09-20 20:05:03 +03:00
commit f88c9d299b
6 changed files with 71 additions and 102 deletions

View File

@ -1185,6 +1185,21 @@ static bool backtrace(GB_gameboy_t *gb, char *arguments, const debugger_command_
return true; return true;
} }
static bool ticks(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command)
{
STOPPED_ONLY
if (strlen(lstrip(arguments))) {
print_usage(gb, command);
return true;
}
GB_log(gb, "Ticks: %lu. (Resetting)\n", gb->debugger_ticks);
gb->debugger_ticks = 0;
return true;
}
static bool help(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command); static bool help(GB_gameboy_t *gb, char *arguments, const debugger_command_t *command);
#define HELP_NEWLINE "\n " #define HELP_NEWLINE "\n "
@ -1198,6 +1213,7 @@ static const debugger_command_t commands[] = {
{"backtrace", 2, backtrace, "Display the current call stack"}, {"backtrace", 2, backtrace, "Display the current call stack"},
{"bt", 2, }, /* Alias */ {"bt", 2, }, /* Alias */
{"sld", 3, stack_leak_detection, "Like finish, but stops if a stack leak is detected. (Experimental)"}, {"sld", 3, stack_leak_detection, "Like finish, but stops if a stack leak is detected. (Experimental)"},
{"ticks", 2, ticks, "Display the number of CPU ticks since the last time 'ticks' was used. "},
{"registers", 1, registers, "Print values of processor registers and other important registers"}, {"registers", 1, registers, "Print values of processor registers and other important registers"},
{"cartridge", 2, mbc, "Displays information about the MBC and cartridge"}, {"cartridge", 2, mbc, "Displays information about the MBC and cartridge"},
{"mbc", 3, }, /* Alias */ {"mbc", 3, }, /* Alias */

View File

@ -45,7 +45,22 @@ static uint32_t get_pixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
uint8_t lowest_sprite_x = 0xFF; uint8_t lowest_sprite_x = 0xFF;
bool use_obp1 = false, priority = false; bool use_obp1 = false, priority = false;
bool in_window = false; bool in_window = false;
if (gb->effective_window_enabled && (gb->io_registers[GB_IO_LCDC] & 0x20)) { /* Window Enabled */ bool window_enabled = (gb->io_registers[GB_IO_LCDC] & 0x20);
bool bg_enabled = true;
bool bg_behind = false;
if ((gb->io_registers[GB_IO_LCDC] & 0x1) == 0) {
if (gb->cgb_mode) {
bg_behind = true;
}
else if (gb->is_cgb) { /* CGB in DMG mode*/
bg_enabled = window_enabled = false;
}
else {
/* DMG */
bg_enabled = false;
}
}
if (gb->effective_window_enabled && window_enabled) { /* Window Enabled */
if (y >= gb->effective_window_y && x + 7 >= gb->io_registers[GB_IO_WX]) { if (y >= gb->effective_window_y && x + 7 >= gb->io_registers[GB_IO_WX]) {
in_window = true; in_window = true;
} }
@ -118,7 +133,7 @@ static uint32_t get_pixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
} }
if (attributes & 0x80) { if (attributes & 0x80) {
priority = true; priority = !bg_behind && bg_enabled;
} }
if (!priority && sprite_pixel) { if (!priority && sprite_pixel) {
@ -129,6 +144,10 @@ static uint32_t get_pixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
return gb->sprite_palletes_rgb[sprite_palette * 4 + sprite_pixel]; return gb->sprite_palletes_rgb[sprite_palette * 4 + sprite_pixel];
} }
if (!bg_enabled) {
return gb->background_palletes_rgb[0];
}
if (gb->io_registers[GB_IO_LCDC] & 0x10) { if (gb->io_registers[GB_IO_LCDC] & 0x10) {
tile_address = tile * 0x10; tile_address = tile * 0x10;
} }
@ -278,10 +297,10 @@ void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index
Todo: Mode lengths are not constants, see http://blog.kevtris.org/blogfiles/Nitty%20Gritty%20Gameboy%20VRAM%20Timing.txt Todo: Mode lengths are not constants, see http://blog.kevtris.org/blogfiles/Nitty%20Gritty%20Gameboy%20VRAM%20Timing.txt
*/ */
#define MODE2_LENGTH 80 #define MODE2_LENGTH (80)
#define MODE3_LENGTH 172 #define MODE3_LENGTH (172)
#define MODE1_LENGTH 204 #define MODE0_LENGTH (204)
#define LINE_LENGTH (MODE2_LENGTH + MODE3_LENGTH + MODE1_LENGTH) // = 456 #define LINE_LENGTH (MODE2_LENGTH + MODE3_LENGTH + MODE0_LENGTH) // = 456
void GB_display_run(GB_gameboy_t *gb) void GB_display_run(GB_gameboy_t *gb)
{ {

View File

@ -409,6 +409,9 @@ typedef struct GB_gameboy_s {
GB_symbol_map_t *bank_symbols[0x200]; GB_symbol_map_t *bank_symbols[0x200];
GB_reversed_symbol_map_t reversed_symbol_map; GB_reversed_symbol_map_t reversed_symbol_map;
/* Ticks command */
unsigned long debugger_ticks;
/* Misc */ /* Misc */
bool turbo; bool turbo;
bool turbo_dont_skip; bool turbo_dont_skip;

View File

@ -53,6 +53,8 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
} }
} }
gb->debugger_ticks += cycles;
if (gb->cgb_double_speed) { if (gb->cgb_double_speed) {
cycles >>=1; cycles >>=1;
} }

View File

@ -19,7 +19,6 @@ static void ill(GB_gameboy_t *gb, uint8_t opcode)
static void nop(GB_gameboy_t *gb, uint8_t opcode) static void nop(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
} }
static void stop(GB_gameboy_t *gb, uint8_t opcode) static void stop(GB_gameboy_t *gb, uint8_t opcode)
@ -33,7 +32,6 @@ static void stop(GB_gameboy_t *gb, uint8_t opcode)
else { else {
gb->stopped = true; gb->stopped = true;
} }
gb->pc++;
} }
/* Operand naming conventions for functions: /* Operand naming conventions for functions:
@ -53,7 +51,6 @@ static void ld_rr_d16(GB_gameboy_t *gb, uint8_t opcode)
uint16_t value; uint16_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
gb->pc++;
value = GB_read_memory(gb, gb->pc++); value = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
value |= GB_read_memory(gb, gb->pc++) << 8; value |= GB_read_memory(gb, gb->pc++) << 8;
@ -66,7 +63,6 @@ static void ld_drr_a(GB_gameboy_t *gb, uint8_t opcode)
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
gb->pc++;
GB_write_memory(gb, gb->registers[register_id], gb->registers[GB_REGISTER_AF] >> 8); GB_write_memory(gb, gb->registers[register_id], gb->registers[GB_REGISTER_AF] >> 8);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
} }
@ -76,7 +72,6 @@ static void inc_rr(GB_gameboy_t *gb, uint8_t opcode)
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
gb->pc++;
gb->registers[register_id]++; gb->registers[register_id]++;
} }
@ -84,7 +79,6 @@ static void inc_hr(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
register_id = ((opcode >> 4) + 1) & 0x03; register_id = ((opcode >> 4) + 1) & 0x03;
gb->registers[register_id] += 0x100; gb->registers[register_id] += 0x100;
gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG);
@ -101,7 +95,6 @@ static void dec_hr(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
register_id = ((opcode >> 4) + 1) & 0x03; register_id = ((opcode >> 4) + 1) & 0x03;
gb->registers[register_id] -= 0x100; gb->registers[register_id] -= 0x100;
gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG);
@ -120,7 +113,6 @@ static void ld_hr_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
register_id = ((opcode >> 4) + 1) & 0x03; register_id = ((opcode >> 4) + 1) & 0x03;
gb->registers[register_id] &= 0xFF; gb->registers[register_id] &= 0xFF;
gb->registers[register_id] |= GB_read_memory(gb, gb->pc++) << 8; gb->registers[register_id] |= GB_read_memory(gb, gb->pc++) << 8;
@ -132,7 +124,6 @@ static void rlca(GB_gameboy_t *gb, uint8_t opcode)
bool carry = (gb->registers[GB_REGISTER_AF] & 0x8000) != 0; bool carry = (gb->registers[GB_REGISTER_AF] & 0x8000) != 0;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] & 0xFF00) << 1; gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] & 0xFF00) << 1;
if (carry) { if (carry) {
gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG | 0x0100; gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG | 0x0100;
@ -145,7 +136,6 @@ static void rla(GB_gameboy_t *gb, uint8_t opcode)
bool carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; bool carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] & 0xFF00) << 1; gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] & 0xFF00) << 1;
if (carry) { if (carry) {
gb->registers[GB_REGISTER_AF] |= 0x0100; gb->registers[GB_REGISTER_AF] |= 0x0100;
@ -160,7 +150,6 @@ static void ld_da16_sp(GB_gameboy_t *gb, uint8_t opcode)
/* Todo: Verify order is correct */ /* Todo: Verify order is correct */
uint16_t addr; uint16_t addr;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
addr = GB_read_memory(gb, gb->pc++); addr = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
addr |= GB_read_memory(gb, gb->pc++) << 8; addr |= GB_read_memory(gb, gb->pc++) << 8;
@ -177,7 +166,6 @@ static void add_hl_rr(GB_gameboy_t *gb, uint8_t opcode)
uint16_t rr; uint16_t rr;
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
gb->pc++;
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
rr = gb->registers[register_id]; rr = gb->registers[register_id];
gb->registers[GB_REGISTER_HL] = hl + rr; gb->registers[GB_REGISTER_HL] = hl + rr;
@ -198,7 +186,6 @@ static void ld_a_drr(GB_gameboy_t *gb, uint8_t opcode)
uint8_t register_id; uint8_t register_id;
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] &= 0xFF; gb->registers[GB_REGISTER_AF] &= 0xFF;
gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[register_id]) << 8; gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[register_id]) << 8;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
@ -209,7 +196,6 @@ static void dec_rr(GB_gameboy_t *gb, uint8_t opcode)
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
gb->pc++;
gb->registers[register_id]--; gb->registers[register_id]--;
} }
@ -219,7 +205,6 @@ static void inc_lr(GB_gameboy_t *gb, uint8_t opcode)
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
gb->pc++;
value = (gb->registers[register_id] & 0xFF) + 1; value = (gb->registers[register_id] & 0xFF) + 1;
gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value;
@ -240,7 +225,6 @@ static void dec_lr(GB_gameboy_t *gb, uint8_t opcode)
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
gb->pc++;
value = (gb->registers[register_id] & 0xFF) - 1; value = (gb->registers[register_id] & 0xFF) - 1;
gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value;
@ -262,7 +246,6 @@ static void ld_lr_d8(GB_gameboy_t *gb, uint8_t opcode)
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
register_id = (opcode >> 4) + 1; register_id = (opcode >> 4) + 1;
gb->pc++;
gb->registers[register_id] &= 0xFF00; gb->registers[register_id] &= 0xFF00;
gb->registers[register_id] |= GB_read_memory(gb, gb->pc++); gb->registers[register_id] |= GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
@ -273,7 +256,6 @@ static void rrca(GB_gameboy_t *gb, uint8_t opcode)
bool carry = (gb->registers[GB_REGISTER_AF] & 0x100) != 0; bool carry = (gb->registers[GB_REGISTER_AF] & 0x100) != 0;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] >> 1) & 0xFF00; gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] >> 1) & 0xFF00;
if (carry) { if (carry) {
gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG | 0x8000; gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG | 0x8000;
@ -286,7 +268,6 @@ static void rra(GB_gameboy_t *gb, uint8_t opcode)
bool carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; bool carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] >> 1) & 0xFF00; gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] >> 1) & 0xFF00;
if (carry) { if (carry) {
gb->registers[GB_REGISTER_AF] |= 0x8000; gb->registers[GB_REGISTER_AF] |= 0x8000;
@ -300,7 +281,6 @@ static void jr_r8(GB_gameboy_t *gb, uint8_t opcode)
{ {
/* Todo: Verify cycles are not 8 and 4 instead */ /* Todo: Verify cycles are not 8 and 4 instead */
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->pc += (int8_t) GB_read_memory(gb, gb->pc++); gb->pc += (int8_t) GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
} }
@ -323,7 +303,6 @@ static bool condition_code(GB_gameboy_t *gb, uint8_t opcode)
static void jr_cc_r8(GB_gameboy_t *gb, uint8_t opcode) static void jr_cc_r8(GB_gameboy_t *gb, uint8_t opcode)
{ {
gb->pc++;
if (condition_code(gb, opcode)) { if (condition_code(gb, opcode)) {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc += (int8_t)GB_read_memory(gb, gb->pc++); gb->pc += (int8_t)GB_read_memory(gb, gb->pc++);
@ -340,7 +319,6 @@ static void daa(GB_gameboy_t *gb, uint8_t opcode)
/* This function is UGLY and UNREADABLE! But it passes Blargg's daa test! */ /* This function is UGLY and UNREADABLE! But it passes Blargg's daa test! */
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->registers[GB_REGISTER_AF] &= ~GB_ZERO_FLAG; gb->registers[GB_REGISTER_AF] &= ~GB_ZERO_FLAG;
gb->pc++;
if (gb->registers[GB_REGISTER_AF] & GB_SUBSTRACT_FLAG) { if (gb->registers[GB_REGISTER_AF] & GB_SUBSTRACT_FLAG) {
if (gb->registers[GB_REGISTER_AF] & GB_HALF_CARRY_FLAG) { if (gb->registers[GB_REGISTER_AF] & GB_HALF_CARRY_FLAG) {
gb->registers[GB_REGISTER_AF] &= ~GB_HALF_CARRY_FLAG; gb->registers[GB_REGISTER_AF] &= ~GB_HALF_CARRY_FLAG;
@ -392,7 +370,6 @@ static void daa(GB_gameboy_t *gb, uint8_t opcode)
static void cpl(GB_gameboy_t *gb, uint8_t opcode) static void cpl(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] ^= 0xFF00; gb->registers[GB_REGISTER_AF] ^= 0xFF00;
gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG;
} }
@ -400,7 +377,6 @@ static void cpl(GB_gameboy_t *gb, uint8_t opcode)
static void scf(GB_gameboy_t *gb, uint8_t opcode) static void scf(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG;
gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG);
} }
@ -408,7 +384,6 @@ static void scf(GB_gameboy_t *gb, uint8_t opcode)
static void ccf(GB_gameboy_t *gb, uint8_t opcode) static void ccf(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] ^= GB_CARRY_FLAG; gb->registers[GB_REGISTER_AF] ^= GB_CARRY_FLAG;
gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG); gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG);
} }
@ -416,7 +391,6 @@ static void ccf(GB_gameboy_t *gb, uint8_t opcode)
static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode) static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
GB_write_memory(gb, gb->registers[GB_REGISTER_HL]++, gb->registers[GB_REGISTER_AF] >> 8); GB_write_memory(gb, gb->registers[GB_REGISTER_HL]++, gb->registers[GB_REGISTER_AF] >> 8);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
} }
@ -424,7 +398,6 @@ static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode)
static void ld_dhld_a(GB_gameboy_t *gb, uint8_t opcode) static void ld_dhld_a(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
GB_write_memory(gb, gb->registers[GB_REGISTER_HL]--, gb->registers[GB_REGISTER_AF] >> 8); GB_write_memory(gb, gb->registers[GB_REGISTER_HL]--, gb->registers[GB_REGISTER_AF] >> 8);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
} }
@ -432,7 +405,6 @@ static void ld_dhld_a(GB_gameboy_t *gb, uint8_t opcode)
static void ld_a_dhli(GB_gameboy_t *gb, uint8_t opcode) static void ld_a_dhli(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] &= 0xFF; gb->registers[GB_REGISTER_AF] &= 0xFF;
gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[GB_REGISTER_HL]++) << 8; gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[GB_REGISTER_HL]++) << 8;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
@ -441,7 +413,6 @@ static void ld_a_dhli(GB_gameboy_t *gb, uint8_t opcode)
static void ld_a_dhld(GB_gameboy_t *gb, uint8_t opcode) static void ld_a_dhld(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] &= 0xFF; gb->registers[GB_REGISTER_AF] &= 0xFF;
gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[GB_REGISTER_HL]--) << 8; gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[GB_REGISTER_HL]--) << 8;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
@ -451,7 +422,6 @@ static void inc_dhl(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]) + 1; value = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]) + 1;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value); GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value);
@ -471,7 +441,6 @@ static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]) - 1; value = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]) - 1;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value); GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value);
@ -491,7 +460,6 @@ static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode)
static void ld_dhl_d8(GB_gameboy_t *gb, uint8_t opcode) static void ld_dhl_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
uint8_t data = GB_read_memory(gb, gb->pc++); uint8_t data = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
GB_write_memory(gb, gb->registers[GB_REGISTER_HL], data); GB_write_memory(gb, gb->registers[GB_REGISTER_HL], data);
@ -553,7 +521,6 @@ static void ld_r_r(GB_gameboy_t *gb, uint8_t opcode)
uint8_t dst_low; uint8_t dst_low;
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
dst_register_id = ((opcode >> 4) + 1) & 3; dst_register_id = ((opcode >> 4) + 1) & 3;
dst_low = opcode & 8; dst_low = opcode & 8;
@ -586,7 +553,6 @@ static void add_a_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] = (a + value) << 8; gb->registers[GB_REGISTER_AF] = (a + value) << 8;
@ -605,7 +571,6 @@ static void adc_a_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a, carry; uint8_t value, a, carry;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0;
@ -626,7 +591,6 @@ static void sub_a_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG; gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG;
@ -645,7 +609,6 @@ static void sbc_a_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a, carry; uint8_t value, a, carry;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0;
@ -666,7 +629,6 @@ static void and_a_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] = ((a & value) << 8) | GB_HALF_CARRY_FLAG; gb->registers[GB_REGISTER_AF] = ((a & value) << 8) | GB_HALF_CARRY_FLAG;
@ -679,7 +641,6 @@ static void xor_a_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] = (a ^ value) << 8; gb->registers[GB_REGISTER_AF] = (a ^ value) << 8;
@ -692,7 +653,6 @@ static void or_a_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] = (a | value) << 8; gb->registers[GB_REGISTER_AF] = (a | value) << 8;
@ -705,7 +665,6 @@ static void cp_a_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
@ -725,13 +684,12 @@ static void halt(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->halted = true; gb->halted = true;
gb->pc++;
} }
static void ret_cc(GB_gameboy_t *gb, uint8_t opcode) static void ret_cc(GB_gameboy_t *gb, uint8_t opcode)
{ {
/* Todo: Verify timing */ /* Todo: Verify timing */
if (condition_code(gb, GB_read_memory(gb, gb->pc++))) { if (condition_code(gb, opcode)) {
GB_debugger_ret_hook(gb); GB_debugger_ret_hook(gb);
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
gb->pc = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]); gb->pc = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]);
@ -750,7 +708,6 @@ static void pop_rr(GB_gameboy_t *gb, uint8_t opcode)
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
register_id = ((opcode >> 4) + 1) & 3; register_id = ((opcode >> 4) + 1) & 3;
gb->pc++;
gb->registers[register_id] = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]); gb->registers[register_id] = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->registers[register_id] |= GB_read_memory(gb, gb->registers[GB_REGISTER_SP] + 1) << 8; gb->registers[register_id] |= GB_read_memory(gb, gb->registers[GB_REGISTER_SP] + 1) << 8;
@ -761,7 +718,6 @@ static void pop_rr(GB_gameboy_t *gb, uint8_t opcode)
static void jp_cc_a16(GB_gameboy_t *gb, uint8_t opcode) static void jp_cc_a16(GB_gameboy_t *gb, uint8_t opcode)
{ {
gb->pc++;
if (condition_code(gb, opcode)) { if (condition_code(gb, opcode)) {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
uint16_t addr = GB_read_memory(gb, gb->pc); uint16_t addr = GB_read_memory(gb, gb->pc);
@ -779,7 +735,6 @@ static void jp_cc_a16(GB_gameboy_t *gb, uint8_t opcode)
static void jp_a16(GB_gameboy_t *gb, uint8_t opcode) static void jp_a16(GB_gameboy_t *gb, uint8_t opcode)
{ {
gb->pc++;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
uint16_t addr = GB_read_memory(gb, gb->pc); uint16_t addr = GB_read_memory(gb, gb->pc);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
@ -789,18 +744,17 @@ static void jp_a16(GB_gameboy_t *gb, uint8_t opcode)
static void call_cc_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; uint16_t call_addr = gb->pc - 1;
gb->pc++;
if (condition_code(gb, opcode)) { if (condition_code(gb, opcode)) {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->registers[GB_REGISTER_SP] -= 2; gb->registers[GB_REGISTER_SP] -= 2;
uint16_t addr = GB_read_memory(gb, gb->pc); uint16_t addr = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
addr |= (GB_read_memory(gb, gb->pc + 1) << 8); addr |= (GB_read_memory(gb, gb->pc++) << 8);
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc + 2) >> 8); GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc) >> 8);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->pc + 2) & 0xFF); GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->pc) & 0xFF);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc = addr; gb->pc = addr;
@ -816,7 +770,6 @@ static void push_rr(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t register_id; uint8_t register_id;
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
gb->pc++;
register_id = ((opcode >> 4) + 1) & 3; register_id = ((opcode >> 4) + 1) & 3;
gb->registers[GB_REGISTER_SP] -= 2; gb->registers[GB_REGISTER_SP] -= 2;
GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->registers[register_id]) >> 8); GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->registers[register_id]) >> 8);
@ -829,7 +782,6 @@ static void add_a_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->pc++); value = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
@ -849,7 +801,6 @@ static void adc_a_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a, carry; uint8_t value, a, carry;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->pc++); value = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
@ -871,7 +822,6 @@ static void sub_a_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->pc++); value = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
@ -891,7 +841,6 @@ static void sbc_a_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a, carry; uint8_t value, a, carry;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->pc++); value = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
@ -913,7 +862,6 @@ static void and_a_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->pc++); value = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
@ -927,7 +875,6 @@ static void xor_a_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->pc++); value = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
@ -941,7 +888,6 @@ static void or_a_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->pc++); value = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
@ -955,7 +901,6 @@ static void cp_a_d8(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value, a; uint8_t value, a;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = GB_read_memory(gb, gb->pc++); value = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
a = gb->registers[GB_REGISTER_AF] >> 8; a = gb->registers[GB_REGISTER_AF] >> 8;
@ -974,12 +919,12 @@ static void cp_a_d8(GB_gameboy_t *gb, uint8_t opcode)
static void rst(GB_gameboy_t *gb, uint8_t opcode) static void rst(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint16_t call_addr = gb->pc; uint16_t call_addr = gb->pc - 1;
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
gb->registers[GB_REGISTER_SP] -= 2; gb->registers[GB_REGISTER_SP] -= 2;
GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc + 1) >> 8); GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc) >> 8);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->pc + 1) & 0xFF); GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->pc) & 0xFF);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc = opcode ^ 0xC7; gb->pc = opcode ^ 0xC7;
GB_debugger_call_hook(gb, call_addr); GB_debugger_call_hook(gb, call_addr);
@ -1004,17 +949,16 @@ static void reti(GB_gameboy_t *gb, uint8_t opcode)
static void call_a16(GB_gameboy_t *gb, uint8_t opcode) static void call_a16(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint16_t call_addr = gb->pc; uint16_t call_addr = gb->pc - 1;
gb->pc++;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->registers[GB_REGISTER_SP] -= 2; gb->registers[GB_REGISTER_SP] -= 2;
uint16_t addr = GB_read_memory(gb, gb->pc); uint16_t addr = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
addr |= (GB_read_memory(gb, gb->pc + 1) << 8); addr |= (GB_read_memory(gb, gb->pc++) << 8);
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc + 2) >> 8); GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc) >> 8);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->pc + 2) & 0xFF); GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->pc) & 0xFF);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc = addr; gb->pc = addr;
GB_debugger_call_hook(gb, call_addr); GB_debugger_call_hook(gb, call_addr);
@ -1023,7 +967,6 @@ static void call_a16(GB_gameboy_t *gb, uint8_t opcode)
static void ld_da8_a(GB_gameboy_t *gb, uint8_t opcode) static void ld_da8_a(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
uint8_t temp = GB_read_memory(gb, gb->pc++); uint8_t temp = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
GB_write_memory(gb, 0xFF00 + temp, gb->registers[GB_REGISTER_AF] >> 8); GB_write_memory(gb, 0xFF00 + temp, gb->registers[GB_REGISTER_AF] >> 8);
@ -1034,7 +977,6 @@ static void ld_a_da8(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->registers[GB_REGISTER_AF] &= 0xFF; gb->registers[GB_REGISTER_AF] &= 0xFF;
gb->pc++;
uint8_t temp = GB_read_memory(gb, gb->pc++); uint8_t temp = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, 0xFF00 + temp) << 8; gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, 0xFF00 + temp) << 8;
@ -1044,7 +986,6 @@ static void ld_a_da8(GB_gameboy_t *gb, uint8_t opcode)
static void ld_dc_a(GB_gameboy_t *gb, uint8_t opcode) static void ld_dc_a(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); 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_write_memory(gb, 0xFF00 + (gb->registers[GB_REGISTER_BC] & 0xFF), gb->registers[GB_REGISTER_AF] >> 8);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
} }
@ -1053,7 +994,6 @@ static void ld_a_dc(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->registers[GB_REGISTER_AF] &= 0xFF; 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->registers[GB_REGISTER_AF] |= GB_read_memory(gb, 0xFF00 + (gb->registers[GB_REGISTER_BC] & 0xFF)) << 8;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
} }
@ -1063,7 +1003,6 @@ static void add_sp_r8(GB_gameboy_t *gb, uint8_t opcode)
int16_t offset; int16_t offset;
uint16_t sp = gb->registers[GB_REGISTER_SP]; uint16_t sp = gb->registers[GB_REGISTER_SP];
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
offset = (int8_t) GB_read_memory(gb, gb->pc++); offset = (int8_t) GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 12); GB_advance_cycles(gb, 12);
gb->registers[GB_REGISTER_SP] += offset; gb->registers[GB_REGISTER_SP] += offset;
@ -1090,7 +1029,6 @@ static void ld_da16_a(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint16_t addr; uint16_t addr;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
addr = GB_read_memory(gb, gb->pc++); addr = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
addr |= GB_read_memory(gb, gb->pc++) << 8; addr |= GB_read_memory(gb, gb->pc++) << 8;
@ -1104,7 +1042,6 @@ static void ld_a_da16(GB_gameboy_t *gb, uint8_t opcode)
uint16_t addr; uint16_t addr;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->registers[GB_REGISTER_AF] &= 0xFF; gb->registers[GB_REGISTER_AF] &= 0xFF;
gb->pc++;
addr = GB_read_memory(gb, gb->pc++); addr = GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
addr |= GB_read_memory(gb, gb->pc++) << 8 ; addr |= GB_read_memory(gb, gb->pc++) << 8 ;
@ -1116,7 +1053,6 @@ static void ld_a_da16(GB_gameboy_t *gb, uint8_t opcode)
static void di(GB_gameboy_t *gb, uint8_t opcode) static void di(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
/* di is delayed in CGB */ /* di is delayed in CGB */
if (!gb->is_cgb) { if (!gb->is_cgb) {
@ -1131,7 +1067,6 @@ static void ei(GB_gameboy_t *gb, uint8_t opcode)
{ {
/* ei is actually "disable interrupts for one instruction, then enable them". */ /* ei is actually "disable interrupts for one instruction, then enable them". */
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->ime = false; gb->ime = false;
gb->ime_toggle = true; gb->ime_toggle = true;
} }
@ -1140,7 +1075,6 @@ static void ld_hl_sp_r8(GB_gameboy_t *gb, uint8_t opcode)
{ {
int16_t offset; int16_t offset;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
offset = (int8_t) GB_read_memory(gb, gb->pc++); offset = (int8_t) GB_read_memory(gb, gb->pc++);
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
@ -1158,7 +1092,6 @@ static void ld_hl_sp_r8(GB_gameboy_t *gb, uint8_t opcode)
static void ld_sp_hl(GB_gameboy_t *gb, uint8_t opcode) static void ld_sp_hl(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 8); GB_advance_cycles(gb, 8);
gb->pc++;
gb->registers[GB_REGISTER_SP] = gb->registers[GB_REGISTER_HL]; gb->registers[GB_REGISTER_SP] = gb->registers[GB_REGISTER_HL];
} }
@ -1167,7 +1100,6 @@ static void rlc_r(GB_gameboy_t *gb, uint8_t opcode)
bool carry; bool carry;
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
carry = (value & 0x80) != 0; carry = (value & 0x80) != 0;
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
@ -1185,7 +1117,6 @@ static void rrc_r(GB_gameboy_t *gb, uint8_t opcode)
bool carry; bool carry;
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
carry = (value & 0x01) != 0; carry = (value & 0x01) != 0;
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
@ -1205,7 +1136,6 @@ static void rl_r(GB_gameboy_t *gb, uint8_t opcode)
uint8_t value; uint8_t value;
bool bit7; bool bit7;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0;
bit7 = (value & 0x80) != 0; bit7 = (value & 0x80) != 0;
@ -1228,7 +1158,6 @@ static void rr_r(GB_gameboy_t *gb, uint8_t opcode)
bool bit1; bool bit1;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0;
bit1 = (value & 0x1) != 0; bit1 = (value & 0x1) != 0;
@ -1249,7 +1178,6 @@ static void sla_r(GB_gameboy_t *gb, uint8_t opcode)
uint8_t value; uint8_t value;
bool carry; bool carry;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
carry = (value & 0x80) != 0; carry = (value & 0x80) != 0;
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
@ -1267,7 +1195,6 @@ static void sra_r(GB_gameboy_t *gb, uint8_t opcode)
uint8_t bit7; uint8_t bit7;
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
bit7 = value & 0x80; bit7 = value & 0x80;
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
@ -1285,7 +1212,6 @@ static void srl_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
set_src_value(gb, opcode, (value >> 1)); set_src_value(gb, opcode, (value >> 1));
@ -1301,7 +1227,6 @@ static void swap_r(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t value; uint8_t value;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
gb->registers[GB_REGISTER_AF] &= 0xFF00; gb->registers[GB_REGISTER_AF] &= 0xFF00;
set_src_value(gb, opcode, (value >> 4) | (value << 4)); set_src_value(gb, opcode, (value >> 4) | (value << 4));
@ -1315,7 +1240,6 @@ static void bit_r(GB_gameboy_t *gb, uint8_t opcode)
uint8_t value; uint8_t value;
uint8_t bit; uint8_t bit;
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
gb->pc++;
value = get_src_value(gb, opcode); value = get_src_value(gb, opcode);
bit = 1 << ((opcode >> 3) & 7); bit = 1 << ((opcode >> 3) & 7);
if ((opcode & 0xC0) == 0x40) { /* Bit */ if ((opcode & 0xC0) == 0x40) { /* Bit */
@ -1336,7 +1260,7 @@ static void bit_r(GB_gameboy_t *gb, uint8_t opcode)
static void cb_prefix(GB_gameboy_t *gb, uint8_t opcode) static void cb_prefix(GB_gameboy_t *gb, uint8_t opcode)
{ {
GB_advance_cycles(gb, 4); GB_advance_cycles(gb, 4);
opcode = GB_read_memory(gb, ++gb->pc); opcode = GB_read_memory(gb, gb->pc++);
switch (opcode >> 3) { switch (opcode >> 3) {
case 0: case 0:
rlc_r(gb, opcode); rlc_r(gb, opcode);
@ -1409,7 +1333,10 @@ void GB_cpu_run(GB_gameboy_t *gb)
{ {
gb->vblank_just_occured = false; gb->vblank_just_occured = false;
bool interrupt = gb->interrupt_enable & gb->io_registers[GB_IO_IF]; bool interrupt = gb->interrupt_enable & gb->io_registers[GB_IO_IF];
bool halt_bug = false;
if (interrupt) { if (interrupt) {
halt_bug = gb->halted && !gb->is_cgb; /* Todo: Does this bug happen on a CGB? */
gb->halted = false; gb->halted = false;
} }
@ -1434,12 +1361,14 @@ void GB_cpu_run(GB_gameboy_t *gb)
gb->io_registers[GB_IO_IF] &= ~(1 << interrupt_bit); gb->io_registers[GB_IO_IF] &= ~(1 << interrupt_bit);
gb->ime = false; gb->ime = false;
nop(gb, 0); nop(gb, 0);
gb->pc -= 2;
/* Run pseudo instructions rst 40-60*/ /* Run pseudo instructions rst 40-60*/
rst(gb, 0x87 + interrupt_bit * 8); rst(gb, 0x87 + interrupt_bit * 8);
} }
else if(!gb->halted && !gb->stopped) { else if(!gb->halted && !gb->stopped) {
uint8_t opcode = GB_read_memory(gb, gb->pc); uint8_t opcode = GB_read_memory(gb, gb->pc++);
if (halt_bug) {
gb->pc--;
}
opcodes[opcode](gb, opcode); opcodes[opcode](gb, opcode);
} }
else { else {

View File

@ -17,13 +17,13 @@ Features common to both Cocoa and SDL versions:
* Emulates LCD timing effects, supporting the Demotronic trick, [GBVideoPlayer](https://github.com/LIJI32/GBVideoPlayer) and other tech demos * Emulates LCD timing effects, supporting the Demotronic trick, [GBVideoPlayer](https://github.com/LIJI32/GBVideoPlayer) and other tech demos
* Accurate instruction and memory timings * Accurate instruction and memory timings
* Real time clock emulation * Real time clock emulation
* High quality 96KHz audio
* Battery save support
* Save states
Features currently supported only with the Cocoa version: Features currently supported only with the Cocoa version:
* Native Cocoa interface, with support for all system-wide features, such as drag-and-drop and smart titlebars * Native Cocoa interface, with support for all system-wide features, such as drag-and-drop and smart titlebars
* Retina display support, allowing a wider range of scaling factors without artifacts * Retina display support, allowing a wider range of scaling factors without artifacts
* High quality 96KHz audio
* Battery save support
* Save states
* Optional frame blending * Optional frame blending
* Several [scaling algorithms](SCALING.md) (Including exclusive algorithms like OmniScale and Anti-aliased Scale2x) * Several [scaling algorithms](SCALING.md) (Including exclusive algorithms like OmniScale and Anti-aliased Scale2x)