Skip to content

Commit

Permalink
Split SettingsHandler into separate reader and writer classes
Browse files Browse the repository at this point in the history
  • Loading branch information
nlebeck committed May 6, 2024
1 parent 2c91367 commit ce757cf
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 110 deletions.
52 changes: 27 additions & 25 deletions Source/Core/Common/SettingsHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,72 +17,74 @@

namespace Common
{
SettingsHandler::SettingsHandler() : m_buffer{}, m_position{0}, m_key{INITIAL_SEED}, decoded{""}
namespace
{
}
// Key used to encrypt/decrypt setting.txt contents
constexpr u32 INITIAL_SEED = 0x73B5DBFA;
} // namespace

SettingsHandler::SettingsHandler(const Buffer& buffer) : SettingsHandler()
SettingsWriter::SettingsWriter() : m_buffer{}, m_position{0}, m_key{INITIAL_SEED}
{
m_buffer = buffer;
Decrypt();
}

const SettingsHandler::Buffer& SettingsHandler::GetBytes() const
const SettingsBuffer& SettingsWriter::GetBytes() const
{
return m_buffer;
}

std::string SettingsHandler::GetValue(std::string_view key) const
std::string SettingsReader::GetValue(std::string_view key) const
{
constexpr char delim[] = "\n";
std::string toFind = std::string(delim).append(key).append("=");
size_t found = decoded.find(toFind);
size_t found = m_decoded.find(toFind);

if (found != std::string_view::npos)
{
size_t delimFound = decoded.find(delim, found + toFind.length());
size_t delimFound = m_decoded.find(delim, found + toFind.length());
if (delimFound == std::string_view::npos)
delimFound = decoded.length() - 1;
return decoded.substr(found + toFind.length(), delimFound - (found + toFind.length()));
delimFound = m_decoded.length() - 1;
return m_decoded.substr(found + toFind.length(), delimFound - (found + toFind.length()));
}
else
{
toFind = std::string(key).append("=");
found = decoded.find(toFind);
found = m_decoded.find(toFind);
if (found == 0)
{
size_t delimFound = decoded.find(delim, found + toFind.length());
size_t delimFound = m_decoded.find(delim, found + toFind.length());
if (delimFound == std::string_view::npos)
delimFound = decoded.length() - 1;
return decoded.substr(found + toFind.length(), delimFound - (found + toFind.length()));
delimFound = m_decoded.length() - 1;
return m_decoded.substr(found + toFind.length(), delimFound - (found + toFind.length()));
}
}

return "";
}

void SettingsHandler::Decrypt()
SettingsReader::SettingsReader(const SettingsBuffer& buffer) : m_decoded{""}
{
while (m_position < m_buffer.size())
u32 position = 0;
u32 key = INITIAL_SEED;
while (position < buffer.size())
{
decoded.push_back((u8)(m_buffer[m_position] ^ m_key));
m_position++;
m_key = (m_key >> 31) | (m_key << 1);
m_decoded.push_back((u8)(buffer[position] ^ key));
position++;
key = (key >> 31) | (key << 1);
}

// The decoded data normally uses CRLF line endings, but occasionally
// (see the comment in WriteLine), lines can be separated by CRLFLF.
// To handle this, we remove every CR and treat LF as the line ending.
// (We ignore empty lines.)
std::erase(decoded, '\x0d');
std::erase(m_decoded, '\x0d');
}

void SettingsHandler::AddSetting(std::string_view key, std::string_view value)
void SettingsWriter::AddSetting(std::string_view key, std::string_view value)
{
WriteLine(fmt::format("{}={}\r\n", key, value));
}

void SettingsHandler::WriteLine(std::string_view str)
void SettingsWriter::WriteLine(std::string_view str)
{
const u32 old_position = m_position;
const u32 old_key = m_key;
Expand All @@ -106,7 +108,7 @@ void SettingsHandler::WriteLine(std::string_view str)
}
}

void SettingsHandler::WriteByte(u8 b)
void SettingsWriter::WriteByte(u8 b)
{
if (m_position >= m_buffer.size())
return;
Expand All @@ -116,7 +118,7 @@ void SettingsHandler::WriteByte(u8 b)
m_key = (m_key >> 31) | (m_key << 1);
}

std::string SettingsHandler::GenerateSerialNumber()
std::string SettingsWriter::GenerateSerialNumber()
{
const std::time_t t = std::time(nullptr);

Expand Down
33 changes: 17 additions & 16 deletions Source/Core/Common/SettingsHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,35 @@

namespace Common
{
class SettingsHandler
using SettingsBuffer = std::array<u8, 0x100>;

class SettingsWriter
{
public:
enum
{
SETTINGS_SIZE = 0x100,
// Key used to encrypt/decrypt setting.txt contents
INITIAL_SEED = 0x73B5DBFA
};

using Buffer = std::array<u8, SETTINGS_SIZE>;
SettingsHandler();
explicit SettingsHandler(const Buffer& buffer);
SettingsWriter();

void AddSetting(std::string_view key, std::string_view value);

const Buffer& GetBytes() const;
std::string GetValue(std::string_view key) const;
const SettingsBuffer& GetBytes() const;

static std::string GenerateSerialNumber();

private:
void Decrypt();
void WriteLine(std::string_view str);
void WriteByte(u8 b);

std::array<u8, SETTINGS_SIZE> m_buffer;
SettingsBuffer m_buffer;
u32 m_position, m_key;
std::string decoded;
};

class SettingsReader
{
public:
explicit SettingsReader(const SettingsBuffer& buffer);

std::string GetValue(std::string_view key) const;

private:
std::string m_decoded;
};
} // namespace Common
29 changes: 15 additions & 14 deletions Source/Core/Core/Boot/Boot_BS2Emu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,12 +371,12 @@ bool CBoot::SetupWiiMemory(Core::System& system, IOS::HLE::IOSC::ConsoleType con

const auto fs = system.GetIOS()->GetFS();
{
Common::SettingsHandler::Buffer data;
Common::SettingsBuffer data;
const auto file = fs->OpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID, settings_file_path,
IOS::HLE::FS::Mode::Read);
if (file && file->Read(data.data(), data.size()))
{
Common::SettingsHandler settings_reader(data);
Common::SettingsReader settings_reader(data);
serno = settings_reader.GetValue("SERNO");
model = settings_reader.GetValue("MODEL");

Expand Down Expand Up @@ -413,28 +413,29 @@ bool CBoot::SetupWiiMemory(Core::System& system, IOS::HLE::IOSC::ConsoleType con
if (Core::WantsDeterminism())
serno = "123456789";
else
serno = Common::SettingsHandler::GenerateSerialNumber();
serno = Common::SettingsWriter::GenerateSerialNumber();
INFO_LOG_FMT(BOOT, "No previous serial number found, generated one instead: {}", serno);
}
else
{
INFO_LOG_FMT(BOOT, "Using serial number: {}", serno);
}

Common::SettingsHandler gen;
gen.AddSetting("AREA", region_setting.area);
gen.AddSetting("MODEL", model);
gen.AddSetting("DVD", "0");
gen.AddSetting("MPCH", "0x7FFE");
gen.AddSetting("CODE", region_setting.code);
gen.AddSetting("SERNO", serno);
gen.AddSetting("VIDEO", region_setting.video);
gen.AddSetting("GAME", region_setting.game);
Common::SettingsWriter settings_writer;
settings_writer.AddSetting("AREA", region_setting.area);
settings_writer.AddSetting("MODEL", model);
settings_writer.AddSetting("DVD", "0");
settings_writer.AddSetting("MPCH", "0x7FFE");
settings_writer.AddSetting("CODE", region_setting.code);
settings_writer.AddSetting("SERNO", serno);
settings_writer.AddSetting("VIDEO", region_setting.video);
settings_writer.AddSetting("GAME", region_setting.game);

constexpr IOS::HLE::FS::Mode rw_mode = IOS::HLE::FS::Mode::ReadWrite;
const auto settings_file = fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID,
settings_file_path, {rw_mode, rw_mode, rw_mode});
if (!settings_file || !settings_file->Write(gen.GetBytes().data(), gen.GetBytes().size()))
if (!settings_file ||
!settings_file->Write(settings_writer.GetBytes().data(), settings_writer.GetBytes().size()))
{
PanicAlertFmtT("SetupWiiMemory: Can't create setting.txt file");
return false;
Expand All @@ -443,7 +444,7 @@ bool CBoot::SetupWiiMemory(Core::System& system, IOS::HLE::IOSC::ConsoleType con
auto& memory = system.GetMemory();

// Write the 256 byte setting.txt to memory.
memory.CopyToEmu(0x3800, gen.GetBytes().data(), gen.GetBytes().size());
memory.CopyToEmu(0x3800, settings_writer.GetBytes().data(), settings_writer.GetBytes().size());

INFO_LOG_FMT(BOOT, "Setup Wii Memory...");

Expand Down
6 changes: 3 additions & 3 deletions Source/Core/Core/IOS/DolphinDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,13 @@ IPCReply GetRealProductCode(Core::System& system, const IOCtlVRequest& request)
if (!file)
return IPCReply(IPC_ENOENT);

Common::SettingsHandler::Buffer data;
Common::SettingsBuffer data;

if (!file.ReadBytes(data.data(), data.size()))
return IPCReply(IPC_ENOENT);

Common::SettingsHandler gen(data);
const std::string code = gen.GetValue("CODE");
Common::SettingsReader settings_reader(data);
const std::string code = settings_reader.GetValue("CODE");

const size_t length = std::min<size_t>(request.io_vectors[0].size, code.length());
if (length == 0)
Expand Down
14 changes: 7 additions & 7 deletions Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -923,16 +923,16 @@ IPCReply NetKDRequestDevice::HandleRequestRegisterUserId(const IOS::HLE::IOCtlRe
return IPCReply{IPC_SUCCESS};
}

Common::SettingsHandler::Buffer data;
Common::SettingsBuffer data;
if (!file->Read(data.data(), data.size()))
{
WriteReturnValue(memory, NWC24::WC24_ERR_FILE_READ, request.buffer_out);
LogError(ErrorType::Account, NWC24::WC24_ERR_FILE_READ);
return IPCReply{IPC_SUCCESS};
}

const Common::SettingsHandler gen{data};
const std::string serno = gen.GetValue("SERNO");
const Common::SettingsReader settings_reader{data};
const std::string serno = settings_reader.GetValue("SERNO");
const std::string form_data =
fmt::format("mlid=w{}&hdid={}&rgncd={}", m_config.Id(), m_ios.GetIOSC().GetDeviceId(), serno);
const Common::HttpRequest::Response response = m_http.Post(m_config.GetAccountURL(), form_data);
Expand Down Expand Up @@ -1076,12 +1076,12 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
const auto fs = m_ios.GetFS();
if (const auto file = fs->OpenFile(PID_KD, PID_KD, settings_file_path, FS::Mode::Read))
{
Common::SettingsHandler::Buffer data;
Common::SettingsBuffer data;
if (file->Read(data.data(), data.size()))
{
const Common::SettingsHandler gen{data};
area = gen.GetValue("AREA");
model = gen.GetValue("MODEL");
const Common::SettingsReader settings_reader{data};
area = settings_reader.GetValue("AREA");
model = settings_reader.GetValue("MODEL");
}
}

Expand Down

0 comments on commit ce757cf

Please sign in to comment.