(Switch 2) Compatibility Mode: Difference between revisions

From Nintendo Switch Brew
Jump to navigation Jump to search
Ootulp (talk | contribs)
No edit summary
Ootulp (talk | contribs)
Line 66: Line 66:
|-
|-
| nn::audio::GetReleasedWaveBuffer || Now returns NULL under certain circumstances.
| nn::audio::GetReleasedWaveBuffer || Now returns NULL under certain circumstances.
|-
| nn::web::OfflineWebSession::Appear || Added sleep 50000000 before calling the original function. Enabled by MiscControlData bit13.
|}
|}



Revision as of 10:24, 6 June 2025

When a Switch 1 game is running on the Switch 2, it is loaded together with 3 new modules:

These binaries are compiled with PAC enabled.


Hooking

Backwards-compatibility is achieved by (ab)using dynamic linking to selectively hook API functions. Three compatibility libraries are mapped into the game process. They provide symbols which override the original sdk codebin implementation, wherein a translation layer for Switch 2 is provided.

Most of these end up doing small tweaks to the parameters, and then calling into the original function implementation.

Switch 2 is mostly backwards-compatible, so most sdk codebin symbols remain unchanged and execute their original code. The overrides are mostly related to Graphics (i.e. translating to the new GPU), but there are also plenty other function overrides to deal with various system differences.

Below is a breakdown what some of the hooks and what their purpose is.

CompatibilityParameter

The system puts an additional information block in the ProgramArgument parameter for the process. This block contains certain extra information and overrides, which allows customization of the compatibility hooks depending on the game.

To retrieve this pointer, 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.

Offset Type Name
0x00 ModuleSdkInfo[11] Modules
0xB0 u64 ModulesCount
0xB8 u64 GraphicsControlData
0xC0 u64 MovieControlData
0xC8 u64 AudioControlData
0xD0 u64 MiscControlData (bit10: NeedsWaitingLaunchLogo)

ModuleSdkInfo

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

nnCompatTrampoline

nnCompatThin

Hooked Symbol Difference
nnosInitialize Captures the ProgramArgument parameter where the #CompatibilityParameter is stored.
nn::os::CreateThread No change.
nn::os::SetThreadCoreMask No change.
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.
nn::web::OfflineWebSession::Appear Added sleep 50000000 before calling the original function. Enabled by MiscControlData bit13.

nnCompat

Hooked Symbol Difference
nn::os::GetSystemTickFrequency Returns 31250000 instead of 19200000.
nn::os::ConvertToTick Uses conversion ratio 31250000 instead of 19200000.