DS Slot-1: Improve savedata setup via IPC sniffing

This commit is contained in:
Vicki Pfau 2017-04-12 00:55:31 -07:00
parent 9a35691a03
commit 5bb811a16e
4 changed files with 72 additions and 23 deletions

View File

@ -2,6 +2,7 @@ medusa alpha 2: (Future)
Features:
- DS Audio: Add PSG audio
- DS Video: Add display capture blending
- DS Slot-1: Improve savedata setup via IPC sniffing
Bugfixes:
- DS Video: Fix VRAM mirroring in the renderer (fixes mgba.io/i/561)
- DS Video: Fix extended modes 1.x screen base range (fixes mgba.io/i/568)

View File

@ -55,7 +55,7 @@ struct DSSlot1 {
uint8_t statusReg;
int spiAddressingRemaining;
uint32_t spiAddress;
int32_t spiAddressingPc;
int spiAddressingBits;
uint8_t* spiData;
struct VFile* spiVf;
@ -70,6 +70,7 @@ void DSSlot1Reset(struct DS* ds);
DSSlot1AUXSPICNT DSSlot1Configure(struct DS* ds, DSSlot1AUXSPICNT config);
DSSlot1ROMCNT DSSlot1Control(struct DS* ds, DSSlot1ROMCNT control);
void DSSlot1WriteSPI(struct DSCommon* dscore, uint8_t datum);
void DSSlot1ConfigureSPI(struct DS* ds, uint32_t paramPtr);
struct GBADMA;
void DSSlot1ScheduleDMA(struct DSCommon* dscore, int number, struct GBADMA* info);

View File

@ -10,6 +10,16 @@
mLOG_DEFINE_CATEGORY(DS_IPC, "DS IPC", "ds.ipc");
static void _parseIPC(struct DS* ds, uint32_t value) {
switch (value & 0x1F) {
case 0x0B: // Savedata
if (value & ~0x3F && ds->memory.slot1.savedataType == DS_SAVEDATA_AUTODETECT) {
DSSlot1ConfigureSPI(ds, value >> 6);
}
break;
}
}
void DSIPCWriteSYNC(struct ARMCore* remoteCpu, uint16_t* remoteIo, int16_t value) {
remoteIo[DS_REG_IPCSYNC >> 1] &= 0xFFF0;
remoteIo[DS_REG_IPCSYNC >> 1] |= (value >> 8) & 0x0F;
@ -41,6 +51,9 @@ void DSIPCWriteFIFO(struct DSCommon* dscore, int32_t value) {
return;
}
mLOG(DS_IPC, DEBUG, "Written from ARM%c: %08X", (dscore == &dscore->p->ds7) ? '7' : '9', value);
if (!dscore->p->isHomebrew && dscore == &dscore->p->ds9) {
_parseIPC(dscore->p, value);
}
CircleBufferWrite32(&dscore->ipc->fifo, value);
size_t fullness = CircleBufferSize(&dscore->ipc->fifo);
if (fullness == 4) {

View File

@ -37,6 +37,7 @@ void DSSlot1Reset(struct DS* ds) {
ds->memory.slot1.spiCommand = 0;
ds->memory.slot1.spiHoldEnabled = 0;
ds->memory.slot1.dmaSource = -1;
ds->memory.slot1.spiAddressingBits = 16;
}
static void _scheduleTransfer(struct DS* ds, struct mTiming* timing, uint32_t cyclesLate) {
@ -223,20 +224,8 @@ static uint8_t _slot1SPIAutodetect(struct DSCommon* dscore, uint8_t datum) {
dscore->p->memory.slot1.spiAddress <<= 8;
dscore->p->memory.slot1.spiAddress |= datum;
dscore->p->memory.slot1.spiAddressingRemaining -= 8;
if (dscore->p->memory.slot1.spiAddressingPc >= 0) {
dscore->p->memory.slot1.spiAddressingPc = dscore->cpu->gprs[ARM_PC];
}
return 0xFF;
} else if (dscore->cpu->gprs[ARM_PC] == dscore->p->memory.slot1.spiAddressingPc) {
dscore->p->memory.slot1.spiAddress <<= 8;
dscore->p->memory.slot1.spiAddress |= datum;
dscore->p->memory.slot1.savedataType = DS_SAVEDATA_FLASH;
return 0xFF;
} else {
if (dscore->p->memory.slot1.spiAddress) {
// Cease autodetection
dscore->p->memory.slot1.spiAddressingPc = -1;
}
} else if (dscore->p->isHomebrew) {
if (!_slot1GuaranteeSize(&dscore->p->memory.slot1)) {
return 0xFF;
}
@ -253,6 +242,29 @@ static uint8_t _slot1SPIAutodetect(struct DSCommon* dscore, uint8_t datum) {
return 0xFF;
}
static uint8_t _slot1SPIEEPROM(struct DSCommon* dscore, uint8_t datum) {
DSSlot1AUXSPICNT control = dscore->memory.io[DS_REG_AUXSPICNT >> 1];
if (dscore->p->memory.slot1.spiAddressingRemaining) {
dscore->p->memory.slot1.spiAddress <<= 8;
dscore->p->memory.slot1.spiAddress |= datum;
dscore->p->memory.slot1.spiAddressingRemaining -= 8;
return 0xFF;
}
switch (dscore->p->memory.slot1.spiCommand) {
case 0x03: // RDLO
case 0x0B: // RDHI
return dscore->p->memory.slot1.spiData[dscore->p->memory.slot1.spiAddress++];
case 0x02: // WRLO
case 0x0A: // WRHI
dscore->p->memory.slot1.spiData[dscore->p->memory.slot1.spiAddress] = datum;
++dscore->p->memory.slot1.spiAddress;
break;
}
return 0xFF;
}
static uint8_t _slot1SPIFlash(struct DSCommon* dscore, uint8_t datum) {
DSSlot1AUXSPICNT control = dscore->memory.io[DS_REG_AUXSPICNT >> 1];
@ -261,7 +273,7 @@ static uint8_t _slot1SPIFlash(struct DSCommon* dscore, uint8_t datum) {
dscore->p->memory.slot1.spiAddress |= datum;
dscore->p->memory.slot1.spiAddressingRemaining -= 8;
return 0xFF;
} else {
} else if (dscore->p->isHomebrew) {
if (!_slot1GuaranteeSize(&dscore->p->memory.slot1)) {
return 0xFF;
}
@ -303,15 +315,12 @@ static void _slot1SPI(struct mTiming* timing, void* context, uint32_t cyclesLate
if (oldValue == 0x0B && dscore->p->memory.slot1.savedataType == DS_SAVEDATA_AUTODETECT) {
dscore->p->memory.slot1.savedataType = DS_SAVEDATA_EEPROM512;
}
dscore->p->memory.slot1.spiAddress = 0;
switch (dscore->p->memory.slot1.savedataType) {
case DS_SAVEDATA_FLASH:
dscore->p->memory.slot1.spiAddressingRemaining = 24;
break;
default:
dscore->p->memory.slot1.spiAddressingRemaining = 16;
break;
if ((oldValue & 0x08) && dscore->p->memory.slot1.savedataType == DS_SAVEDATA_EEPROM512) {
dscore->p->memory.slot1.spiAddress = 1;
} else {
dscore->p->memory.slot1.spiAddress = 0;
}
dscore->p->memory.slot1.spiAddressingRemaining = dscore->p->memory.slot1.spiAddressingBits;
} else {
switch (dscore->p->memory.slot1.spiCommand) {
case 0x04: // WRDI
@ -331,6 +340,10 @@ static void _slot1SPI(struct mTiming* timing, void* context, uint32_t cyclesLate
case DS_SAVEDATA_FLASH:
newValue = _slot1SPIFlash(dscore, oldValue);
break;
case DS_SAVEDATA_EEPROM:
case DS_SAVEDATA_EEPROM512:
newValue = _slot1SPIEEPROM(dscore, oldValue);
break;
default:
mLOG(DS_SLOT1, STUB, "Unimplemented SPI write: %04X:%02X", control, oldValue);
break;
@ -380,6 +393,27 @@ static bool _slot1GuaranteeSize(struct DSSlot1* slot1) {
return slot1->spiData;
}
void DSSlot1ConfigureSPI(struct DS* ds, uint32_t paramPtr) {
struct ARMCore* cpu = ds->ds7.cpu;
uint32_t saveParams = cpu->memory.load32(cpu, paramPtr + 4, NULL);
uint32_t size = 1 << ((saveParams & 0xFF00) >> 8);
if ((saveParams & 0xFF) == 2) {
ds->memory.slot1.savedataType = DS_SAVEDATA_FLASH;
} else {
ds->memory.slot1.savedataType = DS_SAVEDATA_EEPROM;
}
if (size >= 0x10000) {
ds->memory.slot1.spiAddressingBits = 24;
} else if (size <= 0x200) {
ds->memory.slot1.spiAddressingBits = 8;
ds->memory.slot1.savedataType = DS_SAVEDATA_EEPROM512;
} else {
ds->memory.slot1.spiAddressingBits = 16;
}
ds->memory.slot1.spiAddress = size;
_slot1GuaranteeSize(&ds->memory.slot1);
}
void DSSlot1ScheduleDMA(struct DSCommon* dscore, int number, struct GBADMA* info) {
UNUSED(info);
dscore->p->memory.slot1.dmaSource = number;