Refactor DMA channel structure: consolidate and update definitions, remove obsolete header
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
Reference in New Issue
Block a user