mirror of https://github.com/mgba-emu/mgba.git
DS Slot-1: Implement Slot-1 DMAs
This commit is contained in:
parent
9c40ebb301
commit
cf5d6709fe
|
@ -46,6 +46,8 @@ struct DSSlot1 {
|
||||||
struct mTimingEvent transferEvent;
|
struct mTimingEvent transferEvent;
|
||||||
uint8_t readBuffer[4];
|
uint8_t readBuffer[4];
|
||||||
|
|
||||||
|
int dmaSource;
|
||||||
|
|
||||||
enum DSSavedataType savedataType;
|
enum DSSavedataType savedataType;
|
||||||
struct mTimingEvent spiEvent;
|
struct mTimingEvent spiEvent;
|
||||||
bool spiHoldEnabled;
|
bool spiHoldEnabled;
|
||||||
|
@ -64,9 +66,14 @@ struct DS;
|
||||||
struct DSCommon;
|
struct DSCommon;
|
||||||
void DSSlot1SPIInit(struct DS* ds, struct VFile* vf);
|
void DSSlot1SPIInit(struct DS* ds, struct VFile* vf);
|
||||||
void DSSlot1Reset(struct DS* ds);
|
void DSSlot1Reset(struct DS* ds);
|
||||||
|
|
||||||
DSSlot1AUXSPICNT DSSlot1Configure(struct DS* ds, DSSlot1AUXSPICNT config);
|
DSSlot1AUXSPICNT DSSlot1Configure(struct DS* ds, DSSlot1AUXSPICNT config);
|
||||||
DSSlot1ROMCNT DSSlot1Control(struct DS* ds, DSSlot1ROMCNT control);
|
DSSlot1ROMCNT DSSlot1Control(struct DS* ds, DSSlot1ROMCNT control);
|
||||||
void DSSlot1WriteSPI(struct DSCommon* dscore, uint8_t datum);
|
void DSSlot1WriteSPI(struct DSCommon* dscore, uint8_t datum);
|
||||||
|
|
||||||
|
struct GBADMA;
|
||||||
|
void DSSlot1ScheduleDMA(struct DSCommon* dscore, int number, struct GBADMA* info);
|
||||||
|
|
||||||
uint32_t DSSlot1Read(struct DS* ds);
|
uint32_t DSSlot1Read(struct DS* ds);
|
||||||
|
|
||||||
CXX_GUARD_END
|
CXX_GUARD_END
|
||||||
|
|
13
src/ds/dma.c
13
src/ds/dma.c
|
@ -81,15 +81,24 @@ void DS9DMAWriteCNT(struct DSCommon* dscore, int dma, uint32_t value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDMASchedule(struct DSCommon* dscore, int number, struct GBADMA* info) {
|
void DSDMASchedule(struct DSCommon* dscore, int number, struct GBADMA* info) {
|
||||||
switch (GBADMARegisterGetTiming(info->reg)) {
|
int which;
|
||||||
|
if (dscore == &dscore->p->ds9) {
|
||||||
|
which = GBADMARegisterGetTiming9(info->reg);
|
||||||
|
} else {
|
||||||
|
which = GBADMARegisterGetTiming(info->reg);
|
||||||
|
}
|
||||||
|
switch (which) {
|
||||||
case DS_DMA_TIMING_NOW:
|
case DS_DMA_TIMING_NOW:
|
||||||
info->when = mTimingCurrentTime(&dscore->timing) + 3; // DMAs take 3 cycles to start
|
info->when = mTimingCurrentTime(&dscore->timing) + 3; // DMAs take 3 cycles to start
|
||||||
info->nextCount = info->count;
|
info->nextCount = info->count;
|
||||||
break;
|
break;
|
||||||
case DS_DMA_TIMING_HBLANK:
|
|
||||||
case DS_DMA_TIMING_VBLANK:
|
case DS_DMA_TIMING_VBLANK:
|
||||||
// Handled implicitly
|
// Handled implicitly
|
||||||
return;
|
return;
|
||||||
|
case DS9_DMA_TIMING_SLOT1:
|
||||||
|
DSSlot1ScheduleDMA(dscore, number, info);
|
||||||
|
return;
|
||||||
|
case DS_DMA_TIMING_HBLANK: // DS7_DMA_TIMING_SLOT1
|
||||||
default:
|
default:
|
||||||
mLOG(DS_MEM, STUB, "Unimplemented DMA");
|
mLOG(DS_MEM, STUB, "Unimplemented DMA");
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <mgba/internal/arm/macros.h>
|
#include <mgba/internal/arm/macros.h>
|
||||||
#include <mgba/internal/ds/ds.h>
|
#include <mgba/internal/ds/ds.h>
|
||||||
|
#include <mgba/internal/ds/dma.h>
|
||||||
#include <mgba-util/math.h>
|
#include <mgba-util/math.h>
|
||||||
#include <mgba-util/vfs.h>
|
#include <mgba-util/vfs.h>
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ void DSSlot1Reset(struct DS* ds) {
|
||||||
ds->memory.slot1.statusReg = 0;
|
ds->memory.slot1.statusReg = 0;
|
||||||
ds->memory.slot1.spiCommand = 0;
|
ds->memory.slot1.spiCommand = 0;
|
||||||
ds->memory.slot1.spiHoldEnabled = 0;
|
ds->memory.slot1.spiHoldEnabled = 0;
|
||||||
|
ds->memory.slot1.dmaSource = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _scheduleTransfer(struct DS* ds, struct mTiming* timing, uint32_t cyclesLate) {
|
static void _scheduleTransfer(struct DS* ds, struct mTiming* timing, uint32_t cyclesLate) {
|
||||||
|
@ -46,7 +48,7 @@ static void _scheduleTransfer(struct DS* ds, struct mTiming* timing, uint32_t cy
|
||||||
cycles = 5;
|
cycles = 5;
|
||||||
}
|
}
|
||||||
if (!ds->ds7.memory.slot1Access) {
|
if (!ds->ds7.memory.slot1Access) {
|
||||||
cycles << 1;
|
cycles <<= 1;
|
||||||
}
|
}
|
||||||
cycles -= cyclesLate;
|
cycles -= cyclesLate;
|
||||||
mTimingDeschedule(timing, &ds->memory.slot1.transferEvent);
|
mTimingDeschedule(timing, &ds->memory.slot1.transferEvent);
|
||||||
|
@ -64,6 +66,30 @@ static void _transferEvent(struct mTiming* timing, void* context, uint32_t cycle
|
||||||
ds->memory.slot1.address += 4;
|
ds->memory.slot1.address += 4;
|
||||||
ds->memory.slot1.transferRemaining -= 4;
|
ds->memory.slot1.transferRemaining -= 4;
|
||||||
romcnt = DSSlot1ROMCNTFillWordReady(romcnt);
|
romcnt = DSSlot1ROMCNTFillWordReady(romcnt);
|
||||||
|
|
||||||
|
if (ds->memory.slot1.dmaSource >= 0) {
|
||||||
|
struct DSCommon* dscore;
|
||||||
|
if (ds->ds7.memory.slot1Access) {
|
||||||
|
dscore = &ds->ds7;
|
||||||
|
} else {
|
||||||
|
dscore = &ds->ds9;
|
||||||
|
}
|
||||||
|
struct GBADMA* dma = &dscore->memory.dma[ds->memory.slot1.dmaSource];
|
||||||
|
bool cond = false;
|
||||||
|
if (ds->ds7.memory.slot1Access && GBADMARegisterGetTiming(dma->reg) == DS7_DMA_TIMING_SLOT1) {
|
||||||
|
cond = true;
|
||||||
|
}
|
||||||
|
if (ds->ds9.memory.slot1Access && GBADMARegisterGetTiming9(dma->reg) == DS9_DMA_TIMING_SLOT1) {
|
||||||
|
cond = true;
|
||||||
|
}
|
||||||
|
if (cond) {
|
||||||
|
dma->when = mTimingCurrentTime(timing);
|
||||||
|
dma->nextCount = 1;
|
||||||
|
DSDMAUpdate(dscore);
|
||||||
|
} else {
|
||||||
|
ds->memory.slot1.dmaSource = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DSSlot1AUXSPICNT config = ds->memory.io7[DS_REG_AUXSPICNT >> 1];
|
DSSlot1AUXSPICNT config = ds->memory.io7[DS_REG_AUXSPICNT >> 1];
|
||||||
memset(ds->memory.slot1.readBuffer, 0, 4);
|
memset(ds->memory.slot1.readBuffer, 0, 4);
|
||||||
|
@ -331,3 +357,7 @@ static bool _slot1GuaranteeSize(struct DSSlot1* slot1) {
|
||||||
}
|
}
|
||||||
return slot1->spiData;
|
return slot1->spiData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DSSlot1ScheduleDMA(struct DSCommon* dscore, int number, struct GBADMA* info) {
|
||||||
|
dscore->p->memory.slot1.dmaSource = number;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue