diff options
author | Oxore <oxore@protonmail.com> | 2022-10-03 02:59:26 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2022-10-03 02:59:26 +0300 |
commit | 46696e1d57aa33b3bf1cd54cc78ef58dc14c8079 (patch) | |
tree | 5f36e6a9739c002e617a1d8c25f42e912fa4355e | |
parent | b5397045db290c234a1e779b64538933f93b37b6 (diff) |
Impl DMA VRAM fill
-rw-r--r-- | emulator.cpp | 2 | ||||
-rw-r--r-- | vdp.cpp | 81 | ||||
-rw-r--r-- | vdp.hpp | 14 |
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; } @@ -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) @@ -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]{}; |