Initial work on gb_interrupts
This commit is contained in:
parent
5d4d9e2bcb
commit
e40c6ef069
7
Makefile
7
Makefile
|
@ -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
|
||||||
|
|
31
include/gb.h
31
include/gb.h
|
@ -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
119
io/interrupts.c
Normal 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
|
||||||
|
}
|
5
io/ppu.c
5
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);
|
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) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user