diff options
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; |