Mercurial > repos > blastem
comparison vdp.c @ 470:541c1ae8abf3
Properly delay 68K on VDP reads. Dummy VDP test port implementation. Initial stab at handling undefined bits of VSRAM and CRAM.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 13 Sep 2013 19:22:46 -0700 |
parents | 140af5509ce7 |
children | f065769836e8 |
comparison
equal
deleted
inserted
replaced
469:5f3344d0d42f | 470:541c1ae8abf3 |
---|---|
1 /* | 1 /* |
2 Copyright 2013 Michael Pavone | 2 Copyright 2013 Michael Pavone |
3 This file is part of BlastEm. | 3 This file is part of BlastEm. |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. |
5 */ | 5 */ |
6 #include "vdp.h" | 6 #include "vdp.h" |
7 #include "blastem.h" | 7 #include "blastem.h" |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
389 #define DMA_START 0x20 | 389 #define DMA_START 0x20 |
390 | 390 |
391 void external_slot(vdp_context * context) | 391 void external_slot(vdp_context * context) |
392 { | 392 { |
393 fifo_entry * start = (context->fifo_end - FIFO_SIZE); | 393 fifo_entry * start = (context->fifo_end - FIFO_SIZE); |
394 if (context->flags2 & FLAG2_READ_PENDING) { | |
395 context->flags2 &= ~FLAG2_READ_PENDING; | |
396 context->flags |= FLAG_UNUSED_SLOT; | |
397 return; | |
398 } | |
394 if (context->fifo_cur != start && start->cycle <= context->cycles) { | 399 if (context->fifo_cur != start && start->cycle <= context->cycles) { |
395 switch (start->cd & 0xF) | 400 switch (start->cd & 0xF) |
396 { | 401 { |
397 case VRAM_WRITE: | 402 case VRAM_WRITE: |
398 if (start->partial) { | 403 if (start->partial) { |
399 //printf("VRAM Write: %X to %X\n", start->value, context->address ^ 1); | 404 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); |
405 context->last_fifo_val = start->value; | |
400 context->vdpmem[start->address ^ 1] = start->value; | 406 context->vdpmem[start->address ^ 1] = start->value; |
401 } else { | 407 } else { |
402 //printf("VRAM Write High: %X to %X\n", start->value >> 8, context->address); | 408 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); |
403 context->vdpmem[start->address] = start->value >> 8; | 409 context->vdpmem[start->address] = start->value >> 8; |
404 start->partial = 1; | 410 start->partial = 1; |
405 //skip auto-increment and removal of entry from fifo | 411 //skip auto-increment and removal of entry from fifo |
406 return; | 412 return; |
407 } | 413 } |
408 break; | 414 break; |
409 case CRAM_WRITE: { | 415 case CRAM_WRITE: { |
410 //printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1)); | 416 //printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1)); |
411 write_cram(context, start->address, start->value); | 417 write_cram(context, start->address, start->value); |
418 context->last_fifo_val = start->value; | |
412 break; | 419 break; |
413 } | 420 } |
414 case VSRAM_WRITE: | 421 case VSRAM_WRITE: |
415 if (((start->address/2) & 63) < VSRAM_SIZE) { | 422 if (((start->address/2) & 63) < VSRAM_SIZE) { |
416 //printf("VSRAM Write: %X to %X\n", start->value, context->address); | 423 //printf("VSRAM Write: %X to %X\n", start->value, context->address); |
417 context->vsram[(start->address/2) & 63] = start->value; | 424 context->vsram[(start->address/2) & 63] = start->value; |
425 context->last_fifo_val = start->value; | |
418 } | 426 } |
419 | 427 |
420 break; | 428 break; |
421 } | 429 } |
422 fifo_entry * cur = start+1; | 430 fifo_entry * cur = start+1; |
1426 } | 1434 } |
1427 } | 1435 } |
1428 | 1436 |
1429 int vdp_control_port_write(vdp_context * context, uint16_t value) | 1437 int vdp_control_port_write(vdp_context * context, uint16_t value) |
1430 { | 1438 { |
1431 //printf("control port write: %X at %d\n", value, context->cycles); | 1439 printf("control port write: %X at %d\n", value, context->cycles); |
1432 if (context->flags & FLAG_DMA_RUN) { | 1440 if (context->flags & FLAG_DMA_RUN) { |
1433 return -1; | 1441 return -1; |
1434 } | 1442 } |
1435 if (context->flags & FLAG_PENDING) { | 1443 if (context->flags & FLAG_PENDING) { |
1436 context->address = (context->address & 0x3FFF) | (value << 14); | 1444 context->address = (context->address & 0x3FFF) | (value << 14); |
1480 return 0; | 1488 return 0; |
1481 } | 1489 } |
1482 | 1490 |
1483 int vdp_data_port_write(vdp_context * context, uint16_t value) | 1491 int vdp_data_port_write(vdp_context * context, uint16_t value) |
1484 { | 1492 { |
1485 //printf("data port write: %X at %d\n", value, context->cycles); | 1493 printf("data port write: %X at %d\n", value, context->cycles); |
1486 if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & 0xC0) != 0x80) { | 1494 if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & 0xC0) != 0x80) { |
1487 return -1; | 1495 return -1; |
1488 } | 1496 } |
1489 if (!(context->cd & 1)) { | 1497 if (!(context->cd & 1)) { |
1490 //ignore writes when cd is configured for read | 1498 //ignore writes when cd is configured for read |
1512 context->fifo_cur++; | 1520 context->fifo_cur++; |
1513 context->address += context->regs[REG_AUTOINC]; | 1521 context->address += context->regs[REG_AUTOINC]; |
1514 return 0; | 1522 return 0; |
1515 } | 1523 } |
1516 | 1524 |
1525 void vdp_test_port_write(vdp_context * context, uint16_t value) | |
1526 { | |
1527 //TODO: implement test register | |
1528 } | |
1529 | |
1517 uint16_t vdp_control_port_read(vdp_context * context) | 1530 uint16_t vdp_control_port_read(vdp_context * context) |
1518 { | 1531 { |
1519 context->flags &= ~FLAG_PENDING; | 1532 context->flags &= ~FLAG_PENDING; |
1520 uint16_t value = 0x3400; | 1533 uint16_t value = 0x3400; |
1521 if (context->fifo_cur == (context->fifo_end - FIFO_SIZE)) { | 1534 if (context->fifo_cur == (context->fifo_end - FIFO_SIZE)) { |
1547 //printf("status read at cycle %d returned %X\n", context->cycles, value); | 1560 //printf("status read at cycle %d returned %X\n", context->cycles, value); |
1548 //TODO: Sprite overflow, sprite collision, odd frame flag | 1561 //TODO: Sprite overflow, sprite collision, odd frame flag |
1549 return value; | 1562 return value; |
1550 } | 1563 } |
1551 | 1564 |
1565 #define CRAM_BITS 0xEEE | |
1566 #define VSRAM_BITS 0x3FF | |
1567 | |
1552 uint16_t vdp_data_port_read(vdp_context * context) | 1568 uint16_t vdp_data_port_read(vdp_context * context) |
1553 { | 1569 { |
1554 context->flags &= ~FLAG_PENDING; | 1570 context->flags &= ~FLAG_PENDING; |
1555 if (context->cd & 1) { | 1571 if (context->cd & 1) { |
1556 return 0; | 1572 return 0; |
1557 } | 1573 } |
1558 //Not sure if the FIFO should be drained before processing a read or not, but it would make sense | 1574 //Not sure if the FIFO should be drained before processing a read or not, but it would make sense |
1559 context->flags &= ~FLAG_UNUSED_SLOT; | 1575 context->flags &= ~FLAG_UNUSED_SLOT; |
1576 context->flags2 |= FLAG2_READ_PENDING; | |
1560 while (!(context->flags & FLAG_UNUSED_SLOT)) { | 1577 while (!(context->flags & FLAG_UNUSED_SLOT)) { |
1561 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); | 1578 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); |
1562 } | 1579 } |
1563 uint16_t value = 0; | 1580 uint16_t value = 0; |
1564 switch (context->cd & 0xF) | 1581 switch (context->cd & 0xF) |
1565 { | 1582 { |
1566 case VRAM_READ: | 1583 case VRAM_READ: |
1567 value = context->vdpmem[context->address] << 8; | 1584 value = context->vdpmem[context->address] << 8; |
1568 context->flags &= ~FLAG_UNUSED_SLOT; | 1585 context->flags &= ~FLAG_UNUSED_SLOT; |
1586 context->flags2 |= FLAG2_READ_PENDING; | |
1569 while (!(context->flags & FLAG_UNUSED_SLOT)) { | 1587 while (!(context->flags & FLAG_UNUSED_SLOT)) { |
1570 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); | 1588 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); |
1571 } | 1589 } |
1572 value |= context->vdpmem[context->address ^ 1]; | 1590 value |= context->vdpmem[context->address ^ 1]; |
1573 break; | 1591 break; |
1574 case CRAM_READ: | 1592 case CRAM_READ: |
1575 value = context->cram[(context->address/2) & (CRAM_SIZE-1)]; | 1593 value = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS; |
1594 value |= context->last_fifo_val & ~CRAM_BITS; | |
1576 break; | 1595 break; |
1577 case VSRAM_READ: | 1596 case VSRAM_READ: |
1578 if (((context->address / 2) & 63) < VSRAM_SIZE) { | 1597 if (((context->address / 2) & 63) < VSRAM_SIZE) { |
1579 value = context->vsram[context->address & 63]; | 1598 value = context->vsram[context->address & 63] & VSRAM_BITS; |
1599 value |= context->last_fifo_val & ~VSRAM_BITS; | |
1580 } | 1600 } |
1581 break; | 1601 break; |
1582 } | 1602 } |
1583 context->address += context->regs[REG_AUTOINC]; | 1603 context->address += context->regs[REG_AUTOINC]; |
1584 return value; | 1604 return value; |
1691 } | 1711 } |
1692 } | 1712 } |
1693 return (line << 8) | linecyc; | 1713 return (line << 8) | linecyc; |
1694 } | 1714 } |
1695 | 1715 |
1716 uint16_t vdp_test_port_read(vdp_context * context) | |
1717 { | |
1718 //TODO: Find out what actually gets returned here | |
1719 return 0xFFFF; | |
1720 } | |
1721 | |
1696 void vdp_adjust_cycles(vdp_context * context, uint32_t deduction) | 1722 void vdp_adjust_cycles(vdp_context * context, uint32_t deduction) |
1697 { | 1723 { |
1698 context->cycles -= deduction; | 1724 context->cycles -= deduction; |
1699 for(fifo_entry * start = (context->fifo_end - FIFO_SIZE); start < context->fifo_cur; start++) { | 1725 for(fifo_entry * start = (context->fifo_end - FIFO_SIZE); start < context->fifo_cur; start++) { |
1700 if (start->cycle >= deduction) { | 1726 if (start->cycle >= deduction) { |