General code cleanup + various smaller fixes

This commit is contained in:
Exzap
2026-07-26 10:32:32 +02:00
parent fb3d265d70
commit 54d0392375
13 changed files with 103 additions and 45 deletions

View File

@@ -38,6 +38,32 @@ enum RPCOpcode : uint32_t
OpcodePong = 4,
};
static std::string EscapeJSONString(std::string_view value)
{
std::string escaped;
escaped.reserve(value.size() + 16); // original string length plus some extra space for escaped characters
for (unsigned char c : value)
{
switch (c)
{
case '"': escaped.append("\\\""); break;
case '\\': escaped.append("\\\\"); break;
case '\b': escaped.append("\\b"); break;
case '\f': escaped.append("\\f"); break;
case '\n': escaped.append("\\n"); break;
case '\r': escaped.append("\\r"); break;
case '\t': escaped.append("\\t"); break;
default:
if (c < 32)
escaped.append(shim::format("\\u{:04x}", c));
else
escaped.push_back(c);
break;
}
}
return escaped;
}
#ifdef _WIN32
class NamedPipeImpl
{
@@ -307,9 +333,9 @@ class NamedPipe : public NamedPipeImpl
{
jsonPayload.append(R"("activity": {)");
if (!presence.state.empty())
jsonPayload.append(shim::format(R"("state": "{}",)", presence.state));
jsonPayload.append(shim::format(R"("state": "{}",)", EscapeJSONString(presence.state)));
if (!presence.details.empty())
jsonPayload.append(shim::format(R"("details": "{}",)", presence.details));
jsonPayload.append(shim::format(R"("details": "{}",)", EscapeJSONString(presence.details)));
if (presence.startTimestamp || presence.endTimestamp)
{
jsonPayload.append(R"("timestamps": {)");
@@ -321,13 +347,19 @@ class NamedPipe : public NamedPipeImpl
jsonPayload.pop_back();
jsonPayload.append("},");
}
if (!presence.largeImageKey.empty() && !presence.largeImageText.empty() && !presence.smallImageKey.empty() && !presence.smallImageText.empty())
if (!presence.largeImageKey.empty() || !presence.largeImageText.empty() || !presence.smallImageKey.empty() || !presence.smallImageText.empty())
{
jsonPayload.append(R"("assets": {)");
jsonPayload.append(shim::format(R"("large_image": "{}",)", presence.largeImageKey));
jsonPayload.append(shim::format(R"("large_text": "{}",)", presence.largeImageText));
jsonPayload.append(shim::format(R"("small_image": "{}",)", presence.smallImageKey));
jsonPayload.append(shim::format(R"("small_text": "{}",)", presence.smallImageText));
if (!presence.largeImageKey.empty())
jsonPayload.append(shim::format(R"("large_image": "{}",)", EscapeJSONString(presence.largeImageKey)));
if (!presence.largeImageText.empty())
jsonPayload.append(shim::format(R"("large_text": "{}",)", EscapeJSONString(presence.largeImageText)));
if (!presence.smallImageKey.empty())
jsonPayload.append(shim::format(R"("small_image": "{}",)", EscapeJSONString(presence.smallImageKey)));
if (!presence.smallImageText.empty())
jsonPayload.append(shim::format(R"("small_text": "{}",)", EscapeJSONString(presence.smallImageText)));
if (jsonPayload.back() == ',')
jsonPayload.pop_back();
jsonPayload.append("},");
}
// party
@@ -335,7 +367,7 @@ class NamedPipe : public NamedPipeImpl
{
jsonPayload.append(R"("party": {)");
if (!presence.partyId.empty())
jsonPayload.append(shim::format(R"("id": "{}",)", presence.partyId));
jsonPayload.append(shim::format(R"("id": "{}",)", EscapeJSONString(presence.partyId)));
if (presence.partySize > 0 && presence.partyMax > 0)
jsonPayload.append(shim::format(R"("size": [{}, {}],)", presence.partySize, presence.partyMax));
jsonPayload.append(R"("privacy": )").append(std::to_string(presence.partyPrivacy)).append(",");
@@ -346,11 +378,11 @@ class NamedPipe : public NamedPipeImpl
{
jsonPayload.append(R"("secrets": {)");
if (!presence.matchSecret.empty())
jsonPayload.append(shim::format(R"("match": "{}",)", presence.matchSecret));
jsonPayload.append(shim::format(R"("match": "{}",)", EscapeJSONString(presence.matchSecret)));
if (!presence.joinSecret.empty())
jsonPayload.append(shim::format(R"("join": "{}",)", presence.joinSecret));
jsonPayload.append(shim::format(R"("join": "{}",)", EscapeJSONString(presence.joinSecret)));
if (!presence.spectateSecret.empty())
jsonPayload.append(shim::format(R"("spectate": "{}",)", presence.spectateSecret));
jsonPayload.append(shim::format(R"("spectate": "{}",)", EscapeJSONString(presence.spectateSecret)));
if (jsonPayload.back() == ',')
jsonPayload.pop_back();
jsonPayload.append("},");
@@ -649,7 +681,7 @@ void DiscordRPCLite::WorkerThread(std::string applicationId)
{
std::optional<std::string> cmd = ParseJSONField(jsonText, "cmd");
std::optional<std::string> evt = ParseJSONField(jsonText, "evt");
if (CompareStringI(*cmd, "DISPATCH"))
if (cmd && CompareStringI(*cmd, "DISPATCH"))
{
if (evt && CompareStringI(*evt, "READY"))
{

View File

@@ -110,7 +110,7 @@ CURLcode _sslctx_function_CUSTOM(CURL* curl, void* sslctx, void* param)
}
for (auto& clientCertId : requestHelper->GetClientCertIds())
{
if (iosuCrypto_addCACertificate(sslctx, clientCertId) == false)
if (iosuCrypto_addClientCertificate(sslctx, clientCertId) == false)
{
cemuLog_log(LogType::Force, "Invalid client certificate ({})", clientCertId);
}

View File

@@ -122,10 +122,10 @@ namespace NCrypto
for (size_t i = 0, j = 0; i < in_len;)
{
uint32 a = inputStr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(inputStr[i++])];
uint32 b = inputStr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(inputStr[i++])];
uint32 c = inputStr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(inputStr[i++])];
uint32 d = inputStr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(inputStr[i++])];
uint32 a = inputStr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<uint8>(inputStr[i++])];
uint32 b = inputStr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<uint8>(inputStr[i++])];
uint32 c = inputStr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<uint8>(inputStr[i++])];
uint32 d = inputStr[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<uint8>(inputStr[i++])];
uint32 triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
@@ -296,7 +296,7 @@ namespace NCrypto
cemu_assert_debug(extHeader->sectionTableEntrySize == 0x14);
for (uint32 i = 0; i < extHeader->sectionTableNumEntries; i++)
{
ETicketFileHeaderExtV1SectionHeader* sectHeader = (ETicketFileHeaderExtV1SectionHeader*)readStruct(0x2A4 + extHeader->sectionTableOffset, sizeof(ETicketFileHeaderExtV1SectionHeader));
ETicketFileHeaderExtV1SectionHeader* sectHeader = (ETicketFileHeaderExtV1SectionHeader*)readStruct(0x2A4 + extHeader->sectionTableOffset + i * extHeader->sectionTableEntrySize, sizeof(ETicketFileHeaderExtV1SectionHeader));
if (!sectHeader)
return false;
if (sectHeader->type == ETicketFileHeaderExtV1SectionHeader::SECTION_TYPE_CONTENT_RIGHTS)

View File

@@ -59,7 +59,7 @@ bool CreateMiniDump(CrashDump dump, EXCEPTION_POINTERS* pep)
const auto temp_time = std::chrono::system_clock::to_time_t(now);
const auto& time = *std::gmtime(&temp_time);
p /= fmt::format("crash_{:04d}{:02d}{:02d}_{:02d}{:02d}{:02d}.dmp", 1900 + time.tm_year, time.tm_mon + 1, time.tm_mday, time.tm_year, time.tm_hour, time.tm_min, time.tm_sec);
p /= fmt::format("crash_{:04d}{:02d}{:02d}_{:02d}{:02d}{:02d}.dmp", 1900 + time.tm_year, time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec);
const auto hFile = CreateFileW(p.wstring().c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile == INVALID_HANDLE_VALUE)
@@ -232,7 +232,7 @@ void createCrashlog(EXCEPTION_POINTERS* e, PCONTEXT context)
const auto& time = *std::gmtime(&temp_time);
fs::path p = ActiveSettings::GetUserDataPath("crashdump");
p /= fmt::format("log_{:04d}{:02d}{:02d}_{:02d}{:02d}{:02d}.txt", 1900 + time.tm_year, time.tm_mon + 1, time.tm_mday, time.tm_year, time.tm_hour, time.tm_min, time.tm_sec);
p /= fmt::format("log_{:04d}{:02d}{:02d}_{:02d}{:02d}{:02d}.txt", 1900 + time.tm_year, time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec);
std::error_code ec;
fs::copy_file(ActiveSettings::GetUserDataPath("log.txt"), p, ec);

View File

@@ -302,6 +302,7 @@ XMLConfigParser CemuConfig::Save(XMLConfigParser& parser)
config.set("mlc_path", mlc_path.GetValue().c_str());
config.set<bool>("permanent_storage", permanent_storage);
config.set("proxy_server", proxy_server.GetValue().c_str());
config.set<bool>("disable_screensaver", disable_screensaver);
config.set<bool>("play_boot_sound", play_boot_sound);
// config.set("cpu_mode", cpu_mode.GetValue());

View File

@@ -12,6 +12,7 @@
#include "util/crypto/aes128.h"
#include "Cafe/Filesystem/FST/FST.h"
#include "Cafe/TitleList/TitleId.h"
#include "util/helpers/StringHelpers.h"
void requireConsole();
@@ -146,13 +147,14 @@ std::optional<int> LaunchSettings::HandleCommandline(const std::vector<std::wstr
}
if (vm.count("title-id"))
{
auto title_param = vm["title-id"].as<std::string>();
auto titleParam = vm["title-id"].as<std::string>();
try {
if (title_param.starts_with('=')){
title_param.erase(title_param.begin());
}
s_load_title_id = std::stoull(title_param, nullptr, 16);
if (titleParam.starts_with('='))
titleParam.erase(titleParam.begin());
TitleId titleId;
if (!TitleIdParser::ParseFromStr(titleParam, titleId))
std::cerr << "Invalid title id format";
s_load_title_id = titleId;
}
catch (std::invalid_argument const& e)
{
@@ -220,14 +222,22 @@ std::optional<int> LaunchSettings::HandleCommandline(const std::vector<std::wstr
{
for (const auto& argument : vm["cos-mounts"].as<std::vector<std::wstring>>())
{
size_t colon_location = argument.find(L':');
if (colon_location == std::wstring::npos)
sint32 winDriveColonOffset = 0;
#if BOOST_OS_WINDOWS
// on Windows a path may start with \\?\C:\ or C:\ (where C can be an arbitrary drive letter), but the delimiter is also a colon, so filter out the drive colon
static const std::wregex winDrivePrefixRegex(LR"(^(?:\\\\\?\\)?[A-Za-z]:)");
std::wsmatch winDrivePrefixMatch;
if (std::regex_search(argument, winDrivePrefixMatch, winDrivePrefixRegex))
winDriveColonOffset = static_cast<sint32>(winDrivePrefixMatch.length());
#endif
size_t colonLocation = argument.find(L':', winDriveColonOffset);
if (colonLocation == std::wstring::npos)
{
std::cerr << "Argument for a mount expects to be in the format: `path on host:path in emulated system`, was not: `" << boost::nowide::narrow(argument) << "`\n";
continue;
}
s_cos_mounts[argument.substr(0, colon_location)] = argument.substr(colon_location + 1);
s_cos_mounts[argument.substr(0, colonLocation)] = argument.substr(colonLocation + 1);
}
}

View File

@@ -556,6 +556,7 @@ CreateInfinityFigureDialog::CreateInfinityFigureDialog(wxWindow* parent, uint8 s
wxMessageDialog idError(this, "Error Converting Figure Number!", "Number Entered is Invalid");
idError.ShowModal();
this->EndModal(0);
return;
}
uint32 figNum = longFigNum & 0xFFFFFFFF;
auto figure = nsyshid::g_infinitybase.FindFigure(figNum);
@@ -565,7 +566,10 @@ CreateInfinityFigureDialog::CreateInfinityFigureDialog(wxWindow* parent, uint8 s
"BIN files (*.bin)|*.bin", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (saveFileDialog.ShowModal() == wxID_CANCEL)
{
this->EndModal(0);
return;
}
m_filePath = saveFileDialog.GetPath();
@@ -723,6 +727,7 @@ CreateDimensionFigureDialog::CreateDimensionFigureDialog(wxWindow* parent)
wxMessageDialog idError(this, "Error Converting Figure Number!", "Number Entered is Invalid");
idError.ShowModal();
this->EndModal(0);
return;
}
uint16 figNum = longFigNum & 0xFFFF;
auto figure = nsyshid::g_dimensionstoypad.FindFigure(figNum);
@@ -732,7 +737,10 @@ CreateDimensionFigureDialog::CreateDimensionFigureDialog(wxWindow* parent)
"BIN files (*.bin)|*.bin", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (saveFileDialog.ShowModal() == wxID_CANCEL)
{
this->EndModal(0);
return;
}
m_filePath = saveFileDialog.GetPath();

View File

@@ -833,8 +833,7 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event)
if (!QueryIconForTitle(title_id, icon_large, icon_small))
break;
auto icon = m_image_list_data.GetIcon(icon_large);
auto newClipboardData = wxBitmapDataObject(icon);
wxClipboard::Get()->SetData(&newClipboardData);
wxClipboard::Get()->SetData(new wxBitmapDataObject(icon));
wxClipboard::Get()->Close();
}
break;

View File

@@ -678,9 +678,12 @@ EmulatedControllerPtr InputManager::delete_controller(size_t player_index, bool
{
controller = {};
std::error_code ec{};
fs::remove(ActiveSettings::GetConfigPath("controllerProfiles/controller{}.xml", player_index), ec);
fs::remove(ActiveSettings::GetConfigPath("controllerProfiles/controller{}.txt", player_index), ec);
if(delete_profile)
{
std::error_code ec{};
fs::remove(ActiveSettings::GetConfigPath("controllerProfiles/controller{}.xml", player_index), ec);
fs::remove(ActiveSettings::GetConfigPath("controllerProfiles/controller{}.txt", player_index), ec);
}
return result;
}
@@ -840,7 +843,7 @@ std::optional<glm::ivec2> InputManager::get_left_down_mouse_info(bool* is_pad)
*is_pad = false;
{
std::shared_lock lock(m_main_mouse.m_mutex);
std::unique_lock lock(m_main_mouse.m_mutex);
if (std::exchange(m_main_mouse.left_down_toggle, false))
return m_main_mouse.position;
@@ -849,7 +852,7 @@ std::optional<glm::ivec2> InputManager::get_left_down_mouse_info(bool* is_pad)
}
{
std::shared_lock lock(m_main_touch.m_mutex);
std::unique_lock lock(m_main_touch.m_mutex);
if (std::exchange(m_main_touch.left_down_toggle, false))
return m_main_touch.position;
@@ -861,7 +864,7 @@ std::optional<glm::ivec2> InputManager::get_left_down_mouse_info(bool* is_pad)
*is_pad = true;
{
std::shared_lock lock(m_pad_mouse.m_mutex);
std::unique_lock lock(m_pad_mouse.m_mutex);
if (std::exchange(m_pad_mouse.left_down_toggle, false))
return m_pad_mouse.position;
@@ -870,7 +873,7 @@ std::optional<glm::ivec2> InputManager::get_left_down_mouse_info(bool* is_pad)
}
{
std::shared_lock lock(m_pad_touch.m_mutex);
std::unique_lock lock(m_pad_touch.m_mutex);
if (std::exchange(m_pad_touch.left_down_toggle, false))
return m_pad_touch.position;
@@ -887,7 +890,7 @@ std::optional<glm::ivec2> InputManager::get_right_down_mouse_info(bool* is_pad)
*is_pad = false;
{
std::shared_lock lock(m_main_mouse.m_mutex);
std::unique_lock lock(m_main_mouse.m_mutex);
if (std::exchange(m_main_mouse.right_down_toggle, false))
return m_main_mouse.position;
@@ -896,7 +899,7 @@ std::optional<glm::ivec2> InputManager::get_right_down_mouse_info(bool* is_pad)
}
{
std::shared_lock lock(m_main_touch.m_mutex);
std::unique_lock lock(m_main_touch.m_mutex);
if (std::exchange(m_main_touch.right_down_toggle, false))
return m_main_touch.position;
@@ -908,7 +911,7 @@ std::optional<glm::ivec2> InputManager::get_right_down_mouse_info(bool* is_pad)
*is_pad = true;
{
std::shared_lock lock(m_pad_mouse.m_mutex);
std::unique_lock lock(m_pad_mouse.m_mutex);
if (std::exchange(m_pad_mouse.right_down_toggle, false))
return m_pad_mouse.position;
@@ -917,7 +920,7 @@ std::optional<glm::ivec2> InputManager::get_right_down_mouse_info(bool* is_pad)
}
{
std::shared_lock lock(m_pad_touch.m_mutex);
std::unique_lock lock(m_pad_touch.m_mutex);
if (std::exchange(m_pad_touch.right_down_toggle, false))
return m_pad_touch.position;

View File

@@ -60,7 +60,10 @@ bool SDLController::connect()
SDL_JoystickID *gamepad_ids = SDL_GetGamepads(&gamepad_count);
if (!gamepad_ids || index < 0 || index >= gamepad_count)
{
SDL_free(gamepad_ids);
return false;
}
m_diid = gamepad_ids[index];
SDL_free(gamepad_ids);

View File

@@ -775,8 +775,9 @@ void WiimoteControllerProvider::rotate_ir(WiimoteState& wiimote_state)
continue;
// move to center, rotate and move back
dot.pos -= 0.5f;
dot.pos.x = (dot.pos.x * cos) + (dot.pos.y * (-sin));
dot.pos.y = (dot.pos.x * sin) + (dot.pos.y * cos);
auto tmp = dot.pos;
dot.pos.x = (tmp.x * cos) + (tmp.y * (-sin));
dot.pos.y = (tmp.x * sin) + (tmp.y * cos);
dot.pos += 0.5f;
}
}

View File

@@ -106,7 +106,7 @@ void WindowsInitCwd()
executablePath.resize(i);
else
executablePath.clear();
SetCurrentDirectoryW(executablePath.c_str());
SetCurrentDirectoryW(fs::path(executablePath).parent_path().c_str());
// set high priority
SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
#endif

View File

@@ -800,6 +800,7 @@ void (*AES128_CBC_decrypt)(uint8* output, uint8* input, uint32 length, const uin
// AES128-CTR encrypt/decrypt
void AES128CTR_transform(uint8* data, sint32 length, uint8* key, uint8* nonceIv)
{
cemu_assert_debug(length >= 0 && (length&15) == 0); // length must be a multiple of 16
for (sint32 i = 0; i < length; i += 16)
{
uint8* d = data + i;