Starting to remove the delayed interrupts hack – done for timer interrupt, broken for display interrupts
This commit is contained in:
parent
c48097a484
commit
42ab746a66
@ -661,6 +661,8 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
|
|
||||||
void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
||||||
{
|
{
|
||||||
|
if (gb->display_hack == 1) return;
|
||||||
|
if (gb->display_hack == 2) cycles *= 2;
|
||||||
update_display_state(gb, cycles);
|
update_display_state(gb, cycles);
|
||||||
if (gb->disable_rendering) {
|
if (gb->disable_rendering) {
|
||||||
return;
|
return;
|
||||||
|
@ -340,6 +340,7 @@ struct GB_gameboy_internal_s {
|
|||||||
uint16_t serial_length;
|
uint16_t serial_length;
|
||||||
uint8_t future_interrupts; /* Interrupts can occur in any T-cycle. Some timings result in different interrupt
|
uint8_t future_interrupts; /* Interrupts can occur in any T-cycle. Some timings result in different interrupt
|
||||||
timing when the CPU is in halt mode, and might also affect the DI instruction. */
|
timing when the CPU is in halt mode, and might also affect the DI instruction. */
|
||||||
|
uint8_t display_hack; // Temporary hack until the display is rewritten to operate in T-cycle rates;
|
||||||
);
|
);
|
||||||
|
|
||||||
/* APU */
|
/* APU */
|
||||||
|
@ -484,7 +484,9 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case GB_IO_DIV:
|
case GB_IO_DIV:
|
||||||
gb->div_state = 0; // Reset the div state machine
|
/* Reset the div state machine */
|
||||||
|
gb->div_state = 0;
|
||||||
|
gb->div_cycles = 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case GB_IO_JOYP:
|
case GB_IO_JOYP:
|
||||||
|
@ -96,13 +96,11 @@ static void GB_ir_run(GB_gameboy_t *gb)
|
|||||||
|
|
||||||
static void advance_tima_state_machine(GB_gameboy_t *gb)
|
static void advance_tima_state_machine(GB_gameboy_t *gb)
|
||||||
{
|
{
|
||||||
gb->io_registers[GB_IO_IF] |= gb->future_interrupts & 4;
|
|
||||||
gb->future_interrupts &= ~4;
|
|
||||||
if (gb->tima_reload_state == GB_TIMA_RELOADED) {
|
if (gb->tima_reload_state == GB_TIMA_RELOADED) {
|
||||||
gb->tima_reload_state = GB_TIMA_RUNNING;
|
gb->tima_reload_state = GB_TIMA_RUNNING;
|
||||||
}
|
}
|
||||||
else if (gb->tima_reload_state == GB_TIMA_RELOADING) {
|
else if (gb->tima_reload_state == GB_TIMA_RELOADING) {
|
||||||
gb->future_interrupts |= 4;
|
gb->io_registers[GB_IO_IF] |= 4;
|
||||||
gb->tima_reload_state = GB_TIMA_RELOADED;
|
gb->tima_reload_state = GB_TIMA_RELOADED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,14 +138,16 @@ static void GB_timers_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
{
|
{
|
||||||
GB_STATE_MACHINE(gb, div, cycles) {
|
GB_STATE_MACHINE(gb, div, cycles) {
|
||||||
GB_STATE(gb, div, 1);
|
GB_STATE(gb, div, 1);
|
||||||
|
GB_STATE(gb, div, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_set_internal_div_counter(gb, 0);
|
GB_set_internal_div_counter(gb, 0);
|
||||||
|
GB_SLEEP(gb, div, 1, 2);
|
||||||
while (true) {
|
while (true) {
|
||||||
advance_tima_state_machine(gb);
|
advance_tima_state_machine(gb);
|
||||||
GB_set_internal_div_counter(gb, gb->div_counter + 4);
|
GB_set_internal_div_counter(gb, gb->div_counter + 4);
|
||||||
gb->apu.apu_cycles += 4 << !gb->cgb_double_speed;
|
gb->apu.apu_cycles += 4 << !gb->cgb_double_speed;
|
||||||
GB_SLEEP(gb, div, 1, 4);
|
GB_SLEEP(gb, div, 2, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,6 @@ switch ((gb)->unit##_state)
|
|||||||
|
|
||||||
#define GB_STATE(gb, unit, state) case state: goto unit##state
|
#define GB_STATE(gb, unit, state) case state: goto unit##state
|
||||||
|
|
||||||
#define GB_UNIT(unit) uint32_t unit##_cycles, unit##_state
|
#define GB_UNIT(unit) int32_t unit##_cycles, unit##_state
|
||||||
|
|
||||||
#endif /* timing_h */
|
#endif /* timing_h */
|
||||||
|
@ -1337,23 +1337,29 @@ static GB_opcode_t *opcodes[256] = {
|
|||||||
};
|
};
|
||||||
void GB_cpu_run(GB_gameboy_t *gb)
|
void GB_cpu_run(GB_gameboy_t *gb)
|
||||||
{
|
{
|
||||||
|
if (gb->hdma_on) {
|
||||||
|
GB_advance_cycles(gb, 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gb->vblank_just_occured = false;
|
gb->vblank_just_occured = false;
|
||||||
|
if (gb->halted) {
|
||||||
|
gb->display_hack = 1;
|
||||||
|
GB_advance_cycles(gb, 2);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F;
|
uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F;
|
||||||
if (!gb->halted) {
|
|
||||||
interrupt_queue |= gb->future_interrupts & gb->interrupt_enable;
|
if (gb->halted) {
|
||||||
|
gb->display_hack = 2;
|
||||||
|
GB_advance_cycles(gb, 2);
|
||||||
|
gb->display_hack = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb->io_registers[GB_IO_IF] |= gb->future_interrupts;
|
gb->io_registers[GB_IO_IF] |= gb->future_interrupts;
|
||||||
gb->future_interrupts = 0;
|
gb->future_interrupts = 0;
|
||||||
|
|
||||||
if (interrupt_queue) {
|
|
||||||
gb->halted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gb->hdma_on) {
|
|
||||||
GB_advance_cycles(gb, 4);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool effecitve_ime = gb->ime;
|
bool effecitve_ime = gb->ime;
|
||||||
if (gb->ime_toggle) {
|
if (gb->ime_toggle) {
|
||||||
@ -1361,11 +1367,15 @@ void GB_cpu_run(GB_gameboy_t *gb)
|
|||||||
gb->ime_toggle = false;
|
gb->ime_toggle = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effecitve_ime && interrupt_queue) {
|
/* Wake up from HALT mode without calling interrupt code. */
|
||||||
|
if (gb->halted && !effecitve_ime && interrupt_queue) {
|
||||||
nop(gb, 0);
|
gb->halted = false;
|
||||||
|
}
|
||||||
|
/* Call interrupt */
|
||||||
|
else if (effecitve_ime && interrupt_queue) {
|
||||||
|
gb->halted = false;
|
||||||
uint16_t call_addr = gb->pc - 1;
|
uint16_t call_addr = gb->pc - 1;
|
||||||
GB_advance_cycles(gb, 8);
|
GB_advance_cycles(gb, 12);
|
||||||
gb->registers[GB_REGISTER_SP] -= 2;
|
gb->registers[GB_REGISTER_SP] -= 2;
|
||||||
GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc) >> 8);
|
GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc) >> 8);
|
||||||
interrupt_queue = gb->interrupt_enable;
|
interrupt_queue = gb->interrupt_enable;
|
||||||
@ -1391,6 +1401,7 @@ void GB_cpu_run(GB_gameboy_t *gb)
|
|||||||
gb->ime = false;
|
gb->ime = false;
|
||||||
GB_debugger_call_hook(gb, call_addr);
|
GB_debugger_call_hook(gb, call_addr);
|
||||||
}
|
}
|
||||||
|
/* Run mode */
|
||||||
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 (gb->halt_bug) {
|
if (gb->halt_bug) {
|
||||||
@ -1399,7 +1410,4 @@ void GB_cpu_run(GB_gameboy_t *gb)
|
|||||||
}
|
}
|
||||||
opcodes[opcode](gb, opcode);
|
opcodes[opcode](gb, opcode);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
GB_advance_cycles(gb, 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user