# HG changeset patch # User Michael Pavone # Date 1661146187 25200 # Node ID 01ff005b08f600fbaf968186d84bcbed80f8550a # Parent d00fb9c6a6a20734d6a004118b00963a9dcafc2b Very rudimentary support for Game Gear VDP emulation diff -r d00fb9c6a6a2 -r 01ff005b08f6 gen_player.c --- a/gen_player.c Sun Aug 21 16:41:22 2022 -0700 +++ b/gen_player.c Sun Aug 21 22:29:47 2022 -0700 @@ -12,7 +12,7 @@ #ifdef IS_LIB #define MAX_SOUND_CYCLES (MCLKS_PER_YM*NUM_OPERATORS*6*4) #else -#define MAX_SOUND_CYCLES 100000 +#define MAX_SOUND_CYCLES 100000 #endif static void sync_sound(gen_player *gen, uint32_t target) @@ -92,7 +92,7 @@ vdp_replay_event(player->vdp, event, &player->reader); } } - + } if (!player->reader.socket) { reader_ensure_data(&player->reader, 1); @@ -136,17 +136,17 @@ uint8_t name_len = load_int8(&player->reader.buffer); player->header.info.name = calloc(1, name_len + 1); load_buffer8(&player->reader.buffer, player->header.info.name, name_len); - - player->vdp = init_vdp_context(vid_std == VID_PAL, 0); + + player->vdp = init_vdp_context(vid_std == VID_PAL, 0, VDP_GENESIS); render_set_video_standard(vid_std); uint32_t master_clock = vid_std == VID_NTSC ? MCLKS_NTSC : MCLKS_PAL; - + player->ym = malloc(sizeof(ym2612_context)); ym_init(player->ym, master_clock, MCLKS_PER_YM, 0); - + player->psg = malloc(sizeof(psg_context)); psg_init(player->psg, master_clock, MCLKS_PER_PSG); - + player->header.start_context = start_context; player->header.gamepad_down = gamepad_down; player->header.gamepad_up = gamepad_up; diff -r d00fb9c6a6a2 -r 01ff005b08f6 genesis.c --- a/genesis.c Sun Aug 21 16:41:22 2022 -0700 +++ b/genesis.c Sun Aug 21 22:29:47 2022 -0700 @@ -1873,7 +1873,7 @@ } uint8_t max_vsram = !strcmp(tern_find_ptr_default(model, "vsram", "40"), "64"); - gen->vdp = init_vdp_context(gen->version_reg & 0x40, max_vsram); + gen->vdp = init_vdp_context(gen->version_reg & 0x40, max_vsram, VDP_GENESIS); gen->vdp->system = &gen->header; gen->frame_end = vdp_cycles_to_frame_end(gen->vdp); char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval; diff -r d00fb9c6a6a2 -r 01ff005b08f6 sms.c --- a/sms.c Sun Aug 21 16:41:22 2022 -0700 +++ b/sms.c Sun Aug 21 22:29:47 2022 -0700 @@ -397,7 +397,7 @@ system->enter_debugger_frames -= elapsed; } } - + if(exit_after){ if (elapsed >= exit_after) { exit(0); @@ -650,7 +650,7 @@ set_gain_config(sms); - sms->vdp = init_vdp_context(0, 0); + sms->vdp = init_vdp_context(0, 0, strcasecmp(media->extension, "gg") ? VDP_GENESIS : VDP_GAMEGEAR); sms->vdp->system = &sms->header; sms->header.info.save_type = SAVE_NONE; diff -r d00fb9c6a6a2 -r 01ff005b08f6 vdp.c --- 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; diff -r d00fb9c6a6a2 -r 01ff005b08f6 vdp.h --- a/vdp.h Sun Aug 21 16:41:22 2022 -0700 +++ b/vdp.h Sun Aug 21 22:29:47 2022 -0700 @@ -163,6 +163,14 @@ VDP_NUM_DEBUG_TYPES }; +enum { + VDP_GENESIS, + VDP_GAMEGEAR, + VDP_SMS2, + VDP_SMS, + VDP_TMS9918A +}; + typedef struct { system_header *system; //pointer to current line in framebuffer @@ -245,12 +253,14 @@ uint8_t debug_fb_indices[VDP_NUM_DEBUG_TYPES]; uint8_t debug_modes[VDP_NUM_DEBUG_TYPES]; uint8_t pushed_frame; + uint8_t type; + uint8_t cram_latch; uint8_t vdpmem[]; } vdp_context; -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); void vdp_free(vdp_context *context); void vdp_run_context_full(vdp_context * context, uint32_t target_cycles); void vdp_run_context(vdp_context * context, uint32_t target_cycles);