Merge branch 'main' into linux-overlay

This commit is contained in:
Tom Lally 2022-09-06 15:47:06 +01:00
commit 6aa7a0c7b2
35 changed files with 144 additions and 81 deletions

View file

@ -87,6 +87,10 @@ jobs:
cd build
ninja
- name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: mv bin/Cemu_release bin/Cemu
- name: Upload artifact
uses: actions/upload-artifact@v3
if: ${{ inputs.deploymode == 'release' }}
@ -189,6 +193,10 @@ jobs:
cd build
cmake --build . --config ${{ env.BUILD_MODE }} -j 2
- name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: Rename-Item bin/Cemu_release.exe Cemu.exe
- name: Upload artifact
uses: actions/upload-artifact@v3
if: ${{ inputs.deploymode == 'release' }}

View file

@ -63,4 +63,4 @@ jobs:
wget -O ghr.tar.gz https://github.com/tcnksm/ghr/releases/download/v0.15.0/ghr_v0.15.0_linux_amd64.tar.gz
tar xvzf ghr.tar.gz; rm ghr.tar.gz
echo "[INFO] Release tag: v${{ env.CEMU_VERSION }}"
ghr_v0.15.0_linux_amd64/ghr -prerelease -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }} (Experimental)" -b "" "v${{ env.CEMU_VERSION }}" ./upload
ghr_v0.15.0_linux_amd64/ghr -prerelease -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }} (Experimental)" -b "Cemu experimental release - [changelog](https://cemu.info/changelog.html)" "v${{ env.CEMU_VERSION }}" ./upload

7
.gitignore vendored
View file

@ -18,14 +18,15 @@
build/
out/
.cache/
bin/Cemu
bin/Cemu_*
bin/Cemu_*.exe
# Cemu bin files
bin/otp.bin
bin/seeprom.bin
bin/log.txt
bin/Cemu.pdb
bin/Cemu.ilk
bin/Cemu_*.pdb
bin/Cemu_*.ilk
bin/Cemu.exe.backup
bin/mlc01/*
bin/settings.xml

View file

@ -39,7 +39,15 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
if (MSVC)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT CemuBin)
# floating point model: precise, fiber safe optimizations
add_compile_options(/EHsc /fp:precise /GT)
add_compile_options(/EHsc /fp:precise)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Speeds up static linking (especially helpful in incremental compilation)
if((CMAKE_LINKER MATCHES ".*lld-link.*") AND (CMAKE_AR MATCHES ".*llvm-lib.*"))
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY STATIC_LIBRARY_OPTIONS /llvmlibthin)
endif()
else()
add_compile_options(/GT)
endif()
if (PUBLIC_RELEASE)
message(STATUS "Using additional optimization flags for MSVC")
add_compile_options(/Oi /Ot) # enable intrinsic functions, favor speed
@ -81,7 +89,7 @@ find_package(ZLIB REQUIRED)
find_package(zstd MODULE REQUIRED) # MODULE so that zstd::zstd is available
find_package(OpenSSL COMPONENTS Crypto SSL REQUIRED)
find_package(glm REQUIRED)
find_package(fmt 7.0.0 REQUIRED)
find_package(fmt 9.1.0 REQUIRED)
find_package(PNG REQUIRED)
# glslang versions older than 11.11.0 define targets without a namespace

View file

@ -48,10 +48,15 @@
//DEFINE_CLSID(XAudio2_Debug, 47199894, 7cc2, 444d, 98, 73, ce, d2, 56, 2c, c6, 0e);
// XAudio 2.7 (June 2010 SDK)
#ifdef __clang__
class __declspec(uuid("5a508685-a254-4fba-9b82-9a24b00306af")) XAudio2; extern "C" const GUID CLSID_XAudio2;
class __declspec(uuid("db05ea35-0329-4d4b-a53a-6dead03d3852")) XAudio2_Debug; extern "C" const GUID CLSID_XAudio2_Debug;
struct __declspec(uuid("8bcf1f58-9fe7-4583-8ac6-e2adc465c8bb")) IXAudio2; extern "C" const GUID IID_IXAudio2;
#else
DEFINE_CLSID(XAudio2, 5a508685, a254, 4fba, 9b, 82, 9a, 24, b0, 03, 06, af);
DEFINE_CLSID(XAudio2_Debug, db05ea35, 0329, 4d4b, a5, 3a, 6d, ea, d0, 3d, 38, 52);
DEFINE_IID(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb);
#endif
// Ignore the rest of this header if only the GUID definitions were requested
#ifndef GUID_DEFS_ONLY

View file

@ -40,6 +40,9 @@
#include <stdint.h>
#include <immintrin.h>
#if defined(_MSC_VER) && defined(__clang__)
#include <intrin.h>
#endif
#define CLIP_U8(x) CLIP3(0, UINT8_MAX, (x))
#define CLIP_S8(x) CLIP3(INT8_MIN, INT8_MAX, (x))
@ -71,7 +74,7 @@
/* For MSVC x64 */
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(__clang__)
static inline int __builtin_clz(unsigned x)
{

View file

@ -1,10 +1,10 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO fmtlib/fmt
REF 7bdf0628b1276379886c7f6dda2cef2b3b374f0b # v7.1.3
SHA512 52ea8f9d2c0cb52ec3a740e38fcdfd6a0318566e3b599bd2e8d557168642d005c0a59bc213cff2641a88fed3bb771d15f46c39035ccd64809569af982aba47aa
REF a33701196adfad74917046096bf5a2aa0ab0bb50 # v9.1.0
SHA512 0faf00e99b332fcb3d9fc50cc9649ddc004ca9035f3652c1a001facee725dab09f67b65a9dfcce0aedb47e76c74c45a9262a1fd6e250a9e9a27c7d021c8ee6b8
HEAD_REF master
PATCHES fix-warning4189.patch
# PATCHES fix-warning4189.patch
)
vcpkg_cmake_configure(

View file

@ -21,7 +21,7 @@
<p xml:lang="de">Cemu ist ein Nintendo Wii U-Emulator, der die meisten Wii U Spiele und Homebrew in einem spielbaren Zustand ausführen kann. Erstellt von Exzap, und geschrieben in C/C++.</p>
<p xml:lang="fr">Cemu est un émulateur de Wii U capable de lancer la plupart des jeux Wii U et des homebrews en interface de jeu. Crée par Exzap, et développé en C/C++.</p>
<p xml:lang="nl">Cemu is een Nintendo Wii U emulator die de meeste Wii U en Homebrew games speelbaar kan runnen. Het project is begonnen door Exzap, en het is geschreven in C/C++.</p>
<p xml:lang="el">Το Cemu είναι ένας προσομοιωτής της κονσόλας Nintendo Wii U που υποστηρίζει τεπίσημα παιχνίδια, καθώς και μη επίσημα προγράμματα ("homebrew"), για το Wii U. Δημιουργήθηκε από τον Exzap σε C/C++.</p>
<p xml:lang="el">Το Cemu είναι ένας προσομοιωτής της κονσόλας Nintendo Wii U που προσομοιώνει επίσημα παιχνίδια, καθώς και μη επίσημα προγράμματα ("homebrew") του Wii U. Δημιουργήθηκε από τον Exzap σε C/C++.</p>
<p xml:lang="es">Cemu es un emulador de Nintendo Wii U que es capaz de ejecutar la mayoría de los juegos de Wii U y homebrew en un estado jugable. Creado por Exzap, y escrito en C y C++.</p>
<p xml:lang="pt_BR">Cemu é um emulador de Nintendo Wii U que é capaz de executar a maioría dos jogos de Wii U e homebrew em um estado jogavel. Criado por Exzap, e escrito em C e C++.</p>
<p xml:lang="it">Cemu è un emulatore del Nintendo Wii U in grado di eseguire in stato giocabile la maggior parte dei giochi e homebrew per Wii U. Creato da Exzap, e scritto in C/C++.</p>
@ -30,7 +30,7 @@
<p xml:lang="de">Dieser Emulator zielt darauf ab, sowohl hohe Genauigkeit als auch Leistung zu bieten, und wird aktiv mit neuen Funktionen und Korrekturen weiterentwickelt, um Kompatibilität, Komfort und Benutzerfreundlichkeit zu verbessern.</p>
<p xml:lang="fr">Cet émulateur vise à la fois à offrir fidélité et performance, il est activement développé avec des nouvelles fonctionnalités et des correctifs pour augmenter la compatibilité, la commodité et la facilité d'utilisation.</p>
<p xml:lang="nl">De emulator richt zich op integriteit en snelheid, en wordt continu verder ontwikkeld met nieuwe toevoegingen en fixes om de compatibiliteit, het gemak en de gebruiksvriendelijkheid te verbeteren.</p>
<p xml:lang="el">Ο προσομοιωτής αυτός στοχεύει τόσο στην ακρίβεια, όσο και στην ταχύτητα. Βελτιώνεται συνεχώς με νέες δυνατότητες και διορθώσεις που τον καθιστούν πιο βολικό, εύκολο στην χρήση και συμβατό με περισσότερα παιχνίδια.</p>
<p xml:lang="el">Ο προσομοιωτής αυτός στοχεύει τόσο στην ακρίβεια, όσο και στην ταχύτητα, και βελτιώνεται συνεχώς με νέες δυνατότητες και διορθώσεις που τον καθιστούν πιο βολικό, εύκολο στην χρήση και συμβατό με περισσότερα παιχνίδια.</p>
<p xml:lang="es">Este emulador tiene como objetivo proporcionar tanto alta precisión como rendimiento y se desarrolla activamente con nuevas características y correcciones para mejorar la compatibilidad, la comodidad y la usabilidad.</p>
<p xml:lang="pt_BR">Esse emulador visa proporcionar tanto alta precisão como rendimento e está sendo ativamente desenvolvido com novas características e correções para melhorar a compatibilidade, a comodidade e a usabilidade.</p>
<p xml:lang="it">Questo emulatore ha l'obiettivo di fornire sia alta precisione che alte prestazioni, ed è in continuo sviluppo con nuove funzionalità e correzioni per aumentare la compatibilità, la comodità e l'usabilità.</p>
@ -39,7 +39,7 @@
<p xml:lang="de">Er wird seit Anfang 2015 entwickelt.</p>
<p xml:lang="fr">Il a été écrit à partir de zéro et son développement a débuté vers le début de l'année 2015.</p>
<p xml:lang="nl">Ontwikkeling van Cemu begon ongeveer in het voorjaar van 2015.</p>
<p xml:lang="el">Το Cemu βρίσκεται υπό ανάπτυξη από το 2015.</p>
<p xml:lang="el">Αρχισε απο το τίποτα και βρίσκεται υπό ανάπτυξη από το 2015.</p>
<p xml:lang="es">Fue escrito desde cero y el desarrollo del proyecto comenzó aproximadamente a principios de 2015.</p>
<p xml:lang="pt_BR">Foi escrito do zero e o desenvolvimento do projeto começou aproximadamente a princípio de 2015.</p>
<p xml:lang="it">È stato scritto da zero e lo sviluppo del progetto è cominciato intorno all'inizio del 2015.</p>

View file

@ -75,8 +75,10 @@ endif()
set_property(TARGET CemuBin PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set_target_properties(CemuBin PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin/"
OUTPUT_NAME "Cemu"
# multi-configuration generators will add a config subdirectory to RUNTIME_OUTPUT_DIRECTORY if no generator expression is used
# to get the same behavior everywhere we append an empty generator expression
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin/$<1:>"
OUTPUT_NAME "Cemu_$<LOWER_CASE:$<CONFIG>>"
)
target_link_libraries(CemuBin PRIVATE

View file

@ -110,7 +110,8 @@ uint64 PPCTimer_tscToMicroseconds(uint64 us)
uint64 remainder;
#if _MSC_VER < 1923
#if _MSC_VER < 1923 || defined(__clang__)
const uint64 microseconds = udiv128(r.low, r.high, _rdtscFrequency, &remainder);
#else
const uint64 microseconds = _udiv128(r.high, r.low, _rdtscFrequency, &remainder);
@ -158,7 +159,7 @@ uint64 PPCTimer_getFromRDTSC()
#endif
uint64 remainder;
#if _MSC_VER < 1923
#if _MSC_VER < 1923 || defined(__clang__)
uint64 elapsedTick = udiv128(_rdtscAcc.low, _rdtscAcc.high, _rdtscFrequency, &remainder);
#else
uint64 elapsedTick = _udiv128(_rdtscAcc.high, _rdtscAcc.low, _rdtscFrequency, &remainder);

View file

@ -441,9 +441,9 @@ void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateF
ImGui::ProgressBar(percentLoaded, { -1, 0 }, "");
if (isPipelines)
text = fmt::format("{}/{} ({}%%)", g_shaderCacheLoaderState.loadedPipelines, g_shaderCacheLoaderState.pipelineFileCount, (int)(percentLoaded * 100));
text = fmt::format("{}/{} ({}%)", g_shaderCacheLoaderState.loadedPipelines, g_shaderCacheLoaderState.pipelineFileCount, (int)(percentLoaded * 100));
else
text = fmt::format("{}/{} ({}%%)", g_shaderCacheLoaderState.loadedShaderFiles, g_shaderCacheLoaderState.shaderFileCount, (int)(percentLoaded * 100));
text = fmt::format("{}/{} ({}%)", g_shaderCacheLoaderState.loadedShaderFiles, g_shaderCacheLoaderState.shaderFileCount, (int)(percentLoaded * 100));
ImGui::SetCursorPosX(width - ImGui::CalcTextSize(text.c_str()).x / 2);
ImGui::Text("%s", text.c_str());
ImGui::End();

View file

@ -145,7 +145,7 @@ uint32 LatteTexture_CalculateTextureDataHash(LatteTexture* hostTexture)
bool isCompressedFormat = hostTexture->IsCompressedFormat();
if( isCompressedFormat == false )
{
#if BOOST_OS_WINDOWS
#if BOOST_OS_WINDOWS
if (_cpuExtension_AVX2)
{
__m256i h256 = { 0 };
@ -157,7 +157,11 @@ uint32 LatteTexture_CalculateTextureDataHash(LatteTexture* hostTexture)
readPtr += (288 / 32);
h256 = _mm256_xor_si256(h256, temp);
}
#ifdef __clang__
hashVal = h256[0] + h256[1] + h256[2] + h256[3] + h256[4] + h256[5] + h256[6] + h256[7];
#else
hashVal = h256.m256i_u32[0] + h256.m256i_u32[1] + h256.m256i_u32[2] + h256.m256i_u32[3] + h256.m256i_u32[4] + h256.m256i_u32[5] + h256.m256i_u32[6] + h256.m256i_u32[7];
#endif
}
#else
if( false ) {}

View file

@ -378,7 +378,7 @@ void OpenGLRenderer::GetVendorInformation()
forceLog_printf("GL_RENDERER: %s", glRendererString ? glRendererString : "unknown");
forceLog_printf("GL_VERSION: %s", glVersionString ? glVersionString : "unknown");
if(boost::icontains(glVersionString, "Mesa") || IsRunningInWine())
if(boost::icontains(glVersionString, "Mesa"))
{
m_vendor = GfxVendor::Mesa;
return;

View file

@ -197,7 +197,9 @@ void VulkanRenderer::DetermineVendor()
break;
}
if (IsRunningInWine())
VkDriverId driverId = driverProperties.driverID;
if(driverId == VK_DRIVER_ID_MESA_RADV || driverId == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA)
m_vendor = GfxVendor::Mesa;
forceLog_printf("Using GPU: %s", properties.properties.deviceName);

View file

@ -219,7 +219,7 @@ namespace iosu
template <typename ... TArgs>
curl_slist* append_header_param(struct curl_slist* list, const char* format, TArgs&& ... args)
{
return curl_slist_append(list, fmt::format(format, std::forward<TArgs>(args)...).c_str());
return curl_slist_append(list, fmt::format(fmt::runtime(format), std::forward<TArgs>(args)...).c_str());
}
bool starts_with(const char* str, const char* pre)

View file

@ -84,7 +84,7 @@ namespace iosu
name = tmp;
}
g_friend_notifications.emplace_back(fmt::format(msg_format, name), 5000);
g_friend_notifications.emplace_back(fmt::format(fmt::runtime(msg_format), name), 5000);
}
}
}

View file

@ -28,7 +28,7 @@ namespace H264
// both of these are required to allow Breath of the Wild to playback the higher res (1080p) videos from the Switch version
// we mirror these hacks for user convenience and because there are no downsides
uint64 currentTitleId = CafeSystem::GetForegroundTitleId();
if (currentTitleId == 0x00050000101c9500 || currentTitleId == 0x00050000101c9400 || currentTitleId == 0x0005000e101c9300)
if (currentTitleId == 0x00050000101c9500 || currentTitleId == 0x00050000101c9400 || currentTitleId == 0x00050000101c9300)
return true;
return false;
}

View file

@ -36,7 +36,8 @@ enum class LogType : sint32
template <>
struct fmt::formatter<std::u8string_view> : formatter<string_view> {
template <typename FormatContext>
auto format(std::u8string_view v, FormatContext& ctx) {
auto format(std::u8string_view v, FormatContext& ctx)
{
string_view s((char*)v.data(), v.size());
return formatter<string_view>::format(s, ctx);
}
@ -52,18 +53,40 @@ bool cemuLog_log(LogType type, std::u8string_view text);
bool cemuLog_log(LogType type, std::wstring_view text);
void cemuLog_waitForFlush(); // wait until all log lines are written
template<typename TFmt, typename ... TArgs>
bool cemuLog_log(LogType type, TFmt format, TArgs&&... args)
template <typename T>
auto ForwardEnum(T t)
{
if constexpr (std::is_enum_v<T>)
return fmt::underlying(t);
else
return std::forward<T>(t);
}
template <typename... TArgs>
auto ForwardEnum(std::tuple<TArgs...> t)
{
return std::apply([](auto... x) { return std::make_tuple(ForwardEnum(x)...); }, t);
}
template<typename T, typename ... TArgs>
bool cemuLog_log(LogType type, std::basic_string<T> format, TArgs&&... args)
{
if (!cemuLog_isLoggingEnabled(type))
return false;
const auto format_view = fmt::to_string_view(format);
const auto text = fmt::vformat(format_view, fmt::make_args_checked<TArgs...>(format_view, args...));
const auto format_view = fmt::basic_string_view<T>(format);
const auto text = fmt::vformat(format_view, fmt::make_format_args<fmt::buffer_context<T>>(ForwardEnum(args)...));
cemuLog_log(type, std::basic_string_view(text.data(), text.size()));
return true;
}
template<typename T, typename ... TArgs>
bool cemuLog_log(LogType type, const T* format, TArgs&&... args)
{
auto format_str=std::basic_string<T>(format);
return cemuLog_log(type, format_str, std::forward<TArgs>(args)...);
}
// same as cemuLog_log, but only outputs in debug/release mode
template<typename TFmt, typename ... TArgs>
bool cemuLog_logDebug(LogType type, TFmt format, TArgs&&... args)

View file

@ -242,7 +242,7 @@ bool DownloadManager::_connect_queryAccountStatusAndServiceURLs()
NAPI::NAPI_ECSGetAccountStatus_Result accountStatusResult = NAPI::ECS_GetAccountStatus(authInfo);
if (accountStatusResult.apiError != NAPI_RESULT::SUCCESS)
{
cemuLog_log(LogType::Force, fmt::format("ECS - Failed to query account status (error: {0} {1})", accountStatusResult.apiError, accountStatusResult.serviceError));
cemuLog_log(LogType::Force, "ECS - Failed to query account status (error: {0} {1})", accountStatusResult.apiError, accountStatusResult.serviceError);
return false;
}
if (accountStatusResult.accountStatus == NAPI::NAPI_ECSGetAccountStatus_Result::AccountStatus::UNREGISTERED)

View file

@ -30,7 +30,7 @@ public:
[[nodiscard]] static fs::path GetPath(std::string_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != '/' && format[0] != '\\'));
std::string tmpPathStr = fmt::format(format, std::forward<TArgs>(args)...);
std::string tmpPathStr = fmt::format(fmt::runtime(format), std::forward<TArgs>(args)...);
std::basic_string_view<char8_t> s((const char8_t*)tmpPathStr.data(), tmpPathStr.size());
return s_path / fs::path(s);
}
@ -46,7 +46,7 @@ public:
[[nodiscard]] static fs::path GetMlcPath(std::string_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != '/' && format[0] != '\\'));
auto tmp = fmt::format(format, std::forward<TArgs>(args)...);
auto tmp = fmt::format(fmt::runtime(format), std::forward<TArgs>(args)...);
return GetMlcPath() / fs::path(_asUtf8(tmp));
}
@ -54,7 +54,7 @@ public:
[[nodiscard]] static fs::path GetMlcPath(std::wstring_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\'));
return GetMlcPath() / fmt::format(format, std::forward<TArgs>(args)...);
return GetMlcPath() / fmt::format(fmt::runtime(format), std::forward<TArgs>(args)...);
}
// get mlc path to default cemu root dir/mlc01

View file

@ -160,15 +160,15 @@ void CemuConfig::Load(XMLConfigParser& parser)
{
GameEntry entry{};
entry.rpx_file = boost::nowide::widen(rpx);
entry.title_id = element.get("title_id", 0LL);
entry.title_id = element.get<decltype(entry.title_id)>("title_id");
entry.legacy_name = boost::nowide::widen(element.get("name", ""));
entry.custom_name = element.get("custom_name", "");
entry.legacy_region = element.get("region", 0);
entry.legacy_version = element.get("version", 0);
entry.legacy_update_version = element.get("version", 0);
entry.legacy_dlc_version = element.get("dlc_version", 0);
entry.legacy_time_played = element.get("time_played", 0ULL);
entry.legacy_last_played = element.get("last_played", 0ULL);
entry.legacy_time_played = element.get<decltype(entry.legacy_time_played)>("time_played");
entry.legacy_last_played = element.get<decltype(entry.legacy_last_played)>("last_played");
entry.favorite = element.get("favorite", false);
game_cache_entries.emplace_back(entry);

View file

@ -217,7 +217,7 @@ void CemuApp::CreateDefaultFiles(bool first_start)
// check for mlc01 folder missing if custom path has been set
if (!fs::exists(mlc) && !first_start)
{
const std::wstring message = fmt::format(_(L"Your mlc01 folder seems to be missing.\n\nThis is where Cemu stores save files, game updates and other Wii U files.\n\nThe expected path is:\n{}\n\nDo you want to create the folder at the expected path?").ToStdWstring(), mlc);
const std::wstring message = fmt::format(fmt::runtime(_(L"Your mlc01 folder seems to be missing.\n\nThis is where Cemu stores save files, game updates and other Wii U files.\n\nThe expected path is:\n{}\n\nDo you want to create the folder at the expected path?").ToStdWstring()), mlc);
wxMessageDialog dialog(nullptr, message, "Error", wxCENTRE | wxYES_NO | wxCANCEL| wxICON_WARNING);
dialog.SetYesNoCancelLabels(_("Yes"), _("No"), _("Select a custom path"));
@ -293,7 +293,7 @@ void CemuApp::CreateDefaultFiles(bool first_start)
catch (const std::exception& ex)
{
std::stringstream errorMsg;
errorMsg << fmt::format(_("Couldn't create a required mlc01 subfolder or file!\n\nError: {0}\nTarget path:\n{1}").ToStdString(), ex.what(), boost::nowide::narrow(mlc));
errorMsg << fmt::format(fmt::runtime(_("Couldn't create a required mlc01 subfolder or file!\n\nError: {0}\nTarget path:\n{1}").ToStdString()), ex.what(), boost::nowide::narrow(mlc));
#if BOOST_OS_WINDOWS
const DWORD lastError = GetLastError();
@ -319,7 +319,7 @@ void CemuApp::CreateDefaultFiles(bool first_start)
catch (const std::exception& ex)
{
std::stringstream errorMsg;
errorMsg << fmt::format(_("Couldn't create a required cemu directory or file!\n\nError: {0}").ToStdString(), ex.what());
errorMsg << fmt::format(fmt::runtime(_("Couldn't create a required cemu directory or file!\n\nError: {0}").ToStdString()), ex.what());
#if BOOST_OS_WINDOWS
const DWORD lastError = GetLastError();

View file

@ -4,6 +4,7 @@
#include "gui/helpers/wxCustomEvents.h"
#include "util/helpers/helpers.h"
#include "gui/helpers/wxHelpers.h"
#include "gui/wxHelper.h"
#include "Cafe/Filesystem/WUD/wud.h"
#include <zip.h>
@ -518,7 +519,7 @@ void ChecksumTool::VerifyJsonEntry(const rapidjson::Document& doc)
file.flush();
file.close();
wxLaunchDefaultBrowser(fmt::format("file:{}", path));
wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", path)));
}
else
wxMessageBox(_("Can't open file to write!"), _("Error"), wxOK | wxCENTRE | wxICON_ERROR, this);

View file

@ -63,7 +63,7 @@ bool GameUpdateWindow::ParseUpdate(const fs::path& metaPath)
std::string typeStrCurrentlyInstalled = _GetTitleIdTypeStr(tmp.GetAppTitleId());
std::string wxMsg = wxHelper::MakeUTF8(_("It seems that there is already a title installed at the target location but it has a different type.\nCurrently installed: \'{}\' Installing: \'{}\'\n\nThis can happen for titles which were installed with very old Cemu versions.\nDo you still want to continue with the installation? It will replace the currently installed title."));
wxMessageDialog dialog(this, fmt::format(wxMsg, typeStrCurrentlyInstalled, typeStrToInstall), _("Warning"), wxCENTRE | wxYES_NO | wxICON_EXCLAMATION);
wxMessageDialog dialog(this, fmt::format(fmt::runtime(wxMsg), typeStrCurrentlyInstalled, typeStrToInstall), _("Warning"), wxCENTRE | wxYES_NO | wxICON_EXCLAMATION);
if (dialog.ShowModal() != wxID_YES)
return false;
}

View file

@ -1110,7 +1110,7 @@ void GeneralSettings2::OnAccountDelete(wxCommandEvent& event)
auto& account = obj->GetAccount();
const std::wstring format_str = _("Are you sure you want to delete the account {} with id {:x}?").ToStdWstring();
const std::wstring msg = fmt::format(format_str,
const std::wstring msg = fmt::format(fmt::runtime(format_str),
std::wstring{ account.GetMiiName() }, account.GetPersistentId());
const int answer = wxMessageBox(msg, _("Confirmation"), wxYES_NO | wxCENTRE | wxICON_QUESTION, this);

View file

@ -1803,7 +1803,7 @@ public:
void AddHeaderInfo(wxWindow* parent, wxSizer* sizer)
{
auto versionString = fmt::format(_("Cemu\nVersion {0}\nCompiled on {1}\nOriginal authors: {2}").ToStdString(), BUILD_VERSION_STRING, BUILD_DATE, "Exzap, Petergov");
auto versionString = fmt::format(fmt::runtime(_("Cemu\nVersion {0}\nCompiled on {1}\nOriginal authors: {2}").ToStdString()), BUILD_VERSION_STRING, BUILD_DATE, "Exzap, Petergov");
sizer->Add(new wxStaticText(parent, wxID_ANY, versionString), wxSizerFlags().Border(wxALL, 3).Border(wxTOP, 10));
sizer->Add(new wxHyperlinkCtrl(parent, -1, "https://cemu.info", "https://cemu.info"), wxSizerFlags().Expand().Border(wxTOP | wxBOTTOM, 3));
@ -1945,7 +1945,7 @@ public:
"/*****************************************************************************/\r\n"
);
delete fs;
wxLaunchDefaultBrowser(fmt::format("file:{}", _utf8Wrapper(tempPath)));
wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(tempPath))));
});
lineSizer->Add(noticeLink, 0);
lineSizer->Add(new wxStaticText(parent, -1, ")"), 0);

View file

@ -5,6 +5,7 @@
#include "Cafe/TitleList/GameInfo.h"
#include "util/helpers/helpers.h"
#include "gui/helpers/wxHelpers.h"
#include "gui/wxHelper.h"
#include "gui/components/wxTitleManagerList.h"
#include "gui/components/wxDownloadManagerList.h"
#include "gui/GameUpdateWindow.h"
@ -479,7 +480,7 @@ void TitleManager::OnSaveOpenDirectory(wxCommandEvent& event)
if (!fs::exists(target) || !fs::is_directory(target))
return;
wxLaunchDefaultBrowser(fmt::format("file:{}", _utf8Wrapper(target)));
wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(target))));
}
void TitleManager::OnSaveDelete(wxCommandEvent& event)

View file

@ -27,7 +27,7 @@ VulkanCanvas::VulkanCanvas(wxWindow* parent, const wxSize& size, bool is_main_wi
}
catch(const std::exception& ex)
{
const auto msg = fmt::format(_("Error when initializing Vulkan renderer:\n{}").ToStdString(), ex.what());
const auto msg = fmt::format(fmt::runtime(_("Error when initializing Vulkan renderer:\n{}").ToStdString()), ex.what());
forceLog_printf(const_cast<char*>(msg.c_str()));
wxMessageDialog dialog(this, msg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
dialog.ShowModal();

View file

@ -52,10 +52,17 @@ wxGameList::wxGameList(wxWindow* parent, wxWindowID id)
{
CreateListColumns();
const char transparent_bitmap[kIconWidth * kIconWidth * 4] = {0};
wxBitmap blank(transparent_bitmap, kIconWidth, kIconWidth);
blank.UseAlpha(true);
m_image_list = new wxImageList(kIconWidth, kIconWidth);
m_image_list->Add(blank);
wxListCtrl::SetImageList(m_image_list, wxIMAGE_LIST_NORMAL);
m_image_list_small = new wxImageList(kListIconWidth, kListIconWidth);
wxBitmap::Rescale(blank, {kListIconWidth, kListIconWidth});
m_image_list_small->Add(blank);
wxListCtrl::SetImageList(m_image_list_small, wxIMAGE_LIST_SMALL);
m_tooltip_window = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
@ -556,7 +563,7 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event)
{
fs::path path(gameInfo.GetBase().GetPath());
_stripPathFilename(path);
wxLaunchDefaultBrowser(fmt::format("file:{}", _utf8Wrapper(path)));
wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(path))));
break;
}
case kWikiPage:
@ -570,28 +577,28 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event)
wxASSERT(!tokens.empty());
const std::string company_code = gameInfo.GetBase().GetMetaInfo()->GetCompanyCode();
wxASSERT(company_code.size() >= 2);
wxLaunchDefaultBrowser(fmt::format("https://wiki.cemu.info/wiki/{}{}", *tokens.rbegin(), company_code.substr(company_code.size() - 2).c_str()));
wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("https://wiki.cemu.info/wiki/{}{}", *tokens.rbegin(), company_code.substr(company_code.size() - 2).c_str())));
}
break;
}
case kContextMenuSaveFolder:
{
wxLaunchDefaultBrowser(fmt::format("file:{}", _utf8Wrapper(gameInfo.GetSaveFolder())));
wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(gameInfo.GetSaveFolder()))));
break;
}
case kContextMenuUpdateFolder:
{
fs::path path(gameInfo.GetUpdate().GetPath());
_stripPathFilename(path);
wxLaunchDefaultBrowser(fmt::format("file:{}", _utf8Wrapper(path)));
wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(path))));
break;
}
case kContextMenuDLCFolder:
{
fs::path path(gameInfo.GetAOC().front().GetPath());
_stripPathFilename(path);
wxLaunchDefaultBrowser(fmt::format("file:{}", _utf8Wrapper(path)));
wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(path))));
break;
}
case kContextMenuEditGraphicPacks:
@ -857,13 +864,12 @@ void wxGameList::OnGameEntryUpdatedByTitleId(wxTitleIdEvent& event)
isNewEntry = true;
}
int icon = 0;
int icon_small = 0;
bool hasIcon = QueryIconForTitle(baseTitleId, icon, icon_small);
int icon = 0; /* 0 is the default empty icon */
int icon_small = 0; /* 0 is the default empty icon */
QueryIconForTitle(baseTitleId, icon, icon_small);
if (m_style == Style::kList)
{
if(hasIcon)
SetItemColumnImage(index, ColumnIcon, icon_small);
SetItem(index, ColumnName, wxHelper::FromUtf8(GetNameByTitleId(baseTitleId)));
@ -912,12 +918,10 @@ void wxGameList::OnGameEntryUpdatedByTitleId(wxTitleIdEvent& event)
}
else if (m_style == Style::kIcons)
{
if(hasIcon)
SetItemImage(index, icon);
}
else if (m_style == Style::kSmallIcons)
{
if (hasIcon)
SetItemImage(index, icon_small);
}
if (isNewEntry)

View file

@ -293,23 +293,23 @@ void wxTitleManagerList::OnConvertToCompressedFormat(uint64 titleId)
std::string msg = wxHelper::MakeUTF8(_("The following content will be converted to a compressed Wii U archive file (.wua):\n \n"));
if (titleInfo_base.IsValid())
msg.append(fmt::format(wxHelper::MakeUTF8(_("Base game: {}")), _utf8Wrapper(titleInfo_base.GetPath())));
msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Base game: {}"))), _utf8Wrapper(titleInfo_base.GetPath())));
else
msg.append(fmt::format(wxHelper::MakeUTF8(_("Base game: Not installed"))));
msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Base game: Not installed")))));
msg.append("\n");
if (titleInfo_update.IsValid())
msg.append(fmt::format(wxHelper::MakeUTF8(_("Update: {}")), _utf8Wrapper(titleInfo_update.GetPath())));
msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Update: {}"))), _utf8Wrapper(titleInfo_update.GetPath())));
else
msg.append(fmt::format(wxHelper::MakeUTF8(_("Update: Not installed"))));
msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Update: Not installed")))));
msg.append("\n");
if (titleInfo_aoc.IsValid())
msg.append(fmt::format(wxHelper::MakeUTF8(_("DLC: {}")), _utf8Wrapper(titleInfo_aoc.GetPath())));
msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("DLC: {}"))), _utf8Wrapper(titleInfo_aoc.GetPath())));
else
msg.append(fmt::format(wxHelper::MakeUTF8(_("DLC: Not installed"))));
msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("DLC: Not installed")))));
const int answer = wxMessageBox(wxString::FromUTF8(msg), _("Confirmation"), wxOK | wxCANCEL | wxCENTRE | wxICON_QUESTION, this);
if (answer != wxOK)
@ -852,7 +852,7 @@ void wxTitleManagerList::OnContextMenuSelected(wxCommandEvent& event)
case kContextMenuOpenDirectory:
{
const auto path = fs::is_directory(entry->path) ? entry->path : entry->path.parent_path();
wxLaunchDefaultBrowser(fmt::format("file:{}", _utf8Wrapper(path)));
wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(path))));
}
break;
case kContextMenuDelete:

View file

@ -71,7 +71,7 @@ void wxCreateAccountDialog::OnOK(wxCommandEvent& event)
const auto id = GetPersistentId();
if(id < Account::kMinPersistendId)
{
wxMessageBox(fmt::format(_("The persistent id must be greater than {:x}!").ToStdString(), Account::kMinPersistendId),
wxMessageBox(fmt::format(fmt::runtime(_("The persistent id must be greater than {:x}!").ToStdString()), Account::kMinPersistendId),
_("Error"), wxOK | wxCENTRE | wxICON_ERROR, this);
return;
}
@ -79,7 +79,7 @@ void wxCreateAccountDialog::OnOK(wxCommandEvent& event)
const auto& account = Account::GetAccount(id);
if(account.GetPersistentId() == id)
{
const std::wstring msg = fmt::format(_("The persistent id {:x} is already in use by account {}!").ToStdWstring(),
const std::wstring msg = fmt::format(fmt::runtime(_("The persistent id {:x} is already in use by account {}!").ToStdWstring()),
account.GetPersistentId(), std::wstring{ account.GetMiiName() });
wxMessageBox(msg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR, this);
return;

View file

@ -48,13 +48,13 @@ template<typename ...TArgs>
wxString wxStringFormat2(const wxString& format, TArgs&&...args)
{
// ignores locale?
return fmt::format(format.ToStdString(), std::forward<TArgs>(args)...);
return fmt::format(fmt::runtime(format.ToStdString()), std::forward<TArgs>(args)...);
}
template<typename ...TArgs>
wxString wxStringFormat2W(const wxString& format, TArgs&&...args)
{
return fmt::format(format.ToStdWstring(), std::forward<TArgs>(args)...);
return fmt::format(fmt::runtime(format.ToStdWstring()), std::forward<TArgs>(args)...);
}
// executes a function when destroying the obj

Binary file not shown.

View file

@ -35,7 +35,7 @@ public:
void appendFmt(const char* format_str, Args... args)
{
char* buf = (char*)(m_strBuffer + m_offsetEnd);
char* r = fmt::format_to(buf, format_str, std::forward<Args>(args)...);
char* r = fmt::format_to(buf, fmt::runtime(format_str), std::forward<Args>(args)...);
cemu_assert_debug(r <= (char*)(m_strBuffer + N));
m_offsetEnd += (uint32)(r - buf);
}

View file

@ -20,7 +20,7 @@ public:
template<typename TFmt, typename ... TArgs>
void addFmt(const TFmt& format, TArgs&&... args)
{
auto r = fmt::vformat_to_n((char*)(this->str + this->length), (size_t)(this->limit - this->length), fmt::to_string_view(format), fmt::make_args_checked<TArgs...>(format, args...));
auto r = fmt::vformat_to_n((char*)(this->str + this->length), (size_t)(this->limit - this->length), fmt::detail::to_string_view(format), fmt::make_format_args(args...));
this->length += (uint32)r.size;
}