Files
Horizon-OC/pages/dist/main.js
2023-05-26 12:46:41 +09:00

1 line
12 KiB
JavaScript

var __awaiter=this&&this.__awaiter||function(c,d,a,b){function e(b){return b instanceof a?b:new a(function(a){a(b)})}return new(a||(a=Promise))(function(g,f){function h(c){try{a(b.next(c))}catch(a){f(a)}}function i(c){try{a(b.throw(c))}catch(a){f(a)}}function a(a){a.done?g(a.value):e(a.value).then(h,i)}a((b=b.apply(c,d||[])).next())})},CustPlatform,CustTable;const CUST_REV=4;(function(a){a[a.Undefined=0]="Undefined",a[a.Erista=1]="Erista",a[a.Mariko=2]="Mariko",a[a.All=3]="All"})(CustPlatform||(CustPlatform={}));class CustEntry{constructor(g,b,c,d,e,f,a=[0,1e6],h=1,i=!0){this.id=g,this.name=b,this.platform=c,this.size=d,this.desc=e,this.defval=f,this.step=h,this.zeroable=i,this.min=a[0],this.max=a[1]}validate(){let a=new ErrorToolTip(this.id).clear();return Number.isNaN(this.value)||this.value===void 0?(a.setMsg(`Invalid value: Not a number`).show(),!1):!!(this.zeroable&&this.value==0)||(this.value<this.min||this.value>this.max?(a.setMsg(`Expected range: [${this.min}, ${this.max}], got ${this.value}.`).show(),!1):this.value%this.step==0||(a.setMsg(`${this.value} % ${this.step} ≠ 0`).show(),!1))}getInputElement(){return document.getElementById(this.id)}updateValueFromElement(){var a;this.value=Number((a=this.getInputElement())===null||a===void 0?void 0:a.value)}isAvailableFor(a){return a===CustPlatform.Undefined||this.platform===a||this.platform===CustPlatform.All}createElement(){let a=this.getInputElement();if(!a){let b=document.createElement("div");b.classList.add("grid","cust-element"),a=document.createElement("input"),a.min=String(this.zeroable?0:this.min),a.max=String(this.max),a.id=this.id,a.type="number",a.step=String(this.step);let c=document.createElement("label");c.setAttribute("for",this.id),c.innerHTML=this.name,c.appendChild(a),b.appendChild(c);let d=document.createElement("blockquote");d.innerHTML="<ul>"+this.desc.map(a=>`<li>${a}</li>`).join('')+"</ul>",d.setAttribute("for",this.id),b.appendChild(d),document.getElementById("config-list-basic").appendChild(b),new ErrorToolTip(this.id).addChangeListener()}a.value=String(this.value)}setElementValue(){this.getInputElement().value=String(this.value)}setElementDefaultValue(){this.getInputElement().value=String(this.defval)}removeElement(){let a=this.getInputElement();a&&a.parentElement.parentElement.remove()}showElement(){let a=this.getInputElement();a&&a.parentElement.parentElement.style.removeProperty("display")}hideElement(){let a=this.getInputElement();a&&a.parentElement.parentElement.style.setProperty("display","none")}}CustTable=[new CustEntry("mtcConf","DRAM Timing",CustPlatform.Mariko,2,["<b>0</b>: AUTO_ADJ_MARIKO_SAFE: Auto adjust timings for LPDDR4 ≤3733 Mbps specs, 8Gb density. (Default)","<b>1</b>: AUTO_ADJ_MARIKO_4266: Auto adjust timings for LPDDR4X 4266 Mbps specs, 8Gb density.","<b>2</b>: 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("commonCpuBoostClock","Boost Clock in kHz",CustPlatform.All,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("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),new CustEntry("eristaCpuMaxVolt","Erista CPU Max Voltage in mV",CustPlatform.Erista,4,["Acceptable range: 1100 ≤ x ≤ 1300","L4T Default: 1235"],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.","<b>WARNING:</b> RAM overclock could be UNSTABLE if timing parameters are not suitable for your DRAM"],1862400,[16e5,24e5],3200),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("marikoEmcMaxClock","Mariko RAM Max Clock in kHz",CustPlatform.Mariko,4,["Values should be ≥ 1600000, and divided evenly by 3200.","<b>WARNING:</b> 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)];class ErrorToolTip{constructor(a,b){this.id=a,this.msg=b,this.id=a,this.element=document.getElementById(a),b&&this.setMsg(b)}setMsg(a){return this.msg=a,this}show(){var a,b,c,d,e,f;return(a=this.element)===null||a===void 0?void 0:a.setAttribute("aria-invalid","true"),this.msg&&((b=this.element)===null||b===void 0?void 0:b.setAttribute("title",this.msg),(d=(c=this.element)===null||c===void 0?void 0:c.parentElement)===null||d===void 0?void 0:d.setAttribute("data-tooltip",this.msg),(f=(e=this.element)===null||e===void 0?void 0:e.parentElement)===null||f===void 0?void 0:f.setAttribute("data-placement","top")),this}clear(){var a,b,c,d,e,f;return(a=this.element)===null||a===void 0?void 0:a.removeAttribute("aria-invalid"),(b=this.element)===null||b===void 0?void 0:b.removeAttribute("title"),(d=(c=this.element)===null||c===void 0?void 0:c.parentElement)===null||d===void 0?void 0:d.removeAttribute("data-tooltip"),(f=(e=this.element)===null||e===void 0?void 0:e.parentElement)===null||f===void 0?void 0:f.removeAttribute("data-placement"),this}addChangeListener(){var a;(a=this.element)===null||a===void 0?void 0:a.addEventListener('change',b=>{let a=CustTable.filter(a=>a.id===this.id)[0];a.value=Number(this.element.value),a.validate()})}}class CustStorage{constructor(){this.storage={},this.key="last_saved"}updateFromTable(){CustTable.forEach(a=>{var b;if(a.updateValueFromElement(),!a.validate())throw(b=a.getInputElement())===null||b===void 0?void 0:b.focus(),new Error(`Invalid ${a.name}`)}),this.storage={};let a=Object.fromEntries(CustTable.map(a=>[a.id,a.value]));Object.keys(a).forEach(b=>this.storage[b]=a[b])}setTable(){let a=Object.keys(this.storage);a.forEach(a=>CustTable.filter(b=>b.id==a)[0].value=this.storage[a]),CustTable.filter(b=>!a.includes(b.id)).forEach(a=>a.value=a.defval),CustTable.forEach(a=>{var b;if(!a.validate())throw(b=a.getInputElement())===null||b===void 0?void 0:b.focus(),new Error(`Invalid ${a.name}`);a.setElementValue()})}save(){localStorage.setItem(this.key,JSON.stringify(this.storage))}load(){let b=localStorage.getItem(this.key);if(!b)return null;let a=JSON.parse(b),c=CustTable.map(a=>a.id),d=Object.keys(a).filter(a=>!c.includes(a));return d.length&&console.log(`Ignored: ${d}`),Object.keys(a).filter(a=>c.includes(a)).forEach(b=>this.storage[b]=a[b]),this.storage}}class Cust{constructor(){this.storage=new CustStorage,this.magic=1414747459,this.magicLen=4,this.mapper={2:{get:a=>this.view.getUint16(a,!0),set:(a,b)=>this.view.setUint16(a,b,!0)},4:{get:a=>this.view.getUint32(a,!0),set:(a,b)=>this.view.setUint32(a,b,!0)}}}findMagicOffset(){this.view=new DataView(this.buffer);for(let a=0;a<this.view.byteLength;a+=this.magicLen)if(this.mapper[this.magicLen].get(a)==this.magic){this.beginOffset=a;return}throw new Error("Invalid loader.kip file")}save(){this.storage.updateFromTable(),CustTable.forEach(a=>{var b,c;if(!a.offset)throw(b=a.getInputElement())===null||b===void 0?void 0:b.focus(),new Error(`Failed to get offset for ${a.name}`);let d=this.mapper[a.size];if(!d)throw(c=a.getInputElement())===null||c===void 0?void 0:c.focus(),new Error(`Unknown size at ${a.name}`);d.set(a.offset,a.value)}),this.storage.save();let a=document.createElement("a");a.href=window.URL.createObjectURL(new Blob([this.buffer],{type:"application/octet-stream"})),a.download="loader.kip",a.click(),this.toggleLoadLastSavedBtn(!0)}removeHTMLForm(){CustTable.forEach(a=>a.removeElement())}toggleLoadLastSavedBtn(b){let a=document.getElementById("load_saved");b?(a.addEventListener('click',()=>{this.storage.load()&&this.storage.setTable()}),a.style.removeProperty("display"),a.removeAttribute("disabled")):a.style.setProperty("display","none")}createHTMLForm(){var a;CustTable.forEach(a=>a.createElement());let b=document.createElement("p");b.innerHTML="Advanced configuration: Coming soon...",(a=document.getElementById("config-list-advanced"))===null||a===void 0?void 0:a.appendChild(b);let c=document.getElementById("load_default");c.removeAttribute("disabled"),c.addEventListener('click',()=>{CustTable.forEach(a=>a.setElementDefaultValue())}),this.toggleLoadLastSavedBtn(this.storage.load()!==null);let d=document.getElementById("save");d.removeAttribute("disabled"),d.addEventListener('click',()=>{try{this.save()}catch(a){console.error(a),alert(a)}})}initCustTabs(){const a=Array.from(document.querySelectorAll(`nav[role="tablist"] > button`));a.forEach(b=>{b.removeAttribute("disabled");let c=Number(b.getAttribute("data-platform"));b.addEventListener('click',f=>{const d=["outline"];b.classList.remove(...d);let e=a.filter(a=>a!=b);e.forEach(a=>a.classList.add(...d)),CustTable.forEach(a=>{a.isAvailableFor(c)?a.showElement():a.hideElement()})})})}parse(){let a=this.beginOffset+this.magicLen,b=2,c=this.mapper[b].get(a);if(c!=CUST_REV)throw new Error(`Unsupported custRev, expected: ${CUST_REV}, got ${c}`);a+=b,document.getElementById("cust_rev").innerHTML=`Cust v${CUST_REV} is loaded.`,CustTable.forEach(b=>{var c;b.offset=a;let d=this.mapper[b.size];if(!d)throw(c=b.getInputElement())===null||c===void 0?void 0:c.focus(),new Error(`Unknown size at ${b}`);b.value=d.get(a),a+=b.size,b.validate()})}load(a){try{this.buffer=a,this.findMagicOffset(),this.removeHTMLForm(),this.parse(),this.initCustTabs(),this.createHTMLForm()}catch(a){console.error(a),alert(a)}}}class ReleaseAsset{constructor(a){this.downloadUrl=a.browser_download_url,this.updatedAt=a.updated_at}}class ReleaseInfo{constructor(){this.ocLatestApi="https://api.github.com/repos/hanai3Bi/Switch-OC-Suite/releases/latest"}load(){return __awaiter(this,void 0,void 0,function*(){try{this.parseOcResponse(yield this.responseFromApi(this.ocLatestApi).catch())}catch(a){console.error(a),alert(a)}})}responseFromApi(a){return __awaiter(this,void 0,void 0,function*(){const b=yield fetch(a,{method:'GET',headers:{Accept:'application/json'}});if(b.ok)return yield b.json();throw new Error(`Failed to connect to "${a}": ${b.status}`)})}parseOcResponse(a){this.ocVer=a.tag_name,this.amsVer=this.ocVer.split(".").slice(0,3).join("."),this.loaderKipAsset=new ReleaseAsset(a.assets.filter(a=>a.name.endsWith("loader.kip"))[0]),this.sdOutZipAsset=new ReleaseAsset(a.assets.filter(a=>a.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*(){while(!this.isVisible())yield new Promise(a=>setTimeout(a,1e3));const a=new ReleaseInfo;yield a.load(),this.update("loader_kip_btn",`loader.kip <b>${a.ocVer}</b><br>${a.loaderKipAsset.updatedAt}`,a.loaderKipAsset.downloadUrl),this.update("sdout_zip_btn",`SdOut.zip <b>${a.ocVer}</b><br>${a.sdOutZipAsset.updatedAt}`,a.sdOutZipAsset.downloadUrl),this.update("ams_btn",`Atmosphere-NX <b>${a.amsVer}</b>`,a.amsUrl)})}isVisible(){let a=this.element.getBoundingClientRect();return a.top>0&&a.left>0&&a.bottom-a.height<(window.innerHeight||document.documentElement.clientHeight)&&a.right-a.width<(window.innerWidth||document.documentElement.clientWidth)}update(b,c,d){let a=document.getElementById(b);a.innerHTML=c,a.removeAttribute("aria-busy"),a.setAttribute("href",d)}}const fileInput=document.getElementById("file");fileInput.addEventListener('change',a=>{var c=new Cust;if(!a.target||!a.target.files)return;let b=new FileReader;b.readAsArrayBuffer(a.target.files[0]),b.onloadend=a=>{a.target.readyState==FileReader.DONE&&c.load(a.target.result)}}),addEventListener('DOMContentLoaded',a=>__awaiter(this,void 0,void 0,function*(){yield(new DownloadSection).load()}))