slot-1 savestates

This commit is contained in:
zeromus 2013-08-31 18:30:09 +00:00
parent 7555d69e9e
commit dd56e6c231
13 changed files with 178 additions and 120 deletions

View File

@ -83,120 +83,16 @@ public:
{ {
mSelectedImplementation->auxspi_reset(PROCNUM); mSelectedImplementation->auxspi_reset(PROCNUM);
} }
virtual void savestate(EMUFILE* os)
{
mSelectedImplementation->savestate(os);
}
virtual void loadstate(EMUFILE* is)
{
mSelectedImplementation->loadstate(is);
}
}; };
ISlot1Interface* construct_Slot1_Retail_Auto() { return new Slot1_Retail_Auto(); } ISlot1Interface* construct_Slot1_Retail_Auto() { return new Slot1_Retail_Auto(); }
// ///writetoGCControl:
//// --- Ninja SD commands -------------------------------------
// // NJSD init/reset
// case 0x20:
// {
// card.address = 0;
// card.transfer_count = 0;
// }
// break;
// // NJSD_sendCLK()
// case 0xE0:
// {
// card.address = 0;
// card.transfer_count = 0;
// NDS_makeInt(PROCNUM, 20);
// }
// break;
// // NJSD_sendCMDN() / NJSD_sendCMDR()
// case 0xF0:
// case 0xF1:
// switch (card.command[2])
// {
// // GO_IDLE_STATE
// case 0x40:
// card.address = 0;
// card.transfer_count = 0;
// NDS_makeInt(PROCNUM, 20);
// break;
// case 0x42: // ALL_SEND_CID
// case 0x43: // SEND_RELATIVE_ADDR
// case 0x47: // SELECT_CARD
// case 0x49: // SEND_CSD
// case 0x4D:
// case 0x77: // APP_CMD
// case 0x69: // SD_APP_OP_COND
// card.address = 0;
// card.transfer_count = 6;
// NDS_makeInt(PROCNUM, 20);
// break;
// // SET_BLOCKLEN
// case 0x50:
// card.address = 0;
// card.transfer_count = 6;
// card.blocklen = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24);
// NDS_makeInt(PROCNUM, 20);
// break;
// // READ_SINGLE_BLOCK
// case 0x51:
// card.address = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24);
// card.transfer_count = (card.blocklen + 3) >> 2;
// NDS_makeInt(PROCNUM, 20);
// break;
// }
// break;
// // --- Ninja SD commands end ---------------------------------
// //GCDATAIN:
// // --- Ninja SD commands -------------------------------------
// // NJSD_sendCMDN() / NJSD_sendCMDR()
// case 0xF0:
// case 0xF1:
// switch (card.command[2])
// {
// // ALL_SEND_CID
// case 0x42:
// if (card.transfer_count == 2) val = 0x44534A4E;
// else val = 0x00000000;
// // SEND_RELATIVE_ADDR
// case 0x43:
// case 0x47:
// case 0x49:
// case 0x50:
// val = 0x00000000;
// break;
// case 0x4D:
// if (card.transfer_count == 2) val = 0x09000000;
// else val = 0x00000000;
// break;
// // APP_CMD
// case 0x77:
// if (card.transfer_count == 2) val = 0x00000037;
// else val = 0x00000000;
// break;
// // SD_APP_OP_COND
// case 0x69:
// if (card.transfer_count == 2) val = 0x00008000;
// else val = 0x00000000;
// break;
// // READ_SINGLE_BLOCK
// case 0x51:
// val = 0x00000000;
// break;
// }
// break;
// // --- Ninja SD commands end ---------------------------------

View File

@ -78,6 +78,18 @@ public:
rom.start(operation,protocol.address); rom.start(operation,protocol.address);
} }
virtual void savestate(EMUFILE* os)
{
protocol.savestate(os);
rom.savestate(os);
}
virtual void loadstate(EMUFILE* is)
{
protocol.loadstate(is);
rom.loadstate(is);
}
private: private:
u32 slot1client_read_GCDATAIN(eSlot1Operation operation) u32 slot1client_read_GCDATAIN(eSlot1Operation operation)

View File

@ -88,6 +88,18 @@ public:
return protocol.read_GCDATAIN(PROCNUM); return protocol.read_GCDATAIN(PROCNUM);
} }
virtual void savestate(EMUFILE* os)
{
protocol.savestate(os);
rom.savestate(os);
}
virtual void loadstate(EMUFILE* is)
{
protocol.loadstate(is);
rom.loadstate(is);
}
virtual void slot1client_startOperation(eSlot1Operation operation) virtual void slot1client_startOperation(eSlot1Operation operation)
{ {
if (protocol.operation == eSlot1Operation_B7_Read) if (protocol.operation == eSlot1Operation_B7_Read)

View File

@ -155,7 +155,17 @@ public:
} }
} }
virtual void savestate(EMUFILE* os)
{
protocol.savestate(os);
rom.savestate(os);
}
virtual void loadstate(EMUFILE* is)
{
protocol.loadstate(is);
rom.loadstate(is);
}
}; };

View File

@ -223,3 +223,30 @@ u32 Slot1Comp_Protocol::read_GCDATAIN(u8 PROCNUM)
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
void Slot1Comp_Protocol::savestate(EMUFILE* os)
{
s32 version = 0;
os->write32le(version);
os->write32le((s32)mode);
os->write32le((s32)operation);
os->fwrite(command.bytes,8);
os->write32le(address);
os->write32le(length);
os->write32le(delay);
os->write32le(chipId);
os->write32le(gameCode);
}
void Slot1Comp_Protocol::loadstate(EMUFILE* is)
{
s32 version = is->read32le();
mode = (eCardMode)is->read32le();
operation = (eSlot1Operation)is->read32le();
is->fread(command.bytes,8);
address = is->read32le();
length = is->read32le();
delay = is->read32le();
chipId = is->read32le();
gameCode = is->read32le();
}

View File

@ -66,6 +66,9 @@ class Slot1Comp_Protocol
{ {
public: public:
void savestate(EMUFILE* os);
void loadstate(EMUFILE* is);
//set some kind of protocol/hardware reset state //set some kind of protocol/hardware reset state
void reset(ISlot1Comp_Protocol_Client* client); void reset(ISlot1Comp_Protocol_Client* client);
@ -82,6 +85,8 @@ public:
//operations not related to obscurities of the protocol or otherwise unknown are passed through to the client here //operations not related to obscurities of the protocol or otherwise unknown are passed through to the client here
ISlot1Comp_Protocol_Client* client; ISlot1Comp_Protocol_Client* client;
//--state--
//the major operational mode. the protocol shifts modes and interprets commands into operations differently depending on the mode //the major operational mode. the protocol shifts modes and interprets commands into operations differently depending on the mode
eCardMode mode; eCardMode mode;

View File

@ -103,3 +103,19 @@ u32 Slot1Comp_Rom::incAddress()
address = (address&~0xFFF) + ((address+4)&0xFFF); address = (address&~0xFFF) + ((address+4)&0xFFF);
return address; return address;
} }
void Slot1Comp_Rom::savestate(EMUFILE* os)
{
s32 version = 0;
os->write32le(version);
os->write32le((s32)operation);
os->write32le(address);
}
void Slot1Comp_Rom::loadstate(EMUFILE* is)
{
s32 version = is->read32le();
operation = (eSlot1Operation)is->read32le();
address = is->read32le();
}

View File

@ -19,7 +19,7 @@
//this is largely done by accessing the rom provided in the core emulator //this is largely done by accessing the rom provided in the core emulator
#include "slot1comp_protocol.h" #include "slot1comp_protocol.h"
#include "emufile.h"
class Slot1Comp_Rom class Slot1Comp_Rom
{ {
@ -28,6 +28,10 @@ public:
u32 read(); u32 read();
u32 getAddress(); u32 getAddress();
u32 incAddress(); u32 incAddress();
void savestate(EMUFILE* os);
void loadstate(EMUFILE* is);
private: private:
u32 address; u32 address;
eSlot1Operation operation; eSlot1Operation operation;

View File

@ -258,3 +258,25 @@ size_t EMUFILE::readdouble(double* val)
*val = u64_to_double(temp); *val = u64_to_double(temp);
return ret; return ret;
} }
void EMUFILE::writeMemoryStream(EMUFILE_MEMORY* ms)
{
s32 size = (s32)ms->size();
write32le(size);
if(size>0)
{
std::vector<u8>* vec = ms->get_vec();
fwrite(&vec->at(0),size);
}
}
void EMUFILE::readMemoryStream(EMUFILE_MEMORY* ms)
{
s32 size = read32le();
if(size != 0)
{
std::vector<u8> temp(size);
fread(&temp[0],size);
ms->fwrite(&temp[0],size);
}
}

View File

@ -43,6 +43,8 @@ THE SOFTWARE.
#include <unistd.h> #include <unistd.h>
#endif #endif
class EMUFILE_MEMORY;
class EMUFILE { class EMUFILE {
protected: protected:
bool failbit; bool failbit;
@ -120,6 +122,10 @@ public:
virtual void fflush() = 0; virtual void fflush() = 0;
virtual void truncate(s32 length) = 0; virtual void truncate(s32 length) = 0;
void writeMemoryStream(EMUFILE_MEMORY* ms);
void readMemoryStream(EMUFILE_MEMORY* ms);
}; };
//todo - handle read-only specially? //todo - handle read-only specially?
@ -182,10 +188,10 @@ public:
va_start(argptr, format); va_start(argptr, format);
vsprintf(tempbuf,format,argptr); vsprintf(tempbuf,format,argptr);
fwrite(tempbuf,amt); fwrite(tempbuf,amt);
delete[] tempbuf; delete[] tempbuf;
va_end(argptr); va_end(argptr);
return amt; return amt;
}; };

View File

@ -43,6 +43,7 @@
#include "movie.h" #include "movie.h"
#include "mic.h" #include "mic.h"
#include "MMU_timing.h" #include "MMU_timing.h"
#include "slot1.h"
#include "path.h" #include "path.h"
@ -364,6 +365,39 @@ SFORMAT reserveChunks[] = {
{ 0 } { 0 }
}; };
static bool s_slot1_loadstate(EMUFILE* is, int size)
{
u32 version = is->read32le();
//version 0:
if(version >= 0)
{
int slotType = is->read32le();
slot1_Change((NDS_SLOT1_TYPE)slotType);
EMUFILE_MEMORY temp;
is->readMemoryStream(&temp);
temp.fseek(0,SEEK_SET);
slot1_Loadstate(&temp);
}
return true;
}
static void s_slot1_savestate(EMUFILE* os)
{
u32 version = 0;
os->write32le(version);
//version 0:
int slotType = (int)slot1_GetCurrentType();
os->write32le(slotType);
EMUFILE_MEMORY temp;
slot1_Savestate(&temp);
os->writeMemoryStream(&temp);
}
static void mmu_savestate(EMUFILE* os) static void mmu_savestate(EMUFILE* os)
{ {
u32 version = 8; u32 version = 8;
@ -952,8 +986,8 @@ static void writechunks(EMUFILE* os) {
savestate_WriteChunk(os,110,SF_WIFI); savestate_WriteChunk(os,110,SF_WIFI);
savestate_WriteChunk(os,120,SF_RTC); savestate_WriteChunk(os,120,SF_RTC);
savestate_WriteChunk(os,130,SF_NDS_HEADER); savestate_WriteChunk(os,130,SF_NDS_HEADER);
savestate_WriteChunk(os,140,s_slot1_savestate);
// reserved for future versions // reserved for future versions
savestate_WriteChunk(os,140,reserveChunks);
savestate_WriteChunk(os,150,reserveChunks); savestate_WriteChunk(os,150,reserveChunks);
savestate_WriteChunk(os,160,reserveChunks); savestate_WriteChunk(os,160,reserveChunks);
savestate_WriteChunk(os,170,reserveChunks); savestate_WriteChunk(os,170,reserveChunks);
@ -1003,8 +1037,8 @@ static bool ReadStateChunks(EMUFILE* is, s32 totalsize)
case 110: if(!ReadStateChunk(is,SF_WIFI,size)) ret=false; break; case 110: if(!ReadStateChunk(is,SF_WIFI,size)) ret=false; break;
case 120: if(!ReadStateChunk(is,SF_RTC,size)) ret=false; break; case 120: if(!ReadStateChunk(is,SF_RTC,size)) ret=false; break;
case 130: if(!ReadStateChunk(is,SF_HEADER,size)) ret=false; else haveInfo=true; break; case 130: if(!ReadStateChunk(is,SF_HEADER,size)) ret=false; else haveInfo=true; break;
case 140: if(!s_slot1_loadstate(is, size)) ret=false; break;
// reserved for future versions // reserved for future versions
case 140:
case 150: case 150:
case 160: case 160:
case 170: case 170:

View File

@ -166,6 +166,14 @@ NDS_SLOT1_TYPE slot1_GetCurrentType()
return slot1_device_type; return slot1_device_type;
} }
void slot1_Savestate(EMUFILE* os)
{
slot1_device->savestate(os);
}
void slot1_Loadstate(EMUFILE* is)
{
slot1_device->loadstate(is);
}
//// --- Ninja SD commands notes ------------------------------------- //// --- Ninja SD commands notes -------------------------------------
// ///writetoGCControl: // ///writetoGCControl:

View File

@ -80,6 +80,10 @@ public:
//called when the auxspi burst is ended (SPI chipselect in is going low) //called when the auxspi burst is ended (SPI chipselect in is going low)
virtual void auxspi_reset(int PROCNUM) {} virtual void auxspi_reset(int PROCNUM) {}
virtual void savestate(EMUFILE* os) {}
virtual void loadstate(EMUFILE* is) {}
}; };
typedef ISlot1Interface* TISlot1InterfaceConstructor(); typedef ISlot1Interface* TISlot1InterfaceConstructor();
@ -102,6 +106,8 @@ void slot1_Init();
bool slot1_Connect(); bool slot1_Connect();
void slot1_Disconnect(); void slot1_Disconnect();
void slot1_Shutdown(); void slot1_Shutdown();
void slot1_Savestate(EMUFILE* os);
void slot1_Loadstate(EMUFILE* is);
//just disconnects and reconnects the device. ideally, the disconnection and connection would be called with sensible timing //just disconnects and reconnects the device. ideally, the disconnection and connection would be called with sensible timing
void slot1_Reset(); void slot1_Reset();