comparison vdp.c @ 1339:35e6a93b4586

Implement the effect of VDP test register usage on the top and bottom borders. Fixes the remaning issue with the border dissolve in the "Ninja Escape" scene of Overdrive 2
author Michael Pavone <pavone@retrodev.com>
date Wed, 03 May 2017 21:28:40 -0700
parents 3706b683cd48
children 4ea094d15cce
comparison
equal deleted inserted replaced
1338:3706b683cd48 1339:35e6a93b4586
282 } 282 }
283 } 283 }
284 284
285 static void render_sprite_cells(vdp_context * context) 285 static void render_sprite_cells(vdp_context * context)
286 { 286 {
287 sprite_draw * d = context->sprite_draw_list + context->cur_slot;
288 context->serial_address = d->address;
287 if (context->cur_slot >= context->sprite_draws) { 289 if (context->cur_slot >= context->sprite_draws) {
288 sprite_draw * d = context->sprite_draw_list + context->cur_slot;
289 290
290 uint16_t dir; 291 uint16_t dir;
291 int16_t x; 292 int16_t x;
292 if (d->h_flip) { 293 if (d->h_flip) {
293 x = d->x_pos + 7; 294 x = d->x_pos + 7;
1268 static void render_map_output(uint32_t line, int32_t col, vdp_context * context) 1269 static void render_map_output(uint32_t line, int32_t col, vdp_context * context)
1269 { 1270 {
1270 uint32_t *dst; 1271 uint32_t *dst;
1271 uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0; 1272 uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0;
1272 uint8_t test_layer = context->test_port >> 7 & 3; 1273 uint8_t test_layer = context->test_port >> 7 & 3;
1273 if (context->state == PREPARING) { 1274 if (context->state == PREPARING && !test_layer) {
1274 if (col) { 1275 if (col) {
1275 col -= 2; 1276 col -= 2;
1276 dst = context->output + BORDER_LEFT + col * 8; 1277 dst = context->output + BORDER_LEFT + col * 8;
1277 } else { 1278 } else {
1278 dst = context->output; 1279 dst = context->output;
2037 *dst = bg_color; 2038 *dst = bg_color;
2038 external_slot(context); 2039 external_slot(context);
2039 } else { 2040 } else {
2040 render_sprite_cells(context); 2041 render_sprite_cells(context);
2041 } 2042 }
2043 if (context->vcounter == context->inactive_start) {
2044 context->hslot++;
2045 context->cycles += slot_cycles;
2046 return;
2047 }
2042 CHECK_LIMIT 2048 CHECK_LIMIT
2043 //sprite attribute table scan starts 2049 //sprite attribute table scan starts
2044 case 167: 2050 case 167:
2045 if (context->state == PREPARING) { 2051 if (context->state == PREPARING) {
2046 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; 2052 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2175 COLUMN_RENDER_BLOCK(38, 145) 2181 COLUMN_RENDER_BLOCK(38, 145)
2176 COLUMN_RENDER_BLOCK_REFRESH(40, 153) 2182 COLUMN_RENDER_BLOCK_REFRESH(40, 153)
2177 case 161: 2183 case 161:
2178 external_slot(context); 2184 external_slot(context);
2179 CHECK_LIMIT 2185 CHECK_LIMIT
2180 case 162: { 2186 case 162:
2181 external_slot(context); 2187 external_slot(context);
2182 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; 2188 CHECK_LIMIT
2183 for (int i = LINEBUF_SIZE-BORDER_RIGHT; i < LINEBUF_SIZE; i++)
2184 {
2185 context->output[i] = bg_color;
2186 }
2187 CHECK_LIMIT
2188 }
2189 //sprite render to line buffer starts 2189 //sprite render to line buffer starts
2190 case 163: 2190 case 163:
2191 context->cur_slot = MAX_DRAWS-1; 2191 context->cur_slot = MAX_DRAWS-1;
2192 memset(context->linebuf, 0, LINEBUF_SIZE); 2192 memset(context->linebuf, 0, LINEBUF_SIZE);
2193 render_border_garbage( 2193 render_border_garbage(
2210 run_dma_src(context, -1); 2210 run_dma_src(context, -1);
2211 } 2211 }
2212 context->hslot++; 2212 context->hslot++;
2213 context->cycles += slot_cycles; 2213 context->cycles += slot_cycles;
2214 vdp_advance_line(context); 2214 vdp_advance_line(context);
2215 if (context->vcounter == context->inactive_start) {
2216 return;
2217 }
2218 CHECK_ONLY 2215 CHECK_ONLY
2219 } 2216 }
2220 default: 2217 default:
2221 context->hslot++; 2218 context->hslot++;
2222 context->cycles += slot_cycles; 2219 context->cycles += slot_cycles;
2263 *(dst++) = bg_color; 2260 *(dst++) = bg_color;
2264 *dst = bg_color; 2261 *dst = bg_color;
2265 external_slot(context); 2262 external_slot(context);
2266 } else { 2263 } else {
2267 render_sprite_cells(context); 2264 render_sprite_cells(context);
2265 }
2266 if (context->vcounter == context->inactive_start) {
2267 context->hslot++;
2268 context->cycles += slot_cycles;
2269 return;
2268 } 2270 }
2269 CHECK_LIMIT 2271 CHECK_LIMIT
2270 //sprite attribute table scan starts 2272 //sprite attribute table scan starts
2271 case 135: //FIXME - Here 2273 case 135: //FIXME - Here
2272 if (context->state == PREPARING) { 2274 if (context->state == PREPARING) {
2408 run_dma_src(context, -1); 2410 run_dma_src(context, -1);
2409 } 2411 }
2410 context->hslot++; 2412 context->hslot++;
2411 context->cycles += slot_cycles; 2413 context->cycles += slot_cycles;
2412 vdp_advance_line(context); 2414 vdp_advance_line(context);
2413 if (context->vcounter == context->inactive_start) {
2414 return;
2415 }
2416 CHECK_ONLY 2415 CHECK_ONLY
2417 } 2416 }
2418 default: 2417 default:
2419 context->hslot++; 2418 context->hslot++;
2420 context->cycles += MCLKS_SLOT_H32; 2419 context->cycles += MCLKS_SLOT_H32;
2543 context->hslot++; 2542 context->hslot++;
2544 context->cycles += MCLKS_SLOT_H32; 2543 context->cycles += MCLKS_SLOT_H32;
2545 } 2544 }
2546 } 2545 }
2547 2546
2547 static void inactive_test_output(vdp_context *context, uint8_t is_h40, uint8_t test_layer)
2548 {
2549 uint8_t max_slot = is_h40 ? 169 : 136;
2550 if (context->hslot > max_slot) {
2551 return;
2552 }
2553 uint32_t *dst = context->output + (context->hslot >> 3) * SCROLL_BUFFER_DRAW;
2554 int32_t len;
2555 uint32_t src_off;
2556 if (context->hslot) {
2557 dst -= SCROLL_BUFFER_DRAW - BORDER_LEFT;
2558 src_off = 0;
2559 len = context->hslot == max_slot ? BORDER_RIGHT : SCROLL_BUFFER_DRAW;
2560 } else {
2561 src_off = SCROLL_BUFFER_DRAW - BORDER_LEFT;
2562 len = BORDER_LEFT;
2563 }
2564 uint8_t *src;
2565 if (test_layer == 2) {
2566 //plane A
2567 src_off += context->buf_a_off + context->hscroll_a;
2568 src = context->tmp_buf_a;
2569 } else {
2570 //plane B
2571 src_off += context->buf_b_off + context->hscroll_b;
2572 src = context->tmp_buf_b;
2573 }
2574 for (; len >=0; len--, dst++, src_off++)
2575 {
2576 *dst = context->colors[src[src_off & SCROLL_BUFFER_MASK] & 0x3F];
2577 }
2578 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW;
2579 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW;
2580 }
2581
2548 static void vdp_inactive(vdp_context *context, uint32_t target_cycles, uint8_t is_h40, uint8_t mode_5) 2582 static void vdp_inactive(vdp_context *context, uint32_t target_cycles, uint8_t is_h40, uint8_t mode_5)
2549 { 2583 {
2550 uint8_t buf_clear_slot, index_reset_slot, bg_end_slot, vint_slot, line_change, jump_start, jump_dest; 2584 uint8_t buf_clear_slot, index_reset_slot, bg_end_slot, vint_slot, line_change, jump_start, jump_dest;
2551 uint8_t index_reset_value, max_draws, max_sprites; 2585 uint8_t index_reset_value, max_draws, max_sprites;
2552 uint16_t vint_line, active_line; 2586 uint16_t vint_line, active_line;
2603 context->vcounter < context->inactive_start + context->border_bot 2637 context->vcounter < context->inactive_start + context->border_bot
2604 || context->vcounter > 0x200 - context->border_top 2638 || context->vcounter > 0x200 - context->border_top
2605 ) && context->hslot >= BG_START_SLOT && context->hslot < bg_end_slot 2639 ) && context->hslot >= BG_START_SLOT && context->hslot < bg_end_slot
2606 ? context->output + 2 * (context->hslot - BG_START_SLOT) 2640 ? context->output + 2 * (context->hslot - BG_START_SLOT)
2607 : NULL; 2641 : NULL;
2642
2643 uint8_t test_layer = context->test_port >> 7 & 3;
2644 if (test_layer == 1) {
2645 //sprite layer doesn't do anything interesting in the passive area
2646 test_layer = 0;
2647 } else if (test_layer) {
2648 dst = NULL;
2649 }
2608 2650
2609 while(context->cycles < target_cycles) 2651 while(context->cycles < target_cycles)
2610 { 2652 {
2611 if (context->hslot == BG_START_SLOT && ( 2653 if (context->hslot == BG_START_SLOT && !test_layer && (
2612 context->vcounter < context->inactive_start + context->border_bot 2654 context->vcounter < context->inactive_start + context->border_bot
2613 || context->vcounter > 0x200 - context->border_top 2655 || context->vcounter > 0x200 - context->border_top
2614 )) { 2656 )) {
2615 dst = context->output + (context->hslot - BG_START_SLOT) * 2; 2657 dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2616 } else if (context->hslot == bg_end_slot) { 2658 } else if (context->hslot == bg_end_slot) {
2617 advance_output_line(context); 2659 advance_output_line(context);
2618 dst = NULL; 2660 dst = NULL;
2619 } 2661 }
2662 //this will need some tweaking to properly interact with 128K mode,
2663 //but this should be good enough for now
2664 context->serial_address += 1024;
2665 if (test_layer) {
2666 switch (context->hslot & 7)
2667 {
2668 case 3:
2669 render_border_garbage(context, context->serial_address, context->tmp_buf_a, context->buf_a_off, context->col_1);
2670 break;
2671 case 4:
2672 render_border_garbage(context, context->serial_address, context->tmp_buf_a, context->buf_a_off+8, context->col_2);
2673 break;
2674 case 7:
2675 render_border_garbage(context, context->serial_address, context->tmp_buf_b, context->buf_b_off, context->col_1);
2676 break;
2677 case 0:
2678 render_border_garbage(context, context->serial_address, context->tmp_buf_b, context->buf_b_off+8, context->col_2);
2679 inactive_test_output(context, is_h40, test_layer);
2680 break;
2681 }
2682 }
2620 2683
2621 if (context->hslot == buf_clear_slot) { 2684 if (context->hslot == buf_clear_slot) {
2622 if (mode_5) { 2685 if (mode_5) {
2623 context->cur_slot = max_draws; 2686 context->cur_slot = max_draws;
2624 } else { 2687 } else {
2682 { 2745 {
2683 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; 2746 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40;
2684 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; 2747 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5;
2685 while(context->cycles < target_cycles) 2748 while(context->cycles < target_cycles)
2686 { 2749 {
2687 if (context->state == ACTIVE && context->vcounter == context->inactive_start) { 2750 //technically the second hcounter check should be different for H40, but this is probably close enough for now
2751 if (context->state == ACTIVE && context->vcounter == context->inactive_start && (context->hslot >= (is_h40 ? 167 : 135) || context->hslot < 133)) {
2688 context->state = INACTIVE; 2752 context->state = INACTIVE;
2689 } 2753 }
2690 2754
2691 if (is_active(context)) { 2755 if (is_active(context)) {
2692 if (mode_5) { 2756 if (mode_5) {