summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortom-overton <tom.overton@outlook.com>2021-11-30 21:58:57 -0800
committertom-overton <tom.overton@outlook.com>2021-11-30 21:59:03 -0800
commit8de76ba96b838f64600aa3ffb826c0aad1078fa2 (patch)
treedd4fb1f4420f17e45c2cbdb0d6938cc1ba140e8f /src
parent092413713ebf9e86431339e440d16310179abaff (diff)
XY: Add support for randomizing the roamer while they roam
We already supported randomizing the roamer when they come to rest at the Sea Spirit's Den, but while they were roaming, they were still Articuno/Zapdos/Moltres. This allows the randomizer to patch the executable such that the roamer is the same both when it roams and when it comes to rest.
Diffstat (limited to 'src')
-rw-r--r--src/com/dabomstew/pkrandom/config/gen6_offsets.ini1
-rw-r--r--src/com/dabomstew/pkrandom/constants/Gen6Constants.java5
-rw-r--r--src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java64
3 files changed, 69 insertions, 1 deletions
diff --git a/src/com/dabomstew/pkrandom/config/gen6_offsets.ini b/src/com/dabomstew/pkrandom/config/gen6_offsets.ini
index 4222a7c..5943ffc 100644
--- a/src/com/dabomstew/pkrandom/config/gen6_offsets.ini
+++ b/src/com/dabomstew/pkrandom/config/gen6_offsets.ini
@@ -65,6 +65,7 @@ BoxLegendaryOffsets=[2, 12]
BoxLegendaryScriptOffsets=[4658, 5430, 16798]
LinkedStaticEncounterOffsets=[1:3, 2:12]
MainGameLegendaries=[716]
+RoamingLegendaryOffsets=[6, 7, 8]
[Y]
Game=CTR-P-EK2A
diff --git a/src/com/dabomstew/pkrandom/constants/Gen6Constants.java b/src/com/dabomstew/pkrandom/constants/Gen6Constants.java
index c858111..445fdee 100644
--- a/src/com/dabomstew/pkrandom/constants/Gen6Constants.java
+++ b/src/com/dabomstew/pkrandom/constants/Gen6Constants.java
@@ -239,13 +239,16 @@ public class Gen6Constants {
public static final int[] boxLegendaryCodeOffsetsXY = new int[]{ 144, 300, 584 };
public static final String rayquazaFunctionPrefixORAS = "0900A0E1F08FBDE8";
public static final int[] rayquazaScriptOffsetsORAS = new int[]{ 3334, 14734 }, rayquazaCodeOffsetsORAS = new int[]{ 136, 292, 576 };
- public static final String nationalDexFunctionLocator = "080094E5010000E21080BDE8170F122F",xyGetDexFlagFunctionLocator = "000055E30100A0030A00000A",
+ public static final String nationalDexFunctionLocator = "080094E5010000E21080BDE8170F122F", xyGetDexFlagFunctionLocator = "000055E30100A0030A00000A",
orasGetHoennDexCaughtFunctionPrefix = "170F122F1CC15800";
public static final int megastoneTableStartingOffsetORAS = 0xABA, megastoneTableEntrySizeORAS = 0x20, megastoneTableLengthORAS = 27;
public static final String pickupTableLocator = "110012001A00";
public static final int numberOfPickupItems = 29;
+ public static final String xyRoamerFreeSpacePostfix = "540095E50220A0E30810A0E1", xyRoamerSpeciesLocator = "9040A0030400000A",
+ xyRoamerLevelPrefix = "B020DDE13F3BC1E3";
+
public static final List<Integer> consumableHeldItems = setupAllConsumableItems();
private static List<Integer> setupAllConsumableItems() {
diff --git a/src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java
index 6aa4fd4..7d9d3af 100644
--- a/src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/Gen6RomHandler.java
@@ -2113,6 +2113,7 @@ public class Gen6RomHandler extends Abstract3DSRomHandler {
int[] boxLegendaryOffsets = romEntry.arrayEntries.get("BoxLegendaryOffsets");
StaticEncounter boxLegendaryEncounter = staticPokemon.get(boxLegendaryOffsets[0]);
fixBoxLegendariesXY(boxLegendaryEncounter.pkmn.number);
+ setRoamersXY(staticPokemon);
} else {
StaticEncounter rayquazaEncounter = staticPokemon.get(romEntry.getInt("RayquazaEncounterNumber"));
fixRayquazaORAS(rayquazaEncounter.pkmn.number);
@@ -2187,6 +2188,69 @@ public class Gen6RomHandler extends Abstract3DSRomHandler {
writeFile(romEntry.getString("StaticPokemon"), staticCRO);
}
+ private void setRoamersXY(List<StaticEncounter> staticPokemon) throws IOException {
+ int[] roamingLegendaryOffsets = romEntry.arrayEntries.get("RoamingLegendaryOffsets");
+ StaticEncounter[] roamers = new StaticEncounter[roamingLegendaryOffsets.length];
+ for (int i = 0; i < roamers.length; i++) {
+ roamers[i] = staticPokemon.get(roamingLegendaryOffsets[i]);
+ }
+ int roamerSpeciesOffset = find(code, Gen6Constants.xyRoamerSpeciesLocator);
+ int freeSpaceOffset = find(code, Gen6Constants.xyRoamerFreeSpacePostfix);
+ if (roamerSpeciesOffset > 0 && freeSpaceOffset > 0) {
+ // In order to make this code work with all versions of XY, we had to find the *end* of our free space.
+ // The beginning is five instructions back.
+ freeSpaceOffset -= 20;
+
+ // The unmodified code looks like this:
+ // nop
+ // bl FUN_0041b710
+ // nop
+ // nop
+ // b LAB_003b7d1c
+ // We want to move both branches to the top so that we have 12 bytes of space to work with.
+ // Start by moving "bl FUN_0041b710" up one instruction, making sure to adjust the branch accordingly.
+ code[freeSpaceOffset] = (byte)(code[freeSpaceOffset + 4] + 1);
+ code[freeSpaceOffset + 1] = code[freeSpaceOffset + 5];
+ code[freeSpaceOffset + 2] = code[freeSpaceOffset + 6];
+ code[freeSpaceOffset + 3] = code[freeSpaceOffset + 7];
+
+ // Now move "b LAB_003b7d1c" up three instructions, again adjusting the branch accordingly.
+ code[freeSpaceOffset + 4] = (byte)(code[freeSpaceOffset + 16] + 3);
+ code[freeSpaceOffset + 5] = code[freeSpaceOffset + 17];
+ code[freeSpaceOffset + 6] = code[freeSpaceOffset + 18];
+ code[freeSpaceOffset + 7] = code[freeSpaceOffset + 19];
+
+ // In the free space now opened up, write the three roamer species.
+ for (int i = 0; i < roamers.length; i++) {
+ int offset = freeSpaceOffset + 8 + (i * 4);
+ int species = roamers[i].pkmn.getBaseNumber();
+ FileFunctions.writeFullIntLittleEndian(code, offset, species);
+ }
+
+ // To load the species ID, the game currently does "moveq r4, #0x90" for Articuno and similar
+ // things for Zapdos and Moltres. Instead, just pc-relative load what we wrote before. The fact
+ // that we change the conditional moveq to the unconditional pc-relative load only matters for
+ // the case where the player's starter index is *not* 0, 1, or 2, but that can't happen outside
+ // of save editing.
+ for (int i = 0; i < roamers.length; i++) {
+ int offset = roamerSpeciesOffset + (i * 12);
+ code[offset] = (byte)(0xAC - (8 * i));
+ code[offset + 1] = 0x41;
+ code[offset + 2] = (byte) 0x9F;
+ code[offset + 3] = (byte) 0xE5;
+ }
+ }
+
+ // The level of the roamer is set by a separate function in DllField.
+ byte[] fieldCRO = readFile(romEntry.getString("Field"));
+ int levelOffset = find(fieldCRO, Gen6Constants.xyRoamerLevelPrefix);
+ if (levelOffset > 0) {
+ levelOffset += Gen6Constants.xyRoamerLevelPrefix.length() / 2; // because it was a prefix
+ fieldCRO[levelOffset] = (byte) roamers[0].level;
+ }
+ writeFile(romEntry.getString("Field"), fieldCRO);
+ }
+
private void fixRayquazaORAS(int rayquazaEncounterSpecies) throws IOException {
// We need to edit the script file or otherwise the text will still say "Rayquaza"
int rayquazaScriptFile = romEntry.getInt("RayquazaEncounterScriptNumber");