rework the interrupt mechanism

This commit is contained in:
condret 2024-11-15 00:45:01 +01:00
parent f8d11cacc9
commit 5735df623a
3 changed files with 36 additions and 25 deletions

View File

@ -55,8 +55,7 @@ void gb_joypad_fini(GBJoypad *joypad, RIO *io);
typedef struct gb_interrupts_t { typedef struct gb_interrupts_t {
RRegItem *ime; RRegItem *ime;
int fd; int fd;
ut16 flags; ut32 flags;
// ut16 pc;
} GBInterrupts; } GBInterrupts;
enum { enum {
@ -65,16 +64,17 @@ enum {
GB_INTERRUPT_TIMER, GB_INTERRUPT_TIMER,
GB_INTERRUPT_SERIAL, GB_INTERRUPT_SERIAL,
GB_INTERRUPT_JOYPAD, GB_INTERRUPT_JOYPAD,
GB_INTERRUPT_N, //number of interrupts GB_INTERRUPT_N, //number of interrupts
GB_INTERRUPT_VBLANK_ENABLED = GB_INTERRUPT_N, GB_INTERRUPT_VBLANK_ENABLED = GB_INTERRUPT_N,
GB_INTERRUPT_STAT_ENABLED, GB_INTERRUPT_STAT_ENABLED,
GB_INTERRUPT_TIMER_ENABLED, GB_INTERRUPT_TIMER_ENABLED,
GB_INTERRUPT_SERIAL_ENABLED, GB_INTERRUPT_SERIAL_ENABLED,
GB_INTERRUPT_JOYPAD_ENABLED, GB_INTERRUPT_JOYPAD_ENABLED,
GB_INTERRUPT_ENABLED, //general enable of all interrupts GB_INTERRUPT_ENABLED, //general enable of all interrupts
GB_INTERRUPT_ENABLE_WAIT, //wait 1 instruction befor enabling 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_WAIT_TRIGGER, //gb was put in wait state on previous call
GB_INTERRUPT_SEEK, //2 bits for seek 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); bool gb_interrupts_init(GBInterrupts *ints, RIO *io, RReg *reg);
@ -233,7 +233,8 @@ typedef struct gameboy_t {
GBPPU *ppu; GBPPU *ppu;
ut64 addr; ut64 addr;
int cartrigde_fd; int cartrigde_fd;
bool double_speed; ut32 pause_cycles;
// bool double_speed;
} GB; } GB;
void gb_interrupts_request(GB *gb, int interrupt); void gb_interrupts_request(GB *gb, int interrupt);

View File

@ -129,29 +129,33 @@ void gb_interrupts_continue(GB *gb) {
gb->interrupts.flags |= (0x1 << GB_INTERRUPT_ENABLE_WAIT); gb->interrupts.flags |= (0x1 << GB_INTERRUPT_ENABLE_WAIT);
return; return;
} else if (!ime) { } else if (!ime) {
gb->interrupts.flags &= ~0xe00; gb->interrupts.flags &= 0x3ff;
return; 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))) { if (!(gb->interrupts.flags & (0x1 << GB_INTERRUPT_WAIT_TRIGGER))) {
gb->interrupts.flags |= (0x1 << GB_INTERRUPT_WAIT_TRIGGER); ut32 i;
//stop exection of instructions for 20 cycles for (i = 0; i < GB_INTERRUPT_N; i++) {
//gb_pause_exec (gb, 20); 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; 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? //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); r_esil_parse (gb->esil, interrupt_expr);
free (interrupt_expr); free (interrupt_expr);
} }

View File

@ -463,6 +463,12 @@ static ut32 gb_ppu_render_continue (GB *gb, ut32 cycles) {
fifo->flags |= GB_PIXEL_FIFO_FETCH_OBJECT; fifo->flags |= GB_PIXEL_FIFO_FETCH_OBJECT;
} else { } else {
shit_out_pixel (gb->ppu); 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); gb_pixel_fifo_fetch_continue (gb);
if (fifo->n_fpixel < 9 && (fifo->flags & GB_PIXEL_FIFO_FETCH_READY)) { if (fifo->n_fpixel < 9 && (fifo->flags & GB_PIXEL_FIFO_FETCH_READY)) {