loader: fix emc dvb
This commit is contained in:
@@ -412,78 +412,48 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result MemFreqDvbTable(u32 *ptr)
|
||||
{
|
||||
emc_dvb_dvfs_table_t *default_end = reinterpret_cast<emc_dvb_dvfs_table_t *>(ptr);
|
||||
emc_dvb_dvfs_table_t *new_start = default_end + 1;
|
||||
|
||||
Result MemFreqDvbTable(u32* ptr) {
|
||||
emc_dvb_dvfs_table_t* default_end = reinterpret_cast<emc_dvb_dvfs_table_t *>(ptr);
|
||||
emc_dvb_dvfs_table_t* new_start = default_end + 1;
|
||||
|
||||
// Validate existing table
|
||||
void *mem_dvb_table_head = reinterpret_cast<u8 *>(new_start) - sizeof(EmcDvbTableDefault);
|
||||
void* mem_dvb_table_head = reinterpret_cast<u8 *>(new_start) - sizeof(EmcDvbTableDefault);
|
||||
bool validated = std::memcmp(mem_dvb_table_head, EmcDvbTableDefault, sizeof(EmcDvbTableDefault)) == 0;
|
||||
R_UNLESS(validated, ldr::ResultInvalidDvbTable());
|
||||
|
||||
|
||||
if (C.marikoEmcMaxClock <= EmcClkOSLimit)
|
||||
R_SKIP();
|
||||
|
||||
int32_t voltAdd = 25 * C.marikoEmcDvbShift;
|
||||
|
||||
#define DVB_VOLT(zero, one, two) std::min(zero + voltAdd, 1050), std::min(one + voltAdd, 1025), std::min(two + voltAdd, 1000),
|
||||
|
||||
if (C.marikoEmcMaxClock < 1862400)
|
||||
{
|
||||
|
||||
int32_t voltAdd = 25*C.marikoEmcDvbShift;
|
||||
|
||||
#define DVB_VOLT(zero, one, two) std::min(zero+voltAdd, 1050), std::min(one+voltAdd, 1025), std::min(two+voltAdd, 1000),
|
||||
|
||||
if (C.marikoEmcMaxClock < 1862400) {
|
||||
std::memcpy(new_start, default_end, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
if (C.marikoEmcMaxClock < 2131200)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {1866000, {700, 675, 637,}};
|
||||
} else if (C.marikoEmcMaxClock < 2131200){
|
||||
emc_dvb_dvfs_table_t oc_table = { 1862400, { 700, 675, 650, } };
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
} else if (C.marikoEmcMaxClock < 2400000){
|
||||
emc_dvb_dvfs_table_t oc_table = { 2131200, { 725, 700, 675, } };
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
} else if (C.marikoEmcMaxClock < 2665600){
|
||||
emc_dvb_dvfs_table_t oc_table = { 2400000, { DVB_VOLT(750, 725, 700) } };
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
} else if (C.marikoEmcMaxClock < 2931200){
|
||||
emc_dvb_dvfs_table_t oc_table = { 2665600, { DVB_VOLT(775, 750, 725) } };
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
} else if (C.marikoEmcMaxClock < 3200000){
|
||||
emc_dvb_dvfs_table_t oc_table = { 2931200, { DVB_VOLT(800, 775, 750) } };
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
} else {
|
||||
emc_dvb_dvfs_table_t oc_table = { 3200000, { DVB_VOLT(800, 800, 775) } };
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 2400000)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {2133000, {725, 700, 650,}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 2533000)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {2400000, {DVB_VOLT(750, 725, 675)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 2666000)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {2533000, {DVB_VOLT(800, 775, 725)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 2800000)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {2666000, {DVB_VOLT(850, 825, 775)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 2933000)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {2800000, {DVB_VOLT(925, 850, 800)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 3066000)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {2933000, {DVB_VOLT(1000, 900, 875)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 3200000)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {3066000, {DVB_VOLT(1025, 950, 925)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {3200000, {DVB_VOLT(1050, 1025, 1000)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
|
||||
new_start->freq = C.marikoEmcMaxClock;
|
||||
/* Max dvfs entry is 32, but HOS doesn't seem to boot if exact freq doesn't exist in dvb table,
|
||||
reason why it's like this
|
||||
*/
|
||||
|
||||
reason why it's like this
|
||||
*/
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
BIN
docs/img1.png
Normal file
BIN
docs/img1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 156 KiB |
BIN
docs/img2.png
Normal file
BIN
docs/img2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
BIN
docs/img3.png
Normal file
BIN
docs/img3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 218 KiB |
382
docs/index.html
382
docs/index.html
@@ -1,219 +1,167 @@
|
||||
<!doctype html>
|
||||
<html lang=en>
|
||||
<meta charset=UTF-8>
|
||||
<meta name=viewport content="width=device-width,initial-scale=1">
|
||||
<title>Switch OC Suite 2 | "If Switch OC Suite is so good, then why isn't there a Switch OC Suite 2?".</title>
|
||||
<meta name=description content="If Switch OC Suite is so good, then why isn't there a Switch OC Suite 2?">
|
||||
<link rel=stylesheet href=https://unpkg.com/@picocss/pico@latest/css/pico.min.css>
|
||||
<style>
|
||||
#nav-list{display:none}#nav-popup{display:unset}@media (min-width:768px){#nav-list{display:unset}#nav-popup{display:none}}details[open]>summary:not([role]):not(:focus){color:unset}div.hero>nav.container-fluid{position:fixed;top:0;z-index:99;-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}div.hero>header{padding-top:6rem}button[role=tab]{border-radius:0;border-left-width:calc(var(--border-width)/ 2);border-right-width:calc(var(--border-width)/ 2)}button[role=tab]:first-child{border-top-left-radius:var(--border-radius);border-bottom-left-radius:var(--border-radius);border-left-width:var(--border-width)}button[role=tab]:last-child{border-top-right-radius:var(--border-radius);border-bottom-right-radius:var(--border-radius);border-right-width:var(--border-width)}button[role=tab]:not(.outline){pointer-events:none;cursor:default}div.cust-element{margin:1.5rem 0 1.5rem 0}div.cust-element>blockquote,div.cust-element>blockquote>ul{margin:0;font-size:calc(var(--font-size) * .8);color:var(--muted-color)}div#download_btn_grid>a{margin:.5rem 0}
|
||||
</style>
|
||||
<div class=hero>
|
||||
<nav class=container-fluid>
|
||||
<ul>
|
||||
<li><a href=#head class=contrast><b>Switch OC Suite 2</b></a></ul>
|
||||
<ul id=nav-popup>
|
||||
<li>
|
||||
<details role=list dir=rtl>
|
||||
<summary aria-haspopup=group role=link class=contrast>Jump to</summary>
|
||||
<ul role=group>
|
||||
<li><a href=#readme>README</a>
|
||||
<li><a href=#download>Download</a>
|
||||
<li><a href=#config>Configurator</a>
|
||||
<li><a href=https://github.com/souldbminersmwc/Switch-OC-Suite-2 target=_blank>GitHub repository</a></ul>
|
||||
</details>
|
||||
</ul>
|
||||
<ul id=nav-list>
|
||||
<li><a href=#readme>README</a>
|
||||
<li><a href=#download>Download</a>
|
||||
<li><a href=#config>Config</a>
|
||||
<li><a href=https://github.com/souldbminersmwc/Switch-OC-Suite-2 target=_blank>GitHub</a></ul>
|
||||
</nav>
|
||||
<header class=container>
|
||||
<hgroup>
|
||||
<h1>Switch OC Suite 2</h1>
|
||||
<h2><i>"If Switch OC Suite is so good, then why isn't there a Switch OC Suite 2?"</i>.</h2>
|
||||
</hgroup>
|
||||
</header>
|
||||
</div>
|
||||
<section aria-label=README id=readme>
|
||||
<div class=container>
|
||||
<article>
|
||||
<header>
|
||||
<hgroup>
|
||||
<h2>PLEASE READ ME!</h2>
|
||||
<h3>🚨DISCLAIMER: THIS IS PROVIDED AS IS. USE AT YOUR OWN RISK!🚨</h3>
|
||||
</hgroup>
|
||||
<ul>
|
||||
<li>Overclocking in general will shorten the lifespan of some hardware components. <strong>YOU ARE RESPONSIBLE for any problem or potential damage.</strong>
|
||||
<li>Due to Horizon OS's design, instabilities from unsafe RAM clocks may cause filesystem corruption. <strong>Always make backup before enabling DRAM OC.</strong></ul>
|
||||
</header>
|
||||
<h3>Features</h3>
|
||||
<details open>
|
||||
<summary>For Erista variant (HAC-001)</summary>
|
||||
<ul>
|
||||
<li>CPU Overclock (Safe: 1785 MHz)
|
||||
<ul>
|
||||
<li>Unsafe
|
||||
<ul>
|
||||
<li>Due to the limit of board power draw or power IC
|
||||
<li>Unlockable frequencies up to 2295 MHz
|
||||
<li>See <a href=https://github.com/souldbminersmwc/Switch-OC-Suite-2/blob/master/Source/sys-clk-OC/README.md target=_blank>README for sys-clk-OC</a></ul>
|
||||
</ul>
|
||||
<li>DRAM Overclock (Safe: 1862.4 MHz)</ul>
|
||||
</details>
|
||||
<details open>
|
||||
<summary>For Mariko variant (HAC-001-01, HDH-001, HEG-001)</summary>
|
||||
<ul>
|
||||
<li>CPU / GPU Overclock (Safe: 1963 / 1075 MHz)
|
||||
<ul>
|
||||
<li>Unsafe
|
||||
<ul>
|
||||
<li>Due to the limit of board power draw or power IC
|
||||
<li>Unlockable frequencies up to 2907 / 1536 MHz
|
||||
<li>See <a href=https://github.com/souldbminersmwc/Switch-OC-Suite-2/blob/master/Source/sys-clk-OC/README.md target=_blank>README for sys-clk-OC</a></ul>
|
||||
</ul>
|
||||
<li>DRAM Overclock (Safe: 1996.8 MHz)</ul>
|
||||
</details>
|
||||
<details open>
|
||||
<summary>Sys-CLK OC and ReverseNX-RT</summary>
|
||||
<ul>
|
||||
<li>Global Profile
|
||||
<ul>
|
||||
<li>Designated a dummy title id <code>0xA111111111111111</code>.
|
||||
<li>Priority: "Temp overrides" > "Application profile" > "Global profile" > "System default".</ul>
|
||||
</ul>
|
||||
</details>
|
||||
<details open>
|
||||
<summary>System Settings (Optional)</summary>See <a href=https://github.com/souldbminersmwc/Switch-OC-Suite-2/blob/master/system_settings.md>system_settings.md</a></details>
|
||||
<h3 id=installation open>Installation</h3>
|
||||
<ol type=1>
|
||||
<li>Download latest <a href=#download>release</a>.
|
||||
<li>Grab <code>x.x.x_loader.kip</code> for your Atmosphere version, rename it to <code>loader.kip</code> and place it in <code>/atmosphere/kips/</code>.
|
||||
<li>(optional) You can customize via <a href=#config>online loader configurator</a>
|
||||
<table role=grid>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Defaults
|
||||
<th>Mariko
|
||||
<th>Erista
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>CPU OC
|
||||
<td>2295 MHz Max
|
||||
<td>2091 MHz Max
|
||||
<tr>
|
||||
<td>CPU Boost
|
||||
<td>1785 MHz
|
||||
<td>N/A
|
||||
<tr>
|
||||
<td>CPU Volt
|
||||
<td>1235 mV Max
|
||||
<td>1235 mV Max
|
||||
<tr>
|
||||
<td>GPU OC
|
||||
<td>1152 MHz Max
|
||||
<td>998 MHz Max
|
||||
<tr>
|
||||
<td>RAM OC
|
||||
<td>1996 MHz
|
||||
<td>1862 MHz
|
||||
<tr>
|
||||
<td>RAM Volt
|
||||
<td>Disabled
|
||||
<td>Disabled
|
||||
<tr>
|
||||
<td>RAM Timing
|
||||
<td>Auto-Adjusted
|
||||
<td>Auto-Adjusted
|
||||
<tr>
|
||||
<td>CPU UV
|
||||
<td>Disabled
|
||||
<td>N/A
|
||||
<tr>
|
||||
<td>GPU UV
|
||||
<td>Disabled
|
||||
<td>N/A</table>
|
||||
<li>Hekate-ipl bootloader Only (fss0) (Not required for AMS fusee)
|
||||
<ul>
|
||||
<li>At boot entry section in <code>bootloader/hekate_ipl.ini</code>, Add <code>kip1=atmosphere/kips/*.kip</code> to any line that works.</ul>
|
||||
<li>Install [sys-clk-oc]<br>official [sys-clk] (2.0.0+) is compatible but not recommended (no bugfixes or additional features).
|
||||
<li>(optional) Copy SdOut.zip for useful utilities.</ol>
|
||||
<details>
|
||||
<summary>How to build this project</summary>
|
||||
<ol type=1>
|
||||
<li>Grab necessary patches from the repo, then compile sys-clk, ReverseNX-RT and Atmosphere loader with devkitpro.
|
||||
<li>Before compiling Atmosphere loader, run <code>patch.py</code> in <code>Atmosphere/stratosphere/loader/source/</code> to insert oc module into loader sysmodule.
|
||||
<li>Run cd stratosphere/loader then make to build the loader.kip</li>
|
||||
<li>When compilation is done, uncompress the kip to make it work with configurator: <code>hactool -t kip1 loader.kip --uncompress=loader.kip</code></ol>
|
||||
</details>
|
||||
<h3 id=faq>Frequently Asked Questions</h3>
|
||||
<details open>
|
||||
<summary>How to enable unsafe frequencies in sys-clk-OC?</summary>
|
||||
<ul>
|
||||
<li>Above all else, you should know <a href=#readme>what "unsafe" means and issues might arise</a>.
|
||||
<li>See the end of <a href=https://github.com/souldbminersmwc/Switch-OC-Suite-2/blob/master/Source/sys-clk-OC/README.md target=_blank>README in sys-clk-OC</a>. Place this line <code>allow_unsafe_freq=1</code> under <code>[values]</code> section in <code>/config/sys-clk/config.ini</code></ul>
|
||||
</details>
|
||||
<details open>
|
||||
<summary>I would like to bypass limit enforced in sys-clk to improve handheld performance without charger connected.</summary>
|
||||
<ul>
|
||||
<li>Bypassing clock cappings will be bad for battery.
|
||||
<li>See the end of <a href=https://github.com/souldbminersmwc/Switch-OC-Suite-2/blob/master/Source/sys-clk-OC/README.md target=_blank>README in sys-clk-OC</a>. Place this line <code>uncapped_clocks=1</code> under <code>[values]</code> section in <code>/config/sys-clk/config.ini</code></ul>
|
||||
</details>
|
||||
<footer>
|
||||
<details role=list>
|
||||
<summary aria-haspopup=group role=button class=secondary>Acknowledgement</summary>
|
||||
<ul role=group>
|
||||
<li><a href=https://github.com/CTCaer/hekate target=_blank>CTCaer for Hekate-ipl bootloader, RE and hardware research</a>
|
||||
<li><a href=https://devkitpro.org/ target=_blank>devkitPro for All-In-One homebrew toolchains</a>
|
||||
<li><a href=https://github.com/masagrator/ReverseNX-RT target=_blank>masagrator for ReverseNX-RT and info on BatteryChargeInfoFields in psm module</a>
|
||||
<li><a href=https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual target=_blank>Nvidia for Tegra X1 Technical Reference Manual</a>
|
||||
<li><a href=https://github.com/retronx-team/sys-clk target=_blank>RetroNX team for sys-clk</a>
|
||||
<li><a href=https://github.com/Atmosphere-NX/Atmosphere target=_blank>SciresM and Reswitched Team for the state-of-the-art Atmosphere CFW of Switch</a>
|
||||
<li><a href=http://switchbrew.org/wiki/ target=_blank>Switchbrew wiki for Switch in-depth info</a>
|
||||
<li><a href=https://gitlab.com/switchroot/kernel target=_blank>Switchroot for their modified L4T kernel and device tree</a>
|
||||
<li>ZatchyCatGames for RE and original OC loader patches for Atmosphere
|
||||
<li><a href=https://github.com/KazushiMe/Switch-OC-Suite target=_blank>KazushiMe for original Switch-OC-Suite</a>
|
||||
<li>lineon for research and help</ul>
|
||||
</details>
|
||||
</footer>
|
||||
</article>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Horizon OC - Switch Overclocking Tool</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
|
||||
<style>
|
||||
/* Background Image Cycling */
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: sans-serif;
|
||||
overflow-x: hidden;
|
||||
color: white;
|
||||
}
|
||||
.bg-slide {
|
||||
position: fixed;
|
||||
top: 0; left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
z-index: -2;
|
||||
opacity: 0;
|
||||
transition: opacity 2s ease-in-out;
|
||||
}
|
||||
.bg-slide.active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Gradient overlay that changes with image */
|
||||
.gradient-overlay {
|
||||
position: fixed;
|
||||
top: 0; left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
transition: background 2s ease-in-out;
|
||||
}
|
||||
|
||||
/* Pop-in effect */
|
||||
.popin {
|
||||
transform: scale(0.8);
|
||||
opacity: 0;
|
||||
transition: transform 0.6s ease, opacity 0.6s ease;
|
||||
}
|
||||
.popin.aos-animate {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Glassmorphism cards */
|
||||
.glass {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
/* Apple-style liquid glass buttons */
|
||||
.liquid-button {
|
||||
padding: 0.75rem 2rem;
|
||||
border-radius: 1.5rem;
|
||||
font-weight: 600;
|
||||
background: rgba(255,255,255,0.2);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255,255,255,0.3);
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.25), 0 4px 15px rgba(0,0,0,0.25);
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.liquid-button:hover {
|
||||
background: rgba(255,255,255,0.3);
|
||||
box-shadow: inset 0 2px 0 rgba(255,255,255,0.35), 0 6px 20px rgba(0,0,0,0.3);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="text-white">
|
||||
<!-- Background Images -->
|
||||
<div class="bg-slide" style="background-image: url('img1.png');"></div>
|
||||
<div class="bg-slide" style="background-image: url('img2.png');"></div>
|
||||
<div class="bg-slide" style="background-image: url('img3.png');"></div>
|
||||
|
||||
<!-- Gradient overlay -->
|
||||
<div class="gradient-overlay" id="gradient-overlay" style="background: linear-gradient(135deg, rgba(50,0,100,0.6), rgba(0,0,50,0.6));"></div>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<header class="text-center py-28 relative overflow-hidden popin" data-aos="popin">
|
||||
<h1 class="text-6xl font-extrabold mb-4 drop-shadow-lg">Horizon OC</h1>
|
||||
<p class="text-lg text-gray-200 mt-4">
|
||||
Upgrade the performance of your Nintendo Switch Console
|
||||
</p>
|
||||
<div class="mt-8 flex justify-center gap-6">
|
||||
<a href="#download" class="liquid-button">Download Now</a>
|
||||
<a href="benchmarks.html" class="liquid-button">View Benchmarks</a>
|
||||
</div>
|
||||
</section>
|
||||
<section aria-label=Download id=download>
|
||||
<div class=container>
|
||||
<article>
|
||||
<header>
|
||||
<hgroup>
|
||||
<h2>Download</h2>
|
||||
<h3>Get latest version of Switch OC Suite and its corresponding Atmosphere package here.</h3>
|
||||
</hgroup>
|
||||
</header>
|
||||
<div class=grid id=download_btn_grid><a role=button aria-busy=true id=loader_kip_btn>Generating link, please wait...</a> <a role=button aria-busy=true id=sdout_zip_btn>Generating link, please wait...</a> <a target=_blank role=button aria-busy=true id=ams_btn>Generating link, please wait...</a></div>
|
||||
<footer>See <a href=#installation>Installation section</a> for how to use Switch OC Suite.</footer>
|
||||
</article>
|
||||
</header>
|
||||
|
||||
<!-- About -->
|
||||
<section class="max-w-4xl mx-auto text-center py-20 px-6 popin" data-aos="popin" data-aos-delay="100">
|
||||
<h2 class="text-4xl font-bold mb-6">What is Horizon OC?</h2>
|
||||
<p class="text-gray-300 text-lg leading-relaxed">
|
||||
HOC is a tool to overclock your modded Nintendo Switch Console.
|
||||
This can help improve framrates, load times and latency in games.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Features -->
|
||||
<section class="py-20">
|
||||
<div class="max-w-6xl mx-auto px-6 grid md:grid-cols-3 gap-10">
|
||||
<div class="glass p-8 rounded-2xl shadow-xl hover:scale-105 transition popin" data-aos="popin" data-aos-delay="200">
|
||||
<h3 class="text-2xl font-semibold mb-3">⚡ Performance</h3>
|
||||
<p class="text-gray-300">Overclocking your console can lead to significantly better performance in demanding titles</p>
|
||||
</div>
|
||||
<div class="glass p-8 rounded-2xl shadow-xl hover:scale-105 transition popin" data-aos="popin" data-aos-delay="300">
|
||||
<h3 class="text-2xl font-semibold mb-3">☣ Safely</h3>
|
||||
<p class="text-gray-300">Horizon OC aims to be as safe as possible, while allowing advanced users to customize it further</p>
|
||||
</div>
|
||||
<div class="glass p-8 rounded-2xl shadow-xl hover:scale-105 transition popin" data-aos="popin" data-aos-delay="400">
|
||||
<h3 class="text-2xl font-semibold mb-3">🔧 Customizable</h3>
|
||||
<p class="text-gray-300">Horizon OC comes with a advanced configurator which allows you to customize it to your own needs</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section aria-label=Config id=config>
|
||||
<div class=container>
|
||||
<article>
|
||||
<header>
|
||||
<hgroup>
|
||||
<h2>Configurator</h2>
|
||||
<h3>Configure frequencies and voltages to suit your hardware and preferences.</h3>
|
||||
</hgroup>
|
||||
</header>
|
||||
<form id=form>
|
||||
<nav role=tablist><button type=button role=tab id=tab_all data-platform=0 disabled>All</button> <button type=button role=tab class=outline id=tab_erista data-platform=1 disabled>Erista</button> <button type=button role=tab class=outline id=tab_mariko data-platform=2 disabled>Mariko</button></nav><label for=file><input id=file type=file> <small id=cust_rev>Upload loader.kip here</small></label>
|
||||
<div id=config-list-basic></div>
|
||||
<div id=config-list-advanced></div>
|
||||
<div id=config-list-gpu></div>
|
||||
</form>
|
||||
<footer>
|
||||
<div class=grid><button type=button id=load_default role=button disabled>Load Default</button> <button type=button id=load_saved role=button disabled>Load Last Saved</button> <button type=submit id=save role=button disabled>Save</button></div>
|
||||
</footer>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
<footer class=container><small>Build with <a href=https://picocss.com target=_blank>Pico</a>. All trademarks, logos and brand names are the property of their respective owners, used for identification purposes only.</small></footer>
|
||||
<script src=./main.js></script>
|
||||
</section>
|
||||
|
||||
<!-- Download -->
|
||||
<section id="download" class="text-center py-24 popin" data-aos="popin" data-aos-delay="500">
|
||||
<h2 class="text-3xl font-bold mb-6">Get Horizon OC</h2>
|
||||
<a href="#" class="liquid-button">Download Latest Release</a>
|
||||
<p class="text-gray-400 mt-4">Ensure to use the latest version of Atmosphere</p>
|
||||
</section>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-black bg-opacity-60 text-center py-6 text-gray-500 text-sm popin" data-aos="popin">
|
||||
This website is open source!
|
||||
</footer>
|
||||
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script>
|
||||
AOS.init({ once: true, duration: 800 });
|
||||
|
||||
// Background image cycling with gradient
|
||||
const slides = document.querySelectorAll('.bg-slide');
|
||||
const gradientOverlay = document.getElementById('gradient-overlay');
|
||||
|
||||
const gradients = [
|
||||
'linear-gradient(135deg, rgba(80,0,150,0.6), rgba(0,0,60,0.6))',
|
||||
'linear-gradient(135deg, rgba(150,50,0,0.6), rgba(50,0,0,0.6))',
|
||||
'linear-gradient(135deg, rgba(0,100,150,0.6), rgba(0,30,50,0.6))'
|
||||
];
|
||||
|
||||
let current = 0;
|
||||
function cycleBg() {
|
||||
slides.forEach((s,i)=>s.classList.remove('active'));
|
||||
slides[current].classList.add('active');
|
||||
gradientOverlay.style.background = gradients[current];
|
||||
current = (current+1)%slides.length;
|
||||
}
|
||||
cycleBg();
|
||||
setInterval(cycleBg, 6000); // every 6s
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
492
docs/main.js
492
docs/main.js
@@ -1,492 +0,0 @@
|
||||
var __awaiter = this && this.__awaiter || function(e, t, i, n) {
|
||||
return new(i || (i = Promise))((function(a, r) {
|
||||
function s(e) {
|
||||
try {
|
||||
o(n.next(e))
|
||||
} catch (e) {
|
||||
r(e)
|
||||
}
|
||||
}
|
||||
|
||||
function l(e) {
|
||||
try {
|
||||
o(n.throw(e))
|
||||
} catch (e) {
|
||||
r(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(s, l)
|
||||
}
|
||||
o((n = n.apply(e, t || [])).next())
|
||||
}))
|
||||
};
|
||||
const CUST_REV_ADV = 2;
|
||||
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, n, a, r, s = [0, 1e6], l = 1, o = !0) {
|
||||
this.id = e, this.name = t, this.platform = i, this.size = n, this.desc = a, this.defval = r, this.step = l, this.zeroable = o, this.min = s[0], this.max = s[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.value < this.min || this.value > this.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 n = document.createElement("blockquote");
|
||||
n.innerHTML = "<ul>" + this.desc.map((e => `<li>${e}</li>`)).join("") + "</ul>", n.setAttribute("for", this.id), t.appendChild(n), 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")
|
||||
}
|
||||
}
|
||||
class AdvEntry extends CustEntry {
|
||||
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 n = document.createElement("blockquote");
|
||||
n.innerHTML = "<ul>" + this.desc.map((e => `<li>${e}</li>`)).join("") + "</ul>", n.setAttribute("for", this.id), t.appendChild(n), document.getElementById("config-list-advanced").appendChild(t), new ErrorToolTip(this.id).addChangeListener()
|
||||
}
|
||||
e.value = String(this.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class GpuEntry extends CustEntry {
|
||||
constructor(e, t, i = CustPlatform.Mariko, n = 4, a = ["range: vMin ≤ x ≤ 960 (Zero is disabled)"], r = 480, s = [0, 960], l = 5, o = !1) {
|
||||
super(e, t, i, n, a, r, s, l, o), this.id = e, this.name = t, this.platform = i, this.size = n, this.desc = a, this.defval = r, this.step = l, this.zeroable = o
|
||||
}
|
||||
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 n = document.createElement("blockquote");
|
||||
n.innerHTML = "<ul>" + this.desc.map((e => `<li>${e}</li>`)).join("") + "</ul>", n.setAttribute("for", this.id), t.appendChild(n), document.getElementById("config-list-gpu").appendChild(t), new ErrorToolTip(this.id).addChangeListener()
|
||||
}
|
||||
e.value = String(this.value)
|
||||
}
|
||||
}
|
||||
var CustTable = [
|
||||
new CustEntry("mtcConf", "DRAM Timing", CustPlatform.All, 4, [
|
||||
"<b>0</b>: AUTO_ADJ_ALL: Auto adjust mtc table with LPDDR4 3733 Mbps specs, 8Gb density. Change timing with Advanced Config (Default)",
|
||||
"<b>1</b>: CUSTOM_ADJ_ALL: Adjust only non-zero preset timings in Advanced Config",
|
||||
"<b>2</b>: NO_ADJ_ALL: Use 1600 mtc table wihout adjusting (Timing becomes tighter if you raise dram clock)."
|
||||
], 0, [0, 2], 1),
|
||||
|
||||
new CustEntry("commonCpuBoostClock", "Boost Clock in kHz", CustPlatform.All, 4, [
|
||||
"System default: 1785000",
|
||||
"Boost clock will be applied when applications request Boost Mode via performance configuration."
|
||||
], 1785000, [204000, 2907000], 1, !1),
|
||||
|
||||
new CustEntry("commonEmcMemVolt", "EMC Vdd2 Voltage in uV", CustPlatform.All, 4, [
|
||||
"Acceptable range: 1100000 ≤ x ≤ 1250000, and it should be divided evenly by 12500.",
|
||||
"Erista Default: 1175000",
|
||||
"Mariko Default: 1175000",
|
||||
"Official LPDDR4(X) voltage: 1175mV (1175mV nominal)"
|
||||
], 1175000, [11e5, 125e4], 12500),
|
||||
|
||||
new CustEntry("eristaCpuMaxVolt", "Erista CPU Max Voltage in mV", CustPlatform.Erista, 4, [
|
||||
"Acceptable range: 1120 ≤ x ≤ 1300",
|
||||
"Default: 1235"
|
||||
], 1235, [1000, 1500], 1),
|
||||
|
||||
new CustEntry("eristaEmcMaxClock", "Erista RAM Max Clock in kHz", CustPlatform.Erista, 4, [
|
||||
"Values should be ≥ 1600000, and divided evenly by 3200.",
|
||||
"Recommended Clocks: 1862400, 2131200 (JEDEC)",
|
||||
"<b>WARNING:</b> RAM overclock could be UNSTABLE if timing parameters are not suitable for your DRAM"
|
||||
], 1862400, [16e5, 2428800], 3200),
|
||||
|
||||
new CustEntry("marikoCpuMaxVolt", "Mariko CPU Max Voltage in mV", CustPlatform.Mariko, 4, [
|
||||
"System default: 1120",
|
||||
"Acceptable range: 1120 ≤ x ≤ 1300",
|
||||
"Changing this value affects cpu voltage calculation"
|
||||
], 1235, [1120, 1300], 5),
|
||||
|
||||
new CustEntry("marikoEmcMaxClock", "Mariko RAM Max Clock in kHz", CustPlatform.Mariko, 4, [
|
||||
"Values should be ≥ 1600000, and divided evenly by 9600.",
|
||||
"Recommended Clocks: 1862400, 2131200, 2400000, etc. (JEDEC)",
|
||||
"<b>WARNING:</b> RAM overclock could be UNSTABLE if timing parameters are not suitable for your DRAM."
|
||||
], 1996800, [16e5, 3200000], 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",
|
||||
"Official lpddr4(x) range: 570mV~650mV (600mV nominal)",
|
||||
"Not enabled by default."
|
||||
], 600000, [55e4, 65e4], 5e3),
|
||||
|
||||
new CustEntry("marikoCpuUV", "Enable Mariko CPU Undervolt", CustPlatform.Mariko, 4, [
|
||||
"Reduce CPU power draw",
|
||||
"<b>0</b> : Default Table",
|
||||
"<b>1</b> : Undervolt Level 1 (SLT - CPU speedo < 1650)",
|
||||
"<b>2</b> : Undervolt Level 1 (SLT - CPU speedo >= 1650)"
|
||||
], 0, [0, 2], 1),
|
||||
|
||||
new CustEntry("marikoGpuUV", "Enable Mariko GPU Undervolt", CustPlatform.Mariko, 4, [
|
||||
"Reduce GPU power draw",
|
||||
"Your GPU might not withstand undervolt, and can hang your console, or crash games",
|
||||
"Undervolting too much will drop GPU performance even if it seems stable",
|
||||
"GPU voltages are dynamic and will change with temperature and gpu speedo",
|
||||
"<b>0</b> : Default Table",
|
||||
"<b>1</b> : Undervolt Level 1 (SLT: Aggressive)",
|
||||
"<b>2</b> : Undervolt Level 2 (HiOPT: Drastic)",
|
||||
"<b>3</b> : Custom static GPU Voltage Table (Use Gpu Configuation below)"
|
||||
], 0, [0, 3], 1),
|
||||
|
||||
new CustEntry("commonGpuVoltOffset", "GPU Volt Offset", CustPlatform.All, 4, [
|
||||
"Negative Voltage offset value for gpu dynamic voltage calculation",
|
||||
"For example, value of 10 will decrease 10mV gpu volt from all frequencies",
|
||||
"Default gpu vmin: Erista - 812.5mV / Mariko - 610mV",
|
||||
"Acceptable range: 0 ~ 100"
|
||||
], 0, [0, 100], 1),
|
||||
|
||||
new CustEntry("marikoCpuHighVoltOffset", "CPU Voltage offset at high frequencies", CustPlatform.Mariko, 4, [
|
||||
"Reduce CPU power draw at high clocks",
|
||||
], 0, [0, 100], 1),
|
||||
|
||||
new CustEntry("marikoCpuHighUV", "Enable Mariko CPU High Undervolt", CustPlatform.Mariko, 4, [
|
||||
"Reduce CPU power draw at high clocks by offsetting the voltage sent to the CPU",
|
||||
], 0, [0, 12], 1),
|
||||
|
||||
new CustEntry("cpuMaxFreq", "Maximum allowed CPU Frequency (KHz)", CustPlatform.All, 4, [
|
||||
"Default: 1785000",
|
||||
"This is the maximum frequency for the CPU you can set in sys-clk-ocs2.",
|
||||
"The value for this setting is capped at 2091mhz for Erista units and 2907MHz for Mariko units",
|
||||
"Anything above 1785MHz for Erista units and 1963MHz for Mariko units is unsafe without undervolting"
|
||||
], 1785000, [204000, 2907000], 1, !1),
|
||||
|
||||
new CustEntry("gpuMaxFreq", "Maximum allowed GPU Frequency (KHz)", CustPlatform.All, 4, [
|
||||
"Default: 921600",
|
||||
"This is the maximum frequency for the GPU you can set in sys-clk-ocs2.",
|
||||
"The value for this setting is capped at 998mhz for Erista units, and 1305MHz on Mariko units",
|
||||
"The maximum safe value without undervolt is 921MHz for Erista units and 1152MHz for Mariko units",
|
||||
"Higher frequencies via GPU UV3 bypass this setting"
|
||||
], 921600, [76800, 1305600], 1, !1),
|
||||
|
||||
new CustEntry("gpuVmax", "Mariko Maximum allowed GPU Voltage (mV)", CustPlatform.Mariko, 4, [
|
||||
"Default: 800",
|
||||
"This is the maximum voltage you can use in GPU UV3.",
|
||||
"Anything above 800MV is considered UNSAFE (although it depends per frequency)"
|
||||
], 800, [480, 1000], 1, !1),
|
||||
|
||||
new CustEntry("gpuVmin", "Mariko Minimum allowed GPU Voltage (mV)", CustPlatform.Mariko, 4, [
|
||||
"Default: 600",
|
||||
"This is the minimum voltage you can use in GPU UV3.",
|
||||
"A higher Vmin is required for a higher max ram clock"
|
||||
], 600, [480, 1000], 1, !1),
|
||||
|
||||
|
||||
];
|
||||
|
||||
var AdvTable = [
|
||||
new AdvEntry("marikoEmcDvbShift", "Step up Mariko EMC DVB Table", CustPlatform.Mariko, 4, [
|
||||
"Each number adds 25mV to SoC voltage",
|
||||
"Helps with stability at higher memory clock, with the only downside being slightly higher tempratures",
|
||||
"Such functionality is completely useless on Erista units",
|
||||
"Acceptable range : 0~9"
|
||||
], 0, [0, 9], 1),
|
||||
|
||||
|
||||
];
|
||||
|
||||
var GpuTable = [
|
||||
new GpuEntry("0", "76.8"),
|
||||
new GpuEntry("1", "153.6"),
|
||||
new GpuEntry("2", "230.4"),
|
||||
new GpuEntry("3", "307.2"),
|
||||
new GpuEntry("4", "384.0"),
|
||||
new GpuEntry("5", "460.8"),
|
||||
new GpuEntry("6", "537.6"),
|
||||
new GpuEntry("7", "614.4"),
|
||||
new GpuEntry("8", "691.2"),
|
||||
new GpuEntry("9", "768.0"),
|
||||
new GpuEntry("10", "844.8"),
|
||||
new GpuEntry("11", "921.6"),
|
||||
new GpuEntry("12", "998.4"),
|
||||
new GpuEntry("13", "1075.2", CustPlatform.Mariko),
|
||||
new GpuEntry("14", "1152.0", CustPlatform.Mariko),
|
||||
new GpuEntry("15", "1228.8 <span style='color:orange; font-weight:bold;'>(UNSAFE)</span>", CustPlatform.Mariko),
|
||||
new GpuEntry("16", "1267.2 <span style='color:orange; font-weight:bold;'>(UNSAFE)</span>", CustPlatform.Mariko),
|
||||
new GpuEntry("17", "1305.6 <span style='color:orange; font-weight:bold;'>(UNSAFE)</span>", CustPlatform.Mariko),
|
||||
new GpuEntry("18", "1344.0 <span style='color:orange; font-weight:bold;'>(UNSAFE)</span>", CustPlatform.Mariko),
|
||||
new GpuEntry("19", "1382.4 <span style='color:orange; font-weight:bold;'>(UNSAFE)</span>", CustPlatform.Mariko),
|
||||
new GpuEntry("20", "1420.8 <span style='color:red; font-weight:bold;'>(DANGEROUS)</span>", CustPlatform.Mariko),
|
||||
new GpuEntry("21", "1459.2 <span style='color:red; font-weight:bold;'>(DANGEROUS)</span>", CustPlatform.Mariko),
|
||||
new GpuEntry("22", "1497.6 <span style='color:red; font-weight:bold;'>(DANGEROUS)</span>", CustPlatform.Mariko),
|
||||
new GpuEntry("23", "1536.0 <span style='color:red; font-weight:bold;'>(DANGEROUS)</span>", CustPlatform.Mariko)
|
||||
];
|
||||
|
||||
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, n, a, r;
|
||||
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 === (n = null === (i = this.element) || void 0 === i ? void 0 : i.parentElement) || void 0 === n || n.setAttribute("data-tooltip", this.msg), null === (r = null === (a = this.element) || void 0 === a ? void 0 : a.parentElement) || void 0 === r || r.setAttribute("data-placement", "top")), this
|
||||
}
|
||||
clear() {
|
||||
var e, t, i, n, a, r;
|
||||
return null === (e = this.element) || void 0 === e || e.removeAttribute("aria-invalid"), null === (t = this.element) || void 0 === t || t.removeAttribute("title"), null === (n = null === (i = this.element) || void 0 === i ? void 0 : i.parentElement) || void 0 === n || n.removeAttribute("data-tooltip"), null === (r = null === (a = this.element) || void 0 === a ? void 0 : a.parentElement) || void 0 === r || r.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() {
|
||||
let e = e => {
|
||||
var t;
|
||||
if (e.updateValueFromElement(), !e.validate()) throw null === (t = e.getInputElement()) || void 0 === t || t.focus(), new Error(`Invalid ${e.name}`)
|
||||
};
|
||||
CustTable.forEach(e), AdvTable.forEach(e), GpuTable.forEach(e), this.storage = {};
|
||||
let t = Object.fromEntries(CustTable.map((e => [e.id, e.value])));
|
||||
Object.keys(t).forEach((e => this.storage[e] = t[e])), t = Object.fromEntries(AdvTable.map((e => [e.id, e.value]))), Object.keys(t).forEach((e => this.storage[e] = t[e]))
|
||||
}
|
||||
setTable() {
|
||||
let e = Object.keys(this.storage);
|
||||
e.forEach((e => CustTable.filter((t => t.id == e))[0].value = this.storage[e])), e.forEach((e => AdvTable.filter((t => t.id == e))[0].value = this.storage[e])), CustTable.filter((t => !e.includes(t.id))).forEach((e => e.value = e.defval)), AdvTable.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()
|
||||
})), AdvTable.forEach((e => {
|
||||
var t;
|
||||
if (!e.validate()) throw null === (t = e.getInputElement()) || void 0 === t || t.focus(), new Error(`Invalid ${e.name}`);
|
||||
e.setElementValue()
|
||||
})), GpuTable.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)),
|
||||
n = Object.keys(t).filter((e => !i.includes(e)));
|
||||
return n.length && console.log(`Ignored: ${n}`), Object.keys(t).filter((e => i.includes(e))).forEach((e => this.storage[e] = t[e])), i = AdvTable.map((e => e.id)), n = Object.keys(t).filter((e => !i.includes(e))), n.length && console.log(`Ignored: ${n}`), 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 < this.view.byteLength; e += this.magicLen)
|
||||
if (this.mapper[this.magicLen].get(e) == this.magic) return void(this.beginOffset = e);
|
||||
throw new Error("Invalid loader.kip file")
|
||||
}
|
||||
save() {
|
||||
this.storage.updateFromTable();
|
||||
let e = 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 n = this.mapper[e.size];
|
||||
if (!n) throw null === (i = e.getInputElement()) || void 0 === i || i.focus(), new Error(`Unknown size at ${e.name}`);
|
||||
n.set(e.offset, e.value)
|
||||
};
|
||||
CustTable.forEach(e), AdvTable.forEach(e), GpuTable.forEach(e), this.storage.save();
|
||||
let t = document.createElement("a");
|
||||
t.href = window.URL.createObjectURL(new Blob([this.buffer], {
|
||||
type: "application/octet-stream"
|
||||
})), t.download = "loader.kip", t.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() {
|
||||
var e, t;
|
||||
CustTable.forEach((e => e.createElement()));
|
||||
let i = document.createElement("p");
|
||||
i.innerHTML = "Advanced configuration", null === (e = document.getElementById("config-list-advanced")) || void 0 === e || e.appendChild(i);
|
||||
let n = document.createElement("p");
|
||||
n.innerHTML = "Gpu Volt configuration", null === (t = document.getElementById("config-list-gpu")) || void 0 === t || t.appendChild(n), AdvTable.forEach((e => e.createElement())), GpuTable.forEach((e => e.createElement()));
|
||||
let a = document.getElementById("load_default");
|
||||
a.removeAttribute("disabled"), a.addEventListener("click", (() => {
|
||||
CustTable.forEach((e => e.setElementDefaultValue()))
|
||||
})), this.toggleLoadLastSavedBtn(null !== this.storage.load());
|
||||
let r = document.getElementById("save");
|
||||
r.removeAttribute("disabled"), r.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", (n => {
|
||||
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;
|
||||
if (this.rev = this.mapper[4].get(e), CUST_REV_ADV != this.rev) throw new Error(`Unsupported custRev, expected: 1, got ${this.rev}`);
|
||||
e += 4, document.getElementById("cust_rev").innerHTML = `Cust v${this.rev} is loaded.`;
|
||||
let t = t => {
|
||||
var i;
|
||||
t.offset = e;
|
||||
let n = this.mapper[t.size];
|
||||
if (!n) throw null === (i = t.getInputElement()) || void 0 === i || i.focus(), new Error(`Unknown size at ${t}`);
|
||||
t.value = n.get(e), e += t.size, t.validate()
|
||||
};
|
||||
CustTable.forEach(t), AdvTable.forEach(t), GpuTable.forEach(t)
|
||||
}
|
||||
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/souldbminersmwc/Switch-OC-Suite-2/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.loaderKipAsset = new ReleaseAsset(e.assets.filter((e => e.name.endsWith("loader.kip")))[0]), this.sdOutZipAsset = new ReleaseAsset(e.assets.filter((e => e.name.endsWith("SdOut.zip")))[0]), this.sysclkOCAsset = new ReleaseAsset(e.assets.filter((e => e.name.endsWith("sys-clk-ocs2.zip")))[0])
|
||||
}
|
||||
}
|
||||
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 <b>${e.ocVer}</b><br>${e.loaderKipAsset.updatedAt}`, e.loaderKipAsset.downloadUrl), this.update("sdout_zip_btn", `SdOut.zip <b>${e.ocVer}</b><br>${e.sdOutZipAsset.updatedAt}`, e.sdOutZipAsset.downloadUrl), this.update("ams_btn", `sys-clk-ocs2 <b>${e.ocVer}</b><br>${e.sysclkOCAsset.updatedAt}`, e.sysclkOCAsset.downloadUrl)
|
||||
}))
|
||||
}
|
||||
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 n = document.getElementById(e);
|
||||
n.innerHTML = t, n.removeAttribute("aria-busy"), n.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()
|
||||
}))));
|
||||
@@ -1,41 +0,0 @@
|
||||
OCS2-AA-MGCL-PRESET
|
||||
.BL = 16,
|
||||
.tRFCpb = 140,
|
||||
.tRFCab = 280,
|
||||
.tRAS = 42,
|
||||
.tRPpb = 18,
|
||||
.tRPab = 21,
|
||||
.tRC = 60,
|
||||
|
||||
.tDQSCK_min = 1.5,
|
||||
.tDQSCK_max = 3.6,
|
||||
.tWPRE = 2.0,
|
||||
.tRPST = 0.5,
|
||||
.tDQSS_max = 1.25,
|
||||
.tDQS2DQ_max = 0.7,
|
||||
.tDQSQ = 0.18,
|
||||
|
||||
.tWTR = 12,
|
||||
.tRTP = 7.5,
|
||||
.tWR = 20,
|
||||
.tR2REF = 25.5,
|
||||
|
||||
.tRCD = 18,
|
||||
.tRRD = 10,
|
||||
.tREFpb = 488,
|
||||
|
||||
.tXP = 7.5,
|
||||
.tCMDCKE = 1.75,
|
||||
.tMRWCKEL = 14,
|
||||
.tCKELCS = 5,
|
||||
.tCSCKEH = 1.75,
|
||||
.tXSR = 287.5,
|
||||
.tCKE = 7.5,
|
||||
|
||||
.tSR = 15,
|
||||
.tFAW = 40,
|
||||
|
||||
.tCKCKEH = 1.75,
|
||||
|
||||
.WL = 14,
|
||||
.RL = 32,
|
||||
@@ -1,41 +0,0 @@
|
||||
OCS2-AB-MGCL-PRESET
|
||||
.BL = 16,
|
||||
.tRFCpb = 140,
|
||||
.tRFCab = 280,
|
||||
.tRAS = 42,
|
||||
.tRPpb = 18,
|
||||
.tRPab = 21,
|
||||
.tRC = 60,
|
||||
|
||||
.tDQSCK_min = 1.5,
|
||||
.tDQSCK_max = 3.5,
|
||||
.tWPRE = 2.0,
|
||||
.tRPST = 0.5,
|
||||
.tDQSS_max = 1.25,
|
||||
.tDQS2DQ_max = 0.7,
|
||||
.tDQSQ = 0.18,
|
||||
|
||||
.tWTR = 10,
|
||||
.tRTP = 7.5,
|
||||
.tWR = 18,
|
||||
.tR2REF = 25.5,
|
||||
|
||||
.tRCD = 18,
|
||||
.tRRD = 18,
|
||||
.tREFpb = 488,
|
||||
|
||||
.tXP = 7.5,
|
||||
.tCMDCKE = 1.75,
|
||||
.tMRWCKEL = 14,
|
||||
.tCKELCS = 5,
|
||||
.tCSCKEH = 1.75,
|
||||
.tXSR = 287.5,
|
||||
.tCKE = 7.5,
|
||||
|
||||
.tSR = 15,
|
||||
.tFAW = 30,
|
||||
|
||||
.tCKCKEH = 1.75,
|
||||
|
||||
.WL = 14,
|
||||
.RL = 32,
|
||||
@@ -1,41 +0,0 @@
|
||||
OCS2-AM-MGCJ-PRESET
|
||||
.BL = 16,
|
||||
.tRFCpb = 140,
|
||||
.tRFCab = 280,
|
||||
.tRAS = 62,
|
||||
.tRPpb = 18,
|
||||
.tRPab = 21,
|
||||
.tRC = 4,
|
||||
|
||||
.tDQSCK_min = 1.5,
|
||||
.tDQSCK_max = 3.6,
|
||||
.tWPRE = 2.0,
|
||||
.tRPST = 0.5,
|
||||
.tDQSS_max = 1.25,
|
||||
.tDQS2DQ_max = 0.7,
|
||||
.tDQSQ = 0.18,
|
||||
|
||||
.tWTR = 10,
|
||||
.tRTP = 7.5,
|
||||
.tWR = 18,
|
||||
.tR2REF = 25.5,
|
||||
|
||||
.tRCD = 18,
|
||||
.tRRD = 18,
|
||||
.tREFpb = 488,
|
||||
|
||||
.tXP = 7.5,
|
||||
.tCMDCKE = 1.75,
|
||||
.tMRWCKEL = 14,
|
||||
.tCKELCS = 5,
|
||||
.tCSCKEH = 1.75,
|
||||
.tXSR = 287.5,
|
||||
.tCKE = 7.5,
|
||||
|
||||
.tSR = 15,
|
||||
.tFAW = 40,
|
||||
|
||||
.tCKCKEH = 1.75,
|
||||
|
||||
.WL = 18,
|
||||
.RL = 40,
|
||||
@@ -1,41 +0,0 @@
|
||||
OCS2-MICRON-WTB-PRESET
|
||||
.BL = 16,
|
||||
.tRFCpb = 140,
|
||||
.tRFCab = 280,
|
||||
.tRAS = 42,
|
||||
.tRPpb = 18,
|
||||
.tRPab = 21,
|
||||
.tRC = 60,
|
||||
|
||||
.tDQSCK_min = 1.5,
|
||||
.tDQSCK_max = 3.5,
|
||||
.tWPRE = 1.8,
|
||||
.tRPST = 0.4,
|
||||
.tDQSS_max = 1.25,
|
||||
.tDQS2DQ_max = 0.8,
|
||||
.tDQSQ = 0.18,
|
||||
|
||||
.tWTR = MAX(10, 8 * nCK_mariko),
|
||||
.tRTP = 7.5, // Cannot find concrete value for this timing
|
||||
.tWR = MAX(10, 4 * nCK_mariko),
|
||||
.tR2REF = 25.5,
|
||||
|
||||
.tRCD = 20, // Cannot find concrete value for this timing
|
||||
.tRRD = 10, // Cannot find concrete value for this timing
|
||||
.tREFpb = 488,
|
||||
|
||||
.tXP = MAX(7.5, 5 * nCK_mariko),
|
||||
.tCMDCKE = MAX(1.75, 3 * nCK_mariko),
|
||||
.tMRWCKEL = MAX(14, 10 * nCK_mariko),
|
||||
.tCKELCS = MAX(5, 5 * nCK_mariko),
|
||||
.tCSCKEH = 1.75,
|
||||
.tXSR = MAX(C.tRFcpb + 7.5, 5 * nCK_mariko),
|
||||
.tCKE = MAX(7.5, 4 * nCK_mariko),
|
||||
|
||||
.tSR = MAX(15, 3 * nCK_mariko),
|
||||
.tFAW = 30,
|
||||
|
||||
.tCKCKEH = MAX(1.75, 3 * nCK_mariko),
|
||||
|
||||
.WL = 14,
|
||||
.RL = 32,
|
||||
Reference in New Issue
Block a user