private void EditCompatibility(char BitToChangeTo, int PokemonToChange, int MoveNumber) { // Assume TM/HM editing to be the default. int PointerToCompatibilityTable = PointerToTMCompatibilityTable; int SizeOfEntryInBits = 58; switch (CurrentMode) { case "TM": case "HM": default: break; case "Tutor": PointerToCompatibilityTable = PointerToMoveTutorCompatibilityTable; SizeOfEntryInBits = NumberOfMoveTutorMoves; break; } using (GBABinaryReader RomRead = new GBABinaryReader(LoadedRom)) // Access the ROM as a readable file. { RomRead.BaseStream.Seek(PointerToCompatibilityTable, SeekOrigin.Begin); // Go to the pointer to the compatibility table. uint CompatibilityTable = RomRead.ReadPointer(); // Read the pointer. RomRead.BaseStream.Seek(CompatibilityTable + (PokemonToChange * SizeOfCompatibilityTableEntry), SeekOrigin.Begin); // Go to the specified Pokémon's entry in the compatibility table. ulong hexCompatibilityEntry; // Needs to be a ulong to support the 64bit TM/HM compatibility entries. switch (CurrentMode) { case "TM": case "HM": default: hexCompatibilityEntry = RomRead.ReadUInt64(); // Read the specified Pokémon's TM/HM compatibility entry. It is eight bytes long, so is a 64bit integer. break; case "Tutor": switch (LoadedRom.Code) { case "BPRE": default: hexCompatibilityEntry = RomRead.ReadUInt16(); // Read the specified Pokémon's move tutor compatibility entry. It is two bytes long, so is a 16bit integer. break; case "BPEE": hexCompatibilityEntry = RomRead.ReadUInt32(); // In Emerald, the move tutor compatibility entries are four bytes long, and so are 32bit integers. break; } break; } string stringCompatibilityEntry = ReverseString(ConvertToBinary(hexCompatibilityEntry).PadLeft(SizeOfEntryInBits, '0')); // Convert the compatibility entry to binary, as it is structured as a bitfield. // As the leading zeroes will not be there, pad the left of the string with 0s to make it the size of the entry in bits. // The bitfield is backwards, so reverse it. char[] CompatibilityWithMove = stringCompatibilityEntry.ToCharArray(); // Convert this string into an chararray. // This allows access of individual characters, and thereby modify individual entries in the bitfield. // The chararray is 0-indexed, so: // CompatibilityWithMove[0] = TM1 / Move Tutor move 1 // CompatibilityWithMove[14] = TM15 / Move Tutor move 15 // CompatibilityWithMove[49] = TM50 // CompatibilityWithMove[50] = HM01 --> CompatibilityWithMove[57] = HM08 CompatibilityWithMove[MoveNumber] = BitToChangeTo; // Update the specified compatibility with the move to be the specified value. // 0 for no compatibility, 1 for compatibility. stringCompatibilityEntry = new String(CompatibilityWithMove); // Revert the chararray back into a string. stringCompatibilityEntry = BinaryStringToHexString(ReverseString(stringCompatibilityEntry)); // The bitfield needs to be backwards again, so reverse it. // Convert it back into hex from binary. byte[] bytearrayCompatibilityEntry = StringToByteArray(stringCompatibilityEntry); // Convert the string into a bytearray, to be reinserted into the ROM. Array.Reverse(bytearrayCompatibilityEntry); // Reverse it once more to accommodate the ROM's endianness. using (GBABinaryWriter RomWrite = new GBABinaryWriter(LoadedRom)) // Access the ROM as a writeable ROM. { RomWrite.BaseStream.Seek(CompatibilityTable + (PokemonToChange * SizeOfCompatibilityTableEntry), SeekOrigin.Begin); // Go to the specified Pokémon's entry in the compatibility table. RomWrite.Write(bytearrayCompatibilityEntry); // Write the new compatibility entry to the ROM. } } }
private void UpdateROMData() { // Retrieve the number of Pokémon species in the ROM. using (GBABinaryReader RomRead = new GBABinaryReader(LoadedRom)) // Access the ROM as a readable file. { RomRead.BaseStream.Seek(PointerToNumberOfSpecies, SeekOrigin.Begin); // Go to the pointer to the number of species. NumberOfSpecies = RomRead.ReadUInt16(); // Read the number of species. It is two bytes long, so is a 16bit integer. } numPokemonMin.Value = 0; numPokemonMax.Value = NumberOfSpecies; // Clear the move lists. ListOfMoveNames.Clear(); ListOfMoves.Clear(); int PointerToMoveList = PointerToTMMoveList; // Take the TM as default. int NumberOfMovesInList = 50; switch (CurrentMode) { case "TM": // TMs are taken as default, so just exit the switch. default: break; case "HM": // HMs are a part of the TM move list, so the PointerToMoveList is the same. NumberOfMovesInList = 8; // However, there are only eight HMs, so change the NumberOfMovesInList to reflect this. break; case "Tutor": PointerToMoveList = PointerToMoveTutorMoveList; NumberOfMovesInList = NumberOfMoveTutorMoves; break; } using (GBABinaryReader RomRead = new GBABinaryReader(LoadedRom)) // Access the ROM as a readable file. { RomRead.BaseStream.Seek(PointerToMoveList, SeekOrigin.Begin); // Go to the pointer to the move list. uint MoveList = RomRead.ReadPointer(); // Read the pointer. if (CurrentMode == "HM") { MoveList += 50 * 2; // Skip past the TMs to the HM list. } RomRead.BaseStream.Seek(PointerToMoveNames, SeekOrigin.Begin); uint MoveNames = RomRead.ReadPointer(); for (uint i = 0; i < 0x1FF; i++) // Loop through every move and retrieve its name. { string MoveName = ROMCharactersToString(0xD, MoveNames + i * 0xD); // Retrieve the name from its ROM location and convert it from the Pokémon character encoding to ASCII. ListOfMoveNames.Add(MoveName); // Add the name to the list. } RomRead.BaseStream.Seek(MoveList, SeekOrigin.Begin); // Go to the move list. for (int i = 0; i < NumberOfMovesInList; i++) { int MoveId = RomRead.ReadUInt16(); // Read the 2-byte little endian move ID. if (MoveId <= 0x1FF) { ListOfMoves.Add(ListOfMoveNames[MoveId]); // Add the name of the move MoveId. } else { break; // If move ID is too large, or the list delimiter has been reached, exit the loop. } } } lblSelectedMoveRemove.Text = ListOfMoves[Convert.ToInt32(numTMNumberRemove.Value) - 1]; // Update the form. lblSelectedMoveAdd.Text = ListOfMoves[Convert.ToInt32(numTMNumberAdd.Value) - 1]; }