Mercurial > repos > blastem
comparison vdp.c @ 2685:da2e06c42d16
Add a compile-time flag to use RGB565 instead of ABGR/ARGB
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 30 Mar 2025 00:06:53 -0700 |
parents | dbff641a33df |
children | 05915f01046d |
comparison
equal
deleted
inserted
replaced
2684:c649bcc18487 | 2685:da2e06c42d16 |
---|---|
158 | 158 |
159 vdp_context *init_vdp_context(uint8_t region_pal, uint8_t has_max_vsram, uint8_t type) | 159 vdp_context *init_vdp_context(uint8_t region_pal, uint8_t has_max_vsram, uint8_t type) |
160 { | 160 { |
161 vdp_context *context = calloc(1, sizeof(vdp_context) + VRAM_SIZE); | 161 vdp_context *context = calloc(1, sizeof(vdp_context) + VRAM_SIZE); |
162 if (headless) { | 162 if (headless) { |
163 context->fb = malloc(512 * LINEBUF_SIZE * sizeof(uint32_t)); | 163 context->fb = malloc(512 * LINEBUF_SIZE * sizeof(pixel_t)); |
164 context->output_pitch = LINEBUF_SIZE * sizeof(uint32_t); | 164 context->output_pitch = LINEBUF_SIZE * sizeof(pixel_t); |
165 } else { | 165 } else { |
166 context->cur_buffer = FRAMEBUFFER_ODD; | 166 context->cur_buffer = FRAMEBUFFER_ODD; |
167 context->fb = render_get_framebuffer(FRAMEBUFFER_ODD, &context->output_pitch); | 167 context->fb = render_get_framebuffer(FRAMEBUFFER_ODD, &context->output_pitch); |
168 } | 168 } |
169 context->sprite_draws = MAX_SPRITES_LINE; | 169 context->sprite_draws = MAX_SPRITES_LINE; |
337 } | 337 } |
338 if (region_pal) { | 338 if (region_pal) { |
339 context->flags2 |= FLAG2_REGION_PAL; | 339 context->flags2 |= FLAG2_REGION_PAL; |
340 } | 340 } |
341 update_video_params(context); | 341 update_video_params(context); |
342 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * context->border_top); | 342 context->output = (pixel_t *)(((char *)context->fb) + context->output_pitch * context->border_top); |
343 return context; | 343 return context; |
344 } | 344 } |
345 | 345 |
346 void vdp_free(vdp_context *context) | 346 void vdp_free(vdp_context *context) |
347 { | 347 { |
997 context->vcounter < context->inactive_start + context->border_bot | 997 context->vcounter < context->inactive_start + context->border_bot |
998 || context->vcounter > 0x200 - context->border_top | 998 || context->vcounter > 0x200 - context->border_top |
999 )) { | 999 )) { |
1000 uint8_t bg_end_slot = BG_START_SLOT + (context->regs[REG_MODE_4] & BIT_H40) ? LINEBUF_SIZE/2 : (256+HORIZ_BORDER)/2; | 1000 uint8_t bg_end_slot = BG_START_SLOT + (context->regs[REG_MODE_4] & BIT_H40) ? LINEBUF_SIZE/2 : (256+HORIZ_BORDER)/2; |
1001 if (context->hslot < bg_end_slot) { | 1001 if (context->hslot < bg_end_slot) { |
1002 uint32_t color = (context->regs[REG_MODE_2] & BIT_MODE_5) ? context->colors[addr] : context->colors[addr + MODE4_OFFSET]; | 1002 pixel_t color = (context->regs[REG_MODE_2] & BIT_MODE_5) ? context->colors[addr] : context->colors[addr + MODE4_OFFSET]; |
1003 context->output[(context->hslot - BG_START_SLOT)*2 + 1] = color; | 1003 context->output[(context->hslot - BG_START_SLOT)*2 + 1] = color; |
1004 } | 1004 } |
1005 } | 1005 } |
1006 } | 1006 } |
1007 | 1007 |
1818 if (col) { | 1818 if (col) { |
1819 col -= 2; | 1819 col -= 2; |
1820 dst = context->compositebuf + BORDER_LEFT + col * 8; | 1820 dst = context->compositebuf + BORDER_LEFT + col * 8; |
1821 } else { | 1821 } else { |
1822 dst = context->compositebuf; | 1822 dst = context->compositebuf; |
1823 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; | 1823 pixel_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; |
1824 memset(dst, 0, BORDER_LEFT); | 1824 memset(dst, 0, BORDER_LEFT); |
1825 context->done_composite = dst + BORDER_LEFT; | 1825 context->done_composite = dst + BORDER_LEFT; |
1826 return; | 1826 return; |
1827 } | 1827 } |
1828 memset(dst, 0, 16); | 1828 memset(dst, 0, 16); |
2057 line -= total_lines - context->border_top; | 2057 line -= total_lines - context->border_top; |
2058 } else { | 2058 } else { |
2059 line += context->border_top; | 2059 line += context->border_top; |
2060 } | 2060 } |
2061 if (context->enabled_debuggers & (1 << DEBUG_CRAM)) { | 2061 if (context->enabled_debuggers & (1 << DEBUG_CRAM)) { |
2062 uint32_t *fb = context->debug_fbs[DEBUG_CRAM] + context->debug_fb_pitch[DEBUG_CRAM] * line / sizeof(uint32_t); | 2062 pixel_t *fb = context->debug_fbs[DEBUG_CRAM] + context->debug_fb_pitch[DEBUG_CRAM] * line / sizeof(pixel_t); |
2063 if (context->regs[REG_MODE_2] & BIT_MODE_5) { | 2063 if (context->regs[REG_MODE_2] & BIT_MODE_5) { |
2064 for (int i = 0; i < 64; i++) | 2064 for (int i = 0; i < 64; i++) |
2065 { | 2065 { |
2066 for (int x = 0; x < 8; x++) | 2066 for (int x = 0; x < 8; x++) |
2067 { | 2067 { |
2080 uint16_t address = context->regs[REG_COLOR_TABLE] << 6; | 2080 uint16_t address = context->regs[REG_COLOR_TABLE] << 6; |
2081 for (int i = 0; i < 32; i++, address++) | 2081 for (int i = 0; i < 32; i++, address++) |
2082 { | 2082 { |
2083 uint8_t entry = context->vdpmem[mode4_address_map[address] ^ 1]; | 2083 uint8_t entry = context->vdpmem[mode4_address_map[address] ^ 1]; |
2084 uint8_t fg = entry >> 4, bg = entry & 0xF; | 2084 uint8_t fg = entry >> 4, bg = entry & 0xF; |
2085 uint32_t fg_full, bg_full; | 2085 pixel_t fg_full, bg_full; |
2086 if (context->type == VDP_GAMEGEAR) { | 2086 if (context->type == VDP_GAMEGEAR) { |
2087 //Game Gear uses CRAM entries 16-31 for TMS9918A modes | 2087 //Game Gear uses CRAM entries 16-31 for TMS9918A modes |
2088 fg_full = context->colors[fg + 16 + MODE4_OFFSET]; | 2088 fg_full = context->colors[fg + 16 + MODE4_OFFSET]; |
2089 bg_full = context->colors[bg + 16 + MODE4_OFFSET]; | 2089 bg_full = context->colors[bg + 16 + MODE4_OFFSET]; |
2090 } else { | 2090 } else { |
2108 } | 2108 } |
2109 if ( | 2109 if ( |
2110 context->enabled_debuggers & (1 << DEBUG_COMPOSITE) | 2110 context->enabled_debuggers & (1 << DEBUG_COMPOSITE) |
2111 && line < (context->inactive_start + context->border_bot + context->border_top) | 2111 && line < (context->inactive_start + context->border_bot + context->border_top) |
2112 ) { | 2112 ) { |
2113 uint32_t *fb = context->debug_fbs[DEBUG_COMPOSITE] + context->debug_fb_pitch[DEBUG_COMPOSITE] * line / sizeof(uint32_t); | 2113 pixel_t *fb = context->debug_fbs[DEBUG_COMPOSITE] + context->debug_fb_pitch[DEBUG_COMPOSITE] * line / sizeof(pixel_t); |
2114 if (is_mode_5) { | 2114 if (is_mode_5) { |
2115 uint32_t left, right; | 2115 uint32_t left, right; |
2116 uint16_t top_line, bottom_line; | 2116 uint16_t top_line, bottom_line; |
2117 if (context->window_v_latch & WINDOW_DOWN) { | 2117 if (context->window_v_latch & WINDOW_DOWN) { |
2118 top_line = ((context->window_v_latch & 0x1F) << 3) + context->border_top; | 2118 top_line = ((context->window_v_latch & 0x1F) << 3) + context->border_top; |
2173 context->pending_hint_start = context->cycles; | 2173 context->pending_hint_start = context->cycles; |
2174 context->hint_counter = context->regs[REG_HINT]; | 2174 context->hint_counter = context->regs[REG_HINT]; |
2175 } | 2175 } |
2176 } | 2176 } |
2177 | 2177 |
2178 static void vram_debug_mode5(uint32_t *fb, uint32_t pitch, vdp_context *context) | 2178 static void vram_debug_mode5(pixel_t *fb, uint32_t pitch, vdp_context *context) |
2179 { | 2179 { |
2180 uint8_t pal = (context->debug_modes[DEBUG_VRAM] % 4) << 4; | 2180 uint8_t pal = (context->debug_modes[DEBUG_VRAM] % 4) << 4; |
2181 int yshift, ymask, tilesize; | 2181 int yshift, ymask, tilesize; |
2182 if (context->double_res) { | 2182 if (context->double_res) { |
2183 yshift = 5; | 2183 yshift = 5; |
2188 ymask = 0x7; | 2188 ymask = 0x7; |
2189 tilesize = 32; | 2189 tilesize = 32; |
2190 } | 2190 } |
2191 for (int y = 0; y < 512; y++) | 2191 for (int y = 0; y < 512; y++) |
2192 { | 2192 { |
2193 uint32_t *line = fb + y * pitch / sizeof(uint32_t); | 2193 pixel_t *line = fb + y * pitch / sizeof(pixel_t); |
2194 int row = y >> yshift; | 2194 int row = y >> yshift; |
2195 int yoff = y >> 1 & ymask; | 2195 int yoff = y >> 1 & ymask; |
2196 for (int col = 0; col < 64; col++) | 2196 for (int col = 0; col < 64; col++) |
2197 { | 2197 { |
2198 uint16_t address = (row * 64 + col) * tilesize + yoff * 4; | 2198 uint16_t address = (row * 64 + col) * tilesize + yoff * 4; |
2208 } | 2208 } |
2209 } | 2209 } |
2210 } | 2210 } |
2211 } | 2211 } |
2212 | 2212 |
2213 static void vram_debug_mode4(uint32_t *fb, uint32_t pitch, vdp_context *context) | 2213 static void vram_debug_mode4(pixel_t *fb, uint32_t pitch, vdp_context *context) |
2214 { | 2214 { |
2215 for (int y = 0; y < 256; y++) | 2215 for (int y = 0; y < 256; y++) |
2216 { | 2216 { |
2217 uint32_t *line = fb + y * pitch / sizeof(uint32_t); | 2217 pixel_t *line = fb + y * pitch / sizeof(pixel_t); |
2218 int row = y >> 4; | 2218 int row = y >> 4; |
2219 int yoff = y >> 1 & 7; | 2219 int yoff = y >> 1 & 7; |
2220 for (int col = 0; col < 64; col++) | 2220 for (int col = 0; col < 64; col++) |
2221 { | 2221 { |
2222 uint8_t pal = (col >= 32) << 4; | 2222 uint8_t pal = (col >= 32) << 4; |
2235 } | 2235 } |
2236 } | 2236 } |
2237 } | 2237 } |
2238 } | 2238 } |
2239 | 2239 |
2240 static void vram_debug_tms(uint32_t *fb, uint32_t pitch, vdp_context *context) | 2240 static void vram_debug_tms(pixel_t *fb, uint32_t pitch, vdp_context *context) |
2241 { | 2241 { |
2242 uint8_t pal = ((context->debug_modes[DEBUG_VRAM] % 14) + 2) << 1; | 2242 uint8_t pal = ((context->debug_modes[DEBUG_VRAM] % 14) + 2) << 1; |
2243 pal = (pal & 0xE) | (pal << 1 & 0x20); | 2243 pal = (pal & 0xE) | (pal << 1 & 0x20); |
2244 for (int y = 0; y < 512; y++) | 2244 for (int y = 0; y < 512; y++) |
2245 { | 2245 { |
2246 uint32_t *line = fb + y * pitch / sizeof(uint32_t); | 2246 pixel_t *line = fb + y * pitch / sizeof(pixel_t); |
2247 int row = y >> 4; | 2247 int row = y >> 4; |
2248 int yoff = y >> 1 & 7; | 2248 int yoff = y >> 1 & 7; |
2249 for (int col = 0; col < 64; col++) | 2249 for (int col = 0; col < 64; col++) |
2250 { | 2250 { |
2251 uint16_t address = (row * 64 + col) * 8 + yoff; | 2251 uint16_t address = (row * 64 + col) * 8 + yoff; |
2259 } | 2259 } |
2260 } | 2260 } |
2261 } | 2261 } |
2262 } | 2262 } |
2263 | 2263 |
2264 static void plane_debug_mode5(uint32_t *fb, uint32_t pitch, vdp_context *context) | 2264 static void plane_debug_mode5(pixel_t *fb, uint32_t pitch, vdp_context *context) |
2265 { | 2265 { |
2266 uint16_t hscroll_mask; | 2266 uint16_t hscroll_mask; |
2267 uint16_t v_mul; | 2267 uint16_t v_mul; |
2268 uint16_t vscroll_mask = 0x1F | (context->regs[REG_SCROLL] & 0x30) << 1; | 2268 uint16_t vscroll_mask = 0x1F | (context->regs[REG_SCROLL] & 0x30) << 1; |
2269 switch(context->regs[REG_SCROLL] & 0x3) | 2269 switch(context->regs[REG_SCROLL] & 0x3) |
2307 hscroll_mask = 0x1F; | 2307 hscroll_mask = 0x1F; |
2308 } | 2308 } |
2309 vscroll_mask = 0x1F; | 2309 vscroll_mask = 0x1F; |
2310 break; | 2310 break; |
2311 } | 2311 } |
2312 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; | 2312 pixel_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; |
2313 uint16_t num_rows; | 2313 uint16_t num_rows; |
2314 int num_lines; | 2314 int num_lines; |
2315 if (context->double_res) { | 2315 if (context->double_res) { |
2316 num_rows = 64; | 2316 num_rows = 64; |
2317 num_lines = 16; | 2317 num_lines = 16; |
2328 //pccv hnnn nnnn nnnn | 2328 //pccv hnnn nnnn nnnn |
2329 // | 2329 // |
2330 uint16_t entry = context->vdpmem[address] << 8 | context->vdpmem[address + 1]; | 2330 uint16_t entry = context->vdpmem[address] << 8 | context->vdpmem[address + 1]; |
2331 uint8_t pal = entry >> 9 & 0x30; | 2331 uint8_t pal = entry >> 9 & 0x30; |
2332 | 2332 |
2333 uint32_t *dst = fb + (row * pitch * num_lines / sizeof(uint32_t)) + col * 8; | 2333 pixel_t *dst = fb + (row * pitch * num_lines / sizeof(pixel_t)) + col * 8; |
2334 if (context->double_res) { | 2334 if (context->double_res) { |
2335 address = (entry & 0x3FF) * 64; | 2335 address = (entry & 0x3FF) * 64; |
2336 } else { | 2336 } else { |
2337 address = (entry & 0x7FF) * 32; | 2337 address = (entry & 0x7FF) * 32; |
2338 } | 2338 } |
2347 address += 3; | 2347 address += 3; |
2348 } | 2348 } |
2349 for (int y = 0; y < num_lines; y++) | 2349 for (int y = 0; y < num_lines; y++) |
2350 { | 2350 { |
2351 uint16_t trow_address = address; | 2351 uint16_t trow_address = address; |
2352 uint32_t *row_dst = dst; | 2352 pixel_t *row_dst = dst; |
2353 for (int x = 0; x < 4; x++) | 2353 for (int x = 0; x < 4; x++) |
2354 { | 2354 { |
2355 uint8_t byte = context->vdpmem[trow_address]; | 2355 uint8_t byte = context->vdpmem[trow_address]; |
2356 trow_address += x_diff; | 2356 trow_address += x_diff; |
2357 uint8_t left, right; | 2357 uint8_t left, right; |
2364 } | 2364 } |
2365 *(row_dst++) = left ? context->colors[left|pal] : bg_color; | 2365 *(row_dst++) = left ? context->colors[left|pal] : bg_color; |
2366 *(row_dst++) = right ? context->colors[right|pal] : bg_color; | 2366 *(row_dst++) = right ? context->colors[right|pal] : bg_color; |
2367 } | 2367 } |
2368 address += y_diff; | 2368 address += y_diff; |
2369 dst += pitch / sizeof(uint32_t); | 2369 dst += pitch / sizeof(pixel_t); |
2370 } | 2370 } |
2371 } | 2371 } |
2372 } | 2372 } |
2373 } | 2373 } |
2374 | 2374 |
2375 static void sprite_debug_mode5(uint32_t *fb, uint32_t pitch, vdp_context *context) | 2375 static void sprite_debug_mode5(pixel_t *fb, uint32_t pitch, vdp_context *context) |
2376 { | 2376 { |
2377 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; | 2377 pixel_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; |
2378 //clear a single alpha channel bit so we can distinguish between actual bg color and sprite | 2378 //clear a single alpha channel bit so we can distinguish between actual bg color and sprite |
2379 //pixels that just happen to be the same color | 2379 //pixels that just happen to be the same color |
2380 bg_color &= 0xFEFFFFFF; | 2380 bg_color &= 0xFEFFFFFF; |
2381 uint32_t *line = fb; | 2381 pixel_t *line = fb; |
2382 uint32_t border_line = render_map_color(0, 0, 255); | 2382 pixel_t border_line = render_map_color(0, 0, 255); |
2383 uint32_t sprite_outline = render_map_color(255, 0, 255); | 2383 pixel_t sprite_outline = render_map_color(255, 0, 255); |
2384 int right_border = 256 + ((context->h40_lines > context->output_lines / 2) ? 640 : 512); | 2384 int right_border = 256 + ((context->h40_lines > context->output_lines / 2) ? 640 : 512); |
2385 for (int y = 0; y < 1024; y++) | 2385 for (int y = 0; y < 1024; y++) |
2386 { | 2386 { |
2387 uint32_t *cur = line; | 2387 pixel_t *cur = line; |
2388 if (y != 256 && y != 256+context->inactive_start*2) { | 2388 if (y != 256 && y != 256+context->inactive_start*2) { |
2389 for (int x = 0; x < 255; x++) | 2389 for (int x = 0; x < 255; x++) |
2390 { | 2390 { |
2391 *(cur++) = bg_color; | 2391 *(cur++) = bg_color; |
2392 } | 2392 } |
2404 for (int x = 0; x < 1024; x++) | 2404 for (int x = 0; x < 1024; x++) |
2405 { | 2405 { |
2406 *(cur++) = border_line; | 2406 *(cur++) = border_line; |
2407 } | 2407 } |
2408 } | 2408 } |
2409 line += pitch / sizeof(uint32_t); | 2409 line += pitch / sizeof(pixel_t); |
2410 } | 2410 } |
2411 for (int i = 0, index = 0; i < context->max_sprites_frame; i++) | 2411 for (int i = 0, index = 0; i < context->max_sprites_frame; i++) |
2412 { | 2412 { |
2413 uint32_t y = (context->sat_cache[index] & 3) << 8 | context->sat_cache[index + 1]; | 2413 uint32_t y = (context->sat_cache[index] & 3) << 8 | context->sat_cache[index + 1]; |
2414 if (!context->double_res) { | 2414 if (!context->double_res) { |
2429 } | 2429 } |
2430 uint8_t pal = (tileinfo >> 9) & 0x30; | 2430 uint8_t pal = (tileinfo >> 9) & 0x30; |
2431 uint16_t hflip = tileinfo & MAP_BIT_H_FLIP; | 2431 uint16_t hflip = tileinfo & MAP_BIT_H_FLIP; |
2432 uint16_t vflip = tileinfo & MAP_BIT_V_FLIP; | 2432 uint16_t vflip = tileinfo & MAP_BIT_V_FLIP; |
2433 uint32_t x = (((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF) * 2; | 2433 uint32_t x = (((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF) * 2; |
2434 uint32_t *line = fb + y * pitch / sizeof(uint32_t) + x; | 2434 pixel_t *line = fb + y * pitch / sizeof(pixel_t) + x; |
2435 uint32_t *cur = line; | 2435 pixel_t *cur = line; |
2436 for (uint32_t cx = x, x2 = x + pixel_width; cx < x2; cx++) | 2436 for (uint32_t cx = x, x2 = x + pixel_width; cx < x2; cx++) |
2437 { | 2437 { |
2438 *(cur++) = sprite_outline; | 2438 *(cur++) = sprite_outline; |
2439 } | 2439 } |
2440 uint8_t advance_source = 1; | 2440 uint8_t advance_source = 1; |
2451 tile_addr += col_offset * tile_width + 3; | 2451 tile_addr += col_offset * tile_width + 3; |
2452 col_offset = -col_offset; | 2452 col_offset = -col_offset; |
2453 } | 2453 } |
2454 for (; y < y2; y++) | 2454 for (; y < y2; y++) |
2455 { | 2455 { |
2456 line += pitch / sizeof(uint32_t); | 2456 line += pitch / sizeof(pixel_t); |
2457 cur = line; | 2457 cur = line; |
2458 *(cur++) = sprite_outline; | 2458 *(cur++) = sprite_outline; |
2459 uint16_t line_addr = tile_addr; | 2459 uint16_t line_addr = tile_addr; |
2460 for (uint8_t tx = 0; tx <= tile_width; tx++) | 2460 for (uint8_t tx = 0; tx <= tile_width; tx++) |
2461 { | 2461 { |
2462 uint16_t cur_addr = line_addr; | 2462 uint16_t cur_addr = line_addr; |
2463 for (uint8_t cx = 0; cx < 4; cx++) | 2463 for (uint8_t cx = 0; cx < 4; cx++) |
2464 { | 2464 { |
2465 uint8_t pair = context->vdpmem[cur_addr]; | 2465 uint8_t pair = context->vdpmem[cur_addr]; |
2466 uint32_t left, right; | 2466 pixel_t left, right; |
2467 if (hflip) { | 2467 if (hflip) { |
2468 right = pair >> 4; | 2468 right = pair >> 4; |
2469 left = pair & 0xF; | 2469 left = pair & 0xF; |
2470 cur_addr--; | 2470 cur_addr--; |
2471 } else { | 2471 } else { |
2504 tile_addr += line_offset; | 2504 tile_addr += line_offset; |
2505 } | 2505 } |
2506 advance_source = !advance_source; | 2506 advance_source = !advance_source; |
2507 } | 2507 } |
2508 if (y2 != 1024) { | 2508 if (y2 != 1024) { |
2509 line += pitch / sizeof(uint32_t); | 2509 line += pitch / sizeof(pixel_t); |
2510 cur = line; | 2510 cur = line; |
2511 for (uint32_t cx = x, x2 = x + pixel_width; cx < x2; cx++) | 2511 for (uint32_t cx = x, x2 = x + pixel_width; cx < x2; cx++) |
2512 { | 2512 { |
2513 *(cur++) = sprite_outline; | 2513 *(cur++) = sprite_outline; |
2514 } | 2514 } |
2518 break; | 2518 break; |
2519 } | 2519 } |
2520 } | 2520 } |
2521 } | 2521 } |
2522 | 2522 |
2523 static void plane_debug_mode4(uint32_t *fb, uint32_t pitch, vdp_context *context) | 2523 static void plane_debug_mode4(pixel_t *fb, uint32_t pitch, vdp_context *context) |
2524 { | 2524 { |
2525 uint32_t bg_color = context->colors[(context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET]; | 2525 pixel_t bg_color = context->colors[(context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET]; |
2526 uint32_t address = (context->regs[REG_SCROLL_A] & 0xE) << 10; | 2526 uint32_t address = (context->regs[REG_SCROLL_A] & 0xE) << 10; |
2527 for (uint32_t row_address = address, end = address + 32*32*2; row_address < end; row_address += 2 * 32) | 2527 for (uint32_t row_address = address, end = address + 32*32*2; row_address < end; row_address += 2 * 32) |
2528 { | 2528 { |
2529 uint32_t *col = fb; | 2529 pixel_t *col = fb; |
2530 for(uint32_t cur = row_address, row_end = row_address + 2 * 32; cur < row_end; cur += 2) | 2530 for(uint32_t cur = row_address, row_end = row_address + 2 * 32; cur < row_end; cur += 2) |
2531 { | 2531 { |
2532 uint32_t mapped = mode4_address_map[cur]; | 2532 uint32_t mapped = mode4_address_map[cur]; |
2533 uint16_t entry = context->vdpmem[mapped] << 8 | context->vdpmem[mapped + 1]; | 2533 uint16_t entry = context->vdpmem[mapped] << 8 | context->vdpmem[mapped + 1]; |
2534 uint32_t tile_address = (entry & 0x1FF) << 5; | 2534 uint32_t tile_address = (entry & 0x1FF) << 5; |
2549 tile_address += 7*4; | 2549 tile_address += 7*4; |
2550 tile_inc = -4; | 2550 tile_inc = -4; |
2551 } else { | 2551 } else { |
2552 tile_inc = 4; | 2552 tile_inc = 4; |
2553 } | 2553 } |
2554 uint32_t *line = col; | 2554 pixel_t *line = col; |
2555 for (int y = 0; y < 16; y++) | 2555 for (int y = 0; y < 16; y++) |
2556 { | 2556 { |
2557 uint32_t first = mode4_address_map[tile_address]; | 2557 uint32_t first = mode4_address_map[tile_address]; |
2558 uint32_t last = mode4_address_map[tile_address + 2]; | 2558 uint32_t last = mode4_address_map[tile_address + 2]; |
2559 uint32_t pixels = planar_to_chunky[context->vdpmem[first]] << 1; | 2559 uint32_t pixels = planar_to_chunky[context->vdpmem[first]] << 1; |
2560 pixels |= planar_to_chunky[context->vdpmem[first+1]]; | 2560 pixels |= planar_to_chunky[context->vdpmem[first+1]]; |
2561 pixels |= planar_to_chunky[context->vdpmem[last]] << 3; | 2561 pixels |= planar_to_chunky[context->vdpmem[last]] << 3; |
2562 pixels |= planar_to_chunky[context->vdpmem[last+1]] << 2; | 2562 pixels |= planar_to_chunky[context->vdpmem[last+1]] << 2; |
2563 uint32_t *out = line; | 2563 pixel_t *out = line; |
2564 for (uint32_t i = i_init; i != i_limit; i += i_inc) | 2564 for (uint32_t i = i_init; i != i_limit; i += i_inc) |
2565 { | 2565 { |
2566 uint32_t pixel = context->colors[((pixels >> i & 0xF) | pal) + MODE4_OFFSET]; | 2566 pixel_t pixel = context->colors[((pixels >> i & 0xF) | pal) + MODE4_OFFSET]; |
2567 *(out++) = pixel; | 2567 *(out++) = pixel; |
2568 *(out++) = pixel; | 2568 *(out++) = pixel; |
2569 } | 2569 } |
2570 | 2570 |
2571 | 2571 |
2572 if (y & 1) { | 2572 if (y & 1) { |
2573 tile_address += tile_inc; | 2573 tile_address += tile_inc; |
2574 } | 2574 } |
2575 line += pitch / sizeof(uint32_t); | 2575 line += pitch / sizeof(pixel_t); |
2576 } | 2576 } |
2577 | 2577 |
2578 | 2578 |
2579 | 2579 |
2580 col += 16; | 2580 col += 16; |
2581 } | 2581 } |
2582 fb += 16 * pitch / sizeof(uint32_t); | 2582 fb += 16 * pitch / sizeof(pixel_t); |
2583 } | 2583 } |
2584 } | 2584 } |
2585 | 2585 |
2586 static void sprite_debug_mode4(uint32_t *fb, uint32_t pitch, vdp_context *context) | 2586 static void sprite_debug_mode4(pixel_t *fb, uint32_t pitch, vdp_context *context) |
2587 { | 2587 { |
2588 } | 2588 } |
2589 | 2589 |
2590 uint32_t tms_map_color(vdp_context *context, uint8_t color) | 2590 pixel_t tms_map_color(vdp_context *context, uint8_t color) |
2591 { | 2591 { |
2592 if (context->type == VDP_GAMEGEAR) { | 2592 if (context->type == VDP_GAMEGEAR) { |
2593 //Game Gear uses CRAM entries 16-31 for TMS9918A modes | 2593 //Game Gear uses CRAM entries 16-31 for TMS9918A modes |
2594 return context->colors[color + 16 + MODE4_OFFSET]; | 2594 return context->colors[color + 16 + MODE4_OFFSET]; |
2595 } else { | 2595 } else { |
2597 color = (color & 0xE) | (color << 1 & 0x20); | 2597 color = (color & 0xE) | (color << 1 & 0x20); |
2598 return context->color_map[color | FBUF_TMS]; | 2598 return context->color_map[color | FBUF_TMS]; |
2599 } | 2599 } |
2600 } | 2600 } |
2601 | 2601 |
2602 static void plane_debug_tms(uint32_t *fb, uint32_t pitch, vdp_context *context) | 2602 static void plane_debug_tms(pixel_t *fb, uint32_t pitch, vdp_context *context) |
2603 { | 2603 { |
2604 uint16_t table_address = context->regs[REG_SCROLL_A] << 10 & 0x3C00; | 2604 uint16_t table_address = context->regs[REG_SCROLL_A] << 10 & 0x3C00; |
2605 uint16_t color_address = context->regs[REG_COLOR_TABLE] << 6; | 2605 uint16_t color_address = context->regs[REG_COLOR_TABLE] << 6; |
2606 uint16_t pattern_address = context->regs[REG_PATTERN_GEN] << 11 & 0x3800; | 2606 uint16_t pattern_address = context->regs[REG_PATTERN_GEN] << 11 & 0x3800; |
2607 uint16_t upper_vcounter_mask; | 2607 uint16_t upper_vcounter_mask; |
2634 fg = tms_map_color(context, context->regs[REG_BG_COLOR] >> 4); | 2634 fg = tms_map_color(context, context->regs[REG_BG_COLOR] >> 4); |
2635 bg = tms_map_color(context, context->regs[REG_BG_COLOR] & 0xF); | 2635 bg = tms_map_color(context, context->regs[REG_BG_COLOR] & 0xF); |
2636 } | 2636 } |
2637 for (uint32_t row = 0; row < 24; row++) | 2637 for (uint32_t row = 0; row < 24; row++) |
2638 { | 2638 { |
2639 uint32_t *colfb = fb; | 2639 pixel_t *colfb = fb; |
2640 for (uint32_t col = 0; col < cols; col++) | 2640 for (uint32_t col = 0; col < cols; col++) |
2641 { | 2641 { |
2642 uint32_t *linefb = colfb; | 2642 pixel_t *linefb = colfb; |
2643 uint8_t pattern = context->vdpmem[mode4_address_map[table_address] ^ 1]; | 2643 uint8_t pattern = context->vdpmem[mode4_address_map[table_address] ^ 1]; |
2644 uint16_t caddress = color_address; | 2644 uint16_t caddress = color_address; |
2645 uint16_t paddress = pattern_address; | 2645 uint16_t paddress = pattern_address; |
2646 if (context->regs[REG_MODE_2] & BIT_M2) { | 2646 if (context->regs[REG_MODE_2] & BIT_M2) { |
2647 } else { | 2647 } else { |
2663 uint8_t colors = context->vdpmem[mode4_address_map[caddress] ^ 1]; | 2663 uint8_t colors = context->vdpmem[mode4_address_map[caddress] ^ 1]; |
2664 fg = tms_map_color(context, colors >> 4); | 2664 fg = tms_map_color(context, colors >> 4); |
2665 bg = tms_map_color(context, colors & 0xF); | 2665 bg = tms_map_color(context, colors & 0xF); |
2666 } | 2666 } |
2667 | 2667 |
2668 uint32_t *curfb = linefb; | 2668 pixel_t *curfb = linefb; |
2669 for (uint32_t x = 0; x < pixels; x++) | 2669 for (uint32_t x = 0; x < pixels; x++) |
2670 { | 2670 { |
2671 *(curfb++) = (bits & 0x80) ? fg : bg; | 2671 *(curfb++) = (bits & 0x80) ? fg : bg; |
2672 if (x & 1) { | 2672 if (x & 1) { |
2673 bits <<= 1; | 2673 bits <<= 1; |
2674 } | 2674 } |
2675 } | 2675 } |
2676 linefb += pitch / sizeof(uint32_t); | 2676 linefb += pitch / sizeof(pixel_t); |
2677 if (y & 1) { | 2677 if (y & 1) { |
2678 if (context->regs[REG_MODE_1] & BIT_M3) { | 2678 if (context->regs[REG_MODE_1] & BIT_M3) { |
2679 caddress++; | 2679 caddress++; |
2680 } | 2680 } |
2681 paddress++; | 2681 paddress++; |
2683 } | 2683 } |
2684 } | 2684 } |
2685 table_address++; | 2685 table_address++; |
2686 colfb += pixels; | 2686 colfb += pixels; |
2687 } | 2687 } |
2688 fb += 16 * pitch / sizeof(uint32_t); | 2688 fb += 16 * pitch / sizeof(pixel_t); |
2689 } | 2689 } |
2690 } | 2690 } |
2691 | 2691 |
2692 static void sprite_debug_tms(uint32_t *fb, uint32_t pitch, vdp_context *context) | 2692 static void sprite_debug_tms(pixel_t *fb, uint32_t pitch, vdp_context *context) |
2693 { | 2693 { |
2694 } | 2694 } |
2695 | 2695 |
2696 static void vdp_update_per_frame_debug(vdp_context *context) | 2696 static void vdp_update_per_frame_debug(vdp_context *context) |
2697 { | 2697 { |
2698 if (context->enabled_debuggers & (1 << DEBUG_PLANE)) { | 2698 if (context->enabled_debuggers & (1 << DEBUG_PLANE)) { |
2699 | 2699 |
2700 uint32_t pitch; | 2700 uint32_t pitch; |
2701 uint32_t *fb = render_get_framebuffer(context->debug_fb_indices[DEBUG_PLANE], &pitch); | 2701 pixel_t *fb = render_get_framebuffer(context->debug_fb_indices[DEBUG_PLANE], &pitch); |
2702 if (context->type == VDP_GENESIS && (context->regs[REG_MODE_2] & BIT_MODE_5)) { | 2702 if (context->type == VDP_GENESIS && (context->regs[REG_MODE_2] & BIT_MODE_5)) { |
2703 if ((context->debug_modes[DEBUG_PLANE] & 3) == 3) { | 2703 if ((context->debug_modes[DEBUG_PLANE] & 3) == 3) { |
2704 sprite_debug_mode5(fb, pitch, context); | 2704 sprite_debug_mode5(fb, pitch, context); |
2705 } else { | 2705 } else { |
2706 plane_debug_mode5(fb, pitch, context); | 2706 plane_debug_mode5(fb, pitch, context); |
2721 render_framebuffer_updated(context->debug_fb_indices[DEBUG_PLANE], 1024); | 2721 render_framebuffer_updated(context->debug_fb_indices[DEBUG_PLANE], 1024); |
2722 } | 2722 } |
2723 | 2723 |
2724 if (context->enabled_debuggers & (1 << DEBUG_VRAM)) { | 2724 if (context->enabled_debuggers & (1 << DEBUG_VRAM)) { |
2725 uint32_t pitch; | 2725 uint32_t pitch; |
2726 uint32_t *fb = render_get_framebuffer(context->debug_fb_indices[DEBUG_VRAM], &pitch); | 2726 pixel_t *fb = render_get_framebuffer(context->debug_fb_indices[DEBUG_VRAM], &pitch); |
2727 if (context->type == VDP_GENESIS && (context->regs[REG_MODE_2] & BIT_MODE_5)) { | 2727 if (context->type == VDP_GENESIS && (context->regs[REG_MODE_2] & BIT_MODE_5)) { |
2728 vram_debug_mode5(fb, pitch, context); | 2728 vram_debug_mode5(fb, pitch, context); |
2729 } else if (context->type != VDP_TMS9918A && (context->regs[REG_MODE_1] & BIT_MODE_4)) { | 2729 } else if (context->type != VDP_TMS9918A && (context->regs[REG_MODE_1] & BIT_MODE_4)) { |
2730 vram_debug_mode4(fb, pitch, context); | 2730 vram_debug_mode4(fb, pitch, context); |
2731 } else if (context->type != VDP_GENESIS) { | 2731 } else if (context->type != VDP_GENESIS) { |
2734 render_framebuffer_updated(context->debug_fb_indices[DEBUG_VRAM], 1024); | 2734 render_framebuffer_updated(context->debug_fb_indices[DEBUG_VRAM], 1024); |
2735 } | 2735 } |
2736 | 2736 |
2737 if (context->enabled_debuggers & (1 << DEBUG_CRAM)) { | 2737 if (context->enabled_debuggers & (1 << DEBUG_CRAM)) { |
2738 uint32_t starting_line = 512 - 32*4; | 2738 uint32_t starting_line = 512 - 32*4; |
2739 uint32_t *line = context->debug_fbs[DEBUG_CRAM] | 2739 pixel_t *line = context->debug_fbs[DEBUG_CRAM] |
2740 + context->debug_fb_pitch[DEBUG_CRAM] * starting_line / sizeof(uint32_t); | 2740 + context->debug_fb_pitch[DEBUG_CRAM] * starting_line / sizeof(pixel_t); |
2741 pixel_t black = render_map_color(0, 0, 0); | |
2741 if (context->regs[REG_MODE_2] & BIT_MODE_5) { | 2742 if (context->regs[REG_MODE_2] & BIT_MODE_5) { |
2742 for (int pal = 0; pal < 4; pal ++) | 2743 for (int pal = 0; pal < 4; pal ++) |
2743 { | 2744 { |
2744 uint32_t *cur; | 2745 pixel_t *cur; |
2745 for (int y = 0; y < 31; y++) | 2746 for (int y = 0; y < 31; y++) |
2746 { | 2747 { |
2747 cur = line; | 2748 cur = line; |
2748 for (int offset = 0; offset < 16; offset++) | 2749 for (int offset = 0; offset < 16; offset++) |
2749 { | 2750 { |
2750 for (int x = 0; x < 31; x++) | 2751 for (int x = 0; x < 31; x++) |
2751 { | 2752 { |
2752 *(cur++) = context->colors[pal * 16 + offset]; | 2753 *(cur++) = context->colors[pal * 16 + offset]; |
2753 } | 2754 } |
2754 *(cur++) = 0xFF000000; | 2755 *(cur++) = black; |
2755 } | 2756 } |
2756 line += context->debug_fb_pitch[DEBUG_CRAM] / sizeof(uint32_t); | 2757 line += context->debug_fb_pitch[DEBUG_CRAM] / sizeof(pixel_t); |
2757 } | 2758 } |
2758 cur = line; | 2759 cur = line; |
2759 for (int x = 0; x < 512; x++) | 2760 for (int x = 0; x < 512; x++) |
2760 { | 2761 { |
2761 *(cur++) = 0xFF000000; | 2762 *(cur++) = black; |
2762 } | 2763 } |
2763 line += context->debug_fb_pitch[DEBUG_CRAM] / sizeof(uint32_t); | 2764 line += context->debug_fb_pitch[DEBUG_CRAM] / sizeof(pixel_t); |
2764 } | 2765 } |
2765 } else { | 2766 } else { |
2766 for (int pal = 0; pal < 2; pal ++) | 2767 for (int pal = 0; pal < 2; pal ++) |
2767 { | 2768 { |
2768 uint32_t *cur; | 2769 pixel_t *cur; |
2769 for (int y = 0; y < 31; y++) | 2770 for (int y = 0; y < 31; y++) |
2770 { | 2771 { |
2771 cur = line; | 2772 cur = line; |
2772 for (int offset = MODE4_OFFSET; offset < MODE4_OFFSET + 16; offset++) | 2773 for (int offset = MODE4_OFFSET; offset < MODE4_OFFSET + 16; offset++) |
2773 { | 2774 { |
2774 for (int x = 0; x < 31; x++) | 2775 for (int x = 0; x < 31; x++) |
2775 { | 2776 { |
2776 *(cur++) = context->colors[pal * 16 + offset]; | 2777 *(cur++) = context->colors[pal * 16 + offset]; |
2777 } | 2778 } |
2778 *(cur++) = 0xFF000000; | 2779 *(cur++) = black; |
2779 } | 2780 } |
2780 line += context->debug_fb_pitch[DEBUG_CRAM] / sizeof(uint32_t); | 2781 line += context->debug_fb_pitch[DEBUG_CRAM] / sizeof(pixel_t); |
2781 } | 2782 } |
2782 cur = line; | 2783 cur = line; |
2783 for (int x = 0; x < 512; x++) | 2784 for (int x = 0; x < 512; x++) |
2784 { | 2785 { |
2785 *(cur++) = 0xFF000000; | 2786 *(cur++) = black; |
2786 } | 2787 } |
2787 line += context->debug_fb_pitch[DEBUG_CRAM] / sizeof(uint32_t); | 2788 line += context->debug_fb_pitch[DEBUG_CRAM] / sizeof(pixel_t); |
2788 } | 2789 } |
2789 } | 2790 } |
2790 render_framebuffer_updated(context->debug_fb_indices[DEBUG_CRAM], 512); | 2791 render_framebuffer_updated(context->debug_fb_indices[DEBUG_CRAM], 512); |
2791 context->debug_fbs[DEBUG_CRAM] = render_get_framebuffer(context->debug_fb_indices[DEBUG_CRAM], &context->debug_fb_pitch[DEBUG_CRAM]); | 2792 context->debug_fbs[DEBUG_CRAM] = render_get_framebuffer(context->debug_fb_indices[DEBUG_CRAM], &context->debug_fb_pitch[DEBUG_CRAM]); |
2792 } | 2793 } |
2867 } | 2868 } |
2868 if (!context->fb) { | 2869 if (!context->fb) { |
2869 context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch); | 2870 context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch); |
2870 } | 2871 } |
2871 output_line += context->top_offset; | 2872 output_line += context->top_offset; |
2872 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line); | 2873 context->output = (pixel_t *)(((char *)context->fb) + context->output_pitch * output_line); |
2873 #ifdef DEBUG_FB_FILL | 2874 #ifdef DEBUG_FB_FILL |
2874 for (int i = 0; i < LINEBUF_SIZE; i++) | 2875 for (int i = 0; i < LINEBUF_SIZE; i++) |
2875 { | 2876 { |
2876 context->output[i] = 0xFFFF00FF; | 2877 context->output[i] = 0xFFFF00FF; |
2877 } | 2878 } |
2892 void vdp_reacquire_framebuffer(vdp_context *context) | 2893 void vdp_reacquire_framebuffer(vdp_context *context) |
2893 { | 2894 { |
2894 uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top; | 2895 uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top; |
2895 if (context->output_lines <= lines_max && context->output_lines > 0) { | 2896 if (context->output_lines <= lines_max && context->output_lines > 0) { |
2896 context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch); | 2897 context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch); |
2897 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1 + context->top_offset)); | 2898 context->output = (pixel_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1 + context->top_offset)); |
2898 } else { | 2899 } else { |
2899 context->output = NULL; | 2900 context->output = NULL; |
2900 } | 2901 } |
2901 } | 2902 } |
2902 | 2903 |
2963 | 2964 |
2964 #define CHECK_ONLY if (context->cycles >= target_cycles) { return; } | 2965 #define CHECK_ONLY if (context->cycles >= target_cycles) { return; } |
2965 #define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY | 2966 #define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY |
2966 #define OUTPUT_PIXEL(slot) if ((slot) >= BG_START_SLOT) {\ | 2967 #define OUTPUT_PIXEL(slot) if ((slot) >= BG_START_SLOT) {\ |
2967 uint8_t *src = context->compositebuf + ((slot) - BG_START_SLOT) *2;\ | 2968 uint8_t *src = context->compositebuf + ((slot) - BG_START_SLOT) *2;\ |
2968 uint32_t *dst = context->output + ((slot) - BG_START_SLOT) *2;\ | 2969 pixel_t *dst = context->output + ((slot) - BG_START_SLOT) *2;\ |
2969 if ((*src & 0x3F) | test_layer) {\ | 2970 if ((*src & 0x3F) | test_layer) {\ |
2970 *(dst++) = context->colors[*(src++)];\ | 2971 *(dst++) = context->colors[*(src++)];\ |
2971 } else {\ | 2972 } else {\ |
2972 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\ | 2973 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\ |
2973 }\ | 2974 }\ |
2978 }\ | 2979 }\ |
2979 } | 2980 } |
2980 | 2981 |
2981 #define OUTPUT_PIXEL_H40(slot) if (slot <= (BG_START_SLOT + LINEBUF_SIZE/2)) {\ | 2982 #define OUTPUT_PIXEL_H40(slot) if (slot <= (BG_START_SLOT + LINEBUF_SIZE/2)) {\ |
2982 uint8_t *src = context->compositebuf + (slot - BG_START_SLOT) *2;\ | 2983 uint8_t *src = context->compositebuf + (slot - BG_START_SLOT) *2;\ |
2983 uint32_t *dst = context->output + (slot - BG_START_SLOT) *2;\ | 2984 pixel_t *dst = context->output + (slot - BG_START_SLOT) *2;\ |
2984 if ((*src & 0x3F) | test_layer) {\ | 2985 if ((*src & 0x3F) | test_layer) {\ |
2985 *(dst++) = context->colors[*(src++)];\ | 2986 *(dst++) = context->colors[*(src++)];\ |
2986 } else {\ | 2987 } else {\ |
2987 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\ | 2988 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\ |
2988 }\ | 2989 }\ |
2997 }\ | 2998 }\ |
2998 } | 2999 } |
2999 | 3000 |
3000 #define OUTPUT_PIXEL_H32(slot) if (slot <= (BG_START_SLOT + (256+HORIZ_BORDER)/2)) {\ | 3001 #define OUTPUT_PIXEL_H32(slot) if (slot <= (BG_START_SLOT + (256+HORIZ_BORDER)/2)) {\ |
3001 uint8_t *src = context->compositebuf + (slot - BG_START_SLOT) *2;\ | 3002 uint8_t *src = context->compositebuf + (slot - BG_START_SLOT) *2;\ |
3002 uint32_t *dst = context->output + (slot - BG_START_SLOT) *2;\ | 3003 pixel_t *dst = context->output + (slot - BG_START_SLOT) *2;\ |
3003 if ((*src & 0x3F) | test_layer) {\ | 3004 if ((*src & 0x3F) | test_layer) {\ |
3004 *(dst++) = context->colors[*(src++)];\ | 3005 *(dst++) = context->colors[*(src++)];\ |
3005 } else {\ | 3006 } else {\ |
3006 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\ | 3007 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\ |
3007 }\ | 3008 }\ |
3018 | 3019 |
3019 //BG_START_SLOT => dst = 0, src = border | 3020 //BG_START_SLOT => dst = 0, src = border |
3020 //BG_START_SLOT + 13/2=6, dst = 6, src = border + comp + 13 | 3021 //BG_START_SLOT + 13/2=6, dst = 6, src = border + comp + 13 |
3021 #define OUTPUT_PIXEL_MODE4(slot) if ((slot) >= BG_START_SLOT) {\ | 3022 #define OUTPUT_PIXEL_MODE4(slot) if ((slot) >= BG_START_SLOT) {\ |
3022 uint8_t *src = context->compositebuf + ((slot) - BG_START_SLOT) *2;\ | 3023 uint8_t *src = context->compositebuf + ((slot) - BG_START_SLOT) *2;\ |
3023 uint32_t *dst = context->output + ((slot) - BG_START_SLOT) *2;\ | 3024 pixel_t *dst = context->output + ((slot) - BG_START_SLOT) *2;\ |
3024 if ((slot) - BG_START_SLOT < BORDER_LEFT/2) {\ | 3025 if ((slot) - BG_START_SLOT < BORDER_LEFT/2) {\ |
3025 *(dst++) = context->colors[bgindex];\ | 3026 *(dst++) = context->colors[bgindex];\ |
3026 *(dst++) = context->colors[bgindex];\ | 3027 *(dst++) = context->colors[bgindex];\ |
3027 } else if ((slot) - BG_START_SLOT < (BORDER_LEFT+256)/2){\ | 3028 } else if ((slot) - BG_START_SLOT < (BORDER_LEFT+256)/2){\ |
3028 if ((slot) - BG_START_SLOT == BORDER_LEFT/2) {\ | 3029 if ((slot) - BG_START_SLOT == BORDER_LEFT/2) {\ |
3267 case CALC_SLOT(slot, 5):\ | 3268 case CALC_SLOT(slot, 5):\ |
3268 OUTPUT_PIXEL_MODE4(CALC_SLOT(slot, 5))\ | 3269 OUTPUT_PIXEL_MODE4(CALC_SLOT(slot, 5))\ |
3269 render_sprite_cells_mode4(context);\ | 3270 render_sprite_cells_mode4(context);\ |
3270 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 5)) | 3271 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 5)) |
3271 | 3272 |
3272 static uint32_t dummy_buffer[LINEBUF_SIZE]; | 3273 static pixel_t dummy_buffer[LINEBUF_SIZE]; |
3273 static void vdp_h40_line(vdp_context * context) | 3274 static void vdp_h40_line(vdp_context * context) |
3274 { | 3275 { |
3275 uint16_t address; | 3276 uint16_t address; |
3276 uint32_t mask; | 3277 uint32_t mask; |
3277 uint32_t const slot_cycles = MCLKS_SLOT_H40; | 3278 uint32_t const slot_cycles = MCLKS_SLOT_H40; |
3312 ); | 3313 ); |
3313 scan_sprite_table(context->vcounter, context); | 3314 scan_sprite_table(context->vcounter, context); |
3314 | 3315 |
3315 //Do palette lookup for end of previous line | 3316 //Do palette lookup for end of previous line |
3316 uint8_t *src = context->compositebuf + (LINE_CHANGE_H40 - BG_START_SLOT) *2; | 3317 uint8_t *src = context->compositebuf + (LINE_CHANGE_H40 - BG_START_SLOT) *2; |
3317 uint32_t *dst = context->output + (LINE_CHANGE_H40 - BG_START_SLOT) *2; | 3318 pixel_t *dst = context->output + (LINE_CHANGE_H40 - BG_START_SLOT) *2; |
3318 if (context->output) { | 3319 if (context->output) { |
3319 if (test_layer) { | 3320 if (test_layer) { |
3320 for (int i = 0; i < LINEBUF_SIZE - (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++) | 3321 for (int i = 0; i < LINEBUF_SIZE - (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++) |
3321 { | 3322 { |
3322 *(dst++) = context->colors[*(src++)]; | 3323 *(dst++) = context->colors[*(src++)]; |
4290 } | 4291 } |
4291 if (!context->output) { | 4292 if (!context->output) { |
4292 return; | 4293 return; |
4293 } | 4294 } |
4294 } | 4295 } |
4295 uint32_t color; | 4296 pixel_t color; |
4296 if (context->type == VDP_GAMEGEAR) { | 4297 if (context->type == VDP_GAMEGEAR) { |
4297 //Game Gear uses CRAM entries 16-31 for TMS9918A modes | 4298 //Game Gear uses CRAM entries 16-31 for TMS9918A modes |
4298 color = context->colors[(context->regs[REG_BG_COLOR] & 0xF) + 16 + MODE4_OFFSET]; | 4299 color = context->colors[(context->regs[REG_BG_COLOR] & 0xF) + 16 + MODE4_OFFSET]; |
4299 } else { | 4300 } else { |
4300 color = context->regs[REG_BG_COLOR] << 1 & 0x1E; | 4301 color = context->regs[REG_BG_COLOR] << 1 & 0x1E; |
4799 } else { | 4800 } else { |
4800 //never active unless either mode 4 or mode 5 is turned on | 4801 //never active unless either mode 4 or mode 5 is turned on |
4801 active_line = 0x200; | 4802 active_line = 0x200; |
4802 } | 4803 } |
4803 } | 4804 } |
4804 uint32_t *dst; | 4805 pixel_t *dst; |
4805 uint8_t *debug_dst; | 4806 uint8_t *debug_dst; |
4806 if (context->output && context->hslot >= BG_START_SLOT && context->hslot <= bg_end_slot) { | 4807 if (context->output && context->hslot >= BG_START_SLOT && context->hslot <= bg_end_slot) { |
4807 dst = context->output + 2 * (context->hslot - BG_START_SLOT); | 4808 dst = context->output + 2 * (context->hslot - BG_START_SLOT); |
4808 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT); | 4809 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT); |
4809 } else { | 4810 } else { |
4871 context->flags2 ^= FLAG2_EVEN_FIELD; | 4872 context->flags2 ^= FLAG2_EVEN_FIELD; |
4872 } | 4873 } |
4873 | 4874 |
4874 if (dst) { | 4875 if (dst) { |
4875 uint8_t bg_index; | 4876 uint8_t bg_index; |
4876 uint32_t bg_color; | 4877 pixel_t bg_color; |
4877 if (mode_5) { | 4878 if (mode_5) { |
4878 bg_index = context->regs[REG_BG_COLOR] & 0x3F; | 4879 bg_index = context->regs[REG_BG_COLOR] & 0x3F; |
4879 bg_color = context->colors[bg_index]; | 4880 bg_color = context->colors[bg_index]; |
4880 } else if ((context->regs[REG_MODE_1] & BIT_MODE_4) || context->type != VDP_GENESIS) { | 4881 } else if ((context->regs[REG_MODE_1] & BIT_MODE_4) || context->type != VDP_GENESIS) { |
4881 bg_index = 0x10 + (context->regs[REG_BG_COLOR] & 0xF); | 4882 bg_index = 0x10 + (context->regs[REG_BG_COLOR] & 0xF); |