예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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;
            }
        }
예제 #4
0
 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);
         }
     }
 }
예제 #5
0
파일: ObjUtils.cs 프로젝트: Bribz/mm-rando
        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);
        }
예제 #6
0
        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();
        }
예제 #7
0
 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);
     }
 }
예제 #8
0
        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]
                };
            }
        }
예제 #9
0
        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);
            }
        }
예제 #10
0
        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;
        }
예제 #11
0
        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])
                };
            }
        }
예제 #12
0
        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);
            }
        }
예제 #13
0
        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);
            }
        }
예제 #14
0
        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;
            }
        }
예제 #15
0
        //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);
        }
예제 #16
0
        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]);
            //};
        }
예제 #17
0
        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);
            //}
        }
예제 #18
0
        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");
                }
            }
        }
예제 #19
0
        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");
                }
            }
        }
예제 #20
0
        /// <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);
                        }
        }
예제 #21
0
        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;
                }
            }
        }