private IEnumerable <BmsCommand> ConvertLines(IEnumerable <string> lines)
        {
            foreach (var line in lines)
            {
                if (string.IsNullOrEmpty(line))
                {
                    continue;
                }

                var trimmedLine = line.Trim();

                if (string.IsNullOrEmpty(trimmedLine))
                {
                    continue;
                }

                // Lines not starting with # are considered comments.
                if (trimmedLine[0] != '#')
                {
                    yield return(new BmsCommand
                    {
                        Comment = trimmedLine
                    });

                    continue;
                }

                // Determine delimiter.
                var cmd             = new BmsCommand();
                var delimiterOffset = Delimiters
                                      .Select(d => new { Delimiter = d, Index = trimmedLine.IndexOf(d) })
                                      .Where(kv => kv.Index >= 0)
                                      .OrderBy(kv => kv.Index)
                                      .FirstOrDefault();

                if (delimiterOffset != null)
                {
                    cmd.Name  = trimmedLine.Substring(1, delimiterOffset.Index - 1).Trim().ToUpperInvariant();
                    cmd.Value = trimmedLine.Substring(delimiterOffset.Index + 1).Trim();
                    if (delimiterOffset.Delimiter == ':')
                    {
                        cmd.UseColon = true;
                    }
                }
                else
                {
                    cmd.Name = trimmedLine.Substring(1).ToUpperInvariant();
                }

                yield return(cmd);
            }
        }
Example #2
0
        private IEnumerable <IEvent> GetMeasureEvents(BmsCommand command, IDictionary <int, BigRational> bpmMap)
        {
            var measure = Alphabet.DecodeNumeric(command.Name.AsSpan(0, 3));
            var lane    = Alphabet.DecodeHex(command.Name.AsSpan(3, 2));

            switch (lane)
            {
            case 0x02:
            {
                return(new[]
                    {
                        new Event
                        {
                            [NumericData.MeasureLength] = BigRationalParser.ParseString(command.Value),
                            [NumericData.MetricOffset] = measure
                        }
                    });
            }
            }

            var events = new List <Event>();
            var total  = command.Value.Length / 2;

            for (var index = 0; index < total; index++)
            {
                var valueMemory = command.Value.AsMemory(index << 1, 2);
                var value       = valueMemory.Span;
                if (value[0] == '0' && value[1] == '0')
                {
                    continue;
                }

                void AddEvent(Event ev)
                {
                    ev[NumericData.MetricOffset] = new BigRational(new BigInteger(measure), new BigInteger(index),
                                                                   new BigInteger(total));
                    ev[NumericData.SourceData]    = Alphabet.DecodeAlphanumeric(valueMemory.Span);
                    ev[NumericData.SourceCommand] = lane;
                    events.Add(ev);
                }

                switch (lane)
                {
                case 0x01:
                {
                    AddEvent(new Event
                        {
                            [NumericData.PlaySound] = Alphabet.DecodeAlphanumeric(value)
                        });
                    break;
                }

                case 0x03:
                {
                    AddEvent(new Event
                        {
                            [NumericData.Bpm] = Alphabet.DecodeHex(value)
                        });
                    break;
                }

                case 0x04:
                {
                    AddEvent(new Event
                        {
                            [NumericData.BgaBase] = Alphabet.DecodeAlphanumeric(value)
                        });
                    break;
                }

                case 0x05:
                {
                    AddEvent(new Event
                        {
                            [NumericData.BgaObject] = Alphabet.DecodeAlphanumeric(value)
                        });
                    break;
                }

                case 0x06:
                {
                    AddEvent(new Event
                        {
                            [NumericData.BgaPoor] = Alphabet.DecodeAlphanumeric(value)
                        });
                    break;
                }

                case 0x07:
                {
                    AddEvent(new Event
                        {
                            [NumericData.BgaLayer] = Alphabet.DecodeAlphanumeric(value)
                        });
                    break;
                }

                case 0x08:
                {
                    var number = Alphabet.DecodeAlphanumeric(value);
                    if (bpmMap.ContainsKey(number))
                    {
                        AddEvent(new Event
                            {
                                [NumericData.Bpm] = bpmMap[number]
                            });
                    }

                    break;
                }

                case 0x11:
                case 0x12:
                case 0x13:
                case 0x14:
                case 0x15:
                case 0x21:
                case 0x22:
                case 0x23:
                case 0x24:
                case 0x25:
                {
                    AddEvent(new Event
                        {
                            [NumericData.Player] = (lane & 0x20) >> 5,
                            [FlagData.Note]      = true,
                            [NumericData.Column] = lane & 0x0F
                        });
                    break;
                }

                case 0x18:
                case 0x19:
                case 0x28:
                case 0x29:
                {
                    AddEvent(new Event
                        {
                            [NumericData.Player] = (lane & 0x20) >> 5,
                            [FlagData.Note]      = true,
                            [NumericData.Column] = (lane & 0x0F) - 2
                        });
                    break;
                }

                case 0x16:
                case 0x26:
                {
                    AddEvent(new Event
                        {
                            [NumericData.Player] = (lane & 0x20) >> 5,
                            [FlagData.Scratch]   = true,
                            [FlagData.Note]      = true
                        });
                    break;
                }

                case 0x17:
                case 0x27:
                {
                    AddEvent(new Event
                        {
                            [NumericData.Player] = (lane & 0x20) >> 5,
                            [FlagData.FreeZone]  = true,
                            [FlagData.Note]      = true
                        });
                    break;
                }

                case 0x31:
                case 0x32:
                case 0x33:
                case 0x34:
                case 0x35:
                case 0x41:
                case 0x42:
                case 0x43:
                case 0x44:
                case 0x45:
                {
                    AddEvent(new Event
                        {
                            [NumericData.Player]    = (lane & 0x20) >> 5,
                            [NumericData.Column]    = lane & 0x0F,
                            [NumericData.LoadSound] = Alphabet.DecodeAlphanumeric(value)
                        });
                    break;
                }

                case 0x38:
                case 0x39:
                case 0x48:
                case 0x49:
                {
                    AddEvent(new Event
                        {
                            [NumericData.Player]    = (lane & 0x20) >> 5,
                            [NumericData.Column]    = (lane & 0x0F) - 2,
                            [NumericData.LoadSound] = Alphabet.DecodeAlphanumeric(value)
                        });
                    break;
                }

                case 0x36:
                case 0x37:
                case 0x46:
                case 0x47:
                {
                    AddEvent(new Event
                        {
                            [NumericData.Player]    = (lane & 0x20) >> 5,
                            [FlagData.Scratch]      = true,
                            [NumericData.LoadSound] = Alphabet.DecodeAlphanumeric(value)
                        });
                    break;
                }
                }
            }

            return(events);
        }