#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(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; } }