Emulate TIMA reloading

This commit is contained in:
Lior Halphon 2016-08-06 13:56:29 +03:00
parent 55cbe5d4d0
commit 0f98ac5ff9
3 changed files with 44 additions and 3 deletions

View File

@ -193,6 +193,12 @@ struct GB_watchpoint_s;
/* Todo: We might want to typedef our own bool if this prevents SameBoy from working on specific platforms. */ /* Todo: We might want to typedef our own bool if this prevents SameBoy from working on specific platforms. */
_Static_assert(sizeof(bool) == 1, "sizeof(bool) != 1"); _Static_assert(sizeof(bool) == 1, "sizeof(bool) != 1");
enum {
GB_TIMA_RUNNING = 0,
GB_TIMA_RELOADING = 1,
GB_TIMA_RELOADED = 2
};
typedef struct GB_gameboy_s { typedef struct GB_gameboy_s {
GB_SECTION(header, GB_SECTION(header,
/* The magic makes sure a state file is: /* The magic makes sure a state file is:
@ -287,6 +293,7 @@ typedef struct GB_gameboy_s {
GB_PADDING(uint32_t, tima_cycles); GB_PADDING(uint32_t, tima_cycles);
GB_PADDING(uint32_t, dma_cycles); GB_PADDING(uint32_t, dma_cycles);
GB_aligned_double apu_cycles; GB_aligned_double apu_cycles;
uint8_t tima_reload_state; /* After TIMA overflows, it becomes 0 for 4 cycles before actually reloading. */
); );
/* APU */ /* APU */

View File

@ -147,7 +147,6 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
/* Fall through */ /* Fall through */
case GB_IO_JOYP: case GB_IO_JOYP:
case GB_IO_DIV: case GB_IO_DIV:
case GB_IO_TIMA:
case GB_IO_TMA: case GB_IO_TMA:
case GB_IO_LCDC: case GB_IO_LCDC:
case GB_IO_SCY: case GB_IO_SCY:
@ -161,6 +160,11 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
case GB_IO_WX: case GB_IO_WX:
case GB_IO_SB: case GB_IO_SB:
return gb->io_registers[addr & 0xFF]; return gb->io_registers[addr & 0xFF];
case GB_IO_TIMA:
if (gb->tima_reload_state == GB_TIMA_RELOADING) {
return 0;
}
return gb->io_registers[GB_IO_TIMA];
case GB_IO_HDMA5: case GB_IO_HDMA5:
if (!gb->is_cgb) { if (!gb->is_cgb) {
return 0xFF; return 0xFF;
@ -356,8 +360,6 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
case GB_IO_SCX: case GB_IO_SCX:
case GB_IO_IF: case GB_IO_IF:
case GB_IO_TIMA:
case GB_IO_TMA:
case GB_IO_SCY: case GB_IO_SCY:
case GB_IO_LYC: case GB_IO_LYC:
case GB_IO_BGP: case GB_IO_BGP:
@ -374,6 +376,19 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
gb->io_registers[addr & 0xFF] = value; gb->io_registers[addr & 0xFF] = value;
return; return;
case GB_IO_TIMA:
if (gb->tima_reload_state != GB_TIMA_RELOADED) {
gb->io_registers[GB_IO_TIMA] = value;
}
return;
case GB_IO_TMA:
gb->io_registers[GB_IO_TMA] = value;
if (gb->tima_reload_state == GB_TIMA_RELOADED) {
gb->io_registers[GB_IO_TIMA] = value;
}
return;
case GB_IO_TAC: case GB_IO_TAC:
GB_emulate_timer_glitch(gb, gb->io_registers[GB_IO_TAC], value); GB_emulate_timer_glitch(gb, gb->io_registers[GB_IO_TAC], value);
gb->io_registers[GB_IO_TAC] = value; gb->io_registers[GB_IO_TAC] = value;

View File

@ -14,15 +14,33 @@ static void GB_ir_run(GB_gameboy_t *gb)
} }
} }
static void advance_tima_state_machine(GB_gameboy_t *gb)
{
if (gb->tima_reload_state == GB_TIMA_RELOADED) {
gb->tima_reload_state = GB_TIMA_RUNNING;
}
else if (gb->tima_reload_state == GB_TIMA_RELOADING) {
gb->tima_reload_state = GB_TIMA_RELOADED;
}
}
void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles) void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
{ {
// Affected by speed boost // Affected by speed boost
gb->dma_cycles += cycles; gb->dma_cycles += cycles;
advance_tima_state_machine(gb);
for (int i = 0; i < cycles; i += 4) { for (int i = 0; i < cycles; i += 4) {
GB_set_internal_div_counter(gb, gb->div_cycles + 4); GB_set_internal_div_counter(gb, gb->div_cycles + 4);
} }
if (cycles > 4) {
advance_tima_state_machine(gb);
if (cycles > 8) {
advance_tima_state_machine(gb);
}
}
if (gb->cgb_double_speed) { if (gb->cgb_double_speed) {
cycles >>=1; cycles >>=1;
} }
@ -49,6 +67,7 @@ static void increase_tima(GB_gameboy_t *gb)
if (gb->io_registers[GB_IO_TIMA] == 0) { if (gb->io_registers[GB_IO_TIMA] == 0) {
gb->io_registers[GB_IO_TIMA] = gb->io_registers[GB_IO_TMA]; gb->io_registers[GB_IO_TIMA] = gb->io_registers[GB_IO_TMA];
gb->io_registers[GB_IO_IF] |= 4; gb->io_registers[GB_IO_IF] |= 4;
gb->tima_reload_state = GB_TIMA_RELOADING;
} }
} }