Mercurial > repos > blastem
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) |