comparison vdp.c @ 1153:2e3ad914bad3

BlastEm now passes all of the tests on the first page of "Megadrive VDP Test" in VDPTEST.sms
author Michael Pavone <pavone@retrodev.com>
date Thu, 05 Jan 2017 00:08:28 -0800
parents ddbb61be6119
children c83ec07ddbac
comparison
equal deleted inserted replaced
1152:ddbb61be6119 1153:2e3ad914bad3
780 } else { 780 } else {
781 context->prefetch = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1]; 781 context->prefetch = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1];
782 782
783 context->flags |= FLAG_READ_FETCHED; 783 context->flags |= FLAG_READ_FETCHED;
784 } 784 }
785 } else if (!(context->cd & 1) && !(context->flags & FLAG_READ_FETCHED)){ 785 } else if (!(context->cd & 1) && !(context->flags & (FLAG_READ_FETCHED|FLAG_PENDING))) {
786 switch(context->cd & 0xF) 786 switch(context->cd & 0xF)
787 { 787 {
788 case VRAM_READ: 788 case VRAM_READ:
789 if (context->flags2 & FLAG2_READ_PENDING) { 789 if (context->flags2 & FLAG2_READ_PENDING) {
790 context->prefetch |= context->vdpmem[context->address | 1]; 790 context->prefetch |= context->vdpmem[context->address | 1];
791 context->flags |= FLAG_READ_FETCHED; 791 context->flags |= FLAG_READ_FETCHED;
792 context->flags2 &= ~FLAG2_READ_PENDING; 792 context->flags2 &= ~FLAG2_READ_PENDING;
793 //Should this happen after the prefetch or after the read? 793 //Should this happen after the prefetch or after the read?
794 //increment_address(context); 794 increment_address(context);
795 } else { 795 } else {
796 context->prefetch = context->vdpmem[context->address & 0xFFFE] << 8; 796 context->prefetch = context->vdpmem[context->address & 0xFFFE] << 8;
797 context->flags2 |= FLAG2_READ_PENDING; 797 context->flags2 |= FLAG2_READ_PENDING;
798 } 798 }
799 break; 799 break;
804 } 804 }
805 context->prefetch = context->vdpmem[address]; 805 context->prefetch = context->vdpmem[address];
806 context->prefetch |= context->fifo[context->fifo_write].value & 0xFF00; 806 context->prefetch |= context->fifo[context->fifo_write].value & 0xFF00;
807 context->flags |= FLAG_READ_FETCHED; 807 context->flags |= FLAG_READ_FETCHED;
808 //Should this happen after the prefetch or after the read? 808 //Should this happen after the prefetch or after the read?
809 //increment_address(context); 809 increment_address(context);
810 break; 810 break;
811 } 811 }
812 case CRAM_READ: 812 case CRAM_READ:
813 context->prefetch = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS; 813 context->prefetch = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS;
814 context->prefetch |= context->fifo[context->fifo_write].value & ~CRAM_BITS; 814 context->prefetch |= context->fifo[context->fifo_write].value & ~CRAM_BITS;
815 context->flags |= FLAG_READ_FETCHED; 815 context->flags |= FLAG_READ_FETCHED;
816 //Should this happen after the prefetch or after the read? 816 //Should this happen after the prefetch or after the read?
817 //increment_address(context); 817 increment_address(context);
818 break; 818 break;
819 case VSRAM_READ: { 819 case VSRAM_READ: {
820 uint16_t address = (context->address /2) & 63; 820 uint16_t address = (context->address /2) & 63;
821 if (address >= VSRAM_SIZE) { 821 if (address >= VSRAM_SIZE) {
822 address = 0; 822 address = 0;
823 } 823 }
824 context->prefetch = context->vsram[address] & VSRAM_BITS; 824 context->prefetch = context->vsram[address] & VSRAM_BITS;
825 context->prefetch |= context->fifo[context->fifo_write].value & VSRAM_DIRTY_BITS; 825 context->prefetch |= context->fifo[context->fifo_write].value & VSRAM_DIRTY_BITS;
826 context->flags |= FLAG_READ_FETCHED; 826 context->flags |= FLAG_READ_FETCHED;
827 //Should this happen after the prefetch or after the read? 827 //Should this happen after the prefetch or after the read?
828 //increment_address(context); 828 increment_address(context);
829 break; 829 break;
830 } 830 }
831 } 831 }
832 } 832 }
833 } 833 }
2175 } 2175 }
2176 } 2176 }
2177 } else { 2177 } else {
2178 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; 2178 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5;
2179 context->address = (context->address &0xC000) | (value & 0x3FFF); 2179 context->address = (context->address &0xC000) | (value & 0x3FFF);
2180 //Genesis Plus GX doesn't clear out the upper mode bits in Mode 4, but instead 2180 context->cd = (context->cd & 0x3C) | (value >> 14);
2181 //ignores the uppper mode bits when it comes to reads/writes
2182 //testing on hardware is needed to determine which is truly correct
2183 context->cd = (mode_5 ? context->cd &0x3C : 0) | (value >> 14);
2184 if ((value & 0xC000) == 0x8000) { 2181 if ((value & 0xC000) == 0x8000) {
2185 //Register write 2182 //Register write
2186 uint8_t reg = (value >> 8) & 0x1F; 2183 uint8_t reg = (value >> 8) & 0x1F;
2187 if (reg < (mode_5 ? VDP_REGS : 0xB)) { 2184 if (reg < (mode_5 ? VDP_REGS : 0xB)) {
2188 //printf("register %d set to %X\n", reg, value & 0xFF); 2185 //printf("register %d set to %X\n", reg, value & 0xFF);
2255 } 2252 }
2256 fifo_entry * cur = context->fifo + context->fifo_write; 2253 fifo_entry * cur = context->fifo + context->fifo_write;
2257 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 2254 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
2258 cur->address = context->address; 2255 cur->address = context->address;
2259 cur->value = value; 2256 cur->value = value;
2260 cur->cd = context->cd; 2257 if (context->regs[REG_MODE_2] & BIT_MODE_5) {
2258 cur->cd = context->cd;
2259 } else {
2260 cur->cd = (context->cd & 2) | 1;
2261 }
2261 cur->partial = 0; 2262 cur->partial = 0;
2262 if (context->fifo_read < 0) { 2263 if (context->fifo_read < 0) {
2263 context->fifo_read = context->fifo_write; 2264 context->fifo_read = context->fifo_write;
2264 } 2265 }
2265 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1); 2266 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
2269 2270
2270 void vdp_data_port_write_pbc(vdp_context * context, uint8_t value) 2271 void vdp_data_port_write_pbc(vdp_context * context, uint8_t value)
2271 { 2272 {
2272 if (context->flags & FLAG_PENDING) { 2273 if (context->flags & FLAG_PENDING) {
2273 context->flags &= ~FLAG_PENDING; 2274 context->flags &= ~FLAG_PENDING;
2274 context->flags2 &= ~FLAG2_BYTE_PENDING;
2275 //Should these be cleared here? 2275 //Should these be cleared here?
2276 context->flags &= ~FLAG_READ_FETCHED; 2276 context->flags &= ~FLAG_READ_FETCHED;
2277 context->flags2 &= ~FLAG2_READ_PENDING; 2277 context->flags2 &= ~FLAG2_READ_PENDING;
2278 } 2278 }
2279 context->flags2 &= ~FLAG2_BYTE_PENDING;
2279 /*if (context->fifo_cur == context->fifo_end) { 2280 /*if (context->fifo_cur == context->fifo_end) {
2280 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles); 2281 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles);
2281 }*/ 2282 }*/
2282 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 2283 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
2283 context->flags &= ~FLAG_DMA_RUN; 2284 context->flags &= ~FLAG_DMA_RUN;
2287 } 2288 }
2288 fifo_entry * cur = context->fifo + context->fifo_write; 2289 fifo_entry * cur = context->fifo + context->fifo_write;
2289 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 2290 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
2290 cur->address = context->address; 2291 cur->address = context->address;
2291 cur->value = value; 2292 cur->value = value;
2292 cur->cd = context->cd | 1; 2293 if (context->regs[REG_MODE_2] & BIT_MODE_5) {
2294 cur->cd = context->cd;
2295 } else {
2296 cur->cd = (context->cd & 2) | 1;
2297 }
2293 cur->partial = 1; 2298 cur->partial = 1;
2294 if (context->fifo_read < 0) { 2299 if (context->fifo_read < 0) {
2295 context->fifo_read = context->fifo_write; 2300 context->fifo_read = context->fifo_write;
2296 } 2301 }
2297 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1); 2302 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
2369 } 2374 }
2370 while (!(context->flags & FLAG_READ_FETCHED)) { 2375 while (!(context->flags & FLAG_READ_FETCHED)) {
2371 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); 2376 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
2372 } 2377 }
2373 context->flags &= ~FLAG_READ_FETCHED; 2378 context->flags &= ~FLAG_READ_FETCHED;
2374 //Should this happen after the prefetch or after the read?
2375 increment_address(context);
2376 return context->prefetch; 2379 return context->prefetch;
2377 } 2380 }
2378 2381
2379 uint8_t vdp_data_port_read_pbc(vdp_context * context) 2382 uint8_t vdp_data_port_read_pbc(vdp_context * context)
2380 { 2383 {
2381 if (context->flags & FLAG_PENDING) { 2384 context->flags &= ~(FLAG_PENDING | FLAG_READ_FETCHED);
2382 context->flags &= ~FLAG_PENDING; 2385 context->flags2 &= ~FLAG2_BYTE_PENDING;
2383 context->flags2 &= ~FLAG2_BYTE_PENDING;
2384 2386
2385 }
2386 if (context->flags & FLAG_READ_FETCHED) {
2387 context->flags &= ~FLAG_READ_FETCHED;
2388 //Should this happen after the prefetch or after the read?
2389 increment_address(context);
2390 }
2391 context->cd = VRAM_READ8; 2387 context->cd = VRAM_READ8;
2392 return context->prefetch; 2388 return context->prefetch;
2393 } 2389 }
2394 2390
2395 uint16_t vdp_hv_counter_read(vdp_context * context) 2391 uint16_t vdp_hv_counter_read(vdp_context * context)