From 1373c76eb9eb8251f6f12f69b4b26c8bd3f06518 Mon Sep 17 00:00:00 2001 From: bslhq Date: Mon, 5 Sep 2022 00:19:27 +0800 Subject: [PATCH 01/11] fix H264_IsBotW() return false while BotW's TitleRegion is JP (#174) --- src/Cafe/OS/libs/h264_avc/H264Dec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cafe/OS/libs/h264_avc/H264Dec.cpp b/src/Cafe/OS/libs/h264_avc/H264Dec.cpp index d15f6683..085a2e69 100644 --- a/src/Cafe/OS/libs/h264_avc/H264Dec.cpp +++ b/src/Cafe/OS/libs/h264_avc/H264Dec.cpp @@ -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; } From 4ed18a65c320cef3ef05d4f62130927aaa6becbb Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Sun, 4 Sep 2022 22:23:24 +0200 Subject: [PATCH 02/11] Name output binary Cemu_ and always place it in bin/ (#179) --- .github/workflows/build.yml | 14 +++++++++++--- .github/workflows/deploy_experimental.yml | 2 +- .gitignore | 7 ++++--- src/CMakeLists.txt | 6 ++++-- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 926ed4a9..29af2648 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -86,7 +86,11 @@ jobs: run: | 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' }} @@ -188,10 +192,14 @@ jobs: run: | 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' }} with: name: cemu-bin-windows-x64 - path: ./bin/Cemu.exe \ No newline at end of file + path: ./bin/Cemu.exe diff --git a/.github/workflows/deploy_experimental.yml b/.github/workflows/deploy_experimental.yml index 32000986..afe3dee7 100644 --- a/.github/workflows/deploy_experimental.yml +++ b/.github/workflows/deploy_experimental.yml @@ -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 diff --git a/.gitignore b/.gitignore index 6feed97f..ce7f91c2 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ca677710..d3bf8aec 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -75,8 +75,10 @@ endif() set_property(TARGET CemuBin PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$: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_$>" ) target_link_libraries(CemuBin PRIVATE From a54a3ec74ea95326096feb46317fb9c6cd277742 Mon Sep 17 00:00:00 2001 From: Jun Bo Bi <21069675+jambonmcyeah@users.noreply.github.com> Date: Sun, 4 Sep 2022 17:15:40 -0400 Subject: [PATCH 03/11] Fix build using clang-cl on windows and improve driver detection (#129) --- CMakeLists.txt | 10 +++++++++- dependencies/DirectX_2010/XAudio2.h | 7 ++++++- .../ih264d/common/x86/ih264_platform_macros.h | 5 ++++- src/Cafe/HW/Espresso/PPCTimer.cpp | 5 +++-- src/Cafe/HW/Latte/Core/LatteTextureCache.cpp | 6 +++++- .../Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 2 +- .../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 6 ++++-- src/resource/cemu.rc | Bin 9690 -> 4689 bytes 8 files changed, 32 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a47fe8af..b001421d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/dependencies/DirectX_2010/XAudio2.h b/dependencies/DirectX_2010/XAudio2.h index db0ebd8f..a42c0afc 100644 --- a/dependencies/DirectX_2010/XAudio2.h +++ b/dependencies/DirectX_2010/XAudio2.h @@ -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 diff --git a/dependencies/ih264d/common/x86/ih264_platform_macros.h b/dependencies/ih264d/common/x86/ih264_platform_macros.h index 0b15cf5a..ebc1b106 100644 --- a/dependencies/ih264d/common/x86/ih264_platform_macros.h +++ b/dependencies/ih264d/common/x86/ih264_platform_macros.h @@ -40,6 +40,9 @@ #include #include +#if defined(_MSC_VER) && defined(__clang__) +#include +#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) { diff --git a/src/Cafe/HW/Espresso/PPCTimer.cpp b/src/Cafe/HW/Espresso/PPCTimer.cpp index bcf1a58d..2a1a7669 100644 --- a/src/Cafe/HW/Espresso/PPCTimer.cpp +++ b/src/Cafe/HW/Espresso/PPCTimer.cpp @@ -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); diff --git a/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp b/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp index 151f0661..2caa2cd0 100644 --- a/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp @@ -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 ) {} diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp index 80c72918..269f30e8 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp @@ -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; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index e033d954..7c81a3c9 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -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); @@ -216,7 +218,7 @@ void VulkanRenderer::DetermineVendor() else { forceLog_printf("Driver version (as stored in device info): %08X", properties.properties.driverVersion); - + if(m_vendor == GfxVendor::Nvidia) { // if the driver does not support the extension, diff --git a/src/resource/cemu.rc b/src/resource/cemu.rc index 4781111df8a49cd45832f9e3529faf50f585f3e2..aaa2a850d9a44b4ac6a95a0c75646763b26e983b 100644 GIT binary patch literal 4689 zcmcIoUvr{J5Pv>C#hiJGwZRyZOXcnjWpue9c>FQRmQ@t$pw!}wHNeJH?KiuJ`$+c{ zt_Kh>(UhBWd4QRw`E^fsPfs`h{{7G8B^rh^&SDlMXdK3=AEDl-PiR3X;eJBqh?AJ5 zd`3__Sx9G5Iwz>HeS5hbw3ZD?I-8Rqqy#A=+i_LR^en8XrlCK1_S3Ly z>NbF!@DeJ)LI$PI0cR_eED3V(qoWx;-BmH_luLQFhUbui_L<@*R7#jBrC^A6tZ;HO zAcLd{2OplRB=FNHX`=I#ex>Z0qBxz(kxv(Yp!VjjSsEh-cZC7^HFw$kTl(GQda-JOjIqrRWy|UOM^8goCviqwo~q*%&>C z$r45EnZyawRP@b{Qi9fzKZCdpLJrh~AwuJn6XdVgQ8@FHkWm!oKwyKFAJQ1XG!Em0 z&;-F-KZ;QN0@GF8l7`-cp?X@+G_E>#sJaBDnpLB6M@%LWTQE)6U6j{pnlI!z`Mp;>$meVVH0hMTE;AO!q*32tKtw&uXzm2f<`pC)Vt?wom@TW|B%ecjTJ-ar{* zZ)BN$O~;jlqtU@2t2K*>oGUH=)-LoGdu3-&YsT2T$Ldds_gePK!v1O}pGjRj&@bC9{p-VHz4-L zIHpy8q{C@;@s>PP{xq$9bj=X-wgmC0x;>{3e==+&6z}WGz#c00J>=l)K;H(dr{b&Z`!}NZ>A8nf+((CHbEIHx{Famps6G;L%`{c3)FZBL*yc|N+UmE zyuzq`rO||N>PH6TIq^vkxc4&ZWZ_3WwtnH^Vwnh5hxjXWklzHp5P*eRvm;sR(S)A`9oeVbVm6R^!0?EEeBo5JA~|8^pHT?`w~!A(DWwqPRpp zsXq%JkA420gNp?@+@~?PC-+!;1OC21SDkjdgv`>_Pf4IwPgNWx%MRHV7+}lmjEYd_sN>RwCGm8Wtg2z^LGbbhmnhLXVOe z^og&rRn3Odv<`oS>buzUFg^&cn-5-BaU5)IL-U8>p>L3d^`k z&Kcju>wU((d+!O?Yw@G;W=k^ry7Ku~`Gv$4uBKXEA9@qz0eZ<{m7osbRwe9Y5NJDApR@VOU#e7x~J{$rL1+{?eVwu?r9|*^@HQO?CG-~9H*|hcZ^S2 IvZu!X59tHG!vFvP literal 9690 zcmdU#Yi}Ay6o%((EA>BY$(KYezQk#i_M0!*af5AYu#;AikZ(|{7%aezBlWkpecl-k zyUXs{h7v@zT4r{3cIG|zGc)}2_o`cUkvnkL?!xt5&keX+Zb;iHZ3B1b&RmD5ZTB5l zr?8xJ8BoyBc3$cwY#Oyiu=ZW%`B_Fd`4@Rw;g(4`o5*i_p6zf z75BR<`R_H>Gyi4FkEGc)UCq^9!=1Ptx9^Tz(;d4Ctvl2YUDf?cOP${Xw?#{px*-y( z<+}`>m66+nQYb#~r+qZndC$Hr+7J+qlbB8oCHMUtvc>q#LaCIT9D$XS8-`e*p)cQ}4PzxO?ss zzp~CdckascIODnPexhy7-Mcrw|D>i25_Wg(dHQY2{w|qe)9s>p!S3qV*a;T6jqWwU zQ{@tlzqq2pFB^<;jGi~$Z~l7WXRXqDNb3pZp4Vk-Y0_Syy}?(T%<%n~264wYv|MsC zG=|Q~2#dWyI^8kuBn|P~2>D%mYmbnfq$$5EU%d~XBloA*f;(CxJg=lHZ!8ZjU)dk^ z9r9&Fd)MoMq#e=o)_RVIAKB|% zRGRrqAzOE^;Z=}8j80Z2|6cRD-yCsHR-njM#U_qZNaur2(!TYcMqD(l7$B`O{^N`& zbVV)bg1k}BOI}$*8JWH+phMC4Lkex4BtzT0=rDbK10SX9eeB~LyrI_g^?TmQVx+yY zpL{9Q;dNsaZTHA2im}g2N0NMRf>@qk89=bu3sApAXPS8OU)(!N>z|K*55IW;4NY`O z+OvyZNq_R_m_PS}w%njq$~mPyNsgD@4@9IaZuv!JkgZW1$&2r@j#KD)2Q52ek7~Ym zxk`%wRu<)O_Fkp#b);03?dkm%wC{O8p(m4Q)+Z{j`v|9lf2nwXY;!1UoMn!@48Meq zw$RIDHd$ikK6iICdyKLO(Z-C3rk&@Rk7Ji!&kU9H=4sky{97(fOQI1%JzJ@@o_w{U zcwQDVx!$_>(Y#OIH}ILABELOp%*p=A_YrU7jPew}*<^M_tvdRuEFi?UUFyP>d?U+N zyXG)&mF{8Eva*7QJHe}MqRB_hk)2B(Pb)>`kB|30pzqIqq^I^5X3ZS(Qy~xDb_ZPB zpen-uIF`jDkH%cz^*mM76G!U!+OUGyz{;y$K4~wlbwCBLbb?nB5AsF|Bdm|Vzasi7 zGCbUWEzw`AKE;Og7f0X=V_V;N_6EBGHISv}j^EcoyoHpKy=;_xAG-yfBP1)1l$cqT zq3o#*@03woq2*mL_9nbu{%EGh=~36nsMg$%+^@)2%zIm3D<2-wdYvLa?G%Uyr7=dW zB9nVK!7r4&7MIA|uel<=(mLXXJVa{^aS~K)1wN^OfSDB>EvppI; zL?;_#vP_Rzw-@fBtl@qZNIL46Q^t&G)efoqYuJsT$#N z#IoUCu6@7OP}WgoF>(H5I+kroTjD7)?~gTL7Rye{s=;X5lNpRGDrtAxp$T@cSfaJ^ z8dvaj0dI^puIat*Wc**Qx}mc&B3f<}FBG#k$JmXIIF4vPND+Mt4{q|xmdUZQZ?i4g z99b(~?IxaMjcqRZtL!Sc<-K5sb<7Qxt1K#iMRUuW_Q)5ArhIzBPMY>~Ca>k9rwlK` z3i)xmYDn{hh?u{^Tohfm*w>xUD`u5Xjd;09MldOv@Vq!W6mvh%tYtbcsbD!F+g5g* zq-Rl7ggwJss8BRj24O4z$Mq?uK>N*&6#ldiNm5o+pVjVT3UvN8oDqLm1thU8UIIP# zkHd~#*n4?g0()r9q~^plEQ*3le2_A|GG02Ia1`l~@`m)jsm>6z3e!$ejNEGTp+K5l zw09bIBXzQ;JWrnVDcE(&SqHaP%S9A?dF)ziX^o&*H!THPBfa;rTTx#8KhAj6FHb=@ zLn#y4wR#CF5qZ=N@~RbNmX6dlc&+oPx1g;)m~#aEnGS!x|FIq1u+y$n-j3Jwu%}*x zP^aI!aI}J!yv@<;+4TD<2$c=!Tw1Hg-#sT^KEO#yT|3X|6AMEZm-FYO{G7ao&L=j= zq>H7!?d7fYd=m{7M`K*c+WawI_*4B0PHwfs-={1S@5R|7%sK^BMyx%uL#%2O8x!Iq zzt5jU8|u?x)_N~UHvXrF@?h;{D0ZKX&Ledqq5XWFPM(k7u6PS;B{JXQUDm~&YA@GH zD2c|_J64AMw1@uJpy>AhJ@@!;|8UXCz@%=b|KVbMO!9cS>Oxp-6Z-dtPS&&kXUWQ4 GBmE0{ipE_4 From f2ec0b40835ccaca01a99a5c84ee8f8e6a4bb32c Mon Sep 17 00:00:00 2001 From: bitscher Date: Mon, 5 Sep 2022 05:42:15 -0700 Subject: [PATCH 04/11] Fix the reloading of game cache from settings.xml (#169) std::is_same_v does not evaluate the same on Linux Clang and MSVC. MSVC returns true but Clang and GCC both returns false resulting in failing to read the game id from the XML file and therefore rebuilding the cache. Solution: Don't rely on the type of 0LL and 0ULL literals but explicitly provide the type of the field we are trying to read. --- src/config/CemuConfig.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config/CemuConfig.cpp b/src/config/CemuConfig.cpp index 0cbd3c97..bc1f9f97 100644 --- a/src/config/CemuConfig.cpp +++ b/src/config/CemuConfig.cpp @@ -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("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("time_played"); + entry.legacy_last_played = element.get("last_played"); entry.favorite = element.get("favorite", false); game_cache_entries.emplace_back(entry); From 0ed4fdcd789081f210d9587b24af7e5c050cfc55 Mon Sep 17 00:00:00 2001 From: SSimco <37044560+SSimco@users.noreply.github.com> Date: Mon, 5 Sep 2022 15:48:44 +0300 Subject: [PATCH 05/11] Update fmt version to 9.1.0 (#177) --- .../vcpkg_overlay_ports/fmt/portfile.cmake | 6 ++-- src/Cafe/IOSU/legacy/iosu_boss.cpp | 2 +- src/Cafe/IOSU/legacy/iosu_fpd.cpp | 2 +- src/Cemu/Logging/CemuLogging.h | 33 ++++++++++++++++--- .../Tools/DownloadManager/DownloadManager.cpp | 2 +- src/config/ActiveSettings.h | 6 ++-- src/gui/CemuApp.cpp | 6 ++-- src/gui/GameUpdateWindow.cpp | 2 +- src/gui/GeneralSettings2.cpp | 2 +- src/gui/MainWindow.cpp | 2 +- src/gui/canvas/VulkanCanvas.cpp | 2 +- src/gui/components/wxTitleManagerList.cpp | 12 +++---- .../CreateAccount/wxCreateAccountDialog.cpp | 4 +-- src/gui/helpers/wxHelpers.h | 4 +-- src/util/Zir/EmitterGLSL/ZpIREmitGLSL.cpp | 2 +- src/util/helpers/StringBuf.h | 2 +- 16 files changed, 56 insertions(+), 33 deletions(-) diff --git a/dependencies/vcpkg_overlay_ports/fmt/portfile.cmake b/dependencies/vcpkg_overlay_ports/fmt/portfile.cmake index aef43b47..e3edc0f6 100644 --- a/dependencies/vcpkg_overlay_ports/fmt/portfile.cmake +++ b/dependencies/vcpkg_overlay_ports/fmt/portfile.cmake @@ -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( diff --git a/src/Cafe/IOSU/legacy/iosu_boss.cpp b/src/Cafe/IOSU/legacy/iosu_boss.cpp index 4c99f5df..22c11eba 100644 --- a/src/Cafe/IOSU/legacy/iosu_boss.cpp +++ b/src/Cafe/IOSU/legacy/iosu_boss.cpp @@ -219,7 +219,7 @@ namespace iosu template curl_slist* append_header_param(struct curl_slist* list, const char* format, TArgs&& ... args) { - return curl_slist_append(list, fmt::format(format, std::forward(args)...).c_str()); + return curl_slist_append(list, fmt::format(fmt::runtime(format), std::forward(args)...).c_str()); } bool starts_with(const char* str, const char* pre) diff --git a/src/Cafe/IOSU/legacy/iosu_fpd.cpp b/src/Cafe/IOSU/legacy/iosu_fpd.cpp index 678c187f..ec8733ab 100644 --- a/src/Cafe/IOSU/legacy/iosu_fpd.cpp +++ b/src/Cafe/IOSU/legacy/iosu_fpd.cpp @@ -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); } } } diff --git a/src/Cemu/Logging/CemuLogging.h b/src/Cemu/Logging/CemuLogging.h index 4238b638..d89d9cec 100644 --- a/src/Cemu/Logging/CemuLogging.h +++ b/src/Cemu/Logging/CemuLogging.h @@ -36,7 +36,8 @@ enum class LogType : sint32 template <> struct fmt::formatter : formatter { template - 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::format(s, ctx); } @@ -52,17 +53,39 @@ 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 -bool cemuLog_log(LogType type, TFmt format, TArgs&&... args) +template +auto ForwardEnum(T t) +{ + if constexpr (std::is_enum_v) + return fmt::underlying(t); + else + return std::forward(t); +} + +template +auto ForwardEnum(std::tuple t) +{ + return std::apply([](auto... x) { return std::make_tuple(ForwardEnum(x)...); }, t); +} + +template +bool cemuLog_log(LogType type, std::basic_string 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(format_view, args...)); + const auto format_view = fmt::basic_string_view(format); + const auto text = fmt::vformat(format_view, fmt::make_format_args>(ForwardEnum(args)...)); cemuLog_log(type, std::basic_string_view(text.data(), text.size())); return true; } + +template +bool cemuLog_log(LogType type, const T* format, TArgs&&... args) +{ + auto format_str=std::basic_string(format); + return cemuLog_log(type, format_str, std::forward(args)...); +} // same as cemuLog_log, but only outputs in debug/release mode template diff --git a/src/Cemu/Tools/DownloadManager/DownloadManager.cpp b/src/Cemu/Tools/DownloadManager/DownloadManager.cpp index 45b66eed..f953844a 100644 --- a/src/Cemu/Tools/DownloadManager/DownloadManager.cpp +++ b/src/Cemu/Tools/DownloadManager/DownloadManager.cpp @@ -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) diff --git a/src/config/ActiveSettings.h b/src/config/ActiveSettings.h index 44b5f509..95ceae16 100644 --- a/src/config/ActiveSettings.h +++ b/src/config/ActiveSettings.h @@ -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(args)...); + std::string tmpPathStr = fmt::format(fmt::runtime(format), std::forward(args)...); std::basic_string_view 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(args)...); + auto tmp = fmt::format(fmt::runtime(format), std::forward(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(args)...); + return GetMlcPath() / fmt::format(fmt::runtime(format), std::forward(args)...); } // get mlc path to default cemu root dir/mlc01 diff --git a/src/gui/CemuApp.cpp b/src/gui/CemuApp.cpp index 17e31f7a..e78b30b3 100644 --- a/src/gui/CemuApp.cpp +++ b/src/gui/CemuApp.cpp @@ -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(); diff --git a/src/gui/GameUpdateWindow.cpp b/src/gui/GameUpdateWindow.cpp index a42d4087..c689dd6f 100644 --- a/src/gui/GameUpdateWindow.cpp +++ b/src/gui/GameUpdateWindow.cpp @@ -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; } diff --git a/src/gui/GeneralSettings2.cpp b/src/gui/GeneralSettings2.cpp index 012b8557..78e1feec 100644 --- a/src/gui/GeneralSettings2.cpp +++ b/src/gui/GeneralSettings2.cpp @@ -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); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index b23a5ca7..8f26f810 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -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)); diff --git a/src/gui/canvas/VulkanCanvas.cpp b/src/gui/canvas/VulkanCanvas.cpp index dfad8c9a..b8faa8c7 100644 --- a/src/gui/canvas/VulkanCanvas.cpp +++ b/src/gui/canvas/VulkanCanvas.cpp @@ -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(msg.c_str())); wxMessageDialog dialog(this, msg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR); dialog.ShowModal(); diff --git a/src/gui/components/wxTitleManagerList.cpp b/src/gui/components/wxTitleManagerList.cpp index 9ac31bce..c8c1d6e4 100644 --- a/src/gui/components/wxTitleManagerList.cpp +++ b/src/gui/components/wxTitleManagerList.cpp @@ -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) diff --git a/src/gui/dialogs/CreateAccount/wxCreateAccountDialog.cpp b/src/gui/dialogs/CreateAccount/wxCreateAccountDialog.cpp index 49e7f5ec..71b56637 100644 --- a/src/gui/dialogs/CreateAccount/wxCreateAccountDialog.cpp +++ b/src/gui/dialogs/CreateAccount/wxCreateAccountDialog.cpp @@ -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; diff --git a/src/gui/helpers/wxHelpers.h b/src/gui/helpers/wxHelpers.h index 96c8dcfa..8fd0f8a9 100644 --- a/src/gui/helpers/wxHelpers.h +++ b/src/gui/helpers/wxHelpers.h @@ -48,13 +48,13 @@ template wxString wxStringFormat2(const wxString& format, TArgs&&...args) { // ignores locale? - return fmt::format(format.ToStdString(), std::forward(args)...); + return fmt::format(fmt::runtime(format.ToStdString()), std::forward(args)...); } template wxString wxStringFormat2W(const wxString& format, TArgs&&...args) { - return fmt::format(format.ToStdWstring(), std::forward(args)...); + return fmt::format(fmt::runtime(format.ToStdWstring()), std::forward(args)...); } // executes a function when destroying the obj diff --git a/src/util/Zir/EmitterGLSL/ZpIREmitGLSL.cpp b/src/util/Zir/EmitterGLSL/ZpIREmitGLSL.cpp index aab2c49e..0b0c2dc5 100644 --- a/src/util/Zir/EmitterGLSL/ZpIREmitGLSL.cpp +++ b/src/util/Zir/EmitterGLSL/ZpIREmitGLSL.cpp @@ -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)...); + char* r = fmt::format_to(buf, fmt::runtime(format_str), std::forward(args)...); cemu_assert_debug(r <= (char*)(m_strBuffer + N)); m_offsetEnd += (uint32)(r - buf); } diff --git a/src/util/helpers/StringBuf.h b/src/util/helpers/StringBuf.h index 3744caa4..8c7b1645 100644 --- a/src/util/helpers/StringBuf.h +++ b/src/util/helpers/StringBuf.h @@ -20,7 +20,7 @@ public: template 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(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; } From 917b80941e555a2b95b9150f9dba197ef75e2fc3 Mon Sep 17 00:00:00 2001 From: bitscher Date: Mon, 5 Sep 2022 05:51:24 -0700 Subject: [PATCH 06/11] Fix broken icon layout when loading Cemu on Gnome (#171) The icon view was all broken from having entries inserted with non loaded icons, resulting in a layout that had the wrong size and no obvious way to trigger a resizing without incurring a costly window redraw. Solution: When the icon is not yet loaded insert a transparent placeholder icon. --- src/gui/components/wxGameList.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/gui/components/wxGameList.cpp b/src/gui/components/wxGameList.cpp index a9d2946c..665e1d97 100644 --- a/src/gui/components/wxGameList.cpp +++ b/src/gui/components/wxGameList.cpp @@ -51,11 +51,18 @@ wxGameList::wxGameList(wxWindow* parent, wxWindowID id) : wxListCtrl(parent, id, wxDefaultPosition, wxDefaultSize, GetStyleFlags(Style::kList)), m_style(Style::kList) { 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); @@ -857,15 +864,14 @@ 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); - + SetItemColumnImage(index, ColumnIcon, icon_small); + SetItem(index, ColumnName, wxHelper::FromUtf8(GetNameByTitleId(baseTitleId))); SetItem(index, ColumnVersion, fmt::format("{}", gameInfo.GetVersion())); @@ -912,13 +918,11 @@ void wxGameList::OnGameEntryUpdatedByTitleId(wxTitleIdEvent& event) } else if (m_style == Style::kIcons) { - if(hasIcon) - SetItemImage(index, icon); + SetItemImage(index, icon); } else if (m_style == Style::kSmallIcons) { - if (hasIcon) - SetItemImage(index, icon_small); + SetItemImage(index, icon_small); } if (isNewEntry) UpdateItemColors(index); From 391334d64e31e1640cf9f3e939d698709f0952f8 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Mon, 5 Sep 2022 15:36:06 +0200 Subject: [PATCH 07/11] Use ANSI encoding for cemu.rc (#184) Clang has issues with utf16 and MSVC does not like utf8. So ANSI it is. --- src/resource/cemu.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resource/cemu.rc b/src/resource/cemu.rc index aaa2a850..9ff27732 100644 --- a/src/resource/cemu.rc +++ b/src/resource/cemu.rc @@ -1,4 +1,4 @@ -// Microsoft Visual C++ generated resource script. +// Microsoft Visual C++ generated resource script. // #include "resource/resource.h" From 728bd3178b73dc037dfedfceed06a17776a448eb Mon Sep 17 00:00:00 2001 From: Andrea Pappacoda Date: Mon, 5 Sep 2022 15:38:25 +0200 Subject: [PATCH 08/11] build: update required fmt version (#183) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b001421d..e9f7458e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,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 From 5a69505d138453e25eef25f74521c533ef88445d Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Mon, 5 Sep 2022 15:53:50 +0200 Subject: [PATCH 09/11] Fix double %% on shader compilation screen It was a relic from previously using sprintf where % has to be escaped with %% --- src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index bcdaffa2..ebf425bc 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -441,9 +441,9 @@ void LatteShaderCache_ShowProgress(const std::function & 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(); From 0030fa44a5bea51d422bd7d5f413bf0bdc8c7b64 Mon Sep 17 00:00:00 2001 From: Haxorzz Date: Mon, 5 Sep 2022 13:57:02 +0000 Subject: [PATCH 10/11] Slight tweaks to greek translation (#180) --- dist/linux/info.cemu.Cemu.metainfo.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/linux/info.cemu.Cemu.metainfo.xml b/dist/linux/info.cemu.Cemu.metainfo.xml index 4fff800a..d270a8ab 100644 --- a/dist/linux/info.cemu.Cemu.metainfo.xml +++ b/dist/linux/info.cemu.Cemu.metainfo.xml @@ -21,7 +21,7 @@

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++.

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++.

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++.

-

Το Cemu είναι ένας προσομοιωτής της κονσόλας Nintendo Wii U που υποστηρίζει τεπίσημα παιχνίδια, καθώς και μη επίσημα προγράμματα ("homebrew"), για το Wii U. Δημιουργήθηκε από τον Exzap σε C/C++.

+

Το Cemu είναι ένας προσομοιωτής της κονσόλας Nintendo Wii U που προσομοιώνει επίσημα παιχνίδια, καθώς και μη επίσημα προγράμματα ("homebrew") του Wii U. Δημιουργήθηκε από τον Exzap σε C/C++.

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++.

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++.

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++.

@@ -30,7 +30,7 @@

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.

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.

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.

-

Ο προσομοιωτής αυτός στοχεύει τόσο στην ακρίβεια, όσο και στην ταχύτητα. Βελτιώνεται συνεχώς με νέες δυνατότητες και διορθώσεις που τον καθιστούν πιο βολικό, εύκολο στην χρήση και συμβατό με περισσότερα παιχνίδια.

+

Ο προσομοιωτής αυτός στοχεύει τόσο στην ακρίβεια, όσο και στην ταχύτητα, και βελτιώνεται συνεχώς με νέες δυνατότητες και διορθώσεις που τον καθιστούν πιο βολικό, εύκολο στην χρήση και συμβατό με περισσότερα παιχνίδια.

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.

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.

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à.

@@ -39,7 +39,7 @@

Er wird seit Anfang 2015 entwickelt.

Il a été écrit à partir de zéro et son développement a débuté vers le début de l'année 2015.

Ontwikkeling van Cemu begon ongeveer in het voorjaar van 2015.

-

Το Cemu βρίσκεται υπό ανάπτυξη από το 2015.

+

Αρχισε απο το τίποτα και βρίσκεται υπό ανάπτυξη από το 2015.

Fue escrito desde cero y el desarrollo del proyecto comenzó aproximadamente a principios de 2015.

Foi escrito do zero e o desenvolvimento do projeto começou aproximadamente a princípio de 2015.

È stato scritto da zero e lo sviluppo del progetto è cominciato intorno all'inizio del 2015.

From e5d7d5d1736019d08e1ff8d9bd2e385330c5b7de Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Mon, 5 Sep 2022 18:42:24 +0200 Subject: [PATCH 11/11] Use utf8 aware string conversion for wxLaunchDefaultBrowser() (#185) --- src/gui/ChecksumTool.cpp | 3 ++- src/gui/MainWindow.cpp | 2 +- src/gui/TitleManager.cpp | 3 ++- src/gui/components/wxGameList.cpp | 10 +++++----- src/gui/components/wxTitleManagerList.cpp | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/gui/ChecksumTool.cpp b/src/gui/ChecksumTool.cpp index 74422c9b..b8393330 100644 --- a/src/gui/ChecksumTool.cpp +++ b/src/gui/ChecksumTool.cpp @@ -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 @@ -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); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 8f26f810..ec821ce5 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -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); diff --git a/src/gui/TitleManager.cpp b/src/gui/TitleManager.cpp index 370786b6..b643ab8f 100644 --- a/src/gui/TitleManager.cpp +++ b/src/gui/TitleManager.cpp @@ -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) diff --git a/src/gui/components/wxGameList.cpp b/src/gui/components/wxGameList.cpp index 665e1d97..87eb5cdd 100644 --- a/src/gui/components/wxGameList.cpp +++ b/src/gui/components/wxGameList.cpp @@ -563,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: @@ -577,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: diff --git a/src/gui/components/wxTitleManagerList.cpp b/src/gui/components/wxTitleManagerList.cpp index c8c1d6e4..99e6ed94 100644 --- a/src/gui/components/wxTitleManagerList.cpp +++ b/src/gui/components/wxTitleManagerList.cpp @@ -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: