Ejemplo n.º 1
0
        public void QbKeyNormalizeTest3()
        {
            // Forward slash is replaced with backslash
            var s = "a/b";

            Assert.AreEqual("a\\b", QbKey.Normalize(s));
        }
Ejemplo n.º 2
0
        public DatWad(EndianReader dat, Stream wad) : this()
        {
            Nodes.Clear();
            Wad = wad;

            uint num = dat.ReadUInt32();  // Number of nodes

            dat.ReadUInt32();             // Header size
            for (int i = 0; i < num; i++)
            {
                QbKey item = QbKey.Create(dat.ReadUInt32());
                Node  node = new Node()
                {
                    Key      = item,
                    Offset   = dat.ReadUInt32(),
                    Size     = dat.ReadUInt32(),
                    Reserved = dat.ReadBytes(8)
                };
                node.Data = new Substream(Wad, node.Offset, node.Size);
                Nodes.Add(node);
            }

            foreach (Node node in Nodes)
            {
                Wad.Seek((long)(node.Offset + 0x1A), SeekOrigin.Begin);
                node.Filename = Util.ReadCString(Wad, 30);
            }
        }
Ejemplo n.º 3
0
        private static void DecodeChartFretbars(SongData song, QbFile qbchart, NoteChart chart)
        {
            QbItemInteger fretbars          = (qbchart.FindItem(QbKey.Create(song.ID + "_fretbars"), false) as QbItemArray).Items[0] as QbItemInteger;
            ulong         ticks             = 0;
            uint          previousfret      = 0;
            uint          previousMsPerBeat = 0;

            for (int k = 1; k < fretbars.Values.Length; k++)
            {
                uint fret      = fretbars.Values[k];
                uint msPerBeat = fret - previousfret;
                if (msPerBeat != previousMsPerBeat)
                {
                    chart.BPM.Add(new Midi.TempoEvent(ticks, msPerBeat * 1000));
                }

                previousfret      = fret;
                previousMsPerBeat = msPerBeat;
                ticks            += chart.Division.TicksPerBeat;
            }

            chart.Events.End = new NoteChart.Point(chart.GetTicks(fretbars.Values[fretbars.Values.Length - 1]));

            QbItemArray timesig = (qbchart.FindItem(QbKey.Create(song.ID + "_timesig"), false) as QbItemArray).Items[0] as QbItemArray;

            foreach (QbItemInteger sig in timesig.Items)
            {
                chart.Signature.Add(new Midi.TimeSignatureEvent(chart.GetTicks(sig.Values[0]), (byte)sig.Values[1], (byte)Math.Log(sig.Values[2], 2), 24, 8));
            }
        }
Ejemplo n.º 4
0
        public void QbKeyNormalizeTest1()
        {
            // Lowercase string with no / is unchanged
            var n = (int)TestContext.CurrentContext.Random.NextUInt(40);
            var s = TestContext.CurrentContext.Random.GetString(n, "abcdefghijklmnopqrstuvwxyz");

            Assert.AreEqual(s, QbKey.Normalize(s));
        }
Ejemplo n.º 5
0
        public void QbKeyNormalizeTest2()
        {
            // Uppercase string with no / is made lowercase
            var n = (int)TestContext.CurrentContext.Random.NextUInt(40);
            var s = TestContext.CurrentContext.Random.GetString(n, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");

            Assert.AreEqual(s.ToLowerInvariant(), QbKey.Normalize(s));
        }
Ejemplo n.º 6
0
        public void QbKeyUIntTest()
        {
            var  random = TestContext.CurrentContext.Random;
            uint x      = random.NextUInt();
            var  qbKey  = new QbKey(x);

            Assert.AreEqual(x, qbKey.Checksum);
        }
Ejemplo n.º 7
0
        public void QbKeyStringTestNoNormalize()
        {
            string s      = TestContext.CurrentContext.Random.GetString();
            var    latin1 = Encoding.GetEncoding("iso-8859-1");
            var    qbKey  = new QbKey(s, false);
            var    crc    = new CRC32().ComputeHash(latin1.GetBytes(s));

            Assert.AreEqual(~BitConverter.ToUInt32(crc, 0), qbKey.Checksum);
        }
Ejemplo n.º 8
0
        private static void DecodeChartVenue(SongData song, QbFile qbchart, NoteChart chart)
        {
            QbItemArray cameraitems = qbchart.FindItem(QbKey.Create(song.ID + "_cameras_notes"), false) as QbItemArray;

            if (cameraitems != null && cameraitems.Items.Count > 0)
            {
                cameraitems = cameraitems.Items[0] as QbItemArray;
            }
            if (cameraitems != null)
            {
                Random random = new Random();
                foreach (QbItemInteger camera in cameraitems.Items)
                {
                    uint            time  = camera.Values[0];
                    NoteChart.Point point = new NoteChart.Point(chart.GetTicks(camera.Values[0]));

                    if (random.Next() % 9 == 0)
                    {
                        chart.Venue.DirectedShots.Add(new Pair <NoteChart.Point, NoteChart.VenueTrack.DirectedCut>(point, NoteChart.VenueTrack.DirectedCut.None));
                    }
                    else
                    {
                        chart.Venue.CameraShots.Add(new Pair <NoteChart.Point, NoteChart.VenueTrack.CameraShot>(point, new NoteChart.VenueTrack.CameraShot()));
                    }
                }
            }

            QbItemArray crowditems = qbchart.FindItem(QbKey.Create(song.ID + "_crowd_notes"), false) as QbItemArray;

            if (crowditems != null && crowditems.Items.Count > 0)
            {
                crowditems = crowditems.Items[0] as QbItemArray;
            }
            if (crowditems != null)
            {
                foreach (QbItemInteger crowd in crowditems.Items)
                {
                    NoteChart.Point point = new NoteChart.Point(chart.GetTicks(crowd.Values[0]));
                    chart.Events.Crowd.Add(new Pair <NoteChart.Point, NoteChart.EventsTrack.CrowdType>(point, NoteChart.EventsTrack.CrowdType.None));
                }
            }

            QbItemArray lightitems = qbchart.FindItem(QbKey.Create(song.ID + "_lightshow_notes"), false) as QbItemArray;

            if (lightitems != null && lightitems.Items.Count > 0)
            {
                lightitems = lightitems.Items[0] as QbItemArray;
            }
            if (lightitems != null)
            {
                foreach (QbItemInteger light in lightitems.Items)
                {
                    NoteChart.Point point = new NoteChart.Point(chart.GetTicks(light.Values[0]));
                    chart.Venue.Lighting.Add(new Pair <NoteChart.Point, NoteChart.VenueTrack.LightingType>(point, NoteChart.VenueTrack.LightingType.None));
                }
            }
        }
Ejemplo n.º 9
0
 public Entry Find(QbKey key)
 {
     foreach (Entry entry in Entries)
     {
         if (entry.Identifier == key)
         {
             return(entry);
         }
     }
     return(null);
 }
Ejemplo n.º 10
0
        public static QbItemBase GetQbItem(QbItemStruct item, uint[] keys)
        {
            foreach (uint key in keys)
            {
                QbItemBase subitem = item.FindItem(QbKey.Create(key), false);
                if (subitem != null)
                {
                    return(subitem);
                }
            }

            return(null);
        }
Ejemplo n.º 11
0
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            data.Game = Platform.DetermineGame(data);

            FileNode qbpak = dir.Navigate("pak/qb.pak.ngc") as FileNode;

            if (qbpak == null)
            {
                Exceptions.Error("Couldn't find qb.pak.ngc on Guitar Hero 3 Wii disc.");
            }

            try {
                Pak          qb           = new Pak(new EndianReader(qbpak.Data, Endianness.BigEndian));
                FileNode     songlistfile = qb.Root.Find("songlist.qb.ngc", SearchOption.AllDirectories) as FileNode;
                FileNode     albumfile    = dir.Navigate("pak/album_covers/album_covers.pak.ngc", false, true) as FileNode;
                QbFile       songlist     = new QbFile(songlistfile.Data, PakFormat);
                QbItemStruct list         = songlist.FindItem(QbKey.Create(NeversoftMetadata.SonglistKeys[0]), true) as QbItemStruct;

                data.Session["rootdir"] = dir;
                data.Session["rootqb"]  = qb;

                if (albumfile != null)
                {
                    data.Session["albumpak"] = new Pak(new EndianReader(albumfile.Data, Endianness.BigEndian));
                }

                var items = list.Items;
                progress.NewTask(items.Count);
                foreach (QbItemStruct item in items)
                {
                    SongData song = NeversoftMetadata.GetSongData(data, item);

                    try {
                        AddSong(data, song, progress);
                    } catch (Exception exception) {
                        Exceptions.Warning(exception, "Unable to properly parse " + song.Name);
                    }

                    progress.Progress();
                }
                progress.EndTask();
            } catch (Exception exception) {
                Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero 3 Wii disc.");
            }

            return(data);
        }
Ejemplo n.º 12
0
        protected uint[][] GetJaggedChartValues(Notes notes, QbFile qbchart, QbKey notekey, QbKey qbkey, params int[] split)
        {
            Notes.Entry   entry;
            List <uint[]> nums = new List <uint[]>();

            if (notes == null)
            {
                QbItemArray data = qbchart.FindItem(qbkey, false) as QbItemArray;
                while (data.Items[0] is QbItemArray)
                {
                    data = data.Items[0] as QbItemArray;
                }
                foreach (QbItemBase num in data.Items)
                {
                    if (num is QbItemInteger)
                    {
                        nums.Add((num as QbItemInteger).Values);
                    }
                    else if (num is QbItemFloat)
                    {
                        nums.Add((num as QbItemFloat).Values.Cast <uint>().ToArray());
                    }
                }
            }
            else
            {
                entry = notes.Find(notekey);

                if (split.Length == 0)
                {
                    split = new int[] { 4 }
                }
                ;

                for (int i = 0; i < entry.Data.Length; i++)
                {
                    uint[] num = new uint[split.Length];
                    int    pos = 0;
                    for (int k = 0; k < split.Length; k++)
                    {
                        byte[] data = new byte[4];
                        Array.Copy(entry.Data[i], pos, data, 4 - split[k], split[k]);
                        num[k] = BigEndianConverter.ToUInt32(data);
                        pos   += split[k];
                    }
                    nums.Add(num);
                }
            }

            return(nums.ToArray());
        }
Ejemplo n.º 13
0
        protected void AddQbKeyToUserDebugFile(QbKey qbKey)
        {
            string qbKeyText = string.Empty;

            if (qbKey == null)
            {
                return;
            }

            if ((qbKeyText = _qbItemBase.Root.PakFormat.AddNonDebugQbKey(qbKey, _qbItemBase.Root.Filename, _qbItemBase.Root)).Length != 0)
            {
                this.ShowError("QB Key Error", string.Format("QB Key '{0}' has the same crc as item '{1}' from the debug file.{2}{2}The QbKey text '{0}' will not be saved to the User Debug file.", qbKey.Text, qbKeyText, Environment.NewLine));
            }
        }
Ejemplo n.º 14
0
        private static void DecodeChartMarkers(SongData song, QbFile qbsections, QbFile qbchart, NoteChart chart)
        {
            QbItemStructArray markers = (qbchart.FindItem(QbKey.Create(song.ID + "_markers"), false) as QbItemArray).Items[0] as QbItemStructArray;

            if (markers != null)
            {
                foreach (QbItemStruct mark in markers.Items)
                {
                    QbItemString section = qbsections.FindItem((mark.Items[1] as QbItemQbKey).Values[0], false) as QbItemString;

                    chart.Events.Sections.Add(new Pair <NoteChart.Point, string>(new NoteChart.Point(chart.GetTicks((mark.Items[0] as QbItemInteger).Values[0])), section.Strings[0]));
                }
            }
        }
Ejemplo n.º 15
0
        private void DecodeChartVocalPhrases(SongData song, QbFile qbchart, Notes notes, NoteChart chart)
        {
            uint[]         values     = GetChartValues(notes, qbchart, QbKey.Create(0x032292A7), QbKey.Create(song.ID + "_vocals_phrases"), 4, 1);
            NoteChart.Note lastvnote  = null;
            bool           altvphrase = false;
            int            odcounter  = 1;
            ulong          lastvtime  = 0;

            for (int k = 0; k < values.Length; k += 2)
            {
                if (lastvnote != null)
                {
                    lastvnote.Duration = chart.GetTicksDuration(lastvtime, values[k] - lastvtime) - 1;
                }

                lastvtime = values[k];
                lastvnote = new NoteChart.Note(chart.GetTicks(lastvtime));

                odcounter++;
                odcounter %= 4;
                if (odcounter == 0)
                {
                    chart.PartVocals.Overdrive.Add(lastvnote);
                }

                if (altvphrase)
                {
                    chart.PartVocals.Player2.Add(lastvnote);
                }
                else
                {
                    chart.PartVocals.Player1.Add(lastvnote);
                }
                altvphrase = !altvphrase;
            }
            if (lastvnote != null)
            {
                lastvnote.Duration = chart.FindLastNote() - lastvnote.Time;
            }

            uint[][] jaggedvalues = GetJaggedChartValues(notes, qbchart, QbKey.Create("vocalstarpower"), QbKey.Create("vocalstarpower"), 4, 2);
            if (jaggedvalues != null)
            {
                foreach (uint[] star in jaggedvalues)
                {
                    chart.PartVocals.Overdrive.Add(new NoteChart.Note(chart.GetTicks(star[0]), chart.GetTicksDuration(star[0], star[1])));
                }
            }
        }
Ejemplo n.º 16
0
        private static void DecodeChartDrums(SongData song, QbFile qbchart, NoteChart chart)
        {
            QbItemArray drumsitems = qbchart.FindItem(QbKey.Create(song.ID + "_drums_notes"), false) as QbItemArray;

            if (drumsitems != null)
            {
                drumsitems = drumsitems.Items[0] as QbItemArray;
            }
            if (drumsitems != null)
            {
                chart.PartDrums = new NoteChart.Drums(chart);
                Dictionary <uint, int> drumnotes = new Dictionary <uint, int>()                 // Garbage: 65, 70, 48, 64
                {
                    { 60, 0 },
                    { 40, 1 }, { 64, 1 },
                    { 55, 2 }, { 67, 2 }, { 53, 2 },
                    { 39, 3 }, { 38, 3 }, { 63, 3 }, { 62, 3 },
                    { 68, 4 }, { 56, 4 }, { 66, 4 }, { 54, 4 }, { 69, 4 }, { 57, 4 }, { 37, 4 }, { 61, 4 },
                };
                Dictionary <uint, NoteChart.Drums.Animation> drumanimnotes = new Dictionary <uint, NoteChart.Drums.Animation>()
                {
                };

                foreach (QbItemInteger drums in drumsitems.Items)
                {
                    NoteChart.Note note    = new NoteChart.Note(chart.GetTicks(drums.Values[0]), (ulong)chart.Division.TicksPerBeat / 8);
                    uint           notenum = drums.Values[1];
                    if (drumnotes.ContainsKey(notenum))
                    {
                        int notevalue = drumnotes[notenum];
                        chart.PartDrums.Gems[NoteChart.Difficulty.Expert][notevalue].Add(note);
                    }
                    if (drumanimnotes.ContainsKey(notenum))
                    {
                        chart.PartDrums.Animations.Add(new Pair <NoteChart.Note, NoteChart.Drums.Animation>(note, drumanimnotes[notenum]));
                    }
                }
            }

            ChartFormatGH5.FillSections(chart, 1, 8, 1, chart.PartDrums.Overdrive, null);
            ChartFormatGH5.FillSections(chart, 1, 4, 3, chart.PartDrums.DrumFills, null);
        }
Ejemplo n.º 17
0
        public string FindItem(QbKey key)
        {
            foreach (KeyValuePair <QbKey, string> k in Items)
            {
                if (key.Crc == k.Key.Crc)
                {
                    string value = k.Value;
                    if (StripPrefix)
                    {
                        while (value.StartsWith(@"\L") || value.StartsWith(", "))
                        {
                            value = value.Substring(2);
                        }
                    }
                    return(value);
                }
            }

            return(null);
        }
Ejemplo n.º 18
0
        public static QbItemStruct GetSongItem(FormatData formatdata)
        {
            SongData song       = formatdata.Song;
            Stream   datastream = formatdata.GetStream(Instance, "neversoftdata");

            if (datastream == null || datastream.Length == 0)
            {
                SaveSongItem(formatdata);
                datastream = formatdata.GetStream(Instance, "neversoftdata");
            }
            QbItemBase item = new QbFile(datastream, GetSongItemType(song)).FindItem(QbKey.Create(song.Data.GetValue <uint>("NeversoftSongItemKey")), true);

            formatdata.CloseStream(datastream);
            if (item is QbItemArray)
            {
                item.Items[0].ItemQbKey = item.ItemQbKey;
                item = item.Items[0];
            }
            return(item as QbItemStruct);
        }
Ejemplo n.º 19
0
            public static Entry Create(EndianReader stream)
            {
                Entry entry = new Entry();

                uint entries;
                int  sizeofentry;

                entry.Identifier = QbKey.Create(stream.ReadUInt32());
                entries          = stream.ReadUInt32();
                entry.Type       = QbKey.Create(stream.ReadUInt32());
                sizeofentry      = stream.ReadInt32();

                entry.Data = new byte[entries][];
                for (int i = 0; i < entries; i++)
                {
                    entry.Data[i] = stream.ReadBytes(sizeofentry);
                }

                return(entry);
            }
Ejemplo n.º 20
0
        private void DecodeChartSections(SongData song, QbFile qbchart, StringList strings, QbFile qbsections, Notes notes, NoteChart chart)
        {
            if (notes != null)
            {
                uint[] values = GetChartValues(notes, null, QbKey.Create(0x92511D84), null, 4, 4);
                for (int k = 0; k < values.Length; k += 2)
                {
                    uint   time = values[k];
                    string text = strings.FindItem(QbKey.Create(values[k + 1]));

                    chart.Events.Sections.Add(new Pair <NoteChart.Point, string>(new NoteChart.Point(chart.GetTicks(time)), text));
                }
            }
            else
            {
                QbItemStructArray markers = (qbchart.FindItem(QbKey.Create(song.ID + "_guitar_markers"), false) as QbItemArray).Items[0] as QbItemStructArray;
                foreach (QbItemStruct mark in markers.Items)
                {
                    QbItemQbKey section = qbsections.FindItem((mark.Items[1] as QbItemQbKey).Values[0], false) as QbItemQbKey;

                    chart.Events.Sections.Add(new Pair <NoteChart.Point, string>(new NoteChart.Point(chart.GetTicks((mark.Items[0] as QbItemInteger).Values[0])), strings.FindItem(section.Values[0])));
                }
            }
        }
Ejemplo n.º 21
0
        public void ParseFromStream(StreamReader reader, bool stripprefix = true)
        {
            try {
                while (!reader.EndOfStream)
                {
                    char[] chars = new char[8];
                    if (reader.Read(chars, 0, 8) != 8)
                    {
                        break;
                    }

                    QbKey key = QbKey.Create(uint.Parse(new string(chars), System.Globalization.NumberStyles.HexNumber));
                    char  c   = '\0';
                    while (c != '"')
                    {
                        c = (char)reader.Read();
                    }

                    c = (char)reader.Read();
                    string str = string.Empty;
                    while (c != '"')
                    {
                        str += c;
                        c    = (char)reader.Read();
                    }

                    Items.Add(new KeyValuePair <QbKey, string>(key, str));

                    reader.Read(chars, 0, 2);
                    if (chars[0] != 0x0D || chars[1] != 0x0A)
                    {
                        break;
                    }
                }
            } catch { }
        }
Ejemplo n.º 22
0
        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;
            }
        }
Ejemplo n.º 23
0
        public static SongData GetSongData(PlatformData platformdata, QbItemStruct item, StringList strings)
        {
            if (strings == null)
            {
                strings = new StringList();
            }

            SongData data = new SongData(platformdata);

            data.ID = GetSongDataString(item, QbKeysID, strings);

            data.Name = GetSongDataString(item, QbKeysName, strings);

            data.Artist = GetSongDataString(item, QbKeysArtist, strings);

            data.Album = GetSongDataString(item, QbKeysAlbum, strings);

            if (strings.FindItem(QbKey.Create(QbKeysGenres[0].Key[0])) == null)
            {
                strings.Items.AddRange(QbKeysGenres.Select(g => new KeyValuePair <QbKey, string>(QbKey.Create(g.Key[0]), g.Value)));                // TODO: Expand the Key array
            }
            data.Genre = GetSongDataString(item, QbKeysGenre, strings);

            QbItemInteger year = GetQbItem(item, QbKeysYear) as QbItemInteger;

            if (year != null)
            {
                data.Year = (int)year.Values[0];
            }
            else
            {
                int yearnum;
                if (int.TryParse(GetSongDataString(item, QbKeysYear, strings).TrimStart(',', ' '), out yearnum))                 // ", 2009"
                {
                    data.Year = yearnum;
                }
            }

            QbItemInteger master = GetQbItem(item, QbKeysMaster) as QbItemInteger;

            if (master != null)
            {
                data.Master = master.Values[0] == 1;
            }

            QbItemInteger rank = GetQbItem(item, QbKeysDifficulty[Instrument.Ambient]) as QbItemInteger;

            if (rank != null)
            {
                data.Difficulty[Instrument.Ambient] = (int)rank.Values[0] * 60;
            }

            rank = GetQbItem(item, QbKeysDifficulty[Instrument.Drums]) as QbItemInteger;
            if (rank != null)
            {
                data.Difficulty[Instrument.Drums] = (int)rank.Values[0] * 50;
            }

            rank = GetQbItem(item, QbKeysDifficulty[Instrument.Vocals]) as QbItemInteger;
            if (rank != null)
            {
                data.Difficulty[Instrument.Vocals] = (int)rank.Values[0] * 45;
            }

            rank = GetQbItem(item, QbKeysDifficulty[Instrument.Bass]) as QbItemInteger;
            if (rank != null)
            {
                data.Difficulty[Instrument.Bass] = (int)rank.Values[0] * 55;
            }

            rank = GetQbItem(item, QbKeysDifficulty[Instrument.Guitar]) as QbItemInteger;
            if (rank != null)
            {
                data.Difficulty[Instrument.Guitar] = (int)rank.Values[0] * 60;
            }

            QbKey vocalmale   = QbKey.Create(0xAA721F56);
            QbKey vocalfemale = QbKey.Create("female");

            if (strings.FindItem(vocalmale) == null)
            {
                strings.Items.Add(new KeyValuePair <QbKey, string>(vocalmale, "male"));
            }
            if (strings.FindItem(vocalfemale) == null)
            {
                strings.Items.Add(new KeyValuePair <QbKey, string>(vocalfemale, "female"));
            }
            data.Vocalist = GetSongDataString(item, QbKeysVocalist, strings);
            if (!data.Vocalist.HasValue())
            {
                data.Vocalist = "male";
            }

            QbItemFloat hopo = GetQbItem(item, QbKeysHopo) as QbItemFloat;

            if (hopo != null)
            {
                data.HopoThreshold = (int)((float)NoteChart.DefaultTicksPerBeat / hopo.Values[0]);
            }

            // TODO: Better handling of QB items; this uses up a shitload of memory
            MemoryStream itemstream = new MemoryStream();

            item.Root.Write(itemstream);
            data.Data.SetValue("NeversoftSongItem", itemstream.GetBuffer());
            data.Data.SetValue("NeversoftSongType", (int)item.Root.PakFormat.PakFormatType);
            data.Data.SetValue("NeversoftSongItemKey", item.ItemQbKey.Crc);

            return(data);
        }
Ejemplo n.º 24
0
        private void DecodeChartFretbars(SongData song, QbFile qbchart, Notes notes, NoteChart chart)
        {
            uint[] values            = GetChartValues(notes, qbchart, Notes.KeyFretbars, QbKey.Create(song.ID + "_fretbars"));
            ulong  ticks             = 0;
            uint   previousfret      = 0;
            uint   previousMsPerBeat = 0;

            for (int k = 1; k < values.Length; k++)
            {
                uint fret      = values[k];
                uint msPerBeat = fret - previousfret;
                if (msPerBeat != previousMsPerBeat)
                {
                    chart.BPM.Add(new Midi.TempoEvent(ticks, msPerBeat * 1000));
                }

                previousfret      = fret;
                previousMsPerBeat = msPerBeat;
                ticks            += chart.Division.TicksPerBeat;
            }

            chart.Events.End = new NoteChart.Point(chart.GetTicks(values[values.Length - 1]));

            uint[][] jaggedvalues = GetJaggedChartValues(notes, qbchart, Notes.KeyTimesignature, QbKey.Create(song.ID + "_timesig"), 4, 1, 1);
            foreach (uint[] sig in jaggedvalues)
            {
                chart.Signature.Add(new Midi.TimeSignatureEvent(chart.GetTicks(sig[0]), (byte)sig[1], (byte)Math.Log(sig[2], 2), 24, 8));
            }
        }
Ejemplo n.º 25
0
        public override bool AddSong(PlatformData data, SongData song, ProgressIndicator progress)
        {
            string albumname = null;

            switch (song.ID)
            {
            case "dontholdback": albumname = "TheSleepingQuestionsAndAnswers"; break;

            case "minuscelsius": albumname = "BackyardBabiesStockholmSyndrome"; break;

            case "thrufireandflames": albumname = "DragonforceInhumanRampage"; break;

            case "fcpremix": albumname = "FallofTroyDoppelganger"; break;

            case "avalancha": albumname = "HeroesDelSilencioAvalancha"; break;

            case "takethislife": albumname = "InFlamesComeClarity"; break;

            case "ruby": albumname = "KaiserChiefsYoursTrulyAngry_Mob"; break;

            case "mycurse": albumname = "KillswitchEngageAsDaylightDies"; break;

            case "closer": albumname = "LacunaCoilKarmaCode"; break;

            case "metalheavylady": albumname = "LionsLions"; break;

            case "mauvaisgarcon": albumname = "NaastAntichambre"; break;

            case "generationrock": albumname = "RevolverheldRevolverheld"; break;

            case "prayeroftherefugee": albumname = "RiseAgainstTheSuffererAndTheWitness"; break;

            case "cantbesaved": albumname = "SensesFailStillSearching"; break;

            case "shebangsadrum": albumname = "StoneRosesStoneRoses"; break;

            case "radiosong": albumname = "SuperbusPopnGum"; break;

            case "bellyofashark": albumname = "TheGallowsOrchestraofWoles"; break;

            case "gothatfar": albumname = "BretMichealsBandGoThatFar"; break;

            case "impulse": albumname = "endlesssporadic"; break;

            case "thewayitends": albumname = "prototype_continuum_cover"; break;

            case "nothingformehere": albumname = "Dope_PosterCover_edsel"; break;

            case "inlove": albumname = "store_song_ScoutsStSebastian"; break;
            }
            if (albumname != null)
            {
                if (data.Session.ContainsKey("albumpak"))
                {
                    Pak      albumpak = data.Session["albumpak"] as Pak;
                    Pak.Node node     = albumpak.Nodes.Find(n => n.FilenamePakKey == QbKey.Create(albumname).Crc);
                    if (node != null)
                    {
                        song.AlbumArt = NgcImage.Create(new EndianReader(node.Data, Endianness.BigEndian)).Bitmap;
                    }
                }
            }

            DirectoryNode dir = data.Session["rootdir"] as DirectoryNode;
            Pak           qb  = data.Session["rootqb"] as Pak;

            FileNode chartpak = dir.Navigate("songs/" + song.ID + ".pak.ngc", false, true) as FileNode;

            if (chartpak == null)
            {
                return(false);
            }

            chartpak.Data.Position = 0;
            Pak      chartqb     = new Pak(new EndianReader(chartpak.Data, Endianness.BigEndian));
            FileNode sectionfile = chartqb.Root.Find(song.ID + ".mid_text.qb.ngc", SearchOption.AllDirectories, true) as FileNode;

            if (sectionfile == null)             // GHA stores it elsewhere
            {
                sectionfile = qb.Root.Find(song.ID + ".mid_text.qb.ngc", SearchOption.AllDirectories, true) as FileNode;
            }
            if (sectionfile == null)             // Last resort, check for it raw on the disc partition
            {
                sectionfile = dir.Find(song.ID + ".mid_text.qb.ngc", SearchOption.AllDirectories, true) as FileNode;
            }

            for (int coop = 0; coop < 2; coop++)
            {
                if (coop == 1)
                {
                    song       = new SongData(song);
                    song.ID   += "_coop";
                    song.Name += " [coop]";
                }
                FormatData formatdata = new TemporaryFormatData(song, data);

                FileNode datfile = dir.Navigate("music/" + song.ID + ".dat.ngc", false, true) as FileNode;
                FileNode wadfile = dir.Navigate("music/" + song.ID + ".wad.ngc", false, true) as FileNode;

                if (datfile == null || wadfile == null)
                {
                    continue;
                }

                AudioFormatGH3WiiFSB.Instance.Create(formatdata, datfile.Data, wadfile.Data);

                ChartFormatGH3.Instance.Create(formatdata, chartpak.Data, sectionfile.Data, coop == 1);

                data.AddSong(formatdata);
            }

            chartpak.Data.Close();

            return(true);
        }
Ejemplo n.º 26
0
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            data.Game = Platform.DetermineGame(data);

            try {
                FileNode qbpak = dir.Navigate("pak/qb.pak.ngc") as FileNode;
                if (qbpak == null)
                {
                    throw new FormatException("Couldn't find qb.pak on Guitar Hero Wii disc.");
                }

                FileNode qspak = dir.Navigate("pak/qs.pak.ngc") as FileNode;
                if (qspak == null)
                {
                    throw new FormatException("Couldn't find qs.pak on Guitar Hero Wii disc.");
                }

                Pak qs = new Pak(new EndianReader(qspak.Data, Endianness.BigEndian));

                StringList strings = new StringList();
                foreach (Pak.Node node in qs.Nodes)
                {
                    strings.ParseFromStream(node.Data);
                }

                Pak      qb           = new Pak(new EndianReader(qbpak.Data, Endianness.BigEndian));
                FileNode songlistfile = qb.FindFile(@"scripts\guitar\songlist.qb.ngc");
                if (songlistfile == null)
                {
                    songlistfile = qb.FindFile(@"scripts\guitar\songlist.qb");
                }

                if (songlistfile == null)
                {
                    throw new FormatException("Couldn't find the songlist on the Guitar Hero Wii disc pak.");
                }
                QbFile songlist = new QbFile(songlistfile.Data, PakFormat);

                data.Session["rootdir"] = dir;

                List <QbKey> listkeys = new List <QbKey>();
                foreach (uint songlistkey in NeversoftMetadata.SonglistKeys)
                {
                    QbKey        key  = QbKey.Create(songlistkey);
                    QbItemStruct list = songlist.FindItem(key, true) as QbItemStruct;
                    if (list != null && list.Items.Count > 0)
                    {
                        listkeys.Add(key);
                    }
                }

                progress.NewTask(listkeys.Count);
                List <string> songsadded = new List <string>();
                foreach (QbKey songlistkey in listkeys)
                {
                    QbItemStruct list = songlist.FindItem(songlistkey, true) as QbItemStruct;

                    progress.NewTask(list.Items.Count);

                    foreach (QbItemArray item in list.Items.OfType <QbItemArray>())
                    {
                        item.Items[0].ItemQbKey = item.ItemQbKey;
                        SongData song = NeversoftMetadata.GetSongData(data, item.Items[0] as QbItemStruct, strings);

                        progress.Progress();

                        if (songsadded.Contains(song.ID))
                        {
                            continue;
                        }

                        try {
                            if (AddSong(data, song, progress))
                            {
                                songsadded.Add(song.ID);
                            }
                        } catch (Exception exception) {
                            Exceptions.Warning(exception, "Unable to properly parse " + song.Name);
                        }
                    }

                    progress.EndTask();
                    progress.Progress();
                }
                progress.EndTask();

                qbpak.Data.Close();
                qspak.Data.Close();
            } catch (Exception exception) {
                Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero Wii disc.");
            }

            return(data);
        }
Ejemplo n.º 27
0
        public override PlatformData Create(string path, Game game, ProgressIndicator progress)
        {
            PlatformData data = new PlatformData(this, game);

            DirectoryNode dir = data.GetDirectoryStructure(path);

            FileNode binfile = dir.Navigate("001.bin") as FileNode;

            if (binfile == null)
            {
                Exceptions.Error("Unable to open Guitar Hero World Tour DLC because 001.bin is missing.");
            }

            data.Session["rootdir"] = dir;

            try {
                DlcBin   bin          = new DlcBin(binfile.Data);
                U8       u8           = new U8(bin.Data);
                FileNode listfile     = u8.Root.Navigate("DLC1.pak.ngc") as FileNode;
                Pak      qb           = new Pak(new EndianReader(listfile.Data, Endianness.BigEndian));
                FileNode songlistfile = qb.Root.Find("catalog_info.qb.ngc", SearchOption.AllDirectories) as FileNode;
                QbFile   songlist     = new QbFile(songlistfile.Data, PakFormat);

                StringList strings = new StringList();
                foreach (Pak.Node node in qb.Nodes)
                {
                    if (!node.Filename.HasValue())
                    {
                        strings.ParseFromStream(node.Data);
                    }
                }

                List <QbKey> listkeys = new List <QbKey>();
                foreach (uint songlistkey in NeversoftMetadata.SonglistKeys)
                {
                    QbKey        key  = QbKey.Create(songlistkey);
                    QbItemStruct list = songlist.FindItem(key, true) as QbItemStruct;
                    if (list != null && list.Items.Count > 0)
                    {
                        listkeys.Add(key);
                    }
                }

                Stream       str    = new FileStream(@"C:\ghwt.xml", FileMode.Create);
                StreamWriter writer = new StreamWriter(str);

                progress.NewTask(listkeys.Count);
                foreach (QbKey songlistkey in listkeys)
                {
                    QbItemStruct list = songlist.FindItem(songlistkey, true) as QbItemStruct;

                    progress.NewTask(list.Items.Count);

                    foreach (QbItemArray item in list.Items.OfType <QbItemArray>())
                    {
                        item.Items[0].ItemQbKey = item.ItemQbKey;
                        SongData song = NeversoftMetadata.GetSongData(data, item.Items[0] as QbItemStruct, strings);

                        writer.WriteLine("\t<song id=\"" + song.ID + "\">");
                        writer.WriteLine("\t\t<pack>Guitar Hero World Tour DLC</pack>");
                        writer.WriteLine("\t\t<nameprefix>[GHWT DLC]</nameprefix>");
                        writer.WriteLine("\t\t<name>" + song.Name + "</name>");
                        writer.WriteLine("\t\t<artist>" + song.Artist + "</artist>");
                        writer.WriteLine("\t\t<album>" + song.Album + "</album>");
                        writer.WriteLine("\t\t<genre>" + song.Genre + "</genre>");
                        writer.WriteLine("\t\t<track>" + song.AlbumTrack.ToString() + "</track>");
                        writer.WriteLine("\t\t<difficulty instrument=\"band\" rank=\"1\" />");
                        writer.WriteLine("\t\t<difficulty instrument=\"guitar\" rank=\"1\" />");
                        writer.WriteLine("\t\t<difficulty instrument=\"bass\" rank=\"1\" />");
                        writer.WriteLine("\t\t<difficulty instrument=\"drum\" rank=\"1\" />");
                        writer.WriteLine("\t\t<difficulty instrument=\"vocals\" rank=\"1\" />");
                        writer.WriteLine("\t</song>");

                        try {
                            AddSong(data, song, progress);
                        } catch (Exception exception) {
                            Exceptions.Warning(exception, "Unable to properly parse " + song.Name);
                        }
                        progress.Progress();
                    }

                    progress.EndTask();
                    progress.Progress();
                }
                progress.EndTask();
                writer.Close();

                binfile.Data.Close();
            } catch (Exception exception) {
                Exceptions.Error(exception, "An error occurred while parsing the Guitar Hero World Tour DLC list.");
            }

            return(data);
        }
Ejemplo n.º 28
0
        public void QbKeyStringTest2()
        {
            var qbKey = new QbKey("test");

            Assert.AreEqual(0x278081F3, qbKey.Checksum);
        }
Ejemplo n.º 29
0
        public static AudioFormat GetAudioFormat(FormatData data)
        {
            SongData    song        = data.Song;
            AudioFormat audioformat = new AudioFormat();

            QbItemStruct item = GetSongItem(data);

            if (item == null)
            {
                return(null);
            }
            float bandvolume   = 0;
            float guitarvolume = 0;
            float bassvolume   = 0;
            float drumvolume   = 0;

            QbItemFloat subitem = item.FindItem(QbKey.Create(0xD8F335CF), false) as QbItemFloat;             // GH3: band_playback_volume

            if (subitem != null)
            {
                bandvolume = (subitem as QbItemFloat).Values[0];
                bassvolume = bandvolume;
            }
            subitem = item.FindItem(QbKey.Create(0xA449CAD3), false) as QbItemFloat;             // GH3: guitar_playback_volume
            if (subitem != null)
            {
                guitarvolume = (subitem as QbItemFloat).Values[0];
            }
            subitem = item.FindItem(QbKey.Create(0x46507438), false) as QbItemFloat;             // GH4: overall_song_volume
            if (subitem != null)
            {
                bandvolume   = (subitem as QbItemFloat).Values[0];
                guitarvolume = bandvolume;
                bassvolume   = bandvolume;
                drumvolume   = bandvolume;
            }

            // GH4 engine games that came out after GHWT use a different drum audio scheme; the GH5 engine uses the same as GHWT
            bool gh4v2 = NeversoftMetadata.IsGuitarHero4(song.Game) && song.Game != Game.GuitarHeroWorldTour;
            // GHVH is the only BIK-based GH game with stereo bass
            bool ghvh = song.Game == Game.GuitarHeroVanHalen;

            if (gh4v2)
            {
                // Kick
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, -1, Instrument.Drums));
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 1, Instrument.Drums));
                // Snare
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, -1, Instrument.Drums));
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 1, Instrument.Drums));
            }
            else
            {
                // Kick
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 0, Instrument.Drums));
                // Snare
                audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 0, Instrument.Drums));
            }
            // Overhead
            audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, -1, Instrument.Drums));
            audioformat.Mappings.Add(new AudioFormat.Mapping(drumvolume, 1, Instrument.Drums));
            // Guitar
            audioformat.Mappings.Add(new AudioFormat.Mapping(guitarvolume, -1, Instrument.Guitar));
            audioformat.Mappings.Add(new AudioFormat.Mapping(guitarvolume, 1, Instrument.Guitar));
            // Bass
            audioformat.Mappings.Add(new AudioFormat.Mapping(bassvolume, ghvh ? -1 : 0, Instrument.Bass));
            if (ghvh)
            {
                audioformat.Mappings.Add(new AudioFormat.Mapping(bassvolume, 1, Instrument.Bass));
            }
            // Else / Vocals
            audioformat.Mappings.Add(new AudioFormat.Mapping(bandvolume, -1, Instrument.Ambient));
            audioformat.Mappings.Add(new AudioFormat.Mapping(bandvolume, 1, Instrument.Ambient));
            // Preview
            audioformat.Mappings.Add(new AudioFormat.Mapping(bandvolume, -1, Instrument.Preview));
            audioformat.Mappings.Add(new AudioFormat.Mapping(bandvolume, 1, Instrument.Preview));

            return(audioformat);
        }
Ejemplo n.º 30
0
        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;
            }
        }