From 5735df623adbd68514438baa68cffe0aa4fe866d Mon Sep 17 00:00:00 2001 From: condret Date: Fri, 15 Nov 2024 00:45:01 +0100 Subject: [PATCH] rework the interrupt mechanism --- include/gb.h | 17 +++++++++-------- io/interrupts.c | 38 +++++++++++++++++++++----------------- io/ppu.c | 6 ++++++ 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/include/gb.h b/include/gb.h index 96a26f1..b4522cc 100644 --- a/include/gb.h +++ b/include/gb.h @@ -55,8 +55,7 @@ void gb_joypad_fini(GBJoypad *joypad, RIO *io); typedef struct gb_interrupts_t { RRegItem *ime; int fd; - ut16 flags; -// ut16 pc; + ut32 flags; } GBInterrupts; enum { @@ -65,16 +64,17 @@ enum { GB_INTERRUPT_TIMER, GB_INTERRUPT_SERIAL, GB_INTERRUPT_JOYPAD, - GB_INTERRUPT_N, //number of interrupts + GB_INTERRUPT_N, //number of interrupts GB_INTERRUPT_VBLANK_ENABLED = GB_INTERRUPT_N, GB_INTERRUPT_STAT_ENABLED, GB_INTERRUPT_TIMER_ENABLED, GB_INTERRUPT_SERIAL_ENABLED, GB_INTERRUPT_JOYPAD_ENABLED, - GB_INTERRUPT_ENABLED, //general enable of all interrupts - GB_INTERRUPT_ENABLE_WAIT, //wait 1 instruction befor enabling interrupts - GB_INTERRUPT_WAIT_TRIGGER, //gb was put in wait state on previous call - GB_INTERRUPT_SEEK, //2 bits for seek + GB_INTERRUPT_ENABLED, //general enable of all interrupts + GB_INTERRUPT_ENABLE_WAIT, //wait 1 instruction befor enabling interrupts + GB_INTERRUPT_WAIT_TRIGGER, //gb was put in wait state on previous call + GB_INTERRUPT_SEEK, //2 bits for seek + GB_INTERRUPT_PENDING = GB_INTERRUPT_SEEK + 2, //3 bits for pending interrupt }; bool gb_interrupts_init(GBInterrupts *ints, RIO *io, RReg *reg); @@ -233,7 +233,8 @@ typedef struct gameboy_t { GBPPU *ppu; ut64 addr; int cartrigde_fd; - bool double_speed; + ut32 pause_cycles; +// bool double_speed; } GB; void gb_interrupts_request(GB *gb, int interrupt); diff --git a/io/interrupts.c b/io/interrupts.c index d9ff29d..f447948 100644 --- a/io/interrupts.c +++ b/io/interrupts.c @@ -129,29 +129,33 @@ void gb_interrupts_continue(GB *gb) { gb->interrupts.flags |= (0x1 << GB_INTERRUPT_ENABLE_WAIT); return; } else if (!ime) { - gb->interrupts.flags &= ~0xe00; + gb->interrupts.flags &= 0x3ff; return; } - ut32 i; - for (i = 0; i < GB_INTERRUPT_N; i++) { - const ut16 imask = (0x1 << i) | (0x1 << (i + GB_INTERRUPT_N)); - if ((gb->interrupts.flags & imask) == imask) { - goto beach; - } - //remove requests for disabled interrupts - gb->interrupts.flags &= ~(0x1 << i); - } - return; -beach: if (!(gb->interrupts.flags & (0x1 << GB_INTERRUPT_WAIT_TRIGGER))) { - gb->interrupts.flags |= (0x1 << GB_INTERRUPT_WAIT_TRIGGER); - //stop exection of instructions for 20 cycles - //gb_pause_exec (gb, 20); + ut32 i; + for (i = 0; i < GB_INTERRUPT_N; i++) { + const ut16 imask = (0x1 << i) | (0x1 << (i + GB_INTERRUPT_N)); + if ((gb->interrupts.flags & imask) == imask) { + gb->interrupts.flags |= (0x1 << GB_INTERRUPT_WAIT_TRIGGER); + //stop exection of instructions for 20 cycles + //gb_pause_exec (gb, 20); + gb->pause_cycles += 20; + //save pending interrupt index + gb->interrupts.flags &= ~(0x7 << GB_INTERRUPT_PENDING); + gb->interrupts.flags |= (i << GB_INTERRUPT_PENDING); + return; + } + } return; } - const ut64 interrupt_vector = 0x40 + (i << 3); + gb->interrupts.flags ^= 0x1 << GB_INTERRUPT_WAIT_TRIGGER; + const ut32 interrupt = (gb->interrupts.flags & (0x7 << GB_INTERRUPT_PENDING)) >> GB_INTERRUPT_PENDING; + gb->interrupts.flags &= ~(0x1 << interrupt); + const ut64 interrupt_vector = 0x40 + (interrupt << 3); //maybe make this a static buffer? - char *interrupt_expr = r_str_newf ("2,sp,-=,pc,sp,=[2],0x%"PFMT64x",pc,:=", interrupt_vector); + char *interrupt_expr = r_str_newf ( + "0,ime,:=,2,sp,-=,pc,sp,=[2],0x%"PFMT64x",pc,:=", interrupt_vector); r_esil_parse (gb->esil, interrupt_expr); free (interrupt_expr); } diff --git a/io/ppu.c b/io/ppu.c index b115dad..52869e2 100644 --- a/io/ppu.c +++ b/io/ppu.c @@ -463,6 +463,12 @@ static ut32 gb_ppu_render_continue (GB *gb, ut32 cycles) { fifo->flags |= GB_PIXEL_FIFO_FETCH_OBJECT; } else { shit_out_pixel (gb->ppu); + if (fifo->x > 159) { + gb->ppu->buf[GB_PPU_STAT] &= ~GB_PPU_STAT_MODE_MASK; + gb->ppu->buf[GB_PPU_STAT] |= GB_PPU_STAT_MODE_HBLANK; + fifo->remaining_cycles--; + return cycles - 1; + } } gb_pixel_fifo_fetch_continue (gb); if (fifo->n_fpixel < 9 && (fifo->flags & GB_PIXEL_FIFO_FETCH_READY)) {