diff vdp.c @ 2194:01ff005b08f6

Very rudimentary support for Game Gear VDP emulation
author Michael Pavone <pavone@retrodev.com>
date Sun, 21 Aug 2022 22:29:47 -0700
parents c5d0edf1d7e7
children 6f66356af4e2
line wrap: on
line diff
--- a/vdp.c	Sun Aug 21 16:41:22 2022 -0700
+++ b/vdp.c	Sun Aug 21 22:29:47 2022 -0700
@@ -146,7 +146,7 @@
 
 static uint8_t color_map_init_done;
 
-vdp_context *init_vdp_context(uint8_t region_pal, uint8_t has_max_vsram)
+vdp_context *init_vdp_context(uint8_t region_pal, uint8_t has_max_vsram, uint8_t type)
 {
 	vdp_context *context = calloc(1, sizeof(vdp_context) + VRAM_SIZE);
 	if (headless) {
@@ -161,6 +161,7 @@
 	context->fifo_read = -1;
 	context->regs[REG_HINT] = context->hint_counter = 0xFF;
 	context->vsram_size = has_max_vsram ? MAX_VSRAM_SIZE : MIN_VSRAM_SIZE;
+	context->type = type;
 
 	if (!color_map_init_done) {
 		uint8_t b,g,r;
@@ -174,9 +175,16 @@
 				g = levels[((color >> 5) & 0x7) + 7];
 				r = levels[((color >> 1) & 0x7) + 7];
 			} else if(color & FBUF_MODE4) {
-				b = levels[(color >> 4 & 0xC) | (color >> 6 & 0x2)];
-				g = levels[(color >> 2 & 0x8) | (color >> 1 & 0x4) | (color >> 4 & 0x2)];
-				r = levels[(color << 1 & 0xC) | (color >> 1 & 0x2)];
+				if (type == VDP_GAMEGEAR) {
+					b = (color >> 8 & 0xF) * 0x11;
+					g = (color >> 4 & 0xF) * 0x11;
+					r = (color & 0xF) * 0x11;
+				} else {
+					//TODO: Mode 4 has a separate DAC tap so this isn't quite correct
+					b = levels[(color >> 4 & 0xC) | (color >> 6 & 0x2)];
+					g = levels[(color >> 2 & 0x8) | (color >> 1 & 0x4) | (color >> 4 & 0x2)];
+					r = levels[(color << 1 & 0xC) | (color >> 1 & 0x2)];
+				}
 			} else {
 				b = levels[(color >> 8) & 0xE];
 				g = levels[(color >> 4) & 0xE];
@@ -805,7 +813,11 @@
 	context->colors[index] = color_map[value & CRAM_BITS];
 	context->colors[index + SHADOW_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_SHADOW];
 	context->colors[index + HIGHLIGHT_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_HILIGHT];
-	context->colors[index + MODE4_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_MODE4];
+	if (context->type == VDP_GAMEGEAR) {
+		context->colors[index + MODE4_OFFSET] = color_map[(value & 0xFFF) | FBUF_MODE4];
+	} else {
+		context->colors[index + MODE4_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_MODE4];
+	}
 }
 
 void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value)
@@ -819,6 +831,8 @@
 	uint16_t addr;
 	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
 		addr = (address/2) & (CRAM_SIZE-1);
+	} else if (context->type == VDP_GAMEGEAR) {
+		addr = (address/2) & 31;
 	} else {
 		addr = address & 0x1F;
 		value = (value << 1 & 0xE) | (value << 2 & 0xE0) | (value & 0xE00);
@@ -940,7 +954,14 @@
 			//printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1));
 			uint16_t val;
 			if (start->partial == 3) {
-				if ((start->address & 1) && (context->regs[REG_MODE_2] & BIT_MODE_5)) {
+				if (context->type == VDP_GAMEGEAR) {
+					if (start->address & 1) {
+						val = start->value << 8 | context->cram_latch;
+					} else {
+						context->cram_latch = start->value;
+						break;
+					}
+				} else if ((start->address & 1) && (context->regs[REG_MODE_2] & BIT_MODE_5)) {
 					val = (context->cram[start->address >> 1 & (CRAM_SIZE-1)] & 0xFF) | start->value << 8;
 				} else {
 					uint16_t address = (context->regs[REG_MODE_2] & BIT_MODE_5) ? start->address >> 1 & (CRAM_SIZE-1) : start->address & 0x1F;