public static void WriteToROM(int Addr, ushort val) { int f = RomUtils.GetFileIndexForWriting(Addr); int dest = Addr - RomData.MMFileList[f].Addr; var data = new byte[] { (byte)((val & 0xFF00) >> 8), (byte)(val & 0xFF) }; Arr_Insert(data, 0, data.Length, RomData.MMFileList[f].Data, dest); }
public static int AddNewFile(string filename) { byte[] buffer; using (BinaryReader data = new BinaryReader(File.Open(filename, FileMode.Open))) { int len = (int)data.BaseStream.Length; buffer = new byte[len]; data.Read(buffer, 0, len); } int index = RomUtils.AppendFile(buffer); return(RomData.MMFileList[index].Addr); }
public static void ApplyHack(string name) { BinaryReader hack_file = new BinaryReader(File.Open(name, FileMode.Open)); int hack_len = (int)hack_file.BaseStream.Length; byte[] hack_content = new byte[hack_len]; hack_file.Read(hack_content, 0, hack_len); hack_file.Close(); if (name.EndsWith("title-screen")) { Random R = new Random(); int rot = R.Next(360); Color l; float h; for (int i = 0; i < 144 * 64; i++) { int p = (i * 4) + 8; l = Color.FromArgb(hack_content[p + 3], hack_content[p], hack_content[p + 1], hack_content[p + 2]); h = l.GetHue(); h += rot; h %= 360f; l = ColorUtils.FromAHSB(l.A, h, l.GetSaturation(), l.GetBrightness()); hack_content[p] = l.R; hack_content[p + 1] = l.G; hack_content[p + 2] = l.B; hack_content[p + 3] = l.A; } l = Color.FromArgb(hack_content[0x1FE72], hack_content[0x1FE73], hack_content[0x1FE76]); h = l.GetHue(); h += rot; h %= 360f; l = ColorUtils.FromAHSB(255, h, l.GetSaturation(), l.GetBrightness()); hack_content[0x1FE72] = l.R; hack_content[0x1FE73] = l.G; hack_content[0x1FE76] = l.B; } int addr = 0; while (hack_content[addr] != 0xFF) { //Debug.WriteLine(addr.ToString("X4")); uint dest = ReadWriteUtils.Arr_ReadU32(hack_content, addr); addr += 4; uint len = ReadWriteUtils.Arr_ReadU32(hack_content, addr); addr += 4; int f = RomUtils.GetFileIndexForWriting((int)dest); dest -= (uint)RomData.MMFileList[f].Addr; ReadWriteUtils.Arr_Insert(hack_content, addr, (int)len, RomData.MMFileList[f].Data, (int)dest); addr += (int)len; } }
public static void UpdateFormTunics(List <int[]> addresses, Color target) { for (int i = 0; i < addresses.Count; i++) { for (int j = 0; j < addresses[i].Length; j++) { int f = RomUtils.GetFileIndexForWriting(addresses[i][j]); int a = addresses[i][j] - RomData.MMFileList[f].Addr; Color[] c = ReadColours(f, a, sizes[i]); c = ShiftHue(c, target, sizes[i], zora[i], grad[i], fd[i]); WriteColours(f, a, sizes[i], c); } } }
public static byte[] GetObjectData(int objectIndex) { var objectTableFileIndex = RomUtils.GetFileIndexForWriting(Addresses.ObjTable); var baseAddress = Addresses.ObjTable - RomData.MMFileList[objectTableFileIndex].Addr; var objectAddress = ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[objectTableFileIndex].Data, baseAddress + (objectIndex * 8)); var objectFileIndex = RomData.MMFileList.FindIndex(f => f.Addr == objectAddress); if (objectFileIndex == -1) { return(null); } RomUtils.CheckCompressed(objectFileIndex); return(RomData.MMFileList[objectFileIndex].Data); }
public static void ReplaceGetItemTable(string ModsDir) { ResourceUtils.ApplyHack(ModsDir + "replace-gi-table"); int last_file = RomData.MMFileList.Count - 1; GET_ITEM_TABLE = RomUtils.AddNewFile(ModsDir + "gi-table"); ReadWriteUtils.WriteToROM(0xBDAEAC, (uint)last_file + 1); ResourceUtils.ApplyHack(ModsDir + "update-chests"); RomUtils.AddNewFile(ModsDir + "chest-table"); ReadWriteUtils.WriteToROM(0xBDAEA8, (uint)last_file + 2); ResourceUtils.ApplyHack(ModsDir + "standing-hearts"); ResourceUtils.ApplyHack(ModsDir + "fix-item-checks"); cycle_repeat = 0xC72DF6; SceneUtils.ResetSceneFlagMask(); }
public static void WriteROMAddr(int[] Addr, byte[] data) { for (int i = 0; i < Addr.Length; i++) { int var = (int)(Addr[i] & 0xF0000000) >> 28; int rAddr = Addr[i] & 0xFFFFFFF; byte[] rdata = data; if (var == 1) { rdata[0] += 0xA; rdata[1] -= 0x70; } int f = RomUtils.GetFileIndexForWriting(rAddr); int dest = rAddr - RomData.MMFileList[f].Addr; Arr_Insert(rdata, 0, rdata.Length, RomData.MMFileList[f].Data, dest); } }
private static void InitGetBottleList() { RomData.BottleList = new Dictionary <int, BottleCatchEntry>(); int f = RomUtils.GetFileIndexForWriting(BOTTLE_CATCH_TABLE); int baseaddr = BOTTLE_CATCH_TABLE - RomData.MMFileList[f].Addr; var fileData = RomData.MMFileList[f].Data; foreach (var getBottleItemIndex in ItemUtils.AllGetBottleItemIndices()) { int offset = getBottleItemIndex * 6 + baseaddr; RomData.BottleList[getBottleItemIndex] = new BottleCatchEntry { ItemGained = fileData[offset + 3], Index = fileData[offset + 4], Message = fileData[offset + 5] }; } }
public static void WriteNewBottle(int ItemSlot, int NewItem) { int f = RomUtils.GetFileIndexForWriting(Addresses.BottleCatchTable); int baseaddr = Addresses.BottleCatchTable - RomData.MMFileList[f].Addr; var fileData = RomData.MMFileList[f].Data; for (int i = 0; i < RomData.BottleIndices[ItemSlot].Length; i++) { int offset = RomData.BottleIndices[ItemSlot][i] * 6 + baseaddr; var newBottle = RomData.BottleList[NewItem][0]; var data = new byte[] { newBottle.ItemGained, newBottle.Index, newBottle.Message, }; ReadWriteUtils.Arr_Insert(data, 0, data.Length, fileData, offset + 3); } }
public static void UpdateSceneFlagMask(int num) { int offset = num >> 3; int mod = offset % 16; if (mod < 4) { offset += 8; } else if (mod < 12) { offset -= 4; } int bit = 1 << (num & 7); int f = RomUtils.GetFileIndexForWriting(SCENE_FLAG_MASKS); int addr = SCENE_FLAG_MASKS - RomData.MMFileList[f].Addr + offset; RomData.MMFileList[f].Data[addr] |= (byte)bit; }
private static void InitGetItemList() { RomData.GetItemList = new Dictionary <int, GetItemEntry>(); int f = RomUtils.GetFileIndexForWriting(GET_ITEM_TABLE); int baseaddr = GET_ITEM_TABLE - RomData.MMFileList[f].Addr; var fileData = RomData.MMFileList[f].Data; foreach (var getItemIndex in ItemUtils.AllGetItemIndices()) { int offset = (getItemIndex - 1) * 8 + baseaddr; RomData.GetItemList[getItemIndex] = new GetItemEntry { ItemGained = fileData[offset], Flag = fileData[offset + 1], Index = fileData[offset + 2], Type = fileData[offset + 3], Message = (short)((fileData[offset + 4] << 8) | fileData[offset + 5]), Object = (short)((fileData[offset + 6] << 8) | fileData[offset + 7]) }; } }
public static void WriteNewBottle(Item location, Item item) { System.Diagnostics.Debug.WriteLine($"Writing {item.Name()} --> {location.Location()}"); int f = RomUtils.GetFileIndexForWriting(BOTTLE_CATCH_TABLE); int baseaddr = BOTTLE_CATCH_TABLE - RomData.MMFileList[f].Addr; var fileData = RomData.MMFileList[f].Data; foreach (var index in location.GetBottleItemIndices()) { var offset = index * 6 + baseaddr; var newBottle = RomData.BottleList[item.GetBottleItemIndices()[0]]; var data = new byte[] { newBottle.ItemGained, newBottle.Index, newBottle.Message, }; ReadWriteUtils.Arr_Insert(data, 0, data.Length, fileData, offset + 3); } }
public static void WriteNewBottle(int location, int item) { System.Diagnostics.Debug.WriteLine($"Writing {Items.ITEM_NAMES[item]} --> {Items.ITEM_NAMES[location]}"); location = ItemUtils.SubtractItemOffset(location); item = ItemUtils.SubtractItemOffset(item); int f = RomUtils.GetFileIndexForWriting(BOTTLE_CATCH_TABLE); int baseaddr = BOTTLE_CATCH_TABLE - RomData.MMFileList[f].Addr; var fileData = RomData.MMFileList[f].Data; for (int i = 0; i < RomData.BottleIndices[location].Length; i++) { int offset = RomData.BottleIndices[location][i] * 6 + baseaddr; var newBottle = RomData.BottleList[item][0]; var data = new byte[] { newBottle.ItemGained, newBottle.Index, newBottle.Message, }; ReadWriteUtils.Arr_Insert(data, 0, data.Length, fileData, offset + 3); } }
public static void ReadSceneTable() { RomData.SceneList = new List <Scene>(); int f = RomUtils.GetFileIndexForWriting(SCENE_TABLE); int _SceneTable = SCENE_TABLE - RomData.MMFileList[f].Addr; int i = 0; while (true) { Scene s = new Scene(); uint saddr = ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, _SceneTable + i); if (saddr > 0x4000000) { break; } if (saddr != 0) { s.File = RomUtils.AddrToFile((int)saddr); s.Number = i >> 4; RomData.SceneList.Add(s); } i += 16; } }
//todo - allow rebuilding text file private static void WriteMessage(int addr, byte[] msg) { int fileIndex = RomUtils.GetFileIndexForWriting(MESSAGE_DATA_ADDRESS); ReadWriteUtils.Arr_Insert(msg, 0, msg.Length, MMFileList[fileIndex].Data, addr); }
public static void WriteNewItem(int ItemSlot, int NewItem, bool IsRepeatable, bool RepeatCycle) { int f = RomUtils.GetFileIndexForWriting(Addresses.GetItemTable); int baseaddr = Addresses.GetItemTable - RomData.MMFileList[f].Addr; var itemIndex = RomData.GetItemIndices[ItemSlot]; if (ItemSlot == Items.ItemGoldDust) { itemIndex = 0x6A; // Place items intended for Gold Dust at the Goron Race Bottle location. } int offset = (itemIndex - 1) * 8 + baseaddr; var newItem = RomData.GetItemList[NewItem]; var fileData = RomData.MMFileList[f].Data; var data = new byte[] { newItem.ItemGained, newItem.Flag, newItem.Index, newItem.Type, (byte)(newItem.Message >> 8), (byte)(newItem.Message & 0xFF), (byte)(newItem.Object >> 8), (byte)(newItem.Object & 0xFF), }; ReadWriteUtils.Arr_Insert(data, 0, data.Length, fileData, offset); if (RepeatCycle) { ReadWriteUtils.WriteToROM(cycle_repeat, (ushort)itemIndex); cycle_repeat += 2; } if (!IsRepeatable) { SceneUtils.UpdateSceneFlagMask(itemIndex); } if (NewItem == Items.ItemBottleWitch) { ReadWriteUtils.WriteToROM(0xB49982, (ushort)itemIndex); ReadWriteUtils.WriteToROM(0xC72B42, (ushort)itemIndex); } if (NewItem == Items.ItemBottleMadameAroma) { ReadWriteUtils.WriteToROM(0xB4999A, (ushort)itemIndex); ReadWriteUtils.WriteToROM(0xC72B4E, (ushort)itemIndex); } if (NewItem == Items.ItemBottleAliens) { ReadWriteUtils.WriteToROM(0xB499A6, (ushort)itemIndex); ReadWriteUtils.WriteToROM(0xC72B5A, (ushort)itemIndex); } ; // Goron Race Bottle now rewards a plain Gold Dust, so this is unnecessary until a proper fix for Goron Dust is found. //if (NewItem == Items.ItemBottleGoronRace) //{ // WriteToROM(0xB499B2, (ushort)GetItemIndices[ItemSlot]); // WriteToROM(0xC72B66, (ushort)GetItemIndices[ItemSlot]); //}; }
public static void WriteNewItem(int location, int item) { System.Diagnostics.Debug.WriteLine($"Writing {Items.ITEM_NAMES[item]} --> {Items.ITEM_NAMES[location]}"); bool isRepeatable = Items.REPEATABLE.Contains(item); bool isCycleRepeatable = Items.CYCLE_REPEATABLE.Contains(item); location = ItemUtils.SubtractItemOffset(location); item = ItemUtils.SubtractItemOffset(item); int f = RomUtils.GetFileIndexForWriting(GET_ITEM_TABLE); int baseaddr = GET_ITEM_TABLE - RomData.MMFileList[f].Addr; var getItemIndex = RomData.GetItemIndices[location]; if (location == Items.ItemGoldDust) { getItemIndex = 0x6A; // Place items intended for Gold Dust at the Goron Race Bottle location. } int offset = (getItemIndex - 1) * 8 + baseaddr; var newItem = RomData.GetItemList[item]; var fileData = RomData.MMFileList[f].Data; var data = new byte[] { newItem.ItemGained, newItem.Flag, newItem.Index, newItem.Type, (byte)(newItem.Message >> 8), (byte)(newItem.Message & 0xFF), (byte)(newItem.Object >> 8), (byte)(newItem.Object & 0xFF), }; ReadWriteUtils.Arr_Insert(data, 0, data.Length, fileData, offset); if (isCycleRepeatable) { ReadWriteUtils.WriteToROM(cycle_repeat, (ushort)getItemIndex); cycle_repeat += 2; } if (!isRepeatable) { SceneUtils.UpdateSceneFlagMask(getItemIndex); } if (item == Items.ItemBottleWitch) { ReadWriteUtils.WriteToROM(0xB49982, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B42, (ushort)getItemIndex); } if (item == Items.ItemBottleMadameAroma) { ReadWriteUtils.WriteToROM(0xB4999A, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B4E, (ushort)getItemIndex); } if (item == Items.ItemBottleAliens) { ReadWriteUtils.WriteToROM(0xB499A6, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B5A, (ushort)getItemIndex); } // Goron Race Bottle now rewards a plain Gold Dust, so this is unnecessary until a proper fix for Goron Dust is found. //if (NewItem == Items.ItemBottleGoronRace) //{ // WriteToROM(0xB499B2, (ushort)getItemIndex); // WriteToROM(0xC72B66, (ushort)getItemIndex); //} }
public static void WriteNewItem(Item location, Item item, List <MessageEntry> newMessages, bool updateShop, bool preventDowngrades, bool updateChest, ChestTypeAttribute.ChestType?overrideChestType) { System.Diagnostics.Debug.WriteLine($"Writing {item.Name()} --> {location.Location()}"); int f = RomUtils.GetFileIndexForWriting(GET_ITEM_TABLE); int baseaddr = GET_ITEM_TABLE - RomData.MMFileList[f].Addr; var getItemIndex = location.GetItemIndex().Value; if (location == Item.ItemGoldDust) { getItemIndex = 0x6A; // Place items intended for Gold Dust at the Goron Race Bottle location. } int offset = (getItemIndex - 1) * 8 + baseaddr; var newItem = RomData.GetItemList[item.GetItemIndex().Value]; var fileData = RomData.MMFileList[f].Data; var data = new byte[] { newItem.ItemGained, newItem.Flag, newItem.Index, newItem.Type, (byte)(newItem.Message >> 8), (byte)(newItem.Message & 0xFF), (byte)(newItem.Object >> 8), (byte)(newItem.Object & 0xFF), }; ReadWriteUtils.Arr_Insert(data, 0, data.Length, fileData, offset); if (item.IsCycleRepeatable()) { ReadWriteUtils.WriteToROM(cycle_repeat, (ushort)getItemIndex); cycle_repeat += 2; } var isRepeatable = item.IsRepeatable() || (!preventDowngrades && item.IsDowngradable()); if (!isRepeatable) { SceneUtils.UpdateSceneFlagMask(getItemIndex); } if (item == Item.ItemBottleWitch) { ReadWriteUtils.WriteToROM(0xB49982, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B42, (ushort)getItemIndex); } if (item == Item.ItemBottleMadameAroma) { ReadWriteUtils.WriteToROM(0xB4999A, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B4E, (ushort)getItemIndex); } if (item == Item.ItemBottleAliens) { ReadWriteUtils.WriteToROM(0xB499A6, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B5A, (ushort)getItemIndex); } // Goron Race Bottle now rewards a plain Gold Dust, so this is unnecessary until a proper fix for Goron Dust is found. //if (item == Item.ItemBottleGoronRace) //{ // WriteToROM(0xB499B2, (ushort)getItemIndex); // WriteToROM(0xC72B66, (ushort)getItemIndex); //} if (updateChest) { UpdateChest(location, item, overrideChestType); } if (location != item) { if (updateShop) { UpdateShop(location, item, newMessages); } if (location == Item.StartingSword) { ResourceUtils.ApplyHack(Values.ModsDirectory + "fix-sword-song-of-time"); } } }
public static void WriteNewItem(Item location, Item item, List <MessageEntry> newMessages, bool updateShop, bool preventDowngrades, bool updateChest, ChestTypeAttribute.ChestType?overrideChestType, bool isExtraStartingItem) { System.Diagnostics.Debug.WriteLine($"Writing {item.Name()} --> {location.Location()}"); int f = RomUtils.GetFileIndexForWriting(GET_ITEM_TABLE); int baseaddr = GET_ITEM_TABLE - RomData.MMFileList[f].Addr; var getItemIndex = location.GetItemIndex().Value; int offset = (getItemIndex - 1) * 8 + baseaddr; var newItem = isExtraStartingItem ? Items.RecoveryHeart // Warning: this will not work well for starting with Bottle contents (currently impossible), because you'll first have to acquire the Recovery Heart before getting the bottle-less version. Also may interfere with future implementation of progressive upgrades. : RomData.GetItemList[item.GetItemIndex().Value]; var fileData = RomData.MMFileList[f].Data; var data = new byte[] { newItem.ItemGained, newItem.Flag, newItem.Index, newItem.Type, (byte)(newItem.Message >> 8), (byte)(newItem.Message & 0xFF), (byte)(newItem.Object >> 8), (byte)(newItem.Object & 0xFF), }; ReadWriteUtils.Arr_Insert(data, 0, data.Length, fileData, offset); // todo use Logic Editor to handle which locations should be repeatable and which shouldn't. if ((item.IsCycleRepeatable() && location != Item.HeartPieceNotebookMayor) || (item.Name().Contains("Rupee") && location.IsRupeeRepeatable())) { ReadWriteUtils.WriteToROM(cycle_repeat, (ushort)getItemIndex); cycle_repeat += 2; cycle_repeat_count += 2; ReadWriteUtils.WriteToROM(cycle_repeat_count_address, cycle_repeat_count); } var isRepeatable = item.IsRepeatable() || (!preventDowngrades && item.IsDowngradable()); if (!isRepeatable) { SceneUtils.UpdateSceneFlagMask(getItemIndex); } if (item == Item.ItemBottleWitch) { ReadWriteUtils.WriteToROM(0xB4997E, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B42, (ushort)getItemIndex); } if (item == Item.ItemBottleMadameAroma) { ReadWriteUtils.WriteToROM(0xB4998A, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B4E, (ushort)getItemIndex); } if (item == Item.ItemBottleAliens) { ReadWriteUtils.WriteToROM(0xB49996, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B5A, (ushort)getItemIndex); } if (item == Item.ItemBottleGoronRace) { ReadWriteUtils.WriteToROM(0xB499A2, (ushort)getItemIndex); ReadWriteUtils.WriteToROM(0xC72B66, (ushort)getItemIndex); } if (updateChest) { UpdateChest(location, item, overrideChestType); } if (location != item) { if (updateShop) { UpdateShop(location, item, newMessages); } if (location == Item.StartingSword) { ResourceUtils.ApplyHack(Values.ModsDirectory + "fix-sword-song-of-time"); } if (location == Item.MundaneItemSeahorse) { ResourceUtils.ApplyHack(Values.ModsDirectory + "fix-fisherman"); } if (location == Item.MaskFierceDeity) { ResourceUtils.ApplyHack(Values.ModsDirectory + "fix-fd-mask-reset"); } } }
/// <summary> /// Applies the given filename patch to the in-memory RomData /// </summary> /// <param name="filename"></param> /// <returns>SHA256 hash of the patch.</returns> public static byte[] ApplyPatch(string filename) { var hashAlg = new SHA256Managed(); using (var filestream = File.Open(filename, FileMode.Open)) using (var cryptoStream = new CryptoStream(filestream, hashAlg, CryptoStreamMode.Read)) using (var decompressStream = new GZipStream(cryptoStream, CompressionMode.Decompress)) using (var memoryStream = new MemoryStream()) { decompressStream.CopyTo(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); using (var reader = new BinaryReader(memoryStream)) { var magic = ReadWriteUtils.ReadU32(reader); var version = ReadWriteUtils.ReadU32(reader); // Make sure this is a patch file by checking the magic value if (magic != PatchUtil.PATCH_MAGIC) { throw new PatchMagicException(magic); } // Check that this patch version is supported if (version != (uint)PatchUtil.PATCH_VERSION) { throw new PatchVersionException(PatchUtil.PATCH_VERSION, (PatchVersion)version); } while (reader.BaseStream.Position != reader.BaseStream.Length) { var fileIndex = ReadWriteUtils.ReadS32(reader); var fileAddr = ReadWriteUtils.ReadS32(reader); var index = ReadWriteUtils.ReadS32(reader); var isStatic = ReadWriteUtils.ReadS32(reader) != 0 ? true : false; var length = ReadWriteUtils.ReadS32(reader); var data = reader.ReadBytes(length); if (fileIndex >= RomData.MMFileList.Count) { var newFile = new MMFile { Addr = fileAddr, IsCompressed = false, Data = data, End = fileAddr + data.Length, IsStatic = isStatic, }; RomUtils.AppendFile(newFile); } if (index == -1) { RomData.MMFileList[fileIndex].Data = data; if (data.Length == 0) { RomData.MMFileList[fileIndex].Cmp_Addr = -1; RomData.MMFileList[fileIndex].Cmp_End = -1; } } else { CheckCompressed(fileIndex); ReadWriteUtils.Arr_Insert(data, 0, data.Length, RomData.MMFileList[fileIndex].Data, index); } } } return(hashAlg.Hash); } }
public static void RebuildAudioSeq(List <SequenceInfo> SequenceList) { List <MMSequence> OldSeq = new List <MMSequence>(); int f = RomUtils.GetFileIndexForWriting(Addresses.SeqTable); int basea = RomData.MMFileList[f].Addr; for (int i = 0; i < 128; i++) { MMSequence entry = new MMSequence(); if (i == 0x1E) { entry.Addr = 2; entry.Size = 0; OldSeq.Add(entry); continue; } int entryaddr = Addresses.SeqTable + (i * 16); entry.Addr = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, entryaddr - basea); entry.Size = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, (entryaddr - basea) + 4); if (entry.Size > 0) { entry.Data = new byte[entry.Size]; Array.Copy(RomData.MMFileList[4].Data, entry.Addr, entry.Data, 0, entry.Size); } else { int j = SequenceList.FindIndex(u => u.Replaces == i); if (j != -1) { if ((entry.Addr > 0) && (entry.Addr < 128)) { if (SequenceList[j].Replaces != 0x28) { SequenceList[j].Replaces = entry.Addr; } else { entry.Data = OldSeq[0x18].Data; entry.Size = OldSeq[0x18].Size; } } } } OldSeq.Add(entry); } List <MMSequence> NewSeq = new List <MMSequence>(); int addr = 0; byte[] NewAudioSeq = new byte[0]; for (int i = 0; i < 128; i++) { MMSequence newentry = new MMSequence(); if (OldSeq[i].Size == 0) { newentry.Addr = OldSeq[i].Addr; } else { newentry.Addr = addr; } int j = SequenceList.FindIndex(u => u.Replaces == i); if (j != -1) { if (SequenceList[j].MM_seq != -1) { newentry.Size = OldSeq[SequenceList[j].MM_seq].Size; newentry.Data = OldSeq[SequenceList[j].MM_seq].Data; } else { BinaryReader sequence = new BinaryReader(File.Open(SequenceList[j].Name, FileMode.Open)); int len = (int)sequence.BaseStream.Length; byte[] data = new byte[len]; sequence.Read(data, 0, len); sequence.Close(); if (data[1] != 0x20) { data[1] = 0x20; } newentry.Size = len; newentry.Data = data; } } else { newentry.Size = OldSeq[i].Size; newentry.Data = OldSeq[i].Data; } NewSeq.Add(newentry); if (newentry.Data != null) { NewAudioSeq = NewAudioSeq.Concat(newentry.Data).ToArray(); } addr += newentry.Size; } if (addr > (RomData.MMFileList[4].End - RomData.MMFileList[4].Addr)) { MMFile newa = new MMFile(); newa.Addr = RomData.MMFileList[RomData.MMFileList.Count - 1].End; newa.End = newa.Addr + addr; newa.IsCompressed = false; newa.Data = NewAudioSeq; RomData.MMFileList.Add(newa); ResourceUtils.ApplyHack(Values.ModsDirectory + "reloc-audio"); RelocateSeq(RomData.MMFileList.Count - 1); RomData.MMFileList[4].Data = new byte[0]; RomData.MMFileList[4].Cmp_Addr = -1; RomData.MMFileList[4].Cmp_End = -1; } else { RomData.MMFileList[4].Data = NewAudioSeq; } //update pointer table f = RomUtils.GetFileIndexForWriting(Addresses.SeqTable); for (int i = 0; i < 128; i++) { ReadWriteUtils.Arr_WriteU32(RomData.MMFileList[f].Data, (Addresses.SeqTable + (i * 16)) - basea, (uint)NewSeq[i].Addr); ReadWriteUtils.Arr_WriteU32(RomData.MMFileList[f].Data, 4 + (Addresses.SeqTable + (i * 16)) - basea, (uint)NewSeq[i].Size); } //update inst sets f = RomUtils.GetFileIndexForWriting(Addresses.InstSetMap); basea = RomData.MMFileList[f].Addr; for (int i = 0; i < 128; i++) { int paddr = (Addresses.InstSetMap - basea) + (i * 2) + 2; int j = -1; if (NewSeq[i].Size == 0) { j = SequenceList.FindIndex(u => u.Replaces == NewSeq[i].Addr); } else { j = SequenceList.FindIndex(u => u.Replaces == i); } if (j != -1) { RomData.MMFileList[f].Data[paddr] = (byte)SequenceList[j].Instrument; } } }