comparison vdp.c @ 478:2e4a4188cfb0

Fix DMA fill so that it does not cause observable changes to the FIFO. Get DMA copy mostly correct from an observable ffect perspective. DMA copy probably does not reflect internal implementation still given that evidence seems to suggest no FIFO usage at all.
author Mike Pavone <pavone@retrodev.com>
date Tue, 17 Sep 2013 00:11:45 -0700
parents 7fe655d4e2b7
children 863e868752cf
comparison
equal deleted inserted replaced
477:7fe655d4e2b7 478:2e4a4188cfb0
408 switch (start->cd & 0xF) 408 switch (start->cd & 0xF)
409 { 409 {
410 case VRAM_WRITE: 410 case VRAM_WRITE:
411 if (start->partial) { 411 if (start->partial) {
412 //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); 412 //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);
413 context->last_fifo_val = start->value; 413 context->vdpmem[start->address ^ 1] = start->partial == 2 ? start->value >> 8 : start->value;
414 context->vdpmem[start->address ^ 1] = start->value;
415 } else { 414 } else {
416 //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); 415 //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);
417 context->vdpmem[start->address] = start->value >> 8; 416 context->vdpmem[start->address] = start->value >> 8;
418 start->partial = 1; 417 start->partial = 1;
419 //skip auto-increment and removal of entry from fifo 418 //skip auto-increment and removal of entry from fifo
421 } 420 }
422 break; 421 break;
423 case CRAM_WRITE: { 422 case CRAM_WRITE: {
424 //printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1)); 423 //printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1));
425 write_cram(context, start->address, start->value); 424 write_cram(context, start->address, start->value);
426 context->last_fifo_val = start->value;
427 break; 425 break;
428 } 426 }
429 case VSRAM_WRITE: 427 case VSRAM_WRITE:
430 if (((start->address/2) & 63) < VSRAM_SIZE) { 428 if (((start->address/2) & 63) < VSRAM_SIZE) {
431 //printf("VSRAM Write: %X to %X\n", start->value, context->address); 429 //printf("VSRAM Write: %X to %X\n", start->value, context->address);
432 context->vsram[(start->address/2) & 63] = start->value; 430 context->vsram[(start->address/2) & 63] = start->value;
433 context->last_fifo_val = start->value;
434 } 431 }
435 432
436 break; 433 break;
437 } 434 }
438 context->fifo_read = (context->fifo_read+1) & (FIFO_SIZE-1); 435 context->fifo_read = (context->fifo_read+1) & (FIFO_SIZE-1);
450 //TODO: Figure out what happens when CD:0-3 is not set to a write mode in DMA operations 447 //TODO: Figure out what happens when CD:0-3 is not set to a write mode in DMA operations
451 //TODO: Figure out what happens if DMA gets disabled part way through a DMA fill or DMA copy 448 //TODO: Figure out what happens if DMA gets disabled part way through a DMA fill or DMA copy
452 if (context->fifo_write == context->fifo_read) { 449 if (context->fifo_write == context->fifo_read) {
453 return; 450 return;
454 } 451 }
455 uint16_t read_val; 452 fifo_entry * cur = NULL;
456 uint8_t ran_source = 0, partial = 0;
457 uint16_t dma_len;
458 uint8_t cd = context->cd;
459 switch(context->regs[REG_DMASRC_H] & 0xC0) 453 switch(context->regs[REG_DMASRC_H] & 0xC0)
460 { 454 {
461 //68K -> VDP 455 //68K -> VDP
462 case 0: 456 case 0:
463 case 0x40: 457 case 0x40:
464 if (!slot || !is_refresh(context, slot-1)) { 458 if (!slot || !is_refresh(context, slot-1)) {
465 read_val = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); 459 cur = context->fifo + context->fifo_write;
466 ran_source = 1; 460 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
461 cur->address = context->address;
462 cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]);
463 cur->cd = context->cd;
464 cur->partial = 0;
465 if (context->fifo_read < 0) {
466 context->fifo_read = context->fifo_write;
467 }
468 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
467 } 469 }
468 break; 470 break;
469 //Copy 471 //Copy
470 case 0xC0: 472 case 0xC0:
471 if (context->flags & FLAG_UNUSED_SLOT) { 473 if (context->flags & FLAG_UNUSED_SLOT && context->fifo_read < 0) {
472 read_val = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1] | (context->fifo[context->fifo_write].value & 0xFF00); 474 //TODO: Fix this to not use the FIFO at all once read-caching is properly implemented
473 cd = VRAM_WRITE; 475 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1);
474 partial = 1; 476 cur = context->fifo + context->fifo_read;
475 ran_source = 1; 477 cur->cycle = context->cycles;
478 cur->address = context->address;
479 cur->partial = 1;
480 cur->value = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1] | (cur->value & 0xFF00);
481 cur->cd = VRAM_WRITE;
476 context->flags &= ~FLAG_UNUSED_SLOT; 482 context->flags &= ~FLAG_UNUSED_SLOT;
477 } 483 }
478 break; 484 break;
479 case 0x80: 485 case 0x80:
480 read_val = (context->cd & 0xF) == VRAM_WRITE ? context->last_write_val >> 8 : context->last_write_val;
481 partial = 1;
482 ran_source = 1;
483 break;
484 }
485
486 if (ran_source) {
487 fifo_entry * cur = context->fifo + context->fifo_write;
488 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
489 cur->address = context->address;
490 cur->value = read_val;
491 cur->cd = cd;
492 cur->partial = partial;
493 if (context->fifo_read < 0) { 486 if (context->fifo_read < 0) {
494 context->fifo_read = context->fifo_write; 487 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1);
495 } 488 cur = context->fifo + context->fifo_read;
496 context->fifo_write = (context->fifo_write+1) & (FIFO_SIZE-1); 489 cur->cycle = context->cycles;
490 cur->address = context->address;
491 cur->partial = 2;
492 }
493 break;
494 }
495
496 if (cur) {
497 context->regs[REG_DMASRC_L] += 1; 497 context->regs[REG_DMASRC_L] += 1;
498 if (!context->regs[REG_DMASRC_L]) { 498 if (!context->regs[REG_DMASRC_L]) {
499 context->regs[REG_DMASRC_M] += 1; 499 context->regs[REG_DMASRC_M] += 1;
500 } 500 }
501 context->address += context->regs[REG_AUTOINC]; 501 context->address += context->regs[REG_AUTOINC];
502 dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1; 502 uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1;
503 context->regs[REG_DMALEN_H] = dma_len >> 8; 503 context->regs[REG_DMALEN_H] = dma_len >> 8;
504 context->regs[REG_DMALEN_L] = dma_len; 504 context->regs[REG_DMALEN_L] = dma_len;
505 if (!dma_len) { 505 if (!dma_len) {
506 //printf("DMA end at cycle %d\n", context->cycles); 506 //printf("DMA end at cycle %d\n", context->cycles);
507 context->flags &= ~FLAG_DMA_RUN; 507 context->flags &= ~FLAG_DMA_RUN;
1506 } 1506 }
1507 fifo_entry * cur = context->fifo + context->fifo_write; 1507 fifo_entry * cur = context->fifo + context->fifo_write;
1508 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 1508 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
1509 cur->address = context->address; 1509 cur->address = context->address;
1510 cur->value = value; 1510 cur->value = value;
1511 context->last_write_val = value;
1512 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 1511 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
1513 context->flags |= FLAG_DMA_RUN; 1512 context->flags |= FLAG_DMA_RUN;
1514 } 1513 }
1515 cur->cd = context->cd; 1514 cur->cd = context->cd;
1516 cur->partial = 0; 1515 cur->partial = 0;