DS Slot-1: A little work on savegames

This commit is contained in:
Vicki Pfau 2017-02-22 22:34:06 -08:00
parent a557fb6ca6
commit a60f3592d1
5 changed files with 68 additions and 6 deletions

View File

@ -155,6 +155,7 @@ void DSAttachDebugger(struct DS* ds, struct mDebugger* debugger);
void DSDetachDebugger(struct DS* ds); void DSDetachDebugger(struct DS* ds);
bool DSLoadROM(struct DS* ds, struct VFile* vf); bool DSLoadROM(struct DS* ds, struct VFile* vf);
bool DSLoadSave(struct DS* ds, struct VFile* vf);
void DSUnloadROM(struct DS* ds); void DSUnloadROM(struct DS* ds);
void DSApplyPatch(struct DS* ds, struct Patch* patch); void DSApplyPatch(struct DS* ds, struct Patch* patch);

View File

@ -36,6 +36,7 @@ enum DSSavedataType {
DS_SAVEDATA_FLASH = 3 DS_SAVEDATA_FLASH = 3
}; };
struct VFile;
struct DSSlot1 { struct DSSlot1 {
uint8_t command[8]; uint8_t command[8];
uint32_t address; uint32_t address;
@ -48,10 +49,17 @@ struct DSSlot1 {
bool spiHoldEnabled; bool spiHoldEnabled;
uint8_t spiCommand; uint8_t spiCommand;
uint8_t statusReg; uint8_t statusReg;
int spiAddressingRemaining;
uint32_t spiAddress;
uint8_t* spiData;
struct VFile* spiVf;
struct VFile* spiRealVf;
}; };
struct DS; struct DS;
struct DSCommon; struct DSCommon;
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);

View File

@ -163,7 +163,7 @@ static bool _DSCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) {
} }
static bool _DSCoreLoadSave(struct mCore* core, struct VFile* vf) { static bool _DSCoreLoadSave(struct mCore* core, struct VFile* vf) {
return false; return DSLoadSave(core->board, vf);
} }
static bool _DSCoreLoadPatch(struct mCore* core, struct VFile* vf) { static bool _DSCoreLoadPatch(struct mCore* core, struct VFile* vf) {

View File

@ -201,6 +201,7 @@ static void DSInit(void* cpu, struct mCPUComponent* component) {
ds->rumble = NULL; ds->rumble = NULL;
ds->romVf = NULL; ds->romVf = NULL;
DSSlot1SPIInit(ds, NULL);
ds->keyCallback = NULL; ds->keyCallback = NULL;
@ -444,6 +445,11 @@ bool DSLoadROM(struct DS* ds, struct VFile* vf) {
return true; return true;
} }
bool DSLoadSave(struct DS* ds, struct VFile* sav) {
DSSlot1SPIInit(ds, sav);
return true;
}
bool DSIsROM(struct VFile* vf) { bool DSIsROM(struct VFile* vf) {
if (vf->seek(vf, DS_ROM_MAGIC_OFFSET, SEEK_SET) < 0) { if (vf->seek(vf, DS_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {
return false; return false;

View File

@ -7,17 +7,26 @@
#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-util/math.h>
#include <mgba-util/vfs.h> #include <mgba-util/vfs.h>
mLOG_DEFINE_CATEGORY(DS_SLOT1, "DS Slot-1"); mLOG_DEFINE_CATEGORY(DS_SLOT1, "DS Slot-1");
static void _slot1SPI(struct mTiming*, void* context, uint32_t cyclesLate); static void _slot1SPI(struct mTiming*, void* context, uint32_t cyclesLate);
static bool _slot1GuaranteeSize(struct DSSlot1*);
void DSSlot1Reset(struct DS* ds) { void DSSlot1SPIInit(struct DS* ds, struct VFile* vf) {
ds->memory.slot1.spiEvent.name = "DS Slot-1 SPI"; ds->memory.slot1.spiEvent.name = "DS Slot-1 SPI";
ds->memory.slot1.spiEvent.priority = 0x70; ds->memory.slot1.spiEvent.priority = 0x70;
ds->memory.slot1.spiEvent.context = NULL; ds->memory.slot1.spiEvent.context = NULL;
ds->memory.slot1.spiEvent.callback = _slot1SPI; ds->memory.slot1.spiEvent.callback = _slot1SPI;
ds->memory.slot1.savedataType = DS_SAVEDATA_AUTODETECT;
ds->memory.slot1.spiVf = vf;
ds->memory.slot1.spiRealVf = vf;
ds->memory.slot1.spiData = NULL;
}
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;
@ -132,6 +141,26 @@ void DSSlot1WriteSPI(struct DSCommon* dscore, uint8_t datum) {
static uint8_t _slot1SPIAutodetect(struct DSCommon* dscore, uint8_t datum) { static uint8_t _slot1SPIAutodetect(struct DSCommon* dscore, uint8_t datum) {
DSSlot1AUXSPICNT control = dscore->memory.io[DS_REG_AUXSPICNT >> 1]; DSSlot1AUXSPICNT control = dscore->memory.io[DS_REG_AUXSPICNT >> 1];
mLOG(DS_SLOT1, STUB, "Unimplemented SPI write: %04X:%02X:%02X", control, dscore->p->memory.slot1.spiCommand, datum); mLOG(DS_SLOT1, STUB, "Unimplemented SPI write: %04X:%02X:%02X", control, dscore->p->memory.slot1.spiCommand, datum);
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;
} else {
if (!_slot1GuaranteeSize(&dscore->p->memory.slot1)) {
return 0xFF;
}
}
switch (dscore->p->memory.slot1.spiCommand) {
case 0x03: // RD
return dscore->p->memory.slot1.spiData[dscore->p->memory.slot1.spiAddress++];
case 0x02: // WR
dscore->p->memory.slot1.spiData[dscore->p->memory.slot1.spiAddress] = datum;
++dscore->p->memory.slot1.spiAddress;
break;
}
return 0xFF; return 0xFF;
} }
@ -141,7 +170,7 @@ static void _slot1SPI(struct mTiming* timing, void* context, uint32_t cyclesLate
struct DSCommon* dscore = context; struct DSCommon* dscore = context;
DSSlot1AUXSPICNT control = dscore->memory.io[DS_REG_AUXSPICNT >> 1]; DSSlot1AUXSPICNT control = dscore->memory.io[DS_REG_AUXSPICNT >> 1];
uint8_t oldValue = dscore->memory.io[DS_REG_AUXSPIDATA >> 1]; uint8_t oldValue = dscore->memory.io[DS_REG_AUXSPIDATA >> 1];
uint8_t newValue = 0; uint8_t newValue = 0xFF;
if (!dscore->p->memory.slot1.spiCommand) { if (!dscore->p->memory.slot1.spiCommand) {
dscore->p->memory.slot1.spiCommand = oldValue; dscore->p->memory.slot1.spiCommand = oldValue;
@ -149,6 +178,8 @@ static void _slot1SPI(struct mTiming* timing, void* context, uint32_t cyclesLate
if (oldValue == 0x0B && dscore->p->memory.slot1.savedataType == DS_SAVEDATA_AUTODETECT) { if (oldValue == 0x0B && dscore->p->memory.slot1.savedataType == DS_SAVEDATA_AUTODETECT) {
dscore->p->memory.slot1.savedataType = DS_SAVEDATA_EEPROM512; dscore->p->memory.slot1.savedataType = DS_SAVEDATA_EEPROM512;
} }
dscore->p->memory.slot1.spiAddress = 0;
dscore->p->memory.slot1.spiAddressingRemaining = 16;
} else { } else {
switch (dscore->p->memory.slot1.spiCommand) { switch (dscore->p->memory.slot1.spiCommand) {
case 0x04: // WRDI case 0x04: // WRDI
@ -177,7 +208,23 @@ static void _slot1SPI(struct mTiming* timing, void* context, uint32_t cyclesLate
dscore->ipc->memory.io[DS_REG_AUXSPIDATA >> 1] = newValue; dscore->ipc->memory.io[DS_REG_AUXSPIDATA >> 1] = newValue;
dscore->memory.io[DS_REG_AUXSPICNT >> 1] = control; dscore->memory.io[DS_REG_AUXSPICNT >> 1] = control;
dscore->ipc->memory.io[DS_REG_AUXSPICNT >> 1] = control; dscore->ipc->memory.io[DS_REG_AUXSPICNT >> 1] = control;
if (DSSlot1AUXSPICNTIsDoIRQ(control)) { }
DSRaiseIRQ(dscore->cpu, dscore->memory.io, DS_IRQ_SLOT1);
} static bool _slot1GuaranteeSize(struct DSSlot1* slot1) {
if (!slot1->spiVf) {
return false;
}
if (slot1->spiAddress >= slot1->spiVf->size(slot1->spiVf)) {
size_t size = toPow2(slot1->spiAddress + 1);
if (slot1->spiData) {
slot1->spiVf->unmap(slot1->spiVf, slot1->spiData, slot1->spiVf->size(slot1->spiVf));
slot1->spiData = NULL;
}
slot1->spiVf->truncate(slot1->spiVf, size);
// TODO: Write FFs
}
if (!slot1->spiData) {
slot1->spiData = slot1->spiVf->map(slot1->spiVf, slot1->spiVf->size(slot1->spiVf), MAP_WRITE);
}
return slot1->spiData;
} }