Preliminary support for HOS 13.0.0

- pcv/am offsets in ldr_patcher

- ptm offsets in .pchtxt

- drop Erista support

TODOs:

- Update patcher.te to TegraScript v3

- Recompile sys-clk against new libnx

- Generate pcv/ptm/am patches manually
This commit is contained in:
KazushiM
2021-09-16 12:29:52 +08:00
parent a45b767a80
commit 380256f65c
9 changed files with 377 additions and 82 deletions

View File

@@ -1,6 +1,6 @@
# Switch OC Suite # Switch OC Suite
Overclocking suite for Switch **(Mariko Only)** running on Atmosphere CFW. Support Horizon OS 12.1.0. Overclocking suite for Switch **(Mariko Only)** running on Atmosphere CFW. Support Horizon OS 13.0.0.
@@ -85,19 +85,19 @@ Overclocking suite for Switch **(Mariko Only)** running on Atmosphere CFW. Suppo
**Contains:** **Contains:**
- Patches for pcv and ptm modules (for HOS 12.1.0) - Patches for pcv and ptm modules
- Patch tools for pcv module (only for amd64 Windows, build yourself otherwise): - Patch tools for pcv module (only for amd64 Windows, build yourself otherwise):
[hactool](https://github.com/SciresM/hactool), [nx2elf](https://github.com/shuffle2/nx2elf), elf2nso from [switch-tools](https://github.com/switchbrew/switch-tools/), [hacPack](https://github.com/The-4n/hacPack), [bsdiff-win](https://github.com/cnSchwarzer/bsdiff-win/) ([bsdiff](http://www.daemonology.net/bsdiff/)) [hactool](https://github.com/SciresM/hactool), [nx2elf](https://github.com/shuffle2/nx2elf), elf2nso from [switch-tools](https://github.com/switchbrew/switch-tools/), [hacPack](https://github.com/The-4n/hacPack), [bsdiff-win](https://github.com/cnSchwarzer/bsdiff-win/) ([bsdiff](http://www.daemonology.net/bsdiff/))
- Prebuilt sys-clk-OC and ReverseNX-RT modified for OC - Prebuilt sys-clk-OC and ReverseNX-RT modified for OC
- `system-settings.ini` with some QoL improvements - `system-settings.ini` with some QoL improvements
**Notice**: **Notice**:
- **Patching SysNAND is NOT recommended**. Since system files are directly altered, you could **NOT** boot to stock(OFW) until you revert the patch, and ban risks exist (?). - **Patching SysNAND is NOT recommended**. Since system files are directly altered, you could **NOT** boot to stock(OFW) until you revert the patch.
- **Restoring pcv backup is required before updating** Horizon OS and booting OFW. Launch the `patcher.te` script to restore your backup. - **Restoring pcv backup is required before updating** Horizon OS and booting OFW. Launch the `patcher.te` script to restore your backup.
- **Do NOT forget to reapply ptm-patch** after changing RAM OC clock. - **Do NOT forget to reapply ptm-patch** after changing RAM OC clock.
**Steps:** **Steps:**
1. Make sure you are running targeted HOS (12.1.0), and have `prod.keys` *with latest master key (0b)* dumped by [Lockpick_RCM](https://github.com/shchmue/Lockpick_RCM). 1. Make sure you are running targeted HOS, and have `prod.keys` *with latest master key* (`_0c`) dumped by [Lockpick_RCM](https://github.com/shchmue/Lockpick_RCM).
2. Loader patches for Atmosphere: Grab from the web and apply. I won't provide them here. (Or build AMS with `ValidateAcidSignature()` stubbed.) 2. Loader patches for Atmosphere: Grab from the web and apply. I won't provide them here. (Or build AMS with `ValidateAcidSignature()` stubbed.)
3. Place all the files in `SdOut` into SD card. 3. Place all the files in `SdOut` into SD card.
**See [Details](#details) section for more info.** **See [Details](#details) section for more info.**
@@ -122,22 +122,7 @@ Overclocking suite for Switch **(Mariko Only)** running on Atmosphere CFW. Suppo
### Method B: For Pro-users ### Method B: For Pro-users
```bash Grab necessary patches from the repo, then compile sys-clk, ReverseNX-RT and Atmosphere with devkitpro.
git clone https://github.com/KazushiMe/Switch-OC-Suite.git ~/Switch-OC-Suite
cd $YOUR_ATMOSPHERE_REPO
cp -R ~/Switch-OC-Suite/Atmosphere/*pp stratosphere/loader/source/
patch < ~/Switch-OC-Suite/Atmosphere/ldr_patcher.diff
cd $YOUR_SYS_CLK_REPO
git apply ~/Switch-OC-Suite/sys-clk.diff
cd $YOUR_REVERSENX_RT_REPO
git apply ~/Switch-OC-Suite/ReverseNX-RT.diff
```
Then compile sys-clk, ReverseNX-RT and Atmosphere with devkitpro, and don't forget to grab necessary patches in the repo.
Simply build `loader.kip` from Atmosphere and load it with hekate if you don't feel like wasting time. Simply build `loader.kip` from Atmosphere and load it with hekate if you don't feel like wasting time.

View File

@@ -1,5 +1,5 @@
pcvModulePath = "bis:/Contents/registered/3067dd44caacf32f8bca54ecde4c56e2.nca/00" pcvModulePath = "bis:/Contents/registered/6b675f6f9c9ec3a4448d81fa2bbc895e.nca/00"
OldBackupPath = "sd:/atmosphere/oc_patches/12-1-patch.bak" OldBackupPath = "sd:/atmosphere/oc_patches/13-0-patch.bak"
BackupPath = "sd:/atmosphere/oc_patches/pcv-backup" BackupPath = "sd:/atmosphere/oc_patches/pcv-backup"
PatchPath = "sd:/atmosphere/oc_patches/pcv-module" PatchPath = "sd:/atmosphere/oc_patches/pcv-module"
@@ -20,7 +20,7 @@ pausecont = {
} }
header = { header = {
println("\n-- Switch OC Suite Patcher (HOS 12.1.0) --\n\n") println("\n-- Switch OC Suite Patcher (HOS 13.0.0) --\n\n")
println(" OC Suite is provided 'as is' without warranty of any kind,\n USE AT YOUR OWN RISKS!") println(" OC Suite is provided 'as is' without warranty of any kind,\n USE AT YOUR OWN RISKS!")
println(" If you don't have Joy-Cons connected or are using Switch Lite,") println(" If you don't have Joy-Cons connected or are using Switch Lite,")
println(" Press VOL+/- to navigate and POWER button to confirm.\n") println(" Press VOL+/- to navigate and POWER button to confirm.\n")
@@ -77,7 +77,7 @@ if ( mmcMount("SYSTEM") ) {
if ( ! fileExists(pcvModulePath) ) { if ( ! fileExists(pcvModulePath) ) {
color("RED") color("RED")
println("You're NOT using targeted Horizon OS version!") println("You're NOT using targeted Horizon OS version!")
println("Targeted version: 12.1.0\n") println("Targeted version: 13.0.0\n")
color("WHITE") color("WHITE")
pauseexit() pauseexit()
} }

View File

@@ -0,0 +1,158 @@
// placed in Atmosphere/stratosphere/loader/source/
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "ldr_patcher.hpp"
#include "ldr_pcv_patch.hpp"
namespace ams::ldr {
namespace {
constexpr const char *NsoPatchesDirectory = "exefs_patches";
/* Exefs patches want to prevent modification of header, */
/* and also want to adjust offset relative to mapped location. */
constexpr size_t NsoPatchesProtectedSize = sizeof(NsoHeader);
constexpr size_t NsoPatchesProtectedOffset = sizeof(NsoHeader);
constexpr const char * const LoaderSdMountName = "#amsldr-sdpatch";
static_assert(sizeof(LoaderSdMountName) <= fs::MountNameLengthMax);
constinit os::SdkMutex g_ldr_sd_lock;
constinit bool g_mounted_sd;
constinit os::SdkMutex g_embedded_patch_lock;
constinit bool g_got_embedded_patch_settings;
constinit bool g_force_enable_usb30;
bool EnsureSdCardMounted() {
std::scoped_lock lk(g_ldr_sd_lock);
if (g_mounted_sd) {
return true;
}
if (!cfg::IsSdCardInitialized()) {
return false;
}
if (R_FAILED(fs::MountSdCard(LoaderSdMountName))) {
return false;
}
return (g_mounted_sd = true);
}
bool IsUsb30ForceEnabled() {
std::scoped_lock lk(g_embedded_patch_lock);
if (!g_got_embedded_patch_settings) {
g_force_enable_usb30 = spl::IsUsb30ForceEnabled();
g_got_embedded_patch_settings = true;
}
return g_force_enable_usb30;
}
consteval u8 ParseNybble(char c) {
AMS_ASSUME(('0' <= c && c <= '9') || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'));
if ('0' <= c && c <= '9') {
return c - '0' + 0x0;
} else if ('A' <= c && c <= 'F') {
return c - 'A' + 0xA;
} else /* if ('a' <= c && c <= 'f') */ {
return c - 'a' + 0xa;
}
}
consteval ro::ModuleId ParseModuleId(const char *str) {
/* Parse a static module id. */
ro::ModuleId module_id = {};
size_t ofs = 0;
while (str[0] != 0) {
AMS_ASSUME(ofs < sizeof(module_id));
AMS_ASSUME(str[1] != 0);
module_id.build_id[ofs] = (ParseNybble(str[0]) << 4) | (ParseNybble(str[1]) << 0);
str += 2;
ofs++;
}
return module_id;
}
struct EmbeddedPatchEntry {
uintptr_t offset;
const void * const data;
size_t size;
};
struct EmbeddedPatch {
ro::ModuleId module_id;
size_t num_entries;
const EmbeddedPatchEntry *entries;
};
#include "ldr_embedded_usb_patches.inc"
}
/* Apply IPS patches. */
void LocateAndApplyIpsPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size) {
for(int i = 0; i < VERS; i++)
{
if(memcmp(PcvModuleId[i], build_id, sizeof(PcvModuleId[i])) == 0) {
ApplyPcvPatch(reinterpret_cast<u8 *>(mapped_nso), mapped_size, i);
return; // Return here since pcv module loads before sd card can be mounted
}
else if(memcmp(AmModuleId[i], build_id, sizeof(AmModuleId[i])) == 0) {
ApplyCopyrightPatch(reinterpret_cast<u8 *>(mapped_nso), mapped_size, i);
}
}
if (!EnsureSdCardMounted()) {
return;
}
ro::ModuleId module_id;
std::memcpy(&module_id.build_id, build_id, sizeof(module_id.build_id));
ams::patcher::LocateAndApplyIpsPatchesToModule(LoaderSdMountName, NsoPatchesDirectory, NsoPatchesProtectedSize, NsoPatchesProtectedOffset, &module_id, reinterpret_cast<u8 *>(mapped_nso), mapped_size);
}
/* Apply embedded patches. */
void ApplyEmbeddedPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size) {
/* Make module id. */
ro::ModuleId module_id;
std::memcpy(&module_id.build_id, build_id, sizeof(module_id.build_id));
if (IsUsb30ForceEnabled()) {
for (const auto &patch : Usb30ForceEnablePatches) {
if (std::memcmp(std::addressof(patch.module_id), std::addressof(module_id), sizeof(module_id)) == 0) {
for (size_t i = 0; i < patch.num_entries; ++i) {
const auto &entry = patch.entries[i];
if (entry.offset + entry.size <= mapped_size) {
std::memcpy(reinterpret_cast<void *>(mapped_nso + entry.offset), entry.data, entry.size);
}
}
}
}
}
}
}

View File

@@ -1,43 +0,0 @@
--- stratosphere/loader/source/ldr_patcher.cpp @a672917
+++ stratosphere/loader/source/ldr_patcher.cpp
@@ -15,11 +15,22 @@
*/
#include <stratosphere.hpp>
#include "ldr_patcher.hpp"
+#include "ldr_pcv_patch.hpp"
namespace ams::ldr {
namespace {
+ constexpr u8 PcvModuleId[2][20] = {
+ { 0x91, 0xD6, 0x1D, 0x59, 0xD7, 0x00, 0x23, 0x78, 0xE3, 0x55, 0x84, 0xFC, 0x0B, 0x38, 0xC7, 0x69, 0x3A, 0x3A, 0xBA, 0xB5, }, //11.0.0
+ { 0xC5, 0x03, 0xE9, 0x65, 0x50, 0xF3, 0x02, 0xE1, 0x21, 0x87, 0x31, 0x36, 0xB8, 0x14, 0xA5, 0x29, 0x86, 0x3D, 0x94, 0x9B, }, //12.0.0-12.1.0
+ };
+
+ constexpr u8 AmModuleId[2][20] = {
+ { 0x25, 0x50, 0x97, 0xEF, 0x11, 0xC0, 0x75, 0x9B, 0x1F, 0x36, 0x13, 0x2F, 0x73, 0xBD, 0xDB, 0x04, 0xC3, 0xEF, 0x9A, 0xBE, }, //11.0.0
+ { 0x5E, 0x5F, 0x1C, 0xC2, 0x4D, 0x37, 0x45, 0x91, 0xAF, 0xC2, 0xA2, 0x33, 0x6C, 0x94, 0x53, 0xCC, 0xFA, 0x39, 0x61, 0xC1, }, //12.0.0-12.1.0
+ };
+
constexpr const char *NsoPatchesDirectory = "exefs_patches";
/* Exefs patches want to prevent modification of header, */
@@ -113,6 +124,17 @@ namespace ams::ldr {
/* Apply IPS patches. */
void LocateAndApplyIpsPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size) {
+ for(int i = 0; i < 2; i++)
+ {
+ if(memcmp(PcvModuleId[i], build_id, sizeof(PcvModuleId[i])) == 0) {
+ ApplyPcvPatch(reinterpret_cast<u8 *>(mapped_nso), mapped_size, i);
+ return; // Return here since pcv module loads before sd card can be mounted
+ }
+ else if(memcmp(AmModuleId[i], build_id, sizeof(AmModuleId[i])) == 0) {
+ ApplyCopyrightPatch(reinterpret_cast<u8 *>(mapped_nso), mapped_size, i);
+ }
+ }
+
if (!EnsureSdCardMounted()) {
return;
}

View File

@@ -4,14 +4,18 @@
#define EMC_OVERCLOCK 1 #define EMC_OVERCLOCK 1
#define EMC_OVERVOLT 1 #define EMC_OVERVOLT 1
//I'm dropping support for Erista on >= HOS 13.0.0, you may port these offsets by yourself.
//#define ERISTA_SUPPORT
namespace ams::ldr { namespace ams::ldr {
namespace { namespace {
constexpr u32 CopyrightOffset[2] = { 0xC6128, 0xCA414 }; //am_no_copyright port constexpr u32 CopyrightIPSOffset[VERS] = { 0xC6128, 0xCA414, 0xCB90C }; //am_no_copyright port
constexpr u8 BehemothPatch[8] = { 0xE0, 0x03, 0x1F, 0xAA, 0xC0, 0x03, 0x5F, 0xD6 }; //🤔 constexpr u8 RET0[8] = { 0xE0, 0x03, 0x1F, 0xAA, 0xC0, 0x03, 0x5F, 0xD6 };
// MOV X0, XZR
// RET
typedef struct { typedef struct {
u32 hz = 0; u32 hz = 0;
@@ -20,15 +24,17 @@ namespace ams::ldr {
s32 coeffs[6] = {0}; s32 coeffs[6] = {0};
} gpu_clock_table_t; } gpu_clock_table_t;
constexpr u32 EmcFreqOffsets[2][30] = { constexpr u32 EmcFreqOffsets[VERS][30] = {
{ 0xD7C60, 0xD7C68, 0xD7C70, 0xD7C78, 0xD7C80, 0xD7C88, 0xD7C90, 0xD7C98, 0xD7CA0, 0xD7CA8, 0xE1800, 0xEEFA0, 0xF2478, 0xFE284, 0x10A304, 0x10D7DC, 0x110A40, 0x113CA4, 0x116F08, 0x11A16C, 0x11D3D0, 0x120634, 0x123898, 0x126AFC, 0x129D60, 0x12CFC4, 0x130228, 0x13BFE0, 0x140D00, 0x140D50, }, { 0xD7C60, 0xD7C68, 0xD7C70, 0xD7C78, 0xD7C80, 0xD7C88, 0xD7C90, 0xD7C98, 0xD7CA0, 0xD7CA8, 0xE1800, 0xEEFA0, 0xF2478, 0xFE284, 0x10A304, 0x10D7DC, 0x110A40, 0x113CA4, 0x116F08, 0x11A16C, 0x11D3D0, 0x120634, 0x123898, 0x126AFC, 0x129D60, 0x12CFC4, 0x130228, 0x13BFE0, 0x140D00, 0x140D50, },
{ 0xE1810, 0xE6530, 0xE6580, 0xE6AB0, 0xE6AB8, 0xE6AC0, 0xE6AC8, 0xE6AD0, 0xE6AD8, 0xE6AE0, 0xE6AE8, 0xE6AF0, 0xE6AF8, 0xF0650, 0xFDDF0, 0x1012C8, 0x10D0D4, 0x119154, 0x11C62C, 0x11F890, 0x122AF4, 0x125D58, 0x128FBC, 0x12C220, 0x12F484, 0x1326E8, 0x13594C, 0x138BB0, 0x13BE14, 0x13F078, } { 0xE1810, 0xE6530, 0xE6580, 0xE6AB0, 0xE6AB8, 0xE6AC0, 0xE6AC8, 0xE6AD0, 0xE6AD8, 0xE6AE0, 0xE6AE8, 0xE6AF0, 0xE6AF8, 0xF0650, 0xFDDF0, 0x1012C8, 0x10D0D4, 0x119154, 0x11C62C, 0x11F890, 0x122AF4, 0x125D58, 0x128FBC, 0x12C220, 0x12F484, 0x1326E8, 0x13594C, 0x138BB0, 0x13BE14, 0x13F078, },
{ 0xE1860, 0xE6580, 0xE65D0, 0xE6B00, 0xE6B08, 0xE6B10, 0xE6B18, 0xE6B20, 0xE6B28, 0xE6B30, 0xE6B38, 0xE6A40, 0xE6A48, 0xF06A0, 0xFDE40, 0x101318, 0x10D124, 0x1191A4, 0x11C67C, 0x11F8E0, 0x122B44, 0x125DA8, 0x12900C, 0x12C270, 0x12F4D4, 0x132738, 0x13599C, 0x138C00, 0x13BE64, 0x13F0C8, }
}; };
// RAM freqs to choose: 1600000, 1728000, 1795200, 1862400, 1894400, 1932800, 1996800, 2064000, 2099200, 2131200 // RAM freqs to choose: 1600000, 1728000, 1795200, 1862400, 1894400, 1932800, 1996800, 2064000, 2099200, 2131200
constexpr u32 NewEmcFreq = 1862400; constexpr u32 NewEmcFreq = 1862400;
// RAM overclock could be UNSTABLE on some RAM without bumping up voltage, // RAM overclock could be UNSTABLE on some RAM without bumping up voltage,
// and therefore show graphical glitches, hang randomly or even worse, corrupt your NAND // and therefore show graphical glitches, hang randomly or even worse, corrupt your NAND
#ifdef ERISTA_SUPPORT
namespace Erista { namespace Erista {
typedef struct { typedef struct {
@@ -75,6 +81,7 @@ namespace ams::ldr {
// 1150mV for 1862.4 MHz and 1200 mV for 2131.2 MHz, according to the feedback in RetroNX Discord // 1150mV for 1862.4 MHz and 1200 mV for 2131.2 MHz, according to the feedback in RetroNX Discord
// 1125mV(HOS default) for 1731.2 MHz and 1175mV for 1996.8 MHz // 1125mV(HOS default) for 1731.2 MHz and 1175mV for 1996.8 MHz
}; };
#endif
namespace Mariko { namespace Mariko {
@@ -87,20 +94,22 @@ namespace ams::ldr {
} cpu_clock_table_t; } cpu_clock_table_t;
/* CPU */ /* CPU */
constexpr u32 CpuVoltageLimitOffsets[2][11] = { constexpr u32 CpuVoltageLimitOffsets[VERS][11] = {
{ 0xE1A8C, 0xE1A98, 0xE1AA4, 0xE1AB0, 0xE1AF8, 0xE1B04, 0xE1B10, 0xE1B1C, 0xE1B28, 0xE1B34, 0xE1F4C }, { 0xE1A8C, 0xE1A98, 0xE1AA4, 0xE1AB0, 0xE1AF8, 0xE1B04, 0xE1B10, 0xE1B1C, 0xE1B28, 0xE1B34, 0xE1F4C },
{ 0xF08DC, 0xF08E8, 0xF08F4, 0xF0900, 0xF0948, 0xF0954, 0xF0960, 0xF096C, 0xF0978, 0xF0984, 0xF0D9C }, { 0xF08DC, 0xF08E8, 0xF08F4, 0xF0900, 0xF0948, 0xF0954, 0xF0960, 0xF096C, 0xF0978, 0xF0984, 0xF0D9C },
{ 0xF092C, 0xF0938, 0xF0944, 0xF0950, 0xF0998, 0xF09A4, 0xF09B0, 0xF09BC, 0xF09C8, 0xF09D4, 0xF0DEC }
}; };
constexpr u32 NewCpuVoltageLimit = 1220; constexpr u32 NewCpuVoltageLimit = 1220;
static_assert(NewCpuVoltageLimit <= 1300); //1300mV hangs for me static_assert(NewCpuVoltageLimit <= 1300); //1300mV hangs for me
constexpr u32 CpuVoltageCoeffTable[2][10] = { constexpr u32 CpuVoltageCoeffTable[VERS][10] = {
{ 0xE2140, 0xE2178, 0xE21B0, 0xE21E8, 0xE2220, 0xE2258, 0xE2290, 0xE22C8, 0xE2300, 0xE2338 }, { 0xE2140, 0xE2178, 0xE21B0, 0xE21E8, 0xE2220, 0xE2258, 0xE2290, 0xE22C8, 0xE2300, 0xE2338 },
{ 0xF0F90, 0xF0FC8, 0xF1000, 0xF1038, 0xF1070, 0xF10A8, 0xF10E0, 0xF1118, 0xF1150, 0xF1188 }, { 0xF0F90, 0xF0FC8, 0xF1000, 0xF1038, 0xF1070, 0xF10A8, 0xF10E0, 0xF1118, 0xF1150, 0xF1188 },
{ 0xF0FE0, 0xF1018, 0xF1050, 0xF1088, 0xF10C0, 0xF10F8, 0xF1130, 0xF1168, 0xF11A0, 0xF11D8 }
}; };
constexpr u32 NewCpuVoltageCoeff = NewCpuVoltageLimit * 1000; constexpr u32 NewCpuVoltageCoeff = NewCpuVoltageLimit * 1000;
constexpr u32 CpuTablesFreeSpace[2] = { 0xE2350, 0xF11A0 }; constexpr u32 CpuTablesFreeSpace[VERS] = { 0xE2350, 0xF11A0, 0xF11F0 };
constexpr cpu_clock_table_t NewCpuTables[] = { constexpr cpu_clock_table_t NewCpuTables[] = {
{2091000, 0, {1719782, -40440, 27}, NewCpuVoltageCoeff, {}}, {2091000, 0, {1719782, -40440, 27}, NewCpuVoltageCoeff, {}},
{2193000, 0, {1809766, -41939, 27}, NewCpuVoltageCoeff, {}}, {2193000, 0, {1809766, -41939, 27}, NewCpuVoltageCoeff, {}},
@@ -118,11 +127,11 @@ namespace ams::ldr {
}; };
static_assert(sizeof(NewCpuTables) <= sizeof(cpu_clock_table_t)*14); static_assert(sizeof(NewCpuTables) <= sizeof(cpu_clock_table_t)*14);
constexpr u32 MaxCpuClockOffset[2] = { 0xE2740, 0xF1590 }; constexpr u32 MaxCpuClockOffset[VERS] = { 0xE2740, 0xF1590, 0xF15E0 };
constexpr u32 NewMaxCpuClock = 2397000; constexpr u32 NewMaxCpuClock = 2397000;
/* GPU */ /* GPU */
constexpr u32 GpuTablesFreeSpace[2] = { 0xE3410, 0xF2260 }; constexpr u32 GpuTablesFreeSpace[VERS] = { 0xE3410, 0xF2260, 0xF22B0 };
constexpr gpu_clock_table_t NewGpuTables[] = { constexpr gpu_clock_table_t NewGpuTables[] = {
{ 1305600, 0, {}, {1380113, -13465, -874, 0, 2580, 648} }, { 1305600, 0, {}, {1380113, -13465, -874, 0, 2580, 648} },
{ 1344000, 0, {}, {1420000, -14000, -870, 0, 2193, 824} }, { 1344000, 0, {}, {1420000, -14000, -870, 0, 2193, 824} },
@@ -140,8 +149,8 @@ namespace ams::ldr {
}; };
static_assert(sizeof(NewGpuTables) <= sizeof(gpu_clock_table_t)*15); static_assert(sizeof(NewGpuTables) <= sizeof(gpu_clock_table_t)*15);
constexpr u32 Reg1MaxGpuOffset[2] = { 0x2E0AC, 0x3F6CC }; constexpr u32 Reg1MaxGpuOffset[VERS] = { 0x2E0AC, 0x3F6CC, 0x3F12C };
constexpr u8 Reg1NewMaxGpuClock[2][0xC] = { constexpr u8 Reg1NewMaxGpuClock[VERS][0xC] = {
// Original: 1267MHz // Original: 1267MHz
/* /*
MOV W13,#0x5600 MOV W13,#0x5600
@@ -157,10 +166,11 @@ namespace ams::ldr {
//0x0D, 0xC0, 0x8A, 0x52, 0x6D, 0x02, 0xA0, 0x72, 0x1F, 0x20, 0x03, 0xD5 //0x0D, 0xC0, 0x8A, 0x52, 0x6D, 0x02, 0xA0, 0x72, 0x1F, 0x20, 0x03, 0xD5
{ 0x0D, 0x00, 0x8E, 0x52, 0xED, 0x02, 0xA0, 0x72, 0x1F, 0x20, 0x03, 0xD5 }, { 0x0D, 0x00, 0x8E, 0x52, 0xED, 0x02, 0xA0, 0x72, 0x1F, 0x20, 0x03, 0xD5 },
{ 0x0B, 0x00, 0x8E, 0x52, 0xEB, 0x02, 0xA0, 0x72, 0x1F, 0x20, 0x03, 0xD5 }, { 0x0B, 0x00, 0x8E, 0x52, 0xEB, 0x02, 0xA0, 0x72, 0x1F, 0x20, 0x03, 0xD5 },
{ 0x0B, 0x00, 0x8E, 0x52, 0xEB, 0x02, 0xA0, 0x72, 0x1F, 0x20, 0x03, 0xD5 },
}; };
constexpr u32 Reg2MaxGpuOffset[2] = { 0x2E110, 0x3F730 }; constexpr u32 Reg2MaxGpuOffset[VERS] = { 0x2E110, 0x3F730, 0x3F190 };
constexpr u8 Reg2NewMaxGpuClock[2][0x8] = { constexpr u8 Reg2NewMaxGpuClock[VERS][0x8] = {
// Original: 1267MHz // Original: 1267MHz
/* /*
MOV W13,#0x5600 MOV W13,#0x5600
@@ -174,6 +184,7 @@ namespace ams::ldr {
//0x0D, 0xC0, 0x8A, 0x52, 0x6D, 0x02, 0xA0, 0x72 //0x0D, 0xC0, 0x8A, 0x52, 0x6D, 0x02, 0xA0, 0x72
{ 0x0D, 0x00, 0x8E, 0x52, 0xED, 0x02, 0xA0, 0x72, }, { 0x0D, 0x00, 0x8E, 0x52, 0xED, 0x02, 0xA0, 0x72, },
{ 0x0B, 0x00, 0x8E, 0x52, 0xEB, 0x02, 0xA0, 0x72, }, { 0x0B, 0x00, 0x8E, 0x52, 0xEB, 0x02, 0xA0, 0x72, },
{ 0x0B, 0x00, 0x8E, 0x52, 0xEB, 0x02, 0xA0, 0x72, },
}; };
/* EMC */ /* EMC */
@@ -196,6 +207,7 @@ namespace ams::ldr {
void ApplyPcvPatch(u8 *mapped_module, size_t mapped_size, int i) { void ApplyPcvPatch(u8 *mapped_module, size_t mapped_size, int i) {
#ifdef ERISTA_SUPPORT
/* Add new CPU and GPU clock tables for Erista */ /* Add new CPU and GPU clock tables for Erista */
AMS_ABORT_UNLESS(Erista::CpuTablesFreeSpace[i] <= mapped_size && Erista::GpuTablesFreeSpace[i] <= mapped_size); AMS_ABORT_UNLESS(Erista::CpuTablesFreeSpace[i] <= mapped_size && Erista::GpuTablesFreeSpace[i] <= mapped_size);
std::memcpy(mapped_module + Erista::CpuTablesFreeSpace[i], Erista::NewCpuTables, sizeof(Erista::NewCpuTables)); std::memcpy(mapped_module + Erista::CpuTablesFreeSpace[i], Erista::NewCpuTables, sizeof(Erista::NewCpuTables));
@@ -205,6 +217,7 @@ namespace ams::ldr {
for(int j = 0; j < 3; j++) { for(int j = 0; j < 3; j++) {
std::memcpy(mapped_module + Erista::CpuVoltageLimitOffsets[i][j], &Erista::NewCpuVoltageLimit, sizeof(Erista::NewCpuVoltageLimit)); std::memcpy(mapped_module + Erista::CpuVoltageLimitOffsets[i][j], &Erista::NewCpuVoltageLimit, sizeof(Erista::NewCpuVoltageLimit));
} }
#endif
/* Add new CPU and GPU clock tables for Mariko */ /* Add new CPU and GPU clock tables for Mariko */
AMS_ABORT_UNLESS(Mariko::CpuTablesFreeSpace[i] <= mapped_size && Mariko::GpuTablesFreeSpace[i] <= mapped_size); AMS_ABORT_UNLESS(Mariko::CpuTablesFreeSpace[i] <= mapped_size && Mariko::GpuTablesFreeSpace[i] <= mapped_size);
@@ -235,12 +248,14 @@ namespace ams::ldr {
} }
if constexpr(EMC_OVERVOLT) { if constexpr(EMC_OVERVOLT) {
#ifdef ERISTA_SUPPORT
if(spl::GetSocType() == spl::SocType_Erista) { if(spl::GetSocType() == spl::SocType_Erista) {
for(u32 j = 0; j < sizeof(Erista::EmcVolatageOffsets[i])/sizeof(u32); j++) { for(u32 j = 0; j < sizeof(Erista::EmcVolatageOffsets[i])/sizeof(u32); j++) {
AMS_ABORT_UNLESS(Erista::EmcVolatageOffsets[i][j] <= mapped_size); AMS_ABORT_UNLESS(Erista::EmcVolatageOffsets[i][j] <= mapped_size);
std::memcpy(mapped_module + Erista::EmcVolatageOffsets[i][j], &Erista::NewEmcVoltage, sizeof(Erista::NewEmcVoltage)); std::memcpy(mapped_module + Erista::EmcVolatageOffsets[i][j], &Erista::NewEmcVoltage, sizeof(Erista::NewEmcVoltage));
} }
} }
#endif
// Not available on Mariko // Not available on Mariko
/*else if(spl::GetSocType() == spl::SocType_Mariko) { /*else if(spl::GetSocType() == spl::SocType_Mariko) {
for(u32 j = 0; j < sizeof(Mariko::EmcVolatageOffsets[i])/sizeof(u32); j++) { for(u32 j = 0; j < sizeof(Mariko::EmcVolatageOffsets[i])/sizeof(u32); j++) {
@@ -254,8 +269,8 @@ namespace ams::ldr {
} }
void ApplyCopyrightPatch(u8 *mapped_module, size_t mapped_size, int i) { void ApplyCopyrightPatch(u8 *mapped_module, size_t mapped_size, int i) {
AMS_ABORT_UNLESS(CopyrightOffset[i] - 0x100 <= mapped_size); AMS_ABORT_UNLESS(CopyrightIPSOffset[i] - 0x100 <= mapped_size);
std::memcpy(mapped_module + CopyrightOffset[i] - 0x100, BehemothPatch, sizeof(BehemothPatch)); std::memcpy(mapped_module + CopyrightIPSOffset[i] - 0x100, RET0, sizeof(RET0));
} }
} }

View File

@@ -3,8 +3,22 @@
#pragma once #pragma once
#include <stratosphere.hpp> #include <stratosphere.hpp>
#define VERS 3
namespace ams::ldr { namespace ams::ldr {
constexpr u8 PcvModuleId[VERS][20] = {
{ 0x91, 0xD6, 0x1D, 0x59, 0xD7, 0x00, 0x23, 0x78, 0xE3, 0x55, 0x84, 0xFC, 0x0B, 0x38, 0xC7, 0x69, 0x3A, 0x3A, 0xBA, 0xB5, }, //11.0.0
{ 0xC5, 0x03, 0xE9, 0x65, 0x50, 0xF3, 0x02, 0xE1, 0x21, 0x87, 0x31, 0x36, 0xB8, 0x14, 0xA5, 0x29, 0x86, 0x3D, 0x94, 0x9B, }, //12.0.0-12.1.0
{ 0x20, 0x58, 0xC9, 0x7C, 0x55, 0x15, 0x71, 0x50, 0x66, 0x56, 0xAA, 0x04, 0xEC, 0x85, 0xE2, 0xB1, 0xB0, 0x1B, 0x15, 0x5C, }, //13.0.0
};
constexpr u8 AmModuleId[VERS][20] = {
{ 0x25, 0x50, 0x97, 0xEF, 0x11, 0xC0, 0x75, 0x9B, 0x1F, 0x36, 0x13, 0x2F, 0x73, 0xBD, 0xDB, 0x04, 0xC3, 0xEF, 0x9A, 0xBE, }, //11.0.0
{ 0x5E, 0x5F, 0x1C, 0xC2, 0x4D, 0x37, 0x45, 0x91, 0xAF, 0xC2, 0xA2, 0x33, 0x6C, 0x94, 0x53, 0xCC, 0xFA, 0x39, 0x61, 0xC1, }, //12.0.0-12.1.0
{ 0x2C, 0x1A, 0xD2, 0x24, 0x32, 0x8D, 0x2A, 0xF8, 0xB2, 0xC1, 0xA2, 0x40, 0xD0, 0x17, 0x5A, 0x10, 0x89, 0x16, 0xAC, 0x8C, }, //13.0.0
};
void ApplyPcvPatch(u8 *mapped_module, size_t mapped_size, int i); void ApplyPcvPatch(u8 *mapped_module, size_t mapped_size, int i);
void ApplyCopyrightPatch(u8 *mapped_module, size_t mapped_size, int i); void ApplyCopyrightPatch(u8 *mapped_module, size_t mapped_size, int i);

View File

@@ -0,0 +1,166 @@
@nsobid-2CA78D4066C1C11317CC2705EBADA9A51D3AC981
@flag offset_shift 0x100
// PTM PerformanceConfiguration Patch for 13.0.0
// Change all RAM freqs to 1862.4 MHz and Boost CPU freqs to 1963.5 MHz by default
// RAM
// 1600.0 MHz - 00105E5F
// 1728.0 MHz - 0030FF66
// 1795.2 MHz - 0094006B
// 1862.4 MHz - 00F8016F
// 1894.4 MHz - 0040EA70
// 1932.8 MHz - 00303473
// 1996.8 MHz - 00C00477
// 2064.0 MHz - 0024067B
// 2099.2 MHz - 00401F7D
// 2131.2 MHz - 0088077F
// CPU
// 1963.5 MHz - E0A10875
// 2295.0 MHz - C0EBCA88
// All values are Little-Endian
// See https://switchbrew.org/wiki/PTM_services#PerformanceConfiguration for details
// Use IPSwitch(https://github.com/3096/ipswitch/) to convert into ips patch
//0x00010000: 1020, 384.0, 1600.0
@enabled
000A031C 00F7CB3C
000A0320 00F7CB3C
000A0324 0060E316
000A0328 0060E316
000A032C 00F8016F
000A0330 00F8016F
//0x00010001: 1020, 768.0, 1600.0
@enabled
000A033C 00F7CB3C
000A0340 00F7CB3C
000A0344 00C0C62D
000A0348 00C0C62D
000A034C 00F8016F
000A0350 00F8016F
//0x00010002: 1224, 691.0, 1600.0
@enabled
000A035C 00C2F448
000A0360 00C2F448
000A0364 00E03229
000A0368 00E03229
000A036C 00F8016F
000A0370 00F8016F
//0x00020000: 1020, 230.4, 1600.0
@enabled
000A037C 00F7CB3C
000A0380 00F7CB3C
000A0384 00A0BB0D
000A0388 00A0BB0D
000A038C 00F8016F
000A0390 00F8016F
//0x00020001: 1020, 307.2, 1600.0
@enabled
000A039C 00F7CB3C
000A03A0 00F7CB3C
000A03A4 00804F12
000A03A8 00804F12
000A03AC 00F8016F
000A03B0 00F8016F
//0x00020002: 1224, 230.4, 1600.0
@enabled
000A03BC 00C2F448
000A03C0 00C2F448
000A03C4 00A0BB0D
000A03C8 00A0BB0D
000A03CC 00F8016F
000A03D0 00F8016F
//0x00020003: 1020, 307.2, 1331.2
@enabled
000A03DC 00F7CB3C
000A03E0 00F7CB3C
000A03E4 00804F12
000A03E8 00804F12
000A03EC 00F8016F
000A03F0 00F8016F
//0x00020004: 1020, 384.0, 1331.2
@enabled
000A03FC 00F7CB3C
000A0400 00F7CB3C
000A0404 0060E316
000A0408 0060E316
000A040C 00F8016F
000A0410 00F8016F
//0x00020005: 1020, 307.0, 1065.6
@enabled
000A041C 00F7CB3C
000A0420 00F7CB3C
000A0424 00804F12
000A0428 00804F12
000A042C 00F8016F
000A0430 00F8016F
//0x00020006: 1020, 384.0, 1065.6
@enabled
000A043C 00F7CB3C
000A0440 00F7CB3C
000A0444 0060E316
000A0448 0060E316
000A044C 00F8016F
000A0450 00F8016F
//0x92220007: 1020, 460.0, 1600.0
@enabled
000A045C 00F7CB3C
000A0460 00F7CB3C
000A0464 0040771B
000A0468 0040771B
000A046C 00F8016F
000A0470 00F8016F
//0x92220008: 1020, 460.0, 1331.2
@enabled
000A047C 00F7CB3C
000A0480 00F7CB3C
000A0484 0040771B
000A0488 0040771B
000A048C 00F8016F
000A0490 00F8016F
//0x92220009: 1785, 76.8, 1600.0
@enabled
000A049C E0A10875
000A04A0 E0A10875
000A04A4 00E09304
000A04A8 00E09304
000A04AC 00F8016F
000A04B0 00F8016F
//0x9222000A: 1785, 76.8, 1331.2
@enabled
000A04BC E0A10875
000A04C0 E0A10875
000A04C4 00E09304
000A04C8 00E09304
000A04CC 00F8016F
000A04D0 00F8016F
//0x9222000B: 1020, 76.8, 1600.0
@enabled
000A04DC 00F7CB3C
000A04E0 00F7CB3C
000A04E4 00E09304
000A04E8 00E09304
000A04EC 00F8016F
000A04F0 00F8016F
//0x9222000C: 1020, 76.8, 1331.2
@enabled
000A04FC 00F7CB3C
000A0500 00F7CB3C
000A0504 00E09304
000A0508 00E09304
000A050C 00F8016F
000A0510 00F8016F