Refactor DMA channel structure: consolidate and update definitions, remove obsolete header

This commit is contained in:
scawful
2024-11-08 21:02:56 -05:00
parent e21bdb3f44
commit 33f9053e34
3 changed files with 91 additions and 107 deletions

View File

@@ -17,23 +17,23 @@ static const int transferLength[8] = {1, 2, 2, 4, 4, 4, 2, 4};
void Reset(MemoryImpl* memory) { void Reset(MemoryImpl* memory) {
auto channel = memory->dma_channels(); auto channel = memory->dma_channels();
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
channel[i].bAdr = 0xff; channel[i].b_addr = 0xff;
channel[i].aAdr = 0xffff; channel[i].a_addr = 0xffff;
channel[i].aBank = 0xff; channel[i].a_bank = 0xff;
channel[i].size = 0xffff; channel[i].size = 0xffff;
channel[i].indBank = 0xff; channel[i].ind_bank = 0xff;
channel[i].tableAdr = 0xffff; channel[i].table_addr = 0xffff;
channel[i].repCount = 0xff; channel[i].rep_count = 0xff;
channel[i].unusedByte = 0xff; channel[i].unusedByte = 0xff;
channel[i].dmaActive = false; channel[i].dma_active = false;
channel[i].hdmaActive = false; channel[i].hdma_active = false;
channel[i].mode = 7; channel[i].mode = 7;
channel[i].fixed = true; channel[i].fixed = true;
channel[i].decrement = true; channel[i].decrement = true;
channel[i].indirect = true; channel[i].indirect = true;
channel[i].fromB = true; channel[i].from_b = true;
channel[i].unusedBit = true; channel[i].unusedBit = true;
channel[i].doTransfer = false; channel[i].do_transfer = false;
channel[i].terminated = false; channel[i].terminated = false;
} }
memory->set_dma_state(0); memory->set_dma_state(0);
@@ -51,20 +51,20 @@ uint8_t Read(MemoryImpl* memory, uint16_t adr) {
val |= channel[c].decrement << 4; val |= channel[c].decrement << 4;
val |= channel[c].unusedBit << 5; val |= channel[c].unusedBit << 5;
val |= channel[c].indirect << 6; val |= channel[c].indirect << 6;
val |= channel[c].fromB << 7; val |= channel[c].from_b << 7;
return val; return val;
} }
case 0x1: { case 0x1: {
return channel[c].bAdr; return channel[c].b_addr;
} }
case 0x2: { case 0x2: {
return channel[c].aAdr & 0xff; return channel[c].a_addr & 0xff;
} }
case 0x3: { case 0x3: {
return channel[c].aAdr >> 8; return channel[c].a_addr >> 8;
} }
case 0x4: { case 0x4: {
return channel[c].aBank; return channel[c].a_bank;
} }
case 0x5: { case 0x5: {
return channel[c].size & 0xff; return channel[c].size & 0xff;
@@ -73,16 +73,16 @@ uint8_t Read(MemoryImpl* memory, uint16_t adr) {
return channel[c].size >> 8; return channel[c].size >> 8;
} }
case 0x7: { case 0x7: {
return channel[c].indBank; return channel[c].ind_bank;
} }
case 0x8: { case 0x8: {
return channel[c].tableAdr & 0xff; return channel[c].table_addr & 0xff;
} }
case 0x9: { case 0x9: {
return channel[c].tableAdr >> 8; return channel[c].table_addr >> 8;
} }
case 0xa: { case 0xa: {
return channel[c].repCount; return channel[c].rep_count;
} }
case 0xb: case 0xb:
case 0xf: { case 0xf: {
@@ -104,23 +104,23 @@ void Write(MemoryImpl* memory, uint16_t adr, uint8_t val) {
channel[c].decrement = val & 0x10; channel[c].decrement = val & 0x10;
channel[c].unusedBit = val & 0x20; channel[c].unusedBit = val & 0x20;
channel[c].indirect = val & 0x40; channel[c].indirect = val & 0x40;
channel[c].fromB = val & 0x80; channel[c].from_b = val & 0x80;
break; break;
} }
case 0x1: { case 0x1: {
channel[c].bAdr = val; channel[c].b_addr = val;
break; break;
} }
case 0x2: { case 0x2: {
channel[c].aAdr = (channel[c].aAdr & 0xff00) | val; channel[c].a_addr = (channel[c].a_addr & 0xff00) | val;
break; break;
} }
case 0x3: { case 0x3: {
channel[c].aAdr = (channel[c].aAdr & 0xff) | (val << 8); channel[c].a_addr = (channel[c].a_addr & 0xff) | (val << 8);
break; break;
} }
case 0x4: { case 0x4: {
channel[c].aBank = val; channel[c].a_bank = val;
break; break;
} }
case 0x5: { case 0x5: {
@@ -132,19 +132,19 @@ void Write(MemoryImpl* memory, uint16_t adr, uint8_t val) {
break; break;
} }
case 0x7: { case 0x7: {
channel[c].indBank = val; channel[c].ind_bank = val;
break; break;
} }
case 0x8: { case 0x8: {
channel[c].tableAdr = (channel[c].tableAdr & 0xff00) | val; channel[c].table_addr = (channel[c].table_addr & 0xff00) | val;
break; break;
} }
case 0x9: { case 0x9: {
channel[c].tableAdr = (channel[c].tableAdr & 0xff) | (val << 8); channel[c].table_addr = (channel[c].table_addr & 0xff) | (val << 8);
break; break;
} }
case 0xa: { case 0xa: {
channel[c].repCount = val; channel[c].rep_count = val;
break; break;
} }
case 0xb: case 0xb:
@@ -168,22 +168,22 @@ void DoDma(SNES* snes, MemoryImpl* memory, int cpuCycles) {
// full transfer overhead // full transfer overhead
WaitCycle(snes, memory); WaitCycle(snes, memory);
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (!channel[i].dmaActive) continue; if (!channel[i].dma_active) continue;
// do channel i // do channel i
WaitCycle(snes, memory); // overhead per channel WaitCycle(snes, memory); // overhead per channel
int offIndex = 0; int offIndex = 0;
while (channel[i].dmaActive) { while (channel[i].dma_active) {
WaitCycle(snes, memory); WaitCycle(snes, memory);
TransferByte(snes, memory, channel[i].aAdr, channel[i].aBank, TransferByte(snes, memory, channel[i].a_addr, channel[i].a_bank,
channel[i].bAdr + bAdrOffsets[channel[i].mode][offIndex++], channel[i].b_addr + bAdrOffsets[channel[i].mode][offIndex++],
channel[i].fromB); channel[i].from_b);
offIndex &= 3; offIndex &= 3;
if (!channel[i].fixed) { if (!channel[i].fixed) {
channel[i].aAdr += channel[i].decrement ? -1 : 1; channel[i].a_addr += channel[i].decrement ? -1 : 1;
} }
channel[i].size--; channel[i].size--;
if (channel[i].size == 0) { if (channel[i].size == 0) {
channel[i].dmaActive = false; channel[i].dma_active = false;
} }
} }
} }
@@ -224,8 +224,8 @@ void InitHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cpu_cycles) {
bool hdmaEnabled = false; bool hdmaEnabled = false;
// check if a channel is enabled, and do reset // check if a channel is enabled, and do reset
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (channel[i].hdmaActive) hdmaEnabled = true; if (channel[i].hdma_active) hdmaEnabled = true;
channel[i].doTransfer = false; channel[i].do_transfer = false;
channel[i].terminated = false; channel[i].terminated = false;
} }
if (!hdmaEnabled) return; if (!hdmaEnabled) return;
@@ -235,24 +235,24 @@ void InitHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cpu_cycles) {
// full transfer overhead // full transfer overhead
snes->RunCycles(8); snes->RunCycles(8);
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (channel[i].hdmaActive) { if (channel[i].hdma_active) {
// terminate any dma // terminate any dma
channel[i].dmaActive = false; channel[i].dma_active = false;
// load address, repCount, and indirect address if needed // load address, repCount, and indirect address if needed
snes->RunCycles(8); snes->RunCycles(8);
channel[i].tableAdr = channel[i].aAdr; channel[i].table_addr = channel[i].a_addr;
channel[i].repCount = channel[i].rep_count =
snes->Read((channel[i].aBank << 16) | channel[i].tableAdr++); snes->Read((channel[i].a_bank << 16) | channel[i].table_addr++);
if (channel[i].repCount == 0) channel[i].terminated = true; if (channel[i].rep_count == 0) channel[i].terminated = true;
if (channel[i].indirect) { if (channel[i].indirect) {
snes->RunCycles(8); snes->RunCycles(8);
channel[i].size = channel[i].size =
snes->Read((channel[i].aBank << 16) | channel[i].tableAdr++); snes->Read((channel[i].a_bank << 16) | channel[i].table_addr++);
snes->RunCycles(8); snes->RunCycles(8);
channel[i].size |= channel[i].size |=
snes->Read((channel[i].aBank << 16) | channel[i].tableAdr++) << 8; snes->Read((channel[i].a_bank << 16) | channel[i].table_addr++) << 8;
} }
channel[i].doTransfer = true; channel[i].do_transfer = true;
} }
} }
if (do_sync) snes->SyncCycles(false, cpu_cycles); if (do_sync) snes->SyncCycles(false, cpu_cycles);
@@ -264,7 +264,7 @@ void DoHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cycles) {
bool hdmaActive = false; bool hdmaActive = false;
int lastActive = 0; int lastActive = 0;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (channel[i].hdmaActive) { if (channel[i].hdma_active) {
hdmaActive = true; hdmaActive = true;
if (!channel[i].terminated) lastActive = i; if (!channel[i].terminated) lastActive = i;
} }
@@ -280,20 +280,20 @@ void DoHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cycles) {
// do all copies // do all copies
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
// terminate any dma // terminate any dma
if (channel[i].hdmaActive) channel[i].dmaActive = false; if (channel[i].hdma_active) channel[i].dma_active = false;
if (channel[i].hdmaActive && !channel[i].terminated) { if (channel[i].hdma_active && !channel[i].terminated) {
// do the hdma // do the hdma
if (channel[i].doTransfer) { if (channel[i].do_transfer) {
for (int j = 0; j < transferLength[channel[i].mode]; j++) { for (int j = 0; j < transferLength[channel[i].mode]; j++) {
snes->RunCycles(8); snes->RunCycles(8);
if (channel[i].indirect) { if (channel[i].indirect) {
TransferByte(snes, memory, channel[i].size++, channel[i].indBank, TransferByte(snes, memory, channel[i].size++, channel[i].ind_bank,
channel[i].bAdr + bAdrOffsets[channel[i].mode][j], channel[i].b_addr + bAdrOffsets[channel[i].mode][j],
channel[i].fromB); channel[i].from_b);
} else { } else {
TransferByte(snes, memory, channel[i].tableAdr++, channel[i].aBank, TransferByte(snes, memory, channel[i].table_addr++, channel[i].a_bank,
channel[i].bAdr + bAdrOffsets[channel[i].mode][j], channel[i].b_addr + bAdrOffsets[channel[i].mode][j],
channel[i].fromB); channel[i].from_b);
} }
} }
} }
@@ -301,31 +301,31 @@ void DoHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cycles) {
} }
// do all updates // do all updates
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (channel[i].hdmaActive && !channel[i].terminated) { if (channel[i].hdma_active && !channel[i].terminated) {
channel[i].repCount--; channel[i].rep_count--;
channel[i].doTransfer = channel[i].repCount & 0x80; channel[i].do_transfer = channel[i].rep_count & 0x80;
snes->RunCycles(8); snes->RunCycles(8);
uint8_t newRepCount = uint8_t newRepCount =
snes->Read((channel[i].aBank << 16) | channel[i].tableAdr); snes->Read((channel[i].a_bank << 16) | channel[i].table_addr);
if ((channel[i].repCount & 0x7f) == 0) { if ((channel[i].rep_count & 0x7f) == 0) {
channel[i].repCount = newRepCount; channel[i].rep_count = newRepCount;
channel[i].tableAdr++; channel[i].table_addr++;
if (channel[i].indirect) { if (channel[i].indirect) {
if (channel[i].repCount == 0 && i == lastActive) { if (channel[i].rep_count == 0 && i == lastActive) {
// if this is the last active channel, only fetch high, and use 0 // if this is the last active channel, only fetch high, and use 0
// for low // for low
channel[i].size = 0; channel[i].size = 0;
} else { } else {
snes->RunCycles(8); snes->RunCycles(8);
channel[i].size = channel[i].size =
snes->Read((channel[i].aBank << 16) | channel[i].tableAdr++); snes->Read((channel[i].a_bank << 16) | channel[i].table_addr++);
} }
snes->RunCycles(8); snes->RunCycles(8);
channel[i].size |= channel[i].size |=
snes->Read((channel[i].aBank << 16) | channel[i].tableAdr++) << 8; snes->Read((channel[i].a_bank << 16) | channel[i].table_addr++) << 8;
} }
if (channel[i].repCount == 0) channel[i].terminated = true; if (channel[i].rep_count == 0) channel[i].terminated = true;
channel[i].doTransfer = true; channel[i].do_transfer = true;
} }
} }
} }
@@ -359,9 +359,9 @@ void StartDma(MemoryImpl* memory, uint8_t val, bool hdma) {
auto channel = memory->dma_channels(); auto channel = memory->dma_channels();
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (hdma) { if (hdma) {
channel[i].hdmaActive = val & (1 << i); channel[i].hdma_active = val & (1 << i);
} else { } else {
channel[i].dmaActive = val & (1 << i); channel[i].dma_active = val & (1 << i);
} }
} }
if (!hdma) { if (!hdma) {

View File

@@ -12,6 +12,27 @@ namespace emu {
namespace memory { namespace memory {
namespace dma { namespace dma {
typedef struct DmaChannel {
uint8_t b_addr;
uint16_t a_addr;
uint8_t a_bank;
uint16_t size; // also indirect hdma adr
uint8_t ind_bank; // hdma
uint16_t table_addr; // hdma
uint8_t rep_count; // hdma
uint8_t unusedByte;
bool dma_active;
bool hdma_active;
uint8_t mode;
bool fixed;
bool decrement;
bool indirect; // hdma
bool from_b;
bool unusedBit;
bool do_transfer; // hdma
bool terminated; // hdma
} DmaChannel;
void Reset(MemoryImpl* memory); void Reset(MemoryImpl* memory);
void HandleDma(SNES* snes, MemoryImpl* memory, int cpu_cycles); void HandleDma(SNES* snes, MemoryImpl* memory, int cpu_cycles);

View File

@@ -1,37 +0,0 @@
#ifndef YAZE_APP_EMU_MEMORY_DMA_CHANNEL_H
#define YAZE_APP_EMU_MEMORY_DMA_CHANNEL_H
#include <cstdint>
namespace yaze {
namespace app {
namespace emu {
namespace memory {
typedef struct DmaChannel {
uint8_t bAdr;
uint16_t aAdr;
uint8_t aBank;
uint16_t size; // also indirect hdma adr
uint8_t indBank; // hdma
uint16_t tableAdr; // hdma
uint8_t repCount; // hdma
uint8_t unusedByte;
bool dmaActive;
bool hdmaActive;
uint8_t mode;
bool fixed;
bool decrement;
bool indirect; // hdma
bool fromB;
bool unusedBit;
bool doTransfer; // hdma
bool terminated; // hdma
} DmaChannel;
} // namespace memory
} // namespace emu
} // namespace app
} // namespace yaze
#endif // YAZE_APP_EMU_MEMORY_DMA_CHANNEL_H