diff --git a/desmume/src/addons/slot1_retail_auto.cpp b/desmume/src/addons/slot1_retail_auto.cpp index 2120543fd..ecb99a15f 100644 --- a/desmume/src/addons/slot1_retail_auto.cpp +++ b/desmume/src/addons/slot1_retail_auto.cpp @@ -83,120 +83,16 @@ public: { 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(); } - - // ///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 --------------------------------- - - diff --git a/desmume/src/addons/slot1_retail_mcrom.cpp b/desmume/src/addons/slot1_retail_mcrom.cpp index 7f1119af6..fc3a69170 100644 --- a/desmume/src/addons/slot1_retail_mcrom.cpp +++ b/desmume/src/addons/slot1_retail_mcrom.cpp @@ -78,6 +78,18 @@ public: 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: u32 slot1client_read_GCDATAIN(eSlot1Operation operation) diff --git a/desmume/src/addons/slot1_retail_mcrom_debug.cpp b/desmume/src/addons/slot1_retail_mcrom_debug.cpp index c95c96c38..ea231a6ff 100644 --- a/desmume/src/addons/slot1_retail_mcrom_debug.cpp +++ b/desmume/src/addons/slot1_retail_mcrom_debug.cpp @@ -88,6 +88,18 @@ public: 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) { if (protocol.operation == eSlot1Operation_B7_Read) diff --git a/desmume/src/addons/slot1_retail_nand.cpp b/desmume/src/addons/slot1_retail_nand.cpp index 8399c337b..c1c37d330 100644 --- a/desmume/src/addons/slot1_retail_nand.cpp +++ b/desmume/src/addons/slot1_retail_nand.cpp @@ -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); + } }; diff --git a/desmume/src/addons/slot1comp_protocol.cpp b/desmume/src/addons/slot1comp_protocol.cpp index 02d91882b..8dfa82040 100644 --- a/desmume/src/addons/slot1comp_protocol.cpp +++ b/desmume/src/addons/slot1comp_protocol.cpp @@ -222,4 +222,31 @@ u32 Slot1Comp_Protocol::read_GCDATAIN(u8 PROCNUM) } 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(); } \ No newline at end of file diff --git a/desmume/src/addons/slot1comp_protocol.h b/desmume/src/addons/slot1comp_protocol.h index 2af4105ad..5dff4834d 100644 --- a/desmume/src/addons/slot1comp_protocol.h +++ b/desmume/src/addons/slot1comp_protocol.h @@ -65,6 +65,9 @@ public: class Slot1Comp_Protocol { public: + + void savestate(EMUFILE* os); + void loadstate(EMUFILE* is); //set some kind of protocol/hardware reset state 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 ISlot1Comp_Protocol_Client* client; + //--state-- + //the major operational mode. the protocol shifts modes and interprets commands into operations differently depending on the mode eCardMode mode; diff --git a/desmume/src/addons/slot1comp_rom.cpp b/desmume/src/addons/slot1comp_rom.cpp index 6d264fe23..57b51206c 100644 --- a/desmume/src/addons/slot1comp_rom.cpp +++ b/desmume/src/addons/slot1comp_rom.cpp @@ -103,3 +103,19 @@ u32 Slot1Comp_Rom::incAddress() address = (address&~0xFFF) + ((address+4)&0xFFF); 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(); +} \ No newline at end of file diff --git a/desmume/src/addons/slot1comp_rom.h b/desmume/src/addons/slot1comp_rom.h index bbb10acc4..ac40cc889 100644 --- a/desmume/src/addons/slot1comp_rom.h +++ b/desmume/src/addons/slot1comp_rom.h @@ -19,7 +19,7 @@ //this is largely done by accessing the rom provided in the core emulator #include "slot1comp_protocol.h" - +#include "emufile.h" class Slot1Comp_Rom { @@ -28,6 +28,10 @@ public: u32 read(); u32 getAddress(); u32 incAddress(); + + void savestate(EMUFILE* os); + void loadstate(EMUFILE* is); + private: u32 address; eSlot1Operation operation; diff --git a/desmume/src/emufile.cpp b/desmume/src/emufile.cpp index f4e4a9a28..ed21f6a77 100644 --- a/desmume/src/emufile.cpp +++ b/desmume/src/emufile.cpp @@ -258,3 +258,25 @@ size_t EMUFILE::readdouble(double* val) *val = u64_to_double(temp); return ret; } + +void EMUFILE::writeMemoryStream(EMUFILE_MEMORY* ms) +{ + s32 size = (s32)ms->size(); + write32le(size); + if(size>0) + { + std::vector* vec = ms->get_vec(); + fwrite(&vec->at(0),size); + } +} + +void EMUFILE::readMemoryStream(EMUFILE_MEMORY* ms) +{ + s32 size = read32le(); + if(size != 0) + { + std::vector temp(size); + fread(&temp[0],size); + ms->fwrite(&temp[0],size); + } +} \ No newline at end of file diff --git a/desmume/src/emufile.h b/desmume/src/emufile.h index 4a0af94ec..4e60ebb8a 100644 --- a/desmume/src/emufile.h +++ b/desmume/src/emufile.h @@ -43,6 +43,8 @@ THE SOFTWARE. #include #endif +class EMUFILE_MEMORY; + class EMUFILE { protected: bool failbit; @@ -120,6 +122,10 @@ public: virtual void fflush() = 0; virtual void truncate(s32 length) = 0; + + void writeMemoryStream(EMUFILE_MEMORY* ms); + void readMemoryStream(EMUFILE_MEMORY* ms); + }; //todo - handle read-only specially? @@ -182,10 +188,10 @@ public: va_start(argptr, format); vsprintf(tempbuf,format,argptr); - fwrite(tempbuf,amt); + fwrite(tempbuf,amt); delete[] tempbuf; - - va_end(argptr); + + va_end(argptr); return amt; }; diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index 31358d262..a1816b7ef 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -43,6 +43,7 @@ #include "movie.h" #include "mic.h" #include "MMU_timing.h" +#include "slot1.h" #include "path.h" @@ -364,6 +365,39 @@ SFORMAT reserveChunks[] = { { 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) { u32 version = 8; @@ -952,8 +986,8 @@ static void writechunks(EMUFILE* os) { savestate_WriteChunk(os,110,SF_WIFI); savestate_WriteChunk(os,120,SF_RTC); savestate_WriteChunk(os,130,SF_NDS_HEADER); + savestate_WriteChunk(os,140,s_slot1_savestate); // reserved for future versions - savestate_WriteChunk(os,140,reserveChunks); savestate_WriteChunk(os,150,reserveChunks); savestate_WriteChunk(os,160,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 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 140: if(!s_slot1_loadstate(is, size)) ret=false; break; // reserved for future versions - case 140: case 150: case 160: case 170: diff --git a/desmume/src/slot1.cpp b/desmume/src/slot1.cpp index b80962765..527662ff1 100644 --- a/desmume/src/slot1.cpp +++ b/desmume/src/slot1.cpp @@ -166,6 +166,14 @@ NDS_SLOT1_TYPE slot1_GetCurrentType() 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 ------------------------------------- // ///writetoGCControl: diff --git a/desmume/src/slot1.h b/desmume/src/slot1.h index 5864f455c..0119b6965 100644 --- a/desmume/src/slot1.h +++ b/desmume/src/slot1.h @@ -80,6 +80,10 @@ public: //called when the auxspi burst is ended (SPI chipselect in is going low) virtual void auxspi_reset(int PROCNUM) {} + + virtual void savestate(EMUFILE* os) {} + + virtual void loadstate(EMUFILE* is) {} }; typedef ISlot1Interface* TISlot1InterfaceConstructor(); @@ -102,6 +106,8 @@ void slot1_Init(); bool slot1_Connect(); void slot1_Disconnect(); 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 void slot1_Reset();