Improved LLE Manager

Improved VFS
This commit is contained in:
DHrpcs3 2014-11-29 15:16:53 +02:00
parent 795729a0b7
commit a59cf50f03
22 changed files with 559 additions and 175 deletions

View File

@ -102,4 +102,35 @@ std::vector<std::string> fmt::rSplit(const std::string& source, const std::strin
}
} while (true);
return ret;
}
std::vector<std::string> fmt::split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty)
{
std::vector<std::string> result;
size_t cursor_begin = 0;
for (size_t cursor_end = 0; cursor_end < source.length(); ++cursor_end)
{
for (auto &separator : separators)
{
if (strncmp(source.c_str() + cursor_end, separator.c_str(), separator.length()) == 0)
{
std::string candidate = source.substr(cursor_begin, cursor_end - cursor_begin);
if (!is_skip_empty || !candidate.empty())
result.push_back(candidate);
cursor_begin = cursor_end + separator.length();
cursor_end = cursor_begin - 1;
break;
}
}
}
if (cursor_begin != source.length())
{
result.push_back(source.substr(cursor_begin));
}
return std::move(result);
}

View File

@ -192,4 +192,6 @@ namespace fmt{
void Replace(std::string &str, const std::string &searchterm, const std::string& replaceterm);
std::vector<std::string> rSplit(const std::string& source, const std::string& delim);
std::vector<std::string> split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty = true);
}

View File

@ -4,33 +4,91 @@
#include "Emu/HDD/HDD.h"
#include "vfsDeviceLocalFile.h"
#include "Ini.h"
#include "Emu/System.h"
#undef CreateFile // TODO: what's wrong with it?
#undef CreateFile
int sort_devices(const void* _a, const void* _b)
{
const vfsDevice& a = **(const vfsDevice**)_a;
const vfsDevice& b = **(const vfsDevice**)_b;
if(a.GetPs3Path().length() > b.GetPs3Path().length()) return 1;
if(a.GetPs3Path().length() < b.GetPs3Path().length()) return -1;
if (a.GetPs3Path().length() > b.GetPs3Path().length()) return 1;
if (a.GetPs3Path().length() < b.GetPs3Path().length()) return -1;
return 0;
}
std::vector<std::string> simplify_path_blocks(const std::string& path)
{
std::vector<std::string> path_blocks = std::move(fmt::split(path, { "/", "\\" }));
for (size_t i = 0; i < path_blocks.size(); ++i)
{
if (path_blocks[i] == ".")
{
path_blocks.erase(path_blocks.begin() + i--);
}
else if (i && path_blocks[i] == "..")
{
path_blocks.erase(path_blocks.begin() + (i - 1), path_blocks.begin() + (i + 1));
i--;
}
}
return path_blocks;
}
std::string simplify_path(const std::string& path, bool is_dir)
{
std::vector<std::string> path_blocks = simplify_path_blocks(path);
std::string result;
if (path_blocks.empty())
return result;
if (is_dir)
{
for (auto &dir : path_blocks)
{
result += dir + "/";
}
}
else
{
for (size_t i = 0; i < path_blocks.size() - 1; ++i)
{
result += path_blocks[i] + "/";
}
result += path_blocks[path_blocks.size() - 1];
}
return result;
}
VFS::~VFS()
{
UnMountAll();
}
std::string VFS::FindEntry(const std::string &path)
{
return path;
return cwd + "/" + path;
}
void VFS::Mount(const std::string& ps3_path, const std::string& local_path, vfsDevice* device)
{
UnMount(ps3_path);
std::string simpl_ps3_path = simplify_path(ps3_path, true);
device->SetPath(ps3_path, local_path);
UnMount(simpl_ps3_path);
device->SetPath(simpl_ps3_path, simplify_path(local_path, true));
m_devices.push_back(device);
if(m_devices.size() > 1)
if (m_devices.size() > 1)
{
//std::qsort(m_devices.GetPtr(), m_devices.GetCount(), sizeof(vfsDevice*), sort_devices);
}
@ -38,11 +96,14 @@ void VFS::Mount(const std::string& ps3_path, const std::string& local_path, vfsD
void VFS::UnMount(const std::string& ps3_path)
{
for(u32 i=0; i<m_devices.size(); ++i)
std::string simpl_ps3_path = simplify_path(ps3_path, true);
for (u32 i = 0; i < m_devices.size(); ++i)
{
if(!m_devices[i]->GetPs3Path().compare(ps3_path))
if (!stricmp(m_devices[i]->GetPs3Path().c_str(), simpl_ps3_path.c_str()))
{
delete m_devices[i];
m_devices.erase(m_devices.begin() +i);
return;
@ -63,9 +124,9 @@ void VFS::UnMountAll()
vfsFileBase* VFS::OpenFile(const std::string& ps3_path, vfsOpenMode mode) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
if(vfsFileBase* res = dev->GetNewFileStream())
if (vfsFileBase* res = dev->GetNewFileStream())
{
res->Open(path, mode);
return res;
@ -79,9 +140,9 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
if(vfsDirBase* res = dev->GetNewDirStream())
if (vfsDirBase* res = dev->GetNewDirStream())
{
res->Open(path);
return res;
@ -94,11 +155,11 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
bool VFS::CreateFile(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res)
if (res)
{
return res->Create(path);
}
@ -110,11 +171,11 @@ bool VFS::CreateFile(const std::string& ps3_path) const
bool VFS::CreateDir(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res)
if (res)
{
return res->Create(path);
}
@ -126,11 +187,11 @@ bool VFS::CreateDir(const std::string& ps3_path) const
bool VFS::RemoveFile(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res)
if (res)
{
return res->Remove(path);
}
@ -142,11 +203,11 @@ bool VFS::RemoveFile(const std::string& ps3_path) const
bool VFS::RemoveDir(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res)
if (res)
{
return res->Remove(path);
}
@ -158,11 +219,11 @@ bool VFS::RemoveDir(const std::string& ps3_path) const
bool VFS::ExistsFile(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res)
if (res)
{
return res->Exists(path);
}
@ -174,11 +235,11 @@ bool VFS::ExistsFile(const std::string& ps3_path) const
bool VFS::ExistsDir(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res)
if (res)
{
return res->IsExists(path);
}
@ -190,11 +251,11 @@ bool VFS::ExistsDir(const std::string& ps3_path) const
bool VFS::RenameFile(const std::string& ps3_path_from, const std::string& ps3_path_to) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path_from, path))
if (vfsDevice* dev = GetDevice(ps3_path_from, path))
{
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res)
if (res)
{
return res->Rename(path, ps3_path_to);
}
@ -206,11 +267,11 @@ bool VFS::RenameFile(const std::string& ps3_path_from, const std::string& ps3_pa
bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_path_to) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path_from, path))
if (vfsDevice* dev = GetDevice(ps3_path_from, path))
{
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res)
if (res)
{
return res->Rename(path, ps3_path_to);
}
@ -221,53 +282,107 @@ bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_pat
vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const
{
u32 max_eq;
s32 max_i=-1;
for(u32 i=0; i<m_devices.size(); ++i)
auto try_get_device = [this, &path](const std::vector<std::string>& ps3_path_blocks) -> vfsDevice*
{
const u32 eq = m_devices[i]->CmpPs3Path(ps3_path);
size_t max_eq = 0;
int max_i = -1;
if(max_i < 0 || eq > max_eq)
for (u32 i = 0; i < m_devices.size(); ++i)
{
max_eq = eq;
max_i = i;
}
}
std::vector<std::string> dev_ps3_path_blocks = simplify_path_blocks(m_devices[i]->GetPs3Path());
if(max_i < 0) return nullptr;
path = vfsDevice::GetWinPath(m_devices[max_i]->GetLocalPath(), ps3_path.substr(max_eq, ps3_path.length() - max_eq));
return m_devices[max_i];
if (ps3_path_blocks.size() < dev_ps3_path_blocks.size())
continue;
size_t eq = 0;
for (; eq < dev_ps3_path_blocks.size(); ++eq)
{
if (stricmp(ps3_path_blocks[eq].c_str(), dev_ps3_path_blocks[eq].c_str()))
{
break;
}
}
if (eq > max_eq)
{
max_eq = eq;
max_i = i;
}
}
if (max_i < 0)
return nullptr;
path = m_devices[max_i]->GetLocalPath();
for (u32 i = max_eq; i < ps3_path_blocks.size(); i++)
{
path += "/" + ps3_path_blocks[i];
}
path = simplify_path(path, false);
return m_devices[max_i];
};
if (auto res = try_get_device(simplify_path_blocks(ps3_path)))
return res;
if (auto res = try_get_device(simplify_path_blocks(cwd + ps3_path)))
return res;
return nullptr;
}
vfsDevice* VFS::GetDeviceLocal(const std::string& local_path, std::string& path) const
{
u32 max_eq;
s32 max_i=-1;
size_t max_eq = 0;
int max_i = -1;
rFileName file_path(local_path);
file_path.Normalize();
std::string mormalized_path = file_path.GetFullPath();
std::vector<std::string> local_path_blocks = simplify_path_blocks(local_path);
for(u32 i=0; i<m_devices.size(); ++i)
for (u32 i = 0; i < m_devices.size(); ++i)
{
const u32 eq = m_devices[i]->CmpLocalPath(mormalized_path);
std::vector<std::string> dev_local_path_blocks_blocks = simplify_path_blocks(m_devices[i]->GetLocalPath());
if(max_i < 0 || eq > max_eq)
if (local_path_blocks.size() < dev_local_path_blocks_blocks.size())
continue;
size_t eq = 0;
for (; eq < dev_local_path_blocks_blocks.size(); ++eq)
{
if (stricmp(local_path_blocks[eq].c_str(), dev_local_path_blocks_blocks[eq].c_str()))
{
break;
}
}
if (eq > max_eq)
{
max_eq = eq;
max_i = i;
}
}
if(max_i < 0) return nullptr;
if (max_i < 0)
return nullptr;
path = m_devices[max_i]->GetPs3Path();
for (u32 i = max_eq; i < local_path_blocks.size(); i++)
{
path += "/" + local_path_blocks[i];
}
path = simplify_path(path, false);
path = vfsDevice::GetPs3Path(m_devices[max_i]->GetPs3Path(), local_path.substr(max_eq, local_path.length() - max_eq));
return m_devices[max_i];
}
void VFS::Init(const std::string& path)
{
cwd = simplify_path(path, true);
UnMountAll();
std::vector<VFSManagerEntry> entries;
@ -293,8 +408,8 @@ void VFS::Init(const std::string& path)
std::string mpath = entry.path;
// TODO: This shouldn't use current dir
fmt::Replace(mpath,"$(EmulatorDir)", ".");
fmt::Replace(mpath,"$(GameDir)", vfsDevice::GetRoot(path));
fmt::Replace(mpath, "$(EmulatorDir)", Emu.GetEmulatorPath());
fmt::Replace(mpath, "$(GameDir)", cwd);
Mount(entry.mount, mpath, dev);
}
}
@ -305,11 +420,11 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
entries_count.Init("count", "VFSManager");
int count = 0;
if(is_load)
if (is_load)
{
count = entries_count.LoadValue(count);
if(!count)
if (!count)
{
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd0/", "/dev_hdd0/");
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd1/", "/dev_hdd1/");
@ -319,7 +434,6 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)", "/app_home/");
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)/../", "/dev_bdvd/");
res.emplace_back(vfsDevice_LocalFile, "", "/host_root/");
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)", "/");
return;
}
@ -344,7 +458,7 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
entry_mount.Init(fmt::Format("mount[%d]", i), "VFSManager");
entry_device.Init(fmt::Format("device[%d]", i), "VFSManager");
if(is_load)
if (is_load)
{
res[i] = VFSManagerEntry();
res[i].path = entry_path.LoadValue("");

View File

@ -42,10 +42,17 @@ struct VFSManagerEntry
}
};
std::vector<std::string> simplify_path_blocks(const std::string& path);
std::string simplify_path(const std::string& path, bool is_dir);
struct VFS
{
~VFS();
std::string cwd;
std::string FindEntry(const std::string &path);
//TODO: find out where these are supposed to be deleted or just make it shared_ptr
//and also make GetDevice and GetDeviceLocal return shared_ptr then.
// A vfsDevice will be deleted when they're unmounted or the VFS struct is destroyed.

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "vfsDevice.h"
#include "VFS.h"
#include "vfsDir.h"
@ -10,7 +11,7 @@ vfsDir::vfsDir()
{
// TODO: proper implementation
// m_stream is nullptr here. So open root until a proper dir is given
Open("/");
//Open("/");
}
vfsDir::vfsDir(const std::string& path)
@ -26,37 +27,78 @@ bool vfsDir::Open(const std::string& path)
m_stream.reset(Emu.GetVFS().OpenDir(path));
return m_stream && m_stream->IsOpened();
DirEntryInfo info;
m_cwd = simplify_path(0 && m_stream && m_stream->IsOpened() ? m_stream->GetPath() : path, true);
auto blocks = simplify_path_blocks(GetPath());
for (auto dev : Emu.GetVFS().m_devices)
{
auto dev_blocks = simplify_path_blocks(dev->GetPs3Path());
if (dev_blocks.size() < (blocks.size() + 1))
{
continue;
}
bool is_ok = true;
for (size_t i = 0; i < blocks.size(); ++i)
{
if (stricmp(dev_blocks[i].c_str(), blocks[i].c_str()))
{
is_ok = false;
break;
}
}
if (is_ok)
{
info.name = dev_blocks[blocks.size()];
m_entries.push_back(info);
}
}
if (m_stream && m_stream->IsOpened())
{
m_entries.insert(m_entries.begin(), m_stream->GetEntries().begin(), m_stream->GetEntries().end());
}
return !m_entries.empty();
}
bool vfsDir::Create(const std::string& path)
{
return m_stream->Create(path);
return Emu.GetVFS().CreateDir(path);
}
bool vfsDir::IsExists(const std::string& path) const
{
return m_stream->IsExists(path);
}
auto path_blocks = simplify_path_blocks(path);
const std::vector<DirEntryInfo>& vfsDir::GetEntries() const
{
return m_stream->GetEntries();
if (path_blocks.empty())
return false;
std::string dir_name = path_blocks[path_blocks.size() - 1];
for (const auto entry : vfsDir(path + "/.."))
{
if (!stricmp(entry->name.c_str(), dir_name.c_str()))
return true;
}
return false;
}
bool vfsDir::Rename(const std::string& from, const std::string& to)
{
return m_stream->Rename(from, to);
return Emu.GetVFS().RenameDir(from, to);
}
bool vfsDir::Remove(const std::string& path)
{
return m_stream->Remove(path);
}
const DirEntryInfo* vfsDir::Read()
{
return m_stream->Read();
return Emu.GetVFS().RemoveDir(path);
}
void vfsDir::Close()
@ -64,12 +106,7 @@ void vfsDir::Close()
m_stream.reset();
}
std::string vfsDir::GetPath() const
{
return m_stream->GetPath();
}
bool vfsDir::IsOpened() const
{
return m_stream && m_stream->IsOpened();
return !m_entries.empty();
}

View File

@ -13,13 +13,11 @@ public:
virtual bool Open(const std::string& path) override;
virtual bool IsOpened() const override;
virtual bool IsExists(const std::string& path) const override;
virtual const std::vector<DirEntryInfo>& GetEntries() const override;
virtual void Close() override;
virtual std::string GetPath() const override;
//virtual std::string GetPath() const override;
virtual bool Create(const std::string& path) override;
//virtual bool Create(const DirEntryInfo& info) override;
virtual bool Rename(const std::string& from, const std::string& to) override;
virtual bool Remove(const std::string& path) override;
virtual const DirEntryInfo* Read() override;
};

View File

@ -32,7 +32,7 @@ bool vfsDirBase::IsOpened() const
bool vfsDirBase::IsExists(const std::string& path) const
{
return rExists(path);
return false;
}
const std::vector<DirEntryInfo>& vfsDirBase::GetEntries() const
@ -58,3 +58,9 @@ const DirEntryInfo* vfsDirBase::Read()
return &m_entries[m_pos++];
}
const DirEntryInfo* vfsDirBase::First()
{
m_pos = 0;
return Read();
}

View File

@ -53,4 +53,57 @@ public:
virtual bool Rename(const std::string& from, const std::string& to) = 0;
virtual bool Remove(const std::string& path) = 0;
virtual const DirEntryInfo* Read();
virtual const DirEntryInfo* First();
class iterator
{
vfsDirBase *parent;
const DirEntryInfo* data;
public:
iterator(vfsDirBase* parent)
: parent(parent)
, data(parent->First())
{
}
iterator(const DirEntryInfo* data)
: parent(parent)
, data(data)
{
}
iterator& operator++()
{
data = parent->Read();
return *this;
}
iterator operator++(int)
{
const DirEntryInfo* olddata = data;
data = parent->Read();
return iterator(olddata);
}
const DirEntryInfo* operator *()
{
return data;
}
bool operator!=(iterator other) const
{
return data != other.data;
}
};
iterator begin()
{
return iterator(this);
}
iterator end()
{
return iterator((const DirEntryInfo*)nullptr);
}
};

View File

@ -46,6 +46,11 @@ bool vfsLocalDir::Create(const std::string& path)
return rMkpath(path);
}
bool vfsLocalDir::IsExists(const std::string& path) const
{
return rIsDir(path);
}
bool vfsLocalDir::Rename(const std::string& from, const std::string& to)
{
return false;

View File

@ -18,4 +18,5 @@ public:
virtual bool Rename(const std::string& from, const std::string& to) override;
virtual bool Remove(const std::string& path) override;
virtual bool IsOpened() const override;
virtual bool IsExists(const std::string& path) const;
};

View File

@ -219,4 +219,37 @@ namespace vm
assert(location < memory_location_count);
return g_locations[location];
}
class stack
{
u32 m_begin;
u32 m_size;
int m_page_size;
int m_position;
u8 m_align;
public:
void init(u32 begin, u32 size, u32 page_size = 180, u8 align = 0x10)
{
m_begin = begin;
m_size = size;
m_page_size = page_size;
m_position = 0;
m_align = align;
}
u32 alloc_new_page()
{
assert(m_position + m_page_size < (int)m_size);
m_position += (int)m_page_size;
return m_begin + m_position;
}
u32 dealloc_new_page()
{
assert(m_position - m_page_size > 0);
m_position -= (int)m_page_size;
return m_begin + m_position;
}
};
}

View File

@ -10,7 +10,6 @@ class ModuleManager
std::vector<ModuleFunc *> m_modules_funcs_list;
std::vector<Module> m_mod_init; //owner of Module
bool initialized;
std::unordered_map<u32, u32> m_registered_functions;
public:
ModuleManager();
@ -26,20 +25,4 @@ public:
u32 GetFuncNumById(u32 id);
Module* GetModuleByName(const std::string& name);
Module* GetModuleById(u16 id);
void register_function(u32 fnid, u32 fstub)
{
m_registered_functions[fnid] = fstub;
}
bool get_function_stub(u32 fnid, be_t<u32>& res)
{
auto f = m_registered_functions.find(fnid);
if (f == m_registered_functions.end())
return false;
res = f->second;
return true;
}
};

View File

@ -62,10 +62,12 @@ Module::~Module()
{
UnLoad();
for (int i = 0; i < m_funcs_list.size(); i++)
for (auto &i : m_funcs_list)
{
delete m_funcs_list[i];
delete i.second;
}
m_funcs_list.clear();
}
void Module::Load()
@ -75,12 +77,10 @@ void Module::Load()
if(m_load_func) m_load_func();
for(u32 i=0; i<m_funcs_list.size(); ++i)
for (auto &i : m_funcs_list)
{
Emu.GetModuleManager().AddFunc(m_funcs_list[i]);
Emu.GetModuleManager().AddFunc(i.second);
}
SetLoaded(true);
}
void Module::UnLoad()
@ -90,6 +90,11 @@ void Module::UnLoad()
if(m_unload_func) m_unload_func();
for (auto &i : m_funcs_list)
{
i.second->lle_func.set(0);
}
// TODO: Re-enable this when needed
// This was disabled because some functions would get unloaded and
// some games tried to use them, thus only printing a TODO message
@ -106,16 +111,14 @@ bool Module::Load(u32 id)
if(Emu.GetModuleManager().IsLoadedFunc(id))
return false;
for(u32 i=0; i<m_funcs_list.size(); ++i)
{
if(m_funcs_list[i]->id == id)
{
Emu.GetModuleManager().AddFunc(m_funcs_list[i]);
return true;
}
}
auto res = m_funcs_list.find(id);
return false;
if (res == m_funcs_list.end())
return false;
Emu.GetModuleManager().AddFunc(res->second);
return true;
}
bool Module::UnLoad(u32 id)
@ -177,7 +180,7 @@ void fix_import(Module* module, u32 func, u32 addr)
{
using namespace PPU_instr;
vm::ptr<u32>& ptr = (vm::ptr<u32>&)addr;
vm::ptr<u32>& ptr = vm::ptr<u32>::make(addr);
*ptr++ = ADDIS(11, 0, func >> 16);
*ptr++ = ORI(11, 11, func & 0xffff);

View File

@ -9,10 +9,12 @@ struct ModuleFunc
{
u32 id;
func_caller* func;
vm::ptr<void(*)()> lle_func;
ModuleFunc(u32 id, func_caller* func)
ModuleFunc(u32 id, func_caller* func, vm::ptr<void(*)()> lle_func = vm::ptr<void(*)()>::make(0))
: id(id)
, func(func)
, lle_func(lle_func)
{
}
@ -57,7 +59,7 @@ class Module : public LogBase
void PushNewFuncSub(SFunc* func);
public:
std::vector<ModuleFunc*> m_funcs_list;
std::unordered_map<u32, ModuleFunc*> m_funcs_list;
Module(u16 id, const char* name, void(*load)() = nullptr, void(*unload)() = nullptr);
@ -66,6 +68,16 @@ public:
Module &operator =(Module &other) = delete;
Module &operator =(Module &&other);
ModuleFunc* GetFunc(u32 id)
{
auto res = m_funcs_list.find(id);
if (res == m_funcs_list.end())
return nullptr;
return res->second;
}
~Module();
@ -114,9 +126,20 @@ public:
}
bool RemoveId(u32 id);
void RegisterLLEFunc(u32 id, vm::ptr<void(*)()> func)
{
if (auto f = GetFunc(id))
{
f->lle_func = func;
return;
}
m_funcs_list[id] = new ModuleFunc(id, nullptr, func);
}
template<typename T> __forceinline void AddFunc(u32 id, T func);
template<typename T> __forceinline void AddFunc(const char* name, T func);
template<typename T> __forceinline void AddFunc(const char* name, T func);
template<typename T> __forceinline void AddFuncSub(const char group[8], const u64 ops[], const char* name, T func);
};
@ -125,7 +148,7 @@ u32 getFunctionId(const char* name);
template<typename T>
__forceinline void Module::AddFunc(u32 id, T func)
{
m_funcs_list.emplace_back(new ModuleFunc(id, bind_func(func)));
m_funcs_list[id] = new ModuleFunc(id, bind_func(func));
}
template<typename T>

View File

@ -305,7 +305,7 @@ s32 cellFsMkdir(vm::ptr<const char> path, u32 mode)
const std::string _path = path.get_ptr();
if(Emu.GetVFS().ExistsDir(_path))
if(vfsDir().IsExists(_path))
return CELL_EEXIST;
if(!Emu.GetVFS().CreateDir(_path))
return CELL_EBUSY;
@ -395,7 +395,7 @@ s32 cellFsUnlink(vm::ptr<const char> path)
std::string _path = path.get_ptr();
if (Emu.GetVFS().ExistsDir(_path))
if (vfsDir().IsExists(_path))
return CELL_EISDIR;
if (!Emu.GetVFS().ExistsFile(_path))

View File

@ -192,7 +192,7 @@ void Emulator::Load()
LOG_NOTICE(LOADER, "Loading '%s'...", m_path.c_str());
GetInfo().Reset();
GetVFS().Init(m_path);
GetVFS().Init(rFileName(m_path).GetPath());
LOG_NOTICE(LOADER, " "); //used to be skip_line
LOG_NOTICE(LOADER, "Mount info:");

View File

@ -112,6 +112,7 @@ class Emulator
public:
std::string m_path;
std::string m_elf_path;
std::string m_emu_path;
std::string m_title_id;
u32 m_ppu_thr_stop;
s32 m_sdk_version;
@ -128,6 +129,16 @@ public:
return m_elf_path;
}
std::string GetEmulatorPath() const
{
return m_emu_path;
}
void SetEmulatorPath(const std::string& path)
{
m_emu_path = path;
}
std::recursive_mutex& GetCoreMutex() { return m_core_mutex; }
CPUThreadManager& GetCPU() { return *m_thread_manager; }

View File

@ -13,19 +13,20 @@ LLEModulesManagerFrame::LLEModulesManagerFrame(wxWindow* parent) : FrameBase(par
wxBoxSizer *s_p_panel = new wxBoxSizer(wxVERTICAL);
wxPanel *p_main = new wxPanel(this);
m_check_list = new wxCheckListBox(p_main, wxID_ANY);
s_p_panel->Add(m_check_list, 0, wxEXPAND | wxALL, 5);
s_p_panel->Add(m_check_list, 1, wxEXPAND | wxALL, 5);
p_main->SetSizerAndFit(s_p_panel);
s_panel->Add(p_main, 0, wxEXPAND | wxALL, 5);
s_panel->Add(p_main, 1, wxEXPAND | wxALL, 5);
SetSizerAndFit(s_panel);
Refresh();
//Bind(wxEVT_CHECKLISTBOX, [this](wxCommandEvent& event) { UpdateSelection(); });
Bind(wxEVT_SIZE, [p_main, this](wxSizeEvent& event) { p_main->SetSize(GetClientSize()); m_check_list->SetSize(p_main->GetClientSize() - wxSize(10, 10)); });
Bind(wxEVT_CHECKLISTBOX, [this](wxCommandEvent& event) { UpdateSelection(event.GetInt()); event.Skip(); });
Bind(wxEVT_SIZE, [p_main, this](wxSizeEvent& event) { p_main->SetSize(GetClientSize()); m_check_list->SetSize(p_main->GetClientSize() - wxSize(10, 10)); event.Skip(); });
}
void LLEModulesManagerFrame::Refresh()
{
m_check_list->Clear();
m_funcs.clear();
std::string path = "/dev_flash/sys/external/";
@ -34,7 +35,7 @@ void LLEModulesManagerFrame::Refresh()
vfsDir dir(path);
loader::handlers::elf64 sprx_loader;
for (const DirEntryInfo* info = dir.Read(); info; info = dir.Read())
for (const auto info : dir)
{
if (info->flags & DirEntry_TypeFile)
{
@ -49,17 +50,45 @@ void LLEModulesManagerFrame::Refresh()
continue;
}
sprx_loader.load();
//loader::handlers::elf64::sprx_info info;
//sprx_loader.load_sprx(info);
m_check_list->Check(m_check_list->Append(sprx_loader.sprx_get_module_name() +
" v" + std::to_string((int)sprx_loader.m_sprx_module_info.version[0]) + "." + std::to_string((int)sprx_loader.m_sprx_module_info.version[1])));
std::string name = sprx_loader.sprx_get_module_name();
bool is_skip = false;
for (auto &i : m_funcs)
{
if (i == name)
{
is_skip = true;
break;
}
}
if (is_skip)
continue;
m_funcs.push_back(name);
IniEntry<bool> load_lib;
load_lib.Init(name, "LLE");
m_check_list->Check(m_check_list->Append(name +
" v" + std::to_string((int)sprx_loader.m_sprx_module_info.version[0]) +
"." + std::to_string((int)sprx_loader.m_sprx_module_info.version[1])),
load_lib.LoadValue(false));
}
}
Emu.GetVFS().UnMountAll();
}
void LLEModulesManagerFrame::UpdateSelection()
void LLEModulesManagerFrame::UpdateSelection(int index)
{
if (index < 0)
return;
IniEntry<bool> load_lib;
load_lib.Init(m_funcs[index], "LLE");
load_lib.SaveValue(m_check_list->IsChecked(index));
}

View File

@ -5,9 +5,10 @@
class LLEModulesManagerFrame : public FrameBase
{
wxCheckListBox *m_check_list;
std::vector<std::string> m_funcs;
public:
LLEModulesManagerFrame(wxWindow *parent);
void Refresh();
void UpdateSelection();
void UpdateSelection(int index);
};

View File

@ -3,6 +3,7 @@
#include "Utilities/rFile.h"
#include "Emu/FS/vfsStream.h"
#include "Emu/FS/vfsFile.h"
#include "Emu/FS/vfsDir.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/SysCalls.h"
@ -12,6 +13,7 @@
#include "Emu/Cell/PPUInstrTable.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "ELF64.h"
#include "Ini.h"
using namespace PPU_instr;
@ -43,8 +45,6 @@ namespace loader
return broken_file;
}
LOG_WARNING(LOADER, "m_ehdr.e_type = 0x%x", m_ehdr.e_type.ToLE());
if (m_ehdr.e_machine != MACHINE_PPC64 && m_ehdr.e_machine != MACHINE_SPU)
{
LOG_ERROR(LOADER, "Unknown elf64 machine type: 0x%x", m_ehdr.e_machine.ToLE());
@ -73,8 +73,6 @@ namespace loader
if (is_sprx())
{
LOG_NOTICE(LOADER, "SPRX loading...");
m_stream->Seek(handler::get_stream_offset() + m_phdrs[0].p_paddr.addr());
m_stream->Read(&m_sprx_module_info, sizeof(sprx_module_info));
@ -94,7 +92,7 @@ namespace loader
{
for (auto &phdr : m_phdrs)
{
switch (phdr.p_type.ToLE())
switch ((u32)phdr.p_type)
{
case 0x1: //load
if (phdr.p_memsz)
@ -127,6 +125,8 @@ namespace loader
m_stream->Seek(handler::get_stream_offset() + phdr.p_paddr.addr());
m_stream->Read(&module_info, sizeof(module_info));
LOG_ERROR(LOADER, "%s (%x):", module_info.name, (u32)module_info.toc);
info.name = std::string((const char*)module_info.name, 28);
info.rtoc = module_info.toc;
int import_count = (module_info.imports_end - module_info.imports_start) / sizeof(sys_prx_library_info_t);
@ -149,12 +149,12 @@ namespace loader
{
char name[27];
m_stream->Seek(handler::get_stream_offset() + phdr.p_offset + lib.name_addr);
modulename = std::string(name, m_stream->Read(name, sizeof(name)));
m_stream->Read(name, sizeof(name));
modulename = std::string(name);
LOG_ERROR(LOADER, "**** %s", name);
}
//ModuleManager& manager = Emu.GetModuleManager();
//Module* module = manager.GetModuleByName(modulename);
auto &module = info.modules[modulename];
LOG_ERROR(LOADER, "**** 0x%x - 0x%x - 0x%x", (u32)lib.unk4, (u32)lib.unk5, (u32)lib.unk6);
@ -167,7 +167,7 @@ namespace loader
m_stream->Seek(handler::get_stream_offset() + phdr.p_offset + lib.fstub_addr + i * sizeof(fstub));
m_stream->Read(&fstub, sizeof(fstub));
info.exports[fnid] = fstub;
module.exports[fnid] = fstub;
//LOG_NOTICE(LOADER, "Exported function '%s' in '%s' module (LLE)", SysCalls::GetHLEFuncName(fnid).c_str(), module_name.c_str());
LOG_ERROR(LOADER, "**** %s: [%s] -> 0x%x", modulename.c_str(), SysCalls::GetHLEFuncName(fnid).c_str(), (u32)fstub);
@ -201,17 +201,17 @@ namespace loader
switch ((u32)rel.type)
{
case 1:
LOG_ERROR(LOADER, "**** RELOCATION(1): 0x%x <- 0x%x", ADDR, (u32)(info.segments[rel.index_value].begin.addr() + rel.ptr.addr()));
LOG_WARNING(LOADER, "**** RELOCATION(1): 0x%x <- 0x%x", ADDR, (u32)(info.segments[rel.index_value].begin.addr() + rel.ptr.addr()));
*vm::ptr<u32>::make(ADDR) = info.segments[rel.index_value].begin.addr() + rel.ptr.addr();
break;
case 4:
LOG_ERROR(LOADER, "**** RELOCATION(4): 0x%x <- 0x%x", ADDR, (u16)(rel.ptr.addr()));
LOG_WARNING(LOADER, "**** RELOCATION(4): 0x%x <- 0x%x", ADDR, (u16)(rel.ptr.addr()));
*vm::ptr<u16>::make(ADDR) = (u16)(u64)rel.ptr.addr();
break;
case 5:
LOG_ERROR(LOADER, "**** RELOCATION(5): 0x%x <- 0x%x", ADDR, (u16)(info.segments[rel.index_value].begin.addr() >> 16));
LOG_WARNING(LOADER, "**** RELOCATION(5): 0x%x <- 0x%x", ADDR, (u16)(info.segments[rel.index_value].begin.addr() >> 16));
*vm::ptr<u16>::make(ADDR) = info.segments[rel.index_value].begin.addr() >> 16;
break;
@ -230,20 +230,23 @@ namespace loader
}
}
for (auto &e : info.exports)
for (auto &m : info.modules)
{
u32 stub = e.second;
for (auto &s : info.segments)
for (auto &e : m.second.exports)
{
if (stub >= s.initial_addr.addr() && stub < s.initial_addr.addr() + s.size_file)
{
stub += s.begin.addr() - s.initial_addr.addr();
break;
}
}
u32 stub = e.second;
e.second = stub;
for (auto &s : info.segments)
{
if (stub >= s.initial_addr.addr() && stub < s.initial_addr.addr() + s.size_file)
{
stub += s.begin.addr() - s.initial_addr.addr();
break;
}
}
e.second = stub;
}
}
return ok;
@ -266,12 +269,12 @@ namespace loader
std::vector<u32> stop_funcs;
//load modules
static const char* lle_modules[] = { "lv2", "sre", "l10n", "gcm_sys", "fs" };
//TODO: for (auto &module : lle_modules)
char* module; if (0)
vfsDir lle_dir("/dev_flash/sys/external");
for (const auto module : lle_dir)
{
elf64 sprx_handler;
vfsFile fsprx(std::string("/dev_flash/sys/external/lib") + module + ".sprx");
vfsFile fsprx(lle_dir.GetPath() + "/" + module->name);
if (fsprx.IsOpened())
{
@ -279,21 +282,52 @@ namespace loader
if (sprx_handler.is_sprx())
{
IniEntry<bool> load_lib;
load_lib.Init(sprx_handler.sprx_get_module_name(), "LLE");
if (!load_lib.LoadValue(false))
{
LOG_ERROR(LOADER, "skipped lle library '%s'", sprx_handler.sprx_get_module_name().c_str());
continue;
}
else
{
LOG_WARNING(LOADER, "loading lle library '%s'", sprx_handler.sprx_get_module_name().c_str());
}
sprx_info info;
sprx_handler.load_sprx(info);
std::unordered_map<u32, u32>::iterator f;
if ((f = info.exports.find(0xbc9a0086)) != info.exports.end())
start_funcs.push_back(f->second);
if ((f = info.exports.find(0xab779874)) != info.exports.end())
stop_funcs.push_back(f->second);
for (auto &e : info.exports)
for (auto &m : info.modules)
{
if (e.first != 0xbc9a0086 && e.first != 0xab779874)
Emu.GetModuleManager().register_function(e.first, e.second);
if (m.first == "")
{
for (auto &e : m.second.exports)
{
switch (e.first)
{
case 0xbc9a0086: start_funcs.push_back(e.second); break;
case 0xab779874: stop_funcs.push_back(e.second); break;
default: LOG_ERROR(LOADER, "unknown special func 0x%08x in '%s' library", e.first, info.name.c_str()); break;
}
}
continue;
}
Module* module = Emu.GetModuleManager().GetModuleByName(m.first);
if (!module)
{
LOG_ERROR(LOADER, "unknown module '%s' in '%s' library", m.first.c_str(), info.name.c_str());
module = new Module(-1, m.first.c_str());
}
for (auto &e : m.second.exports)
{
module->RegisterLLEFunc(e.first, vm::ptr<void(*)()>::make(e.second));
}
}
}
}
@ -469,8 +503,9 @@ namespace loader
for (u32 i = 0; i < stub->s_imports; ++i)
{
const u32 nid = stub->s_nid[i];
auto func = module->GetFunc(nid);
if (!Emu.GetModuleManager().get_function_stub(nid, stub->s_text[i]))
if (!func || !func->lle_func)
{
dst[i] = stub_data;
@ -490,6 +525,7 @@ namespace loader
}
else
{
stub->s_text[i] = func->lle_func.addr();
//Is function auto exported, than we can use it
LOG_NOTICE(LOADER, "Imported function '%s' in '%s' module (LLE: 0x%x)", SysCalls::GetHLEFuncName(nid).c_str(), module_name.c_str(), (u32)stub->s_text[i]);
}

View File

@ -131,8 +131,16 @@ namespace loader
struct sprx_info
{
std::unordered_map<u32, u32> exports;
std::unordered_map<u32, u32> imports;
std::string name;
u32 rtoc;
struct module_info
{
std::unordered_map<u32, u32> exports;
std::unordered_map<u32, u32> imports;
};
std::unordered_map<std::string, module_info> modules;
std::vector<sprx_segment_info> segments;
};

View File

@ -40,6 +40,8 @@ wxDEFINE_EVENT(wxEVT_DBG_COMMAND, wxCommandEvent);
IMPLEMENT_APP(Rpcs3App)
Rpcs3App* TheApp;
std::string simplify_path(const std::string& path, bool is_dir);
bool Rpcs3App::OnInit()
{
SetSendDbgCommandCallback([](DbgCommand id, CPUThread* t)
@ -128,8 +130,8 @@ bool Rpcs3App::OnInit()
wxInitAllImageHandlers();
// RPCS3 assumes the current working directory is the folder where it is contained, so we make sure this is true
const wxString executablePath = wxStandardPaths::Get().GetExecutablePath();
wxSetWorkingDirectory(wxPathOnly(executablePath));
const wxString executablePath = wxPathOnly(wxStandardPaths::Get().GetExecutablePath());
wxSetWorkingDirectory(executablePath);
main_thread = std::this_thread::get_id();
@ -137,6 +139,7 @@ bool Rpcs3App::OnInit()
m_MainFrame = new MainFrame();
SetTopWindow(m_MainFrame);
Emu.Init();
Emu.SetEmulatorPath(executablePath.ToStdString());
m_MainFrame->Show();
m_MainFrame->DoSettings(true);