public void ExpandDrumRoll(NoteChart chart, NoteChart.Difficulty difficulty, NoteChart.Note note, int gem) { if (note.Duration >= (ulong)chart.Division.TicksPerBeat) { ulong rolllen = 0; switch (difficulty) { case NoteChart.Difficulty.Expert: rolllen = (ulong)chart.Division.TicksPerBeat / 2; // 8th note rolls break; case NoteChart.Difficulty.Hard: case NoteChart.Difficulty.Medium: rolllen = (ulong)chart.Division.TicksPerBeat; // 4th note rolls break; case NoteChart.Difficulty.Easy: rolllen = 0; // Single hit break; } if (rolllen > 0) { for (ulong pos = rolllen; pos < note.Duration; pos += rolllen) { NoteChart.Note newnote = new NoteChart.Note(note.Time + pos, (ulong)chart.Division.TicksPerBeat / 8); chart.PartDrums.Gems[difficulty][gem].Add(newnote); } } } note.Duration = (ulong)chart.Division.TicksPerBeat / 8; }
public override ChartFormat DecodeChart(FormatData data, ProgressIndicator progress) { IList <Stream> streams = GetChartStreams(data); float bpm = 0; NoteChart chart = new NoteChart(); chart.BPM.Add(new Midi.TempoEvent(0, (uint)(Mid.MicrosecondsPerMinute / bpm))); chart.Signature.Add(new Midi.TimeSignatureEvent(0, 4, 2, 24, 8)); Mub mub = null; // TODO: Determine charts by filenames or some shit chart.PartGuitar = new NoteChart.Guitar(chart); NoteChart.Instrument instrument = chart.PartGuitar; NoteChart.IGems gems = instrument as NoteChart.IGems; NoteChart.IForcedHopo hopo = instrument as NoteChart.IForcedHopo; NoteChart.Difficulty difficulty = NoteChart.Difficulty.Expert; int fadeposition = 0; foreach (Mub.Node node in mub.Nodes) { ulong time = (ulong)(node.Time * chart.Division.TicksPerBeat / 4); ulong duration = (ulong)(node.Duration * chart.Division.TicksPerBeat / 4); NoteChart.Note fullnote = new NoteChart.Note(time, duration); NoteChart.Note note = new NoteChart.Note(time, chart.Division.TicksPerBeat / 4U); NoteChart.Note prevnote = new NoteChart.Note(time - chart.Division.TicksPerBeat / 2U, chart.Division.TicksPerBeat / 4U); int greennote = fadeposition < 0 ? 0 : 1; int bluenote = fadeposition > 0 ? 4 : 3; switch (node.Type) { case 0x00: // Green dot gems.Gems[difficulty][greennote].Add(note); hopo.ForceHammeron[difficulty].Add(note); break; case 0x01: // Blue dot gems.Gems[difficulty][bluenote].Add(note); hopo.ForceHammeron[difficulty].Add(note); break; case 0x02: // Red dot gems.Gems[difficulty][2].Add(note); hopo.ForceHammeron[difficulty].Add(note); break; case 0x09: // Blue Crossfade right fadeposition = 1; gems.Gems[difficulty][4].Add(note); gems.Gems[difficulty][fadeposition < 0 ? 0 : 3].Add(prevnote); hopo.ForceHammeron[difficulty].Add(note); break; case 0x0A: // Green Crossfade left (revert to rightish normal) fadeposition = 0; break; case 0x0B: // Green Crossfade left fadeposition = -1; gems.Gems[difficulty][0].Add(note); gems.Gems[difficulty][fadeposition > 0 ? 4 : 1].Add(prevnote); hopo.ForceHammeron[difficulty].Add(note); break; case 0x0C: // Weird whammy thing on left green gems.Gems[difficulty][greennote].Add(fullnote); hopo.ForceHammeron[difficulty].Add(note); break; case 0x0D: // ?? Not sure, Weird whammy thing on right blue maybe gems.Gems[difficulty][bluenote].Add(fullnote); hopo.ForceHammeron[difficulty].Add(note); break; default: break; } } return(new ChartFormat(chart)); }
public override ChartFormat DecodeChart(FormatData data, ProgressIndicator progress) { if (!data.HasStream(this, ChartName) || !data.HasStream(this, SectionsName)) { throw new FormatException(); } progress.NewTask(6 + 8); Stream chartstream = data.GetStream(this, ChartName); Stream sectionstream = data.GetStream(this, SectionsName); PakFormat format = NeversoftMetadata.GetSongItemType(data.Song); SongData song = NeversoftMetadata.GetSongData(data.PlatformData, NeversoftMetadata.GetSongItem(data)); Pak chartpak = new Pak(new EndianReader(chartstream, Endianness.BigEndian)); // TODO: Endianness based on format? FileNode chartfile = chartpak.Root.Find(song.ID + ".mid.qb.ngc", SearchOption.AllDirectories, true) as FileNode; QbFile qbsections = new QbFile(sectionstream, format); QbFile qbchart = new QbFile(chartfile.Data, format); NoteChart chart = new NoteChart(); chart.PartGuitar = new NoteChart.Guitar(chart); chart.PartBass = new NoteChart.Bass(chart); chart.Events = new NoteChart.EventsTrack(chart); chart.Venue = new NoteChart.VenueTrack(chart); chart.Beat = new NoteChart.BeatTrack(chart); progress.Progress(); DecodeChartFretbars(song, qbchart, chart); progress.Progress(); DecodeChartMarkers(song, qbsections, qbchart, chart); progress.Progress(); for (NoteChart.TrackType track = NoteChart.TrackType.Guitar; track <= NoteChart.TrackType.Bass; track++) { for (NoteChart.Difficulty difficulty = NoteChart.Difficulty.Easy; difficulty <= NoteChart.Difficulty.Expert; difficulty++) { DecodeChartNotes(data, song, qbchart, chart, track, difficulty, data.Song.Data.GetValue <bool>("GH3ChartCoop")); progress.Progress(); } } progress.Progress(); DecodeChartDrums(song, qbchart, chart); progress.Progress(); DecodeChartVenue(song, qbchart, chart); ImportMap.ImportChart(data.Song, chart); progress.Progress(); data.CloseStream(chartstream); data.CloseStream(sectionstream); progress.EndTask(); return(new ChartFormat(chart)); }
private static void DecodeChartNotes(FormatData data, SongData song, QbFile qbchart, NoteChart chart, NoteChart.TrackType track, NoteChart.Difficulty difficulty, bool coop) { string basetrack = string.Empty; string basetrackstar = string.Empty; string basetrackstarbattle = string.Empty; string basetrackfaceoff = string.Empty; NoteChart.Instrument instrument = null; switch (track) { case NoteChart.TrackType.Guitar: basetrack = song.ID + (coop ? "_song_guitarcoop_" : "_song_") + difficulty.DifficultyToString(); basetrackstar = song.ID + (coop ? "_guitarcoop_" : "_") + difficulty.DifficultyToString() + "_Star"; basetrackstarbattle = song.ID + (coop ? "_guitarcoop_" : "_") + difficulty.DifficultyToString() + "_StarBattleMode"; basetrackfaceoff = song.ID + "_FaceOffp"; instrument = chart.PartGuitar; break; case NoteChart.TrackType.Bass: basetrack = song.ID + (coop ? "_song_rhythmcoop_" : "_song_rhythm_") + difficulty.DifficultyToString(); basetrackstar = song.ID + (coop ? "_rhythmcoop_" : "_rhythm_") + difficulty.DifficultyToString() + "_Star"; basetrackstarbattle = song.ID + (coop ? "_rhythmcoop_" : "_rhythm_") + difficulty.DifficultyToString() + "_StarBattleMode"; basetrackfaceoff = song.ID + "_FaceOffP"; instrument = chart.PartBass; break; } if (instrument == null) { return; } if (difficulty == NoteChart.Difficulty.Expert) // GH3 has SP for each difficulty; RB2 has one OD for all { QbItemArray faceoff1 = (qbchart.FindItem(QbKey.Create(basetrackfaceoff + "1"), false) as QbItemArray).Items[0] as QbItemArray; if (faceoff1 != null) { foreach (QbItemInteger faceoff in faceoff1.Items) { NoteChart.Note fnote = new NoteChart.Note(chart.GetTicks(faceoff.Values[0]), chart.GetTicksDuration(faceoff.Values[0], faceoff.Values[1])); instrument.Player1.Add(fnote); } } QbItemArray faceoff2 = (qbchart.FindItem(QbKey.Create(basetrackfaceoff + "2"), false) as QbItemArray).Items[0] as QbItemArray; if (faceoff2 != null) { foreach (QbItemInteger faceoff in faceoff2.Items) { NoteChart.Note fnote = new NoteChart.Note(chart.GetTicks(faceoff.Values[0]), chart.GetTicksDuration(faceoff.Values[0], faceoff.Values[1])); instrument.Player2.Add(fnote); } } QbItemArray starpower = (qbchart.FindItem(QbKey.Create(basetrackstar), false) as QbItemArray).Items[0] as QbItemArray; if (starpower != null) { foreach (QbItemInteger star in starpower.Items) { instrument.Overdrive.Add(new NoteChart.Note(chart.GetTicks(star.Values[0]), chart.GetTicksDuration(star.Values[0], star.Values[1]))); } } if (instrument.Overdrive.Count == 0) { starpower = (qbchart.FindItem(QbKey.Create(basetrackstarbattle), false) as QbItemArray).Items[0] as QbItemArray; if (starpower != null) { foreach (QbItemInteger star in starpower.Items) { instrument.Overdrive.Add(new NoteChart.Note(chart.GetTicks(star.Values[0]), chart.GetTicksDuration(star.Values[0], star.Values[1]))); } } } } int previouschordnum = 0; int previouschord = 0; NoteChart.Note previousnote = new NoteChart.Note() { Time = uint.MaxValue, Duration = 0 }; QbItemInteger notes = (qbchart.FindItem(QbKey.Create(basetrack), false) as QbItemArray).Items[0] as QbItemInteger; if (notes == null) { if (track == NoteChart.TrackType.Guitar) { chart.PartGuitar = null; } else { chart.PartBass = null; } return; } int note32 = chart.Division.TicksPerBeat / 8; int note16 = chart.Division.TicksPerBeat / 4; for (int k = 0; k < notes.Values.Length; k += 3) { NoteChart.Note note = new NoteChart.Note(chart.GetTicks(notes.Values[k]), chart.GetTicksDuration(notes.Values[k], notes.Values[k + 1])); int chordnum = 0; int chord = 0; // Cut off sustains to a 32nd note before the next previousnote.Duration = (ulong)Math.Max(Math.Min((long)previousnote.Duration, (long)note.Time - (long)previousnote.Time - note16), note32); bool hopo = note.Time - previousnote.Time <= (ulong)data.Song.HopoThreshold; bool ishopo = hopo; hopo = hopo && previouschordnum == 1; uint fret = notes.Values[k + 2]; for (int l = 0; l < 6; l++) { if ((fret & 0x01) != 0) { if (l < 5) { chord = l; chordnum++; (instrument as NoteChart.IGems).Gems[difficulty][l].Add(note); } else // l == 5; hopo toggle bit { ishopo = !ishopo; } } fret >>= 1; } if (chordnum == 0) // Old TheGHOST bug, should be a green note { chordnum = 1; chord = 0; (instrument as NoteChart.IGems).Gems[difficulty][0].Add(note); } if (chord == previouschord) { ishopo = false; } if (ishopo != hopo && chordnum == 1) { if (ishopo) { (instrument as NoteChart.IForcedHopo).ForceHammeron[difficulty].Add(note); } else { (instrument as NoteChart.IForcedHopo).ForceStrum[difficulty].Add(note); } } previouschord = chord; previousnote = note; previouschordnum = chordnum; } }
public ChartFormat DecodeChart(FormatData data, ProgressIndicator progress, params Stream[] chartstreams) { progress.NewTask(5 + 12); PakFormat format = NeversoftMetadata.GetSongItemType(data.Song); SongData song = NeversoftMetadata.GetSongData(data.PlatformData, NeversoftMetadata.GetSongItem(data)); List <Pak> chartpaks = new List <Pak>(); foreach (Stream stream in chartstreams) { chartpaks.Add(new Pak(new EndianReader(stream, Endianness.BigEndian))); // TODO: Endianness based on format? } FileNode chartfile = null; foreach (Pak pak in chartpaks) { chartfile = pak.FindFile(song.ID + ".mid.qb.ngc") ?? chartfile; chartfile = pak.FindFile(song.ID + ".mid.qb") ?? chartfile; } if (chartfile == null) { foreach (Pak pak in chartpaks) { chartfile = chartfile ?? pak.FindFileType(0xa7f505c4); } } QbFile qbchart = null; if (chartfile != null) { qbchart = new QbFile(chartfile.Data, format); } StringList strings = new StringList(); foreach (Pak pak in chartpaks) { foreach (Pak.Node n in pak.Nodes) { if (!n.Filename.HasValue()) { strings.ParseFromStream(n.Data); } } } QbFile qbsections = null; FileNode qbsectionfile = null; foreach (Pak pak in chartpaks) { qbsectionfile = pak.FindFile(song.ID + ".mid_text.qb.ngc") as FileNode ?? qbsectionfile; qbsectionfile = pak.FindFile(song.ID + ".mid_text.qb") as FileNode ?? qbsectionfile; } if (qbsectionfile != null) { qbsections = new QbFile(qbsectionfile.Data, format); } Notes notes = null; FileNode notesfile = null; foreach (Pak pak in chartpaks) { notesfile = notesfile ?? pak.FindFileType(0xa9d5bc8f); notesfile = pak.FindFile(song.ID + ".note.ngc") as FileNode ?? notesfile; notesfile = pak.FindFile(song.ID + ".note") as FileNode ?? notesfile; } if (notesfile == null) { foreach (Pak pak in chartpaks) { notesfile = pak.FindFileType(0xa9d5bc8f) ?? notesfile; } } if (notesfile != null) { notesfile.Data.Position = 0; notes = Notes.Create(new EndianReader(notesfile.Data, Endianness.BigEndian)); } NoteChart chart = new NoteChart(); chart.PartGuitar = new NoteChart.Guitar(chart); chart.PartBass = new NoteChart.Bass(chart); chart.PartDrums = new NoteChart.Drums(chart); chart.PartVocals = new NoteChart.Vocals(chart); chart.Events = new NoteChart.EventsTrack(chart); chart.Venue = new NoteChart.VenueTrack(chart); chart.Beat = new NoteChart.BeatTrack(chart); bool gh4v2 = NeversoftMetadata.IsGuitarHero4(data.PlatformData.Game) && data.PlatformData.Game != Game.GuitarHeroWorldTour; string drumconfig = gh4v2 ? "drums3" : "drums2"; chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Easy, drumconfig + "easy"))); chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Medium, drumconfig))); chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Hard, drumconfig))); chart.PartDrums.Mixing.Add(new Pair <NoteChart.Point, Pair <NoteChart.Difficulty, string> >(new NoteChart.Point(0), new Pair <NoteChart.Difficulty, string>(NoteChart.Difficulty.Expert, drumconfig))); progress.Progress(); DecodeChartFretbars(song, qbchart, notes, chart); progress.Progress(); DecodeChartSections(song, qbchart, strings, qbsections, notes, chart); progress.Progress(); for (NoteChart.TrackType track = NoteChart.TrackType.Guitar; track <= NoteChart.TrackType.Drums;) { for (NoteChart.Difficulty difficulty = NoteChart.Difficulty.Easy; difficulty <= NoteChart.Difficulty.Expert; difficulty++) { DecodeChartNotes(song, qbchart, notes, chart, track, difficulty); progress.Progress(); } switch (track) { case NoteChart.TrackType.Guitar: track = NoteChart.TrackType.Bass; break; case NoteChart.TrackType.Bass: track = NoteChart.TrackType.Drums; break; case NoteChart.TrackType.Drums: track = NoteChart.TrackType.Events; break; } } // Automatic Drum Fills - 1-measure fills every 4 measures, if there's no overdrive overlap FillSections(chart, 1, 4, 3, chart.PartDrums.DrumFills, chart.PartDrums.Overdrive); progress.Progress(); if (DecodeChartVocals(song, qbchart, strings, notes, chart)) { DecodeChartVocalPhrases(song, qbchart, notes, chart); } ImportMap.ImportChart(data.Song, chart); progress.Progress(); progress.EndTask(); return(new ChartFormat(chart)); }
private void DecodeChartNotes(SongData song, QbFile qbchart, Notes notes, NoteChart chart, NoteChart.TrackType track, NoteChart.Difficulty difficulty) { bool expertplus = song.Data.GetValue <bool>("GH5ChartExpertPlus"); uint[] values; uint[][] jaggedvalues; QbKey basetrack = null; QbKey basetrackstar = null; QbKey basetrackfaceoff1 = null; QbKey basetrackfaceoff2 = null; QbKey basetracktapping = null; NoteChart.Instrument instrument = null; switch (track) { case NoteChart.TrackType.Guitar: instrument = chart.PartGuitar; if (notes != null) { basetrack = QbKey.Create("guitar" + difficulty.DifficultyToString().ToLower() + "instrument"); basetracktapping = QbKey.Create("guitar" + difficulty.DifficultyToString().ToLower() + "tapping"); basetrackstar = QbKey.Create("guitar" + difficulty.DifficultyToString().ToLower() + "starpower"); } else { basetrack = QbKey.Create(song.ID + "_song_" + difficulty.DifficultyToString().ToLower()); basetrackstar = QbKey.Create(song.ID + "_" + difficulty.DifficultyToString().ToLower() + "_star"); basetrackfaceoff1 = QbKey.Create(song.ID + "_faceoffp1"); basetrackfaceoff2 = QbKey.Create(song.ID + "_faceoffp2"); basetracktapping = QbKey.Create(song.ID + "_" + difficulty.DifficultyToString().ToLower() + "_tapping"); } break; case NoteChart.TrackType.Bass: instrument = chart.PartBass; if (notes != null) { basetrack = QbKey.Create("bass" + difficulty.DifficultyToString().ToLower() + "instrument"); basetracktapping = QbKey.Create("bass" + difficulty.DifficultyToString().ToLower() + "tapping"); basetrackstar = QbKey.Create("bass" + difficulty.DifficultyToString().ToLower() + "starpower"); } else { basetrack = QbKey.Create(song.ID + "_song_rhythm_" + difficulty.DifficultyToString().ToLower()); basetrackstar = QbKey.Create(song.ID + "_rhythm_" + difficulty.DifficultyToString().ToLower() + "_star"); basetrackfaceoff1 = QbKey.Create(song.ID + "_rhythm_faceoffp1"); basetrackfaceoff2 = QbKey.Create(song.ID + "_rhythm_faceoffp2"); // basetracktapping = song.ID + "_rhythm_" + difficulty.DifficultyToString().ToLower() + "_tapping"; } break; case NoteChart.TrackType.Drums: instrument = chart.PartDrums; if (notes != null) { basetrack = QbKey.Create("drums" + difficulty.DifficultyToString().ToLower() + "instrument"); basetrackstar = QbKey.Create("drums" + difficulty.DifficultyToString().ToLower() + "starpower"); } else { basetrack = QbKey.Create(song.ID + "_song_drum_" + difficulty.DifficultyToString().ToLower()); basetrackstar = QbKey.Create(song.ID + "_drum_" + difficulty.DifficultyToString().ToLower() + "_star"); basetrackfaceoff1 = QbKey.Create(song.ID + "_drum_faceoffp1"); basetrackfaceoff2 = QbKey.Create(song.ID + "_drum_faceoffp2"); // basetracktapping = song.ID + "_drum_" + difficulty.DifficultyToString().ToLower() + "_tapping"; } break; } if (difficulty == NoteChart.Difficulty.Expert) // GH has SP for each difficulty; RB2 has one OD for all { jaggedvalues = GetJaggedChartValues(notes, qbchart, basetrackstar, basetrackstar, 4, 2); foreach (uint[] star in jaggedvalues) { instrument.Overdrive.Add(new NoteChart.Note(chart.GetTicks(star[0]), chart.GetTicksDuration(star[0], star[1]))); } if (notes == null) { jaggedvalues = GetJaggedChartValues(notes, qbchart, basetrackfaceoff1, basetrackfaceoff1, 1); foreach (uint[] faceoff in jaggedvalues) { instrument.Player1.Add(new NoteChart.Note(chart.GetTicks(faceoff[0]), chart.GetTicksDuration(faceoff[0], faceoff[1]))); } jaggedvalues = GetJaggedChartValues(notes, qbchart, basetrackfaceoff2, basetrackfaceoff2, 2); foreach (uint[] faceoff in jaggedvalues) { instrument.Player2.Add(new NoteChart.Note(chart.GetTicks(faceoff[0]), chart.GetTicksDuration(faceoff[0], faceoff[1]))); } } } if (basetracktapping != null) { jaggedvalues = GetJaggedChartValues(notes, qbchart, basetracktapping, basetracktapping, 4, 4); foreach (uint[] tap in jaggedvalues) { if (instrument is NoteChart.IForcedHopo) { (instrument as NoteChart.IForcedHopo).ForceHammeron[difficulty].Add(new NoteChart.Note(chart.GetTicks(tap[0]), chart.GetTicksDuration(tap[0], tap[1]))); } } } int previouschordnum = 0; int previouschord = 0; NoteChart.Note previousnote = new NoteChart.Note(uint.MaxValue); int note32 = chart.Division.TicksPerBeat / 8; int note16 = chart.Division.TicksPerBeat / 4; values = GetChartValues(notes, qbchart, basetrack, basetrack, 4, 4); for (int k = 0; k < values.Length; k += 2) { uint fret = values[k + 1]; uint length = 0; if (notes != null) { length = fret >> 16; fret = fret & 0x0000FFFF; } else { length = fret & 0x0000FFFF; fret >>= 16; } if (notes != null) { fret = ((fret & 0xFF00) >> 8) | ((fret & 0x00FF) << 8); } NoteChart.Note note = new NoteChart.Note(chart.GetTicks(values[k]), chart.GetTicksDuration(values[k], length)); int chordnum = 0; int chord = 0; // Cut off sustains to a 32nd note before the next previousnote.Duration = (ulong)Math.Max(Math.Min((long)previousnote.Duration, (long)note.Time - (long)previousnote.Time - note16), note32); uint numfrets = 5; if (track == NoteChart.TrackType.Drums) { numfrets += 2; } int[] transform; if (notes == null) { transform = new int[] { 4, 1, 2, 3, 3, 0, -1 } } ; else { //transform = new int[] { 4, 1, 2, 3, -1, 0, 4 }; // -1 -> 4? transform = new int[] { 4, 1, 2, 3, 3, 0, 4 } }; // TODO: Verify charts for (int l = 0; l < numfrets; l++) { if (((fret >> l) & 0x01) != 0) { chordnum++; chord = l; if (track == NoteChart.TrackType.Drums) { chord = transform[l]; //if ((fret & 0x2000) != 0) // continue; //if (chord == 0 && ((fret & 0x2000) == 0) && !expertplus) // TODO: Verify expert+ // continue; } if (chord >= 0) { (instrument as NoteChart.IGems).Gems[difficulty][chord].Add(note); if (instrument is NoteChart.Drums) { ExpandDrumRoll(chart, difficulty, note, chord); } } } } if (chordnum == 0) // Bass open note, actually fret bit 6 { chordnum++; if (!(instrument is NoteChart.Drums)) { (instrument as NoteChart.IGems).Gems[difficulty][0].Add(note); } if (instrument is NoteChart.IForcedHopo) { (instrument as NoteChart.IForcedHopo).ForceHammeron[difficulty].Add(note); // Bass open notes become hopos, lulz } } else if (chordnum == 1 && chord != previouschord) { if (instrument is NoteChart.IForcedHopo) { if ((fret & 0x0040) != 0) { (instrument as NoteChart.IForcedHopo).ForceHammeron[difficulty].Add(note); } else { (instrument as NoteChart.IForcedHopo).ForceStrum[difficulty].Add(note); } } } previouschord = chord; previousnote = note; previouschordnum = chordnum; } }