Mercurial > repos > blastem
comparison vdp.c @ 1371:5b20840711c1
Remove HINT_FUDGE and make a small adjustment to how VDP syncs with rest of system instead. Worse results on CRAM dot issue, but much less of a hack
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 23 May 2017 21:09:38 -0700 |
parents | 3e7a921718de |
children | e587f16e7d3d |
comparison
equal
deleted
inserted
replaced
1370:eaca4443e831 | 1371:5b20840711c1 |
---|---|
2756 } | 2756 } |
2757 } | 2757 } |
2758 } | 2758 } |
2759 } | 2759 } |
2760 | 2760 |
2761 void vdp_run_context(vdp_context * context, uint32_t target_cycles) | 2761 void vdp_run_context_full(vdp_context * context, uint32_t target_cycles) |
2762 { | 2762 { |
2763 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; | 2763 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; |
2764 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; | 2764 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; |
2765 while(context->cycles < target_cycles) | 2765 while(context->cycles < target_cycles) |
2766 { | 2766 { |
2780 vdp_inactive(context, target_cycles, is_h40, mode_5); | 2780 vdp_inactive(context, target_cycles, is_h40, mode_5); |
2781 } | 2781 } |
2782 } | 2782 } |
2783 } | 2783 } |
2784 | 2784 |
2785 void vdp_run_context(vdp_context *context, uint32_t target_cycles) | |
2786 { | |
2787 //TODO: Deal with H40 hsync shenanigans | |
2788 uint32_t slot_cyc = context->regs[REG_MODE_4] & BIT_H40 ? 15 : 19; | |
2789 if (target_cycles < slot_cyc) { | |
2790 //avoid overflow | |
2791 return; | |
2792 } | |
2793 vdp_run_context_full(context, target_cycles - slot_cyc); | |
2794 } | |
2795 | |
2785 uint32_t vdp_run_to_vblank(vdp_context * context) | 2796 uint32_t vdp_run_to_vblank(vdp_context * context) |
2786 { | 2797 { |
2787 uint32_t old_frame = context->frame; | 2798 uint32_t old_frame = context->frame; |
2788 while (context->frame == old_frame) { | 2799 while (context->frame == old_frame) { |
2789 vdp_run_context(context, context->cycles + MCLKS_LINE); | 2800 vdp_run_context_full(context, context->cycles + MCLKS_LINE); |
2790 } | 2801 } |
2791 return context->cycles; | 2802 return context->cycles; |
2792 } | 2803 } |
2793 | 2804 |
2794 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles) | 2805 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles) |
2807 //unless 128KB mode is enabled | 2818 //unless 128KB mode is enabled |
2808 min_dma_complete *= 2; | 2819 min_dma_complete *= 2; |
2809 } | 2820 } |
2810 min_dma_complete += context->cycles; | 2821 min_dma_complete += context->cycles; |
2811 if (target_cycles < min_dma_complete) { | 2822 if (target_cycles < min_dma_complete) { |
2812 vdp_run_context(context, target_cycles); | 2823 vdp_run_context_full(context, target_cycles); |
2813 return; | 2824 return; |
2814 } else { | 2825 } else { |
2815 vdp_run_context(context, min_dma_complete); | 2826 vdp_run_context_full(context, min_dma_complete); |
2816 if (!(context->flags & FLAG_DMA_RUN)) { | 2827 if (!(context->flags & FLAG_DMA_RUN)) { |
2817 return; | 2828 return; |
2818 } | 2829 } |
2819 } | 2830 } |
2820 } | 2831 } |
2880 //printf("DMA Address: %X, New CD: %X, Source: %X, Length: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_H] << 17) | (context->regs[REG_DMASRC_M] << 9) | (context->regs[REG_DMASRC_L] << 1), context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L]); | 2891 //printf("DMA Address: %X, New CD: %X, Source: %X, Length: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_H] << 17) | (context->regs[REG_DMASRC_M] << 9) | (context->regs[REG_DMASRC_L] << 1), context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L]); |
2881 //68K -> VDP DMA takes a few slots to actually start reading even though it acquires the bus immediately | 2892 //68K -> VDP DMA takes a few slots to actually start reading even though it acquires the bus immediately |
2882 //logic analyzer captures made it seem like the proper value is 4 slots, but that seems to cause trouble with the Nemesis' FIFO Wait State test | 2893 //logic analyzer captures made it seem like the proper value is 4 slots, but that seems to cause trouble with the Nemesis' FIFO Wait State test |
2883 //only captures are from a direct color DMA demo which will generally start DMA at a very specific point in display so other values are plausible | 2894 //only captures are from a direct color DMA demo which will generally start DMA at a very specific point in display so other values are plausible |
2884 //sticking with 3 slots for now until I can do some more captures | 2895 //sticking with 3 slots for now until I can do some more captures |
2885 vdp_run_context(context, context->cycles + 12 * ((context->regs[REG_MODE_2] & BIT_MODE_5) && (context->regs[REG_MODE_4] & BIT_H40) ? 4 : 5)); | 2896 vdp_run_context_full(context, context->cycles + 12 * ((context->regs[REG_MODE_2] & BIT_MODE_5) && (context->regs[REG_MODE_4] & BIT_H40) ? 4 : 5)); |
2886 context->flags |= FLAG_DMA_RUN; | 2897 context->flags |= FLAG_DMA_RUN; |
2887 return 1; | 2898 return 1; |
2888 } else { | 2899 } else { |
2889 context->flags |= FLAG_DMA_RUN; | 2900 context->flags |= FLAG_DMA_RUN; |
2890 //printf("DMA Copy Address: %X, New CD: %X, Source: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); | 2901 //printf("DMA Copy Address: %X, New CD: %X, Source: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); |
2968 }*/ | 2979 }*/ |
2969 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { | 2980 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { |
2970 context->flags &= ~FLAG_DMA_RUN; | 2981 context->flags &= ~FLAG_DMA_RUN; |
2971 } | 2982 } |
2972 while (context->fifo_write == context->fifo_read) { | 2983 while (context->fifo_write == context->fifo_read) { |
2973 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); | 2984 vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); |
2974 } | 2985 } |
2975 fifo_entry * cur = context->fifo + context->fifo_write; | 2986 fifo_entry * cur = context->fifo + context->fifo_write; |
2976 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; | 2987 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; |
2977 cur->address = context->address; | 2988 cur->address = context->address; |
2978 cur->value = value; | 2989 cur->value = value; |
3004 }*/ | 3015 }*/ |
3005 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { | 3016 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { |
3006 context->flags &= ~FLAG_DMA_RUN; | 3017 context->flags &= ~FLAG_DMA_RUN; |
3007 } | 3018 } |
3008 while (context->fifo_write == context->fifo_read) { | 3019 while (context->fifo_write == context->fifo_read) { |
3009 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); | 3020 vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); |
3010 } | 3021 } |
3011 fifo_entry * cur = context->fifo + context->fifo_write; | 3022 fifo_entry * cur = context->fifo + context->fifo_write; |
3012 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; | 3023 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; |
3013 cur->address = context->address; | 3024 cur->address = context->address; |
3014 cur->value = value; | 3025 cur->value = value; |
3089 } | 3100 } |
3090 if (context->cd & 1) { | 3101 if (context->cd & 1) { |
3091 warning("Read from VDP data port while writes are configured, CPU is now frozen. VDP Address: %X, CD: %X\n", context->address, context->cd); | 3102 warning("Read from VDP data port while writes are configured, CPU is now frozen. VDP Address: %X, CD: %X\n", context->address, context->cd); |
3092 } | 3103 } |
3093 while (!(context->flags & FLAG_READ_FETCHED)) { | 3104 while (!(context->flags & FLAG_READ_FETCHED)) { |
3094 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); | 3105 vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); |
3095 } | 3106 } |
3096 context->flags &= ~FLAG_READ_FETCHED; | 3107 context->flags &= ~FLAG_READ_FETCHED; |
3097 return context->prefetch; | 3108 return context->prefetch; |
3098 } | 3109 } |
3099 | 3110 |
3241 uint32_t vdp_cycles_to_frame_end(vdp_context * context) | 3252 uint32_t vdp_cycles_to_frame_end(vdp_context * context) |
3242 { | 3253 { |
3243 return context->cycles + vdp_cycles_to_line(context, context->inactive_start); | 3254 return context->cycles + vdp_cycles_to_line(context, context->inactive_start); |
3244 } | 3255 } |
3245 | 3256 |
3246 //This gives correct values in my test ROM. Kind of a hack, might be partly | |
3247 //due to interrupts getting latched at the end of a "dbi" micro-instruction | |
3248 //but that would only account for 28 of the 36 cycles. More hardware testing | |
3249 //necessary to determine the cause of the discrepency | |
3250 #define HINT_FUDGE 36 | |
3251 uint32_t vdp_next_hint(vdp_context * context) | 3257 uint32_t vdp_next_hint(vdp_context * context) |
3252 { | 3258 { |
3253 if (!(context->regs[REG_MODE_1] & BIT_HINT_EN)) { | 3259 if (!(context->regs[REG_MODE_1] & BIT_HINT_EN)) { |
3254 return 0xFFFFFFFF; | 3260 return 0xFFFFFFFF; |
3255 } | 3261 } |
3256 if (context->flags2 & FLAG2_HINT_PENDING) { | 3262 if (context->flags2 & FLAG2_HINT_PENDING) { |
3257 return context->pending_hint_start - HINT_FUDGE; | 3263 return context->pending_hint_start; |
3258 } | 3264 } |
3259 uint32_t hint_line; | 3265 uint32_t hint_line; |
3260 if (context->state != ACTIVE) { | 3266 if (context->state != ACTIVE) { |
3261 hint_line = context->regs[REG_HINT]; | 3267 hint_line = context->regs[REG_HINT]; |
3262 if (hint_line > context->inactive_start) { | 3268 if (hint_line > context->inactive_start) { |
3273 if (hint_line >= context->vcounter) { | 3279 if (hint_line >= context->vcounter) { |
3274 //Next interrupt is for a line in the next frame that | 3280 //Next interrupt is for a line in the next frame that |
3275 //is higher than the line we're on now so just passing | 3281 //is higher than the line we're on now so just passing |
3276 //that line number to vdp_cycles_to_line will yield the wrong | 3282 //that line number to vdp_cycles_to_line will yield the wrong |
3277 //result | 3283 //result |
3278 return context->cycles + vdp_cycles_to_line(context, 0) + hint_line * MCLKS_LINE - HINT_FUDGE; | 3284 return context->cycles + vdp_cycles_to_line(context, 0) + hint_line * MCLKS_LINE; |
3279 } | 3285 } |
3280 } | 3286 } |
3281 } else { | 3287 } else { |
3282 uint32_t jump_start, jump_dst; | 3288 uint32_t jump_start, jump_dst; |
3283 get_jump_params(context, &jump_start, &jump_dst); | 3289 get_jump_params(context, &jump_start, &jump_dst); |
3287 if (hint_line < context->vcounter && hint_line > context->inactive_start) { | 3293 if (hint_line < context->vcounter && hint_line > context->inactive_start) { |
3288 return 0xFFFFFFFF; | 3294 return 0xFFFFFFFF; |
3289 } | 3295 } |
3290 } | 3296 } |
3291 } | 3297 } |
3292 return context->cycles + vdp_cycles_to_line(context, hint_line) - HINT_FUDGE; | 3298 return context->cycles + vdp_cycles_to_line(context, hint_line); |
3293 } | 3299 } |
3294 | 3300 |
3295 static uint32_t vdp_next_vint_real(vdp_context * context) | 3301 static uint32_t vdp_next_vint_real(vdp_context * context) |
3296 { | 3302 { |
3297 if (!(context->regs[REG_MODE_2] & BIT_VINT_EN)) { | 3303 if (!(context->regs[REG_MODE_2] & BIT_VINT_EN)) { |