예제 #1
0
        public CMM(byte[] data)
        {
            for (int lineskip = 0; lineskip < data.Length; lineskip += 8)
            {
                if (ByteUtilities.ByteArrayEquals(data, lineskip, new byte[] { 0x16, 0x1A, 0x47, 0xE8, 0, 0, 0 }, 0, 7))
                {
                    int byteCount = data[lineskip + 7];
                    TracklistModifier = data.Skip(lineskip + 8).Take(byteCount).ToArray();
                }
            }

            Map = new Dictionary <int, IEnumerable <Song> >();
            for (int lineskip = 0; lineskip < data.Length; lineskip += 8)
            {
                if (data[lineskip] == 0x00 && data[lineskip + 1] == 0x53 && data[lineskip + 2] == 0xCE)
                {
                    int tracklistIndex = data[lineskip + 3] - 0xA0;
                    int tracks         = data[lineskip + 7];
                    foreach (Stage stage in GetStageByIdInTracklist(tracklistIndex))
                    {
                        IEnumerable <Song> songs = ReadSongs(data, lineskip + 16, tracks);
                        if (Map.TryGetValue(stage.ID, out IEnumerable <Song> existing))
                        {
                            Console.Error.WriteLine(
                                $"Replacing already read {existing.Count()}-song tracklist for {stage} with newly read {songs.Count()}-song tracklist");
                        }

                        Map[stage.ID] = songs;
                    }
                }
            }
        }
예제 #2
0
        public StageDependentSongLoader(byte[] data)
        {
            SongsByStage = new Dictionary <byte, Song>();

            for (int line = 0; line < data.Length; line += 8)
            {
                if (ByteUtilities.ByteArrayEquals(data, line, SDSL_HEADER, 0, SDSL_HEADER.Length))
                {
                    byte   stageID = data[line + 7];
                    byte   songID1 = data[line + 22];
                    byte   songID2 = data[line + 23];
                    ushort songID  = (ushort)(0x100 * songID1 + songID2);
                    Song   s       = (from g in SongIDMap.Songs
                                      where g.ID == songID
                                      select g).First();
                    if (SongsByStage.ContainsKey(stageID))
                    {
                        Console.WriteLine(String.Format("WARNING: code mapping stage {0} to song {1} will not " +
                                                        "take effect, since a later code maps it to song {2}", stageID, SongsByStage[stageID], s));
                        SongsByStage.Remove(stageID);
                    }
                    SongsByStage.Add(stageID, s);
                    line += 24;
                }
            }
        }
        public StageDependentSongLoader(byte[] data)
        {
            songReplacements = new List <SongReplacement>();

            for (int line = 0; line < data.Length; line += 8)
            {
                if (ByteUtilities.ByteArrayEquals(data, line, SDSL_HEADER, 0, SDSL_HEADER.Length))
                {
                    byte   stageID  = data[line + 0x7];
                    ushort?songIDIn = null;
                    ushort songIDOut;
                    if (ByteUtilities.ByteArrayEquals(data, line + 8, SONG_ID_CONDITION, 0, SONG_ID_CONDITION.Length))
                    {
                        songIDIn  = (ushort)(0x100 * data[line + 14] + data[line + 15]);
                        songIDOut = (ushort)(0x100 * data[line + 30] + data[line + 31]);
                    }
                    else
                    {
                        songIDOut = (ushort)(0x100 * data[line + 22] + data[line + 23]);
                    }

                    Song s = (from g in SongIDMap.Songs
                              where g.ID == songIDOut
                              select g).FirstOrDefault();
                    if (s != null)
                    {
                        songReplacements.Add(new SongReplacement
                        {
                            stageID = stageID,
                            songID  = songIDIn,
                            song    = s
                        });
                        line += 24;
                    }
                    else
                    {
                        Console.WriteLine("Unknown song ID " + songIDOut.ToString("X4") +
                                          " - not currently supported.");
                    }
                }
            }
        }
예제 #4
0
        public TracklistModifier(byte[] data)
        {
            Dictionary <byte, byte> map1 = new Dictionary <byte, byte>();
            Dictionary <byte, byte> map2 = new Dictionary <byte, byte>();

            using (MemoryStream ms = new MemoryStream(data)) {
                byte[] line = new byte[8];
                while (true)
                {
                    int read = ms.Read(line, 0, 8);
                    if (read < 8)
                    {
                        break;
                    }

                    if (ByteUtilities.ByteArrayEquals(line, 0, HEADER, 0, 7))
                    {
                        int lines = line[7];
                        for (int i = 0; i < lines; i++)
                        {
                            read = ms.Read(line, 0, 8);
                            if (read < 8)
                            {
                                throw new FormatException($"Could not read all of Tracklist Modifier code (line {i + 1}, read {read} bytes)");
                            }

                            switch (line[0])
                            {
                            case 0x2C:
                                map1.Add(line[3], line[7]);
                                break;

                            case 0x48:
                                map2.Add(line[3], line[7]);
                                break;

                            case 0x7c:
                                break;

                            default:
                                throw new FormatException("Unrecognized line in Tracklist Modifier code: " + string.Join("", line.Select(b => ((int)b).ToString("X2"))));
                            }
                        }
                        break;
                    }
                }
            }

            this.StageIdMap = new Dictionary <byte, byte>();
            foreach (var pair in map1)
            {
                if (map2.TryGetValue(pair.Value, out byte newStageId))
                {
                    StageIdMap.Add(pair.Key, newStageId);
                }
                else
                {
                    throw new FormatException($"Part 2 of Tracklist Modifier uses ID {pair.Value} not present in Part 3");
                }
            }
        }
예제 #5
0
        private void init(byte[] data)
        {
            OtherCodesIgnoredInSameFile = 0;
            IgnoredMetadata             = false;
            int index = -1;

            for (int line = 0; line < data.Length; line += 8)
            {
                if (ByteUtilities.ByteArrayEquals(data, line, SSS_HEADER, 0, SSS_HEADER.Length))
                {
                    if (index != -1)
                    {
                        OtherCodesIgnoredInSameFile++;
                    }

                    index = line;
                }
            }

            if (index < 0)
            {
                if (data.Length > 0)
                {
                    MessageBox.Show("No custom SSS code found. A default code will be used.");
                }

                DataBefore = gctheader.ToArray();
                sss1       = ByteUtilities.StringToByteArray(
                    "00010203 04050709 080A0B0C 0D0E0F10 11141516 1A191217 0618131D 1E1B1C");
                sss2 = ByteUtilities.StringToByteArray("1F202122 23242526 2728");
                sss3 = ByteUtilities.StringToByteArray(
                    "01010202 03030404 05050606 07070808 0909330A 0B0B0C0C 0D0D0E0E 130F1410 " +
                    "15111612 17131814 19151C16 1D171E18 1F19201A 211B221C 231D241E 251F2932 " +
                    "2A332B34 2C352D36 2F373038 3139323A 2E3BFFFF");
                DataAfter = data.Skip(gctheader.Length).ToArray();
            }
            else
            {
                int start = index;
                DataBefore = new byte[start];
                Array.ConstrainedCopy(data, 0, DataBefore, 0, start);

                index += 14 * 8;
                byte sss1_count = data[index - 1];
                sss1 = new byte[sss1_count];
                Array.ConstrainedCopy(data, index, sss1, 0, sss1_count);

                index += sss1_count;
                while (index % 8 != 0)
                {
                    index++;
                }

                index += 2 * 8;
                byte sss2_count = data[index - 1];
                sss2 = new byte[sss2_count];
                Array.ConstrainedCopy(data, index, sss2, 0, sss2_count);

                index += sss2_count;
                while (index % 8 != 0)
                {
                    index++;
                }

                index += 1 * 8;
                byte sss3_count = data[index - 1];
                sss3 = new byte[sss3_count];
                Array.ConstrainedCopy(data, index, sss3, 0, sss3_count);

                index += sss3_count;
                while (index % 8 != 0)
                {
                    index++;
                }

                DataAfter = new byte[data.Length - index];
                Array.ConstrainedCopy(data, index, DataAfter, 0, data.Length - index);
            }

            bool footer_found = false;

            for (int i = 0; i < DataAfter.Length; i += 8)
            {
                if (footer_found)
                {
                    IgnoredMetadata = true;
                    DataAfter       = DataAfter.Take(i).ToArray();
                    break;
                }
                else
                {
                    if (ByteUtilities.ByteArrayEquals(DataAfter, i, gctfooter, 0, 8))
                    {
                        footer_found = true;
                    }
                }
            }
        }
예제 #6
0
        public AltStageSongForcer(byte[] data)
        {
            songReplacements = new List <SongReplacement>();

            for (int lineskip = 0; lineskip < data.Length; lineskip += 8)
            {
                if (ByteUtilities.ByteArrayEquals(data, lineskip, HEADER, 0, HEADER.Length))
                {
                    lineskip += HEADER.Length;
                    using (MemoryStream ms = new MemoryStream(data, lineskip, data.Length - lineskip))
                    {
                        byte   stageID = 0;
                        ushort buttons = 0;
                        ushort?songID  = null;

                        byte[] line = new byte[4];
                        while (true)
                        {
                            int read = ms.Read(line, 0, 4);
                            if (read < 8)
                            {
                                throw new FormatException();
                            }

                            if (ByteUtilities.ByteArrayEquals(line, 0, new byte[] { 0x2C, 0x1B, 0x00 }, 0, 3))
                            {
                                stageID = line[3];
                                buttons = 0;
                                songID  = null;
                            }
                            else if (ByteUtilities.ByteArrayEquals(line, 0, new byte[] { 0x2C, 0x0C }, 0, 2))
                            {
                                buttons = (ushort)(line[2] << (8 + line[3]));
                            }
                            else if (ByteUtilities.ByteArrayEquals(line, 0, new byte[] { 0x2C, 0x00 }, 0, 2))
                            {
                                songID = (ushort)(line[2] << (8 + line[3]));
                            }
                            else if (ByteUtilities.ByteArrayEquals(line, 0, new byte[] { 0x38, 0x00 }, 0, 2))
                            {
                                ushort replacementSongID = (ushort)(line[2] << (8 + line[3]));
                                songReplacements.Add(new SongReplacement
                                {
                                    stageID = stageID,
                                    buttons = buttons,
                                    songID  = songID,
                                    song    = (from g in SongIDMap.Songs
                                               where g.ID == replacementSongID
                                               select g).First()
                                });
                            }
                            else if (ByteUtilities.ByteArrayEquals(line, 0, new byte[] { 0x40, 0x82, 0x00 }, 0, 3))
                            {
                            }
                            else if (ByteUtilities.ByteArrayEquals(line, 0, new byte[] { 0x90, 0x1D, 0x00, 0x00 }, 0, 4))
                            {
                                break;
                            }
                            else
                            {
                                throw new FormatException();
                            }
                        }
                    }

                    break;
                }
            }
        }
        public AlternateStageLoaderData(byte[] data)
        {
            AlternatesByStage = new Dictionary <string, AlternateStageEntry>();

            for (int index = 0; index < data.Length; index += 8)
            {
                if (ByteUtilities.ByteArrayEquals(data, index, HEADER_BRAWL, 0, HEADER_BRAWL.Length) ||
                    ByteUtilities.ByteArrayEquals(data, index, HEADER_PM36, 0, HEADER_PM36.Length))
                {
                    int countbyte = data[index + 19];
                    index += 24;
                    int endIndex = index + 8 * countbyte - 8;
                    while (index < endIndex)
                    {
                        char[] name = new char[4];
                        name[0] = (char)data[index];
                        name[1] = (char)data[index + 1];
                        name[2] = (char)data[index + 2];
                        name[3] = (char)data[index + 3];
                        if (name[0] == '\0')
                        {
                            throw new Exception("Invalid stage name in alternate stage loader data: " +
                                                string.Join("", name.Select(c => ((int)c).ToString("X2"))));
                        }

                        Console.WriteLine(new string(name) + " " + data[index + 3].ToString("X2"));

                        int buttonActivatedCount = data[index + 4];
                        if (buttonActivatedCount > 26)
                        {
                            throw new Exception("There are more than 26 button activated alternate stages for stage " +
                                                new string(name) + ". This is probably incorrect.");
                        }

                        int randomCount = data[index + 5];
                        if (randomCount > 26)
                        {
                            throw new Exception("There are more than 26 random alternate stages for stage " +
                                                new string(name) + ". This is probably incorrect.");
                        }

                        index += 8;

                        List <AlternateStageEntry.Alternate> buttonActivated = new List <AlternateStageEntry.Alternate>();
                        for (int j = 0; j < buttonActivatedCount; j++)
                        {
                            int  buttonMask = data[index] << (8 + data[index + 1]);
                            char letter     = (char)('A' + data[index + 3]);

                            buttonActivated.Add(new AlternateStageEntry.Alternate
                            {
                                ButtonMask = (ushort)buttonMask,
                                Letter     = letter
                            });

                            index += 8;
                        }

                        List <AlternateStageEntry.Alternate> random = new List <AlternateStageEntry.Alternate>();
                        for (int j = 0; j < randomCount; j++)
                        {
                            char letter = (char)('A' + j);
                            random.Add(new AlternateStageEntry.Alternate
                            {
                                Letter     = letter,
                                ButtonMask = 0
                            });
                        }

                        AlternatesByStage.Add(new string(name), new AlternateStageEntry
                        {
                            Random          = random,
                            ButtonActivated = buttonActivated
                        });
                    }

                    break;
                }
            }
        }
        private void init(byte[] data)
        {
            Settings = new Dictionary <ushort, byte>();

            int index = -1;

            for (int line = 0; line < data.Length; line += 8)
            {
                if (ByteUtilities.ByteArrayEquals(data, line, CSV_HEADER, 0, CSV_HEADER.Length))
                {
                    index = line;
                }
            }

            if (index < 0)
            {
                Console.WriteLine("No Custom Song Volume code found. An empty code will be created.");

                DataBefore = gctheader.ToArray();
                DataAfter  = data.Skip(gctheader.Length).ToArray();
            }
            else
            {
                int start = index;
                DataBefore = new byte[start];
                Array.ConstrainedCopy(data, 0, DataBefore, 0, start);

                index += 9 * 8;
                byte byte_count       = data[index - 1];
                bool found_terminator = false;
                for (int i = 0; i < byte_count; i += 4)
                {
                    ushort u = (ushort)(data[index + i] * 0x100 + data[index + i + 1]);
                    if (u == 0x7FFF)
                    {
                        if (found_terminator)
                        {
                            throw new InvalidDataException("Two terminators");
                        }
                        found_terminator = true;
                    }
                    else
                    {
                        Settings.Add(u, data[index + i + 3]);
                    }
                }
                if (!found_terminator)
                {
                    throw new InvalidDataException("No terminators");
                }

                index += byte_count;
                while (index % 8 != 0)
                {
                    index++;
                }

                DataAfter = new byte[data.Length - index];
                Array.ConstrainedCopy(data, index, DataAfter, 0, data.Length - index);
            }

            bool footer_found = false;

            for (int i = 0; i < DataAfter.Length; i += 8)
            {
                if (footer_found)
                {
                    MessageBox.Show("Extra data found after GCT footer - this will be discarded if you save the GCT.");
                    DataAfter = DataAfter.Take(i).ToArray();
                    break;
                }
                else
                {
                    if (ByteUtilities.ByteArrayEquals(DataAfter, i, gctfooter, 0, 8))
                    {
                        footer_found = true;
                    }
                }
            }
        }