From 63bbde2f58e8565e33976c970d65178e05242ce9 Mon Sep 17 00:00:00 2001 From: KazushiM <85604869+KazushiMe@users.noreply.github.com> Date: Sun, 12 Feb 2023 23:55:54 +0800 Subject: [PATCH] pages: cleanup --- README.md | 23 - .../sys-clk-OC/common/include/sysclk/clocks.h | 35 +- .../overlay/src/ui/gui/app_profile_gui.cpp | 10 +- Source/sys-clk-OC/sysmodule/src/oc_extra.cpp | 21 +- Source/sys-clk-OC/sysmodule/src/oc_extra.h | 2 +- pages/build.sh | 2 +- pages/dist/index.html | 2 +- pages/dist/main.js | 2 +- pages/src/index.html | 304 ++++---- pages/src/main.ts | 686 +++++++++--------- 10 files changed, 571 insertions(+), 516 deletions(-) diff --git a/README.md b/README.md index 65cd25cf..b369c33c 100644 --- a/README.md +++ b/README.md @@ -80,29 +80,6 @@ Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW. 5. Hekate-ipl bootloader Only - Add `kip1=atmosphere/kips/loader.kip` to boot entry section in `bootloader/hekate_ipl.ini`. -
- Deprecated: patching sysmodules manually - - - This method is only served as reference as it could damage your MMC file system if not handled properly. - - - Patched sysmodules would be persistent until pcv or ptm was updated in new HOS (normally in `x.0.0`). - - - Tools: - - Lockpick_RCM - - TegraExplorer - - [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) - - 1. Dump `prod.keys` with Lockpick_RCM - 2. Dump HOS firmware with TegraExplorer - 3. Configure and run `test_patch.sh` to generate patched pcv & ptm sysmodules in nca - 4. Replace nca in `SYSTEM:/Contents/registered/` with TegraExplorer - 5. `ValidateAcidSignature()` should be stubbed to allow unsigned sysmodules to load (a.k.a. `loader_patch`) - -
- ## Build diff --git a/Source/sys-clk-OC/common/include/sysclk/clocks.h b/Source/sys-clk-OC/common/include/sysclk/clocks.h index 8f3d6fe5..f8628be2 100644 --- a/Source/sys-clk-OC/common/include/sysclk/clocks.h +++ b/Source/sys-clk-OC/common/include/sysclk/clocks.h @@ -77,15 +77,46 @@ uint32_t GetModuleMaximumFreq(SysClkModule module); typedef enum { SysClkOcGovernorConfig_AllDisabled = 0, SysClkOcGovernorConfig_CPU_Shift = 0, - SysClkOcGovernorConfig_CPUOnly = 1, + SysClkOcGovernorConfig_CPUOnly = 1 << SysClkOcGovernorConfig_CPU_Shift, SysClkOcGovernorConfig_CPU = 1 << SysClkOcGovernorConfig_CPU_Shift, - SysClkOcGovernorConfig_GPU_Shift = 1 << SysClkOcGovernorConfig_CPU_Shift, + SysClkOcGovernorConfig_GPU_Shift = 1, SysClkOcGovernorConfig_GPUOnly = 1 << SysClkOcGovernorConfig_GPU_Shift, SysClkOcGovernorConfig_GPU = 1 << SysClkOcGovernorConfig_GPU_Shift, + SysClkOcGovernorConfig_AllEnabled = 3, SysClkOcGovernorConfig_Default = 3, SysClkOcGovernorConfig_Mask = 3, } SysClkOcGovernorConfig; +inline bool GetGovernorEnabled(SysClkOcGovernorConfig config, SysClkModule module) { + switch (module) { + case SysClkModule_CPU: + return (config >> SysClkOcGovernorConfig_CPU_Shift) & 1; + case SysClkModule_GPU: + return (config >> SysClkOcGovernorConfig_GPU_Shift) & 1; + case SysClkModule_MEM: + return false; + default: + return config != SysClkOcGovernorConfig_AllDisabled; + } +} + +inline SysClkOcGovernorConfig ToggleGovernor(SysClkOcGovernorConfig prev, SysClkModule module, bool state) { + uint8_t shift; + switch (module) { + case SysClkModule_CPU: + shift = SysClkOcGovernorConfig_CPU_Shift; + break; + case SysClkModule_GPU: + shift = SysClkOcGovernorConfig_GPU_Shift; + break; + case SysClkModule_MEM: + return prev; + default: + return state ? SysClkOcGovernorConfig_AllEnabled : SysClkOcGovernorConfig_AllDisabled; + } + return (SysClkOcGovernorConfig)((prev & ~(1 << shift)) | state << shift); +} + typedef struct { union { diff --git a/Source/sys-clk-OC/overlay/src/ui/gui/app_profile_gui.cpp b/Source/sys-clk-OC/overlay/src/ui/gui/app_profile_gui.cpp index 36811401..a1008444 100644 --- a/Source/sys-clk-OC/overlay/src/ui/gui/app_profile_gui.cpp +++ b/Source/sys-clk-OC/overlay/src/ui/gui/app_profile_gui.cpp @@ -74,10 +74,9 @@ void AppProfileGui::listUI() if (globalGovernorEnabled) { tsl::elm::ToggleListItem* cpuGovernorToggle = new tsl::elm::ToggleListItem("CPU Freq Governor", - (this->profileList->governorConfig >> SysClkOcGovernorConfig_CPU_Shift) & 1); + GetGovernorEnabled(this->profileList->governorConfig, SysClkModule_CPU)); cpuGovernorToggle->setStateChangedListener([this](bool state) { - this->profileList->governorConfig = - SysClkOcGovernorConfig((this->profileList->governorConfig & SysClkOcGovernorConfig_GPUOnly) | state << SysClkOcGovernorConfig_CPU_Shift); + this->profileList->governorConfig = ToggleGovernor(this->profileList->governorConfig, SysClkModule_CPU, state); Result rc = sysclkIpcSetProfiles(this->applicationId, this->profileList); if (R_FAILED(rc)) @@ -86,10 +85,9 @@ void AppProfileGui::listUI() this->listElement->addItem(cpuGovernorToggle); tsl::elm::ToggleListItem* gpuGovernorToggle = new tsl::elm::ToggleListItem("GPU Freq Governor", - (this->profileList->governorConfig >> SysClkOcGovernorConfig_GPU_Shift) & 1); + GetGovernorEnabled(this->profileList->governorConfig, SysClkModule_GPU)); gpuGovernorToggle->setStateChangedListener([this](bool state) { - this->profileList->governorConfig = - SysClkOcGovernorConfig((this->profileList->governorConfig & SysClkOcGovernorConfig_CPUOnly) | state << SysClkOcGovernorConfig_GPU_Shift); + this->profileList->governorConfig = ToggleGovernor(this->profileList->governorConfig, SysClkModule_GPU, state); Result rc = sysclkIpcSetProfiles(this->applicationId, this->profileList); if (R_FAILED(rc)) diff --git a/Source/sys-clk-OC/sysmodule/src/oc_extra.cpp b/Source/sys-clk-OC/sysmodule/src/oc_extra.cpp index 1c917db0..4e71b5a2 100644 --- a/Source/sys-clk-OC/sysmodule/src/oc_extra.cpp +++ b/Source/sys-clk-OC/sysmodule/src/oc_extra.cpp @@ -257,19 +257,6 @@ void GpuGovernor::Apply() { } -bool Governor::IsHandledByGovernor(SysClkModule module) { - switch (module) { - case SysClkModule_CPU: - return ((this->GetConfig() >> SysClkOcGovernorConfig_CPU_Shift) & 1); - case SysClkModule_GPU: - return ((this->GetConfig() >> SysClkOcGovernorConfig_GPU_Shift) & 1); - case SysClkModule_MEM: - return false; - default: - return this->GetConfig() != SysClkOcGovernorConfig_AllDisabled; - } -} - void Governor::SetConfig(SysClkOcGovernorConfig config) { if (m_config == config) return; @@ -342,16 +329,16 @@ void Governor::GovernorManager::ContextManager(void* args) { } uint32_t perf_conf = self->GetPerfConf(); - if ((gpuThrottled = apmExtIsBoostMode(perf_conf)) && (self->GetConfig() & SysClkOcGovernorConfig_GPU)) + if ((gpuThrottled = apmExtIsBoostMode(perf_conf)) && self->IsHandledByGovernor(SysClkModule_GPU)) self->m_gpu_gov->ApplyBoost(); - if ((cpuBoosted = apmExtIsCPUBoosted(perf_conf)) && (self->GetConfig() & SysClkOcGovernorConfig_CPU)) + if ((cpuBoosted = apmExtIsCPUBoosted(perf_conf)) && self->IsHandledByGovernor(SysClkModule_CPU)) self->m_cpu_gov->ApplyBoost(); } - if (!gpuThrottled && (self->GetConfig() & SysClkOcGovernorConfig_GPU)) + if (!gpuThrottled && self->IsHandledByGovernor(SysClkModule_GPU)) self->m_gpu_gov->Apply(); - if (!cpuBoosted && (self->GetConfig() & SysClkOcGovernorConfig_CPU)) + if (!cpuBoosted && self->IsHandledByGovernor(SysClkModule_CPU)) self->m_cpu_gov->Apply(); svcSleepThread(TICK_TIME_NS); diff --git a/Source/sys-clk-OC/sysmodule/src/oc_extra.h b/Source/sys-clk-OC/sysmodule/src/oc_extra.h index 8cec552b..3c227ef2 100644 --- a/Source/sys-clk-OC/sysmodule/src/oc_extra.h +++ b/Source/sys-clk-OC/sysmodule/src/oc_extra.h @@ -329,7 +329,7 @@ public: }; SysClkOcGovernorConfig GetConfig() { return m_config; }; - bool IsHandledByGovernor(SysClkModule module = SysClkModule_EnumMax); + inline bool IsHandledByGovernor(SysClkModule module) { return GetGovernorEnabled(this->GetConfig(), module); }; void SetConfig(SysClkOcGovernorConfig config); void SetPerfConf(uint32_t id); diff --git a/pages/build.sh b/pages/build.sh index 3fa553df..914ee38b 100755 --- a/pages/build.sh +++ b/pages/build.sh @@ -6,7 +6,7 @@ # README_HTML=`pandoc -f gfm -t html5 ../README.md` cp -Rf ./src/*.html ./tmp/ -tsc ./src/main.ts --outDir ./tmp/ -lib es2015,dom -t es2015 +tsc ./src/main.ts --outDir ./tmp/ -lib es2019,dom -t es2015 for FILE in ./tmp/*; do minify "${FILE}" > "./dist/${FILE/.\/tmp\/}" diff --git a/pages/dist/index.html b/pages/dist/index.html index c2c561ac..84edec66 100644 --- a/pages/dist/index.html +++ b/pages/dist/index.html @@ -1 +1 @@ -Switch OC Suite | Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW. Licensed under GPL v2.

Switch OC Suite

Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW. Licensed under GPL v2.

Read Me

🚨DISCLAIMER: THIS IS PROVIDED AS IS. USE AT YOUR OWN RISK!🚨

  • Overclocking in general will shorten the lifespan of some hardware components. YOU ARE RESPONSIBLE for any problem or potential damage if unsafe frequencies are ENABLED in sys-clk-OC. Issues like asking for bypassing limit will BE IGNORED OR CLOSED WITHOUT REPLY.
  • Due to HorizonOS design, instabilities from unsafe RAM clocks may cause filesystem corruption. Always make backup before enabling DRAM OC.
  • Features

    For Erista variant (HAC-001)
    • CPU Overclock (Safe: 1785 MHz)
      • Unsafe
        • Due to the limit of board power draw or power IC
        • Unlockable frequencies up to 2091 MHz
        • See README for sys-clk-OC
    • DRAM Overclock (Safe: 1862.4 MHz)
    For Mariko variant (HAC-001-01, HDH-001, HEG-001)
    • CPU / GPU Overclock (Safe: 1963 / 998 MHz)
      • Unsafe
        • Due to the limit of board power draw or power IC
        • Unlockable frequencies up to 2397 / 1305 MHz or 2295 / 1267 MHz
        • See README for sys-clk-OC
    • DRAM Overclock (Safe: 1996.8 MHz)
    Modded sys-clk and ReverseNX-RT
    • Auto CPU Boost
      • For faster game loading
      • Enable CPU Boost (1785 MHz) when CPU Core#3 (System Core) is stressed (mainly I/O operations).
      • Effective only when charger is connected.
    • CPU & GPU frequency governor (Experimental)
      • Adjust frequency based on load. Might decrease power draw but can introduce stutters. Can be turned off for specific titles.
    • Set charging current (100 mA - 2000 mA) and charging limit (20% - 100%)
      • Long-term use of charge limit may render the battery gauge inaccurate. Performing full cycles could help recalibration, or try battery_desync_fix_nx.
    • Global Profile
      • Designated a dummy title id 0xA111111111111111.
      • Priority: "Temp overrides" > "Application profile" > "Global profile" > "System default".
    • Sync ReverseNX Mode
      • No need to change clocks manually after toggling modes in ReverseNX (-RT and -Tool)
    System Settings (Optional)See system_settings.md

    Installation

    1. Download latest release.
    2. Copy all files in SdOut to the root of SD card.
    3. Grab x.x.x_loader.kip for your Atmosphere version, rename it to loader.kip and place it in /atmosphere/kips/.
    4. Customization via online loader configurator
      Default config
      DefaultsMarikoErista
      CPU OC2397 MHz Max2091 MHz Max
      CPU Boost1785 MHzN/A
      CPU Volt1235 mV Max1235 mV Max
      GPU OC1305 MHz MaxN/A
      RAM OC1996 MHz Max1862 MHz Max
      RAM VoltDisabledDisabled
      RAM TimingAuto-AdjustedDisabled
    5. Hekate-ipl bootloader Only
      • Add kip1=atmosphere/kips/loader.kip to boot entry section in bootloader/hekate_ipl.ini.
    Deprecated: patching sysmodules manually
    • This method is only served as reference as it could damage your MMC file system if not handled properly.
    • Patched sysmodules would be persistent until pcv or ptm was updated in new HOS (normally in x.0.0).
    • Tools:
    1. Dump prod.keys with Lockpick_RCM
    2. Dump HOS firmware with TegraExplorer
    3. Configure and run test_patch.sh to generate patched pcv & ptm sysmodules in nca
    4. Replace nca in SYSTEM:/Contents/registered/ with TegraExplorer
    5. ValidateAcidSignature() should be stubbed to allow unsigned sysmodules to load (a.k.a. loader_patch)
    How to build this project
    1. Grab necessary patches from the repo, then compile sys-clk, ReverseNX-RT and Atmosphere loader with devkitpro.
    2. Before compiling Atmosphere loader, run patch.py in Atmosphere/stratosphere/loader/source/ to insert oc module into loader sysmodule.
    3. When compilation is done, uncompress the kip to make it work with configurator: hactool -t kip1 Atmosphere/stratosphere/loader/out/nintendo_nx_arm64_armv8a/release/loader.kip --uncompress=./loader.kip

    Frequently Asked Questions

    How to enable unsafe frequencies in sys-clk-OC?
  • Above all else, you should know what "unsafe" means and issues might arise.
  • See the end of README in sys-clk-OC. Add this line allow_unsafe_freq=1 into /config/sys-clk/config.ini
  • I would like to bypass limit enforced in sys-clk to improve handheld performance without charger connected.
  • Never will it be implemented here, or work out of the box.
  • You have to modify the code yourself for your own use. If you are to share modified binaries you have made based on this project publicly, make sure to comply with GPL v2 licenses.
  • Configurator

    Configure frequencies and voltages to suit your hardware and preferences.

    +Switch OC Suite | Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW. Licensed under GPL v2.

    Switch OC Suite

    Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW. Licensed under GPL v2.

    README

    🚨DISCLAIMER: THIS IS PROVIDED AS IS. USE AT YOUR OWN RISK!🚨

    • Overclocking in general will shorten the lifespan of some hardware components. YOU ARE RESPONSIBLE for any problem or potential damage if unsafe frequencies are ENABLED in sys-clk-OC. Issues like asking for bypassing limit will BE IGNORED OR CLOSED WITHOUT REPLY.
    • Due to HorizonOS design, instabilities from unsafe RAM clocks may cause filesystem corruption. Always make backup before enabling DRAM OC.

    Features

    For Erista variant (HAC-001)
    • CPU Overclock (Safe: 1785 MHz)
      • Unsafe
        • Due to the limit of board power draw or power IC
        • Unlockable frequencies up to 2091 MHz
        • See README for sys-clk-OC
    • DRAM Overclock (Safe: 1862.4 MHz)
    For Mariko variant (HAC-001-01, HDH-001, HEG-001)
    • CPU / GPU Overclock (Safe: 1963 / 998 MHz)
      • Unsafe
        • Due to the limit of board power draw or power IC
        • Unlockable frequencies up to 2397 / 1305 MHz or 2295 / 1267 MHz
        • See README for sys-clk-OC
    • DRAM Overclock (Safe: 1996.8 MHz)
    Modded sys-clk and ReverseNX-RT
    • Auto CPU Boost
      • For faster game loading
      • Enable CPU Boost (1785 MHz) when CPU Core#3 (System Core) is stressed (mainly I/O operations).
      • Effective only when charger is connected.
    • CPU & GPU frequency governor (Experimental)
      • Adjust frequency based on load. Might decrease power draw but can introduce stutters. Can be turned off for specific titles.
    • Set charging current (100 mA - 2000 mA) and charging limit (20% - 100%)
      • Long-term use of charge limit may render the battery gauge inaccurate. Performing full cycles could help recalibration, or try battery_desync_fix_nx.
    • Global Profile
      • Designated a dummy title id 0xA111111111111111.
      • Priority: "Temp overrides" > "Application profile" > "Global profile" > "System default".
    • Sync ReverseNX Mode
      • No need to change clocks manually after toggling modes in ReverseNX (-RT and -Tool)
    System Settings (Optional)See system_settings.md

    Installation

    1. Download latest release.
    2. Copy all files in SdOut to the root of SD card.
    3. Grab x.x.x_loader.kip for your Atmosphere version, rename it to loader.kip and place it in /atmosphere/kips/.
    4. Customization via online loader configurator
      DefaultsMarikoErista
      CPU OC2397 MHz Max2091 MHz Max
      CPU Boost1785 MHzN/A
      CPU Volt1235 mV Max1235 mV Max
      GPU OC1305 MHz MaxN/A
      RAM OC1996 MHz Max1862 MHz Max
      RAM VoltDisabledDisabled
      RAM TimingAuto-AdjustedDisabled
    5. Hekate-ipl bootloader Only
      • Add kip1=atmosphere/kips/loader.kip to boot entry section in bootloader/hekate_ipl.ini.
    How to build this project
    1. Grab necessary patches from the repo, then compile sys-clk, ReverseNX-RT and Atmosphere loader with devkitpro.
    2. Before compiling Atmosphere loader, run patch.py in Atmosphere/stratosphere/loader/source/ to insert oc module into loader sysmodule.
    3. When compilation is done, uncompress the kip to make it work with configurator: hactool -t kip1 Atmosphere/stratosphere/loader/out/nintendo_nx_arm64_armv8a/release/loader.kip --uncompress=./loader.kip

    Frequently Asked Questions

    How to enable unsafe frequencies in sys-clk-OC?
    I would like to bypass limit enforced in sys-clk to improve handheld performance without charger connected.
    • Never will it be implemented here, or work out of the box.
    • You have to modify the code yourself for your own use. If you are to share modified binaries you have made based on this project publicly, make sure to comply with GPL v2 licenses.

    Configurator

    Configure frequencies and voltages to suit your hardware and preferences.

    diff --git a/pages/dist/main.js b/pages/dist/main.js index 1d9ec3f8..e2c49f65 100644 --- a/pages/dist/main.js +++ b/pages/dist/main.js @@ -1 +1 @@ -var __awaiter=this&&this.__awaiter||function(e,t,i,l){return new(i||(i=Promise))((function(a,n){function r(e){try{o(l.next(e))}catch(e){n(e)}}function s(e){try{o(l.throw(e))}catch(e){n(e)}}function o(e){var t;e.done?a(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(r,s)}o((l=l.apply(e,t||[])).next())}))};const CUST_REV=3;var buffer,CustPlatform;!function(e){e[e.Undefined=0]="Undefined",e[e.Erista=1]="Erista",e[e.Mariko=2]="Mariko",e[e.All=3]="All"}(CustPlatform||(CustPlatform={}));class CustEntry{constructor(e,t,i,l,a,n,r=[0,1e6],s=1,o=!0){this.id=e,this.name=t,this.platform=i,this.size=l,this.desc=a,this.defval=n,this.min=r[0],this.max=r[1],this.step=s,this.zeroable=o}validate(){let e=new ErrorToolTip(this.id);return e.clear(),Number.isNaN(this.value)||void 0===this.value?(e.setMsg("Invalid value: Not a number"),e.show(),!1):!(!this.zeroable||0!=this.value)||(this.valuethis.max?(e.setMsg(`Expected range: [${this.min}, ${this.max}], got ${this.value}.`),e.show(),!1):this.value%this.step==0||(e.setMsg(`${this.value} % ${this.step} ≠ 0`),e.show(),!1))}getInputElement(){return document.getElementById(this.id)}updateValueFromElement(){this.value=Number(this.getInputElement().value)}isAvailableFor(e){return e===CustPlatform.Undefined||this.platform===e||this.platform===CustPlatform.All}createElement(){let e=this.getInputElement();if(!e){let t=document.createElement("div");t.classList.add("grid","cust-element"),e=document.createElement("input"),e.min=String(this.zeroable?0:this.min),e.max=String(this.max),e.id=this.id,e.type="number",e.step=String(this.step);let i=document.createElement("label");i.setAttribute("for",this.id),i.innerHTML=this.name,i.appendChild(e),t.appendChild(i);let l=document.createElement("blockquote");l.innerHTML=this.desc,l.setAttribute("for",this.id),t.appendChild(l),document.getElementById("form").appendChild(t),new ErrorToolTip(this.id).addChangeListener()}e.value=String(this.value)}setElementDefaultValue(){document.getElementById(this.id).value=String(this.defval)}removeElement(){let e=this.getInputElement();e&&e.parentElement.parentElement.remove()}showElement(){let e=this.getInputElement();e&&e.parentElement.parentElement.style.removeProperty("display")}hideElement(){let e=this.getInputElement();e&&e.parentElement.parentElement.style.setProperty("display","none")}}var CustTable=[new CustEntry("mtcConf","DRAM Timing",CustPlatform.Mariko,2,"
  • 0: AUTO_ADJ_MARIKO_SAFE: Auto adjust timings for LPDDR4 ≤3733 Mbps specs, 8Gb density. (Default)
  • 1: AUTO_ADJ_MARIKO_4266: Auto adjust timings for LPDDR4X 4266 Mbps specs, 8Gb density.
  • 2: NO_ADJ_ALL: No timing adjustment for both Erista and Mariko. Might achieve better performance on Mariko but lower maximum frequency is expected.",0,[0,2],1),new CustEntry("marikoCpuMaxClock","Mariko CPU Max Clock in kHz",CustPlatform.Mariko,4,"
  • System default: 1785000
  • 2397000 might be unreachable for some SoCs.
  • ",2397e3,[1785e3,3e6],1),new CustEntry("marikoCpuBoostClock","Mariko CPU Boost Clock in kHz",CustPlatform.Mariko,4,"
  • System default: 1785000
  • Boost clock will be applied when applications request higher CPU frequency for quicker loading.
  • This will be set regardless of whether sys-clk is enabled.
  • ",1785e3,[102e4,3e6],1,!1),new CustEntry("marikoCpuMaxVolt","Mariko CPU Max Voltage in mV",CustPlatform.Mariko,4,"
  • System default: 1120
  • Acceptable range: 1100 ≤ x ≤ 1300
  • ",1235,[1100,1300],5),new CustEntry("marikoGpuMaxClock","Mariko GPU Max Clock in kHz",CustPlatform.Mariko,4,"
  • System default: 921600
  • Tegra X1+ official maximum: 1267200
  • 1305600 might be unreachable for some SoCs.
  • ",1305600,[768e3,1536e3],100),new CustEntry("marikoEmcMaxClock","Mariko RAM Max Clock in kHz",CustPlatform.Mariko,4,"
  • Values should be ≥ 1600000, and divided evenly by 3200.
  • WARNING: RAM overclock could be UNSTABLE if timing parameters are not suitable for your DRAM
  • ",1996800,[16e5,24e5],3200),new CustEntry("marikoEmcVddqVolt","EMC Vddq (Mariko Only) Voltage in uV",CustPlatform.Mariko,4,"
  • Acceptable range: 550000 ≤ x ≤ 650000
  • Value should be divided evenly by 5000
  • Default: 600000
  • Not enabled by default.
  • This will not work without sys-clk-OC.
  • ",0,[55e4,65e4],5e3),new CustEntry("eristaCpuMaxVolt","Erista CPU Max Voltage in mV",CustPlatform.Erista,4,"
  • Acceptable range: 1100 ≤ x ≤ 1300
  • ",1235,[1100,1300],1),new CustEntry("eristaEmcMaxClock","Erista RAM Max Clock in kHz",CustPlatform.Erista,4,"
  • Values should be ≥ 1600000, and divided evenly by 3200.
  • WARNING: RAM overclock could be UNSTABLE if timing parameters are not suitable for your DRAM
  • ",1862400,[16e5,24e5],3200),new CustEntry("commonEmcMemVolt","EMC Vddq (Erista Only) & RAM Vdd2 Voltage in uV",CustPlatform.All,4,"
  • Acceptable range: 1100000 ≤ x ≤ 1250000, and it should be divided evenly by 12500.
  • Erista Default (HOS): 1125000 (bootloader: 1100000)
  • Mariko Default: 1100000 (It will not work without sys-clk-OC)
  • Not enabled by default
  • ",0,[11e5,125e4],12500)];function FindMagicOffset(e){let t=new DataView(e);for(let e=0;e{let t=CustTable.filter((e=>e.id===this.id))[0];t.value=Number(this.element.value),t.validate()}))}}function SaveCust(e){let t=new DataView(e),i={};CustTable.forEach((e=>{if(e.updateValueFromElement(),!e.validate())throw document.getElementById(e.id).focus(),new Error(`Invalid ${e.name}`);if(!e.offset)throw document.getElementById(e.id).focus(),new Error(`Failed to get offset for ${e.name}`);switch(e.size){case 2:t.setUint16(e.offset,e.value,!0);break;case 4:t.setUint32(e.offset,e.value,!0);break;default:throw document.getElementById(e.id).focus(),new Error(`Unknown size at ${e.name}`)}i[e.id]=e.value})),i.custRev=3,localStorage.setItem("last_saved",JSON.stringify(i));let l=document.createElement("a");l.href=window.URL.createObjectURL(new Blob([e],{type:"application/octet-stream"})),l.download="loader.kip",l.click()}function LastSaved(){let e=localStorage.getItem("last_saved");if(!e)return!1;let t=JSON.parse(e);return!(!t.custRev||3!=t.custRev)||(localStorage.removeItem("last_saved"),!1)}function CustNavTabsInit(){const e=Array.from(document.querySelectorAll('nav[role="tab-control"] > button'));e.forEach((t=>{t.removeAttribute("disabled");let i=Number(t.getAttribute("data-filter"));t.addEventListener("click",(l=>{const a=["outline"];t.classList.remove(...a),e.filter((e=>e!=t)).forEach((e=>e.classList.add(...a))),CustTable.forEach((e=>{e.isAvailableFor(i)?e.showElement():e.hideElement()}))}))}))}function UpdateHTMLForm(){CustTable.forEach((e=>e.createElement()));let e=document.getElementById("load_default");e.removeAttribute("disabled"),e.addEventListener("click",(()=>{CustTable.forEach((e=>e.setElementDefaultValue()))}));let t=document.getElementById("load_saved");LastSaved()?(t.style.removeProperty("display"),t.removeAttribute("disabled"),t.addEventListener("click",(()=>{let e=JSON.parse(localStorage.getItem("last_saved"));delete e.custRev,e.forEach((e=>document.getElementById(e).value=e))}))):t.style.setProperty("display","none");let i=document.getElementById("save");i.removeAttribute("disabled"),i.addEventListener("click",(()=>{try{SaveCust(buffer)}catch(e){console.log(e),alert(e)}}))}function ParseCust(e,t){let i=new DataView(t),l=e+4,a=i.getUint16(l,!0);if(l+=2,3!=a)throw new Error(`Unsupported custRev, expected: 3, got ${a}`);document.getElementById("cust_rev").innerHTML="Cust V3 is loaded.",CustTable.forEach((e=>{switch(e.offset=l,e.size){case 2:e.value=i.getUint16(l,!0);break;case 4:e.value=i.getUint32(l,!0);break;default:throw document.getElementById(e.id).focus(),new Error("Unknown size at "+e)}l+=e.size,e.validate()}))}const fileInput=document.getElementById("file");function fetchRelease(){return __awaiter(this,void 0,void 0,(function*(){try{const e=yield fetch("https://api.github.com/repos/KazushiMe/Switch-OC-Suite/releases/latest",{method:"GET",headers:{Accept:"application/json"}});if(!e.ok)throw new Error(`Failed to fetch latest release info from GitHub: ${e.status}`);const t=yield e.json(),i=t.tag_name,l=i.split(".").slice(0,3).join("."),a=t.assets.filter((e=>e.name.endsWith("loader.kip")))[0],n=t.assets.filter((e=>e.name.endsWith(".zip")))[0],r=`https://github.com/Atmosphere-NX/Atmosphere/releases/tags/${l}`;return{OCSuiteVer:i,LoaderKipUrl:a.browser_download_url,LoaderKipTime:a.updated_at,SdOutZipUrl:n.browser_download_url,SdOutZipTime:n.updated_at,AMSVer:l,AMSUrl:r}}catch(e){console.log(e),alert(e)}}))}fileInput.addEventListener("change",(e=>{let t=new FileReader;t.readAsArrayBuffer(e.target.files[0]),t.onloadend=e=>{if(e.target.readyState===FileReader.DONE){buffer=e.target.result;try{let e=FindMagicOffset(buffer);CustTable.forEach((e=>e.removeElement())),ParseCust(e,buffer),CustNavTabsInit(),UpdateHTMLForm()}catch(e){console.log(e),alert(e),fileInput.value=""}}}}));const isElementVisible=e=>{let t=e.getBoundingClientRect();return t.top>0&&t.left>0&&t.bottom-t.height<(window.innerHeight||document.documentElement.clientHeight)&&t.right-t.width<(window.innerWidth||document.documentElement.clientWidth)};function updateDownloadUrls(){return __awaiter(this,void 0,void 0,(function*(){for(;!isElementVisible(document.getElementById("download_btn_grid"));)yield new Promise((e=>setTimeout(e,1e3)));const e=(e,t,i)=>{let l=document.getElementById(e);l.innerHTML=t,l.removeAttribute("aria-busy"),l.setAttribute("href",i)};let t=yield fetchRelease();if(t){e("loader_kip_btn",`loader.kip ${t.OCSuiteVer}
    ${t.LoaderKipTime}`,t.LoaderKipUrl);e("sdout_zip_btn",`SdOut.zip ${t.OCSuiteVer}
    ${t.SdOutZipTime}`,t.SdOutZipUrl);e("ams_btn",`Atmosphere-NX ${t.AMSVer}`,t.AMSUrl)}}))}addEventListener("DOMContentLoaded",(e=>__awaiter(this,void 0,void 0,(function*(){yield updateDownloadUrls()})))); +var __awaiter=this&&this.__awaiter||function(e,t,i,s){return new(i||(i=Promise))((function(a,l){function r(e){try{n(s.next(e))}catch(e){l(e)}}function o(e){try{n(s.throw(e))}catch(e){l(e)}}function n(e){var t;e.done?a(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(r,o)}n((s=s.apply(e,t||[])).next())}))};const CUST_REV=3;var CustPlatform;!function(e){e[e.Undefined=0]="Undefined",e[e.Erista=1]="Erista",e[e.Mariko=2]="Mariko",e[e.All=3]="All"}(CustPlatform||(CustPlatform={}));class CustEntry{constructor(e,t,i,s,a,l,r=[0,1e6],o=1,n=!0){this.id=e,this.name=t,this.platform=i,this.size=s,this.desc=a,this.defval=l,this.step=o,this.zeroable=n,this.min=r[0],this.max=r[1]}validate(){let e=new ErrorToolTip(this.id).clear();return Number.isNaN(this.value)||void 0===this.value?(e.setMsg("Invalid value: Not a number").show(),!1):!(!this.zeroable||0!=this.value)||(this.valuethis.max?(e.setMsg(`Expected range: [${this.min}, ${this.max}], got ${this.value}.`).show(),!1):this.value%this.step==0||(e.setMsg(`${this.value} % ${this.step} ≠ 0`).show(),!1))}getInputElement(){return document.getElementById(this.id)}updateValueFromElement(){var e;this.value=Number(null===(e=this.getInputElement())||void 0===e?void 0:e.value)}isAvailableFor(e){return e===CustPlatform.Undefined||this.platform===e||this.platform===CustPlatform.All}createElement(){let e=this.getInputElement();if(!e){let t=document.createElement("div");t.classList.add("grid","cust-element"),e=document.createElement("input"),e.min=String(this.zeroable?0:this.min),e.max=String(this.max),e.id=this.id,e.type="number",e.step=String(this.step);let i=document.createElement("label");i.setAttribute("for",this.id),i.innerHTML=this.name,i.appendChild(e),t.appendChild(i);let s=document.createElement("blockquote");s.innerHTML="
      "+this.desc.map((e=>`
    • ${e}
    • `)).join("")+"
    ",s.setAttribute("for",this.id),t.appendChild(s),document.getElementById("config-list-basic").appendChild(t),new ErrorToolTip(this.id).addChangeListener()}e.value=String(this.value)}setElementValue(){this.getInputElement().value=String(this.value)}setElementDefaultValue(){this.getInputElement().value=String(this.defval)}removeElement(){let e=this.getInputElement();e&&e.parentElement.parentElement.remove()}showElement(){let e=this.getInputElement();e&&e.parentElement.parentElement.style.removeProperty("display")}hideElement(){let e=this.getInputElement();e&&e.parentElement.parentElement.style.setProperty("display","none")}}var CustTable=[new CustEntry("mtcConf","DRAM Timing",CustPlatform.Mariko,2,["0: AUTO_ADJ_MARIKO_SAFE: Auto adjust timings for LPDDR4 ≤3733 Mbps specs, 8Gb density. (Default)","1: AUTO_ADJ_MARIKO_4266: Auto adjust timings for LPDDR4X 4266 Mbps specs, 8Gb density.","2: NO_ADJ_ALL: No timing adjustment for both Erista and Mariko. Might achieve better performance on Mariko but lower maximum frequency is expected."],0,[0,2],1),new CustEntry("marikoCpuMaxClock","Mariko CPU Max Clock in kHz",CustPlatform.Mariko,4,["System default: 1785000","2397000 might be unreachable for some SoCs."],2397e3,[1785e3,3e6],1),new CustEntry("marikoCpuBoostClock","Mariko CPU Boost Clock in kHz",CustPlatform.Mariko,4,["System default: 1785000","Boost clock will be applied when applications request higher CPU frequency for quicker loading.","This will be set regardless of whether sys-clk is enabled."],1785e3,[102e4,3e6],1,!1),new CustEntry("marikoCpuMaxVolt","Mariko CPU Max Voltage in mV",CustPlatform.Mariko,4,["System default: 1120","Acceptable range: 1100 ≤ x ≤ 1300"],1235,[1100,1300],5),new CustEntry("marikoGpuMaxClock","Mariko GPU Max Clock in kHz",CustPlatform.Mariko,4,["System default: 921600","Tegra X1+ official maximum: 1267200","1305600 might be unreachable for some SoCs."],1305600,[768e3,1536e3],100),new CustEntry("marikoEmcMaxClock","Mariko RAM Max Clock in kHz",CustPlatform.Mariko,4,["Values should be ≥ 1600000, and divided evenly by 3200.","WARNING: RAM overclock could be UNSTABLE if timing parameters are not suitable for your DRAM."],1996800,[16e5,24e5],3200),new CustEntry("marikoEmcVddqVolt","EMC Vddq (Mariko Only) Voltage in uV",CustPlatform.Mariko,4,["Acceptable range: 550000 ≤ x ≤ 650000","Value should be divided evenly by 5000","Default: 600000","Not enabled by default.","This will not work without sys-clk-OC."],0,[55e4,65e4],5e3),new CustEntry("eristaCpuMaxVolt","Erista CPU Max Voltage in mV",CustPlatform.Erista,4,["Acceptable range: 1100 ≤ x ≤ 1300"],1235,[1100,1300],1),new CustEntry("eristaEmcMaxClock","Erista RAM Max Clock in kHz",CustPlatform.Erista,4,["Values should be ≥ 1600000, and divided evenly by 3200.","WARNING: RAM overclock could be UNSTABLE if timing parameters are not suitable for your DRAM"],1862400,[16e5,24e5],3200),new CustEntry("commonEmcMemVolt","EMC Vddq (Erista Only) & RAM Vdd2 Voltage in uV",CustPlatform.All,4,["Acceptable range: 1100000 ≤ x ≤ 1250000, and it should be divided evenly by 12500.","Erista Default (HOS): 1125000 (bootloader: 1100000)","Mariko Default: 1100000 (It will not work without sys-clk-OC)","Not enabled by default"],0,[11e5,125e4],12500)];class ErrorToolTip{constructor(e,t){this.id=e,this.msg=t,this.id=e,this.element=document.getElementById(e),t&&this.setMsg(t)}setMsg(e){return this.msg=e,this}show(){var e,t,i,s,a,l;return null===(e=this.element)||void 0===e||e.setAttribute("aria-invalid","true"),this.msg&&(null===(t=this.element)||void 0===t||t.setAttribute("title",this.msg),null===(s=null===(i=this.element)||void 0===i?void 0:i.parentElement)||void 0===s||s.setAttribute("data-tooltip",this.msg),null===(l=null===(a=this.element)||void 0===a?void 0:a.parentElement)||void 0===l||l.setAttribute("data-placement","top")),this}clear(){var e,t,i,s,a,l;return null===(e=this.element)||void 0===e||e.removeAttribute("aria-invalid"),null===(t=this.element)||void 0===t||t.removeAttribute("title"),null===(s=null===(i=this.element)||void 0===i?void 0:i.parentElement)||void 0===s||s.removeAttribute("data-tooltip"),null===(l=null===(a=this.element)||void 0===a?void 0:a.parentElement)||void 0===l||l.removeAttribute("data-placement"),this}addChangeListener(){var e;null===(e=this.element)||void 0===e||e.addEventListener("change",(e=>{let t=CustTable.filter((e=>e.id===this.id))[0];t.value=Number(this.element.value),t.validate()}))}}class CustStorage{constructor(){this.storage={},this.key="last_saved"}updateFromTable(){CustTable.forEach((e=>{var t;if(e.updateValueFromElement(),!e.validate())throw null===(t=e.getInputElement())||void 0===t||t.focus(),new Error(`Invalid ${e.name}`)})),this.storage={};let e=Object.fromEntries(CustTable.map((e=>[e.id,e.value])));Object.keys(e).forEach((t=>this.storage[t]=e[t]))}setTable(){let e=Object.keys(this.storage);e.forEach((e=>CustTable.filter((t=>t.id==e))[0].value=this.storage[e])),CustTable.filter((t=>!e.includes(t.id))).forEach((e=>e.value=e.defval)),CustTable.forEach((e=>{var t;if(!e.validate())throw null===(t=e.getInputElement())||void 0===t||t.focus(),new Error(`Invalid ${e.name}`);e.setElementValue()}))}save(){localStorage.setItem(this.key,JSON.stringify(this.storage))}load(){let e=localStorage.getItem(this.key);if(!e)return null;let t=JSON.parse(e),i=CustTable.map((e=>e.id)),s=Object.keys(t).filter((e=>!i.includes(e)));return s.length&&console.log(`Ignored: ${s}`),Object.keys(t).filter((e=>i.includes(e))).forEach((e=>this.storage[e]=t[e])),this.storage}}class Cust{constructor(){this.storage=new CustStorage,this.magic=1414747459,this.magicLen=4,this.mapper={2:{get:e=>this.view.getUint16(e,!0),set:(e,t)=>this.view.setUint16(e,t,!0)},4:{get:e=>this.view.getUint32(e,!0),set:(e,t)=>this.view.setUint32(e,t,!0)}}}findMagicOffset(){this.view=new DataView(this.buffer);for(let e=0;e{var t,i;if(!e.offset)throw null===(t=e.getInputElement())||void 0===t||t.focus(),new Error(`Failed to get offset for ${e.name}`);let s=this.mapper[e.size];if(!s)throw null===(i=e.getInputElement())||void 0===i||i.focus(),new Error(`Unknown size at ${e.name}`);s.set(e.offset,e.value)})),this.storage.save();let e=document.createElement("a");e.href=window.URL.createObjectURL(new Blob([this.buffer],{type:"application/octet-stream"})),e.download="loader.kip",e.click(),this.toggleLoadLastSavedBtn(!0)}removeHTMLForm(){CustTable.forEach((e=>e.removeElement()))}toggleLoadLastSavedBtn(e){let t=document.getElementById("load_saved");e?(t.addEventListener("click",(()=>{this.storage.load()&&this.storage.setTable()})),t.style.removeProperty("display"),t.removeAttribute("disabled")):t.style.setProperty("display","none")}createHTMLForm(){CustTable.forEach((e=>e.createElement()));let e=document.getElementById("load_default");e.removeAttribute("disabled"),e.addEventListener("click",(()=>{CustTable.forEach((e=>e.setElementDefaultValue()))})),this.toggleLoadLastSavedBtn(null!==this.storage.load());let t=document.getElementById("save");t.removeAttribute("disabled"),t.addEventListener("click",(()=>{try{this.save()}catch(e){console.error(e),alert(e)}}))}initCustTabs(){const e=Array.from(document.querySelectorAll('nav[role="tablist"] > button'));e.forEach((t=>{t.removeAttribute("disabled");let i=Number(t.getAttribute("data-platform"));t.addEventListener("click",(s=>{const a=["outline"];t.classList.remove(...a),e.filter((e=>e!=t)).forEach((e=>e.classList.add(...a))),CustTable.forEach((e=>{e.isAvailableFor(i)?e.showElement():e.hideElement()}))}))}))}parse(){let e=this.beginOffset+this.magicLen,t=this.mapper[2].get(e);if(3!=t)throw new Error(`Unsupported custRev, expected: 3, got ${t}`);e+=2,document.getElementById("cust_rev").innerHTML="Cust v3 is loaded.",CustTable.forEach((t=>{var i;t.offset=e;let s=this.mapper[t.size];if(!s)throw null===(i=t.getInputElement())||void 0===i||i.focus(),new Error(`Unknown size at ${t}`);t.value=s.get(e),e+=t.size,t.validate()}))}load(e){try{this.buffer=e,this.findMagicOffset(),this.removeHTMLForm(),this.parse(),this.initCustTabs(),this.createHTMLForm()}catch(e){console.error(e),alert(e)}}}class ReleaseAsset{constructor(e){this.downloadUrl=e.browser_download_url,this.updatedAt=e.updated_at}}class ReleaseInfo{constructor(){this.ocLatestApi="https://api.github.com/repos/KazushiMe/Switch-OC-Suite/releases/latest"}load(){return __awaiter(this,void 0,void 0,(function*(){try{this.parseOcResponse(yield this.responseFromApi(this.ocLatestApi).catch())}catch(e){console.error(e),alert(e)}}))}responseFromApi(e){return __awaiter(this,void 0,void 0,(function*(){const t=yield fetch(e,{method:"GET",headers:{Accept:"application/json"}});if(t.ok)return yield t.json();throw new Error(`Failed to connect to "${e}": ${t.status}`)}))}parseOcResponse(e){this.ocVer=e.tag_name,this.amsVer=this.ocVer.split(".").slice(0,3).join("."),this.loaderKipAsset=new ReleaseAsset(e.assets.filter((e=>e.name.endsWith("loader.kip")))[0]),this.sdOutZipAsset=new ReleaseAsset(e.assets.filter((e=>e.name.endsWith(".zip")))[0]),this.amsUrl=`https://github.com/Atmosphere-NX/Atmosphere/releases/tags/${this.amsVer}`}}class DownloadSection{constructor(){this.element=document.getElementById("download_btn_grid")}load(){return __awaiter(this,void 0,void 0,(function*(){for(;!this.isVisible();)yield new Promise((e=>setTimeout(e,1e3)));const e=new ReleaseInfo;yield e.load(),this.update("loader_kip_btn",`loader.kip ${e.ocVer}
    ${e.loaderKipAsset.updatedAt}`,e.loaderKipAsset.downloadUrl),this.update("sdout_zip_btn",`SdOut.zip ${e.ocVer}
    ${e.sdOutZipAsset.updatedAt}`,e.sdOutZipAsset.downloadUrl),this.update("ams_btn",`Atmosphere-NX ${e.amsVer}`,e.amsUrl)}))}isVisible(){let e=this.element.getBoundingClientRect();return e.top>0&&e.left>0&&e.bottom-e.height<(window.innerHeight||document.documentElement.clientHeight)&&e.right-e.width<(window.innerWidth||document.documentElement.clientWidth)}update(e,t,i){let s=document.getElementById(e);s.innerHTML=t,s.removeAttribute("aria-busy"),s.setAttribute("href",i)}}const fileInput=document.getElementById("file");fileInput.addEventListener("change",(e=>{var t=new Cust;if(!e.target||!e.target.files)return;let i=new FileReader;i.readAsArrayBuffer(e.target.files[0]),i.onloadend=e=>{e.target.readyState==FileReader.DONE&&t.load(e.target.result)}})),addEventListener("DOMContentLoaded",(e=>__awaiter(this,void 0,void 0,(function*(){yield(new DownloadSection).load()})))); diff --git a/pages/src/index.html b/pages/src/index.html index 3b493623..73770d49 100644 --- a/pages/src/index.html +++ b/pages/src/index.html @@ -10,25 +10,59 @@ content="Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW. Licensed under GPL v2.">