Improve WII state saves by saving /tmp and IPC request/reply queues
mp3:c stores temporary files in /tmp and needs them restored to resume properly. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7564 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
5b5e8edb17
commit
3bcb406c46
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -127,6 +128,18 @@ public:
|
|||
DoArray(&x[0], vec_size);
|
||||
}
|
||||
|
||||
// Store deques.
|
||||
template<class T>
|
||||
void Do(std::deque<T> &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)
|
||||
{
|
||||
|
|
|
@ -71,7 +71,7 @@ typedef std::map<u32, std::string> TFileNameMap;
|
|||
TFileNameMap g_FileNameMap;
|
||||
u32 g_LastDeviceID;
|
||||
|
||||
typedef std::queue<u32> ipc_msg_queue;
|
||||
typedef std::deque<u32> 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<u32>();
|
||||
reply_queue = std::queue<u32>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -76,7 +76,6 @@ private:
|
|||
File::IOFile m_pFileHandle;
|
||||
u32 m_FileLength;
|
||||
u32 m_Mode;
|
||||
s32 m_Seek;
|
||||
|
||||
std::string m_Filename;
|
||||
};
|
||||
|
|
|
@ -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<File::FSTEntry> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<CWII_IPC_HLE_WiiMote> m_WiiMotes;
|
||||
|
||||
std::deque<SQueuedEvent> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ private:
|
|||
|
||||
SHCICommandMessage m_CtrlSetup;
|
||||
CtrlBuffer m_HCIEndpoint;
|
||||
std::queue<SQueuedEvent> m_EventQueue;
|
||||
std::deque<SQueuedEvent> m_EventQueue;
|
||||
|
||||
u32 m_ACLSetup;
|
||||
CtrlBuffer m_ACLEndpoint;
|
||||
|
|
|
@ -65,7 +65,7 @@ static std::vector<u8> 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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue