comparison vdp.c @ 1637:95880d947257

Fix for VRAM byte write order broke VDP FIFO testing ROM results. This change cleans up VRAM writes and fixes the regression while preserving the correct VRAM byte write order
author Michael Pavone <pavone@retrodev.com>
date Sun, 11 Nov 2018 22:39:29 -0800
parents e397766c3028
children f27142c48567
comparison
equal deleted inserted replaced
1636:d2775a242dc6 1637:95880d947257
876 address = mode4_address_map[address & 0x3FFF]; 876 address = mode4_address_map[address & 0x3FFF];
877 } 877 }
878 context->vdpmem[address] = value; 878 context->vdpmem[address] = value;
879 } 879 }
880 880
881 #define DMA_FILL 0x80
882 #define DMA_COPY 0xC0
883 #define DMA_TYPE_MASK 0xC0
881 static void external_slot(vdp_context * context) 884 static void external_slot(vdp_context * context)
882 { 885 {
883 if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80 && context->fifo_read < 0) { 886 if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_FILL && context->fifo_read < 0) {
884 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1); 887 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1);
885 fifo_entry * cur = context->fifo + context->fifo_read; 888 fifo_entry * cur = context->fifo + context->fifo_read;
886 cur->cycle = context->cycles; 889 cur->cycle = context->cycles;
887 cur->address = context->address; 890 cur->address = context->address;
888 cur->partial = 2; 891 cur->partial = 1;
889 vdp_advance_dma(context); 892 vdp_advance_dma(context);
890 } 893 }
891 fifo_entry * start = context->fifo + context->fifo_read; 894 fifo_entry * start = context->fifo + context->fifo_read;
892 if (context->fifo_read >= 0 && start->cycle <= context->cycles) { 895 if (context->fifo_read >= 0 && start->cycle <= context->cycles) {
893 switch (start->cd & 0xF) 896 switch (start->cd & 0xF)
894 { 897 {
895 case VRAM_WRITE: 898 case VRAM_WRITE:
896 if ((context->regs[REG_MODE_2] & (BIT_128K_VRAM|BIT_MODE_5)) == (BIT_128K_VRAM|BIT_MODE_5)) { 899 if ((context->regs[REG_MODE_2] & (BIT_128K_VRAM|BIT_MODE_5)) == (BIT_128K_VRAM|BIT_MODE_5)) {
897 vdp_check_update_sat(context, start->address, start->value); 900 vdp_check_update_sat(context, start->address, start->value);
898 write_vram_word(context, start->address, start->value); 901 write_vram_word(context, start->address, start->value);
899 } else if (start->partial == 3) {
900 vdp_check_update_sat_byte(context, start->address ^ 1, start->value);
901 write_vram_byte(context, start->address ^ 1, start->value);
902 } else if (start->partial) {
903 //printf("VRAM Write: %X to %X at %d (line %d, slot %d)\n", start->value, start->address ^ 1, context->cycles, context->cycles/MCLKS_LINE, (context->cycles%MCLKS_LINE)/16);
904 uint8_t byte = start->value >> 8;
905 if (start->partial > 1) {
906 vdp_check_update_sat_byte(context, start->address, byte);
907 }
908 write_vram_byte(context, start->address, byte);
909 } else { 902 } else {
910 //printf("VRAM Write High: %X to %X at %d (line %d, slot %d)\n", start->value >> 8, start->address, context->cycles, context->cycles/MCLKS_LINE, (context->cycles%MCLKS_LINE)/16); 903 uint8_t byte = start->partial == 1 ? start->value >> 8 : start->value;
911 vdp_check_update_sat(context, start->address, start->value); 904 vdp_check_update_sat_byte(context, start->address ^ 1, byte);
912 write_vram_byte(context, start->address ^ 1, start->value); 905 write_vram_byte(context, start->address ^ 1, byte);
913 start->partial = 1; 906 if (!start->partial) {
914 //skip auto-increment and removal of entry from fifo 907 start->address = start->address ^ 1;
915 return; 908 start->partial = 1;
909 //skip auto-increment and removal of entry from fifo
910 return;
911 }
916 } 912 }
917 break; 913 break;
918 case CRAM_WRITE: { 914 case CRAM_WRITE: {
919 //printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1)); 915 //printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1));
920 if (start->partial == 3) { 916 if (start->partial == 3) {
925 uint16_t address = (context->regs[REG_MODE_2] & BIT_MODE_5) ? start->address >> 1 & (CRAM_SIZE-1) : start->address & 0x1F; 921 uint16_t address = (context->regs[REG_MODE_2] & BIT_MODE_5) ? start->address >> 1 & (CRAM_SIZE-1) : start->address & 0x1F;
926 val = (context->cram[address] & 0xFF00) | start->value; 922 val = (context->cram[address] & 0xFF00) | start->value;
927 } 923 }
928 write_cram(context, start->address, val); 924 write_cram(context, start->address, val);
929 } else { 925 } else {
930 write_cram(context, start->address, start->partial == 2 ? context->fifo[context->fifo_write].value : start->value); 926 write_cram(context, start->address, start->partial ? context->fifo[context->fifo_write].value : start->value);
931 } 927 }
932 break; 928 break;
933 } 929 }
934 case VSRAM_WRITE: 930 case VSRAM_WRITE:
935 if (((start->address/2) & 63) < VSRAM_SIZE) { 931 if (((start->address/2) & 63) < VSRAM_SIZE) {
941 } else { 937 } else {
942 context->vsram[(start->address/2) & 63] &= 0xFF00; 938 context->vsram[(start->address/2) & 63] &= 0xFF00;
943 context->vsram[(start->address/2) & 63] |= start->value; 939 context->vsram[(start->address/2) & 63] |= start->value;
944 } 940 }
945 } else { 941 } else {
946 context->vsram[(start->address/2) & 63] = start->partial == 2 ? context->fifo[context->fifo_write].value : start->value; 942 context->vsram[(start->address/2) & 63] = start->partial ? context->fifo[context->fifo_write].value : start->value;
947 } 943 }
948 } 944 }
949 945
950 break; 946 break;
951 } 947 }
952 context->fifo_read = (context->fifo_read+1) & (FIFO_SIZE-1); 948 context->fifo_read = (context->fifo_read+1) & (FIFO_SIZE-1);
953 if (context->fifo_read == context->fifo_write) { 949 if (context->fifo_read == context->fifo_write) {
954 if ((context->cd & 0x20) && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 950 if ((context->cd & 0x20) && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_FILL) {
955 context->flags |= FLAG_DMA_RUN; 951 context->flags |= FLAG_DMA_RUN;
956 } 952 }
957 context->fifo_read = -1; 953 context->fifo_read = -1;
958 } 954 }
959 } else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0xC0) { 955 } else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_COPY) {
960 if (context->flags & FLAG_READ_FETCHED) { 956 if (context->flags & FLAG_READ_FETCHED) {
961 write_vram_byte(context, context->address ^ 1, context->prefetch); 957 write_vram_byte(context, context->address ^ 1, context->prefetch);
962 958
963 //Update DMA state 959 //Update DMA state
964 vdp_advance_dma(context); 960 vdp_advance_dma(context);
3103 if (!dmalen) { 3099 if (!dmalen) {
3104 dmalen = 0x10000; 3100 dmalen = 0x10000;
3105 } 3101 }
3106 uint32_t min_dma_complete = dmalen * (context->regs[REG_MODE_4] & BIT_H40 ? 16 : 20); 3102 uint32_t min_dma_complete = dmalen * (context->regs[REG_MODE_4] & BIT_H40 ? 16 : 20);
3107 if ( 3103 if (
3108 (context->regs[REG_DMASRC_H] & 0xC0) == 0xC0 3104 (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_COPY
3109 || (((context->cd & 0xF) == VRAM_WRITE) && !(context->regs[REG_MODE_2] & BIT_128K_VRAM))) { 3105 || (((context->cd & 0xF) == VRAM_WRITE) && !(context->regs[REG_MODE_2] & BIT_128K_VRAM))) {
3110 //DMA copies take twice as long to complete since they require a read and a write 3106 //DMA copies take twice as long to complete since they require a read and a write
3111 //DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word 3107 //DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word
3112 //unless 128KB mode is enabled 3108 //unless 128KB mode is enabled
3113 min_dma_complete *= 2; 3109 min_dma_complete *= 2;
3179 context->flags &= ~FLAG_READ_FETCHED; 3175 context->flags &= ~FLAG_READ_FETCHED;
3180 context->flags2 &= ~FLAG2_READ_PENDING; 3176 context->flags2 &= ~FLAG2_READ_PENDING;
3181 //printf("New Address: %X, New CD: %X\n", context->address, context->cd); 3177 //printf("New Address: %X, New CD: %X\n", context->address, context->cd);
3182 if (context->cd & 0x20) { 3178 if (context->cd & 0x20) {
3183 // 3179 //
3184 if((context->regs[REG_DMASRC_H] & 0xC0) != 0x80) { 3180 if((context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) != DMA_FILL) {
3185 //DMA copy or 68K -> VDP, transfer starts immediately 3181 //DMA copy or 68K -> VDP, transfer starts immediately
3186 //printf("DMA start (length: %X) at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L], context->cycles, context->frame, context->vcounter, context->hslot); 3182 //printf("DMA start (length: %X) at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L], context->cycles, context->frame, context->vcounter, context->hslot);
3187 if (!(context->regs[REG_DMASRC_H] & 0x80)) { 3183 if (!(context->regs[REG_DMASRC_H] & 0x80)) {
3188 //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]); 3184 //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]);
3189 //68K -> VDP DMA takes a few slots to actually start reading even though it acquires the bus immediately 3185 //68K -> VDP DMA takes a few slots to actually start reading even though it acquires the bus immediately
3260 } 3256 }
3261 3257
3262 int vdp_data_port_write(vdp_context * context, uint16_t value) 3258 int vdp_data_port_write(vdp_context * context, uint16_t value)
3263 { 3259 {
3264 //printf("data port write: %X at %d\n", value, context->cycles); 3260 //printf("data port write: %X at %d\n", value, context->cycles);
3265 if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & 0xC0) != 0x80) { 3261 if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) != DMA_FILL) {
3266 return -1; 3262 return -1;
3267 } 3263 }
3268 if (context->flags & FLAG_PENDING) { 3264 if (context->flags & FLAG_PENDING) {
3269 context->flags &= ~FLAG_PENDING; 3265 context->flags &= ~FLAG_PENDING;
3270 //Should these be cleared here? 3266 //Should these be cleared here?
3272 context->flags2 &= ~FLAG2_READ_PENDING; 3268 context->flags2 &= ~FLAG2_READ_PENDING;
3273 } 3269 }
3274 /*if (context->fifo_cur == context->fifo_end) { 3270 /*if (context->fifo_cur == context->fifo_end) {
3275 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles); 3271 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles);
3276 }*/ 3272 }*/
3277 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 3273 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_FILL) {
3278 context->flags &= ~FLAG_DMA_RUN; 3274 context->flags &= ~FLAG_DMA_RUN;
3279 } 3275 }
3280 while (context->fifo_write == context->fifo_read) { 3276 while (context->fifo_write == context->fifo_read) {
3281 vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); 3277 vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
3282 } 3278 }
3308 } 3304 }
3309 context->flags2 &= ~FLAG2_BYTE_PENDING; 3305 context->flags2 &= ~FLAG2_BYTE_PENDING;
3310 /*if (context->fifo_cur == context->fifo_end) { 3306 /*if (context->fifo_cur == context->fifo_end) {
3311 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles); 3307 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles);
3312 }*/ 3308 }*/
3313 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 3309 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_FILL) {
3314 context->flags &= ~FLAG_DMA_RUN; 3310 context->flags &= ~FLAG_DMA_RUN;
3315 } 3311 }
3316 while (context->fifo_write == context->fifo_read) { 3312 while (context->fifo_write == context->fifo_read) {
3317 vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); 3313 vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
3318 } 3314 }