ragb/io/interrupts.c
2024-11-07 18:06:27 +01:00

135 lines
3.1 KiB
C

#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(GB *gb) {
//TODO
}
void gb_interrupts_request (GB *gb, int interrupt) {
switch (interrupt) {
case GB_INTERRUPTS_VBLANK:
case GB_INTERRUPTS_STAT:
case GB_INTERRUPTS_TIMER:
case GB_INTERRUPTS_SERIAL:
case GB_INTERRUPTS_JOYPAD:
gb->interrupts.flags |= interrupt;
break;
default:
break;
}
}