コード例 #1
0
ファイル: SceneUtils.cs プロジェクト: az64/mm-rando
 public static void GetMaps()
 {
     for (int i = 0; i < RomData.SceneList.Count; i++)
     {
         int f = RomData.SceneList[i].File;
         RomUtils.CheckCompressed(f);
         int j = 0;
         while (true)
         {
             byte cmd = RomData.MMFileList[f].Data[j];
             if (cmd == 0x04)
             {
                 byte mapcount = RomData.MMFileList[f].Data[j + 1];
                 int  mapsaddr = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, j + 4) & 0xFFFFFF;
                 for (int k = 0; k < mapcount; k++)
                 {
                     Map m = new Map();
                     m.File = RomUtils.AddrToFile((int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, mapsaddr));
                     RomData.SceneList[i].Maps.Add(m);
                     mapsaddr += 8;
                 }
                 break;
             }
             if (cmd == 0x14)
             {
                 break;
             }
             j += 8;
         }
     }
 }
コード例 #2
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;
            }
        }
コード例 #3
0
ファイル: Yaz0Utils.cs プロジェクト: zelda180/mm-rando
        public static byte[] Decompress(byte[] CmpFile)
        {
            if (ReadWriteUtils.Arr_ReadU32(CmpFile, 0) != 0x59617A30)
            {
                return(null);
            }

            int dest_len = (int)ReadWriteUtils.Arr_ReadU32(CmpFile, 4);

            byte[] dest     = new byte[dest_len];
            int    src_pos  = 16;
            int    src_len  = CmpFile.Length;
            int    dest_pos = 0;

            while ((src_pos < src_len) && (dest_pos < dest_len))
            {
                byte code = CmpFile[src_pos];
                src_pos++;
                for (int i = 0; i < 8; i++)
                {
                    if ((src_pos >= src_len) || (dest_pos >= dest_len))
                    {
                        break;
                    }
                    ;
                    if ((code & 0x80) > 0)
                    {
                        dest[dest_pos] = CmpFile[src_pos];
                        dest_pos++;
                        src_pos++;
                    }
                    else
                    {
                        byte b1 = CmpFile[src_pos];
                        src_pos++;
                        byte b2 = CmpFile[src_pos];
                        src_pos++;
                        int copy_from = dest_pos - (((b1 & 0xF) << 8) | b2) - 1;
                        int n         = b1 >> 4;
                        if (n == 0)
                        {
                            n = CmpFile[src_pos] + 0x12;
                            src_pos++;
                        }
                        else
                        {
                            n += 2;
                        }
                        for (int j = 0; j < n; j++)
                        {
                            dest[dest_pos] = dest[copy_from];
                            dest_pos++;
                            copy_from++;
                        }
                    }
                    code <<= 1;
                }
            }
            return(dest);
        }
コード例 #4
0
ファイル: SceneUtils.cs プロジェクト: az64/mm-rando
 public static void GetActors()
 {
     for (int i = 0; i < RomData.SceneList.Count; i++)
     {
         for (int j = 0; j < RomData.SceneList[i].Maps.Count; j++)
         {
             int f = RomData.SceneList[i].Maps[j].File;
             RomUtils.CheckCompressed(f);
             int k = RomData.SceneList[i].Maps[j].Header;
             while (true)
             {
                 byte cmd = RomData.MMFileList[f].Data[k];
                 if (cmd == 0x01)
                 {
                     byte ActorCount = RomData.MMFileList[f].Data[k + 1];
                     int  ActorAddr  = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, k + 4) & 0xFFFFFF;
                     RomData.SceneList[i].Maps[j].ActorAddr = ActorAddr;
                     RomData.SceneList[i].Maps[j].Actors    = ReadMapActors(RomData.MMFileList[f].Data, ActorAddr, ActorCount);
                 }
                 if (cmd == 0x0B)
                 {
                     byte ObjectCount = RomData.MMFileList[f].Data[k + 1];
                     int  ObjectAddr  = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, k + 4) & 0xFFFFFF;
                     RomData.SceneList[i].Maps[j].ObjAddr = ObjectAddr;
                     RomData.SceneList[i].Maps[j].Objects = ReadMapObjects(RomData.MMFileList[f].Data, ObjectAddr, ObjectCount);
                 }
                 if (cmd == 0x14)
                 {
                     break;
                 }
                 k += 8;
             }
         }
     }
 }
コード例 #5
0
        public static List <int[]> GetAddresses(string path, string name)
        {
            List <int[]> Addrs = new List <int[]>();

            byte[] a;
            using (BinaryReader AddrFile = new BinaryReader(File.Open(Path.Combine(path, name), FileMode.Open, FileAccess.Read)))
            {
                a = new byte[AddrFile.BaseStream.Length];
                AddrFile.Read(a, 0, a.Length);
            }
            int i = 0;

            while (a[i] != 0xFF)
            {
                int   count = (int)ReadWriteUtils.Arr_ReadU32(a, i);
                int[] alist = new int[count];
                i += 4;
                for (int j = 0; j < count; j++)
                {
                    alist[j] = (int)ReadWriteUtils.Arr_ReadU32(a, i);
                    i       += 4;
                }
                Addrs.Add(alist);
            }
            return(Addrs);
        }
コード例 #6
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))));
        }
コード例 #7
0
ファイル: SceneUtils.cs プロジェクト: az64/mm-rando
 public static void GetMapHeaders()
 {
     for (int i = 0; i < RomData.SceneList.Count; i++)
     {
         int maps = RomData.SceneList[i].Maps.Count;
         for (int j = 0; j < maps; j++)
         {
             int f = RomData.SceneList[i].Maps[j].File;
             RomUtils.CheckCompressed(f);
             int k          = 0;
             int setupsaddr = -1;
             int nextlowest = -1;
             while (true)
             {
                 byte cmd = RomData.MMFileList[f].Data[k];
                 if (cmd == 0x18)
                 {
                     setupsaddr = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, k + 4) & 0xFFFFFF;
                 }
                 else if (cmd == 0x14)
                 {
                     break;
                 }
                 else
                 {
                     if (RomData.MMFileList[f].Data[k + 4] == 0x03)
                     {
                         int p = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, k + 4) & 0xFFFFFF;
                         if (((p < nextlowest) || (nextlowest == -1)) && ((p > setupsaddr) && (setupsaddr != -1)))
                         {
                             nextlowest = p;
                         }
                     }
                 }
                 k += 8;
             }
             if ((setupsaddr == -1) || (nextlowest == -1))
             {
                 continue;
             }
             for (k = setupsaddr; k < nextlowest; k += 4)
             {
                 byte s = RomData.MMFileList[f].Data[k];
                 if (s != 0x03)
                 {
                     break;
                 }
                 int p = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, k) & 0xFFFFFF;
                 Map m = new Map();
                 m.File   = f;
                 m.Header = p;
                 RomData.SceneList[i].Maps.Add(m);
             }
         }
     }
 }
コード例 #8
0
        private static void CheckHeaderForExits(int f, int headeraddr, Scene scene)
        {
            int  j          = headeraddr;
            int  setupsaddr = -1;
            int  nextlowest = -1;
            byte s;
            var  setup = new SceneSetup();

            scene.Setups.Add(setup);
            while (true)
            {
                byte cmd = RomData.MMFileList[f].Data[j];
                if (cmd == 0x13)
                {
                    setup.ExitListAddress = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, j + 4) & 0xFFFFFF;
                }
                else if (cmd == 0x17)
                {
                    setup.CutsceneListAddress = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, j + 4) & 0xFFFFFF;
                }
                else if (cmd == 0x18)
                {
                    setupsaddr = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, j + 4) & 0xFFFFFF;
                }
                else if (cmd == 0x14)
                {
                    break;
                }
                else
                {
                    if (RomData.MMFileList[f].Data[j + 4] == 0x02)
                    {
                        int p = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, j + 4) & 0xFFFFFF;
                        if (((p < nextlowest) || (nextlowest == -1)) && ((p > setupsaddr) && (setupsaddr != -1)))
                        {
                            nextlowest = p;
                        }
                    }
                }
                j += 8;
            }
            if ((setupsaddr != -1) && nextlowest != -1)
            {
                j = setupsaddr;
                s = RomData.MMFileList[f].Data[j];
                while (s == 0x02)
                {
                    int p = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, j) & 0xFFFFFF;
                    CheckHeaderForExits(f, p, scene);
                    j += 4;
                    s  = RomData.MMFileList[f].Data[j];
                }
            }
        }
コード例 #9
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;
            }
        }
コード例 #10
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);
        }
コード例 #11
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;
            }
        }
コード例 #12
0
        public static List <int[]> GetAddresses(byte[] addresses_content)
        {
            List <int[]> Addrs = new List <int[]>();
            int          i     = 0;

            while (addresses_content[i] != 0xFF)
            {
                int   count = (int)ReadWriteUtils.Arr_ReadU32(addresses_content, i);
                int[] alist = new int[count];
                i += 4;
                for (int j = 0; j < count; j++)
                {
                    alist[j] = (int)ReadWriteUtils.Arr_ReadU32(addresses_content, i);
                    i       += 4;
                }
                Addrs.Add(alist);
            }
            return(Addrs);
        }
コード例 #13
0
        public static void ApplyHack_File(string name, byte[] data)
        {
            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();
            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;
                ReadWriteUtils.Arr_Insert(hack_content, addr, (int)len, data, (int)dest);
                addr += (int)len;
            }
        }
コード例 #14
0
 public static void GetMaps()
 {
     foreach (var scene in RomData.SceneList)
     {
         int f = scene.File;
         RomUtils.CheckCompressed(f);
         int j = 0;
         while (true)
         {
             byte cmd = RomData.MMFileList[f].Data[j];
             if (cmd == 0x04)
             {
                 byte mapcount = RomData.MMFileList[f].Data[j + 1];
                 int  mapsaddr = (int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, j + 4) & 0xFFFFFF;
                 for (int k = 0; k < mapcount; k++)
                 {
                     Map m = new Map();
                     m.File = RomUtils.AddrToFile((int)ReadWriteUtils.Arr_ReadU32(RomData.MMFileList[f].Data, mapsaddr));
                     scene.Maps.Add(m);
                     mapsaddr += 8;
                 }
                 break;
             }
             if (cmd == 0x14)
             {
                 break;
             }
             j += 8;
         }
         CheckHeaderForExits(f, 0, scene);
         if (scene.Number == 108) // avoid modifying unused setup in East Clock Town. doesn't seem to actually affect anything in-game, but best not to touch it.
         {
             scene.Setups.RemoveAt(2);
         }
     }
 }
コード例 #15
0
        private static void FixCRC(byte[] ROM)
        {
            // reference: http://n64dev.org/n64crc.html
            uint[] CRC = new uint[2];
            uint   seed = 0xDF26F436;
            uint   t1, t2, t3, t4, t5, t6, r, d;
            int    i = 0x1000;

            t1 = t2 = t3 = t4 = t5 = t6 = seed;
            while (i < 0x101000)
            {
                d = ReadWriteUtils.Arr_ReadU32(ROM, i);
                if ((t6 + d) < t6)
                {
                    t4++;
                }
                t6 += d;
                t3 ^= d;
                r   = (d << (byte)(d & 0x1F)) | (d >> (byte)(32 - (d & 0x1F)));
                t5 += r;
                if (t2 < d)
                {
                    t2 ^= (t6 ^ d);
                }
                else
                {
                    t2 ^= r;
                }
                t1 += (ReadWriteUtils.Arr_ReadU32(ROM, 0x750 + (i & 0xFF)) ^ d);
                i  += 4;
            }
            CRC[0] = t6 ^ t4 ^ t3;
            CRC[1] = t5 ^ t2 ^ t1;
            ReadWriteUtils.Arr_WriteU32(ROM, 16, CRC[0]);
            ReadWriteUtils.Arr_WriteU32(ROM, 20, CRC[1]);
        }
コード例 #16
0
ファイル: SceneUtils.cs プロジェクト: az64/mm-rando
        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;
            }
        }
コード例 #17
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);
            //}
        }