updated stage loader

This commit is contained in:
QbeRoot 2018-02-03 22:14:40 +01:00
parent 705a4283d0
commit a95ea19a02
4 changed files with 68 additions and 35 deletions

View file

@ -10,9 +10,13 @@
<body>
<div id="guide_content" class="framed">
<h1 style="text-align:center;width:100%;">Full Changelog</h1>
<h2 id="180203"><a href="#180203">Feb 03, 2018</a></h2>
<h3 id="1802031"><a href="#1802031">Updated Stage Loader</a></h3>
<p>Added "Random, no duplicates" order that will only load each stage once.</p>
<p>Exiting area or dying now reloads the current stage instead of moving on.</p>
<h2 id="180202"><a href="#180202">Feb 02, 2018</a></h2>
<h3 id="1802021"><a href="#1802021">Site changes</a></h3>
<p>Integrated <a href="https://qberoot.github.io/fastcodes/">Noki Dokis Stage Loader</a> into the Generator.</p>
<p>Integrated <a href="https://qberoot.github.io/fastcodes/">Noki Dokis Stage Loader</a> into the Generator.</p>
<h2 id="180124"><a href="#180124">Jan 24, 2018</a></h2>
<h3 id="1801241"><a href="#1801241">Optimized 'Fast Any%'</a></h3>
<p>Shortens the code by a few lines</p>

View file

@ -1,5 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<updates>
<update>
<date>Feb 03, 2018</date>
<change>Updated Stage Loader.</change>
</update>
<update>
<date>Feb 02, 2018</date>
<change>Integrated Noki Dokis Stage Loader.</change>

View file

@ -187,8 +187,8 @@ function updateUIDescription(s) {
document.getElementById("descriptionbox").innerHTML = "<h2>Remove Dialogue</h2><p>Replaces all Dialogue with \"!!!\". 'Always' and 'Not in Pianta 5' will override the dialogue skip from the DPad Functions.</p>";
else if (s.id === "route_nofmvs")
document.getElementById("descriptionbox").innerHTML = "<h2>Skippable Cutscenes</h2><p>Makes FMVs Skippable. 'Always' has the same effect as the 'FMV Skips' code. Also, having 'FMV Skips' enabled will override 'Not in Pinna 1' - so don't use both simultaneously.</p>";
else if (s.id === "route_random")
document.getElementById("descriptionbox").innerHTML = "<h2>Random Level Order</h2><p>Randomizes what level is loaded next - it can be any from the levels you choose on the list. Even levels that you've finished already.</p>";
else if (s.id === "route_order")
document.getElementById("descriptionbox").innerHTML = "<h2>Level Order</h2><p>The order in which levels are loaded:</p><h4>As specified</h4><p>The code loads levels in the order of the list.</p><h4>Random, no duplicates</h4><p>The code picks levels at random, excluding levels that youve finished already.</p><h4>Fully random</h4><p>The code picks levels at random, even levels that youve finished already.</p>";
else if (s.id === "downloadformat")
document.getElementById("descriptionbox").innerHTML = "<h2>File Format</h2><p>You can choose between 3 file formats:</p><h4>GCT</h4><p>Download a GCT file for use with Nintendont</p><h4>Dolphin INI</h4><p>Download a textfile containing the formatted codes for use with Dolphin. Copy the contents of the file on top of your games .ini file.</p><p>You can open the .ini file by right clicking the game in Dolphin. In the context menu select 'Properties' and then 'Edit configuration'.</p><h4>Cheat Manager TXT</h4><p>Download the cheats in a textfile formatted for use with the <a target=\"_blank\" href=\"http://wiibrew.org/wiki/CheatManager\">Gecko Cheat Manager</a>. Place the txt file in SD:/txtcodes/.</p><p>A zip archive containing pregenerated txt files with all available codes on this site can be downloaded <a target=\"_blank\" href=\"files/GCMCodes.zip\">here</a>.</p>";
else if (s.id === "stageloader")
@ -337,12 +337,13 @@ function getFastCode() {
if (!(document.getElementById("usefastcode").checked) || levelCodes.length <= 1) return false;
let game = JSON.parse(atob(document.getElementById("route_levels").getAttribute("data-json")));
const randomize = (document.getElementById("route_random").value === "yes");
const order = document.getElementById("route_order").value;
const levelWords = Math.ceil(levelCodes.length / 2);
const branchBase = 0x14 + 0x24 * (order !== 'list');
const asm = [];
asm.push("48" + ("00000" + (levelWords + 1 << 2 | 1).toString(16).toUpperCase()).slice(-6)); // bl to the code
for (let i = 0; i < levelWords; ++i) {
asm.push(levelCodes[2 * i] + (levelCodes[2 * i + 1] || "0000"));
asm.push("48" + ("00000" + (Math.ceil(levelCodes.length / 2) + 1 << 2 | 1).toString(16).toUpperCase()).slice(-6)); // bl to the code
for (let i = levelCodes.length - 1; i >= 0; i -= 2) {
asm.push(levelCodes[i] + (levelCodes[i - 1] || "0000"));
}
//Timer compatibility
@ -354,36 +355,59 @@ function getFastCode() {
asm.push("881F0012"); // lbz r0, 0x12(r31)
if (!randomize) {
asm.push("2C00000F"); // cmpwi r0, 15
asm.push("40820010"); // bne- 0x10
asm.push("38000000"); // li r0, 0
asm.push("90040000"); // stw r0, 0(r4)
asm.push("4800002C"); // b 0x2C
}
asm.push("2C00000F"); // cmpwi r0, 15
asm.push("40820010"); // bne- 0x10
asm.push("3800" + ("000" + ((levelCodes.length - (order === 'random')) * 2).toString(16).toUpperCase()).slice(-4)); // li r0, length
asm.push("90040000"); // stw r0, 0(r4)
asm.push("4800" + ("000" + (branchBase + 0x38).toString(16).toUpperCase()).slice(-4)); // b done
asm.push("2C000001"); // cmpwi r0, 1
asm.push("4181" + ("000" + (branchBase + 0x30).toString(16).toUpperCase()).slice(-4)); // bgt- done
if (randomize) {
asm.push("41810030"); // bgt- 0x30
asm.push("7C6C42E6"); // mftbl r3
asm.push("3880" + ("000" + (levelCodes.length * 2).toString(16).toUpperCase()).slice(-4)); // li r4, length
asm.push("7C032396"); // divwu r0, r3, r4
asm.push("7C0021D6"); // mullw r0, r0, r4
asm.push("7C601850"); // sub r3, r3, r0
asm.push("5463003C"); // rlwinm r3, r3, 0, 0, 30
} else {
asm.push("41810024"); // bgt- 0x24
asm.push("80640000"); // lwz r3, 0(r4)
asm.push("38030002"); // addi r0, r3, 2
asm.push("90040000"); // stw r0, 0(r4)
asm.push("80AD" + game.fmOffset); // lwz r5, TFlagManager::smInstance
asm.push("7CC802A6"); // mflr r6
asm.push("80640000"); // lwz r3, 0(r4)
asm.push("881F000E"); // lbz r0, 0x0E(r31)
asm.push("2C00000F"); // cmpwi r0, 15
asm.push("41820010"); // beq- 0x10
asm.push("880500CC"); // lbz r0, 0xCC(r5)
asm.push("54000673"); // rlwinm. r0, r0, 0, 25, 25
asm.push("4182" + ("000" + branchBase.toString(16).toUpperCase()).slice(-4)); // beq- loadStage
if (order === "random") {
asm.push("38630002"); // addi r3, r3, 2
}
asm.push("7C8802A6"); // mflr r4
asm.push("7C641A2E"); // lhzx r3, r4, r3
asm.push("2C030000"); // cmpwi r3, 0
asm.push("4081" + ("000" + (branchBase + 4 * (order !== "random")).toString(16).toUpperCase()).slice(-4)); // ble- done
if (order !== "list") {
asm.push("7CEC42E6"); // mftbl r7
asm.push("7C071B96"); // divwu r0, r7, r3
asm.push("7C0019D6"); // mullw r0, r0, r3
asm.push("7CE03850"); // sub r7, r7, r0
asm.push("54E7003C"); // rlwinm r7, r7, 0, 0, 30
}
asm.push("3863FFFE"); // subi r3, r3, 2
if (order !== "random") {
asm.push("90640000"); // stw r3, 0(r4)
}
if (order !== "list") {
asm.push("7C061A2E"); // lhzx r0, r6, r3
asm.push("7C863A2E"); // lhzx r4, r6, r7
asm.push("7C063B2E"); // sthx r0, r6, r7
asm.push("7C861B2E"); // sthx r4, r6, r3
}
// loadStage:
asm.push("7C661A2E"); // lhzx r3, r6, r3
asm.push("B07F0012"); // sth r3, 0x12(r31)
asm.push("808D" + game.fmOffset); // lwz r4, TFlagManager::smInstance
asm.push("986400DF"); // stb r3, 0xDF(r4)
asm.push("986500DF"); // stb r3, 0xDF(r5)
// done:
asm.push("807F0020"); // lwz r3, 0x20(r31)
if (asm.length % 2 === 0) {

View file

@ -95,12 +95,13 @@
</tr>
<tr>
<td nowrap>
<label for="route_random">Random Level Order:</label>
<label for="route_order">Level Order:</label>
</td>
<td style="width:100%">
<select id="route_random" style="width:100%" onmouseover="updateUIDescription(this)">
<option value="yes">Yes</option>
<option selected value="no">No</option>
<select id="route_order" style="width:100%" onmouseover="updateUIDescription(this)">
<option selected value="list">As specified</option>
<option value="shuffle">Random, no duplicates</option>
<option value="random">Fully random</option>
</select>
</td>
</tr>