comparison vdp.c @ 1834:304d47a5c67f

Get rid of writes to INVALID_LINE in the framebuffer and fix a crash in OD2 from the recent accuracy work
author Michael Pavone <pavone@retrodev.com>
date Tue, 09 Apr 2019 22:39:01 -0700
parents 4f3443ecb6d6
children 84f16a804ce5
comparison
equal deleted inserted replaced
1832:b35743f28744 1834:304d47a5c67f
48 #define BORDER_BOT_V24 24 48 #define BORDER_BOT_V24 24
49 #define BORDER_BOT_V28 8 49 #define BORDER_BOT_V28 8
50 #define BORDER_BOT_V24_PAL 48 50 #define BORDER_BOT_V24_PAL 48
51 #define BORDER_BOT_V28_PAL 32 51 #define BORDER_BOT_V28_PAL 32
52 #define BORDER_BOT_V30_PAL 24 52 #define BORDER_BOT_V30_PAL 24
53
54 #define INVALID_LINE (PAL_INACTIVE_START+BORDER_TOP_V30_PAL+BORDER_BOT_V30_PAL)
55 53
56 enum { 54 enum {
57 INACTIVE = 0, 55 INACTIVE = 0,
58 PREPARING, //used for line 0x1FF 56 PREPARING, //used for line 0x1FF
59 ACTIVE 57 ACTIVE
2073 //potential screen rolling if the mode is changed at an inopportune time 2071 //potential screen rolling if the mode is changed at an inopportune time
2074 context->output_lines = 0; 2072 context->output_lines = 0;
2075 } 2073 }
2076 output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top); 2074 output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top);
2077 } else { 2075 } else {
2078 output_line = INVALID_LINE; 2076 context->output = NULL;
2079 } 2077 }
2080 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line); 2078 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line);
2081 #ifdef DEBUG_FB_FILL 2079 #ifdef DEBUG_FB_FILL
2082 for (int i = 0; i < LINEBUF_SIZE; i++) 2080 for (int i = 0; i < LINEBUF_SIZE; i++)
2083 { 2081 {
2084 context->output[i] = 0xFFFF00FF; 2082 context->output[i] = 0xFFFF00FF;
2085 } 2083 }
2086 #endif 2084 #endif
2087 if (output_line != INVALID_LINE && (context->regs[REG_MODE_4] & BIT_H40)) { 2085 if (context->output && (context->regs[REG_MODE_4] & BIT_H40)) {
2088 context->h40_lines++; 2086 context->h40_lines++;
2089 } 2087 }
2090 } 2088 }
2091 } 2089 }
2092 2090
2103 ? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL 2101 ? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL
2104 : 224 + BORDER_TOP_V28 + BORDER_BOT_V28; 2102 : 224 + BORDER_TOP_V28 + BORDER_BOT_V28;
2105 if (context->output_lines <= lines_max && context->output_lines > 0) { 2103 if (context->output_lines <= lines_max && context->output_lines > 0) {
2106 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1)); 2104 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1));
2107 } else { 2105 } else {
2108 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * INVALID_LINE); 2106 context->output = NULL;
2109 } 2107 }
2110 } 2108 }
2111 2109
2112 static void render_border_garbage(vdp_context *context, uint32_t address, uint8_t *buf, uint8_t buf_off, uint16_t col) 2110 static void render_border_garbage(vdp_context *context, uint32_t address, uint8_t *buf, uint8_t buf_off, uint16_t col)
2113 { 2111 {
2330 #define SPRITE_RENDER_H40(slot) \ 2328 #define SPRITE_RENDER_H40(slot) \
2331 case slot:\ 2329 case slot:\
2332 OUTPUT_PIXEL_H40(slot)\ 2330 OUTPUT_PIXEL_H40(slot)\
2333 if ((slot) == BG_START_SLOT + LINEBUF_SIZE/2) {\ 2331 if ((slot) == BG_START_SLOT + LINEBUF_SIZE/2) {\
2334 advance_output_line(context);\ 2332 advance_output_line(context);\
2333 if (!context->output) {\
2334 context->output = dummy_buffer;\
2335 }\
2335 }\ 2336 }\
2336 if (slot == 168 || slot == 247 || slot == 248) {\ 2337 if (slot == 168 || slot == 247 || slot == 248) {\
2337 render_border_garbage(\ 2338 render_border_garbage(\
2338 context,\ 2339 context,\
2339 context->sprite_draw_list[context->cur_slot].address,\ 2340 context->sprite_draw_list[context->cur_slot].address,\
2365 #define SPRITE_RENDER_H32(slot) \ 2366 #define SPRITE_RENDER_H32(slot) \
2366 case slot:\ 2367 case slot:\
2367 OUTPUT_PIXEL_H32(slot)\ 2368 OUTPUT_PIXEL_H32(slot)\
2368 if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\ 2369 if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\
2369 advance_output_line(context);\ 2370 advance_output_line(context);\
2371 if (!context->output) {\
2372 context->output = dummy_buffer;\
2373 }\
2370 }\ 2374 }\
2371 if (slot == 136 || slot == 247 || slot == 248) {\ 2375 if (slot == 136 || slot == 247 || slot == 248) {\
2372 render_border_garbage(\ 2376 render_border_garbage(\
2373 context,\ 2377 context,\
2374 context->sprite_draw_list[context->cur_slot].address,\ 2378 context->sprite_draw_list[context->cur_slot].address,\
2396 2400
2397 #define MODE4_CHECK_SLOT_LINE(slot) \ 2401 #define MODE4_CHECK_SLOT_LINE(slot) \
2398 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \ 2402 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
2399 if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\ 2403 if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\
2400 advance_output_line(context);\ 2404 advance_output_line(context);\
2405 if (!context->output) {\
2406 context->output = dummy_buffer;\
2407 }\
2401 }\ 2408 }\
2402 if ((slot) == 147) {\ 2409 if ((slot) == 147) {\
2403 context->hslot = 233;\ 2410 context->hslot = 233;\
2404 } else {\ 2411 } else {\
2405 context->hslot++;\ 2412 context->hslot++;\
2439 case CALC_SLOT(slot, 5):\ 2446 case CALC_SLOT(slot, 5):\
2440 OUTPUT_PIXEL(CALC_SLOT(slot, 5))\ 2447 OUTPUT_PIXEL(CALC_SLOT(slot, 5))\
2441 render_sprite_cells_mode4(context);\ 2448 render_sprite_cells_mode4(context);\
2442 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 5)) 2449 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 5))
2443 2450
2451 static uint32_t dummy_buffer[LINEBUF_SIZE];
2444 static void vdp_h40(vdp_context * context, uint32_t target_cycles) 2452 static void vdp_h40(vdp_context * context, uint32_t target_cycles)
2445 { 2453 {
2446 uint16_t address; 2454 uint16_t address;
2447 uint32_t mask; 2455 uint32_t mask;
2448 uint32_t const slot_cycles = MCLKS_SLOT_H40; 2456 uint32_t const slot_cycles = MCLKS_SLOT_H40;
2449 uint8_t bgindex = context->regs[REG_BG_COLOR] & 0x3F; 2457 uint8_t bgindex = context->regs[REG_BG_COLOR] & 0x3F;
2450 uint8_t test_layer = context->test_port >> 7 & 3; 2458 uint8_t test_layer = context->test_port >> 7 & 3;
2459 if (!context->output) {
2460 //This shouldn't happen normally, but it can theoretically
2461 //happen when doing border busting
2462 context->output = dummy_buffer;
2463 }
2451 switch(context->hslot) 2464 switch(context->hslot)
2452 { 2465 {
2453 for (;;) 2466 for (;;)
2454 { 2467 {
2455 case 165: 2468 case 165:
2652 uint16_t address; 2665 uint16_t address;
2653 uint32_t mask; 2666 uint32_t mask;
2654 uint32_t const slot_cycles = MCLKS_SLOT_H32; 2667 uint32_t const slot_cycles = MCLKS_SLOT_H32;
2655 uint8_t bgindex = context->regs[REG_BG_COLOR] & 0x3F; 2668 uint8_t bgindex = context->regs[REG_BG_COLOR] & 0x3F;
2656 uint8_t test_layer = context->test_port >> 7 & 3; 2669 uint8_t test_layer = context->test_port >> 7 & 3;
2670 if (!context->output) {
2671 //This shouldn't happen normally, but it can theoretically
2672 //happen when doing border busting
2673 context->output = dummy_buffer;
2674 }
2657 switch(context->hslot) 2675 switch(context->hslot)
2658 { 2676 {
2659 for (;;) 2677 for (;;)
2660 { 2678 {
2661 case 133: 2679 case 133:
2858 uint16_t address; 2876 uint16_t address;
2859 uint32_t mask; 2877 uint32_t mask;
2860 uint32_t const slot_cycles = MCLKS_SLOT_H32; 2878 uint32_t const slot_cycles = MCLKS_SLOT_H32;
2861 uint8_t bgindex = 0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET; 2879 uint8_t bgindex = 0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET;
2862 uint8_t test_layer = context->test_port >> 7 & 3; 2880 uint8_t test_layer = context->test_port >> 7 & 3;
2881 if (!context->output) {
2882 //This shouldn't happen normally, but it can theoretically
2883 //happen when doing border busting
2884 context->output = dummy_buffer;
2885 }
2863 switch(context->hslot) 2886 switch(context->hslot)
2864 { 2887 {
2865 for (;;) 2888 for (;;)
2866 { 2889 {
2867 //sprite rendering starts 2890 //sprite rendering starts
3000 len = context->hslot == max_slot ? BORDER_RIGHT : SCROLL_BUFFER_DRAW; 3023 len = context->hslot == max_slot ? BORDER_RIGHT : SCROLL_BUFFER_DRAW;
3001 } else { 3024 } else {
3002 src_off = SCROLL_BUFFER_DRAW - BORDER_LEFT; 3025 src_off = SCROLL_BUFFER_DRAW - BORDER_LEFT;
3003 len = BORDER_LEFT; 3026 len = BORDER_LEFT;
3004 } 3027 }
3005 uint8_t *src; 3028 uint8_t *src = NULL;
3006 if (test_layer == 2) { 3029 if (test_layer == 2) {
3007 //plane A 3030 //plane A
3008 src_off += context->buf_a_off + context->hscroll_a; 3031 src_off += context->buf_a_off + context->hscroll_a;
3009 src = context->tmp_buf_a; 3032 src = context->tmp_buf_a;
3010 } else if (test_layer == 3){ 3033 } else if (test_layer == 3){
3015 //sprite layer 3038 //sprite layer
3016 memset(dst, 0, len); 3039 memset(dst, 0, len);
3017 dst += len; 3040 dst += len;
3018 len = 0; 3041 len = 0;
3019 } 3042 }
3020 for (; len >=0; len--, dst++, src_off++) 3043 if (src) {
3021 { 3044 for (; len >=0; len--, dst++, src_off++)
3022 *dst = src[src_off & SCROLL_BUFFER_MASK] & 0x3F; 3045 {
3046 *dst = src[src_off & SCROLL_BUFFER_MASK] & 0x3F;
3047 }
3023 } 3048 }
3024 context->done_composite = dst; 3049 context->done_composite = dst;
3025 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW; 3050 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW;
3026 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW; 3051 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW;
3027 } 3052 }
3093 active_line = 0x200; 3118 active_line = 0x200;
3094 } 3119 }
3095 } 3120 }
3096 uint32_t *dst; 3121 uint32_t *dst;
3097 uint8_t *debug_dst; 3122 uint8_t *debug_dst;
3098 if ( 3123 if (context->output && context->hslot >= BG_START_SLOT && context->hslot < bg_end_slot) {
3099 (
3100 context->vcounter < context->inactive_start + context->border_bot
3101 || context->vcounter >= 0x200 - context->border_top
3102 ) && context->hslot >= BG_START_SLOT && context->hslot < bg_end_slot
3103 ) {
3104 dst = context->output + 2 * (context->hslot - BG_START_SLOT); 3124 dst = context->output + 2 * (context->hslot - BG_START_SLOT);
3105 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT); 3125 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT);
3106 } else { 3126 } else {
3107 dst = NULL; 3127 dst = NULL;
3108 }
3109
3110 if (
3111 !dst && context->vcounter == context->inactive_start + context->border_bot
3112 && context->hslot >= line_change && context->hslot < bg_end_slot
3113 ) {
3114 dst = context->output + 2 * (context->hslot - BG_START_SLOT);
3115 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT);
3116 } 3128 }
3117 3129
3118 uint8_t test_layer = context->test_port >> 7 & 3; 3130 uint8_t test_layer = context->test_port >> 7 & 3;
3119 3131
3120 while(context->cycles < target_cycles) 3132 while(context->cycles < target_cycles)
3121 { 3133 {
3122 check_switch_inactive(context, is_h40); 3134 check_switch_inactive(context, is_h40);
3123 if (context->hslot == BG_START_SLOT && ( 3135 if (context->hslot == BG_START_SLOT && context->output) {
3124 context->vcounter < context->inactive_start + context->border_bot
3125 || context->vcounter >= 0x200 - context->border_top
3126 )) {
3127 dst = context->output + (context->hslot - BG_START_SLOT) * 2; 3136 dst = context->output + (context->hslot - BG_START_SLOT) * 2;
3128 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT); 3137 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT);
3129 } else if (context->hslot == bg_end_slot) { 3138 } else if (context->hslot == bg_end_slot) {
3130 advance_output_line(context); 3139 advance_output_line(context);
3131 dst = NULL; 3140 dst = NULL;