summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/com/dabomstew/pkrandom/config/gen7_offsets.ini4
-rw-r--r--src/com/dabomstew/pkrandom/constants/Gen7Constants.java3
-rw-r--r--src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java101
3 files changed, 104 insertions, 4 deletions
diff --git a/src/com/dabomstew/pkrandom/config/gen7_offsets.ini b/src/com/dabomstew/pkrandom/config/gen7_offsets.ini
index 9c2d3f6..cfb9682 100644
--- a/src/com/dabomstew/pkrandom/config/gen7_offsets.ini
+++ b/src/com/dabomstew/pkrandom/config/gen7_offsets.ini
@@ -25,6 +25,7 @@ PokemonGraphics=a/0/6/2
ZoneData=a/0/7/7
WildPokemon=a/0/8/2
WorldData=a/0/9/1
+Scripts=a/0/9/2
TrainerData=a/1/0/5
TrainerPokemon=a/1/0/6
StaticPokemon=a/1/5/5
@@ -55,6 +56,7 @@ DoublesTrainerClasses=[172, 173, 174, 174, 175, 176, 177, 178, 179, 181, 182]
CosmoemEvolutionNumber=791
LinkedStaticEncounterOffsets=[112:113, 120:131, 124:130] // UBs probably need to be added to this too
MainGameLegendaries=[791]
+ZygardeScriptLevelOffsets=[0x19D6, 0x19F8]
[Moon]
Game=CTR-P-BNEA
@@ -93,6 +95,7 @@ PokemonGraphics=a/0/6/2
ZoneData=a/0/7/7
WildPokemon=a/0/8/2
WorldData=a/0/9/1
+Scripts=a/0/9/2
TrainerData=a/1/0/6
TrainerPokemon=a/1/0/7
StaticPokemon=a/1/5/9
@@ -123,6 +126,7 @@ DoublesTrainerClasses=[172, 173, 174, 174, 175, 176, 177, 178, 179, 181, 182, 21
CosmoemEvolutionNumber=791
LinkedStaticEncounterOffsets=[127:128, 135:146, 139:145] // Unused SM UBs need to be added to this, probably other stuff too
MainGameLegendaries=[800]
+ZygardeScriptLevelOffsets=[0x1B3E, 0x1B60]
[Ultra Moon]
Game=CTR-P-A2BA
diff --git a/src/com/dabomstew/pkrandom/constants/Gen7Constants.java b/src/com/dabomstew/pkrandom/constants/Gen7Constants.java
index fa0a040..19e4f91 100644
--- a/src/com/dabomstew/pkrandom/constants/Gen7Constants.java
+++ b/src/com/dabomstew/pkrandom/constants/Gen7Constants.java
@@ -173,6 +173,9 @@ public class Gen7Constants {
public static final String miniorWildEncounterPatchPrefix = "032C42E2062052E2";
+ public static final int zygardeAssemblyScriptFile = 45;
+ public static final String zygardeAssemblyFormePrefix = "BC21CDE1B801CDE1", zygardeAssemblySpeciesPrefix = "FBEB4CD08DE20400A0E1F08FBDE8";
+
public static int getPokemonCount(int romType) {
if (romType == Type_SM) {
return pokemonCountSM;
diff --git a/src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java
index 89bb1bb..a586429 100644
--- a/src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java
+++ b/src/com/dabomstew/pkrandom/romhandlers/Gen7RomHandler.java
@@ -28,6 +28,7 @@ import com.dabomstew.pkrandom.MiscTweak;
import com.dabomstew.pkrandom.RomFunctions;
import com.dabomstew.pkrandom.Settings;
import com.dabomstew.pkrandom.constants.*;
+import com.dabomstew.pkrandom.ctr.AMX;
import com.dabomstew.pkrandom.ctr.BFLIM;
import com.dabomstew.pkrandom.ctr.GARCArchive;
import com.dabomstew.pkrandom.ctr.Mini;
@@ -36,9 +37,7 @@ import com.dabomstew.pkrandom.pokemon.*;
import pptxt.N3DSTxtHandler;
import java.awt.image.BufferedImage;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.PrintStream;
+import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
@@ -1300,7 +1299,7 @@ public class Gen7RomHandler extends Abstract3DSRomHandler {
byte[] worldData = zoneDataGarc.getFile(1);
List<String> locationList = createGoodLocationList();
ZoneData[] zoneData = getZoneData(zoneDataBytes, worldData, locationList, worlds);
- encounterGarc = readGARC(romEntry.getString("WildPokemon"), Gen7Constants.getRelevantEncounterFiles(romEntry.romType));;
+ encounterGarc = readGARC(romEntry.getString("WildPokemon"), Gen7Constants.getRelevantEncounterFiles(romEntry.romType));
int fileCount = encounterGarc.files.size();
int numberOfAreas = fileCount / 11;
AreaData[] areaData = new AreaData[numberOfAreas];
@@ -1910,6 +1909,9 @@ public class Gen7RomHandler extends Abstract3DSRomHandler {
StaticEncounter se = readStaticEncounter(staticEncountersFile, offset);
statics.add(se);
}
+
+ // Zygarde created via Assembly on Route 16 is hardcoded
+ readAssemblyZygarde(statics);
} catch (IOException e) {
throw new RandomizerIOException(e);
}
@@ -1952,6 +1954,62 @@ public class Gen7RomHandler extends Abstract3DSRomHandler {
}
}
+ private void readAssemblyZygarde(List<StaticEncounter> statics) throws IOException {
+ GARCArchive scriptGarc = readGARC(romEntry.getString("Scripts"), true);
+ int[] scriptLevelOffsets = romEntry.arrayEntries.get("ZygardeScriptLevelOffsets");
+ int[] levels = new int[scriptLevelOffsets.length];
+ byte[] zygardeAssemblyScriptBytes = scriptGarc.getFile(Gen7Constants.zygardeAssemblyScriptFile);
+ AMX zygardeAssemblyScript = new AMX(zygardeAssemblyScriptBytes);
+ for (int i = 0; i < scriptLevelOffsets.length; i++) {
+ levels[i] = zygardeAssemblyScript.decData[scriptLevelOffsets[i]];
+ }
+
+ int speciesOffset = find(code, Gen7Constants.zygardeAssemblySpeciesPrefix);
+ int formeOffset = find(code, Gen7Constants.zygardeAssemblyFormePrefix);
+ if (speciesOffset > 0 && formeOffset > 0) {
+ speciesOffset += Gen7Constants.zygardeAssemblySpeciesPrefix.length() / 2; // because it was a prefix
+ formeOffset += Gen7Constants.zygardeAssemblyFormePrefix.length() / 2; // because it was a prefix
+ int species = FileFunctions.read2ByteInt(code, speciesOffset);
+
+ // The original code for this passed in the forme via a parameter, stored that onto
+ // the stack, then did a ldr to put that stack variable into r0 before finally
+ // storing that value in the right place. If we already modified this code, then we
+ // don't care about all of this; we just wrote a "mov r0, #forme" over the ldr instead.
+ // Thus, if the original ldr instruction is still there, assume we haven't touched it.
+ int forme = 0;
+ if (FileFunctions.readFullIntLittleEndian(code, formeOffset) == 0xE59D0040) {
+ // Since we haven't modified the code yet, this is Zygarde. For SM, use 10%,
+ // since you can get it fairly early. For USUM, use 50%, since it's only
+ // obtainable in the postgame.
+ forme = isSM ? 1 : 0;
+ } else {
+ // We have modified the code, so just read the constant forme number we wrote.
+ forme = code[formeOffset];
+ }
+
+ StaticEncounter lowLevelAssembly = new StaticEncounter();
+ Pokemon pokemon = pokes[species];
+ if (forme > pokemon.cosmeticForms && forme != 30 && forme != 31) {
+ int speciesWithForme = absolutePokeNumByBaseForme
+ .getOrDefault(species, dummyAbsolutePokeNums)
+ .getOrDefault(forme, 0);
+ pokemon = pokes[speciesWithForme];
+ }
+ lowLevelAssembly.pkmn = pokemon;
+ lowLevelAssembly.forme = forme;
+ lowLevelAssembly.level = levels[0];
+ for (int i = 1; i < levels.length; i++) {
+ StaticEncounter higherLevelAssembly = new StaticEncounter();
+ higherLevelAssembly.pkmn = pokemon;
+ higherLevelAssembly.forme = forme;
+ higherLevelAssembly.level = levels[i];
+ lowLevelAssembly.linkedEncounters.add(higherLevelAssembly);
+ }
+
+ statics.add(lowLevelAssembly);
+ }
+ }
+
@Override
public boolean setStaticPokemon(List<StaticEncounter> staticPokemon) {
try {
@@ -1997,6 +2055,9 @@ public class Gen7RomHandler extends Abstract3DSRomHandler {
}
}
+ // Zygarde created via Assembly on Route 16 is hardcoded
+ writeAssemblyZygarde(staticIter.next());
+
writeGARC(romEntry.getString("StaticPokemon"), staticGarc);
return true;
} catch (IOException e) {
@@ -2019,6 +2080,38 @@ public class Gen7RomHandler extends Abstract3DSRomHandler {
}
}
+ private void writeAssemblyZygarde(StaticEncounter se) throws IOException {
+ int[] levels = new int[se.linkedEncounters.size() + 1];
+ levels[0] = se.level;
+ for (int i = 0; i < se.linkedEncounters.size(); i++) {
+ levels[i + 1] = se.linkedEncounters.get(i).level;
+ }
+
+ GARCArchive scriptGarc = readGARC(romEntry.getString("Scripts"), true);
+ int[] scriptLevelOffsets = romEntry.arrayEntries.get("ZygardeScriptLevelOffsets");
+ byte[] zygardeAssemblyScriptBytes = scriptGarc.getFile(Gen7Constants.zygardeAssemblyScriptFile);
+ AMX zygardeAssemblyScript = new AMX(zygardeAssemblyScriptBytes);
+ for (int i = 0; i < scriptLevelOffsets.length; i++) {
+ zygardeAssemblyScript.decData[scriptLevelOffsets[i]] = (byte) levels[i];
+ }
+ scriptGarc.setFile(Gen7Constants.zygardeAssemblyScriptFile, zygardeAssemblyScript.getBytes());
+ writeGARC(romEntry.getString("Scripts"), scriptGarc);
+
+ int speciesOffset = find(code, Gen7Constants.zygardeAssemblySpeciesPrefix);
+ int formeOffset = find(code, Gen7Constants.zygardeAssemblyFormePrefix);
+ if (speciesOffset > 0 && formeOffset > 0) {
+ speciesOffset += Gen7Constants.zygardeAssemblySpeciesPrefix.length() / 2; // because it was a prefix
+ formeOffset += Gen7Constants.zygardeAssemblyFormePrefix.length() / 2; // because it was a prefix
+ FileFunctions.write2ByteInt(code, speciesOffset, se.pkmn.getBaseNumber());
+
+ // Just write "mov r0, #forme" to where the game originally loaded the forme.
+ code[formeOffset] = (byte) se.forme;
+ code[formeOffset + 1] = 0x00;
+ code[formeOffset + 2] = (byte) 0xA0;
+ code[formeOffset + 3] = (byte) 0xE3;
+ }
+ }
+
@Override
public int miscTweaksAvailable() {
int available = 0;