Switch 2: Compatibility Mode: Difference between revisions
| (18 intermediate revisions by 2 users not shown) | |||
| Line 7: | Line 7: | ||
These binaries are compiled with PAC enabled. | These binaries are compiled with PAC enabled. | ||
= NPDM Adjustments = | |||
* Game has access to SVC 0x54, 0x80 even though it's not in the game NPDM. | |||
* Game has CoreMask 0x3F (so access to core0-5) even though the game NPDM only has CoreMask 0x7. | |||
* It's unknown if the service whitelist is updated for the game when running in Compatibility mode. | |||
= Hooking = | = Hooking = | ||
| Line 16: | Line 20: | ||
Below is a breakdown what some of the hooks and what their purpose is. | Below is a breakdown what some of the hooks and what their purpose is. | ||
== Modules == | |||
Rtld is identical besides the extra page at the end of .bss for [[#CompatibilityParameter|CompatibilityParameter]]. | |||
The compat modules are loaded between the main module and the (sub)sdk* modules. | |||
The existing modules are not directly modified. | |||
== CompatibilityParameter == | == CompatibilityParameter == | ||
| Line 21: | Line 32: | ||
To retrieve this pointer, [[#nnCompatThin|nnCompatThin]] intercepts the nnosInitialize function and retrieves it from there. Normally, a game doesn't use the ProgramParameter so it doesn't care this parameter was passed. | To retrieve this pointer, [[#nnCompatThin|nnCompatThin]] intercepts the nnosInitialize function and retrieves it from there. Normally, a game doesn't use the ProgramParameter so it doesn't care this parameter was passed. | ||
{| class=wikitable | |||
! Offset || Type || Name | |||
|- | |||
| 0x00 || ModuleSdkInfo[11] || Modules | |||
|- | |||
| 0xB0 || u64 || ModulesCount | |||
|- | |||
| 0xB8 || u64 || GraphicsControlData | |||
|- | |||
| 0xC0 || u64 || MovieControlData | |||
|- | |||
| 0xC8 || u64 || AudioControlData | |||
|- | |||
| 0xD0 || u64 || [[#MiscControlData]] | |||
|} | |||
=== MiscControlData === | |||
{| class=wikitable | |||
! Bit || Name || Description | |||
|- | |||
| 0 || PreventShaderCacheOpenFile || Prevents game from opening file: "ROM:/data/scaleform_cache/GFxShaders.cache". | |||
|- | |||
| 1 || PreventShaderCacheGetEntryType || Prevents game from getting the entry type on 5 different hardcoded paths. | |||
|- | |||
| 2 || PreventShaderCacheOpenDirectory || Prevents game from opening directory: "host:/shaders/build/" | |||
|- | |||
| 4 || SerializeSavedataAccess || A global mutex is taken when a file starting with "savedata" is opened, and held until the file has been closed. Commit-action also takes the mutex, so the commit will not complete until the file has been closed. | |||
|- | |||
| 6 || PreventNegativeVibrationValue || | |||
|- | |||
| 10 || NeedsWaitingLaunchLogo || | |||
|- | |||
| 13 || ExtraSleepForOfflineWebApplet || | |||
|- | |||
|} | |||
=== ModuleSdkInfo === | |||
{| class=wikitable | |||
! Offset || Type || Name | |||
|- | |||
| 0x00 || const char* || SdkNameStringPtr. Points to a string of the form "SDK MW+Nintendo+NintendoSdk_nnSdk-XX_Y_Z-Release". | |||
|- | |||
| 0x08 || u32 || SdkNameStringLength | |||
|- | |||
|} | |||
= ApplicationCompatibilityInfo = | |||
The [[Switch 2: Title list|ApplicationCompatibilityInfo]] SystemData contains "ApplicationCompatibilityInfo.json". | |||
The json "records" contains an array, each object entry then contains the following: | |||
* "application_id": "0x<lowercase hex ApplicationId>" | |||
* "target_max_version": <value> (normally u32-max) | |||
* "application_layer_info": This object contains various number fields, only fields needed by the current entry are present. "graphics_config", "misc_config", ... | |||
** The data from here is likely passed as input to [[#CompatibilityParameter|CompatibilityParameter]]. | |||
= nnCompatTrampoline = | = nnCompatTrampoline = | ||
| Line 27: | Line 93: | ||
{| class=wikitable | {| class=wikitable | ||
! Hooked Symbol || Difference | ! Hooked Symbol || Difference || Conditional | ||
|- | |||
| nnosInitialize || Captures the ProgramArgument parameter where the [[#CompatibilityParameter]] is stored. || | |||
|- | |||
| nn::os::CreateThread || No change. || | |||
|- | |||
| nn::os::SetThreadCoreMask || No change. || | |||
|- | |||
| nn::os::GetThreadAvailableCoreMask, nn::os::GetThreadAvailableCoreMask || Returns actual core mask masked with 0x7, effectively pretending that there are only 3 CPU cores available. || | |||
|- | |||
| nn::audio::GetAudioInName || If the primary audio in name is "XUac", it returns the secondary device name instead. Presumably, the "XUac" device has been removed in Switch 2. || | |||
|- | |||
| nn::audio::GetReleasedWaveBuffer || Now returns NULL under certain circumstances. || AudioControlData bit0 | |||
|- | |||
| nn::web::OfflineWebSession::Appear || Added sleep 50000000 before calling the original function. || MiscControlData bit13 | |||
|- | |- | ||
| | | nn::ssl::Connection::SetSocketDescriptor || Calls nn::socket::Fnctl(..., 3); nn::socket::Fnctl(..., 4); on the socket fd. || MiscControlData bit15 | ||
|- | |- | ||
| nn:: | | nn::swkbd::InlineKeyboard::GetImage, nn::swkbd::InlineKeyboard::Calc || Takes a shared mutex before calling original functions. No other changes. Probably prevents a race condition that only manifests on Switch 2. || | ||
|- | |- | ||
| nn:: | | nn::socket::Socket || If nn::socket::IsInitialized() is 0, sleep for 1 second, and see it reaches 1 before calling the original function. Probably prevents a race condition that only manifests on Switch 2. || MiscControlData bit9 | ||
|- | |- | ||
| nn::os:: | | nn::os::TimedAcquireSemaphore || Force arg1=true. || MiscControlData bit8. | ||
|- | |- | ||
| nn:: | | nn::os::QueryMemoryInfo,nn::os::QueryMemoryInfoForDebug || Hides stolen Heap memory that it uses for itself... || | ||
|- | |- | ||
| nn:: | | nn::hid::VibrationPlayer::SetCurrentPosition || If position is negative, drop the call. || MiscControlData bit6 | ||
|} | |} | ||
| Line 50: | Line 130: | ||
|- | |- | ||
| nn::os::ConvertToTick || Uses conversion ratio 31250000 instead of 19200000. | | nn::os::ConvertToTick || Uses conversion ratio 31250000 instead of 19200000. | ||
|- | |||
| gl*, _gl*, egl* || OpenGL API translation for new GPU? | |||
|- | |||
| vk* || Vulkan API translation for new GPU? | |||
|- | |||
| NvOsFopen || | |||
|- | |||
| NvOsGetTimeMS || Adjusted for new clock frequency. | |||
|- | |||
| nn::vi::* || Translation layer because vi:u was removed? | |||
|- | |||
| nn::pl::IsRunningOnOunce || Returns 1 instead of 0. | |||
|} | |} | ||