Exemplo n.º 1
0
        public static byte Read(int address)
        {
            int f   = RomUtils.GetFileIndexForWriting(address);
            int src = address - RomData.MMFileList[f].Addr;

            return(RomData.MMFileList[f].Data[src]);
        }
Exemplo n.º 2
0
        public static void WriteToROM(int Addr, byte val)
        {
            int f    = RomUtils.GetFileIndexForWriting(Addr);
            int dest = Addr - RomData.MMFileList[f].Addr;

            RomData.MMFileList[f].Data[dest] = val;
        }
Exemplo n.º 3
0
        public static void WriteToROM(int Addr, byte[] val)
        {
            int f    = RomUtils.GetFileIndexForWriting(Addr);
            int dest = Addr - RomData.MMFileList[f].Addr;

            Arr_Insert(val, 0, val.Length, RomData.MMFileList[f].Data, dest);
        }
Exemplo n.º 4
0
        public static void UpdateSceneFlagMask(int num)
        {
            int offset = num >> 3;

            if (num >= 0x380) // skip scene 7 (Grottos) and scene 8 (Cutscene Map)
            {
                offset += 0x20;
            }
            if (num >= 0x400) // skip scenes 0xA through 0xD (Magic Hag's Potion Shop, Majora's Lair, Beneath the Graveyard, Curiosity Shop)
            {
                offset += 0x40;
            }
            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;
        }
Exemplo n.º 5
0
        public static void UpdateSceneFlagMask(int num)
        {
            int offset = num >> 3;

            if (num >= 0x380) // skip scene 7 (Grottos)
            {
                offset += 0x10;
            }
            // TODO maybe skip Cutscene Map?
            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;
        }
Exemplo n.º 6
0
        public static void InsertObj(byte[] obj, int replace)
        {
            int  f           = RomUtils.GetFileIndexForWriting(OBJECT_TABLE);
            int  basea       = OBJECT_TABLE - RomData.MMFileList[f].Addr;
            uint replaceaddr = ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, basea + (replace * 8));
            int  objf        = RomData.MMFileList.FindIndex(u => u.Addr == replaceaddr);

            if (objf == -1)
            {
                return;
            }
            ;
            if (obj.Length > (RomData.MMFileList[objf].End - RomData.MMFileList[objf].Addr))
            {
                MMFile newfile = new MMFile();
                newfile.Addr         = RomData.MMFileList[RomData.MMFileList.Count - 1].End;
                newfile.End          = newfile.Addr + obj.Length;
                newfile.IsCompressed = true;
                newfile.WasEdited    = true;
                newfile.Data         = obj;
                RomData.MMFileList[objf].Cmp_Addr     = -1;
                RomData.MMFileList[objf].Cmp_End      = -1;
                RomData.MMFileList[objf].Data         = null;
                RomData.MMFileList[objf].IsCompressed = false;
                RomData.MMFileList.Add(newfile);
                ReadWriteUtils.Arr_WriteU32(RomData.MMFileList[f].Data, basea + (replace * 8), (uint)newfile.Addr);
                ReadWriteUtils.Arr_WriteU32(RomData.MMFileList[f].Data, basea + (replace * 8) + 4, (uint)newfile.End);
            }
            else
            {
                RomData.MMFileList[objf].Data      = obj;
                RomData.MMFileList[objf].WasEdited = true;
            }
        }
Exemplo n.º 7
0
        public static ushort ReadU16(int address)
        {
            int f   = RomUtils.GetFileIndexForWriting(address);
            int src = address - RomData.MMFileList[f].Addr;

            return((ushort)((RomData.MMFileList[f].Data[src] << 8)
                            + RomData.MMFileList[f].Data[src + 1]));
        }
Exemplo n.º 8
0
        public static void WriteToROM(int Addr, ReadOnlyMemory <byte> val)
        {
            int f      = RomUtils.GetFileIndexForWriting(Addr);
            int dest   = Addr - RomData.MMFileList[f].Addr;
            var memory = new Memory <byte>(RomData.MMFileList[f].Data);

            val.CopyTo(memory.Slice(dest));
        }
Exemplo n.º 9
0
        public static int GetObjSize(int obj)
        {
            int f        = RomUtils.GetFileIndexForWriting(OBJECT_TABLE);
            int basea    = OBJECT_TABLE - RomData.MMFileList[f].Addr;
            var fileData = RomData.MMFileList[f].Data;

            return((int)(ReadWriteUtils.Arr_ReadU32(fileData, basea + (obj * 8) + 4)
                         - ReadWriteUtils.Arr_ReadU32(fileData, basea + (obj * 8))));
        }
Exemplo n.º 10
0
        public static byte[] ReadBytes(int address, uint count)
        {
            var f     = RomUtils.GetFileIndexForWriting(address);
            var src   = address - RomData.MMFileList[f].Addr;
            var bytes = new byte[count];

            Array.Copy(RomData.MMFileList[f].Data, src, bytes, 0, count);
            return(bytes);
        }
Exemplo n.º 11
0
        public static uint ReadU32(int address)
        {
            int f   = RomUtils.GetFileIndexForWriting(address);
            int src = address - RomData.MMFileList[f].Addr;

            return((uint)((RomData.MMFileList[f].Data[src] << 24)
                          | (RomData.MMFileList[f].Data[src + 1] << 16)
                          | (RomData.MMFileList[f].Data[src + 2] << 8)
                          | (RomData.MMFileList[f].Data[src + 3])));
        }
Exemplo n.º 12
0
 public static void UpdateFormTunics(int tunicIndex, List <int[]> addresses, Color targetColor)
 {
     for (int j = 0; j < addresses[tunicIndex].Length; j++)
     {
         int     fileInRom     = RomUtils.GetFileIndexForWriting(addresses[tunicIndex][j]);
         int     addressInFile = addresses[tunicIndex][j] - RomData.MMFileList[fileInRom].Addr;
         Color[] colorArray    = ReadColours(fileInRom, addressInFile, paletteSize[tunicIndex]);
         colorArray = ShiftHue(colorArray, targetColor, paletteSize[tunicIndex], isZora[tunicIndex], isGradientImage[tunicIndex], isFierceDeity[tunicIndex]);
         WriteColours(fileInRom, addressInFile, paletteSize[tunicIndex], colorArray);
     }
 }
Exemplo n.º 13
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);
        }
Exemplo n.º 14
0
        public static void RebuildAudioBank(List <InstrumentSetInfo> InstrumentSetList)
        {
            // get index for the old audiobank, we're putting it back int the same spot but letting it expand into audioseq's spot, because the later is no longer there
            int f = RomUtils.GetFileIndexForWriting(Addresses.AudiobankTable);
            // the DMA table doesn't point directly to the table on the rom, its part of a larger yaz0 file, we have to use an offset to get the address in the file
            int audiobank_table_adjusted_addr = Addresses.AudiobankTable - RomData.MMFileList[RomUtils.GetFileIndexForWriting(Addresses.AudiobankTable)].Addr;

            int current_audiobank_addr = 0;

            byte[] new_audiobank = new byte[0];

            // for each bank, concat onto the new bank byte object, update the table to match the new instrument sets
            for (int inst_set_num = 0; inst_set_num <= 0x28; ++inst_set_num)
            {
                InstrumentSetInfo current_bank = InstrumentSetList[inst_set_num];   // not sure lists are sequential in C#
                int bank_len = current_bank.BankBinary.Length;
                new_audiobank = new_audiobank.Concat(current_bank.BankBinary).ToArray();

                // update address of the bank in the table
                RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16]     = (byte)((current_audiobank_addr & 0xFF000000) >> 24);
                RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 1] = (byte)((current_audiobank_addr & 0xFF0000) >> 16);
                RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 2] = (byte)((current_audiobank_addr & 0xFF00) >> 8);
                RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 3] = (byte)(current_audiobank_addr & 0xFF);

                // adjust the address for the next sequence to use
                current_audiobank_addr += bank_len;
                int remainder = bank_len % 16;
                if (remainder > 0)                                                              // in the event the user made an audiobank instrument set that isn't padded
                {
                    new_audiobank = new_audiobank.Concat(new byte[remainder + 0x10]).ToArray(); // padding with a spare 16 byte line sounds cheap enough to try
                    Debug.WriteLine("Bank " + inst_set_num + " wasn't padded to 16 bytes:" + bank_len.ToString("X"));
                    current_audiobank_addr += remainder;
                }

                // update length of the bank in the table
                RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 4] = (byte)((bank_len & 0xFF000000) >> 24);
                RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 5] = (byte)((bank_len & 0xFF0000) >> 16);
                RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 6] = (byte)((bank_len & 0xFF00) >> 8);
                RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + inst_set_num * 16 + 7] = (byte)(bank_len & 0xFF);

                // update metadata of the bank in the table
                for (int meta_iter = 0; meta_iter < 8; ++meta_iter)
                {
                    RomData.MMFileList[f].Data[audiobank_table_adjusted_addr + (inst_set_num * 16) + 8 + meta_iter] = current_bank.BankMetaData[meta_iter];
                }
            }

            // write audioseq as a new file
            f = RomUtils.GetFileIndexForWriting(Addresses.Audiobank);
            RomData.MMFileList[f].Data = new_audiobank;
        }
Exemplo n.º 15
0
        public static void ApplyHack(string path, string name)
        {
            BinaryReader hack_file = new BinaryReader(File.Open(Path.Combine(path, 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;
            }
        }
Exemplo n.º 16
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);
         }
     }
 }
Exemplo n.º 17
0
        public static byte[] GetObjectData(int objectIndex)
        {
            var objectTableFileIndex = RomUtils.GetFileIndexForWriting(OBJECT_TABLE);
            var baseAddress          = OBJECT_TABLE - 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);
        }
Exemplo n.º 18
0
        public static void RebuildAudioBank(List <InstrumentSetInfo> InstrumentSetList)
        {
            // get index for the old audiobank, we're putting it back in the same spot but letting it expand into audioseq's spot, which was moved to the end
            int fid = RomUtils.GetFileIndexForWriting(Addresses.AudiobankTable);
            // the DMA table doesn't point directly to the indextable on the rom, its part of a larger yaz0 file, we have to use an offset to get the address in the file
            int audiobankIndexOffset = Addresses.AudiobankTable - RomData.MMFileList[RomUtils.GetFileIndexForWriting(Addresses.AudiobankTable)].Addr;

            int audiobankBankOffset = 0;
            var audiobankData       = new byte[0];

            // for each bank, concat onto the new bank byte object, update the table to match the new instrument sets
            for (int audiobankIndex = 0; audiobankIndex <= 0x28; ++audiobankIndex)
            {
                var currentBank = InstrumentSetList[audiobankIndex];
                audiobankData = audiobankData.Concat(currentBank.BankBinary).ToArray();

                // update address of the bank in the index table
                RomData.MMFileList[fid].Data[audiobankIndexOffset + (audiobankIndex * 16) + 0] = (byte)((audiobankBankOffset & 0xFF000000) >> 24);
                RomData.MMFileList[fid].Data[audiobankIndexOffset + (audiobankIndex * 16) + 1] = (byte)((audiobankBankOffset & 0xFF0000) >> 16);
                RomData.MMFileList[fid].Data[audiobankIndexOffset + (audiobankIndex * 16) + 2] = (byte)((audiobankBankOffset & 0xFF00) >> 8);
                RomData.MMFileList[fid].Data[audiobankIndexOffset + (audiobankIndex * 16) + 3] = (byte)(audiobankBankOffset & 0xFF);

                // update length of the bank in the table
                int currentBankLength = currentBank.BankBinary.Length;
                RomData.MMFileList[fid].Data[audiobankIndexOffset + (audiobankIndex * 16) + 4] = (byte)((currentBankLength & 0xFF000000) >> 24);
                RomData.MMFileList[fid].Data[audiobankIndexOffset + (audiobankIndex * 16) + 5] = (byte)((currentBankLength & 0xFF0000) >> 16);
                RomData.MMFileList[fid].Data[audiobankIndexOffset + (audiobankIndex * 16) + 6] = (byte)((currentBankLength & 0xFF00) >> 8);
                RomData.MMFileList[fid].Data[audiobankIndexOffset + (audiobankIndex * 16) + 7] = (byte)(currentBankLength & 0xFF);

                // update metadata of the bank in the table
                for (int metadataIter = 0; metadataIter < 8; ++metadataIter)
                {
                    RomData.MMFileList[fid].Data[audiobankIndexOffset + (audiobankIndex * 16) + 8 + metadataIter] = currentBank.BankMetaData[metadataIter];
                }

                // adjust the address for the next bank to use
                audiobankBankOffset += currentBankLength;
                int paddingRemainder = currentBankLength % 0x10;
                if (paddingRemainder > 0)                                                                     // in the event the user made an audiobank instrument set that isn't padded
                {
                    audiobankData        = audiobankData.Concat(new byte[paddingRemainder + 0x10]).ToArray(); // padding with a spare 16 byte line sounds cheap enough to try
                    audiobankBankOffset += paddingRemainder;
                }
            }

            // write new audiobank back to file
            RomData.MMFileList[RomUtils.GetFileIndexForWriting(Addresses.Audiobank)].Data = audiobankData;
        }
Exemplo n.º 19
0
        public static void ApplyHack(byte[] hack_content)
        {
            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;
            }
        }
Exemplo n.º 20
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);
     }
 }
Exemplo n.º 21
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]
                };
            }
        }
Exemplo n.º 22
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;
        }
Exemplo n.º 23
0
        private static void InitGetItemList()
        {
            RomData.GetItemList = new Dictionary <int, GetItemEntry>();
            int f        = RomUtils.GetFileIndexForWriting(GET_ITEM_TABLE);
            var fileData = RomData.MMFileList[f].Data;

            for (var i = 0; i < fileData.Length; i += 8)
            {
                var getItemIndex = (i / 8) + 1;
                RomData.GetItemList[getItemIndex] = new GetItemEntry
                {
                    ItemGained = fileData[i],
                    Flag       = fileData[i + 1],
                    Index      = fileData[i + 2],
                    Type       = fileData[i + 3],
                    Message    = (short)((fileData[i + 4] << 8) | fileData[i + 5]),
                    Object     = (short)((fileData[i + 6] << 8) | fileData[i + 7])
                };
            }
        }
Exemplo n.º 24
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])
                };
            }
        }
Exemplo n.º 25
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);
            }
        }
Exemplo n.º 26
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;
            }
        }
Exemplo n.º 27
0
        public static void WriteNewItem(ItemObject itemObject, List <MessageEntry> newMessages, GameplaySettings settings, ChestTypeAttribute.ChestType?overrideChestType)
        {
            var item     = itemObject.Item;
            var location = itemObject.NewLocation.Value;

            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 fileData     = RomData.MMFileList[f].Data;

            GetItemEntry newItem;

            if (item.IsExclusiveItem())
            {
                newItem = item.ExclusiveItemEntry();
            }
            else
            {
                newItem = RomData.GetItemList[item.GetItemIndex().Value];
            }

            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.
            var isCycleRepeatable = item.IsCycleRepeatable();

            if (item.Name().Contains("Rupee") && location.IsRupeeRepeatable())
            {
                isCycleRepeatable = true;
            }
            if (item.ToString().StartsWith("Trade") && settings.QuestItemStorage)
            {
                isCycleRepeatable = false;
            }
            if (isCycleRepeatable)
            {
                settings.AsmOptions.MMRConfig.CycleRepeatableLocations.Add(getItemIndex);
            }

            var isRepeatable = item.IsRepeatable() || (!settings.PreventDowngrades && item.IsDowngradable());

            if (settings.ProgressiveUpgrades && item.HasAttribute <ProgressiveAttribute>())
            {
                isRepeatable = false;
            }
            if (!isRepeatable)
            {
                SceneUtils.UpdateSceneFlagMask(getItemIndex);
            }

            if (settings.UpdateChests)
            {
                UpdateChest(location, item, overrideChestType);
            }

            if (settings.UpdateShopAppearance)
            {
                UpdateShop(itemObject, newMessages);
            }

            if (location != item)
            {
                if (location == Item.StartingSword)
                {
                    ResourceUtils.ApplyHack(Resources.mods.fix_sword_song_of_time);
                }

                if (location == Item.MundaneItemSeahorse)
                {
                    ResourceUtils.ApplyHack(Resources.mods.fix_fisherman);
                }

                if (location == Item.MaskFierceDeity)
                {
                    ResourceUtils.ApplyHack(Resources.mods.fix_fd_mask_reset);
                }
            }
        }
Exemplo n.º 28
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");
                }
            }
        }
Exemplo n.º 29
0
        public static void WriteNewItem(ItemObject itemObject, List <MessageEntry> newMessages, GameplaySettings settings, ChestTypeAttribute.ChestType?overrideChestType, MessageTable messageTable, ExtendedObjects extendedObjects)
        {
            var item     = itemObject.Item;
            var location = itemObject.NewLocation.Value;

            System.Diagnostics.Debug.WriteLine($"Writing {item.Name()} --> {location.Location()}");

            if (!itemObject.IsRandomized)
            {
                var indices = location.GetCollectableIndices();
                if (indices.Any())
                {
                    foreach (var collectableIndex in location.GetCollectableIndices())
                    {
                        ReadWriteUtils.Arr_WriteU16(RomData.MMFileList[COLLECTABLE_TABLE_FILE_INDEX].Data, collectableIndex * 2, 0);
                    }
                    return;
                }
            }

            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 fileData     = RomData.MMFileList[f].Data;

            GetItemEntry newItem;

            if (!itemObject.IsRandomized && location.IsNullableItem())
            {
                newItem = new GetItemEntry();
            }
            else if (item.IsExclusiveItem())
            {
                newItem = item.ExclusiveItemEntry();
            }
            else
            {
                newItem = RomData.GetItemList[item.GetItemIndex().Value];
            }

            // Attempt to resolve extended object Id, which should affect "Exclusive Items" as well.
            var graphics = extendedObjects.ResolveGraphics(newItem);

            if (graphics.HasValue)
            {
                newItem.Object = graphics.Value.objectId;
                newItem.Index  = graphics.Value.graphicId;
            }

            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);

            int?refillGetItemIndex = item switch
            {
                Item.ItemBottleMadameAroma => 0x91,
                Item.ItemBottleAliens => 0x92,
                _ => null,
            };

            if (refillGetItemIndex.HasValue)
            {
                var refillItem     = RomData.GetItemList[refillGetItemIndex.Value];
                var refillGraphics = extendedObjects.ResolveGraphics(refillItem);
                if (refillGraphics.HasValue)
                {
                    refillItem.Object = refillGraphics.Value.objectId;
                    refillItem.Index  = refillGraphics.Value.graphicId;
                }
                var refillData = new byte[]
                {
                    refillItem.ItemGained,
                    refillItem.Flag,
                    refillItem.Index,
                    refillItem.Type,
                    (byte)(refillItem.Message >> 8),
                    (byte)(refillItem.Message & 0xFF),
                    (byte)(refillItem.Object >> 8),
                    (byte)(refillItem.Object & 0xFF),
                };
                var refillOffset = (refillGetItemIndex.Value - 1) * 8 + baseaddr;
                ReadWriteUtils.Arr_Insert(refillData, 0, refillData.Length, fileData, refillOffset);
            }

            if (location.IsRupeeRepeatable())
            {
                settings.AsmOptions.MMRConfig.RupeeRepeatableLocations.Add(getItemIndex);
            }

            var isRepeatable = item.IsRepeatable(settings) || (!settings.PreventDowngrades && item.IsDowngradable());

            if (settings.ProgressiveUpgrades && item.HasAttribute <ProgressiveAttribute>())
            {
                isRepeatable = false;
            }
            if (item.IsReturnable(settings))
            {
                isRepeatable = false;
                settings.AsmOptions.MMRConfig.ItemsToReturnIds.Add(getItemIndex);
            }
            if (!isRepeatable)
            {
                SceneUtils.UpdateSceneFlagMask(getItemIndex);
            }

            if (settings.UpdateChests)
            {
                UpdateChest(location, item, overrideChestType);
            }

            if (settings.UpdateShopAppearance)
            {
                UpdateShop(itemObject, newMessages, messageTable);
            }

            if (itemObject.IsRandomized)
            {
                var hackContentAttributes = location.GetAttributes <HackContentAttribute>();
                if (location == item)
                {
                    hackContentAttributes = hackContentAttributes.Where(h => !h.ApplyOnlyIfItemIsDifferent);
                }
                foreach (var hackContent in hackContentAttributes.Select(h => h.HackContent))
                {
                    ResourceUtils.ApplyHack(hackContent);
                }
            }
        }
Exemplo n.º 30
0
        // gets passed RomData.SequenceList in Builder.cs::WriteAudioSeq
        public static void RebuildAudioSeq(List <SequenceInfo> SequenceList, OutputSettings _settings)
        {
            // spoiler log output DEBUG
            StringBuilder log = new StringBuilder();

            void WriteOutput(string str)
            {
                Debug.WriteLine(str); // we still want debug output though
                log.AppendLine(str);
            }

            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) // intro music when link gets ambushed
                {
                    entry.Addr = 2;
                    OldSeq.Add(entry);
                    continue;
                }

                int entryaddr = Addresses.SeqTable + (i * 16);
                entry.Addr = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, entryaddr - basea);
                var size = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, (entryaddr - basea) + 4);
                if (size > 0)
                {
                    entry.Data = new byte[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) // 28 (fairy fountain)
                            {
                                SequenceList[j].Replaces = entry.Addr;
                            }
                            else
                            {
                                entry.Data = OldSeq[0x18].Data;
                            }
                        }
                    }
                }
                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;
                }

                if (SequenceList.FindAll(u => u.Replaces == i).Count > 1)
                {
                    WriteOutput("Error: Slot " + i.ToString("X") + " has multiple songs pointing at it!");
                }

                int p = RomData.PointerizedSequences.FindIndex(u => u.PreviousSlot == i);
                int j = SequenceList.FindIndex(u => u.Replaces == i);
                if (p != -1)
                {
                    // found song we want to pointerize
                    newentry.Addr = RomData.PointerizedSequences[p].Replaces;
                }
                else if (j != -1)
                {
                    // new song to replace old slot found
                    if (SequenceList[j].MM_seq != -1)
                    {
                        newentry.Data = OldSeq[SequenceList[j].MM_seq].Data;
                        WriteOutput("Slot " + i.ToString("X2") + " -> " + SequenceList[j].Name);
                    }
                    else if (SequenceList[j].SequenceBinaryList != null && SequenceList[j].SequenceBinaryList.Count > 0)
                    {
                        if (SequenceList[j].SequenceBinaryList.Count > 1)
                        {
                            WriteOutput("Warning: writing song with multiple sequence/bank combos, selecting first available");
                        }
                        newentry.Data = SequenceList[j].SequenceBinaryList[0].SequenceBinary;
                        WriteOutput("Slot " + i.ToString("X2") + " := " + SequenceList[j].Name + " *");
                    }
                    else // non mm, load file and add
                    {
                        byte[] data;
                        if (File.Exists(SequenceList[j].Filename))
                        {
                            using (var reader = new BinaryReader(File.OpenRead(SequenceList[j].Filename)))
                            {
                                data = new byte[(int)reader.BaseStream.Length];
                                reader.Read(data, 0, data.Length);
                            }
                        }
                        else if (SequenceList[j].Name == nameof(Properties.Resources.mmr_f_sot))
                        {
                            data = Properties.Resources.mmr_f_sot;
                        }
                        else
                        {
                            throw new Exception("Music not found as file or built-in resource." + SequenceList[j].Filename);
                        }

                        // I think this checks if the sequence type is correct for MM
                        //  because DB ripped sequences from SF64/SM64/MK64 without modifying them
                        if (data[1] != 0x20)
                        {
                            data[1] = 0x20;
                        }

                        newentry.Data = data;
                        WriteOutput("Slot " + i.ToString("X2") + " := " + SequenceList[j].Name);
                    }
                }
                else // not found, song wasn't touched by rando, just transfer over
                {
                    newentry.Data = OldSeq[i].Data;
                }

                // if the sequence is not padded to 16 bytes, the DMA fails
                //  music can stop from playing and on hardware it will just straight crash
                var Padding = 0x10 - newentry.Size % 0x10;
                if (Padding != 0x10)
                {
                    newentry.Data = newentry.Data.Concat(new byte[Padding]).ToArray();
                }

                NewSeq.Add(newentry);
                // TODO is there not a better way to write this?
                if (newentry.Data != null)
                {
                    NewAudioSeq = NewAudioSeq.Concat(newentry.Data).ToArray();
                }

                addr += newentry.Size;
            }

            // discovered when MM-only music was fixed, if the audioseq is left in it's old spot
            // audio quality is garbage, sounds like static
            //if (addr > (RomData.MMFileList[4].End - RomData.MMFileList[4].Addr))
            //else
            //RomData.MMFileList[4].Data = NewAudioSeq;

            int index = RomUtils.AppendFile(NewAudioSeq);

            ResourceUtils.ApplyHack(Values.ModsDirectory, "reloc-audio");
            RelocateSeq(index);
            RomData.MMFileList[4].Data     = new byte[0];
            RomData.MMFileList[4].Cmp_Addr = -1;
            RomData.MMFileList[4].Cmp_End  = -1;

            //update sequence index 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 used by each new seq
            // this is NOT the audiobank, its the complementary instrument set value for each sequence
            //   IE, sequence 7 uses instrument set "10", we replaced it with sequnece ae which needs bank "23"
            f     = RomUtils.GetFileIndexForWriting(Addresses.InstSetMap);
            basea = RomData.MMFileList[f].Addr;
            for (int i = 0; i < 128; i++)
            {
                // huh? paddr? pointer? padding?
                int paddr = (Addresses.InstSetMap - basea) + (i * 2) + 2;

                int j = -1;
                if (NewSeq[i].Size == 0) // pointer, we need to copy the instrumnet set from the destination
                {
                    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;
                }
            }

            //// DEBUG spoiler log output
            //String dir = Path.GetDirectoryName(_settings.OutputROMFilename);
            //String path = $"{Path.GetFileNameWithoutExtension(_settings.OutputROMFilename)}";
            //// spoiler log should already be written by the time we reach this far
            //if (File.Exists(Path.Combine(dir, path + "_SpoilerLog.txt")))
            //    path += "_SpoilerLog.txt";
            //else // TODO add HTML log compatibility
            //    path += "_SongLog.txt";

            //using (StreamWriter sw = new StreamWriter(Path.Combine(dir, path), append: true))
            //{
            //    sw.WriteLine(""); // spacer
            //    sw.Write(log);
            //}
        }