#include #include #include #include #include RIOPlugin r_io_plugin_gb_ppu; static ut64 __lseek(RIO* io, RIODesc *desc, ut64 offset, int whence) { GBPPU *ppu = desc->data; ut64 seek = ppu->seek & 0xffff; switch (whence) { case R_IO_SEEK_SET: seek = R_MIN (GB_PPU_N_REGS, offset); break; case R_IO_SEEK_CUR: seek = R_MIN (GB_PPU_N_REGS, seek + offset); break; case R_IO_SEEK_END: seek = GB_PPU_N_REGS; break; } ppu->seek = (ppu->seek & (~0xffff)) | seek; return seek; } static bool __check(RIO *io, const char *pathname, bool many) { return r_str_startswith (pathname, "gb_ppu://"); } static int __read(RIO *io, RIODesc *desc, ut8 *buf, int len) { GBPPU *ppu = desc->data; ut64 seek = ppu->seek & 0xffff; if (ppu->seek >= GB_PPU_N_REGS || len < 1) { return 0; } len = R_MIN (len, GB_PPU_N_REGS - seek); memcpy (buf, &ppu->buf[ppu->seek], len); seek += len; ppu->seek = (ppu->seek & (~0xffff)) | seek; return len; } static int __write(RIO *io, RIODesc *desc, const ut8 *buf, int len) { GBPPU *ppu = desc->data; ut64 seek = ppu->seek & 0xffff; if (ppu->seek >= GB_PPU_N_REGS || len < 1) { return 0; } len = R_MIN (len, GB_PPU_N_REGS - seek); ut32 i; for (i = 0; i < len; i++) { switch (seek) { case GB_PPU_STAT: ppu->buf[GB_PPU_STAT] = (buf[i] & 0xf8) | (ppu->buf[GB_PPU_STAT] & 0x7); case GB_PPU_LY: break; default: ppu->buf[seek] = buf[i]; break; } seek++; } return len; } static bool __close(RIODesc *desc) { return true; } static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { if (!r_str_startswith (pathname, "gb_ppu://")) { return NULL; } GBPPU *ppu = NULL; sscanf (pathname, "gb_ppu://%p", &ppu); RIODesc *desc = r_io_desc_new (io, &r_io_plugin_gb_ppu, pathname, R_PERM_RWX, mode, ppu); return desc; } RIOPlugin r_io_plugin_gb_ppu = { .meta = { .name = "gb_ppu", .desc = "gb_ppu", .license = "LGPL", }, .uris = "gb_ppu://", .open = __open, .close = __close, .read = __read, .check = __check, .seek = __lseek, .write = __write, };