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. */
_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 {
GB_SECTION(header,
/* 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, dma_cycles);
GB_aligned_double apu_cycles;
uint8_t tima_reload_state; /* After TIMA overflows, it becomes 0 for 4 cycles before actually reloading. */
);
/* APU */

View File

@ -147,7 +147,6 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
/* Fall through */
case GB_IO_JOYP:
case GB_IO_DIV:
case GB_IO_TIMA:
case GB_IO_TMA:
case GB_IO_LCDC:
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_SB:
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:
if (!gb->is_cgb) {
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_IF:
case GB_IO_TIMA:
case GB_IO_TMA:
case GB_IO_SCY:
case GB_IO_LYC:
case GB_IO_BGP:
@ -373,6 +375,19 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
case GB_IO_DMG_EMULATION_INDICATION:
gb->io_registers[addr & 0xFF] = value;
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:
GB_emulate_timer_glitch(gb, 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)
{
// Affected by speed boost
gb->dma_cycles += cycles;
advance_tima_state_machine(gb);
for (int i = 0; i < cycles; i += 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) {
cycles >>=1;
}
@ -49,6 +67,7 @@ static void increase_tima(GB_gameboy_t *gb)
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_IF] |= 4;
gb->tima_reload_state = GB_TIMA_RELOADING;
}
}