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)) {