Example #1
0
        static public Chart Read(Stream source)
        {
            BinaryReader reader = new BinaryReader(source);
            Chart        chart  = new Chart();

            if (reader.ReadInt32() != 0x00000008)
            {
                throw new Exception("Can't load this file: invalid signature.");
            }

            long granularity = reader.ReadInt32();

            while (true)
            {
                Entry entry       = new Entry();
                long  eventOffset = reader.ReadInt16();

                if (eventOffset >= 0x7FFF)
                {
                    break;
                }

                entry.LinearOffset = new Fraction(eventOffset * granularity, 1000000);
                entry.Value        = new Fraction(0, 1);

                int eventType  = reader.ReadByte();
                int eventValue = reader.ReadByte();
                int eventParameter;

                eventParameter = eventType >> 4;
                eventType     &= 0xF;

                // unhandled parameter types:
                //  0x05: measure length
                //  also does not interpret note count 100% (it's a carryover from older bm formats)

                switch (eventType)
                {
                case 0x00: if (eventOffset > 0)
                    {
                        entry.Type = EntryType.Marker; entry.Player = 1; entry.Column = eventParameter;
                    }
                    break;

                case 0x01: if (eventOffset > 0)
                    {
                        entry.Type = EntryType.Marker; entry.Player = 2; entry.Column = eventParameter;
                    }
                    break;

                case 0x02: entry.Type = EntryType.Sample; entry.Player = 1; entry.Column = eventParameter; entry.Value = new Fraction(eventValue, 1); break;

                case 0x03: entry.Type = EntryType.Sample; entry.Player = 2; entry.Column = eventParameter; entry.Value = new Fraction(eventValue, 1); break;

                case 0x04: entry.Type = EntryType.Tempo; entry.Value = new Fraction(eventValue + (eventParameter * 256), 1); break;

                case 0x06: entry.Type = EntryType.EndOfSong; entry.Player = eventParameter + 1; break;

                case 0x07: entry.Type = EntryType.Marker; entry.Player = 0; entry.Value = new Fraction(eventValue, 1); entry.Parameter = eventParameter; break;

                case 0x08: entry.Type = EntryType.Judgement; entry.Player = 0; entry.Value = new Fraction(eventValue, 1); entry.Parameter = eventParameter; break;

                case 0x0C: entry.Type = (eventParameter == 0 ? EntryType.Measure : EntryType.Invalid); entry.Player = eventParameter + 1; break;

                default: entry.Type = EntryType.Invalid; break;
                }

                if (entry.Type != EntryType.Invalid)
                {
                    chart.Entries.Add(entry);
                }
            }
            chart.Entries.Sort();

            // find the default bpm
            foreach (Entry entry in chart.Entries)
            {
                if (entry.Type == EntryType.Tempo)
                {
                    chart.DefaultBPM = entry.Value;
                    break;
                }
            }

            // fill in the metric offsets
            chart.CalculateMetricOffsets();

            return(chart);
        }
Example #2
0
        static public Chart Read(Stream source)
        {
            BinaryReaderEx reader = new BinaryReaderEx(source);

            Chart result = new Chart();

            result.TickRate = new Fraction(100, 5980);

            int[] lastSample     = new int[16];
            int   eventParameter = 0;
            int   eventValue     = 0;
            int   eventType      = 0;
            int   eventOffset    = 0;
            bool  notecountMode  = true;
            bool  defaultBPMSet  = false;

            while (true)
            {
                eventOffset    = reader.ReadUInt16();
                eventType      = reader.ReadByte();
                eventParameter = (eventType >> 4);
                eventType     &= 0xF;
                eventValue     = reader.ReadByte();

                // end of chart?
                if (eventOffset == 0x7FFF)
                {
                    break;
                }

                // ignore events in note count mode
                if (notecountMode)
                {
                    if (eventType != 0 || eventOffset > 0)
                    {
                        notecountMode = false;
                    }
                }

                // process events
                if (!notecountMode)
                {
                    Entry entry = new Entry();

                    entry.LinearOffset = new Fraction(eventOffset, 1);

                    switch (eventType)
                    {
                    case 0x0:     // marker
                        switch (eventParameter)
                        {
                        case 0x0: entry.Type = EntryType.Marker; entry.Player = 1; entry.Column = 0; entry.Value = new Fraction(lastSample[0x0], 1); break;

                        case 0x1: entry.Type = EntryType.Marker; entry.Player = 1; entry.Column = 1; entry.Value = new Fraction(lastSample[0x1], 1); break;

                        case 0x2: entry.Type = EntryType.Marker; entry.Player = 1; entry.Column = 2; entry.Value = new Fraction(lastSample[0x2], 1); break;

                        case 0x3: entry.Type = EntryType.Marker; entry.Player = 1; entry.Column = 3; entry.Value = new Fraction(lastSample[0x3], 1); break;

                        case 0x4: entry.Type = EntryType.Marker; entry.Player = 1; entry.Column = 4; entry.Value = new Fraction(lastSample[0x4], 1); break;

                        case 0x5: entry.Type = EntryType.Marker; entry.Player = 1; entry.Column = 5; entry.Value = new Fraction(lastSample[0x5], 1); break;

                        case 0x6: entry.Type = EntryType.Marker; entry.Player = 1; entry.Column = 6; entry.Value = new Fraction(lastSample[0x6], 1); break;

                        case 0x7: entry.Type = EntryType.Marker; entry.Player = 1; entry.Column = 7; entry.Value = new Fraction(lastSample[0x7], 1); break;
                        }
                        break;

                    case 0x1:     // marker
                        switch (eventParameter)
                        {
                        case 0x0: entry.Type = EntryType.Marker; entry.Player = 2; entry.Column = 0; entry.Value = new Fraction(lastSample[0x8], 1); break;

                        case 0x1: entry.Type = EntryType.Marker; entry.Player = 2; entry.Column = 1; entry.Value = new Fraction(lastSample[0x9], 1); break;

                        case 0x2: entry.Type = EntryType.Marker; entry.Player = 2; entry.Column = 2; entry.Value = new Fraction(lastSample[0xA], 1); break;

                        case 0x3: entry.Type = EntryType.Marker; entry.Player = 2; entry.Column = 3; entry.Value = new Fraction(lastSample[0xB], 1); break;

                        case 0x4: entry.Type = EntryType.Marker; entry.Player = 2; entry.Column = 4; entry.Value = new Fraction(lastSample[0xC], 1); break;

                        case 0x5: entry.Type = EntryType.Marker; entry.Player = 2; entry.Column = 5; entry.Value = new Fraction(lastSample[0xD], 1); break;

                        case 0x6: entry.Type = EntryType.Marker; entry.Player = 2; entry.Column = 6; entry.Value = new Fraction(lastSample[0xE], 1); break;

                        case 0x7: entry.Type = EntryType.Marker; entry.Player = 2; entry.Column = 7; entry.Value = new Fraction(lastSample[0xF], 1); break;
                        }
                        break;

                    case 0x2:     // sample
                        switch (eventParameter)
                        {
                        case 0x0: entry.Type = EntryType.Sample; entry.Player = 1; entry.Column = 0; lastSample[0x0] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x1: entry.Type = EntryType.Sample; entry.Player = 1; entry.Column = 1; lastSample[0x1] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x2: entry.Type = EntryType.Sample; entry.Player = 1; entry.Column = 2; lastSample[0x2] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x3: entry.Type = EntryType.Sample; entry.Player = 1; entry.Column = 3; lastSample[0x3] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x4: entry.Type = EntryType.Sample; entry.Player = 1; entry.Column = 4; lastSample[0x4] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x5: entry.Type = EntryType.Sample; entry.Player = 1; entry.Column = 5; lastSample[0x5] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x6: entry.Type = EntryType.Sample; entry.Player = 1; entry.Column = 6; lastSample[0x6] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x7: entry.Type = EntryType.Sample; entry.Player = 1; entry.Column = 7; lastSample[0x7] = eventValue; entry.Value = new Fraction(eventValue, 1); break;
                        }
                        break;

                    case 0x3:     // sample
                        switch (eventParameter)
                        {
                        case 0x0: entry.Type = EntryType.Sample; entry.Player = 2; entry.Column = 0; lastSample[0x8] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x1: entry.Type = EntryType.Sample; entry.Player = 2; entry.Column = 1; lastSample[0x9] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x2: entry.Type = EntryType.Sample; entry.Player = 2; entry.Column = 2; lastSample[0xA] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x3: entry.Type = EntryType.Sample; entry.Player = 2; entry.Column = 3; lastSample[0xB] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x4: entry.Type = EntryType.Sample; entry.Player = 2; entry.Column = 4; lastSample[0xC] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x5: entry.Type = EntryType.Sample; entry.Player = 2; entry.Column = 5; lastSample[0xD] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x6: entry.Type = EntryType.Sample; entry.Player = 2; entry.Column = 6; lastSample[0xE] = eventValue; entry.Value = new Fraction(eventValue, 1); break;

                        case 0x7: entry.Type = EntryType.Sample; entry.Player = 2; entry.Column = 7; lastSample[0xF] = eventValue; entry.Value = new Fraction(eventValue, 1); break;
                        }
                        break;

                    case 0x4:     // tempo
                        entry.Type  = EntryType.Tempo;
                        entry.Value = new Fraction((eventParameter * 256) + eventValue, 1);
                        if (!defaultBPMSet)
                        {
                            defaultBPMSet     = true;
                            result.DefaultBPM = entry.Value;
                        }
                        break;

                    case 0x6:     // end of song
                        entry.Type = EntryType.EndOfSong;
                        break;

                    case 0x7:     // bgm
                        entry.Type   = EntryType.Marker;
                        entry.Player = 0;
                        entry.Value  = new Fraction(eventValue, 1);
                        break;

                    case 0xC:     // measure
                        entry.Type = EntryType.Measure; entry.Player = entry.Parameter + 1;
                        break;

                    case 0xE:     // judgement
                        entry.Type      = EntryType.Judgement;
                        entry.Value     = new Fraction(eventValue, 1);
                        entry.Parameter = eventParameter;
                        break;
                    }

                    if (entry.Type != EntryType.Invalid)
                    {
                        result.Entries.Add(entry);
                    }
                }
            }

            if (result.Entries.Count > 0)
            {
                result.Entries.Sort();
                result.CalculateMetricOffsets();
            }
            else
            {
                result = null;
            }

            return(result);
        }
        static public Chart Read(Stream source)
        {
            BinaryReaderEx reader = new BinaryReaderEx(source);

            Chart result = new Chart();

            result.TickRate = new Fraction(1, 1000);

            Dictionary <int, int> lastSample = new Dictionary <int, int>();
            int  eventParameter = 0;
            int  eventValue     = 0;
            int  eventType      = 0;
            int  eventOffset    = 0;
            int  currentOffset  = 0;
            bool defaultBPMSet  = false;

            // read chart header
            reader.ReadBytes(0x20);

            while (true)
            {
                currentOffset += (int)reader.ReadUInt16S();
                eventOffset    = currentOffset;
                eventType      = reader.ReadByte();
                int eventPlayer = reader.ReadByte();
                eventParameter = reader.ReadByte();
                eventValue     = reader.ReadByte();
                eventValue    |= (eventParameter & 0xF0) << 4;

                // end of chart?
                if (eventType == 0xFF)
                {
                    break;
                }

                Entry entry = new Entry();

                entry.LinearOffset = new Fraction(eventOffset, 1);

                int eventColumn;

                switch (eventType)
                {
                case 0x0:     // marker
                    if (eventValue >= 0x00 && eventValue <= 0x08)
                    {
                        if (eventPlayer <= 1)
                        {
                            if (eventValue == 0x05)
                            {
                                eventValue = 0x07;
                            }
                            else if (eventValue == 0x06)
                            {
                                eventValue = 0x05;
                            }
                            else if (eventValue == 0x07)
                            {
                                eventValue = 0x06;
                            }
                            eventColumn  = eventValue + (eventPlayer * 0x10);
                            entry.Type   = EntryType.Marker;
                            entry.Column = eventValue;
                            entry.Player = eventPlayer + 1;
                            if (lastSample.ContainsKey(eventColumn))
                            {
                                entry.Value = new Fraction(lastSample[eventColumn], 1);
                            }
                            else
                            {
                                entry.Value = new Fraction(0, 1);
                            }
                        }
                        break;
                    }
                    else
                    {
                        break;
                    }

                case 0x2:     // sample
                    if (eventParameter >= 0x00 && eventParameter <= 0x08)
                    {
                        if (eventPlayer <= 1)
                        {
                            if (eventParameter == 0x05)
                            {
                                eventParameter = 0x07;
                            }
                            else if (eventParameter == 0x06)
                            {
                                eventParameter = 0x05;
                            }
                            else if (eventParameter == 0x07)
                            {
                                eventParameter = 0x06;
                            }
                            if (eventValue > 0)
                            {
                                eventValue++;
                            }
                            eventColumn             = eventParameter + (eventPlayer * 0x10);
                            entry.Type              = EntryType.Sample;
                            entry.Player            = eventPlayer + 1;
                            entry.Column            = eventParameter;
                            entry.Value             = new Fraction(eventValue, 1);
                            lastSample[eventColumn] = eventValue;
                        }
                        break;
                    }
                    else
                    {
                        break;
                    }

                case 0x4:     // tempo
                    entry.Type  = EntryType.Tempo;
                    entry.Value = new Fraction(eventValue, 1);
                    if (!defaultBPMSet)
                    {
                        defaultBPMSet     = true;
                        result.DefaultBPM = entry.Value;
                    }
                    break;

                case 0x6:     // end of song
                    entry.Type = EntryType.EndOfSong;
                    break;

                case 0x7:     // bgm
                    if (eventValue > 0)
                    {
                        eventValue++;
                    }
                    entry.Type   = EntryType.Marker;
                    entry.Player = 0;
                    entry.Value  = new Fraction(eventValue, 1);
                    break;

                case 0x8:     // judgement
                    entry.Type      = EntryType.Judgement;
                    entry.Value     = new Fraction(eventValue, 1);
                    entry.Parameter = eventParameter;
                    break;

                case 0xB:     // unknown
                    break;

                case 0xC:     // measure
                    entry.Type   = EntryType.Measure;
                    entry.Player = entry.Player + 1;
                    break;

                case 0xD:     // unknown
                    break;

                case 0xE:     // bgm track?
                    entry.Type   = EntryType.Marker;
                    entry.Player = 0;
                    entry.Value  = new Fraction(1, 1);
                    break;

                default:
                    break;
                }

                if (entry.Type != EntryType.Invalid)
                {
                    result.Entries.Add(entry);
                }
            }

            if (result.Entries.Count > 0)
            {
                result.Entries.Sort();
                result.CalculateMetricOffsets();
            }
            else
            {
                result = null;
            }

            return(result);
        }