add stage loader code generator
This commit is contained in:
parent
df1aef2c11
commit
e2b9e2bd44
6 changed files with 224 additions and 29 deletions
|
@ -1,5 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<ButtonComponent label="Download" :onClick="onClick" :disabled="!codes || codes.length === 0" />
|
<ButtonComponent
|
||||||
|
label="Download"
|
||||||
|
:onClick="onClick"
|
||||||
|
:disabled="(!codes || codes.length === 0) && !stageLoaderCode"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -9,33 +13,39 @@ import CodeFormatter from "./scripts/codeFormatter";
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
codes: { type: Array },
|
codes: { type: Array },
|
||||||
|
stageLoaderCode: { type: String },
|
||||||
format: { type: String },
|
format: { type: String },
|
||||||
versionIdentifier: { type: String }
|
versionIdentifier: { type: String },
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onClick() {
|
onClick() {
|
||||||
if (!this.codes || this.codes.length === 0) {
|
if (!(this.codes || this.codes.length === 0) && !this.stageLoaderCode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const c = [...(this.codes ?? [])];
|
||||||
|
|
||||||
|
if (this.stageLoaderCode)
|
||||||
|
c.push({
|
||||||
|
title: "Stage List Loader",
|
||||||
|
author: "Noki Doki",
|
||||||
|
date: "-",
|
||||||
|
version: "",
|
||||||
|
source: this.stageLoaderCode,
|
||||||
|
});
|
||||||
|
|
||||||
console.log(`Preparing download for ${this.format}`);
|
console.log(`Preparing download for ${this.format}`);
|
||||||
switch (this.format) {
|
switch (this.format) {
|
||||||
case "gct":
|
case "gct":
|
||||||
CodeFormatter.generateGCT(this.codes, this.versionIdentifier);
|
CodeFormatter.generateGCT(c, this.versionIdentifier);
|
||||||
break;
|
break;
|
||||||
case "dolphin":
|
case "dolphin":
|
||||||
CodeFormatter.generateDolphinINI(this.codes, this.versionIdentifier);
|
CodeFormatter.generateDolphinINI(c, this.versionIdentifier);
|
||||||
break;
|
break;
|
||||||
case "gcm":
|
case "gcm":
|
||||||
CodeFormatter.generateCheatManagerTXT(
|
CodeFormatter.generateCheatManagerTXT(c, this.versionIdentifier);
|
||||||
this.codes,
|
|
||||||
this.versionIdentifier
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<SelectComponent :options="options" :onChange="onChange" />
|
<SelectComponent
|
||||||
|
placeholder="Choose Format"
|
||||||
|
:options="options"
|
||||||
|
:selectedValue="selectedValue"
|
||||||
|
:onChange="onChange"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// Components
|
||||||
import SelectComponent from "./SelectComponent";
|
import SelectComponent from "./SelectComponent";
|
||||||
|
|
||||||
|
// Data
|
||||||
import downloadFormats from "../data/downloadFormats.json";
|
import downloadFormats from "../data/downloadFormats.json";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -12,9 +19,6 @@ export default {
|
||||||
selectedValue: { type: String },
|
selectedValue: { type: String },
|
||||||
onChange: { type: Function },
|
onChange: { type: Function },
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
this.onChange(downloadFormats[0].target);
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
options: downloadFormats.map((v) => ({
|
options: downloadFormats.map((v) => ({
|
||||||
|
|
|
@ -6,28 +6,38 @@
|
||||||
<section class="config">
|
<section class="config">
|
||||||
<div>
|
<div>
|
||||||
<span>Game Version:</span>
|
<span>Game Version:</span>
|
||||||
<VersionSelect :onChange="onVersionChanged" />
|
<VersionSelect
|
||||||
|
:onChange="onVersionChanged"
|
||||||
|
:selectedValue="selectedVersion"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>Download Format:</span>
|
<span>Download Format:</span>
|
||||||
<FormatSelect :onChange="onFormatChanged" />
|
<FormatSelect
|
||||||
|
:onChange="onFormatChanged"
|
||||||
|
:selectedValue="selectedFormat"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>Use Stage Loader:</span>
|
<span>Use Stage Loader:</span>
|
||||||
<SelectComponent
|
<SelectComponent
|
||||||
:options="useStageLoaderOptions"
|
:options="useStageLoaderOptions"
|
||||||
:onChange="onStageLoaderChanged"
|
:onChange="onStageLoaderChanged"
|
||||||
|
:value="useStageLoader"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>Download:</span>
|
<span>Download:</span>
|
||||||
<DownloadButton
|
<DownloadButton
|
||||||
:codes="selectedCheats"
|
:codes="selectedCheats"
|
||||||
|
:stageLoaderCode="selectedStageLoader"
|
||||||
:versionIdentifier="selectedVersion"
|
:versionIdentifier="selectedVersion"
|
||||||
:format="selectedFormat"
|
:format="selectedFormat"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
<section>
|
<section>
|
||||||
<div v-if="codes && codes.length > 0">
|
<div v-if="codes && codes.length > 0">
|
||||||
<h3>Available Codes</h3>
|
<h3>Available Codes</h3>
|
||||||
|
@ -42,7 +52,10 @@
|
||||||
v-if="codes && codes.length > 0 && useStageLoader"
|
v-if="codes && codes.length > 0 && useStageLoader"
|
||||||
>
|
>
|
||||||
<h3>Stage Loader</h3>
|
<h3>Stage Loader</h3>
|
||||||
<StageLoader :fastCodes="stageLoaderCodes" />
|
<StageLoader
|
||||||
|
:fastCodes="stageLoaderCodes"
|
||||||
|
:onChange="onStageLoaderCodeChanged"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="codes && codes.length > 0" class="help">
|
<div v-if="codes && codes.length > 0" class="help">
|
||||||
|
@ -126,7 +139,7 @@ import DownloadButton from "./DownloadButton";
|
||||||
// Data
|
// Data
|
||||||
import gameVersions from "../data/gameVersions.json";
|
import gameVersions from "../data/gameVersions.json";
|
||||||
|
|
||||||
// Helpers
|
// Util
|
||||||
import parseXml from "./scripts/parseXml";
|
import parseXml from "./scripts/parseXml";
|
||||||
|
|
||||||
// Libs
|
// Libs
|
||||||
|
@ -157,7 +170,7 @@ export default {
|
||||||
selectedStageLoader: null,
|
selectedStageLoader: null,
|
||||||
inspectingCode: null,
|
inspectingCode: null,
|
||||||
selectedVersion: null,
|
selectedVersion: null,
|
||||||
selectedFormat: null,
|
selectedFormat: "gct",
|
||||||
useStageLoader: false,
|
useStageLoader: false,
|
||||||
stageLoaderCodes: [],
|
stageLoaderCodes: [],
|
||||||
useStageLoaderOptions: [
|
useStageLoaderOptions: [
|
||||||
|
@ -182,10 +195,14 @@ export default {
|
||||||
},
|
},
|
||||||
onStageLoaderChanged(e) {
|
onStageLoaderChanged(e) {
|
||||||
this.useStageLoader = e === true || e === "true";
|
this.useStageLoader = e === true || e === "true";
|
||||||
|
if (!this.useStageLoader) this.selectedStageLoader = null;
|
||||||
},
|
},
|
||||||
onCheatSelectionChanged(e) {
|
onCheatSelectionChanged(e) {
|
||||||
this.selectedCheats = e;
|
this.selectedCheats = e;
|
||||||
},
|
},
|
||||||
|
onStageLoaderCodeChanged(e) {
|
||||||
|
this.selectedStageLoader = e;
|
||||||
|
},
|
||||||
inspect(code) {
|
inspect(code) {
|
||||||
this.inspectingCode = code;
|
this.inspectingCode = code;
|
||||||
},
|
},
|
||||||
|
|
|
@ -96,12 +96,16 @@ import GroupSelectComponent from "./GroupSelectComponent";
|
||||||
import stageLoaderLevels from "../data/stageLoaderLevels.json";
|
import stageLoaderLevels from "../data/stageLoaderLevels.json";
|
||||||
import stageLoaderPresets from "../data/stageLoaderPresets.json";
|
import stageLoaderPresets from "../data/stageLoaderPresets.json";
|
||||||
|
|
||||||
|
// Util
|
||||||
|
import generateStageLoaderCode from "./scripts/generateStageLoadercode";
|
||||||
|
|
||||||
// Lib
|
// Lib
|
||||||
import draggable from "vuedraggable";
|
import draggable from "vuedraggable";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
fastCodes: { type: Object },
|
fastCodes: { type: Object },
|
||||||
|
onChange: { type: Function },
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
draggable,
|
draggable,
|
||||||
|
@ -132,39 +136,46 @@ export default {
|
||||||
{ value: "3400", label: "Load post-Corona plaza" },
|
{ value: "3400", label: "Load post-Corona plaza" },
|
||||||
{ value: "3C00", label: "Load the Bowser fight" },
|
{ value: "3C00", label: "Load the Bowser fight" },
|
||||||
],
|
],
|
||||||
removeDialogSelection: null,
|
removeDialogSelection: "yes",
|
||||||
skippableFMVsSelection: null,
|
skippableFMVsSelection: "yes",
|
||||||
levelOrderSelection: null,
|
levelOrderSelection: "list",
|
||||||
postGameSelection: null,
|
postGameSelection: "0F00",
|
||||||
generation: 0,
|
generation: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onRemoveDialogueSelectionChanged(e) {
|
onRemoveDialogueSelectionChanged(e) {
|
||||||
this.removeDialogSelection = e;
|
this.removeDialogSelection = e;
|
||||||
|
this.updateCode();
|
||||||
},
|
},
|
||||||
onSkippableFMVsSelectionChanged(e) {
|
onSkippableFMVsSelectionChanged(e) {
|
||||||
this.skippableFMVsSelection = e;
|
this.skippableFMVsSelection = e;
|
||||||
|
this.updateCode();
|
||||||
},
|
},
|
||||||
onLevelOrderSelectionChanged(e) {
|
onLevelOrderSelectionChanged(e) {
|
||||||
this.levelOrderSelection = e;
|
this.levelOrderSelection = e;
|
||||||
|
this.updateCode();
|
||||||
},
|
},
|
||||||
onPostGameSelectionChanged(e) {
|
onPostGameSelectionChanged(e) {
|
||||||
this.postGameSelection = e;
|
this.postGameSelection = e;
|
||||||
|
this.updateCode();
|
||||||
},
|
},
|
||||||
onStageLoaderLevelSelected(e) {
|
onStageLoaderLevelSelected(e) {
|
||||||
this.generation++;
|
this.generation++;
|
||||||
this.selectedRoute.push({
|
this.selectedRoute.push({
|
||||||
value: e,
|
value: e,
|
||||||
});
|
});
|
||||||
|
this.updateCode();
|
||||||
},
|
},
|
||||||
onStageLoaderLevelChanged(index, e) {
|
onStageLoaderLevelChanged(index, e) {
|
||||||
this.selectedRoute[index] = {
|
this.selectedRoute[index] = {
|
||||||
value: e,
|
value: e,
|
||||||
};
|
};
|
||||||
|
this.updateCode();
|
||||||
},
|
},
|
||||||
onLevelDeleted(e) {
|
onLevelDeleted(e) {
|
||||||
this.selectedRoute.splice(e, 1);
|
this.selectedRoute.splice(e, 1);
|
||||||
|
this.updateCode();
|
||||||
},
|
},
|
||||||
onStageLoaderPresetSelected(e) {
|
onStageLoaderPresetSelected(e) {
|
||||||
this.generation++;
|
this.generation++;
|
||||||
|
@ -185,7 +196,9 @@ export default {
|
||||||
newRoute.push({ value: preset.substr(i, 4) });
|
newRoute.push({ value: preset.substr(i, 4) });
|
||||||
|
|
||||||
this.selectedRoute = newRoute;
|
this.selectedRoute = newRoute;
|
||||||
this.postGameSelection = ending;
|
|
||||||
|
if (ending) this.postGameSelection;
|
||||||
|
this.updateCode();
|
||||||
},
|
},
|
||||||
onClearList() {
|
onClearList() {
|
||||||
if (
|
if (
|
||||||
|
@ -195,9 +208,31 @@ export default {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.selectedRoute = [];
|
this.selectedRoute = [];
|
||||||
|
this.updateCode();
|
||||||
},
|
},
|
||||||
checkMove(e) {
|
updateCode() {
|
||||||
window.console.log("Future index: " + e.draggedContext.futureIndex);
|
if (
|
||||||
|
this.selectedRoute.length === 0 ||
|
||||||
|
this.levelOrderSelection == null ||
|
||||||
|
this.postGameSelection == null ||
|
||||||
|
this.skippableFMVsSelection == null ||
|
||||||
|
this.removeDialogSelection == null
|
||||||
|
) {
|
||||||
|
this.onChange(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Generating new Stageloader-Code");
|
||||||
|
this.onChange(
|
||||||
|
generateStageLoaderCode(
|
||||||
|
this.fastCodes,
|
||||||
|
this.selectedRoute.map((v) => v.value),
|
||||||
|
this.levelOrderSelection,
|
||||||
|
this.postGameSelection,
|
||||||
|
this.skippableFMVsSelection,
|
||||||
|
this.removeDialogSelection
|
||||||
|
)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -208,6 +243,7 @@ export default {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config:not(:first-child) span {
|
.config:not(:first-child) span {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<SelectComponent
|
<SelectComponent
|
||||||
placeholder="Choose Version.."
|
placeholder="Choose Version.."
|
||||||
|
:selectedValue="selectedValue"
|
||||||
:options="options"
|
:options="options"
|
||||||
:onChange="onChange"
|
:onChange="onChange"
|
||||||
/>
|
/>
|
||||||
|
|
127
docs/.vuepress/components/scripts/generateStageLoadercode.js
Normal file
127
docs/.vuepress/components/scripts/generateStageLoadercode.js
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
const generateStageLoaderCode = (
|
||||||
|
gameConfig,
|
||||||
|
selectedLevels,
|
||||||
|
routeOrder,
|
||||||
|
routeEnding,
|
||||||
|
fmvSkips,
|
||||||
|
dialgueSkips
|
||||||
|
) => {
|
||||||
|
const loadStageLength = {
|
||||||
|
list: 0x20,
|
||||||
|
random: 0x2c,
|
||||||
|
shuffle: 0x40,
|
||||||
|
}[routeOrder];
|
||||||
|
|
||||||
|
let codes = "";
|
||||||
|
|
||||||
|
// Reset counter on file select
|
||||||
|
codes +=
|
||||||
|
"0" +
|
||||||
|
(0x04000000 + (gameConfig.fileSelect & 0x01ffffff)).toString(16) +
|
||||||
|
(
|
||||||
|
0x48000001 +
|
||||||
|
((gameConfig.system + 0x52c - gameConfig.fileSelect) & 0x03fffffc)
|
||||||
|
).toString(16);
|
||||||
|
|
||||||
|
// Load next stage on Shine get
|
||||||
|
codes +=
|
||||||
|
"0" +
|
||||||
|
(0x04000000 + (gameConfig.shineGet & 0x01ffffff)).toString(16) +
|
||||||
|
(
|
||||||
|
0x48000001 +
|
||||||
|
((gameConfig.system + 0x53c - gameConfig.shineGet) & 0x03fffffc)
|
||||||
|
).toString(16);
|
||||||
|
|
||||||
|
// Reload stage on exit area
|
||||||
|
codes +=
|
||||||
|
"0" +
|
||||||
|
(0x04000000 + (gameConfig.system & 0x01ffffff)).toString(16) +
|
||||||
|
"48000511";
|
||||||
|
|
||||||
|
// Set next stage on game over
|
||||||
|
codes +=
|
||||||
|
"0" +
|
||||||
|
(0x06000000 + ((gameConfig.system + 0xb4) & 0x01ffffff)).toString(16) +
|
||||||
|
"000000084800048948000044";
|
||||||
|
|
||||||
|
// Reset timer on secret death
|
||||||
|
codes +=
|
||||||
|
(0xc2000000 + ((gameConfig.system + 0x208) & 0x01ffffff)).toString(16) +
|
||||||
|
"000000033C60817F38000001980300FF881C00006000000000000000";
|
||||||
|
|
||||||
|
// Reset coin count on loading main world
|
||||||
|
codes +=
|
||||||
|
(0xc2000000 + ((gameConfig.shineGet - 0x674) & 0x01ffffff)).toString(16) +
|
||||||
|
"00000005887D00002C030002418000142C0300074182000C2C03000A418000087C0400406000000000000000";
|
||||||
|
|
||||||
|
// Overwrite decideNextStage(void) with useful routines
|
||||||
|
codes +=
|
||||||
|
"0" +
|
||||||
|
(0x06000000 + ((gameConfig.system + 0x510) & 0x01ffffff)).toString(16) +
|
||||||
|
("0000000" + (loadStageLength + 0x5c).toString(16)).slice(-8) +
|
||||||
|
"3C60817F38000001980300FFA00300023C60" +
|
||||||
|
gameConfig.gpAppHi +
|
||||||
|
"B003" +
|
||||||
|
gameConfig.gpAppLo +
|
||||||
|
"4E800020" + // reload current level
|
||||||
|
"3C60817F" +
|
||||||
|
(0x38800000 + ((selectedLevels.length * 2) & 0x0000ffff)).toString(16) +
|
||||||
|
"B08300004E800020" + // reset counter
|
||||||
|
"3C60817F38000001980300FFA00300002C00000038E0" +
|
||||||
|
routeEnding + // load next stage - the fun begins
|
||||||
|
(0x40810000 + (loadStageLength & 0x0000fffc)).toString(16) +
|
||||||
|
"7C8802A6600000007CC802A67C8803A6";
|
||||||
|
|
||||||
|
switch (routeOrder) {
|
||||||
|
case "list":
|
||||||
|
codes += "3400FFFEB00300007CE6022E";
|
||||||
|
break;
|
||||||
|
case "random":
|
||||||
|
codes += "7C8C42E67CA403967CA501D67C8520505484003C7CE6222E";
|
||||||
|
break;
|
||||||
|
case "shuffle":
|
||||||
|
codes +=
|
||||||
|
"7C8C42E67CA403967CA501D67C8520505484003C3400FFFEB00300007CE6222E7CA6022E7CA6232E7CE6032E";
|
||||||
|
}
|
||||||
|
|
||||||
|
codes +=
|
||||||
|
"B0E300023C60" +
|
||||||
|
gameConfig.gpAppHi +
|
||||||
|
"B0E3" +
|
||||||
|
gameConfig.gpAppLo +
|
||||||
|
"806D" +
|
||||||
|
gameConfig.fmOffset +
|
||||||
|
"98E300DF4E800020" +
|
||||||
|
(routeOrder === "random" ? "" : "00000000");
|
||||||
|
|
||||||
|
selectedLevels.reverse();
|
||||||
|
|
||||||
|
while (selectedLevels.length % 4) selectedLevels.push("0000");
|
||||||
|
|
||||||
|
// Insert the list of levels into the loader
|
||||||
|
codes +=
|
||||||
|
(0xc2000000 + ((gameConfig.system + 0x55c) & 0x01ffffff)).toString(16) +
|
||||||
|
("0000000" + (selectedLevels.length / 4 + 1).toString(16)).slice(-8) +
|
||||||
|
(0x48000001 + ((selectedLevels.length * 2 + 4) & 0x03fffffc)).toString(16) +
|
||||||
|
selectedLevels.join("") +
|
||||||
|
"00000000";
|
||||||
|
|
||||||
|
// Load next stage on setNextStage into main level
|
||||||
|
codes +=
|
||||||
|
"0" +
|
||||||
|
(0x06000000 + ((gameConfig.system + 0x118c) & 0x01ffffff)).toString(16) +
|
||||||
|
"00000028B07D00143C80817F38000000B00400FFA0010038B01D00122C1C00094181000C4BFFF391B0E10038";
|
||||||
|
|
||||||
|
// Setup timer
|
||||||
|
codes +=
|
||||||
|
(0xc2000000 + (gameConfig.proc & 0x01ffffff)).toString(16) +
|
||||||
|
"000000053CA0817F388000009085010C880500FF98050100988500FF38800001988501016000000000000000";
|
||||||
|
|
||||||
|
codes = codes.toUpperCase();
|
||||||
|
|
||||||
|
codes += gameConfig.notext[dialgueSkips] + gameConfig.nofmvs[fmvSkips];
|
||||||
|
|
||||||
|
return codes;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default generateStageLoaderCode;
|
Loading…
Reference in a new issue