Mercurial > repos > blastem
changeset 2579:bd8d1babbfb5
Implement background plane debug view for Mode 4
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 07 Feb 2025 23:32:15 -0800 |
parents | 9b01541cbd60 |
children | 939b818df589 |
files | vdp.c |
diffstat | 1 files changed, 352 insertions(+), 249 deletions(-) [+] |
line wrap: on
line diff
--- a/vdp.c Fri Feb 07 19:58:20 2025 -0800 +++ b/vdp.c Fri Feb 07 23:32:15 2025 -0800 @@ -2261,264 +2261,363 @@ } } +static void plane_debug_mode5(uint32_t *fb, uint32_t pitch, vdp_context *context) +{ + uint16_t hscroll_mask; + uint16_t v_mul; + uint16_t vscroll_mask = 0x1F | (context->regs[REG_SCROLL] & 0x30) << 1; + switch(context->regs[REG_SCROLL] & 0x3) + { + case 0: + hscroll_mask = 0x1F; + v_mul = 64; + break; + case 0x1: + hscroll_mask = 0x3F; + v_mul = 128; + break; + case 0x2: + //TODO: Verify this behavior + hscroll_mask = 0x1F; + v_mul = 0; + break; + case 0x3: + hscroll_mask = 0x7F; + v_mul = 256; + break; + } + uint16_t table_address; + switch(context->debug_modes[DEBUG_PLANE] & 3) + { + case 0: + table_address = context->regs[REG_SCROLL_A] << 10 & 0xE000; + break; + case 1: + table_address = context->regs[REG_SCROLL_B] << 13 & 0xE000; + break; + case 2: + table_address = context->regs[REG_WINDOW] << 10; + if (context->regs[REG_MODE_4] & BIT_H40) { + table_address &= 0xF000; + v_mul = 128; + hscroll_mask = 0x3F; + } else { + table_address &= 0xF800; + v_mul = 64; + hscroll_mask = 0x1F; + } + vscroll_mask = 0x1F; + break; + } + uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; + uint16_t num_rows; + int num_lines; + if (context->double_res) { + num_rows = 64; + num_lines = 16; + } else { + num_rows = 128; + num_lines = 8; + } + for (uint16_t row = 0; row < num_rows; row++) + { + uint16_t row_address = table_address + (row & vscroll_mask) * v_mul; + for (uint16_t col = 0; col < 128; col++) + { + uint16_t address = row_address + (col & hscroll_mask) * 2; + //pccv hnnn nnnn nnnn + // + uint16_t entry = context->vdpmem[address] << 8 | context->vdpmem[address + 1]; + uint8_t pal = entry >> 9 & 0x30; + + uint32_t *dst = fb + (row * pitch * num_lines / sizeof(uint32_t)) + col * 8; + if (context->double_res) { + address = (entry & 0x3FF) * 64; + } else { + address = (entry & 0x7FF) * 32; + } + int y_diff = 4; + if (entry & 0x1000) { + y_diff = -4; + address += (num_lines - 1) * 4; + } + int x_diff = 1; + if (entry & 0x800) { + x_diff = -1; + address += 3; + } + for (int y = 0; y < num_lines; y++) + { + uint16_t trow_address = address; + uint32_t *row_dst = dst; + for (int x = 0; x < 4; x++) + { + uint8_t byte = context->vdpmem[trow_address]; + trow_address += x_diff; + uint8_t left, right; + if (x_diff > 0) { + left = byte >> 4; + right = byte & 0xF; + } else { + left = byte & 0xF; + right = byte >> 4; + } + *(row_dst++) = left ? context->colors[left|pal] : bg_color; + *(row_dst++) = right ? context->colors[right|pal] : bg_color; + } + address += y_diff; + dst += pitch / sizeof(uint32_t); + } + } + } +} + +static void sprite_debug_mode5(uint32_t *fb, uint32_t pitch, vdp_context *context) +{ + uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; + //clear a single alpha channel bit so we can distinguish between actual bg color and sprite + //pixels that just happen to be the same color + bg_color &= 0xFEFFFFFF; + uint32_t *line = fb; + uint32_t border_line = render_map_color(0, 0, 255); + uint32_t sprite_outline = render_map_color(255, 0, 255); + int right_border = 256 + ((context->h40_lines > context->output_lines / 2) ? 640 : 512); + for (int y = 0; y < 1024; y++) + { + uint32_t *cur = line; + if (y != 256 && y != 256+context->inactive_start*2) { + for (int x = 0; x < 255; x++) + { + *(cur++) = bg_color; + } + *(cur++) = border_line; + for (int x = 256; x < right_border; x++) + { + *(cur++) = bg_color; + } + *(cur++) = border_line; + for (int x = right_border + 1; x < 1024; x++) + { + *(cur++) = bg_color; + } + } else { + for (int x = 0; x < 1024; x++) + { + *(cur++) = border_line; + } + } + line += pitch / sizeof(uint32_t); + } + for (int i = 0, index = 0; i < context->max_sprites_frame; i++) + { + uint32_t y = (context->sat_cache[index] & 3) << 8 | context->sat_cache[index + 1]; + if (!context->double_res) { + y &= 0x1FF; + y <<= 1; + } + uint8_t tile_width = ((context->sat_cache[index+2] >> 2) & 0x3); + uint32_t pixel_width = (tile_width + 1) * 16; + uint8_t height = ((context->sat_cache[index+2] & 3) + 1) * 16; + uint16_t col_offset = height * (context->double_res ? 4 : 2); + uint16_t att_addr = mode5_sat_address(context) + index * 2 + 4; + uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1]; + uint16_t tile_addr; + if (context->double_res) { + tile_addr = (tileinfo & 0x3FF) << 6; + } else { + tile_addr = (tileinfo & 0x7FF) << 5; + } + uint8_t pal = (tileinfo >> 9) & 0x30; + uint16_t hflip = tileinfo & MAP_BIT_H_FLIP; + uint16_t vflip = tileinfo & MAP_BIT_V_FLIP; + uint32_t x = (((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF) * 2; + uint32_t *line = fb + y * pitch / sizeof(uint32_t) + x; + uint32_t *cur = line; + for (uint32_t cx = x, x2 = x + pixel_width; cx < x2; cx++) + { + *(cur++) = sprite_outline; + } + uint8_t advance_source = 1; + uint32_t y2 = y + height - 1; + if (y2 > 1024) { + y2 = 1024; + } + uint16_t line_offset = 4; + if (vflip) { + tile_addr += col_offset - 4; + line_offset = -line_offset; + } + if (hflip) { + tile_addr += col_offset * tile_width + 3; + col_offset = -col_offset; + } + for (; y < y2; y++) + { + line += pitch / sizeof(uint32_t); + cur = line; + *(cur++) = sprite_outline; + uint16_t line_addr = tile_addr; + for (uint8_t tx = 0; tx <= tile_width; tx++) + { + uint16_t cur_addr = line_addr; + for (uint8_t cx = 0; cx < 4; cx++) + { + uint8_t pair = context->vdpmem[cur_addr]; + uint32_t left, right; + if (hflip) { + right = pair >> 4; + left = pair & 0xF; + cur_addr--; + } else { + left = pair >> 4; + right = pair & 0xF; + cur_addr++; + } + left = left ? context->colors[pal | left] : bg_color; + right = right ? context->colors[pal | right] : bg_color; + if (*cur == bg_color) { + *(cur) = left; + } + cur++; + if (cx | tx) { + if (*cur == bg_color) { + *(cur) = left; + } + cur++; + } + if (*cur == bg_color) { + *(cur) = right; + } + cur++; + if (cx != 3 || tx != tile_width) { + if (*cur == bg_color) { + *(cur) = right; + } + cur++; + } + } + line_addr += col_offset; + } + + *(cur++) = sprite_outline; + if (advance_source || context->double_res) { + tile_addr += line_offset; + } + advance_source = !advance_source; + } + if (y2 != 1024) { + line += pitch / sizeof(uint32_t); + cur = line; + for (uint32_t cx = x, x2 = x + pixel_width; cx < x2; cx++) + { + *(cur++) = sprite_outline; + } + } + index = context->sat_cache[index+3] * 4; + if (!index) { + break; + } + } +} + +static void plane_debug_mode4(uint32_t *fb, uint32_t pitch, vdp_context *context) +{ + uint32_t bg_color = context->colors[(context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET]; + uint32_t address = (context->regs[REG_SCROLL_A] & 0xE) << 10; + for (uint32_t row_address = address, end = address + 32*32*2; row_address < end; row_address += 2 * 32) + { + uint32_t *col = fb; + for(uint32_t cur = row_address, row_end = row_address + 2 * 32; cur < row_end; cur += 2) + { + uint32_t mapped = mode4_address_map[cur]; + uint16_t entry = context->vdpmem[mapped] << 8 | context->vdpmem[mapped + 1]; + uint32_t tile_address = (entry & 0x1FF) << 5; + uint8_t pal = entry >> 7 & 0x10; + uint32_t i_init, i_inc, i_limit, tile_inc; + if (entry & 0x200) { + //hflip + i_init = 0; + i_inc = 4; + i_limit = 32; + } else { + i_init = 28; + i_inc = -4; + i_limit = -4; + } + if (entry & 0x400) { + //vflip + tile_address += 7*4; + tile_inc = -4; + } else { + tile_inc = 4; + } + uint32_t *line = col; + for (int y = 0; y < 16; y++) + { + uint32_t first = mode4_address_map[tile_address]; + uint32_t last = mode4_address_map[tile_address + 2]; + uint32_t pixels = planar_to_chunky[context->vdpmem[first]] << 1; + pixels |= planar_to_chunky[context->vdpmem[first+1]]; + pixels |= planar_to_chunky[context->vdpmem[last]] << 3; + pixels |= planar_to_chunky[context->vdpmem[last+1]] << 2; + uint32_t *out = line; + for (uint32_t i = i_init; i != i_limit; i += i_inc) + { + uint32_t pixel = context->colors[((pixels >> i & 0xF) | pal) + MODE4_OFFSET]; + *(out++) = pixel; + *(out++) = pixel; + } + + + if (y & 1) { + tile_address += tile_inc; + } + line += pitch / sizeof(uint32_t); + } + + + + col += 16; + } + fb += 16 * pitch / sizeof(uint32_t); + } +} + +static void sprite_debug_mode4(uint32_t *fb, uint32_t pitch, vdp_context *context) +{ +} + +static void plane_debug_tms(uint32_t *fb, uint32_t pitch, vdp_context *context) +{ +} + +static void sprite_debug_tms(uint32_t *fb, uint32_t pitch, vdp_context *context) +{ +} static void vdp_update_per_frame_debug(vdp_context *context) { if (context->enabled_debuggers & (1 << DEBUG_PLANE)) { + uint32_t pitch; uint32_t *fb = render_get_framebuffer(context->debug_fb_indices[DEBUG_PLANE], &pitch); - uint16_t hscroll_mask; - uint16_t v_mul; - uint16_t vscroll_mask = 0x1F | (context->regs[REG_SCROLL] & 0x30) << 1; - switch(context->regs[REG_SCROLL] & 0x3) - { - case 0: - hscroll_mask = 0x1F; - v_mul = 64; - break; - case 0x1: - hscroll_mask = 0x3F; - v_mul = 128; - break; - case 0x2: - //TODO: Verify this behavior - hscroll_mask = 0x1F; - v_mul = 0; - break; - case 0x3: - hscroll_mask = 0x7F; - v_mul = 256; - break; - } - uint16_t table_address; - switch(context->debug_modes[DEBUG_PLANE] & 3) - { - case 0: - table_address = context->regs[REG_SCROLL_A] << 10 & 0xE000; - break; - case 1: - table_address = context->regs[REG_SCROLL_B] << 13 & 0xE000; - break; - case 2: - table_address = context->regs[REG_WINDOW] << 10; - if (context->regs[REG_MODE_4] & BIT_H40) { - table_address &= 0xF000; - v_mul = 128; - hscroll_mask = 0x3F; + if (context->type == VDP_GENESIS && (context->regs[REG_MODE_2] & BIT_MODE_5)) { + if ((context->debug_modes[DEBUG_PLANE] & 3) == 3) { + sprite_debug_mode5(fb, pitch, context); } else { - table_address &= 0xF800; - v_mul = 64; - hscroll_mask = 0x1F; - } - vscroll_mask = 0x1F; - break; - } - uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR & 0x3F]]; - if ((context->debug_modes[DEBUG_PLANE] & 3) == 3) { - //clear a single alpha channel bit so we can distinguish between actual bg color and sprite - //pixels that just happen to be the same color - bg_color &= 0xFEFFFFFF; - uint32_t *line = fb; - uint32_t border_line = render_map_color(0, 0, 255); - uint32_t sprite_outline = render_map_color(255, 0, 255); - int right_border = 256 + ((context->h40_lines > context->output_lines / 2) ? 640 : 512); - for (int y = 0; y < 1024; y++) - { - uint32_t *cur = line; - if (y != 256 && y != 256+context->inactive_start*2) { - for (int x = 0; x < 255; x++) - { - *(cur++) = bg_color; - } - *(cur++) = border_line; - for (int x = 256; x < right_border; x++) - { - *(cur++) = bg_color; - } - *(cur++) = border_line; - for (int x = right_border + 1; x < 1024; x++) - { - *(cur++) = bg_color; - } - } else { - for (int x = 0; x < 1024; x++) - { - *(cur++) = border_line; - } - } - line += pitch / sizeof(uint32_t); + plane_debug_mode5(fb, pitch, context); } - for (int i = 0, index = 0; i < context->max_sprites_frame; i++) - { - uint32_t y = (context->sat_cache[index] & 3) << 8 | context->sat_cache[index + 1]; - if (!context->double_res) { - y &= 0x1FF; - y <<= 1; - } - uint8_t tile_width = ((context->sat_cache[index+2] >> 2) & 0x3); - uint32_t pixel_width = (tile_width + 1) * 16; - uint8_t height = ((context->sat_cache[index+2] & 3) + 1) * 16; - uint16_t col_offset = height * (context->double_res ? 4 : 2); - uint16_t att_addr = mode5_sat_address(context) + index * 2 + 4; - uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1]; - uint16_t tile_addr; - if (context->double_res) { - tile_addr = (tileinfo & 0x3FF) << 6; - } else { - tile_addr = (tileinfo & 0x7FF) << 5; - } - uint8_t pal = (tileinfo >> 9) & 0x30; - uint16_t hflip = tileinfo & MAP_BIT_H_FLIP; - uint16_t vflip = tileinfo & MAP_BIT_V_FLIP; - uint32_t x = (((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF) * 2; - uint32_t *line = fb + y * pitch / sizeof(uint32_t) + x; - uint32_t *cur = line; - for (uint32_t cx = x, x2 = x + pixel_width; cx < x2; cx++) - { - *(cur++) = sprite_outline; - } - uint8_t advance_source = 1; - uint32_t y2 = y + height - 1; - if (y2 > 1024) { - y2 = 1024; - } - uint16_t line_offset = 4; - if (vflip) { - tile_addr += col_offset - 4; - line_offset = -line_offset; - } - if (hflip) { - tile_addr += col_offset * tile_width + 3; - col_offset = -col_offset; - } - for (; y < y2; y++) - { - line += pitch / sizeof(uint32_t); - cur = line; - *(cur++) = sprite_outline; - uint16_t line_addr = tile_addr; - for (uint8_t tx = 0; tx <= tile_width; tx++) - { - uint16_t cur_addr = line_addr; - for (uint8_t cx = 0; cx < 4; cx++) - { - uint8_t pair = context->vdpmem[cur_addr]; - uint32_t left, right; - if (hflip) { - right = pair >> 4; - left = pair & 0xF; - cur_addr--; - } else { - left = pair >> 4; - right = pair & 0xF; - cur_addr++; - } - left = left ? context->colors[pal | left] : bg_color; - right = right ? context->colors[pal | right] : bg_color; - if (*cur == bg_color) { - *(cur) = left; - } - cur++; - if (cx | tx) { - if (*cur == bg_color) { - *(cur) = left; - } - cur++; - } - if (*cur == bg_color) { - *(cur) = right; - } - cur++; - if (cx != 3 || tx != tile_width) { - if (*cur == bg_color) { - *(cur) = right; - } - cur++; - } - } - line_addr += col_offset; - } - - *(cur++) = sprite_outline; - if (advance_source || context->double_res) { - tile_addr += line_offset; - } - advance_source = !advance_source; - } - if (y2 != 1024) { - line += pitch / sizeof(uint32_t); - cur = line; - for (uint32_t cx = x, x2 = x + pixel_width; cx < x2; cx++) - { - *(cur++) = sprite_outline; - } - } - index = context->sat_cache[index+3] * 4; - if (!index) { - break; - } + } else if (context->type != VDP_TMS9918A && (context->regs[REG_MODE_1] & BIT_MODE_4)) { + if (context->debug_modes[DEBUG_PLANE] & 1) { + sprite_debug_mode4(fb, pitch, context); + } else { + plane_debug_mode4(fb, pitch, context); } - } else { - - uint16_t num_rows; - int num_lines; - if (context->double_res) { - num_rows = 64; - num_lines = 16; + } else if (context->type != VDP_GENESIS) { + if (context->debug_modes[DEBUG_PLANE] & 1) { + sprite_debug_tms(fb, pitch, context); } else { - num_rows = 128; - num_lines = 8; - } - for (uint16_t row = 0; row < num_rows; row++) - { - uint16_t row_address = table_address + (row & vscroll_mask) * v_mul; - for (uint16_t col = 0; col < 128; col++) - { - uint16_t address = row_address + (col & hscroll_mask) * 2; - //pccv hnnn nnnn nnnn - // - uint16_t entry = context->vdpmem[address] << 8 | context->vdpmem[address + 1]; - uint8_t pal = entry >> 9 & 0x30; - - uint32_t *dst = fb + (row * pitch * num_lines / sizeof(uint32_t)) + col * 8; - if (context->double_res) { - address = (entry & 0x3FF) * 64; - } else { - address = (entry & 0x7FF) * 32; - } - int y_diff = 4; - if (entry & 0x1000) { - y_diff = -4; - address += (num_lines - 1) * 4; - } - int x_diff = 1; - if (entry & 0x800) { - x_diff = -1; - address += 3; - } - for (int y = 0; y < num_lines; y++) - { - uint16_t trow_address = address; - uint32_t *row_dst = dst; - for (int x = 0; x < 4; x++) - { - uint8_t byte = context->vdpmem[trow_address]; - trow_address += x_diff; - uint8_t left, right; - if (x_diff > 0) { - left = byte >> 4; - right = byte & 0xF; - } else { - left = byte & 0xF; - right = byte >> 4; - } - *(row_dst++) = left ? context->colors[left|pal] : bg_color; - *(row_dst++) = right ? context->colors[right|pal] : bg_color; - } - address += y_diff; - dst += pitch / sizeof(uint32_t); - } - } + plane_debug_tms(fb, pitch, context); } } render_framebuffer_updated(context->debug_fb_indices[DEBUG_PLANE], 1024); @@ -5804,7 +5903,11 @@ { case DEBUG_PLANE: caption = "BlastEm - VDP Plane Debugger"; - width = height = 1024; + if (context->type == VDP_GENESIS) { + width = height = 1024; + } else { + width = height = 512; + } break; case DEBUG_VRAM: caption = "BlastEm - VDP VRAM Debugger";