From 8285e84071656c46049b8177eb9f845befabeda1 Mon Sep 17 00:00:00 2001 From: KazushiM <85604869+KazushiMe@users.noreply.github.com> Date: Thu, 2 Feb 2023 17:13:52 +0800 Subject: [PATCH] Maximum RAM frequency will not be used automatically --- .../stratosphere/loader/source/oc/ptm/ptm.cpp | 21 ++---------- .../sys-clk-OC/common/src/apm_profile_table.c | 32 +++++++++---------- .../sysmodule/src/clock_manager.cpp | 4 +-- Source/sys-clk-OC/sysmodule/src/clocks.cpp | 8 ++--- Source/sys-clk-OC/sysmodule/src/clocks.h | 6 ++-- pages/dist/main.js | 2 +- pages/src/main.ts | 6 ++-- 7 files changed, 32 insertions(+), 47 deletions(-) diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp index 9cecb100..29f6de57 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp @@ -30,19 +30,7 @@ Result CpuPtmBoost(perf_conf_entry* entry) { R_SUCCEED(); } -Result MemPtmMax(perf_conf_entry* entry) { - if (!C.marikoEmcMaxClock) - R_SUCCEED(); - - u32 memPtmMax = C.marikoEmcMaxClock * 1000; - - PatchOffset(&(entry->emc_freq_1), memPtmMax); - PatchOffset(&(entry->emc_freq_2), memPtmMax); - - R_SUCCEED(); -} - -Result MemPtmAlt(perf_conf_entry* entry) { +Result MemPtm(perf_conf_entry* entry) { PatchOffset(&(entry->emc_freq_1), memPtmLimit); PatchOffset(&(entry->emc_freq_2), memPtmLimit); @@ -89,8 +77,7 @@ void Patch(uintptr_t mapped_nso, size_t nso_size) { PatcherEntry patches[] = { { "CPU Ptm Boost", &CpuPtmBoost, 2, }, - { "MEM Ptm Max", &MemPtmMax, 9, }, - { "MEM Ptm Alt", &MemPtmAlt, 7, }, + { "MEM Ptm", &MemPtm, 16, }, }; for (u32 i = 0; i < entryCnt; i++) { @@ -115,11 +102,9 @@ void Patch(uintptr_t mapped_nso, size_t nso_size) { switch (entry->emc_freq_1) { case memPtmLimit: - patches[1].Apply(entry); - break; case memPtmAlt: case memPtmClamp: - patches[2].Apply(entry); + patches[1].Apply(entry); break; default: LOGGING("%u (0x%08x) @%p", entry->emc_freq_1, entry->conf_id, &(entry->emc_freq_2)); diff --git a/Source/sys-clk-OC/common/src/apm_profile_table.c b/Source/sys-clk-OC/common/src/apm_profile_table.c index 2e0ff9be..7439ff1a 100644 --- a/Source/sys-clk-OC/common/src/apm_profile_table.c +++ b/Source/sys-clk-OC/common/src/apm_profile_table.c @@ -11,22 +11,22 @@ #include SysClkApmConfiguration sysclk_g_apm_configurations[] = { - {0x00010000, 1020000000, 384000000, 1862400000}, - {0x00010001, 1020000000, 768000000, 1862400000}, - {0x00010002, 1224000000, 691200000, 1862400000}, - {0x00020000, 1020000000, 230400000, 1862400000}, - {0x00020001, 1020000000, 307200000, 1862400000}, - {0x00020002, 1224000000, 230400000, 1862400000}, - {0x00020003, 1020000000, 307200000, 1600000000}, - {0x00020004, 1020000000, 384000000, 1600000000}, - {0x00020005, 1020000000, 307200000, 1600000000}, - {0x00020006, 1020000000, 384000000, 1600000000}, - {0x92220007, 1020000000, 460800000, 1862400000}, - {0x92220008, 1020000000, 460800000, 1600000000}, - {0x92220009, 1785000000, 76800000, 1862400000}, - {0x9222000A, 1785000000, 76800000, 1600000000}, - {0x9222000B, 1020000000, 76800000, 1862400000}, - {0x9222000C, 1020000000, 76800000, 1600000000}, + {0x00010000, 1020000000, 384000000, 1600000000}, + {0x00010001, 1020000000, 768000000, 1600000000}, + {0x00010002, 1224000000, 691200000, 1600000000}, + {0x00020000, 1020000000, 230400000, 1600000000}, + {0x00020001, 1020000000, 307200000, 1600000000}, + {0x00020002, 1224000000, 230400000, 1600000000}, + {0x00020003, 1020000000, 307000000, 1331200000}, + {0x00020004, 1020000000, 384000000, 1331200000}, + {0x00020005, 1020000000, 307200000, 1065600000}, + {0x00020006, 1020000000, 384000000, 1065600000}, + {0x92220007, 1020000000, 460800000, 1600000000}, + {0x92220008, 1020000000, 460800000, 1331200000}, + {0x92220009, 1785000000, 76800000, 1600000000}, + {0x9222000A, 1785000000, 76800000, 1331200000}, + {0x9222000B, 1020000000, 76800000, 1600000000}, + {0x9222000C, 1020000000, 76800000, 1331200000}, {0, 0, 0, 0}, }; diff --git a/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp b/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp index 87236aad..2f5b15b3 100644 --- a/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp +++ b/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp @@ -113,9 +113,7 @@ uint32_t ClockManager::GetHz(SysClkModule module) 768'000'000 : 460'800'000; break; case SysClkModule_MEM: - hz = (mode == ReverseNX_Docked || - this->oc->realProfile == SysClkProfile_Docked) ? - Clocks::maxMemFreq : 1600'000'000; + hz = MEM_CLOCK_DOCK; break; default: break; diff --git a/Source/sys-clk-OC/sysmodule/src/clocks.cpp b/Source/sys-clk-OC/sysmodule/src/clocks.cpp index e6d7e257..795d1f6a 100644 --- a/Source/sys-clk-OC/sysmodule/src/clocks.cpp +++ b/Source/sys-clk-OC/sysmodule/src/clocks.cpp @@ -251,7 +251,7 @@ uint32_t Clocks::GetStockClock(SysClkApmConfiguration* apm, SysClkModule module) case SysClkModule_GPU: return apm->gpu_hz; case SysClkModule_MEM: - return apm->mem_hz; + return GetIsMariko() ? MEM_CLOCK_MARIKO_MIN : apm->mem_hz; default: ERROR_THROW("Unknown SysClkModule: %x", module); return 0; @@ -270,15 +270,15 @@ void Clocks::ResetToStock(unsigned int module) if (module == SysClkModule_EnumMax || module == SysClkModule_CPU) { - Clocks::SetHz(SysClkModule_CPU, apmConfiguration->cpu_hz); + Clocks::SetHz(SysClkModule_CPU, GetStockClock(apmConfiguration, SysClkModule_CPU)); } if (module == SysClkModule_EnumMax || module == SysClkModule_GPU) { - Clocks::SetHz(SysClkModule_GPU, apmConfiguration->gpu_hz); + Clocks::SetHz(SysClkModule_GPU, GetStockClock(apmConfiguration, SysClkModule_GPU)); } if (module == SysClkModule_EnumMax || module == SysClkModule_MEM) { - Clocks::SetHz(SysClkModule_MEM, apmConfiguration->mem_hz); + Clocks::SetHz(SysClkModule_MEM, GetStockClock(apmConfiguration, SysClkModule_MEM)); } } else diff --git a/Source/sys-clk-OC/sysmodule/src/clocks.h b/Source/sys-clk-OC/sysmodule/src/clocks.h index 0d1319c6..130be6c6 100644 --- a/Source/sys-clk-OC/sysmodule/src/clocks.h +++ b/Source/sys-clk-OC/sysmodule/src/clocks.h @@ -13,8 +13,10 @@ #include #include -#define MAX_MEM_CLOCK 1862'400'000 -#define BOOST_THRESHOLD 95'0 +#define MAX_MEM_CLOCK 1862'400'000 +#define MEM_CLOCK_MARIKO_MIN 1600'000'000 +#define MEM_CLOCK_DOCK 1600'000'000 +#define BOOST_THRESHOLD 95'0 class Clocks { diff --git a/pages/dist/main.js b/pages/dist/main.js index 15df399c..1d9ec3f8 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",(()=>{JSON.parse(localStorage.getItem("last_saved")).filter((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,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()})))); diff --git a/pages/src/main.ts b/pages/src/main.ts index 2a2eba4c..e37ae917 100644 --- a/pages/src/main.ts +++ b/pages/src/main.ts @@ -392,9 +392,9 @@ function UpdateHTMLForm() { last_btn.removeAttribute("disabled"); last_btn.addEventListener('click', () => { // Load last saved from localStorage - JSON.parse(localStorage.getItem("last_saved")!) - .filter((key: string) => key != "custRev") - .forEach((key: string) => (document.getElementById(key) as HTMLInputElement).value = key); + let dict = JSON.parse(localStorage.getItem("last_saved")!); + delete dict["custRev"]; + dict.forEach((key: string) => (document.getElementById(key) as HTMLInputElement).value = key); }); } else { last_btn.style.setProperty("display", "none");