Emulate TIMA reloading
This commit is contained in:
parent
55cbe5d4d0
commit
0f98ac5ff9
@ -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 */
|
||||
|
@ -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:
|
||||
@ -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;
|
||||
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);
|
||||
gb->io_registers[GB_IO_TAC] = value;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user