rework the interrupt mechanism
This commit is contained in:
parent
f8d11cacc9
commit
5735df623a
17
include/gb.h
17
include/gb.h
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
6
io/ppu.c
6
io/ppu.c
|
@ -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)) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user