Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
pierrewillenbrock committed May 27, 2011
1 parent 5b5e8ed commit 3bcb406
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 40 deletions.
13 changes: 13 additions & 0 deletions Source/Core/Common/Src/ChunkFile.h
Expand Up @@ -29,6 +29,7 @@

#include <map>
#include <vector>
#include <deque>
#include <string>

#include "Common.h"
Expand Down Expand Up @@ -127,6 +128,18 @@ class PointerWrap
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)
{
Expand Down
55 changes: 34 additions & 21 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp
Expand Up @@ -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

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand All @@ -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())
{
if (itr->second->IsHardware())
itr->second->DoState(p);
++itr;
}
//then all the files
itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
g_DeviceMap[itr->first]->DoState(p);
if (!itr->second->IsHardware())
itr->second->DoState(p);
++itr;
}
}
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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();
}
}

Expand Down
24 changes: 13 additions & 11 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp
Expand Up @@ -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);
}
Expand All @@ -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;
Expand All @@ -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",
Expand Down Expand Up @@ -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);
}
1 change: 0 additions & 1 deletion Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h
Expand Up @@ -76,7 +76,6 @@ class CWII_IPC_HLE_Device_FileIO : public IWII_IPC_HLE_Device
File::IOFile m_pFileHandle;
u32 m_FileLength;
u32 m_Mode;
s32 m_Seek;

std::string m_Filename;
};
Expand Down
94 changes: 94 additions & 0 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp
Expand Up @@ -25,6 +25,7 @@
#include "FileSearch.h"
#include "FileUtil.h"
#include "NandPaths.h"
#include "ChunkFile.h"

#include "../VolumeHandler.h"

Expand Down Expand Up @@ -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);
}
}
4 changes: 3 additions & 1 deletion Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.h
Expand Up @@ -46,7 +46,9 @@ class CWII_IPC_HLE_Device_fs : public IWII_IPC_HLE_Device
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);
Expand Down
21 changes: 17 additions & 4 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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...",
Expand All @@ -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);
}
}

Expand All @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
Expand Up @@ -152,7 +152,7 @@ class CWII_IPC_HLE_Device_usb_oh1_57e_305 : public IWII_IPC_HLE_Device

SHCICommandMessage m_CtrlSetup;
CtrlBuffer m_HCIEndpoint;
std::queue<SQueuedEvent> m_EventQueue;
std::deque<SQueuedEvent> m_EventQueue;

u32 m_ACLSetup;
CtrlBuffer m_ACLEndpoint;
Expand Down

0 comments on commit 3bcb406

Please sign in to comment.