From e40c6ef0695567965df19f4e4ca32c67f7fa5eae Mon Sep 17 00:00:00 2001 From: condret Date: Thu, 7 Nov 2024 14:52:04 +0100 Subject: [PATCH] Initial work on gb_interrupts --- Makefile | 7 ++- include/gb.h | 31 ++++++++++++- io/interrupts.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ io/ppu.c | 5 +- 4 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 io/interrupts.c diff --git a/Makefile b/Makefile index 9d57918..637145f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ 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: gcc -c sdl/pixbuf.c -o sdl/pixbuf.o $(CFLAGS) @@ -24,5 +24,8 @@ io/dma.o: io/ppu.o: gcc -c io/ppu.c -o io/ppu.o $(CFLAGS) +io/interrupts.o: + gcc -c io/interrupts.c -o io/interrupts.o $(CFLAGS) + clean: rm sdl/*.o && rm io/*.o diff --git a/include/gb.h b/include/gb.h index 68bdce9..3dc2e9b 100644 --- a/include/gb.h +++ b/include/gb.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #define WHITE 0x86c06c #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_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 { ut64 seek; //17 bit seek and some flags int dma_fd; //fd representing the dma register @@ -126,7 +154,6 @@ typedef struct pixel_fifo_fetcher_t { ut8 state_ctr; } PixelFifoFetcher; - // flags #define GB_PIXEL_FIFO_FETCH_OBJECT 0x10 #define GB_PIXEL_FIFO_FETCH_WINDOW 0x20 @@ -188,9 +215,11 @@ typedef struct gb_dmg_ppu_t { typedef struct gameboy_t { RIO *io; + REsil *esil; RArch *arch; GBTimers timers; GBJoypad joypad; + GBInterrupts interrupts; GBDMA *dma; GBPPU *ppu; ut64 addr; diff --git a/io/interrupts.c b/io/interrupts.c new file mode 100644 index 0000000..33b6ff5 --- /dev/null +++ b/io/interrupts.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include + +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 +} diff --git a/io/ppu.c b/io/ppu.c index aba5133..0fd8baa 100644 --- a/io/ppu.c +++ b/io/ppu.c @@ -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); newpixels <<= 4; //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; continue; } +#if 0 if ((bg_pixel & 0xc) == 0x4) { //bg is window //TODO: check for window priority } +#endif if (!priority && (bg_pixel & 0x3)) { newpixels |= bg_pixel; continue; @@ -429,6 +431,7 @@ static ut32 gb_ppu_render_continue (GB *gb, ut32 cycles) { fifo->n_fpixel = 0; } } + //Wat du wen window gets enabled while obj is fetched? } #endif if (fifo->n_fpixel < 9) {