Compare commits

...

217 commits

Author SHA1 Message Date
goeiecool9999
e68c31e5fb Fix path text encoding creating shortcuts on windows
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 57s
also fix a memory leak
(hopefully)
fixes: #1627
2025-07-02 13:31:21 +02:00
qurious-pixel
35ecfa3f54
build: Fix glslang dependency for Fedora 42 (#1622)
Some checks failed
Generate translation template / generate-pot (push) Failing after 47s
Build check / build (push) Has been cancelled
2025-07-01 05:00:11 +02:00
oltolm
6c392d5a22
UI: Fix assertions (#1623)
Some checks failed
Generate translation template / generate-pot (push) Failing after 41s
Build check / build (push) Has been cancelled
2025-06-30 00:15:23 +02:00
Colin Kinloch
9fb3c76b76
UI: Include wx button header for wxWidgets 3.3 compatibility (#1621) 2025-06-29 19:36:22 +02:00
Exzap
13ccf9a160 MMU: Fix bit width for 32bit MMIO reads
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 31s
This resolves the ghost input issue in N64 virtual console
2025-06-28 21:43:40 +02:00
Exzap
7db2b77983 CPU: Implement more instructions in interpreter + various fixes
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 44s
All of the changes are verified against real hardware, except for the byte string instructions
2025-06-28 14:54:31 +02:00
capitalistspz
0a121c97c7
Input: Detect Classic Controller Pro as Classic Controller (#1614)
Some checks failed
Generate translation template / generate-pot (push) Failing after 44s
Build check / build (push) Has been cancelled
2025-06-26 17:25:34 +02:00
Exzap
e91740cf29 coreinit: Make sure thread deallocation runs before join returns
Some checks failed
Generate translation template / generate-pot (push) Failing after 36s
Build check / build (push) Has been cancelled
Fixes crash in Coaster Crazy Deluxe
2025-06-22 23:34:41 +02:00
Exzap
4f4c9594ac GX2: Fix command buffer padding writing out of bounds 2025-06-22 22:17:29 +02:00
Exzap
5a4731f919 HLE: Make HLE table access thread-safe
Previous code could sometimes resize the vector while a read access was happening
2025-06-22 20:56:47 +02:00
Exzap
522b5ef260 UI: Correctly interpret supporter names as UTF8
Some checks failed
Generate translation template / generate-pot (push) Failing after 40s
Build check / build (push) Has been cancelled
2025-06-21 18:58:58 +02:00
capitalistspz
057ef4598e
cmake: Respect ENABLE_HIDAPI option (#1604)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 2m36s
2025-06-20 13:32:41 +02:00
Joshua de Reeper
4f4412b334
nsyshid: Play Emulated Portal Audio via Mono Audio (#1478)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 42s
2025-06-19 23:30:19 +02:00
Exverge
00ff5549d9
General aarch64 improvements & Apple Silicon support (#1255)
Some checks failed
Generate translation template / generate-pot (push) Failing after 1m1s
Build check / build (push) Has been cancelled
2025-06-18 10:36:05 +02:00
oltolm
c8ffff8f41
Replace basic_string<> of betype with std::vector (#1601) 2025-06-18 10:34:06 +02:00
oltolm
2f02fda9ea
Refactor to use Microsoft::WRL::ComPtr (#1599)
Some checks failed
Generate translation template / generate-pot (push) Failing after 2m59s
Build check / build (push) Has been cancelled
2025-06-16 23:25:06 +02:00
oltolm
da98aa4176
UI: Make code compatible with wxWidgets 3.3 (#1598)
Some checks failed
Build check / build (push) Has been cancelled
Generate translation template / generate-pot (push) Has been cancelled
2025-06-14 20:38:53 +02:00
oltolm
95dc590d2c
UI: Improve wxListView sorting and add sort order indicators (#1597)
Some checks are pending
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Waiting to run
2025-06-14 10:25:56 +02:00
goeiecool9999
f3fe6f3455
GameList: Allow sorting by more columns (#1571)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 25s
2025-06-13 12:47:46 +02:00
oltolm
2eec6b44c3
UI: Use wxListView instead of wxListCtrl (#1584)
Some checks failed
Generate translation template / generate-pot (push) Failing after 36s
Build check / build (push) Has been cancelled
2025-06-10 08:15:25 +02:00
Luminyx
3eff2d4a60
GraphicPack: Allow overlay for code folder (#1574) 2025-06-10 08:03:18 +02:00
Wiichele
d427b59019
boss: Use HTTP/1.1 instead of default (#1593)
Some checks failed
Generate translation template / generate-pot (push) Failing after 34s
Build check / build (push) Has been cancelled
2025-06-08 07:16:09 +02:00
neebyA
a184a04e56
macOS: Minor UI improvements (#1575)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 30s
2025-06-07 22:42:49 +02:00
Colin Kinloch
162fdabb9d
debug: "verbose" command line argument to log to stdout (#1587)
Some checks failed
Generate translation template / generate-pot (push) Failing after 1s
Build check / build (push) Has been cancelled
2025-06-02 01:38:21 +02:00
Colin Kinloch
c8045f7f04
UI: wxCAPTION flag on input API dialog to fix kwin (#1586)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s
2025-06-01 03:57:33 +02:00
oltolm
6df3e1742e
UI: Fix wxWidgets assert in InfinityPage (#1582)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 37s
2025-05-31 16:29:07 +02:00
oltolm
152b790242
UI: Use wxID_ANY and wxNOT_FOUND instead of hardcoding -1 (#1581)
Some checks failed
Generate translation template / generate-pot (push) Failing after 1s
Build check / build (push) Has been cancelled
2025-05-30 01:39:02 +02:00
capitalistspz
02616bf6be
build: Allow Linux builds to be made without Bluez (#1579)
Some checks failed
Generate translation template / generate-pot (push) Failing after 1s
Build check / build (push) Has been cancelled
2025-05-28 15:18:01 +02:00
Exzap
7168d20cde FST: Refactor IV handling
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s
2025-05-27 16:51:46 +02:00
Exzap
783d88a892 coreinit: Fix race condition in __FSAIoctlResponseCallback
Some checks failed
Generate translation template / generate-pot (push) Failing after 1s
Build check / build (push) Has been cancelled
2025-05-17 21:35:42 +02:00
Exzap
28ea70b6d8 GX2+TCL: Reimplement command buffer submission
- GX2 utilizes TCL(.rpl) API for command submission instead of directly writing to an internal GPU fifo
- Submission & retire timestamps are correctly implemented as incremental counters
- Command buffering behaviour matches console
- Fixes race conditions on aarch64
2025-05-17 21:35:42 +02:00
Exzap
96765e4ac6 Latte: Refactor clear code 2025-05-17 20:47:01 +02:00
gamerbross
111637a9fd
nsyshid: Skylander 360 Portal small optimization and code formatting (#1568)
Some checks failed
Generate translation template / generate-pot (push) Failing after 1s
Build check / build (push) Has been cancelled
2025-05-15 19:58:43 +02:00
Issa
bed5fdb195
UI: Disable Ctrl+Q shortcut on non-macOS platforms to prevent accidental exits during gameplay (#1565)
Some checks failed
Generate translation template / generate-pot (push) Failing after 1s
Build check / build (push) Has been cancelled
2025-05-13 03:38:11 +02:00
shinra-electric
996539fce8
CI: Bump MoltenVK to v1.3.0 (#1559)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s
2025-05-12 20:12:40 +02:00
Mefiresu
05617a332b
dmae: Implement 16bit endian swap for DMAECopyMem (#1564)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s
2025-05-12 18:16:14 +02:00
Joshua de Reeper
caef34f2ff
nsyshid: Add Kamen Rider USB Device to Whitelist (#1560)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s
2025-05-12 09:28:01 +02:00
neebyA
f801fc1fe8
Fix Mac build for Xcode 16.3 (#1558)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 2s
2025-05-12 00:08:25 +02:00
Exzap
61484598fc Vulkan: Use per-pipeline buffer robustness
Some checks failed
Generate translation template / generate-pot (push) Failing after 2s
Build check / build (push) Has been cancelled
And if the extension is not supported then fallback to enabling robust buffer access for all shaders.
2025-05-10 09:49:21 +02:00
SSimco
081ebead5f
Add AArch64 recompiler backend (#1556)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s
2025-05-09 12:47:22 +02:00
Exzap
d13dab0fd8 Vulkan: During shutdown submit buffer before deleting resources 2025-05-09 10:00:38 +02:00
Exzap
ba09daf328 PPCRec: Reenable float copy optimization
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s
2025-05-09 02:06:08 +02:00
Exzap
557aff4024 PPCRec: Implement PSQ scaling 2025-05-08 08:29:47 +02:00
Exzap
de542410c2
PPCRec: Rework floating point instructions (#1554)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s
2025-05-08 03:48:22 +02:00
gamerbross
33d5c6d490
nsyshid: Add Skylander Xbox 360 Portal support (#1550)
Some checks failed
Generate translation template / generate-pot (push) Failing after 1s
Build check / build (push) Has been cancelled
2025-05-04 21:44:46 +02:00
Crementif
352a918494
debug: add CLI option to have multi-core interpreter (#1553)
This option still allows you to have proper stack traces for crashes or for the PPC debugger, but is a lot faster then the really slow interpreter (especially when loading into large games like BotW where there has to be a lot of asset decompressing). It makes memory access breakpoints much more brittle though, so it's not a perfect option.

Normal users should of course stick with using the recompiler.
2025-05-04 18:04:26 +02:00
Crementif
d083fc0470 Reorder PPCInterpreter memory layout to keep plugin compatibility
Commit b089ae5b32 changed the PPCInterpreter struct that external plugins rely on to hook Cemu through e.g. the exported "osLib_registerHLEFunction". This commit moves some unused values down so that it keeps the same memory layout as before the PPC recompiler rework.
2025-05-04 17:19:56 +02:00
neebyA
fa7ae84314
macOS: Fix browsing of directory paths with spaces (#1546)
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s
2025-05-04 13:46:01 +02:00
Shikakiben
00099c5ecc
Set StartupWMClass in .desktop file (#1552) 2025-05-04 13:29:27 +02:00
goeiecool9999
e6a64aadda undo revert of style improvement
Some checks failed
Build check / build (push) Failing after 0s
Generate translation template / generate-pot (push) Failing after 1s
2025-04-27 17:03:00 +02:00
goeiecool9999
a5f3558b79 Revert "fix building with fmt11 and GCC"
This reverts commit 372c314f06.
It broke formatting in an attempt to fix GCC builds.
Some other change (perhaps dependency updates) has resolved the issue.
2025-04-27 16:57:22 +02:00
Exzap
b089ae5b32
PowerPC recompiler rework (#641)
Some checks failed
Build check / build (push) Failing after 0s
Generate translation template / generate-pot (push) Failing after 0s
2025-04-26 17:59:32 +02:00
Exzap
06233e3462 UI: Fix wxWidgets debug assert
Some checks failed
Build check / build (push) Failing after 0s
Generate translation template / generate-pot (push) Failing after 36s
Adding the same component multiple times is not allowed. Use sizers instead
2025-04-16 14:36:11 +02:00
Exzap
4972381edc Vulkan: Fix imgui validation error when sRGB framebuffer is used 2025-04-15 22:46:19 +02:00
Exzap
cd6eb1097b Vulkan: Fix a validation error + minor code refactor
We were using VK_EXT_DEPTH_CLIP_ENABLE but didn't actually request it.

Also fixed an assert when closing Cemu caused by incorrectly tracking the number of allocated pipelines
2025-04-15 21:10:11 +02:00
Exzap
c4eab08f30 Update vcpkg
Some checks failed
Build check / build (push) Failing after 0s
Generate translation template / generate-pot (push) Failing after 1s
2025-04-03 19:11:14 +02:00
mitoposter
57ff99ce53
cubeb: Show default device option even if enumerating devices fails (#1515)
Some checks failed
Build check / build (push) Failing after 0s
Generate translation template / generate-pot (push) Failing after 36s
2025-03-19 17:06:55 +01:00
capitalistspz
8b5cafa98e
Wiimote/L2CAP: More accurate descriptions for descriptors (#1512) 2025-03-13 01:09:45 +01:00
Crementif
186e92221a
debugger: allow printing registers using logging breakpoint placeholders (#1510)
This allows a savy user, developer or modder to change the comment field of a logging breakpoint to include placeholders such as {r3} or {f3} to log the register values whenever that code is hit.
2025-03-07 23:40:17 +01:00
goeiecool9999
31d2db6f78 OpenGL: Add explicit/matching qualifiers in output shader interface
fixes issues with old intel drivers
2025-03-05 22:23:06 +01:00
capitalistspz
ebb5ab53e2
Add menu item for opening shader cache directory (#1494)
Some checks failed
Build check / build (push) Failing after 0s
Generate translation template / generate-pot (push) Failing after 8s
2025-02-14 20:56:51 +01:00
capitalistspz
a6fb0a48eb
BUILD.md: Provide more info about build configuration flags (#1486) 2025-02-04 10:56:33 +01:00
Exzap
ec2d7c086a coreinit: Clean up time functions
Some checks failed
Generate translation template / generate-pot (push) Failing after 34s
Build check / build (push) Failing after 40s
2025-01-30 03:49:17 +01:00
Exzap
c714e8cb6b coreinit: Time to tick conversion is unsigned
The result is treated as signed in most cases, but the calculation uses unsigned arithmetic.

As a concrete example where this matters, DS VC passes -1 (2^64-1) to OSWaitEventWithTimeout which internally causes an overflow. But only with unsigned arithmetic this will result in a large positive number that behaves like the intended infinite timeout. With signed arithmetic the result is negative and the events will timeout immediately.
2025-01-30 03:32:24 +01:00
goeiecool9999
e834515f43
Vulkan: Improve post-shutdown cleanup and minor improvements (#1401) 2025-01-23 21:20:03 +01:00
Exzap
4f9eea07e0 CI: Update action version 2025-01-23 21:06:07 +01:00
goeiecool9999
372c314f06 fix building with fmt11 and GCC 2025-01-23 21:03:11 +01:00
Exzap
5bd253a1f8 Revert "Fix building against fmt 11.1.0 (#1474)"
Reverting commit 4ac65159ef because game profile enums use the stringifying formatters from config.h and are not supposed to store raw integers
2025-01-23 17:33:06 +01:00
Alexandre Bouvier
4ac65159ef
Fix building against fmt 11.1.0 (#1474) 2025-01-16 12:54:29 +01:00
Joshua de Reeper
eab1b24320
nsyshid: Initialise interface index as 0 (#1473) 2025-01-12 20:20:48 +01:00
Exzap
07cd402531
Update precompiled.h 2025-01-12 18:33:15 +01:00
Joshua de Reeper
0a59085021
nsyshid: Make Libusb the Windows backend (#1471) 2025-01-12 14:33:24 +01:00
Exzap
8dd809d725
Latte: Implement better index caching (#1443) 2025-01-12 12:39:02 +01:00
rcaridade145
1923b7a7c4
Vulkan: Added R5_G6_B5_UNORM to supported readback formats (#1430) 2025-01-12 12:37:56 +01:00
brysma1
f61539a262
Update build instructions for fedora and add troubleshooting step for alternative architectures (#1468) 2025-01-08 04:22:55 +01:00
Crementif
92021db230
Use one CPU emulation thread for --force-interpreter (#1467) 2025-01-05 04:08:13 +01:00
Crementif
4b792aa4d2
debug: Fix shader dumping (#1466) 2025-01-04 20:38:42 +01:00
capitalistspz
1e30d72658
build: Add ALLOW_PORTABLE flag (#1464)
* Add ALLOW_PORTABLE cmake flag
* Also check that `portable` is a directory
2024-12-30 18:49:51 +01:00
Mike Lothian
2b0cbf7f6b
Fix building against Boost 1.87.0 (#1455) 2024-12-18 22:15:42 +01:00
goeiecool9999
3738ccd2e6
Play bootSound.btsnd while shaders/pipelines are compiling (#1047) 2024-12-18 15:55:23 +01:00
Exzap
b53b223ba9 Vulkan: Use cache for sampler objects 2024-12-16 13:05:22 +01:00
Exzap
6aaad1eb83 Debugger: Added right click context menu to disasm view + small fixes 2024-12-16 13:05:22 +01:00
Exzap
adab729f43 UI: Correctly handle unicode paths during save export 2024-12-16 13:05:22 +01:00
capitalistspz
dd0af0a56f
Linux: Allow connecting Wiimotes via L2CAP (#1353) 2024-12-07 12:02:40 +01:00
Exzap
934cb54605 Properly check if MLC is writeable 2024-12-07 10:26:17 +01:00
Exzap
356cf0e5e0 Multiple smaller HLE improvements 2024-12-07 10:26:17 +01:00
Exzap
e2d0871ca3 Camera: Set error code in CAMInit
Fixes Hunter's Trophy 2 crashing on boot
2024-12-07 10:26:17 +01:00
Cemu-Language CI
40d9664d1c Update translation files 2024-12-07 07:14:20 +00:00
neebyA
eca7374567
Set version for macOS bundle (#1431) 2024-12-02 05:19:15 +01:00
Jeremy Kescher
80a6057512
build: Fix linker failure with glslang 15.0.0 (#1436) 2024-12-02 01:01:22 +01:00
capitalistspz
0735237686
Input: Move pairing dialog button and source (#1424) 2024-11-30 23:05:50 +01:00
capitalistspz
90eb2e01f4
nsyshid/dimensions: add missing return (#1425) 2024-11-22 13:43:12 +01:00
Exzap
409f12b13a coreinit: Fix calculation of thread total awake time 2024-11-21 20:34:24 +01:00
Exzap
7b513f1744 Latte: Add workaround for infinite loop in Fatal Frame shaders 2024-11-21 20:34:24 +01:00
Exzap
c3e29fb619 Latte: Add support for shader instructions MIN_UINT and MAX_UINT
Seen in the eShop version of Fatal Frame
Also made some warnings less spammy since this game seems to trigger it a lot
2024-11-21 20:34:24 +01:00
Exzap
2065ac5f63 GfxPack: Better logging messages for diagnosing problems in rules.txt 2024-11-21 20:34:24 +01:00
goeiecool9999
269d5b9aab
Vulkan: Make scaling shaders compatible + fixes (#1392) 2024-11-16 10:02:43 +01:00
Exzap
6f9f3d52ea CI: Remove outdated workflow 2024-11-13 06:38:17 +01:00
Exzap
719c631f13 config: Fix receive_untested_updates using the wrong default 2024-11-13 06:29:24 +01:00
Exzap
66658351c1 erreula: Rework implementation and fix bugs
- ErrEula doesn't disappear on its own anymore. The expected behavior is for the game to call Disappear once a button has been selected. This fixes issues where the dialog would softlock in some games
- Modernized code a bit
- Added a subtle fade in/out effect
2024-11-13 06:29:24 +01:00
Exzap
a5717e1b11 FST: Refactoring to fix a read bug + verify all reads
- Fixes a bug where corrupted data would be returned when reading files from unhashed sections with non-block aligned offset or size
- Added hash checks for all reads where possible. This means that FST now can automatically catch corruptions when they are encountered while reading from the volume
2024-11-13 06:29:23 +01:00
Joshua de Reeper
ca2e0a7c31
nsyshid: Add support for emulated Dimensions Toypad (#1371) 2024-11-11 08:58:01 +01:00
capitalistspz
2e829479d9
nsyshid/libusb: correct error message formatting and print error string on open fail (#1407) 2024-11-09 06:22:13 +01:00
capitalistspz
4ac1ab162a
procui: swap tickDelay and priority args in callbacks (#1408) 2024-11-09 06:21:06 +01:00
SamoZ256
813f9148b1
macOS: Fix absolute path to libusb dylib (#1405) 2024-11-07 07:09:35 +01:00
SamoZ256
9941e00b54
macOS: Fix libusb path for bundle (#1403) 2024-11-05 22:22:00 +01:00
Exzap
1c49a8a1ba nn_nfp: Implement GetNfpReadOnlyInfo and fix deactivate event
Fixes Amiibos not being detected in MK8
2024-11-01 22:47:19 +01:00
capitalistspz
47001ad233
Make MEMPTR<T> a little more T*-like (#1385) 2024-10-30 23:10:32 +01:00
goeiecool9999
459fd5d9bb
input: Fix crash when closing add controller dialog before search completes (#1386) 2024-10-28 09:37:30 +01:00
capitalistspz
63e1289bb5
Windows: Save icons to Cemu user data directory (#1390) 2024-10-25 18:48:21 +02:00
goeiecool9999
f9a4b2dbb1
input: Add option to make show screen button a toggle (#1383) 2024-10-19 01:56:56 +02:00
goeiecool9999
d6575455ee Linux: Fix crash on invalid command-line arguments
use std::cout instead of wxMessageBox which does not work when wxWidgets has not been initialised yet
2024-10-17 22:24:20 +02:00
goeiecool9999
3acd0c4f2c
Vulkan: Protect against uniform var ringbuffer overflow (#1378) 2024-10-14 14:03:36 +02:00
Alexandre Bouvier
6dc73f5d79
Add support for fmt 11 (#1366) 2024-10-03 08:48:25 +02:00
capitalistspz
8508c62540
Various smaller code improvements (#1343) 2024-09-17 02:00:26 +02:00
Andrea Toska
adffd53dbd
boss: Fix BOSS not honoring the proxy_server setting (#1344) 2024-09-16 12:40:38 +02:00
goeiecool9999
a05bdb172d
Vulkan: Add explicit synchronization on frame boundaries (#1290) 2024-09-15 20:23:11 +02:00
Cemu-Language CI
1a4d9660e7 Update translation files 2024-09-08 15:40:13 +00:00
Exzap
ba54d1540c Fix "Receive untested updates" option not being synced to config 2024-09-08 17:21:20 +02:00
MoonlightWave-12
0d8fd7c0dc
appimage: Do not copy libstdc++.so.6 to usr/lib/ (#1319) 2024-09-02 21:22:38 +02:00
Joshua de Reeper
b06990607d
nsysnet: Avoid crash on NULL timeout in select (#1324) 2024-09-02 16:20:16 +02:00
squidbus
9a53b19403
CI+build: Improve macOS builds (#1310) 2024-08-28 11:06:49 +02:00
Cemu-Language CI
03484d2146 Update translation files 2024-08-28 09:05:50 +00:00
Exzap
1234e2c118
Preparations for 2.1 (#1306) 2024-08-26 11:43:38 +02:00
Cemu-Language CI
d7f39aab05 Update translation files 2024-08-26 09:16:11 +00:00
bl
dc9d99b03b
nn_fp: Implement GetMyComment and UpdateCommentAsync (#1173) 2024-08-24 21:03:03 +02:00
Exzap
573c98b2f8 GfxPack: Workaround for invisible detail panel
Fixes #1307
There is probably a better way to calculate the maximum width. But this suffices for now as a workaround
2024-08-23 19:26:33 +02:00
Cemu-Language CI
9e53c1ce27 Update translation files 2024-08-22 05:17:01 +00:00
Exzap
958137a301 vpad: Keep second channel empty if no extra GamePad is configured 2024-08-15 18:27:08 +02:00
20943204920434
294a6de779
Update appimage.sh to support runtime libstdc++.so.6 loading (#1292)
Add checkrt plugin in order to detect the right libstdc++.so.6 version to load.
2024-08-15 16:22:41 +02:00
Exzap
2843da4479 padscore: Invoke sampling callbacks every 5ms
This fixes high input latency in games like Pokemon Rumble U which update input via the sampling callbacks
2024-08-15 05:00:09 +02:00
Exzap
b0bab273e2 padscore: Simulate queue behaviour for KPADRead 2024-08-15 02:16:24 +02:00
Skyth (Asilkan)
c49296acdc
Add support for iterating directories in graphics pack content folders. (#1288) 2024-08-13 15:53:04 +02:00
goeiecool9999
a6d8c0fb9f
CI: Fix macOS build (#1291) 2024-08-13 15:48:13 +02:00
Exzap
e551f8f524 Fix clang compile error 2024-08-13 05:57:55 +02:00
Exzap
f52970c822 Vulkan: Allow RGBA16F texture format with SRGB bit 2024-08-13 04:47:43 +02:00
Exzap
e02cc42d67 COS: Implement PPC va_list, va_arg and update related functions 2024-08-13 01:00:56 +02:00
goeiecool9999
9812a47cb1
clang-format: Put class braces on a new line (#1283) 2024-08-08 19:35:50 +02:00
Exzap
7fd532436d CI: Manual unshallow of vcpkg is no longer needed 2024-08-08 16:07:45 +02:00
Exzap
598298cb3d Vulkan: Fix stencil front mask 2024-08-08 16:07:45 +02:00
goeiecool9999
54e695a6e8
git: unshallow vcpkg, shallow vulkan-headers and imgui (#1282) 2024-08-08 15:58:24 +02:00
Exzap
bf2208145b Enable async shader compile by default 2024-08-07 16:35:15 +02:00
Exzap
b52b676413 vcpkg: Automatically unshallow submodule 2024-08-07 02:50:24 +02:00
Exzap
2129644781 Remove shaderCache directory
The location of the shaderCache path is different for non-portable cases so let's not confuse the user by shipping with a precreated directory that isn't actually used
2024-08-06 23:02:28 +02:00
Exzap
d81eb952a4 nsyshid: Silence some logging in release builds 2024-08-06 22:58:23 +02:00
Exzap
1575866eca Vulkan: Add R32_X8_FLOAT format 2024-08-04 14:47:51 +02:00
Joshua de Reeper
517e68fe57
nsyshid: Tidyups and Fixes (#1275) 2024-07-28 18:50:20 +02:00
Exzap
593da5ed79 CI: Workaround for MoltenVK crash
1.2.10 and later crash during descriptor set creation. So for now let's stick with the older version
2024-07-27 18:35:23 +02:00
Exzap
c73fa3761c Fix compatibility with GCC 2024-07-27 04:45:36 +02:00
Exzap
5328e9eb10 CPU: Fix overflow bit calculation in SUBFO instruction
Since rD can overlap with rA or rB the result needs to be stored in a temporary
2024-07-26 06:03:00 +02:00
Exzap
47f1dcf996 debugger: Add symbol support to PPC stack traces
Also moved the declaration to precompiled.h instead of redefining it wherever it is used
2024-07-26 06:03:00 +02:00
Exzap
252429933f debugger: Slightly optimize symbol list updates 2024-07-26 06:03:00 +02:00
Exzap
026d547dcc Use HTTP 1.1 in Nintendo API requests 2024-07-26 06:03:00 +02:00
Exzap
f1685eab66
h264: Use asynchronous decoding when possible (#1257) 2024-07-26 05:48:42 +02:00
Exverge
4b9c7c0d30
Update Fedora build instructions (#1269) 2024-07-24 08:32:40 +02:00
capitalistspz
e65abf4898
Suppress unnecessary GTK messages (#1267) 2024-07-23 22:18:55 +02:00
Joshua de Reeper
a1c1a608d7
nsyshid: Emulate Infinity Base (#1246) 2024-07-23 03:18:48 +02:00
Exzap
64232ffdbd
Windows default to non-portable + Reworked MLC handling and related UI (#1252) 2024-07-23 03:13:36 +02:00
goeiecool9999
7522c8470e
resource: move fontawesome to .rodata (#1259) 2024-07-19 14:24:46 +02:00
Exzap
9d366937cd Workaround for compiler issue with Visual Studio 17.10 2024-07-07 08:55:26 +02:00
Joshua de Reeper
5209677f2f
nsyshid: Add SetProtocol and SetReport support for libusb backend (#1243) 2024-07-02 03:32:37 +02:00
Colin Kinloch
64b0b85ed5
Create GamePad window at correct size (#1247)
Don't change the size on canvas initialization
2024-06-29 22:31:47 +02:00
Joshua de Reeper
aefbb918be
nsyshid: Skylander emulation fixes and code cleanup (#1244) 2024-06-28 15:44:49 +02:00
Joshua de Reeper
93b58ae6f7
nsyshid: Add infrastructure and support for emulating Skylander Portal (#971) 2024-06-28 00:55:20 +02:00
Exzap
f3d20832c1 Avoid an unhandled exception when mlc path is invalid 2024-06-25 19:28:21 +02:00
Exzap
d4c2c3d209 nsyskbd: Stub KBDGetKey
Fixes MSX VC games freezing on boot
2024-06-25 15:50:06 +02:00
Exzap
1672f969bb Latte: Add support for vertex format used by Rabbids Land 2024-06-09 17:53:34 +02:00
goeiecool9999
6772b1993f
vcpkg: Update dependencies (#1229) 2024-06-05 16:34:42 +02:00
Exzap
16070458ed Logging: Restructure menu + allow toggeling APIErrors logtype
The logtype "APIErrors" previously was always enabled. This option is intended to help homebrew developers notice mistakes in how they use CafeOS API. But some commercial games trigger these a lot and cause log.txt bloat (e.g. seen in XCX). Thus this commit changes it so that it's off by default and instead can be toggled if desired.

Additionally in this commit:
- COS module logging options are no longer translatable (our debug logging is fundamentally English)
- Restructured the log menu and moved the logging options that are mainly of interest to Cemu devs into a separate submenu
2024-06-02 21:39:40 +02:00
Exzap
5f825a1fa8 Latte: Always allow views with the same format as base texture
Fixes crash/assert in VC N64 titles
2024-06-02 21:39:40 +02:00
Colin Kinloch
d33337d539
Fix GamePad window size (#1224) 2024-05-29 00:36:12 +02:00
Exzap
f576269ed0 Refactor legacy method of emulating thread events 2024-05-29 00:34:11 +02:00
Exzap
da8fd5b7c7 nn_save: Refactor and modernize code 2024-05-29 00:07:37 +02:00
Exzap
1ee9d5c78c coreinit: Tweak JD2019 workaround to avoid XCX softlock 2024-05-27 01:24:24 +02:00
goeiecool9999
aadd2f4a1a
Input: Assign profile name correctly on save (#1217) 2024-05-25 01:48:53 +02:00
qurious-pixel
149fe10a4e
CI+MacOS: Use libusb dylib from vcpkg (#1219) 2024-05-25 01:48:17 +02:00
Cemu-Language CI
917ea2ef23 Update translation files 2024-05-23 17:48:04 +00:00
Exzap
b048a1fd9e Use CURLOPT_USERAGENT instead of manually setting User-Agent 2024-05-22 05:08:03 +02:00
Exzap
a059338890
Add initial NTAG and NFC implementation 2024-05-22 04:45:10 +02:00
goeiecool9999
523a1652df
OpenGL: Restore ProgramBinary cache for GL shaders (#1209) 2024-05-22 04:23:33 +02:00
goeiecool9999
c913a59c7a
TitleList: Add homebrew title type (#1203) 2024-05-22 04:11:02 +02:00
GaryOderNichts
964d2acb44 Filestream_unix: Include cstdarg 2024-05-18 20:47:09 +02:00
GaryOderNichts
a115921b43 Fix inconsistency with int types 2024-05-18 20:37:37 +02:00
GaryOderNichts
eb1983daa6 nfc: Remove backup path 2024-05-18 20:37:37 +02:00
GaryOderNichts
8fe69cd0fb Properly implement NFC result codes 2024-05-18 20:37:37 +02:00
GaryOderNichts
41fe598e33 nfc: Implement UID filter 2024-05-18 20:37:37 +02:00
GaryOderNichts
8e8431113a ntag: Implement NTAGWrite 2024-05-18 20:37:37 +02:00
GaryOderNichts
1c6b209692 Add initial ntag and nfc implementation 2024-05-18 20:37:37 +02:00
GaryOderNichts
84e78088fb PPCCoreCallback: Add support for stack args if GPR limit is reached 2024-05-18 20:37:37 +02:00
splatoon1enjoyer
13b90874f9
Fix commas edge case in strings when parsing an assembly line (#1201) 2024-05-13 16:52:25 +02:00
Exzap
cf41c3b136
CI: Use submodule commit of vcpkg 2024-05-10 09:33:32 +02:00
Xphalnos
97d8cf4ba3
vcpkg: Update libraries (#1198) 2024-05-10 09:32:06 +02:00
GaryOderNichts
b2a6cccc89
nn_act: Implement GetTransferableId (#1197) 2024-05-09 12:12:34 +02:00
GaryOderNichts
10d553e1c9
zlib125: Implement deflateInit_ (#1194) 2024-05-07 11:56:28 +02:00
Exzap
3f8722f0a6 Track online-enable and network-service settings per-account instead of globally 2024-05-06 18:18:42 +02:00
Exzap
065fb7eb58 coreinit: Add reschedule special case to avoid a deadlock
Fixes Just Dance 2019 locking up on boot
2024-05-06 09:15:36 +02:00
capitalistspz
7d6d417354
Input: Improve setting of dpd_enable_fg (#1127) 2024-05-06 03:27:30 +02:00
Exzap
bd13d4bdc3 nn_act: Make AcquireToken gracefully fail in offline mode + refactor 2024-05-05 17:05:11 +02:00
Exzap
bf37a8281e CI: Update action versions 2024-05-05 14:06:26 +02:00
Exzap
dd3ed56509 nn_save: Fix inverted condition preventing accessing other title's saves 2024-05-05 10:05:35 +02:00
Exzap
70afe3a033 nlibcurl: Use separte logging type 2024-05-05 09:11:08 +02:00
goeiecool9999
dc480ac00b
Add support for WUHB file format (#1190) 2024-05-05 02:35:01 +02:00
qurious-pixel
f28043e0e9
Linux/Mac Auto-Updater (#1145) 2024-05-05 01:34:36 +02:00
Exzap
a744670486 coreinit: Add export for OSGetForegroundBucketFreeArea 2024-05-05 01:33:15 +02:00
Exzap
48d2a8371b sndcore: Write log message instead of asserting in AXSetDeviceRemixMatrix
Fixes a crash in Watch Dogs due to the non-debug assert
2024-05-05 01:33:15 +02:00
Exzap
91a010fbdd proc_ui: Fix crash due to incorrect version handling
Resolves a crash in NEX Remix
2024-05-04 08:05:10 +02:00
Exzap
a16c37f0c5 coreinit: Rework thread creation
New implementation is much closer to console behavior. For example we didn't align the stack which would cause crashes in the Miiverse applet
2024-05-04 07:05:59 +02:00
Exzap
041f29a914 nn_act: Implement GetTimeZoneId placeholder 2024-05-03 02:44:10 +02:00
Exzap
1b5c885621 nn_acp: Implement ACPGetTitleMetaXml 2024-05-03 02:41:39 +02:00
Exzap
c11d83e9d8 coreinit: Implement MCP_GetTitleId 2024-05-03 02:41:05 +02:00
Exzap
379950d185 coreinit+nn_save: Cleanup some legacy code 2024-05-01 05:06:50 +02:00
Exzap
e7c6862e19 DownloadManager: Fix missing updates 2024-05-01 01:55:55 +02:00
Exzap
1c73dc9e1b Implement proc_ui.rpl + stub SYSSwitchToEManual() to avoid softlocks
- Full reimplementation of proc_ui.rpl with all 19 exports
- Foreground/Background messages now go to the coreinit system message queue as they should (instead of using a hack where proc_ui receives them directly)
- Add missing coreinit API needed by proc_ui: OSGetPFID(), OSGetUPID(), OSGetTitleID(), __OSCreateThreadType()
- Use big-endian types in OSMessage
- Flesh out the stubs for OSDriver_Register and OSDriver_Unregister a bit more since we need to call it from proc_ui. Similiar small tweaks to other coreinit API
- Stub sysapp SYSSwitchToEManual() and _SYSSwitchToEManual() in such a way that they will trigger the expected background/foreground transition, avoiding softlocks in games that call these functions
2024-04-30 23:29:15 +02:00
Exzap
c038e758ae IOSU: Clean up resource on service shutdown
Also set device-dependent thread name
2024-04-30 23:19:11 +02:00
Exzap
b2be3c13df Add example network_services.xml 2024-04-30 23:19:04 +02:00
GaryOderNichts
fdf239929f
nsysnet: Various improvements (#1188)
- Do not raise an assert for unimplemented optnames
- recvfrom: src_addr and addrlen can be NULL
- getsockopt: Implement SO_TYPE
2024-04-29 00:24:43 +02:00
goeiecool9999
5be98da0ac
OpenGL: Fix a crash when GL_VERSION is null (#1187) 2024-04-27 15:49:49 +02:00
457 changed files with 39569 additions and 23958 deletions

View file

@ -15,6 +15,7 @@ BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterExternBlock: true

View file

@ -1,9 +0,0 @@
#include <stdio.h>
#include "./../src/Common/version.h"
// output current Cemu version for CI workflow. Do not modify
int main()
{
printf("%d.%d", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR);
return 0;
}

View file

@ -3,10 +3,10 @@ name: Build Cemu
on:
workflow_call:
inputs:
deploymode:
next_version_major:
required: false
type: string
experimentalversion:
next_version_minor:
required: false
type: string
@ -19,41 +19,27 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: "Checkout repo"
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: "recursive"
fetch-depth: 0
- name: "Fetch full history for vcpkg submodule"
run: |
cd dependencies/vcpkg
git fetch --unshallow
git checkout 431eb6bda0950874c8d4ed929cc66e15d8aae46f
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
- name: Setup release mode parameters
run: |
echo "BUILD_MODE=release" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is release"
- name: Setup debug mode parameters (for continous build)
if: ${{ inputs.deploymode != 'release' }}
- name: Setup build flags for version
if: ${{ inputs.next_version_major != '' }}
run: |
echo "BUILD_MODE=debug" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" >> $GITHUB_ENV
- name: "Install system dependencies"
run: |
sudo apt update -qq
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libudev-dev nasm ninja-build
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libudev-dev nasm ninja-build libbluetooth-dev
- name: "Setup cmake"
uses: jwlawson/actions-setup-cmake@v2
@ -87,12 +73,10 @@ jobs:
cmake --build build
- 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' }}
uses: actions/upload-artifact@v4
with:
name: cemu-bin-linux-x64
path: ./bin/Cemu
@ -102,9 +86,9 @@ jobs:
needs: build-ubuntu
steps:
- name: Checkout Upstream Repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: cemu-bin-linux-x64
path: bin
@ -112,7 +96,7 @@ jobs:
- name: "Install system dependencies"
run: |
sudo apt update -qq
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build appstream
sudo apt install -y clang-15 cmake freeglut3-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build appstream libbluetooth-dev
- name: "Build AppImage"
run: |
@ -121,7 +105,7 @@ jobs:
dist/linux/appimage.sh
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: cemu-appimage-x64
path: artifacts
@ -130,34 +114,21 @@ jobs:
runs-on: windows-2022
steps:
- name: "Checkout repo"
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: "recursive"
- name: "Fetch full history for vcpkg submodule"
run: |
cd dependencies/vcpkg
git fetch --unshallow
git checkout 431eb6bda0950874c8d4ed929cc66e15d8aae46f
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
- name: Setup release mode parameters
run: |
echo "BUILD_MODE=release" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "BUILD_FLAGS=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "Build mode is release"
- name: Setup debug mode parameters (for continous build)
if: ${{ inputs.deploymode != 'release' }}
- name: Setup build flags for version
if: ${{ inputs.next_version_major != '' }}
run: |
echo "BUILD_MODE=debug" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "BUILD_FLAGS=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
- name: "Setup cmake"
uses: jwlawson/actions-setup-cmake@v2
@ -196,53 +167,48 @@ jobs:
cmake --build . --config ${{ env.BUILD_MODE }}
- 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' }}
uses: actions/upload-artifact@v4
with:
name: cemu-bin-windows-x64
path: ./bin/Cemu.exe
build-macos:
runs-on: macos-12
runs-on: macos-14
strategy:
matrix:
arch: [x86_64, arm64]
steps:
- name: "Checkout repo"
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: "recursive"
- name: "Fetch full history for vcpkg submodule"
run: |
cd dependencies/vcpkg
git fetch --unshallow
git pull --all
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
- name: Setup release mode parameters
run: |
echo "BUILD_MODE=release" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is release"
- name: Setup debug mode parameters (for continous build)
if: ${{ inputs.deploymode != 'release' }}
- name: Setup build flags for version
if: ${{ inputs.next_version_major != '' }}
run: |
echo "BUILD_MODE=debug" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" >> $GITHUB_ENV
- name: "Install system dependencies"
run: |
brew update
brew install llvm@15 ninja nasm molten-vk automake libtool
brew install ninja nasm automake libtool
- name: "Install molten-vk"
run: |
curl -L -O https://github.com/KhronosGroup/MoltenVK/releases/download/v1.3.0/MoltenVK-macos.tar
tar xf MoltenVK-macos.tar
sudo mkdir -p /usr/local/lib
sudo cp MoltenVK/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib /usr/local/lib
- name: "Setup cmake"
uses: jwlawson/actions-setup-cmake@v2
@ -273,9 +239,8 @@ jobs:
cd build
cmake .. ${{ env.BUILD_FLAGS }} \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \
-DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} \
-DMACOS_BUNDLE=ON \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++ \
-G Ninja
- name: "Build Cemu"
@ -283,21 +248,19 @@ jobs:
cmake --build build
- name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: |
mkdir bin/Cemu_app
mv bin/Cemu_release.app bin/Cemu_app/Cemu.app
mv bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu_release bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu
sed -i '' 's/Cemu_release/Cemu/g' bin/Cemu_app/Cemu.app/Contents/Info.plist
chmod a+x bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu
chmod a+x bin/Cemu_app/Cemu.app/Contents/MacOS/{Cemu,update.sh}
ln -s /Applications bin/Cemu_app/Applications
hdiutil create ./bin/tmp.dmg -ov -volname "Cemu" -fs HFS+ -srcfolder "./bin/Cemu_app"
hdiutil convert ./bin/tmp.dmg -format UDZO -o bin/Cemu.dmg
rm bin/tmp.dmg
- name: Upload artifact
uses: actions/upload-artifact@v3
if: ${{ inputs.deploymode == 'release' }}
uses: actions/upload-artifact@v4
with:
name: cemu-bin-macos-x64
name: cemu-bin-macos-${{ matrix.arch }}
path: ./bin/Cemu.dmg

View file

@ -16,6 +16,3 @@ on:
jobs:
build:
uses: ./.github/workflows/build.yml
with:
deploymode: release
experimentalversion: 999999

View file

@ -1,86 +0,0 @@
name: Deploy experimental release
on:
workflow_dispatch:
jobs:
call-release-build:
uses: ./.github/workflows/build.yml
with:
deploymode: release
experimentalversion: ${{ github.run_number }}
deploy:
name: Deploy experimental release
runs-on: ubuntu-22.04
needs: call-release-build
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: cemu-bin-linux-x64
path: cemu-bin-linux-x64
- uses: actions/download-artifact@v3
with:
name: cemu-appimage-x64
path: cemu-appimage-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-windows-x64
path: cemu-bin-windows-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-macos-x64
path: cemu-bin-macos-x64
- name: Initialize
run: |
mkdir upload
sudo apt install zip
- name: Get version
run: |
echo "Experimental version: ${{ github.run_number }}"
ls
gcc -o getversion .github/getversion.cpp
./getversion
echo "Cemu CI version: $(./getversion)"
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)-${{ github.run_number }}" >> $GITHUB_ENV
echo "CEMU_VERSION=$(./getversion)-${{ github.run_number }}" >> $GITHUB_ENV
- name: Create release from windows-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create appimage
run: |
VERSION=${{ env.CEMU_VERSION }}
echo "Cemu Version is $VERSION"
ls cemu-appimage-x64
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
- name: Create release from linux-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-linux-x64/Cemu ./${{ env.CEMU_FOLDER_NAME }}/Cemu
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-ubuntu-22.04-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create release from macos-bin
run: cp cemu-bin-macos-x64/Cemu.dmg upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.dmg
- name: Create release
run: |
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 "Cemu experimental release" "v${{ env.CEMU_VERSION }}" ./upload

151
.github/workflows/deploy_release.yml vendored Normal file
View file

@ -0,0 +1,151 @@
name: Deploy release
on:
workflow_dispatch:
inputs:
changelog0:
description: 'Enter the changelog lines for this release. Each line is a feature / bullet point. Do not use dash.'
required: true
type: string
changelog1:
description: 'Feature 2'
required: false
type: string
changelog2:
description: 'Feature 3'
required: false
type: string
changelog3:
description: 'Feature 4'
required: false
type: string
changelog4:
description: 'Feature 5'
required: false
type: string
changelog5:
description: 'Feature 6'
required: false
type: string
changelog6:
description: 'Feature 7'
required: false
type: string
changelog7:
description: 'Feature 8'
required: false
type: string
changelog8:
description: 'Feature 9'
required: false
type: string
changelog9:
description: 'Feature 10'
required: false
type: string
jobs:
calculate-version:
name: Calculate Version
uses: ./.github/workflows/determine_release_version.yml
call-release-build:
uses: ./.github/workflows/build.yml
needs: calculate-version
with:
next_version_major: ${{ needs.calculate-version.outputs.next_version_major }}
next_version_minor: ${{ needs.calculate-version.outputs.next_version_minor }}
deploy:
name: Deploy release
runs-on: ubuntu-22.04
needs: [call-release-build, calculate-version]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: generate_changelog
run: |
CHANGELOG=""
if [ -n "${{ github.event.inputs.changelog0 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog0 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog1 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog1 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog2 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog2 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog3 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog3 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog4 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog4 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog5 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog5 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog6 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog6 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog7 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog7 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog8 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog8 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog9 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog9 }}\n"; fi
echo -e "$CHANGELOG"
echo "RELEASE_BODY=$CHANGELOG" >> $GITHUB_ENV
- uses: actions/download-artifact@v4
with:
name: cemu-bin-linux-x64
path: cemu-bin-linux-x64
- uses: actions/download-artifact@v4
with:
name: cemu-appimage-x64
path: cemu-appimage-x64
- uses: actions/download-artifact@v4
with:
name: cemu-bin-windows-x64
path: cemu-bin-windows-x64
- uses: actions/download-artifact@v4
with:
name: cemu-bin-macos-x64
path: cemu-bin-macos-x64
- name: Initialize
run: |
mkdir upload
sudo apt install zip
- name: Set version dependent vars
run: |
echo "Version: ${{ needs.calculate-version.outputs.next_version }}"
echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}"
echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}"
echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
- name: Create release from windows-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create appimage
run: |
VERSION=${{ env.CEMU_VERSION }}
echo "Cemu Version is $VERSION"
ls cemu-appimage-x64
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
- name: Create release from linux-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-linux-x64/Cemu ./${{ env.CEMU_FOLDER_NAME }}/Cemu
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-ubuntu-22.04-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create release from macos-bin
run: cp cemu-bin-macos-x64/Cemu.dmg upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.dmg
- name: Create release
run: |
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 }}"
CHANGELOG_UNESCAPED=$(printf "%s\n" "${{ env.RELEASE_BODY }}" | sed 's/\\n/\n/g')
RELEASE_BODY=$(printf "%s\n%s" \
"**Changelog:**" \
"$CHANGELOG_UNESCAPED")
ghr_v0.15.0_linux_amd64/ghr -draft -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }}" -b "$RELEASE_BODY" "v${{ env.CEMU_VERSION }}" ./upload

View file

@ -1,85 +0,0 @@
name: Create new release
on:
workflow_dispatch:
inputs:
PlaceholderInput:
description: PlaceholderInput
required: false
jobs:
call-release-build:
uses: ./.github/workflows/build.yml
with:
deploymode: release
deploy:
name: Deploy release
runs-on: ubuntu-20.04
needs: call-release-build
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: cemu-bin-linux-x64
path: cemu-bin-linux-x64
- uses: actions/download-artifact@v3
with:
name: cemu-appimage-x64
path: cemu-appimage-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-windows-x64
path: cemu-bin-windows-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-macos-x64
path: cemu-bin-macos-x64
- name: Initialize
run: |
mkdir upload
sudo apt update -qq
sudo apt install -y zip
- name: Get Cemu release version
run: |
gcc -o getversion .github/getversion.cpp
echo "Cemu CI version: $(./getversion)"
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)" >> $GITHUB_ENV
echo "CEMU_VERSION=$(./getversion)" >> $GITHUB_ENV
- name: Create release from windows-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create appimage
run: |
VERSION=${{ env.CEMU_VERSION }}
echo "Cemu Version is $VERSION"
ls cemu-appimage-x64
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
- name: Create release from ubuntu-bin
run: |
ls ./
ls ./bin/
cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }}
mv cemu-bin-linux-x64/Cemu ./${{ env.CEMU_FOLDER_NAME }}/Cemu
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-ubuntu-20.04-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create release from macos-bin
run: cp cemu-bin-macos-x64/Cemu.dmg upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.dmg
- name: Create release
run: |
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
ghr_v0.15.0_linux_amd64/ghr -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }}" -b "Changelog:" v${{ env.CEMU_VERSION }} ./upload

View file

@ -0,0 +1,74 @@
name: Calculate Next Version from release history
on:
workflow_dispatch:
workflow_call:
outputs:
next_version:
description: "The next semantic version"
value: ${{ jobs.calculate-version.outputs.next_version }}
next_version_major:
description: "The next semantic version (major)"
value: ${{ jobs.calculate-version.outputs.next_version_major }}
next_version_minor:
description: "The next semantic version (minor)"
value: ${{ jobs.calculate-version.outputs.next_version_minor }}
jobs:
calculate-version:
runs-on: ubuntu-latest
outputs:
next_version: ${{ steps.calculate_next_version.outputs.next_version }}
next_version_major: ${{ steps.calculate_next_version.outputs.next_version_major }}
next_version_minor: ${{ steps.calculate_next_version.outputs.next_version_minor }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Get all releases
id: get_all_releases
run: |
# Fetch all releases and check for API errors
RESPONSE=$(curl -s -o response.json -w "%{http_code}" "https://api.github.com/repos/${{ github.repository }}/releases?per_page=100")
if [ "$RESPONSE" -ne 200 ]; then
echo "Failed to fetch releases. HTTP status: $RESPONSE"
cat response.json
exit 1
fi
# Extract and sort tags
ALL_TAGS=$(jq -r '.[].tag_name' response.json | grep -E '^v[0-9]+\.[0-9]+(-[0-9]+)?$' | sed 's/-.*//' | sort -V | tail -n 1)
# Exit if no tags were found
if [ -z "$ALL_TAGS" ]; then
echo "No valid tags found."
exit 1
fi
echo "::set-output name=tag::$ALL_TAGS"
# echo "tag=$ALL_TAGS" >> $GITHUB_STATE
- name: Calculate next semver minor
id: calculate_next_version
run: |
LATEST_VERSION=${{ steps.get_all_releases.outputs.tag }}
# strip 'v' prefix and split into major.minor
LATEST_VERSION=${LATEST_VERSION//v/}
IFS='.' read -r -a VERSION_PARTS <<< "$LATEST_VERSION"
MAJOR=${VERSION_PARTS[0]}
MINOR=${VERSION_PARTS[1]}
# increment the minor version
MINOR=$((MINOR + 1))
NEXT_VERSION="${MAJOR}.${MINOR}"
echo "Major: $MAJOR"
echo "Minor: $MINOR"
echo "Next version: $NEXT_VERSION"
echo "::set-output name=next_version::$NEXT_VERSION"
echo "::set-output name=next_version_major::$MAJOR"
echo "::set-output name=next_version_minor::$MINOR"

View file

@ -35,7 +35,7 @@ jobs:
-o cemu.pot
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: POT file
path: ./cemu.pot

1
.gitignore vendored
View file

@ -39,6 +39,7 @@ bin/sdcard/*
bin/screenshots/*
bin/dump/*
bin/cafeLibs/*
bin/portable/*
bin/keys.txt
!bin/shaderCache/info.txt

7
.gitmodules vendored
View file

@ -9,10 +9,15 @@
[submodule "dependencies/vcpkg"]
path = dependencies/vcpkg
url = https://github.com/microsoft/vcpkg
shallow = true
shallow = false
[submodule "dependencies/Vulkan-Headers"]
path = dependencies/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers
shallow = true
[submodule "dependencies/imgui"]
path = dependencies/imgui
url = https://github.com/ocornut/imgui
shallow = true
[submodule "dependencies/xbyak_aarch64"]
path = dependencies/xbyak_aarch64
url = https://github.com/fujitsu/xbyak_aarch64

View file

@ -16,11 +16,11 @@
- [Compiling Errors](#compiling-errors)
- [Building Errors](#building-errors)
- [macOS](#macos)
- [On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used](#on-apple-silicon-macs-rosetta-2-and-the-x86_64-version-of-homebrew-must-be-used)
- [Installing brew](#installing-brew)
- [Installing Dependencies](#installing-dependencies)
- [Build Cemu using CMake and Clang](#build-cemu-using-cmake-and-clang)
- [Updating Cemu and source code](#updating-cemu-and-source-code)
- [Installing Tool Dependencies](#installing-tool-dependencies)
- [Installing Library Dependencies](#installing-library-dependencies)
- [Build Cemu using CMake](#build-cemu-using-cmake)
- [Updating Cemu and source code](#updating-cemu-and-source-code)
## Windows
@ -46,10 +46,10 @@ To compile Cemu, a recent enough compiler and STL with C++20 support is required
### Dependencies
#### For Arch and derivatives:
`sudo pacman -S --needed base-devel clang cmake freeglut git glm gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip`
`sudo pacman -S --needed base-devel bluez-libs clang cmake freeglut git glm gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip`
#### For Debian, Ubuntu and derivatives:
`sudo apt install -y cmake curl clang-15 freeglut3-dev git libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libtool nasm ninja-build`
`sudo apt install -y cmake curl clang-15 freeglut3-dev git libbluetooth-dev libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libtool nasm ninja-build`
You may also need to install `libusb-1.0-0-dev` as a workaround for an issue with the vcpkg hidapi package.
@ -57,7 +57,7 @@ At Step 3 in [Build Cemu using cmake and clang](#build-cemu-using-cmake-and-clan
`cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
#### For Fedora and derivatives:
`sudo dnf install clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel llvm nasm ninja-build perl-core systemd-devel zlib-devel`
`sudo dnf install bluez-libs-devel clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel llvm nasm ninja-build perl-core systemd-devel wayland-protocols-devel zlib-devel zlib-static`
### Build Cemu
@ -120,6 +120,9 @@ This section refers to running `cmake -S...` (truncated).
* Compiling failed during rebuild after `git pull` with an error that mentions RPATH
* Add the following and try running the command again:
* `-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON`
* Environment variable `VCPKG_FORCE_SYSTEM_BINARIES` must be set.
* Execute the folowing and then try running the command again:
* `export VCPKG_FORCE_SYSTEM_BINARIES=1`
* If you are getting a random error, read the [package-name-and-platform]-out.log and [package-name-and-platform]-err.log for the actual reason to see if you might be lacking the headers from a dependency.
@ -141,31 +144,41 @@ If you are getting a different error than any of the errors listed above, you ma
## macOS
To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and
below, built in LLVM, and Xcode LLVM don't support the C++20 feature set required. The OpenGL graphics
API isn't support on macOS, Vulkan must be used. Additionally Vulkan must be used through the
Molten-VK compatibility layer
### On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used
You can skip this section if you have an Intel Mac. Every time you compile, you need to perform steps 2.
1. `softwareupdate --install-rosetta` # Install Rosetta 2 if you don't have it. This only has to be done once
2. `arch -x86_64 zsh` # run an x64 shell
To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and below
don't support the C++20 feature set required, so either install LLVM from Homebrew or make sure that
you have a recent enough version of Xcode. Xcode 15 is known to work. The OpenGL graphics API isn't
supported on macOS, so Vulkan must be used through the Molten-VK compatibility layer.
### Installing brew
1. `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
2. `eval "$(/usr/local/Homebrew/bin/brew shellenv)"` # set x86_64 brew env
2. Set up the Homebrew shell environment:
1. **On an Intel Mac:** `eval "$(/usr/local/Homebrew/bin/brew shellenv)"`
2. **On an Apple Silicon Mac:** eval `"$(/opt/homebrew/bin/brew shellenv)"`
### Installing Dependencies
### Installing Tool Dependencies
`brew install boost git cmake llvm ninja nasm molten-vk automake libtool`
The native versions of these can be used regardless of what type of Mac you have.
`brew install git cmake ninja nasm automake libtool`
### Installing Library Dependencies
**On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used to install these dependencies:**
1. `softwareupdate --install-rosetta` # Install Rosetta 2 if you don't have it. This only has to be done once
2. `arch -x86_64 zsh` # run an x64 shell
3. `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
4. `eval "$(/usr/local/Homebrew/bin/brew shellenv)"`
Then install the dependencies:
`brew install boost molten-vk`
### Build Cemu using CMake
### Build Cemu using CMake and Clang
1. `git clone --recursive https://github.com/cemu-project/Cemu`
2. `cd Cemu`
3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -G Ninja`
3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_OSX_ARCHITECTURES=x86_64 -G Ninja`
4. `cmake --build build`
5. You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu_release`.
@ -179,3 +192,41 @@ You can skip this section if you have an Intel Mac. Every time you compile, you
If CMake complains about Cemu already being compiled or another similar error, try deleting the `CMakeCache.txt` file inside the `build` folder and retry building.
## CMake configure flags
Some flags can be passed during CMake configure to customise which features are enabled on build.
Example usage: `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DENABLE_SDL=ON -DENABLE_VULKAN=OFF`
### All platforms
| Flag | | Description | Default | Note |
|--------------------|:--|-----------------------------------------------------------------------------|---------|--------------------|
| ALLOW_PORTABLE | | Allow Cemu to use the `portable` directory to store configs and data | ON | |
| CEMU_CXX_FLAGS | | Flags passed straight to the compiler, e.g. `-march=native`, `-Wall`, `/W3` | "" | |
| ENABLE_CUBEB | | Enable cubeb audio backend | ON | |
| ENABLE_DISCORD_RPC | | Enable Discord Rich presence support | ON | |
| ENABLE_OPENGL | | Enable OpenGL graphics backend | ON | Currently required |
| ENABLE_HIDAPI | | Enable HIDAPI (used for Wiimote controller API) | ON | |
| ENABLE_SDL | | Enable SDLController controller API | ON | Currently required |
| ENABLE_VCPKG | | Use VCPKG package manager to obtain dependencies | ON | |
| ENABLE_VULKAN | | Enable the Vulkan graphics backend | ON | |
| ENABLE_WXWIDGETS | | Enable wxWidgets UI | ON | Currently required |
### Windows
| Flag | Description | Default | Note |
|--------------------|-----------------------------------|---------|--------------------|
| ENABLE_DIRECTAUDIO | Enable DirectAudio audio backend | ON | Currently required |
| ENABLE_DIRECTINPUT | Enable DirectInput controller API | ON | Currently required |
| ENABLE_XAUDIO | Enable XAudio audio backend | ON | |
| ENABLE_XINPUT | Enable XInput controller API | ON | |
### Linux
| Flag | Description | Default |
|-----------------------|----------------------------------------------------|---------|
| ENABLE_BLUEZ | Build with Bluez (used for Wiimote controller API) | ON |
| ENABLE_FERAL_GAMEMODE | Enable Feral Interactive GameMode support | ON |
| ENABLE_WAYLAND | Enable Wayland support | ON |
### macOS
| Flag | Description | Default |
|--------------|------------------------------------------------|---------|
| MACOS_BUNDLE | MacOS executable will be an application bundle | OFF |

View file

@ -2,20 +2,40 @@ cmake_minimum_required(VERSION 3.21.1)
option(ENABLE_VCPKG "Enable the vcpkg package manager" ON)
option(MACOS_BUNDLE "The executable when built on macOS will be created as an application bundle" OFF)
set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version
option(ALLOW_PORTABLE "Allow Cemu to be run in portable mode" ON)
if (EXPERIMENTAL_VERSION)
add_definitions(-DEMULATOR_VERSION_MINOR=${EXPERIMENTAL_VERSION})
execute_process(
COMMAND git log --format=%h -1
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DEMULATOR_HASH=${GIT_HASH})
endif()
# used by CI script to set version:
set(EMULATOR_VERSION_MAJOR "0" CACHE STRING "")
set(EMULATOR_VERSION_MINOR "0" CACHE STRING "")
set(EMULATOR_VERSION_PATCH "0" CACHE STRING "")
execute_process(
COMMAND git log --format=%h -1
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DEMULATOR_HASH=${GIT_HASH})
if (ENABLE_VCPKG)
# check if vcpkg is shallow and unshallow it if necessary
execute_process(
COMMAND git rev-parse --is-shallow-repository
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/vcpkg
OUTPUT_VARIABLE is_vcpkg_shallow
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(is_vcpkg_shallow STREQUAL "true")
message(STATUS "vcpkg is shallow. Unshallowing it now...")
execute_process(
COMMAND git fetch --unshallow
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/dependencies/vcpkg"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
)
endif()
if(UNIX AND NOT APPLE)
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_linux")
elseif(APPLE)
@ -44,6 +64,10 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_definitions($<$<CONFIG:Debug>:CEMU_DEBUG_ASSERT>) # if build type is debug, set CEMU_DEBUG_ASSERT
add_definitions(-DEMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR})
add_definitions(-DEMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR})
add_definitions(-DEMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH})
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# enable link time optimization for release builds
@ -69,11 +93,13 @@ endif()
if (APPLE)
enable_language(OBJC OBJCXX)
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0")
endif()
if (UNIX AND NOT APPLE)
option(ENABLE_WAYLAND "Build with Wayland support" ON)
option(ENABLE_FERAL_GAMEMODE "Enables Feral Interactive GameMode Support" ON)
option(ENABLE_BLUEZ "Build with Bluez support" ON)
endif()
option(ENABLE_OPENGL "Enables the OpenGL backend" ON)
@ -98,23 +124,6 @@ if (WIN32)
endif()
option(ENABLE_CUBEB "Enabled cubeb backend" ON)
# usb hid backends
if (WIN32)
option(ENABLE_NSYSHID_WINDOWS_HID "Enables the native Windows HID backend for nsyshid" ON)
endif ()
# libusb and windows hid backends shouldn't be active at the same time; otherwise we'd see all devices twice!
if (NOT ENABLE_NSYSHID_WINDOWS_HID)
option(ENABLE_NSYSHID_LIBUSB "Enables the libusb backend for nsyshid" ON)
else ()
set(ENABLE_NSYSHID_LIBUSB OFF CACHE BOOL "" FORCE)
endif ()
if (ENABLE_NSYSHID_WINDOWS_HID)
add_compile_definitions(NSYSHID_ENABLE_BACKEND_WINDOWS_HID)
endif ()
if (ENABLE_NSYSHID_LIBUSB)
add_compile_definitions(NSYSHID_ENABLE_BACKEND_LIBUSB)
endif ()
option(ENABLE_WXWIDGETS "Build with wxWidgets UI (Currently required)" ON)
set(THREADS_PREFER_PTHREAD_FLAG true)
@ -155,6 +164,12 @@ if (UNIX AND NOT APPLE)
endif()
find_package(GTK3 REQUIRED)
if(ENABLE_BLUEZ)
find_package(bluez REQUIRED)
set(SUPPORTS_WIIMOTE ON)
add_compile_definitions(HAS_BLUEZ)
endif()
endif()
if (ENABLE_VULKAN)
@ -173,7 +188,7 @@ endif()
if (ENABLE_HIDAPI)
find_package(hidapi REQUIRED)
set(ENABLE_WIIMOTE ON)
set(SUPPORTS_WIIMOTE ON)
add_compile_definitions(HAS_HIDAPI)
endif ()
@ -198,7 +213,7 @@ if (ENABLE_CUBEB)
option(BUILD_TOOLS "" OFF)
option(BUNDLE_SPEEX "" OFF)
set(USE_WINMM OFF CACHE BOOL "")
add_subdirectory("dependencies/cubeb" EXCLUDE_FROM_ALL)
add_subdirectory("dependencies/cubeb" EXCLUDE_FROM_ALL SYSTEM)
set_property(TARGET cubeb PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
add_library(cubeb::cubeb ALIAS cubeb)
endif()
@ -207,9 +222,18 @@ endif()
add_subdirectory("dependencies/ih264d" EXCLUDE_FROM_ALL)
if (CMAKE_OSX_ARCHITECTURES)
set(CEMU_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES})
else()
set(CEMU_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
endif()
if(CEMU_ARCHITECTURE MATCHES "(aarch64)|(AARCH64)|(arm64)|(ARM64)")
add_subdirectory("dependencies/xbyak_aarch64" EXCLUDE_FROM_ALL)
endif()
find_package(ZArchive)
if (NOT ZArchive_FOUND)
add_subdirectory("dependencies/ZArchive" EXCLUDE_FROM_ALL)
endif()
add_subdirectory(src)
add_subdirectory(src)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1 +0,0 @@
If you plan to transfer the shader cache to a different PC or Cemu installation you only need to copy the 'transferable' directory.

26
boost.natvis Normal file
View file

@ -0,0 +1,26 @@
<?xml version='1.0' encoding='utf-8'?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="boost::container::small_vector&lt;*&gt;">
<Expand>
<Item Name="[size]">m_holder.m_size</Item>
<ArrayItems>
<Size>m_holder.m_size</Size>
<ValuePointer>m_holder.m_start</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="boost::container::static_vector&lt;*&gt;">
<DisplayString>{{ size={m_holder.m_size} }}</DisplayString>
<Expand>
<Item Name="[size]" ExcludeView="simple">m_holder.m_size</Item>
<Item Name="[capacity]" ExcludeView="simple">static_capacity</Item>
<ArrayItems>
<Size>m_holder.m_size</Size>
<ValuePointer>($T1*)m_holder.storage.data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
</AutoVisualizer>

20
cmake/Findbluez.cmake Normal file
View file

@ -0,0 +1,20 @@
# SPDX-FileCopyrightText: 2022 Andrea Pappacoda <andrea@pappacoda.it>
# SPDX-License-Identifier: ISC
find_package(bluez CONFIG)
if (NOT bluez_FOUND)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_search_module(bluez IMPORTED_TARGET GLOBAL bluez-1.0 bluez)
if (bluez_FOUND)
add_library(bluez::bluez ALIAS PkgConfig::bluez)
endif ()
endif ()
endif ()
find_package_handle_standard_args(bluez
REQUIRED_VARS
bluez_LINK_LIBRARIES
bluez_FOUND
VERSION_VAR bluez_VERSION
)

View file

@ -117,7 +117,13 @@ add_library (ih264d
"decoder/ivd.h"
)
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64")
if (CMAKE_OSX_ARCHITECTURES)
set(IH264D_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES})
else()
set(IH264D_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
endif()
if (IH264D_ARCHITECTURE STREQUAL "x86_64" OR IH264D_ARCHITECTURE STREQUAL "amd64" OR IH264D_ARCHITECTURE STREQUAL "AMD64")
set(LIBAVCDEC_X86_INCLUDES "common/x86" "decoder/x86")
include_directories("common/" "decoder/" ${LIBAVCDEC_X86_INCLUDES})
target_sources(ih264d PRIVATE
@ -140,7 +146,7 @@ target_sources(ih264d PRIVATE
"decoder/x86/ih264d_function_selector_sse42.c"
"decoder/x86/ih264d_function_selector_ssse3.c"
)
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
elseif(IH264D_ARCHITECTURE STREQUAL "aarch64" OR IH264D_ARCHITECTURE STREQUAL "arm64")
enable_language( C CXX ASM )
set(LIBAVCDEC_ARM_INCLUDES "common/armv8" "decoder/arm")
include_directories("common/" "decoder/" ${LIBAVCDEC_ARM_INCLUDES})
@ -177,8 +183,11 @@ target_sources(ih264d PRIVATE
"decoder/arm/ih264d_function_selector.c"
)
target_compile_options(ih264d PRIVATE -DARMV8)
if(APPLE)
target_sources(ih264d PRIVATE "common/armv8/macos_arm_symbol_aliases.s")
endif()
else()
message(FATAL_ERROR "ih264d unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
message(FATAL_ERROR "ih264d unknown architecture: ${IH264D_ARCHITECTURE}")
endif()
if(MSVC)

View file

@ -429,8 +429,13 @@ ih264_intra_pred_chroma_8x8_mode_plane_av8:
rev64 v7.4h, v2.4h
ld1 {v3.2s}, [x10]
sub x5, x3, #8
#ifdef __APPLE__
adrp x12, _ih264_gai1_intrapred_chroma_plane_coeffs1@GOTPAGE
ldr x12, [x12, _ih264_gai1_intrapred_chroma_plane_coeffs1@GOTPAGEOFF]
#else
adrp x12, :got:ih264_gai1_intrapred_chroma_plane_coeffs1
ldr x12, [x12, #:got_lo12:ih264_gai1_intrapred_chroma_plane_coeffs1]
#endif
usubl v10.8h, v5.8b, v1.8b
ld1 {v8.8b, v9.8b}, [x12] // Load multiplication factors 1 to 8 into D3
mov v8.d[1], v9.d[0]
@ -484,10 +489,13 @@ ih264_intra_pred_chroma_8x8_mode_plane_av8:
zip1 v1.8h, v0.8h, v2.8h
zip2 v2.8h, v0.8h, v2.8h
mov v0.16b, v1.16b
#ifdef __APPLE__
adrp x12, _ih264_gai1_intrapred_chroma_plane_coeffs2@GOTPAGE
ldr x12, [x12, _ih264_gai1_intrapred_chroma_plane_coeffs2@GOTPAGEOFF]
#else
adrp x12, :got:ih264_gai1_intrapred_chroma_plane_coeffs2
ldr x12, [x12, #:got_lo12:ih264_gai1_intrapred_chroma_plane_coeffs2]
#endif
ld1 {v8.2s, v9.2s}, [x12]
mov v8.d[1], v9.d[0]
mov v10.16b, v8.16b

View file

@ -431,10 +431,13 @@ ih264_intra_pred_luma_16x16_mode_plane_av8:
mov x10, x1 //top_left
mov x4, #-1
ld1 {v2.2s}, [x1], x8
#ifdef __APPLE__
adrp x7, _ih264_gai1_intrapred_luma_plane_coeffs@GOTPAGE
ldr x7, [x7, _ih264_gai1_intrapred_luma_plane_coeffs@GOTPAGEOFF]
#else
adrp x7, :got:ih264_gai1_intrapred_luma_plane_coeffs
ldr x7, [x7, #:got_lo12:ih264_gai1_intrapred_luma_plane_coeffs]
#endif
ld1 {v0.2s}, [x1]
rev64 v2.8b, v2.8b
ld1 {v6.2s, v7.2s}, [x7]

View file

@ -1029,9 +1029,13 @@ ih264_intra_pred_luma_8x8_mode_horz_u_av8:
mov v3.d[0], v2.d[1]
ext v4.16b, v2.16b , v2.16b , #1
mov v5.d[0], v4.d[1]
#ifdef __APPLE__
adrp x12, _ih264_gai1_intrapred_luma_8x8_horz_u@GOTPAGE
ldr x12, [x12, _ih264_gai1_intrapred_luma_8x8_horz_u@GOTPAGEOFF]
#else
adrp x12, :got:ih264_gai1_intrapred_luma_8x8_horz_u
ldr x12, [x12, #:got_lo12:ih264_gai1_intrapred_luma_8x8_horz_u]
#endif
uaddl v20.8h, v0.8b, v2.8b
uaddl v22.8h, v1.8b, v3.8b
uaddl v24.8h, v2.8b, v4.8b

View file

@ -142,14 +142,22 @@ ih264_weighted_bi_pred_luma_av8:
sxtw x4, w4
sxtw x5, w5
stp x19, x20, [sp, #-16]!
#ifndef __APPLE__
ldr w8, [sp, #80] //Load wt2 in w8
ldr w9, [sp, #88] //Load ofst1 in w9
add w6, w6, #1 //w6 = log_WD + 1
neg w10, w6 //w10 = -(log_WD + 1)
dup v0.8h, w10 //Q0 = -(log_WD + 1) (32-bit)
ldr w10, [sp, #96] //Load ofst2 in w10
ldr w11, [sp, #104] //Load ht in w11
ldr w12, [sp, #112] //Load wd in w12
#else
ldr w8, [sp, #80] //Load wt2 in w8
ldr w9, [sp, #84] //Load ofst1 in w9
ldr w10, [sp, #88] //Load ofst2 in w10
ldr w11, [sp, #92] //Load ht in w11
ldr w12, [sp, #96] //Load wd in w12
#endif
add w6, w6, #1 //w6 = log_WD + 1
neg w10, w6 //w10 = -(log_WD + 1)
dup v0.8h, w10 //Q0 = -(log_WD + 1) (32-bit)
add w9, w9, #1 //w9 = ofst1 + 1
add w9, w9, w10 //w9 = ofst1 + ofst2 + 1
mov v2.s[0], w7
@ -424,17 +432,24 @@ ih264_weighted_bi_pred_chroma_av8:
sxtw x5, w5
stp x19, x20, [sp, #-16]!
#ifndef __APPLE__
ldr w8, [sp, #80] //Load wt2 in w8
ldr w9, [sp, #88] //Load ofst1 in w9
ldr w10, [sp, #96] //Load ofst2 in w10
ldr w11, [sp, #104] //Load ht in w11
ldr w12, [sp, #112] //Load wd in w12
#else
ldr w8, [sp, #80] //Load wt2 in w8
ldr w9, [sp, #84] //Load ofst1 in w9
ldr w10, [sp, #88] //Load ofst2 in w10
ldr w11, [sp, #92] //Load ht in w11
ldr w12, [sp, #96] //Load wd in w12
#endif
dup v4.4s, w8 //Q2 = (wt2_u, wt2_v) (32-bit)
dup v2.4s, w7 //Q1 = (wt1_u, wt1_v) (32-bit)
add w6, w6, #1 //w6 = log_WD + 1
ldr w9, [sp, #88] //Load ofst1 in w9
ldr w10, [sp, #96] //Load ofst2 in w10
neg w20, w6 //w20 = -(log_WD + 1)
dup v0.8h, w20 //Q0 = -(log_WD + 1) (16-bit)
ldr w11, [sp, #104] //Load ht in x11
ldr w12, [sp, #112] //Load wd in x12
dup v20.8h, w9 //0ffset1
dup v21.8h, w10 //0ffset2
srhadd v6.8b, v20.8b, v21.8b

View file

@ -0,0 +1,185 @@
// macOS clang compilers append preceding underscores to function names, this is to prevent
// mismatches with the assembly function names and the C functions as defined in the header.
.global _ih264_deblk_chroma_horz_bs4_av8
_ih264_deblk_chroma_horz_bs4_av8 = ih264_deblk_chroma_horz_bs4_av8
.global _ih264_deblk_chroma_horz_bslt4_av8
_ih264_deblk_chroma_horz_bslt4_av8 = ih264_deblk_chroma_horz_bslt4_av8
.global _ih264_deblk_chroma_vert_bs4_av8
_ih264_deblk_chroma_vert_bs4_av8 = ih264_deblk_chroma_vert_bs4_av8
.global _ih264_deblk_chroma_vert_bslt4_av8
_ih264_deblk_chroma_vert_bslt4_av8 = ih264_deblk_chroma_vert_bslt4_av8
.global _ih264_deblk_luma_horz_bs4_av8
_ih264_deblk_luma_horz_bs4_av8 = ih264_deblk_luma_horz_bs4_av8
.global _ih264_deblk_luma_horz_bslt4_av8
_ih264_deblk_luma_horz_bslt4_av8 = ih264_deblk_luma_horz_bslt4_av8
.global _ih264_deblk_luma_vert_bs4_av8
_ih264_deblk_luma_vert_bs4_av8 = ih264_deblk_luma_vert_bs4_av8
.global _ih264_deblk_luma_vert_bslt4_av8
_ih264_deblk_luma_vert_bslt4_av8 = ih264_deblk_luma_vert_bslt4_av8
.global _ih264_default_weighted_pred_chroma_av8
_ih264_default_weighted_pred_chroma_av8 = ih264_default_weighted_pred_chroma_av8
.global _ih264_default_weighted_pred_luma_av8
_ih264_default_weighted_pred_luma_av8 = ih264_default_weighted_pred_luma_av8
.global _ih264_ihadamard_scaling_4x4_av8
_ih264_ihadamard_scaling_4x4_av8 = ih264_ihadamard_scaling_4x4_av8
.global _ih264_inter_pred_chroma_av8
_ih264_inter_pred_chroma_av8 = ih264_inter_pred_chroma_av8
.global _ih264_inter_pred_luma_copy_av8
_ih264_inter_pred_luma_copy_av8 = ih264_inter_pred_luma_copy_av8
.global _ih264_inter_pred_luma_horz_av8
_ih264_inter_pred_luma_horz_av8 = ih264_inter_pred_luma_horz_av8
.global _ih264_inter_pred_luma_horz_hpel_vert_hpel_av8
_ih264_inter_pred_luma_horz_hpel_vert_hpel_av8 = ih264_inter_pred_luma_horz_hpel_vert_hpel_av8
.global _ih264_inter_pred_luma_horz_hpel_vert_qpel_av8
_ih264_inter_pred_luma_horz_hpel_vert_qpel_av8 = ih264_inter_pred_luma_horz_hpel_vert_qpel_av8
.global _ih264_inter_pred_luma_horz_qpel_av8
_ih264_inter_pred_luma_horz_qpel_av8 = ih264_inter_pred_luma_horz_qpel_av8
.global _ih264_inter_pred_luma_horz_qpel_vert_hpel_av8
_ih264_inter_pred_luma_horz_qpel_vert_hpel_av8 = ih264_inter_pred_luma_horz_qpel_vert_hpel_av8
.global _ih264_inter_pred_luma_horz_qpel_vert_qpel_av8
_ih264_inter_pred_luma_horz_qpel_vert_qpel_av8 = ih264_inter_pred_luma_horz_qpel_vert_qpel_av8
.global _ih264_inter_pred_luma_vert_av8
_ih264_inter_pred_luma_vert_av8 = ih264_inter_pred_luma_vert_av8
.global _ih264_inter_pred_luma_vert_qpel_av8
_ih264_inter_pred_luma_vert_qpel_av8 = ih264_inter_pred_luma_vert_qpel_av8
.global _ih264_intra_pred_chroma_8x8_mode_horz_av8
_ih264_intra_pred_chroma_8x8_mode_horz_av8 = ih264_intra_pred_chroma_8x8_mode_horz_av8
.global _ih264_intra_pred_chroma_8x8_mode_plane_av8
_ih264_intra_pred_chroma_8x8_mode_plane_av8 = ih264_intra_pred_chroma_8x8_mode_plane_av8
.global _ih264_intra_pred_chroma_8x8_mode_vert_av8
_ih264_intra_pred_chroma_8x8_mode_vert_av8 = ih264_intra_pred_chroma_8x8_mode_vert_av8
.global _ih264_intra_pred_luma_16x16_mode_dc_av8
_ih264_intra_pred_luma_16x16_mode_dc_av8 = ih264_intra_pred_luma_16x16_mode_dc_av8
.global _ih264_intra_pred_luma_16x16_mode_horz_av8
_ih264_intra_pred_luma_16x16_mode_horz_av8 = ih264_intra_pred_luma_16x16_mode_horz_av8
.global _ih264_intra_pred_luma_16x16_mode_plane_av8
_ih264_intra_pred_luma_16x16_mode_plane_av8 = ih264_intra_pred_luma_16x16_mode_plane_av8
.global _ih264_intra_pred_luma_16x16_mode_vert_av8
_ih264_intra_pred_luma_16x16_mode_vert_av8 = ih264_intra_pred_luma_16x16_mode_vert_av8
.global _ih264_intra_pred_luma_4x4_mode_dc_av8
_ih264_intra_pred_luma_4x4_mode_dc_av8 = ih264_intra_pred_luma_4x4_mode_dc_av8
.global _ih264_intra_pred_luma_4x4_mode_diag_dl_av8
_ih264_intra_pred_luma_4x4_mode_diag_dl_av8 = ih264_intra_pred_luma_4x4_mode_diag_dl_av8
.global _ih264_intra_pred_luma_4x4_mode_diag_dr_av8
_ih264_intra_pred_luma_4x4_mode_diag_dr_av8 = ih264_intra_pred_luma_4x4_mode_diag_dr_av8
.global _ih264_intra_pred_luma_4x4_mode_horz_av8
_ih264_intra_pred_luma_4x4_mode_horz_av8 = ih264_intra_pred_luma_4x4_mode_horz_av8
.global _ih264_intra_pred_luma_4x4_mode_horz_d_av8
_ih264_intra_pred_luma_4x4_mode_horz_d_av8 = ih264_intra_pred_luma_4x4_mode_horz_d_av8
.global _ih264_intra_pred_luma_4x4_mode_horz_u_av8
_ih264_intra_pred_luma_4x4_mode_horz_u_av8 = ih264_intra_pred_luma_4x4_mode_horz_u_av8
.global _ih264_intra_pred_luma_4x4_mode_vert_av8
_ih264_intra_pred_luma_4x4_mode_vert_av8 = ih264_intra_pred_luma_4x4_mode_vert_av8
.global _ih264_intra_pred_luma_4x4_mode_vert_l_av8
_ih264_intra_pred_luma_4x4_mode_vert_l_av8 = ih264_intra_pred_luma_4x4_mode_vert_l_av8
.global _ih264_intra_pred_luma_4x4_mode_vert_r_av8
_ih264_intra_pred_luma_4x4_mode_vert_r_av8 = ih264_intra_pred_luma_4x4_mode_vert_r_av8
.global _ih264_intra_pred_luma_8x8_mode_dc_av8
_ih264_intra_pred_luma_8x8_mode_dc_av8 = ih264_intra_pred_luma_8x8_mode_dc_av8
.global _ih264_intra_pred_luma_8x8_mode_diag_dl_av8
_ih264_intra_pred_luma_8x8_mode_diag_dl_av8 = ih264_intra_pred_luma_8x8_mode_diag_dl_av8
.global _ih264_intra_pred_luma_8x8_mode_diag_dr_av8
_ih264_intra_pred_luma_8x8_mode_diag_dr_av8 = ih264_intra_pred_luma_8x8_mode_diag_dr_av8
.global _ih264_intra_pred_luma_8x8_mode_horz_av8
_ih264_intra_pred_luma_8x8_mode_horz_av8 = ih264_intra_pred_luma_8x8_mode_horz_av8
.global _ih264_intra_pred_luma_8x8_mode_horz_d_av8
_ih264_intra_pred_luma_8x8_mode_horz_d_av8 = ih264_intra_pred_luma_8x8_mode_horz_d_av8
.global _ih264_intra_pred_luma_8x8_mode_horz_u_av8
_ih264_intra_pred_luma_8x8_mode_horz_u_av8 = ih264_intra_pred_luma_8x8_mode_horz_u_av8
.global _ih264_intra_pred_luma_8x8_mode_vert_av8
_ih264_intra_pred_luma_8x8_mode_vert_av8 = ih264_intra_pred_luma_8x8_mode_vert_av8
.global _ih264_intra_pred_luma_8x8_mode_vert_l_av8
_ih264_intra_pred_luma_8x8_mode_vert_l_av8 = ih264_intra_pred_luma_8x8_mode_vert_l_av8
.global _ih264_intra_pred_luma_8x8_mode_vert_r_av8
_ih264_intra_pred_luma_8x8_mode_vert_r_av8 = ih264_intra_pred_luma_8x8_mode_vert_r_av8
.global _ih264_iquant_itrans_recon_4x4_av8
_ih264_iquant_itrans_recon_4x4_av8 = ih264_iquant_itrans_recon_4x4_av8
.global _ih264_iquant_itrans_recon_4x4_dc_av8
_ih264_iquant_itrans_recon_4x4_dc_av8 = ih264_iquant_itrans_recon_4x4_dc_av8
.global _ih264_iquant_itrans_recon_8x8_av8
_ih264_iquant_itrans_recon_8x8_av8 = ih264_iquant_itrans_recon_8x8_av8
.global _ih264_iquant_itrans_recon_8x8_dc_av8
_ih264_iquant_itrans_recon_8x8_dc_av8 = ih264_iquant_itrans_recon_8x8_dc_av8
.global _ih264_iquant_itrans_recon_chroma_4x4_av8
_ih264_iquant_itrans_recon_chroma_4x4_av8 = ih264_iquant_itrans_recon_chroma_4x4_av8
.global _ih264_iquant_itrans_recon_chroma_4x4_dc_av8
_ih264_iquant_itrans_recon_chroma_4x4_dc_av8 = ih264_iquant_itrans_recon_chroma_4x4_dc_av8
.global _ih264_pad_left_chroma_av8
_ih264_pad_left_chroma_av8 = ih264_pad_left_chroma_av8
.global _ih264_pad_left_luma_av8
_ih264_pad_left_luma_av8 = ih264_pad_left_luma_av8
.global _ih264_pad_right_chroma_av8
_ih264_pad_right_chroma_av8 = ih264_pad_right_chroma_av8
.global _ih264_pad_right_luma_av8
_ih264_pad_right_luma_av8 = ih264_pad_right_luma_av8
.global _ih264_pad_top_av8
_ih264_pad_top_av8 = ih264_pad_top_av8
.global _ih264_weighted_bi_pred_chroma_av8
_ih264_weighted_bi_pred_chroma_av8 = ih264_weighted_bi_pred_chroma_av8
.global _ih264_weighted_bi_pred_luma_av8
_ih264_weighted_bi_pred_luma_av8 = ih264_weighted_bi_pred_luma_av8
.global _ih264_weighted_pred_chroma_av8
_ih264_weighted_pred_chroma_av8 = ih264_weighted_pred_chroma_av8
.global _ih264_weighted_pred_luma_av8
_ih264_weighted_pred_luma_av8 = ih264_weighted_pred_luma_av8

2
dependencies/vcpkg vendored

@ -1 +1 @@
Subproject commit 53bef8994c541b6561884a8395ea35715ece75db
Subproject commit 533a5fda5c0646d1771345fb572e759283444d5f

View file

@ -1,13 +0,0 @@
diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in
index cc8bcf26d..ead829767 100644
--- a/SDL2Config.cmake.in
+++ b/SDL2Config.cmake.in
@@ -35,7 +35,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
set(SDL_ALSA @SDL_ALSA@)
set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
+if(SDL_ALSA)
sdlFindALSA()
endif()
unset(SDL_ALSA)

View file

@ -1,13 +0,0 @@
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
index 65a98efbe..2f99f28f1 100644
--- a/cmake/sdlchecks.cmake
+++ b/cmake/sdlchecks.cmake
@@ -352,7 +352,7 @@ endmacro()
# - HAVE_SDL_LOADSO opt
macro(CheckLibSampleRate)
if(SDL_LIBSAMPLERATE)
- find_package(SampleRate QUIET)
+ find_package(SampleRate CONFIG REQUIRED)
if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
set(HAVE_LIBSAMPLERATE TRUE)
set(HAVE_LIBSAMPLERATE_H TRUE)

View file

@ -1,137 +0,0 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO libsdl-org/SDL
REF "release-${VERSION}"
SHA512 c7635a83a52f3970a372b804a8631f0a7e6b8d89aed1117bcc54a2040ad0928122175004cf2b42cf84a4fd0f86236f779229eaa63dfa6ca9c89517f999c5ff1c
HEAD_REF main
PATCHES
deps.patch
alsa-dep-fix.patch
)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
alsa SDL_ALSA
alsa CMAKE_REQUIRE_FIND_PACKAGE_ALSA
ibus SDL_IBUS
samplerate SDL_LIBSAMPLERATE
vulkan SDL_VULKAN
wayland SDL_WAYLAND
x11 SDL_X11
INVERTED_FEATURES
alsa CMAKE_DISABLE_FIND_PACKAGE_ALSA
)
if ("x11" IN_LIST FEATURES)
message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
endif()
if ("wayland" IN_LIST FEATURES)
message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
endif()
if ("ibus" IN_LIST FEATURES)
message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
endif()
if(VCPKG_TARGET_IS_UWP)
set(configure_opts WINDOWS_USE_MSBUILD)
endif()
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
${configure_opts}
OPTIONS ${FEATURE_OPTIONS}
-DSDL_STATIC=${SDL_STATIC}
-DSDL_SHARED=${SDL_SHARED}
-DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
-DSDL_LIBC=ON
-DSDL_TEST=OFF
-DSDL_INSTALL_CMAKEDIR="cmake"
-DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
-DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON
-DSDL_LIBSAMPLERATE_SHARED=OFF
MAYBE_UNUSED_VARIABLES
SDL_FORCE_STATIC_VCRT
PKG_CONFIG_USE_CMAKE_PREFIX_PATH
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
"${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/share/licenses"
"${CURRENT_PACKAGES_DIR}/share/aclocal"
)
file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
if(NOT BINS)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/bin"
"${CURRENT_PACKAGES_DIR}/debug/bin"
)
endif()
if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
endif()
file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
foreach(SHARE_FILE ${SHARE_FILES})
vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
endforeach()
endif()
vcpkg_copy_pdbs()
set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
endif()
if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
endif()
endif()
if(VCPKG_TARGET_IS_UWP)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "d")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
endif()
vcpkg_fixup_pkgconfig()
file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")

View file

@ -1,8 +0,0 @@
sdl2 provides CMake targets:
find_package(SDL2 CONFIG REQUIRED)
target_link_libraries(main
PRIVATE
$<TARGET_NAME_IF_EXISTS:SDL2::SDL2main>
$<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
)

View file

@ -1,68 +0,0 @@
{
"name": "sdl2",
"version": "2.30.0",
"description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
"homepage": "https://www.libsdl.org/download-2.0.php",
"license": "Zlib",
"dependencies": [
{
"name": "dbus",
"default-features": false,
"platform": "linux"
},
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
{
"name": "ibus",
"platform": "linux"
},
{
"name": "wayland",
"platform": "linux"
},
{
"name": "x11",
"platform": "linux"
}
],
"features": {
"alsa": {
"description": "Support for alsa audio",
"dependencies": [
{
"name": "alsa",
"platform": "linux"
}
]
},
"ibus": {
"description": "Build with ibus IME support",
"supports": "linux"
},
"samplerate": {
"description": "Use libsamplerate for audio rate conversion",
"dependencies": [
"libsamplerate"
]
},
"vulkan": {
"description": "Vulkan functionality for SDL"
},
"wayland": {
"description": "Build with Wayland support",
"supports": "linux"
},
"x11": {
"description": "Build with X11 support",
"supports": "!windows"
}
}
}

View file

@ -1,13 +0,0 @@
diff --git a/cmake/FindCMath.cmake b/cmake/FindCMath.cmake
index ad92218..dd42aba 100644
--- a/cmake/FindCMath.cmake
+++ b/cmake/FindCMath.cmake
@@ -31,7 +31,7 @@ include(CheckSymbolExists)
include(CheckLibraryExists)
check_symbol_exists(pow "math.h" CMath_HAVE_LIBC_POW)
-find_library(CMath_LIBRARY NAMES m)
+find_library(CMath_LIBRARY NAMES m PATHS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
if(NOT CMath_HAVE_LIBC_POW)
set(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES})

View file

@ -1,86 +0,0 @@
vcpkg_from_gitlab(
GITLAB_URL https://gitlab.com
OUT_SOURCE_PATH SOURCE_PATH
REPO libtiff/libtiff
REF "v${VERSION}"
SHA512 ef2f1d424219d9e245069b7d23e78f5e817cf6ee516d46694915ab6c8909522166f84997513d20a702f4e52c3f18467813935b328fafa34bea5156dee00f66fa
HEAD_REF master
PATCHES
FindCMath.patch
)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
cxx cxx
jpeg jpeg
jpeg CMAKE_REQUIRE_FIND_PACKAGE_JPEG
libdeflate libdeflate
libdeflate CMAKE_REQUIRE_FIND_PACKAGE_Deflate
lzma lzma
lzma CMAKE_REQUIRE_FIND_PACKAGE_liblzma
tools tiff-tools
webp webp
webp CMAKE_REQUIRE_FIND_PACKAGE_WebP
zip zlib
zip CMAKE_REQUIRE_FIND_PACKAGE_ZLIB
zstd zstd
zstd CMAKE_REQUIRE_FIND_PACKAGE_ZSTD
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
${FEATURE_OPTIONS}
-DCMAKE_FIND_PACKAGE_PREFER_CONFIG=ON
-Dtiff-docs=OFF
-Dtiff-contrib=OFF
-Dtiff-tests=OFF
-Djbig=OFF # This is disabled by default due to GPL/Proprietary licensing.
-Djpeg12=OFF
-Dlerc=OFF
-DCMAKE_DISABLE_FIND_PACKAGE_OpenGL=ON
-DCMAKE_DISABLE_FIND_PACKAGE_GLUT=ON
-DZSTD_HAVE_DECOMPRESS_STREAM=ON
-DHAVE_JPEGTURBO_DUAL_MODE_8_12=OFF
OPTIONS_DEBUG
-DCMAKE_DEBUG_POSTFIX=d # tiff sets "d" for MSVC only.
MAYBE_UNUSED_VARIABLES
CMAKE_DISABLE_FIND_PACKAGE_GLUT
CMAKE_DISABLE_FIND_PACKAGE_OpenGL
ZSTD_HAVE_DECOMPRESS_STREAM
)
vcpkg_cmake_install()
# CMake config wasn't packaged in the past and is not yet usable now,
# cf. https://gitlab.com/libtiff/libtiff/-/merge_requests/496
# vcpkg_cmake_config_fixup(CONFIG_PATH "lib/cmake/tiff")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/cmake" "${CURRENT_PACKAGES_DIR}/debug/lib/cmake")
set(_file "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libtiff-4.pc")
if(EXISTS "${_file}")
vcpkg_replace_string("${_file}" "-ltiff" "-ltiffd")
endif()
vcpkg_fixup_pkgconfig()
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
)
configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake.in" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-cmake-wrapper.cmake" @ONLY)
if ("tools" IN_LIST FEATURES)
vcpkg_copy_tools(TOOL_NAMES
tiffcp
tiffdump
tiffinfo
tiffset
tiffsplit
AUTO_CLEAN
)
endif()
vcpkg_copy_pdbs()
file(COPY "${CURRENT_PORT_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.md")

View file

@ -1,9 +0,0 @@
tiff is compatible with built-in CMake targets:
find_package(TIFF REQUIRED)
target_link_libraries(main PRIVATE TIFF::TIFF)
tiff provides pkg-config modules:
# Tag Image File Format (TIFF) library.
libtiff-4

View file

@ -1,104 +0,0 @@
cmake_policy(PUSH)
cmake_policy(SET CMP0012 NEW)
cmake_policy(SET CMP0057 NEW)
set(z_vcpkg_tiff_find_options "")
if("REQUIRED" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "REQUIRED")
endif()
if("QUIET" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "QUIET")
endif()
_find_package(${ARGS})
if(TIFF_FOUND AND "@VCPKG_LIBRARY_LINKAGE@" STREQUAL "static")
include(SelectLibraryConfigurations)
set(z_vcpkg_tiff_link_libraries "")
set(z_vcpkg_tiff_libraries "")
if("@webp@")
find_package(WebP CONFIG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:WebP::WebP>")
list(APPEND z_vcpkg_tiff_libraries ${WebP_LIBRARIES})
endif()
if("@lzma@")
find_package(LibLZMA ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:LibLZMA::LibLZMA>")
list(APPEND z_vcpkg_tiff_libraries ${LIBLZMA_LIBRARIES})
endif()
if("@jpeg@")
find_package(JPEG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:JPEG::JPEG>")
list(APPEND z_vcpkg_tiff_libraries ${JPEG_LIBRARIES})
endif()
if("@zstd@")
find_package(zstd CONFIG ${z_vcpkg_tiff_find_options})
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_LOCATION_")
if(TARGET zstd::libzstd_shared)
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_shared>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_shared)
if(WIN32)
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_static>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_static)
endif()
get_target_property(z_vcpkg_tiff_zstd_configs "${z_vcpkg_tiff_zstd_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_tiff_zstd_configs)
get_target_property(ZSTD_LIBRARY_${z_vcpkg_config} "${z_vcpkg_tiff_zstd_target}" "${z_vcpkg_tiff_zstd_target_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(ZSTD)
if(NOT TARGET ZSTD::ZSTD)
add_library(ZSTD::ZSTD INTERFACE IMPORTED)
set_property(TARGET ZSTD::ZSTD APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_zstd})
endif()
list(APPEND z_vcpkg_tiff_link_libraries ${z_vcpkg_tiff_zstd})
list(APPEND z_vcpkg_tiff_libraries ${ZSTD_LIBRARIES})
unset(z_vcpkg_tiff_zstd)
unset(z_vcpkg_tiff_zstd_configs)
unset(z_vcpkg_config)
unset(z_vcpkg_tiff_zstd_target)
endif()
if("@libdeflate@")
find_package(libdeflate ${z_vcpkg_tiff_find_options})
set(z_vcpkg_property "IMPORTED_LOCATION_")
if(TARGET libdeflate::libdeflate_shared)
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_shared)
if(WIN32)
set(z_vcpkg_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_static)
endif()
get_target_property(z_vcpkg_libdeflate_configs "${z_vcpkg_libdeflate_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_libdeflate_configs)
get_target_property(Z_VCPKG_DEFLATE_LIBRARY_${z_vcpkg_config} "${z_vcpkg_libdeflate_target}" "${z_vcpkg_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(Z_VCPKG_DEFLATE)
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:${z_vcpkg_libdeflate_target}>")
list(APPEND z_vcpkg_tiff_libraries ${Z_VCPKG_DEFLATE_LIBRARIES})
unset(z_vcpkg_config)
unset(z_vcpkg_libdeflate_configs)
unset(z_vcpkg_libdeflate_target)
unset(z_vcpkg_property)
unset(Z_VCPKG_DEFLATE_FOUND)
endif()
if("@zlib@")
find_package(ZLIB ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:ZLIB::ZLIB>")
list(APPEND z_vcpkg_tiff_libraries ${ZLIB_LIBRARIES})
endif()
if(UNIX)
list(APPEND z_vcpkg_tiff_link_libraries m)
list(APPEND z_vcpkg_tiff_libraries m)
endif()
if(TARGET TIFF::TIFF)
set_property(TARGET TIFF::TIFF APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_link_libraries})
endif()
list(APPEND TIFF_LIBRARIES ${z_vcpkg_tiff_libraries})
unset(z_vcpkg_tiff_link_libraries)
unset(z_vcpkg_tiff_libraries)
endif()
unset(z_vcpkg_tiff_find_options)
cmake_policy(POP)

View file

@ -1,67 +0,0 @@
{
"name": "tiff",
"version": "4.6.0",
"port-version": 2,
"description": "A library that supports the manipulation of TIFF image files",
"homepage": "https://libtiff.gitlab.io/libtiff/",
"license": "libtiff",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
"jpeg",
"zip"
],
"features": {
"cxx": {
"description": "Build C++ libtiffxx library"
},
"jpeg": {
"description": "Support JPEG compression in TIFF image files",
"dependencies": [
"libjpeg-turbo"
]
},
"libdeflate": {
"description": "Use libdeflate for faster ZIP support",
"dependencies": [
"libdeflate",
{
"name": "tiff",
"default-features": false,
"features": [
"zip"
]
}
]
},
"tools": {
"description": "Build tools"
},
"webp": {
"description": "Support WEBP compression in TIFF image files",
"dependencies": [
"libwebp"
]
},
"zip": {
"description": "Support ZIP/deflate compression in TIFF image files",
"dependencies": [
"zlib"
]
},
"zstd": {
"description": "Support ZSTD compression in TIFF image files",
"dependencies": [
"zstd"
]
}
}
}

View file

@ -1,15 +0,0 @@
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 8cde1ffe0..d4d09f223 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -91,7 +91,9 @@ endif()
add_executable(dbus-launch ${dbus_launch_SOURCES})
target_link_libraries(dbus-launch ${DBUS_LIBRARIES})
if(DBUS_BUILD_X11)
- target_link_libraries(dbus-launch ${X11_LIBRARIES} )
+ find_package(Threads REQUIRED)
+ target_link_libraries(dbus-launch ${X11_LIBRARIES} ${X11_xcb_LIB} ${X11_Xau_LIB} ${X11_Xdmcp_LIB} Threads::Threads)
+ target_include_directories(dbus-launch PRIVATE ${X11_INCLUDE_DIR})
endif()
install(TARGETS dbus-launch ${INSTALL_TARGETS_DEFAULT_ARGS})

View file

@ -1,26 +0,0 @@
diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake
index b7f3702..e2336ba 100644
--- a/cmake/ConfigureChecks.cmake
+++ b/cmake/ConfigureChecks.cmake
@@ -51,6 +51,7 @@ check_symbol_exists(closefrom "unistd.h" HAVE_CLOSEFROM) #
check_symbol_exists(environ "unistd.h" HAVE_DECL_ENVIRON)
check_symbol_exists(fstatfs "sys/vfs.h" HAVE_FSTATFS)
check_symbol_exists(getgrouplist "grp.h" HAVE_GETGROUPLIST) # dbus-sysdeps.c
+check_symbol_exists(getpeereid "sys/types.h;unistd.h" HAVE_GETPEEREID) # dbus-sysdeps.c,
check_symbol_exists(getpeerucred "ucred.h" HAVE_GETPEERUCRED) # dbus-sysdeps.c, dbus-sysdeps-win.c
check_symbol_exists(getpwnam_r "errno.h;pwd.h" HAVE_GETPWNAM_R) # dbus-sysdeps-util-unix.c
check_symbol_exists(getrandom "sys/random.h" HAVE_GETRANDOM)
diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake
index 77fc19c..2f25643 100644
--- a/cmake/config.h.cmake
+++ b/cmake/config.h.cmake
@@ -140,6 +140,9 @@
/* Define to 1 if you have getgrouplist */
#cmakedefine HAVE_GETGROUPLIST 1
+/* Define to 1 if you have getpeereid */
+#cmakedefine HAVE_GETPEEREID 1
+
/* Define to 1 if you have getpeerucred */
#cmakedefine HAVE_GETPEERUCRED 1

View file

@ -1,15 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d3ec71b..932066a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -141,6 +141,10 @@ if(DBUS_LINUX)
if(ENABLE_SYSTEMD AND SYSTEMD_FOUND)
set(DBUS_BUS_ENABLE_SYSTEMD ON)
set(HAVE_SYSTEMD ${SYSTEMD_FOUND})
+ pkg_check_modules(SYSTEMD libsystemd IMPORTED_TARGET)
+ set(SYSTEMD_LIBRARIES PkgConfig::SYSTEMD CACHE INTERNAL "")
+ else()
+ set(SYSTEMD_LIBRARIES "" CACHE INTERNAL "")
endif()
option(ENABLE_USER_SESSION "enable user-session semantics for session bus under systemd" OFF)
set(DBUS_ENABLE_USER_SESSION ${ENABLE_USER_SESSION})

View file

@ -1,21 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index caef738..b878f42 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -724,11 +724,11 @@ add_custom_target(help-options
#
if(DBUS_ENABLE_PKGCONFIG)
set(PLATFORM_LIBS pthread ${LIBRT})
- if(PKG_CONFIG_FOUND)
- # convert lists of link libraries into -lstdc++ -lm etc..
- foreach(LIB ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS})
- set(LIBDBUS_LIBS "${LIBDBUS_LIBS} -l${LIB}")
- endforeach()
+ if(1)
+ set(LIBDBUS_LIBS "${CMAKE_THREAD_LIBS_INIT}")
+ if(LIBRT)
+ string(APPEND LIBDBUS_LIBS " -lrt")
+ endif()
set(original_prefix "${CMAKE_INSTALL_PREFIX}")
if(DBUS_RELOCATABLE)
set(pkgconfig_prefix "\${pcfiledir}/../..")

View file

@ -1,88 +0,0 @@
vcpkg_check_linkage(ONLY_DYNAMIC_LIBRARY)
vcpkg_from_gitlab(
GITLAB_URL https://gitlab.freedesktop.org/
OUT_SOURCE_PATH SOURCE_PATH
REPO dbus/dbus
REF "dbus-${VERSION}"
SHA512 8e476b408514e6540c36beb84e8025827c22cda8958b6eb74d22b99c64765eb3cd5a6502aea546e3e5f0534039857b37edee89c659acef40e7cab0939947d4af
HEAD_REF master
PATCHES
cmake.dep.patch
pkgconfig.patch
getpeereid.patch # missing check from configure.ac
libsystemd.patch
)
vcpkg_check_features(OUT_FEATURE_OPTIONS options
FEATURES
systemd ENABLE_SYSTEMD
x11 DBUS_BUILD_X11
x11 CMAKE_REQUIRE_FIND_PACKAGE_X11
)
unset(ENV{DBUSDIR})
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
-DDBUS_BUILD_TESTS=OFF
-DDBUS_ENABLE_DOXYGEN_DOCS=OFF
-DDBUS_ENABLE_XML_DOCS=OFF
-DDBUS_INSTALL_SYSTEM_LIBS=OFF
#-DDBUS_SERVICE=ON
-DDBUS_WITH_GLIB=OFF
-DTHREADS_PREFER_PTHREAD_FLAG=ON
-DXSLTPROC_EXECUTABLE=FALSE
"-DCMAKE_INSTALL_SYSCONFDIR=${CURRENT_PACKAGES_DIR}/etc/${PORT}"
"-DWITH_SYSTEMD_SYSTEMUNITDIR=lib/systemd/system"
"-DWITH_SYSTEMD_USERUNITDIR=lib/systemd/user"
${options}
OPTIONS_RELEASE
-DDBUS_DISABLE_ASSERT=OFF
-DDBUS_ENABLE_STATS=OFF
-DDBUS_ENABLE_VERBOSE_MODE=OFF
MAYBE_UNUSED_VARIABLES
DBUS_BUILD_X11
DBUS_WITH_GLIB
ENABLE_SYSTEMD
THREADS_PREFER_PTHREAD_FLAG
WITH_SYSTEMD_SYSTEMUNITDIR
WITH_SYSTEMD_USERUNITDIR
)
vcpkg_cmake_install()
vcpkg_copy_pdbs()
vcpkg_cmake_config_fixup(PACKAGE_NAME "DBus1" CONFIG_PATH "lib/cmake/DBus1")
vcpkg_fixup_pkgconfig()
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
"${CURRENT_PACKAGES_DIR}/debug/var/"
"${CURRENT_PACKAGES_DIR}/etc"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/services"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/session.d"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/system-services"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/system.d"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/system.conf"
"${CURRENT_PACKAGES_DIR}/share/dbus-1/system.conf"
"${CURRENT_PACKAGES_DIR}/share/doc"
"${CURRENT_PACKAGES_DIR}/var"
)
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/dbus-1/session.conf" "<include ignore_missing=\"yes\">${CURRENT_PACKAGES_DIR}/etc/dbus/dbus-1/session.conf</include>" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/dbus-1/session.conf" "<includedir>${CURRENT_PACKAGES_DIR}/etc/dbus/dbus-1/session.d</includedir>" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/dbus-1/session.conf" "<include ignore_missing=\"yes\">${CURRENT_PACKAGES_DIR}/etc/dbus/dbus-1/session-local.conf</include>" "")
set(TOOLS daemon launch monitor run-session send test-tool update-activation-environment)
if(VCPKG_TARGET_IS_WINDOWS)
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/tools/${PORT}")
file(RENAME "${CURRENT_PACKAGES_DIR}/bin/dbus-env.bat" "${CURRENT_PACKAGES_DIR}/tools/${PORT}/dbus-env.bat")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/tools/${PORT}/dbus-env.bat" "${CURRENT_PACKAGES_DIR}" "%~dp0/../..")
else()
list(APPEND TOOLS cleanup-sockets uuidgen)
endif()
list(TRANSFORM TOOLS PREPEND "dbus-" )
vcpkg_copy_tools(TOOL_NAMES ${TOOLS} AUTO_CLEAN)
file(INSTALL "${SOURCE_PATH}/COPYING" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)

View file

@ -1,30 +0,0 @@
{
"name": "dbus",
"version": "1.15.8",
"port-version": 2,
"description": "D-Bus specification and reference implementation, including libdbus and dbus-daemon",
"homepage": "https://gitlab.freedesktop.org/dbus/dbus",
"license": "AFL-2.1 OR GPL-2.0-or-later",
"supports": "!uwp & !staticcrt",
"dependencies": [
"expat",
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
],
"features": {
"x11": {
"description": "Build with X11 autolaunch support",
"dependencies": [
"libx11"
]
}
}
}

View file

@ -1,13 +0,0 @@
diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in
index cc8bcf26d..ead829767 100644
--- a/SDL2Config.cmake.in
+++ b/SDL2Config.cmake.in
@@ -35,7 +35,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
set(SDL_ALSA @SDL_ALSA@)
set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
+if(SDL_ALSA)
sdlFindALSA()
endif()
unset(SDL_ALSA)

View file

@ -1,13 +0,0 @@
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
index 65a98efbe..2f99f28f1 100644
--- a/cmake/sdlchecks.cmake
+++ b/cmake/sdlchecks.cmake
@@ -352,7 +352,7 @@ endmacro()
# - HAVE_SDL_LOADSO opt
macro(CheckLibSampleRate)
if(SDL_LIBSAMPLERATE)
- find_package(SampleRate QUIET)
+ find_package(SampleRate CONFIG REQUIRED)
if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
set(HAVE_LIBSAMPLERATE TRUE)
set(HAVE_LIBSAMPLERATE_H TRUE)

View file

@ -1,137 +0,0 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO libsdl-org/SDL
REF "release-${VERSION}"
SHA512 c7635a83a52f3970a372b804a8631f0a7e6b8d89aed1117bcc54a2040ad0928122175004cf2b42cf84a4fd0f86236f779229eaa63dfa6ca9c89517f999c5ff1c
HEAD_REF main
PATCHES
deps.patch
alsa-dep-fix.patch
)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
alsa SDL_ALSA
alsa CMAKE_REQUIRE_FIND_PACKAGE_ALSA
ibus SDL_IBUS
samplerate SDL_LIBSAMPLERATE
vulkan SDL_VULKAN
wayland SDL_WAYLAND
x11 SDL_X11
INVERTED_FEATURES
alsa CMAKE_DISABLE_FIND_PACKAGE_ALSA
)
if ("x11" IN_LIST FEATURES)
message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
endif()
if ("wayland" IN_LIST FEATURES)
message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
endif()
if ("ibus" IN_LIST FEATURES)
message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
endif()
if(VCPKG_TARGET_IS_UWP)
set(configure_opts WINDOWS_USE_MSBUILD)
endif()
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
${configure_opts}
OPTIONS ${FEATURE_OPTIONS}
-DSDL_STATIC=${SDL_STATIC}
-DSDL_SHARED=${SDL_SHARED}
-DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
-DSDL_LIBC=ON
-DSDL_TEST=OFF
-DSDL_INSTALL_CMAKEDIR="cmake"
-DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
-DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON
-DSDL_LIBSAMPLERATE_SHARED=OFF
MAYBE_UNUSED_VARIABLES
SDL_FORCE_STATIC_VCRT
PKG_CONFIG_USE_CMAKE_PREFIX_PATH
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
"${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/share/licenses"
"${CURRENT_PACKAGES_DIR}/share/aclocal"
)
file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
if(NOT BINS)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/bin"
"${CURRENT_PACKAGES_DIR}/debug/bin"
)
endif()
if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
endif()
file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
foreach(SHARE_FILE ${SHARE_FILES})
vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
endforeach()
endif()
vcpkg_copy_pdbs()
set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
endif()
if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
endif()
endif()
if(VCPKG_TARGET_IS_UWP)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "d")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
endif()
vcpkg_fixup_pkgconfig()
file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")

View file

@ -1,8 +0,0 @@
sdl2 provides CMake targets:
find_package(SDL2 CONFIG REQUIRED)
target_link_libraries(main
PRIVATE
$<TARGET_NAME_IF_EXISTS:SDL2::SDL2main>
$<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
)

View file

@ -1,68 +0,0 @@
{
"name": "sdl2",
"version": "2.30.0",
"description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
"homepage": "https://www.libsdl.org/download-2.0.php",
"license": "Zlib",
"dependencies": [
{
"name": "dbus",
"default-features": false,
"platform": "linux"
},
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
{
"name": "ibus",
"platform": "linux"
},
{
"name": "wayland",
"platform": "linux"
},
{
"name": "x11",
"platform": "linux"
}
],
"features": {
"alsa": {
"description": "Support for alsa audio",
"dependencies": [
{
"name": "alsa",
"platform": "linux"
}
]
},
"ibus": {
"description": "Build with ibus IME support",
"supports": "linux"
},
"samplerate": {
"description": "Use libsamplerate for audio rate conversion",
"dependencies": [
"libsamplerate"
]
},
"vulkan": {
"description": "Vulkan functionality for SDL"
},
"wayland": {
"description": "Build with Wayland support",
"supports": "linux"
},
"x11": {
"description": "Build with X11 support",
"supports": "!windows"
}
}
}

View file

@ -1,13 +0,0 @@
diff --git a/cmake/FindCMath.cmake b/cmake/FindCMath.cmake
index ad92218..dd42aba 100644
--- a/cmake/FindCMath.cmake
+++ b/cmake/FindCMath.cmake
@@ -31,7 +31,7 @@ include(CheckSymbolExists)
include(CheckLibraryExists)
check_symbol_exists(pow "math.h" CMath_HAVE_LIBC_POW)
-find_library(CMath_LIBRARY NAMES m)
+find_library(CMath_LIBRARY NAMES m PATHS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
if(NOT CMath_HAVE_LIBC_POW)
set(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES})

View file

@ -1,86 +0,0 @@
vcpkg_from_gitlab(
GITLAB_URL https://gitlab.com
OUT_SOURCE_PATH SOURCE_PATH
REPO libtiff/libtiff
REF "v${VERSION}"
SHA512 ef2f1d424219d9e245069b7d23e78f5e817cf6ee516d46694915ab6c8909522166f84997513d20a702f4e52c3f18467813935b328fafa34bea5156dee00f66fa
HEAD_REF master
PATCHES
FindCMath.patch
)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
cxx cxx
jpeg jpeg
jpeg CMAKE_REQUIRE_FIND_PACKAGE_JPEG
libdeflate libdeflate
libdeflate CMAKE_REQUIRE_FIND_PACKAGE_Deflate
lzma lzma
lzma CMAKE_REQUIRE_FIND_PACKAGE_liblzma
tools tiff-tools
webp webp
webp CMAKE_REQUIRE_FIND_PACKAGE_WebP
zip zlib
zip CMAKE_REQUIRE_FIND_PACKAGE_ZLIB
zstd zstd
zstd CMAKE_REQUIRE_FIND_PACKAGE_ZSTD
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
${FEATURE_OPTIONS}
-DCMAKE_FIND_PACKAGE_PREFER_CONFIG=ON
-Dtiff-docs=OFF
-Dtiff-contrib=OFF
-Dtiff-tests=OFF
-Djbig=OFF # This is disabled by default due to GPL/Proprietary licensing.
-Djpeg12=OFF
-Dlerc=OFF
-DCMAKE_DISABLE_FIND_PACKAGE_OpenGL=ON
-DCMAKE_DISABLE_FIND_PACKAGE_GLUT=ON
-DZSTD_HAVE_DECOMPRESS_STREAM=ON
-DHAVE_JPEGTURBO_DUAL_MODE_8_12=OFF
OPTIONS_DEBUG
-DCMAKE_DEBUG_POSTFIX=d # tiff sets "d" for MSVC only.
MAYBE_UNUSED_VARIABLES
CMAKE_DISABLE_FIND_PACKAGE_GLUT
CMAKE_DISABLE_FIND_PACKAGE_OpenGL
ZSTD_HAVE_DECOMPRESS_STREAM
)
vcpkg_cmake_install()
# CMake config wasn't packaged in the past and is not yet usable now,
# cf. https://gitlab.com/libtiff/libtiff/-/merge_requests/496
# vcpkg_cmake_config_fixup(CONFIG_PATH "lib/cmake/tiff")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/cmake" "${CURRENT_PACKAGES_DIR}/debug/lib/cmake")
set(_file "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libtiff-4.pc")
if(EXISTS "${_file}")
vcpkg_replace_string("${_file}" "-ltiff" "-ltiffd")
endif()
vcpkg_fixup_pkgconfig()
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
)
configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake.in" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-cmake-wrapper.cmake" @ONLY)
if ("tools" IN_LIST FEATURES)
vcpkg_copy_tools(TOOL_NAMES
tiffcp
tiffdump
tiffinfo
tiffset
tiffsplit
AUTO_CLEAN
)
endif()
vcpkg_copy_pdbs()
file(COPY "${CURRENT_PORT_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.md")

View file

@ -1,9 +0,0 @@
tiff is compatible with built-in CMake targets:
find_package(TIFF REQUIRED)
target_link_libraries(main PRIVATE TIFF::TIFF)
tiff provides pkg-config modules:
# Tag Image File Format (TIFF) library.
libtiff-4

View file

@ -1,104 +0,0 @@
cmake_policy(PUSH)
cmake_policy(SET CMP0012 NEW)
cmake_policy(SET CMP0057 NEW)
set(z_vcpkg_tiff_find_options "")
if("REQUIRED" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "REQUIRED")
endif()
if("QUIET" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "QUIET")
endif()
_find_package(${ARGS})
if(TIFF_FOUND AND "@VCPKG_LIBRARY_LINKAGE@" STREQUAL "static")
include(SelectLibraryConfigurations)
set(z_vcpkg_tiff_link_libraries "")
set(z_vcpkg_tiff_libraries "")
if("@webp@")
find_package(WebP CONFIG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:WebP::WebP>")
list(APPEND z_vcpkg_tiff_libraries ${WebP_LIBRARIES})
endif()
if("@lzma@")
find_package(LibLZMA ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:LibLZMA::LibLZMA>")
list(APPEND z_vcpkg_tiff_libraries ${LIBLZMA_LIBRARIES})
endif()
if("@jpeg@")
find_package(JPEG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:JPEG::JPEG>")
list(APPEND z_vcpkg_tiff_libraries ${JPEG_LIBRARIES})
endif()
if("@zstd@")
find_package(zstd CONFIG ${z_vcpkg_tiff_find_options})
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_LOCATION_")
if(TARGET zstd::libzstd_shared)
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_shared>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_shared)
if(WIN32)
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_static>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_static)
endif()
get_target_property(z_vcpkg_tiff_zstd_configs "${z_vcpkg_tiff_zstd_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_tiff_zstd_configs)
get_target_property(ZSTD_LIBRARY_${z_vcpkg_config} "${z_vcpkg_tiff_zstd_target}" "${z_vcpkg_tiff_zstd_target_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(ZSTD)
if(NOT TARGET ZSTD::ZSTD)
add_library(ZSTD::ZSTD INTERFACE IMPORTED)
set_property(TARGET ZSTD::ZSTD APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_zstd})
endif()
list(APPEND z_vcpkg_tiff_link_libraries ${z_vcpkg_tiff_zstd})
list(APPEND z_vcpkg_tiff_libraries ${ZSTD_LIBRARIES})
unset(z_vcpkg_tiff_zstd)
unset(z_vcpkg_tiff_zstd_configs)
unset(z_vcpkg_config)
unset(z_vcpkg_tiff_zstd_target)
endif()
if("@libdeflate@")
find_package(libdeflate ${z_vcpkg_tiff_find_options})
set(z_vcpkg_property "IMPORTED_LOCATION_")
if(TARGET libdeflate::libdeflate_shared)
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_shared)
if(WIN32)
set(z_vcpkg_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_static)
endif()
get_target_property(z_vcpkg_libdeflate_configs "${z_vcpkg_libdeflate_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_libdeflate_configs)
get_target_property(Z_VCPKG_DEFLATE_LIBRARY_${z_vcpkg_config} "${z_vcpkg_libdeflate_target}" "${z_vcpkg_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(Z_VCPKG_DEFLATE)
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:${z_vcpkg_libdeflate_target}>")
list(APPEND z_vcpkg_tiff_libraries ${Z_VCPKG_DEFLATE_LIBRARIES})
unset(z_vcpkg_config)
unset(z_vcpkg_libdeflate_configs)
unset(z_vcpkg_libdeflate_target)
unset(z_vcpkg_property)
unset(Z_VCPKG_DEFLATE_FOUND)
endif()
if("@zlib@")
find_package(ZLIB ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:ZLIB::ZLIB>")
list(APPEND z_vcpkg_tiff_libraries ${ZLIB_LIBRARIES})
endif()
if(UNIX)
list(APPEND z_vcpkg_tiff_link_libraries m)
list(APPEND z_vcpkg_tiff_libraries m)
endif()
if(TARGET TIFF::TIFF)
set_property(TARGET TIFF::TIFF APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_link_libraries})
endif()
list(APPEND TIFF_LIBRARIES ${z_vcpkg_tiff_libraries})
unset(z_vcpkg_tiff_link_libraries)
unset(z_vcpkg_tiff_libraries)
endif()
unset(z_vcpkg_tiff_find_options)
cmake_policy(POP)

View file

@ -1,67 +0,0 @@
{
"name": "tiff",
"version": "4.6.0",
"port-version": 2,
"description": "A library that supports the manipulation of TIFF image files",
"homepage": "https://libtiff.gitlab.io/libtiff/",
"license": "libtiff",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
"jpeg",
"zip"
],
"features": {
"cxx": {
"description": "Build C++ libtiffxx library"
},
"jpeg": {
"description": "Support JPEG compression in TIFF image files",
"dependencies": [
"libjpeg-turbo"
]
},
"libdeflate": {
"description": "Use libdeflate for faster ZIP support",
"dependencies": [
"libdeflate",
{
"name": "tiff",
"default-features": false,
"features": [
"zip"
]
}
]
},
"tools": {
"description": "Build tools"
},
"webp": {
"description": "Support WEBP compression in TIFF image files",
"dependencies": [
"libwebp"
]
},
"zip": {
"description": "Support ZIP/deflate compression in TIFF image files",
"dependencies": [
"zlib"
]
},
"zstd": {
"description": "Support ZSTD compression in TIFF image files",
"dependencies": [
"zstd"
]
}
}
}

View file

@ -1,13 +0,0 @@
diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in
index cc8bcf26d..ead829767 100644
--- a/SDL2Config.cmake.in
+++ b/SDL2Config.cmake.in
@@ -35,7 +35,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
set(SDL_ALSA @SDL_ALSA@)
set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
+if(SDL_ALSA)
sdlFindALSA()
endif()
unset(SDL_ALSA)

View file

@ -1,13 +0,0 @@
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
index 65a98efbe..2f99f28f1 100644
--- a/cmake/sdlchecks.cmake
+++ b/cmake/sdlchecks.cmake
@@ -352,7 +352,7 @@ endmacro()
# - HAVE_SDL_LOADSO opt
macro(CheckLibSampleRate)
if(SDL_LIBSAMPLERATE)
- find_package(SampleRate QUIET)
+ find_package(SampleRate CONFIG REQUIRED)
if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
set(HAVE_LIBSAMPLERATE TRUE)
set(HAVE_LIBSAMPLERATE_H TRUE)

View file

@ -1,137 +0,0 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO libsdl-org/SDL
REF "release-${VERSION}"
SHA512 c7635a83a52f3970a372b804a8631f0a7e6b8d89aed1117bcc54a2040ad0928122175004cf2b42cf84a4fd0f86236f779229eaa63dfa6ca9c89517f999c5ff1c
HEAD_REF main
PATCHES
deps.patch
alsa-dep-fix.patch
)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
alsa SDL_ALSA
alsa CMAKE_REQUIRE_FIND_PACKAGE_ALSA
ibus SDL_IBUS
samplerate SDL_LIBSAMPLERATE
vulkan SDL_VULKAN
wayland SDL_WAYLAND
x11 SDL_X11
INVERTED_FEATURES
alsa CMAKE_DISABLE_FIND_PACKAGE_ALSA
)
if ("x11" IN_LIST FEATURES)
message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
endif()
if ("wayland" IN_LIST FEATURES)
message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
endif()
if ("ibus" IN_LIST FEATURES)
message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
endif()
if(VCPKG_TARGET_IS_UWP)
set(configure_opts WINDOWS_USE_MSBUILD)
endif()
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
${configure_opts}
OPTIONS ${FEATURE_OPTIONS}
-DSDL_STATIC=${SDL_STATIC}
-DSDL_SHARED=${SDL_SHARED}
-DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
-DSDL_LIBC=ON
-DSDL_TEST=OFF
-DSDL_INSTALL_CMAKEDIR="cmake"
-DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
-DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON
-DSDL_LIBSAMPLERATE_SHARED=OFF
MAYBE_UNUSED_VARIABLES
SDL_FORCE_STATIC_VCRT
PKG_CONFIG_USE_CMAKE_PREFIX_PATH
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
"${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
"${CURRENT_PACKAGES_DIR}/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
"${CURRENT_PACKAGES_DIR}/share/licenses"
"${CURRENT_PACKAGES_DIR}/share/aclocal"
)
file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
if(NOT BINS)
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/bin"
"${CURRENT_PACKAGES_DIR}/debug/bin"
)
endif()
if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
endif()
file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
foreach(SHARE_FILE ${SHARE_FILES})
vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
endforeach()
endif()
vcpkg_copy_pdbs()
set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
endif()
if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
endif()
endif()
if(VCPKG_TARGET_IS_UWP)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$<CONFIG:Debug>:d>.lib" "d")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
endif()
endif()
vcpkg_fixup_pkgconfig()
file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")

View file

@ -1,8 +0,0 @@
sdl2 provides CMake targets:
find_package(SDL2 CONFIG REQUIRED)
target_link_libraries(main
PRIVATE
$<TARGET_NAME_IF_EXISTS:SDL2::SDL2main>
$<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
)

View file

@ -1,68 +0,0 @@
{
"name": "sdl2",
"version": "2.30.0",
"description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
"homepage": "https://www.libsdl.org/download-2.0.php",
"license": "Zlib",
"dependencies": [
{
"name": "dbus",
"default-features": false,
"platform": "linux"
},
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
{
"name": "ibus",
"platform": "linux"
},
{
"name": "wayland",
"platform": "linux"
},
{
"name": "x11",
"platform": "linux"
}
],
"features": {
"alsa": {
"description": "Support for alsa audio",
"dependencies": [
{
"name": "alsa",
"platform": "linux"
}
]
},
"ibus": {
"description": "Build with ibus IME support",
"supports": "linux"
},
"samplerate": {
"description": "Use libsamplerate for audio rate conversion",
"dependencies": [
"libsamplerate"
]
},
"vulkan": {
"description": "Vulkan functionality for SDL"
},
"wayland": {
"description": "Build with Wayland support",
"supports": "linux"
},
"x11": {
"description": "Build with X11 support",
"supports": "!windows"
}
}
}

View file

@ -1,13 +0,0 @@
diff --git a/cmake/FindCMath.cmake b/cmake/FindCMath.cmake
index ad92218..dd42aba 100644
--- a/cmake/FindCMath.cmake
+++ b/cmake/FindCMath.cmake
@@ -31,7 +31,7 @@ include(CheckSymbolExists)
include(CheckLibraryExists)
check_symbol_exists(pow "math.h" CMath_HAVE_LIBC_POW)
-find_library(CMath_LIBRARY NAMES m)
+find_library(CMath_LIBRARY NAMES m PATHS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
if(NOT CMath_HAVE_LIBC_POW)
set(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES})

View file

@ -1,86 +0,0 @@
vcpkg_from_gitlab(
GITLAB_URL https://gitlab.com
OUT_SOURCE_PATH SOURCE_PATH
REPO libtiff/libtiff
REF "v${VERSION}"
SHA512 ef2f1d424219d9e245069b7d23e78f5e817cf6ee516d46694915ab6c8909522166f84997513d20a702f4e52c3f18467813935b328fafa34bea5156dee00f66fa
HEAD_REF master
PATCHES
FindCMath.patch
)
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
cxx cxx
jpeg jpeg
jpeg CMAKE_REQUIRE_FIND_PACKAGE_JPEG
libdeflate libdeflate
libdeflate CMAKE_REQUIRE_FIND_PACKAGE_Deflate
lzma lzma
lzma CMAKE_REQUIRE_FIND_PACKAGE_liblzma
tools tiff-tools
webp webp
webp CMAKE_REQUIRE_FIND_PACKAGE_WebP
zip zlib
zip CMAKE_REQUIRE_FIND_PACKAGE_ZLIB
zstd zstd
zstd CMAKE_REQUIRE_FIND_PACKAGE_ZSTD
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
${FEATURE_OPTIONS}
-DCMAKE_FIND_PACKAGE_PREFER_CONFIG=ON
-Dtiff-docs=OFF
-Dtiff-contrib=OFF
-Dtiff-tests=OFF
-Djbig=OFF # This is disabled by default due to GPL/Proprietary licensing.
-Djpeg12=OFF
-Dlerc=OFF
-DCMAKE_DISABLE_FIND_PACKAGE_OpenGL=ON
-DCMAKE_DISABLE_FIND_PACKAGE_GLUT=ON
-DZSTD_HAVE_DECOMPRESS_STREAM=ON
-DHAVE_JPEGTURBO_DUAL_MODE_8_12=OFF
OPTIONS_DEBUG
-DCMAKE_DEBUG_POSTFIX=d # tiff sets "d" for MSVC only.
MAYBE_UNUSED_VARIABLES
CMAKE_DISABLE_FIND_PACKAGE_GLUT
CMAKE_DISABLE_FIND_PACKAGE_OpenGL
ZSTD_HAVE_DECOMPRESS_STREAM
)
vcpkg_cmake_install()
# CMake config wasn't packaged in the past and is not yet usable now,
# cf. https://gitlab.com/libtiff/libtiff/-/merge_requests/496
# vcpkg_cmake_config_fixup(CONFIG_PATH "lib/cmake/tiff")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/cmake" "${CURRENT_PACKAGES_DIR}/debug/lib/cmake")
set(_file "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libtiff-4.pc")
if(EXISTS "${_file}")
vcpkg_replace_string("${_file}" "-ltiff" "-ltiffd")
endif()
vcpkg_fixup_pkgconfig()
file(REMOVE_RECURSE
"${CURRENT_PACKAGES_DIR}/debug/include"
"${CURRENT_PACKAGES_DIR}/debug/share"
)
configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake.in" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-cmake-wrapper.cmake" @ONLY)
if ("tools" IN_LIST FEATURES)
vcpkg_copy_tools(TOOL_NAMES
tiffcp
tiffdump
tiffinfo
tiffset
tiffsplit
AUTO_CLEAN
)
endif()
vcpkg_copy_pdbs()
file(COPY "${CURRENT_PORT_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.md")

View file

@ -1,9 +0,0 @@
tiff is compatible with built-in CMake targets:
find_package(TIFF REQUIRED)
target_link_libraries(main PRIVATE TIFF::TIFF)
tiff provides pkg-config modules:
# Tag Image File Format (TIFF) library.
libtiff-4

View file

@ -1,104 +0,0 @@
cmake_policy(PUSH)
cmake_policy(SET CMP0012 NEW)
cmake_policy(SET CMP0057 NEW)
set(z_vcpkg_tiff_find_options "")
if("REQUIRED" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "REQUIRED")
endif()
if("QUIET" IN_LIST ARGS)
list(APPEND z_vcpkg_tiff_find_options "QUIET")
endif()
_find_package(${ARGS})
if(TIFF_FOUND AND "@VCPKG_LIBRARY_LINKAGE@" STREQUAL "static")
include(SelectLibraryConfigurations)
set(z_vcpkg_tiff_link_libraries "")
set(z_vcpkg_tiff_libraries "")
if("@webp@")
find_package(WebP CONFIG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:WebP::WebP>")
list(APPEND z_vcpkg_tiff_libraries ${WebP_LIBRARIES})
endif()
if("@lzma@")
find_package(LibLZMA ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:LibLZMA::LibLZMA>")
list(APPEND z_vcpkg_tiff_libraries ${LIBLZMA_LIBRARIES})
endif()
if("@jpeg@")
find_package(JPEG ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:JPEG::JPEG>")
list(APPEND z_vcpkg_tiff_libraries ${JPEG_LIBRARIES})
endif()
if("@zstd@")
find_package(zstd CONFIG ${z_vcpkg_tiff_find_options})
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_LOCATION_")
if(TARGET zstd::libzstd_shared)
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_shared>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_shared)
if(WIN32)
set(z_vcpkg_tiff_zstd_target_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_tiff_zstd "\$<LINK_ONLY:zstd::libzstd_static>")
set(z_vcpkg_tiff_zstd_target zstd::libzstd_static)
endif()
get_target_property(z_vcpkg_tiff_zstd_configs "${z_vcpkg_tiff_zstd_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_tiff_zstd_configs)
get_target_property(ZSTD_LIBRARY_${z_vcpkg_config} "${z_vcpkg_tiff_zstd_target}" "${z_vcpkg_tiff_zstd_target_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(ZSTD)
if(NOT TARGET ZSTD::ZSTD)
add_library(ZSTD::ZSTD INTERFACE IMPORTED)
set_property(TARGET ZSTD::ZSTD APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_zstd})
endif()
list(APPEND z_vcpkg_tiff_link_libraries ${z_vcpkg_tiff_zstd})
list(APPEND z_vcpkg_tiff_libraries ${ZSTD_LIBRARIES})
unset(z_vcpkg_tiff_zstd)
unset(z_vcpkg_tiff_zstd_configs)
unset(z_vcpkg_config)
unset(z_vcpkg_tiff_zstd_target)
endif()
if("@libdeflate@")
find_package(libdeflate ${z_vcpkg_tiff_find_options})
set(z_vcpkg_property "IMPORTED_LOCATION_")
if(TARGET libdeflate::libdeflate_shared)
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_shared)
if(WIN32)
set(z_vcpkg_property "IMPORTED_IMPLIB_")
endif()
else()
set(z_vcpkg_libdeflate_target libdeflate::libdeflate_static)
endif()
get_target_property(z_vcpkg_libdeflate_configs "${z_vcpkg_libdeflate_target}" IMPORTED_CONFIGURATIONS)
foreach(z_vcpkg_config IN LISTS z_vcpkg_libdeflate_configs)
get_target_property(Z_VCPKG_DEFLATE_LIBRARY_${z_vcpkg_config} "${z_vcpkg_libdeflate_target}" "${z_vcpkg_property}${z_vcpkg_config}")
endforeach()
select_library_configurations(Z_VCPKG_DEFLATE)
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:${z_vcpkg_libdeflate_target}>")
list(APPEND z_vcpkg_tiff_libraries ${Z_VCPKG_DEFLATE_LIBRARIES})
unset(z_vcpkg_config)
unset(z_vcpkg_libdeflate_configs)
unset(z_vcpkg_libdeflate_target)
unset(z_vcpkg_property)
unset(Z_VCPKG_DEFLATE_FOUND)
endif()
if("@zlib@")
find_package(ZLIB ${z_vcpkg_tiff_find_options})
list(APPEND z_vcpkg_tiff_link_libraries "\$<LINK_ONLY:ZLIB::ZLIB>")
list(APPEND z_vcpkg_tiff_libraries ${ZLIB_LIBRARIES})
endif()
if(UNIX)
list(APPEND z_vcpkg_tiff_link_libraries m)
list(APPEND z_vcpkg_tiff_libraries m)
endif()
if(TARGET TIFF::TIFF)
set_property(TARGET TIFF::TIFF APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${z_vcpkg_tiff_link_libraries})
endif()
list(APPEND TIFF_LIBRARIES ${z_vcpkg_tiff_libraries})
unset(z_vcpkg_tiff_link_libraries)
unset(z_vcpkg_tiff_libraries)
endif()
unset(z_vcpkg_tiff_find_options)
cmake_policy(POP)

View file

@ -1,67 +0,0 @@
{
"name": "tiff",
"version": "4.6.0",
"port-version": 2,
"description": "A library that supports the manipulation of TIFF image files",
"homepage": "https://libtiff.gitlab.io/libtiff/",
"license": "libtiff",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"default-features": [
"jpeg",
"zip"
],
"features": {
"cxx": {
"description": "Build C++ libtiffxx library"
},
"jpeg": {
"description": "Support JPEG compression in TIFF image files",
"dependencies": [
"libjpeg-turbo"
]
},
"libdeflate": {
"description": "Use libdeflate for faster ZIP support",
"dependencies": [
"libdeflate",
{
"name": "tiff",
"default-features": false,
"features": [
"zip"
]
}
]
},
"tools": {
"description": "Build tools"
},
"webp": {
"description": "Support WEBP compression in TIFF image files",
"dependencies": [
"libwebp"
]
},
"zip": {
"description": "Support ZIP/deflate compression in TIFF image files",
"dependencies": [
"zlib"
]
},
"zstd": {
"description": "Support ZSTD compression in TIFF image files",
"dependencies": [
"zstd"
]
}
}
}

1
dependencies/xbyak_aarch64 vendored Submodule

@ -0,0 +1 @@
Subproject commit 904b8923457f3ec0d6f82ea2d6832a792851194d

View file

@ -10,6 +10,8 @@ curl -sSfL https://github.com"$(curl https://github.com/probonopd/go-appimage/re
chmod a+x mkappimage.AppImage
curl -sSfLO "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh"
chmod a+x linuxdeploy-plugin-gtk.sh
curl -sSfLO "https://github.com/darealshinji/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt.sh"
chmod a+x linuxdeploy-plugin-checkrt.sh
if [[ ! -e /usr/lib/x86_64-linux-gnu ]]; then
sed -i 's#lib\/x86_64-linux-gnu#lib64#g' linuxdeploy-plugin-gtk.sh
@ -39,7 +41,8 @@ export NO_STRIP=1
-d "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.desktop \
-i "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.png \
-e "${GITHUB_WORKSPACE}"/AppDir/usr/bin/Cemu \
--plugin gtk
--plugin gtk \
--plugin checkrt
if ! GITVERSION="$(git rev-parse --short HEAD 2>/dev/null)"; then
GITVERSION=experimental
@ -47,7 +50,6 @@ fi
echo "Cemu Version Cemu-${GITVERSION}"
rm AppDir/usr/lib/libwayland-client.so.0
cp /lib/x86_64-linux-gnu/libstdc++.so.6 AppDir/usr/lib/
echo -e "export LC_ALL=C\nexport FONTCONFIG_PATH=/etc/fonts" >> AppDir/apprun-hooks/linuxdeploy-plugin-gtk.sh
VERSION="${GITVERSION}" ./mkappimage.AppImage --appimage-extract-and-run "${GITHUB_WORKSPACE}"/AppDir

View file

@ -24,3 +24,4 @@ Comment[it]=Software per emulare giochi e applicazioni per Wii U su PC
Categories=Game;Emulator;
Keywords=Nintendo;
MimeType=application/x-wii-u-rom;
StartupWMClass=Cemu

17
dist/network_services.xml vendored Normal file
View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<content>
<networkname>CustomExample</networkname>
<disablesslverification>0</disablesslverification>
<urls>
<act>https://account.nintendo.net</act>
<ecs>https://ecs.wup.shop.nintendo.net/ecs/services/ECommerceSOAP</ecs>
<nus>https://nus.wup.shop.nintendo.net/nus/services/NetUpdateSOAP</nus>
<ias>https://ias.wup.shop.nintendo.net/ias/services/IdentityAuthenticationSOAP</ias>
<ccsu>https://ccs.wup.shop.nintendo.net/ccs/download</ccsu>
<ccs>http://ccs.cdn.wup.shop.nintendo.net/ccs/download</ccs>
<idbe>https://idbe-wup.cdn.nintendo.net/icondata</idbe>
<boss>https://npts.app.nintendo.net/p01/tasksheet</boss>
<tagaya>https://tagaya.wup.shop.nintendo.net/tagaya/versionlist</tagaya>
<olv>https://discovery.olv.nintendo.net/v1/endpoint</olv>
</urls>
</content>

View file

@ -49,13 +49,18 @@ add_subdirectory(audio)
add_subdirectory(util)
add_subdirectory(imgui)
add_subdirectory(resource)
add_subdirectory(asm)
add_executable(CemuBin
main.cpp
mainLLE.cpp
)
if(MSVC AND MSVC_VERSION EQUAL 1940)
# workaround for an msvc issue on VS 17.10 where generated ILK files are too large
# see https://developercommunity.visualstudio.com/t/After-updating-to-VS-1710-the-size-of-/10665511
set_target_properties(CemuBin PROPERTIES LINK_FLAGS "/INCREMENTAL:NO")
endif()
if(WIN32)
target_sources(CemuBin PRIVATE
resource/cemu.rc
@ -76,8 +81,8 @@ if (MACOS_BUNDLE)
set(MACOSX_BUNDLE_ICON_FILE "cemu.icns")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "info.cemu.Cemu")
set(MACOSX_BUNDLE_BUNDLE_NAME "Cemu")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${CMAKE_PROJECT_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION ${CMAKE_PROJECT_VERSION})
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}")
set(MACOSX_BUNDLE_BUNDLE_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}")
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2024 Cemu Project")
set(MACOSX_BUNDLE_CATEGORY "public.app-category.games")
@ -95,11 +100,26 @@ if (MACOS_BUNDLE)
COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory "${CMAKE_SOURCE_DIR}/bin/${folder}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/SharedSupport/${folder}")
endforeach(folder)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(LIBUSB_PATH "${CMAKE_BINARY_DIR}/vcpkg_installed/${VCPKG_TARGET_TRIPLET}/debug/lib/libusb-1.0.0.dylib")
else()
set(LIBUSB_PATH "${CMAKE_BINARY_DIR}/vcpkg_installed/${VCPKG_TARGET_TRIPLET}/lib/libusb-1.0.0.dylib")
endif()
if (EXISTS "/usr/local/lib/libMoltenVK.dylib")
set(MOLTENVK_PATH "/usr/local/lib/libMoltenVK.dylib")
elseif (EXISTS "/opt/homebrew/lib/libMoltenVK.dylib")
set(MOLTENVK_PATH "/opt/homebrew/lib/libMoltenVK.dylib")
else()
message(FATAL_ERROR "failed to find libMoltenVK.dylib")
endif ()
add_custom_command (TARGET CemuBin POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy "/usr/local/lib/libMoltenVK.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib"
COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_BINARY_DIR}/vcpkg_installed/x64-osx/lib/libusb-1.0.0.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libusb-1.0.0.dylib"
COMMAND ${CMAKE_COMMAND} ARGS -E copy "${MOLTENVK_PATH}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib"
COMMAND ${CMAKE_COMMAND} ARGS -E copy "${LIBUSB_PATH}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libusb-1.0.0.dylib"
COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_SOURCE_DIR}/src/resource/update.sh" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/update.sh"
COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}"
COMMAND bash -c "install_name_tool -change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}")
COMMAND bash -c "install_name_tool -change ${LIBUSB_PATH} @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}")
endif()
set_target_properties(CemuBin PROPERTIES

View file

@ -10,6 +10,7 @@ add_library(CemuCafe
Filesystem/fscDeviceRedirect.cpp
Filesystem/fscDeviceWua.cpp
Filesystem/fscDeviceWud.cpp
Filesystem/fscDeviceWuhb.cpp
Filesystem/fsc.h
Filesystem/FST/FST.cpp
Filesystem/FST/FST.h
@ -18,6 +19,9 @@ add_library(CemuCafe
Filesystem/FST/KeyCache.h
Filesystem/WUD/wud.cpp
Filesystem/WUD/wud.h
Filesystem/WUHB/RomFSStructs.h
Filesystem/WUHB/WUHBReader.cpp
Filesystem/WUHB/WUHBReader.h
GamePatch.cpp
GamePatch.h
GameProfile/GameProfile.cpp
@ -63,24 +67,31 @@ add_library(CemuCafe
HW/Espresso/Recompiler/PPCFunctionBoundaryTracker.h
HW/Espresso/Recompiler/PPCRecompiler.cpp
HW/Espresso/Recompiler/PPCRecompiler.h
HW/Espresso/Recompiler/PPCRecompilerImlAnalyzer.cpp
HW/Espresso/Recompiler/IML/IML.h
HW/Espresso/Recompiler/IML/IMLSegment.cpp
HW/Espresso/Recompiler/IML/IMLSegment.h
HW/Espresso/Recompiler/IML/IMLInstruction.cpp
HW/Espresso/Recompiler/IML/IMLInstruction.h
HW/Espresso/Recompiler/IML/IMLDebug.cpp
HW/Espresso/Recompiler/IML/IMLAnalyzer.cpp
HW/Espresso/Recompiler/IML/IMLOptimizer.cpp
HW/Espresso/Recompiler/IML/IMLRegisterAllocator.cpp
HW/Espresso/Recompiler/IML/IMLRegisterAllocator.h
HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.cpp
HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.h
HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp
HW/Espresso/Recompiler/PPCRecompilerImlGenFPU.cpp
HW/Espresso/Recompiler/PPCRecompilerIml.h
HW/Espresso/Recompiler/PPCRecompilerImlOptimizer.cpp
HW/Espresso/Recompiler/PPCRecompilerImlRanges.cpp
HW/Espresso/Recompiler/PPCRecompilerImlRanges.h
HW/Espresso/Recompiler/PPCRecompilerImlRegisterAllocator2.cpp
HW/Espresso/Recompiler/PPCRecompilerImlRegisterAllocator.cpp
HW/Espresso/Recompiler/PPCRecompilerIntermediate.cpp
HW/Espresso/Recompiler/PPCRecompilerX64AVX.cpp
HW/Espresso/Recompiler/PPCRecompilerX64BMI.cpp
HW/Espresso/Recompiler/PPCRecompilerX64.cpp
HW/Espresso/Recompiler/PPCRecompilerX64FPU.cpp
HW/Espresso/Recompiler/PPCRecompilerX64Gen.cpp
HW/Espresso/Recompiler/PPCRecompilerX64GenFPU.cpp
HW/Espresso/Recompiler/PPCRecompilerX64.h
HW/Espresso/Recompiler/x64Emit.hpp
HW/Espresso/Recompiler/BackendX64/BackendX64AVX.cpp
HW/Espresso/Recompiler/BackendX64/BackendX64BMI.cpp
HW/Espresso/Recompiler/BackendX64/BackendX64.cpp
HW/Espresso/Recompiler/BackendX64/BackendX64FPU.cpp
HW/Espresso/Recompiler/BackendX64/BackendX64Gen.cpp
HW/Espresso/Recompiler/BackendX64/BackendX64GenFPU.cpp
HW/Espresso/Recompiler/BackendX64/BackendX64.h
HW/Espresso/Recompiler/BackendX64/X64Emit.hpp
HW/Espresso/Recompiler/BackendX64/x86Emitter.h
HW/Latte/Common/RegisterSerializer.cpp
HW/Latte/Common/RegisterSerializer.h
HW/Latte/Common/ShaderSerializer.cpp
@ -214,6 +225,8 @@ add_library(CemuCafe
HW/SI/SI.cpp
HW/SI/si.h
HW/VI/VI.cpp
IOSU/ccr_nfc/iosu_ccr_nfc.cpp
IOSU/ccr_nfc/iosu_ccr_nfc.h
IOSU/fsa/fsa_types.h
IOSU/fsa/iosu_fsa.cpp
IOSU/fsa/iosu_fsa.h
@ -368,12 +381,24 @@ add_library(CemuCafe
OS/libs/gx2/GX2_Texture.h
OS/libs/gx2/GX2_TilingAperture.cpp
OS/libs/h264_avc/H264Dec.cpp
OS/libs/h264_avc/H264DecBackendAVC.cpp
OS/libs/h264_avc/h264dec.h
OS/libs/h264_avc/H264DecInternal.h
OS/libs/h264_avc/parser
OS/libs/h264_avc/parser/H264Parser.cpp
OS/libs/h264_avc/parser/H264Parser.h
OS/libs/mic/mic.cpp
OS/libs/mic/mic.h
OS/libs/nfc/ndef.cpp
OS/libs/nfc/ndef.h
OS/libs/nfc/nfc.cpp
OS/libs/nfc/nfc.h
OS/libs/nfc/stream.cpp
OS/libs/nfc/stream.h
OS/libs/nfc/TagV0.cpp
OS/libs/nfc/TagV0.h
OS/libs/nfc/TLV.cpp
OS/libs/nfc/TLV.h
OS/libs/nlibcurl/nlibcurl.cpp
OS/libs/nlibcurl/nlibcurlDebug.hpp
OS/libs/nlibcurl/nlibcurl.h
@ -441,14 +466,26 @@ add_library(CemuCafe
OS/libs/nsyshid/AttachDefaultBackends.cpp
OS/libs/nsyshid/Whitelist.cpp
OS/libs/nsyshid/Whitelist.h
OS/libs/nsyshid/BackendEmulated.cpp
OS/libs/nsyshid/BackendEmulated.h
OS/libs/nsyshid/BackendLibusb.cpp
OS/libs/nsyshid/BackendLibusb.h
OS/libs/nsyshid/BackendWindowsHID.cpp
OS/libs/nsyshid/BackendWindowsHID.h
OS/libs/nsyshid/Dimensions.cpp
OS/libs/nsyshid/Dimensions.h
OS/libs/nsyshid/Infinity.cpp
OS/libs/nsyshid/Infinity.h
OS/libs/nsyshid/Skylander.cpp
OS/libs/nsyshid/Skylander.h
OS/libs/nsyshid/SkylanderXbox360.cpp
OS/libs/nsyshid/SkylanderXbox360.h
OS/libs/nsyshid/g721/g721.cpp
OS/libs/nsyshid/g721/g721.h
OS/libs/nsyskbd/nsyskbd.cpp
OS/libs/nsyskbd/nsyskbd.h
OS/libs/nsysnet/nsysnet.cpp
OS/libs/nsysnet/nsysnet.h
OS/libs/ntag/ntag.cpp
OS/libs/ntag/ntag.h
OS/libs/padscore/padscore.cpp
OS/libs/padscore/padscore.h
OS/libs/proc_ui/proc_ui.cpp
@ -500,12 +537,25 @@ if(APPLE)
target_sources(CemuCafe PRIVATE "HW/Latte/Renderer/Vulkan/CocoaSurface.mm")
endif()
if(CEMU_ARCHITECTURE MATCHES "(aarch64)|(AARCH64)|(arm64)|(ARM64)")
target_sources(CemuCafe PRIVATE
HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp
HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.h
)
target_link_libraries(CemuCafe PRIVATE xbyak_aarch64)
endif()
set_property(TARGET CemuCafe PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
target_include_directories(CemuCafe PUBLIC "../")
if (glslang_VERSION VERSION_LESS "15.0.0")
set(glslang_target "glslang::SPIRV")
else()
set(glslang_target "glslang::glslang")
endif()
target_link_libraries(CemuCafe PRIVATE
CemuAsm
CemuAudio
CemuCommon
CemuComponents
@ -519,7 +569,7 @@ target_link_libraries(CemuCafe PRIVATE
Boost::nowide
CURL::libcurl
fmt::fmt
glslang::SPIRV
${glslang_target}
ih264d
OpenSSL::Crypto
OpenSSL::SSL
@ -535,15 +585,16 @@ if (ENABLE_WAYLAND)
target_link_libraries(CemuCafe PUBLIC Wayland::Client)
endif()
if (ENABLE_NSYSHID_LIBUSB)
if (ENABLE_VCPKG)
find_package(PkgConfig REQUIRED)
pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0)
target_link_libraries(CemuCafe PRIVATE PkgConfig::libusb)
else ()
find_package(libusb MODULE REQUIRED)
target_link_libraries(CemuCafe PRIVATE libusb::libusb)
endif ()
if (ENABLE_VCPKG)
if(WIN32)
set(PKG_CONFIG_EXECUTABLE "${VCPKG_INSTALLED_DIR}/x64-windows/tools/pkgconf/pkgconf.exe")
endif()
find_package(PkgConfig REQUIRED)
pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0)
target_link_libraries(CemuCafe PRIVATE PkgConfig::libusb)
else ()
find_package(libusb MODULE REQUIRED)
target_link_libraries(CemuCafe PRIVATE libusb::libusb)
endif ()
if (ENABLE_WXWIDGETS)

View file

@ -9,6 +9,7 @@
#include "audio/IAudioAPI.h"
#include "audio/IAudioInputAPI.h"
#include "config/ActiveSettings.h"
#include "config/LaunchSettings.h"
#include "Cafe/TitleList/GameInfo.h"
#include "Cafe/GraphicPack/GraphicPack2.h"
#include "util/helpers/SystemException.h"
@ -35,6 +36,7 @@
#include "Cafe/IOSU/legacy/iosu_boss.h"
#include "Cafe/IOSU/legacy/iosu_nim.h"
#include "Cafe/IOSU/PDM/iosu_pdm.h"
#include "Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.h"
// IOSU initializer functions
#include "Cafe/IOSU/kernel/iosu_kernel.h"
@ -51,6 +53,8 @@
#include "Cafe/OS/libs/gx2/GX2.h"
#include "Cafe/OS/libs/gx2/GX2_Misc.h"
#include "Cafe/OS/libs/mic/mic.h"
#include "Cafe/OS/libs/nfc/nfc.h"
#include "Cafe/OS/libs/ntag/ntag.h"
#include "Cafe/OS/libs/nn_aoc/nn_aoc.h"
#include "Cafe/OS/libs/nn_pdm/nn_pdm.h"
#include "Cafe/OS/libs/nn_cmpt/nn_cmpt.h"
@ -393,7 +397,7 @@ void cemu_initForGame()
// replace any known function signatures with our HLE implementations and patch bugs in the games
GamePatch_scan();
}
LatteGPUState.alwaysDisplayDRC = ActiveSettings::DisplayDRCEnabled();
LatteGPUState.isDRCPrimary = ActiveSettings::DisplayDRCEnabled();
InfoLog_PrintActiveSettings();
Latte_Start();
// check for debugger entrypoint bp
@ -533,6 +537,7 @@ namespace CafeSystem
iosu::acp::GetModule(),
iosu::fpd::GetModule(),
iosu::pdm::GetModule(),
iosu::ccr_nfc::GetModule(),
};
// initialize all subsystems which are persistent and don't depend on a game running
@ -587,6 +592,8 @@ namespace CafeSystem
H264::Initialize();
snd_core::Initialize();
mic::Initialize();
nfc::Initialize();
ntag::Initialize();
// init hardware register interfaces
HW_SI::Initialize();
}
@ -631,40 +638,40 @@ namespace CafeSystem
fsc_unmount("/cemuBossStorage/", FSC_PRIORITY_BASE);
}
STATUS_CODE LoadAndMountForegroundTitle(TitleId titleId)
PREPARE_STATUS_CODE LoadAndMountForegroundTitle(TitleId titleId)
{
cemuLog_log(LogType::Force, "Mounting title {:016x}", (uint64)titleId);
sGameInfo_ForegroundTitle = CafeTitleList::GetGameInfo(titleId);
if (!sGameInfo_ForegroundTitle.IsValid())
{
cemuLog_log(LogType::Force, "Mounting failed: Game meta information is either missing, inaccessible or not valid (missing or invalid .xml files in code and meta folder)");
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
// check base
TitleInfo& titleBase = sGameInfo_ForegroundTitle.GetBase();
if (!titleBase.IsValid())
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
if(!titleBase.ParseXmlInfo())
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
cemuLog_log(LogType::Force, "Base: {}", titleBase.GetPrintPath());
// mount base
if (!titleBase.Mount("/vol/content", "content", FSC_PRIORITY_BASE) || !titleBase.Mount(GetInternalVirtualCodeFolder(), "code", FSC_PRIORITY_BASE))
{
cemuLog_log(LogType::Force, "Mounting failed");
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
// check update
TitleInfo& titleUpdate = sGameInfo_ForegroundTitle.GetUpdate();
if (titleUpdate.IsValid())
{
if (!titleUpdate.ParseXmlInfo())
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
cemuLog_log(LogType::Force, "Update: {}", titleUpdate.GetPrintPath());
// mount update
if (!titleUpdate.Mount("/vol/content", "content", FSC_PRIORITY_PATCH) || !titleUpdate.Mount(GetInternalVirtualCodeFolder(), "code", FSC_PRIORITY_PATCH))
{
cemuLog_log(LogType::Force, "Mounting failed");
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
}
else
@ -676,20 +683,20 @@ namespace CafeSystem
// todo - support for multi-title AOC
TitleInfo& titleAOC = aocList[0];
if (!titleAOC.ParseXmlInfo())
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
cemu_assert_debug(titleAOC.IsValid());
cemuLog_log(LogType::Force, "DLC: {}", titleAOC.GetPrintPath());
// mount AOC
if (!titleAOC.Mount(fmt::format("/vol/aoc{:016x}", titleAOC.GetAppTitleId()), "content", FSC_PRIORITY_PATCH))
{
cemuLog_log(LogType::Force, "Mounting failed");
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
}
else
cemuLog_log(LogType::Force, "DLC: Not present");
sForegroundTitleId = titleId;
return STATUS_CODE::SUCCESS;
return PREPARE_STATUS_CODE::SUCCESS;
}
void UnmountForegroundTitle()
@ -717,7 +724,7 @@ namespace CafeSystem
}
}
STATUS_CODE SetupExecutable()
PREPARE_STATUS_CODE SetupExecutable()
{
// set rpx path from cos.xml if available
_pathToBaseExecutable = _pathToExecutable;
@ -749,7 +756,7 @@ namespace CafeSystem
}
}
LoadMainExecutable();
return STATUS_CODE::SUCCESS;
return PREPARE_STATUS_CODE::SUCCESS;
}
void SetupMemorySpace()
@ -763,7 +770,7 @@ namespace CafeSystem
memory_unmapForCurrentTitle();
}
STATUS_CODE PrepareForegroundTitle(TitleId titleId)
PREPARE_STATUS_CODE PrepareForegroundTitle(TitleId titleId)
{
CafeTitleList::WaitForMandatoryScan();
sLaunchModeIsStandalone = false;
@ -774,21 +781,21 @@ namespace CafeSystem
// mount mlc storage
MountBaseDirectories();
// mount title folders
STATUS_CODE r = LoadAndMountForegroundTitle(titleId);
if (r != STATUS_CODE::SUCCESS)
PREPARE_STATUS_CODE r = LoadAndMountForegroundTitle(titleId);
if (r != PREPARE_STATUS_CODE::SUCCESS)
return r;
gameProfile_load();
// setup memory space and PPC recompiler
SetupMemorySpace();
PPCRecompiler_init();
r = SetupExecutable(); // load RPX
if (r != STATUS_CODE::SUCCESS)
if (r != PREPARE_STATUS_CODE::SUCCESS)
return r;
InitVirtualMlcStorage();
return STATUS_CODE::SUCCESS;
return PREPARE_STATUS_CODE::SUCCESS;
}
STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path)
PREPARE_STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path)
{
sLaunchModeIsStandalone = true;
cemuLog_log(LogType::Force, "Launching executable in standalone mode due to incorrect layout or missing meta files");
@ -806,7 +813,7 @@ namespace CafeSystem
if (!r)
{
cemuLog_log(LogType::Force, "Failed to mount {}", _pathToUtf8(contentPath));
return STATUS_CODE::UNABLE_TO_MOUNT;
return PREPARE_STATUS_CODE::UNABLE_TO_MOUNT;
}
}
}
@ -818,7 +825,7 @@ namespace CafeSystem
// since a lot of systems (including save folder location) rely on a TitleId, we derive a placeholder id from the executable hash
auto execData = fsc_extractFile(_pathToExecutable.c_str());
if (!execData)
return STATUS_CODE::INVALID_RPX;
return PREPARE_STATUS_CODE::INVALID_RPX;
uint32 h = generateHashFromRawRPXData(execData->data(), execData->size());
sForegroundTitleId = 0xFFFFFFFF00000000ULL | (uint64)h;
cemuLog_log(LogType::Force, "Generated placeholder TitleId: {:016x}", sForegroundTitleId);
@ -828,7 +835,7 @@ namespace CafeSystem
// load executable
SetupExecutable();
InitVirtualMlcStorage();
return STATUS_CODE::SUCCESS;
return PREPARE_STATUS_CODE::SUCCESS;
}
void _LaunchTitleThread()
@ -837,7 +844,7 @@ namespace CafeSystem
module->TitleStart();
cemu_initForGame();
// enter scheduler
if (ActiveSettings::GetCPUMode() == CPUMode::MulticoreRecompiler)
if ((ActiveSettings::GetCPUMode() == CPUMode::MulticoreRecompiler || LaunchSettings::ForceMultiCoreInterpreter()) && !LaunchSettings::ForceInterpreter())
coreinit::OSSchedulerBegin(3);
else
coreinit::OSSchedulerBegin(1);

View file

@ -15,20 +15,19 @@ namespace CafeSystem
virtual void CafeRecreateCanvas() = 0;
};
enum class STATUS_CODE
enum class PREPARE_STATUS_CODE
{
SUCCESS,
INVALID_RPX,
UNABLE_TO_MOUNT, // failed to mount through TitleInfo (most likely caused by an invalid or outdated path)
//BAD_META_DATA, - the title list only stores titles with valid meta, so this error code is impossible
};
void Initialize();
void SetImplementation(SystemImplementation* impl);
void Shutdown();
STATUS_CODE PrepareForegroundTitle(TitleId titleId);
STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path);
PREPARE_STATUS_CODE PrepareForegroundTitle(TitleId titleId);
PREPARE_STATUS_CODE PrepareForegroundTitleFromStandaloneRPX(const fs::path& path);
void LaunchForegroundTitle();
bool IsTitleRunning();

View file

@ -3,8 +3,7 @@
#include "Cemu/ncrypto/ncrypto.h"
#include "Cafe/Filesystem/WUD/wud.h"
#include "util/crypto/aes128.h"
#include "openssl/evp.h" /* EVP_Digest */
#include "openssl/sha.h" /* SHA1 / SHA256_DIGEST_LENGTH */
#include "openssl/sha.h" /* SHA1 / SHA256 */
#include "fstUtil.h"
#include "FST.h"
@ -14,6 +13,8 @@
#define SET_FST_ERROR(__code) if (errorCodeOut) *errorCodeOut = ErrorCode::__code
static_assert(sizeof(NCrypto::AesIv) == 16); // make sure IV is actually 16 bytes
class FSTDataSource
{
public:
@ -141,7 +142,7 @@ struct DiscPartitionTableHeader
static constexpr uint32 MAGIC_VALUE = 0xCCA6E67B;
/* +0x00 */ uint32be magic;
/* +0x04 */ uint32be sectorSize; // must be 0x8000?
/* +0x04 */ uint32be blockSize; // must be 0x8000?
/* +0x08 */ uint8 partitionTableHash[20]; // hash of the data range at +0x800 to end of sector (0x8000)
/* +0x1C */ uint32be numPartitions;
};
@ -164,10 +165,10 @@ struct DiscPartitionHeader
static constexpr uint32 MAGIC_VALUE = 0xCC93A4F5;
/* +0x00 */ uint32be magic;
/* +0x04 */ uint32be sectorSize; // must match DISC_SECTOR_SIZE
/* +0x04 */ uint32be sectorSize; // must match DISC_SECTOR_SIZE for hashed blocks
/* +0x08 */ uint32be ukn008;
/* +0x0C */ uint32be ukn00C;
/* +0x0C */ uint32be ukn00C; // h3 array size?
/* +0x10 */ uint32be h3HashNum;
/* +0x14 */ uint32be fstSize; // in bytes
/* +0x18 */ uint32be fstSector; // relative to partition start
@ -178,13 +179,15 @@ struct DiscPartitionHeader
/* +0x24 */ uint8 fstHashType;
/* +0x25 */ uint8 fstEncryptionType; // purpose of this isn't really understood. Maybe it controls which key is being used? (1 -> disc key, 2 -> partition key)
/* +0x26 */ uint8 versionA;
/* +0x27 */ uint8 ukn027; // also a version field?
/* +0x26 */ uint8be versionA;
/* +0x27 */ uint8be ukn027; // also a version field?
// there is an array at +0x40 ? Related to H3 list. Also related to value at +0x0C and h3HashNum
/* +0x28 */ uint8be _uknOrPadding028[0x18];
/* +0x40 */ uint8be h3HashArray[32]; // dynamic size. Only present if fstHashType != 0
};
static_assert(sizeof(DiscPartitionHeader) == 0x28);
static_assert(sizeof(DiscPartitionHeader) == 0x40+0x20);
bool FSTVolume::FindDiscKey(const fs::path& path, NCrypto::AesKey& discTitleKey)
{
@ -269,7 +272,7 @@ FSTVolume* FSTVolume::OpenFromDiscImage(const fs::path& path, NCrypto::AesKey& d
cemuLog_log(LogType::Force, "Disc image rejected because decryption failed");
return nullptr;
}
if (partitionHeader->sectorSize != DISC_SECTOR_SIZE)
if (partitionHeader->blockSize != DISC_SECTOR_SIZE)
{
cemuLog_log(LogType::Force, "Disc image rejected because partition sector size is invalid");
return nullptr;
@ -336,6 +339,9 @@ FSTVolume* FSTVolume::OpenFromDiscImage(const fs::path& path, NCrypto::AesKey& d
cemu_assert_debug(partitionHeaderSI.fstEncryptionType == 1);
// todo - check other fields?
if(partitionHeaderSI.fstHashType == 0 && partitionHeaderSI.h3HashNum != 0)
cemuLog_log(LogType::Force, "FST: Partition uses unhashed blocks but stores a non-zero amount of H3 hashes");
// GM partition
DiscPartitionHeader partitionHeaderGM{};
if (!readPartitionHeader(partitionHeaderGM, gmPartitionIndex))
@ -349,9 +355,10 @@ FSTVolume* FSTVolume::OpenFromDiscImage(const fs::path& path, NCrypto::AesKey& d
// if decryption is necessary
// load SI FST
dataSource->SetBaseOffset((uint64)partitionArray[siPartitionIndex].partitionAddress * DISC_SECTOR_SIZE);
auto siFST = OpenFST(dataSource.get(), (uint64)partitionHeaderSI.fstSector * DISC_SECTOR_SIZE, partitionHeaderSI.fstSize, &discTitleKey, static_cast<FSTVolume::ClusterHashMode>(partitionHeaderSI.fstHashType));
auto siFST = OpenFST(dataSource.get(), (uint64)partitionHeaderSI.fstSector * DISC_SECTOR_SIZE, partitionHeaderSI.fstSize, &discTitleKey, static_cast<FSTVolume::ClusterHashMode>(partitionHeaderSI.fstHashType), nullptr);
if (!siFST)
return nullptr;
cemu_assert_debug(!(siFST->HashIsDisabled() && partitionHeaderSI.h3HashNum != 0)); // if hash is disabled, no H3 data may be present
// load ticket file for partition that we want to decrypt
NCrypto::ETicketParser ticketParser;
std::vector<uint8> ticketData = siFST->ExtractFile(fmt::format("{:02x}/title.tik", gmPartitionIndex));
@ -360,16 +367,32 @@ FSTVolume* FSTVolume::OpenFromDiscImage(const fs::path& path, NCrypto::AesKey& d
cemuLog_log(LogType::Force, "Disc image ticket file is invalid");
return nullptr;
}
#if 0
// each SI partition seems to contain a title.tmd that we could parse and which should have information about the associated GM partition
// but the console seems to ignore this file for disc images, at least when mounting, so we shouldn't rely on it either
std::vector<uint8> tmdData = siFST->ExtractFile(fmt::format("{:02x}/title.tmd", gmPartitionIndex));
if (tmdData.empty())
{
cemuLog_log(LogType::Force, "Disc image TMD file is missing");
return nullptr;
}
// parse TMD
NCrypto::TMDParser tmdParser;
if (!tmdParser.parse(tmdData.data(), tmdData.size()))
{
cemuLog_log(LogType::Force, "Disc image TMD file is invalid");
return nullptr;
}
#endif
delete siFST;
NCrypto::AesKey gmTitleKey;
ticketParser.GetTitleKey(gmTitleKey);
// load GM partition
dataSource->SetBaseOffset((uint64)partitionArray[gmPartitionIndex].partitionAddress * DISC_SECTOR_SIZE);
FSTVolume* r = OpenFST(std::move(dataSource), (uint64)partitionHeaderGM.fstSector * DISC_SECTOR_SIZE, partitionHeaderGM.fstSize, &gmTitleKey, static_cast<FSTVolume::ClusterHashMode>(partitionHeaderGM.fstHashType));
FSTVolume* r = OpenFST(std::move(dataSource), (uint64)partitionHeaderGM.fstSector * DISC_SECTOR_SIZE, partitionHeaderGM.fstSize, &gmTitleKey, static_cast<FSTVolume::ClusterHashMode>(partitionHeaderGM.fstHashType), nullptr);
if (r)
SET_FST_ERROR(OK);
cemu_assert_debug(!(r->HashIsDisabled() && partitionHeaderGM.h3HashNum != 0)); // if hash is disabled, no H3 data may be present
return r;
}
@ -426,15 +449,15 @@ FSTVolume* FSTVolume::OpenFromContentFolder(fs::path folderPath, ErrorCode* erro
}
// load FST
// fstSize = size of first cluster?
FSTVolume* fstVolume = FSTVolume::OpenFST(std::move(dataSource), 0, fstSize, &titleKey, fstHashMode);
FSTVolume* fstVolume = FSTVolume::OpenFST(std::move(dataSource), 0, fstSize, &titleKey, fstHashMode, &tmdParser);
if (fstVolume)
SET_FST_ERROR(OK);
return fstVolume;
}
FSTVolume* FSTVolume::OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode)
FSTVolume* FSTVolume::OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode, NCrypto::TMDParser* optionalTMD)
{
cemu_assert_debug(fstHashMode != ClusterHashMode::RAW || fstHashMode != ClusterHashMode::RAW2);
cemu_assert_debug(fstHashMode != ClusterHashMode::RAW || fstHashMode != ClusterHashMode::RAW_STREAM);
if (fstSize < sizeof(FSTHeader))
return nullptr;
constexpr uint64 FST_CLUSTER_OFFSET = 0;
@ -465,6 +488,34 @@ FSTVolume* FSTVolume::OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint3
clusterTable[i].offset = clusterDataTable[i].offset;
clusterTable[i].size = clusterDataTable[i].size;
clusterTable[i].hashMode = static_cast<FSTVolume::ClusterHashMode>((uint8)clusterDataTable[i].hashMode);
clusterTable[i].hasContentHash = false; // from the TMD file (H4?)
}
// if the TMD is available (when opening .app files) we can use the extra info from it to validate unhashed clusters
// each content entry in the TMD corresponds to one cluster used by the FST
if(optionalTMD)
{
if(numCluster != optionalTMD->GetContentList().size())
{
cemuLog_log(LogType::Force, "FST: Number of clusters does not match TMD content list");
return nullptr;
}
auto& contentList = optionalTMD->GetContentList();
for(size_t i=0; i<contentList.size(); i++)
{
auto& cluster = clusterTable[i];
auto& content = contentList[i];
cluster.hasContentHash = true;
cluster.contentHashIsSHA1 = HAS_FLAG(contentList[i].contentFlags, NCrypto::TMDParser::TMDContentFlags::FLAG_SHA1);
cluster.contentSize = content.size;
static_assert(sizeof(content.hash32) == sizeof(cluster.contentHash32));
memcpy(cluster.contentHash32, content.hash32, sizeof(cluster.contentHash32));
// if unhashed mode, then initialize the hash context
if(cluster.hashMode == ClusterHashMode::RAW || cluster.hashMode == ClusterHashMode::RAW_STREAM)
{
cluster.singleHashCtx.reset(EVP_MD_CTX_new());
EVP_DigestInit_ex(cluster.singleHashCtx.get(), cluster.contentHashIsSHA1 ? EVP_sha1() : EVP_sha256(), nullptr);
}
}
}
// preprocess FST table
FSTHeader_FileEntry* fileTable = (FSTHeader_FileEntry*)(clusterDataTable + numCluster);
@ -491,16 +542,17 @@ FSTVolume* FSTVolume::OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint3
fstVolume->m_offsetFactor = fstHeader->offsetFactor;
fstVolume->m_sectorSize = DISC_SECTOR_SIZE;
fstVolume->m_partitionTitlekey = *partitionTitleKey;
std::swap(fstVolume->m_cluster, clusterTable);
std::swap(fstVolume->m_entries, fstEntries);
std::swap(fstVolume->m_nameStringTable, nameStringTable);
fstVolume->m_hashIsDisabled = fstHeader->hashIsDisabled != 0;
fstVolume->m_cluster = std::move(clusterTable);
fstVolume->m_entries = std::move(fstEntries);
fstVolume->m_nameStringTable = std::move(nameStringTable);
return fstVolume;
}
FSTVolume* FSTVolume::OpenFST(std::unique_ptr<FSTDataSource> dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode)
FSTVolume* FSTVolume::OpenFST(std::unique_ptr<FSTDataSource> dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode, NCrypto::TMDParser* optionalTMD)
{
FSTDataSource* ds = dataSource.release();
FSTVolume* fstVolume = OpenFST(ds, fstOffset, fstSize, partitionTitleKey, fstHashMode);
FSTVolume* fstVolume = OpenFST(ds, fstOffset, fstSize, partitionTitleKey, fstHashMode, optionalTMD);
if (!fstVolume)
{
delete ds;
@ -757,7 +809,7 @@ uint32 FSTVolume::ReadFile(FSTFileHandle& fileHandle, uint32 offset, uint32 size
return 0;
cemu_assert_debug(!HAS_FLAG(entry.GetFlags(), FSTEntry::FLAGS::FLAG_LINK));
FSTCluster& cluster = m_cluster[entry.fileInfo.clusterIndex];
if (cluster.hashMode == ClusterHashMode::RAW || cluster.hashMode == ClusterHashMode::RAW2)
if (cluster.hashMode == ClusterHashMode::RAW || cluster.hashMode == ClusterHashMode::RAW_STREAM)
return ReadFile_HashModeRaw(entry.fileInfo.clusterIndex, entry, offset, size, dataOut);
else if (cluster.hashMode == ClusterHashMode::HASH_INTERLEAVED)
return ReadFile_HashModeHashed(entry.fileInfo.clusterIndex, entry, offset, size, dataOut);
@ -765,87 +817,15 @@ uint32 FSTVolume::ReadFile(FSTFileHandle& fileHandle, uint32 offset, uint32 size
return 0;
}
uint32 FSTVolume::ReadFile_HashModeRaw(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut)
{
const uint32 readSizeInput = readSize;
uint8* dataOutU8 = (uint8*)dataOut;
if (readOffset >= entry.fileInfo.fileSize)
return 0;
else if ((readOffset + readSize) >= entry.fileInfo.fileSize)
readSize = (entry.fileInfo.fileSize - readOffset);
const FSTCluster& cluster = m_cluster[clusterIndex];
uint64 clusterOffset = (uint64)cluster.offset * m_sectorSize;
uint64 absFileOffset = entry.fileInfo.fileOffset * m_offsetFactor + readOffset;
// make sure the raw range we read is aligned to AES block size (16)
uint64 readAddrStart = absFileOffset & ~0xF;
uint64 readAddrEnd = (absFileOffset + readSize + 0xF) & ~0xF;
bool usesInitialIV = readOffset < 16;
if (!usesInitialIV)
readAddrStart -= 16; // read previous AES block since we require it for the IV
uint32 prePadding = (uint32)(absFileOffset - readAddrStart); // number of extra bytes we read before readOffset (for AES alignment and IV calculation)
uint32 postPadding = (uint32)(readAddrEnd - (absFileOffset + readSize));
uint8 readBuffer[64 * 1024];
// read first chunk
// if file read offset (readOffset) is within the first AES-block then use initial IV calculated from cluster index
// otherwise read previous AES-block is the IV (AES-CBC)
uint64 readAddrCurrent = readAddrStart;
uint32 rawBytesToRead = (uint32)std::min((readAddrEnd - readAddrStart), (uint64)sizeof(readBuffer));
if (m_dataSource->readData(clusterIndex, clusterOffset, readAddrCurrent, readBuffer, rawBytesToRead) != rawBytesToRead)
{
cemuLog_log(LogType::Force, "FST read error in raw content");
return 0;
}
readAddrCurrent += rawBytesToRead;
uint8 iv[16]{};
if (usesInitialIV)
{
// for the first AES block, the IV is initialized from cluster index
iv[0] = (uint8)(clusterIndex >> 8);
iv[1] = (uint8)(clusterIndex >> 0);
AES128_CBC_decrypt_updateIV(readBuffer, readBuffer, rawBytesToRead, m_partitionTitlekey.b, iv);
std::memcpy(dataOutU8, readBuffer + prePadding, rawBytesToRead - prePadding - postPadding);
dataOutU8 += (rawBytesToRead - prePadding - postPadding);
readSize -= (rawBytesToRead - prePadding - postPadding);
}
else
{
// IV is initialized from previous AES block (AES-CBC)
std::memcpy(iv, readBuffer, 16);
AES128_CBC_decrypt_updateIV(readBuffer + 16, readBuffer + 16, rawBytesToRead - 16, m_partitionTitlekey.b, iv);
std::memcpy(dataOutU8, readBuffer + prePadding, rawBytesToRead - prePadding - postPadding);
dataOutU8 += (rawBytesToRead - prePadding - postPadding);
readSize -= (rawBytesToRead - prePadding - postPadding);
}
// read remaining chunks
while (readSize > 0)
{
uint32 bytesToRead = (uint32)std::min((uint32)sizeof(readBuffer), readSize);
uint32 alignedBytesToRead = (bytesToRead + 15) & ~0xF;
if (m_dataSource->readData(clusterIndex, clusterOffset, readAddrCurrent, readBuffer, alignedBytesToRead) != alignedBytesToRead)
{
cemuLog_log(LogType::Force, "FST read error in raw content");
return 0;
}
AES128_CBC_decrypt_updateIV(readBuffer, readBuffer, alignedBytesToRead, m_partitionTitlekey.b, iv);
std::memcpy(dataOutU8, readBuffer, bytesToRead);
dataOutU8 += bytesToRead;
readSize -= bytesToRead;
readAddrCurrent += alignedBytesToRead;
}
return readSizeInput - readSize;
}
constexpr size_t BLOCK_SIZE = 0x10000;
constexpr size_t BLOCK_HASH_SIZE = 0x0400;
constexpr size_t BLOCK_FILE_SIZE = 0xFC00;
struct FSTRawBlock
{
std::vector<uint8> rawData; // unhashed block size depends on sector size field in partition header
};
struct FSTHashedBlock
{
uint8 rawData[BLOCK_SIZE];
@ -887,12 +867,160 @@ struct FSTHashedBlock
static_assert(sizeof(FSTHashedBlock) == BLOCK_SIZE);
struct FSTCachedRawBlock
{
FSTRawBlock blockData;
NCrypto::AesIv ivForNextBlock;
uint64 lastAccess;
};
struct FSTCachedHashedBlock
{
FSTHashedBlock blockData;
uint64 lastAccess;
};
// Checks cache fill state and if necessary drops least recently accessed block from the cache. Optionally allows to recycle the released cache entry to cut down cost of memory allocation and clearing
void FSTVolume::TrimCacheIfRequired(FSTCachedRawBlock** droppedRawBlock, FSTCachedHashedBlock** droppedHashedBlock)
{
// calculate size used by cache
size_t cacheSize = 0;
for (auto& itr : m_cacheDecryptedRawBlocks)
cacheSize += itr.second->blockData.rawData.size();
for (auto& itr : m_cacheDecryptedHashedBlocks)
cacheSize += sizeof(FSTCachedHashedBlock) + sizeof(FSTHashedBlock);
// only trim if cache is full (larger than 2MB)
if (cacheSize < 2*1024*1024) // 2MB
return;
// scan both cache lists to find least recently accessed block to drop
auto dropRawItr = std::min_element(m_cacheDecryptedRawBlocks.begin(), m_cacheDecryptedRawBlocks.end(), [](const auto& a, const auto& b) -> bool
{ return a.second->lastAccess < b.second->lastAccess; });
auto dropHashedItr = std::min_element(m_cacheDecryptedHashedBlocks.begin(), m_cacheDecryptedHashedBlocks.end(), [](const auto& a, const auto& b) -> bool
{ return a.second->lastAccess < b.second->lastAccess; });
uint64 lastAccess = std::numeric_limits<uint64>::max();
if(dropRawItr != m_cacheDecryptedRawBlocks.end())
lastAccess = dropRawItr->second->lastAccess;
if(dropHashedItr != m_cacheDecryptedHashedBlocks.end())
lastAccess = std::min<uint64>(lastAccess, dropHashedItr->second->lastAccess);
if(dropRawItr != m_cacheDecryptedRawBlocks.end() && dropRawItr->second->lastAccess == lastAccess)
{
if (droppedRawBlock)
*droppedRawBlock = dropRawItr->second;
else
delete dropRawItr->second;
m_cacheDecryptedRawBlocks.erase(dropRawItr);
return;
}
else if(dropHashedItr != m_cacheDecryptedHashedBlocks.end() && dropHashedItr->second->lastAccess == lastAccess)
{
if (droppedHashedBlock)
*droppedHashedBlock = dropHashedItr->second;
else
delete dropHashedItr->second;
m_cacheDecryptedHashedBlocks.erase(dropHashedItr);
}
}
void FSTVolume::DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, NCrypto::AesIv& ivOut)
{
ivOut = {};
if(blockIndex == 0)
{
ivOut.iv[0] = (uint8)(clusterIndex >> 8);
ivOut.iv[1] = (uint8)(clusterIndex >> 0);
}
else
{
// the last 16 encrypted bytes of the previous block are the IV (AES CBC)
// if the previous block is cached we can grab the IV from there. Otherwise we have to read the 16 bytes from the data source
uint32 prevBlockIndex = blockIndex - 1;
uint64 cacheBlockId = ((uint64)clusterIndex << (64 - 16)) | (uint64)prevBlockIndex;
auto itr = m_cacheDecryptedRawBlocks.find(cacheBlockId);
if (itr != m_cacheDecryptedRawBlocks.end())
{
ivOut = itr->second->ivForNextBlock;
}
else
{
cemu_assert(m_sectorSize >= NCrypto::AesIv::SIZE);
uint64 clusterOffset = (uint64)m_cluster[clusterIndex].offset * m_sectorSize;
NCrypto::AesIv prevIV{};
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * m_sectorSize - NCrypto::AesIv::SIZE, prevIV.iv, NCrypto::AesIv::SIZE) != NCrypto::AesIv::SIZE)
{
cemuLog_log(LogType::Force, "Failed to read IV for raw FST block");
m_detectedCorruption = true;
return;
}
ivOut = prevIV;
}
}
}
FSTCachedRawBlock* FSTVolume::GetDecryptedRawBlock(uint32 clusterIndex, uint32 blockIndex)
{
FSTCluster& cluster = m_cluster[clusterIndex];
uint64 clusterOffset = (uint64)cluster.offset * m_sectorSize;
// generate id for cache
uint64 cacheBlockId = ((uint64)clusterIndex << (64 - 16)) | (uint64)blockIndex;
// lookup block in cache
FSTCachedRawBlock* block = nullptr;
auto itr = m_cacheDecryptedRawBlocks.find(cacheBlockId);
if (itr != m_cacheDecryptedRawBlocks.end())
{
block = itr->second;
block->lastAccess = ++m_cacheAccessCounter;
return block;
}
// if cache already full, drop least recently accessed block and recycle FSTCachedRawBlock object if possible
TrimCacheIfRequired(&block, nullptr);
if (!block)
block = new FSTCachedRawBlock();
block->blockData.rawData.resize(m_sectorSize);
// block not cached, read new
block->lastAccess = ++m_cacheAccessCounter;
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * m_sectorSize, block->blockData.rawData.data(), m_sectorSize) != m_sectorSize)
{
cemuLog_log(LogType::Force, "Failed to read raw FST block");
delete block;
m_detectedCorruption = true;
return nullptr;
}
// decrypt hash data
NCrypto::AesIv iv{};
DetermineUnhashedBlockIV(clusterIndex, blockIndex, iv);
std::copy(block->blockData.rawData.data() + m_sectorSize - NCrypto::AesIv::SIZE, block->blockData.rawData.data() + m_sectorSize, block->ivForNextBlock.iv);
AES128_CBC_decrypt(block->blockData.rawData.data(), block->blockData.rawData.data(), m_sectorSize, m_partitionTitlekey.b, iv.iv);
// if this is the next block, then hash it
if(cluster.hasContentHash)
{
if(cluster.singleHashNumBlocksHashed == blockIndex)
{
cemu_assert_debug(!(cluster.contentSize % m_sectorSize)); // size should be multiple of sector size? Regardless, the hashing code below can handle non-aligned sizes
bool isLastBlock = blockIndex == (std::max<uint32>(cluster.contentSize / m_sectorSize, 1) - 1);
uint32 hashSize = m_sectorSize;
if(isLastBlock)
hashSize = cluster.contentSize - (uint64)blockIndex*m_sectorSize;
EVP_DigestUpdate(cluster.singleHashCtx.get(), block->blockData.rawData.data(), hashSize);
cluster.singleHashNumBlocksHashed++;
if(isLastBlock)
{
uint8 hash[32];
EVP_DigestFinal_ex(cluster.singleHashCtx.get(), hash, nullptr);
if(memcmp(hash, cluster.contentHash32, cluster.contentHashIsSHA1 ? 20 : 32) != 0)
{
cemuLog_log(LogType::Force, "FST: Raw section hash mismatch");
delete block;
m_detectedCorruption = true;
return nullptr;
}
}
}
}
// register in cache
m_cacheDecryptedRawBlocks.emplace(cacheBlockId, block);
return block;
}
FSTCachedHashedBlock* FSTVolume::GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex)
{
const FSTCluster& cluster = m_cluster[clusterIndex];
@ -908,22 +1036,17 @@ FSTCachedHashedBlock* FSTVolume::GetDecryptedHashedBlock(uint32 clusterIndex, ui
block->lastAccess = ++m_cacheAccessCounter;
return block;
}
// if cache already full, drop least recently accessed block (but recycle the FSTHashedBlock* object)
if (m_cacheDecryptedHashedBlocks.size() >= 16)
{
auto dropItr = std::min_element(m_cacheDecryptedHashedBlocks.begin(), m_cacheDecryptedHashedBlocks.end(), [](const auto& a, const auto& b) -> bool
{ return a.second->lastAccess < b.second->lastAccess; });
block = dropItr->second;
m_cacheDecryptedHashedBlocks.erase(dropItr);
}
else
// if cache already full, drop least recently accessed block and recycle FSTCachedHashedBlock object if possible
TrimCacheIfRequired(nullptr, &block);
if (!block)
block = new FSTCachedHashedBlock();
// block not cached, read new
block->lastAccess = ++m_cacheAccessCounter;
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * BLOCK_SIZE, block->blockData.rawData, BLOCK_SIZE) != BLOCK_SIZE)
{
cemuLog_log(LogType::Force, "Failed to read FST block");
cemuLog_log(LogType::Force, "Failed to read hashed FST block");
delete block;
m_detectedCorruption = true;
return nullptr;
}
// decrypt hash data
@ -931,11 +1054,46 @@ FSTCachedHashedBlock* FSTVolume::GetDecryptedHashedBlock(uint32 clusterIndex, ui
AES128_CBC_decrypt(block->blockData.getHashData(), block->blockData.getHashData(), BLOCK_HASH_SIZE, m_partitionTitlekey.b, iv);
// decrypt file data
AES128_CBC_decrypt(block->blockData.getFileData(), block->blockData.getFileData(), BLOCK_FILE_SIZE, m_partitionTitlekey.b, block->blockData.getH0Hash(blockIndex%16));
// compare with H0 to verify data integrity
NCrypto::CHash160 h0;
SHA1(block->blockData.getFileData(), BLOCK_FILE_SIZE, h0.b);
uint32 h0Index = (blockIndex % 4096);
if (memcmp(h0.b, block->blockData.getH0Hash(h0Index & 0xF), sizeof(h0.b)) != 0)
{
cemuLog_log(LogType::Force, "FST: Hash H0 mismatch in hashed block (section {} index {})", clusterIndex, blockIndex);
delete block;
m_detectedCorruption = true;
return nullptr;
}
// register in cache
m_cacheDecryptedHashedBlocks.emplace(cacheBlockId, block);
return block;
}
uint32 FSTVolume::ReadFile_HashModeRaw(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut)
{
uint8* dataOutU8 = (uint8*)dataOut;
if (readOffset >= entry.fileInfo.fileSize)
return 0;
else if ((readOffset + readSize) >= entry.fileInfo.fileSize)
readSize = (entry.fileInfo.fileSize - readOffset);
uint64 absFileOffset = entry.fileInfo.fileOffset * m_offsetFactor + readOffset;
uint32 remainingReadSize = readSize;
while (remainingReadSize > 0)
{
const FSTCachedRawBlock* rawBlock = this->GetDecryptedRawBlock(clusterIndex, absFileOffset/m_sectorSize);
if (!rawBlock)
break;
uint32 blockOffset = (uint32)(absFileOffset % m_sectorSize);
uint32 bytesToRead = std::min<uint32>(remainingReadSize, m_sectorSize - blockOffset);
std::memcpy(dataOutU8, rawBlock->blockData.rawData.data() + blockOffset, bytesToRead);
dataOutU8 += bytesToRead;
remainingReadSize -= bytesToRead;
absFileOffset += bytesToRead;
}
return readSize - remainingReadSize;
}
uint32 FSTVolume::ReadFile_HashModeHashed(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut)
{
/*
@ -966,7 +1124,6 @@ uint32 FSTVolume::ReadFile_HashModeHashed(uint32 clusterIndex, FSTEntry& entry,
*/
const FSTCluster& cluster = m_cluster[clusterIndex];
uint64 clusterBaseOffset = (uint64)cluster.offset * m_sectorSize;
uint64 fileReadOffset = entry.fileInfo.fileOffset * m_offsetFactor + readOffset;
uint32 blockIndex = (uint32)(fileReadOffset / BLOCK_FILE_SIZE);
uint32 bytesRemaining = readSize;
@ -1019,6 +1176,8 @@ bool FSTVolume::Next(FSTDirectoryIterator& directoryIterator, FSTFileHandle& fil
FSTVolume::~FSTVolume()
{
for (auto& itr : m_cacheDecryptedRawBlocks)
delete itr.second;
for (auto& itr : m_cacheDecryptedHashedBlocks)
delete itr.second;
if (m_sourceIsOwned)
@ -1115,4 +1274,4 @@ bool FSTVerifier::VerifyHashedContentFile(FileStream* fileContent, const NCrypto
void FSTVolumeTest()
{
FSTPathUnitTest();
}
}

View file

@ -1,5 +1,6 @@
#pragma once
#include "Cemu/ncrypto/ncrypto.h"
#include "openssl/evp.h"
struct FSTFileHandle
{
@ -45,6 +46,7 @@ public:
~FSTVolume();
uint32 GetFileCount() const;
bool HasCorruption() const { return m_detectedCorruption; }
bool OpenFile(std::string_view path, FSTFileHandle& fileHandleOut, bool openOnlyFiles = false);
@ -81,20 +83,29 @@ public:
}
private:
/* FST data (in memory) */
enum class ClusterHashMode : uint8
{
RAW = 0, // raw data + encryption, no hashing?
RAW2 = 1, // raw data + encryption, with hash stored in tmd?
RAW_STREAM = 1, // raw data + encryption, with hash stored in tmd?
HASH_INTERLEAVED = 2, // hashes + raw interleaved in 0x10000 blocks (0x400 bytes of hashes at the beginning, followed by 0xFC00 bytes of data)
};
struct FSTCluster
{
FSTCluster() : singleHashCtx(nullptr, &EVP_MD_CTX_free) {}
uint32 offset;
uint32 size;
ClusterHashMode hashMode;
// extra data if TMD is available
bool hasContentHash;
uint8 contentHash32[32];
bool contentHashIsSHA1; // if true then it's SHA1 (with extra bytes zeroed out), otherwise it's SHA256
uint64 contentSize; // size of the content (in blocks)
// hash context for single hash mode (content hash must be available)
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> singleHashCtx; // unique_ptr to make this move-only
uint32 singleHashNumBlocksHashed{0};
};
struct FSTEntry
@ -164,17 +175,30 @@ private:
bool m_sourceIsOwned{};
uint32 m_sectorSize{}; // for cluster offsets
uint32 m_offsetFactor{}; // for file offsets
bool m_hashIsDisabled{}; // disables hash verification (for all clusters of this volume?)
std::vector<FSTCluster> m_cluster;
std::vector<FSTEntry> m_entries;
std::vector<char> m_nameStringTable;
NCrypto::AesKey m_partitionTitlekey;
bool m_detectedCorruption{false};
/* Cache for decrypted hashed blocks */
bool HashIsDisabled() const
{
return m_hashIsDisabled;
}
/* Cache for decrypted raw and hashed blocks */
std::unordered_map<uint64, struct FSTCachedRawBlock*> m_cacheDecryptedRawBlocks;
std::unordered_map<uint64, struct FSTCachedHashedBlock*> m_cacheDecryptedHashedBlocks;
uint64 m_cacheAccessCounter{};
void DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, NCrypto::AesIv& ivOut);
struct FSTCachedRawBlock* GetDecryptedRawBlock(uint32 clusterIndex, uint32 blockIndex);
struct FSTCachedHashedBlock* GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex);
void TrimCacheIfRequired(struct FSTCachedRawBlock** droppedRawBlock, struct FSTCachedHashedBlock** droppedHashedBlock);
/* File reading */
uint32 ReadFile_HashModeRaw(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut);
uint32 ReadFile_HashModeHashed(uint32 clusterIndex, FSTEntry& entry, uint32 readOffset, uint32 readSize, void* dataOut);
@ -185,7 +209,10 @@ private:
/* +0x00 */ uint32be magic;
/* +0x04 */ uint32be offsetFactor;
/* +0x08 */ uint32be numCluster;
/* +0x0C */ uint32be ukn0C;
/* +0x0C */ uint8be hashIsDisabled;
/* +0x0D */ uint8be ukn0D;
/* +0x0E */ uint8be ukn0E;
/* +0x0F */ uint8be ukn0F;
/* +0x10 */ uint32be ukn10;
/* +0x14 */ uint32be ukn14;
/* +0x18 */ uint32be ukn18;
@ -262,8 +289,8 @@ private:
static_assert(sizeof(FSTHeader_FileEntry) == 0x10);
static FSTVolume* OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode);
static FSTVolume* OpenFST(std::unique_ptr<FSTDataSource> dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode);
static FSTVolume* OpenFST(FSTDataSource* dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode, NCrypto::TMDParser* optionalTMD);
static FSTVolume* OpenFST(std::unique_ptr<FSTDataSource> dataSource, uint64 fstOffset, uint32 fstSize, NCrypto::AesKey* partitionTitleKey, ClusterHashMode fstHashMode, NCrypto::TMDParser* optionalTMD);
static bool ProcessFST(FSTHeader_FileEntry* fileTable, uint32 numFileEntries, uint32 numCluster, std::vector<char>& nameStringTable, std::vector<FSTEntry>& fstEntries);
bool MatchFSTEntryName(FSTEntry& entry, std::string_view comparedName)

View file

@ -3,6 +3,8 @@
#include <boost/container/small_vector.hpp>
#include "../fsc.h"
// path parser and utility class for Wii U paths
// optimized to be allocation-free for common path lengths
class FSCPath
@ -119,9 +121,7 @@ public:
template<typename F>
class FSAFileTree
{
public:
private:
private:
enum NODETYPE : uint8
{
@ -133,6 +133,7 @@ private:
{
std::string name;
std::vector<node_t*> subnodes;
size_t fileSize;
F* custom;
NODETYPE type;
};
@ -179,13 +180,54 @@ private:
return newNode;
}
class DirectoryIterator : public FSCVirtualFile
{
public:
DirectoryIterator(node_t* node)
: m_node(node), m_subnodeIndex(0)
{
}
sint32 fscGetType() override
{
return FSC_TYPE_DIRECTORY;
}
bool fscDirNext(FSCDirEntry* dirEntry) override
{
if (m_subnodeIndex >= m_node->subnodes.size())
return false;
const node_t* subnode = m_node->subnodes[m_subnodeIndex];
strncpy(dirEntry->path, subnode->name.c_str(), sizeof(dirEntry->path) - 1);
dirEntry->path[sizeof(dirEntry->path) - 1] = '\0';
dirEntry->isDirectory = subnode->type == FSAFileTree::NODETYPE_DIRECTORY;
dirEntry->isFile = subnode->type == FSAFileTree::NODETYPE_FILE;
dirEntry->fileSize = subnode->type == FSAFileTree::NODETYPE_FILE ? subnode->fileSize : 0;
++m_subnodeIndex;
return true;
}
bool fscRewindDir() override
{
m_subnodeIndex = 0;
return true;
}
private:
node_t* m_node;
size_t m_subnodeIndex;
};
public:
FSAFileTree()
{
rootNode.type = NODETYPE_DIRECTORY;
}
bool addFile(std::string_view path, F* custom)
bool addFile(std::string_view path, size_t fileSize, F* custom)
{
FSCPath p(path);
if (p.GetNodeCount() == 0)
@ -196,6 +238,7 @@ public:
return false; // node already exists
// add file node
node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.GetNodeName(p.GetNodeCount() - 1));
fileNode->fileSize = fileSize;
fileNode->custom = custom;
return true;
}
@ -214,6 +257,20 @@ public:
return true;
}
bool getDirectory(std::string_view path, FSCVirtualFile*& dirIterator)
{
FSCPath p(path);
if (p.GetNodeCount() == 0)
return false;
node_t* node = getByNodePath(p, p.GetNodeCount(), false);
if (node == nullptr)
return false;
if (node->type != NODETYPE_DIRECTORY)
return false;
dirIterator = new DirectoryIterator(node);
return true;
}
bool removeFile(std::string_view path)
{
FSCPath p(path);

View file

@ -0,0 +1,40 @@
#pragma once
struct romfs_header_t
{
uint32 header_magic;
uint32be header_size;
uint64be dir_hash_table_ofs;
uint64be dir_hash_table_size;
uint64be dir_table_ofs;
uint64be dir_table_size;
uint64be file_hash_table_ofs;
uint64be file_hash_table_size;
uint64be file_table_ofs;
uint64be file_table_size;
uint64be file_partition_ofs;
};
struct romfs_direntry_t
{
uint32be parent;
uint32be listNext; // offset to next directory entry in linked list of parent directory (aka "sibling")
uint32be dirListHead; // offset to first entry in linked list of directory entries (aka "child")
uint32be fileListHead; // offset to first entry in linked list of file entries (aka "file")
uint32be hash;
uint32be name_size;
std::string name;
};
struct romfs_fentry_t
{
uint32be parent;
uint32be listNext; // offset to next file entry in linked list of parent directory (aka "sibling")
uint64be offset;
uint64be size;
uint32be hash;
uint32be name_size;
std::string name;
};
#define ROMFS_ENTRY_EMPTY 0xFFFFFFFF

View file

@ -0,0 +1,224 @@
#include "WUHBReader.h"
WUHBReader* WUHBReader::FromPath(const fs::path& path)
{
FileStream* fileIn{FileStream::openFile2(path)};
if (!fileIn)
return nullptr;
WUHBReader* ret = new WUHBReader(fileIn);
if (!ret->CheckMagicValue())
{
delete ret;
return nullptr;
}
if (!ret->ReadHeader())
{
delete ret;
return nullptr;
}
return ret;
}
static const romfs_direntry_t fallbackDirEntry{
.parent = ROMFS_ENTRY_EMPTY,
.listNext = ROMFS_ENTRY_EMPTY,
.dirListHead = ROMFS_ENTRY_EMPTY,
.fileListHead = ROMFS_ENTRY_EMPTY,
.hash = ROMFS_ENTRY_EMPTY,
.name_size = 0,
.name = ""
};
static const romfs_fentry_t fallbackFileEntry{
.parent = ROMFS_ENTRY_EMPTY,
.listNext = ROMFS_ENTRY_EMPTY,
.offset = 0,
.size = 0,
.hash = ROMFS_ENTRY_EMPTY,
.name_size = 0,
.name = ""
};
template<bool File>
const WUHBReader::EntryType<File>& WUHBReader::GetFallback()
{
if constexpr (File)
return fallbackFileEntry;
else
return fallbackDirEntry;
}
template<bool File>
WUHBReader::EntryType<File> WUHBReader::GetEntry(uint32 offset) const
{
auto fallback = GetFallback<File>();
if(offset == ROMFS_ENTRY_EMPTY)
return fallback;
const char* typeName = File ? "fentry" : "direntry";
EntryType<File> ret;
if (offset >= (File ? m_header.file_table_size : m_header.dir_table_size))
{
cemuLog_log(LogType::Force, "WUHB {} offset exceeds table size declared in header", typeName);
return fallback;
}
// read the entry
m_fileIn->SetPosition((File ? m_header.file_table_ofs : m_header.dir_table_ofs) + offset);
auto read = m_fileIn->readData(&ret, offsetof(EntryType<File>, name));
if (read != offsetof(EntryType<File>, name))
{
cemuLog_log(LogType::Force, "failed to read WUHB {} at offset: {}", typeName, offset);
return fallback;
}
// read the name
ret.name.resize(ret.name_size);
read = m_fileIn->readData(ret.name.data(), ret.name_size);
if (read != ret.name_size)
{
cemuLog_log(LogType::Force, "failed to read WUHB {} name", typeName);
return fallback;
}
return ret;
}
romfs_direntry_t WUHBReader::GetDirEntry(uint32 offset) const
{
return GetEntry<false>(offset);
}
romfs_fentry_t WUHBReader::GetFileEntry(uint32 offset) const
{
return GetEntry<true>(offset);
}
uint64 WUHBReader::GetFileSize(uint32 entryOffset) const
{
return GetFileEntry(entryOffset).size;
}
uint64 WUHBReader::ReadFromFile(uint32 entryOffset, uint64 fileOffset, uint64 length, void* buffer) const
{
const auto fileEntry = GetFileEntry(entryOffset);
if (fileOffset >= fileEntry.size)
return 0;
const uint64 readAmount = std::min(length, fileEntry.size - fileOffset);
const uint64 wuhbOffset = m_header.file_partition_ofs + fileEntry.offset + fileOffset;
m_fileIn->SetPosition(wuhbOffset);
return m_fileIn->readData(buffer, readAmount);
}
uint32 WUHBReader::GetHashTableEntryOffset(uint32 hash, bool isFile) const
{
const uint64 hash_table_size = (isFile ? m_header.file_hash_table_size : m_header.dir_hash_table_size);
const uint64 hash_table_ofs = (isFile ? m_header.file_hash_table_ofs : m_header.dir_hash_table_ofs);
const uint64 hash_table_entry_count = hash_table_size / sizeof(uint32);
const uint64 hash_table_entry_offset = hash_table_ofs + (hash % hash_table_entry_count) * sizeof(uint32);
m_fileIn->SetPosition(hash_table_entry_offset);
uint32 tableOffset;
if (!m_fileIn->readU32(tableOffset))
{
cemuLog_log(LogType::Force, "failed to read WUHB hash table entry at file offset: {}", hash_table_entry_offset);
return ROMFS_ENTRY_EMPTY;
}
return uint32be::from_bevalue(tableOffset);
}
template<bool T>
bool WUHBReader::SearchHashList(uint32& entryOffset, const fs::path& targetName) const
{
for (;;)
{
if (entryOffset == ROMFS_ENTRY_EMPTY)
return false;
auto entry = GetEntry<T>(entryOffset);
if (entry.name == targetName)
return true;
entryOffset = entry.hash;
}
return false;
}
uint32 WUHBReader::Lookup(const std::filesystem::path& path, bool isFile) const
{
uint32 currentEntryOffset = 0;
auto look = [&](const fs::path& part, bool lookInFileHT) {
const auto partString = part.string();
currentEntryOffset = GetHashTableEntryOffset(CalcPathHash(currentEntryOffset, partString.c_str(), 0, partString.size()), lookInFileHT);
if (lookInFileHT)
return SearchHashList<true>(currentEntryOffset, part);
else
return SearchHashList<false>(currentEntryOffset, part);
};
// look for the root entry
if (!look("", false))
return ROMFS_ENTRY_EMPTY;
auto it = path.begin();
while (it != path.end())
{
fs::path part = *it;
++it;
// no need to recurse after trailing forward slash (e.g. directory/)
if (part.empty() && !isFile)
break;
// skip leading forward slash
if (part == "/")
continue;
// if the lookup target is a file and this is the last iteration, look in the file hash table instead.
if (!look(part, it == path.end() && isFile))
return ROMFS_ENTRY_EMPTY;
}
return currentEntryOffset;
}
bool WUHBReader::CheckMagicValue() const
{
uint8 magic[4];
m_fileIn->SetPosition(0);
int read = m_fileIn->readData(magic, 4);
if (read != 4)
{
cemuLog_log(LogType::Force, "Failed to read WUHB magic numbers");
return false;
}
static_assert(sizeof(magic) == s_headerMagicValue.size());
return std::memcmp(&magic, s_headerMagicValue.data(), sizeof(magic)) == 0;
}
bool WUHBReader::ReadHeader()
{
m_fileIn->SetPosition(0);
auto read = m_fileIn->readData(&m_header, sizeof(m_header));
auto readSuccess = read == sizeof(m_header);
if (!readSuccess)
cemuLog_log(LogType::Force, "Failed to read WUHB header");
return readSuccess;
}
unsigned char WUHBReader::NormalizeChar(unsigned char c)
{
if (c >= 'a' && c <= 'z')
{
return c + 'A' - 'a';
}
else
{
return c;
}
}
uint32 WUHBReader::CalcPathHash(uint32 parent, const char* path, uint32 start, size_t path_len)
{
cemu_assert(path != nullptr || path_len == 0);
uint32 hash = parent ^ 123456789;
for (uint32 i = 0; i < path_len; i++)
{
hash = (hash >> 5) | (hash << 27);
hash ^= NormalizeChar(path[start + i]);
}
return hash;
}

View file

@ -0,0 +1,45 @@
#pragma once
#include <Common/FileStream.h>
#include "RomFSStructs.h"
class WUHBReader
{
public:
static WUHBReader* FromPath(const fs::path& path);
romfs_direntry_t GetDirEntry(uint32 offset) const;
romfs_fentry_t GetFileEntry(uint32 offset) const;
uint64 GetFileSize(uint32 entryOffset) const;
uint64 ReadFromFile(uint32 entryOffset, uint64 fileOffset, uint64 length, void* buffer) const;
uint32 Lookup(const std::filesystem::path& path, bool isFile) const;
private:
WUHBReader(FileStream* file)
: m_fileIn(file)
{
cemu_assert_debug(file != nullptr);
};
WUHBReader() = delete;
romfs_header_t m_header;
std::unique_ptr<FileStream> m_fileIn;
constexpr static std::string_view s_headerMagicValue = "WUHB";
bool ReadHeader();
bool CheckMagicValue() const;
static inline unsigned char NormalizeChar(unsigned char c);
static uint32 CalcPathHash(uint32 parent, const char* path, uint32 start, size_t path_len);
template<bool File>
using EntryType = std::conditional_t<File, romfs_fentry_t, romfs_direntry_t>;
template<bool File>
static const EntryType<File>& GetFallback();
template<bool File>
EntryType<File> GetEntry(uint32 offset) const;
template<bool T>
bool SearchHashList(uint32& entryOffset, const fs::path& targetName) const;
uint32 GetHashTableEntryOffset(uint32 hash, bool isFile) const;
};

View file

@ -204,9 +204,12 @@ bool FSCDeviceWUD_Mount(std::string_view mountPath, std::string_view destination
// wua device
bool FSCDeviceWUA_Mount(std::string_view mountPath, std::string_view destinationBaseDir, class ZArchiveReader* archive, sint32 priority);
// wuhb device
bool FSCDeviceWUHB_Mount(std::string_view mountPath, std::string_view destinationBaseDir, class WUHBReader* wuhbReader, sint32 priority);
// hostFS device
bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority);
// redirect device
void fscDeviceRedirect_map();
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority);
void fscDeviceRedirect_add(std::string_view virtualSourcePath, size_t fileSize, const fs::path& targetFilePath, sint32 priority);

View file

@ -11,7 +11,7 @@ struct RedirectEntry
FSAFileTree<RedirectEntry> redirectTree;
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority)
void fscDeviceRedirect_add(std::string_view virtualSourcePath, size_t fileSize, const fs::path& targetFilePath, sint32 priority)
{
// check if source already has a redirection
RedirectEntry* existingEntry;
@ -24,7 +24,7 @@ void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& t
delete existingEntry;
}
RedirectEntry* entry = new RedirectEntry(targetFilePath, priority);
redirectTree.addFile(virtualSourcePath, entry);
redirectTree.addFile(virtualSourcePath, fileSize, entry);
}
class fscDeviceTypeRedirect : public fscDeviceC
@ -32,8 +32,15 @@ class fscDeviceTypeRedirect : public fscDeviceC
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
{
RedirectEntry* redirectionEntry;
if (redirectTree.getFile(path, redirectionEntry))
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE) && redirectTree.getFile(path, redirectionEntry))
return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus);
FSCVirtualFile* dirIterator;
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR) && redirectTree.getDirectory(path, dirIterator))
return dirIterator;
return nullptr;
}

View file

@ -0,0 +1,151 @@
#include "Filesystem/WUHB/WUHBReader.h"
#include "Cafe/Filesystem/fsc.h"
#include "Cafe/Filesystem/FST/FST.h"
class FSCDeviceWuhbFileCtx : public FSCVirtualFile
{
public:
FSCDeviceWuhbFileCtx(WUHBReader* reader, uint32 entryOffset, uint32 fscType)
: m_wuhbReader(reader), m_entryOffset(entryOffset), m_fscType(fscType)
{
cemu_assert(entryOffset != ROMFS_ENTRY_EMPTY);
if (fscType == FSC_TYPE_DIRECTORY)
{
romfs_direntry_t entry = reader->GetDirEntry(entryOffset);
m_dirIterOffset = entry.dirListHead;
m_fileIterOffset = entry.fileListHead;
}
}
sint32 fscGetType() override
{
return m_fscType;
}
uint64 fscQueryValueU64(uint32 id) override
{
if (m_fscType == FSC_TYPE_FILE)
{
if (id == FSC_QUERY_SIZE)
return m_wuhbReader->GetFileSize(m_entryOffset);
else if (id == FSC_QUERY_WRITEABLE)
return 0; // WUHB images are read-only
else
cemu_assert_error();
}
else
{
cemu_assert_unimplemented();
}
return 0;
}
uint32 fscWriteData(void* buffer, uint32 size) override
{
cemu_assert_error();
return 0;
}
uint32 fscReadData(void* buffer, uint32 size) override
{
if (m_fscType != FSC_TYPE_FILE)
return 0;
auto read = m_wuhbReader->ReadFromFile(m_entryOffset, m_seek, size, buffer);
m_seek += read;
return read;
}
void fscSetSeek(uint64 seek) override
{
m_seek = seek;
}
uint64 fscGetSeek() override
{
if (m_fscType != FSC_TYPE_FILE)
return 0;
return m_seek;
}
void fscSetFileLength(uint64 endOffset) override
{
cemu_assert_error();
}
bool fscDirNext(FSCDirEntry* dirEntry) override
{
if (m_dirIterOffset != ROMFS_ENTRY_EMPTY)
{
romfs_direntry_t entry = m_wuhbReader->GetDirEntry(m_dirIterOffset);
m_dirIterOffset = entry.listNext;
if(entry.name_size > 0)
{
dirEntry->isDirectory = true;
dirEntry->isFile = false;
dirEntry->fileSize = 0;
std::strncpy(dirEntry->path, entry.name.c_str(), FSC_MAX_DIR_NAME_LENGTH);
return true;
}
}
if (m_fileIterOffset != ROMFS_ENTRY_EMPTY)
{
romfs_fentry_t entry = m_wuhbReader->GetFileEntry(m_fileIterOffset);
m_fileIterOffset = entry.listNext;
if(entry.name_size > 0)
{
dirEntry->isDirectory = false;
dirEntry->isFile = true;
dirEntry->fileSize = entry.size;
std::strncpy(dirEntry->path, entry.name.c_str(), FSC_MAX_DIR_NAME_LENGTH);
return true;
}
}
return false;
}
private:
WUHBReader* m_wuhbReader{};
uint32 m_fscType;
uint32 m_entryOffset = ROMFS_ENTRY_EMPTY;
uint32 m_dirIterOffset = ROMFS_ENTRY_EMPTY;
uint32 m_fileIterOffset = ROMFS_ENTRY_EMPTY;
uint64 m_seek = 0;
};
class fscDeviceWUHB : public fscDeviceC
{
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
{
WUHBReader* reader = (WUHBReader*)ctx;
cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to WUHB is not supported
bool isFile;
uint32 table_offset = ROMFS_ENTRY_EMPTY;
if (table_offset == ROMFS_ENTRY_EMPTY && HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR))
{
table_offset = reader->Lookup(path, false);
isFile = false;
}
if (table_offset == ROMFS_ENTRY_EMPTY && HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE))
{
table_offset = reader->Lookup(path, true);
isFile = true;
}
if (table_offset == ROMFS_ENTRY_EMPTY)
{
*fscStatus = FSC_STATUS_FILE_NOT_FOUND;
return nullptr;
}
*fscStatus = FSC_STATUS_OK;
return new FSCDeviceWuhbFileCtx(reader, table_offset, isFile ? FSC_TYPE_FILE : FSC_TYPE_DIRECTORY);
}
// singleton
public:
static fscDeviceWUHB& instance()
{
static fscDeviceWUHB _instance;
return _instance;
}
};
bool FSCDeviceWUHB_Mount(std::string_view mountPath, std::string_view destinationBaseDir, WUHBReader* wuhbReader, sint32 priority)
{
return fsc_mount(mountPath, destinationBaseDir, &fscDeviceWUHB::instance(), wuhbReader, priority) == FSC_STATUS_OK;
}

View file

@ -140,7 +140,7 @@ bool gameProfile_loadEnumOption(IniParser& iniParser, const char* optionName, T&
for(const T& v : T())
{
// test integer option
if (boost::iequals(fmt::format("{}", static_cast<typename std::underlying_type<T>::type>(v)), *option_value))
if (boost::iequals(fmt::format("{}", fmt::underlying(v)), *option_value))
{
option = v;
return true;

View file

@ -345,7 +345,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
const auto preset_name = rules.FindOption("name");
if (!preset_name)
{
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Preset in line {} skipped because it has no name option defined", m_name, rules.GetCurrentSectionLineNumber());
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Preset in line {} skipped because it has no name option defined", GetNormalizedPathString(), rules.GetCurrentSectionLineNumber());
continue;
}
@ -369,7 +369,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
}
catch (const std::exception & ex)
{
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Can't parse preset \"{}\": {}", m_name, *preset_name, ex.what());
cemuLog_log(LogType::Force, "Graphic pack \"{}\": Can't parse preset \"{}\": {}", GetNormalizedPathString(), *preset_name, ex.what());
}
}
else if (boost::iequals(currentSectionName, "RAM"))
@ -383,7 +383,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
{
if (m_version <= 5)
{
cemuLog_log(LogType::Force, "Graphic pack \"{}\": [RAM] options are only available for graphic pack version 6 or higher", m_name, optionNameBuf);
cemuLog_log(LogType::Force, "Graphic pack \"{}\": [RAM] options are only available for graphic pack version 6 or higher", GetNormalizedPathString(), optionNameBuf);
throw std::exception();
}
@ -393,12 +393,12 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
{
if (addrEnd <= addrStart)
{
cemuLog_log(LogType::Force, "Graphic pack \"{}\": start address (0x{:08x}) must be greater than end address (0x{:08x}) for {}", m_name, addrStart, addrEnd, optionNameBuf);
cemuLog_log(LogType::Force, "Graphic pack \"{}\": start address (0x{:08x}) must be greater than end address (0x{:08x}) for {}", GetNormalizedPathString(), addrStart, addrEnd, optionNameBuf);
throw std::exception();
}
else if ((addrStart & 0xFFF) != 0 || (addrEnd & 0xFFF) != 0)
{
cemuLog_log(LogType::Force, "Graphic pack \"{}\": addresses for %s are not aligned to 0x1000", m_name, optionNameBuf);
cemuLog_log(LogType::Force, "Graphic pack \"{}\": addresses for %s are not aligned to 0x1000", GetNormalizedPathString(), optionNameBuf);
throw std::exception();
}
else
@ -408,7 +408,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
}
else
{
cemuLog_log(LogType::Force, "Graphic pack \"{}\": has invalid syntax for option {}", m_name, optionNameBuf);
cemuLog_log(LogType::Force, "Graphic pack \"{}\": has invalid syntax for option {}", GetNormalizedPathString(), optionNameBuf);
throw std::exception();
}
}
@ -422,24 +422,32 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
std::unordered_map<std::string, std::vector<PresetPtr>> tmp_map;
// all vars must be defined in the default preset vars before
for (const auto& entry : m_presets)
std::vector<std::pair<std::string, std::string>> mismatchingPresetVars;
for (const auto& presetEntry : m_presets)
{
tmp_map[entry->category].emplace_back(entry);
tmp_map[presetEntry->category].emplace_back(presetEntry);
for (auto& kv : entry->variables)
for (auto& presetVar : presetEntry->variables)
{
const auto it = m_preset_vars.find(kv.first);
const auto it = m_preset_vars.find(presetVar.first);
if (it == m_preset_vars.cend())
{
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains preset variables which are not defined in the default section", m_name);
throw std::exception();
mismatchingPresetVars.emplace_back(presetEntry->name, presetVar.first);
continue;
}
// overwrite var type with default var type
kv.second.first = it->second.first;
presetVar.second.first = it->second.first;
}
}
if(!mismatchingPresetVars.empty())
{
cemuLog_log(LogType::Force, "Graphic pack \"{}\" contains preset variables which are not defined in the [Default] section:", GetNormalizedPathString());
for (const auto& [presetName, varName] : mismatchingPresetVars)
cemuLog_log(LogType::Force, "Preset: {} Variable: {}", presetName, varName);
throw std::exception();
}
// have first entry be default active for every category if no default= is set
for(auto entry : get_values(tmp_map))
{
@ -469,7 +477,7 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
auto& p2 = kv.second[i + 1];
if (p1->variables.size() != p2->variables.size())
{
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", m_name);
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", GetNormalizedPathString());
throw std::exception();
}
@ -477,14 +485,14 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
std::set<std::string> keys2(get_keys(p2->variables).begin(), get_keys(p2->variables).end());
if (keys1 != keys2)
{
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", m_name);
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" contains inconsistent preset variables", GetNormalizedPathString());
throw std::exception();
}
if(p1->is_default)
{
if(has_default)
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" has more than one preset with the default key set for the same category \"{}\"", m_name, p1->name);
cemuLog_log(LogType::Force, "Graphic pack: \"{}\" has more than one preset with the default key set for the same category \"{}\"", GetNormalizedPathString(), p1->name);
p1->active = true;
has_default = true;
}
@ -813,7 +821,7 @@ void GraphicPack2::AddConstantsForCurrentPreset(ExpressionParser& ep)
}
}
void GraphicPack2::_iterateReplacedFiles(const fs::path& currentPath, bool isAOC)
void GraphicPack2::_iterateReplacedFiles(const fs::path& currentPath, bool isAOC, const char* virtualMountBase)
{
uint64 currentTitleId = CafeSystem::GetForegroundTitleId();
uint64 aocTitleId = (currentTitleId & 0xFFFFFFFFull) | 0x0005000c00000000ull;
@ -828,9 +836,9 @@ void GraphicPack2::_iterateReplacedFiles(const fs::path& currentPath, bool isAOC
}
else
{
virtualMountPath = fs::path("vol/content/") / virtualMountPath;
virtualMountPath = fs::path(virtualMountBase) / virtualMountPath;
}
fscDeviceRedirect_add(virtualMountPath.generic_string(), it.path().generic_string(), m_fs_priority);
fscDeviceRedirect_add(virtualMountPath.generic_string(), it.file_size(), it.path().generic_string(), m_fs_priority);
}
}
}
@ -853,7 +861,7 @@ void GraphicPack2::LoadReplacedFiles()
{
// setup redirections
fscDeviceRedirect_map();
_iterateReplacedFiles(contentPath, false);
_iterateReplacedFiles(contentPath, false, "vol/content/");
}
// /aoc/
fs::path aocPath(gfxPackPath);
@ -866,7 +874,18 @@ void GraphicPack2::LoadReplacedFiles()
aocTitleId |= 0x0005000c00000000ULL;
// setup redirections
fscDeviceRedirect_map();
_iterateReplacedFiles(aocPath, true);
_iterateReplacedFiles(aocPath, true, nullptr);
}
// /code/
fs::path codePath(gfxPackPath);
codePath.append("code");
if (fs::exists(codePath, ec))
{
// setup redirections
fscDeviceRedirect_map();
_iterateReplacedFiles(codePath, false, CafeSystem::GetInternalVirtualCodeFolder().c_str());
}
}
@ -960,7 +979,7 @@ bool GraphicPack2::Activate()
auto option_upscale = rules.FindOption("upscaleMagFilter");
if(option_upscale && boost::iequals(*option_upscale, "NearestNeighbor"))
m_output_settings.upscale_filter = LatteTextureView::MagFilter::kNearestNeighbor;
auto option_downscale = rules.FindOption("NearestNeighbor");
auto option_downscale = rules.FindOption("downscaleMinFilter");
if (option_downscale && boost::iequals(*option_downscale, "NearestNeighbor"))
m_output_settings.downscale_filter = LatteTextureView::MagFilter::kNearestNeighbor;
}

View file

@ -260,7 +260,7 @@ private:
CustomShader LoadShader(const fs::path& path, uint64 shader_base_hash, uint64 shader_aux_hash, GP_SHADER_TYPE shader_type) const;
void ApplyShaderPresets(std::string& shader_source) const;
void LoadReplacedFiles();
void _iterateReplacedFiles(const fs::path& currentPath, bool isAOC);
void _iterateReplacedFiles(const fs::path& currentPath, bool isAOC, const char* virtualMountBase);
// ram mappings
std::vector<std::pair<MPTR, MPTR>> m_ramMappings;

View file

@ -8,6 +8,7 @@
#include "gui/debugger/DebuggerWindow2.h"
#include "Cafe/OS/libs/coreinit/coreinit.h"
#include "util/helpers/helpers.h"
#if BOOST_OS_WINDOWS
#include <Windows.h>
@ -136,11 +137,6 @@ void debugger_createCodeBreakpoint(uint32 address, uint8 bpType)
debugger_updateExecutionBreakpoint(address);
}
void debugger_createExecuteBreakpoint(uint32 address)
{
debugger_createCodeBreakpoint(address, DEBUGGER_BP_T_NORMAL);
}
namespace coreinit
{
std::vector<std::thread::native_handle_type>& OSGetSchedulerThreads();
@ -294,8 +290,23 @@ void debugger_toggleExecuteBreakpoint(uint32 address)
}
else
{
// create new breakpoint
debugger_createExecuteBreakpoint(address);
// create new execution breakpoint
debugger_createCodeBreakpoint(address, DEBUGGER_BP_T_NORMAL);
}
}
void debugger_toggleLoggingBreakpoint(uint32 address)
{
auto existingBP = debugger_getFirstBP(address, DEBUGGER_BP_T_LOGGING);
if (existingBP)
{
// delete existing breakpoint
debugger_deleteBreakpoint(existingBP);
}
else
{
// create new logging breakpoint
debugger_createCodeBreakpoint(address, DEBUGGER_BP_T_LOGGING);
}
}
@ -447,6 +458,34 @@ bool debugger_hasPatch(uint32 address)
return false;
}
void debugger_removePatch(uint32 address)
{
for (sint32 i = 0; i < debuggerState.patches.size(); i++)
{
auto& patch = debuggerState.patches[i];
if (address < patch->address || address >= (patch->address + patch->length))
continue;
MPTR startAddress = patch->address;
MPTR endAddress = patch->address + patch->length;
// remove any breakpoints overlapping with the patch
for (auto& bp : debuggerState.breakpoints)
{
if (bp->address + 4 > startAddress && bp->address < endAddress)
{
bp->enabled = false;
debugger_updateExecutionBreakpoint(bp->address);
}
}
// restore original data
memcpy(MEMPTR<void>(startAddress).GetPtr(), patch->origData.data(), patch->length);
PPCRecompiler_invalidateRange(startAddress, endAddress);
// remove patch
delete patch;
debuggerState.patches.erase(debuggerState.patches.begin() + i);
return;
}
}
void debugger_stepInto(PPCInterpreter_t* hCPU, bool updateDebuggerWindow = true)
{
bool isRecEnabled = ppcRecompilerEnabled;
@ -501,8 +540,6 @@ void debugger_createPPCStateSnapshot(PPCInterpreter_t* hCPU)
debuggerState.debugSession.ppcSnapshot.cr[i] = hCPU->cr[i];
}
void DebugLogStackTrace(OSThread_t* thread, MPTR sp);
void debugger_enterTW(PPCInterpreter_t* hCPU)
{
// handle logging points
@ -512,7 +549,48 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
{
if (bp->bpType == DEBUGGER_BP_T_LOGGING && bp->enabled)
{
std::string logName = !bp->comment.empty() ? "Breakpoint '"+boost::nowide::narrow(bp->comment)+"'" : fmt::format("Breakpoint at 0x{:08X} (no comment)", bp->address);
std::string comment = !bp->comment.empty() ? boost::nowide::narrow(bp->comment) : fmt::format("Breakpoint at 0x{:08X} (no comment)", bp->address);
auto replacePlaceholders = [&](const std::string& prefix, const auto& formatFunc)
{
size_t pos = 0;
while ((pos = comment.find(prefix, pos)) != std::string::npos)
{
size_t endPos = comment.find('}', pos);
if (endPos == std::string::npos)
break;
try
{
if (int regNum = ConvertString<int>(comment.substr(pos + prefix.length(), endPos - pos - prefix.length())); regNum >= 0 && regNum < 32)
{
std::string replacement = formatFunc(regNum);
comment.replace(pos, endPos - pos + 1, replacement);
pos += replacement.length();
}
else
{
pos = endPos + 1;
}
}
catch (...)
{
pos = endPos + 1;
}
}
};
// Replace integer register placeholders {rX}
replacePlaceholders("{r", [&](int regNum) {
return fmt::format("0x{:08X}", hCPU->gpr[regNum]);
});
// Replace floating point register placeholders {fX}
replacePlaceholders("{f", [&](int regNum) {
return fmt::format("{}", hCPU->fpr[regNum].fpr);
});
std::string logName = "Breakpoint '" + comment + "'";
std::string logContext = fmt::format("Thread: {:08x} LR: 0x{:08x}", MEMPTR<OSThread_t>(coreinit::OSGetCurrentThread()).GetMPTR(), hCPU->spr.LR, cemuLog_advancedPPCLoggingEnabled() ? " Stack Trace:" : "");
cemuLog_log(LogType::Force, "[Debugger] {} was executed! {}", logName, logContext);
if (cemuLog_advancedPPCLoggingEnabled())
@ -549,7 +627,7 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
debuggerState.debugSession.stepInto = false;
debuggerState.debugSession.stepOver = false;
debuggerState.debugSession.run = false;
while (true)
while (debuggerState.debugSession.isTrapped)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
// check for step commands

View file

@ -100,8 +100,8 @@ extern debuggerState_t debuggerState;
// new API
DebuggerBreakpoint* debugger_getFirstBP(uint32 address);
void debugger_createCodeBreakpoint(uint32 address, uint8 bpType);
void debugger_createExecuteBreakpoint(uint32 address);
void debugger_toggleExecuteBreakpoint(uint32 address); // create/remove execute breakpoint
void debugger_toggleLoggingBreakpoint(uint32 address); // create/remove logging breakpoint
void debugger_toggleBreakpoint(uint32 address, bool state, DebuggerBreakpoint* bp);
void debugger_createMemoryBreakpoint(uint32 address, bool onRead, bool onWrite);
@ -114,6 +114,7 @@ void debugger_updateExecutionBreakpoint(uint32 address, bool forceRestore = fals
void debugger_createPatch(uint32 address, std::span<uint8> patchData);
bool debugger_hasPatch(uint32 address);
void debugger_removePatch(uint32 address);
void debugger_forceBreak(); // force breakpoint at the next possible instruction
bool debugger_isTrapped();

View file

@ -10,6 +10,18 @@ namespace Espresso
CR_BIT_INDEX_SO = 3,
};
enum class PSQ_LOAD_TYPE
{
TYPE_F32 = 0,
TYPE_UNUSED1 = 1,
TYPE_UNUSED2 = 2,
TYPE_UNUSED3 = 3,
TYPE_U8 = 4,
TYPE_U16 = 5,
TYPE_S8 = 6,
TYPE_S16 = 7,
};
enum class PrimaryOpcode
{
// underscore at the end of the name means that this instruction always updates CR0 (as if RC bit is set)
@ -91,13 +103,15 @@ namespace Espresso
BCCTR = 528
};
enum class OPCODE_31
enum class Opcode31
{
TW = 4,
MFTB = 371,
};
inline PrimaryOpcode GetPrimaryOpcode(uint32 opcode) { return (PrimaryOpcode)(opcode >> 26); };
inline Opcode19 GetGroup19Opcode(uint32 opcode) { return (Opcode19)((opcode >> 1) & 0x3FF); };
inline Opcode31 GetGroup31Opcode(uint32 opcode) { return (Opcode31)((opcode >> 1) & 0x3FF); };
struct BOField
{
@ -132,6 +146,12 @@ namespace Espresso
uint8 bo;
};
// returns true if LK bit is set, only valid for branch instructions
inline bool DecodeLK(uint32 opcode)
{
return (opcode & 1) != 0;
}
inline void _decodeForm_I(uint32 opcode, uint32& LI, bool& AA, bool& LK)
{
LI = opcode & 0x3fffffc;
@ -183,13 +203,7 @@ namespace Espresso
_decodeForm_D_branch(opcode, BD, BO, BI, AA, LK);
}
inline void decodeOp_BCLR(uint32 opcode, BOField& BO, uint32& BI, bool& LK)
{
// form XL (with BD field expected to be zero)
_decodeForm_XL(opcode, BO, BI, LK);
}
inline void decodeOp_BCCTR(uint32 opcode, BOField& BO, uint32& BI, bool& LK)
inline void decodeOp_BCSPR(uint32 opcode, BOField& BO, uint32& BI, bool& LK) // BCLR and BCSPR
{
// form XL (with BD field expected to be zero)
_decodeForm_XL(opcode, BO, BI, LK);

View file

@ -3,12 +3,12 @@ static void PPCInterpreter_setXerOV(PPCInterpreter_t* hCPU, bool hasOverflow)
{
if (hasOverflow)
{
hCPU->spr.XER |= XER_SO;
hCPU->spr.XER |= XER_OV;
hCPU->xer_so = 1;
hCPU->xer_ov = 1;
}
else
{
hCPU->spr.XER &= ~XER_OV;
hCPU->xer_ov = 0;
}
}
@ -41,7 +41,7 @@ static void PPCInterpreter_ADD(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_ADDO(PPCInterpreter_t* hCPU, uint32 opcode)
{
// untested (Don't Starve Giant Edition uses this instruction + BSO)
// Don't Starve Giant Edition uses this instruction + BSO
PPC_OPC_TEMPL3_XO();
uint32 result = hCPU->gpr[rA] + hCPU->gpr[rB];
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(hCPU->gpr[rA], hCPU->gpr[rB], result));
@ -113,7 +113,6 @@ static void PPCInterpreter_ADDEO(PPCInterpreter_t* hCPU, uint32 opcode)
else
hCPU->xer_ca = 0;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(a, b, hCPU->gpr[rD]));
// update CR
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
@ -130,7 +129,7 @@ static void PPCInterpreter_ADDI(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_ADDIC(PPCInterpreter_t* hCPU, uint32 opcode)
{
int rD, rA;
sint32 rD, rA;
uint32 imm;
PPC_OPC_TEMPL_D_SImm(opcode, rD, rA, imm);
uint32 a = hCPU->gpr[rA];
@ -145,7 +144,7 @@ static void PPCInterpreter_ADDIC(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_ADDIC_(PPCInterpreter_t* hCPU, uint32 opcode)
{
int rD, rA;
sint32 rD, rA;
uint32 imm;
PPC_OPC_TEMPL_D_SImm(opcode, rD, rA, imm);
uint32 a = hCPU->gpr[rA];
@ -155,14 +154,13 @@ static void PPCInterpreter_ADDIC_(PPCInterpreter_t* hCPU, uint32 opcode)
hCPU->xer_ca = 1;
else
hCPU->xer_ca = 0;
// update cr0 flags
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_ADDIS(PPCInterpreter_t* hCPU, uint32 opcode)
{
int rD, rA;
sint32 rD, rA;
uint32 imm;
PPC_OPC_TEMPL_D_Shift16(opcode, rD, rA, imm);
hCPU->gpr[rD] = (rA ? hCPU->gpr[rA] : 0) + imm;
@ -185,6 +183,23 @@ static void PPCInterpreter_ADDZE(PPCInterpreter_t* hCPU, uint32 opcode)
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_ADDZEO(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
PPC_ASSERT(rB == 0);
uint32 a = hCPU->gpr[rA];
uint32 ca = hCPU->xer_ca;
hCPU->gpr[rD] = a + ca;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(a, 0, hCPU->gpr[rD]));
if ((a == 0xffffffff) && ca)
hCPU->xer_ca = 1;
else
hCPU->xer_ca = 0;
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_ADDME(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
@ -201,6 +216,23 @@ static void PPCInterpreter_ADDME(PPCInterpreter_t* hCPU, uint32 opcode)
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_ADDMEO(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
PPC_ASSERT(rB == 0);
uint32 a = hCPU->gpr[rA];
uint32 ca = hCPU->xer_ca;
hCPU->gpr[rD] = a + ca + 0xffffffff;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(a, 0xffffffff, hCPU->gpr[rD]));
if (a || ca)
hCPU->xer_ca = 1;
else
hCPU->xer_ca = 0;
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_SUBF(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
@ -212,11 +244,12 @@ static void PPCInterpreter_SUBF(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_SUBFO(PPCInterpreter_t* hCPU, uint32 opcode)
{
// untested (Don't Starve Giant Edition uses this)
// Seen in Don't Starve Giant Edition and Teslagrad
// also used by DS Virtual Console (Super Mario 64 DS)
PPC_OPC_TEMPL3_XO();
hCPU->gpr[rD] = ~hCPU->gpr[rA] + hCPU->gpr[rB] + 1;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~hCPU->gpr[rA], hCPU->gpr[rB], hCPU->gpr[rD]));
uint32 result = ~hCPU->gpr[rA] + hCPU->gpr[rB] + 1;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~hCPU->gpr[rA], hCPU->gpr[rB], result));
hCPU->gpr[rD] = result;
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
@ -245,7 +278,7 @@ static void PPCInterpreter_SUBFCO(PPCInterpreter_t* hCPU, uint32 opcode)
uint32 a = hCPU->gpr[rA];
uint32 b = hCPU->gpr[rB];
hCPU->gpr[rD] = ~a + b + 1;
// update xer
// update carry
if (ppc_carry_3(~a, b, 1))
hCPU->xer_ca = 1;
else
@ -259,7 +292,7 @@ static void PPCInterpreter_SUBFCO(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_SUBFIC(PPCInterpreter_t* hCPU, uint32 opcode)
{
int rD, rA;
sint32 rD, rA;
uint32 imm;
PPC_OPC_TEMPL_D_SImm(opcode, rD, rA, imm);
uint32 a = hCPU->gpr[rA];
@ -283,7 +316,6 @@ static void PPCInterpreter_SUBFE(PPCInterpreter_t* hCPU, uint32 opcode)
hCPU->xer_ca = 1;
else
hCPU->xer_ca = 0;
// update cr0
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
@ -303,7 +335,6 @@ static void PPCInterpreter_SUBFEO(PPCInterpreter_t* hCPU, uint32 opcode)
else
hCPU->xer_ca = 0;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~a, b, result));
// update cr0
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
@ -325,9 +356,25 @@ static void PPCInterpreter_SUBFZE(PPCInterpreter_t* hCPU, uint32 opcode)
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_SUBFZEO(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
PPC_ASSERT(rB == 0);
uint32 a = hCPU->gpr[rA];
uint32 ca = hCPU->xer_ca;
hCPU->gpr[rD] = ~a + ca;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~a, 0, hCPU->gpr[rD]));
if (a == 0 && ca)
hCPU->xer_ca = 1;
else
hCPU->xer_ca = 0;
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_SUBFME(PPCInterpreter_t* hCPU, uint32 opcode)
{
// untested
PPC_OPC_TEMPL3_XO();
PPC_ASSERT(rB == 0);
uint32 a = hCPU->gpr[rA];
@ -338,7 +385,24 @@ static void PPCInterpreter_SUBFME(PPCInterpreter_t* hCPU, uint32 opcode)
hCPU->xer_ca = 1;
else
hCPU->xer_ca = 0;
// update cr0
if (opcode & PPC_OPC_RC)
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_SUBFMEO(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
PPC_ASSERT(rB == 0);
uint32 a = hCPU->gpr[rA];
uint32 ca = hCPU->xer_ca;
hCPU->gpr[rD] = ~a + 0xFFFFFFFF + ca;
PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~a, 0xFFFFFFFF, hCPU->gpr[rD]));
// update xer carry
if (ppc_carry_3(~a, 0xFFFFFFFF, ca))
hCPU->xer_ca = 1;
else
hCPU->xer_ca = 0;
if (opcode & PPC_OPC_RC)
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
@ -351,13 +415,8 @@ static void PPCInterpreter_MULHW_(PPCInterpreter_t* hCPU, uint32 opcode)
sint64 b = (sint32)hCPU->gpr[rB];
sint64 c = a * b;
hCPU->gpr[rD] = ((uint64)c) >> 32;
if (opcode & PPC_OPC_RC) {
// update cr0 flags
#ifdef CEMU_DEBUG_ASSERT
assert_dbg();
#endif
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
}
PPCInterpreter_nextInstruction(hCPU);
}
@ -408,14 +467,14 @@ static void PPCInterpreter_MULLI(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_DIVW(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
sint32 a = hCPU->gpr[rA];
sint32 b = hCPU->gpr[rB];
sint32 a = (sint32)hCPU->gpr[rA];
sint32 b = (sint32)hCPU->gpr[rB];
if (b == 0)
{
cemuLog_logDebug(LogType::Force, "Error: Division by zero! [{:08x}]", (uint32)hCPU->instructionPointer);
b++;
}
hCPU->gpr[rD] = a / b;
hCPU->gpr[rD] = a < 0 ? 0xFFFFFFFF : 0;
else if (a == 0x80000000 && b == 0xFFFFFFFF)
hCPU->gpr[rD] = 0xFFFFFFFF;
else
hCPU->gpr[rD] = a / b;
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
@ -424,16 +483,23 @@ static void PPCInterpreter_DIVW(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_DIVWO(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
sint32 a = hCPU->gpr[rA];
sint32 b = hCPU->gpr[rB];
sint32 a = (sint32)hCPU->gpr[rA];
sint32 b = (sint32)hCPU->gpr[rB];
if (b == 0)
{
PPCInterpreter_setXerOV(hCPU, true);
PPCInterpreter_nextInstruction(hCPU);
return;
hCPU->gpr[rD] = a < 0 ? 0xFFFFFFFF : 0;
}
else if(a == 0x80000000 && b == 0xFFFFFFFF)
{
PPCInterpreter_setXerOV(hCPU, true);
hCPU->gpr[rD] = 0xFFFFFFFF;
}
else
{
hCPU->gpr[rD] = a / b;
PPCInterpreter_setXerOV(hCPU, false);
}
hCPU->gpr[rD] = a / b;
PPCInterpreter_setXerOV(hCPU, false);
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
@ -442,12 +508,14 @@ static void PPCInterpreter_DIVWO(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_DIVWU(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
if (hCPU->gpr[rB] == 0)
{
PPCInterpreter_nextInstruction(hCPU);
return;
}
hCPU->gpr[rD] = hCPU->gpr[rA] / hCPU->gpr[rB];
uint32 a = hCPU->gpr[rA];
uint32 b = hCPU->gpr[rB];
if (b == 0)
hCPU->gpr[rD] = 0;
else if (a == 0x80000000 && b == 0xFFFFFFFF)
hCPU->gpr[rD] = 0;
else
hCPU->gpr[rD] = a / b;
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
@ -456,14 +524,23 @@ static void PPCInterpreter_DIVWU(PPCInterpreter_t* hCPU, uint32 opcode)
static void PPCInterpreter_DIVWUO(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL3_XO();
if (hCPU->gpr[rB] == 0)
uint32 a = hCPU->gpr[rA];
uint32 b = hCPU->gpr[rB];
if (b == 0)
{
PPCInterpreter_setXerOV(hCPU, true);
PPCInterpreter_nextInstruction(hCPU);
return;
hCPU->gpr[rD] = 0;
}
else if(a == 0x80000000 && b == 0xFFFFFFFF)
{
PPCInterpreter_setXerOV(hCPU, false);
hCPU->gpr[rD] = 0;
}
else
{
hCPU->gpr[rD] = a / b;
PPCInterpreter_setXerOV(hCPU, false);
}
hCPU->gpr[rD] = hCPU->gpr[rA] / hCPU->gpr[rB];
PPCInterpreter_setXerOV(hCPU, false);
if (opHasRC())
ppc_update_cr0(hCPU, hCPU->gpr[rD]);
PPCInterpreter_nextInstruction(hCPU);
@ -490,6 +567,13 @@ static void PPCInterpreter_CRANDC(PPCInterpreter_t* hCPU, uint32 opcode)
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_CRNAND(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL_X_CR();
ppc_setCRBit(hCPU, crD, (ppc_getCRBit(hCPU, crA)&ppc_getCRBit(hCPU, crB)) ^ 1);
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_CROR(PPCInterpreter_t* hCPU, uint32 opcode)
{
PPC_OPC_TEMPL_X_CR();
@ -847,8 +931,7 @@ static void PPCInterpreter_CMP(PPCInterpreter_t* hCPU, uint32 opcode)
hCPU->cr[cr * 4 + CR_BIT_GT] = 1;
else
hCPU->cr[cr * 4 + CR_BIT_EQ] = 1;
if ((hCPU->spr.XER & XER_SO) != 0)
hCPU->cr[cr * 4 + CR_BIT_SO] = 1;
hCPU->cr[cr * 4 + CR_BIT_SO] = hCPU->xer_so;
PPCInterpreter_nextInstruction(hCPU);
}
@ -870,8 +953,7 @@ static void PPCInterpreter_CMPL(PPCInterpreter_t* hCPU, uint32 opcode)
hCPU->cr[cr * 4 + CR_BIT_GT] = 1;
else
hCPU->cr[cr * 4 + CR_BIT_EQ] = 1;
if ((hCPU->spr.XER & XER_SO) != 0)
hCPU->cr[cr * 4 + CR_BIT_SO] = 1;
hCPU->cr[cr * 4 + CR_BIT_SO] = hCPU->xer_so;
PPCInterpreter_nextInstruction(hCPU);
}
@ -894,8 +976,7 @@ static void PPCInterpreter_CMPI(PPCInterpreter_t* hCPU, uint32 opcode)
hCPU->cr[cr * 4 + CR_BIT_GT] = 1;
else
hCPU->cr[cr * 4 + CR_BIT_EQ] = 1;
if (hCPU->spr.XER & XER_SO)
hCPU->cr[cr * 4 + CR_BIT_SO] = 1;
hCPU->cr[cr * 4 + CR_BIT_SO] = hCPU->xer_so;
PPCInterpreter_nextInstruction(hCPU);
}
@ -918,8 +999,7 @@ static void PPCInterpreter_CMPLI(PPCInterpreter_t* hCPU, uint32 opcode)
hCPU->cr[cr * 4 + CR_BIT_GT] = 1;
else
hCPU->cr[cr * 4 + CR_BIT_EQ] = 1;
if (hCPU->spr.XER & XER_SO)
hCPU->cr[cr * 4 + CR_BIT_SO] = 1;
hCPU->cr[cr * 4 + CR_BIT_SO] = hCPU->xer_so;
PPCInterpreter_nextInstruction(hCPU);
}

View file

@ -32,7 +32,7 @@ espresso_frsqrte_entry_t frsqrteLookupTable[32] =
{0x20c1000, 0x35e},{0x1f12000, 0x332},{0x1d79000, 0x30a},{0x1bf4000, 0x2e6},
};
double frsqrte_espresso(double input)
ATTR_MS_ABI double frsqrte_espresso(double input)
{
unsigned long long x = *(unsigned long long*)&input;
@ -111,7 +111,7 @@ espresso_fres_entry_t fresLookupTable[32] =
{0x88400, 0x11a}, {0x65000, 0x11a}, {0x41c00, 0x108}, {0x20c00, 0x106}
};
double fres_espresso(double input)
ATTR_MS_ABI double fres_espresso(double input)
{
// based on testing we know that fres uses only the first 15 bits of the mantissa
// seee eeee eeee mmmm mmmm mmmm mmmx xxxx .... (s = sign, e = exponent, m = mantissa, x = not used)

View file

@ -2,62 +2,70 @@
#include "PPCInterpreterInternal.h"
#include "PPCInterpreterHelper.h"
std::unordered_set<std::string> sUnsupportedHLECalls;
std::unordered_set<std::string> s_unsupportedHLECalls;
void PPCInterpreter_handleUnsupportedHLECall(PPCInterpreter_t* hCPU)
{
const char* libFuncName = (char*)memory_getPointerFromVirtualOffset(hCPU->instructionPointer + 8);
std::string tempString = fmt::format("Unsupported lib call: {}", libFuncName);
if (sUnsupportedHLECalls.find(tempString) == sUnsupportedHLECalls.end())
if (s_unsupportedHLECalls.find(tempString) == s_unsupportedHLECalls.end())
{
cemuLog_log(LogType::UnsupportedAPI, "{}", tempString);
sUnsupportedHLECalls.emplace(tempString);
s_unsupportedHLECalls.emplace(tempString);
}
hCPU->gpr[3] = 0;
PPCInterpreter_nextInstruction(hCPU);
}
std::vector<void(*)(PPCInterpreter_t* hCPU)>* sPPCHLETable{};
static constexpr size_t HLE_TABLE_CAPACITY = 0x4000;
HLECALL s_ppcHleTable[HLE_TABLE_CAPACITY]{};
sint32 s_ppcHleTableWriteIndex = 0;
std::mutex s_ppcHleTableMutex;
HLEIDX PPCInterpreter_registerHLECall(HLECALL hleCall, std::string hleName)
{
if (!sPPCHLETable)
sPPCHLETable = new std::vector<void(*)(PPCInterpreter_t* hCPU)>();
for (sint32 i = 0; i < sPPCHLETable->size(); i++)
std::unique_lock _l(s_ppcHleTableMutex);
if (s_ppcHleTableWriteIndex >= HLE_TABLE_CAPACITY)
{
if ((*sPPCHLETable)[i] == hleCall)
return i;
cemuLog_log(LogType::Force, "HLE table is full");
cemu_assert(false);
}
HLEIDX newFuncIndex = (sint32)sPPCHLETable->size();
sPPCHLETable->resize(sPPCHLETable->size() + 1);
(*sPPCHLETable)[newFuncIndex] = hleCall;
return newFuncIndex;
for (sint32 i = 0; i < s_ppcHleTableWriteIndex; i++)
{
if (s_ppcHleTable[i] == hleCall)
{
return i;
}
}
cemu_assert(s_ppcHleTableWriteIndex < HLE_TABLE_CAPACITY);
s_ppcHleTable[s_ppcHleTableWriteIndex] = hleCall;
HLEIDX funcIndex = s_ppcHleTableWriteIndex;
s_ppcHleTableWriteIndex++;
return funcIndex;
}
HLECALL PPCInterpreter_getHLECall(HLEIDX funcIndex)
{
if (funcIndex < 0 || funcIndex >= sPPCHLETable->size())
if (funcIndex < 0 || funcIndex >= HLE_TABLE_CAPACITY)
return nullptr;
return sPPCHLETable->data()[funcIndex];
return s_ppcHleTable[funcIndex];
}
std::mutex g_hleLogMutex;
std::mutex s_hleLogMutex;
void PPCInterpreter_virtualHLE(PPCInterpreter_t* hCPU, unsigned int opcode)
{
uint32 hleFuncId = opcode & 0xFFFF;
if (hleFuncId == 0xFFD0)
if (hleFuncId == 0xFFD0) [[unlikely]]
{
g_hleLogMutex.lock();
s_hleLogMutex.lock();
PPCInterpreter_handleUnsupportedHLECall(hCPU);
g_hleLogMutex.unlock();
return;
s_hleLogMutex.unlock();
}
else
{
// os lib function
cemu_assert(hleFuncId < sPPCHLETable->size());
auto hleCall = (*sPPCHLETable)[hleFuncId];
auto hleCall = PPCInterpreter_getHLECall(hleFuncId);
cemu_assert(hleCall);
hleCall(hCPU);
}

View file

@ -428,9 +428,6 @@ public:
}
};
uint32 testIP[100];
uint32 testIPC = 0;
template <typename ppcItpCtrl>
class PPCInterpreterContainer
{
@ -466,6 +463,10 @@ public:
case 1: // virtual HLE
PPCInterpreter_virtualHLE(hCPU, opcode);
break;
case 3:
cemuLog_logDebug(LogType::Force, "Unsupported TWI instruction executed at {:08x}", hCPU->instructionPointer);
PPCInterpreter_nextInstruction(hCPU);
break;
case 4:
switch (PPC_getBits(opcode, 30, 5))
{
@ -482,8 +483,9 @@ public:
PPCInterpreter_PS_CMPU1(hCPU, opcode);
break;
default:
debug_printf("Unknown execute %04X as [4->0] at %08X\n", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer);
cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [4->0] at {:08x}", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer);
cemu_assert_unimplemented();
hCPU->instructionPointer += 4;
break;
}
break;
@ -509,8 +511,9 @@ public:
PPCInterpreter_PS_ABS(hCPU, opcode);
break;
default:
debug_printf("Unknown execute %04X as [4->8] at %08X\n", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer);
cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [4->8] at {:08x}", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer);
cemu_assert_unimplemented();
hCPU->instructionPointer += 4;
break;
}
break;
@ -548,8 +551,9 @@ public:
PPCInterpreter_PS_MERGE11(hCPU, opcode);
break;
default:
debug_printf("Unknown execute %04X as [4->16] at %08X\n", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer);
debugBreakpoint();
cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [4->16] at {:08x}", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer);
cemu_assert_unimplemented();
hCPU->instructionPointer += 4;
break;
}
break;
@ -590,8 +594,9 @@ public:
PPCInterpreter_PS_NMADD(hCPU, opcode);
break;
default:
debug_printf("Unknown execute %04X as [4] at %08X\n", PPC_getBits(opcode, 30, 5), hCPU->instructionPointer);
cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [4] at {:08x}", PPC_getBits(opcode, 30, 5), hCPU->instructionPointer);
cemu_assert_unimplemented();
hCPU->instructionPointer += 4;
break;
}
break;
@ -623,12 +628,15 @@ public:
PPCInterpreter_BCX(hCPU, opcode);
break;
case 17:
if (PPC_getBits(opcode, 30, 1) == 1) {
if (PPC_getBits(opcode, 30, 1) == 1)
{
PPCInterpreter_SC(hCPU, opcode);
}
else {
debug_printf("Unsupported Opcode [0x17 --> 0x0]\n");
else
{
cemuLog_logDebug(LogType::Force, "Unsupported Opcode [0x17 --> 0x0]");
cemu_assert_unimplemented();
hCPU->instructionPointer += 4;
}
break;
case 18:
@ -658,6 +666,9 @@ public:
case 193:
PPCInterpreter_CRXOR(hCPU, opcode);
break;
case 225:
PPCInterpreter_CRNAND(hCPU, opcode);
break;
case 257:
PPCInterpreter_CRAND(hCPU, opcode);
break;
@ -674,8 +685,9 @@ public:
PPCInterpreter_BCCTR(hCPU, opcode);
break;
default:
debug_printf("Unknown execute %04X as [19] at %08X\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer);
cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [19] at {:08x}\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer);
cemu_assert_unimplemented();
hCPU->instructionPointer += 4;
break;
}
break;
@ -713,9 +725,6 @@ public:
PPCInterpreter_CMP(hCPU, opcode);
break;
case 4:
#ifdef CEMU_DEBUG_ASSERT
debug_printf("TW instruction executed at %08x\n", hCPU->instructionPointer);
#endif
PPCInterpreter_TW(hCPU, opcode);
break;
case 8:
@ -895,6 +904,12 @@ public:
case 522:
PPCInterpreter_ADDCO(hCPU, opcode);
break;
case 523: // 11 | OE
PPCInterpreter_MULHWU_(hCPU, opcode); // OE is ignored
break;
case 533:
PPCInterpreter_LSWX(hCPU, opcode);
break;
case 534:
PPCInterpreter_LWBRX(hCPU, opcode);
break;
@ -913,6 +928,9 @@ public:
case 567:
PPCInterpreter_LFSUX(hCPU, opcode);
break;
case 587: // 75 | OE
PPCInterpreter_MULHW_(hCPU, opcode); // OE is ignored for MULHW
break;
case 595:
PPCInterpreter_MFSR(hCPU, opcode);
break;
@ -943,15 +961,30 @@ public:
case 663:
PPCInterpreter_STFSX(hCPU, opcode);
break;
case 661:
PPCInterpreter_STSWX(hCPU, opcode);
break;
case 695:
PPCInterpreter_STFSUX(hCPU, opcode);
break;
case 712: // 200 | OE
PPCInterpreter_SUBFZEO(hCPU, opcode);
break;
case 714: // 202 | OE
PPCInterpreter_ADDZEO(hCPU, opcode);
break;
case 725:
PPCInterpreter_STSWI(hCPU, opcode);
break;
case 727:
PPCInterpreter_STFDX(hCPU, opcode);
break;
case 744: // 232 | OE
PPCInterpreter_SUBFMEO(hCPU, opcode);
break;
case 746: // 234 | OE
PPCInterpreter_ADDMEO(hCPU, opcode);
break;
case 747:
PPCInterpreter_MULLWO(hCPU, opcode);
break;
@ -998,10 +1031,8 @@ public:
PPCInterpreter_DCBZ(hCPU, opcode);
break;
default:
debug_printf("Unknown execute %04X as [31] at %08X\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer);
#ifdef CEMU_DEBUG_ASSERT
assert_dbg();
#endif
cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [31] at {:08x}\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer);
cemu_assert_unimplemented();
hCPU->instructionPointer += 4;
break;
}
@ -1084,7 +1115,7 @@ public:
case 57:
PPCInterpreter_PSQ_LU(hCPU, opcode);
break;
case 59: //Opcode category
case 59: // opcode category
switch (PPC_getBits(opcode, 30, 5))
{
case 18:
@ -1115,8 +1146,9 @@ public:
PPCInterpreter_FNMADDS(hCPU, opcode);
break;
default:
debug_printf("Unknown execute %04X as [59] at %08X\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer);
cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [59] at {:08x}\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer);
cemu_assert_unimplemented();
hCPU->instructionPointer += 4;
break;
}
break;
@ -1195,18 +1227,19 @@ public:
case 583:
PPCInterpreter_MFFS(hCPU, opcode);
break;
case 711: // IBM documentation has this wrong as 771?
case 711:
PPCInterpreter_MTFSF(hCPU, opcode);
break;
default:
debug_printf("Unknown execute %04X as [63] at %08X\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer);
cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [63] at {:08x}\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer);
cemu_assert_unimplemented();
PPCInterpreter_nextInstruction(hCPU);
break;
}
}
break;
default:
debug_printf("Unknown execute %04X at %08X\n", PPC_getBits(opcode, 5, 6), (unsigned int)hCPU->instructionPointer);
cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} at {:08x}\n", PPC_getBits(opcode, 5, 6), (unsigned int)hCPU->instructionPointer);
cemu_assert_unimplemented();
}
}

View file

@ -50,9 +50,9 @@
#define CR_BIT_EQ 2
#define CR_BIT_SO 3
#define XER_SO (1<<31) // summary overflow bit
#define XER_OV (1<<30) // overflow bit
#define XER_BIT_CA (29) // carry bit index. To accelerate frequent access, this bit is stored as a separate uint8
#define XER_BIT_SO (31) // summary overflow, counterpart to CR SO
#define XER_BIT_OV (30)
// FPSCR
#define FPSCR_VXSNAN (1<<24)
@ -118,7 +118,8 @@
static inline void ppc_update_cr0(PPCInterpreter_t* hCPU, uint32 r)
{
hCPU->cr[CR_BIT_SO] = (hCPU->spr.XER&XER_SO) ? 1 : 0;
cemu_assert_debug(hCPU->xer_so <= 1);
hCPU->cr[CR_BIT_SO] = hCPU->xer_so;
hCPU->cr[CR_BIT_LT] = ((r != 0) ? 1 : 0) & ((r & 0x80000000) ? 1 : 0);
hCPU->cr[CR_BIT_EQ] = (r == 0);
hCPU->cr[CR_BIT_GT] = hCPU->cr[CR_BIT_EQ] ^ hCPU->cr[CR_BIT_LT] ^ 1; // this works because EQ and LT can never be set at the same time. So the only case where GT becomes 1 is when LT=0 and EQ=0
@ -190,8 +191,8 @@ inline double roundTo25BitAccuracy(double d)
return *(double*)&v;
}
double fres_espresso(double input);
double frsqrte_espresso(double input);
ATTR_MS_ABI double fres_espresso(double input);
ATTR_MS_ABI double frsqrte_espresso(double input);
void fcmpu_espresso(PPCInterpreter_t* hCPU, int crfD, double a, double b);

View file

@ -31,7 +31,7 @@ static void PPCInterpreter_STW(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STWU(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS;
sint32 rA, rS;
uint32 imm;
PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm);
ppcItpCtrl::ppcMem_writeDataU32(hCPU, hCPU->gpr[rA] + imm, hCPU->gpr[rS]);
@ -42,7 +42,7 @@ static void PPCInterpreter_STWU(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STWX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS, rB;
sint32 rA, rS, rB;
PPC_OPC_TEMPL_X(Opcode, rS, rA, rB);
ppcItpCtrl::ppcMem_writeDataU32(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], hCPU->gpr[rS]);
PPCInterpreter_nextInstruction(hCPU);
@ -85,7 +85,8 @@ static void PPCInterpreter_STWCX(PPCInterpreter_t* hCPU, uint32 Opcode)
ppc_setCRBit(hCPU, CR_BIT_GT, 0);
ppc_setCRBit(hCPU, CR_BIT_EQ, 1);
}
ppc_setCRBit(hCPU, CR_BIT_SO, (hCPU->spr.XER&XER_SO) != 0 ? 1 : 0);
cemu_assert_debug(hCPU->xer_so <= 1);
ppc_setCRBit(hCPU, CR_BIT_SO, hCPU->xer_so);
// remove reservation
hCPU->reservedMemAddr = 0;
hCPU->reservedMemValue = 0;
@ -102,7 +103,7 @@ static void PPCInterpreter_STWCX(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STWUX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS, rB;
sint32 rA, rS, rB;
PPC_OPC_TEMPL_X(Opcode, rS, rA, rB);
ppcItpCtrl::ppcMem_writeDataU32(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], hCPU->gpr[rS]);
if (rA)
@ -112,7 +113,7 @@ static void PPCInterpreter_STWUX(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STWBRX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS, rB;
sint32 rA, rS, rB;
PPC_OPC_TEMPL_X(Opcode, rS, rA, rB);
ppcItpCtrl::ppcMem_writeDataU32(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], _swapEndianU32(hCPU->gpr[rS]));
PPCInterpreter_nextInstruction(hCPU);
@ -120,7 +121,7 @@ static void PPCInterpreter_STWBRX(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STMW(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rS, rA;
sint32 rS, rA;
uint32 imm;
PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm);
uint32 ea = (rA ? hCPU->gpr[rA] : 0) + imm;
@ -135,7 +136,7 @@ static void PPCInterpreter_STMW(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STH(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS;
sint32 rA, rS;
uint32 imm;
PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm);
ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + imm, (uint16)hCPU->gpr[rS]);
@ -144,7 +145,7 @@ static void PPCInterpreter_STH(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STHU(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS;
sint32 rA, rS;
uint32 imm;
PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm);
ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + imm, (uint16)hCPU->gpr[rS]);
@ -155,7 +156,7 @@ static void PPCInterpreter_STHU(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STHX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS, rB;
sint32 rA, rS, rB;
PPC_OPC_TEMPL_X(Opcode, rS, rA, rB);
ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], (uint16)hCPU->gpr[rS]);
PPCInterpreter_nextInstruction(hCPU);
@ -163,7 +164,7 @@ static void PPCInterpreter_STHX(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STHUX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS, rB;
sint32 rA, rS, rB;
PPC_OPC_TEMPL_X(Opcode, rS, rA, rB);
ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], (uint16)hCPU->gpr[rS]);
if (rA)
@ -173,7 +174,7 @@ static void PPCInterpreter_STHUX(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STHBRX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS, rB;
sint32 rA, rS, rB;
PPC_OPC_TEMPL_X(Opcode, rS, rA, rB);
ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], _swapEndianU16((uint16)hCPU->gpr[rS]));
PPCInterpreter_nextInstruction(hCPU);
@ -181,7 +182,7 @@ static void PPCInterpreter_STHBRX(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STB(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS;
sint32 rA, rS;
uint32 imm;
PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm);
ppcItpCtrl::ppcMem_writeDataU8(hCPU, (rA ? hCPU->gpr[rA] : 0) + imm, (uint8)hCPU->gpr[rS]);
@ -190,7 +191,7 @@ static void PPCInterpreter_STB(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STBU(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS;
sint32 rA, rS;
uint32 imm;
PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm);
ppcItpCtrl::ppcMem_writeDataU8(hCPU, hCPU->gpr[rA] + imm, (uint8)hCPU->gpr[rS]);
@ -200,7 +201,7 @@ static void PPCInterpreter_STBU(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STBX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS, rB;
sint32 rA, rS, rB;
PPC_OPC_TEMPL_X(Opcode, rS, rA, rB);
ppcItpCtrl::ppcMem_writeDataU8(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], (uint8)hCPU->gpr[rS]);
PPCInterpreter_nextInstruction(hCPU);
@ -208,7 +209,7 @@ static void PPCInterpreter_STBX(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STBUX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS, rB;
sint32 rA, rS, rB;
PPC_OPC_TEMPL_X(Opcode, rS, rA, rB);
ppcItpCtrl::ppcMem_writeDataU8(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], (uint8)hCPU->gpr[rS]);
if (rA)
@ -218,7 +219,7 @@ static void PPCInterpreter_STBUX(PPCInterpreter_t* hCPU, uint32 Opcode)
static void PPCInterpreter_STSWI(PPCInterpreter_t* hCPU, uint32 Opcode)
{
int rA, rS, nb;
sint32 rA, rS, nb;
PPC_OPC_TEMPL_X(Opcode, rS, rA, nb);
if (nb == 0) nb = 32;
uint32 ea = rA ? hCPU->gpr[rA] : 0;
@ -228,7 +229,39 @@ static void PPCInterpreter_STSWI(PPCInterpreter_t* hCPU, uint32 Opcode)
{
if (i == 0)
{
r = hCPU->gpr[rS];
r = rS < 32 ? hCPU->gpr[rS] : 0; // what happens if rS is out of bounds?
rS++;
rS %= 32;
i = 4;
}
ppcItpCtrl::ppcMem_writeDataU8(hCPU, ea, (r >> 24));
r <<= 8;
ea++;
i--;
nb--;
}
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_STSWX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
sint32 rA, rS, rB;
PPC_OPC_TEMPL_X(Opcode, rS, rA, rB);
sint32 nb = hCPU->spr.XER&0x7F;
if (nb == 0)
{
PPCInterpreter_nextInstruction(hCPU);
return;
}
uint32 ea = rA ? hCPU->gpr[rA] : 0;
ea += hCPU->gpr[rB];
uint32 r = 0;
int i = 0;
while (nb > 0)
{
if (i == 0)
{
r = rS < 32 ? hCPU->gpr[rS] : 0; // what happens if rS is out of bounds?
rS++;
rS %= 32;
i = 4;
@ -459,7 +492,6 @@ static void PPCInterpreter_LSWI(PPCInterpreter_t* hCPU, uint32 Opcode)
PPC_OPC_TEMPL_X(Opcode, rD, rA, nb);
if (nb == 0)
nb = 32;
uint32 ea = rA ? hCPU->gpr[rA] : 0;
uint32 r = 0;
int i = 4;
@ -469,7 +501,8 @@ static void PPCInterpreter_LSWI(PPCInterpreter_t* hCPU, uint32 Opcode)
if (i == 0)
{
i = 4;
hCPU->gpr[rD] = r;
if(rD < 32)
hCPU->gpr[rD] = r;
rD++;
rD %= 32;
r = 0;
@ -486,7 +519,52 @@ static void PPCInterpreter_LSWI(PPCInterpreter_t* hCPU, uint32 Opcode)
r <<= 8;
i--;
}
hCPU->gpr[rD] = r;
if(rD < 32)
hCPU->gpr[rD] = r;
PPCInterpreter_nextInstruction(hCPU);
}
static void PPCInterpreter_LSWX(PPCInterpreter_t* hCPU, uint32 Opcode)
{
sint32 rA, rD, rB;
PPC_OPC_TEMPL_X(Opcode, rD, rA, rB);
// byte count comes from XER
uint32 nb = (hCPU->spr.XER>>0)&0x7F;
if (nb == 0)
{
PPCInterpreter_nextInstruction(hCPU);
return; // no-op
}
uint32 ea = rA ? hCPU->gpr[rA] : 0;
ea += hCPU->gpr[rB];
uint32 r = 0;
int i = 4;
uint8 v;
while (nb>0)
{
if (i == 0)
{
i = 4;
if(rD < 32)
hCPU->gpr[rD] = r;
rD++;
rD %= 32;
r = 0;
}
v = ppcItpCtrl::ppcMem_readDataU8(hCPU, ea);
r <<= 8;
r |= v;
ea++;
i--;
nb--;
}
while (i)
{
r <<= 8;
i--;
}
if(rD < 32)
hCPU->gpr[rD] = r;
PPCInterpreter_nextInstruction(hCPU);
}

View file

@ -63,16 +63,25 @@ void PPCInterpreter_setDEC(PPCInterpreter_t* hCPU, uint32 newValue)
uint32 PPCInterpreter_getXER(PPCInterpreter_t* hCPU)
{
uint32 xerValue = hCPU->spr.XER;
xerValue &= ~(1<<XER_BIT_CA);
if( hCPU->xer_ca )
xerValue |= (1<<XER_BIT_CA);
xerValue &= ~(1 << XER_BIT_CA);
xerValue &= ~(1 << XER_BIT_SO);
xerValue &= ~(1 << XER_BIT_OV);
if (hCPU->xer_ca)
xerValue |= (1 << XER_BIT_CA);
if (hCPU->xer_so)
xerValue |= (1 << XER_BIT_SO);
if (hCPU->xer_ov)
xerValue |= (1 << XER_BIT_OV);
return xerValue;
}
void PPCInterpreter_setXER(PPCInterpreter_t* hCPU, uint32 v)
{
hCPU->spr.XER = v;
hCPU->xer_ca = (v>>XER_BIT_CA)&1;
const uint32 XER_MASK = 0xE0FFFFFF; // some bits are masked out. Figure out which ones exactly
hCPU->spr.XER = v & XER_MASK;
hCPU->xer_ca = (v >> XER_BIT_CA) & 1;
hCPU->xer_so = (v >> XER_BIT_SO) & 1;
hCPU->xer_ov = (v >> XER_BIT_OV) & 1;
}
uint32 PPCInterpreter_getCoreIndex(PPCInterpreter_t* hCPU)
@ -90,7 +99,7 @@ uint8* PPCInterpreterGetStackPointer()
return memory_getPointerFromVirtualOffset(PPCInterpreter_getCurrentInstance()->gpr[1]);
}
uint8* PPCInterpreterGetAndModifyStackPointer(sint32 offset)
uint8* PPCInterpreter_PushAndReturnStackPointer(sint32 offset)
{
PPCInterpreter_t* hCPU = PPCInterpreter_getCurrentInstance();
uint8* result = memory_getPointerFromVirtualOffset(hCPU->gpr[1] - offset);

View file

@ -5,7 +5,6 @@
#include "Cafe/OS/libs/coreinit/coreinit_CodeGen.h"
#include "../Recompiler/PPCRecompiler.h"
#include "../Recompiler/PPCRecompilerX64.h"
#include <float.h>
#include "Cafe/HW/Latte/Core/LatteBufferCache.h"
@ -94,7 +93,6 @@ void PPCInterpreter_MTCRF(PPCInterpreter_t* hCPU, uint32 Opcode)
{
// frequently used by GCC compiled code (e.g. SM64 port)
// tested
uint32 rS;
uint32 crfMask;
PPC_OPC_TEMPL_XFX(Opcode, rS, crfMask);

View file

@ -68,6 +68,8 @@ static void PPCInterpreter_TW(PPCInterpreter_t* hCPU, uint32 opcode)
PPC_OPC_TEMPL_X(opcode, to, rA, rB);
cemu_assert_debug(to == 0);
if(to != 0)
PPCInterpreter_nextInstruction(hCPU);
if (rA == DEBUGGER_BP_T_DEBUGGER)
debugger_enterTW(hCPU);

Some files were not shown because too many files have changed in this diff Show more