summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2022-10-03 02:59:26 +0300
committerOxore <oxore@protonmail.com>2022-10-03 02:59:26 +0300
commit46696e1d57aa33b3bf1cd54cc78ef58dc14c8079 (patch)
tree5f36e6a9739c002e617a1d8c25f42e912fa4355e
parentb5397045db290c234a1e779b64538933f93b37b6 (diff)
Impl DMA VRAM fill
-rw-r--r--emulator.cpp2
-rw-r--r--vdp.cpp81
-rw-r--r--vdp.hpp14
3 files changed, 72 insertions, 25 deletions
diff --git a/emulator.cpp b/emulator.cpp
index 7b2e8a8..2ee42ba 100644
--- a/emulator.cpp
+++ b/emulator.cpp
@@ -330,7 +330,7 @@ int m68k_irq_ack(int level)
{
(void) level;
// TODO
- printf("IRQ ack\n");
+ printf("IRQ level %d acknowledged\n", level);
return level;
}
diff --git a/vdp.cpp b/vdp.cpp
index 0395d30..b1f5817 100644
--- a/vdp.cpp
+++ b/vdp.cpp
@@ -94,7 +94,24 @@ void VDP::Write(const uint32_t offset, const enum bitness bitness, const uint32_
bitness * 2,
value);
}
- if (bitness == BITNESS_32) {
+ if (_dma_ready) {
+ _dma_ready = false;
+ if (DEBUG_TRACE_VDP_ACCESS) {
+ printf(": Running DMA VRAM Fill");
+ }
+ const uint16_t destination_address = _address;
+ const uint16_t transfer_size =
+ _reg[static_cast<size_t>(RegID::kDMALengthCounterLow)] |
+ (_reg[static_cast<size_t>(RegID::kDMALengthCounterHigh)] << 8);
+ const uint8_t increment = _reg[static_cast<size_t>(RegID::kAutoIncrement)];
+ runDMAVRAMFill(
+ baseFromAddressMode(_address_mode),
+ destination_address,
+ transfer_size,
+ increment,
+ value);
+ _address += transfer_size * increment / 2;
+ } else if (bitness == BITNESS_32) {
if (offset == 0) {
writeData(_address_mode, _address & 0xfffe, (value >> 16) & 0xffff);
_address += _reg[static_cast<size_t>(RegID::kAutoIncrement)];
@@ -142,6 +159,8 @@ void VDP::Reset()
{
_status = {};
_control_write_second_word = {};
+ _dma_ready = {};
+ _lines_counter = {};
_address_mode = {};
_address = {};
memset(_reg, 0, kRegistersCount);
@@ -233,6 +252,7 @@ void VDP::writeControl(const uint16_t value)
const uint16_t transfer_size =
_reg[static_cast<size_t>(RegID::kDMALengthCounterLow)] |
(_reg[static_cast<size_t>(RegID::kDMALengthCounterHigh)] << 8);
+ const uint8_t increment = _reg[static_cast<size_t>(RegID::kAutoIncrement)];
const uint8_t dma_action =
DMASRCADRHIGH_DMD_GET(_reg[static_cast<size_t>(RegID::kDMASourceAddressHigh)]);
switch (dma_action) {
@@ -240,7 +260,7 @@ void VDP::writeControl(const uint16_t value)
case 1:
{
if (DEBUG_TRACE_VDP_ACCESS) {
- printf(": Running DMA Memory to VRAM\n");
+ printf(": Running DMA Memory to VRAM");
}
const uint32_t source_address =
_reg[static_cast<size_t>(RegID::kDMASourceAddressLow)] |
@@ -250,23 +270,26 @@ void VDP::writeControl(const uint16_t value)
baseFromAddressMode(_address_mode),
source_address,
destination_address,
- transfer_size);
+ transfer_size,
+ increment);
+ _address += transfer_size * increment / 2;
}
break;
case 2:
{
if (DEBUG_TRACE_VDP_ACCESS) {
- printf(": Running DMA VRAM Fill\n");
+ printf(": Ready to run DMA VRAM Fill");
}
- runDMAVRAMFill(baseFromAddressMode(_address_mode));
+ _dma_ready = true;
}
break;
case 3:
{
if (DEBUG_TRACE_VDP_ACCESS) {
- printf(": Running DMA VRAM Copy\n");
+ printf(": Running DMA VRAM Copy");
}
runDMAVRAMCopy(baseFromAddressMode(_address_mode));
+ _address += transfer_size * increment / 2;
}
break;
}
@@ -527,33 +550,47 @@ void VDP::runDMAMemoryToVRAM(
uint8_t* const base,
const uint32_t source_address,
const uint16_t destination_address,
- const uint16_t transfer_size)
+ const uint16_t transfer_size,
+ const uint8_t increment)
{
constexpr size_t kDumpWidth = 16;
- constexpr size_t kVisualColumnWidth = 8;
- for (size_t i = 0; i < transfer_size; i++) {
+ for (size_t i = 0, o = 0; i < transfer_size; i += 2, o += increment) {
const uint32_t src_addr = source_address + i;
- const uint32_t dst_addr = destination_address + i;
- const uint8_t value = m68k_read_memory_8(src_addr);
+ const uint32_t dst_addr = destination_address + o;
+ const uint16_t value = m68k_read_memory_16(src_addr);
if (DEBUG_TRACE_VDP_ACCESS) {
if (i % kDumpWidth == 0) {
- printf("%06x:%06x: ", src_addr, dst_addr);
- }
- printf("%02x ", value);
- if (i % kVisualColumnWidth == kVisualColumnWidth - 1) {
- printf(" ");
- } else if (i % kDumpWidth == kDumpWidth - 1) {
- printf("\n");
+ printf("\n%06x:%06x: ", src_addr, dst_addr);
}
+ printf("%04x ", value);
}
- base[dst_addr] = value;
+ base[dst_addr + 0] = (value >> 8) & 0xff;
+ base[dst_addr + 1] = value & 0xff;
}
}
-void VDP::runDMAVRAMFill(uint8_t* base)
+void VDP::runDMAVRAMFill(
+ uint8_t* const base,
+ const uint16_t destination_address,
+ const uint16_t transfer_size,
+ const uint8_t increment,
+ const uint16_t filler)
{
- (void) base;
- // TODO
+ if (DEBUG_TRACE_VDP_ACCESS) {
+ printf(
+ "\nVDP DMA Fill @%06x..%06x = 0x%04x",
+ destination_address,
+ destination_address + transfer_size,
+ filler);
+ }
+ for (size_t i = 0, o = 0; i < transfer_size; i += 2, o += increment) {
+ // TODO: There must some complex byte order shit be happening, depending
+ // on odd/even destination address
+ const uint16_t dst_addr = destination_address + o;
+ const uint16_t value = filler;
+ base[dst_addr + 0] = (value >> 8) & 0xff;
+ base[dst_addr + 1] = value & 0xff;
+ }
}
void VDP::runDMAVRAMCopy(uint8_t* base)
diff --git a/vdp.hpp b/vdp.hpp
index 030b38e..1db49db 100644
--- a/vdp.hpp
+++ b/vdp.hpp
@@ -77,8 +77,14 @@ class VDP {
uint8_t* base,
uint32_t source_address,
uint16_t destination_address,
- uint16_t transfer_size);
- static void runDMAVRAMFill(uint8_t* base);
+ uint16_t transfer_size,
+ uint8_t increment);
+ static void runDMAVRAMFill(
+ uint8_t* base,
+ uint16_t destination_address,
+ uint16_t transfer_size,
+ uint8_t increment,
+ uint16_t filler);
static void runDMAVRAMCopy(uint8_t* base);
static constexpr size_t kRegistersCount = static_cast<size_t>(RegID::kRegistersCount);
@@ -90,7 +96,11 @@ class VDP {
StatusRegister _status{};
bool _control_write_second_word{};
+ // DMA Fill is ready to kick in, waiting for filler set to data port
+ bool _dma_ready{};
uint16_t _lines_counter{};
+ // TODO: Make _address_mode of type AddressMode somehow and all private
+ // methods using it should be accepting AddressMode instead of uint8_t.
uint8_t _address_mode{};
uint16_t _address{};
uint8_t _reg[kRegistersCount]{};