Add DMA to SNES

This commit is contained in:
scawful
2023-10-17 17:06:36 -04:00
parent 013a989928
commit df6327078d
3 changed files with 79 additions and 70 deletions

View File

@@ -6,6 +6,7 @@ add_executable(
app/emu/audio/spc700.cc
app/emu/audio/dsp.cc
app/emu/video/ppu.cc
app/emu/memory/dma.cc
app/emu/cpu.cc
app/emu/snes.cc
${YAZE_APP_CORE_SRC}

75
src/app/emu/memory/dma.cc Normal file
View File

@@ -0,0 +1,75 @@
#include "app/emu/memory/dma.h"
#include <iostream>
namespace yaze {
namespace app {
namespace emu {
void DMA::StartDMATransfer(uint8_t channelMask) {
for (int i = 0; i < 8; ++i) {
if ((channelMask & (1 << i)) != 0) {
Channel& ch = channels[i];
// Validate channel parameters (e.g., DMAPn, BBADn, A1Tn, DASn)
// ...
// Determine the transfer direction based on the DMAPn register
bool fromMemory = (ch.DMAPn & 0x80) != 0;
// Determine the transfer size based on the DMAPn register
bool transferTwoBytes = (ch.DMAPn & 0x40) != 0;
// Perform the DMA transfer based on the channel parameters
std::cout << "Starting DMA transfer for channel " << i << std::endl;
for (uint16_t j = 0; j < ch.DASn; ++j) {
// Read a byte or two bytes from memory based on the transfer size
// ...
// Write the data to the B-bus address (BBADn) if transferring from
// memory
// ...
// Update the A1Tn register based on the transfer direction
if (fromMemory) {
ch.A1Tn += transferTwoBytes ? 2 : 1;
} else {
ch.A1Tn -= transferTwoBytes ? 2 : 1;
}
}
// Update the channel registers after the transfer (e.g., A1Tn, DASn)
// ...
}
}
MDMAEN = channelMask; // Set the MDMAEN register to the channel mask
}
void DMA::EnableHDMATransfers(uint8_t channelMask) {
for (int i = 0; i < 8; ++i) {
if ((channelMask & (1 << i)) != 0) {
Channel& ch = channels[i];
// Validate channel parameters (e.g., DMAPn, BBADn, A1Tn, A2An, NLTRn)
// ...
// Perform the HDMA setup based on the channel parameters
std::cout << "Enabling HDMA transfer for channel " << i << std::endl;
// Read the HDMA table from memory starting at A1Tn
// ...
// Update the A2An register based on the HDMA table
// ...
// Update the NLTRn register based on the HDMA table
// ...
}
}
HDMAEN = channelMask; // Set the HDMAEN register to the channel mask
}
} // namespace emu
} // namespace app
} // namespace yaze

View File

@@ -58,70 +58,6 @@ void audio_callback(void* userdata, uint8_t* stream, int len) {
} // namespace
void DMA::StartDMATransfer(uint8_t channelMask) {
for (int i = 0; i < 8; ++i) {
if ((channelMask & (1 << i)) != 0) {
Channel& ch = channels[i];
// Validate channel parameters (e.g., DMAPn, BBADn, A1Tn, DASn)
// ...
// Determine the transfer direction based on the DMAPn register
bool fromMemory = (ch.DMAPn & 0x80) != 0;
// Determine the transfer size based on the DMAPn register
bool transferTwoBytes = (ch.DMAPn & 0x40) != 0;
// Perform the DMA transfer based on the channel parameters
std::cout << "Starting DMA transfer for channel " << i << std::endl;
for (uint16_t j = 0; j < ch.DASn; ++j) {
// Read a byte or two bytes from memory based on the transfer size
// ...
// Write the data to the B-bus address (BBADn) if transferring from
// memory
// ...
// Update the A1Tn register based on the transfer direction
if (fromMemory) {
ch.A1Tn += transferTwoBytes ? 2 : 1;
} else {
ch.A1Tn -= transferTwoBytes ? 2 : 1;
}
}
// Update the channel registers after the transfer (e.g., A1Tn, DASn)
// ...
}
}
MDMAEN = channelMask; // Set the MDMAEN register to the channel mask
}
void DMA::EnableHDMATransfers(uint8_t channelMask) {
for (int i = 0; i < 8; ++i) {
if ((channelMask & (1 << i)) != 0) {
Channel& ch = channels[i];
// Validate channel parameters (e.g., DMAPn, BBADn, A1Tn, A2An, NLTRn)
// ...
// Perform the HDMA setup based on the channel parameters
std::cout << "Enabling HDMA transfer for channel " << i << std::endl;
// Read the HDMA table from memory starting at A1Tn
// ...
// Update the A2An register based on the HDMA table
// ...
// Update the NLTRn register based on the HDMA table
// ...
}
}
HDMAEN = channelMask; // Set the HDMAEN register to the channel mask
}
ROMInfo SNES::ReadRomHeader(uint32_t offset) {
ROMInfo romInfo;
@@ -289,9 +225,7 @@ void SNES::Run() {
running_ = true;
const double targetFPS = 60.0; // 60 frames per second
const double frameTime = 1.0 / targetFPS;
const double frame_time = 1.0 / targetFPS;
double frame_accumulated_time = 0.0;
auto last_time = std::chrono::high_resolution_clock::now();
@@ -316,9 +250,9 @@ void SNES::Run() {
apu.UpdateClock(delta_time);
apu.Update();
if (frame_accumulated_time >= frameTime) {
if (frame_accumulated_time >= frame_time) {
// renderer.Render();
frame_accumulated_time -= frameTime;
frame_accumulated_time -= frame_time;
}
HandleInput();
@@ -376,7 +310,6 @@ void SNES::NmiIsr() {
void SNES::VBlankRoutine() {
// Execute code that needs to run during VBlank, such as transferring data to
// the PPU
// ...
}
void SNES::BootAPUWithIPL() {