137 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			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);
 | 
						|
}
 |