public override void Load(string path) { base.Load(path); // Parse line-by-line _index = 0; _line = ""; string section = String.Empty; ReadAheadStreamReader reader = new ReadAheadStreamReader(path); // Main loop while (reader.PeekLine() != null) { _index++; _line = reader.ReadLine().Trim(); // Empty line if (_line.Length == 0) { continue; // Comment } else if (_line[0] == '/' || _line[0] == ';') { continue; // Section start } else if (_line[0] == '[') { if (_line.IndexOf(']') != -1) { section = _line.Substring(_line.IndexOf('[') + 1, _line.IndexOf(']') - 1); if (section == INFO_SECTION) { continue; } else if (section.IndexOf('-') != -1 && section.IndexOf(',') != -1) { Pattern pattern = this.ParsePattern(section); _info.patterns.Add(pattern); } } // Info section // Note: pattern data is parsed with LoadPattern } else if (section == INFO_SECTION) { // Parse key-value pair string key, val; if (!this.ParseKeyValuePair(_line, out key, out val)) { // Skip if not a key-value pair this.Warning("Unparsed line"); continue; } // Set data based on key switch(key) { case "Version": this.CheckVersion(val); break; case "Song": _info.song = this.FindAudioFile("Song", val, true); break; case "Title": _info.title = val; break; case "TitleTranslit": _info.titleTranslit = val; break; case "Subtitle": _info.subtitle = val; break; case "SubtitleTranslit": _info.subtitleTranslit = val; break; case "Artist": _info.artist = val; break; case "ArtistTranslit": _info.artistTranslit = val; break; case "Album": _info.album = val; break; case "AlbumTranslit": _info.albumTranslit = val; break; case "Genre": _info.genre = val; break; case "Credits": _info.credits = val; break; case "Link": _info.link = val; break; case "Description": _info.description = val; break; case "Tags": _info.tags.AddRange(val.Split(',')); break; case "DisplayBpm": _info.displayBpm = this.ParseDisplayBpms(val); break; case "SampleStart": _info.sampleStart = this.ParseFloat("SampleStart", val, false); break; case "SampleLength": _info.sampleLength = this.ParseFloat("SampleLength", val, false); break; case "Cover": _info.cover = this.FindImageFile("Cover", val, false); break; case "Banner": _info.banner = this.FindImageFile("Banner", val, false); break; case "Backgrounds": _info.backgrounds = this.ParseBackgrounds(val); break; case "Lyrics": _info.lyrics = this.FindLyricsFile("Lyrics", val, false); break; default: this.Warning("Unrecognized key: " + key); break; } } else { this.Warning("Unparsed line"); } } // Cleanup reader.Close(); }
public override void LoadPattern(Pattern pattern) { // Don't unnecessarily reload if (pattern.loaded == true) { return; } // Parse line-by-line _index = 0; _line = ""; ReadAheadStreamReader reader = new ReadAheadStreamReader(_info.path); // Skip to main section while (_index < pattern.lineIndex) { _index++; reader.SkipLine(); } // Parsing loop while (reader.PeekLine() != null) { _index++; _line = reader.ReadLine().Trim(); // Empty line if (_line.Length == 0) { continue; // Comment } else if (_line[0] == ';' || _line[0] == '/') { continue; // Section start } else if (_line[0] == '[') { break; // End of pattern data // Pattern data } else { // Parse key-value pair string key, val; if (!this.ParseKeyValuePair(_line, out key, out val)) { // Skip if not a key-value pair this.Warning("Unparsed line"); continue; } this.ParseNote(pattern, key, val); } } // Sort notes this.SortNotes(pattern); // Cleanup pattern.loaded = true; reader.Close(); }
public override void Load(string path) { base.Load(path); // Parse line-by-line _index = 0; _line = ""; string section = String.Empty; ReadAheadStreamReader reader = new ReadAheadStreamReader(path); // Main loop while (reader.PeekLine() != null) { _index++; _line = reader.ReadLine().Trim(); // Empty line if (_line.Length == 0) { continue; // Comment } else if (_line[0] == '/' || _line[0] == ';') { continue; // Section start } else if (_line[0] == '[') { if (_line.IndexOf(']') != -1) { section = _line.Substring(_line.IndexOf('[') + 1, _line.IndexOf(']') - 1); if (section == INFO_SECTION) { continue; } else if (section.IndexOf('-') != -1 && section.IndexOf(',') != -1) { Pattern pattern = this.ParsePattern(section); _info.patterns.Add(pattern); } } // Info section // Note: pattern data is parsed with LoadPattern } else if (section == INFO_SECTION) { // Parse key-value pair string key, val; if (!this.ParseKeyValuePair(_line, out key, out val)) { // Skip if not a key-value pair this.Warning("Unparsed line"); continue; } // Set data based on key switch (key) { case "Version": this.CheckVersion(val); break; case "Song": _info.song = this.FindAudioFile("Song", val, true); break; case "Title": _info.title = val; break; case "TitleTranslit": _info.titleTranslit = val; break; case "Subtitle": _info.subtitle = val; break; case "SubtitleTranslit": _info.subtitleTranslit = val; break; case "Artist": _info.artist = val; break; case "ArtistTranslit": _info.artistTranslit = val; break; case "Album": _info.album = val; break; case "AlbumTranslit": _info.albumTranslit = val; break; case "Genre": _info.genre = val; break; case "Credits": _info.credits = val; break; case "Link": _info.link = val; break; case "Description": _info.description = val; break; case "Tags": _info.tags.AddRange(val.Split(',')); break; case "DisplayBpm": _info.displayBpm = this.ParseDisplayBpms(val); break; case "SampleStart": _info.sampleStart = this.ParseFloat("SampleStart", val, false); break; case "SampleLength": _info.sampleLength = this.ParseFloat("SampleLength", val, false); break; case "Cover": _info.cover = this.FindImageFile("Cover", val, false); break; case "Banner": _info.banner = this.FindImageFile("Banner", val, false); break; case "Backgrounds": _info.backgrounds = this.ParseBackgrounds(val); break; case "Lyrics": _info.lyrics = this.FindLyricsFile("Lyrics", val, false); break; default: this.Warning("Unrecognized key: " + key); break; } } else { this.Warning("Unparsed line"); } } // Cleanup reader.Close(); }
public override void LoadPattern(Pattern pattern) { // Don't unnecessarily reload if (pattern.loaded == true) { return; } // Parse line-by-line _index = 0; _line = ""; int beat = 0; List <string> measure = new List <string>(); ReadAheadStreamReader reader = new ReadAheadStreamReader(_info.path); // Skip to main section while (_index < pattern.lineIndex) { _index++; reader.SkipLine(); } // Parsing loop while (reader.PeekLine() != null) { _index++; _line = reader.ReadLine().Trim(); // Empty line if (_line.Length == 0) { continue; // Comment } else if (_line[0] == '/') { continue; // New #NOTES section } else if (_line[0] == '#') { break; // End of pattern data // End of measure } else if (_line[0] == ',' || _line[0] == ';') { this.ParseMeasure(pattern, beat, measure); measure = new List <string>(); beat += BEATS_PER_MEASURE; if (_line[0] == ';') { break; // End of pattern data, } // Pattern data } else { if (_line.Length != pattern.keyCount) { Warning("Line width does not match expected column count of " + pattern.keyCount); } else { measure.Add(_line); } } } // Add BPM change events foreach (Bpm bpm in _bpms) { Note note = new Note(); note.type = NoteType.BPM; note.eventTime = this.CalculateTime(bpm.beat); note.eventFloatVal = bpm.bpm; this.AddNote(pattern, note); } // Add Stop events foreach (Stop stop in _stops) { Note note = new Note(); note.type = NoteType.STOP; note.eventTime = this.CalculateTime(stop.beat); note.eventFloatVal = stop.beat; this.AddNote(pattern, note); } // Add background change events foreach (Bg bg in _bgs) { Note note = new Note(); note.type = NoteType.BG; note.eventTime = this.CalculateTime(bg.beat); note.eventStringVal = bg.filename; this.AddNote(pattern, note); } // Add Label events foreach (Label label in _labels) { Note note = new Note(); note.type = NoteType.LABEL; note.eventTime = this.CalculateTime(label.beat); note.eventStringVal = label.text; this.AddNote(pattern, note); } // Sort notes this.SortNotes(pattern); // Cleanup pattern.loaded = true; reader.Close(); }
public override void Load(string path) { base.Load(path); // Parse line-by-line _index = 0; _line = ""; ReadAheadStreamReader reader = new ReadAheadStreamReader(path); // Main loop while ((reader.PeekLine()) != null) { _index++; _line = reader.ReadLine().Trim(); // Empty line if (_line.Length == 0) { continue; // Comment } else if (_line[0] == '/') { continue; // Tag data } else if (_line[0] == '#') { // Parse key-value pair string key, val; if (!this.ParseKeyValuePair(_line, out key, out val)) { // Skip if not a key-value pair this.Warning("Unparsed line"); continue; } // Pattern data if (key == "#NOTES") { // Read all the notes metadata into one buffer. // We'll assume there's 5 colons before the notes data. If not, this breaks _line = ""; int colonCount = 0; while (colonCount < 5 && reader.PeekLine() != null) { _index++; _line += reader.ReadLine().Trim(); } Pattern pattern = this.ParsePattern(_line); _info.patterns.Add(pattern); // Simfile info } else { // The .sm format specifies that keys be marked as ended with ';' // Usually this is on the same line, but not always if (val.IndexOf(';') != -1) { // Remove ending ';' val = val.Substring(0, val.IndexOf(';')); } else { string nextLine; while ((nextLine = reader.PeekLine()) != null) { // Key did not properly end with a ';' if (nextLine[0] == '#') { Warning("Improperly formatted .sm file"); break; } // Valid next line, continue reading nextLine = reader.ReadLine(); _index++; _line += nextLine; // Ignore empty lines or comments nextLine = nextLine.Trim(); if (nextLine.Length == 0 || nextLine[0] == '/') { continue; } // Key ending line if (nextLine.IndexOf(';') == -1) { val += nextLine; // Key not ended yet } else { // Remove ending ';' and stop peeking val += nextLine.Substring(0, nextLine.IndexOf(';')); break; } } } // Set data based on key switch (key) { case "#VERSION": this.CheckVersion(val); break; case "#TITLE": _info.title = val; break; case "#TITLETRANSLIT": _info.titleTranslit = val; break; case "#SUBTITLE": _info.subtitle = val; break; case "#SUBTITLETRANSLIT": _info.subtitleTranslit = val; break; case "#ARTIST": _info.artist = val; break; case "#ARTISTTRANSLIT": _info.artistTranslit = val; break; case "#GENRE": _info.genre = val; break; case "#CREDIT": _info.credits = val; break; case "#BANNER": _info.banner = this.FindImageFile("Banner", val, false); break; case "#BACKGROUND": this.ParseBackground(val); break; case "#LYRICSPATH": _info.lyrics = this.FindLyricsFile("Lyrics", val, false); break; case "#CDTITLE": _info.cover = this.FindImageFile("Cover", val, false); break; case "#MUSIC": _info.song = this.FindAudioFile("Song", val, true); break; case "#OFFSET": this.ParseOffset(val); break; case "#SAMPLESTART": _info.sampleStart = this.ParseFloat("SampleStart", val, false); break; case "#SAMPLELENGTH": _info.sampleLength = this.ParseFloat("SampleLength", val, false); break; case "#DISPLAYBPM": _info.displayBpm = this.ParseDisplayBpms(val); break; case "#BPMS": this.ParseBpms(val); break; case "#BGCHANGE": this.ParseBackgrounds(val); break; case "#STOPS": this.ParseStops(val); break; case "#DELAYS": this.ParseStops(val); break; case "#LABELS": this.ParseLabels(val); break; // Ignored/unsupported // Mostly .ssc stuff that I don't understand or don't want to implement /* #SELECTABLE #LISTSORT #WARPS #TIMESIGNATURES #TICKCOUNT #COMBOS #SPEEDS #SCROLLS #FAKES #KEYSOUNDS #ATTACKS */ default: this.Warning("Unsupported key: " + key); break; } } } else { this.Warning("Unparsed line"); } } // Sort things this.SortList <Bpm>(_bpms); this.SortList <Stop>(_stops); this.SortList <Bg>(_bgs); // Cleanup reader.Close(); }