Compare commits
	
		
			10 Commits
		
	
	
		
			fe0a183ae5
			...
			3436097c6d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3436097c6d | |||
| e88697c773 | |||
| d1842269d4 | |||
| 8721a99d6c | |||
| 6167122d8e | |||
| b2ebb5472f | |||
| e04e63907b | |||
| 21875865c4 | |||
| 13685b7903 | |||
| ca3b4e4168 | 
							
								
								
									
										10
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile
									
									
									
									
									
								
							|  | @ -1,7 +1,7 @@ | |||
| LDFLAGS = $(shell pkg-config --libs sdl2 r_util r_io) | ||||
| CFLAGS = -Wall -I include/ $(shell pkg-config --cflags sdl2 r_util r_io) | ||||
| CFLAGS = -Wall -I include/ $(shell pkg-config --cflags sdl2 r_util r_io r_arch r_esil)  | ||||
| 
 | ||||
| all: sdl/pixbuf.o io/timers.o io/mbc1.o io/mbc2.o io/joypad.o | ||||
| all: sdl/pixbuf.o io/timers.o io/mbc1.o io/mbc2.o io/joypad.o io/dma.o io/ppu.o | ||||
| 
 | ||||
| sdl/pixbuf.o: | ||||
| 	gcc -c sdl/pixbuf.c -o sdl/pixbuf.o $(CFLAGS) | ||||
|  | @ -18,5 +18,11 @@ io/mbc2.o: | |||
| io/joypad.o: | ||||
| 	gcc -c io/joypad.c -o io/joypad.o $(CFLAGS) | ||||
| 
 | ||||
| io/dma.o: | ||||
| 	gcc -c io/dma.c -o io/dma.o $(CFLAGS) | ||||
| 
 | ||||
| io/ppu.o: | ||||
| 	gcc -c io/ppu.c -o io/ppu.o $(CFLAGS) | ||||
| 
 | ||||
| clean: | ||||
| 	rm sdl/*.o && rm io/*.o | ||||
|  |  | |||
							
								
								
									
										84
									
								
								include/gb.h
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								include/gb.h
									
									
									
									
									
								
							|  | @ -1,12 +1,16 @@ | |||
| #ifndef GB_H | ||||
| #define GB_H | ||||
| #include <ragb_sdl.h> | ||||
| #include <r_io.h> | ||||
| #include <r_arch.h> | ||||
| #include <r_esil.h> | ||||
| 
 | ||||
| enum { | ||||
| 	GB_TIMERS_DIV = 0, | ||||
| 	GB_TIMERS_TIMA, | ||||
| 	GB_TIMERS_TMA, | ||||
| 	GB_TIMERS_TAC, | ||||
| 	GB_TIMERS_N_REGS, | ||||
| }; | ||||
| 
 | ||||
| typedef struct gb_timers_t { | ||||
|  | @ -47,6 +51,7 @@ typedef struct gb_dma_t { | |||
| 	ut64 seek;	//17 bit seek and some flags
 | ||||
| 	int dma_fd;	//fd representing the dma register
 | ||||
| 	int dma_bus_fd;	//fd representing the memory bus while dma occupies it
 | ||||
| 	int oam_fd;	//fd representing oam
 | ||||
| 	ut32 dma_bank_id; | ||||
| 	ut32 default_bank_id; | ||||
| //	ut16 bus_occupancy_size;
 | ||||
|  | @ -60,11 +65,88 @@ typedef struct gb_dma_t { | |||
| #define	GB_DMA_LAUNCH	0x20000 | ||||
| #define	GB_DMA_RUNNING	0x40000 | ||||
| #define	GB_DMA_ACTIVE	0x60000 | ||||
| #define	GB_DMA_CGB_MODE	0x80000 | ||||
| 
 | ||||
| GBDMA *gb_dma_open(RIO *io, bool cgb); | ||||
| GBDMA *gb_dma_open(RIO *io); | ||||
| //void gb_dma_enable_cgb(GBDMA *dma);
 | ||||
| void gb_dma_update(GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec); | ||||
| void gb_dma_close(GBDMA *dma, RIO *io); | ||||
| 
 | ||||
| enum { | ||||
| 	GB_PPU_LCDC = 0,	//0xff40
 | ||||
| 	GB_PPU_STAT,		//0xff41
 | ||||
| 	GB_PPU_SCY,		//0xff42
 | ||||
| 	GB_PPU_SCX,		//0xff43
 | ||||
| 	GB_PPU_LY,		//0xff44
 | ||||
| 	GB_PPU_LYC,		//0xff45
 | ||||
| 	GB_PPU_BGP,		//0xff47
 | ||||
| 	GB_PPU_OBP0,		//0xff48
 | ||||
| 	GB_PPU_OBP1,		//0xff49
 | ||||
| 	GB_PPU_WY,		//0xff4a
 | ||||
| 	GB_PPU_WX,		//0xff4b
 | ||||
| 	GB_PPU_N_REGS, | ||||
| }; | ||||
| 
 | ||||
| enum { | ||||
| 	GB_PPU_STAT_MODE_HBLANK = 0, | ||||
| 	GB_PPU_STAT_MODE_VBLANK, | ||||
| 	GB_PPU_STAT_MODE_OAM_SCAN, | ||||
| 	GB_PPU_STAT_MODE_RENDER, | ||||
| }; | ||||
| 
 | ||||
| #define	GB_PPU_STAT_MODE_MASK	0x3 | ||||
| 
 | ||||
| typedef struct oam_scan_table { | ||||
| 	ut16 data[10];	//low byte is x coordinate of sprite; high byte is addr of entry (0xffe0 + high byte)
 | ||||
| 	ut8 n_entries;	//max 10
 | ||||
| 	ut8 addr; | ||||
| } OAMScanTable; | ||||
| 
 | ||||
| typedef struct pixel_fifo_t { | ||||
| 	ut64 data; | ||||
| 	ut32 fetch; | ||||
| 	ut32 obj_fetch; | ||||
| 	ut8 shift_out;	//lower nibble is sourch info, pallet, color
 | ||||
| 			// 0b....spcc
 | ||||
| #if 0 | ||||
| bg	-	00 | ||||
| win	-	01 | ||||
| obj p0	-	10 | ||||
| obj p1	-	11 | ||||
| #endif | ||||
| 	ut8 n_fpixel;	//number of pixel that are currently in the upper half of the fifo - 1
 | ||||
| 	ut8 x; | ||||
| 	ut8 y; | ||||
| } PixelFifo; | ||||
| 
 | ||||
| typedef struct gb_dmg_ppu_t { | ||||
| 	GBPixBuf *pixbuf; | ||||
| 	ut64 seek; | ||||
| 	ut8 buf[GB_PPU_N_REGS]; | ||||
| 	OAMScanTable ost; | ||||
| 	PixelFifo fifo; | ||||
| 	int reg_fd; | ||||
| 	int vram_fd; | ||||
| 	ut32 vram_mapid; | ||||
| 	ut32 oam_mapid; | ||||
| } GBPPU; | ||||
| 
 | ||||
| typedef struct gameboy_t { | ||||
| 	RIO *io; | ||||
| 	RArch *arch; | ||||
| 	GBTimers *timers; | ||||
| 	GBJoypad *joypad; | ||||
| 	GBDMA *dma; | ||||
| 	GBPPU *ppu; | ||||
| 	ut64 addr; | ||||
| 	int cartrigde_fd; | ||||
| 	bool double_speed; | ||||
| } GB; | ||||
| 
 | ||||
| GBPPU *gb_ppu_open (RIO *io, SDL_Renderer *renderer); | ||||
| void gb_ppu_update (GB *gb, ut32 cycles); | ||||
| void gb_ppu_close (GBPPU *ppu, RIO *io); | ||||
| 
 | ||||
| extern RIOPlugin r_io_plugin_gb_timers; | ||||
| extern RIOPlugin r_io_plugin_gb_mbc1; | ||||
| extern RIOPlugin r_io_plugin_gb_mbc2; | ||||
|  |  | |||
							
								
								
									
										45
									
								
								io/dma.c
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								io/dma.c
									
									
									
									
									
								
							|  | @ -1,4 +1,5 @@ | |||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <gb.h> | ||||
| #include <r_io.h> | ||||
| #include <r_util.h> | ||||
|  | @ -18,7 +19,7 @@ static ut64 __bus_lseek(RIO* io, RIODesc *desc, ut64 offset, int whence) { | |||
| 		break; | ||||
| 	case R_IO_SEEK_END: | ||||
| 		seek = 0xff80; | ||||
| 		break | ||||
| 		break; | ||||
| 	} | ||||
| 	dma->seek = (dma->seek & (~0xffff)) | seek; | ||||
| 	return seek; | ||||
|  | @ -31,7 +32,7 @@ static bool __bus_check(RIO *io, const char *pathname, bool many) { | |||
| static int __bus_read(RIO *io, RIODesc *desc, ut8 *buf, int len) { | ||||
| 	GBDMA *dma = desc->data; | ||||
| 	ut64 seek = dma->seek & 0xffff; | ||||
| 	if (timers->seek > 0xff7f || len < 1) { | ||||
| 	if (dma->seek > 0xff7f || len < 1) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	len = R_MIN (len, 0xff80 - seek); | ||||
|  | @ -41,7 +42,7 @@ static int __bus_read(RIO *io, RIODesc *desc, ut8 *buf, int len) { | |||
| #if 1 | ||||
| 	if (len != _len) { | ||||
| 		ut64 vseek = r_io_p2v (io, seek + _len); | ||||
| 		r_io_bank_read_at (io, dma->default_bank_id, &buf[_len], len - _len) | ||||
| 		r_io_bank_read_at (io, dma->default_bank_id, vseek, &buf[_len], len - _len); | ||||
| 	} | ||||
| #endif | ||||
| 	seek += len; | ||||
|  | @ -52,17 +53,17 @@ static int __bus_read(RIO *io, RIODesc *desc, ut8 *buf, int len) { | |||
| static int __bus_write(RIO *io, RIODesc *desc, const ut8 *buf, int len) { | ||||
| 	GBDMA *dma = desc->data; | ||||
| 	ut64 seek = dma->seek & 0xffff; | ||||
| 	if (timers->seek > 0xff7f || len < 1) { | ||||
| 	if (dma->seek > 0xff7f || len < 1) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	len = R_MIN (len, 0xff80 - seek); | ||||
| 	int _len = R_MIN (len, 0xa0 - ((ut32)dma->dst + (st32)dma->frontrun)); | ||||
| //	memcpy (buf, &dma->buf[dma->dst + dma->frontrun], _len);
 | ||||
| 	dma->frontrun += _len; | ||||
| #if 0 | ||||
| #if 1 | ||||
| 	if (len != _len) { | ||||
| 		ut64 vseek = r_io_p2v (io, seek + _len); | ||||
| 		r_io_bank_write_at (io, dma->default_bank_id, &buf[_len], len - _len) | ||||
| 		r_io_bank_write_at (io, dma->default_bank_id, vseek, &buf[_len], len - _len); | ||||
| 	} | ||||
| #endif | ||||
| 	seek += len; | ||||
|  | @ -171,13 +172,13 @@ RIOPlugin r_io_plugin_gb_dma = { | |||
| 	.write = __write, | ||||
| }; | ||||
| 
 | ||||
| GBDMA *gb_dma_open (RIO *io, bool cgb) { | ||||
| GBDMA *gb_dma_open (RIO *io) { | ||||
| 	GBDMA *dma = R_NEW0 (GBDMA); | ||||
| 	if (!dma) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	dma->default_bank_id = io->bank; | ||||
| 	RIOBank *bank = r_io_bank_new (io, "dma bus"); | ||||
| 	RIOBank *bank = r_io_bank_new ("dma bus"); | ||||
| 	if (!bank) { | ||||
| 		free (dma); | ||||
| 		return NULL; | ||||
|  | @ -188,12 +189,20 @@ GBDMA *gb_dma_open (RIO *io, bool cgb) { | |||
| 		return NULL; | ||||
| 	} | ||||
| 	dma->dma_bank_id = bank->id; | ||||
| //	strcpy (uri, "malloc://0xa0");
 | ||||
| 	dma->oam_fd = r_io_fd_open (io, "malloc://0xa0", R_PERM_RWX, 0); | ||||
| 	if (dma->oam_fd < 0) { | ||||
| 		r_io_bank_free (bank); | ||||
| 		free (dma); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	char uri[64]; | ||||
| 	memset (uri, 0x00, sizeof (char) * 64); | ||||
| 	sprintf (uri, "gb_dma://%p", dma); | ||||
| 	RIODesc *desc = r_io_desc_open_plugin (io, &r_io_plugin_gb_dma, | ||||
| 		uri, R_PERM_RWX, 0); | ||||
| 	if (!desc) { | ||||
| 		r_io_fd_close (io, dma->oam_fd); | ||||
| 		r_io_bank_free (bank); | ||||
| 		free (dma); | ||||
| 		return NULL; | ||||
|  | @ -202,7 +211,8 @@ GBDMA *gb_dma_open (RIO *io, bool cgb) { | |||
| 	sprintf (uri, "gb_dma_bus://%p", dma); | ||||
| 	desc = r_io_desc_open_plugin (io, &r_io_plugin_gb_dma_bus, uri, R_PERM_RWX, 0); | ||||
| 	if (!desc) { | ||||
| 		r_io_fd_close (dma->dma_fd); | ||||
| 		r_io_fd_close (io, dma->oam_fd); | ||||
| 		r_io_fd_close (io, dma->dma_fd); | ||||
| 		r_io_bank_free (bank); | ||||
| 		free (dma); | ||||
| 		return NULL; | ||||
|  | @ -236,8 +246,13 @@ void gb_dma_update (GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec) { | |||
| 		dma->frontrun = ((st32)cycles) * (-1); | ||||
| 	} | ||||
| 	if (cycles) { | ||||
| #if 1 | ||||
| 		r_io_fd_write_at (io, dma->oam_fd, (ut64)dma->dst, | ||||
| 			&dma->buf[dma->dst], cycles); | ||||
| #else | ||||
| 		r_io_bank_write_at (io, dma->default_bank_id, 0xfe00 | dma->dst, | ||||
| 				&dma->buf[dma->dst], cycles); | ||||
| #endif | ||||
| 		dma->dst += cycles; | ||||
| 	} | ||||
| 	if (pre_exec) { | ||||
|  | @ -248,3 +263,15 @@ void gb_dma_update (GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec) { | |||
| 		dma->seek &= (~GB_DMA_ACTIVE); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void gb_dma_close (GBDMA *dma, RIO *io) { | ||||
| 	if (!dma || !io) { | ||||
| 		return; | ||||
| 	} | ||||
| 	r_io_bank_use (io, dma->default_bank_id); | ||||
| 	r_io_bank_del (io, dma->dma_bank_id); | ||||
| 	r_io_fd_close (io, dma->dma_bus_fd); | ||||
| 	r_io_fd_close (io, dma->dma_fd); | ||||
| 	r_io_fd_close (io, dma->oam_fd); | ||||
| 	free (dma); | ||||
| } | ||||
|  |  | |||
|  | @ -45,7 +45,8 @@ static int __read(RIO *io, RIODesc *desc, ut8 *buf, int len) { | |||
| #if 0 | ||||
| 	joypad->data = buf[0] & 0xf; | ||||
| #else | ||||
| 	buf[0] = joypad->data & 0x3f | ||||
| 	buf[0] = joypad->data & 0x3f; | ||||
| #endif | ||||
| 	joypad->odata |= 0x40; | ||||
| 	return 1; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										218
									
								
								io/ppu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								io/ppu.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,218 @@ | |||
| #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; | ||||
| } | ||||
| 
 | ||||
| static ut32 gb_ppu_oam_scan_update (GB *gb, ut32 cycles) { | ||||
| 	if (gb->ppu->ost.addr >= 0xa0) { | ||||
| 		gb->ppu->ost.addr = 0; | ||||
| 		gb->ppu->ost.n_entries = 0; | ||||
| 	} | ||||
| 	if (cycles & 0x1) { | ||||
| 		R_LOG_WARN ("Odd amount of cycles"); | ||||
| 	} | ||||
| 	if (gb->dma->seek & GB_DMA_ACTIVE) { | ||||
| 		const ut8 running_cycles = R_MIN (cycles, (0xa0 - gb->ppu->ost.addr) >> 1); | ||||
| 		//every oam entry costs 2 cycles
 | ||||
| 		gb->ppu->ost.addr += running_cycles << 1; | ||||
| 		cycles -= running_cycles; | ||||
| 		goto beach; | ||||
| 	} | ||||
| 	const ut8 height = gb->ppu->buf[GB_PPU_LCDC] & 0x3? 16: 8; | ||||
| 	const ut8 ly = gb->ppu->buf[GB_PPU_LY] + 16;  | ||||
| 	while (cycles && gb->ppu->ost.addr <= 0xa0) { | ||||
| 		if (gb->ppu->ost.n_entries < 10) { | ||||
| 			ut8 yx[2]; | ||||
| 			r_io_fd_read_at (gb->io, gb->dma->oam_fd, (ut64)gb->ppu->ost.addr, yx, 2); | ||||
| 			if ((yx[0] <= ly) && (ly < (yx[0] + height)) && yx[1]) { | ||||
| 				gb->ppu->ost.data[gb->ppu->ost.n_entries] = | ||||
| 					(gb->ppu->ost.addr << 8) | yx[1]; | ||||
| 				gb->ppu->ost.n_entries++; | ||||
| 			} | ||||
| 		} | ||||
| 		gb->ppu->ost.addr += 4; | ||||
| 		cycles -= 2; | ||||
| 	} | ||||
| beach: | ||||
| 	if (gb->ppu->ost.addr == 0xa0) { | ||||
| 		//indicate next mode
 | ||||
| 		gb->ppu->buf[GB_PPU_STAT] |= GB_PPU_STAT_MODE_RENDER; | ||||
| 		RIOMap *vram = r_io_map_get (gb->io, gb->ppu->vram_mapid); | ||||
| 		vram->perm = 0;	//disable vram access for rendering
 | ||||
| 	} | ||||
| 	return cycles; | ||||
| } | ||||
| 
 | ||||
| static void gb_ppu_pixel_fifo_merge_opixels (PixelFifo *pxf, bool priority) { | ||||
| 	ut32 pixels = pxf->data >> 32; | ||||
| 	ut32 newpixels = 0; | ||||
| 	ut32 i; | ||||
| 	for (i = 0; i < 8; i++) { | ||||
| 		if (!(pixels & (0x3 << 28))) { | ||||
| 			newpixels = (newpixels << 4) | | ||||
| 				((pxf->obj_fetch & (0xf << ((i - 1) << 2))) >> ((i - 1) << 2)); | ||||
| 			pixels = pixels << 4; | ||||
| 			continue; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static ut32 gb_ppu_render_update (GB *gb, ut32 cycles) { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static ut32 gb_ppu_hblank_update (GB *gb, ut32 cycles) { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static ut32 gb_ppu_vblank_update (GB *gb, ut32 cycles) { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void gb_ppu_update (GB *gb, ut32 cycles) { | ||||
| 	while (cycles) { | ||||
| 		switch (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_MODE_MASK) { | ||||
| 		case GB_PPU_STAT_MODE_OAM_SCAN: | ||||
| 			cycles = gb_ppu_oam_scan_update (gb, cycles); | ||||
| 			break; | ||||
| 		case GB_PPU_STAT_MODE_RENDER: | ||||
| 			cycles = gb_ppu_render_update (gb, cycles); | ||||
| 			break; | ||||
| 		case GB_PPU_STAT_MODE_HBLANK: | ||||
| 			cycles = gb_ppu_hblank_update (gb, cycles); | ||||
| 			break; | ||||
| 		case GB_PPU_STAT_MODE_VBLANK: | ||||
| 			cycles = gb_ppu_vblank_update (gb, cycles); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	//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); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user