diff --git a/QueenBee/InfoForm.Designer.cs b/QueenBee/InfoForm.Designer.cs index c22e973..777668d 100644 --- a/QueenBee/InfoForm.Designer.cs +++ b/QueenBee/InfoForm.Designer.cs @@ -53,7 +53,7 @@ private void InitializeComponent() this.tabs.Location = new System.Drawing.Point(2, 5); this.tabs.Name = "tabs"; this.tabs.SelectedIndex = 0; - this.tabs.Size = new System.Drawing.Size(671, 536); + this.tabs.Size = new System.Drawing.Size(787, 536); this.tabs.TabIndex = 0; // // tabPage1 @@ -62,7 +62,7 @@ private void InitializeComponent() this.tabPage1.Location = new System.Drawing.Point(4, 22); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3); - this.tabPage1.Size = new System.Drawing.Size(663, 510); + this.tabPage1.Size = new System.Drawing.Size(779, 510); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "About"; this.tabPage1.UseVisualStyleBackColor = true; @@ -76,7 +76,7 @@ private void InitializeComponent() this.txtAbout.Location = new System.Drawing.Point(0, 0); this.txtAbout.Name = "txtAbout"; this.txtAbout.ReadOnly = true; - this.txtAbout.Size = new System.Drawing.Size(663, 510); + this.txtAbout.Size = new System.Drawing.Size(779, 510); this.txtAbout.TabIndex = 1; this.txtAbout.Text = ""; // @@ -86,7 +86,7 @@ private void InitializeComponent() this.tabPage2.Location = new System.Drawing.Point(4, 22); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(459, 433); + this.tabPage2.Size = new System.Drawing.Size(779, 510); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Usage"; this.tabPage2.UseVisualStyleBackColor = true; @@ -100,7 +100,7 @@ private void InitializeComponent() this.txtUsage.Location = new System.Drawing.Point(0, 0); this.txtUsage.Name = "txtUsage"; this.txtUsage.ReadOnly = true; - this.txtUsage.Size = new System.Drawing.Size(459, 433); + this.txtUsage.Size = new System.Drawing.Size(779, 510); this.txtUsage.TabIndex = 0; this.txtUsage.Text = ""; // @@ -109,7 +109,7 @@ private void InitializeComponent() this.tabPage3.Controls.Add(this.txtVersionHistory); this.tabPage3.Location = new System.Drawing.Point(4, 22); this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(459, 433); + this.tabPage3.Size = new System.Drawing.Size(779, 510); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "Version History"; this.tabPage3.UseVisualStyleBackColor = true; @@ -123,7 +123,7 @@ private void InitializeComponent() this.txtVersionHistory.Location = new System.Drawing.Point(0, 0); this.txtVersionHistory.Name = "txtVersionHistory"; this.txtVersionHistory.ReadOnly = true; - this.txtVersionHistory.Size = new System.Drawing.Size(459, 433); + this.txtVersionHistory.Size = new System.Drawing.Size(779, 510); this.txtVersionHistory.TabIndex = 0; this.txtVersionHistory.Text = ""; // @@ -131,7 +131,7 @@ private void InitializeComponent() // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(674, 542); + this.ClientSize = new System.Drawing.Size(790, 542); this.Controls.Add(this.tabs); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MaximizeBox = false; diff --git a/QueenBee/InfoForm.cs b/QueenBee/InfoForm.cs index df33e7e..2aff826 100644 --- a/QueenBee/InfoForm.cs +++ b/QueenBee/InfoForm.cs @@ -31,7 +31,7 @@ private void InfoForm_Load(object sender, EventArgs e) \lang1024\f1\'b7\tab\lang2057\f0 Edits a PAK's QB file in memory (No Import / Export required).\par \lang1024\f1\'b7\tab\lang2057\f0 Import / Export / Export All functionality for PAK files.\par \lang1024\f1\'b7\tab\lang2057\f0 Create New / Add / Rename / Remove files in PAK files.\par -\lang1024\f1\'b7\tab\lang2057\f0 Supports all internal QB structures contained in Guitar Hero 3 / Aerosmith / World Tour / Metallica / Smash Hits / Greatest Hits / Tony Hawk's Proving Ground and Downhill Jam.\par +\lang1024\f1\'b7\tab\lang2057\f0 Supports all internal QB structures contained in Guitar Hero 3 / Aerosmith / World Tour / Metallica / Smash Hits / Greatest Hits / Guitar Hero 5 / Warriors of Rock / Tony Hawk's Proving Ground and Downhill Jam.\par \lang1024\f1\'b7\tab\lang2057\f0 QB structure and array items can be created, removed, copied and pasted.\par \lang1024\f1\'b7\tab\lang2057\f0 All items are editable including increasing the size of text and script items.\par \lang1024\f1\'b7\tab\lang2057\f0 Array items can be saved to text files for easy editing.\par @@ -235,6 +235,17 @@ Queen Bee creates various files in the same folder as the source files (PAK/PAB/ txtVersionHistory.Rtf = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 Tahoma;}} {\*\generator Msftedit 5.41.15.1515;}\viewkind4\uc1\pard\lang2057\b\f0\fs24 Version History\b0\fs16\par \par +\b\fs20 v1.9\b0\fs16\par + - \b Added\b0 : Warriors of Rock (WoR) DLC support. PAK files with duplicate CRC-based filenames (e.g. localized .qs files) are now handled gracefully.\par + - \b Added\b0 : Guitar Hero 5 and Warriors of Rock to the supported games list.\par + - \b Fixed\b0 : Export/Import file dialogs in Script Editor and Array Editor now correctly remember the last used directory.\par + - \b Fixed\b0 : QbKey.GetHashCode() was inconsistent with Equals(), which could cause incorrect Dictionary/HashSet lookups.\par + - \b Fixed\b0 : PAK file extraction opened files with ReadWrite access instead of Read, preventing read-only files from loading.\par + - \b Fixed\b0 : Undisposed BinaryReader/BinaryWriter in PAK data copy operations.\par + - \b Fixed\b0 : Undisposed BinaryEndianWriter when writing QB files.\par + - \b Changed\b0 : Widened the Information dialog to prevent text wrapping in Version History and About tabs.\par + - \b Changed\b0 : Upgraded to .NET 10 single-target build.\par +\par \b\fs20 v1.8\b0\fs16\par - \b Fixed\b0 : Certain item types were being saved with the wrong ID.\par - \b Fixed\b0 : Handle Invalid path exception without crashing.\par diff --git a/QueenBee/QbItemEditors/ScriptEditor.cs b/QueenBee/QbItemEditors/ScriptEditor.cs index b375f7a..cb6ea45 100644 --- a/QueenBee/QbItemEditors/ScriptEditor.cs +++ b/QueenBee/QbItemEditors/ScriptEditor.cs @@ -280,7 +280,7 @@ private void btnExport_Click(object sender, EventArgs e) { string fname = string.Format("{0}_{1}.{2}", _qbItem.Root.Filename.Replace('\\', '#').Replace('/', '#').Replace('.', '#'), _qbItem.ItemQbKey.Crc.ToString("X").PadLeft(8, '0'), _fileExt); - if (AppState.LastScriptPath.Length == 0) + if (AppState.LastScriptPath.Length != 0) fname = Path.Combine(AppState.LastScriptPath, fname); fname = getBestFullFilename(fname); @@ -313,7 +313,7 @@ private void btnImport_Click(object sender, EventArgs e) { string fname = string.Format("{0}_{1}.{2}", _qbItem.Root.Filename.Replace('\\', '#').Replace('/', '#').Replace('.', '#'), _qbItem.ItemQbKey.Crc.ToString("X").PadLeft(8, '0'), _fileExt); - if (AppState.LastScriptPath.Length == 0) + if (AppState.LastScriptPath.Length != 0) fname = Path.Combine(AppState.LastScriptPath, fname); fname = getBestFullFilename(fname); diff --git a/QueenBee/QbItemEditors/SimpleArrayEditor.cs b/QueenBee/QbItemEditors/SimpleArrayEditor.cs index 991660e..d6dcbc4 100644 --- a/QueenBee/QbItemEditors/SimpleArrayEditor.cs +++ b/QueenBee/QbItemEditors/SimpleArrayEditor.cs @@ -743,7 +743,7 @@ private void btnExport_Click(object sender, EventArgs e) { string fname = string.Empty; // string.Format("{0}.{1}", base.QbItem.Root.Filename.Replace('\\', '#').Replace('/', '#').Replace('.', '#'), _fileExt); - if (AppState.LastArrayPath.Length == 0) + if (AppState.LastArrayPath.Length != 0) fname = Path.Combine(AppState.LastArrayPath, fname); fname = getBestFullFilename(fname); @@ -785,7 +785,7 @@ private void btnImport_Click(object sender, EventArgs e) { string fname = string.Empty; // string.Format("{0}_{1}.array.txt", base.QbItem.Root.Filename.Replace('\\', '#').Replace('/', '#').Replace('.', '#'), base.QbItem.ItemQbKey.Crc.ToString("X").PadLeft(8, '0')); - if (AppState.LastArrayPath.Length == 0) + if (AppState.LastArrayPath.Length != 0) fname = Path.Combine(AppState.LastArrayPath, fname); fname = getBestFullFilename(fname); diff --git a/QueenBeeParser/BinaryEndianWriter.cs b/QueenBeeParser/BinaryEndianWriter.cs index 803453e..b8cebad 100644 --- a/QueenBeeParser/BinaryEndianWriter.cs +++ b/QueenBeeParser/BinaryEndianWriter.cs @@ -12,6 +12,11 @@ public BinaryEndianWriter(Stream input) : base(input) { } + + public BinaryEndianWriter(Stream input, bool leaveOpen) + : base(input, System.Text.Encoding.UTF8, leaveOpen) + { + } public void Write(UInt32 value, EndianType endianType) { diff --git a/QueenBeeParser/Pak/PakEditor.cs b/QueenBeeParser/Pak/PakEditor.cs index 6dd45cb..be55ca2 100644 --- a/QueenBeeParser/Pak/PakEditor.cs +++ b/QueenBeeParser/Pak/PakEditor.cs @@ -186,7 +186,21 @@ private void parsePak(PakFormat pakFormat, bool debugFile) try { - _pakHeaders.Add(phi.Filename.ToLower(), phi); + string key = phi.Filename.ToLower(); + if (_pakHeaders.ContainsKey(key)) + { + int dupIndex = 2; + string newKey; + do + { + newKey = key + "_" + dupIndex; + dupIndex++; + } + while (_pakHeaders.ContainsKey(newKey)); + phi.Filename = phi.Filename + "_" + (dupIndex - 1); + key = newKey; + } + _pakHeaders.Add(key, phi); } catch (Exception ex) { @@ -377,7 +391,7 @@ public void ExtractFile(string qbFilename, Stream stream) using (BinaryWriter bw = new BinaryWriter(stream)) { //open input pak - using (FileStream fsPak = File.Open(fname, FileMode.Open, FileAccess.ReadWrite)) + using (FileStream fsPak = File.Open(fname, FileMode.Open, FileAccess.Read)) { if ((offset + phi.FileLength) - 1 > fsPak.Length) throw new ApplicationException(string.Format("End of file '{0}' is located at 0x{1} which is beyond the PAK/PAB size 0x{2}", qbFilename, (offset + phi.FileLength).ToString("X").PadLeft(8, '0'), fsPak.Length.ToString("X").PadLeft(8, '0'))); @@ -935,22 +949,23 @@ private void writeHeaderItem(BinaryEndianWriter bwPakO, PakHeaderItem ph) /// private void copyData(Stream sr, Stream sw, long length) { - BinaryReader br = new BinaryReader(sr); - BinaryWriter bw = new BinaryWriter(sw); - long chunk = 1000000; - while (length > 0) + using (BinaryReader br = new BinaryReader(sr, Encoding.UTF8, leaveOpen: true)) + using (BinaryWriter bw = new BinaryWriter(sw, Encoding.UTF8, leaveOpen: true)) { - if (length > chunk) - { - bw.Write(br.ReadBytes((int)chunk)); - length -= chunk; - } - else + long chunk = 1000000; + while (length > 0) { - bw.Write(br.ReadBytes((int)length)); - length = 0; + if (length > chunk) + { + bw.Write(br.ReadBytes((int)chunk)); + length -= chunk; + } + else + { + bw.Write(br.ReadBytes((int)length)); + length = 0; + } } - } } diff --git a/QueenBeeParser/Qb/QbFile.cs b/QueenBeeParser/Qb/QbFile.cs index f0ca451..89495f2 100644 --- a/QueenBeeParser/Qb/QbFile.cs +++ b/QueenBeeParser/Qb/QbFile.cs @@ -645,9 +645,8 @@ public void Write(string filename) public void Write(Stream s) { - BinaryEndianWriter bw = new BinaryEndianWriter(s); - //using (BinaryEndianWriter bw = new BinaryEndianWriter(s)) - //{ + using (BinaryEndianWriter bw = new BinaryEndianWriter(s, leaveOpen: true)) + { this.startLengthCheck(bw); bw.Write(_magic, this.PakFormat.EndianType); @@ -656,10 +655,9 @@ public void Write(Stream s) foreach (QbItemBase qib in _items) qib.Write(bw); - ApplicationException ex = this.testLengthCheck(this, bw); if (ex != null) throw ex; - //} + } } diff --git a/QueenBeeParser/Qb/QbKey.cs b/QueenBeeParser/Qb/QbKey.cs index c3d5eb7..fab6fba 100644 --- a/QueenBeeParser/Qb/QbKey.cs +++ b/QueenBeeParser/Qb/QbKey.cs @@ -118,7 +118,7 @@ public string Text public override int GetHashCode() { - return base.GetHashCode() & (int)this._crc; //Hmm + return this._crc.GetHashCode(); } public bool HasText diff --git a/QueenBeeParser/Qb/base/QbItemBase.cs b/QueenBeeParser/Qb/base/QbItemBase.cs index c4fad22..4dbe923 100644 --- a/QueenBeeParser/Qb/base/QbItemBase.cs +++ b/QueenBeeParser/Qb/base/QbItemBase.cs @@ -614,7 +614,7 @@ public virtual IsValidReturnType IsValid } else if (_childMode == 2) { - if (this.ItemCount < 0) + if (this.ItemCount < 0) // uint is always >= 0; validation is a no-op return IsValidReturnType.ItemMustHave0OrMoreItems; } else if (_childMode == 3) diff --git a/QueenBeeParser/QueenBeeParser.csproj b/QueenBeeParser/QueenBeeParser.csproj index 2e8f96c..d3630bf 100644 --- a/QueenBeeParser/QueenBeeParser.csproj +++ b/QueenBeeParser/QueenBeeParser.csproj @@ -1,7 +1,7 @@  - net10.0;net9.0;net8.0;net7.0;net6.0;net5.0;net48;net46;net35;net20 + net10.0 false disable diff --git a/QueenBeeParser/Zlib/zlib.net.csproj b/QueenBeeParser/Zlib/zlib.net.csproj deleted file mode 100644 index 40f303a..0000000 --- a/QueenBeeParser/Zlib/zlib.net.csproj +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/QueenBeeParser/Zlib/zlib.net.sln b/QueenBeeParser/Zlib/zlib.net.sln deleted file mode 100644 index f2685b0..0000000 --- a/QueenBeeParser/Zlib/zlib.net.sln +++ /dev/null @@ -1,21 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "zlib.net", "zlib.net.csproj", "{0C89B7A2-A218-49E4-B545-5B044A45F977}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {0C89B7A2-A218-49E4-B545-5B044A45F977}.Debug.ActiveCfg = Debug|.NET - {0C89B7A2-A218-49E4-B545-5B044A45F977}.Debug.Build.0 = Debug|.NET - {0C89B7A2-A218-49E4-B545-5B044A45F977}.Release.ActiveCfg = Release|.NET - {0C89B7A2-A218-49E4-B545-5B044A45F977}.Release.Build.0 = Release|.NET - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal