Add translatable text in core code & add API in gui interface for showing error dialogs

This commit is contained in:
SSimco 2025-07-08 18:20:13 +03:00
parent 60f51cdb65
commit 1fa6695aea
28 changed files with 206 additions and 562 deletions

View File

@ -128,7 +128,7 @@ void SetEntryPoint(MPTR entryPoint)
}
// load executable into virtual memory and set entrypoint
bool LoadMainExecutable()
void LoadMainExecutable()
{
isLaunchTypeELF = false;
// when launching from a disc image _pathToExecutable is initially empty
@ -142,7 +142,6 @@ bool LoadMainExecutable()
cemuLog_log(LogType::Force, "Unable to find RPX executable");
cemuLog_waitForFlush();
cemu_assert(false);
return false;
}
}
// extract and load RPX
@ -153,7 +152,6 @@ bool LoadMainExecutable()
cemuLog_log(LogType::Force, "Failed to load \"{}\"", _pathToExecutable);
cemuLog_waitForFlush();
cemu_assert(false);
return false;
}
currentUpdatedApplicationHash = generateHashFromRawRPXData(rpxData, rpxSize);
// determine if this file is an ELF
@ -171,10 +169,10 @@ bool LoadMainExecutable()
applicationRPX = RPLLoader_LoadFromMemory(rpxData, rpxSize, (char*)_pathToExecutable.c_str());
if (!applicationRPX)
{
cemuLog_log(LogType::Force, "Failed to run this title because the executable is damaged");
WindowSystem::showErrorDialog(_tr("Failed to run this title because the executable is damaged"));
cemuLog_createLogFile(false);
cemuLog_waitForFlush();
cemu_assert(false);
return false;
exit(0);
}
RPLLoader_SetMainModule(applicationRPX);
SetEntryPoint(RPLLoader_GetModuleEntrypoint(applicationRPX));
@ -193,7 +191,6 @@ bool LoadMainExecutable()
}
free(baseRpxData);
debug_printf("RPXHash: 0x%08x\n", currentBaseApplicationHash);
return true;
}
fs::path getTitleSavePath()
@ -755,12 +752,7 @@ namespace CafeSystem
}
}
}
if (!LoadMainExecutable())
{
return PREPARE_STATUS_CODE::INVALID_RPX;
}
LoadMainExecutable();
return PREPARE_STATUS_CODE::SUCCESS;
}

View File

@ -1,6 +1,7 @@
#include <mutex>
#include "Cemu/Logging/CemuLogging.h"
#include "WindowSystem.h"
#include "config/ActiveSettings.h"
#include "util/crypto/aes128.h"
#include "Common/FileStream.h"
@ -74,7 +75,7 @@ void KeyCache_Prepare()
}
else
{
cemuLog_log(LogType::Force, "Unable to create file keys.txt\nThis can happen if Cemu does not have write permission to its own directory, the disk is full or if anti-virus software is blocking Cemu.");
WindowSystem::showErrorDialog(_tr("Unable to create file keys.txt\nThis can happen if Cemu does not have write permission to its own directory, the disk is full or if anti-virus software is blocking Cemu."), _tr("Error"), WindowSystem::ErrorCategory::KEYS_TXT_CREATION);
}
mtxKeyCache.unlock();
return;
@ -107,7 +108,8 @@ void KeyCache_Prepare()
continue;
if( strishex(line) == false )
{
cemuLog_log(LogType::Force, "Error in keys.txt at line {}", lineNumber);
auto errorMsg = fmt::format(fmt::runtime(_tr("Error in keys.txt at line {}")), lineNumber);
WindowSystem::showErrorDialog(errorMsg, WindowSystem::ErrorCategory::KEYS_TXT_CREATION);
continue;
}
if(line.size() == 32 )

View File

@ -1,6 +1,7 @@
#include "Cafe/GraphicPack/GraphicPack2.h"
#include "Cemu/Logging/CemuLogging.h"
#include "Common/FileStream.h"
#include "WindowSystem.h"
#include "util/helpers/StringParser.h"
#include "Cemu/PPCAssembler/ppcAssembler.h"
#include "Cafe/OS/RPL/rpl_structs.h"
@ -36,15 +37,15 @@ void PatchErrorHandler::printError(class PatchGroup* patchGroup, sint32 lineNumb
errorMessages.emplace_back(msg);
}
void PatchErrorHandler::logStageError()
void PatchErrorHandler::showStageErrorMessageBox()
{
std::string errorMsg;
if (m_gp)
{
if (m_stage == STAGE::PARSER)
errorMsg = fmt::format("Failed to load patches for graphic pack \'{}\'", m_gp->GetName());
errorMsg.assign(fmt::format(fmt::runtime(_tr("Failed to load patches for graphic pack \'{}\'")), m_gp->GetName()));
else
errorMsg = fmt::format("Failed to apply patches for graphic pack \'{}\'", m_gp->GetName());
errorMsg.assign(fmt::format(fmt::runtime(_tr("Failed to apply patches for graphic pack \'{}\'")), m_gp->GetName()));
}
else
{
@ -53,7 +54,7 @@ void PatchErrorHandler::logStageError()
if (cemuLog_isLoggingEnabled(LogType::Patches))
{
errorMsg.append("\n \n")
.append("Details:")
.append(_tr("Details:"))
.append("\n");
for (auto& itr : errorMessages)
{
@ -62,7 +63,7 @@ void PatchErrorHandler::logStageError()
}
}
cemuLog_log(LogType::Force, errorMsg);
WindowSystem::showErrorDialog(errorMsg, _tr("Graphic pack error"), WindowSystem::ErrorCategory::GRAPHIC_PACKS);
}
// loads Cemu-style patches (patch_<anything>.asm)

View File

@ -691,13 +691,13 @@ void GraphicPack2::ApplyPatchGroups(std::vector<PatchGroup*>& groups, const RPLM
patchContext.errorHandler.printError(nullptr, -1, "Some symbols could not be resolved because the dependency chain is too deep");
for (auto& itr : patchContext.unresolvedSymbols)
patchContext.errorHandler.printError(itr.patchGroup, itr.lineNumber, fmt::format("Unresolved symbol: {}", itr.symbolName));
patchContext.errorHandler.logStageError();
patchContext.errorHandler.showStageErrorMessageBox();
return;
}
}
if (!isUnresolvedPatchesEmpty() || patchContext.errorHandler.hasError())
{
patchContext.errorHandler.logStageError();
patchContext.errorHandler.showStageErrorMessageBox();
return;
}
// apply relocated patches

View File

@ -21,7 +21,7 @@ public:
}
void printError(class PatchGroup* patchGroup, sint32 lineNumber, std::string_view errorMsg);
void logStageError();
void showStageErrorMessageBox();
bool hasError() const { return m_anyErrorTriggered; };

View File

@ -357,8 +357,6 @@ void LatteShaderCache_Load()
RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId);
// get cache file name
const auto pathGeneric = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_shaders.bin", cacheTitleId);
const auto pathGenericPre1_25_0 = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}.bin", cacheTitleId); // before 1.25.0
const auto pathGenericPre1_16_0 = ActiveSettings::GetCachePath("shaderCache/transferable/{:08x}.bin", CafeSystem::GetRPXHashBase()); // before 1.16.0
// calculate extraVersion for transferable and precompiled shader cache
uint32 transferableExtraVersion = SHADER_CACHE_GENERIC_EXTRA_VERSION;

View File

@ -307,7 +307,7 @@ void VulkanRenderer::GetDeviceFeatures()
cemuLog_log(LogType::Force, "VK_EXT_pipeline_creation_cache_control not supported. Cannot use asynchronous shader and pipeline compilation");
// if async shader compilation is enabled show warning message
if (GetConfig().async_compile)
LatteOverlay_pushNotification("Async shader compile is enabled but not supported by the graphics driver\nCemu will use synchronous compilation which can cause additional stutter", 10000);
LatteOverlay_pushNotification(_tr("Async shader compile is enabled but not supported by the graphics driver\nCemu will use synchronous compilation which can cause additional stutter"), 10000);
}
if (!m_featureControl.deviceExtensions.custom_border_color_without_format)
{

View File

@ -1,6 +1,7 @@
#include "Cafe/HW/MMU/MMU.h"
#include "Cafe/GraphicPack/GraphicPack2.h"
#include "Cemu/Logging/CemuLogging.h"
#include "WindowSystem.h"
#include "util/MemMapper/MemMapper.h"
#include "config/ActiveSettings.h"
@ -90,7 +91,8 @@ void MMURange::mapMem()
cemu_assert_debug(!m_isMapped);
if (MemMapper::AllocateMemory(memory_base + baseAddress, size, MemMapper::PAGE_PERMISSION::P_RW, true) == nullptr)
{
cemuLog_log(LogType::Force, "Unable to allocate {} memory", name);
std::string errorMsg = fmt::format(fmt::runtime(_tr("Unable to allocate {} memory")), name);
WindowSystem::showErrorDialog(errorMsg, _tr("Error"));
#if BOOST_OS_WINDOWS
ExitProcess(-1);
#else
@ -130,8 +132,9 @@ void memory_init()
memory_base = (uint8*)MemMapper::ReserveMemory(nullptr, (size_t)0x100000000, MemMapper::PAGE_PERMISSION::P_RW);
if( !memory_base )
{
debug_printf("memory_init(): Unable to reserve 4GB of memory\n");
debugBreakpoint();
cemuLog_log(LogType::Force, "Unable to reserve 4GB of memory");
WindowSystem::showErrorDialog(_tr("Unable to reserve 4GB of memory"), _tr("Error"));
exit(-1);
}
for (auto& itr : g_mmuRanges)

View File

@ -331,7 +331,9 @@ bool DownloadManager::syncAccountTickets()
for (auto& tiv : resultTicketIds.tivs)
{
index++;
setStatus(DownloadManagerStatuses::DownloadingAccountTicket{.index = index, .count = count});
std::string msg = _tr("Downloading account ticket");
msg.append(fmt::format(" {0}/{1}", index, count));
setStatusMessage(msg, DLMGR_STATUS_CODE::CONNECTING);
// skip if already cached
ETicketInfo* cachedTicket = findTicketByTicketId(tiv.ticketId);
if (cachedTicket)
@ -382,7 +384,7 @@ bool DownloadManager::syncAccountTickets()
bool DownloadManager::syncSystemTitleTickets()
{
setStatus(DownloadManagerStatuses::DownloadingSystemTickets{});
setStatusMessage(_tr("Downloading system tickets..."), DLMGR_STATUS_CODE::CONNECTING);
NAPI::AuthInfo authInfo = GetAuthInfo(true);
auto querySystemTitleTicket = [&](uint64 titleId) -> void
{
@ -432,7 +434,7 @@ bool DownloadManager::syncSystemTitleTickets()
// build list of updates for which either an installed game exists or the base title ticket is cached
bool DownloadManager::syncUpdateTickets()
{
setStatus(DownloadManagerStatuses::RetrievingUpdateInformation{});
setStatusMessage(_tr("Retrieving update information..."), DLMGR_STATUS_CODE::CONNECTING);
// download update version list
downloadTitleVersionList();
if (!m_hasTitleVersionList)
@ -454,7 +456,10 @@ bool DownloadManager::syncUpdateTickets()
if (titleIdParser.GetType() != TitleIdParser::TITLE_TYPE::BASE_TITLE_UPDATE)
continue;
setStatus(DownloadManagerStatuses::DownloadingTicket{.updateIndex = updateIndex, .numUpdates = numUpdates});
std::string msg = _tr("Downloading ticket");
msg.append(fmt::format(" {0}/{1}", updateIndex, numUpdates));
updateIndex++;
setStatusMessage(msg, DLMGR_STATUS_CODE::CONNECTING);
if (!itr.isUpdateAvailable)
continue;
@ -503,10 +508,12 @@ bool DownloadManager::syncTicketCache()
for (auto& ticketInfo : m_ticketCache)
{
index++;
setStatus(DownloadManagerStatuses::DownloadingMetaData{.index = index, .count = count});
std::string msg = _tr("Downloading meta data");
msg.append(fmt::format(" {0}/{1}", index, count));
setStatusMessage(msg, DLMGR_STATUS_CODE::CONNECTING);
prepareIDBE(ticketInfo.titleId);
}
setStatus(DownloadManagerStatuses::Connected{});
setStatusMessage(_tr("Connected. Right click entries in the list to start downloading"), DLMGR_STATUS_CODE::CONNECTED);
return true;
}
@ -592,7 +599,7 @@ void DownloadManager::_handle_connect()
// reset login state
m_iasToken.serviceAccountId.clear();
m_iasToken.deviceToken.clear();
setStatus(DownloadManagerStatuses::LoggingIn{});
setStatusMessage(_tr("Logging in..."), DLMGR_STATUS_CODE::CONNECTING);
// retrieve ECS AccountId + DeviceToken from cache
if (s_nupFileCache)
{
@ -615,7 +622,7 @@ void DownloadManager::_handle_connect()
cemuLog_log(LogType::Force, "Failed to request IAS token");
cemu_assert_debug(false);
m_connectState.store(CONNECT_STATE::FAILED);
setStatus(DownloadManagerStatuses::LoginFailed{});
setStatusMessage(_tr("Login failed. Outdated or incomplete online files?"), DLMGR_STATUS_CODE::FAILED);
return;
}
}
@ -623,16 +630,16 @@ void DownloadManager::_handle_connect()
if (!_connect_queryAccountStatusAndServiceURLs())
{
m_connectState.store(CONNECT_STATE::FAILED);
setStatus(DownloadManagerStatuses::FailedToQueryAccountStatus{});
setStatusMessage(_tr("Failed to query account status"), DLMGR_STATUS_CODE::FAILED);
return;
}
// load ticket cache and sync
setStatus(DownloadManagerStatuses::UpdatingTicketCache{});
setStatusMessage(_tr("Updating ticket cache"), DLMGR_STATUS_CODE::CONNECTING);
loadTicketCache();
if (!syncTicketCache())
{
m_connectState.store(CONNECT_STATE::FAILED);
setStatus(DownloadManagerStatuses::FailedToRequestTickets{});
setStatusMessage(_tr("Failed to request tickets"), DLMGR_STATUS_CODE::FAILED);
return;
}
searchForIncompleteDownloads();
@ -914,13 +921,13 @@ void DownloadManager::checkPackagesState()
}
}
void DownloadManager::setPackageError(Package* package, PackageErrorCode errorCode)
void DownloadManager::setPackageError(Package* package, std::string errorMsg)
{
package->state.isActive = false;
if (package->state.hasError)
return; // dont overwrite already set error message
package->state.hasError = true;
package->state.errorCode = errorCode;
package->state.errorMsg = std::move(errorMsg);
reportPackageStatus(package);
}
@ -959,7 +966,7 @@ void DownloadManager::reportPackageStatus(Package* package)
DlMgrTitleReport reportInfo(status, package->titleId, package->version, getNameFromCachedIDBE(package->titleId), package->state.progress, package->state.progressMax, package->state.isPaused);
if (package->state.hasError)
reportInfo.errorCode = package->state.errorCode;
reportInfo.errorMsg = package->state.errorMsg;
m_mutex.unlock();
m_cbAddDownloadableTitle(reportInfo);
@ -997,7 +1004,7 @@ void DownloadManager::asyncPackageDownloadTMD(Package* package)
std::unique_lock<std::recursive_mutex> _l(m_mutex);
if (!tmdResult.isValid)
{
setPackageError(package, PackageErrorCode::TMD_DOWNLOAD_FAILED);
setPackageError(package, _tr("TMD download failed"));
package->state.isDownloadingTMD = false;
return;
}
@ -1006,7 +1013,7 @@ void DownloadManager::asyncPackageDownloadTMD(Package* package)
NCrypto::TMDParser tmdParser;
if (!tmdParser.parse(tmdResult.tmdData.data(), tmdResult.tmdData.size()))
{
setPackageError(package, PackageErrorCode::INVALID_TMD);
setPackageError(package, _tr("Invalid TMD"));
package->state.isDownloadingTMD = false;
return;
}
@ -1115,7 +1122,7 @@ void DownloadManager::asyncPackageDownloadContentFile(Package* package, uint16 i
size_t bytesWritten = callbackInfo->receiveBuffer.size();
if (callbackInfo->fileOutput->writeData(callbackInfo->receiveBuffer.data(), callbackInfo->receiveBuffer.size()) != (uint32)callbackInfo->receiveBuffer.size())
{
callbackInfo->downloadMgr->setPackageError(callbackInfo->package, PackageErrorCode::DISK_FULL_FAILED_TO_WRITE_FILE);
callbackInfo->downloadMgr->setPackageError(callbackInfo->package, _tr("Cannot write file. Disk full?"));
return false;
}
callbackInfo->receiveBuffer.clear();
@ -1136,12 +1143,12 @@ void DownloadManager::asyncPackageDownloadContentFile(Package* package, uint16 i
callbackInfoData.fileOutput = FileStream::createFile2(packageDownloadPath / fmt::format("{:08x}.app", contentId));
if (!callbackInfoData.fileOutput)
{
setPackageError(package, PackageErrorCode::CANNOT_CREATE_FILE);
setPackageError(package, _tr("Cannot create file"));
return;
}
if (!NAPI::CCS_GetContentFile(GetDownloadMgrNetworkService(), titleId, contentId, CallbackInfo::writeCallback, &callbackInfoData))
{
setPackageError(package, PackageErrorCode::DOWNLOAD_FAILED);
setPackageError(package, _tr("Download failed"));
delete callbackInfoData.fileOutput;
return;
}
@ -1184,7 +1191,7 @@ void DownloadManager::asyncPackageVerifyFile(Package* package, uint16 index, boo
_l.lock();
contentFileItr->second.finishProcessing(newStateOnError);
if (!isCheckState)
setPackageError(package, PackageErrorCode::MISSING_FILE_DURING_VERIFICATION);
setPackageError(package, "Missing file during verification");
_l.unlock();
updatePackage(package);
return;
@ -1203,7 +1210,7 @@ void DownloadManager::asyncPackageVerifyFile(Package* package, uint16 index, boo
_l.lock();
contentFileItr->second.finishProcessing(newStateOnError);
if (!isCheckState)
setPackageError(package, PackageErrorCode::VERIFICATION_FAILED);
setPackageError(package, "Verification failed");
_l.unlock();
updatePackage(package);
return;
@ -1226,7 +1233,7 @@ bool DownloadManager::asyncPackageInstallRecursiveExtractFiles(Package* package,
if (!fstVolume->OpenDirectoryIterator(sourcePath, dirItr))
{
std::unique_lock<std::recursive_mutex> _l(m_mutex);
setPackageError(package, PackageErrorCode::INTERNAL_ERROR);
setPackageError(package, "Internal error");
return false;
}
if (fstVolume->HasLinkFlag(dirItr.GetDirHandle()))
@ -1272,7 +1279,7 @@ bool DownloadManager::asyncPackageInstallRecursiveExtractFiles(Package* package,
FileStream* fileOut = FileStream::createFile2(nodeDestinationPath);
if (!fileOut)
{
setPackageError(package, PackageErrorCode::FAILED_TO_CREATE_FILE);
setPackageError(package, "Failed to create file");
return false;
}
uint32 fileSize = fstVolume->GetFileSize(itr);
@ -1282,12 +1289,12 @@ bool DownloadManager::asyncPackageInstallRecursiveExtractFiles(Package* package,
uint32 numBytesToTransfer = std::min(fileSize - currentPos, (uint32)buffer.size());
if (fstVolume->ReadFile(itr, currentPos, numBytesToTransfer, buffer.data()) != numBytesToTransfer)
{
setPackageError(package, PackageErrorCode::FAILED_TO_EXTRACT_DATA);
setPackageError(package, "Failed to extract data");
return false;
}
if (fileOut->writeData(buffer.data(), numBytesToTransfer) != numBytesToTransfer)
{
setPackageError(package, PackageErrorCode::DISK_FULL_FAILED_TO_WRITE_FILE);
setPackageError(package, "Failed to write to file. Disk full?");
return false;
}
currentPos += numBytesToTransfer;
@ -1317,7 +1324,7 @@ void DownloadManager::asyncPackageInstall(Package* package)
if (!fileStream || fileStream->writeData(package->state.tmdData.data(), package->state.tmdData.size()) != package->state.tmdData.size())
{
_l.lock();
setPackageError(package, PackageErrorCode::FAILED_TO_WRITE_TITLE_TMD);
setPackageError(package, "Failed to write title.tmd");
package->state.isInstalling = false;
return;
}
@ -1327,7 +1334,7 @@ void DownloadManager::asyncPackageInstall(Package* package)
if (!fileStream || fileStream->writeData(package->eTicketData.data(), package->eTicketData.size()) != package->eTicketData.size())
{
_l.lock();
setPackageError(package, PackageErrorCode::FAILED_TO_WRITE_TITLE_TIK);
setPackageError(package, "Failed to write title.tik");
package->state.isInstalling = false;
return;
}
@ -1343,7 +1350,7 @@ void DownloadManager::asyncPackageInstall(Package* package)
if (!fileStream || fileStream->writeData(package->eTicketData.data(), package->eTicketData.size()) != package->eTicketData.size())
{
_l.lock();
setPackageError(package, PackageErrorCode::FAILED_TO_INSTALL_TITLE_TIK);
setPackageError(package, "Failed to install title.tik");
package->state.isInstalling = false;
return;
}
@ -1354,7 +1361,7 @@ void DownloadManager::asyncPackageInstall(Package* package)
if (!fst)
{
_l.lock();
setPackageError(package, PackageErrorCode::FAILED_TO_EXTRACT_CONTENT);
setPackageError(package, "Failed to extract content");
package->state.isInstalling = false;
return;
}
@ -1365,21 +1372,21 @@ void DownloadManager::asyncPackageInstall(Package* package)
if (!asyncPackageInstallRecursiveExtractFiles(package, fst, "code/", installPath / "code"))
{
_l.lock();
setPackageError(package, PackageErrorCode::FAILED_TO_EXTRACT_CODE_FOLDER);
setPackageError(package, "Failed to extract code folder");
package->state.isInstalling = false;
return;
}
if (!asyncPackageInstallRecursiveExtractFiles(package, fst, "content/", installPath / "content"))
{
_l.lock();
setPackageError(package, PackageErrorCode::FAILED_TO_EXTRACT_CONTENT_FOLDER);
setPackageError(package, "Failed to extract content folder");
package->state.isInstalling = false;
return;
}
if (!asyncPackageInstallRecursiveExtractFiles(package, fst, "meta/", installPath / "meta"))
{
_l.lock();
setPackageError(package, PackageErrorCode::FAILED_TO_EXTRACT_META_FOLDER);
setPackageError(package, "Failed to extract meta folder");
package->state.isInstalling = false;
return;
}

View File

@ -5,8 +5,6 @@
#include "util/helpers/ConcurrentQueue.h"
#include "config/NetworkSettings.h"
#include <variant>
// forward declarations
namespace NAPI
{
@ -19,27 +17,6 @@ namespace NCrypto
class TMDParser;
}
enum class PackageErrorCode
{
TMD_DOWNLOAD_FAILED,
INVALID_TMD,
CANNOT_CREATE_FILE,
DOWNLOAD_FAILED,
MISSING_FILE_DURING_VERIFICATION,
VERIFICATION_FAILED,
INTERNAL_ERROR,
FAILED_TO_CREATE_FILE,
FAILED_TO_EXTRACT_DATA,
DISK_FULL_FAILED_TO_WRITE_FILE,
FAILED_TO_WRITE_TITLE_TMD,
FAILED_TO_WRITE_TITLE_TIK,
FAILED_TO_INSTALL_TITLE_TIK,
FAILED_TO_EXTRACT_CONTENT,
FAILED_TO_EXTRACT_CODE_FOLDER,
FAILED_TO_EXTRACT_CONTENT_FOLDER,
FAILED_TO_EXTRACT_META_FOLDER,
};
struct DlMgrTitleReport
{
enum class STATUS
@ -68,7 +45,7 @@ struct DlMgrTitleReport
uint32 progress;
uint32 progressMax;
bool isPaused;
PackageErrorCode errorCode;
std::string errorMsg;
};
enum class DLMGR_STATUS_CODE
@ -79,82 +56,6 @@ enum class DLMGR_STATUS_CODE
CONNECTED
};
namespace DownloadManagerStatuses
{
struct Uninitialized
{
};
struct DownloadingAccountTicket
{
size_t index;
size_t count;
};
struct DownloadingSystemTickets
{
};
struct RetrievingUpdateInformation
{
};
struct DownloadingTicket
{
size_t updateIndex;
size_t numUpdates;
};
struct DownloadingMetaData
{
size_t index;
size_t count;
};
struct LoggingIn
{
};
struct UpdatingTicketCache
{
};
struct Failed
{
};
// Outdated or incomplete online files?
struct LoginFailed : Failed
{
};
struct FailedToQueryAccountStatus : Failed
{
};
struct FailedToRequestTickets : Failed
{
};
struct Connected
{
};
}; // namespace DownloadManagerStatuses
using DownloadManagerStatus = std::variant<
DownloadManagerStatuses::Uninitialized,
DownloadManagerStatuses::DownloadingAccountTicket,
DownloadManagerStatuses::DownloadingSystemTickets,
DownloadManagerStatuses::RetrievingUpdateInformation,
DownloadManagerStatuses::DownloadingTicket,
DownloadManagerStatuses::DownloadingMetaData,
DownloadManagerStatuses::LoggingIn,
DownloadManagerStatuses::UpdatingTicketCache,
DownloadManagerStatuses::LoginFailed,
DownloadManagerStatuses::FailedToQueryAccountStatus,
DownloadManagerStatuses::FailedToRequestTickets,
DownloadManagerStatuses::Connected>;
class DownloadManager
{
public:
@ -451,7 +352,7 @@ private:
bool isInstalling{};
// error state
bool hasError{};
PackageErrorCode errorCode;
std::string errorMsg;
}state;
};
@ -469,7 +370,7 @@ private:
void updatePackage(Package* package);
void checkPackagesState();
void setPackageError(Package* package, PackageErrorCode errorCode);
void setPackageError(Package* package, std::string errorMsg);
void reportPackageStatus(Package* package);
void reportPackageProgress(Package* package, uint32 newProgress);
@ -495,7 +396,7 @@ public:
// register/unregister callbacks
// setting valid callbacks will also trigger transfer of the entire title/package state and the current status message
void registerCallbacks(
void(*cbUpdateConnectStatus)(DownloadManagerStatus),
void(*cbUpdateConnectStatus)(std::string statusText, DLMGR_STATUS_CODE statusCode),
void(*cbAddDownloadableTitle)(const DlMgrTitleReport& titleInfo),
void(*cbRemoveDownloadableTitle)(uint64 titleId, uint16 version)
)
@ -508,22 +409,23 @@ public:
if (m_cbUpdateConnectStatus || m_cbAddDownloadableTitle)
{
std::unique_lock<std::recursive_mutex> _l(m_mutex);
setStatus(m_status);
setStatusMessage(m_statusMessage, m_statusCode);
reportAvailableTitles();
for (auto& p : m_packageList)
reportPackageStatus(p);
}
}
void setStatus(DownloadManagerStatus status)
void setStatusMessage(std::string_view msg, DLMGR_STATUS_CODE statusCode)
{
m_status = status;
m_statusMessage = msg;
m_statusCode = statusCode;
if (m_cbUpdateConnectStatus)
m_cbUpdateConnectStatus(status);
m_cbUpdateConnectStatus(m_statusMessage, statusCode);
}
std::string m_statusMessage{};
DownloadManagerStatus m_status = DownloadManagerStatuses::Uninitialized{};
DLMGR_STATUS_CODE m_statusCode{ DLMGR_STATUS_CODE::UNINITIALIZED };
bool hasActiveDownloads()
{
@ -543,12 +445,12 @@ public:
{
std::unique_lock<std::recursive_mutex> _l(m_mutex);
m_packageList.clear();
m_status = DownloadManagerStatuses::Uninitialized{};
m_statusCode = DLMGR_STATUS_CODE::UNINITIALIZED;
m_statusMessage.clear();
}
private:
void(*m_cbUpdateConnectStatus)(DownloadManagerStatus status) { nullptr };
void(*m_cbUpdateConnectStatus)(std::string statusText, DLMGR_STATUS_CODE statusCode) { nullptr };
void(*m_cbAddDownloadableTitle)(const DlMgrTitleReport& titleInfo);
void(*m_cbRemoveDownloadableTitle)(uint64 titleId, uint16 version);
void* m_userData{};

View File

@ -119,6 +119,27 @@ using uint8le = uint8_t;
#include "Cemu/Logging/CemuDebugLogging.h"
#include "Cemu/Logging/CemuLogging.h"
// localization
namespace
{
std::function<std::string(std::string_view)> g_translate;
}
inline void SetTranslationCallback(std::function<std::string(std::string_view)> translate)
{
g_translate = translate;
}
#define TR_NOOP(str) str
inline std::string _tr(std::string_view msgId)
{
if (g_translate)
return g_translate(msgId);
return std::string{msgId};
}
// manual endian-swapping
#if _MSC_VER

View File

@ -258,15 +258,15 @@ struct fmt::formatter<CafeConsoleRegion> : formatter<string_view> {
string_view name;
switch (v)
{
case CafeConsoleRegion::JPN: name = "Japan"; break;
case CafeConsoleRegion::USA: name = "USA"; break;
case CafeConsoleRegion::EUR: name = "Europe"; break;
case CafeConsoleRegion::AUS_DEPR: name = "Australia"; break;
case CafeConsoleRegion::CHN: name = "China"; break;
case CafeConsoleRegion::KOR: name = "Korea"; break;
case CafeConsoleRegion::TWN: name = "Taiwan"; break;
case CafeConsoleRegion::Auto: name = "Auto"; break;
default: name = "many"; break;
case CafeConsoleRegion::JPN: name = TR_NOOP("Japan"); break;
case CafeConsoleRegion::USA: name = TR_NOOP("USA"); break;
case CafeConsoleRegion::EUR: name = TR_NOOP("Europe"); break;
case CafeConsoleRegion::AUS_DEPR: name = TR_NOOP("Australia"); break;
case CafeConsoleRegion::CHN: name = TR_NOOP("China"); break;
case CafeConsoleRegion::KOR: name = TR_NOOP("Korea"); break;
case CafeConsoleRegion::TWN: name = TR_NOOP("Taiwan"); break;
case CafeConsoleRegion::Auto: name = TR_NOOP("Auto"); break;
default: name = TR_NOOP("many"); break;
}
return formatter<string_view>::format(name, ctx);

View File

@ -222,7 +222,10 @@ bool LaunchSettings::HandleCommandline(const std::vector<std::wstring>& args)
}
catch (const std::exception& ex)
{
cemuLog_log(LogType::Force, "Error while trying to parse command line parameter: {}", ex.what());
std::string errorMsg;
errorMsg.append("Error while trying to parse command line parameter:\n");
errorMsg.append(ex.what());
std::cout << errorMsg << std::endl;
return false;
}

View File

@ -82,6 +82,18 @@ namespace WindowSystem
std::unordered_map<uint32, bool> m_keydown;
};
enum class ErrorCategory
{
KEYS_TXT_CREATION = 0,
GRAPHIC_PACKS = 1,
};
void showErrorDialog(std::string_view message, std::string_view title, std::optional<ErrorCategory> errorCategory = {});
inline void showErrorDialog(std::string_view message, std::optional<ErrorCategory> errorCategory = {})
{
showErrorDialog(message, "", errorCategory);
}
void create();
WindowInfo& getWindowInfo();

View File

@ -247,6 +247,11 @@ void CemuApp::InitializeExistingMLCOrFail(fs::path mlc)
}
}
std::string TranslationCallback(std::string_view msgId)
{
return wxGetTranslation(to_wxString(msgId)).utf8_string();
}
bool CemuApp::OnInit()
{
#if __WXGTK__
@ -273,6 +278,8 @@ bool CemuApp::OnInit()
LocalizeUI(static_cast<wxLanguage>(wxLocale::GetSystemLanguage()));
}
SetTranslationCallback(TranslationCallback);
for (auto&& path : failedWriteAccess)
{
wxMessageBox(formatWxString(_("Cemu can't write to {}!"), wxString::FromUTF8(_pathToUtf8(path))),

View File

@ -11,8 +11,6 @@
#include "wxgui/GameUpdateWindow.h"
#include "wxgui/dialogs/SaveImport/SaveTransfer.h"
#include <optional>
#include <type_traits>
#include <wx/listbase.h>
#include <wx/sizer.h>
#include <wx/listctrl.h>
@ -819,50 +817,11 @@ void TitleManager::SetConnected(bool state)
m_download_list->Enable(state);
}
void TitleManager::Callback_ConnectStatusUpdate(DownloadManagerStatus status)
void TitleManager::Callback_ConnectStatusUpdate(std::string statusText, DLMGR_STATUS_CODE statusCode)
{
TitleManager* titleManager = static_cast<TitleManager*>(DownloadManager::GetInstance()->getUserData());
auto downloadStatusText = std::visit([](auto&& status) -> std::optional<wxString> {
using T = std::decay_t<decltype(status)>;
if constexpr (std::is_same_v<T, DownloadManagerStatuses::Uninitialized>)
return std::nullopt;
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::DownloadingAccountTicket>)
return _("Downloading account ticket") + fmt::format(" {0}/{1}", status.index, status.count);
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::DownloadingSystemTickets>)
return _("Downloading system tickets...");
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::RetrievingUpdateInformation>)
return _("Retrieving update information...");
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::DownloadingTicket>)
return _("Downloading ticket") + fmt::format(" {0}/{1}", status.updateIndex, status.numUpdates);
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::DownloadingMetaData>)
return _("Downloading meta data") + fmt::format(" {0}/{1}", status.index, status.count);
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::LoggingIn>)
return _("Logging in...");
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::UpdatingTicketCache>)
return _("Updating ticket cache");
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::LoginFailed>)
return _("Login failed. Outdated or incomplete online files?");
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::FailedToQueryAccountStatus>)
return _("Failed to query account status");
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::FailedToRequestTickets>)
return _("Failed to request tickets");
else if constexpr (std::is_same_v<T, DownloadManagerStatuses::Connected>)
return _("Connected. Right click entries in the list to start downloading");
cemu_assert_unimplemented();
return std::nullopt; }, status);
if (!downloadStatusText.has_value())
{
return;
}
titleManager->SetDownloadStatusText(downloadStatusText.value());
bool isFailedStatus = std::visit([](auto&& status) -> bool {
constexpr bool isFailedStatus = std::is_base_of_v<DownloadManagerStatuses::Failed, std::decay_t<decltype(status)>>;
return isFailedStatus; }, status);
if (isFailedStatus)
titleManager->SetDownloadStatusText(wxString::FromUTF8(statusText));
if (statusCode == DLMGR_STATUS_CODE::FAILED)
{
auto* evt = new wxCommandEvent(wxEVT_DL_DISCONNECT_COMPLETE);
wxQueueEvent(titleManager, evt); // this will set SetConnected() to false
@ -870,29 +829,6 @@ void TitleManager::Callback_ConnectStatusUpdate(DownloadManagerStatus status)
}
}
wxString getPackageErrorMessage(PackageErrorCode code) {
switch (code) {
case PackageErrorCode::TMD_DOWNLOAD_FAILED: return _("TMD download failed");
case PackageErrorCode::INVALID_TMD: return _("Invalid TMD");
case PackageErrorCode::CANNOT_CREATE_FILE: return _("Cannot create file");
case PackageErrorCode::DOWNLOAD_FAILED: return _("Download failed");
case PackageErrorCode::MISSING_FILE_DURING_VERIFICATION: return _("Missing file during verification");
case PackageErrorCode::VERIFICATION_FAILED: return _("Verification failed");
case PackageErrorCode::INTERNAL_ERROR: return _("Internal error");
case PackageErrorCode::FAILED_TO_CREATE_FILE: return _("Failed to create file");
case PackageErrorCode::FAILED_TO_EXTRACT_DATA: return _("Failed to extract data");
case PackageErrorCode::DISK_FULL_FAILED_TO_WRITE_FILE: return _("Failed to write to file. Disk full?");
case PackageErrorCode::FAILED_TO_WRITE_TITLE_TMD: return _("Failed to write title.tmd");
case PackageErrorCode::FAILED_TO_WRITE_TITLE_TIK: return _("Failed to write title.tik");
case PackageErrorCode::FAILED_TO_INSTALL_TITLE_TIK: return _("Failed to install title.tik");
case PackageErrorCode::FAILED_TO_EXTRACT_CONTENT: return _("Failed to extract content");
case PackageErrorCode::FAILED_TO_EXTRACT_CODE_FOLDER: return _("Failed to extract code folder");
case PackageErrorCode::FAILED_TO_EXTRACT_CONTENT_FOLDER: return _("Failed to extract content folder");
case PackageErrorCode::FAILED_TO_EXTRACT_META_FOLDER: return _("Failed to extract meta folder");
default: return _("Unknown error");
}
}
void TitleManager::Callback_AddDownloadableTitle(const DlMgrTitleReport& titleInfo)
{
TitleManager* titleManager = static_cast<TitleManager*>(DownloadManager::GetInstance()->getUserData());
@ -949,7 +885,7 @@ void TitleManager::Callback_AddDownloadableTitle(const DlMgrTitleReport& titleIn
break;
case DlMgrTitleReport::STATUS::HAS_ERROR:
titleEntry.status = wxDownloadManagerList::TitleDownloadStatus::Error;
titleEntry.errorMsg = getPackageErrorMessage(titleInfo.errorCode);
titleEntry.errorMsg = titleInfo.errorMsg;
break;
default:
titleEntry.status = wxDownloadManagerList::TitleDownloadStatus::None;

View File

@ -30,6 +30,8 @@ enum class TitleManagerPage
DownloadManager = 1
};
enum class DLMGR_STATUS_CODE;
class TitleManager : public wxFrame
{
public:
@ -89,7 +91,7 @@ private:
void SetConnected(bool state);
static void Callback_ConnectStatusUpdate(DownloadManagerStatus status);
static void Callback_ConnectStatusUpdate(std::string statusText, DLMGR_STATUS_CODE statusCode);
static void Callback_AddDownloadableTitle(const struct DlMgrTitleReport& titleInfo);
static void Callback_RemoveDownloadableTitle(uint64 titleId, uint16 version);

View File

@ -101,69 +101,9 @@ ClassicControllerInputPanel::ClassicControllerInputPanel(wxWindow* parent)
Layout();
}
wxString get_classic_controller_button_name(ClassicController::ButtonId id)
{
switch (id)
{
case ClassicController::kButtonId_A:
return "A";
case ClassicController::kButtonId_B:
return "B";
case ClassicController::kButtonId_X:
return "X";
case ClassicController::kButtonId_Y:
return "Y";
case ClassicController::kButtonId_L:
return "L";
case ClassicController::kButtonId_R:
return "R";
case ClassicController::kButtonId_ZL:
return "ZL";
case ClassicController::kButtonId_ZR:
return "ZR";
case ClassicController::kButtonId_Plus:
return "+";
case ClassicController::kButtonId_Minus:
return "-";
case ClassicController::kButtonId_Home:
return _("home");
case ClassicController::kButtonId_Up:
return _("up");
case ClassicController::kButtonId_Down:
return _("down");
case ClassicController::kButtonId_Left:
return _("left");
case ClassicController::kButtonId_Right:
return _("right");
case ClassicController::kButtonId_StickL_Up:
return _("up");
case ClassicController::kButtonId_StickL_Down:
return _("down");
case ClassicController::kButtonId_StickL_Left:
return _("left");
case ClassicController::kButtonId_StickL_Right:
return _("right");
case ClassicController::kButtonId_StickR_Up:
return _("up");
case ClassicController::kButtonId_StickR_Down:
return _("down");
case ClassicController::kButtonId_StickR_Left:
return _("left");
case ClassicController::kButtonId_StickR_Right:
return _("right");
default:
return "";
}
}
void ClassicControllerInputPanel::add_button_row(wxGridBagSizer *sizer, sint32 row, sint32 column, const ClassicController::ButtonId &button_id) {
sizer->Add(
new wxStaticText(this, wxID_ANY, get_classic_controller_button_name(button_id)),
new wxStaticText(this, wxID_ANY, wxGetTranslation(to_wxString(ClassicController::get_button_name(button_id)))),
wxGBPosition(row, column),
wxDefaultSpan,
wxALL | wxALIGN_CENTER_VERTICAL, 5);

View File

@ -99,70 +99,9 @@ ProControllerInputPanel::ProControllerInputPanel(wxWindow* parent)
SetSizerAndFit(main_sizer);
}
wxString get_pro_controller_button_name(ProController::ButtonId id)
{
switch (id)
{
case ProController::kButtonId_A:
return "A";
case ProController::kButtonId_B:
return "B";
case ProController::kButtonId_X:
return "X";
case ProController::kButtonId_Y:
return "Y";
case ProController::kButtonId_L:
return "L";
case ProController::kButtonId_R:
return "R";
case ProController::kButtonId_ZL:
return "ZL";
case ProController::kButtonId_ZR:
return "ZR";
case ProController::kButtonId_Plus:
return "+";
case ProController::kButtonId_Minus:
return "-";
case ProController::kButtonId_Up:
return _("up");
case ProController::kButtonId_Down:
return _("down");
case ProController::kButtonId_Left:
return _("left");
case ProController::kButtonId_Right:
return _("right");
case ProController::kButtonId_StickL:
return _("click");
case ProController::kButtonId_StickR:
return _("click");
case ProController::kButtonId_StickL_Up:
return _("up");
case ProController::kButtonId_StickL_Down:
return _("down");
case ProController::kButtonId_StickL_Left:
return _("left");
case ProController::kButtonId_StickL_Right:
return _("right");
case ProController::kButtonId_StickR_Up:
return _("up");
case ProController::kButtonId_StickR_Down:
return _("down");
case ProController::kButtonId_StickR_Left:
return _("left");
case ProController::kButtonId_StickR_Right:
return _("right");
case ProController::kButtonId_Home:
return _("home");
default:
cemu_assert_debug(false);
return "";
}
}
void ProControllerInputPanel::add_button_row(wxGridBagSizer* sizer, sint32 row, sint32 column, const ProController::ButtonId& button_id)
{
void ProControllerInputPanel::add_button_row(wxGridBagSizer *sizer, sint32 row, sint32 column, const ProController::ButtonId &button_id) {
sizer->Add(
new wxStaticText(this, wxID_ANY, get_pro_controller_button_name(button_id)),
new wxStaticText(this, wxID_ANY, wxGetTranslation(to_wxString(ProController::get_button_name(button_id)))),
wxGBPosition(row, column),
wxDefaultSpan,
wxALL | wxALIGN_CENTER_VERTICAL, 5);

View File

@ -156,68 +156,8 @@ VPADInputPanel::VPADInputPanel(wxWindow* parent)
Layout();
}
wxString get_vpad_controllerbutton_name(VPADController::ButtonId id)
{
switch (id)
{
case VPADController::kButtonId_A:
return "A";
case VPADController::kButtonId_B:
return "B";
case VPADController::kButtonId_X:
return "X";
case VPADController::kButtonId_Y:
return "Y";
case VPADController::kButtonId_L:
return "L";
case VPADController::kButtonId_R:
return "R";
case VPADController::kButtonId_ZL:
return "ZL";
case VPADController::kButtonId_ZR:
return "ZR";
case VPADController::kButtonId_Plus:
return "+";
case VPADController::kButtonId_Minus:
return "-";
case VPADController::kButtonId_Up:
return _("up");
case VPADController::kButtonId_Down:
return _("down");
case VPADController::kButtonId_Left:
return _("left");
case VPADController::kButtonId_Right:
return _("right");
case VPADController::kButtonId_StickL:
return _("click");
case VPADController::kButtonId_StickR:
return _("click");
case VPADController::kButtonId_StickL_Up:
return _("up");
case VPADController::kButtonId_StickL_Down:
return _("down");
case VPADController::kButtonId_StickL_Left:
return _("left");
case VPADController::kButtonId_StickL_Right:
return _("right");
case VPADController::kButtonId_StickR_Up:
return _("up");
case VPADController::kButtonId_StickR_Down:
return _("down");
case VPADController::kButtonId_StickR_Left:
return _("left");
case VPADController::kButtonId_StickR_Right:
return _("right");
case VPADController::kButtonId_Home:
return _("home");
default:
cemu_assert_debug(false);
return "";
}
}
void VPADInputPanel::add_button_row(wxGridBagSizer *sizer, sint32 row, sint32 column, const VPADController::ButtonId &button_id) {
add_button_row(sizer, row, column, button_id, get_vpad_controllerbutton_name(button_id));
add_button_row(sizer, row, column, button_id, wxGetTranslation(to_wxString(VPADController::get_button_name(button_id))));
}
void VPADInputPanel::add_button_row(wxGridBagSizer *sizer, sint32 row, sint32 column,

View File

@ -156,57 +156,9 @@ WiimoteInputPanel::WiimoteInputPanel(wxWindow* parent)
Layout();
}
wxString get_wiimote_controller_button_name(WiimoteController::ButtonId id)
{
switch (id)
{
case WiimoteController::kButtonId_A:
return "A";
case WiimoteController::kButtonId_B:
return "B";
case WiimoteController::kButtonId_1:
return "1";
case WiimoteController::kButtonId_2:
return "2";
case WiimoteController::kButtonId_Home:
return _("home");
case WiimoteController::kButtonId_Plus:
return "+";
case WiimoteController::kButtonId_Minus:
return "-";
case WiimoteController::kButtonId_Up:
return _("up");
case WiimoteController::kButtonId_Down:
return _("down");
case WiimoteController::kButtonId_Left:
return _("left");
case WiimoteController::kButtonId_Right:
return _("right");
case WiimoteController::kButtonId_Nunchuck_Z:
return "Z";
case WiimoteController::kButtonId_Nunchuck_C:
return "C";
case WiimoteController::kButtonId_Nunchuck_Up:
return _("up");
case WiimoteController::kButtonId_Nunchuck_Down:
return _("down");
case WiimoteController::kButtonId_Nunchuck_Left:
return _("left");
case WiimoteController::kButtonId_Nunchuck_Right:
return _("right");
default:
return "";
}
}
void WiimoteInputPanel::add_button_row(sint32 row, sint32 column, const WiimoteController::ButtonId &button_id) {
m_item_sizer->Add(
new wxStaticText(this, wxID_ANY, get_wiimote_controller_button_name(button_id)),
new wxStaticText(this, wxID_ANY, wxGetTranslation(to_wxString(WiimoteController::get_button_name(button_id)))),
wxGBPosition(row, column),
wxDefaultSpan,
wxALL | wxALIGN_CENTER_VERTICAL, 5);

View File

@ -1,5 +1,7 @@
#include "interface/WindowSystem.h"
#include "helpers/wxHelpers.h"
#if BOOST_OS_LINUX
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
@ -53,6 +55,16 @@ void WindowSystem::create()
#endif
}
void WindowSystem::showErrorDialog(std::string_view message, std::string_view title, std::optional<WindowSystem::ErrorCategory> /*errorId*/)
{
wxString caption;
if (title.empty())
caption = wxASCII_STR(wxMessageBoxCaptionStr);
else
caption = to_wxString(title);
wxMessageBox(to_wxString(message), caption, wxOK | wxCENTRE | wxICON_ERROR);
}
WindowSystem::WindowInfo& WindowSystem::getWindowInfo()
{
return g_window_info;

View File

@ -68,22 +68,22 @@ std::string_view ClassicController::get_button_name(ButtonId id)
case kButtonId_Plus: return "+";
case kButtonId_Minus: return "-";
case kButtonId_Home: return "home";
case kButtonId_Home: return TR_NOOP("home");
case kButtonId_Up: return "up";
case kButtonId_Down: return "down";
case kButtonId_Left: return "left";
case kButtonId_Right: return "right";
case kButtonId_Up: return TR_NOOP("up");
case kButtonId_Down: return TR_NOOP("down");
case kButtonId_Left: return TR_NOOP("left");
case kButtonId_Right: return TR_NOOP("right");
case kButtonId_StickL_Up: return "up";
case kButtonId_StickL_Down: return "down";
case kButtonId_StickL_Left: return "left";
case kButtonId_StickL_Right: return "right";
case kButtonId_StickL_Up: return TR_NOOP("up");
case kButtonId_StickL_Down: return TR_NOOP("down");
case kButtonId_StickL_Left: return TR_NOOP("left");
case kButtonId_StickL_Right: return TR_NOOP("right");
case kButtonId_StickR_Up: return "up";
case kButtonId_StickR_Down: return "down";
case kButtonId_StickR_Left: return "left";
case kButtonId_StickR_Right: return "right";
case kButtonId_StickR_Up: return TR_NOOP("up");
case kButtonId_StickR_Down: return TR_NOOP("down");
case kButtonId_StickR_Left: return TR_NOOP("left");
case kButtonId_StickR_Right: return TR_NOOP("right");
default:
return "";

View File

@ -73,21 +73,21 @@ std::string_view ProController::get_button_name(ButtonId id)
case kButtonId_ZR: return "ZR";
case kButtonId_Plus: return "+";
case kButtonId_Minus: return "-";
case kButtonId_Up: return "up";
case kButtonId_Down: return "down";
case kButtonId_Left: return "left";
case kButtonId_Right: return "right";
case kButtonId_StickL: return "click";
case kButtonId_StickR: return "click";
case kButtonId_StickL_Up: return "up";
case kButtonId_StickL_Down: return "down";
case kButtonId_StickL_Left: return "left";
case kButtonId_StickL_Right: return "right";
case kButtonId_StickR_Up: return "up";
case kButtonId_StickR_Down: return "down";
case kButtonId_StickR_Left: return "left";
case kButtonId_StickR_Right: return "right";
case kButtonId_Home: return "home";
case kButtonId_Up: return TR_NOOP("up");
case kButtonId_Down: return TR_NOOP("down");
case kButtonId_Left: return TR_NOOP("left");
case kButtonId_Right: return TR_NOOP("right");
case kButtonId_StickL: return TR_NOOP("click");
case kButtonId_StickR: return TR_NOOP("click");
case kButtonId_StickL_Up: return TR_NOOP("up");
case kButtonId_StickL_Down: return TR_NOOP("down");
case kButtonId_StickL_Left: return TR_NOOP("left");
case kButtonId_StickL_Right: return TR_NOOP("right");
case kButtonId_StickR_Up: return TR_NOOP("up");
case kButtonId_StickR_Down: return TR_NOOP("down");
case kButtonId_StickR_Left: return TR_NOOP("left");
case kButtonId_StickR_Right: return TR_NOOP("right");
case kButtonId_Home: return TR_NOOP("home");
default:
cemu_assert_debug(false);
return "";

View File

@ -366,21 +366,21 @@ std::string_view VPADController::get_button_name(ButtonId id)
case kButtonId_ZR: return "ZR";
case kButtonId_Plus: return "+";
case kButtonId_Minus: return "-";
case kButtonId_Up: return "up";
case kButtonId_Down: return "down";
case kButtonId_Left: return "left";
case kButtonId_Right: return "right";
case kButtonId_StickL: return "click";
case kButtonId_StickR: return "click";
case kButtonId_StickL_Up: return "up";
case kButtonId_StickL_Down: return "down";
case kButtonId_StickL_Left: return "left";
case kButtonId_StickL_Right: return "right";
case kButtonId_StickR_Up: return "up";
case kButtonId_StickR_Down: return "down";
case kButtonId_StickR_Left: return "left";
case kButtonId_StickR_Right: return "right";
case kButtonId_Home: return "home";
case kButtonId_Up: return TR_NOOP("up");
case kButtonId_Down: return TR_NOOP("down");
case kButtonId_Left: return TR_NOOP("left");
case kButtonId_Right: return TR_NOOP("right");
case kButtonId_StickL: return TR_NOOP("click");
case kButtonId_StickR: return TR_NOOP("click");
case kButtonId_StickL_Up: return TR_NOOP("up");
case kButtonId_StickL_Down: return TR_NOOP("down");
case kButtonId_StickL_Left: return TR_NOOP("left");
case kButtonId_StickL_Right: return TR_NOOP("right");
case kButtonId_StickR_Up: return TR_NOOP("up");
case kButtonId_StickR_Down: return TR_NOOP("down");
case kButtonId_StickR_Left: return TR_NOOP("left");
case kButtonId_StickR_Right: return TR_NOOP("right");
case kButtonId_Home: return TR_NOOP("home");
default:
cemu_assert_debug(false);
return "";

View File

@ -158,22 +158,22 @@ std::string_view WiimoteController::get_button_name(ButtonId id)
case kButtonId_1: return "1";
case kButtonId_2: return "2";
case kButtonId_Home: return "home";
case kButtonId_Home: return TR_NOOP("home");
case kButtonId_Plus: return "+";
case kButtonId_Minus: return "-";
case kButtonId_Up: return "up";
case kButtonId_Down: return "down";
case kButtonId_Left: return "left";
case kButtonId_Right: return "right";
case kButtonId_Up: return TR_NOOP("up");
case kButtonId_Down: return TR_NOOP("down");
case kButtonId_Left: return TR_NOOP("left");
case kButtonId_Right: return TR_NOOP("right");
case kButtonId_Nunchuck_Z: return "Z";
case kButtonId_Nunchuck_C: return "C";
case kButtonId_Nunchuck_Up: return "up";
case kButtonId_Nunchuck_Down: return "down";
case kButtonId_Nunchuck_Left: return "left";
case kButtonId_Nunchuck_Right: return "right";
case kButtonId_Nunchuck_Up: return TR_NOOP("up");
case kButtonId_Nunchuck_Down: return TR_NOOP("down");
case kButtonId_Nunchuck_Left: return TR_NOOP("left");
case kButtonId_Nunchuck_Right: return TR_NOOP("right");
default:
return "";

View File

@ -51,29 +51,6 @@ std::string_view& trim(std::string_view& str, const std::string& chars)
#if BOOST_OS_WINDOWS
std::wstring GetSystemErrorMessageW()
{
return GetSystemErrorMessageW(GetLastError());
}
std::wstring GetSystemErrorMessageW(DWORD error_code)
{
if(error_code == ERROR_SUCCESS)
return {};
LPWSTR lpMsgBuf = nullptr;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error_code, 0, (LPWSTR)&lpMsgBuf, 0, nullptr);
if (lpMsgBuf)
{
std::wstring str = fmt::format(L"{}: {}", L"Error", lpMsgBuf);
LocalFree(lpMsgBuf);
return str;
}
return fmt::format(L"{}: {:#x}", L"Error code", error_code);
}
std::string GetSystemErrorMessage(DWORD error_code)
{
if(error_code == ERROR_SUCCESS)
@ -83,12 +60,12 @@ std::string GetSystemErrorMessage(DWORD error_code)
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error_code, 0, (LPSTR)&lpMsgBuf, 0, nullptr);
if (lpMsgBuf)
{
std::string str = fmt::format("{}: {}", "Error", lpMsgBuf);
std::string str = fmt::format("{}: {}", _tr("Error") lpMsgBuf); // TRANSLATE
LocalFree(lpMsgBuf);
return str;
}
return fmt::format("{}: {:#x}", "Error code", error_code);
return fmt::format("{}: {:#x}", _tr("Error code"), error_code);
}
std::string GetSystemErrorMessage()

View File

@ -76,8 +76,6 @@ std::string_view& trim(std::string_view& str, const std::string& chars = "\t\n\v
std::string GenerateRandomString(size_t length);
std::string GenerateRandomString(size_t length, std::string_view characters);
std::wstring GetSystemErrorMessageW();
std::wstring GetSystemErrorMessageW(DWORD error_code);
std::string GetSystemErrorMessage();
std::string GetSystemErrorMessage(DWORD error_code);
std::string GetSystemErrorMessage(const std::exception& ex);