comparison vdp.c @ 980:928442068afe

Implemented VDP read prefetch and made DMA copy not use the FIFO any more. Now up to 114 out of 122 passing on VDP FIFO Test ROM
author Michael Pavone <pavone@retrodev.com>
date Sun, 24 Apr 2016 01:24:38 -0700
parents 08346262990b
children 902c53d9c16f
comparison
equal deleted inserted replaced
979:771875b5f519 980:928442068afe
227 //2 would trigger register write 0010 227 //2 would trigger register write 0010
228 #define CRAM_WRITE 3 //0011 228 #define CRAM_WRITE 3 //0011
229 #define VSRAM_READ 4 //0100 229 #define VSRAM_READ 4 //0100
230 #define VSRAM_WRITE 5//0101 230 #define VSRAM_WRITE 5//0101
231 //6 would trigger regsiter write 0110 231 //6 would trigger regsiter write 0110
232 //7 is a mystery 232 //7 is a mystery //0111
233 #define CRAM_READ 8 //1000 233 #define CRAM_READ 8 //1000
234 //9 is also a mystery //1001 234 //9 is also a mystery //1001
235 //A would trigger register write 1010 235 //A would trigger register write 1010
236 //B is a mystery 1011 236 //B is a mystery 1011
237 #define VRAM_READ8 0xC //1100 237 #define VRAM_READ8 0xC //1100
238 //D is a mystery 1101 238 //D is a mystery 1101
239 //E would trigger register write 1110 239 //E would trigger register write 1110
240 //F is a mystery 1111 240 //F is a mystery 1111
241
242 //Possible theory on how bits work
243 //CD0 = Read/Write flag
244 //CD2,(CD1|CD3) = RAM type
245 // 00 = VRAM
246 // 01 = CRAM
247 // 10 = VSRAM
248 // 11 = VRAM8
249 //Would result in
250 // 7 = VRAM8 write
251 // 9 = CRAM write alias
252 // B = CRAM write alias
253 // D = VRAM8 write alias
254 // F = VRAM8 write alais
255
241 #define DMA_START 0x20 256 #define DMA_START 0x20
242 257
243 const char * cd_name(uint8_t cd) 258 const char * cd_name(uint8_t cd)
244 { 259 {
245 switch (cd & 0xF) 260 switch (cd & 0xF)
466 context->colors[addr] = color_map[value & 0xEEE]; 481 context->colors[addr] = color_map[value & 0xEEE];
467 context->colors[addr + CRAM_SIZE] = color_map[(value & 0xEEE) | FBUF_SHADOW]; 482 context->colors[addr + CRAM_SIZE] = color_map[(value & 0xEEE) | FBUF_SHADOW];
468 context->colors[addr + CRAM_SIZE*2] = color_map[(value & 0xEEE) | FBUF_HILIGHT]; 483 context->colors[addr + CRAM_SIZE*2] = color_map[(value & 0xEEE) | FBUF_HILIGHT];
469 } 484 }
470 485
486 #define CRAM_BITS 0xEEE
487 #define VSRAM_BITS 0x7FF
488 #define VSRAM_DIRTY_BITS 0xF800
489
471 void external_slot(vdp_context * context) 490 void external_slot(vdp_context * context)
472 { 491 {
473 fifo_entry * start = context->fifo + context->fifo_read; 492 fifo_entry * start = context->fifo + context->fifo_read;
474 /*if (context->flags2 & FLAG2_READ_PENDING) {
475 context->flags2 &= ~FLAG2_READ_PENDING;
476 context->flags |= FLAG_UNUSED_SLOT;
477 return;
478 }*/
479 if (context->fifo_read >= 0 && start->cycle <= context->cycles) { 493 if (context->fifo_read >= 0 && start->cycle <= context->cycles) {
480 switch (start->cd & 0xF) 494 switch (start->cd & 0xF)
481 { 495 {
482 case VRAM_WRITE: 496 case VRAM_WRITE:
483 if (start->partial) { 497 if (start->partial) {
506 } 520 }
507 context->fifo_read = (context->fifo_read+1) & (FIFO_SIZE-1); 521 context->fifo_read = (context->fifo_read+1) & (FIFO_SIZE-1);
508 if (context->fifo_read == context->fifo_write) { 522 if (context->fifo_read == context->fifo_write) {
509 context->fifo_read = -1; 523 context->fifo_read = -1;
510 } 524 }
511 context->flags &= ~FLAG_UNUSED_SLOT; 525 } else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0xC0) {
512 } else { 526 if (context->flags & FLAG_READ_FETCHED) {
513 context->flags |= FLAG_UNUSED_SLOT; 527 context->vdpmem[context->address ^ 1] = context->prefetch;
528
529 //Update DMA state
530 context->regs[REG_DMASRC_L] += 1;
531 if (!context->regs[REG_DMASRC_L]) {
532 context->regs[REG_DMASRC_M] += 1;
533 }
534 context->address += context->regs[REG_AUTOINC];
535 uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1;
536 context->regs[REG_DMALEN_H] = dma_len >> 8;
537 context->regs[REG_DMALEN_L] = dma_len;
538 if (!dma_len) {
539 context->flags &= ~FLAG_DMA_RUN;
540 context->cd &= 0xF;
541 }
542
543 context->flags &= ~FLAG_READ_FETCHED;
544 } else {
545 context->prefetch = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1];
546
547 context->flags |= FLAG_READ_FETCHED;
548 }
549 } else if (!(context->cd & 1) && !(context->flags & FLAG_READ_FETCHED)){
550 switch(context->cd & 0xF)
551 {
552 case VRAM_READ:
553 if (context->flags2 & FLAG2_READ_PENDING) {
554 context->prefetch |= context->vdpmem[context->address | 1];
555 context->flags |= FLAG_READ_FETCHED;
556 context->flags2 &= ~FLAG2_READ_PENDING;
557 //Should this happen after the prefetch or after the read?
558 //context->address += context->regs[REG_AUTOINC];
559 } else {
560 context->prefetch = context->vdpmem[context->address & 0xFFFE] << 8;
561 context->flags2 |= FLAG2_READ_PENDING;
562 }
563 break;
564 case VRAM_READ8:
565 context->prefetch = context->vdpmem[context->address ^ 1];
566 context->prefetch |= context->fifo[context->fifo_write].value & 0xFF00;
567 context->flags |= FLAG_READ_FETCHED;
568 //Should this happen after the prefetch or after the read?
569 //context->address += context->regs[REG_AUTOINC];
570 break;
571 case CRAM_READ:
572 context->prefetch = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS;
573 context->prefetch |= context->fifo[context->fifo_write].value & ~CRAM_BITS;
574 context->flags |= FLAG_READ_FETCHED;
575 //Should this happen after the prefetch or after the read?
576 //context->address += context->regs[REG_AUTOINC];
577 break;
578 case VSRAM_READ: {
579 uint16_t address = (context->address /2) & 63;
580 if (address >= VSRAM_SIZE) {
581 address = 0;
582 }
583 context->prefetch = context->vsram[address] & VSRAM_BITS;
584 context->prefetch |= context->fifo[context->fifo_write].value & VSRAM_DIRTY_BITS;
585 context->flags |= FLAG_READ_FETCHED;
586 //Should this happen after the prefetch or after the read?
587 //context->address += context->regs[REG_AUTOINC];
588 break;
589 }
590 }
514 } 591 }
515 } 592 }
516 593
517 void run_dma_src(vdp_context * context, int32_t slot) 594 void run_dma_src(vdp_context * context, int32_t slot)
518 { 595 {
539 context->fifo_read = context->fifo_write; 616 context->fifo_read = context->fifo_write;
540 } 617 }
541 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1); 618 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
542 } 619 }
543 break; 620 break;
544 //Copy 621 //Fill
545 case 0xC0:
546 if (context->flags & FLAG_UNUSED_SLOT && context->fifo_read < 0) {
547 //TODO: Fix this to not use the FIFO at all once read-caching is properly implemented
548 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1);
549 cur = context->fifo + context->fifo_read;
550 cur->cycle = context->cycles;
551 cur->address = context->address;
552 cur->partial = 1;
553 cur->value = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1] | (cur->value & 0xFF00);
554 cur->cd = VRAM_WRITE;
555 context->flags &= ~FLAG_UNUSED_SLOT;
556 }
557 break;
558 case 0x80: 622 case 0x80:
559 if (context->fifo_read < 0) { 623 if (context->fifo_read < 0) {
560 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1); 624 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1);
561 cur = context->fifo + context->fifo_read; 625 cur = context->fifo + context->fifo_read;
562 cur->cycle = context->cycles; 626 cur->cycle = context->cycles;
1525 } 1589 }
1526 if (context->flags & FLAG_PENDING) { 1590 if (context->flags & FLAG_PENDING) {
1527 context->address = (context->address & 0x3FFF) | (value << 14); 1591 context->address = (context->address & 0x3FFF) | (value << 14);
1528 context->cd = (context->cd & 0x3) | ((value >> 2) & 0x3C); 1592 context->cd = (context->cd & 0x3) | ((value >> 2) & 0x3C);
1529 context->flags &= ~FLAG_PENDING; 1593 context->flags &= ~FLAG_PENDING;
1594 //Should these be taken care of here or after the first write?
1595 context->flags &= ~FLAG_READ_FETCHED;
1596 context->flags2 &= ~FLAG2_READ_PENDING;
1530 //printf("New Address: %X, New CD: %X\n", context->address, context->cd); 1597 //printf("New Address: %X, New CD: %X\n", context->address, context->cd);
1531 if (context->cd & 0x20 && (context->regs[REG_MODE_2] & BIT_DMA_ENABLE)) { 1598 if (context->cd & 0x20 && (context->regs[REG_MODE_2] & BIT_DMA_ENABLE)) {
1532 // 1599 //
1533 if((context->regs[REG_DMASRC_H] & 0xC0) != 0x80) { 1600 if((context->regs[REG_DMASRC_H] & 0xC0) != 0x80) {
1534 //DMA copy or 68K -> VDP, transfer starts immediately 1601 //DMA copy or 68K -> VDP, transfer starts immediately
1571 } 1638 }
1572 } else { 1639 } else {
1573 context->flags |= FLAG_PENDING; 1640 context->flags |= FLAG_PENDING;
1574 context->address = (context->address &0xC000) | (value & 0x3FFF); 1641 context->address = (context->address &0xC000) | (value & 0x3FFF);
1575 context->cd = (context->cd &0x3C) | (value >> 14); 1642 context->cd = (context->cd &0x3C) | (value >> 14);
1643 //Should these be taken care of here or after the second write?
1644 //context->flags &= ~FLAG_READ_FETCHED;
1645 //context->flags2 &= ~FLAG2_READ_PENDING;
1576 } 1646 }
1577 } 1647 }
1578 return 0; 1648 return 0;
1579 } 1649 }
1580 1650
1582 { 1652 {
1583 //printf("data port write: %X at %d\n", value, context->cycles); 1653 //printf("data port write: %X at %d\n", value, context->cycles);
1584 if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & 0xC0) != 0x80) { 1654 if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & 0xC0) != 0x80) {
1585 return -1; 1655 return -1;
1586 } 1656 }
1587 context->flags &= ~FLAG_PENDING; 1657 if (context->flags & FLAG_PENDING) {
1658 context->flags &= ~FLAG_PENDING;
1659 //Should these be cleared here?
1660 context->flags &= ~FLAG_READ_FETCHED;
1661 context->flags2 &= ~FLAG2_READ_PENDING;
1662 }
1588 /*if (context->fifo_cur == context->fifo_end) { 1663 /*if (context->fifo_cur == context->fifo_end) {
1589 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles); 1664 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles);
1590 }*/ 1665 }*/
1591 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 1666 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
1592 context->flags &= ~FLAG_DMA_RUN; 1667 context->flags &= ~FLAG_DMA_RUN;
1617 } 1692 }
1618 1693
1619 uint16_t vdp_control_port_read(vdp_context * context) 1694 uint16_t vdp_control_port_read(vdp_context * context)
1620 { 1695 {
1621 context->flags &= ~FLAG_PENDING; 1696 context->flags &= ~FLAG_PENDING;
1622 uint16_t value = 0x3400; 1697 //TODO: Open bus emulation
1698 //Bits 15-10 are not fixed like Charles MacDonald's doc suggests, but instead open bus values that reflect 68K prefetch
1699 uint16_t value = 0;
1623 if (context->fifo_read < 0) { 1700 if (context->fifo_read < 0) {
1624 value |= 0x200; 1701 value |= 0x200;
1625 } 1702 }
1626 if (context->fifo_read == context->fifo_write) { 1703 if (context->fifo_read == context->fifo_write) {
1627 value |= 0x100; 1704 value |= 0x100;
1663 } 1740 }
1664 //printf("status read at cycle %d returned %X\n", context->cycles, value); 1741 //printf("status read at cycle %d returned %X\n", context->cycles, value);
1665 return value; 1742 return value;
1666 } 1743 }
1667 1744
1668 #define CRAM_BITS 0xEEE
1669 #define VSRAM_BITS 0x7FF
1670 #define VSRAM_DIRTY_BITS 0xF800
1671
1672 uint16_t vdp_data_port_read(vdp_context * context) 1745 uint16_t vdp_data_port_read(vdp_context * context)
1673 { 1746 {
1674 context->flags &= ~FLAG_PENDING; 1747 if (context->flags & FLAG_PENDING) {
1748 context->flags &= ~FLAG_PENDING;
1749 //Should these be cleared here?
1750 context->flags &= ~FLAG_READ_FETCHED;
1751 context->flags2 &= ~FLAG2_READ_PENDING;
1752 }
1675 if (context->cd & 1) { 1753 if (context->cd & 1) {
1676 return 0; 1754 return 0;
1677 } 1755 }
1678 //Not sure if the FIFO should be drained before processing a read or not, but it would make sense 1756 while (!(context->flags & FLAG_READ_FETCHED)) {
1679 context->flags &= ~FLAG_UNUSED_SLOT;
1680 //context->flags2 |= FLAG2_READ_PENDING;
1681 while (!(context->flags & FLAG_UNUSED_SLOT)) {
1682 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); 1757 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1683 } 1758 }
1684 uint16_t value = 0; 1759 context->flags &= ~FLAG_READ_FETCHED;
1685 switch (context->cd & 0xF) 1760 //Should this happen after the prefetch or after the read?
1686 {
1687 case VRAM_READ:
1688 value = context->vdpmem[context->address & 0xFFFE] << 8;
1689 context->flags &= ~FLAG_UNUSED_SLOT;
1690 context->flags2 |= FLAG2_READ_PENDING;
1691 while (!(context->flags & FLAG_UNUSED_SLOT)) {
1692 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1693 }
1694 value |= context->vdpmem[context->address | 1];
1695 break;
1696 case VRAM_READ8:
1697 value = context->vdpmem[context->address ^ 1];
1698 value |= context->fifo[context->fifo_write].value & 0xFF00;
1699 break;
1700 case CRAM_READ:
1701 value = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS;
1702 value |= context->fifo[context->fifo_write].value & ~CRAM_BITS;
1703 break;
1704 case VSRAM_READ: {
1705 uint16_t address = (context->address /2) & 63;
1706 if (address >= VSRAM_SIZE) {
1707 address = 0;
1708 }
1709 value = context->vsram[address] & VSRAM_BITS;
1710 value |= context->fifo[context->fifo_write].value & VSRAM_DIRTY_BITS;
1711 break;
1712 }
1713 }
1714 context->address += context->regs[REG_AUTOINC]; 1761 context->address += context->regs[REG_AUTOINC];
1715 return value; 1762 return context->prefetch;
1716 } 1763 }
1717 1764
1718 uint16_t vdp_hv_counter_read(vdp_context * context) 1765 uint16_t vdp_hv_counter_read(vdp_context * context)
1719 { 1766 {
1720 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) { 1767 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) {