Initial work on gb_interrupts

This commit is contained in:
condret 2024-11-07 14:52:04 +01:00
parent 5d4d9e2bcb
commit e40c6ef069
4 changed files with 158 additions and 4 deletions

View File

@ -1,7 +1,7 @@
LDFLAGS = $(shell pkg-config --libs sdl2 r_util r_io) LDFLAGS = $(shell pkg-config --libs sdl2 r_util r_io)
CFLAGS = -Wall -I include/ $(shell pkg-config --cflags sdl2 r_util r_io r_arch r_esil) CFLAGS = -Wall -I include/ $(shell pkg-config --cflags sdl2 r_util r_io r_arch r_esil r_anal r_reg)
all: sdl/pixbuf.o io/timers.o io/mbc1.o io/mbc2.o io/joypad.o io/dma.o io/ppu.o all: sdl/pixbuf.o io/timers.o io/mbc1.o io/mbc2.o io/joypad.o io/dma.o io/ppu.o io/interrupts.o
sdl/pixbuf.o: sdl/pixbuf.o:
gcc -c sdl/pixbuf.c -o sdl/pixbuf.o $(CFLAGS) gcc -c sdl/pixbuf.c -o sdl/pixbuf.o $(CFLAGS)
@ -24,5 +24,8 @@ io/dma.o:
io/ppu.o: io/ppu.o:
gcc -c io/ppu.c -o io/ppu.o $(CFLAGS) gcc -c io/ppu.c -o io/ppu.o $(CFLAGS)
io/interrupts.o:
gcc -c io/interrupts.c -o io/interrupts.o $(CFLAGS)
clean: clean:
rm sdl/*.o && rm io/*.o rm sdl/*.o && rm io/*.o

View File

@ -4,6 +4,8 @@
#include <r_io.h> #include <r_io.h>
#include <r_arch.h> #include <r_arch.h>
#include <r_esil.h> #include <r_esil.h>
#include <r_anal.h>
#include <r_reg.h>
#define WHITE 0x86c06c #define WHITE 0x86c06c
#define LIGHT_GRAY 0xe0f8cf #define LIGHT_GRAY 0xe0f8cf
@ -52,6 +54,32 @@ bool gb_joypad_init(GBJoypad *joypad, RIO *io);
void gb_joypad_continue(GBJoypad *joypad); void gb_joypad_continue(GBJoypad *joypad);
void gb_joypad_fini(GBJoypad *joypad, RIO *io); void gb_joypad_fini(GBJoypad *joypad, RIO *io);
typedef struct gb_interrupts_t {
int fd;
ut16 flags;
} GBInterrupts;
enum {
GB_INTERRUPTS_VBLANK_PENDING = 0,
GB_INTERRUPTS_STAT_PENDING,
GB_INTERRUPTS_TIMER_PENDING,
GB_INTERRUPTS_SERIAL_PENDING,
GB_INTERRUPTS_JOYPAD_PENDING,
GB_INTERRUPTS_N, //number of interrupts
GB_INTERRUPTS_VBLANK_ENABLED = GB_INTERRUPTS_N,
GB_INTERRUPTS_STAT_ENABLED,
GB_INTERRUPTS_TIMER_ENABLED,
GB_INTERRUPTS_SERIAL_ENABLED,
GB_INTERRUPTS_JOYPAD_ENABLED,
GB_INTERRUPTS_ENABLED, //general enable of all interrupts
GB_INTERRUPTS_ENABLE_WAIT, //wait 1 instruction befor enabling interrupts
GB_INTERRUPTS_SEEK, //2 bits for seek
}
;
bool gb_interrupts_init(GBInterrupts *ints, RIO *io);
void gb_interrupts_continue(GBInterrupts *ints);
void gb_interrupts_fini(GBInterrupts *ints, RIO *io);
typedef struct gb_dma_t { typedef struct gb_dma_t {
ut64 seek; //17 bit seek and some flags ut64 seek; //17 bit seek and some flags
int dma_fd; //fd representing the dma register int dma_fd; //fd representing the dma register
@ -126,7 +154,6 @@ typedef struct pixel_fifo_fetcher_t {
ut8 state_ctr; ut8 state_ctr;
} PixelFifoFetcher; } PixelFifoFetcher;
// flags // flags
#define GB_PIXEL_FIFO_FETCH_OBJECT 0x10 #define GB_PIXEL_FIFO_FETCH_OBJECT 0x10
#define GB_PIXEL_FIFO_FETCH_WINDOW 0x20 #define GB_PIXEL_FIFO_FETCH_WINDOW 0x20
@ -188,9 +215,11 @@ typedef struct gb_dmg_ppu_t {
typedef struct gameboy_t { typedef struct gameboy_t {
RIO *io; RIO *io;
REsil *esil;
RArch *arch; RArch *arch;
GBTimers timers; GBTimers timers;
GBJoypad joypad; GBJoypad joypad;
GBInterrupts interrupts;
GBDMA *dma; GBDMA *dma;
GBPPU *ppu; GBPPU *ppu;
ut64 addr; ut64 addr;

119
io/interrupts.c Normal file
View File

@ -0,0 +1,119 @@
#include <gb.h>
#include <r_io.h>
#include <r_util.h>
#include <r_esil.h>
#include <r_anal.h>
#include <r_reg.h>
RIOPlugin r_io_plugin_gb_interrupts;
static ut64 __lseek(RIO* io, RIODesc *desc, ut64 offset, int whence) {
GBInterrupts *ints = desc->data;
ut64 seek = (ints->flags >> GB_INTERRUPTS_SEEK) & 0x3;
switch (whence) {
case R_IO_SEEK_SET:
seek = R_MIN (2, offset);
break;
case R_IO_SEEK_CUR:
seek = R_MIN (2, seek + offset);
break;
case R_IO_SEEK_END:
seek = 2;
break;
}
ints->flags &= ~(0x3 << GB_INTERRUPTS_SEEK);
ints->flags |= seek << GB_INTERRUPTS_SEEK;
return seek;
}
static int __read(RIO *io, RIODesc *desc, ut8 *buf, int len) {
GBInterrupts *ints = desc->data;
ut64 seek = (ints->flags >> GB_INTERRUPTS_SEEK) & 0x3;
if (seek > 1 || len < 1) {
return 0;
}
len = R_MIN (len, 2 - seek);
ut32 i;
for (i = 0; i < len; i++) {
buf[i] = (ints->flags & (0x1f << (GB_INTERRUPTS_N * seek))) >>
(GB_INTERRUPTS_N * seek);
seek++;
}
ints->flags &= ~(0x3 << GB_INTERRUPTS_SEEK);
ints->flags |= seek << GB_INTERRUPTS_SEEK;
return len;
}
static int __write(RIO *io, RIODesc *desc, const ut8 *buf, int len) {
GBInterrupts *ints = desc->data;
ut64 seek = (ints->flags >> GB_INTERRUPTS_SEEK) & 0x3;
if (seek > 1 || len < 1) {
return 0;
}
len = R_MIN (len, 2 - seek);
ut32 i;
for (i = 0; i < len; i++) {
ints->flags &= ~(0x1f << (GB_INTERRUPTS_N * seek));
ints->flags |= (buf[i] & 0x1f) << (GB_INTERRUPTS_N * seek);
seek++;
}
ints->flags &= ~(0x3 << GB_INTERRUPTS_SEEK);
ints->flags |= seek << GB_INTERRUPTS_SEEK;
return len;
}
static bool __check(RIO *io, const char *pathname, bool many) {
return r_str_startswith (pathname, "gb_interrupts://");
}
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) {
if (!r_str_startswith (pathname, "gb_interrupts://")) {
return NULL;
}
GBInterrupts *ints = NULL;
sscanf (pathname, "gb_interrupts://%p", &ints);
RIODesc *desc = r_io_desc_new (io, &r_io_plugin_gb_interrupts, pathname,
R_PERM_RWX, mode, ints);
return desc;
}
static bool __close(RIODesc *desc) {
return true;
}
RIOPlugin r_io_plugin_gb_interrupts = {
.meta = {
.name = "gb_interrupts",
.desc = "gb_interrupts",
.license = "LGPL",
},
.uris = "gb_interrupts://",
.open = __open,
.close = __close,
.read = __read,
.check = __check,
.seek = __lseek,
.write = __write,
};
bool gb_interrupts_init(GBInterrupts *ints, RIO *io) {
ints[0] = (const GBInterrupts) {0};
char uri[64];
memset (uri, 0x00, sizeof (char) * 64);
sprintf (uri, "gb_interrupts://%p", ints);
RIODesc *desc = r_io_desc_open_plugin (io, &r_io_plugin_gb_interrupts,
uri, R_PERM_RWX, 0);
if (!desc) {
return false;
}
ints->fd = desc->fd;
return true;
}
void gb_interrupts_fini(GBInterrupts *ints, RIO *io) {
r_io_fd_close (io, ints->fd);
}
void gb_interrupts_continue(GBInterrupts *ints) {
//TODO
}

View File

@ -206,14 +206,16 @@ static void gb_ppu_pixel_fifo_merge_opixels (PixelFifo *pxf, bool priority) {
const ut8 fg_pixel = (pxf->fetcher[1].fetched & (0xf << ((7 - i) << 2))) >> ((7 - i) << 2); const ut8 fg_pixel = (pxf->fetcher[1].fetched & (0xf << ((7 - i) << 2))) >> ((7 - i) << 2);
newpixels <<= 4; newpixels <<= 4;
//background always wins if obj is transparent or bg is obj //background always wins if obj is transparent or bg is obj
if ((!(fg_pixel & 0x3)) || ((bg_pixel & 0xc) == 0x4) || (bg_pixel & 0x8)) { if ((!(fg_pixel & 0x3)) || (bg_pixel & 0x8)) {
newpixels |= bg_pixel; newpixels |= bg_pixel;
continue; continue;
} }
#if 0
if ((bg_pixel & 0xc) == 0x4) { if ((bg_pixel & 0xc) == 0x4) {
//bg is window //bg is window
//TODO: check for window priority //TODO: check for window priority
} }
#endif
if (!priority && (bg_pixel & 0x3)) { if (!priority && (bg_pixel & 0x3)) {
newpixels |= bg_pixel; newpixels |= bg_pixel;
continue; continue;
@ -429,6 +431,7 @@ static ut32 gb_ppu_render_continue (GB *gb, ut32 cycles) {
fifo->n_fpixel = 0; fifo->n_fpixel = 0;
} }
} }
//Wat du wen window gets enabled while obj is fetched?
} }
#endif #endif
if (fifo->n_fpixel < 9) { if (fifo->n_fpixel < 9) {