SysConf: Migrate to new filesystem interface
It was discovered that some titles rely on filesystem metadata to work properly. Currently, in master they either simply won't find their save files (for example Bolt) or will complain about the Wii system memory being corrupted (on first use or every time depending on the title). In order to even be able to keep track of file metadata, we first need to eliminate all direct accesses to the NAND and make all kinds of operations go through the filesystem code added in PR 6421. This commit starts the migration process by making SysConf use the new FS interface.
This commit is contained in:
parent
3744a6d3f5
commit
0856d4a68a
|
@ -14,6 +14,7 @@
|
|||
#include "Common/FileUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/Swap.h"
|
||||
#include "Core/IOS/FS/FileSystem.h"
|
||||
|
||||
constexpr size_t SYSCONF_SIZE = 0x4000;
|
||||
|
||||
|
@ -35,9 +36,8 @@ static size_t GetNonArrayEntrySize(SysConf::Entry::Type type)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
SysConf::SysConf(const Common::FromWhichRoot root_type)
|
||||
SysConf::SysConf(std::shared_ptr<IOS::HLE::FS::FileSystem> fs) : m_fs{fs}
|
||||
{
|
||||
m_file_name = Common::RootUserPath(root_type) + DIR_SEP WII_SYSCONF_DIR DIR_SEP WII_SYSCONF;
|
||||
Load();
|
||||
}
|
||||
|
||||
|
@ -55,39 +55,40 @@ void SysConf::Load()
|
|||
{
|
||||
Clear();
|
||||
|
||||
if (File::GetSize(m_file_name) != SYSCONF_SIZE || !LoadFromFile(m_file_name))
|
||||
const auto file = m_fs->OpenFile(IOS::HLE::FS::Uid{0}, IOS::HLE::FS::Gid{0},
|
||||
"/shared2/sys/SYSCONF", IOS::HLE::FS::Mode::Read);
|
||||
if (!file || file->GetStatus()->size != SYSCONF_SIZE || !LoadFromFile(*file))
|
||||
{
|
||||
WARN_LOG(CORE, "No valid SYSCONF detected. Creating a new one.");
|
||||
InsertDefaultEntries();
|
||||
}
|
||||
}
|
||||
|
||||
bool SysConf::LoadFromFile(const std::string& file_name)
|
||||
bool SysConf::LoadFromFile(const IOS::HLE::FS::FileHandle& file)
|
||||
{
|
||||
File::IOFile file(file_name, "rb");
|
||||
file.Seek(4, SEEK_SET);
|
||||
file.Seek(4, IOS::HLE::FS::SeekMode::Set);
|
||||
u16 number_of_entries;
|
||||
file.ReadBytes(&number_of_entries, sizeof(number_of_entries));
|
||||
file.Read(&number_of_entries, 1);
|
||||
number_of_entries = Common::swap16(number_of_entries);
|
||||
|
||||
std::vector<u16> offsets(number_of_entries);
|
||||
for (u16& offset : offsets)
|
||||
{
|
||||
file.ReadBytes(&offset, sizeof(offset));
|
||||
file.Read(&offset, 1);
|
||||
offset = Common::swap16(offset);
|
||||
}
|
||||
|
||||
for (const u16 offset : offsets)
|
||||
{
|
||||
file.Seek(offset, SEEK_SET);
|
||||
file.Seek(offset, IOS::HLE::FS::SeekMode::Set);
|
||||
|
||||
// Metadata
|
||||
u8 description = 0;
|
||||
file.ReadBytes(&description, sizeof(description));
|
||||
file.Read(&description, 1);
|
||||
const Entry::Type type = static_cast<Entry::Type>((description & 0xe0) >> 5);
|
||||
const u8 name_length = (description & 0x1f) + 1;
|
||||
std::string name(name_length, '\0');
|
||||
file.ReadBytes(&name[0], name.size());
|
||||
file.Read(&name[0], name.size());
|
||||
|
||||
// Data
|
||||
std::vector<u8> data;
|
||||
|
@ -96,7 +97,7 @@ bool SysConf::LoadFromFile(const std::string& file_name)
|
|||
case Entry::Type::BigArray:
|
||||
{
|
||||
u16 data_length = 0;
|
||||
file.ReadBytes(&data_length, sizeof(data_length));
|
||||
file.Read(&data_length, 1);
|
||||
// The stored u16 is length - 1, not length.
|
||||
data.resize(Common::swap16(data_length) + 1);
|
||||
break;
|
||||
|
@ -104,7 +105,7 @@ bool SysConf::LoadFromFile(const std::string& file_name)
|
|||
case Entry::Type::SmallArray:
|
||||
{
|
||||
u8 data_length = 0;
|
||||
file.ReadBytes(&data_length, sizeof(data_length));
|
||||
file.Read(&data_length, 1);
|
||||
data.resize(data_length + 1);
|
||||
break;
|
||||
}
|
||||
|
@ -121,7 +122,7 @@ bool SysConf::LoadFromFile(const std::string& file_name)
|
|||
return false;
|
||||
}
|
||||
|
||||
file.ReadBytes(data.data(), data.size());
|
||||
file.Read(data.data(), data.size());
|
||||
AddEntry({type, name, std::move(data)});
|
||||
}
|
||||
return true;
|
||||
|
@ -194,14 +195,19 @@ bool SysConf::Save() const
|
|||
std::copy(footer.cbegin(), footer.cend(), buffer.end() - footer.size());
|
||||
|
||||
// Write the new data.
|
||||
const std::string temp_file = m_file_name + ".tmp";
|
||||
File::CreateFullPath(temp_file);
|
||||
const std::string temp_file = "/tmp/SYSCONF";
|
||||
constexpr u32 SYSMENU_UID = 0x1000;
|
||||
constexpr u16 SYSMENU_GID = 1;
|
||||
constexpr auto rw_mode = IOS::HLE::FS::Mode::ReadWrite;
|
||||
{
|
||||
File::IOFile file(temp_file, "wb");
|
||||
if (!file.WriteBytes(buffer.data(), buffer.size()))
|
||||
m_fs->CreateFile(SYSMENU_UID, SYSMENU_GID, temp_file, 0, rw_mode, rw_mode, rw_mode);
|
||||
auto file = m_fs->OpenFile(SYSMENU_UID, SYSMENU_GID, temp_file, IOS::HLE::FS::Mode::Write);
|
||||
if (!file || !file->Write(buffer.data(), buffer.size()))
|
||||
return false;
|
||||
}
|
||||
return File::RenameSync(temp_file, m_file_name);
|
||||
m_fs->CreateDirectory(SYSMENU_UID, SYSMENU_GID, "/shared2/sys", 0, rw_mode, rw_mode, rw_mode);
|
||||
const auto result = m_fs->Rename(SYSMENU_UID, SYSMENU_GID, temp_file, "/shared2/sys/SYSCONF");
|
||||
return result == IOS::HLE::FS::ResultCode::Success;
|
||||
}
|
||||
|
||||
SysConf::Entry::Entry(Type type_, const std::string& name_) : type(type_), name(name_)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -14,10 +15,16 @@
|
|||
#include "Common/CommonTypes.h"
|
||||
#include "Common/NandPaths.h"
|
||||
|
||||
namespace IOS::HLE::FS
|
||||
{
|
||||
class FileHandle;
|
||||
class FileSystem;
|
||||
}
|
||||
|
||||
class SysConf final
|
||||
{
|
||||
public:
|
||||
explicit SysConf(Common::FromWhichRoot root_type);
|
||||
explicit SysConf(std::shared_ptr<IOS::HLE::FS::FileSystem> fs);
|
||||
~SysConf();
|
||||
|
||||
void Clear();
|
||||
|
@ -85,8 +92,8 @@ public:
|
|||
|
||||
private:
|
||||
void InsertDefaultEntries();
|
||||
bool LoadFromFile(const std::string& file_name);
|
||||
bool LoadFromFile(const IOS::HLE::FS::FileHandle& file);
|
||||
|
||||
std::string m_file_name;
|
||||
std::vector<Entry> m_entries;
|
||||
std::shared_ptr<IOS::HLE::FS::FileSystem> m_fs;
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "Core/Config/SYSCONFSettings.h"
|
||||
#include "Core/ConfigLoaders/IsSettingSaveable.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/IOS/IOS.h"
|
||||
#include "Core/IOS/USB/Bluetooth/BTBase.h"
|
||||
|
||||
namespace ConfigLoaders
|
||||
|
@ -31,7 +32,8 @@ void SaveToSYSCONF(Config::LayerType layer)
|
|||
if (Core::IsRunning())
|
||||
return;
|
||||
|
||||
SysConf sysconf{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
|
||||
IOS::HLE::Kernel ios;
|
||||
SysConf sysconf{ios.GetFS()};
|
||||
|
||||
for (const Config::SYSCONFSetting& setting : Config::SYSCONF_SETTINGS)
|
||||
{
|
||||
|
@ -154,7 +156,8 @@ private:
|
|||
if (Core::IsRunning())
|
||||
return;
|
||||
|
||||
SysConf sysconf{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
|
||||
IOS::HLE::Kernel ios;
|
||||
SysConf sysconf{ios.GetFS()};
|
||||
for (const Config::SYSCONFSetting& setting : Config::SYSCONF_SETTINGS)
|
||||
{
|
||||
std::visit(
|
||||
|
|
|
@ -42,8 +42,7 @@ namespace Device
|
|||
BluetoothEmu::BluetoothEmu(Kernel& ios, const std::string& device_name)
|
||||
: BluetoothBase(ios, device_name)
|
||||
{
|
||||
SysConf sysconf{Core::WantsDeterminism() ? Common::FromWhichRoot::FROM_SESSION_ROOT :
|
||||
Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
|
||||
SysConf sysconf{ios.GetFS()};
|
||||
if (!Core::WantsDeterminism())
|
||||
BackUpBTInfoSection(&sysconf);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "Common/StringUtil.h"
|
||||
#include "Common/SysConf.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/IOS/IOS.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/NetPlayClient.h"
|
||||
|
||||
|
@ -64,7 +65,7 @@ void InitializeWiiRoot(bool use_temporary)
|
|||
WARN_LOG(IOS_FS, "Using temporary directory %s for minimal Wii FS", s_temp_wii_root.c_str());
|
||||
File::SetUserPath(D_SESSION_WIIROOT_IDX, s_temp_wii_root);
|
||||
// Generate a SYSCONF with default settings for the temporary Wii NAND.
|
||||
SysConf sysconf{Common::FromWhichRoot::FROM_SESSION_ROOT};
|
||||
SysConf sysconf{IOS::HLE::Kernel{}.GetFS()};
|
||||
sysconf.Save();
|
||||
|
||||
InitializeDeterministicWiiSaves();
|
||||
|
|
|
@ -136,7 +136,7 @@ bool InstallWAD(IOS::HLE::Kernel& ios, const DiscIO::WiiWAD& wad, InstallType in
|
|||
}
|
||||
|
||||
// Delete a previous temporary title, if it exists.
|
||||
SysConf sysconf{Common::FROM_SESSION_ROOT};
|
||||
SysConf sysconf{ios.GetFS()};
|
||||
SysConf::Entry* tid_entry = sysconf.GetOrAddEntry("IPL.TID", SysConf::Entry::Type::LongLong);
|
||||
if (const u64 previous_temporary_title_id = Common::swap64(tid_entry->GetData<u64>(0)))
|
||||
ios.GetES()->DeleteTitleContent(previous_temporary_title_id);
|
||||
|
|
Loading…
Reference in New Issue