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. */
|
/* 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 */
|
||||||
|
@ -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:
|
||||||
@ -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:
|
case GB_IO_DMG_EMULATION_INDICATION:
|
||||||
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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user