public override void Construct(BinaryEndianReader br, QbItemType type) { //System.Diagnostics.Debug.WriteLine(string.Format("{0} - 0x{1}", type.ToString(), (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'))); base.Construct(br, type); QbItemBase qib; QbItemType headerType; uint headerValue; for (int i = 0; i < base.ItemCount; i++) { if (base.StreamPos(br) != base.Pointers[i]) //pointer test { throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[i])); } headerValue = br.ReadUInt32(this.Root.PakFormat.EndianType); headerType = this.Root.PakFormat.GetQbItemType(headerValue); switch (headerType) { case QbItemType.StructHeader: qib = new QbItemStruct(this.Root); break; default: throw new ApplicationException(string.Format("Location 0x{0}: Not a struct header type 0x{1}", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), headerValue.ToString("X").PadLeft(8, '0'))); } qib.Construct(br, headerType); AddItem(qib); } base.ConstructEnd(br); }
/// <summary> /// Deep clones this item and all children. Positions and lengths are not cloned. When inserted in to another item they should be calculated. /// </summary> /// <returns></returns> public override QbItemBase Clone() { QbItemStruct s = new QbItemStruct(this.Root); s.Create(this.QbItemType); if (this.ItemQbKey != null) s.ItemQbKey = this.ItemQbKey.Clone(); foreach (QbItemBase qib in this.Items) s.Items.Add(qib.Clone()); s.ItemCount = this.ItemCount; return s; }
/// <summary> /// Deep clones this item and all children. Positions and lengths are not cloned. When inserted in to another item they should be calculated. /// </summary> /// <returns></returns> public override QbItemBase Clone() { QbItemStruct s = new QbItemStruct(this.Root); s.Create(this.QbItemType); if (this.ItemQbKey != null) { s.ItemQbKey = this.ItemQbKey.Clone(); } foreach (QbItemBase qib in this.Items) { s.Items.Add(qib.Clone()); } s.ItemCount = this.ItemCount; return(s); }
/// <summary> /// Clones Tier1 to the battle tiers. /// </summary> /// <param name="guitarProgressionQb"></param> public void EditTiers(QbFile guitarProgressionQb, QbFile storeQb, QbFile songlistQb, QbFile coopQb, bool removeBossBattles, int setTierCount, int bonusSongCount, int[] songCounts, bool unlockTiers) { bool isGh3 = _project.GameInfo.Game == Game.GH3_Wii; int minTierSongCount = int.MaxValue; //so we can work out the encore unlock values QbKey qkUnlockSong = _project.GameInfo.Game == Game.GH3_Wii ? QbKey.Create("thrufireandflames") : QbKey.Create("kingsandqueens"); QbKey qkCreditsSong = QbKey.Create("kingsandqueenscredits"); bool unlockSongExists = false; bool creditsSongExists = false; QbKey qkDevil = _project.GameInfo.Game == Game.GH3_Wii ? QbKey.Create("bossdevil") : QbKey.Create(""); //don't do it for Aerosmith QbKey[] bossSongs = new QbKey[] { QbKey.Create("bosstom"), QbKey.Create("bossslash"), QbKey.Create("bossdevil"), QbKey.Create("bossjoe") }; string tierSongsComplete = "career_tier{0}_songscomplete"; QbFile qb = guitarProgressionQb; //short ref QbKey tname = QbKey.Create("name"); QbKey tcomp = QbKey.Create(string.Format(tierSongsComplete, "1")); QbItemStruct[] progs = new QbItemStruct[4]; string[][] masks = new string[4][]; List<QbKey> careerSongs = getAllCareerSongs(guitarProgressionQb); List<QbKey> bonusSongs = getAllBonusSongs(storeQb); int usedSong = 0; if (removeBossBattles) { foreach (QbKey qk in bossSongs) careerSongs.Remove(qk); } if (songCounts != null) { //find TTFAF or KQ and remove, it will be added as the last song of the career for (int c = careerSongs.Count - 1; c >= 0; c--) { QbKey qk = careerSongs[c]; if (qk.Crc == qkUnlockSong.Crc || qk.Crc == qkCreditsSong.Crc) //TTFAF or KQ (no credits) { careerSongs.Remove(qk); if (qk.Crc == qkUnlockSong.Crc) unlockSongExists = true; else creditsSongExists = true; } } for (int c = bonusSongs.Count - 1; c >= 0; c--) { QbKey qk = bonusSongs[c]; if (qk.Crc == qkUnlockSong.Crc || qk.Crc == qkCreditsSong.Crc) //TTFAF or KQ (no credits) { removeBonusSong(storeQb, qk); bonusSongs.Remove(qk); if (qk.Crc == qkUnlockSong.Crc) unlockSongExists = true; else creditsSongExists = true; } } } else if (removeBossBattles && isGh3) //add TTFAF to the end of the career tiers { for (int c = bonusSongs.Count - 1; c >= 0; c--) { QbKey qk = bonusSongs[c]; if (qk.Crc == qkUnlockSong.Crc) //TTFAF { removeBonusSong(storeQb, qk); bonusSongs.Remove(qk); unlockSongExists = true; break; } } } //remove the boss items and set to encore QbItemStruct careerSongsSec = qb.FindItem(QbKey.Create("GH3_Career_Songs"), false) as QbItemStruct; QbItemInteger qbNumTiers = careerSongsSec.FindItem(QbKey.Create("num_tiers"), false) as QbItemInteger; int currTierCount = (int)qbNumTiers.Values[0]; if (setTierCount != 0 && currTierCount != setTierCount) { setCareerTiers(careerSongsSec, currTierCount, setTierCount, unlockTiers); qbNumTiers.Values[0] = (uint)setTierCount; } if (setTierCount == 0) setTierCount = currTierCount; //no change #region career editing if (careerSongsSec != null) { QbKey qkEncore = QbKey.Create("encorep1"); QbKey qkAeroEncore = QbKey.Create("aerosmith_encore_p1"); QbKey qkBoss = QbKey.Create("boss"); QbKey qkLevel = QbKey.Create("level"); QbKey qkSongs = QbKey.Create("songs"); QbKey qkUnlocked = QbKey.Create("defaultunlocked"); QbKey qkNumTiers = QbKey.Create("num_tiers"); int tierCount = 0; int tierNo = 0; //remove Through the fire and flames. It can only be unlocked with the cheat or by beating the devil //this.RemoveBonusSongQbItems(QbKey.Create("thrufireandflames"), storeQb); foreach (QbItemBase qib in careerSongsSec.Items) { bool hasEncore = false; bool hasBoss = false; List<QbKey> sngs = null; if (qib is QbItemInteger && qib.ItemQbKey != null && qib.ItemQbKey.Crc == qkNumTiers.Crc) tierCount = (int)((QbItemInteger)qib).Values[0]; if (qib is QbItemStruct) { tierNo++; //assume they QB hold them in order foreach (QbItemBase qib2 in qib.Items) { bool devilRemoved = false; QbKey qiQk = null; if (qib2.QbItemType == QbItemType.StructItemArray) //find songs to be removed { qiQk = qib2.ItemQbKey; if (qiQk.Crc == qkSongs.Crc) { if (removeBossBattles) //remove the battles if required { sngs = new List<QbKey>(((QbItemQbKey)qib2.Items[0]).Values); for (int si = sngs.Count - 1; si >= 0; si--) { foreach (QbKey k in bossSongs) { if (sngs[si].Crc == k.Crc) { devilRemoved = k == qkDevil; //is it the devil? removeSongFromSonglist(songlistQb, k); sngs.RemoveAt(si--); //remove the boss song from the list } } } } //are we to modify the career tier song counts if (songCounts != null) { //set the career tier songs int tierSongs = songCounts[Math.Min(songCounts.Length - 1, tierNo - 1)]; sngs.Clear(); for (int i = 0; i < tierSongs; i++) { //last song of the career, use TTFAF or KQ (no credits) if (tierNo == tierCount && i == tierSongs - 1 && unlockSongExists) { careerSongs.Insert(usedSong, qkUnlockSong); } else if (usedSong >= careerSongs.Count) { //move song from bonus to career tier removeBonusSong(storeQb, bonusSongs[0]); careerSongs.Add(bonusSongs[0]); bonusSongs.RemoveAt(0); } sngs.Add(careerSongs[usedSong++]); } } else if (isGh3 && removeBossBattles && devilRemoved) //if tier songs are not to be edited then add ttfaf to the last tier (replace devil battle) { sngs.Add(qkUnlockSong); } if (sngs.Count < minTierSongCount) minTierSongCount = sngs.Count; ((QbItemQbKey)qib2.Items[0]).Values = sngs.ToArray(); } } else if (qib2.QbItemType == QbItemType.StructItemQbKey) //set the encore flag on all tiers, remove the boss { qiQk = ((QbItemQbKey)qib2).Values[0]; if (qiQk.Crc == qkEncore.Crc) hasEncore = true; else if (qiQk.Crc == qkBoss.Crc || qiQk.Crc == qkAeroEncore.Crc) { if (hasEncore) //just remove the boss or Aerosmith item qib.RemoveItem(qib2); else ((QbItemQbKey)qib2).Values[0] = QbKey.Create("encorep1"); hasBoss = true; break; } else if (qiQk.Crc == qkLevel.Crc && !hasBoss && !hasEncore) { QbItemQbKey enc = new QbItemQbKey(qib2.Root); enc.Create(QbItemType.StructItemQbKey); enc.Values = new QbKey[] { QbKey.Create("encorep1") }; //insert new item qib.InsertItem(enc, qib2, true); break; } } else if (qib2.QbItemType == QbItemType.StructItemInteger) { if (qib2.ItemQbKey != null && qib2.ItemQbKey.Crc == qkUnlocked.Crc && sngs != null && ((QbItemInteger)qib2).Values[0] < (uint)sngs.Count - 1) ((QbItemInteger)qib2).Values[0] = (uint)sngs.Count - 1; } } } } if (songCounts == null) usedSong = careerSongs.Count; //songs not touched //move the remaining Career Songs to the bonus section - ttfaf will not be the last song while (usedSong < careerSongs.Count) { bonusSongs.Insert(0, careerSongs[careerSongs.Count - 1]); this.AddBonusSongQbItems(careerSongs[careerSongs.Count - 1], storeQb, true); careerSongs.RemoveAt(careerSongs.Count - 1); } while (bonusSongs.Count != 0 && bonusSongs.Count > bonusSongCount) { this.BonusSongRemoveFromGame(storeQb, songlistQb, bonusSongs[bonusSongs.Count - 1]); //remove from set list also //removeBonusSong(storeQb, bonusSongs[bonusSongs.Count - 1]); bonusSongs.RemoveAt(bonusSongs.Count - 1); } //set the last bonus song to the creditsSongExists song if (!isGh3 && creditsSongExists) { if (bonusSongs.Count != 0 && bonusSongs.Count == bonusSongCount) //remove last song { this.BonusSongRemoveFromGame(storeQb, songlistQb, bonusSongs[bonusSongs.Count - 1]); //remove from set list also //removeBonusSong(storeQb, bonusSongs[bonusSongs.Count - 1]); bonusSongs.RemoveAt(bonusSongs.Count - 1); } bonusSongs.Add(qkCreditsSong); this.AddBonusSongQbItems(qkCreditsSong, storeQb, false); } //System.Diagnostics.Debug.WriteLine("\r\nCAREER\r\n"); //foreach (QbKey q1 in careerSongs) // System.Diagnostics.Debug.WriteLine(q1.Text); //System.Diagnostics.Debug.WriteLine("\r\nBONUS\r\n"); //foreach (QbKey q1 in bonusSongs) // System.Diagnostics.Debug.WriteLine(q1.Text); //set the songs to unlock section unlockXSongsToProgress(guitarProgressionQb, Math.Max(1, (int)(minTierSongCount * 0.65)), Math.Max(1, (int)(minTierSongCount * 0.75)), Math.Max(1, (int)(minTierSongCount * 0.85)), Math.Max(1, (int)(minTierSongCount * 0.95)), Math.Max(1, bonusSongs.Count)); } #endregion //modify the progression rules. QbItemArray careerProgSec = qb.FindItem(QbKey.Create("GH3_Career_Progression"), false) as QbItemArray; if (careerProgSec != null) { //use this temp progs[0] = findTierProgStruct(QbKey.Create("career_tier1_intro_songscomplete"), careerProgSec); if (progs[0] != null) careerProgSec.Items[0].RemoveItem(progs[0]); progs[0] = findTierProgStruct(QbKey.Create("career_tier1_songscomplete"), careerProgSec); masks[0] = new string[] { "career_tier{0}_songscomplete", "career_tier{0}_complete" }; progs[1] = findTierProgStruct(QbKey.Create("career_tier1_encoreunlock"), careerProgSec); masks[1] = new string[] { "career_tier{0}_encoreunlock", "career_tier{0}_songscomplete" }; progs[2] = findTierProgStruct(QbKey.Create("career_tier1_encorecomplete"), careerProgSec); masks[2] = new string[] { "career_tier{0}_encorecomplete", "career_tier{0}_encoreunlock" }; progs[3] = findTierProgStruct(QbKey.Create("career_tier1_complete"), careerProgSec); masks[3] = new string[] { "career_tier{0}_complete", "career_tier{0}_songscomplete", "career_tier{0}_encorecomplete" }; progs[0] = (QbItemStruct)progs[0].Clone(); //we need to clone this before modifying it or the modified version will be saved. addDependencyToTier1SongsComplete(progs[0]); QbItemStruct copy = null; QbItemStruct last = progs[3]; //insert new items after this one QbItemBase rem = null; if (setTierCount == 1) insertFinishGame(progs[3]); //set all prog items that trigger when completing the last tier QbKey qkCurr = QbKey.Create(string.Format("career_tier{0}_complete", currTierCount.ToString())); QbKey qkLast = QbKey.Create(string.Format("career_tier{0}_complete", setTierCount.ToString())); QbKey qkAtom = QbKey.Create("atom"); careerProgSec.FindItem(true, delegate(QbItemBase qib) { if (qib.ItemQbKey != null && qib.ItemQbKey.Crc == qkAtom.Crc && ((QbItemQbKey)qib).Values[0].Crc == qkCurr.Crc) ((QbItemQbKey)qib).Values[0] = qkLast.Clone(); //set to new last value return false; }); //copy tier 1 to all tiers for (int t = 2; t <= Math.Max(setTierCount, currTierCount); t++) { //remove the boss items rem = findTierProgStruct(QbKey.Create(string.Format("career_tier{0}_bosscomplete", t.ToString())), careerProgSec); if (rem != null) careerProgSec.Items[0].RemoveItem(rem); rem = findTierProgStruct(QbKey.Create(string.Format("career_tier{0}_bossunlock", t.ToString())), careerProgSec); if (rem != null) careerProgSec.Items[0].RemoveItem(rem); rem = findTierProgStruct(QbKey.Create(string.Format("career_tier{0}_intro_songscomplete", t.ToString())), careerProgSec); if (rem != null) careerProgSec.Items[0].RemoveItem(rem); for (int p = 0; p < progs.Length; p++) { //replace all 1s for our new number copy = copyTierProg(progs[p], t, masks[p]); //remove the existing item if present rem = findTierProgStruct(((QbItemQbKey)copy.Items[0]).Values[0], careerProgSec); careerProgSec.Items[0].RemoveItem(rem); if (t <= setTierCount) { if (t == setTierCount && p == progs.Length - 1) insertFinishGame(copy); careerProgSec.Items[0].InsertItem(copy, last, false); } qb.AlignPointers(); qb.IsValid(); last = copy; } } } QbItemStruct[] src = new QbItemStruct[] { (QbItemStruct)qb.FindItem(QbKey.Create("GH3_General_Songs"), false), (QbItemStruct)qb.FindItem(QbKey.Create("GH3_GeneralP2_Songs"), false), (QbItemStruct)qb.FindItem(QbKey.Create("GH3_GeneralP2_Songs_Coop"), false) }; for (int i = 0; i < src.Length; i++) { if (src[i] != null) { QbItemStruct dst = copyCareerTiers(careerSongsSec, src[i]); qb.InsertItem(dst, src[i], true); qb.RemoveItem(src[i]); qb.AlignPointers(); qb.IsValid(); } } if (coopQb != null) { copyCareerTiersToCoop(coopQb, guitarProgressionQb); } }
private void insertFinishGame(QbItemStruct prog) { prog.FindItem(true, delegate(QbItemBase qib) { if (qib is QbItemStruct && qib.ItemQbKey.Crc == QbKey.Create("atom_params").Crc) { QbItemQbKey qk = new QbItemQbKey(prog.Root); qk.Create(QbItemType.StructItemQbKey); qk.Values = new QbKey[] { QbKey.Create("finished_game") }; ((QbItemStruct)qib).AddItem(qk); return true; //stop after the first find } return false; //return false to continue search }); }
private void setCareerTiers(QbItemStruct careerSongsSec, int existingTierCount, int newTierCount, bool setUnlockIfOneTier) { //if setUnlockIfOneTier is false and we only have only 1 tier then don't unlock the new tiers, if tier 2 exists the lock is clones from that int add = newTierCount - existingTierCount; int clone; QbKey qkTier; QbKey qkNewTier; QbKey qkLastTier = QbKey.Create(string.Format("tier{0}", newTierCount.ToString())); for (int t = existingTierCount + 1; t <= newTierCount; t++) { int origTiersCount = Math.Min(existingTierCount, (_project.GameInfo.Game == Game.GH3_Wii) ? 8 : 6); //6 for aerosmith clone = t % origTiersCount; if (clone == 0) clone = origTiersCount; qkTier = QbKey.Create(string.Format("tier{0}", clone.ToString())); qkNewTier = QbKey.Create(string.Format("tier{0}", t.ToString())); QbItemStruct clonedTier = careerSongsSec.FindItem(qkTier, false).Clone() as QbItemStruct; clonedTier.ItemQbKey = qkNewTier.Clone(); if (clone == 1) //if tier 1 is being cloned then check is tier 1 has the unlocked value and make this the same { QbItemStruct tier2 = careerSongsSec.FindItem(QbKey.Create("tier2"), false) as QbItemStruct; if (tier2 != null) { tier2 = tier2.Clone() as QbItemStruct; QbItemInteger ul = tier2.FindItem(QbKey.Create("defaultunlocked"), false) as QbItemInteger; if (ul == null) //remove the cloned item { if ((ul = clonedTier.FindItem(QbKey.Create("defaultunlocked"), false) as QbItemInteger) != null) clonedTier.RemoveItem(ul); } } else if (!setUnlockIfOneTier) { //clear lock QbItemInteger ul = clonedTier.FindItem(QbKey.Create("defaultunlocked"), false) as QbItemInteger; if (ul != null) clonedTier.RemoveItem(ul); } } careerSongsSec.AddItem(clonedTier); } while (careerSongsSec.Items.Count > 3 && careerSongsSec.Items[careerSongsSec.Items.Count - 1].ItemQbKey.Crc != qkLastTier.Crc) careerSongsSec.RemoveItem(careerSongsSec.Items[careerSongsSec.Items.Count - 1]); //remove last item careerSongsSec.Root.AlignPointers(); careerSongsSec.Root.IsValid(); }
private QbItemStruct copyCareerTiers(QbItemStruct careerSongsSec, QbItemStruct toTier) { //all other tier structs have encore2 in them so add it. and no completion movie item QbItemBase tmp; QbKey qkInitialMovie = QbKey.Create("initial_movie"); QbKey qkCompletionMovie = QbKey.Create("completion_movie"); QbKey qkEncoreP1 = QbKey.Create("encorep1"); QbKey qkPrefix = QbKey.Create("prefix"); string prefix = ((QbItemString)toTier.FindItem(qkPrefix, false)).Strings[0]; QbItemStruct to = (QbItemStruct)careerSongsSec.Clone(); if ((tmp = to.FindItem(qkInitialMovie, false)) != null) to.RemoveItem(tmp); //remove initial move if found to.ItemQbKey = toTier.ItemQbKey.Clone(); ((QbItemString)to.FindItem(qkPrefix, false)).Strings[0] = prefix; QbItemQbKey encorep2 = new QbItemQbKey(to.Root); encorep2.Create(QbItemType.StructItemQbKey); encorep2.Values = new QbKey[] { QbKey.Create("encorep2") }; foreach (QbItemBase qb in to.Items) { if (qb.QbItemType == QbItemType.StructItemStruct) { if ((tmp = qb.FindItem(qkCompletionMovie, false)) != null) qb.RemoveItem(tmp); //remove initial move if found if ((tmp = qb.FindItem(false, delegate (QbItemBase q) { return (qb.QbItemType == QbItemType.StructItemQbKey && qb.ItemQbKey != null && qb.ItemQbKey.Crc == 0 && ((QbItemQbKey)qb).Values[0].Crc == qkEncoreP1.Crc); })) != null) { qb.InsertItem(encorep2.Clone(), tmp, false); } } } return to; }
private QbItemStruct copyTierProg(QbItemStruct prog, int toTierNo, params string[] qbKeyMask) { QbItemStruct copy = (QbItemStruct)prog.Clone(); //replace all 1s for our new number copy.FindItem(true, delegate(QbItemBase qib) { if (qib.ItemQbKey != null) { if (qib is QbItemInteger && qib.ItemQbKey.Crc == QbKey.Create("tier").Crc) ((QbItemInteger)qib).Values[0] = (uint)toTierNo; else if (qib is QbItemQbKey) { foreach (string s in qbKeyMask) { QbKey k = QbKey.Create(string.Format(s, "1")); QbKey k2 = QbKey.Create(string.Format(s, "0")); if (((QbItemQbKey)qib).Values[0].Crc == k.Crc) ((QbItemQbKey)qib).Values[0] = QbKey.Create(string.Format(s, toTierNo.ToString())); else if (((QbItemQbKey)qib).Values[0].Crc == k2.Crc) ((QbItemQbKey)qib).Values[0] = QbKey.Create(string.Format(s, (toTierNo - 1).ToString())); } } } return false; //return false to continue search }); return copy; }
public static QbItemStruct CreateSong(QbFile root, string songname) { QbItemStruct song = new QbItemStruct(root); song.Create(QbItemType.StructItemStruct); song.ItemQbKey = QbKey.Create(songname); QbItemQbKey checksum = new QbItemQbKey(root); checksum.Create(QbItemType.StructItemQbKey); checksum.ItemQbKey = QbKey.Create("checksum"); checksum.Values = new QbKey[] { QbKey.Create(songname) }; song.AddItem(checksum); QbItemString name = new QbItemString(root); name.Create(QbItemType.StructItemString); name.ItemQbKey = QbKey.Create("name"); name.Strings = new string[] { songname }; song.AddItem(name); QbItemString title = new QbItemString(root); title.Create(QbItemType.StructItemString); title.ItemQbKey = QbKey.Create("title"); title.Strings = new string[] { songname }; song.AddItem(title); QbItemString artist = new QbItemString(root); artist.Create(QbItemType.StructItemString); artist.ItemQbKey = QbKey.Create("artist"); artist.Strings = new string[] { songname }; song.AddItem(artist); QbItemString year = new QbItemString(root); year.Create(QbItemType.StructItemString); year.ItemQbKey = QbKey.Create("year"); year.Strings = new string[] { string.Empty }; song.AddItem(year); QbItemQbKey artistText = new QbItemQbKey(root); artistText.Create(QbItemType.StructItemQbKeyString); artistText.ItemQbKey = QbKey.Create("artist_text"); artistText.Values = new QbKey[] { QbKey.Create("artist_text_by") }; song.AddItem(artistText); QbItemInteger originalArtist = new QbItemInteger(root); originalArtist.Create(QbItemType.StructItemInteger); originalArtist.ItemQbKey = QbKey.Create("original_artist"); originalArtist.Values = new uint[] { 1 }; song.AddItem(originalArtist); QbItemQbKey version = new QbItemQbKey(root); version.Create(QbItemType.StructItemQbKey); version.ItemQbKey = QbKey.Create("version"); version.Values = new QbKey[] { QbKey.Create("gh3") }; song.AddItem(version); QbItemInteger leaderboard = new QbItemInteger(root); leaderboard.Create(QbItemType.StructItemInteger); leaderboard.ItemQbKey = QbKey.Create("leaderboard"); leaderboard.Values = new uint[] { 1 }; song.AddItem(leaderboard); QbItemInteger gemOffset = new QbItemInteger(root); gemOffset.Create(QbItemType.StructItemInteger); gemOffset.ItemQbKey = QbKey.Create("gem_offset"); gemOffset.Values = new uint[] { 0 }; song.AddItem(gemOffset); QbItemInteger inputOffset = new QbItemInteger(root); inputOffset.Create(QbItemType.StructItemInteger); inputOffset.ItemQbKey = QbKey.Create("input_offset"); inputOffset.Values = new uint[] { 0 }; song.AddItem(inputOffset); QbItemQbKey singer = new QbItemQbKey(root); singer.Create(QbItemType.StructItemQbKey); singer.ItemQbKey = QbKey.Create("singer"); singer.Values = new QbKey[] { QbKey.Create("male") }; song.AddItem(singer); QbItemQbKey keyboard = new QbItemQbKey(root); keyboard.Create(QbItemType.StructItemQbKey); keyboard.ItemQbKey = QbKey.Create("keyboard"); keyboard.Values = new QbKey[] { QbKey.Create("false") }; song.AddItem(keyboard); QbItemFloat bandPlaybackVolume = new QbItemFloat(root); bandPlaybackVolume.Create(QbItemType.StructItemFloat); bandPlaybackVolume.ItemQbKey = QbKey.Create("band_playback_volume"); bandPlaybackVolume.Values = new float[] { 0F }; song.AddItem(bandPlaybackVolume); QbItemFloat guitarPlaybackVolume = new QbItemFloat(root); guitarPlaybackVolume.Create(QbItemType.StructItemFloat); guitarPlaybackVolume.ItemQbKey = QbKey.Create("guitar_playback_volume"); guitarPlaybackVolume.Values = new float[] { 0F }; song.AddItem(guitarPlaybackVolume); QbItemString countOff = new QbItemString(root); countOff.Create(QbItemType.StructItemString); countOff.ItemQbKey = QbKey.Create("countoff"); countOff.Strings = new string[] { "sticks_normal" }; song.AddItem(countOff); QbItemInteger rhythmTrack = new QbItemInteger(root); rhythmTrack.Create(QbItemType.StructItemInteger); rhythmTrack.ItemQbKey = QbKey.Create("rhythm_track"); rhythmTrack.Values = new uint[] { 0 }; song.AddItem(rhythmTrack); return song; }
/// <summary> /// All but this tier 1 have a dependency on the previous tier being completed /// </summary> /// <param name="tier"></param> private void addDependencyToTier1SongsComplete(QbItemStruct prog) { //insert dependency on previous tier. Obviously tier 0 does exist, it's just for replacement purposes QbItemBase qbs = prog.Items[prog.Items.Count - 1]; if (qbs is QbItemArray) { QbItemStructArray qsa = (QbItemStructArray)qbs.Items[0]; QbItemStruct qis = new QbItemStruct(prog.Root); qis.Create(QbItemType.StructHeader); QbItemQbKey qbQk = new QbItemQbKey(prog.Root); qbQk.Create(QbItemType.StructItemQbKey); qbQk.ItemQbKey = QbKey.Create("type"); qbQk.Values = new QbKey[] { QbKey.Create("atom") }; qis.AddItem(qbQk); qbQk = new QbItemQbKey(prog.Root); qbQk.Create(QbItemType.StructItemQbKey); qbQk.ItemQbKey = QbKey.Create("atom"); qbQk.Values = new QbKey[] { QbKey.Create("career_tier0_complete") }; qis.AddItem(qbQk); qsa.InsertItem(qis, qsa.Items[0], true); } }
private void calculateMarkers(int[] frets, QbItemArray arr, QbFile text) { int minNote = this.Notes.MinNoteOffsetSynced + _startPaddingMs + _fretPadding; int maxNote = this.Notes.MaxNoteOffsetSynced + _startPaddingMs + _fretPadding; int pos = minNote; int sectionSecs = 20000; int sections = (maxNote - minNote) / sectionSecs; //every x seconds for (int c = text.Items.Count - 1; c > 0; c--) text.RemoveItem(text.Items[c]); QbItemStructArray sa = new QbItemStructArray(arr.Root); sa.Create(QbItemType.ArrayStruct); arr.Items.Clear(); arr.AddItem(sa); QbItemStruct s; QbItemInteger i; QbItemQbKey q; string sectionTitle; QbKey qbKey; QbItemString txt; for (int c = 0; c < sections; c++) { if (pos + 3000 > this.Length) break; //don't create a section less than 3 seconds long sectionTitle = string.Format("Section {0}", (c + 1).ToString()); qbKey = QbKey.Create(string.Format("{0}_markers_text_{1}", this.SongQb.Id, QbKey.Create(sectionTitle).Crc.ToString("x").ToLower())); txt = new QbItemString(text); txt.Create(QbItemType.SectionString); txt.ItemQbKey = qbKey; txt.Strings = new string[] { sectionTitle }; text.AddItem(txt); s = new QbItemStruct(arr.Root); s.Create(QbItemType.StructHeader); sa.AddItem(s); i = new QbItemInteger(arr.Root); i.Create(QbItemType.StructItemInteger); i.ItemQbKey = QbKey.Create("time"); i.Values = new uint[] { findNearestFret((uint)pos, frets) }; s.AddItem(i); pos += sectionSecs; q = new QbItemQbKey(arr.Root); q.Create(QbItemType.StructItemQbKeyString); q.ItemQbKey = QbKey.Create("marker"); q.Values = new QbKey[] { qbKey }; s.AddItem(q); } text.AlignPointers(); arr.Root.AlignPointers(); }
private void setMarkers(int[] frets, QbItemArray arr, QbFile text, NotesMarker[] markers) { int minNote = this.Notes.MinNoteOffsetSynced + _startPaddingMs + _fretPadding; QbItemStruct s; QbItemInteger i; QbItemQbKey q; QbKey qbKey; QbItemString txt; for (int c = text.Items.Count - 1; c > 0; c--) text.RemoveItem(text.Items[c]); if (arr.Items[0] is QbItemFloats) { QbItemStructArray newArr = new QbItemStructArray(arr.Root); newArr.Create(QbItemType.ArrayStruct); arr.AddItem(newArr); arr.RemoveItem(arr.Items[0]); } QbItemStructArray sa = (QbItemStructArray)arr.Items[0]; sa.Items.Clear(); NotesMarker marker; List<NotesMarker> mrk = new List<NotesMarker>(markers); if (mrk.Count > 0 && mrk[0].Offset > minNote) //some charts don't have sections at the start so you can't practice the start notes :-( { if (mrk[0].Offset > minNote + 5000) // if > 5secs then add new mrk.Insert(0, new NotesMarker("Start", minNote)); else //else move first marker back to start mrk[0].Offset = minNote; } for (int c = 0; c < mrk.Count; c++) { marker = mrk[c]; if (c < mrk.Count - 1 && mrk[c + 1].Offset < minNote) continue; //don't add sections at the start that would have no notes (crashes song??) qbKey = QbKey.Create(string.Format("{0}_markers_text_{1}", this.SongQb.Id, QbKey.Create(marker.Title).Crc.ToString("x").ToLower())); txt = new QbItemString(text); txt.Create(QbItemType.SectionString); txt.ItemQbKey = qbKey; txt.Strings = new string[] { marker.Title }; text.AddItem(txt); s = new QbItemStruct(arr.Root); s.Create(QbItemType.StructHeader); sa.AddItem(s); i = new QbItemInteger(arr.Root); i.Create(QbItemType.StructItemInteger); i.ItemQbKey = QbKey.Create("time"); i.Values = new uint[] { findNearestFret((uint)marker.Offset, frets) }; s.AddItem(i); q = new QbItemQbKey(arr.Root); q.Create(QbItemType.StructItemQbKeyString); q.ItemQbKey = QbKey.Create("marker"); q.Values = new QbKey[] { qbKey }; s.AddItem(q); } text.AlignPointers(); arr.Root.AlignPointers(); }
private void parse(Stream stream) { _streamStartPosition = stream.Position; _items = new List <QbItemBase>(); //if (stream.Position != 0) // throw new ApplicationException("The stream must start at position 0 as this parser uses the position to validate pointers."); using (BinaryEndianReader br = new BinaryEndianReader(stream)) { _magic = br.ReadUInt32(this.PakFormat.EndianType); _fileSize = br.ReadUInt32(this.PakFormat.EndianType); uint sectionValue; QbItemBase qib = new QbItemUnknown(20, this); qib.Construct(br, QbItemType.Unknown); AddItem(qib); while (this.StreamPos(br.BaseStream) < _fileSize) { sectionValue = br.ReadUInt32(this.PakFormat.EndianType); QbItemType sectionType = this.PakFormat.GetQbItemType(sectionValue); switch (sectionType) { case QbItemType.SectionString: case QbItemType.SectionStringW: qib = new QbItemString(this); break; case QbItemType.SectionArray: qib = new QbItemArray(this); break; case QbItemType.SectionStruct: qib = new QbItemStruct(this); break; case QbItemType.SectionScript: qib = new QbItemScript(this); break; case QbItemType.SectionFloat: qib = new QbItemFloat(this); break; case QbItemType.SectionFloatsX2: case QbItemType.SectionFloatsX3: qib = new QbItemFloatsArray(this); break; case QbItemType.SectionInteger: case QbItemType.SectionStringPointer: qib = new QbItemInteger(this); break; case QbItemType.SectionQbKey: case QbItemType.SectionQbKeyString: case QbItemType.SectionQbKeyStringQs: //GH:GH qib = new QbItemQbKey(this); break; default: throw new ApplicationException(string.Format("Location 0x{0}: Unknown section type 0x{1}", (this.StreamPos(br.BaseStream) - 4).ToString("X").PadLeft(8, '0'), sectionValue.ToString("X").PadLeft(8, '0'))); } qib.Construct(br, sectionType); AddItem(qib); } } uint f = this.FileId; //gettin this sets the file id }
private static QbItemBase createQbItemType(QbFile qbFile, QbItemType type, QbFormat qbFormat, bool hasQbFormat) { QbItemBase qib = null; if (qbFile.PakFormat.GetQbItemValue(type, qbFile) == 0xFFFFFFFF) throw new ApplicationException(string.Format("'{0}' data value not known for {1}", type.ToString(), qbFile.PakFormat.FriendlyName)); switch (type) { //case QbItemType.Unknown: // break; case QbItemType.SectionString: case QbItemType.SectionStringW: case QbItemType.ArrayString: case QbItemType.ArrayStringW: case QbItemType.StructItemString: case QbItemType.StructItemStringW: qib = new QbItemString(qbFile); break; case QbItemType.SectionArray: case QbItemType.ArrayArray: case QbItemType.StructItemArray: qib = new QbItemArray(qbFile); break; case QbItemType.SectionStruct: case QbItemType.StructItemStruct: case QbItemType.StructHeader: qib = new QbItemStruct(qbFile); break; case QbItemType.SectionScript: qib = new QbItemScript(qbFile); break; case QbItemType.SectionFloat: case QbItemType.ArrayFloat: case QbItemType.StructItemFloat: qib = new QbItemFloat(qbFile); break; case QbItemType.SectionFloatsX2: case QbItemType.SectionFloatsX3: case QbItemType.ArrayFloatsX2: case QbItemType.ArrayFloatsX3: case QbItemType.StructItemFloatsX2: case QbItemType.StructItemFloatsX3: qib = new QbItemFloatsArray(qbFile); break; case QbItemType.SectionInteger: case QbItemType.SectionStringPointer: case QbItemType.ArrayInteger: case QbItemType.ArrayStringPointer: //GH:GH case QbItemType.StructItemStringPointer: case QbItemType.StructItemInteger: qib = new QbItemInteger(qbFile); break; case QbItemType.SectionQbKey: case QbItemType.SectionQbKeyString: case QbItemType.SectionQbKeyStringQs: //GH:GH case QbItemType.ArrayQbKey: case QbItemType.ArrayQbKeyString: case QbItemType.ArrayQbKeyStringQs: //GH:GH case QbItemType.StructItemQbKey: case QbItemType.StructItemQbKeyString: case QbItemType.StructItemQbKeyStringQs: qib = new QbItemQbKey(qbFile); break; case QbItemType.Floats: qib = new QbItemFloats(qbFile); break; case QbItemType.ArrayStruct: qib = new QbItemStructArray(qbFile); break; default: throw new ApplicationException(string.Format("'{0}' is not recognised by CreateQbItemType.", type.ToString())); } if (qib != null) qib.Create(type); return qib; }
private static QbItemBase createQbItemType(QbFile qbFile, QbItemType type, QbFormat qbFormat, bool hasQbFormat) { QbItemBase qib = null; if (qbFile.PakFormat.GetQbItemValue(type, qbFile) == 0xFFFFFFFF) { throw new ApplicationException(string.Format("'{0}' data value not known for {1}", type.ToString(), qbFile.PakFormat.FriendlyName)); } switch (type) { //case QbItemType.Unknown: // break; case QbItemType.SectionString: case QbItemType.SectionStringW: case QbItemType.ArrayString: case QbItemType.ArrayStringW: case QbItemType.StructItemString: case QbItemType.StructItemStringW: qib = new QbItemString(qbFile); break; case QbItemType.SectionArray: case QbItemType.ArrayArray: case QbItemType.StructItemArray: qib = new QbItemArray(qbFile); break; case QbItemType.SectionStruct: case QbItemType.StructItemStruct: case QbItemType.StructHeader: qib = new QbItemStruct(qbFile); break; case QbItemType.SectionScript: qib = new QbItemScript(qbFile); break; case QbItemType.SectionFloat: case QbItemType.ArrayFloat: case QbItemType.StructItemFloat: qib = new QbItemFloat(qbFile); break; case QbItemType.SectionFloatsX2: case QbItemType.SectionFloatsX3: case QbItemType.ArrayFloatsX2: case QbItemType.ArrayFloatsX3: case QbItemType.StructItemFloatsX2: case QbItemType.StructItemFloatsX3: qib = new QbItemFloatsArray(qbFile); break; case QbItemType.SectionInteger: case QbItemType.SectionStringPointer: case QbItemType.ArrayInteger: case QbItemType.ArrayStringPointer: //GH:GH case QbItemType.StructItemStringPointer: case QbItemType.StructItemInteger: qib = new QbItemInteger(qbFile); break; case QbItemType.SectionQbKey: case QbItemType.SectionQbKeyString: case QbItemType.SectionQbKeyStringQs: //GH:GH case QbItemType.ArrayQbKey: case QbItemType.ArrayQbKeyString: case QbItemType.ArrayQbKeyStringQs: //GH:GH case QbItemType.StructItemQbKey: case QbItemType.StructItemQbKeyString: case QbItemType.StructItemQbKeyStringQs: qib = new QbItemQbKey(qbFile); break; case QbItemType.Floats: qib = new QbItemFloats(qbFile); break; case QbItemType.ArrayStruct: qib = new QbItemStructArray(qbFile); break; default: throw new ApplicationException(string.Format("'{0}' is not recognised by CreateQbItemType.", type.ToString())); } if (qib != null) { qib.Create(type); } return(qib); }
internal SongQb(Project project, QbItemStruct song) { _song = song; QbItemBase temp; _hopoMeasure = null; _checksum = (QbItemQbKey)song.FindItem(QbKey.Create("checksum"), false); //_key = song.ItemQbKey; _key = QbKey.Create(((QbItemString)song.FindItem(QbKey.Create("name"), false)).Strings[0]); _title = (QbItemString)song.FindItem(QbKey.Create("title"), false); _artist = (QbItemString)song.FindItem(QbKey.Create("artist"), false); _leaderboard = (QbItemInteger)song.FindItem(QbKey.Create("leaderboard"), false); _year = (QbItemString)song.FindItem(QbKey.Create("year"), false); _boss = song.FindItem(QbKey.Create("boss"), false) as QbItemQbKey; //is this a boss temp = song.FindItem(QbKey.Create("band_playback_volume"), false); //sometimes integer instead of float if (temp == null) { _songVolume = new QbItemFloat(song.Root); _songVolume.Create(QbItemType.StructItemFloat); _songVolume.ItemQbKey = QbKey.Create("band_playback_volume"); _songVolume.Values = new float[1]; _songVolume.Values[0] = 0; song.AddItem(_songVolume); song.Root.AlignPointers(); } else if (temp is QbItemInteger) _songVolume = replaceItemIntForFloat(song, (QbItemInteger)temp); else _songVolume = (QbItemFloat)temp; temp = song.FindItem(QbKey.Create("guitar_playback_volume"), false); //sometimes integer instead of float if (temp == null) { _guitarVolume = new QbItemFloat(song.Root); _guitarVolume.Create(QbItemType.StructItemFloat); _guitarVolume.ItemQbKey = QbKey.Create("guitar_playback_volume"); _guitarVolume.Values = new float[1]; _guitarVolume.Values[0] = 0; song.AddItem(_guitarVolume); song.Root.AlignPointers(); } else if (temp is QbItemInteger) _guitarVolume = replaceItemIntForFloat(song, (QbItemInteger)temp); else _guitarVolume = (QbItemFloat)temp; _rhythmTrack = (QbItemInteger)song.FindItem(QbKey.Create("rhythm_track"), false); temp = song.FindItem(QbKey.Create("artist_text"), false); if (temp is QbItemString) { _artistTextString = (QbItemString)temp; _artistText = null; } else { _artistText = song.FindItem(QbKey.Create("artist_text"), false) as QbItemQbKey; _artistTextString = null; } _originalArtist = (QbItemInteger)song.FindItem(QbKey.Create("original_artist"), false); temp = song.FindItem(QbKey.Create("singer"), false); if (temp == null) //GH3 wii Cream sunshine for your love has no singer item { _singer = new QbItemQbKey(song.Root); _singer.Create(QbItemType.StructItemQbKey); _singer.ItemQbKey = QbKey.Create("singer"); _singer.Values = new QbKey[1]; _singer.Values[0] = QbKey.Create("male"); song.AddItem(_singer); song.Root.AlignPointers(); } else _singer = (QbItemQbKey)temp; _fretbarOffset = song.FindItem(QbKey.Create("fretbar_offset"), false) as QbItemInteger; _gemOffset = song.FindItem(QbKey.Create("gem_offset"), false) as QbItemInteger; _inputOffset = song.FindItem(QbKey.Create("input_offset"), false) as QbItemInteger; //this fixes an issue with GH3(cult of personality) and GHA (talk talking) if (this.key.Crc != this.checksum.Crc) _id = (project.GameInfo.Game == Game.GH3_Wii) ? this.checksum : this.key; else _id = this.checksum.HasText ? this.checksum : this.key; }
/// <summary> /// Some items are not the correct type, replace them. /// </summary> /// <param name="song"></param> /// <param name="item"></param> /// <returns></returns> private QbItemFloat replaceItemIntForFloat(QbItemStruct song, QbItemInteger item) { QbItemFloat f = new QbItemFloat(song.Root); f.Create(QbItemType.StructItemFloat); f.ItemQbKey = item.ItemQbKey; f.Values[0] = item.Values[0]; song.InsertItem(f, item, true); song.RemoveItem(item); song.Root.AlignPointers(); return f; }
/// <summary> /// Add song to bonus list and shop /// </summary> /// <param name="songQk"></param> public void AddBonusSongQbItems(QbKey songQk, QbFile qbStore, bool insertAdd) { QbKey qkCreditsSong = _project.GameInfo.Game == Game.GH3_Wii ? QbKey.Create("thrufireandflames") : QbKey.Create("kingsandqueenscredits"); //find bonus song list QbItemArray bonusSongs = qbStore.FindItem(QbKey.Create("songs"), true) as QbItemArray; //find bonus song price list QbItemStruct songData = qbStore.FindItem(QbKey.Create("store_song_data"), true) as QbItemStruct; //find bonus song info QbItemArray bonusInfo = qbStore.FindItem(QbKey.Create("Bonus_Songs_Info"), true) as QbItemArray; //add bonus song to list if (bonusSongs != null) { List<QbKey> songs = new List<QbKey>((bonusSongs.Items[0] as QbItemQbKey).Values); if (!songs.Contains(songQk)) { if (insertAdd) songs.Insert(0, songQk.Clone()); else { //insert second from the end (before TTFAF / kingandqueenscredits) if (songs.Count == 0 || songs[songs.Count - 1].Crc != qkCreditsSong.Crc) songs.Add(songQk.Clone()); //clone qbkey else songs.Insert(songs.Count - 1, songQk.Clone()); //clone qbkey } (bonusSongs.Items[0] as QbItemQbKey).Values = songs.ToArray(); } } if (songData != null) { //add bonus song price if (null == songData.FindItem(false, delegate(QbItemBase qib) { return (qib.ItemQbKey.Crc == songQk.Crc); })) { QbItemStruct songDataItem = new QbItemStruct(qbStore); songDataItem.Create(QbItemType.StructItemStruct); songDataItem.ItemQbKey = songQk.Clone(); QbItemInteger songDataItemPrice = new QbItemInteger(qbStore); songDataItemPrice.Create(QbItemType.StructItemInteger); songDataItemPrice.ItemQbKey = QbKey.Create("price"); songDataItemPrice.Values = new uint[] { 0 }; songDataItem.AddItem(songDataItemPrice); if (!insertAdd || songData.Items.Count == 0) songData.AddItem(songDataItem); else songData.InsertItem(songDataItem, songData.Items[0], true); } } if (bonusInfo != null) { //add bonus info QbKey itemQk = QbKey.Create("item"); QbItemStructArray infoArray = (bonusInfo.Items[0] as QbItemStructArray); if (null == infoArray.FindItem(false, delegate(QbItemBase qib) { QbItemQbKey iqk = (QbItemQbKey)(qib.Items[0]); return iqk.ItemQbKey.Crc == itemQk.Crc && iqk.Values[0] == songQk.Crc; })) { QbItemStruct infoStruct = new QbItemStruct(qbStore); infoStruct.Create(QbItemType.StructHeader); if (!insertAdd || infoArray.Items.Count == 0) infoArray.AddItem(infoStruct); else infoArray.InsertItem(infoStruct, infoArray.Items[0], true); qbStore.AlignPointers(); qbStore.IsValid(); QbItemQbKey infoItem = new QbItemQbKey(qbStore); infoItem.Create(QbItemType.StructItemQbKey); infoItem.ItemQbKey = itemQk; //"item" infoItem.Values = new QbKey[] { songQk.Clone() }; infoStruct.AddItem(infoItem); qbStore.AlignPointers(); qbStore.IsValid(); QbItemString infoText = new QbItemString(qbStore); infoText.Create(QbItemType.StructItemString); infoText.ItemQbKey = QbKey.Create("text"); infoText.Strings = new string[] { "Bonus song added with TheGHOST" }; infoStruct.AddItem(infoText); qbStore.AlignPointers(); qbStore.IsValid(); QbItemQbKey infoCover = new QbItemQbKey(qbStore); infoCover.Create(QbItemType.StructItemQbKey); infoCover.ItemQbKey = QbKey.Create("album_cover"); infoCover.Values = new QbKey[] { QbKey.Create("store_song_default") }; infoStruct.AddItem(infoCover); qbStore.AlignPointers(); qbStore.IsValid(); } } }
public override void Construct(BinaryEndianReader br, QbItemType type) { //System.Diagnostics.Debug.WriteLine(string.Format("{0} - 0x{1}", type.ToString(), (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'))); base.Construct(br, type); uint pointer; if (type != QbItemType.StructHeader) { _headerValue = br.ReadUInt32(base.Root.PakFormat.EndianType); } else { _headerValue = base.Root.PakFormat.GetQbItemValue(type, this.Root); } _headerType = base.Root.PakFormat.GetQbItemType(_headerValue); QbItemBase qib = null; QbItemType structType; uint structValue; if (_headerType == QbItemType.StructHeader) { pointer = br.ReadUInt32(base.Root.PakFormat.EndianType); //Should be the current stream position after reading _iniNextItemPointer = pointer; if (pointer != 0 && base.StreamPos(br) != pointer) //pointer test { throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), pointer)); } while (pointer != 0) { structValue = br.ReadUInt32(this.Root.PakFormat.EndianType); structType = this.Root.PakFormat.GetQbItemType(structValue); switch (structType) { case QbItemType.StructItemStruct: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemStruct(this.Root); break; case QbItemType.StructItemStringPointer: case QbItemType.StructItemInteger: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemInteger(this.Root); break; case QbItemType.StructItemQbKeyString: case QbItemType.StructItemQbKeyStringQs: case QbItemType.StructItemQbKey: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemQbKey(this.Root); break; case QbItemType.StructItemString: case QbItemType.StructItemStringW: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemString(this.Root); break; case QbItemType.StructItemFloat: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemFloat(this.Root); break; case QbItemType.StructItemFloatsX2: case QbItemType.StructItemFloatsX3: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemFloatsArray(this.Root); break; case QbItemType.StructItemArray: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemArray(this.Root); break; //Convert array types to structitems to fit in with this parser (if QbFile.HasStructItems is false then internal type will be swapped back to array) case QbItemType.ArrayStruct: structType = QbItemType.StructItemStruct; qib = new QbItemArray(this.Root); break; case QbItemType.ArrayInteger: structType = QbItemType.StructItemInteger; qib = new QbItemInteger(this.Root); break; case QbItemType.ArrayQbKeyString: structType = QbItemType.StructItemQbKeyString; qib = new QbItemQbKey(this.Root); break; case QbItemType.ArrayStringPointer: structType = QbItemType.StructItemStringPointer; qib = new QbItemInteger(this.Root); break; case QbItemType.ArrayQbKeyStringQs: structType = QbItemType.StructItemQbKeyStringQs; qib = new QbItemQbKey(this.Root); break; case QbItemType.ArrayQbKey: structType = QbItemType.StructItemQbKey; qib = new QbItemQbKey(this.Root); break; case QbItemType.ArrayString: structType = QbItemType.StructItemString; qib = new QbItemString(this.Root); break; case QbItemType.ArrayStringW: structType = QbItemType.StructItemStringW; qib = new QbItemString(this.Root); break; case QbItemType.ArrayFloat: structType = QbItemType.StructItemFloat; qib = new QbItemFloat(this.Root); break; case QbItemType.ArrayFloatsX2: structType = QbItemType.StructItemFloatsX2; qib = new QbItemFloatsArray(this.Root); break; case QbItemType.ArrayFloatsX3: structType = QbItemType.StructItemFloatsX3; qib = new QbItemFloatsArray(this.Root); break; case QbItemType.ArrayArray: structType = QbItemType.StructItemArray; qib = new QbItemArray(this.Root); break; default: qib = null; break; } if (qib != null) { if (this.Root.PakFormat.StructItemChildrenType == StructItemChildrenType.NotSet) //will have been set to structItem if qib is not null) { this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.ArrayItems; } qib.Construct(br, structType); AddItem(qib); pointer = qib.NextItemPointer; } else { throw new ApplicationException(string.Format("Location 0x{0}: Unknown item type 0x{1} in struct ", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), structValue.ToString("X").PadLeft(8, '0'))); } } } else { throw new ApplicationException(string.Format("Location 0x{0}: Struct without header type", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'))); } base.ConstructEnd(br); }
private void parse(Stream stream) { _streamStartPosition = stream.Position; _items = new List<QbItemBase>(); //if (stream.Position != 0) // throw new ApplicationException("The stream must start at position 0 as this parser uses the position to validate pointers."); using (BinaryEndianReader br = new BinaryEndianReader(stream)) { _magic = br.ReadUInt32(this.PakFormat.EndianType); _fileSize = br.ReadUInt32(this.PakFormat.EndianType); uint sectionValue; QbItemBase qib = new QbItemUnknown(20, this); qib.Construct(br, QbItemType.Unknown); AddItem(qib); while (this.StreamPos(br.BaseStream) < _fileSize) { sectionValue = br.ReadUInt32(this.PakFormat.EndianType); QbItemType sectionType = this.PakFormat.GetQbItemType(sectionValue); switch (sectionType) { case QbItemType.SectionString: case QbItemType.SectionStringW: qib = new QbItemString(this); break; case QbItemType.SectionArray: qib = new QbItemArray(this); break; case QbItemType.SectionStruct: qib = new QbItemStruct(this); break; case QbItemType.SectionScript: qib = new QbItemScript(this); break; case QbItemType.SectionFloat: qib = new QbItemFloat(this); break; case QbItemType.SectionFloatsX2: case QbItemType.SectionFloatsX3: qib = new QbItemFloatsArray(this); break; case QbItemType.SectionInteger: case QbItemType.SectionStringPointer: qib = new QbItemInteger(this); break; case QbItemType.SectionQbKey: case QbItemType.SectionQbKeyString: case QbItemType.SectionQbKeyStringQs: //GH:GH qib = new QbItemQbKey(this); break; default: throw new ApplicationException(string.Format("Location 0x{0}: Unknown section type 0x{1}", (this.StreamPos(br.BaseStream) - 4).ToString("X").PadLeft(8, '0'), sectionValue.ToString("X").PadLeft(8, '0'))); } qib.Construct(br, sectionType); AddItem(qib); } } uint f = this.FileId; //gettin this sets the file id }
public override void Construct(BinaryEndianReader br, QbItemType type) { //System.Diagnostics.Debug.WriteLine(string.Format("{0} - 0x{1}", type.ToString(), (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'))); base.Construct(br, type); QbItemBase qib = null; QbItemType arrayType; uint arrayValue; for (int i = 0; i < base.ItemCount; i++) { arrayValue = br.ReadUInt32(this.Root.PakFormat.EndianType); arrayType = this.Root.PakFormat.GetQbItemType(arrayValue); switch (arrayType) { case QbItemType.Floats: qib = new QbItemFloats(this.Root); break; case QbItemType.ArrayStruct: qib = new QbItemStructArray(this.Root); break; case QbItemType.ArrayFloat: qib = new QbItemFloat(this.Root); break; case QbItemType.ArrayString: case QbItemType.ArrayStringW: qib = new QbItemString(this.Root); break; case QbItemType.ArrayFloatsX2: case QbItemType.ArrayFloatsX3: qib = new QbItemFloatsArray(this.Root); break; case QbItemType.ArrayStringPointer: case QbItemType.ArrayInteger: qib = new QbItemInteger(this.Root); break; case QbItemType.ArrayArray: qib = new QbItemArray(this.Root); break; case QbItemType.ArrayQbKey: case QbItemType.ArrayQbKeyString: case QbItemType.ArrayQbKeyStringQs: //GH:GH qib = new QbItemQbKey(this.Root); break; case QbItemType.StructHeader: qib = new QbItemStruct(this.Root); break; default: throw new ApplicationException(string.Format("Location 0x{0}: Unknown array type 0x{1}", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), arrayValue.ToString("X").PadLeft(8, '0'))); } qib.Construct(br, arrayType); AddItem(qib); } base.ConstructEnd(br); }
public override void Construct(BinaryEndianReader br, QbItemType type) { //System.Diagnostics.Debug.WriteLine(string.Format("{0} - 0x{1}", type.ToString(), (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'))); base.Construct(br, type); uint pointer; if (type != QbItemType.StructHeader) _headerValue = br.ReadUInt32(base.Root.PakFormat.EndianType); else _headerValue = base.Root.PakFormat.GetQbItemValue(type, this.Root); _headerType = base.Root.PakFormat.GetQbItemType(_headerValue); QbItemBase qib = null; QbItemType structType; uint structValue; if (_headerType == QbItemType.StructHeader) { pointer = br.ReadUInt32(base.Root.PakFormat.EndianType); //Should be the current stream position after reading _iniNextItemPointer = pointer; if (pointer != 0 && base.StreamPos(br) != pointer) //pointer test throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), pointer)); while (pointer != 0) { structValue = br.ReadUInt32(this.Root.PakFormat.EndianType); structType = this.Root.PakFormat.GetQbItemType(structValue); switch (structType) { case QbItemType.StructItemStruct: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemStruct(this.Root); break; case QbItemType.StructItemStringPointer: case QbItemType.StructItemInteger: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemInteger(this.Root); break; case QbItemType.StructItemQbKeyString: case QbItemType.StructItemQbKeyStringQs: case QbItemType.StructItemQbKey: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemQbKey(this.Root); break; case QbItemType.StructItemString: case QbItemType.StructItemStringW: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemString(this.Root); break; case QbItemType.StructItemFloat: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemFloat(this.Root); break; case QbItemType.StructItemFloatsX2: case QbItemType.StructItemFloatsX3: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemFloatsArray(this.Root); break; case QbItemType.StructItemArray: this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems; qib = new QbItemArray(this.Root); break; //Convert array types to structitems to fit in with this parser (if QbFile.HasStructItems is false then internal type will be swapped back to array) case QbItemType.ArrayStruct: structType = QbItemType.StructItemStruct; qib = new QbItemArray(this.Root); break; case QbItemType.ArrayInteger: structType = QbItemType.StructItemInteger; qib = new QbItemInteger(this.Root); break; case QbItemType.ArrayQbKeyString: structType = QbItemType.StructItemQbKeyString; qib = new QbItemQbKey(this.Root); break; case QbItemType.ArrayStringPointer: structType = QbItemType.StructItemStringPointer; qib = new QbItemInteger(this.Root); break; case QbItemType.ArrayQbKeyStringQs: structType = QbItemType.StructItemQbKeyStringQs; qib = new QbItemQbKey(this.Root); break; case QbItemType.ArrayQbKey: structType = QbItemType.StructItemQbKey; qib = new QbItemQbKey(this.Root); break; case QbItemType.ArrayString: structType = QbItemType.StructItemString; qib = new QbItemString(this.Root); break; case QbItemType.ArrayStringW: structType = QbItemType.StructItemStringW; qib = new QbItemString(this.Root); break; case QbItemType.ArrayFloat: structType = QbItemType.StructItemFloat; qib = new QbItemFloat(this.Root); break; case QbItemType.ArrayFloatsX2: structType = QbItemType.StructItemFloatsX2; qib = new QbItemFloatsArray(this.Root); break; case QbItemType.ArrayFloatsX3: structType = QbItemType.StructItemFloatsX3; qib = new QbItemFloatsArray(this.Root); break; case QbItemType.ArrayArray: structType = QbItemType.StructItemArray; qib = new QbItemArray(this.Root); break; default: qib = null; break; } if (qib != null) { if (this.Root.PakFormat.StructItemChildrenType == StructItemChildrenType.NotSet) //will have been set to structItem if qib is not null) this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.ArrayItems; qib.Construct(br, structType); AddItem(qib); pointer = qib.NextItemPointer; } else throw new ApplicationException(string.Format("Location 0x{0}: Unknown item type 0x{1} in struct ", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), structValue.ToString("X").PadLeft(8, '0'))); } } else throw new ApplicationException(string.Format("Location 0x{0}: Struct without header type", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'))); base.ConstructEnd(br); }