47 Commits
0.34 ... 0.37

Author SHA1 Message Date
Lightos1
aa72176196 Remove budget dvfs 2026-02-12 17:15:26 +01:00
Lightos1
7af0721847 DVFS: Safety check fix 2026-02-12 17:02:52 +01:00
Lightos1
2a6320e646 Bracket fix 2026-02-12 16:49:12 +01:00
Lightos1
fc212bb419 Bump version 2026-02-12 16:46:49 +01:00
Lightos1
14e0053335 DVFS: Add offset 2026-02-12 16:44:04 +01:00
Lightos1
8f28daceef DVFS: Add safety check 2026-02-12 16:12:36 +01:00
souldbminersmwc
f1044673d0 sysclk: modify dvfs logic 2026-02-11 19:28:43 -05:00
souldbminersmwc
61a0ebffee sysclk: fully fix dvfs 2026-02-11 19:22:25 -05:00
souldbminersmwc
8de8f4013e sysclk: fix dvfs config option 2026-02-11 19:11:02 -05:00
souldbminersmwc
dd447553d4 sysclk: make dvfs work 2026-02-11 19:09:55 -05:00
Lightos1
11c456e00c Fix random } 2026-02-11 17:42:10 +01:00
Lightos1
5efb4bdd6b Add hijack dvfs from sys-clk-eos 2026-02-11 16:57:26 +01:00
Lightos1
e331f1249b Why did this not commit? 2026-02-11 11:08:29 +01:00
Lightos1
786467d7ea add r2w fine tuning 2026-02-11 11:05:45 +01:00
Lightos1
496e77301b bump version 2026-02-11 01:06:52 +01:00
Lightos1
d657f1d156 Fix typo 2 2026-02-10 15:33:47 +01:00
Lightos1
7ab5c2f540 Fix typo 2026-02-10 15:33:03 +01:00
Lightos1
71900721cf Make AUTO_RAM default (for now) 2026-02-10 15:26:12 +01:00
Lightos1
0bc9547701 Add advanced header 2026-02-10 15:12:17 +01:00
Lightos1
96ac254022 Add w2r fine tune 2026-02-10 15:04:28 +01:00
Souldbminer
92f378a80f fix svfs again 2026-02-09 18:59:09 -05:00
Lightos1
589af01ad8 Budget dvfs fix 2026-02-10 00:39:22 +01:00
Lightos1
e7f14b88e5 Replace floor with ceil 2026-02-09 16:29:05 +01:00
souldbminersmwc
35a269e4a7 Update README.md 2026-02-08 15:51:46 -05:00
souldbminersmwc
ff95ca527f Merge branch 'develop' of https://github.com/Horizon-OC/Horizon-OC into develop 2026-02-08 15:33:53 -05:00
souldbminersmwc
550e4e5204 Delete HOC_AUTO_RAM_TEST.zip 2026-02-08 15:33:39 -05:00
Lightos1
a088c4795a Update readme 2026-02-08 18:52:23 +01:00
Lightos1
e8a264fa11 New timings, fix budget gpu dvfs 2026-02-08 18:46:10 +01:00
souldbminersmwc
de681c20a0 ldr: code cleanup 2026-02-08 12:00:27 -05:00
souldbminersmwc
22aef264ab Update pcv_mariko.cpp 2026-02-08 11:57:54 -05:00
souldbminersmwc
309717c468 ldr: fix auto_ram vmin 2026-02-08 11:57:43 -05:00
souldbminersmwc
9b91d7487c ldr: rename namespace 2026-02-08 11:56:04 -05:00
souldbminersmwc
c0b458243c ldr: add auto ram vmin 2026-02-08 11:54:21 -05:00
souldbminersmwc
7d9c60cdfe Merge branch 'develop' of https://github.com/Horizon-OC/Horizon-OC into develop 2026-02-07 19:20:33 -05:00
souldbminersmwc
12c9effec2 Update README.md 2026-02-07 19:20:31 -05:00
Souldbminer
6eeab63075 Rearrange CPU clock entries in README
Reordered CPU clock entries for clarity.
2026-02-07 18:53:41 -05:00
Souldbminer
2d81c5e127 Merge pull request #34 from OEMunlag/develop
Remove dist.zip hash on actions
2026-02-07 18:51:12 -05:00
souldbminersmwc
b1739cea74 sysclk: rework clock capping 2026-02-07 18:38:37 -05:00
souldbminersmwc
aa607ab1a7 sysclk: safety display changes 2026-02-07 18:28:49 -05:00
souldbminersmwc
d1242a17d4 sysclk: 2133MHz is a JEDEC clock 2026-02-07 18:23:49 -05:00
2fort sink
80701c2891 Merge branch 'Horizon-OC:develop' into develop 2026-02-07 20:18:15 -03:00
souldbminersmwc
cfd0d84ac8 update dist 2026-02-07 18:10:21 -05:00
souldbminersmwc
c33aabdc84 chore: code cleanup 2026-02-07 18:10:12 -05:00
2fort sink
c70fd82e60 Modify build.yml to set commit SHA and dist
Updated the GitHub Actions workflow to include a distribution file with the commit SHA.
2026-02-07 20:07:56 -03:00
2fort sink
574c248d68 Merge branch 'Horizon-OC:develop' into develop 2026-02-07 19:55:21 -03:00
2fort sink
0ae65c8740 Merge branch 'Horizon-OC:develop' into develop 2026-02-04 18:07:27 -03:00
2fort sink
39fbe25afc Update build.yml 2026-02-04 18:07:16 -03:00
40 changed files with 790 additions and 403 deletions

View File

@@ -10,7 +10,7 @@ jobs:
build:
runs-on: ubuntu-latest
# Minimal devkitA64 container, apparently dkp-toolchain isn't needed?
# Minimal devkitA64 container
container:
image: devkitpro/devkita64:20251231
@@ -47,9 +47,12 @@ jobs:
# -------------------------------------------------
# Get short commit SHA
# -------------------------------------------------
- name: Set commit SHA
- name: Set commit SHA & dist
id: vars
run: echo "SHORT_SHA=$(echo $GITHUB_SHA | cut -c1-7)" >> $GITHUB_ENV
run: |
echo "SHORT_SHA=$(echo $GITHUB_SHA | cut -c1-7)" >> $GITHUB_ENV
echo $SHORT_SHA > dist/.commit
echo $GITHUB_SHA >> dist/.commit
- name: Clone Atmosphere
run: git clone --depth=1 --single-branch https://github.com/Atmosphere-NX/Atmosphere.git atmosphere -b $(cat ams_ver.txt)
@@ -149,23 +152,12 @@ jobs:
- name: ccache stats
run: ccache --show-stats
# -------------------------------------------------
# Package dist folder as ZIP with commit SHA
# -------------------------------------------------
- name: Package dist
# working-directory: horizon-oc
run: |
ZIP_NAME="horizon-oc-zeus-dist-${SHORT_SHA}.zip"
zip -r "$ZIP_NAME" dist
echo "ZIP_NAME=$ZIP_NAME" >> $GITHUB_ENV
# -------------------------------------------------
# Upload ZIP artifact
# -------------------------------------------------
- name: Upload build artifact
uses: actions/upload-artifact@v6
with:
name: horizon-oc-zeus-dist-${{ env.SHORT_SHA }}
name: horizon-oc-zeus-dist
path: dist/
compression-level: 3

View File

@@ -41,10 +41,8 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to
* Built-in configurator
* Compatible with most homebrew
> *Higher (potentially dangerous) frequencies are unlockable via configuration.*
> *Erista and Mariko units can usually push a bit further fully safely with a bit of undervolting, however this may not work on all units.*
> *The exact maximum overclock possible varies per console, although most consoles should be able to do this safely.*
> *You may refer to the Clock Table to see clocks in more detail*
> It is reccomended to read the [guide](https://rentry.co/howtoget60fps) before proceeding, as this can help you get a *significant* performance boost over the default settings, often times with less power draw and heat output
---
## Installation
@@ -91,15 +89,15 @@ Refer to COMPILATION.md
* 1866 → mariko safe max (3733 Modules), JEDEC.
* 1600 → official docked, boost mode, erista safe max, JEDEC.
* 1331 → official handheld, JEDEC.
* 1065
* 1065
* 800
* 665
### CPU clocks
* 2601 → mariko absolute max, very dangerous
* 2499
* 2397
* 2295 → mariko safe max with UV (low speedo)
* 2397 → mariko safe max with UV (low speedo)
* 2295
* 2193
* 2091
* 1963 → mariko no UV max clock
@@ -153,6 +151,7 @@ Refer to COMPILATION.md
* **Souldbminer** hoc-clk and loader development
* **Lightos** loader patches development
* **SciresM** - Atmosphere CFW
* **CTCaer** - L4T, Hekate, perfect ram timings
* **KazushiMe** Switch OC Suite
* **hanai3bi (meha)** Switch OC Suite, EOS, sys-clk-eos
* **NaGaa95** L4T-OC-kernel

View File

@@ -694,11 +694,11 @@ namespace ams::ldr {
/* Apply PCV and PTM patches */
if (g_is_pcv) {
oc::pcv::Patch(map_address, nso_size);
hoc::pcv::Patch(map_address, nso_size);
}
if (g_is_ptm) {
oc::ptm::Patch(map_address, nso_size);
hoc::ptm::Patch(map_address, nso_size);
}
}

View File

@@ -28,17 +28,17 @@
#define GPU_MIN_MIN_VOLT 480000
#define CPU_MAX_MAX_VOLT 1235000
namespace ams::ldr::oc {
namespace ams::ldr::hoc {
volatile CustomizeTable C = {
/* Disables RAM powerdown */
.hpMode = DISABLED,
.commonEmcMemVolt = 1175000, // LPDDR4X JEDEC Specification
.eristaEmcMaxClock = 1600000, // Maximum HB-MGCH ram rating
.commonEmcMemVolt = 1175000, /* LPDDR4X JEDEC Specification */
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
.marikoEmcMaxClock = 1866000, // 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units
.marikoEmcVddqVolt = 600000,
.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
.marikoEmcVddqVolt = 600000, /* Micron: 600mV, other manafacturers: 640mV */
.emcDvbShift = 0,
// Primary
@@ -52,9 +52,7 @@ volatile CustomizeTable C = {
.t7_tWTR = 0,
.t8_tREFI = 0,
/* Set to 4 read and 2 write for 1866b tWRL. */
/* For 2133 tWRL: 8 read and 4 write. */
/* You can mix and match different latencies if needed */
/*
* Read:
* 2133RL = 40
@@ -67,8 +65,9 @@ volatile CustomizeTable C = {
* 1600WL = 14
* 1331WL = 12
*/
.mem_burst_read_latency = 36,
.mem_burst_write_latency = 16,
.mem_burst_read_latency = RL_1866,
.mem_burst_write_latency = WL_1866,
.eristaCpuUV = 0,
.eristaCpuVmin = 800,
@@ -78,9 +77,11 @@ volatile CustomizeTable C = {
.marikoCpuUVLow = 0, // No undervolt
.marikoCpuUVHigh = 0, // No undervolt
.tableConf = DEFAULT_TABLE,
.marikoCpuLowVmin = 620,
.marikoCpuHighVmin = 750,
/* 1120mV is NVIDIA rating */
.marikoCpuMaxVolt = 1120,
/* Supported values: 1963000, 2091000, 2193000, 2295000, 2397000, 2499000, 2601000, 2703000. */
@@ -99,19 +100,22 @@ volatile CustomizeTable C = {
.eristaGpuVmin = 810,
.marikoGpuUV = 0,
/* For automatic vmin detection, set this to AUTO. */
/* vmin past 795mV won't work due to HOS limitation */
/* Vmin is automatically set to 800mV when SoC temperature is below 20C */
.marikoGpuVmin = AUTO,
.marikoGpuVmax = 800,
.commonGpuVoltOffset = 0,
/* Speedo is automatically set by hoc-clk on first boot */
.gpuSpeedo = 1450,
/* This table is used with a gpu uv mode of 2. */
/* Setting DEACTIVATED_GPU_FREQ on any freq will disable it and all freqs greater than it. (the latter is a bug :/) */
/* AUTO: Voltage is optimally chosen; with commonGpuVoltOffset applied. */
/* AUTO only works up to 1305 GPU on Mariko and 921 GPU on Erista */
/* AUTO only works up to 1305 GPU on Mariko and 998 GPU on Erista (it is reccomended to manually set your 998MHz voltage though) */
/* You can overwrite auto with any voltage (in mv) of your choice - offset will not be applied. */
.eristaGpuVoltArray = {
@@ -159,8 +163,8 @@ volatile CustomizeTable C = {
AUTO /* 921 */,
AUTO /* 998 */,
AUTO /* 1075 */,
DEACTIVATED_GPU_FREQ /* 1152 */,
DEACTIVATED_GPU_FREQ /* 1228 */,
AUTO /* 1152 (SLT / HiOPT Only!) */,
AUTO /* 1228 (HiOPT Only!) */,
DEACTIVATED_GPU_FREQ /* 1267 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1305 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1344 (Disabled by default) */,
@@ -171,6 +175,10 @@ volatile CustomizeTable C = {
DEACTIVATED_GPU_FREQ /* 1536 (Disabled by default) */,
},
/* Advanced. */
.fineTune_t6_tRTW = 0,
.fineTune_t7_tWTR = 0,
/* You shouldn't have to anything past here. */
.eristaCpuDvfsTable = {
{ 204000, { 721094, }, { } },

View File

@@ -20,20 +20,15 @@
#pragma once
#define CUST_REV 11
#define CUST_REV 1
#include "oc_common.hpp"
#include "pcv/pcv_common.hpp"
namespace ams::ldr::oc {
namespace ams::ldr::hoc {
#include "mtc_timing_table.hpp"
enum MtcConfig: u32 {
AUTO_ADJ = 0,
AUTO_ADJ_BL = 1,
};
enum TableConfig: u32 {
DEFAULT_TABLE = 1,
TBREAK_1581 = 2,
@@ -41,6 +36,33 @@ enum TableConfig: u32 {
EXTREME_TABLE = 4,
};
/*
* Read:
* 2133RL = 40
* 1866RL = 36
* 1600RL = 32
* 1331RL = 28
* Write:
* 2133WL = 18
* 1866WL = 16
* 1600WL = 14
* 1331WL = 12
*/
enum ReadLatency: u32 {
RL_2133 = 40,
RL_1866 = 36,
RL_1600 = 32,
RL_1331 = 28,
};
enum WriteLatency: u32 {
WL_2133 = 18,
WL_1866 = 16,
WL_1600 = 14,
WL_1331 = 12,
};
using CustomizeCpuDvfsTable = pcv::cvb_entry_t[pcv::DvfsTableEntryLimit];
using CustomizeGpuDvfsTable = pcv::cvb_entry_t[pcv::DvfsTableEntryLimit];
static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(CustomizeGpuDvfsTable));
@@ -53,7 +75,7 @@ typedef struct CustomizeTable {
u8 cust[4] = {'C', 'U', 'S', 'T'};
u32 custRev = CUST_REV;
u32 mtcConf;
u32 placeholder;
u32 hpMode;
u32 commonEmcMemVolt;
@@ -99,12 +121,16 @@ typedef struct CustomizeTable {
u32 commonGpuVoltOffset;
/* TODO: Automatically detect speedo. */
u32 gpuSpeedo;
u32 eristaGpuVoltArray[27];
u32 marikoGpuVoltArray[24];
u32 reserved[64];
u32 fineTune_t6_tRTW;
u32 fineTune_t7_tWTR;
u32 reserved[60];
CustomizeCpuDvfsTable eristaCpuDvfsTable;
CustomizeCpuDvfsTable eristaCpuDvfsTableSLT;

View File

@@ -18,49 +18,16 @@
#include "../mtc_timing_value.hpp"
#include "timing_tables.hpp"
namespace ams::ldr::oc::pcv::mariko {
namespace ams::ldr::hoc::pcv::mariko {
u32 GetRext() {
void GetRext() {
if (auto r = FindRext()) {
return r->correct;
rext = r->rext;
return;
}
return 0x1A;
}
void CalculateTWTPDEN() {
tWTPDEN = tW2P + 1 + CEIL(tDQSS_max / tCK_avg) + CEIL(tDQS2DQ_max / tCK_avg) + 6;
if (C.marikoEmcMaxClock >= 2'233'000 && C.marikoEmcMaxClock < 2'533'000) tWTPDEN++;
if (C.marikoEmcMaxClock >= 2'433'000 && C.marikoEmcMaxClock < 2'800'000) tWTPDEN--;
}
void CalculateTR2W() {
tR2W = CEIL(RL_DBI + (tDQSCK_max / tCK_avg) + (BL / 2) - WL + tWPRE + FLOOR(tRPST) + 9.0) - (C.t6_tRTW * 3);
if (auto patch = FindTR2WPatch()) {
tR2W += patch->adjust;
}
}
void CalculatePdex2rw() {
double freq_mhz = C.marikoEmcMaxClock / 1000.0;
double pdex_local = (0.011 * freq_mhz) - 1.443;
pdex2rw = static_cast<u32>(ROUND(pdex_local));
if (pdex2rw < 22) pdex2rw = 22;
if (pdex2rw > 33) pdex2rw = 33;
if (auto patch = FindPdex2rwPatch()) {
pdex2rw += patch->adjust;
}
}
void CalculateCke2pden() {
cke2pden = (static_cast<double>((C.marikoEmcMaxClock / 1000.0) * 0.00875) - 0.65);
if (auto patch = FindCke2pdenPatch()) {
cke2pden += patch->adjust;
}
/* Fallback. */
rext = 0x1A;
}
void CalculateMrw2() {
@@ -93,11 +60,7 @@ namespace ams::ldr::oc::pcv::mariko {
}
void CalculateTimings() {
rext = GetRext();
CalculateTWTPDEN();
CalculateTR2W();
CalculatePdex2rw();
CalculateCke2pden();
GetRext();
CalculateMrw2();
}

View File

@@ -16,7 +16,7 @@
#pragma once
namespace ams::ldr::oc::pcv::mariko {
namespace ams::ldr::hoc::pcv::mariko {
void CalculateTimings();

View File

@@ -17,7 +17,7 @@
#include "../mtc_timing_value.hpp"
#include "timing_tables.hpp"
namespace ams::ldr::oc::pcv::mariko {
namespace ams::ldr::hoc::pcv::mariko {
const ReplacePatch g_rext_table[] = {
{2'133'000, 0x1A}, {2'166'000, 0x19}, {2'200'000, 0x19},
@@ -36,78 +36,11 @@ namespace ams::ldr::oc::pcv::mariko {
const u32 g_rext_table_size = sizeof(g_rext_table) / sizeof(g_rext_table[0]);
const ReplacePatch *FindRext() {
for (u32 i = 0; i < g_rext_table_size; i++)
if (g_rext_table[i].freq == C.marikoEmcMaxClock)
for (u32 i = 0; i < g_rext_table_size; i++) {
if (g_rext_table[i].freq >= C.marikoEmcMaxClock) {
return &g_rext_table[i];
return nullptr;
}
const AdjustPatch g_tr2w_patches[] = {
{2'500'000, 1},
{2'533'000, 1},
{2'566'000, 1},
{2'866'000, -1},
{3'100'000, 1},
{3'133'000, 1},
};
const u32 g_tr2w_table_size = sizeof(g_tr2w_patches) / sizeof(g_tr2w_patches[0]);
const AdjustPatch *FindTR2WPatch() {
for (u32 i = 0; i < g_tr2w_table_size; i++)
if (g_tr2w_patches[i].freq == C.marikoEmcMaxClock)
return &g_tr2w_patches[i];
return nullptr;
}
const AdjustPatch g_pdex2rw_patches[] = {
{2'166'000, 1},
{2'300'000, 1},
{2'333'000, 1},
{2'433'000, 1},
{2'533'000, 0},
{2'633'000, -1},
{2'666'000, -1},
{2'733'000, -1},
{2'766'000, -1},
{2'800'000, -1},
{2'833'000, -1},
{2'933'000, -1},
{3'066'000, 1},
};
const u32 g_pdex2rw_table_size = sizeof(g_pdex2rw_patches) / sizeof(g_pdex2rw_patches[0]);
const AdjustPatch *FindPdex2rwPatch() {
for (u32 i = 0; i < g_pdex2rw_table_size; i++)
if (g_pdex2rw_patches[i].freq == C.marikoEmcMaxClock)
return &g_pdex2rw_patches[i];
return nullptr;
}
const AdjustPatch g_cke2pden_patches[] = {
{2'133'000, 1},
{2'166'000, 1},
{2'266'000, 1},
{2'300'000, 1},
{2'366'000, 1},
{2'400'000, 1},
{2'500'000, 1},
{2'633'000, 1},
{2'733'000, 1},
{2'833'000, 1},
{2'866'000, 1},
{2'966'000, 1},
{3'066'000, 1},
{3'100'000, 1},
};
const u32 g_cke2pden_table_size = sizeof(g_cke2pden_patches) / sizeof(g_cke2pden_patches[0]);
const AdjustPatch *FindCke2pdenPatch() {
for (u32 i = 0; i < g_cke2pden_table_size; i++)
if (g_cke2pden_patches[i].freq == C.marikoEmcMaxClock)
return &g_cke2pden_patches[i];
}
}
return nullptr;
}

View File

@@ -17,32 +17,15 @@
#pragma once
#include "../mtc_timing_value.hpp"
namespace ams::ldr::oc::pcv::mariko {
namespace ams::ldr::hoc::pcv::mariko {
struct ReplacePatch {
u32 freq;
u32 correct;
u32 rext;
};
extern const ReplacePatch g_rext_table[];
extern const u32 g_rext_table_size;
const ReplacePatch *FindRext();
struct AdjustPatch {
u32 freq;
s32 adjust;
};
extern const AdjustPatch g_tr2w_patches[];
extern const u32 g_tr2w_table_size;
const AdjustPatch *FindTR2WPatch();
extern const AdjustPatch g_pdex2rw_patches[];
extern const u32 g_pdex2rw_table_size;
const AdjustPatch *FindPdex2rwPatch();
extern const AdjustPatch g_cke2pden_patches[];
extern const u32 g_cke2pden_table_size;
const AdjustPatch *FindCke2pdenPatch();
}

View File

@@ -20,20 +20,20 @@
#include "oc_common.hpp"
namespace ams::ldr::oc {
#define MAX(A, B) std::max(A, B)
#define MIN(A, B) std::min(A, B)
#define CEIL(A) std::ceil(A)
#define FLOOR(A) std::floor(A)
#define ROUND(A) std::lround(A)
namespace ams::ldr::hoc {
#define MAX(A, B) std::max(A, B)
#define MIN(A, B) std::min(A, B)
#define CEIL(A) std::ceil(A)
#define FLOOR(A) std::floor(A)
#define ROUND(A) std::lround(A)
#define PACK_U32(high, low) ((static_cast<u32>(high) << 16) | (static_cast<u32>(low) & 0xFFFF))
#define PACK_U32_NIBBLE_HIGH_BYTE_LOW(high, low) ((static_cast<u32>(high & 0xF) << 28) | (static_cast<u32>(low) & 0xFF))
/* Primary timings. */
const std::array<u32, 8> tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
const std::array<u32, 8> tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
const std::array<u32, 10> tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
const std::array<u32, 8> tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
const std::array<u32, 8> tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
const std::array<u32, 10> tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
const std::array<double, 7> tRRD_values = { /*10.0,*/ 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }; /* 10.0 is used for <2133mhz; do we care? 8gb uses 7.5 tRRD on >=1331. */
const std::array<u32, 11> tRFC_values = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
const std::array<u32, 10> tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
@@ -96,7 +96,7 @@ namespace ams::ldr::oc {
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
const u32 tW2R = CEIL(MAX(WL + (0.010322547033278747 * (C.eristaEmcMaxClock / 1000.0)), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg));
const u32 wdv = WL;
const u32 wsv = WL - 2;
const u32 wev = 0xA + (WL - 14);
@@ -132,6 +132,8 @@ namespace ams::ldr::oc {
const double tRRD = tRRD_values[C.t4_tRRD];
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
const s32 finetRTW = C.fineTune_t6_tRTW;
const s32 finetWTR = C.fineTune_t7_tWTR;
const u32 tRC = tRAS + tRPpb;
const u32 tRFCab = tRFCpb * 2;
@@ -139,43 +141,41 @@ namespace ams::ldr::oc {
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
const double tRPab = tRPpb + 3;
const u32 tR2P = 12 + ((RL_DBI - 32) / 2);
inline u32 tR2W;
const u32 tRTM = RL + 9 + (tDQSCK_max / tCK_avg) + FLOOR(tRPST) + CEIL(10 / tCK_avg); // Fix?
const u32 tRATM = tRTM + CEIL(10 / tCK_avg) - 12; // Fix?
const u32 tR2P = CEIL((RL_DBI * 0.426) - 2.0);
const u32 tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL_DBI - (C.t6_tRTW * 3) + finetRTW;
const u32 tRTM = FLOOR((10.0 + RL_DBI) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg);
const u32 tRATM = CEIL((tRTM - 10.0) + (RL_DBI * 0.426));
inline u32 rext;
const u32 rdv = FLOOR(17.02046755653219 + (RL_DBI + (ramFreqMhz * 0.00510056573299173)));
const u32 qpop = rdv - 14;
const u32 quse_width = CEIL(((3.7165006256863955 - ramFreqMhz) + (-0.002446584377651142 * ramFreqMhz)) - FLOOR(ramFreqMhz / -0.9952024303111688));
const u32 quse = CEIL(MIN(RL_DBI + (2.991255208275918 - (quse_width + (-0.00511180626826906 * ramFreqMhz))), ramFreqMhz * 0.021333773138874437));
const u32 einput_duration = CEIL(quse_width + (ramFreqMhz * 0.01) + 4);
const u32 einput = 5 + qpop - einput_duration;
const u32 ibdly = 0x10000000 + FLOOR(MAX(RL_DBI - 1.9999956603408224, quse - 5.9999987787411175) + (-0.0011929079761504341 * ramFreqMhz));
const u32 qrst_duration = FLOOR((ramFreqMhz * 0.001477125119082522) + 4.272302254983803);
const u32 qrstLow = MAX(static_cast<s32>(einput - qrst_duration - 2), static_cast<s32>(0));
const u32 qrst = PACK_U32(qrst_duration, qrstLow);
const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput);
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
inline u32 tWTPDEN;
const u32 tW2R = CEIL(MAX(WL + (0.010322547033278747 * ramFreqMhz), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg));
const u32 tWTM = WL + (BL / 2) + 1 + CEIL(7.5 / tCK_avg);
const u32 tWATM = tWTM + CEIL(tWR / tCK_avg);
const u32 rdv = RL_DBI + FLOOR((5.105 / tCK_avg) + 17.017);
const u32 qpop = rdv - 14;
const u32 quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782);
const u32 quse = FLOOR(RL_DBI + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg);
const u32 einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width;
const u32 einput = quse - CEIL(9.928 / tCK_avg);
const u32 qrst_duration = FLOOR(8.399 - tCK_avg);
const u32 qrstLow = MAX(static_cast<s32>(einput - qrst_duration - 2), static_cast<s32>(0));
const u32 qrst = PACK_U32(qrst_duration, qrstLow);
const u32 ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0);
const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput);
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
const u32 tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL_DBI + (2.694 / tCK_avg), static_cast<double>(tW2P))) + (BL / 2));
const u32 tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL_DBI)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR;
const u32 tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753));
const u32 tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0;
const u32 wdv = WL;
const u32 wsv = WL - 2;
const u32 wev = 0xA + (WL - 14);
const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast<double>(2), tCK_avg * (WL - 7)));
const u32 obdlyLow = WL - MIN(static_cast<double>(WL), 12 - (CEIL(-0.0003991 * ramFreqMhz) * 2));
const u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0);
const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow);
inline u32 pdex2rw;
inline u32 cke2pden;
const u32 pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361)));
const u32 tCKE = CEIL(1.0795 * CEIL(0.0074472 * ramFreqMhz));
const u32 tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0;
const double tMMRI = tRCD + (tCK_avg * 3);
const double pdex2mrr = tMMRI + 10; /* Do this properly? */

View File

@@ -52,7 +52,7 @@ namespace ams::ldr {
R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015);
}
namespace ams::ldr::oc {
namespace ams::ldr::hoc {
template<typename Pointer>
struct PatcherEntry {
using patternFn = bool(*)(Pointer* ptr);

View File

@@ -65,7 +65,7 @@ void saveExec(const char* file_loc, const void* buf, size_t size) {
}
Result Test_PcvDvfsTable() {
using namespace ams::ldr::oc::pcv;
using namespace ams::ldr::hoc::pcv;
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&mariko::CpuCvbTableDefault)) == 18);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&erista::CpuCvbTableDefault)) == 16);
@@ -76,19 +76,19 @@ Result Test_PcvDvfsTable() {
cvb_entry_t last_mariko_cpu_cvb_entry_default = { 1963500, { 1675751, -38635, 27 }, { 1120000 } };
assert(memcmp(GetDvfsTableLastEntry((cvb_entry_t *)(&mariko::CpuCvbTableDefault)), (void *)&last_mariko_cpu_cvb_entry_default, sizeof(last_mariko_cpu_cvb_entry_default)) == 0);
assert(GetDvfsTableLastEntry((cvb_entry_t *)(&erista::GpuCvbTableDefault))->freq == 921600);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoCpuDvfsTableSLT)) == 25);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoCpuDvfsTableSLT)) == 25);
// Customized table default
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.eristaCpuDvfsTable)) == 19);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoCpuDvfsTable)) == 21);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoCpuDvfsTableSLT)) == 22);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.eristaCpuDvfsTable)) == 19);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoCpuDvfsTable)) == 21);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoCpuDvfsTableSLT)) == 22);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.eristaGpuDvfsTable)) == 12);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoGpuDvfsTable)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoGpuDvfsTableSLT)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoGpuDvfsTableHiOPT)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.eristaGpuDvfsTable)) == 12);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoGpuDvfsTable)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoGpuDvfsTableSLT)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoGpuDvfsTableHiOPT)) == 17);
constexpr size_t limit = ams::ldr::oc::pcv::DvfsTableEntryLimit;
constexpr size_t limit = ams::ldr::hoc::pcv::DvfsTableEntryLimit;
cvb_entry_t customized_table[limit] = {};
for (size_t i = 0; i < limit; i++) {
assert(GetDvfsTableEntryCount(customized_table) == i);
@@ -156,14 +156,14 @@ int main(int argc, char** argv) {
size_t exec_path_patched_len = exec_path_len + std::max(strlen(mariko_ext), strlen(erista_ext)) + 1;
if (exe_opt == EXE_PCV) {
ams::ldr::oc::pcv::SafetyCheck();
ams::ldr::hoc::pcv::SafetyCheck();
{
void* erista_buf = malloc(file_size);
std::memcpy(erista_buf, file_buffer, file_size);
printf("Patching %s for Erista...\n", pcv_opt);
ams::ldr::oc::pcv::erista::Patch(reinterpret_cast<uintptr_t>(erista_buf), file_size);
ams::ldr::hoc::pcv::erista::Patch(reinterpret_cast<uintptr_t>(erista_buf), file_size);
if (save_patched) {
char* exec_path_erista = reinterpret_cast<char *>(malloc(exec_path_patched_len));
strncpy(exec_path_erista, exec_path, exec_path_patched_len);
@@ -179,7 +179,7 @@ int main(int argc, char** argv) {
std::memcpy(mariko_buf, file_buffer, file_size);
printf("Patching %s for Mariko...\n", pcv_opt);
ams::ldr::oc::pcv::mariko::Patch(reinterpret_cast<uintptr_t>(mariko_buf), file_size);
ams::ldr::hoc::pcv::mariko::Patch(reinterpret_cast<uintptr_t>(mariko_buf), file_size);
if (save_patched) {
char* exec_path_mariko = reinterpret_cast<char *>(malloc(exec_path_patched_len));
strncpy(exec_path_mariko, exec_path, exec_path_patched_len);
@@ -196,7 +196,7 @@ int main(int argc, char** argv) {
std::memcpy(mariko_buf, file_buffer, file_size);
printf("Patching %s (Mariko Only)...\n", ptm_opt);
ams::ldr::oc::ptm::Patch(reinterpret_cast<uintptr_t>(mariko_buf), file_size);
ams::ldr::hoc::ptm::Patch(reinterpret_cast<uintptr_t>(mariko_buf), file_size);
if (save_patched) {
char* exec_path_mariko = reinterpret_cast<char *>(malloc(exec_path_patched_len));
strncpy(exec_path_mariko, exec_path, exec_path_patched_len);

View File

@@ -20,7 +20,7 @@
#include "pcv.hpp"
namespace ams::ldr::oc::pcv {
namespace ams::ldr::hoc::pcv {
Result MemFreqPllmLimit(u32* ptr) {
clk_pll_param* entry = reinterpret_cast<clk_pll_param *>(ptr);

View File

@@ -23,7 +23,7 @@
#include "../oc_common.hpp"
#include "pcv_common.hpp"
namespace ams::ldr::oc::pcv {
namespace ams::ldr::hoc::pcv {
namespace mariko {
constexpr cvb_entry_t CpuCvbTableDefault[] = {

View File

@@ -18,7 +18,7 @@
#pragma once
namespace ams::ldr::oc::pcv {
namespace ams::ldr::hoc::pcv {
typedef struct cvb_coefficients {
s32 c0 = 0;

View File

@@ -21,7 +21,7 @@
#include "pcv.hpp"
#include "../mtc_timing_value.hpp"
namespace ams::ldr::oc::pcv::erista {
namespace ams::ldr::hoc::pcv::erista {
Result CpuVoltDvfs(u32 *ptr) {
if (MatchesPattern(ptr, cpuVoltDvfsPattern, cpuVoltDvfsOffsets)) {

View File

@@ -22,7 +22,7 @@
#include "../mtc_timing_value.hpp"
#include "../mariko/calculate_timings.hpp"
namespace ams::ldr::oc::pcv::mariko {
namespace ams::ldr::hoc::pcv::mariko {
u32 GetGpuVminVoltage() {
for (auto e : vminTable) {
@@ -84,18 +84,18 @@ namespace ams::ldr::oc::pcv::mariko {
}
/* C.marikoGpuVmin is zero, auto voltage is applied. */
/* Get vmin depending on speedo and ram clock. */
u32 autoVmin = GetAutoVoltage();
PATCH_OFFSET(ptr, autoVmin);
R_SUCCEED();
}
Result GpuVoltThermals(u32 *ptr) {
u32 vmin = std::memcmp(ptr - 3, gpuVoltThermalPattern, sizeof(gpuVoltThermalPattern));
if (vmin) {
if (std::memcmp(ptr - 3, gpuVoltThermalPattern, sizeof(gpuVoltThermalPattern))) {
R_THROW(ldr::ResultInvalidGpuDvfs());
}
u32 vmin = C.marikoGpuVmin;
/* Automatic voltage. */
if (!C.marikoGpuVmin) {
vmin = GetAutoVoltage();
@@ -105,11 +105,10 @@ namespace ams::ldr::oc::pcv::mariko {
PATCH_OFFSET(ptr + 9, vmin);
} else {
/* Manual voltage. */
PATCH_OFFSET(ptr, C.marikoGpuVmin);
PATCH_OFFSET(ptr + 3, C.marikoGpuVmin);
PATCH_OFFSET(ptr + 6, C.marikoGpuVmin);
PATCH_OFFSET(ptr + 9, C.marikoGpuVmin);
vmin = C.marikoGpuVmin;
PATCH_OFFSET(ptr, vmin);
PATCH_OFFSET(ptr + 3, vmin);
PATCH_OFFSET(ptr + 6, vmin);
PATCH_OFFSET(ptr + 9, vmin);
}
PATCH_OFFSET(ptr + 12, vmin);
@@ -432,9 +431,9 @@ namespace ams::ldr::oc::pcv::mariko {
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
WRITE_PARAM_ALL_REG(table, emc_trpab, MIN(GET_CYCLE_CEIL(tRPab), static_cast<u32>(0x3F)));
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR));
WRITE_PARAM_ALL_REG(table, emc_tcke, tCKE);
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(7.425) + 2);
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tXP));
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tXP) + 8); // TODO analyse
WRITE_PARAM_ALL_REG(table, emc_tclkstop, tCLKSTOP);
WRITE_PARAM_ALL_REG(table, emc_r2p, tR2P);
WRITE_PARAM_ALL_REG(table, emc_r2w, tR2W);
WRITE_PARAM_ALL_REG(table, emc_trtm, tRTM);
@@ -452,12 +451,11 @@ namespace ams::ldr::oc::pcv::mariko {
WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control);
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, pdex2rw);
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, pdex2rw);
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(1.75));
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(1.763));
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(1.75));
WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(1.05));
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(14.0));
WRITE_PARAM_ALL_REG(table, emc_cke2pden, /* cke2pden */ GET_CYCLE_CEIL(8.5));
(void) cke2pden;
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(8.499));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(pdex2mrr));
WRITE_PARAM_ALL_REG(table, emc_rw2pden, tWTPDEN);
WRITE_PARAM_ALL_REG(table, emc_einput, einput);

View File

@@ -18,7 +18,7 @@
#include "ptm.hpp"
namespace ams::ldr::oc::ptm {
namespace ams::ldr::hoc::ptm {
Result CpuPtmBoost(perf_conf_entry* entry) {

View File

@@ -20,7 +20,7 @@
#include "../oc_common.hpp"
namespace ams::ldr::oc::ptm {
namespace ams::ldr::hoc::ptm {
typedef struct {
u32 conf_id;

View File

@@ -12,7 +12,7 @@ def image_to_rgba8888_array(image_path, output_path):
# Write as C header file
with open(output_path, 'w') as f:
f.write('// This is a generated automatically generated file, do not edit manually.\n')
f.write('// This is a automatically generated file, do not edit manually.\n')
f.write(f'// {os.path.basename(image_path)} - {width}x{height}\n')
f.write(f'const unsigned int IMG_WIDTH = {width};\n')
f.write(f'const unsigned int IMG_HEIGHT = {height};\n')
@@ -32,7 +32,7 @@ def image_to_rgba8888_array(image_path, output_path):
def main():
parser = argparse.ArgumentParser(
description='PNG -> RGB8888 script'
description='PNG to RGB8888 script'
)
parser.add_argument('input', help='Input image file (e.g. cat.png)')
parser.add_argument(

View File

@@ -0,0 +1,41 @@
/*
MIT License
Copyright (c) 2024 Roy Merkel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef MEMMEM_IMPL_H
#define MEMMEM_IMPL_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void *memmem_impl(void *haystack, size_t haystacklen,
const void *needle, size_t needlelen);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -132,6 +132,14 @@ typedef enum {
GPUUVLevel_EnumMax,
} GPUUndervoltLevel;
enum {
DVFSMode_Disabled,
DVFSMode_Hijack,
// DVFSMode_OfficialService,
// DVFSMode_Hack,
DVFSMode_EnumMax,
};
#define SYSCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax)
static inline const char* sysclkFormatModule(SysClkModule module, bool pretty)

View File

@@ -12,9 +12,9 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
/* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
@@ -57,10 +57,14 @@ typedef enum {
HorizonOCConfigValue_OverwriteRefreshRate,
HorizonOCConfigValue_EnableUnsafeDisplayFreqs,
HorizonOCConfigValue_DVFSMode,
HorizonOCConfigValue_DVFSOffset,
HocClkConfigValue_FixCpuVoltBug,
KipConfigValue_custRev,
KipConfigValue_mtcConf,
// KipConfigValue_mtcConf,
KipConfigValue_hpMode,
KipConfigValue_commonEmcMemVolt,
@@ -158,6 +162,9 @@ typedef enum {
KipConfigValue_g_volt_e_1036800,
KipConfigValue_g_volt_e_1075200,
KipConfigValue_t6_tRTW_fine_tune,
KipConfigValue_t7_tWTR_fine_tune,
KipCrc32,
HocClkConfigValue_IsFirstLoad,
SysClkConfigValue_EnumMax,
@@ -223,11 +230,17 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
return pretty ? "Enable Unsafe Display Frequencies" : "drr_unsafe";
case HorizonOCConfigValue_DVFSMode:
return pretty ? "DVFS Mode" : "dvfs_mode";
case HorizonOCConfigValue_DVFSOffset:
return pretty ? "DVFS Offset" : "dvfs_offset";
// KIP config values
case KipConfigValue_custRev:
return pretty ? "Custom Revision" : "kip_cust_rev";
case KipConfigValue_mtcConf:
return pretty ? "MTC Config" : "kip_mtc_conf";
// case KipConfigValue_mtcConf:
// return pretty ? "MTC Config" : "kip_mtc_conf";
case KipConfigValue_hpMode:
return pretty ? "HP Mode" : "kip_hp_mode";
@@ -370,6 +383,8 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
case KipConfigValue_g_volt_e_998400: return pretty ? "Erista GPU Volt 998 MHz" : "g_volt_e_998400";
case KipConfigValue_g_volt_e_1036800: return pretty ? "Erista GPU Volt 1036 MHz" : "g_volt_e_1036800";
case KipConfigValue_g_volt_e_1075200: return pretty ? "Erista GPU Volt 1075 MHz" : "g_volt_e_1075200";
case KipConfigValue_t6_tRTW_fine_tune: return pretty ? "t6 - tRTW Fine Tune" : "t6_tRTW_fine_fune";
case KipConfigValue_t7_tWTR_fine_tune: return pretty ? "t7 - tWTR Fine Tune" : "t7_tWTR_fine_tune";
case KipCrc32:
return pretty ? "CRC32" : "crc32";
case HocClkConfigValue_IsFirstLoad:
@@ -406,6 +421,7 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val)
case HocClkConfigValue_EnforceBoardLimit:
case HocClkConfigValue_FixCpuVoltBug:
case HocClkConfigValue_IsFirstLoad:
case HorizonOCConfigValue_DVFSMode:
return 1ULL;
case HocClkConfigValue_ThermalThrottleThreshold:
return 70ULL;
@@ -429,7 +445,7 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
case HocClkConfigValue_LiteTDPLimit:
case SysClkConfigValue_PollingIntervalMs:
return input > 0;
case SysClkConfigValue_TempLogIntervalMs:
case SysClkConfigValue_FreqLogIntervalMs:
case SysClkConfigValue_PowerLogIntervalMs:
@@ -444,9 +460,9 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
case HocClkConfigValue_IsFirstLoad:
return (input & 0x1) == input;
case KipConfigValue_custRev:
case KipConfigValue_mtcConf:
// case KipConfigValue_mtcConf:
case KipConfigValue_hpMode:
case KipConfigValue_commonEmcMemVolt:
case KipConfigValue_eristaEmcMaxClock:
@@ -534,7 +550,11 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
case KipConfigValue_g_volt_e_1075200:
case KipConfigValue_eristaCpuVmin:
case KipConfigValue_eristaCpuUnlock:
case KipConfigValue_t6_tRTW_fine_tune:
case KipConfigValue_t7_tWTR_fine_tune:
case KipCrc32:
case HorizonOCConfigValue_DVFSMode:
case HorizonOCConfigValue_DVFSOffset:
return true;
case HorizonOCConfigValue_BatteryChargeCurrent:
return ((input >= 1024) && (input <= 3072)) || !input;

View File

@@ -0,0 +1,83 @@
/*
MIT License
Copyright (c) 2024 Roy Merkel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "memmem.h"
void *memmem_impl(void *haystack, size_t haystacklen, const void *needle, size_t needlelen)
{
const unsigned char *cmpp;
const unsigned char *p;
const unsigned char *endp;
const unsigned char *q;
const unsigned char *endq;
unsigned char found;
if(haystack == NULL)
{
return NULL;
}
if(needle == NULL)
{
return haystack;
}
if(haystacklen == 0)
{
return NULL;
}
if(needlelen == 0)
{
return haystack;
}
if(needlelen > haystacklen)
{
return NULL;
}
endp = haystack + haystacklen - needlelen;
endq = needle + needlelen;
for(p = haystack; p <= endp; p++)
{
found = 1;
cmpp = p;
for(q = needle; q < endq; q++)
{
if(*cmpp != *q)
{
found = 0;
break;
}
else
{
cmpp++;
}
}
if(found)
{
return (void*)p;
}
}
return NULL;
}

View File

@@ -39,7 +39,7 @@ include ${TOPDIR}/lib/libultrahand/ultrahand.mk
# version control constants
#---------------------------------------------------------------------------------
#TARGET_VERSION := $(shell git describe --dirty --always --tags)
APP_VERSION := 0.34
APP_VERSION := 0.37
TARGET_VERSION := $(APP_VERSION)
#---------------------------------------------------------------------------------

View File

@@ -59,7 +59,6 @@ tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t hz, bool sel
if (selected)
text += " \uE14B";
// NEW: Right-side label
std::string rightText = "";
auto it = labels.find(hz);
if (it != labels.end())
@@ -156,16 +155,26 @@ void FreqChoiceGui::listUI()
if (IsMariko())
{
unsafe_cpu = 1964;
unsafe_gpu = 1076;
danger_cpu = 2398;
unsafe_cpu = this->configList->values[KipConfigValue_marikoCpuUVHigh] ? 2296 : 1964;
if(this->configList->values[KipConfigValue_marikoGpuUV] == 0) {
unsafe_gpu = 1076;
} else if (this->configList->values[KipConfigValue_marikoGpuUV] == 1) {
unsafe_gpu = 1153;
} else {
unsafe_gpu = 1229;
}
danger_cpu = this->configList->values[KipConfigValue_marikoCpuUVHigh] ? 2500 : 2398;
danger_gpu = 1306;
}
else
{
unsafe_cpu = 1786;
unsafe_gpu = 922;
danger_cpu = 2092;
unsafe_cpu = this->configList->values[KipConfigValue_eristaCpuUV] ? 1964 : 1786;
if(this->configList->values[KipConfigValue_eristaGpuUV] == 0) {
unsafe_gpu = 922;
} else {
unsafe_gpu = 961;
}
danger_cpu = this->configList->values[KipConfigValue_eristaCpuUV] ? 2194 : 1964;
danger_gpu = 999;
}

View File

@@ -1,3 +1,20 @@
/*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* 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 <map>
#include <cstdint>
#include <string>
@@ -30,7 +47,7 @@ std::map<uint32_t, std::string> gpu_freq_label_e = {
{768000000, "Docked"},
{921600000, "Safe Max"},
{960000000, "Unsafe Max"},
{1075200000, "Aboslute Max"},
{1075200000, "Absolute Max"},
};
std::map<uint32_t, std::string> gpu_freq_label_m = {
@@ -42,5 +59,6 @@ std::map<uint32_t, std::string> gpu_freq_label_m = {
{768000000, "Docked"},
{1075200000, "Safe Max"},
{1305600000, "Unsafe Max"},
{1536000000, "Aboslute Max"},
};
{1536000000, "Absolute Max"},
};

View File

@@ -1,3 +1,20 @@
/*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* 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/>.
*
*/
#pragma once
#include <map>
#include <cstdint>

View File

@@ -27,6 +27,7 @@
#if IS_MINIMAL == 1
#pragma message("Compiling with minimal features")
#endif
class RamSubmenuGui;
class RamTimingsSubmenuGui;
class RamLatenciesSubmenuGui;
@@ -255,9 +256,6 @@ void MiscGui::listUI()
addConfigToggle(HocClkConfigValue_EnforceBoardLimit, nullptr);
#if IS_MINIMAL == 0
std::map<uint32_t, std::string> labels_pwr_r = {
{8600, "Official Rating"}
};
std::map<uint32_t, std::string> labels_pwr_l = {
{6400, "Official Rating"}
};
@@ -273,14 +271,13 @@ void MiscGui::listUI()
labels_pwr_l
);
} else {
ValueThresholds tdpThresholds(8600, 9500);
ValueThresholds tdpThresholds(9600, 11000);
addConfigButton(
HocClkConfigValue_HandheldTDPLimit,
"TDP Threshold",
ValueRange(5000, 10000, 100, "mW", 1),
ValueRange(8000, 12000, 100, "mW", 1),
"Power",
&tdpThresholds,
labels_pwr_r
&tdpThresholds
);
}
@@ -301,6 +298,45 @@ void MiscGui::listUI()
addFreqButton(HocClkConfigValue_EristaMaxCpuClock, nullptr, SysClkModule_CPU, cpu_freq_label_e);
}
if (IsMariko()) {
std::vector<NamedValue> dvfsValues = {
NamedValue("Disabled", DVFSMode_Disabled),
NamedValue("PCV Hijack", DVFSMode_Hijack),
// NamedValue("Official Service", DVFSMode_OfficialService),
// NamedValue("Hack", DVFSMode_Hack),
};
addConfigButton(
HorizonOCConfigValue_DVFSMode,
"GPU DVFS Mode",
ValueRange(0, 0, 1, "", 0),
"GPU DVFS Mode",
&thresholdsDisabled,
{},
dvfsValues,
false
);
std::vector<NamedValue> dvfsOffset = {
NamedValue("-50", 0xFFFFFFCE),
NamedValue("-45", 0xFFFFFFD3),
NamedValue("-40", 0xFFFFFFD8),
NamedValue("-30", 0xFFFFFFE2),
NamedValue("-25", 0xFFFFFFE7),
NamedValue("-20", 0xFFFFFFEC),
NamedValue("-10", 0xFFFFFFF6),
NamedValue(" -5", 0xFFFFFFFB),
NamedValue(" 0", 0),
NamedValue(" +5", 5),
NamedValue("+10", 10),
NamedValue("+15", 15),
NamedValue("+20", 20),
};
addConfigButton(HorizonOCConfigValue_DVFSOffset, "GPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "GPU DVFS Offset", &thresholdsDisabled, {}, dvfsOffset, false);
}
this->listElement->addItem(new tsl::elm::CategoryHeader("KIP"));
tsl::elm::ListItem* saveBtn = new tsl::elm::ListItem("Save KIP Settings");
@@ -347,8 +383,9 @@ void MiscGui::listUI()
});
this->listElement->addItem(gpuSubmenu);
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
#if IS_MINIMAL == 0
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
std::vector<NamedValue> chargerCurrents = {
NamedValue("Disabled", 0),
NamedValue("1024mA", 1024),
@@ -461,7 +498,7 @@ protected:
NamedValue("2033MHz", 2033000),
NamedValue("2066MHz", 2066000),
NamedValue("2100MHz", 2100000),
NamedValue("2133MHz", 2133000),
NamedValue("2133MHz", 2133000, "JEDEC."),
NamedValue("2166MHz", 2166000),
NamedValue("2200MHz", 2200000),
NamedValue("2233MHz", 2233000),
@@ -654,10 +691,33 @@ protected:
addConfigButton(KipConfigValue_t6_tRTW, "t6 tRTW", ValueRange(0, 10, 1, "", 1), "tRTW", &thresholdsDisabled, {}, {}, false);
addConfigButton(KipConfigValue_t7_tWTR, "t7 tWTR", ValueRange(0, 10, 1, "", 1), "tWTR", &thresholdsDisabled, {}, {}, false);
addConfigButton(KipConfigValue_t8_tREFI, "t8 tREFI", ValueRange(0, 6, 1, "", 1), "tREFI", &thresholdsDisabled, {}, {}, false);
std::vector<NamedValue> t6_tRTW_fine_tune = {
NamedValue("-2", 0xFFFFFFFE),
NamedValue("-1", 0xFFFFFFFF),
NamedValue(" 0", 0),
NamedValue("+1", 1),
NamedValue("+2", 2),
};
std::vector<NamedValue> t7_tWTR_fine_tune = {
NamedValue("-3", 0xFFFFFFFD),
NamedValue("-2", 0xFFFFFFFE),
NamedValue("-1", 0xFFFFFFFF),
NamedValue(" 0", 0),
NamedValue("+1", 1),
NamedValue("+2", 2),
NamedValue("+3", 3),
};
this->listElement->addItem(new tsl::elm::CategoryHeader("Advanced"));
addConfigButton(KipConfigValue_t6_tRTW_fine_tune, "t6 tRTW Fine Tune", ValueRange(0, 4, 1, "", 0), "tRTW Fine Tune", &thresholdsDisabled, {}, t6_tRTW_fine_tune, false);
addConfigButton(KipConfigValue_t7_tWTR_fine_tune, "t7 tWTR Fine Tune", ValueRange(0, 6, 1, "", 0), "tWTR Fine Tune", &thresholdsDisabled, {}, t7_tWTR_fine_tune, false);
#if IS_MINIMAL == 0
if(IsMariko()) {
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
tsl::elm::ListItem* emcUpdBtn = new tsl::elm::ListItem("Update RAM Timings");
emcUpdBtn->setClickListener([this](u64 keys) {
if (keys & HidNpadButton_A) {
@@ -1192,7 +1252,7 @@ protected:
};
if (IsMariko()) {
tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
renderer->drawString("\uE150 Setting GPU Clocks past", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
renderer->drawString("1075MHz without UV, 1152MHz on SLT", false, x + 20, y + 50, 18, tsl::style::color::ColorText);

View File

@@ -12,9 +12,9 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
/* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
@@ -41,6 +41,7 @@
#include <cstring>
#include <registers.h>
#include <notification.h>
#include <memmem.h>
#define MAX(A, B) std::max(A, B)
#define MIN(A, B) std::min(A, B)
@@ -96,9 +97,23 @@ std::atomic<uint64_t> idletick2{systemtickfrequency};
std::atomic<uint64_t> idletick3{systemtickfrequency};
u32 cpu0, cpu1, cpu2, cpu3, cpuAvg;
u16 cpuSpeedo0, cpuSpeedo2, socSpeedo0; // CPU, GPU, SOC
u32 speedoBracket;
u16 cpuIDDQ, gpuIDDQ, socIDDQ;
u8 g_dramID = 0;
static const u32 ramBrackets[][22] = {
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, },
};
static const u32 gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
u32 dvfsTable[6][32] = {};
u64 dvfsAddress;
u32 ramVmin;
const char* Board::GetModuleName(SysClkModule module, bool pretty)
{
ASSERT_ENUM_VALID(SysClkModule, module);
@@ -311,7 +326,7 @@ void Board::fuseReadSpeedos() {
cpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_CPU_IDDQ_CALIB);
gpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_SOC_IDDQ_CALIB);
socIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_GPU_IDDQ_CALIB);
svcCloseHandle(debug);
return;
}
@@ -458,7 +473,7 @@ std::uint32_t Board::GetHz(SysClkModule module)
hz = 60;
return hz;
}
if(HOSSVC_HAS_CLKRST)
{
ClkrstSession session = {0};
@@ -753,7 +768,7 @@ std::int32_t Board::GetPowerMw(SysClkPowerSensor sensor)
}
std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource)
{
{
switch(loadSource)
{
case SysClkPartLoad_EMC:
@@ -792,6 +807,7 @@ u8 Board::GetDramID() {
void Board::FetchHardwareInfos()
{
fuseReadSpeedos();
SetSpeedoBracket();
u64 sku = 0, dramID = 0;
Result rc = splInitialize();
ASSERT_RESULT_OK(rc, "splInitialize");
@@ -801,7 +817,7 @@ void Board::FetchHardwareInfos()
rc = splGetConfig(SplConfigItem_DramId, &dramID);
ASSERT_RESULT_OK(rc, "splGetConfig");
splExit();
switch(sku)
@@ -816,9 +832,12 @@ void Board::FetchHardwareInfos()
g_socType = SysClkSocType_Erista;
}
if (g_socType == SysClkSocType_Mariko) {
CacheDvfsTable();
}
g_consoleType = (HorizonOCConsoleType)sku;
g_dramID = (u8)dramID;
}
/*
@@ -926,6 +945,169 @@ std::uint32_t Board::GetVoltage(HocClkVoltage voltage)
return out > 0 ? out : 0;
}
void Board::SetSpeedoBracket() {
if (cpuSpeedo2 >= 1754) {
speedoBracket = 3;
} else if (cpuSpeedo2 >= 1690) {
speedoBracket = 2;
} else if (cpuSpeedo2 > 1625) {
speedoBracket = 1;
} else {
speedoBracket = 0;
}
}
u32 Board::GetMinimumGpuVoltage(u32 freqMhz) {
if (freqMhz <= 1600)
return 0;
for (u32 voltageIndex = 0; voltageIndex < 22; ++voltageIndex) {
if (freqMhz <= ramBrackets[speedoBracket][voltageIndex]) {
return gpuDvfsArray[voltageIndex];
}
}
return 800;
}
Handle Board::GetPcvHandle() {
constexpr u64 PcvID = 0x10000000000001a;
u64 processIDList[80]{};
s32 processCount = 0;
Handle handle = INVALID_HANDLE;
DebugEventInfo debugEvent{};
/* Get all running processes. */
Result resultGetProcessList = svcGetProcessList(&processCount, processIDList, std::size(processIDList));
if (R_FAILED(resultGetProcessList)) {
return INVALID_HANDLE;
}
/* Try to find pcv. */
for (int i = 0; i < processCount; ++i) {
if (handle != INVALID_HANDLE) {
svcCloseHandle(handle);
handle = INVALID_HANDLE;
}
/* Try to debug process, if it fails, try next process. */
Result resultSvcDebugProcess = svcDebugActiveProcess(&handle, processIDList[i]);
if (R_FAILED(resultSvcDebugProcess)) {
continue;
}
/* Try to get a debug event. */
Result resultDebugEvent = svcGetDebugEvent(&debugEvent, handle);
if (R_SUCCEEDED(resultDebugEvent)) {
if (debugEvent.info.create_process.program_id == PcvID) {
return handle;
}
}
}
/* Failed to get handle. */
return INVALID_HANDLE;
}
void Board::CacheDvfsTable() {
const u32 voltagePattern[] = { 600000, 12500, 1400000, };
Handle handle = GetPcvHandle();
if (handle == INVALID_HANDLE) {
FileUtils::LogLine("[Board] Invalid handle!");
return;
}
MemoryInfo memoryInfo = {};
u64 address = 0;
u32 pageInfo = 0;
constexpr u32 PageSize = 0x1000;
u8 buffer[PageSize];
/* Loop until failure. */
while (true) {
/* Find pcv heap. */
while (true) {
Result resultProcessMemory = svcQueryDebugProcessMemory(&memoryInfo, &pageInfo, handle, address);
address = memoryInfo.addr + memoryInfo.size;
if (R_FAILED(resultProcessMemory) || !address) {
svcCloseHandle(handle);
FileUtils::LogLine("[Board] Failed to get process data. %u", R_DESCRIPTION(resultProcessMemory));
handle = INVALID_HANDLE;
return;
}
if (memoryInfo.size && (memoryInfo.perm & 3) == 3 && static_cast<char>(memoryInfo.type) == 0x04) {
/* Found valid memory. */
break;
}
}
for (u64 base = 0; base < memoryInfo.size; base += PageSize) {
u32 memorySize = std::min(memoryInfo.size, static_cast<u64>(PageSize));
if (R_FAILED(svcReadDebugProcessMemory(buffer, handle, base + memoryInfo.addr, memorySize))) {
break;
}
u8 *resultPattern = static_cast<u8 *>(memmem_impl(buffer, sizeof(buffer), voltagePattern, sizeof(voltagePattern)));
u32 index = resultPattern - buffer;
if (!resultPattern) {
continue;
}
/* Assuming mariko. */
const u32 vmax = 800;
constexpr u32 DvfsTableOffset = 312;
if (!std::memcmp(&buffer[index + DvfsTableOffset], &vmax, sizeof(vmax))) {
std::memcpy(dvfsTable, &buffer[index + DvfsTableOffset], sizeof(dvfsTable));
dvfsAddress = base + memoryInfo.addr + DvfsTableOffset + index;
}
svcCloseHandle(handle);
handle = INVALID_HANDLE;
return;
}
}
svcCloseHandle(handle);
handle = INVALID_HANDLE;
return;
}
void Board::PcvHijackDvfs(u32 vmin) {
u32 table[192];
static_assert(sizeof(table) == sizeof(dvfsTable));
std::memcpy(table, dvfsTable, sizeof(dvfsTable));
if (ramVmin == vmin) {
return;
}
for (u32 i = 0; i < std::size(table); ++i) {
if (table[i] && table[i] <= vmin) {
table[i] = vmin;
}
}
Handle handle = GetPcvHandle();
if (handle == INVALID_HANDLE) {
FileUtils::LogLine("Invalid handle!");
return;
}
Result rc = svcWriteDebugProcessMemory(handle, table, dvfsAddress, sizeof(table));
if (R_SUCCEEDED(rc)) {
ramVmin = vmin;
}
svcCloseHandle(handle);
FileUtils::LogLine("[dvfs] voltage set to %u mV", vmin);
}
#define MC_REGISTER_BASE 0x70019000
#define MC_REGISTER_REGION_SIZE 0x1000
@@ -1021,13 +1203,13 @@ void Board::UpdateShadowRegs(u32 tRCD_i, u32 tRP_i, u32 tRAS_i, u32 tRRD_i, u32
double tXSR = (double) (tRFCab + 7.5);
args = {};
args.X[0] = 0xF0000002;
args.X[1] = EMC_REGISTER_BASE + EMC_INTSTATUS_0;
svcCallSecureMonitor(&args);
args = {};
args.X[0] = 0xF0000002;
args.X[1] = EMC_REGISTER_BASE + EMC_INTSTATUS_0;
svcCallSecureMonitor(&args);
if(args.X[1] == (EMC_REGISTER_BASE + EMC_INTSTATUS_0)) { // if param 1 is identical read failed, exosphere needs patch!
writeNotification("Horizon OC\nExosphere not patched\nfor EMC r/w");
writeNotification("Horizon OC\nExosphere not patched\nfor EMC r/w");
return;
}
@@ -1079,21 +1261,21 @@ void Board::UpdateShadowRegs(u32 tRCD_i, u32 tRP_i, u32 tRAS_i, u32 tRRD_i, u32
WRITE_REGISTER_MC(MC_EMEM_ARB_DA_COVERS_0, da_covers);
// TODO: modify mc_emem_arb_misc0
WRITE_REGISTER_MC(MC_TIMING_CONTROL_0, 0x1); // update timing regs as they are shadowed
WRITE_REGISTER_EMC(EMC_TIMING_CONTROL_0, 0x1);
}
bool Board::IsDram8GB() {
SecmonArgs args = {};
args.X[0] = 0xF0000002;
args.X[1] = MC_REGISTER_BASE + MC_EMEM_CFG_0;
svcCallSecureMonitor(&args);
SecmonArgs args = {};
args.X[0] = 0xF0000002;
args.X[1] = MC_REGISTER_BASE + MC_EMEM_CFG_0;
svcCallSecureMonitor(&args);
if(args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed
writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!");
writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!");
return false;
} else
return args.X[1] == 0x00002000 ? true : false;
}
}

View File

@@ -12,9 +12,9 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
/* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
@@ -33,6 +33,8 @@
class Board
{
public:
static void PcvHijackDvfs(u32 vmin);
static u32 GetMinimumGpuVoltage(u32 freqMhz);
static void fuseReadSpeedos();
static u16 getSpeedo(HorizonOCSpeedo speedoType);
static u16 getIDDQ(HorizonOCSpeedo speedoType);
@@ -67,4 +69,8 @@ class Board
static void FetchHardwareInfos();
static PcvModule GetPcvModule(SysClkModule sysclkModule);
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
private:
static void SetSpeedoBracket();
static void CacheDvfsTable();
static Handle GetPcvHandle();
};

View File

@@ -47,8 +47,9 @@ bool hasChanged = true;
ClockManager *ClockManager::instance = NULL;
Thread governorTHREAD;
u32 initialConfigValues[SysClkConfigValue_EnumMax]; // initial config. used for safety checks
u64 previousRamHz;
bool kipAvailable = false;
ClockManager *ClockManager::GetInstance()
{
return instance;
@@ -110,6 +111,7 @@ ClockManager::ClockManager()
this->context->dramID = Board::GetDramID();
this->context->isDram8GB = Board::IsDram8GB();
previousRamHz = Board::GetHz(SysClkModule_MEM);
}
@@ -196,7 +198,7 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
{
if (this->config->GetConfigValue(HocClkConfigValue_UncappedClocks))
{
return 4294967294; // Integer limit, uncapped clocks ON
return ~0; // Integer limit, uncapped clocks ON
}
else
{
@@ -208,9 +210,18 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
case SysClkSocType_Erista:
return 460800000;
case SysClkSocType_Mariko:
return 614400000;
switch(this->config->GetConfigValue(KipConfigValue_marikoGpuUV)) {
case 0:
return 614400000;
case 1:
return 691200000;
case 2:
return 768000000;
default:
return 614400000;
}
default:
return 4294967294;
return 460800000;
}
}
else if (profile <= SysClkProfile_HandheldChargingUSB)
@@ -219,11 +230,26 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
case SysClkSocType_Erista:
return 768000000;
case SysClkSocType_Mariko:
return 921600000;
switch(this->config->GetConfigValue(KipConfigValue_marikoGpuUV)) {
case 0:
return 844800000;
case 1:
return 921600000;
case 2:
return 998400000;
default:
return 844800000;
}
default:
return 4294967294;
return 768000000;
}
}
} else if(module == SysClkModule_CPU) {
if(profile < SysClkProfile_HandheldCharging && Board::GetSocType() == SysClkSocType_Erista) {
return 1581000000;
} else {
return ~0;
}
}
}
return 0;
@@ -338,7 +364,7 @@ void ClockManager::GovernorThread(void* arg)
svcSleepThread(50'000'000);
continue;
}
std::scoped_lock lock{mgr->contextMutex};
u32 currentHz = Board::GetHz(SysClkModule_GPU);
@@ -460,6 +486,7 @@ void ClockManager::Tick()
if (this->RefreshContext() || this->config->Refresh())
{
if(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)) {
I2c_Bq24193_SetFastChargeCurrentLimit(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent));
}
@@ -471,10 +498,13 @@ void ClockManager::Tick()
// ResetToStockClocks();
return;
}
previousRamHz = Board::GetHz(SysClkModule_MEM);
bool returnRaw = false;
for (unsigned int module = 0; module < SysClkModule_EnumMax; module++)
{
u32 oldHz = Board::GetHz((SysClkModule)module);
if(module > SysClkModule_MEM)
returnRaw = true;
else
@@ -535,9 +565,47 @@ void ClockManager::Tick()
targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10
);
if(module == SysClkModule_MEM && Board::GetSocType() == SysClkSocType_Mariko && targetHz > oldHz && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
s32 dvfsOffset = this->config->GetConfigValue(HorizonOCConfigValue_DVFSOffset);
dvfsOffset = std::max(dvfsOffset, -50);
u32 vmin = Board::GetMinimumGpuVoltage(targetHz / 1000000) + dvfsOffset;
Board::PcvHijackDvfs(vmin);
/* Update the voltage. */
if (I2c_BuckConverter_GetMvOut(&I2c_Mariko_GPU) < vmin) {
I2c_BuckConverter_SetMvOut(&I2c_Mariko_GPU, vmin);
}
this->context->voltages[HocClkVoltage_GPU] = vmin;
}
Board::SetHz((SysClkModule)module, nearestHz);
this->context->freqs[module] = nearestHz;
}
if(module == SysClkModule_MEM && Board::GetSocType() == SysClkSocType_Mariko && targetHz < oldHz && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
s32 dvfsOffset = this->config->GetConfigValue(HorizonOCConfigValue_DVFSOffset);
dvfsOffset = std::max(dvfsOffset, -50);
u32 vmin = Board::GetMinimumGpuVoltage(targetHz / 1000000) + dvfsOffset;
Board::PcvHijackDvfs(vmin);
targetHz = this->context->overrideFreqs[SysClkModule_GPU];
if (!targetHz)
{
targetHz = this->config->GetAutoClockHz(this->context->applicationId, SysClkModule_GPU, this->context->profile, false);
if(!targetHz)
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_GPU, this->context->profile, false);
}
if(targetHz) {
Board::SetHz(SysClkModule_GPU, ~0);
Board::SetHz(SysClkModule_GPU, targetHz);
} else {
Board::SetHz(SysClkModule_GPU, ~0);
Board::ResetToStockGpu();
}
}
if(module == SysClkModule_CPU && this->config->GetConfigValue(HocClkConfigValue_FixCpuVoltBug)) {
FixCpuBug();
}
@@ -562,7 +630,7 @@ void ClockManager::WaitForNextTick()
bool ClockManager::RefreshContext()
{
bool hasChanged = false;
std::uint32_t mode = 0;
Result rc = apmExtGetCurrentPerformanceConfiguration(&mode);
ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration");
@@ -624,6 +692,26 @@ bool ClockManager::RefreshContext()
break;
case SysClkModule_MEM:
Board::ResetToStockMem();
if (Board::GetSocType() == SysClkSocType_Mariko && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
Board::PcvHijackDvfs(0);
u32 targetHz = this->context->overrideFreqs[SysClkModule_GPU];
if (!targetHz)
{
targetHz = this->config->GetAutoClockHz(this->context->applicationId, SysClkModule_GPU, this->context->profile, false);
if(!targetHz)
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_GPU, this->context->profile, false);
}
if(targetHz) {
Board::SetHz(SysClkModule_GPU, ~0);
Board::SetHz(SysClkModule_GPU, targetHz);
} else {
Board::SetHz(SysClkModule_GPU, ~0);
Board::ResetToStockGpu();
}
}
break;
}
}
@@ -739,7 +827,7 @@ void ClockManager::SetKipData() {
}
CUST_WRITE_FIELD_BATCH(&table, custRev, this->config->GetConfigValue(KipConfigValue_custRev));
CUST_WRITE_FIELD_BATCH(&table, mtcConf, this->config->GetConfigValue(KipConfigValue_mtcConf));
// CUST_WRITE_FIELD_BATCH(&table, mtcConf, this->config->GetConfigValue(KipConfigValue_mtcConf));
CUST_WRITE_FIELD_BATCH(&table, hpMode, this->config->GetConfigValue(KipConfigValue_hpMode));
CUST_WRITE_FIELD_BATCH(&table, commonEmcMemVolt, this->config->GetConfigValue(KipConfigValue_commonEmcMemVolt));
@@ -792,6 +880,9 @@ void ClockManager::SetKipData() {
table.eristaGpuVoltArray[i] = this->config->GetConfigValue((SysClkConfigValue)(KipConfigValue_g_volt_e_76800 + i));
}
CUST_WRITE_FIELD_BATCH(&table, t6_tRTW_fine_tune, this->config->GetConfigValue(KipConfigValue_t6_tRTW_fine_tune));
CUST_WRITE_FIELD_BATCH(&table, t7_tWTR_fine_tune, this->config->GetConfigValue(KipConfigValue_t7_tWTR_fine_tune));
if (!cust_write_table("sdmc:/atmosphere/kips/hoc.kip", &table)) {
FileUtils::LogLine("[clock_manager] Failed to write KIP file");
writeNotification("Horizon OC\nKip write failed");
@@ -859,7 +950,7 @@ void ClockManager::GetKipData() {
if(writeBootConfigValues) {
writeBootConfigValues = false;
initialConfigValues[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table);
// initialConfigValues[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table);
initialConfigValues[KipConfigValue_hpMode] = cust_get_hp_mode(&table);
initialConfigValues[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table);
@@ -884,7 +975,6 @@ void ClockManager::GetKipData() {
initialConfigValues[KipConfigValue_eristaCpuMaxVolt] = cust_get_erista_cpu_max_volt(&table);
initialConfigValues[KipConfigValue_eristaCpuUnlock] = cust_get_eristaCpuUnlock(&table);
initialConfigValues[KipConfigValue_marikoCpuUVLow] = cust_get_mariko_cpu_uv_low(&table);
initialConfigValues[KipConfigValue_marikoCpuUVHigh] = cust_get_mariko_cpu_uv_high(&table);
initialConfigValues[KipConfigValue_tableConf] = cust_get_table_conf(&table);
@@ -902,9 +992,11 @@ void ClockManager::GetKipData() {
initialConfigValues[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table);
initialConfigValues[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table);
initialConfigValues[KipConfigValue_gpuSpeedo] = cust_get_gpu_speedo(&table);
initialConfigValues[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table);
initialConfigValues[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table);
}
configValues.values[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table);
// configValues.values[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table);
configValues.values[KipConfigValue_hpMode] = cust_get_hp_mode(&table);
configValues.values[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table);
@@ -958,6 +1050,9 @@ void ClockManager::GetKipData() {
initialConfigValues[KipConfigValue_g_volt_e_76800 + i] = cust_get_erista_gpu_volt(&table, i);
}
configValues.values[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table);
configValues.values[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table);
// if(cust_get_cust_rev(&table) == KIP_CUST_REV)
// return;
@@ -996,55 +1091,3 @@ void ClockManager::UpdateRamTimings() {
Board::UpdateShadowRegs(t1_tRCD, t2_tRP, t3_tRAS, t4_tRRD, t5_tRFC, t6_tRTW, t7_tWTR, t8_tREFI, ramFreq, rlAdd, wlAdd, hpMode);
}
unsigned int ramBrackets[][22] =
{
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, }
};
unsigned int gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
int ClockManager::GetSpeedoBracket (int speedo)
{
int speedoBracket = 3;
if ((speedo < 1754) && (speedoBracket = 2, speedo < 1690)) {
speedoBracket = !!(1625 < speedo);
}
return speedoBracket;
}
unsigned int ClockManager::GetGpuVoltage (unsigned int freq, int speedo)
{
long int loop;
int bracket = GetSpeedoBracket(speedo);
if (freq < 1601)
return 610;
loop = 0;
do
{
if (freq <= ramBrackets[bracket][loop])
return gpuDvfsArray[loop];
loop++;
} while (loop != 22);
return 800;
}
void ClockManager::calculateGpuVmin (void)
{
if(this->config->Refresh()) {
SysClkConfigValueList configValues;
this->config->GetConfigValues(&configValues);
int speedo = Board::getSpeedo(HorizonOCSpeedo_CPU), freq = this->config->GetConfigValue(KipConfigValue_marikoEmcMaxClock);
configValues.values[KipConfigValue_marikoGpuVmin] = GetGpuVoltage(freq, speedo);
this->config->SetConfigValues(&configValues, true);
}
}

View File

@@ -12,9 +12,9 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
/* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
@@ -43,7 +43,7 @@ IpcService::IpcService(ClockManager* clockMgr)
this->running = false;
this->clockMgr = clockMgr;
}
void IpcService::SetRunning(bool running)
@@ -214,11 +214,6 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8*
return ipcSrv->UpdateEmcRegs();
}
break;
case HocClkIpcCmd_CalculateGpuVmin:
if (r->data.size >= 0) {
return ipcSrv->CalculateGPUVmin();
}
break;
}
return SYSCLK_ERROR(Generic);
@@ -377,13 +372,13 @@ Result IpcService::SetReverseNXRTMode(ReverseNXMode mode) {
Result IpcService::SetKipData() {
this->clockMgr->SetKipData();
return 0;
}
Result IpcService::GetKipData() {
this->clockMgr->GetKipData();
return 0;
}
@@ -392,8 +387,3 @@ Result IpcService::UpdateEmcRegs() {
return 0;
}
Result IpcService::CalculateGPUVmin() {
this->clockMgr->calculateGpuVmin();
return 0;
}

View File

@@ -12,9 +12,9 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#pragma once
#include <switch.h>
@@ -28,7 +28,7 @@
typedef struct {
u8 cust[4];
u32 custRev;
u32 mtcConf;
u32 placeholder;
u32 hpMode;
u32 commonEmcMemVolt;
u32 eristaEmcMaxClock;
@@ -77,7 +77,11 @@ typedef struct {
u32 eristaGpuVoltArray[27];
u32 marikoGpuVoltArray[24];
u32 reserved[64];
u32 t6_tRTW_fine_tune;
u32 t7_tWTR_fine_tune;
u32 reserved[60];
} CustomizeTable;
#pragma pack(pop)
@@ -183,7 +187,7 @@ static inline bool cust_read_and_cache(const char* path, CustomizeTable* out) {
} while (0)
static inline bool cust_set_cust_rev(const char* p, u32 v) { CUST_WRITE_FIELD(p, custRev, v); }
static inline bool cust_set_mtc_conf(const char* p, u32 v) { CUST_WRITE_FIELD(p, mtcConf, v); }
// static inline bool cust_set_mtc_conf(const char* p, u32 v) { CUST_WRITE_FIELD(p, mtcConf, v); }
static inline bool cust_set_hp_mode(const char* p, u32 v) { CUST_WRITE_FIELD(p, hpMode, v); }
static inline bool cust_set_common_emc_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonEmcMemVolt, v); }
@@ -200,6 +204,8 @@ static inline bool cust_set_tRFC(const char* p, u32 v) { CUST_WRITE_FIELD(p, t5_
static inline bool cust_set_tRTW(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW, v); }
static inline bool cust_set_tWTR(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR, v); }
static inline bool cust_set_tREFI(const char* p, u32 v) { CUST_WRITE_FIELD(p, t8_tREFI, v); }
static inline bool cust_set_tRTW_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW_fine_tune, v); }
static inline bool cust_set_tWTR_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR_fine_tune, v); }
static inline bool cust_set_burst_read_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_read_latency, v); }
static inline bool cust_set_burst_write_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_write_latency, v); }
@@ -250,7 +256,7 @@ static inline u32 cust_get_field(const CustomizeTable* t, u32 offset) {
#define CUST_GET_FIELD(table, field) ((table) ? (table)->field : 0)
static inline u32 cust_get_cust_rev(const CustomizeTable* t) { return CUST_GET_FIELD(t, custRev); }
static inline u32 cust_get_mtc_conf(const CustomizeTable* t) { return CUST_GET_FIELD(t, mtcConf); }
// static inline u32 cust_get_mtc_conf(const CustomizeTable* t) { return CUST_GET_FIELD(t, mtcConf); }
static inline u32 cust_get_hp_mode(const CustomizeTable* t) { return CUST_GET_FIELD(t, hpMode); }
static inline u32 cust_get_common_emc_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonEmcMemVolt); }
@@ -267,6 +273,8 @@ static inline u32 cust_get_tRFC(const CustomizeTable* t) { return CUST_GET_FIELD
static inline u32 cust_get_tRTW(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW); }
static inline u32 cust_get_tWTR(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR); }
static inline u32 cust_get_tREFI(const CustomizeTable* t) { return CUST_GET_FIELD(t, t8_tREFI); }
static inline u32 cust_get_tRTW_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW_fine_tune); }
static inline u32 cust_get_tWTR_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR_fine_tune); }
static inline u32 cust_get_burst_read_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_read_latency); }
static inline u32 cust_get_burst_write_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_write_latency); }

View File

@@ -28,6 +28,7 @@
#include "process_management.h"
#include "file_utils.h"
#include "errors.h"
#define IS_QLAUNCH 0x20f
void ProcessManagement::Initialize()
{
@@ -47,7 +48,7 @@ void ProcessManagement::WaitForQLaunch()
do
{
rc = pmdmntGetProcessId(&pid, PROCESS_MANAGEMENT_QLAUNCH_TID);
svcSleepThread(500000000ULL);
svcSleepThread(50 * 1000000ULL); // 50ms
} while (R_FAILED(rc));
}
@@ -58,7 +59,7 @@ std::uint64_t ProcessManagement::GetCurrentApplicationId()
std::uint64_t tid = 0;
rc = pmdmntGetApplicationProcessId(&pid);
if (rc == 0x20f)
if (rc == IS_QLAUNCH)
{
return PROCESS_MANAGEMENT_QLAUNCH_TID;
}
@@ -67,7 +68,7 @@ std::uint64_t ProcessManagement::GetCurrentApplicationId()
rc = pminfoGetProgramId(&tid, pid);
if (rc == 0x20f)
if (rc == IS_QLAUNCH)
{
return PROCESS_MANAGEMENT_QLAUNCH_TID;
}

13
dist/README.md vendored
View File

@@ -41,10 +41,8 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to
* Built-in configurator
* Compatible with most homebrew
> *Higher (potentially dangerous) frequencies are unlockable via configuration.*
> *Erista and Mariko units can usually push a bit further fully safely with a bit of undervolting, however this may not work on all units.*
> *The exact maximum overclock possible varies per console, although most consoles should be able to do this safely.*
> *You may refer to the Clock Table to see clocks in more detail*
> It is reccomended to read the [guide](https://rentry.co/howtoget60fps) before proceeding, as this can help you get a *significant* performance boost over the default settings, often times with less power draw and heat output
---
## Installation
@@ -91,15 +89,15 @@ Refer to COMPILATION.md
* 1866 → mariko safe max (3733 Modules), JEDEC.
* 1600 → official docked, boost mode, erista safe max, JEDEC.
* 1331 → official handheld, JEDEC.
* 1065
* 1065
* 800
* 665
### CPU clocks
* 2601 → mariko absolute max, very dangerous
* 2499
* 2397
* 2295 → mariko safe max with UV (low speedo)
* 2397 → mariko safe max with UV (low speedo)
* 2295
* 2193
* 2091
* 1963 → mariko no UV max clock
@@ -153,6 +151,7 @@ Refer to COMPILATION.md
* **Souldbminer** hoc-clk and loader development
* **Lightos** loader patches development
* **SciresM** - Atmosphere CFW
* **CTCaer** - L4T, Hekate, perfect ram timings
* **KazushiMe** Switch OC Suite
* **hanai3bi (meha)** Switch OC Suite, EOS, sys-clk-eos
* **NaGaa95** L4T-OC-kernel

Binary file not shown.

Binary file not shown.

Binary file not shown.