Mercurial > repos > blastem
comparison 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 |
comparison
equal
deleted
inserted
replaced
2193:d00fb9c6a6a2 | 2194:01ff005b08f6 |
---|---|
144 context->top_offset = border_top - context->border_top; | 144 context->top_offset = border_top - context->border_top; |
145 } | 145 } |
146 | 146 |
147 static uint8_t color_map_init_done; | 147 static uint8_t color_map_init_done; |
148 | 148 |
149 vdp_context *init_vdp_context(uint8_t region_pal, uint8_t has_max_vsram) | 149 vdp_context *init_vdp_context(uint8_t region_pal, uint8_t has_max_vsram, uint8_t type) |
150 { | 150 { |
151 vdp_context *context = calloc(1, sizeof(vdp_context) + VRAM_SIZE); | 151 vdp_context *context = calloc(1, sizeof(vdp_context) + VRAM_SIZE); |
152 if (headless) { | 152 if (headless) { |
153 context->fb = malloc(512 * LINEBUF_SIZE * sizeof(uint32_t)); | 153 context->fb = malloc(512 * LINEBUF_SIZE * sizeof(uint32_t)); |
154 context->output_pitch = LINEBUF_SIZE * sizeof(uint32_t); | 154 context->output_pitch = LINEBUF_SIZE * sizeof(uint32_t); |
159 context->sprite_draws = MAX_SPRITES_LINE; | 159 context->sprite_draws = MAX_SPRITES_LINE; |
160 context->fifo_write = 0; | 160 context->fifo_write = 0; |
161 context->fifo_read = -1; | 161 context->fifo_read = -1; |
162 context->regs[REG_HINT] = context->hint_counter = 0xFF; | 162 context->regs[REG_HINT] = context->hint_counter = 0xFF; |
163 context->vsram_size = has_max_vsram ? MAX_VSRAM_SIZE : MIN_VSRAM_SIZE; | 163 context->vsram_size = has_max_vsram ? MAX_VSRAM_SIZE : MIN_VSRAM_SIZE; |
164 context->type = type; | |
164 | 165 |
165 if (!color_map_init_done) { | 166 if (!color_map_init_done) { |
166 uint8_t b,g,r; | 167 uint8_t b,g,r; |
167 for (uint16_t color = 0; color < (1 << 12); color++) { | 168 for (uint16_t color = 0; color < (1 << 12); color++) { |
168 if (color & FBUF_SHADOW) { | 169 if (color & FBUF_SHADOW) { |
172 } else if(color & FBUF_HILIGHT) { | 173 } else if(color & FBUF_HILIGHT) { |
173 b = levels[((color >> 9) & 0x7) + 7]; | 174 b = levels[((color >> 9) & 0x7) + 7]; |
174 g = levels[((color >> 5) & 0x7) + 7]; | 175 g = levels[((color >> 5) & 0x7) + 7]; |
175 r = levels[((color >> 1) & 0x7) + 7]; | 176 r = levels[((color >> 1) & 0x7) + 7]; |
176 } else if(color & FBUF_MODE4) { | 177 } else if(color & FBUF_MODE4) { |
177 b = levels[(color >> 4 & 0xC) | (color >> 6 & 0x2)]; | 178 if (type == VDP_GAMEGEAR) { |
178 g = levels[(color >> 2 & 0x8) | (color >> 1 & 0x4) | (color >> 4 & 0x2)]; | 179 b = (color >> 8 & 0xF) * 0x11; |
179 r = levels[(color << 1 & 0xC) | (color >> 1 & 0x2)]; | 180 g = (color >> 4 & 0xF) * 0x11; |
181 r = (color & 0xF) * 0x11; | |
182 } else { | |
183 //TODO: Mode 4 has a separate DAC tap so this isn't quite correct | |
184 b = levels[(color >> 4 & 0xC) | (color >> 6 & 0x2)]; | |
185 g = levels[(color >> 2 & 0x8) | (color >> 1 & 0x4) | (color >> 4 & 0x2)]; | |
186 r = levels[(color << 1 & 0xC) | (color >> 1 & 0x2)]; | |
187 } | |
180 } else { | 188 } else { |
181 b = levels[(color >> 8) & 0xE]; | 189 b = levels[(color >> 8) & 0xE]; |
182 g = levels[(color >> 4) & 0xE]; | 190 g = levels[(color >> 4) & 0xE]; |
183 r = levels[color & 0xE]; | 191 r = levels[color & 0xE]; |
184 } | 192 } |
803 static void update_color_map(vdp_context *context, uint16_t index, uint16_t value) | 811 static void update_color_map(vdp_context *context, uint16_t index, uint16_t value) |
804 { | 812 { |
805 context->colors[index] = color_map[value & CRAM_BITS]; | 813 context->colors[index] = color_map[value & CRAM_BITS]; |
806 context->colors[index + SHADOW_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_SHADOW]; | 814 context->colors[index + SHADOW_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_SHADOW]; |
807 context->colors[index + HIGHLIGHT_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_HILIGHT]; | 815 context->colors[index + HIGHLIGHT_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_HILIGHT]; |
808 context->colors[index + MODE4_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_MODE4]; | 816 if (context->type == VDP_GAMEGEAR) { |
817 context->colors[index + MODE4_OFFSET] = color_map[(value & 0xFFF) | FBUF_MODE4]; | |
818 } else { | |
819 context->colors[index + MODE4_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_MODE4]; | |
820 } | |
809 } | 821 } |
810 | 822 |
811 void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value) | 823 void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value) |
812 { | 824 { |
813 context->cram[addr] = value; | 825 context->cram[addr] = value; |
817 static void write_cram(vdp_context * context, uint16_t address, uint16_t value) | 829 static void write_cram(vdp_context * context, uint16_t address, uint16_t value) |
818 { | 830 { |
819 uint16_t addr; | 831 uint16_t addr; |
820 if (context->regs[REG_MODE_2] & BIT_MODE_5) { | 832 if (context->regs[REG_MODE_2] & BIT_MODE_5) { |
821 addr = (address/2) & (CRAM_SIZE-1); | 833 addr = (address/2) & (CRAM_SIZE-1); |
834 } else if (context->type == VDP_GAMEGEAR) { | |
835 addr = (address/2) & 31; | |
822 } else { | 836 } else { |
823 addr = address & 0x1F; | 837 addr = address & 0x1F; |
824 value = (value << 1 & 0xE) | (value << 2 & 0xE0) | (value & 0xE00); | 838 value = (value << 1 & 0xE) | (value << 2 & 0xE0) | (value & 0xE00); |
825 } | 839 } |
826 write_cram_internal(context, addr, value); | 840 write_cram_internal(context, addr, value); |
938 break; | 952 break; |
939 case CRAM_WRITE: { | 953 case CRAM_WRITE: { |
940 //printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1)); | 954 //printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1)); |
941 uint16_t val; | 955 uint16_t val; |
942 if (start->partial == 3) { | 956 if (start->partial == 3) { |
943 if ((start->address & 1) && (context->regs[REG_MODE_2] & BIT_MODE_5)) { | 957 if (context->type == VDP_GAMEGEAR) { |
958 if (start->address & 1) { | |
959 val = start->value << 8 | context->cram_latch; | |
960 } else { | |
961 context->cram_latch = start->value; | |
962 break; | |
963 } | |
964 } else if ((start->address & 1) && (context->regs[REG_MODE_2] & BIT_MODE_5)) { | |
944 val = (context->cram[start->address >> 1 & (CRAM_SIZE-1)] & 0xFF) | start->value << 8; | 965 val = (context->cram[start->address >> 1 & (CRAM_SIZE-1)] & 0xFF) | start->value << 8; |
945 } else { | 966 } else { |
946 uint16_t address = (context->regs[REG_MODE_2] & BIT_MODE_5) ? start->address >> 1 & (CRAM_SIZE-1) : start->address & 0x1F; | 967 uint16_t address = (context->regs[REG_MODE_2] & BIT_MODE_5) ? start->address >> 1 & (CRAM_SIZE-1) : start->address & 0x1F; |
947 val = (context->cram[address] & 0xFF00) | start->value; | 968 val = (context->cram[address] & 0xFF00) | start->value; |
948 } | 969 } |