Mercurial > repos > blastem
comparison vdp.c @ 984:bd4d698d995b
FIFO should show as empty during a DMA fill after the initial write is done. BlastEm now gets a perfect score in VDP FIFO Testing
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 24 Apr 2016 14:30:15 -0700 |
parents | 14d2f3b0e45d |
children | f9ee6f746cb4 |
comparison
equal
deleted
inserted
replaced
983:14d2f3b0e45d | 984:bd4d698d995b |
---|---|
485 | 485 |
486 #define CRAM_BITS 0xEEE | 486 #define CRAM_BITS 0xEEE |
487 #define VSRAM_BITS 0x7FF | 487 #define VSRAM_BITS 0x7FF |
488 #define VSRAM_DIRTY_BITS 0xF800 | 488 #define VSRAM_DIRTY_BITS 0xF800 |
489 | 489 |
490 void vdp_advance_dma(vdp_context * context) | |
491 { | |
492 context->regs[REG_DMASRC_L] += 1; | |
493 if (!context->regs[REG_DMASRC_L]) { | |
494 context->regs[REG_DMASRC_M] += 1; | |
495 } | |
496 context->address += context->regs[REG_AUTOINC]; | |
497 uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1; | |
498 context->regs[REG_DMALEN_H] = dma_len >> 8; | |
499 context->regs[REG_DMALEN_L] = dma_len; | |
500 if (!dma_len) { | |
501 context->flags &= ~FLAG_DMA_RUN; | |
502 context->cd &= 0xF; | |
503 } | |
504 } | |
505 | |
490 void external_slot(vdp_context * context) | 506 void external_slot(vdp_context * context) |
491 { | 507 { |
508 if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80 && context->fifo_read < 0) { | |
509 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1); | |
510 fifo_entry * cur = context->fifo + context->fifo_read; | |
511 cur->cycle = context->cycles; | |
512 cur->address = context->address; | |
513 cur->partial = 2; | |
514 vdp_advance_dma(context); | |
515 } | |
492 fifo_entry * start = context->fifo + context->fifo_read; | 516 fifo_entry * start = context->fifo + context->fifo_read; |
493 if (context->fifo_read >= 0 && start->cycle <= context->cycles) { | 517 if (context->fifo_read >= 0 && start->cycle <= context->cycles) { |
494 switch (start->cd & 0xF) | 518 switch (start->cd & 0xF) |
495 { | 519 { |
496 case VRAM_WRITE: | 520 case VRAM_WRITE: |
528 } else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0xC0) { | 552 } else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0xC0) { |
529 if (context->flags & FLAG_READ_FETCHED) { | 553 if (context->flags & FLAG_READ_FETCHED) { |
530 context->vdpmem[context->address ^ 1] = context->prefetch; | 554 context->vdpmem[context->address ^ 1] = context->prefetch; |
531 | 555 |
532 //Update DMA state | 556 //Update DMA state |
533 context->regs[REG_DMASRC_L] += 1; | 557 vdp_advance_dma(context); |
534 if (!context->regs[REG_DMASRC_L]) { | |
535 context->regs[REG_DMASRC_M] += 1; | |
536 } | |
537 context->address += context->regs[REG_AUTOINC]; | |
538 uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1; | |
539 context->regs[REG_DMALEN_H] = dma_len >> 8; | |
540 context->regs[REG_DMALEN_L] = dma_len; | |
541 if (!dma_len) { | |
542 context->flags &= ~FLAG_DMA_RUN; | |
543 context->cd &= 0xF; | |
544 } | |
545 | 558 |
546 context->flags &= ~FLAG_READ_FETCHED; | 559 context->flags &= ~FLAG_READ_FETCHED; |
547 } else { | 560 } else { |
548 context->prefetch = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1]; | 561 context->prefetch = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1]; |
549 | 562 |
596 | 609 |
597 void run_dma_src(vdp_context * context, int32_t slot) | 610 void run_dma_src(vdp_context * context, int32_t slot) |
598 { | 611 { |
599 //TODO: Figure out what happens if CD bit 4 is not set in DMA copy mode | 612 //TODO: Figure out what happens if CD bit 4 is not set in DMA copy mode |
600 //TODO: Figure out what happens when CD:0-3 is not set to a write mode in DMA operations | 613 //TODO: Figure out what happens when CD:0-3 is not set to a write mode in DMA operations |
601 //TODO: Figure out what happens if DMA gets disabled part way through a DMA fill or DMA copy | |
602 if (context->fifo_write == context->fifo_read) { | 614 if (context->fifo_write == context->fifo_read) { |
603 return; | 615 return; |
604 } | 616 } |
605 fifo_entry * cur = NULL; | 617 fifo_entry * cur = NULL; |
606 switch(context->regs[REG_DMASRC_H] & 0xC0) | 618 if (!(context->regs[REG_DMASRC_H] & 0x80)) |
607 { | 619 { |
608 //68K -> VDP | 620 //68K -> VDP |
609 case 0: | |
610 case 0x40: | |
611 if (slot == -1 || !is_refresh(context, slot-1)) { | 621 if (slot == -1 || !is_refresh(context, slot-1)) { |
612 cur = context->fifo + context->fifo_write; | 622 cur = context->fifo + context->fifo_write; |
613 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; | 623 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; |
614 cur->address = context->address; | 624 cur->address = context->address; |
615 cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); | 625 cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); |
617 cur->partial = 0; | 627 cur->partial = 0; |
618 if (context->fifo_read < 0) { | 628 if (context->fifo_read < 0) { |
619 context->fifo_read = context->fifo_write; | 629 context->fifo_read = context->fifo_write; |
620 } | 630 } |
621 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1); | 631 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1); |
622 } | 632 vdp_advance_dma(context); |
623 break; | |
624 //Fill | |
625 case 0x80: | |
626 if (context->fifo_read < 0) { | |
627 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1); | |
628 cur = context->fifo + context->fifo_read; | |
629 cur->cycle = context->cycles; | |
630 cur->address = context->address; | |
631 cur->partial = 2; | |
632 } | |
633 break; | |
634 } | |
635 | |
636 if (cur) { | |
637 context->regs[REG_DMASRC_L] += 1; | |
638 if (!context->regs[REG_DMASRC_L]) { | |
639 context->regs[REG_DMASRC_M] += 1; | |
640 } | |
641 context->address += context->regs[REG_AUTOINC]; | |
642 uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1; | |
643 context->regs[REG_DMALEN_H] = dma_len >> 8; | |
644 context->regs[REG_DMALEN_L] = dma_len; | |
645 if (!dma_len) { | |
646 //printf("DMA end at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", context->cycles, context->frame, context->vcounter, context->hslot); | |
647 context->flags &= ~FLAG_DMA_RUN; | |
648 context->cd &= 0xF; | |
649 } | 633 } |
650 } | 634 } |
651 } | 635 } |
652 | 636 |
653 #define WINDOW_RIGHT 0x80 | 637 #define WINDOW_RIGHT 0x80 |