Implement per-thread current directory

This commit is contained in:
KentuckyCompass 2013-01-10 03:27:10 -08:00
parent 2f394fb7ed
commit 320c0d06c3
5 changed files with 81 additions and 17 deletions

View File

@ -17,6 +17,7 @@
#include <set>
#include "Common/StringUtil.h"
#include "../HLE/sceKernelThread.h"
#include "MetaFileSystem.h"
static bool ApplyPathStringToComponentsVector(std::vector<std::string> &vector, const std::string &pathString)
@ -163,7 +164,6 @@ IFileSystem *MetaFileSystem::GetHandleOwner(u32 handle)
bool MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpath, IFileSystem **system)
{
//TODO: implement current directory per thread (NOT per drive)
std::string realpath;
// Special handling: host0:command.txt (as seen in Super Monkey Ball Adventures, for example)
@ -174,7 +174,22 @@ bool MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpat
inpath = inpath.substr(6);
}
if ( RealPath(currentDirectory, inpath, realpath) )
const std::string *currentDirectory = &startingDirectory;
int currentThread = __KernelGetCurThread();
currentDir_t::iterator i = currentDir.find(currentThread);
if (i == currentDir.end())
{
//TODO: emulate PSP's error 8002032C: "no current working directory" if relative... may break things requiring fixes elsewhere
if (inpath.find(':') == std::string::npos /* means path is relative */)
WARN_LOG(HLE, "Path is relative, but current directory not set for thread %i. Should give error, instead falling back to %s", currentThread, startingDirectory.c_str());
}
else
{
currentDirectory = &(i->second);
}
if ( RealPath(*currentDirectory, inpath, realpath) )
{
for (size_t i = 0; i < fileSystems.size(); i++)
{
@ -203,7 +218,7 @@ void MetaFileSystem::Mount(std::string prefix, IFileSystem *system)
fileSystems.push_back(x);
}
void MetaFileSystem::UnmountAll()
void MetaFileSystem::Shutdown()
{
current = 6;
@ -220,7 +235,8 @@ void MetaFileSystem::UnmountAll()
}
fileSystems.clear();
currentDirectory = "";
currentDir.clear();
startingDirectory = "";
}
u32 MetaFileSystem::OpenFile(std::string filename, FileAccess access)
@ -278,6 +294,19 @@ std::vector<PSPFileInfo> MetaFileSystem::GetDirListing(std::string path)
}
}
void MetaFileSystem::ThreadEnded(int threadID)
{
currentDir.erase(threadID);
}
void MetaFileSystem::ChDir(const std::string &dir)
{
//TODO: test sceIoChdir("..") on PSP - maybe we should map it before saving it?
int curThread = __KernelGetCurThread();
currentDir[curThread] = dir;
}
bool MetaFileSystem::MkDir(const std::string &dirname)
{
std::string of;
@ -372,9 +401,34 @@ size_t MetaFileSystem::SeekFile(u32 handle, s32 position, FileMove type)
void MetaFileSystem::DoState(PointerWrap &p)
{
p.Do(current);
p.Do(currentDirectory);
int n = (int) fileSystems.size();
// Save/load per-thread current directory map
u32 n = (u32) currentDir.size();
p.Do(n);
if (p.mode == p.MODE_READ)
{
std::string dir;
currentDir.clear();
for (u32 i = 0; i < n; ++i)
{
int threadID;
p.Do(threadID);
p.Do(dir);
currentDir[threadID] = dir;
}
}
else
{
currentDir_t::iterator i = currentDir.begin(), end = currentDir.end();
for (; i != end; ++i)
{
p.Do(i->first);
p.Do(i->second);
}
}
n = (u32) fileSystems.size();
p.Do(n);
if (n != fileSystems.size())
{
@ -382,7 +436,7 @@ void MetaFileSystem::DoState(PointerWrap &p)
return;
}
for (int i = 0; i < n; ++i)
for (u32 i = 0; i < n; ++i)
fileSystems[i].system->DoState(p);
p.DoMarker("MetaFileSystem");

View File

@ -30,8 +30,9 @@ public:
void Mount(std::string prefix, IFileSystem *system);
void Unmount(IFileSystem *system);
// Effectively "Shutdown".
void UnmountAll();
void ThreadEnded(int threadID);
void Shutdown();
u32 GetNewHandle() {return current++;}
void FreeHandle(u32 handle) {}
@ -57,7 +58,7 @@ public:
return SeekFile(handle, 0, FILEMOVE_CURRENT);
}
virtual void ChDir(std::string dir) {currentDirectory = dir;}
virtual void ChDir(const std::string &dir);
virtual bool MkDir(const std::string &dirname);
virtual bool RmDir(const std::string &dirname);
@ -66,8 +67,8 @@ public:
// TODO: void IoCtl(...)
void SetCurrentDirectory(const std::string &dir) {
currentDirectory = dir;
void SetStartingDirectory(const std::string &dir) {
startingDirectory = dir;
}
private:
u32 current;
@ -78,5 +79,8 @@ private:
};
std::vector<System> fileSystems;
std::string currentDirectory;
typedef std::map<int, std::string> currentDir_t;
currentDir_t currentDir;
std::string startingDirectory;
};

View File

@ -159,6 +159,10 @@ public:
PSPFileInfo info;
};
void TellFsThreadEnded (SceUID threadID) {
pspFileSystem.ThreadEnded(threadID);
}
void __IoInit() {
INFO_LOG(HLE, "Starting up I/O...");
@ -199,6 +203,8 @@ void __IoInit() {
pspFileSystem.Mount("fatms:", memstick);
pspFileSystem.Mount("flash0:", flash);
pspFileSystem.Mount("flash1:", flash);
__KernelListenThreadEnd(&TellFsThreadEnded);
}
void __IoDoState(PointerWrap &p) {

View File

@ -92,11 +92,11 @@ bool LoadFile(const char *filename, std::string *error_string)
// If loading from memstick...
size_t pos = path.find("/PSP/GAME/");
if (pos != std::string::npos)
pspFileSystem.SetCurrentDirectory("ms0:" + path.substr(pos));
pspFileSystem.SetStartingDirectory("ms0:" + path.substr(pos));
return Load_PSP_ELF_PBP(filename, error_string);
}
case FILETYPE_PSP_ISO:
pspFileSystem.SetCurrentDirectory("disc0:/PSP_GAME/USRDIR");
pspFileSystem.SetStartingDirectory("disc0:/PSP_GAME/USRDIR");
return Load_PSP_ISO(filename, error_string);
case FILETYPE_ERROR:
ERROR_LOG(LOADER, "Could not file");

View File

@ -64,7 +64,7 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
if (!LoadFile(coreParameter.fileToStart.c_str(), error_string))
{
pspFileSystem.UnmountAll();
pspFileSystem.Shutdown();
CoreTiming::ClearPendingEvents();
CoreTiming::UnregisterAllEvents();
__KernelShutdown();
@ -90,7 +90,7 @@ bool PSP_IsInited()
void PSP_Shutdown()
{
pspFileSystem.UnmountAll();
pspFileSystem.Shutdown();
TextureCache_Clear(true);