diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h index 9dd1578890..03216deaf1 100644 --- a/Source/Core/Common/Src/ChunkFile.h +++ b/Source/Core/Common/Src/ChunkFile.h @@ -29,6 +29,7 @@ #include #include +#include #include #include "Common.h" @@ -127,6 +128,18 @@ public: DoArray(&x[0], vec_size); } + // Store deques. + template + void Do(std::deque &x) + { + u32 deq_size = (u32)x.size(); + Do(deq_size); + x.resize(deq_size); + u32 i; + for(i = 0; i < deq_size; i++) + DoVoid(&x[i],sizeof(T)); + } + // Store strings. void Do(std::string &x) { diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp index 0c6bff53d8..2fa2587e60 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -71,7 +71,7 @@ typedef std::map TFileNameMap; TFileNameMap g_FileNameMap; u32 g_LastDeviceID; -typedef std::queue ipc_msg_queue; +typedef std::deque ipc_msg_queue; static ipc_msg_queue request_queue; // ppc -> arm static ipc_msg_queue reply_queue; // arm -> ppc @@ -120,8 +120,8 @@ void Reset(bool _bHard) g_DeviceMap.erase(itr, g_DeviceMap.end()); g_FileNameMap.clear(); - request_queue = std::queue(); - reply_queue = std::queue(); + request_queue.clear(); + reply_queue.clear(); g_LastDeviceID = IPC_FIRST_FILEIO_ID; } @@ -205,23 +205,20 @@ void DoState(PointerWrap &p) { p.Do(g_LastDeviceID); - // Currently only USB device needs to be saved - IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(GetDeviceIDByName(std::string("/dev/usb/oh1/57e/305"))); - if (pDevice) - pDevice->DoState(p); - else - PanicAlert("WII_IPC_HLE: Save/Load State failed, Device /dev/usb/oh1/57e/305 doesn't exist!"); - - TFileNameMap::const_iterator itr; if (p.GetMode() == PointerWrap::MODE_READ) { + TFileNameMap::const_iterator itr; // Delete file Handles itr = g_FileNameMap.begin(); while (itr != g_FileNameMap.end()) { - if (g_DeviceMap[itr->first]) - delete g_DeviceMap[itr->first]; - g_DeviceMap.erase(itr->first); + TDeviceMap::const_iterator devitr = g_DeviceMap.find(itr->first); + if (devitr != g_DeviceMap.end()) + { + if (devitr->second) + delete devitr->second; + g_DeviceMap.erase(itr->first); + } ++itr; } // Load file names @@ -239,10 +236,26 @@ void DoState(PointerWrap &p) p.Do(g_FileNameMap); } - itr = g_FileNameMap.begin(); - while (itr != g_FileNameMap.end()) + p.Do(request_queue); + p.Do(reply_queue); + + + TDeviceMap::const_iterator itr; + //first, all the real devices + //(because we need fs to be deserialized first) + itr = g_DeviceMap.begin(); + while (itr != g_DeviceMap.end()) { - g_DeviceMap[itr->first]->DoState(p); + if (itr->second->IsHardware()) + itr->second->DoState(p); + ++itr; + } + //then all the files + itr = g_DeviceMap.begin(); + while (itr != g_DeviceMap.end()) + { + if (!itr->second->IsHardware()) + itr->second->DoState(p); ++itr; } } @@ -393,13 +406,13 @@ void ExecuteCommand(u32 _Address) // Happens AS SOON AS IPC gets a new pointer! void EnqRequest(u32 _Address) { - request_queue.push(_Address); + request_queue.push_back(_Address); } // Called when IOS module has some reply void EnqReply(u32 _Address) { - reply_queue.push(_Address); + reply_queue.push_back(_Address); } // This is called every IPC_HLE_PERIOD from SystemTimers.cpp @@ -417,7 +430,7 @@ void Update() INFO_LOG(WII_IPC_HLE, "||-- Acknowledge IPC Request @ 0x%08x", request_queue.front()); ExecuteCommand(request_queue.front()); - request_queue.pop(); + request_queue.pop_front(); #if MAX_LOGLEVEL >= DEBUG_LEVEL Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG); @@ -428,7 +441,7 @@ void Update() { WII_IPCInterface::GenerateReply(reply_queue.front()); INFO_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", reply_queue.front()); - reply_queue.pop(); + reply_queue.pop_front(); } } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp index 59e53cd242..685b3bbbd2 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp @@ -87,7 +87,6 @@ CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std: , m_pFileHandle(NULL) , m_FileLength(0) , m_Mode(0) - , m_Seek(0) { Common::ReadReplacements(replacements); } @@ -104,10 +103,9 @@ bool CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress, bool _bForce) m_FileLength = 0; m_Mode = 0; - m_Seek = 0; // Close always return 0 for success - if (!_bForce) + if (_CommandAddress && !_bForce) Memory::Write_U32(0, _CommandAddress + 4); m_Active = false; return true; @@ -121,7 +119,7 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) // close the file handle if we get a reopen m_pFileHandle.Close(); - const char* const Modes[] = + static const char* const Modes[] = { "Unk Mode", "Read only", @@ -326,20 +324,24 @@ bool CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress) void CWII_IPC_HLE_Device_FileIO::DoState(PointerWrap &p) { - if (p.GetMode() == PointerWrap::MODE_WRITE) - { - m_Seek = (m_pFileHandle) ? (s32)m_pFileHandle.Tell() : 0; - } + bool have_file_handle = m_pFileHandle; + s32 seek = (have_file_handle) ? (s32)m_pFileHandle.Tell() : 0; + p.Do(have_file_handle); p.Do(m_Mode); - p.Do(m_Seek); + p.Do(seek); if (p.GetMode() == PointerWrap::MODE_READ) { - if (m_Mode) + if (have_file_handle) { Open(0, m_Mode); - m_pFileHandle.Seek(m_Seek, SEEK_SET); + _dbg_assert_msg_(WII_IPC_HLE, m_pFileHandle, "bad filehandle"); } + else + Close(0, true); } + + if (have_file_handle) + m_pFileHandle.Seek(seek, SEEK_SET); } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h index 6cbda120c5..d1f51b7dfc 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h @@ -76,7 +76,6 @@ private: File::IOFile m_pFileHandle; u32 m_FileLength; u32 m_Mode; - s32 m_Seek; std::string m_Filename; }; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp index 7e73369513..6119eef325 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp @@ -25,6 +25,7 @@ #include "FileSearch.h" #include "FileUtil.h" #include "NandPaths.h" +#include "ChunkFile.h" #include "../VolumeHandler.h" @@ -484,3 +485,96 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B return FS_RESULT_FATAL; } + +void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p) +{ + // handle /tmp + + std::string Path = File::GetUserPath(D_WIIUSER_IDX) + "tmp"; + if (p.GetMode() == PointerWrap::MODE_READ) + { + File::DeleteDirRecursively(Path); + File::CreateDir(Path.c_str()); + + //now restore from the stream + while(1) { + char type; + p.Do(type); + if (!type) + break; + std::string filename; + p.Do(filename); + std::string name = Path + DIR_SEP + filename; + switch(type) + { + case 'd': + { + File::CreateDir(name.c_str()); + break; + } + case 'f': + { + u32 size; + p.Do(size); + + File::IOFile handle(name, "wb"); + char buf[65536]; + u32 count = size; + while(count > 65536) { + p.DoArray(&buf[0], 65536); + handle.WriteArray(&buf[0], 65536); + count -= 65536; + } + p.DoArray(&buf[0], count); + handle.WriteArray(&buf[0], count); + break; + } + } + } + } + else + { + //recurse through tmp and save dirs and files + + File::FSTEntry parentEntry; + File::ScanDirectoryTree(Path, parentEntry); + std::deque todo; + todo.insert(todo.end(), parentEntry.children.begin(), + parentEntry.children.end()); + + while(!todo.empty()) + { + File::FSTEntry &entry = todo.front(); + std::string name = entry.physicalName; + name.erase(0,Path.length()+1); + char type = entry.isDirectory?'d':'f'; + p.Do(type); + p.Do(name); + if (entry.isDirectory) + { + todo.insert(todo.end(), entry.children.begin(), + entry.children.end()); + } + else + { + u32 size = entry.size; + p.Do(size); + + File::IOFile handle(entry.physicalName, "rb"); + char buf[65536]; + u32 count = size; + while(count > 65536) { + handle.ReadArray(&buf[0], 65536); + p.DoArray(&buf[0], 65536); + count -= 65536; + } + handle.ReadArray(&buf[0], count); + p.DoArray(&buf[0], count); + } + todo.pop_front(); + } + + char type = 0; + p.Do(type); + } +} diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.h index 60e9127b81..be78de7e39 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.h @@ -46,7 +46,9 @@ public: CWII_IPC_HLE_Device_fs(u32 _DeviceID, const std::string& _rDeviceName); virtual ~CWII_IPC_HLE_Device_fs(); - virtual bool Open(u32 _CommandAddress, u32 _Mode); + virtual void DoState(PointerWrap& p); + + virtual bool Open(u32 _CommandAddress, u32 _Mode); virtual bool Close(u32 _CommandAddress, bool _bForce); virtual bool IOCtl(u32 _CommandAddress); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index 4e35e9f96b..69e1781041 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -106,13 +106,26 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::~CWII_IPC_HLE_Device_usb_oh1_57e_305() void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p) { +/* + //things that do not get saved: + + std::vector m_WiiMotes; + + std::deque m_EventQueue; + */ + p.Do(m_CtrlSetup); p.Do(m_ACLSetup); p.Do(m_HCIEndpoint); p.Do(m_ACLEndpoint); p.Do(m_last_ticks); + p.DoArray(m_PacketCount,4); + p.Do(m_ScanEnable); m_acl_pool.DoState(p); + if (p.GetMode() == PointerWrap::MODE_READ) { + m_EventQueue.clear(); + } if (p.GetMode() == PointerWrap::MODE_READ && SConfig::GetInstance().m_WiimoteReconnectOnLoad) { @@ -397,7 +410,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e DEBUG_LOG(WII_IPC_WIIMOTE, "HCI endpoint not " "currently valid, queueing(%lu)...", (unsigned long)m_EventQueue.size()); - m_EventQueue.push(_event); + m_EventQueue.push_back(_event); const SQueuedEvent& event = m_EventQueue.front(); DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x " "being written from queue(%lu) to %08x...", @@ -409,14 +422,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e // Send a reply to indicate HCI buffer is filled WII_IPC_HLE_Interface::EnqReply(m_HCIEndpoint.m_address); m_HCIEndpoint.Invalidate(); - m_EventQueue.pop(); + m_EventQueue.pop_front(); } } else { DEBUG_LOG(WII_IPC_WIIMOTE, "HCI endpoint not currently valid, " "queueing(%lu)...", (unsigned long)m_EventQueue.size()); - m_EventQueue.push(_event); + m_EventQueue.push_back(_event); } } @@ -439,7 +452,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() // Send a reply to indicate HCI buffer is filled WII_IPC_HLE_Interface::EnqReply(m_HCIEndpoint.m_address); m_HCIEndpoint.Invalidate(); - m_EventQueue.pop(); + m_EventQueue.pop_front(); packet_transferred = true; } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h index 1b09e5742a..897f3a9e86 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h @@ -152,7 +152,7 @@ private: SHCICommandMessage m_CtrlSetup; CtrlBuffer m_HCIEndpoint; - std::queue m_EventQueue; + std::deque m_EventQueue; u32 m_ACLSetup; CtrlBuffer m_ACLEndpoint; diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 305c6bdb76..7f682ec4e6 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -65,7 +65,7 @@ static std::vector g_current_buffer; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const int STATE_VERSION = 4; +static const int STATE_VERSION = 5; struct StateHeader {