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); _values = new QbKey[base.ItemCount]; uint crc; string debug; for (int i = 0; i < base.ItemCount; i++) { crc = br.ReadUInt32(base.Root.PakFormat.EndianType); debug = this.Root.LookupDebugName(crc); if (debug.Length != 0) { _values[i] = QbKey.Create(crc, debug); } else { _values[i] = QbKey.Create(crc); } } base.ConstructEnd(br); }
public QbItemBase FindItem(QbKey key, bool recursive) { return(SearchItems(this, _items, recursive, delegate(QbItemBase item) { return (item.ItemQbKey != null && item.ItemQbKey.Crc == key.Crc); })); }
public void NewFile(string newQbFilename, QbKey itemType, bool filenameInHeader, uint magic, byte[] unknownData) { createBlankFile(newQbFilename, itemType, filenameInHeader); QbFile blank = new QbFile(newQbFilename, _pakFormat, magic, unknownData); this.ReplaceFile(newQbFilename, blank); }
/// <summary> /// Add the non debug item to the user defined list if it's not already there /// </summary> /// <param name="qbKey"></param> /// <param name="qbFilename"></param> /// <param name="qbfile"></param> /// <returns>True if crc already exists with different text.</returns> public string AddNonDebugQbKey(QbKey qbKey, string qbFilename, QbFile qbfile) { //check that it's not already in the real debug file if (qbKey.HasText) { string t = string.Empty; if (qbfile != null) { t = qbfile.LookupDebugName(qbKey.Crc, false); } //it's in the debug file if (t.Length != 0) { if (t != qbKey.Text) { return(t); } } else { //check that it's not in the user debug file if (GetNonDebugQbKey(qbKey.Crc, qbFilename) == null) { if (_qbKeys == null) { _qbKeys = new List <NonDebugQbKey>(); } _qbKeys.Add(new NonDebugQbKey(qbKey, qbFilename)); } } } return(string.Empty); }
/// <summary> /// Converts the qbkey to the enum /// </summary> /// <param name="fileType"></param> /// <returns>The enum item or Other if not in enum</returns> public static PakItemType FileTypeToPakItemType(QbKey fileType) { if (fileType == _itemTypes[0].Crc) //.qb { return(PakItemType.Qb); } else if (fileType == _itemTypes[1].Crc) //.sqb { return(PakItemType.Sqb); } else if (fileType == _itemTypes[2].Crc) //.dbg { return(PakItemType.Debug); } else if (fileType == _itemTypes[3].Crc) //.img { return(PakItemType.Image); } else if (fileType == _itemTypes[4].Crc) //.mqb { return(PakItemType.Midi); } else if (fileType == _itemTypes[5].Crc) //.tex { return(PakItemType.Texture); } else if (fileType == _itemTypes[6].Crc) //.skin { return(PakItemType.Skin); } else { return(PakItemType.Other); } }
/// <summary> /// Rename the filename, this does not set the fileid for all the qb types /// </summary> /// <param name="qbFilename">Source full filename.</param> /// <param name="newFullQbFilename">Full QB filename</param> /// <param name="fileType">.qb or .sqb=QB, .mqb=mid, .img=img .dbg=dbg etc</param> /// <param name="extension">.qb.ngc for Wii for example</param> public void RenameFile(string qbFilename, string newQbFilename, QbKey itemType) { PakHeaderItem phi = _pakHeaders[qbFilename.ToLower()]; phi.SetFilename(newQbFilename, itemType, _pakFormat.FileExtension, phi); using (BinaryEndianWriter bw = new BinaryEndianWriter(File.OpenWrite(_pakFormat.FullPakFilename))) { bw.BaseStream.Seek(phi.HeaderStart, SeekOrigin.Begin); writeHeaderItem(bw, phi); } //update the filename in the collection Dictionary <string, PakHeaderItem> p = new Dictionary <string, PakHeaderItem>(_pakHeaders.Count); foreach (PakHeaderItem ph in _pakHeaders.Values) { p.Add(ph.Filename.ToLower(), ph); } _pakHeaders = p; if (phi.PakFileType == PakItemType.Qb || phi.PakFileType == PakItemType.Sqb || phi.PakFileType == PakItemType.Midi) { try { QbFile qbf = ReadQbFile(newQbFilename); qbf.SetNewFileId(); ReplaceFile(newQbFilename, qbf); } catch { } } }
internal DatItem(QbKey itemQbKey, uint fileOffset, uint fileSize, byte[] reserved) { _itemQkey = itemQbKey; _fileOffset = fileOffset; _fileSize = fileSize; _reserved = reserved; }
/// <summary> /// Rename the filename and set the data types /// </summary> /// <param name="newFullQbFilename">Full QB filename</param> /// <param name="fileType">.qb or .sqb=QB, .mqb=mid, .img=img .dbg=dbg etc</param> /// <param name="extension">.ngc for Wii for example</param> /// <param name="baseOn">base the qbKeys that are present on the passed item</param> public void SetFilename(string newFullQbFilename, QbKey itemType, string extension, PakHeaderItem baseOn) { if (newFullQbFilename.Length > PakHeaderItem.FileNameMaxLength) { throw new ApplicationException("newQbFilename is too long"); } if (!itemType.HasText || itemType.Text.Length == 0) { throw new ApplicationException("fileType is not recognised"); } //filename is stored in the header if ((this.Flags & PakHeaderFlags.Filename) == PakHeaderFlags.Filename) { this.Filename = newFullQbFilename; this.FullFilenameQbKey = 0; } else { this.Filename = QbKey.Create(newFullQbFilename).Crc.ToString("X").PadLeft(8, '0').ToLower(); if (baseOn == null || baseOn.FullFilenameQbKey != 0) { this.FullFilenameQbKey = QbKey.Create(newFullQbFilename).Crc; } else { this.FullFilenameQbKey = 0; } } string[] pts = newFullQbFilename.Split('.'); string nameOnly = pts[0]; if (baseOn == null || baseOn.FullFilenameQbKey != 0) { this.NameOnlyCrc = QbKey.Create(nameOnly).Crc; } else { this.NameOnlyCrc = 0; } this.FileType = itemType; if (baseOn == null || baseOn.PakFullFileNameQbKey != 0) { this.PakFullFileNameQbKey = QbKey.Create(newFullQbFilename).Crc; } else { this.PakFullFileNameQbKey = 0; } }
public QbKey ToQbKey() { Type t = typeof(QbKey); if (t != _type) { throw new ApplicationException(getToError(_type, t)); } return(QbKey.Create(_value)); }
public GenericQbItem(string name, QbKey value, Type editType, bool readOnly, bool useQbItemType, QbItemType qbType, string sourceProperty) : this(name, editType, readOnly, useQbItemType, qbType, sourceProperty) { _value = value.ToString(); _type = value.GetType(); _typeNumeric = true; _qbKey = value; this.ConvertTo(editType); }
/// <summary> /// Create a QbKey that has an already known CRC and Text /// </summary> /// <param name="crc">QBKey crc</param> /// <param name="text">Text from debug file etc</param> /// <returns></returns> public static QbKey Create(uint crc, string text) { QbKey qb = Create(text); if (crc != qb.Crc) { throw new ArgumentException(string.Format("The Crc 0x{0} does not match the Text '{1}'", crc.ToString("X").PadLeft(8, '0'), text)); } return(qb); }
public QbKey Clone() { if (this.HasText) { return(QbKey.Create(this.Text)); } else { return(QbKey.Create(this.Crc)); } }
/// <summary> /// Attempts to take a qbkey key without any text and lookup a named file type /// </summary> /// <returns></returns> public static QbKey LookupFileType(QbKey fileType) { foreach (QbKey k in _itemTypes) { if (fileType.Crc == k.Crc) { return(k); } } return(fileType); }
private void loadNonDebugQbKey() { if (File.Exists(FullNonDebugQbKeyFilename)) { string[] f; foreach (string s in File.ReadAllLines(FullNonDebugQbKeyFilename)) { f = s.Split('|'); AddNonDebugQbKey(QbKey.Create(uint.Parse(f[0].Substring(2), System.Globalization.NumberStyles.HexNumber), f[1]), f[2], null); } } }
/// <summary> /// The FileId is based on the filename, this will recalculate it, GH3 has a bug where the first character is missing from the path. /// The FileId doesn't appear to affect the game, it may just need to be unique /// </summary> public void SetNewFileId() { uint fileId = QbKey.Create(this.Filename).Crc; foreach (QbItemBase qbi in this.Items) { if (qbi.QbItemType != QbItemType.Unknown) { qbi.FileId = fileId; } } }
public override void Create(QbItemType type) { if (type != QbItemType.SectionQbKey && type != QbItemType.SectionQbKeyString && type != QbItemType.SectionQbKeyStringQs && type != QbItemType.ArrayQbKey && type != QbItemType.ArrayQbKeyString && type != QbItemType.ArrayQbKeyStringQs && type != QbItemType.StructItemQbKey && type != QbItemType.StructItemQbKeyString && type != QbItemType.StructItemQbKeyStringQs) { throw new ApplicationException(string.Format("type '{0}' is not a QB key item type", type.ToString())); } base.Create(type); this.Values = new QbKey[1]; //sets item count _values[0] = QbKey.Create(0); }
static PakHeaderItem() { // qb, qb, debug, image, midi string[] s = new string[] { ".qb", ".sqb", ".dbg", ".img", ".mqb", ".tex", ".skin", ".cam", ".col", ".fam", ".fnc", ".fnt", ".fnv", ".gap", ".hkc", ".imv", ".last", ".mcol", ".mdl", ".mdv", ".nav", ".nqb", ".oba", ".pfx", ".pimg", ".png", ".rag", ".rnb", ".rnb_lvl", ".rnb_mdl", ".scn", ".scv", ".shd", ".ska", ".ske", ".skiv", ".stex", ".table", ".tvx", ".wav", ".empty", ".clt", ".jam", ".note", ".nqb", ".perf", ".pimv", ".qs", ".qs.br", ".qs.de", ".qs.en", ".qs.es", ".qs.fr", ".qs.it", ".raw", ".rgn", ".trkobj", ".xml" }; _itemTypes = new QbKey[s.Length]; for (int i = 0; i < s.Length; i++) { _itemTypes[i] = QbKey.Create(s[i]); } }
public static void CreateDatWad(QbKey songQk, EndianType endianType, string datFilename, string wadFilename, string songFilename, string guitarFilename, string rhythmFilename, string previewFilename) { QbKey[] keys = new QbKey[4]; int[] offsets = new int[5]; int[] sizes = new int[4]; FileHelper.Delete(wadFilename); FileHelper.Delete(datFilename); using (FileStream fsWad = File.OpenWrite(wadFilename)) { offsets[0] = (int)fsWad.Position; keys[0] = QbKey.Create(string.Format("{0}_guitar", songQk.Text)); sizes[0] = (int)writeFsbToStream(fsWad, guitarFilename, string.Concat(keys[0].Text, ".wav")); offsets[1] = (int)fsWad.Position; keys[1] = QbKey.Create(string.Format("{0}_preview", songQk.Text)); sizes[1] = (int)writeFsbToStream(fsWad, previewFilename, string.Concat(keys[1].Text, ".wav")); offsets[2] = (int)fsWad.Position; keys[2] = QbKey.Create(string.Format("{0}_rhythm", songQk.Text)); sizes[2] = (int)writeFsbToStream(fsWad, rhythmFilename, string.Concat(keys[2].Text, ".wav")); offsets[3] = (int)fsWad.Position; keys[3] = QbKey.Create(string.Format("{0}_song", songQk.Text)); sizes[3] = (int)writeFsbToStream(fsWad, songFilename, string.Concat(keys[3].Text, ".wav")); offsets[4] = (int)fsWad.Position; fsWad.Flush(); } using (FileStream fsDat = File.OpenWrite(datFilename)) { using (BinaryEndianWriter bw = new BinaryEndianWriter(fsDat)) { int l = offsets[3] + sizes[3]; if (l % 16 != 0) l += 16 - (l % 16); bw.Write((uint)keys.Length, endianType); bw.Write((uint)l, endianType); for (int i = 0; i < offsets.Length - 1; i++) { bw.Write(keys[i].Crc, endianType); bw.Write(offsets[i], endianType); bw.Write(sizes[i], endianType); bw.Write(new byte[] { 0,0,0,0,0,0,0,0 }); } fsDat.Flush(); } } }
/// <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() { QbItemQbKey qk = new QbItemQbKey(this.Root); qk.Create(this.QbItemType); if (this.ItemQbKey != null) qk.ItemQbKey = this.ItemQbKey.Clone(); QbKey[] q = new QbKey[this.Values.Length]; for (int i = 0; i < q.Length; i++ ) q[i] = this.Values[i].Clone(); qk.Values = q; qk.ItemCount = this.ItemCount; return qk; }
internal string LookupDebugName(uint debugCrc, bool allowUserQbkeyLookup) { if (_debugNames != null && _debugNames.ContainsKey(debugCrc)) { return(_debugNames[debugCrc]); } if (allowUserQbkeyLookup) { QbKey qbKey = _pakFormat.GetNonDebugQbKey(debugCrc, _filename); if (qbKey != null) { return(qbKey.Text); } } return(string.Empty); }
/// <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() { QbItemQbKey qk = new QbItemQbKey(this.Root); qk.Create(this.QbItemType); if (this.ItemQbKey != null) { qk.ItemQbKey = this.ItemQbKey.Clone(); } QbKey[] q = new QbKey[this.Values.Length]; for (int i = 0; i < q.Length; i++) { q[i] = this.Values[i].Clone(); } qk.Values = q; qk.ItemCount = this.ItemCount; return(qk); }
/// <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(); } } }
/// <summary> /// Remove song to bonus list and shop /// </summary> /// <param name="songQk"></param> public void RemoveBonusSongQbItems(QbKey songQk, QbFile qbStore) { QbItemBase item; //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; //remove bonus song from list if (bonusSongs != null) { List<QbKey> songs = new List<QbKey>((bonusSongs.Items[0] as QbItemQbKey).Values); songs.Remove(songQk); (bonusSongs.Items[0] as QbItemQbKey).Values = songs.ToArray(); } //remove bonus song price if (songData != null) { item = songData.FindItem(false, delegate(QbItemBase qib) { return (qib.ItemQbKey.Crc == songQk.Crc); }); if (item != null) songData.RemoveItem(item); } //remove bonus info if (bonusInfo != null && bonusInfo.Items.Count > 0) { QbKey itemQk = QbKey.Create("item"); QbItemStructArray infoArray = (bonusInfo.Items[0] as QbItemStructArray); item = infoArray.FindItem(false, delegate(QbItemBase qib) { QbItemQbKey iqk = (QbItemQbKey)(qib.Items[0]); return iqk.ItemQbKey.Crc == itemQk.Crc && iqk.Values[0] == songQk.Crc; }); if (item != null) infoArray.RemoveItem(item); } qbStore.AlignPointers(); qbStore.IsValid(); }
/// <summary> /// Edits tiers using the files in Partition folder /// </summary> /// <param name="removeBossBattles"></param> /// <param name="bonusSongs"></param> /// <param name="songCounts"></param> public void EditTiers(PakEditor pak, bool removeBossBattles, int setTierCount, int bonusSongs, int[] songCounts, bool unlockTiers) { QbKey[] nonCareerSongs = new QbKey[0]; string progQb = @"scripts\guitar\guitar_progression.qb.ngc"; string coopQb = @"scripts\guitar\guitar_coop.qb.ngc"; string storeDataQb = @"scripts\guitar\store_data.qb.ngc"; string songlistQb = @"scripts\guitar\songlist.qb.ngc"; if (_project.GameInfo.Game == Game.GH3_Wii) { progQb = progQb.Substring(1); //remove first char coopQb = coopQb.Substring(1); //remove first char storeDataQb = storeDataQb.Substring(1); //remove first char songlistQb = songlistQb.Substring(1); //remove first char } if (_project.GameInfo.Game == Game.GH3_Wii || _project.GameInfo.Game == Game.GHA_Wii) { //add song to song list QbFile qbProg = pak.ReadQbFile(progQb); QbFile qbCoop = _project.GameInfo.Game == Game.GH3_Wii ? pak.ReadQbFile(coopQb) : null; QbFile qbStore = pak.ReadQbFile(storeDataQb); QbFile qbSonglist = pak.ReadQbFile(songlistQb); this.EditTiers(qbProg, qbStore, qbSonglist, qbCoop, removeBossBattles, setTierCount, bonusSongs, songCounts, unlockTiers); pak.ReplaceFile(progQb, qbProg); pak.ReplaceFile(storeDataQb, qbStore); if (qbCoop != null) pak.ReplaceFile(coopQb, qbCoop); pak.ReplaceFile(songlistQb, qbSonglist); } }
/// <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); } }
internal List<TierQb> BuildTierList(QbFile fileQb, QbKey tiersQk) { List<TierQb> tierList = new List<TierQb>(); QbItemBase tiersQi = fileQb.FindItem(tiersQk, false); if (tiersQi != null) { tiersQi.FindItem(false, delegate(QbItemBase item) { if (item.QbItemType == QbItemType.StructItemStruct) tierList.Add(new TierQb((QbItemStruct)item)); return false; //if we return false then the search continues }); } foreach (TierQb t in tierList) { for (int i = 0; i < t.Songs.Length; i++) { if (this.Songs.ContainsKey(t.Songs[i].Crc)) t.Songs[i] = this.Songs[t.Songs[i].Crc].SongQb.Id; //get the key from the songlist (it has the text) } } return tierList; }
/// <summary> /// Remove song from bonus list and shop /// </summary> public void BonusSongRemoveFromGame(QbFile qbStore, QbFile qbSongList, QbKey qkSong) { //is this song (this) in the bonus tiers? bool found = getAllBonusSongs(qbStore).Contains(qkSong); removeSongFromSonglist(qbSongList, qkSong); this.RemoveBonusSongQbItems(qkSong, qbStore); }
private void parsePak(PakFormat pakFormat, bool debugFile) { _debugFile = debugFile; _pakFormat = pakFormat; _pakFilename = (!_debugFile ? _pakFormat.FullPakFilename : _pakFormat.FullDebugFilename); Dictionary <uint, PakDbgQbKey> qbKeyFilenames = new Dictionary <uint, PakDbgQbKey>(); //if PC or xbox then we need to look up the filename from the debug file //create a PakEditor and load the debug pak, then load all internal debug files, add the first line to our filenames dictionary if (!debugFile) // && (_pakFormat.PakFormatType == PakFormatType.PC || _pakFormat.PakFormatType == PakFormatType.XBox)) { try { _pakFormat.Decompress(); _pakFilename = _pakFormat.FullPakFilename; } catch (Exception ex) { throw new Exception("Decompression Error", ex); } if (_pakFormat.DebugFileExists && _debugFile) // cancer { string debugFileContents; string filename; uint crc; PakEditor pakDebug = new PakEditor(new PakFormat(_pakFormat.FullDebugFilename, "", _pakFormat.FullDebugFilename, _pakFormat.PakFormatType), true); foreach (PakHeaderItem dphi in pakDebug.Headers.Values) { debugFileContents = string.Empty; filename = string.Empty; crc = 0; if (dphi.FullFilenameQbKey != 0) { crc = dphi.FullFilenameQbKey; } else if (dphi.PakFullFileNameQbKey != 0) { crc = dphi.PakFullFileNameQbKey; } else if (dphi.NameOnlyCrc != 0) { crc = dphi.NameOnlyCrc; } if (crc != 0) { filename = crc.ToString("X").PadLeft(8, '0'); if (pakDebug.Headers.ContainsKey(filename.ToLower())) { debugFileContents = pakDebug.ExtractFileToString(filename); if (debugFileContents.Length != 0) { addDebugFilename(debugFileContents, qbKeyFilenames, crc); } } } } } } long minOffset = uint.MaxValue; long maxOffset = 0; _pakHeaders = new Dictionary <string, PakHeaderItem>(); using (Stream st = File.Open(_pakFilename, FileMode.Open, FileAccess.Read)) { _pakFileLength = st.Length; using (BinaryEndianReader br = new BinaryEndianReader(st)) { PakHeaderItem phi = null; QbKey lastQbKey = QbKey.Create("last"); QbKey dotLastQbKey = QbKey.Create(".last"); do { phi = new PakHeaderItem(); phi.HeaderStart = (uint)st.Position; phi.IsStoredInPak = true; phi.FileType = QbKey.Create(br.ReadUInt32(_pakFormat.EndianType)); //if the entry has the file type of last then we're done if (phi.FileType == lastQbKey || phi.FileType == dotLastQbKey) { break; } phi.FileOffset = br.ReadUInt32(_pakFormat.EndianType); phi.FileLength = br.ReadUInt32(_pakFormat.EndianType); phi.PakFullFileNameQbKey = br.ReadUInt32(_pakFormat.EndianType); phi.FullFilenameQbKey = br.ReadUInt32(_pakFormat.EndianType); phi.NameOnlyCrc = br.ReadUInt32(_pakFormat.EndianType); phi.Unknown = br.ReadUInt32(_pakFormat.EndianType); phi.Flags = (PakHeaderFlags)br.ReadUInt32(_pakFormat.EndianType); if ((phi.Flags & PakHeaderFlags.Filename) != PakHeaderFlags.Filename) { uint crc = 0; //get any Crc if (phi.FullFilenameQbKey != 0) { crc = phi.FullFilenameQbKey; } else if (phi.PakFullFileNameQbKey != 0) { crc = phi.PakFullFileNameQbKey; } else if (phi.NameOnlyCrc != 0) { crc = phi.NameOnlyCrc; } if (!debugFile) { uint crc2 = 0; //get a crc that exists in the debug names if (qbKeyFilenames.ContainsKey(phi.FullFilenameQbKey)) { crc2 = phi.FullFilenameQbKey; } else if (qbKeyFilenames.ContainsKey(phi.PakFullFileNameQbKey)) { crc2 = phi.PakFullFileNameQbKey; } else if (qbKeyFilenames.ContainsKey(phi.NameOnlyCrc)) { crc2 = phi.NameOnlyCrc; } //if 0 then get any crc if (crc2 != 0) { phi.Filename = qbKeyFilenames[crc2].Filename; phi.DebugQbKey = qbKeyFilenames[crc2].DebugQbKey; crc = crc2; } } if (phi.Filename == null) { if (crc != 0) { phi.Filename = crc.ToString("X").PadLeft(8, '0'); } else { phi.Filename = string.Format("Unknown={0}", phi.HeaderStart.ToString("X").PadLeft(8, '0')); } } } else { phi.Filename = UTF8Encoding.UTF8.GetString(br.ReadBytes(PakHeaderItem.FileNameMaxLength)).TrimEnd(new char[] { '\0' }); } try { _pakHeaders.Add(phi.Filename.ToLower(), phi); } catch (Exception ex) { throw new ApplicationException(string.Format("Error adding '{0}' to headers: {1}", phi.Filename, ex.Message)); } if (phi.HeaderStart + phi.FileOffset < minOffset) { minOffset = phi.HeaderStart + phi.FileOffset; } if (phi.HeaderStart + phi.FileOffset > maxOffset) { maxOffset = phi.HeaderStart + phi.FileOffset; } }while (1 == 1); //minOffset > fs.Position + 0x100); //drop out if we reach the data //this is a simple hack/fix to cater for padding on PAK files, //it relies on the data starting at the top of the PAB file (which it always does, currently) _requiresPab = maxOffset >= st.Length; if (!debugFile) //only when loading pak { _pakFormat.PakPabMinDataOffset = minOffset; //remember this value } //detect GH5 PAB files if (_requiresPab) { foreach (PakHeaderItem ph in _pakHeaders.Values) { ph.FileOffset += (uint)(_pakFileLength - _pakFormat.PakPabMinDataOffset) - (_pakFormat.PakPabMinDataOffset == 0 ? ph.HeaderStart : 0); //gh5 doesn't hold the offset in relation to the data. } minOffset = _pakFileLength; } } } _qbFilenames = new string[_pakHeaders.Count]; int i = 0; foreach (PakHeaderItem hi in _pakHeaders.Values) { _qbFilenames[i++] = hi.Filename; } StructItemChildrenType s; if (!debugFile) { s = this.StructItemChildrenType; //auto detect the structitemchildren type } }
public NonDebugQbKey(QbKey qbKey, string qbFilename) { this.QbKey = qbKey; this.QbFilename = qbFilename; }
/// <summary> /// Load type data from binary reader /// </summary> public virtual void Construct(BinaryEndianReader br, QbItemType type) { setQbFormat(type); _qbItemType = type; _qbItemValue = this.Root.PakFormat.GetQbItemValue(type, this.Root); _position = this.StreamPos(br) - (1 * 4); //subtract the already read header uint itemQbKeyCrc = 0; #region switch switch (_qbFormat) { case QbFormat.SectionPointer: //Complex section type: // ItemId, FileId, Pointer, Reserved _hasQbKey = true; itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType); _fileId = br.ReadUInt32(this.Root.PakFormat.EndianType); _pointer = br.ReadUInt32(this.Root.PakFormat.EndianType); _reserved = br.ReadUInt32(this.Root.PakFormat.EndianType); _length = (5*4); if (type == QbItemType.SectionScript) _itemCount = 0; else _itemCount = 1; _pointers = new uint[1]; _pointers[0] = _pointer; if (this.StreamPos(br) != _pointer) //pointer test throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer)); break; case QbFormat.SectionValue: //Simple section type: // ItemId, FileId, Value, Reserved _hasQbKey = true; itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType); _fileId = br.ReadUInt32(this.Root.PakFormat.EndianType); _itemCount = 1; _length = (3*4); break; case QbFormat.StructItemPointer: //Complex struct type: // ItemId, Pointer, NextItemPointer _hasQbKey = true; itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType); _pointer = br.ReadUInt32(this.Root.PakFormat.EndianType); _nextItemPointer = br.ReadUInt32(this.Root.PakFormat.EndianType); if (this.StreamPos(br) != _pointer) //pointer test throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer)); _itemCount = 1; _pointers = new uint[1]; _pointers[0] = _pointer; _length = (4*4); break; case QbFormat.StructItemValue: //Simple struct type: // ItemId, Value (4 byte), NextItemPointer _hasQbKey = true; itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType); //always null? if (_itemQbKey == 0 && _qbItemType == QbItemType.StructItemQbKeyString) _itemQbKey = null; _itemCount = 1; _length = (2*4); break; case QbFormat.ArrayPointer: //Complex array type: // ItemCount, Pointer, Pointers - (if length is 1 then pointer points to first item and Pointers are abscent) _hasQbKey = false; _itemCount = br.ReadUInt32(this.Root.PakFormat.EndianType); _pointer = br.ReadUInt32(this.Root.PakFormat.EndianType); itemQbKeyCrc = 0; _length = (3 * 4); if (_pointer != 0 && this.StreamPos(br) != _pointer) //pointer test throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer)); _pointers = new uint[_itemCount]; if (_itemCount == 1) _pointers[0] = _pointer; else if (_itemCount > 1) { for (int i = 0; i < _itemCount; i++) _pointers[i] = br.ReadUInt32(this.Root.PakFormat.EndianType); _length += (_itemCount * 4); } break; case QbFormat.ArrayValue: //Simple array type: // ItemCount, Pointer, Pointers - (if length is 1 then pointer points to first item and Pointers are abscent) _hasQbKey = false; itemQbKeyCrc = 0; _itemCount = br.ReadUInt32(this.Root.PakFormat.EndianType); _length = (2*4); if (_itemCount > 1) { _pointer = br.ReadUInt32(this.Root.PakFormat.EndianType); if (this.StreamPos(br) != _pointer) //pointer test throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer)); _length += (1 * 4); } break; case QbFormat.StructHeader: //when struct array item _hasQbKey = false; _length = (1 * 4); break; case QbFormat.Floats: _hasQbKey = false; _length = (1 * 4); break; case QbFormat.Unknown: _hasQbKey = false; _position += 4; //there is no header so re add the previously removed 4 _length = (0*4); break; default: break; } #endregion if (!_hasQbKey) _itemQbKey = null; else { string debugName = Root.LookupDebugName(itemQbKeyCrc); if (debugName.Length != 0) _itemQbKey = QbKey.Create(itemQbKeyCrc, debugName); else _itemQbKey = QbKey.Create(itemQbKeyCrc); } }
public QbItemBase FindItem(QbKey key, bool recursive) { return this.Root.SearchItems(this.Root, _items, recursive, delegate(QbItemBase item) { return (item.ItemQbKey != 0 && item.ItemQbKey.Crc == key.Crc); }); }
public string GetNotesTextQbFilename(QbKey song) { if (this.Game == Game.GH3_Wii || this.Game == Game.GHA_Wii) { if (!song.HasText) { song = findMissingText(song); if (!song.HasText) throw new ApplicationException(string.Format("Missing text in Song QbKey '{0}'", song.Crc)); } if (this.Game == Game.GHA_Wii) return string.Format(@"songs\{0}.mid_text.qb.{1}", song.Text, FileExtension); else //GH3 return string.Format(@"data/songs/{0}.mid_text.qb.{1}", song.Text, FileExtension); } else if (this.Game == Game.GH3_PS2) { return null; } else throw new ApplicationException(string.Format("'{0}' is not a supported Game type", this.Game.ToString())); }
private static void addSongToSonglist(QbFile qbSongList, QbKey qkSong) { QbItemStruct songs = qbSongList.FindItem(QbKey.Create("permanent_songlist_props"), false) as QbItemStruct; QbItemArray songsList = qbSongList.FindItem(QbKey.Create("gh3_songlist"), false) as QbItemArray; if (songsList != null) { List<QbKey> songlistQk = new List<QbKey>(((QbItemQbKey)songsList.Items[0]).Values); if (!songlistQk.Contains(qkSong)) { songs.AddItem((QbItemBase)SongQb.CreateSong(songs.Root, qkSong.Text)); songlistQk.Add(qkSong); } //update gh3_songlist ((QbItemQbKey)songsList.Items[0]).Values = songlistQk.ToArray(); qbSongList.AlignPointers(); qbSongList.IsValid(); } }
public static void SetGenericItems(QbItemBase item, List<GenericQbItem> gItems) { MemberInfo[] ms = item.GetType().FindMembers(MemberTypes.Property, /*BindingFlags.DeclaredOnly |*/ BindingFlags.Instance | BindingFlags.Public, Type.FilterName, "*"); int i = 0; GenericQbItem gi; List<GenericQbItem> list = null; if (gItems.Count == 0) { //test if this is an array item GenericQbItem gqi = QbFile.CreateGenericArrayItem(item); //null if not an array type if (gqi != null) { //use this item to identify the array to set to 0 items MemberInfo m = Array.Find(ms, delegate(MemberInfo mi) { return (mi.Name == gqi.SourceProperty); }); if (m != null) { Type t = ((PropertyInfo)m).GetValue(item, null).GetType(); if (t == typeof(QbKey[])) ((PropertyInfo)m).SetValue(item, new QbKey[0], null); else if (t == typeof(float[])) ((PropertyInfo)m).SetValue(item, new float[0], null); else if (t == typeof(uint[])) ((PropertyInfo)m).SetValue(item, new uint[0], null); else if (t == typeof(int[])) ((PropertyInfo)m).SetValue(item, new int[0], null); else if (t == typeof(string[])) ((PropertyInfo)m).SetValue(item, new string[0], null); } } } while (i < gItems.Count) { gi = gItems[i++]; if (gi.ReadOnly) continue; //list = null; list = new List<GenericQbItem>(); list.Add(gi); while (i < gItems.Count && gi.SourceProperty == gItems[i].SourceProperty) list.Add(gItems[i++]); MemberInfo m = Array.Find(ms, delegate(MemberInfo mi) { return (mi.Name == gi.SourceProperty); }); if (m != null) { Type t = ((PropertyInfo)m).GetValue(item, null).GetType(); if (t == typeof(QbKey[])) { QbKey[] qb = new QbKey[list.Count]; QbKey q; string qS; for (int c = 0; c < list.Count; c++) { q = list[c].ToQbKey(); qS = item.Root.LookupDebugName(q.Crc); if (qS.Length != 0) q = QbKey.Create(q.Crc, qS); qb[c] = q; } ((PropertyInfo)m).SetValue(item, qb, null); } else if (t == typeof(float[])) { float[] f = new float[list.Count]; for (int c = 0; c < list.Count; c++) f[c] = list[c].ToSingle(); ((PropertyInfo)m).SetValue(item, f, null); } else if (t == typeof(uint[])) { uint[] ui = new uint[list.Count]; for (int c = 0; c < list.Count; c++) ui[c] = list[c].ToUInt32(); ((PropertyInfo)m).SetValue(item, ui, null); } else if (t == typeof(int[])) { int[] si = new int[list.Count]; for (int c = 0; c < list.Count; c++) si[c] = list[c].ToInt32(); ((PropertyInfo)m).SetValue(item, si, null); } else if (t == typeof(string[])) { string[] s = new string[list.Count]; for (int c = 0; c < list.Count; c++) s[c] = list[c].ToString(); ((PropertyInfo)m).SetValue(item, s, null); } else if (t == typeof(QbKey)) { QbKey q = gi.ToQbKey(); string qS = item.Root.LookupDebugName(q.Crc); if (qS.Length != 0) q = QbKey.Create(q.Crc, qS); ((PropertyInfo)m).SetValue(item, q, null); } else if (t == typeof(float)) ((PropertyInfo)m).SetValue(item, gi.ToSingle(), null); else if (t == typeof(uint)) ((PropertyInfo)m).SetValue(item, gi.ToUInt32(), null); else if (t == typeof(int)) ((PropertyInfo)m).SetValue(item, gi.ToInt32(), null); else if (t == typeof(string)) ((PropertyInfo)m).SetValue(item, gi.ToString(), null); else if (t == typeof(byte[])) ((PropertyInfo)m).SetValue(item, gi.ToByteArray(), null); else { throw new ApplicationException(string.Format("DataType {0} not supported.", t.Name)); } } } }
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)); }
/// <summary> /// Add the non debug item to the user defined list if it's not already there /// </summary> /// <param name="qbKey"></param> /// <param name="qbFilename"></param> /// <param name="qbfile"></param> /// <returns>True if crc already exists with different text.</returns> public string AddNonDebugQbKey(QbKey qbKey, string qbFilename, QbFile qbfile) { //check that it's not already in the real debug file if (qbKey.HasText) { string t = string.Empty; if (qbfile != null) t = qbfile.LookupDebugName(qbKey.Crc, false); //it's in the debug file if (t.Length != 0) { if (t != qbKey.Text) return t; } else { //check that it's not in the user debug file if ( GetNonDebugQbKey(qbKey.Crc, qbFilename) == null) { if (_qbKeys == null) _qbKeys = new List<NonDebugQbKey>(); _qbKeys.Add(new NonDebugQbKey(qbKey, qbFilename)); } } } return string.Empty; }
public static void SetGenericItems(QbItemBase item, List <GenericQbItem> gItems) { MemberInfo[] ms = item.GetType().FindMembers(MemberTypes.Property, /*BindingFlags.DeclaredOnly |*/ BindingFlags.Instance | BindingFlags.Public, Type.FilterName, "*"); int i = 0; GenericQbItem gi; List <GenericQbItem> list = null; if (gItems.Count == 0) { //test if this is an array item GenericQbItem gqi = QbFile.CreateGenericArrayItem(item); //null if not an array type if (gqi != null) { //use this item to identify the array to set to 0 items MemberInfo m = Array.Find(ms, delegate(MemberInfo mi) { return(mi.Name == gqi.SourceProperty); }); if (m != null) { Type t = ((PropertyInfo)m).GetValue(item, null).GetType(); if (t == typeof(QbKey[])) { ((PropertyInfo)m).SetValue(item, new QbKey[0], null); } else if (t == typeof(float[])) { ((PropertyInfo)m).SetValue(item, new float[0], null); } else if (t == typeof(uint[])) { ((PropertyInfo)m).SetValue(item, new uint[0], null); } else if (t == typeof(int[])) { ((PropertyInfo)m).SetValue(item, new int[0], null); } else if (t == typeof(string[])) { ((PropertyInfo)m).SetValue(item, new string[0], null); } } } } while (i < gItems.Count) { gi = gItems[i++]; if (gi.ReadOnly) { continue; } //list = null; list = new List <GenericQbItem>(); list.Add(gi); while (i < gItems.Count && gi.SourceProperty == gItems[i].SourceProperty) { list.Add(gItems[i++]); } MemberInfo m = Array.Find(ms, delegate(MemberInfo mi) { return(mi.Name == gi.SourceProperty); }); if (m != null) { Type t = ((PropertyInfo)m).GetValue(item, null).GetType(); if (t == typeof(QbKey[])) { QbKey[] qb = new QbKey[list.Count]; QbKey q; string qS; for (int c = 0; c < list.Count; c++) { q = list[c].ToQbKey(); qS = item.Root.LookupDebugName(q.Crc); if (qS.Length != 0) { q = QbKey.Create(q.Crc, qS); } qb[c] = q; } ((PropertyInfo)m).SetValue(item, qb, null); } else if (t == typeof(float[])) { float[] f = new float[list.Count]; for (int c = 0; c < list.Count; c++) { f[c] = list[c].ToSingle(); } ((PropertyInfo)m).SetValue(item, f, null); } else if (t == typeof(uint[])) { uint[] ui = new uint[list.Count]; for (int c = 0; c < list.Count; c++) { ui[c] = list[c].ToUInt32(); } ((PropertyInfo)m).SetValue(item, ui, null); } else if (t == typeof(int[])) { int[] si = new int[list.Count]; for (int c = 0; c < list.Count; c++) { si[c] = list[c].ToInt32(); } ((PropertyInfo)m).SetValue(item, si, null); } else if (t == typeof(string[])) { string[] s = new string[list.Count]; for (int c = 0; c < list.Count; c++) { s[c] = list[c].ToString(); } ((PropertyInfo)m).SetValue(item, s, null); } else if (t == typeof(QbKey)) { QbKey q = gi.ToQbKey(); string qS = item.Root.LookupDebugName(q.Crc); if (qS.Length != 0) { q = QbKey.Create(q.Crc, qS); } ((PropertyInfo)m).SetValue(item, q, null); } else if (t == typeof(float)) { ((PropertyInfo)m).SetValue(item, gi.ToSingle(), null); } else if (t == typeof(uint)) { ((PropertyInfo)m).SetValue(item, gi.ToUInt32(), null); } else if (t == typeof(int)) { ((PropertyInfo)m).SetValue(item, gi.ToInt32(), null); } else if (t == typeof(string)) { ((PropertyInfo)m).SetValue(item, gi.ToString(), null); } else if (t == typeof(byte[])) { ((PropertyInfo)m).SetValue(item, gi.ToByteArray(), null); } else { throw new ApplicationException(string.Format("DataType {0} not supported.", t.Name)); } } } }
private QbKey findMissingText(QbKey song) { for (int i = 1; i < 100; i++) { if (song.Crc == QbKey.Create(string.Format("theghost{0}", i.ToString().PadLeft(3, '0'))).Crc) song = QbKey.Create(string.Format("theghost{0}", i.ToString().PadLeft(3, '0'))); } return song; }
private PakHeaderItem createBlankFile(string newQbFilename, QbKey itemType, bool filenameInHeader) { //update the filename in the collection List <PakHeaderItem> hd = new List <PakHeaderItem>(_pakHeaders.Values); PakHeaderItem newHdr = new PakHeaderItem(); newHdr.FileLength = 0; // (uint)(new FileInfo(localFilename)).Length; newHdr.FileOffset = hd[0].FileOffset + (uint)(filenameInHeader ? PakHeaderItem.FullHeaderLength : 0x20); newHdr.Flags = (PakHeaderFlags)(filenameInHeader ? PakHeaderFlags.Filename : 0); newHdr.HeaderStart = 0; newHdr.IsStoredInPak = true; newHdr.Filename = newQbFilename; newHdr.FileType = itemType; hd.Insert(0, newHdr); //update the filename in the collection bool pastNew = false; Dictionary <string, PakHeaderItem> p = new Dictionary <string, PakHeaderItem>(_pakHeaders.Count); bool hasFoundMatch = filenameInHeader; foreach (PakHeaderItem ph in hd) { //small hack to determine which items need to be filled - Find another header with if (!hasFoundMatch && ((ph.Flags & PakHeaderFlags.Filename) != PakHeaderFlags.Filename) && ph != newHdr) { newHdr.SetFilename(newQbFilename, itemType, _pakFormat.FileExtension, ph); hasFoundMatch = true; } if (pastNew) { ph.HeaderStart += (uint)(filenameInHeader ? PakHeaderItem.FullHeaderLength : 0x20); } else if (ph != newHdr) { ph.FileOffset += (uint)(filenameInHeader ? PakHeaderItem.FullHeaderLength : 0x20); } else // (ph == newHdr) { pastNew = true; } p.Add(ph.Filename.ToLower(), ph); } if (!hasFoundMatch) { newHdr.SetFilename(newQbFilename, itemType, _pakFormat.FileExtension, null); } _pakFileLength += (uint)(filenameInHeader ? PakHeaderItem.FullHeaderLength : PakHeaderItem.FullHeaderLength - PakHeaderItem.FileNameMaxLength); _pakHeaders = p; string newPakFilename = string.Format("{0}_{1}", _pakFilename, Guid.NewGuid().ToString("N")); using (FileStream fsO = File.Open(newPakFilename, FileMode.CreateNew)) { using (BinaryEndianWriter bw = new BinaryEndianWriter(fsO)) { writeHeaderItem(bw, newHdr); using (FileStream fsI = File.OpenRead(_pakFilename)) copyData(fsI, fsO, new FileInfo(_pakFilename).Length); } } File.Delete(_pakFilename); File.Move(newPakFilename, _pakFilename); return(newHdr); }
/// <summary> /// Converts the qbkey to the enum /// </summary> /// <param name="fileType"></param> /// <returns>The enum item or Other if not in enum</returns> public static PakItemType FileTypeToPakItemType(QbKey fileType) { if (fileType == _itemTypes[0].Crc) //.qb return PakItemType.Qb; else if (fileType == _itemTypes[1].Crc) //.sqb return PakItemType.Sqb; else if (fileType == _itemTypes[2].Crc) //.dbg return PakItemType.Debug; else if (fileType == _itemTypes[3].Crc) //.img return PakItemType.Image; else if (fileType == _itemTypes[4].Crc) //.mqb return PakItemType.Midi; else if (fileType == _itemTypes[5].Crc) //.tex return PakItemType.Texture; else if (fileType == _itemTypes[6].Crc) //.skin return PakItemType.Skin; else return PakItemType.Other; }
private void replaceFile(string qbFilename, long newLength, bool remove, WriteDataToStream callback) { int filePad = _pakFormat.FilePadSize; PakHeaderItem phi = null; if (_pakHeaders.ContainsKey(qbFilename.ToLower())) { phi = _pakHeaders[qbFilename.ToLower()]; } else { string fqk = QbKey.Create(qbFilename).Crc.ToString("X").PadLeft(8, '0').ToLower(); if (_pakHeaders.ContainsKey(fqk)) { phi = _pakHeaders[fqk]; } } if (phi != null) { long pad = filePad - (newLength % filePad); if (pad == filePad) { pad = 0; } string newPakFilename = string.Format("{0}_{1}", _pakFormat.FullPakFilename, Guid.NewGuid().ToString("N")); string newPabFilename = string.Format("{0}_{1}", _pakFormat.FullPabFilename, Guid.NewGuid().ToString("N")); uint minOffset = uint.MaxValue; bool itemFound = false; uint nextOffset = 0; foreach (PakHeaderItem ph in _pakHeaders.Values) { if (itemFound) { nextOffset = ph.FileOffset + ph.HeaderStart; itemFound = false; //don't enter this if again } if (object.ReferenceEquals(phi, ph)) { itemFound = true; } if (ph.HeaderStart + ph.FileOffset < minOffset) { minOffset = ph.HeaderStart + ph.FileOffset; } } uint lastItemPad = 0; int repPad = filePad - ((int)phi.FileLength % filePad); if (repPad == filePad) { repPad = 0; } //previously badly padded or last file if (nextOffset != 0 && (nextOffset - (phi.FileOffset + phi.HeaderStart)) % filePad != 0) { repPad = (int)((nextOffset - (phi.FileOffset + phi.HeaderStart)) - phi.FileLength); } //position of the LAST header item long lastHeaderPos = 0; //the length of all the headers (like pak when there's a pab) with padding long allHeadersLen = minOffset; //position in the input file where our file is to be replaced (not including header pos) long fileReplacePos = (phi.HeaderStart + phi.FileOffset) - allHeadersLen; //position in the input file after the file that is to be replaced long fileAfterReplacePos = fileReplacePos + phi.FileLength + repPad; //item size before modifying header //open input pak using (FileStream fsPakI = File.Open(_pakFilename, FileMode.Open, FileAccess.Read)) { using (BinaryEndianReader brPakI = new BinaryEndianReader(fsPakI)) { //open output pak temp file using (FileStream fsPakO = File.Create(newPakFilename)) { using (BinaryEndianWriter bwPakO = new BinaryEndianWriter(fsPakO)) { long diffLen = 0; //do not compensate for missing header when using zlib compression as the header is padded if (remove && _pakFormat.CompressionType != CompressionType.ZLibChunk) //we need to cater for the header being removed on all items before it. { diffLen = PakHeaderItem.FullHeaderLength; if ((phi.Flags & PakHeaderFlags.Filename) != PakHeaderFlags.Filename) { diffLen -= PakHeaderItem.FileNameMaxLength; } } //write out the headers foreach (PakHeaderItem ph in _pakHeaders.Values) { //apply offset change before finding file to be replaced //this will prevents the offset of the replaced file being changed ph.FileOffset = (uint)(ph.FileOffset - (long)diffLen); if (object.ReferenceEquals(phi, ph)) { if (remove) { long remPad = filePad - (phi.FileLength % filePad); if (remPad == filePad) { remPad = 0; } diffLen = phi.FileLength + remPad; //now cater for the difference in file size } else { diffLen = (long)((ph.FileLength + repPad) - (newLength + pad)); ph.FileLength = (uint)newLength; //0 for remove } } lastHeaderPos += PakHeaderItem.FullHeaderLength; if (!(remove && object.ReferenceEquals(phi, ph))) { writeHeaderItem(bwPakO, ph); } if ((ph.Flags & PakHeaderFlags.Filename) != PakHeaderFlags.Filename) { lastHeaderPos -= PakHeaderItem.FileNameMaxLength; } } //Move to the "last" header fsPakI.Seek(lastHeaderPos, SeekOrigin.Begin); //write out "last" HeaderType bwPakO.Write(brPakI.ReadBytes(4)); //Modify and write the offset of the "last" header's data uint lastOffset = brPakI.ReadUInt32(_pakFormat.EndianType); lastOffset = (uint)(lastOffset - (long)diffLen); //fix bad padding on last file if (nextOffset == 0 && ((lastOffset - (phi.FileOffset + phi.HeaderStart) % filePad) % filePad) != 0) { lastItemPad = (uint)filePad - (uint)(lastOffset % filePad); lastOffset += lastItemPad; } bwPakO.Write(lastOffset, _pakFormat.EndianType); //write out the end of the last header copyData(fsPakI, fsPakO, allHeadersLen - fsPakI.Position); } } } } //open input pak using (FileStream fsPakI = File.Open(_requiresPab ? _pakFormat.FullPabFilename : _pakFilename, FileMode.Open, FileAccess.Read)) { using (BinaryEndianReader brPakI = new BinaryEndianReader(fsPakI)) { //open output pak temp file using (FileStream fsPakO = _requiresPab ? File.Open(newPabFilename, FileMode.Create) : File.Open(newPakFilename, FileMode.Append)) { using (BinaryEndianWriter bwPakO = new BinaryEndianWriter(fsPakO)) { if (!_requiresPab) { fsPakI.Seek(allHeadersLen, SeekOrigin.Begin); } //Write out the data starting from the last header to the start of the file to be replaced (minus the length of the type and offset) copyData(fsPakI, fsPakO, fileReplacePos); //Write the new file into the pak file int pos = (int)fsPakO.Position; callback(fsPakO); if (pad != 0) { fsPakO.Write(new byte[pad], 0, (int)pad); } if (!_requiresPab) { fileAfterReplacePos += allHeadersLen; } if (lastItemPad != 0) { fileAfterReplacePos -= lastItemPad; // a bit of a hack as this was not applied when this var was set as we didn't know the values } //write the remainder of source the pak file fsPakI.Seek(fileAfterReplacePos, SeekOrigin.Begin); copyData(fsPakI, fsPakO, fsPakI.Length - fileAfterReplacePos); fsPakO.Flush(); } } } } fixUncompressedFileLengths(newPakFilename, newPabFilename); File.Delete(_pakFilename); File.Move(newPakFilename, _pakFilename); if (_requiresPab) { File.Delete(_pakFormat.FullPabFilename); File.Move(newPabFilename, _pakFormat.FullPabFilename); } _pakFormat.Compress(); } else { throw new ApplicationException(string.Format("'{0}' does not exist in '{1}'", qbFilename, _pakFilename)); } }
/// <summary> /// Rename the filename and set the data types /// </summary> /// <param name="newFullQbFilename">Full QB filename</param> /// <param name="fileType">.qb or .sqb=QB, .mqb=mid, .img=img .dbg=dbg etc</param> /// <param name="extension">.ngc for Wii for example</param> /// <param name="baseOn">base the qbKeys that are present on the passed item</param> public void SetFilename(string newFullQbFilename, QbKey itemType, string extension, PakHeaderItem baseOn) { if (newFullQbFilename.Length > PakHeaderItem.FileNameMaxLength) throw new ApplicationException("newQbFilename is too long"); if (!itemType.HasText || itemType.Text.Length == 0) throw new ApplicationException("fileType is not recognised"); //filename is stored in the header if ((this.Flags & PakHeaderFlags.Filename) == PakHeaderFlags.Filename) { this.Filename = newFullQbFilename; this.FullFilenameQbKey = 0; } else { this.Filename = QbKey.Create(newFullQbFilename).Crc.ToString("X").PadLeft(8, '0').ToLower(); if (baseOn == null || baseOn.FullFilenameQbKey != 0) this.FullFilenameQbKey = QbKey.Create(newFullQbFilename).Crc; else this.FullFilenameQbKey = 0; } string[] pts = newFullQbFilename.Split('.'); string nameOnly = pts[0]; if (baseOn == null || baseOn.FullFilenameQbKey != 0) this.NameOnlyCrc = QbKey.Create(nameOnly).Crc; else this.NameOnlyCrc = 0; this.FileType = itemType; if (baseOn == null || baseOn.PakFullFileNameQbKey != 0) this.PakFullFileNameQbKey = QbKey.Create(newFullQbFilename).Crc; else this.PakFullFileNameQbKey = 0; }
/// <summary> /// Load type data from binary reader /// </summary> public virtual void Create(QbItemType type) { setQbFormat(type); _qbItemType = type; _qbItemValue = this.Root.PakFormat.GetQbItemValue(type, this.Root); _position = 0; //unknown #region switch switch (_qbFormat) { case QbFormat.SectionPointer: //Complex section type: // ItemId, FileId, Pointer, Reserved _itemQbKey = QbKey.Create(0); _fileId = this.Root.FileId; _pointer = 0; _reserved = 0; _length = (5 * 4); _itemCount = 1; _pointers = new uint[1]; _pointers[0] = 0; break; case QbFormat.SectionValue: //Simple section type: // ItemId, FileId, Value, Reserved _itemQbKey = QbKey.Create(0); _fileId = this.Root.FileId; _itemCount = 1; _length = (4 * 4); break; case QbFormat.StructItemPointer: //Complex struct type: // ItemId, Pointer, NextItemPointer _itemQbKey = QbKey.Create(0); _pointer = 0; _nextItemPointer = 0; _itemCount = 1; _pointers = new uint[1]; _pointers[0] = _pointer; _length = (4 * 4); break; case QbFormat.StructItemValue: //Simple struct type: // ItemId, Value (4 byte), NextItemPointer _itemQbKey = QbKey.Create(0); //always null? _itemCount = 1; _length = (3 * 4); break; case QbFormat.ArrayPointer: //Complex array type: // ItemCount, Pointer, Pointers - (if length is 1 then pointer points to first item and Pointers are abscent) _itemCount = 0; _pointer = 0; _itemQbKey = null; _length = (3 * 4); _pointers = new uint[_itemCount]; break; case QbFormat.ArrayValue: //Simple array type: // ItemCount, Pointer, Pointers - (if length is 1 then pointer points to first item and Pointers are abscent) _itemQbKey = null; _itemCount = 0; _length = (2 * 4); break; case QbFormat.StructHeader: //when struct array item _length = (1 * 4); break; case QbFormat.Floats: _itemCount = 2; _length = (1 * 4); break; case QbFormat.Unknown: _position += 4; //there is no header so re add the previously removed 4 _length = (0 * 4); break; default: break; } #endregion setChildMode(); _itemCount = (uint)this.CalcItemCount(); }
private bool removeBonusSong(QbFile storeQb, QbKey songId) { //find bonus song list QbItemArray bonusSongs = storeQb.FindItem(true, delegate(QbItemBase qib) { return (qib.QbItemType == QbItemType.StructItemArray && qib.ItemQbKey == QbKey.Create("songs")); }) as QbItemArray; //remove bonus song from list List<QbKey> songs = new List<QbKey>((bonusSongs.Items[0] as QbItemQbKey).Values); if (songs.Exists(delegate(QbKey qk) { return qk.Crc == songId.Crc; })) { this.RemoveBonusSongQbItems(songId, storeQb); return true; } else return false; }
/// <summary> /// Convert text representations /// </summary> /// <param name="text"></param> /// <param name="toType">Type to convert to</param> /// <returns></returns> private string convert(Type toType) { byte[] b = null; float f; uint u; int i; string result = _value; if (_currType == null) _currType = _type; if (_currType == toType) return _value; if (!this.CanConvertTo(toType)) return _value; //if QBKey then swap between Hex and String if (_type == typeof(QbKey)) { QbKey qb = QbKey.Create(_value); if (_currType == typeof(byte[]) && toType == typeof(string)) { if (_qbKey == qb) return _qbKey.ToString(); else return qb.ToString(); } else if (_currType == typeof(string) && toType == typeof(byte[])) { if (_value.Trim().Length != 0) _qbKey = QbKey.Create(_value); return _qbKey.Crc.ToString("X").PadLeft(8, '0'); } else return _value; } //get the data into a byte array if (_currType == typeof(float)) { if (float.TryParse(_value, out f)) b = BitConverter.GetBytes(f); } else if (_currType == typeof(uint)) { if (uint.TryParse(_value, out u)) b = BitConverter.GetBytes(u); } else if (_currType == typeof(int)) { if (int.TryParse(_value, out i)) b = BitConverter.GetBytes(i); } else if (_currType == typeof(byte[])) { if (_value.Length > 2) { b = new byte[_value.Length / 2]; for (int c = 0; c < _value.Length; c += 2) b[c / 2] = byte.Parse(_value.Substring(c, 2), System.Globalization.NumberStyles.HexNumber); if (_typeNumeric && BitConverter.IsLittleEndian) Array.Reverse(b); } } else if (_currType == typeof(string)) { b = Encoding.Default.GetBytes(_value); } //else // throw new ArgumentOutOfRangeException(string.Format("{0} is not supported", _currType.FullName)); if (b != null) { //convert the data to the new type if (toType == typeof(float)) { f = BitConverter.ToSingle(b, 0); result = f.ToString(); } else if (toType == typeof(uint)) { u = BitConverter.ToUInt32(b, 0); result = u.ToString(); } else if (toType == typeof(int)) { i = BitConverter.ToInt32(b, 0); result = i.ToString(); } else if (toType == typeof(byte[])) { StringBuilder sb = new StringBuilder(); if (_typeNumeric && BitConverter.IsLittleEndian) Array.Reverse(b); foreach (byte x in b) sb.Append(x.ToString("X").PadLeft(2, '0')); result = sb.ToString(); } else if (toType == typeof(string)) { result = Encoding.Default.GetString(b); } //else // throw new ArgumentOutOfRangeException(string.Format("{0} is not supported", toType.FullName)); } return result; }
private void removeSongFromSonglist(QbFile qbSongList, QbKey qkSong) { QbItemArray songsList = qbSongList.FindItem(QbKey.Create("gh3_songlist"), false) as QbItemArray; if (songsList != null) { List<QbKey> songlistQk = new List<QbKey>(((QbItemQbKey)songsList.Items[0]).Values); if (songlistQk.Contains(qkSong)) songlistQk.Remove(qkSong); //update gh3_songlist ((QbItemQbKey)songsList.Items[0]).Values = songlistQk.ToArray(); qbSongList.AlignPointers(); qbSongList.IsValid(); } }
/// <summary> /// Convert text representations /// </summary> /// <param name="text"></param> /// <param name="toType">Type to convert to</param> /// <returns></returns> private string convert(Type toType) { byte[] b = null; float f; uint u; int i; string result = _value; if (_currType == null) { _currType = _type; } if (_currType == toType) { return(_value); } if (!this.CanConvertTo(toType)) { return(_value); } //if QBKey then swap between Hex and String if (_type == typeof(QbKey)) { QbKey qb = QbKey.Create(_value); if (_currType == typeof(byte[]) && toType == typeof(string)) { if (_qbKey == qb) { return(_qbKey.ToString()); } else { return(qb.ToString()); } } else if (_currType == typeof(string) && toType == typeof(byte[])) { if (_value.Trim().Length != 0) { _qbKey = QbKey.Create(_value); } return(_qbKey.Crc.ToString("X").PadLeft(8, '0')); } else { return(_value); } } //get the data into a byte array if (_currType == typeof(float)) { if (float.TryParse(_value, out f)) { b = BitConverter.GetBytes(f); } } else if (_currType == typeof(uint)) { if (uint.TryParse(_value, out u)) { b = BitConverter.GetBytes(u); } } else if (_currType == typeof(int)) { if (int.TryParse(_value, out i)) { b = BitConverter.GetBytes(i); } } else if (_currType == typeof(byte[])) { if (_value.Length > 2) { b = new byte[_value.Length / 2]; for (int c = 0; c < _value.Length; c += 2) { b[c / 2] = byte.Parse(_value.Substring(c, 2), System.Globalization.NumberStyles.HexNumber); } if (_typeNumeric && BitConverter.IsLittleEndian) { Array.Reverse(b); } } } else if (_currType == typeof(string)) { b = Encoding.Default.GetBytes(_value); } //else // throw new ArgumentOutOfRangeException(string.Format("{0} is not supported", _currType.FullName)); if (b != null) { //convert the data to the new type if (toType == typeof(float)) { f = BitConverter.ToSingle(b, 0); result = f.ToString(); } else if (toType == typeof(uint)) { u = BitConverter.ToUInt32(b, 0); result = u.ToString(); } else if (toType == typeof(int)) { i = BitConverter.ToInt32(b, 0); result = i.ToString(); } else if (toType == typeof(byte[])) { StringBuilder sb = new StringBuilder(); if (_typeNumeric && BitConverter.IsLittleEndian) { Array.Reverse(b); } foreach (byte x in b) { sb.Append(x.ToString("X").PadLeft(2, '0')); } result = sb.ToString(); } else if (toType == typeof(string)) { result = Encoding.Default.GetString(b); } //else // throw new ArgumentOutOfRangeException(string.Format("{0} is not supported", toType.FullName)); } return(result); }
/// <summary> /// Add song to bonus list and shop /// </summary> /// <param name="songQk"></param> public void BonusSongAddToGame(QbFile qbStore, QbFile qbSongList, QbKey qkSong, bool insertAdd) { //is this song (this) in the bonus tiers already? bool found = getAllBonusSongs(qbStore).Contains(qkSong); addSongToSonglist(qbSongList, qkSong); this.AddBonusSongQbItems(qkSong, qbStore, insertAdd); }
private void addBonusSongNotes(DirectoryInfo rootPath, QbKey source, QbKey dest, PakEditor qbPak) { string srcFolder = string.Format(@"{0}\songs", rootPath.FullName.TrimEnd('\\')); string srcMask = string.Format(@"{0}*.pak.ngc", source.Text); string[] srcFi = Directory.GetFiles(srcFolder, srcMask, SearchOption.TopDirectoryOnly); if (_project.GameInfo.Game == Game.GHA_Wii) { //GHA holds the section text in the main qb.pak file string destNotes = string.Format(@"songs\{0}.mid_text.qb.ngc", dest.Text); if (!qbPak.Headers.ContainsKey(destNotes.ToLower())) { QbFile qbNotes = qbPak.ReadQbFile(string.Format(@"songs\{0}.mid_text.qb.ngc", source.Text)); //copy notes section qb file to new file in qb.pak.ngc qbPak.AddFile(qbNotes, destNotes, QbKey.Create(".qb"), true); } } foreach (string src in srcFi) { FileInfo srcF = new FileInfo(src); string dst = string.Format(@"{0}\{1}{2}", srcF.Directory.FullName.TrimEnd('\\'), dest.Text, srcF.Name.Substring(source.Text.Length)); //skip if exists if (File.Exists(dst) || !Regex.IsMatch(src, string.Format(@"{0}(|_.)\.pak\.ngc$", source.Text))) //only allow "" or _<fgis> continue; File.Copy(src, dst, true); PakFormat pf = new PakFormat(dst, string.Empty, string.Empty, PakFormatType.Wii, false); PakEditor pe = new PakEditor(pf, false); string qbDst; QbFile qb; Dictionary<uint, string> srcQk; string dstS; foreach (string qbSrc in pe.QbFilenames) { qbDst = qbSrc.ToLower().Replace(source.Text.ToLower(), dest.Text.ToLower()); pe.RenameFile(qbSrc, qbDst, QbKey.Create(".mqb")); if (!qbSrc.Contains(".mid_text.")) { //map the section QbKeys qb = pe.ReadQbFile(qbDst); srcQk = getMidItems(source.Text); foreach (QbItemBase qib in qb.Items) { if (qib.ItemQbKey != null) { if (srcQk.ContainsKey(qib.ItemQbKey.Crc)) { dstS = string.Format("{0}{1}", dest.Text, srcQk[qib.ItemQbKey.Crc].Substring(source.Text.Length)); qib.ItemQbKey = QbKey.Create(dstS); } //else // throw new ApplicationException("Item QBKey not recognised"); } } pe.ReplaceFile(qbDst, qb); } } } }
/// <summary> /// Add a new file in to the PAK, currently just inserts it at the start. /// </summary> /// <param name="newFullQbFilename">Full QB filename</param> /// <param name="fileType">.qb or .sqb=QB, .mqb=mid, .img=img .dbg=dbg etc</param> /// <param name="extension">.qb.ngc for Wii for example</param> public void AddFile(QbFile newQbFile, string newQbFilename, QbKey itemType, bool filenameInHeader) { createBlankFile(newQbFilename, itemType, filenameInHeader); this.ReplaceFile(newQbFilename, newQbFile); }
/// <summary> /// Attempts to take a qbkey key without any text and lookup a named file type /// </summary> /// <returns></returns> public static QbKey LookupFileType(QbKey fileType) { foreach (QbKey k in _itemTypes) { if (fileType.Crc == k.Crc) return k; } return fileType; }
private void createBonusSongAudio(DirectoryInfo rootPath, string xboxWav, QbKey dest) { string dat = string.Format(@"{0}\music\{1}.dat.ngc", rootPath.FullName.TrimEnd('\\'), dest.Text); string wad = string.Format(@"{0}\music\{1}.wad.ngc", rootPath.FullName.TrimEnd('\\'), dest.Text); if (!File.Exists(dat) || !File.Exists(wad)) DatWad.CreateDatWad(dest, _project.FileManager.PakFormat.EndianType, dat, wad, xboxWav, xboxWav, xboxWav, xboxWav); }
private QbItemStruct findTierProgStruct(QbKey firstChild, QbItemArray careerProgressionStruct) { QbKey tname = QbKey.Create("name"); return careerProgressionStruct.FindItem(true, delegate(QbItemBase qib) { QbItemStruct qs = (qib as QbItemStruct); if (qs != null && qs.Items.Count != 0 && qs.Items[0] is QbItemQbKey) { QbItemQbKey qk = (QbItemQbKey)qs.Items[0]; if (qk.ItemQbKey.Crc == tname.Crc && qk.Values[0].Crc == firstChild.Crc) return true; } return false; }) as QbItemStruct; }
/// <summary> /// Load type data from binary reader /// </summary> public virtual void Construct(BinaryEndianReader br, QbItemType type) { setQbFormat(type); _qbItemType = type; _qbItemValue = this.Root.PakFormat.GetQbItemValue(type, this.Root); _position = this.StreamPos(br) - (1 * 4); //subtract the already read header uint itemQbKeyCrc = 0; #region switch switch (_qbFormat) { case QbFormat.SectionPointer: //Complex section type: // ItemId, FileId, Pointer, Reserved _hasQbKey = true; itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType); _fileId = br.ReadUInt32(this.Root.PakFormat.EndianType); _pointer = br.ReadUInt32(this.Root.PakFormat.EndianType); _reserved = br.ReadUInt32(this.Root.PakFormat.EndianType); _length = (5 * 4); if (type == QbItemType.SectionScript) { _itemCount = 0; } else { _itemCount = 1; } _pointers = new uint[1]; _pointers[0] = _pointer; if (this.StreamPos(br) != _pointer) //pointer test { throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer)); } break; case QbFormat.SectionValue: //Simple section type: // ItemId, FileId, Value, Reserved _hasQbKey = true; itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType); _fileId = br.ReadUInt32(this.Root.PakFormat.EndianType); _itemCount = 1; _length = (3 * 4); break; case QbFormat.StructItemPointer: //Complex struct type: // ItemId, Pointer, NextItemPointer _hasQbKey = true; itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType); _pointer = br.ReadUInt32(this.Root.PakFormat.EndianType); _nextItemPointer = br.ReadUInt32(this.Root.PakFormat.EndianType); if (this.StreamPos(br) != _pointer) //pointer test { throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer)); } _itemCount = 1; _pointers = new uint[1]; _pointers[0] = _pointer; _length = (4 * 4); break; case QbFormat.StructItemValue: //Simple struct type: // ItemId, Value (4 byte), NextItemPointer _hasQbKey = true; itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType); //always null? if (_itemQbKey == 0 && _qbItemType == QbItemType.StructItemQbKeyString) { _itemQbKey = null; } _itemCount = 1; _length = (2 * 4); break; case QbFormat.ArrayPointer: //Complex array type: // ItemCount, Pointer, Pointers - (if length is 1 then pointer points to first item and Pointers are abscent) _hasQbKey = false; _itemCount = br.ReadUInt32(this.Root.PakFormat.EndianType); _pointer = br.ReadUInt32(this.Root.PakFormat.EndianType); itemQbKeyCrc = 0; _length = (3 * 4); if (_pointer != 0 && this.StreamPos(br) != _pointer) //pointer test { throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer)); } _pointers = new uint[_itemCount]; if (_itemCount == 1) { _pointers[0] = _pointer; } else if (_itemCount > 1) { for (int i = 0; i < _itemCount; i++) { _pointers[i] = br.ReadUInt32(this.Root.PakFormat.EndianType); } _length += (_itemCount * 4); } break; case QbFormat.ArrayValue: //Simple array type: // ItemCount, Pointer, Pointers - (if length is 1 then pointer points to first item and Pointers are abscent) _hasQbKey = false; itemQbKeyCrc = 0; _itemCount = br.ReadUInt32(this.Root.PakFormat.EndianType); _length = (2 * 4); if (_itemCount > 1) { _pointer = br.ReadUInt32(this.Root.PakFormat.EndianType); if (this.StreamPos(br) != _pointer) //pointer test { throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer)); } _length += (1 * 4); } break; case QbFormat.StructHeader: //when struct array item _hasQbKey = false; _length = (1 * 4); break; case QbFormat.Floats: _hasQbKey = false; _length = (1 * 4); break; case QbFormat.Unknown: _hasQbKey = false; _position += 4; //there is no header so re add the previously removed 4 _length = (0 * 4); break; default: break; } #endregion if (!_hasQbKey) { _itemQbKey = null; } else { string debugName = Root.LookupDebugName(itemQbKeyCrc); if (debugName.Length != 0) { _itemQbKey = QbKey.Create(itemQbKeyCrc, debugName); } else { _itemQbKey = QbKey.Create(itemQbKeyCrc); } } }