#include #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, }; GBPPU *gb_ppu_open (RIO *io, SDL_Renderer *renderer) { GBPPU *ppu = R_NEW0 (GBPPU); if (!ppu) { return NULL; } ppu->vram_fd = r_io_fd_open (io, "malloc//:0x2000", R_PERM_RWX, 0); if (ppu->vram_fd < 0) { free (ppu); return NULL; } char uri[64]; sprintf (uri, "gb_ppu://%p", ppu); RIODesc *desc = r_io_desc_open_plugin (io, &r_io_plugin_gb_ppu, uri, R_PERM_RWX, 0); if (!desc) { r_io_fd_close (io, ppu->vram_fd); free (ppu); return NULL; } ppu->reg_fd = desc->fd; ppu->pixbuf = gb_pix_buf_new (renderer, 160, 144); if (!ppu->pixbuf) { r_io_desc_close (desc); r_io_fd_close (io, ppu->vram_fd); free (ppu); return NULL; } return ppu; } void gb_ppu_update (GB *gb, ut32 cycles) { //TODO } void gb_ppu_close (GBPPU *ppu, RIO *io) { r_io_fd_close (io, ppu->vram_fd); r_io_fd_close (io, ppu->reg_fd); gb_pix_buf_free (ppu->pixbuf); free (ppu); }