diff options
author | Michael Pavone <pavone@retrodev.com> | 2017-04-29 16:51:57 -0700 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2017-04-29 16:51:57 -0700 |
commit | a30f75864549ef92822375a82567f43ca3fc930e (patch) | |
tree | 71b76d55268f3bc3b4d275cf7dd936ba9bb7a171 /vdp.c | |
parent | 7628cbbe645079989d2e25fb2e47c8a41f8bcb7c (diff) |
Initial stab at horizontal border when VDP test register layer selection is in effect for H40. Extended horizontal borders in Titancade scene and ninja escape scene mostly correct now
Diffstat (limited to 'vdp.c')
-rw-r--r-- | vdp.c | 205 |
1 files changed, 185 insertions, 20 deletions
@@ -316,6 +316,8 @@ static void render_sprite_cells(vdp_context * context) } x += dir; } + } else { + context->cur_slot--; } } @@ -717,6 +719,7 @@ static void read_sprite_x(uint32_t line, vdp_context * context) for (i=0; i < width && context->sprite_draws; i++) { --context->sprite_draws; context->sprite_draw_list[context->sprite_draws].x_pos = -128; + context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4; } } else { x -= 128; @@ -1265,12 +1268,11 @@ static void fetch_map_mode4(uint16_t col, uint32_t line, vdp_context *context) static void render_map_output(uint32_t line, int32_t col, vdp_context * context) { uint32_t *dst; + uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0; + uint8_t test_layer = context->test_port >> 7 & 3; if (context->state == PREPARING) { - if (!col) { - return; - } - col -= 2; if (col) { + col -= 2; dst = context->output + BORDER_LEFT + col * 8; } else { dst = context->output; @@ -1279,6 +1281,7 @@ static void render_map_output(uint32_t line, int32_t col, vdp_context * context) { *dst = bg_color; } + return; } uint32_t color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; for (int i = 0; i < 16; i++) @@ -1294,16 +1297,7 @@ static void render_map_output(uint32_t line, int32_t col, vdp_context * context) if (col) { col-=2; - if (col) { - dst = context->output + BORDER_LEFT + col * 8; - } else { - dst = context->output; - uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; - for (int i = 0; i < BORDER_LEFT; i++, dst++) - { - *dst = bg_color; - } - } + dst = context->output + BORDER_LEFT + col * 8; if (context->debug < 2) { sprite_buf = context->linebuf + col * 8; uint8_t a_src, src; @@ -1316,8 +1310,6 @@ static void render_map_output(uint32_t line, int32_t col, vdp_context * context) } plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF); //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7)); - uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0; - uint8_t test_layer = context->test_port >> 7 & 3; if (context->regs[REG_MODE_4] & BIT_HILIGHT) { for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) { @@ -1490,6 +1482,63 @@ static void render_map_output(uint32_t line, int32_t col, vdp_context * context) address++; } } + } else { + dst = context->output; + uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F; + if (output_disabled) { + pixel = 0x3F; + } + uint32_t bg_color = context->colors[pixel]; + if (test_layer) { + switch(test_layer) + { + case 1: + //TODO: Display garbage from bus? + for (int i = 0; i < BORDER_LEFT; i++, dst++) + { + *dst = bg_color; + } + break; + case 2: { + //plane A + //TODO: Deal with Window layer + int i; + /*for (i = 0; i < (context->hscroll_a & 0xF) - (16 - BORDER_LEFT); i++, dst++) + { + *dst = bg_color; + }*/ + i = 0; + uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF) + (16 - BORDER_LEFT); + //uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); + for (; i < BORDER_LEFT; buf_off++, i++, dst++) + { + *dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK]]; + } + break; + } + case 3: { + //plane B + int i; + /*for (i = 0; i < (context->hscroll_b & 0xF) - (16 - BORDER_LEFT); i++, dst++) + { + *dst = bg_color; + }*/ + i = 0; + uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF) + (16 - BORDER_LEFT); + //uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); + for (; i < BORDER_LEFT; buf_off++, i++, dst++) + { + *dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK]]; + } + break; + } + } + } else { + for (int i = 0; i < BORDER_LEFT; i++, dst++) + { + *dst = bg_color; + } + } } context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; @@ -1697,6 +1746,80 @@ static void advance_output_line(vdp_context *context) } } +static void render_border_garbage(vdp_context *context, uint32_t address, uint8_t *buf, uint8_t buf_off, uint16_t col) +{ + uint8_t base = col >> 9 & 0x30; + for (int i = 0; i < 4; i++, address++) + { + uint8_t byte = context->vdpmem[address & 0xFFFF]; + buf[(buf_off++) & SCROLL_BUFFER_MASK] = base | byte >> 4; + buf[(buf_off++) & SCROLL_BUFFER_MASK] = base | byte & 0xF; + } +} + +static void draw_right_border(vdp_context *context) +{ + uint32_t *dst = context->output + BORDER_LEFT + ((context->regs[REG_MODE_4] & BIT_H40) ? 320 : 256); + uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F; + if ((context->test_port & TEST_BIT_DISABLE) != 0) { + pixel = 0x3F; + } + uint32_t bg_color = context->colors[pixel]; + uint8_t test_layer = context->test_port >> 7 & 3; + if (test_layer) { + switch(test_layer) + { + case 1: + //TODO: Display garbage from bus? + for (int i = 0; i < BORDER_RIGHT; i++, dst++) + { + *dst = bg_color; + } + break; + case 2: { + //plane A + //TODO: Deal with Window layer + int i; + /*for (i = 0; i < (context->hscroll_a & 0xF) - (16 - BORDER_LEFT); i++, dst++) + { + *dst = bg_color; + }*/ + i = 0; + uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF); + //uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); + for (; i < BORDER_RIGHT; buf_off++, i++, dst++) + { + *dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK] & 0x3F]; + } + break; + } + case 3: { + //plane B + int i; + /*for (i = 0; i < (context->hscroll_b & 0xF) - (16 - BORDER_LEFT); i++, dst++) + { + *dst = bg_color; + }*/ + i = 0; + uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF); + //uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); + for (; i < BORDER_RIGHT; buf_off++, i++, dst++) + { + *dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK] & 0x3F]; + } + break; + } + } + } else { + for (int i = 0; i < BORDER_RIGHT; i++, dst++) + { + *dst = bg_color; + } + } + context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; + context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; +} + #define CHECK_ONLY if (context->cycles >= target_cycles) { return; } #define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY @@ -1791,6 +1914,29 @@ static void advance_output_line(vdp_context *context) if ((slot) == BG_START_SLOT + LINEBUF_SIZE/2) {\ advance_output_line(context);\ }\ + if (slot == 168 || slot == 247 || slot == 248) {\ + render_border_garbage(\ + context,\ + context->sprite_draw_list[context->cur_slot].address,\ + context->tmp_buf_b,\ + context->buf_b_off + (slot == 247 ? 0 : 8),\ + slot == 247 ? context->col_1 : context->col_2\ + );\ + if (slot == 248) {\ + context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\ + context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\ + }\ + } else if (slot == 243) {\ + render_border_garbage(\ + context,\ + context->sprite_draw_list[context->cur_slot].address,\ + context->tmp_buf_a,\ + context->buf_a_off,\ + context->col_1\ + );\ + } else if (slot == 169) {\ + draw_right_border(context);\ + }\ render_sprite_cells( context);\ scan_sprite_table(context->vcounter, context);\ CHECK_LIMIT_HSYNC(slot) @@ -1912,6 +2058,12 @@ static void vdp_h40(vdp_context * context, uint32_t target_cycles) } context->sprite_index = 0x80; context->slot_counter = 0; + render_border_garbage( + context, + context->sprite_draw_list[context->cur_slot].address, + context->tmp_buf_b, context->buf_b_off, + context->col_1 + ); render_sprite_cells( context); scan_sprite_table(context->vcounter, context); CHECK_LIMIT @@ -1947,7 +2099,7 @@ static void vdp_h40(vdp_context * context, uint32_t target_cycles) SPRITE_RENDER_H40(240) SPRITE_RENDER_H40(241) SPRITE_RENDER_H40(242) - SPRITE_RENDER_H40(243) + SPRITE_RENDER_H40(243) //provides "garbage" for border when plane A selected case 244: address = (context->regs[REG_HSCROLL] & 0x3F) << 10; mask = 0; @@ -1957,6 +2109,7 @@ static void vdp_h40(vdp_context * context, uint32_t target_cycles) if (context->regs[REG_MODE_3] & 0x1) { mask |= 0x7; } + render_border_garbage(context, address, context->tmp_buf_a, context->buf_a_off+8, context->col_2); address += (context->vcounter & mask) * 4; context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; @@ -1964,12 +2117,12 @@ static void vdp_h40(vdp_context * context, uint32_t target_cycles) if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += h40_hsync_cycles[14]; - CHECK_ONLY + CHECK_ONLY //provides "garbage" for border when plane A selected //!HSYNC high SPRITE_RENDER_H40(245) SPRITE_RENDER_H40(246) - SPRITE_RENDER_H40(247) - SPRITE_RENDER_H40(248) + SPRITE_RENDER_H40(247) //provides "garbage" for border when plane B selected + SPRITE_RENDER_H40(248) //provides "garbage" for border when plane B selected case 249: read_map_scroll_a(0, context->vcounter, context); CHECK_LIMIT @@ -2037,9 +2190,21 @@ static void vdp_h40(vdp_context * context, uint32_t target_cycles) case 163: context->cur_slot = MAX_DRAWS-1; memset(context->linebuf, 0, LINEBUF_SIZE); + render_border_garbage( + context, + context->sprite_draw_list[context->cur_slot].address, + context->tmp_buf_a, context->buf_a_off, + context->col_1 + ); render_sprite_cells(context); CHECK_LIMIT case 164: + render_border_garbage( + context, + context->sprite_draw_list[context->cur_slot].address, + context->tmp_buf_a, context->buf_a_off + 8, + context->col_2 + ); render_sprite_cells(context); if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); |