ragb/io/ppu.c
2024-10-30 04:46:40 +01:00

137 lines
2.9 KiB
C

#include <stdio.h>
#include <string.h>
#include <r_io.h>
#include <r_util.h>
#include <gb.h>
#include <ragb_sdl.h>
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 (ppu->vram_fd);
r_io_fd_close (ppu->reg_fd);
gb_pix_buf_free (ppu->pixbuf);
free (ppu);
}