IOS/FS: Split FSDevice into FSCore and FSDevice.
FSCore implements the core functionality that can also be used outside of emulation. FSDevice implements the IOS device and is only available during emulation.
This commit is contained in:
parent
6a339cbdb3
commit
3d767edd8a
|
@ -254,7 +254,7 @@ IPCReply ESDevice::GetTitleId(const IOCtlVRequest& request)
|
|||
|
||||
static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd)
|
||||
{
|
||||
ES::UIDSys uid_sys{kernel.GetFSDevice()};
|
||||
ES::UIDSys uid_sys{kernel.GetFSCore()};
|
||||
const u64 title_id = tmd.GetTitleId();
|
||||
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
|
||||
if (uid == 0)
|
||||
|
@ -270,7 +270,7 @@ static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd)
|
|||
static ReturnCode CheckIsAllowedToSetUID(Kernel& kernel, const u32 caller_uid,
|
||||
const ES::TMDReader& active_tmd)
|
||||
{
|
||||
ES::UIDSys uid_map{kernel.GetFSDevice()};
|
||||
ES::UIDSys uid_map{kernel.GetFSCore()};
|
||||
const u32 system_menu_uid = uid_map.GetOrInsertUIDForTitle(Titles::SYSTEM_MENU);
|
||||
if (!system_menu_uid)
|
||||
return ES_SHORT_READ;
|
||||
|
@ -388,7 +388,7 @@ bool ESDevice::LaunchIOS(u64 ios_title_id, HangPPC hang_ppc)
|
|||
|
||||
s32 ESDevice::WriteLaunchFile(const ES::TMDReader& tmd, Ticks ticks)
|
||||
{
|
||||
GetEmulationKernel().GetFSDevice()->DeleteFile(PID_KERNEL, PID_KERNEL, SPACE_FILE_PATH, ticks);
|
||||
GetEmulationKernel().GetFSCore().DeleteFile(PID_KERNEL, PID_KERNEL, SPACE_FILE_PATH, ticks);
|
||||
|
||||
std::vector<u8> launch_data(sizeof(u64) + sizeof(ES::TicketView));
|
||||
const u64 title_id = tmd.GetTitleId();
|
||||
|
@ -432,7 +432,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
|
|||
// To keep track of the PPC title launch, a temporary launch file (LAUNCH_FILE_PATH) is used
|
||||
// to store the title ID of the title to launch and its TMD.
|
||||
// The launch file not existing means an IOS reload is required.
|
||||
if (const auto launch_file_fd = GetEmulationKernel().GetFSDevice()->Open(
|
||||
if (const auto launch_file_fd = GetEmulationKernel().GetFSCore().Open(
|
||||
PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, FS::Mode::Read, {}, &ticks);
|
||||
launch_file_fd.Get() < 0)
|
||||
{
|
||||
|
@ -452,7 +452,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
|
|||
|
||||
// Otherwise, assume that the PPC title can now be launched directly.
|
||||
// Unlike IOS, we won't bother checking the title ID in the launch file. (It's not useful.)
|
||||
GetEmulationKernel().GetFSDevice()->DeleteFile(PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, &ticks);
|
||||
GetEmulationKernel().GetFSCore().DeleteFile(PID_KERNEL, PID_KERNEL, LAUNCH_FILE_PATH, &ticks);
|
||||
WriteSystemFile(SPACE_FILE_PATH, std::vector<u8>(SPACE_FILE_SIZE), &ticks);
|
||||
|
||||
m_core.m_title_context.Update(tmd, ticket, DiscIO::Platform::WiiWAD);
|
||||
|
|
|
@ -554,17 +554,16 @@ struct SharedContentMap::Entry
|
|||
};
|
||||
|
||||
constexpr char CONTENT_MAP_PATH[] = "/shared1/content.map";
|
||||
SharedContentMap::SharedContentMap(std::shared_ptr<HLE::FSDevice> fs)
|
||||
: m_fs_device{fs}, m_fs{fs->GetFS()}
|
||||
SharedContentMap::SharedContentMap(HLE::FSCore& fs_core) : m_fs_core{fs_core}, m_fs{fs_core.GetFS()}
|
||||
{
|
||||
static_assert(sizeof(Entry) == 28, "SharedContentMap::Entry has the wrong size");
|
||||
|
||||
Entry entry;
|
||||
const auto fd =
|
||||
fs->Open(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
|
||||
fs_core.Open(PID_KERNEL, PID_KERNEL, CONTENT_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
|
||||
if (fd.Get() < 0)
|
||||
return;
|
||||
while (fs->Read(fd.Get(), &entry, 1, &m_ticks) == sizeof(entry))
|
||||
while (fs_core.Read(fd.Get(), &entry, 1, &m_ticks) == sizeof(entry))
|
||||
{
|
||||
m_entries.push_back(entry);
|
||||
m_last_id++;
|
||||
|
@ -637,7 +636,7 @@ bool SharedContentMap::WriteEntries() const
|
|||
HLE::FS::ResultCode::Success;
|
||||
}
|
||||
|
||||
static std::pair<u32, u64> ReadUidSysEntry(HLE::FSDevice& fs, u64 fd, u64* ticks)
|
||||
static std::pair<u32, u64> ReadUidSysEntry(HLE::FSCore& fs, u64 fd, u64* ticks)
|
||||
{
|
||||
u64 title_id = 0;
|
||||
if (fs.Read(fd, &title_id, 1, ticks) != sizeof(title_id))
|
||||
|
@ -651,15 +650,15 @@ static std::pair<u32, u64> ReadUidSysEntry(HLE::FSDevice& fs, u64 fd, u64* ticks
|
|||
}
|
||||
|
||||
constexpr char UID_MAP_PATH[] = "/sys/uid.sys";
|
||||
UIDSys::UIDSys(std::shared_ptr<HLE::FSDevice> fs) : m_fs_device{fs}, m_fs{fs->GetFS()}
|
||||
UIDSys::UIDSys(HLE::FSCore& fs_core) : m_fs_core{fs_core}, m_fs{fs_core.GetFS()}
|
||||
{
|
||||
if (const auto fd =
|
||||
fs->Open(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
|
||||
fs_core.Open(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, HLE::FS::Mode::Read, {}, &m_ticks);
|
||||
fd.Get() >= 0)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::pair<u32, u64> entry = ReadUidSysEntry(*fs, fd.Get(), &m_ticks);
|
||||
std::pair<u32, u64> entry = ReadUidSysEntry(fs_core, fd.Get(), &m_ticks);
|
||||
if (!entry.first && !entry.second)
|
||||
break;
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ public:
|
|||
class SharedContentMap final
|
||||
{
|
||||
public:
|
||||
explicit SharedContentMap(std::shared_ptr<HLE::FSDevice> fs);
|
||||
explicit SharedContentMap(HLE::FSCore& fs_core);
|
||||
~SharedContentMap();
|
||||
|
||||
std::optional<std::string> GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
|
||||
|
@ -296,7 +296,7 @@ private:
|
|||
struct Entry;
|
||||
u32 m_last_id = 0;
|
||||
std::vector<Entry> m_entries;
|
||||
std::shared_ptr<HLE::FSDevice> m_fs_device;
|
||||
HLE::FSCore& m_fs_core;
|
||||
std::shared_ptr<HLE::FS::FileSystem> m_fs;
|
||||
u64 m_ticks = 0;
|
||||
};
|
||||
|
@ -304,7 +304,7 @@ private:
|
|||
class UIDSys final
|
||||
{
|
||||
public:
|
||||
explicit UIDSys(std::shared_ptr<HLE::FSDevice> fs);
|
||||
explicit UIDSys(HLE::FSCore& fs_core);
|
||||
|
||||
u32 GetUIDFromTitle(u64 title_id) const;
|
||||
u32 GetOrInsertUIDForTitle(u64 title_id);
|
||||
|
@ -313,7 +313,7 @@ public:
|
|||
u64 GetTicks() const { return m_ticks; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<HLE::FSDevice> m_fs_device;
|
||||
HLE::FSCore& m_fs_core;
|
||||
std::shared_ptr<HLE::FS::FileSystem> m_fs;
|
||||
std::map<u32, u64> m_entries;
|
||||
u64 m_ticks = 0;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
namespace IOS::HLE
|
||||
{
|
||||
static ES::TMDReader FindTMD(FSDevice& fs, const std::string& tmd_path, Ticks ticks)
|
||||
static ES::TMDReader FindTMD(FSCore& fs, const std::string& tmd_path, Ticks ticks)
|
||||
{
|
||||
const auto fd = fs.Open(PID_KERNEL, PID_KERNEL, tmd_path, FS::Mode::Read, {}, ticks);
|
||||
if (fd.Get() < 0)
|
||||
|
@ -40,13 +40,13 @@ static ES::TMDReader FindTMD(FSDevice& fs, const std::string& tmd_path, Ticks ti
|
|||
|
||||
ES::TMDReader ESCore::FindImportTMD(u64 title_id, Ticks ticks) const
|
||||
{
|
||||
return FindTMD(*m_ios.GetFSDevice(), Common::GetImportTitlePath(title_id) + "/content/title.tmd",
|
||||
return FindTMD(m_ios.GetFSCore(), Common::GetImportTitlePath(title_id) + "/content/title.tmd",
|
||||
ticks);
|
||||
}
|
||||
|
||||
ES::TMDReader ESCore::FindInstalledTMD(u64 title_id, Ticks ticks) const
|
||||
{
|
||||
return FindTMD(*m_ios.GetFSDevice(), Common::GetTMDFileName(title_id), ticks);
|
||||
return FindTMD(m_ios.GetFSCore(), Common::GetTMDFileName(title_id), ticks);
|
||||
}
|
||||
|
||||
ES::TicketReader ESCore::FindSignedTicket(u64 title_id, std::optional<u8> desired_version) const
|
||||
|
@ -228,7 +228,7 @@ u32 ESCore::GetSharedContentsCount() const
|
|||
|
||||
std::vector<std::array<u8, 20>> ESCore::GetSharedContents() const
|
||||
{
|
||||
const ES::SharedContentMap map{m_ios.GetFSDevice()};
|
||||
const ES::SharedContentMap map{m_ios.GetFSCore()};
|
||||
return map.GetHashes();
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ bool ESCore::CreateTitleDirectories(u64 title_id, u16 group_id) const
|
|||
return false;
|
||||
}
|
||||
|
||||
ES::UIDSys uid_sys{m_ios.GetFSDevice()};
|
||||
ES::UIDSys uid_sys{m_ios.GetFSCore()};
|
||||
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
|
||||
if (fs->SetMetadata(0, data_dir, uid, group_id, 0, data_dir_modes) != FS::ResultCode::Success)
|
||||
{
|
||||
|
@ -397,7 +397,7 @@ std::string ESCore::GetContentPath(const u64 title_id, const ES::Content& conten
|
|||
{
|
||||
if (content.IsShared())
|
||||
{
|
||||
ES::SharedContentMap content_map{m_ios.GetFSDevice()};
|
||||
ES::SharedContentMap content_map{m_ios.GetFSCore()};
|
||||
ticks.Add(content_map.GetTicks());
|
||||
return content_map.GetFilenameFromSHA1(content.sha1).value_or("");
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ std::string ESCore::GetContentPath(const u64 title_id, const ES::Content& conten
|
|||
|
||||
s32 ESDevice::WriteSystemFile(const std::string& path, const std::vector<u8>& data, Ticks ticks)
|
||||
{
|
||||
auto& fs = *GetEmulationKernel().GetFSDevice();
|
||||
auto& fs = GetEmulationKernel().GetFSCore();
|
||||
const std::string tmp_path = "/tmp/" + PathToFileName(path);
|
||||
|
||||
auto result = fs.CreateFile(PID_KERNEL, PID_KERNEL, tmp_path, {},
|
||||
|
|
|
@ -29,7 +29,7 @@ s32 ESCore::OpenContent(const ES::TMDReader& tmd, u16 content_index, u32 uid, Ti
|
|||
continue;
|
||||
|
||||
const std::string path = GetContentPath(title_id, content, ticks);
|
||||
auto fd = m_ios.GetFSDevice()->Open(PID_KERNEL, PID_KERNEL, path, FS::Mode::Read, {}, ticks);
|
||||
auto fd = m_ios.GetFSCore().Open(PID_KERNEL, PID_KERNEL, path, FS::Mode::Read, {}, ticks);
|
||||
if (fd.Get() < 0)
|
||||
return fd.Get();
|
||||
|
||||
|
@ -84,7 +84,7 @@ IPCReply ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& r
|
|||
if (!m_core.m_title_context.active)
|
||||
return ES_EINVAL;
|
||||
|
||||
ES::UIDSys uid_map{GetEmulationKernel().GetFSDevice()};
|
||||
ES::UIDSys uid_map{GetEmulationKernel().GetFSCore()};
|
||||
const u32 uid = uid_map.GetOrInsertUIDForTitle(m_core.m_title_context.tmd.GetTitleId());
|
||||
ticks.Add(uid_map.GetTicks());
|
||||
if (caller_uid != 0 && caller_uid != uid)
|
||||
|
@ -105,7 +105,7 @@ s32 ESCore::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid, Ticks ticks)
|
|||
if (!entry.m_opened)
|
||||
return IPC_EINVAL;
|
||||
|
||||
return m_ios.GetFSDevice()->Read(entry.m_fd, buffer, size, {}, ticks);
|
||||
return m_ios.GetFSCore().Read(entry.m_fd, buffer, size, {}, ticks);
|
||||
}
|
||||
|
||||
IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
|
||||
|
@ -137,7 +137,7 @@ s32 ESCore::CloseContent(u32 cfd, u32 uid, Ticks ticks)
|
|||
if (!entry.m_opened)
|
||||
return IPC_EINVAL;
|
||||
|
||||
m_ios.GetFSDevice()->Close(entry.m_fd, ticks);
|
||||
m_ios.GetFSCore().Close(entry.m_fd, ticks);
|
||||
entry = {};
|
||||
INFO_LOG_FMT(IOS_ES, "CloseContent: CFD {}", cfd);
|
||||
return IPC_SUCCESS;
|
||||
|
@ -167,7 +167,7 @@ s32 ESCore::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid, Ticks ticks
|
|||
if (!entry.m_opened)
|
||||
return IPC_EINVAL;
|
||||
|
||||
return m_ios.GetFSDevice()->Seek(entry.m_fd, offset, static_cast<FS::SeekMode>(mode), ticks);
|
||||
return m_ios.GetFSCore().Seek(entry.m_fd, offset, static_cast<FS::SeekMode>(mode), ticks);
|
||||
}
|
||||
|
||||
IPCReply ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
|
||||
|
|
|
@ -408,7 +408,7 @@ ReturnCode ESCore::ImportContentEnd(Context& context, u32 content_fd)
|
|||
std::string content_path;
|
||||
if (content_info.IsShared())
|
||||
{
|
||||
ES::SharedContentMap shared_content{m_ios.GetFSDevice()};
|
||||
ES::SharedContentMap shared_content{m_ios.GetFSCore()};
|
||||
content_path = shared_content.AddSharedContent(content_info.sha1);
|
||||
}
|
||||
else
|
||||
|
@ -458,7 +458,7 @@ static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd)
|
|||
{
|
||||
const u64 title_id = tmd.GetTitleId();
|
||||
const std::vector<ES::Content> contents = tmd.GetContents();
|
||||
const ES::SharedContentMap shared_content_map{ios.GetFSDevice()};
|
||||
const ES::SharedContentMap shared_content_map{ios.GetFSCore()};
|
||||
return std::all_of(contents.cbegin(), contents.cend(), [&](const ES::Content& content) {
|
||||
if (content.IsOptional())
|
||||
return true;
|
||||
|
@ -865,7 +865,7 @@ IPCReply ESDevice::ExportTitleDone(Context& context, const IOCtlVRequest& reques
|
|||
|
||||
ReturnCode ESCore::DeleteSharedContent(const std::array<u8, 20>& sha1) const
|
||||
{
|
||||
ES::SharedContentMap map{m_ios.GetFSDevice()};
|
||||
ES::SharedContentMap map{m_ios.GetFSCore()};
|
||||
const auto content_path = map.GetFilenameFromSHA1(sha1);
|
||||
if (!content_path)
|
||||
return ES_EINVAL;
|
||||
|
|
|
@ -83,7 +83,7 @@ constexpr SystemTimers::TimeBaseTick GetFreeClusterCheckTbTicks()
|
|||
|
||||
constexpr size_t CLUSTER_DATA_SIZE = 0x4000;
|
||||
|
||||
FSDevice::FSDevice(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
|
||||
FSCore::FSCore(Kernel& ios) : m_ios(ios)
|
||||
{
|
||||
if (ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, "/tmp") == ResultCode::Success)
|
||||
{
|
||||
|
@ -92,14 +92,23 @@ FSDevice::FSDevice(Kernel& ios, const std::string& device_name) : Device(ios, de
|
|||
}
|
||||
}
|
||||
|
||||
FSCore::~FSCore() = default;
|
||||
|
||||
FSDevice::FSDevice(EmulationKernel& ios, FSCore& core, const std::string& device_name)
|
||||
: EmulationDevice(ios, device_name), m_core(core)
|
||||
{
|
||||
}
|
||||
|
||||
FSDevice::~FSDevice() = default;
|
||||
|
||||
void FSDevice::DoState(PointerWrap& p)
|
||||
{
|
||||
Device::DoState(p);
|
||||
p.Do(m_dirty_cache);
|
||||
p.Do(m_cache_chain_index);
|
||||
p.Do(m_cache_fd);
|
||||
p.Do(m_next_fd);
|
||||
p.Do(m_fd_map);
|
||||
p.Do(m_core.m_dirty_cache);
|
||||
p.Do(m_core.m_cache_chain_index);
|
||||
p.Do(m_core.m_cache_fd);
|
||||
p.Do(m_core.m_next_fd);
|
||||
p.Do(m_core.m_fd_map);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
|
@ -161,14 +170,15 @@ static IPCReply GetReplyForSuperblockOperation(int ios_version, ResultCode resul
|
|||
std::optional<IPCReply> FSDevice::Open(const OpenRequest& request)
|
||||
{
|
||||
return MakeIPCReply([&](Ticks t) {
|
||||
return Open(request.uid, request.gid, request.path, static_cast<Mode>(request.flags & 3),
|
||||
request.fd, t)
|
||||
return m_core
|
||||
.Open(request.uid, request.gid, request.path, static_cast<Mode>(request.flags & 3),
|
||||
request.fd, t)
|
||||
.Release();
|
||||
});
|
||||
}
|
||||
|
||||
FSDevice::ScopedFd FSDevice::Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode,
|
||||
std::optional<u32> ipc_fd, Ticks ticks)
|
||||
FSCore::ScopedFd FSCore::Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode,
|
||||
std::optional<u32> ipc_fd, Ticks ticks)
|
||||
{
|
||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||
|
||||
|
@ -200,10 +210,10 @@ FSDevice::ScopedFd FSDevice::Open(FS::Uid uid, FS::Gid gid, const std::string& p
|
|||
|
||||
std::optional<IPCReply> FSDevice::Close(u32 fd)
|
||||
{
|
||||
return MakeIPCReply([&](Ticks t) { return Close(static_cast<u64>(fd), t); });
|
||||
return MakeIPCReply([&](Ticks t) { return m_core.Close(static_cast<u64>(fd), t); });
|
||||
}
|
||||
|
||||
s32 FSDevice::Close(u64 fd, Ticks ticks)
|
||||
s32 FSCore::Close(u64 fd, Ticks ticks)
|
||||
{
|
||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||
|
||||
|
@ -232,7 +242,7 @@ s32 FSDevice::Close(u64 fd, Ticks ticks)
|
|||
return IPC_SUCCESS;
|
||||
}
|
||||
|
||||
u64 FSDevice::SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size)
|
||||
u64 FSCore::SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size)
|
||||
{
|
||||
if (HasCacheForFile(fd, offset))
|
||||
return 0;
|
||||
|
@ -246,7 +256,7 @@ u64 FSDevice::SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size)
|
|||
return ticks;
|
||||
}
|
||||
|
||||
u64 FSDevice::SimulateFlushFileCache()
|
||||
u64 FSCore::SimulateFlushFileCache()
|
||||
{
|
||||
if (!m_cache_fd.has_value() || !m_dirty_cache)
|
||||
return 0;
|
||||
|
@ -256,8 +266,8 @@ u64 FSDevice::SimulateFlushFileCache()
|
|||
}
|
||||
|
||||
// Simulate parts of the FS read/write logic to estimate ticks for file operations correctly.
|
||||
u64 FSDevice::EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command,
|
||||
u32 size)
|
||||
u64 FSCore::EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command,
|
||||
u32 size)
|
||||
{
|
||||
u64 ticks = 0;
|
||||
|
||||
|
@ -304,7 +314,7 @@ u64 FSDevice::EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommand
|
|||
return ticks;
|
||||
}
|
||||
|
||||
bool FSDevice::HasCacheForFile(u64 fd, u32 offset) const
|
||||
bool FSCore::HasCacheForFile(u64 fd, u32 offset) const
|
||||
{
|
||||
const u16 chain_index = static_cast<u16>(offset / CLUSTER_DATA_SIZE);
|
||||
return m_cache_fd == fd && m_cache_chain_index == chain_index;
|
||||
|
@ -313,13 +323,14 @@ bool FSDevice::HasCacheForFile(u64 fd, u32 offset) const
|
|||
std::optional<IPCReply> FSDevice::Read(const ReadWriteRequest& request)
|
||||
{
|
||||
return MakeIPCReply([&](Ticks t) {
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& system = GetSystem();
|
||||
auto& memory = system.GetMemory();
|
||||
return Read(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t);
|
||||
return m_core.Read(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer,
|
||||
t);
|
||||
});
|
||||
}
|
||||
|
||||
s32 FSDevice::Read(u64 fd, u8* data, u32 size, std::optional<u32> ipc_buffer_addr, Ticks ticks)
|
||||
s32 FSCore::Read(u64 fd, u8* data, u32 size, std::optional<u32> ipc_buffer_addr, Ticks ticks)
|
||||
{
|
||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||
|
||||
|
@ -343,14 +354,14 @@ s32 FSDevice::Read(u64 fd, u8* data, u32 size, std::optional<u32> ipc_buffer_add
|
|||
std::optional<IPCReply> FSDevice::Write(const ReadWriteRequest& request)
|
||||
{
|
||||
return MakeIPCReply([&](Ticks t) {
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& system = GetSystem();
|
||||
auto& memory = system.GetMemory();
|
||||
return Write(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t);
|
||||
return m_core.Write(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer,
|
||||
t);
|
||||
});
|
||||
}
|
||||
|
||||
s32 FSDevice::Write(u64 fd, const u8* data, u32 size, std::optional<u32> ipc_buffer_addr,
|
||||
Ticks ticks)
|
||||
s32 FSCore::Write(u64 fd, const u8* data, u32 size, std::optional<u32> ipc_buffer_addr, Ticks ticks)
|
||||
{
|
||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||
|
||||
|
@ -374,11 +385,11 @@ s32 FSDevice::Write(u64 fd, const u8* data, u32 size, std::optional<u32> ipc_buf
|
|||
std::optional<IPCReply> FSDevice::Seek(const SeekRequest& request)
|
||||
{
|
||||
return MakeIPCReply([&](Ticks t) {
|
||||
return Seek(request.fd, request.offset, HLE::FS::SeekMode(request.mode), t);
|
||||
return m_core.Seek(request.fd, request.offset, HLE::FS::SeekMode(request.mode), t);
|
||||
});
|
||||
}
|
||||
|
||||
s32 FSDevice::Seek(u64 fd, u32 offset, FS::SeekMode mode, Ticks ticks)
|
||||
s32 FSCore::Seek(u64 fd, u32 offset, FS::SeekMode mode, Ticks ticks)
|
||||
{
|
||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||
|
||||
|
@ -422,14 +433,11 @@ struct ISFSFileStats
|
|||
#pragma pack(pop)
|
||||
|
||||
template <typename T>
|
||||
static Result<T> GetParams(const IOCtlRequest& request)
|
||||
static Result<T> GetParams(Memory::MemoryManager& memory, const IOCtlRequest& request)
|
||||
{
|
||||
if (request.buffer_in_size < sizeof(T))
|
||||
return ResultCode::Invalid;
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
T params;
|
||||
memory.CopyFromEmu(¶ms, request.buffer_in, sizeof(params));
|
||||
return params;
|
||||
|
@ -437,8 +445,8 @@ static Result<T> GetParams(const IOCtlRequest& request)
|
|||
|
||||
std::optional<IPCReply> FSDevice::IOCtl(const IOCtlRequest& request)
|
||||
{
|
||||
const auto it = m_fd_map.find(request.fd);
|
||||
if (it == m_fd_map.end())
|
||||
const auto it = m_core.m_fd_map.find(request.fd);
|
||||
if (it == m_core.m_fd_map.end())
|
||||
return IPCReply(ConvertResult(ResultCode::Invalid));
|
||||
|
||||
switch (request.request)
|
||||
|
@ -472,8 +480,8 @@ std::optional<IPCReply> FSDevice::IOCtl(const IOCtlRequest& request)
|
|||
|
||||
std::optional<IPCReply> FSDevice::IOCtlV(const IOCtlVRequest& request)
|
||||
{
|
||||
const auto it = m_fd_map.find(request.fd);
|
||||
if (it == m_fd_map.end())
|
||||
const auto it = m_core.m_fd_map.find(request.fd);
|
||||
if (it == m_core.m_fd_map.end())
|
||||
return IPCReply(ConvertResult(ResultCode::Invalid));
|
||||
|
||||
switch (request.request)
|
||||
|
@ -506,7 +514,7 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
|
|||
if (!stats)
|
||||
return IPCReply(ConvertResult(stats.Error()));
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& system = GetSystem();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
ISFSNandStats out;
|
||||
|
@ -523,7 +531,7 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
|
|||
|
||||
IPCReply FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequest& request)
|
||||
{
|
||||
const auto params = GetParams<ISFSParams>(request);
|
||||
const auto params = GetParams<ISFSParams>(GetSystem().GetMemory(), request);
|
||||
if (!params)
|
||||
return GetFSReply(ConvertResult(params.Error()));
|
||||
|
||||
|
@ -541,7 +549,7 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ
|
|||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||
}
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& system = GetSystem();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
u32 file_list_address, file_count_address, max_count;
|
||||
|
@ -592,7 +600,7 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ
|
|||
|
||||
IPCReply FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest& request)
|
||||
{
|
||||
const auto params = GetParams<ISFSParams>(request);
|
||||
const auto params = GetParams<ISFSParams>(GetSystem().GetMemory(), request);
|
||||
if (!params)
|
||||
return GetFSReply(ConvertResult(params.Error()));
|
||||
|
||||
|
@ -607,7 +615,7 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques
|
|||
if (request.buffer_in_size < 64 || request.buffer_out_size < sizeof(ISFSParams))
|
||||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& system = GetSystem();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
const std::string path = memory.GetString(request.buffer_in, 64);
|
||||
|
@ -629,7 +637,7 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques
|
|||
return GetFSReply(IPC_SUCCESS, ticks);
|
||||
}
|
||||
|
||||
FS::ResultCode FSDevice::DeleteFile(FS::Uid uid, FS::Gid gid, const std::string& path, Ticks ticks)
|
||||
FS::ResultCode FSCore::DeleteFile(FS::Uid uid, FS::Gid gid, const std::string& path, Ticks ticks)
|
||||
{
|
||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||
|
||||
|
@ -644,16 +652,17 @@ IPCReply FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest& request)
|
|||
if (request.buffer_in_size < 64)
|
||||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& system = GetSystem();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
const std::string path = memory.GetString(request.buffer_in, 64);
|
||||
return MakeIPCReply(
|
||||
[&](Ticks ticks) { return ConvertResult(DeleteFile(handle.uid, handle.gid, path, ticks)); });
|
||||
return MakeIPCReply([&](Ticks ticks) {
|
||||
return ConvertResult(m_core.DeleteFile(handle.uid, handle.gid, path, ticks));
|
||||
});
|
||||
}
|
||||
|
||||
FS::ResultCode FSDevice::RenameFile(FS::Uid uid, FS::Gid gid, const std::string& old_path,
|
||||
const std::string& new_path, Ticks ticks)
|
||||
FS::ResultCode FSCore::RenameFile(FS::Uid uid, FS::Gid gid, const std::string& old_path,
|
||||
const std::string& new_path, Ticks ticks)
|
||||
{
|
||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||
|
||||
|
@ -668,18 +677,18 @@ IPCReply FSDevice::RenameFile(const Handle& handle, const IOCtlRequest& request)
|
|||
if (request.buffer_in_size < 64 * 2)
|
||||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& system = GetSystem();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
const std::string old_path = memory.GetString(request.buffer_in, 64);
|
||||
const std::string new_path = memory.GetString(request.buffer_in + 64, 64);
|
||||
return MakeIPCReply([&](Ticks ticks) {
|
||||
return ConvertResult(RenameFile(handle.uid, handle.gid, old_path, new_path, ticks));
|
||||
return ConvertResult(m_core.RenameFile(handle.uid, handle.gid, old_path, new_path, ticks));
|
||||
});
|
||||
}
|
||||
|
||||
FS::ResultCode FSDevice::CreateFile(FS::Uid uid, FS::Gid gid, const std::string& path,
|
||||
FS::FileAttribute attribute, FS::Modes modes, Ticks ticks)
|
||||
FS::ResultCode FSCore::CreateFile(FS::Uid uid, FS::Gid gid, const std::string& path,
|
||||
FS::FileAttribute attribute, FS::Modes modes, Ticks ticks)
|
||||
{
|
||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||
|
||||
|
@ -691,18 +700,18 @@ FS::ResultCode FSDevice::CreateFile(FS::Uid uid, FS::Gid gid, const std::string&
|
|||
|
||||
IPCReply FSDevice::CreateFile(const Handle& handle, const IOCtlRequest& request)
|
||||
{
|
||||
const auto params = GetParams<ISFSParams>(request);
|
||||
const auto params = GetParams<ISFSParams>(GetSystem().GetMemory(), request);
|
||||
if (!params)
|
||||
return GetFSReply(ConvertResult(params.Error()));
|
||||
return MakeIPCReply([&](Ticks ticks) {
|
||||
return ConvertResult(
|
||||
CreateFile(handle.uid, handle.gid, params->path, params->attribute, params->modes));
|
||||
m_core.CreateFile(handle.uid, handle.gid, params->path, params->attribute, params->modes));
|
||||
});
|
||||
}
|
||||
|
||||
IPCReply FSDevice::SetFileVersionControl(const Handle& handle, const IOCtlRequest& request)
|
||||
{
|
||||
const auto params = GetParams<ISFSParams>(request);
|
||||
const auto params = GetParams<ISFSParams>(GetSystem().GetMemory(), request);
|
||||
if (!params)
|
||||
return GetFSReply(ConvertResult(params.Error()));
|
||||
|
||||
|
@ -718,11 +727,11 @@ IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& reques
|
|||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||
|
||||
return MakeIPCReply([&](Ticks ticks) {
|
||||
const Result<FileStatus> status = GetFileStatus(request.fd, ticks);
|
||||
const Result<FileStatus> status = m_core.GetFileStatus(request.fd, ticks);
|
||||
if (!status)
|
||||
return ConvertResult(status.Error());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& system = GetSystem();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
ISFSFileStats out;
|
||||
|
@ -733,7 +742,7 @@ IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& reques
|
|||
});
|
||||
}
|
||||
|
||||
FS::Result<FS::FileStatus> FSDevice::GetFileStatus(u64 fd, Ticks ticks)
|
||||
FS::Result<FS::FileStatus> FSCore::GetFileStatus(u64 fd, Ticks ticks)
|
||||
{
|
||||
ticks.Add(IPC_OVERHEAD_TICKS);
|
||||
const auto& handle = m_fd_map[fd];
|
||||
|
@ -753,7 +762,7 @@ IPCReply FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request)
|
|||
return GetFSReply(ConvertResult(ResultCode::Invalid));
|
||||
}
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& system = GetSystem();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
const std::string directory = memory.GetString(request.in_vectors[0].address, 64);
|
||||
|
|
|
@ -20,13 +20,22 @@ namespace IOS::HLE
|
|||
{
|
||||
constexpr FS::Fd INVALID_FD = 0xffffffff;
|
||||
|
||||
class FSDevice : public Device
|
||||
class FSDevice;
|
||||
|
||||
class FSCore final
|
||||
{
|
||||
public:
|
||||
explicit FSCore(Kernel& ios);
|
||||
FSCore(const FSCore& other) = delete;
|
||||
FSCore(FSCore&& other) = delete;
|
||||
FSCore& operator=(const FSCore& other) = delete;
|
||||
FSCore& operator=(FSCore&& other) = delete;
|
||||
~FSCore();
|
||||
|
||||
class ScopedFd
|
||||
{
|
||||
public:
|
||||
ScopedFd(FSDevice* fs, s64 fd, Ticks tick_tracker = {})
|
||||
ScopedFd(FSCore* fs, s64 fd, Ticks tick_tracker = {})
|
||||
: m_fs{fs}, m_fd{fd}, m_tick_tracker{tick_tracker}
|
||||
{
|
||||
}
|
||||
|
@ -46,13 +55,11 @@ public:
|
|||
s64 Release() { return std::exchange(m_fd, -1); }
|
||||
|
||||
private:
|
||||
FSDevice* m_fs{};
|
||||
FSCore* m_fs{};
|
||||
s64 m_fd = -1;
|
||||
Ticks m_tick_tracker{};
|
||||
};
|
||||
|
||||
FSDevice(Kernel& ios, const std::string& device_name);
|
||||
|
||||
// These are the equivalent of the IPC command handlers so IPC overhead is included
|
||||
// in timing calculations.
|
||||
ScopedFd Open(FS::Uid uid, FS::Gid gid, const std::string& path, FS::Mode mode,
|
||||
|
@ -78,16 +85,6 @@ public:
|
|||
|
||||
std::shared_ptr<FS::FileSystem> GetFS() const { return m_ios.GetFS(); }
|
||||
|
||||
void DoState(PointerWrap& p) override;
|
||||
|
||||
std::optional<IPCReply> Open(const OpenRequest& request) override;
|
||||
std::optional<IPCReply> Close(u32 fd) override;
|
||||
std::optional<IPCReply> Read(const ReadWriteRequest& request) override;
|
||||
std::optional<IPCReply> Write(const ReadWriteRequest& request) override;
|
||||
std::optional<IPCReply> Seek(const SeekRequest& request) override;
|
||||
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
|
||||
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
|
||||
|
||||
private:
|
||||
struct Handle
|
||||
{
|
||||
|
@ -99,6 +96,40 @@ private:
|
|||
bool superblock_flush_needed = false;
|
||||
};
|
||||
|
||||
u64 EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command, u32 size);
|
||||
u64 SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size);
|
||||
u64 SimulateFlushFileCache();
|
||||
bool HasCacheForFile(u64 fd, u32 offset) const;
|
||||
|
||||
Kernel& m_ios;
|
||||
|
||||
bool m_dirty_cache = false;
|
||||
u16 m_cache_chain_index = 0;
|
||||
std::optional<u64> m_cache_fd;
|
||||
// The first 0x18 IDs are reserved for the PPC.
|
||||
u64 m_next_fd = 0x18;
|
||||
std::map<u64, Handle> m_fd_map;
|
||||
|
||||
friend class FSDevice;
|
||||
};
|
||||
|
||||
class FSDevice final : public EmulationDevice
|
||||
{
|
||||
public:
|
||||
FSDevice(EmulationKernel& ios, FSCore& core, const std::string& device_name);
|
||||
~FSDevice();
|
||||
|
||||
void DoState(PointerWrap& p) override;
|
||||
|
||||
std::optional<IPCReply> Open(const OpenRequest& request) override;
|
||||
std::optional<IPCReply> Close(u32 fd) override;
|
||||
std::optional<IPCReply> Read(const ReadWriteRequest& request) override;
|
||||
std::optional<IPCReply> Write(const ReadWriteRequest& request) override;
|
||||
std::optional<IPCReply> Seek(const SeekRequest& request) override;
|
||||
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
|
||||
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
ISFS_IOCTL_FORMAT = 1,
|
||||
|
@ -116,6 +147,8 @@ private:
|
|||
ISFS_IOCTL_SHUTDOWN = 13,
|
||||
};
|
||||
|
||||
using Handle = FSCore::Handle;
|
||||
|
||||
IPCReply Format(const Handle& handle, const IOCtlRequest& request);
|
||||
IPCReply GetStats(const Handle& handle, const IOCtlRequest& request);
|
||||
IPCReply CreateDirectory(const Handle& handle, const IOCtlRequest& request);
|
||||
|
@ -130,16 +163,6 @@ private:
|
|||
IPCReply GetUsage(const Handle& handle, const IOCtlVRequest& request);
|
||||
IPCReply Shutdown(const Handle& handle, const IOCtlRequest& request);
|
||||
|
||||
u64 EstimateTicksForReadWrite(const Handle& handle, u64 fd, IPCCommandType command, u32 size);
|
||||
u64 SimulatePopulateFileCache(u64 fd, u32 offset, u32 file_size);
|
||||
u64 SimulateFlushFileCache();
|
||||
bool HasCacheForFile(u64 fd, u32 offset) const;
|
||||
|
||||
bool m_dirty_cache = false;
|
||||
u16 m_cache_chain_index = 0;
|
||||
std::optional<u64> m_cache_fd;
|
||||
// The first 0x18 IDs are reserved for the PPC.
|
||||
u64 m_next_fd = 0x18;
|
||||
std::map<u64, Handle> m_fd_map;
|
||||
FSCore& m_core;
|
||||
};
|
||||
} // namespace IOS::HLE
|
||||
|
|
|
@ -303,7 +303,7 @@ Kernel::Kernel(IOSC::ConsoleType console_type) : m_iosc(console_type)
|
|||
m_fs = FS::MakeFileSystem(IOS::HLE::FS::Location::Session, Core::GetActiveNandRedirects());
|
||||
ASSERT(m_fs);
|
||||
|
||||
AddDevice(std::make_unique<FSDevice>(*this, "/dev/fs"));
|
||||
m_fs_core = std::make_unique<FSCore>(*this);
|
||||
m_es_core = std::make_unique<ESCore>(*this);
|
||||
}
|
||||
|
||||
|
@ -340,7 +340,8 @@ EmulationKernel::EmulationKernel(Core::System& system, u64 title_id)
|
|||
m_fs = FS::MakeFileSystem(IOS::HLE::FS::Location::Session, Core::GetActiveNandRedirects());
|
||||
ASSERT(m_fs);
|
||||
|
||||
AddDevice(std::make_unique<FSDevice>(*this, "/dev/fs"));
|
||||
m_fs_core = std::make_unique<FSCore>(*this);
|
||||
AddDevice(std::make_unique<FSDevice>(*this, *m_fs_core, "/dev/fs"));
|
||||
m_es_core = std::make_unique<ESCore>(*this);
|
||||
AddDevice(std::make_unique<ESDevice>(*this, *m_es_core, "/dev/es"));
|
||||
|
||||
|
@ -365,7 +366,12 @@ std::shared_ptr<FS::FileSystem> Kernel::GetFS()
|
|||
return m_fs;
|
||||
}
|
||||
|
||||
std::shared_ptr<FSDevice> Kernel::GetFSDevice()
|
||||
FSCore& Kernel::GetFSCore()
|
||||
{
|
||||
return *m_fs_core;
|
||||
}
|
||||
|
||||
std::shared_ptr<FSDevice> EmulationKernel::GetFSDevice()
|
||||
{
|
||||
return std::static_pointer_cast<FSDevice>(m_device_map.at("/dev/fs"));
|
||||
}
|
||||
|
@ -407,19 +413,19 @@ u16 Kernel::GetGidForPPC() const
|
|||
return m_ppc_gid;
|
||||
}
|
||||
|
||||
static std::vector<u8> ReadBootContent(FSDevice* fs, const std::string& path, size_t max_size,
|
||||
static std::vector<u8> ReadBootContent(FSCore& fs, const std::string& path, size_t max_size,
|
||||
Ticks ticks = {})
|
||||
{
|
||||
const auto fd = fs->Open(0, 0, path, FS::Mode::Read, {}, ticks);
|
||||
const auto fd = fs.Open(0, 0, path, FS::Mode::Read, {}, ticks);
|
||||
if (fd.Get() < 0)
|
||||
return {};
|
||||
|
||||
const size_t file_size = fs->GetFileStatus(fd.Get(), ticks)->size;
|
||||
const size_t file_size = fs.GetFileStatus(fd.Get(), ticks)->size;
|
||||
if (max_size != 0 && file_size > max_size)
|
||||
return {};
|
||||
|
||||
std::vector<u8> buffer(file_size);
|
||||
if (!fs->Read(fd.Get(), buffer.data(), buffer.size(), ticks))
|
||||
if (!fs.Read(fd.Get(), buffer.data(), buffer.size(), ticks))
|
||||
return {};
|
||||
return buffer;
|
||||
}
|
||||
|
@ -431,7 +437,7 @@ bool Kernel::BootstrapPPC(Core::System& system, const std::string& boot_content_
|
|||
// Seeking and processing overhead is ignored as most time is spent reading from the NAND.
|
||||
u64 ticks = 0;
|
||||
|
||||
const DolReader dol{ReadBootContent(GetFSDevice().get(), boot_content_path, 0, &ticks)};
|
||||
const DolReader dol{ReadBootContent(GetFSCore(), boot_content_path, 0, &ticks)};
|
||||
|
||||
if (!dol.IsValid())
|
||||
return false;
|
||||
|
@ -512,7 +518,7 @@ bool Kernel::BootIOS(Core::System& system, const u64 ios_title_id, HangPPC hang_
|
|||
// Load the ARM binary to memory (if possible).
|
||||
// Because we do not actually emulate the Starlet, only load the sections that are in MEM1.
|
||||
|
||||
ARMBinary binary{ReadBootContent(GetFSDevice().get(), boot_content_path, 0xB00000)};
|
||||
ARMBinary binary{ReadBootContent(GetFSCore(), boot_content_path, 0xB00000)};
|
||||
if (!binary.IsValid())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ class FileSystem;
|
|||
class Device;
|
||||
class ESCore;
|
||||
class ESDevice;
|
||||
class FSCore;
|
||||
class FSDevice;
|
||||
class WiiSockMan;
|
||||
|
||||
|
@ -123,7 +124,7 @@ public:
|
|||
// These are *always* part of the IOS kernel and always available.
|
||||
// They are also the only available resource managers even before loading any module.
|
||||
std::shared_ptr<FS::FileSystem> GetFS();
|
||||
std::shared_ptr<FSDevice> GetFSDevice();
|
||||
FSCore& GetFSCore();
|
||||
ESCore& GetESCore();
|
||||
|
||||
void SetUidForPPC(u32 uid);
|
||||
|
@ -145,6 +146,7 @@ protected:
|
|||
void AddDevice(std::unique_ptr<Device> device);
|
||||
std::shared_ptr<Device> GetDeviceByName(std::string_view device_name);
|
||||
|
||||
std::unique_ptr<FSCore> m_fs_core;
|
||||
std::unique_ptr<ESCore> m_es_core;
|
||||
|
||||
bool m_is_responsible_for_nand_root = false;
|
||||
|
@ -180,6 +182,7 @@ public:
|
|||
// This only works for devices which are part of the device map.
|
||||
std::shared_ptr<Device> GetDeviceByName(std::string_view device_name);
|
||||
|
||||
std::shared_ptr<FSDevice> GetFSDevice();
|
||||
std::shared_ptr<ESDevice> GetESDevice();
|
||||
|
||||
void DoState(PointerWrap& p);
|
||||
|
|
Loading…
Reference in New Issue