Mercurial > repos > blastem
comparison vdp.c @ 1840:3d0b20e9a187
Merge
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 18 Apr 2019 19:48:04 -0700 |
parents | 304d47a5c67f |
children | 84f16a804ce5 |
comparison
equal
deleted
inserted
replaced
1838:0c1491818f4b | 1840:3d0b20e9a187 |
---|---|
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; |