mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-07-10 09:34:40 -06:00
Add translatable text in core code & add API in gui interface for showing error dialogs
This commit is contained in:
parent
60f51cdb65
commit
1fa6695aea
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 )
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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; };
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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{};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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))),
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 "";
|
||||
|
||||
@ -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 "";
|
||||
|
||||
@ -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 "";
|
||||
|
||||
@ -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 "";
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user