diff --git a/App.config b/App.config
index 8e15646..660c48a 100644
--- a/App.config
+++ b/App.config
@@ -1,6 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+ engine
+
+
+
\ No newline at end of file
diff --git a/Forms/Launcher.Designer.cs b/Forms/Launcher.Designer.cs
new file mode 100644
index 0000000..f0a69ef
--- /dev/null
+++ b/Forms/Launcher.Designer.cs
@@ -0,0 +1,328 @@
+
+namespace GettingUpTool.Forms
+{
+ partial class Launcher
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Launcher));
+ this.btnRun = new System.Windows.Forms.Button();
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.textureToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.levelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.pakToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.cmbLevelSelect = new System.Windows.Forms.ComboBox();
+ this.lblLevelSelect = new System.Windows.Forms.Label();
+ this.chkClearAssetCache = new System.Windows.Forms.CheckBox();
+ this.txtArgs = new System.Windows.Forms.TextBox();
+ this.lblArgs = new System.Windows.Forms.Label();
+ this.txtCmdLine = new System.Windows.Forms.TextBox();
+ this.lblCmdLine = new System.Windows.Forms.Label();
+ this.lblCharSelect = new System.Windows.Forms.Label();
+ this.cmbCharSelect = new System.Windows.Forms.ComboBox();
+ this.lblGameRoot = new System.Windows.Forms.Label();
+ this.cmbRootSelect = new System.Windows.Forms.ComboBox();
+ this.lblGamePath = new System.Windows.Forms.Label();
+ this.txtGamePath = new System.Windows.Forms.TextBox();
+ this.btnGamePathBrowse = new System.Windows.Forms.Button();
+ this.folderBrowser = new System.Windows.Forms.FolderBrowserDialog();
+ this.menuStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // btnRun
+ //
+ this.btnRun.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnRun.Location = new System.Drawing.Point(12, 415);
+ this.btnRun.Name = "btnRun";
+ this.btnRun.Size = new System.Drawing.Size(287, 23);
+ this.btnRun.TabIndex = 0;
+ this.btnRun.Text = "Run";
+ this.btnRun.UseVisualStyleBackColor = true;
+ this.btnRun.Click += new System.EventHandler(this.btnRun_Click);
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.textureToolStripMenuItem1,
+ this.levelToolStripMenuItem,
+ this.helpToolStripMenuItem});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Size = new System.Drawing.Size(311, 24);
+ this.menuStrip1.TabIndex = 1;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // textureToolStripMenuItem1
+ //
+ this.textureToolStripMenuItem1.Name = "textureToolStripMenuItem1";
+ this.textureToolStripMenuItem1.Size = new System.Drawing.Size(136, 22);
+ this.textureToolStripMenuItem1.Text = "Texture tool";
+ this.textureToolStripMenuItem1.Click += new System.EventHandler(this.textureToolStripMenuItem1_Click);
+ //
+ // levelToolStripMenuItem
+ //
+ this.levelToolStripMenuItem.Name = "levelToolStripMenuItem";
+ this.levelToolStripMenuItem.Size = new System.Drawing.Size(136, 22);
+ this.levelToolStripMenuItem.Text = "Level tool";
+ this.levelToolStripMenuItem.Click += new System.EventHandler(this.levelToolStripMenuItem_Click);
+ //
+ // pakToolStripMenuItem
+ //
+ this.pakToolStripMenuItem.Name = "pakToolStripMenuItem";
+ this.pakToolStripMenuItem.Size = new System.Drawing.Size(136, 22);
+ this.pakToolStripMenuItem.Text = "PAK tool";
+ this.pakToolStripMenuItem.Click += new System.EventHandler(this.pakToolStripMenuItem_Click);
+ //
+ // helpToolStripMenuItem
+ //
+ this.helpToolStripMenuItem.Name = "helpToolStripMenuItem";
+ this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
+ this.helpToolStripMenuItem.Text = "Help";
+ this.helpToolStripMenuItem.Click += new System.EventHandler(this.helpToolStripMenuItem_Click);
+ //
+ // cmbLevelSelect
+ //
+ this.cmbLevelSelect.FormattingEnabled = true;
+ this.cmbLevelSelect.Location = new System.Drawing.Point(12, 196);
+ this.cmbLevelSelect.Name = "cmbLevelSelect";
+ this.cmbLevelSelect.Size = new System.Drawing.Size(170, 21);
+ this.cmbLevelSelect.TabIndex = 2;
+ this.cmbLevelSelect.SelectionChangeCommitted += new System.EventHandler(this.comboBox_CmdArg_SelectionChangeCommitted);
+ //
+ // lblLevelSelect
+ //
+ this.lblLevelSelect.AutoSize = true;
+ this.lblLevelSelect.Location = new System.Drawing.Point(12, 180);
+ this.lblLevelSelect.Name = "lblLevelSelect";
+ this.lblLevelSelect.Size = new System.Drawing.Size(64, 13);
+ this.lblLevelSelect.TabIndex = 3;
+ this.lblLevelSelect.Text = "Level select";
+ //
+ // chkClearAssetCache
+ //
+ this.chkClearAssetCache.AutoSize = true;
+ this.chkClearAssetCache.Checked = true;
+ this.chkClearAssetCache.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkClearAssetCache.Location = new System.Drawing.Point(188, 198);
+ this.chkClearAssetCache.Name = "chkClearAssetCache";
+ this.chkClearAssetCache.Size = new System.Drawing.Size(111, 17);
+ this.chkClearAssetCache.TabIndex = 0;
+ this.chkClearAssetCache.Text = "Clear asset cache";
+ this.chkClearAssetCache.UseVisualStyleBackColor = true;
+ //
+ // txtArgs
+ //
+ this.txtArgs.Location = new System.Drawing.Point(12, 313);
+ this.txtArgs.Name = "txtArgs";
+ this.txtArgs.Size = new System.Drawing.Size(287, 20);
+ this.txtArgs.TabIndex = 5;
+ //
+ // lblArgs
+ //
+ this.lblArgs.AutoSize = true;
+ this.lblArgs.Location = new System.Drawing.Point(12, 297);
+ this.lblArgs.Name = "lblArgs";
+ this.lblArgs.Size = new System.Drawing.Size(105, 13);
+ this.lblArgs.TabIndex = 6;
+ this.lblArgs.Text = "Additional arguments";
+ //
+ // txtCmdLine
+ //
+ this.txtCmdLine.Location = new System.Drawing.Point(12, 352);
+ this.txtCmdLine.Multiline = true;
+ this.txtCmdLine.Name = "txtCmdLine";
+ this.txtCmdLine.ReadOnly = true;
+ this.txtCmdLine.Size = new System.Drawing.Size(287, 48);
+ this.txtCmdLine.TabIndex = 7;
+ //
+ // lblCmdLine
+ //
+ this.lblCmdLine.AutoSize = true;
+ this.lblCmdLine.Location = new System.Drawing.Point(12, 336);
+ this.lblCmdLine.Name = "lblCmdLine";
+ this.lblCmdLine.Size = new System.Drawing.Size(73, 13);
+ this.lblCmdLine.TabIndex = 8;
+ this.lblCmdLine.Text = "Command-line";
+ //
+ // lblCharSelect
+ //
+ this.lblCharSelect.AutoSize = true;
+ this.lblCharSelect.Location = new System.Drawing.Point(12, 131);
+ this.lblCharSelect.Name = "lblCharSelect";
+ this.lblCharSelect.Size = new System.Drawing.Size(84, 13);
+ this.lblCharSelect.TabIndex = 10;
+ this.lblCharSelect.Text = "Character select";
+ //
+ // cmbCharSelect
+ //
+ this.cmbCharSelect.FormattingEnabled = true;
+ this.cmbCharSelect.Items.AddRange(new object[] {
+ "Trane",
+ "ConWorker",
+ "Cope2",
+ "Dip",
+ "Dog",
+ "Gabe",
+ "ManfredsArmy",
+ "Kry1",
+ "MeatWorker",
+ "OrangeGuardHeavy",
+ "OrangeGuardLight",
+ "PoliceChief",
+ "SecurityGuard",
+ "ShannaRay",
+ "SilverGuardHeavy",
+ "SilverGuardLight",
+ "Spleen",
+ "Stake",
+ "VandalSquad",
+ "VandalSquadBoss",
+ "VanR",
+ "VanRHeavy",
+ "Welder",
+ "WhiteMike",
+ "WorkBum",
+ "WWAHeavy"});
+ this.cmbCharSelect.Location = new System.Drawing.Point(12, 147);
+ this.cmbCharSelect.Name = "cmbCharSelect";
+ this.cmbCharSelect.Size = new System.Drawing.Size(139, 21);
+ this.cmbCharSelect.TabIndex = 9;
+ this.cmbCharSelect.SelectionChangeCommitted += new System.EventHandler(this.comboBox_CmdArg_SelectionChangeCommitted);
+ //
+ // lblGameRoot
+ //
+ this.lblGameRoot.AutoSize = true;
+ this.lblGameRoot.Location = new System.Drawing.Point(12, 82);
+ this.lblGameRoot.Name = "lblGameRoot";
+ this.lblGameRoot.Size = new System.Drawing.Size(56, 13);
+ this.lblGameRoot.TabIndex = 12;
+ this.lblGameRoot.Text = "Game root";
+ //
+ // cmbRootSelect
+ //
+ this.cmbRootSelect.FormattingEnabled = true;
+ this.cmbRootSelect.Items.AddRange(new object[] {
+ "engine",
+ "beta"});
+ this.cmbRootSelect.Location = new System.Drawing.Point(12, 98);
+ this.cmbRootSelect.Name = "cmbRootSelect";
+ this.cmbRootSelect.Size = new System.Drawing.Size(139, 21);
+ this.cmbRootSelect.TabIndex = 11;
+ this.cmbRootSelect.SelectionChangeCommitted += new System.EventHandler(this.cmbRootSelect_SelectionChangeCommitted);
+ //
+ // lblGamePath
+ //
+ this.lblGamePath.AutoSize = true;
+ this.lblGamePath.Location = new System.Drawing.Point(12, 33);
+ this.lblGamePath.Name = "lblGamePath";
+ this.lblGamePath.Size = new System.Drawing.Size(59, 13);
+ this.lblGamePath.TabIndex = 14;
+ this.lblGamePath.Text = "Game path";
+ //
+ // txtGamePath
+ //
+ this.txtGamePath.Location = new System.Drawing.Point(12, 49);
+ this.txtGamePath.Name = "txtGamePath";
+ this.txtGamePath.Size = new System.Drawing.Size(215, 20);
+ this.txtGamePath.TabIndex = 13;
+ //
+ // btnGamePathBrowse
+ //
+ this.btnGamePathBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnGamePathBrowse.Location = new System.Drawing.Point(233, 48);
+ this.btnGamePathBrowse.Name = "btnGamePathBrowse";
+ this.btnGamePathBrowse.Size = new System.Drawing.Size(66, 22);
+ this.btnGamePathBrowse.TabIndex = 15;
+ this.btnGamePathBrowse.Text = "Browse";
+ this.btnGamePathBrowse.UseVisualStyleBackColor = true;
+ this.btnGamePathBrowse.Click += new System.EventHandler(this.btnGamePathBrowse_Click);
+ //
+ // Launcher
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(311, 450);
+ this.Controls.Add(this.btnGamePathBrowse);
+ this.Controls.Add(this.lblGamePath);
+ this.Controls.Add(this.txtGamePath);
+ this.Controls.Add(this.lblGameRoot);
+ this.Controls.Add(this.cmbRootSelect);
+ this.Controls.Add(this.lblCharSelect);
+ this.Controls.Add(this.cmbCharSelect);
+ this.Controls.Add(this.lblCmdLine);
+ this.Controls.Add(this.txtCmdLine);
+ this.Controls.Add(this.lblArgs);
+ this.Controls.Add(this.lblLevelSelect);
+ this.Controls.Add(this.chkClearAssetCache);
+ this.Controls.Add(this.cmbLevelSelect);
+ this.Controls.Add(this.txtArgs);
+ this.Controls.Add(this.btnRun);
+ this.Controls.Add(this.menuStrip1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MainMenuStrip = this.menuStrip1;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "Launcher";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "MEGU Launcher";
+ this.Load += new System.EventHandler(this.Launcher_Load);
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button btnRun;
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem textureToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem levelToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem pakToolStripMenuItem;
+ private System.Windows.Forms.ComboBox cmbLevelSelect;
+ private System.Windows.Forms.Label lblLevelSelect;
+ private System.Windows.Forms.CheckBox chkClearAssetCache;
+ private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem;
+ private System.Windows.Forms.TextBox txtArgs;
+ private System.Windows.Forms.Label lblArgs;
+ private System.Windows.Forms.TextBox txtCmdLine;
+ private System.Windows.Forms.Label lblCmdLine;
+ private System.Windows.Forms.Label lblCharSelect;
+ private System.Windows.Forms.ComboBox cmbCharSelect;
+ private System.Windows.Forms.Label lblGameRoot;
+ private System.Windows.Forms.ComboBox cmbRootSelect;
+ private System.Windows.Forms.Label lblGamePath;
+ private System.Windows.Forms.TextBox txtGamePath;
+ private System.Windows.Forms.Button btnGamePathBrowse;
+ private System.Windows.Forms.FolderBrowserDialog folderBrowser;
+ }
+}
\ No newline at end of file
diff --git a/Forms/Launcher.cs b/Forms/Launcher.cs
new file mode 100644
index 0000000..2d2da7e
--- /dev/null
+++ b/Forms/Launcher.cs
@@ -0,0 +1,278 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace GettingUpTool.Forms
+{
+ public partial class Launcher : Form
+ {
+ #region Public variables
+ #endregion
+
+ #region Private variables
+ private TextureTool _textureTool;
+ private LevelTool _levelTool;
+ private PakTool _pakTool;
+
+ private DirectoryInfo _gamePath;
+ private string _gameRoot = "engine";
+ private string _exePath = string.Empty;
+
+ private Properties.Settings _settings = Properties.Settings.Default;
+ #endregion
+
+ #region Constructor
+ public Launcher()
+ {
+ InitializeComponent();
+ }
+
+ public Launcher(TextureTool frm)
+ {
+ _textureTool = frm;
+ InitializeComponent();
+ }
+ #endregion
+
+ #region Load event
+ private void Launcher_Load(object sender, EventArgs e)
+ {
+ // Use current system font, rather than WinForms default font
+ this.Font = SystemFonts.MessageBoxFont;
+
+ // So we can just do Encoding GetString and not worry about newlines etc.
+ Encoding.GetEncoding("Latin1");
+
+ if (!string.IsNullOrWhiteSpace(_settings.GamePath))
+ {
+ _gamePath = new DirectoryInfo(_settings.GamePath);
+ }
+
+ if (_gamePath == null || !GameFinder.ValidateGamePath(_gamePath))
+ {
+ _gamePath = null;
+
+ try
+ {
+ if (_textureTool != null)
+ _gamePath = _textureTool.GamePath;
+ }
+ catch (NullReferenceException _) { }
+ try
+ {
+ _gamePath = GameFinder.LocateGamePath();
+ }
+ catch (DirectoryNotFoundException _) {
+ MessageBox.Show("Failed to find the game, cannot continue.");
+ Application.Exit();
+ return;
+ }
+
+ _settings.GamePath = _gamePath.FullName;
+ _settings.Save();
+ }
+
+ _exePath = Path.Combine(_gamePath.FullName, @"_Bin\GettingUp.exe");
+
+ if (!string.IsNullOrWhiteSpace(_settings.GameRoot.ToString()))
+ {
+ _gameRoot = _settings.GameRoot.ToString();
+ cmbRootSelect.SelectedText = _gameRoot;
+ }
+
+ // TODO: Read default_pc.cfg and vars_pc.cfg
+
+ PopulateLevelSelect(cmbLevelSelect, _gamePath, _gameRoot);
+
+ txtCmdLine.Text = BuildCommandLine();
+
+ txtGamePath.Text = _gamePath.FullName;
+ }
+ #endregion
+
+ private string BuildCmdArg(string arg, string value)
+ {
+ if (value == string.Empty) return string.Empty;
+ return string.IsNullOrWhiteSpace(value) ? string.Empty : $"{arg}:\"{value}\"";
+ }
+
+ private string BuildCmdArg(string arg, int value)
+ {
+ return $"{arg}:{value}";
+ }
+
+ private string BuildCommandArgs()
+ {
+ List args = new List();
+
+ args.Add(BuildCmdArg("game", "rhapsody"));
+ args.Add(BuildCmdArg("root", $"..\\{_gameRoot}")); // cmbRootSelect.SelectedIndex >= 0 ? $"..\\{cmbRootSelect.SelectedItem.ToString()}" : string.Empty));
+
+ /*
+ rnd_bones=1
+ rnd_brushes=true
+ rnd_particleaxis=true
+ rnd_particlebounds=true
+ rnd_particles=true
+ rnd_portals=true
+ rnd_reflections=true
+ rnd_shadows=true
+ rnd_skybox=true
+ rnd_stripfx=true
+ rnd_water=true
+ rnd_wire=true
+ */
+ args.Add(BuildCmdArg("map", cmbLevelSelect.SelectedIndex >= 0 ? cmbLevelSelect.SelectedItem.ToString() : string.Empty));
+ args.Add(BuildCmdArg("player", cmbCharSelect.SelectedIndex >= 0 ? cmbCharSelect.SelectedItem.ToString() : string.Empty));
+
+ string argstr = string.Join(" ", args.ToArray());
+
+ if (string.IsNullOrWhiteSpace(argstr))
+ argstr = txtArgs.Text.Trim();
+ else
+ argstr = $"{argstr.Trim()} {txtArgs.Text.Trim()}";
+
+ return argstr;
+ }
+
+ private string BuildCommandLine()
+ {
+ string exe = _exePath;
+ return $"\"{exe}\" {BuildCommandArgs()}".Trim();
+ }
+
+ private void btnRun_Click(object sender, EventArgs e)
+ {
+ if (chkClearAssetCache.Checked)
+ {
+ string path = Path.Combine(_gamePath.FullName, $@"{_gameRoot}\allassets.pak");
+ if (File.Exists(path))
+ File.Delete(path);
+ }
+
+ _settings.GamePath = _gamePath.FullName;
+ _settings.GameRoot = _gameRoot;
+ _settings.Save();
+
+ var procGame = new Process();
+ procGame.StartInfo.FileName = _exePath;
+ procGame.StartInfo.WorkingDirectory = Path.Combine(_gamePath.FullName, "_Bin");
+ procGame.StartInfo.UseShellExecute = true;
+
+ string args = BuildCommandArgs();
+
+ procGame.StartInfo.Arguments = args;
+
+ procGame.Start();
+
+ /*
+ Thread.Sleep(2000);
+
+ for (int timeout = 0; timeout < 20; timeout++)
+ {
+ if (GameFinder.IsGameRunning())
+ Application.Exit();
+
+ Thread.Sleep(500);
+ }
+ */
+
+ Application.Exit();
+ }
+
+ private void btnGamePathBrowse_Click(object sender, EventArgs e)
+ {
+ folderBrowser.Description = "Choose the game folder. This should be the folder containing the \"_Bin\" and \"engine\" folders";
+ folderBrowser.ShowNewFolderButton = false;
+
+ DialogResult dresFindGame = folderBrowser.ShowDialog();
+
+ if (dresFindGame == DialogResult.OK && !string.IsNullOrWhiteSpace(folderBrowser.SelectedPath))
+ {
+ DirectoryInfo inpath = new DirectoryInfo(folderBrowser.SelectedPath);
+
+ if (GameFinder.ValidateGamePath(inpath))
+ {
+ _settings.GamePath = inpath.FullName;
+ _settings.Save();
+ txtCmdLine.Text = BuildCommandLine();
+ }
+ else
+ {
+ this.Focus();
+ MessageBox.Show("Game not found. Please try again", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+
+ private void PopulateLevelSelect(ComboBox cmbLevelSelect, DirectoryInfo gamePath, string gameRoot)
+ {
+ cmbLevelSelect.Items.Clear();
+
+ FileInfo[] files = gamePath.GetFiles($"{gameRoot}/Levels/*.slp", SearchOption.AllDirectories);
+ foreach (FileInfo file in files)
+ {
+ cmbLevelSelect.Items.Add(Path.GetFileNameWithoutExtension(file.FullName).ToLower());
+ }
+ }
+
+ #region Control events
+ private void comboBox_CmdArg_SelectionChangeCommitted(object sender, EventArgs e)
+ {
+ txtCmdLine.Text = BuildCommandLine();
+ }
+
+ private void cmbRootSelect_SelectionChangeCommitted(object sender, EventArgs e)
+ {
+ _gameRoot = cmbRootSelect.SelectedIndex >= 0 ? cmbRootSelect.SelectedItem.ToString() : string.Empty;
+
+ if (!string.IsNullOrWhiteSpace(_gameRoot))
+ {
+ _settings.GameRoot = _gameRoot;
+ _settings.Save();
+ }
+
+ PopulateLevelSelect(cmbLevelSelect, _gamePath, _gameRoot);
+
+ comboBox_CmdArg_SelectionChangeCommitted(sender, e);
+ }
+
+ private void textureToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ if (_textureTool == null)
+ _textureTool = new TextureTool();
+ this.Hide();
+ _textureTool.ShowDialog();
+ this.Show();
+ }
+
+ private void levelToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (_levelTool == null)
+ _levelTool = new LevelTool();
+ this.Hide();
+ _levelTool.ShowDialog();
+ this.Show();
+ }
+
+ private void pakToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (_pakTool == null)
+ _pakTool = new PakTool();
+ this.Hide();
+ _pakTool.ShowDialog();
+ this.Show();
+ }
+
+ private void helpToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Process.Start(UI.HelpUrl);
+ }
+ #endregion
+ }
+}
diff --git a/Forms/Launcher.resx b/Forms/Launcher.resx
new file mode 100644
index 0000000..99ae67d
--- /dev/null
+++ b/Forms/Launcher.resx
@@ -0,0 +1,260 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+
+
+ 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
+ NP+LRyT/i0ck/1kuF//LaDT/y2g0/8toNP/LaDT/y2g0/8toNP8AAAD9AAAA2AAAAGkAAAAAAAAAAAAA
+ AAAAAAAsAAAAdwAAANEAAAD5dj0e/04oFP0AAAD5AAAA/F8xGf6PSSX/j0kl/4ZFI/9DIhH+hkUj/8to
+ NP/LaDT/i0ck/4tHJP9MJhP/WS4X/5FKJf+RSiX/y2g0/8toNP/LaDT/y2g0/0MiEf0AAADmAAAAkQAA
+ AAAAAAAAAAAAGAAAAG0AAACpAAAA9hkNB/yPSyX/j0sl/1QsFv4AAAD5hkUj/4ZFI/+GRSP/sFou/5ZN
+ J/98QCD/y2g0/8toNP+jUyr/y2g0/49JJf+PSyX/o1Uq/6NVKv/LaDT/gkMi/8RkMv/EZDL/AAAA/AAA
+ AN0AAABfAAAAAAAAAAAAAABtAAAAqQAAAOkAAAD2VCwW/49LJf/LajT/y2o0/4ZFI//LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/y2g0/7deL/+3Xi//y2g0/8toNP+3Xy//y2g0/8toNP/EZDL/xGQy/wAA
+ APwAAAD2AAAAvAAAAF8AAAAAAAAAAAAAAKkAAADpAAAA9mIyGf+PSyX/y2o0/8tqNP/LajT/y2g0/8to
+ NP/LaDT/y2g0/8toNP+wWi7/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/6NVKv+3Xy//t18v/8Rk
+ Mv9BIRH+AAAA9gAAAOoAAACGAAAANAAAAAAAAAAAAAAA0QAAAPZBIRH8YjIZ/xkNB/2PSyX/VCwW/8tq
+ NP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP/LaDT/xGQy/wAAAPwAAAD2AAAAsgAAADQAAAAAAAAAAAAAAAAAAADeQyIR/stoNP/LaDT/iUYj/8to
+ NP/LaDT/y2g0/8toNP+0XS//tF0v/8toNP/LaDT/y2g0/8toNP/LaDT/xmUz/8hmNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP9DIhH+AAAA/AAAAPMAAACUAAAASgAAAAAAAAAAAAAAAAAAAN5DIhH+y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/n1Ep/7RdL/+0XS//y2g0/8toNP/LaDT/y2g0/8toNP/GZTP/xmUz/8to
+ NP/LaDT/y2g0/8toNP/LaDT/j0kl/wAAAPwAAAD8AAAA/AAAAMUAAACGAAAASgAAAAAAAAAAAAAAugAA
+ APEAAAD7hkUj/8toNP+JRiP/SCUS/kglEv6fUSn/iUYj/7RdL//LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP/EZDL/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/hkUj/gAAAPwAAAD8AAAA/AAAAM8AAACGAAAASgAA
+ AAAAAACAAAAAugAAAPEAAAD7BgMC+QYDAv6JRiP/SCUS/olGI/+JRiP/tF0v/8toNP/LaDT/y2g0/7de
+ L//LaDT/y2g0/8hmNP/IZjT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/4ZFI/4AAAD8AAAA+QAA
+ AOQAAACwAAAASgAAADAAAACAAAAAtwAAANkAAADyAAAA+gAAAPpvORz/n1Ep/3M7Hv/LaDT/y2g0/8to
+ NP/GZTP/vWEx/8ZlM//GZTP/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP8AAAD8AAAA/AAAAOMAAACUAAAAAAAAADAAAAAwAAAAXAAAAKYAAADkAAAA+gAAAPpIJRL+y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/xmUz/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP+GRSP/AAAA/AAAAMUAAAAAAAAAAAAAAAAAAAAwAAAAcgAAAOQAAAD6AAAA+sto
+ NP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/EZDL/y2g0/8toNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP8AAAD8AAAA4wAAAAAAAAAAAAAAAAAAADAAAACmAAAA8gAA
+ APpvORz/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8hmNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/wAAAPwAAADjAAAAAAAAAAAAAAAAAAAAZAAA
+ ANMAAAD6AAAA+stoNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP8AAAD+AAAA+AAAAMcAAAAAAAAAAAAA
+ ADcAAACoAAAA8wAAAPrLaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/wAAAPgAAAD4AAAAigAA
+ AAAAAAAAAAAAZAAAANIAAAD6QyIR/ctoNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP8AAAD4AAAA+AAA
+ AMcAAAAmAAAAAAAAAAAAAABkAAAA4AAAAPrLaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP98QiD/sFwu/8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/aDUb/wAA
+ APgAAADoAAAAigAAACYAAAAAAAAAAAAAAGIAAADeAAAA+8toNP/LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/vWEx/wAAAPkAAAD5AAAA/stoNP/LaDT/y2g0/8toNP/LaDT/y2g0/8to
+ NP8AAAD8AAAA+QAAALAAAABKAAAAAAAAAAAAAAAAAAAAYgAAALwAAAD7AAAA+8toNP/LaDT/y2g0/8to
+ NP/LaDT/y2g0/8toNP/LaDT/y2g0/8toNP8AAAD5AAAA+QAAAPkAAAD5AAAA9UMiEf7LaDT/y2g0/8to
+ NP/LaDT/AAAA/AAAAPUAAADPAAAAhgAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAhgAAAOAAAADzAAAA+0Mi
+ Ef7LaDT/y2g0/8toNP/LaDT/y2g0/8toNP/LaDT/BgMC/AAAAPkAAAD5AAAA1gAAANYAAAD1AAAA9QAA
+ APxDIhH8y2g0/4ZFI/4AAAD1AAAA5wAAAIYAAABKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAjAAA
+ AL8AAADzAAAA8w0EA/vLaDT/y2g0/8toNP/LaDT/y2g0/8toNP8GAwL6AAAA+QAAAKsAAABnAAAAZwAA
+ AKgAAADoAAAA9QAAAPUAAAD8AAAA9QAAAOcAAAClAAAASgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ ABQAAAAwAAAAfAAAAJgAAADVAAAA9wAAAPcAAAD3y2g0/8toNP/LaDT/AAAA+QAAAPkAAADVAAAAWQAA
+ ADAAAAAAAAAARwAAAGQAAACXAAAAvAAAAMUAAAC0AAAAigAAAE0AAAAbAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAwAAAAWQAAAHwAAAC/AAAA5QAAAPcAAAD3y2g0/8toNP8AAAD5AAAA7gAA
+ AJgAAAAwAAAAAAAAAAAAAAAAAAAAAAAAACYAAABHAAAATQAAAE0AAAAqAAAAKgAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAHwAAAB8AAAAvwAAAOUAAADuAAAA7gAA
+ ANMAAAClAAAAWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAB8AAAAfAAA
+ AKUAAAClAAAApQAAAFkAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
+
+
+
\ No newline at end of file
diff --git a/Forms/LevelTool.Designer.cs b/Forms/LevelTool.Designer.cs
new file mode 100644
index 0000000..8e44f8c
--- /dev/null
+++ b/Forms/LevelTool.Designer.cs
@@ -0,0 +1,220 @@
+
+namespace GettingUpTool.Forms
+{
+ partial class LevelTool
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.treeGameFiles = new System.Windows.Forms.TreeView();
+ this.textDebugLog = new System.Windows.Forms.TextBox();
+ this.textDebugLog2 = new System.Windows.Forms.TextBox();
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.splitContainer2 = new System.Windows.Forms.SplitContainer();
+ this.label1 = new System.Windows.Forms.Label();
+ this.textMeshes = new System.Windows.Forms.TextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.textTextures = new System.Windows.Forms.TextBox();
+ this.panel1 = new System.Windows.Forms.Panel();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
+ this.splitContainer2.Panel1.SuspendLayout();
+ this.splitContainer2.Panel2.SuspendLayout();
+ this.splitContainer2.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // treeGameFiles
+ //
+ this.treeGameFiles.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)));
+ this.treeGameFiles.Location = new System.Drawing.Point(12, 12);
+ this.treeGameFiles.Name = "treeGameFiles";
+ this.treeGameFiles.Size = new System.Drawing.Size(240, 612);
+ this.treeGameFiles.TabIndex = 15;
+ this.treeGameFiles.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeGameFiles_AfterSelect);
+ //
+ // textDebugLog
+ //
+ this.textDebugLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.textDebugLog.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.textDebugLog.Location = new System.Drawing.Point(3, 3);
+ this.textDebugLog.MaxLength = 3276700;
+ this.textDebugLog.Multiline = true;
+ this.textDebugLog.Name = "textDebugLog";
+ this.textDebugLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.textDebugLog.Size = new System.Drawing.Size(344, 423);
+ this.textDebugLog.TabIndex = 16;
+ this.textDebugLog.WordWrap = false;
+ //
+ // textDebugLog2
+ //
+ this.textDebugLog2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.textDebugLog2.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.textDebugLog2.Location = new System.Drawing.Point(3, 3);
+ this.textDebugLog2.MaxLength = 3276700;
+ this.textDebugLog2.Multiline = true;
+ this.textDebugLog2.Name = "textDebugLog2";
+ this.textDebugLog2.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.textDebugLog2.Size = new System.Drawing.Size(344, 419);
+ this.textDebugLog2.TabIndex = 17;
+ this.textDebugLog2.TabStop = false;
+ this.textDebugLog2.WordWrap = false;
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.splitContainer1.Location = new System.Drawing.Point(614, 12);
+ this.splitContainer1.Name = "splitContainer1";
+ this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.textDebugLog);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.textDebugLog2);
+ this.splitContainer1.Size = new System.Drawing.Size(350, 858);
+ this.splitContainer1.SplitterDistance = 429;
+ this.splitContainer1.TabIndex = 18;
+ //
+ // splitContainer2
+ //
+ this.splitContainer2.Location = new System.Drawing.Point(258, 12);
+ this.splitContainer2.Name = "splitContainer2";
+ this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitContainer2.Panel1
+ //
+ this.splitContainer2.Panel1.Controls.Add(this.label1);
+ this.splitContainer2.Panel1.Controls.Add(this.textMeshes);
+ //
+ // splitContainer2.Panel2
+ //
+ this.splitContainer2.Panel2.Controls.Add(this.label2);
+ this.splitContainer2.Panel2.Controls.Add(this.textTextures);
+ this.splitContainer2.Size = new System.Drawing.Size(350, 858);
+ this.splitContainer2.SplitterDistance = 429;
+ this.splitContainer2.TabIndex = 19;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(3, 3);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(106, 13);
+ this.label1.TabIndex = 1;
+ this.label1.Text = "Meshes used in level";
+ //
+ // textMeshes
+ //
+ this.textMeshes.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.textMeshes.Location = new System.Drawing.Point(0, 23);
+ this.textMeshes.MaxLength = 3276700;
+ this.textMeshes.Multiline = true;
+ this.textMeshes.Name = "textMeshes";
+ this.textMeshes.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.textMeshes.Size = new System.Drawing.Size(350, 406);
+ this.textMeshes.TabIndex = 0;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(3, 3);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(110, 13);
+ this.label2.TabIndex = 2;
+ this.label2.Text = "Textures used in level";
+ //
+ // textTextures
+ //
+ this.textTextures.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.textTextures.Location = new System.Drawing.Point(0, 19);
+ this.textTextures.MaxLength = 3276700;
+ this.textTextures.Multiline = true;
+ this.textTextures.Name = "textTextures";
+ this.textTextures.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.textTextures.Size = new System.Drawing.Size(350, 406);
+ this.textTextures.TabIndex = 1;
+ //
+ // panel1
+ //
+ this.panel1.Location = new System.Drawing.Point(12, 630);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(240, 240);
+ this.panel1.TabIndex = 20;
+ //
+ // LevelTool
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(976, 881);
+ this.Controls.Add(this.panel1);
+ this.Controls.Add(this.splitContainer2);
+ this.Controls.Add(this.splitContainer1);
+ this.Controls.Add(this.treeGameFiles);
+ this.Name = "LevelTool";
+ this.Text = "Level Tool";
+ this.Load += new System.EventHandler(this.LevelTool_Load);
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel1.PerformLayout();
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ this.splitContainer1.Panel2.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
+ this.splitContainer1.ResumeLayout(false);
+ this.splitContainer2.Panel1.ResumeLayout(false);
+ this.splitContainer2.Panel1.PerformLayout();
+ this.splitContainer2.Panel2.ResumeLayout(false);
+ this.splitContainer2.Panel2.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
+ this.splitContainer2.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TreeView treeGameFiles;
+ private System.Windows.Forms.TextBox textDebugLog;
+ private System.Windows.Forms.TextBox textDebugLog2;
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private System.Windows.Forms.SplitContainer splitContainer2;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox textMeshes;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.TextBox textTextures;
+ private System.Windows.Forms.Panel panel1;
+ }
+}
\ No newline at end of file
diff --git a/Forms/LevelTool.cs b/Forms/LevelTool.cs
new file mode 100644
index 0000000..f385697
--- /dev/null
+++ b/Forms/LevelTool.cs
@@ -0,0 +1,363 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
+
+namespace GettingUpTool.Forms
+{
+ public partial class LevelTool : Form
+ {
+ #region Public variables
+ #endregion
+
+ #region Private variables
+ private DirectoryInfo _gamePath;
+ private string _gameRoot = "engine";
+ private string[] _targetFileExtensions = { ".slp" };
+
+ private Properties.Settings _settings = Properties.Settings.Default;
+
+ private SLP slp;
+ private SLS sls;
+ #endregion
+
+ #region Constructor
+ public LevelTool()
+ {
+ InitializeComponent();
+ }
+ #endregion
+
+ private static string StringFromByteArray(byte[] array, int index, int length)
+ {
+ return Encoding.ASCII.GetString(array, index, length).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?');
+ }
+
+ private static string HexLine(ref Int32 offset, ArraySegment bytes, Type type = null, string comment = "", bool show_bytes = true, bool show_chars = true)
+ {
+ string str = $"{offset:X4}";
+
+ if (show_bytes == true)
+ {
+ str += $"\t";
+ List bstr = new List();
+ for (int i = 0; i < bytes.Count; i++)
+ bstr.Add($"{bytes.Array[bytes.Offset + i]:X2}");
+ str += string.Join(" ", bstr.ToArray()).PadRight(11);
+ }
+
+ if (show_chars == true && (type == null || type.FullName != "System.String"))
+ {
+ str += $"\t";
+ // List bstr = new List();
+ for (int i = 0; i < bytes.Count; i++)
+ {
+ if (bytes.Offset + i >= bytes.Array.Length - 1) continue;
+ char chr = BitConverter.ToChar(bytes.Array, bytes.Offset + i);
+ if (chr < 0x20 || chr > 0x7E) chr = '.';
+ str += chr;
+ // bstr.Add($"{bytes.Array[bytes.Offset + i]}");
+ }
+ // str += string.Join(" ", bstr.ToArray()).PadRight(11);
+ }
+
+ if (type == null)
+ str += $"\t{BitConverter.ToInt32(bytes.Array, bytes.Offset),12}\t{BitConverter.ToSingle(bytes.Array, bytes.Offset),12}";
+ else if (type.FullName == "System.String")
+ str += $"\t{StringFromByteArray(bytes.Array, bytes.Offset, bytes.Count)}";
+ else if (type.FullName == "System.Char")
+ str += $"\t{BitConverter.ToChar(bytes.Array, bytes.Offset)}";
+ else if (type.FullName == "System.Int16")
+ str += $"\t{BitConverter.ToInt16(bytes.Array, bytes.Offset)}";
+ else if (type.FullName == "System.Int32")
+ str += $"\t{BitConverter.ToInt32(bytes.Array, bytes.Offset)}";
+ else if (type.FullName == "System.UInt16")
+ str += $"\t{BitConverter.ToUInt16(bytes.Array, bytes.Offset)}";
+ else if (type.FullName == "System.UInt32")
+ str += $"\t{BitConverter.ToUInt32(bytes.Array, bytes.Offset)}";
+ else if (type.FullName == "System.Single")
+ str += $"\t{BitConverter.ToSingle(bytes.Array, bytes.Offset)}";
+
+ if (comment != "")
+ str += $"\t{comment}";
+
+ str += Environment.NewLine;
+
+ offset += bytes.Count;
+
+ return str;
+ }
+
+ private class Level
+ {
+ public bool Valid = false;
+
+ public string Path = string.Empty;
+ public string FileName = string.Empty;
+ public int FileSize = 0;
+
+ public byte[] Data;
+
+ public string Name = string.Empty;
+ public Int32 Offset = 0;
+
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential, Pack = 0)]
+ private unsafe struct LevelFile
+ {
+ // Offsets based on m02_hoo_subway_2.slp
+ public Int32 Version; // 0000
+ public string Header; // 0004 3DF!
+ public Int16 _0008; // 0008
+ public Int16 _000A; // 000A
+ public Int32 NameLength; // 000C
+ public string Name; // 0010
+ public UInt32 Checksum; // Checksum?
+ public Int32 _0048; // 1
+ public Int32 _004C; // 0
+ public Int32 _0050; // 1
+ public Int32 _0054;
+ public Int32 _0058;
+ public Int32 _005C;
+ public Int32 _0060;
+ }
+ private LevelFile Struct;
+
+ private Int16 DataReadInt16(int index)
+ {
+ byte[] bytes = new byte[2];
+ Buffer.BlockCopy(Data, index, bytes, 0, 2);
+ return BitConverter.ToInt16(bytes, 0);
+ }
+
+ private Int32 DataReadInt32(int index)
+ {
+ byte[] bytes = new byte[4];
+ Buffer.BlockCopy(Data, index, bytes, 0, 4);
+ return BitConverter.ToInt32(bytes, 0);
+ }
+
+ private UInt32 DataReadUInt32(int index)
+ {
+ byte[] bytes = new byte[4];
+ Buffer.BlockCopy(Data, index, bytes, 0, 4);
+ return BitConverter.ToUInt32(bytes, 0);
+ }
+
+ public Level(string path)
+ {
+ Path = path;
+
+ if (!File.Exists(path))
+ return;
+
+ Valid = true;
+
+ FileInfo fi = new FileInfo(path);
+ FileSize = (int)fi.Length;
+ FileName = fi.Name;
+
+ Data = File.ReadAllBytes(path);
+
+ Struct.Version = DataReadInt32(0x00); // 4
+
+ Struct.Header = Encoding.ASCII.GetString(Data, 0x04, 4); // 3DF!
+
+ Struct._0008 = DataReadInt16(0x08);
+ Struct._000A = DataReadInt16(0x0A);
+
+ Struct.NameLength = DataReadInt32(0x0C);
+
+ Name = StringFromByteArray(Data, 0x10, Struct.NameLength);
+
+ Offset = 0x10 + Struct.NameLength;
+
+ Struct.Checksum = DataReadUInt32(Offset + 0x00);
+ Struct._0048 = DataReadInt32(Offset + 0x04);
+ Struct._004C = DataReadInt32(Offset + 0x08);
+ Struct._0050 = DataReadInt32(Offset + 0x0C);
+ }
+
+ private static bool Equals(byte[] source, byte[] separator, int index)
+ {
+ for (int i = 0; i < separator.Length; ++i)
+ if (index + i >= source.Length || source[index + i] != separator[i])
+ return false;
+ return true;
+ }
+
+ private static byte[][] Separate(byte[] source, byte[] separator)
+ {
+ var Parts = new List();
+ var Index = 0;
+ byte[] Part;
+
+ for (var I = 0; I < source.Length; ++I)
+ {
+ if (Equals(source, separator, I))
+ {
+ Part = new byte[I - Index];
+ Array.Copy(source, Index, Part, 0, Part.Length);
+ Parts.Add(Part);
+ Index = I + separator.Length;
+ I += separator.Length - 1;
+ }
+ }
+
+ Part = new byte[source.Length - Index];
+ Array.Copy(source, Index, Part, 0, Part.Length);
+ Parts.Add(Part);
+
+ return Parts.ToArray();
+ }
+
+ public string Analyze()
+ {
+ if (!Valid)
+ return string.Empty;
+
+ string output = string.Empty;
+ int offset = 0;
+
+ output += $"File\t{FileName}" + Environment.NewLine;
+ output += $"FSize\t{FileSize} / {FileSize.ToString("X")}" + Environment.NewLine;
+
+ output += $"Version\t{Struct.Version}" + Environment.NewLine;
+ output += $"Header\t{Struct.Header}" + Environment.NewLine;
+ output += $"Name\t{Name}" + Environment.NewLine;
+
+ output += Environment.NewLine;
+
+ output += $"{Offset:X4}\t{Struct.Checksum:X4}\t{Struct.Checksum}" + Environment.NewLine;
+
+ System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
+ sw.Start();
+ for (offset = Offset + 4; offset < FileSize / 4;)
+ {
+ if (FileSize - offset < 4)
+ break;
+ else
+ output += HexLine(ref offset, new ArraySegment(Data, offset, 4));
+ }
+ sw.Stop();
+ output += Environment.NewLine + $"{sw.Elapsed.TotalSeconds}";
+
+ output += Environment.NewLine;
+
+ return output;
+ ///////////////////////////////////////////////////////////////
+
+ // TODO: Read the entire file and split by 0xFFFF
+ // ArraySegment(Data, offset, 4);
+ byte[] splitter = { 0xFF, 0xFF };
+ var segments = Separate(Data, splitter);
+
+ output += $"Segs.\t{segments.Length}" + Environment.NewLine;
+
+ offset = Offset;
+ for (int n = 1; n < segments.Length; n++)
+ {
+ output += $"{offset:X4}";
+ output += $"\t";
+
+ List bstr = new List();
+
+ int i = 0;
+ for (i = 0; i < segments[n].Length; i++)
+ bstr.Add($"{segments[n][i]:X2}");
+ offset += segments[n].Length;
+
+ output += string.Join(" ", bstr.ToArray()).PadRight(11);
+
+ output += Environment.NewLine;
+ }
+
+ return output;
+ }
+ }
+
+ private class SLS : Level
+ {
+ public SLS(string path) : base(path) { }
+ }
+
+ private class SLP : Level
+ {
+ public SLP(string path) : base(path) { }
+ }
+
+ private void LevelTool_Load(object sender, EventArgs e)
+ {
+ // Use current system font, rather than WinForms default font
+ this.Font = SystemFonts.MessageBoxFont;
+
+ // So we can just do Encoding GetString and not worry about newlines etc.
+ Encoding.GetEncoding("Latin1");
+
+ if (!string.IsNullOrWhiteSpace(_settings.GamePath))
+ {
+ _gamePath = new DirectoryInfo(_settings.GamePath);
+ }
+
+ if (!string.IsNullOrWhiteSpace(_settings.GameRoot))
+ {
+ _gameRoot = _settings.GameRoot;
+ }
+
+ DirectoryInfo levelsDir = new DirectoryInfo(Path.Combine(_gamePath.FullName, $@"{_gameRoot}\Levels"));
+
+ treeGameFiles.SuspendLayout();
+ treeGameFiles.Nodes.Clear();
+ foreach (FileInfo file in levelsDir.GetFiles("*.slp", SearchOption.AllDirectories))
+ {
+ treeGameFiles.Nodes.Add(file.FullName, file.FullName.Replace(levelsDir.FullName, ""));
+ }
+ treeGameFiles.SelectedNode = null;
+ treeGameFiles.ResumeLayout();
+ }
+
+ //
+ // Load level from file
+ //
+ private bool LoadLevel(string path)
+ {
+ FileInfo fileInfo = new FileInfo(path);
+
+ string pathNoExt = Path.Combine(fileInfo.DirectoryName, fileInfo.Name);
+
+ slp = new SLP(path);
+ sls = new SLS(Path.ChangeExtension(path, ".sls"));
+
+ textDebugLog.Text = slp.Analyze();
+ // textDebugLog2.Text = sls.Analyze();
+
+ textMeshes.Text = "";
+ textTextures.Text = "";
+
+ return true;
+ }
+
+ //
+ // Load selected file when selecting in the tree view
+ //
+ bool firstRun = true;
+ private void treeGameFiles_AfterSelect(object sender, TreeViewEventArgs e)
+ {
+ if (firstRun)
+ {
+ firstRun = false;
+ return;
+ }
+
+ string path = treeGameFiles.SelectedNode.Name;
+
+ if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
+ return;
+
+ LoadLevel(path);
+ }
+ }
+}
diff --git a/Forms/LevelTool.resx b/Forms/LevelTool.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/Forms/LevelTool.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Forms/PakTool.Designer.cs b/Forms/PakTool.Designer.cs
new file mode 100644
index 0000000..03d7d57
--- /dev/null
+++ b/Forms/PakTool.Designer.cs
@@ -0,0 +1,48 @@
+
+namespace GettingUpTool.Forms
+{
+ partial class PakTool
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // PakViewer
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(800, 450);
+ this.Name = "PakViewer";
+ this.Text = "PAK Viewer";
+ this.Load += new System.EventHandler(this.PakViewer_Load);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Forms/PakTool.cs b/Forms/PakTool.cs
new file mode 100644
index 0000000..3dce8e9
--- /dev/null
+++ b/Forms/PakTool.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace GettingUpTool.Forms
+{
+ public partial class PakTool : Form
+ {
+ #region Public variables
+ #endregion
+
+ #region Private variables
+ private TextureTool _mainForm;
+ private DirectoryInfo _gamePath;
+ #endregion
+
+ #region Constructor
+ public PakTool()
+ {
+ InitializeComponent();
+ }
+
+ public PakTool(TextureTool frm)
+ {
+ _mainForm = frm;
+ InitializeComponent();
+ }
+ #endregion
+
+ private void PakViewer_Load(object sender, EventArgs e)
+ {
+ // Use current system font, rather than WinForms default font
+ this.Font = SystemFonts.MessageBoxFont;
+
+ // So we can just do Encoding GetString and not worry about newlines etc.
+ Encoding.GetEncoding("Latin1");
+
+ if (_gamePath == null)
+ {
+ try
+ {
+ if (_mainForm != null)
+ _gamePath = _mainForm.GamePath;
+ }
+ catch (NullReferenceException _) { }
+ try
+ {
+ _gamePath = GameFinder.LocateGamePath();
+ }
+ catch (DirectoryNotFoundException _) { }
+ }
+
+ if (_gamePath != null) {
+ string path = Path.Combine(_gamePath.FullName, @"engine\allassets.pak");
+ byte[] data = File.ReadAllBytes(path);
+ }
+ }
+ }
+}
diff --git a/Forms/PakTool.resx b/Forms/PakTool.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/Forms/PakTool.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Forms/TextureTool.Designer.cs b/Forms/TextureTool.Designer.cs
index 2df40f7..dc4e45d 100644
--- a/Forms/TextureTool.Designer.cs
+++ b/Forms/TextureTool.Designer.cs
@@ -1,4 +1,4 @@
-namespace GettingUpTool
+namespace GettingUpTool.Forms
{
partial class TextureTool
{
@@ -55,6 +55,8 @@ private void InitializeComponent()
this.panelDebug = new System.Windows.Forms.Panel();
this.comboDXTOverride = new System.Windows.Forms.ComboBox();
this.textTextureName = new System.Windows.Forms.TextBox();
+ this.chkTreeViewFlat = new System.Windows.Forms.CheckBox();
+ this.btnRefreshTreeView = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.picAlpha)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picRGB)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picPixelColor)).BeginInit();
@@ -137,7 +139,7 @@ private void InitializeComponent()
| System.Windows.Forms.AnchorStyles.Left)));
this.treeGameFiles.Location = new System.Drawing.Point(12, 9);
this.treeGameFiles.Name = "treeGameFiles";
- this.treeGameFiles.Size = new System.Drawing.Size(214, 720);
+ this.treeGameFiles.Size = new System.Drawing.Size(214, 694);
this.treeGameFiles.TabIndex = 14;
this.treeGameFiles.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeGameFiles_AfterSelect);
//
@@ -321,11 +323,37 @@ private void InitializeComponent()
this.textTextureName.Size = new System.Drawing.Size(200, 20);
this.textTextureName.TabIndex = 45;
//
+ // chkTreeViewFlat
+ //
+ this.chkTreeViewFlat.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.chkTreeViewFlat.AutoSize = true;
+ this.chkTreeViewFlat.Location = new System.Drawing.Point(12, 710);
+ this.chkTreeViewFlat.Name = "chkTreeViewFlat";
+ this.chkTreeViewFlat.Size = new System.Drawing.Size(58, 17);
+ this.chkTreeViewFlat.TabIndex = 46;
+ this.chkTreeViewFlat.Text = "Flatten";
+ this.chkTreeViewFlat.UseVisualStyleBackColor = true;
+ this.chkTreeViewFlat.CheckedChanged += new System.EventHandler(this.chkTreeViewFlat_CheckedChanged);
+ //
+ // btnRefreshTreeView
+ //
+ this.btnRefreshTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.btnRefreshTreeView.Font = new System.Drawing.Font("Segoe UI Symbol", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.btnRefreshTreeView.Location = new System.Drawing.Point(202, 705);
+ this.btnRefreshTreeView.Name = "btnRefreshTreeView";
+ this.btnRefreshTreeView.Size = new System.Drawing.Size(24, 24);
+ this.btnRefreshTreeView.TabIndex = 47;
+ this.btnRefreshTreeView.Text = "🔃";
+ this.btnRefreshTreeView.UseVisualStyleBackColor = true;
+ this.btnRefreshTreeView.Click += new System.EventHandler(this.btnRefreshTreeView_Click);
+ //
// TextureTool
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1136, 741);
+ this.Controls.Add(this.btnRefreshTreeView);
+ this.Controls.Add(this.chkTreeViewFlat);
this.Controls.Add(this.textTextureName);
this.Controls.Add(this.comboDXTOverride);
this.Controls.Add(this.panelDebug);
@@ -390,6 +418,8 @@ private void InitializeComponent()
private System.Windows.Forms.Panel panelDebug;
private System.Windows.Forms.ComboBox comboDXTOverride;
private System.Windows.Forms.TextBox textTextureName;
+ private System.Windows.Forms.CheckBox chkTreeViewFlat;
+ private System.Windows.Forms.Button btnRefreshTreeView;
}
}
diff --git a/Forms/TextureTool.cs b/Forms/TextureTool.cs
index 2364fe1..6f88f41 100644
--- a/Forms/TextureTool.cs
+++ b/Forms/TextureTool.cs
@@ -1,4 +1,5 @@
-using System;
+using MonoGame;
+using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
@@ -8,7 +9,7 @@
using System.Text.RegularExpressions;
using System.Windows.Forms;
-namespace GettingUpTool
+namespace GettingUpTool.Forms
{
public partial class TextureTool : Form
{
@@ -17,32 +18,16 @@ public TextureTool()
InitializeComponent();
}
+ #region Public variables
+ public DirectoryInfo GamePath;
+ #endregion
+
#region Private variables
- private string _gamePath;
private Texture _texture;
private Bitmap bmpAlpha, bmpRGB;
- private string _githubUrl = "https://github.com/Asbra/GettingUpTool";
- private string _helpUrl = "https://github.com/Asbra/GettingUpTool/wiki/Replacing-textures-graffiti-in-Marc-Ecko%27s-Getting-Up";
- #endregion
-
- private void BuildTree(DirectoryInfo directoryInfo, TreeNodeCollection addInMe)
- {
- TreeNode curNode = addInMe.Add(directoryInfo.Name);
-
- foreach (FileInfo file in directoryInfo.GetFiles())
- {
- string filext = file.Extension.ToLower();
- if (filext == ".st") // || filext == ".bir" || filext == ".dds" || filext == ".st2")
- {
- curNode.Nodes.Add(file.FullName, file.Name);
- }
- }
- foreach (DirectoryInfo subdir in directoryInfo.GetDirectories())
- {
- BuildTree(subdir, curNode.Nodes);
- }
- }
+ private string[] _targetFileExtensions = { ".st", ".stx", ".dds" };
+ #endregion
#region Texture functions
//
@@ -73,27 +58,31 @@ private bool LoadTexture(string path)
//
// Get file information
//
- // @TODO: Fix this inheritance
+ // TODO: Fix this inheritance
_texture = new Texture(path);
- if (_texture.Type == TextureType.ST)
- {
- _texture = new ST(path);// _texture.Data);
- }
- else if (_texture.Type == TextureType.ST2)
- {
- _texture = new ST2(path);//_texture.Data);
- }
- else if (_texture.Type == TextureType.DDS)
- {
- _texture = new DDS(path);//_texture.Data);
- }
- else
+ try
{
- // Other file extension
- MessageBox.Show("Unknown file format", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
- return false;
+ if (_texture.Type == TextureType.ST)
+ {
+ _texture = new ST(path);// _texture.Data);
+ }
+ else if (_texture.Type == TextureType.ST2)
+ {
+ _texture = new ST2(path);//_texture.Data);
+ }
+ else if (_texture.Type == TextureType.DDS)
+ {
+ _texture = new DDS(path);//_texture.Data);
+ }
+ else
+ {
+ // Other file extension
+ MessageBox.Show("Unknown file format", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ return false;
+ }
}
+ catch (Exception _) { MessageBox.Show(_.ToString()); }
// Debug output
if (chkDebug.Checked)
@@ -128,7 +117,7 @@ private bool LoadTexture(string path)
}
else
{
- compression = "Unknown";
+ compression = "";
}
string textureFormat = $"DDS {compression}";
@@ -162,7 +151,7 @@ private void TextureTool_Load(object sender, EventArgs e)
DirectoryInfo path = null;
- // @TODO: Implement a config file
+ // TODO: Implement a config file
try
{
@@ -211,22 +200,16 @@ private void TextureTool_Load(object sender, EventArgs e)
{
if (path != null && path.Exists)
{
- _gamePath = path.FullName;
- openFileDialog.InitialDirectory = _gamePath;
+ GamePath = path;
+ openFileDialog.InitialDirectory = GamePath.FullName;
- BuildTree(path, treeGameFiles.Nodes);
- if (treeGameFiles.Nodes.Count > 0)
- {
- treeGameFiles.Nodes[0].Expand();
- if (treeGameFiles.Nodes[0].Nodes.Count > 0)
- treeGameFiles.Nodes[0].Nodes[0].Expand();
- }
+ UI.RebuildFileTree(GamePath, treeGameFiles.Nodes, _targetFileExtensions);
}
else throw new DirectoryNotFoundException();
}
catch (Exception ex)
{
- MessageBox.Show($"Invalid game folder, please report the following error at {_githubUrl}/issues" + Environment.NewLine + ex.ToString());
+ MessageBox.Show($"Invalid game folder, please report the following error at {UI.GithubUrl}/issues" + Environment.NewLine + ex.ToString());
}
}
@@ -252,7 +235,7 @@ private void UpdatePreviews()
if (_texture.DXT > 0)
{
- // @TODO: Detect file format
+ // TODO: Detect file format
byte[] ddsBytes = null;
if (_texture.Type == TextureType.ST)
{
@@ -282,7 +265,21 @@ private void UpdatePreviews()
Array.Copy(_texture.Data, TextureUtil.DDS_HEADER_SIZE, ddsBytes, 0, _texture.Data.Length - TextureUtil.DDS_HEADER_SIZE);
}
- byte[] bmpBytes = _texture.DXT == 1 ? DxtUtil.DecompressDxt1(ddsBytes, _texture.Width, _texture.Height) : (_texture.DXT >= 4 ? DxtUtil.DecompressDxt5(ddsBytes, _texture.Width, _texture.Height) : DxtUtil.DecompressDxt3(ddsBytes, _texture.Width, _texture.Height));
+ byte[] bmpBytes = null;
+ switch (_texture.DXT)
+ {
+ case 1:
+ bmpBytes = DxtUtil.DecompressDxt1(ddsBytes, _texture.Width, _texture.Height);
+ break;
+ case 3:
+ bmpBytes = DxtUtil.DecompressDxt3(ddsBytes, _texture.Width, _texture.Height);
+ break;
+ case 5:
+ bmpBytes = DxtUtil.DecompressDxt5(ddsBytes, _texture.Width, _texture.Height);
+ break;
+ default:
+ throw new ArgumentException($"Unsupported texture compression DXT{_texture.DXT}");
+ }
int idx = 0;
for (int y = 0; y < _texture.Height; y++)
@@ -303,6 +300,31 @@ private void UpdatePreviews()
}
}
}
+ else
+ {
+ // Uncompressed RGB data
+ int idx = 0;
+ for (int y = 0; y < _texture.Height; y++)
+ {
+ for (int x = 0; x < _texture.Width; x++)
+ {
+ byte r = _texture.Pixels[idx + 0];
+ byte g = _texture.Pixels[idx + 1];
+ byte b = _texture.Pixels[idx + 2];
+ byte a = _texture.Pixels[idx + 3];
+ Color color = Color.FromArgb(a, r, g, b);
+
+ bmpRGB.SetPixel(x, y, color);
+
+ bmpAlpha.SetPixel(x, y, Color.FromArgb(a, 255, 255, 255));
+
+ idx += 4;
+ }
+ }
+
+ // buttonExportTexture.Enabled = true;
+ // buttonReplaceTexture.Enabled = true;
+ }
picAlpha.Image = bmpAlpha;
picRGB.Image = bmpRGB;
@@ -470,7 +492,7 @@ private void linkFile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
return;
- Process.Start("explorer.exe", $"/select,\"{path}\"");
+ // Process.Start("explorer.exe", $"/select,\"{path}\"");
}
//
@@ -551,6 +573,14 @@ private void buttonReplaceTexture_Click(object sender, EventArgs e)
File.Move(_texture.Path, _texture.Path + filext);
}
+ if (_texture.Type == TextureType.ST)
+ {
+ // ((ST)_texture).Width
+ }
+ else
+ {
+ }
+
// Replace texture data in memory
for (int i = TextureUtil.DDS_HEADER_SIZE; i < fileBytes.Length; i++)
{
@@ -579,23 +609,11 @@ private void buttonExportTexture_Click(object sender, EventArgs e)
switch (saveFileDialog.FilterIndex)
{
case 1: // DDS
- try
- {
- byte[] outBytes = TextureUtil.STtoDDS(_texture.Data);
+ byte[] outBytes = TextureUtil.STtoDDS(_texture.Data);
- using (Stream fileStream = saveFileDialog.OpenFile())
- {
- fileStream.Write(outBytes, 0, outBytes.Length);
- }
-
- // Write metadata to other file
- // @NOTE: We shouldn't need this anymore
- // string pathOutMetadata = Path.Combine(Path.GetDirectoryName(_texture.Path), Path.GetFileNameWithoutExtension(_texture.Path) + ".dat");
- // File.WriteAllBytes(pathOutMetadata, TextureConversion.STmetadata(_texture.Data));
- }
- catch (Exception)
+ using (Stream fileStream = saveFileDialog.OpenFile())
{
- throw;
+ fileStream.Write(outBytes, 0, outBytes.Length);
}
break;
case 2: // PNG
@@ -632,12 +650,24 @@ private void chkDebug_CheckedChanged(object sender, EventArgs e)
//
private void linkGithub_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
- Process.Start(_githubUrl);
+ Process.Start(UI.GithubUrl);
}
private void linkReadme_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
- Process.Start(_helpUrl);
+ Process.Start(UI.HelpUrl);
+ }
+ #endregion
+
+ #region Controls for the tree view
+ private void chkTreeViewFlat_CheckedChanged(object sender, EventArgs e)
+ {
+ UI.RebuildFileTree(GamePath, treeGameFiles.Nodes, _targetFileExtensions, chkTreeViewFlat.Checked);
+ }
+
+ private void btnRefreshTreeView_Click(object sender, EventArgs e)
+ {
+ UI.RebuildFileTree(GamePath, treeGameFiles.Nodes, _targetFileExtensions);
}
#endregion
}
diff --git a/GettingUpTool.csproj b/GettingUpTool.csproj
index c87700a..6d70c3a 100644
--- a/GettingUpTool.csproj
+++ b/GettingUpTool.csproj
@@ -36,6 +36,7 @@
DEBUG;TRACE
prompt
4
+ true
AnyCPU
@@ -45,6 +46,7 @@
TRACE
prompt
4
+ true
Resources\GettingUp.ico
@@ -62,6 +64,24 @@
+
+ Form
+
+
+ Launcher.cs
+
+
+ Form
+
+
+ LevelTool.cs
+
+
+ Form
+
+
+ PakTool.cs
+
True
@@ -77,8 +97,18 @@
-
+
+
+
+ Launcher.cs
+
+
+ LevelTool.cs
+
+
+ PakTool.cs
+
TextureTool.cs
diff --git a/Textures/MonoGame-DxtUtil.cs b/MonoGame/DxtUtil.cs
similarity index 99%
rename from Textures/MonoGame-DxtUtil.cs
rename to MonoGame/DxtUtil.cs
index 8a342d0..c2f035f 100644
--- a/Textures/MonoGame-DxtUtil.cs
+++ b/MonoGame/DxtUtil.cs
@@ -41,7 +41,7 @@
using System;
using System.IO;
-namespace GettingUpTool
+namespace MonoGame
{
internal static class DxtUtil
{
diff --git a/Program.cs b/Program.cs
index 45949e3..f9ee558 100644
--- a/Program.cs
+++ b/Program.cs
@@ -1,10 +1,7 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
using System.Windows.Forms;
-namespace GettingUpTool
+namespace GettingUpTool.Forms
{
static class Program
{
@@ -14,9 +11,19 @@ static class Program
[STAThread]
static void Main()
{
+ while (GameFinder.IsGameRunning())
+ {
+ DialogResult res = MessageBox.Show("Game is already running!\r\nClose game and press OK to continue.", "MEGU Launcher", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
+ if (res != DialogResult.OK)
+ {
+ Application.Exit();
+ return;
+ }
+ }
+
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new TextureTool());
+ Application.Run(new Launcher());
}
}
}
diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
index 82b8b72..9aba07c 100644
--- a/Properties/Settings.Designer.cs
+++ b/Properties/Settings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.18408
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,7 +12,7 @@ namespace GettingUpTool.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -22,5 +22,29 @@ public static Settings Default {
return defaultInstance;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string GamePath {
+ get {
+ return ((string)(this["GamePath"]));
+ }
+ set {
+ this["GamePath"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("engine")]
+ public string GameRoot {
+ get {
+ return ((string)(this["GameRoot"]));
+ }
+ set {
+ this["GameRoot"] = value;
+ }
+ }
}
}
diff --git a/Properties/Settings.settings b/Properties/Settings.settings
index 3964565..4a2a64c 100644
--- a/Properties/Settings.settings
+++ b/Properties/Settings.settings
@@ -1,7 +1,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+ engine
+
+
+
\ No newline at end of file
diff --git a/Resources/GettingUp.png b/Resources/GettingUp.png
new file mode 100644
index 0000000..5ba411d
Binary files /dev/null and b/Resources/GettingUp.png differ
diff --git a/Screenshots/01.jpg b/Screenshots/01.jpg
new file mode 100644
index 0000000..46e74a6
Binary files /dev/null and b/Screenshots/01.jpg differ
diff --git a/Screenshots/02.jpg b/Screenshots/02.jpg
new file mode 100644
index 0000000..d8a9607
Binary files /dev/null and b/Screenshots/02.jpg differ
diff --git a/Screenshots/03.jpg b/Screenshots/03.jpg
new file mode 100644
index 0000000..b1888da
Binary files /dev/null and b/Screenshots/03.jpg differ
diff --git a/Screenshots/04.jpg b/Screenshots/04.jpg
new file mode 100644
index 0000000..dc3a241
Binary files /dev/null and b/Screenshots/04.jpg differ
diff --git a/Screenshots/05.jpg b/Screenshots/05.jpg
new file mode 100644
index 0000000..f9b0d95
Binary files /dev/null and b/Screenshots/05.jpg differ
diff --git a/Textures/TextureUtil.cs b/Textures/TextureUtil.cs
index 5a4444e..69aeb3f 100644
--- a/Textures/TextureUtil.cs
+++ b/Textures/TextureUtil.cs
@@ -21,6 +21,7 @@ public class Texture
public const int ST_TEXTURE_OFFSET = 0x184;
public byte[] Data;
+ public byte[] Pixels;
public string Path = string.Empty;
public string FileName = string.Empty;
@@ -33,6 +34,284 @@ public class Texture
public int DXT = 0;
public int Width = 0;
public int Height = 0;
+ public int AlphaBitDepth = 0;
+
+ public static T BytesToStructure(byte[] bytes)
+ {
+ int size = Marshal.SizeOf(typeof(T));
+ if (bytes.Length < size)
+ throw new ArgumentException("Invalid parameter");
+
+ IntPtr ptr = IntPtr.Zero;
+ try
+ {
+ ptr = Marshal.AllocHGlobal(size);
+
+ Marshal.Copy(bytes, 0, ptr, size);
+
+ return (T)Marshal.PtrToStructure(ptr, typeof(T));
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+
+ public static byte[] StructureToBytes(T structure)
+ {
+ int size = Marshal.SizeOf(typeof(T));
+ byte[] bytes = new byte[size];
+
+ IntPtr ptr = IntPtr.Zero;
+ try
+ {
+ ptr = Marshal.AllocHGlobal(size);
+
+ // Marshal.StructureToPtr(structure, ptr, false);
+ Marshal.Copy(ptr, bytes, 0, size);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+
+ return bytes;
+ }
+
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential, Pack = 0)]
+ public unsafe struct DDS_PIXELFORMAT
+ {
+ public Int32 dwSize;
+ public Int32 dwFlags;
+ public Int32 dwFourCC;
+ public Int32 dwRGBBitCount;
+ public Int32 dwRBitMask;
+ public Int32 dwGBitMask;
+ public Int32 dwBBitMask;
+ public Int32 dwABitMask;
+ }
+
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential, Pack = 0)]
+ public unsafe struct DDSfile
+ {
+ public fixed char DDS[4]; // 0000
+ public Int32 dwSize; // 0004
+ public Int32 dwFlags; // 0008
+ public Int32 dwHeight; // 000C
+ public Int32 dwWidth; // 0010
+ public Int32 dwPitchOrLinearSize; // 0014
+ public Int32 dwDepth; // 0018
+ public Int32 dwMipMapCount; // 001C
+ public fixed Int32 dwReserved[11]; // 0020
+ public DDS_PIXELFORMAT PixelFormat; // 0x004C
+ public Int32 dwCaps; // 006C
+ public Int32 dwCaps2;
+ public Int32 dwCaps3;
+ public Int32 dwCaps4;
+ public Int32 dwReserved2;
+ public byte[] Texture; // 0080
+ }
+
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential, Pack = 0)]
+ public unsafe struct STfile
+ {
+ public fixed char ST[4]; // 0000
+ public Int32 _0004 { get; set; }
+ public Int32 Compression { get; set; } // 0008
+ public Int32 Width { get; set; } // 000C
+ public Int32 Height { get; set; } // 0010
+ public Int32 Width2 { get; set; } // 0014
+ public Int32 Height2 { get; set; } // 0018
+ public Int32 _001C { get; set; } // 001C
+ public Int32 _0020 { get; set; } // 0020
+ public Int32 _0024 { get; set; } // 0024
+ public Int32 _0028 { get; set; } // 0028
+ public Int32 _002C { get; set; } // 002C
+ public Int32 _0030 { get; set; } // 0030
+ public Int32 DdsSize { get; set; } // 0034
+ public Int32 _0038 { get; set; } // 0038
+ public Int32 Unknown { get; set; } // 003C
+ public fixed char Name[32]; // 0040
+ public Int32 _0060 { get; set; } // 0060
+ public Int32 _0064 { get; set; } // 0064
+ public Int32 _0068 { get; set; } // 0068
+ public Int32 _006C { get; set; } // 006C
+ public Int32 _0070 { get; set; } // 0070
+ public Int32 _0074 { get; set; } // 0074
+ public Int32 _0078 { get; set; } // 0078
+ public Int32 _007C { get; set; } // 007C
+ public Int32 _0080 { get; set; } // 0080
+ public Int32 DdsSize2 { get; set; } // 0084
+ public Int32 _0088 { get; set; } // 0088
+ public Int32 DdsSize3 { get; set; } // 008C
+ public Int32 DdsSize4 { get; set; } // 0090
+ public Int32 _0094 { get; set; } // 0094
+ public Int32 _0098 { get; set; } // 0098
+ public Int32 _009C { get; set; } // 009C
+ public Int32 _00A0 { get; set; } // 00A0
+ public Int32 _00A4 { get; set; } // 00A4
+ public Int32 _00A8 { get; set; } // 00A8
+ public Int32 _00AC { get; set; } // 00AC
+ public Int32 _00B0 { get; set; } // 00B0
+ public Int32 _00B4 { get; set; } // 00B4
+ public Int32 _00B8 { get; set; } // 00B8
+ public Int32 _00BC { get; set; } // 00BC
+ public Int32 _00C0 { get; set; } // 00C0
+ public Int32 _00C4 { get; set; } // 00C4
+ public Int32 _00C8 { get; set; } // 00C8
+ public Int32 _00CC { get; set; } // 00CC
+ public Int32 _00D0 { get; set; } // 00D0
+ public Int32 _00D4 { get; set; } // 00D4
+ public Int32 _00D8 { get; set; } // 00D8
+ public Int32 _00DC { get; set; } // 00DC
+ public Int32 _00E0 { get; set; } // 00E0
+ public Int32 _00E4 { get; set; } // 00E4
+ public Int32 _00E8 { get; set; } // 00E8
+ public Int32 _00EC { get; set; } // 00EC
+ public Int32 _00F0 { get; set; } // 00F0
+ public Int32 _00F4 { get; set; } // 00F4
+ public Int32 _00F8 { get; set; } // 00F8
+ public Int32 _00FC { get; set; } // 00FC
+ public Int32 _0100 { get; set; } // 0100
+ public fixed char BIR[4]; // 0104
+ public Int32 _0108 { get; set; } // 0108
+ public Int32 _010C { get; set; } // 010C
+ public Int32 _0110 { get; set; } // 0110
+ public Int32 _0114 { get; set; } // 0114
+ public Int32 _0118 { get; set; } // 0118
+ public Int32 _011C { get; set; } // 011C
+ public Int32 _0120 { get; set; } // 0120
+ public Int32 _0124 { get; set; } // 0124
+ public Int32 _0128 { get; set; } // 0128
+ public Int32 _012C { get; set; } // 012C
+ public Int32 _0130 { get; set; } // 0130
+ public Int32 _0134 { get; set; } // 0134
+ public Int32 _0138 { get; set; } // 0138
+ public Int32 _013C { get; set; } // 013C
+ public Int32 _0140 { get; set; } // 0140
+ public Int32 _0144 { get; set; } // 0144
+ public Int32 _0148 { get; set; } // 0148
+ public Int32 _014C { get; set; } // 014C
+ public Int32 _0150 { get; set; } // 0150
+ public Int32 _0154 { get; set; } // 0154
+ public Int32 _0158 { get; set; } // 0158
+ public Int32 _015C { get; set; } // 015C
+ public Int32 _0160 { get; set; } // 0160
+ public Int32 _0164 { get; set; } // 0164
+ public Int32 _0168 { get; set; } // 0168
+ public Int32 _016C { get; set; } // 016C
+ public Int32 _0170 { get; set; } // 0170
+ public Int32 _0174 { get; set; } // 0174
+ public Int32 _0178 { get; set; } // 0178
+ public Int32 _017C { get; set; } // 017C
+ public Int32 _0180 { get; set; } // 0180
+ public byte[] Texture { get; set; } // 0184
+ }
+
+ public static DDSfile DdsFromBytes(byte[] bytes)
+ {
+ int size = Marshal.SizeOf(typeof(DDSfile));
+ if (bytes.Length < size)
+ throw new ArgumentException("Invalid parameter");
+
+ DDSfile result = new DDSfile();
+ IntPtr ptr = IntPtr.Zero;
+
+ try
+ {
+ ptr = Marshal.AllocHGlobal(size);
+
+ Marshal.Copy(bytes, 0, ptr, size);
+
+ var dataSize = bytes.Length - size;
+ result.Texture = new byte[dataSize];
+ Array.Copy(bytes, size, result.Texture, 0, dataSize);
+
+ return result;
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+
+ public static byte[] DdsToBytes(DDSfile structure)
+ {
+ int size = Marshal.SizeOf(typeof(DDSfile));
+ byte[] bytes = new byte[size + structure.Texture.Length];
+
+ IntPtr ptr = IntPtr.Zero;
+ try
+ {
+ ptr = Marshal.AllocHGlobal(size);
+
+ // Marshal.StructureToPtr(structure, ptr, false);
+ Marshal.Copy(ptr, bytes, 0, size);
+
+ var dataSize = bytes.Length - size;
+ Array.Copy(structure.Texture, 0, bytes, size, structure.Texture.Length);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+
+ return bytes;
+ }
+
+ public static STfile StFromBytes(byte[] bytes)
+ {
+ int size = Marshal.SizeOf(typeof(STfile));
+ if (bytes.Length < size)
+ throw new ArgumentException("Invalid parameter");
+
+ STfile result = new STfile();
+ IntPtr ptr = IntPtr.Zero;
+
+ try
+ {
+ ptr = Marshal.AllocHGlobal(size);
+
+ Marshal.Copy(bytes, 0, ptr, size);
+
+ var dataSize = bytes.Length - size;
+ result.Texture = new byte[dataSize];
+ Array.Copy(bytes, size, result.Texture, 0, dataSize);
+
+ return result;
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+
+ public static byte[] StToBytes(STfile structure)
+ {
+ int size = Marshal.SizeOf(typeof(STfile));
+ byte[] bytes = new byte[size + structure.Texture.Length];
+
+ IntPtr ptr = IntPtr.Zero;
+ try
+ {
+ ptr = Marshal.AllocHGlobal(size);
+
+ // Marshal.StructureToPtr(structure, ptr, false);
+ Marshal.Copy(ptr, bytes, 0, size);
+
+ var dataSize = bytes.Length - size;
+ Array.Copy(structure.Texture, 0, bytes, size, structure.Texture.Length);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+
+ return bytes;
+ }
public Texture(string path)
{
@@ -78,25 +357,6 @@ public virtual void Initialize()
break;
default: break;
}
-
- /*
- if (HeaderString == "ST2") // fileBytes[0] == 'S' && fileBytes[1] == 'T' && fileBytes[2] == '2')
- {
- Type = TextureType.ST2;
- }
- else if (fileBytes[0] == 'S' && fileBytes[1] == 'T')
- {
- Type = TextureType.ST;
- }
- else if (fileBytes[0] == 'B' && fileBytes[1] == 'I' && fileBytes[2] == 'R')
- {
- Type = TextureType.BIR;
- }
- else if (fileBytes[0] == 'D' && fileBytes[1] == 'D' && fileBytes[2] == 'S')
- {
- Type = TextureType.DDS;
- }
- */
}
}
@@ -106,6 +366,8 @@ public ST(string path) : base(path) { }
public ST(byte[] fileBytes) : base(fileBytes) { }
+ public STfile Struct;
+
public override void Initialize()
{
base.Initialize();
@@ -115,15 +377,23 @@ public override void Initialize()
Name += (char)Data[i];
}
- Width = Data[0xC] | Data[0xD] << 8 | Data[0xE] << 16 | Data[0xF] << 24;
- Height = Data[0x10] | Data[0x11] << 8 | Data[0x12] << 16 | Data[0x13] << 24;
+ Width = BitConverter.ToInt32(Data, 0x0C); // Data[0xC] | Data[0xD] << 8 | Data[0xE] << 16 | Data[0xF] << 24;
+ Height = BitConverter.ToInt32(Data, 0x10); // Data[0x10] | Data[0x11] << 8 | Data[0x12] << 16 | Data[0x13] << 24;
+
+ int textureLength = BitConverter.ToInt32(Data, 0x34);
+ int birOffset = Data.Length - textureLength;
+ int textureOffset = birOffset + 0x80;
+ int pixelsSize = Data.Length - textureOffset;
+
+ Pixels = new byte[pixelsSize];
+ Array.Copy(Data, textureOffset, Pixels, 0, pixelsSize);
- // DXT = Data[0x1C] > 0 ? 5 : 1;
- // DXT = Data[0x1C] == 0 ? 1 : Data[0x1C];
+ Struct = StFromBytes(Data);
+ /*
byte[] fmtNibble = { (byte)((Data[0x3C] & 0xF0) >> 4), (byte)(Data[0x3C] & 0x0F) };
// Second nibble is 0=DXT1, 1=DXT3?, 2=DXT5
- // First nibble ?? 1 offset image, 4 used in DXT1, 5/6 used in DXT5
+ // First nibble ?? 1 offset image?, 4 used in DXT1, 5/6 used in DXT5
if (fmtNibble[1] == 0)
{
@@ -137,9 +407,19 @@ public override void Initialize()
{
DXT = 5;
}
- else
+ */
+ switch (Data[0x08])
{
- throw new FormatException($"Unknown texture compression {Data[0x3C]:X2}");
+ case 3:
+ DXT = 1;
+ break;
+ case 4:
+ DXT = 5;
+ break;
+ default:
+ DXT = 0;
+ break;
+ // throw new FormatException($"Unknown texture compression {Data[0x08]:X2}");
}
}
}
@@ -162,25 +442,16 @@ public override void Initialize()
Width = BitConverter.ToInt32(Data, 0x0C);
Height = BitConverter.ToInt32(Data, 0x10);
- byte[] fmtNibble = { (byte)((Data[0x38] & 0xF0) >> 4), (byte)(Data[0x38] & 0x0F) };
- // Second nibble is 0=DXT1, 1=DXT3?, 2=DXT5
- // First nibble ?? 1 offset image, 4 used in DXT1, 5/6 used in DXT5
-
- if (fmtNibble[1] == 0)
- {
- DXT = 1;
- }
- else if (fmtNibble[1] == 1)
- {
- DXT = 3;
- }
- else if (fmtNibble[1] == 2)
- {
- DXT = 5;
- }
- else
+ switch (Data[0x08])
{
- throw new FormatException($"Unknown texture compression {Data[0x38]:X2} ({fmtNibble[0]:X} {fmtNibble[1]:X})");
+ case 3:
+ DXT = 1;
+ break;
+ case 4:
+ DXT = 5;
+ break;
+ default:
+ throw new FormatException($"Unknown texture compression {Data[0x08]:X2}");
}
}
}
@@ -191,10 +462,29 @@ public DDS(string path) : base(path) { }
public DDS(byte[] fileBytes) : base(fileBytes) { }
+ public DDSfile Struct;
+
public override void Initialize()
{
base.Initialize();
+ Struct = DdsFromBytes(Data);
+
+ /*
+ switch (Struct.PixelFormat.dwFourCC)
+ {
+ case 827611204: // DXT1
+ DXT = 1;
+ break;
+ case 861165636: // DXT3
+ DXT = 3;
+ break;
+ case 894720068: // DXT5
+ DXT = 5;
+ break;
+ }
+ */
+
if (Data[0x57] == '5') DXT = 5;
else if (Data[0x57] == '1') DXT = 1;
else if (Data[0x57] == '3') DXT = 3;
@@ -210,6 +500,39 @@ public class TextureUtil
public const int DDS_HEADER_SIZE = 128;
public const int ST_BIR_OFFSET = 0x104;
public const int ST_TEXTURE_OFFSET = 0x184;
+
+ // https://github.com/zigox/arturas-kalonline-coding/blob/master/KDE/KDE/XNAGraphics/DDSLib.cs
+ private const int DDSD_CAPS = 0x1; //Required in every .dds file.
+ private const int DDSD_HEIGHT = 0x2; //Required in every .dds file.
+ private const int DDSD_WIDTH = 0x4; //Required in every .dds file.
+ private const int DDSD_PITCH = 0x8; //Required when pitch is provided for an uncompressed texture.
+ private const int DDSD_PIXELFORMAT = 0x1000; //Required in every .dds file.
+ private const int DDSD_MIPMAPCOUNT = 0x20000; //Required in a mipmapped texture.
+ private const int DDSD_LINEARSIZE = 0x80000; //Required when pitch is provided for a compressed texture.
+ private const int DDSD_DEPTH = 0x800000; //Required in a depth texture.
+
+ private const int DDPF_ALPHAPIXELS = 0x1; //Texture contains alpha data; dwRGBAlphaBitMask contains valid data.
+ private const int DDPF_ALPHA = 0x2; //Used in some older DDS files for alpha channel only uncompressed data (dwRGBBitCount contains the alpha channel bitcount; dwABitMask contains valid data)
+ private const int DDPF_FOURCC = 0x4; //Texture contains compressed RGB data; dwFourCC contains valid data.
+ private const int DDPF_RGB = 0x40; //Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks (dwRBitMask, dwRBitMask, dwRBitMask) contain valid data.
+ private const int DDPF_YUV = 0x200; //Used in some older DDS files for YUV uncompressed data (dwRGBBitCount contains the YUV bit count; dwRBitMask contains the Y mask, dwGBitMask contains the U mask, dwBBitMask contains the V mask)
+ private const int DDPF_LUMINANCE = 0x2000; //Used in some older DDS files for single channel color uncompressed data (dwRGBBitCount contains the luminance channel bit count; dwRBitMask contains the channel mask). Can be combined with DDPF_ALPHAPIXELS for a two channel DDS file.
+ private const int DDPF_Q8W8V8U8 = 0x00080000; //Used by Microsoft tools when a Q8W8V8U8 is present, this is not a documeneted flag.
+
+ private const int DDSCAPS_COMPLEX = 0x8; //Optional; must be used on any file that contains more than one surface (a mipmap, a cubic environment map, or mipmapped volume texture).
+ private const int DDSCAPS_MIPMAP = 0x400000; //Optional; should be used for a mipmap.
+ private const int DDSCAPS_TEXTURE = 0x1000; //Required
+
+ private const int DDSCAPS2_CUBEMAP = 0x200; //Required for a cube map.
+ private const int DDSCAPS2_CUBEMAP_POSITIVEX = 0x400; //Required when these surfaces are stored in a cube map.
+ private const int DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800; //Required when these surfaces are stored in a cube map.
+ private const int DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000; //Required when these surfaces are stored in a cube map.
+ private const int DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000; //Required when these surfaces are stored in a cube map.
+ private const int DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000; //Required when these surfaces are stored in a cube map.
+ private const int DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; //Required when these surfaces are stored in a cube map.
+ private const int DDSCAPS2_VOLUME = 0x200000; //Required for a volume texture.
+
+ private const uint DDS_MAGIC = 0x20534444; // "DDS "
#endregion
[StructLayout(LayoutKind.Sequential)]
@@ -254,35 +577,6 @@ public PixelData(byte[] buffer, int index)
}
}
- //
- // Get "metadata" bytes from ST file
- //
- static public byte[] STmetadata(byte[] fileBytes)
- {
- byte[] metaBytes = new byte[0x22];
-
- string textureName = "";
- for (int i = 0x40; fileBytes[i] != 0; i++)
- {
- textureName += (char)fileBytes[i];
- }
-
- byte[] extraBytes = {
- fileBytes[0x08],
- fileBytes[0x1C],
- fileBytes[0x3C] };
-
- using (MemoryStream ms = new MemoryStream())
- {
- ms.Write(Encoding.ASCII.GetBytes(textureName), 0, Encoding.ASCII.GetBytes(textureName).Length);
- ms.Write(new byte[32 - Encoding.ASCII.GetBytes(textureName).Length], 0, 32 - Encoding.ASCII.GetBytes(textureName).Length);
- ms.Write(extraBytes, 0, extraBytes.Length);
- metaBytes = ms.ToArray();
- }
-
- return metaBytes;
- }
-
//
// Convert DDS to ST
//
@@ -411,7 +705,22 @@ static public byte[] STtoDDS(byte[] fileBytes, bool header=true)
int width = fileBytes[0xC] | fileBytes[0xD] << 8 | fileBytes[0xE] << 16 | fileBytes[0xF] << 24;
int height = fileBytes[0x10] | fileBytes[0x11] << 8 | fileBytes[0x12] << 16 | fileBytes[0x13] << 24;
- int dxt_version = fileBytes[0x1C] > 0 ? 5 : 1;
+ int bitCount = fileBytes[0x88];
+ int alphaMask = fileBytes[0x1C];
+
+ int dxt_version = 0; // fileBytes[0x1C] > 0 ? 5 : 1;
+ switch (fileBytes[0x08])
+ {
+ case 3:
+ dxt_version = 1;
+ break;
+ case 4:
+ dxt_version = 5;
+ break;
+ default:
+ // throw new FormatException($"Unknown texture compression {fileBytes[0x08]:X2}");
+ break;
+ }
PixelData[] pixels = new PixelData[(fileBytes.Length - 0x184) / 16];
int p = 0;
@@ -434,44 +743,58 @@ static public byte[] STtoDDS(byte[] fileBytes, bool header=true)
// DDS_HEADER
ms.Write(Encoding.ASCII.GetBytes("DDS "), 0, 4);
- ms.Write(BitConverter.GetBytes(124), 0, 4); // dwSize
- ms.Write(BitConverter.GetBytes(0x081007), 0, 4); // dwFlags
+ ms.Write(BitConverter.GetBytes(124), 0, 4); // 0004 dwSize
+ ms.Write(BitConverter.GetBytes(0x081007), 0, 4); // 0008 dwFlags
- ms.Write(BitConverter.GetBytes(height), 0, 4); // dwHeight
- ms.Write(BitConverter.GetBytes(width), 0, 4); // dwWidth
+ ms.Write(BitConverter.GetBytes(height), 0, 4); // 000C dwHeight
+ ms.Write(BitConverter.GetBytes(width), 0, 4); // 0010 dwWidth
- ms.Write(BitConverter.GetBytes(width == height ? 0x4000 : 0x2000), 0, 4); // dwPitchOrLinearSize
+ ms.Write(BitConverter.GetBytes(width == height ? 0x4000 : 0x2000), 0, 4); // 0014 dwPitchOrLinearSize
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwDepth
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwMipMapCount
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 0018 dwDepth
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 001C dwMipMapCount
- // dwReserved1[11]
- ms.Write(nullBytes, 0, 11);
+ ms.Write(nullBytes, 0, 44); // 0020 dwReserved1[11]
// DDS_PIXELFORMAT
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwSize
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwFlags
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwFourCC
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwRGBBitCount
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwRBitMask
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwGBitMask
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwBBitMask
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwABitMask
-
- ms.WriteByte(0); // ?
- ms.Write(BitConverter.GetBytes(0x20), 0, 4); // ?
- ms.Write(BitConverter.GetBytes(0x04), 0, 4); // ?
-
- ms.Write(Encoding.ASCII.GetBytes("DXT" + dxt_version), 0, 4);
- ms.Write(nullBytes, 0, 20);
-
- ms.Write(BitConverter.GetBytes(0x1000), 0, 4); // dwCaps
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwCaps2
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwCaps3
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwCaps4
- ms.Write(BitConverter.GetBytes(0), 0, 4); // dwReserved2
+ ms.Write(BitConverter.GetBytes(32), 0, 4); // 004C dwSize
+
+ if (dxt_version != 0)
+ {
+ ms.Write(BitConverter.GetBytes(DDPF_FOURCC), 0, 4); // 0050 dwFlags
+ ms.Write(Encoding.ASCII.GetBytes("DXT" + dxt_version), 0, 4); // 0054 dwFourCC
+ }
+ else
+ {
+ ms.Write(BitConverter.GetBytes(DDPF_RGB), 0, 4); // 0050 dwFlags
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 0054 dwFourCC
+ }
+
+ if (dxt_version != 0)
+ {
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 0058 dwRGBBitCount
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 005C dwRBitMask
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 0060 dwGBitMask
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 0064 dwBBitMask
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 0068 dwABitMask
+ }
+ else
+ {
+ ms.Write(BitConverter.GetBytes(bitCount), 0, 4); // 0058 dwRGBBitCount
+ ms.Write(BitConverter.GetBytes(0x00ff0000), 0, 4); // 005C dwRBitMask
+ ms.Write(BitConverter.GetBytes(0x0000ff00), 0, 4); // 0060 dwGBitMask
+ ms.Write(BitConverter.GetBytes(0x000000ff), 0, 4); // 0064 dwBBitMask
+ ms.Write(BitConverter.GetBytes(0xff000000), 0, 4); // 0068 dwABitMask
+ }
+
+ ms.Write(BitConverter.GetBytes(0x1000), 0, 4); // 006C dwCaps
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 0070 dwCaps2
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 0074 dwCaps3
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 0078 dwCaps4
+ ms.Write(BitConverter.GetBytes(0), 0, 4); // 007C dwReserved2
}
+ // Texture data
foreach (PixelData pixel in pixels)
{
ms.WriteByte(pixel.alpha);
diff --git a/Utils/FileAnalysis.cs b/Utils/FileAnalysis.cs
index 6330d9b..17c14bd 100644
--- a/Utils/FileAnalysis.cs
+++ b/Utils/FileAnalysis.cs
@@ -1,5 +1,6 @@
using System;
using System.Text;
+using static GettingUpTool.Texture;
namespace GettingUpTool
{
@@ -10,224 +11,103 @@ private static string StringFromByteArray(byte[] array, int index, int length)
return Encoding.ASCII.GetString(array, index, length).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?');
}
+ private static string HexLine(ref Int32 offset, ArraySegment bytes, Type type, string comment="", bool show_bytes=true)
+ {
+ string str = $"{offset:X4}";
+
+ if (show_bytes == true)
+ str += $"\t{bytes.Array[bytes.Offset + 0]:X2} {bytes.Array[bytes.Offset + 1]:X2} {bytes.Array[bytes.Offset + 2]:X2} {bytes.Array[bytes.Offset + 3]:X2}";
+
+ if (type.FullName == "System.String")
+ str += $"\t{StringFromByteArray(bytes.Array, bytes.Offset, bytes.Count)}";
+ else if (type.FullName == "System.Int32")
+ str += $"\t{BitConverter.ToInt32(bytes.Array, bytes.Offset)}";
+ else
+ str += "\t\t";
+
+ if (comment != "")
+ str += $"\t{comment}";
+
+ str += Environment.NewLine;
+
+ offset += bytes.Count;
+
+ return str;
+ }
+
public static string AnalyzeST(byte[] fileBytes)
{
string debugLog = string.Empty;
int i = 0;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{StringFromByteArray(fileBytes, i, 4)}";
- // debugLog += $"\t{Convert.ToChar(fileBytes[0])}";
- // debugLog += $"{Convert.ToChar(fileBytes[1])}";
- // debugLog += $"{Convert.ToChar(fileBytes[2])}";
- // debugLog += $"{Convert.ToChar(fileBytes[3])}";
- debugLog += $"\tST header";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tWidth";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tHeight";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tWidth";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tHeight";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tAlpha?";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t0";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t1";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t1";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t1";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tDDS size";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tTexture data offset?";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tCompression?";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 32).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- // debugLog += $"\tFilename";
- debugLog += Environment.NewLine;
- i += 32;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t2";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t0x0A";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tDDS size";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tBit output?";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tDDS size 2";
- debugLog += Environment.NewLine;
- i += 4;
-
- for (int n = 0; n < 0x70; n += 4)
- {
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- // debugLog += $"\t{Convert.ToChar(fileBytes[i + 0])}{Convert.ToChar(fileBytes[i + 1])}{Convert.ToChar(fileBytes[i + 2])}{Convert.ToChar(fileBytes[i + 3])}";
- debugLog += Environment.NewLine;
- i += 4; // 0x70;
- }
-
- // 0104
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- // debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tBIR header";
- debugLog += Environment.NewLine;
- i += 4;
-
- for (int n = 0; n < 0x7C; n += 4)
- {
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
- }
-
- // 0184
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\tTexture data {fileBytes.Length - i} bytes";
- debugLog += Environment.NewLine;
- i += 4;
+ // var fileStruct = BytesToStructure(fileBytes);
+
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(string), "header ----------");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Compression");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Width");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Height");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Width2");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Height2");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Alpha bit depth");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "0");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "1 / 8");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "1 / 4");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "??");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "1");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "DDS size");
+ int birOffset = 0x84 + fileBytes[i];
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Texture data offset?");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Tiling?");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 32), typeof(string), "", false);
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "2");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "10");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "DDS size 2");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Bit output?");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "DDS size 3");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "DDS size 4");
+ while (i < birOffset)
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(string), "header ----------");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += $". Texture data {fileBytes.Length - i} bytes";
return debugLog;
}
@@ -237,227 +117,46 @@ public static string AnalyzeST2(byte[] fileBytes)
string debugLog = string.Empty;
int i = 0;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{StringFromByteArray(fileBytes, i, 4)}";
- // debugLog += $"\t{Convert.ToChar(fileBytes[0])}";
- // debugLog += $"{Convert.ToChar(fileBytes[1])}";
- // debugLog += $"{Convert.ToChar(fileBytes[2])}";
- // debugLog += $"{Convert.ToChar(fileBytes[3])}";
- debugLog += $"\tHeader";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tWidth";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tHeight";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tWidth";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tHeight";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tAlpha?";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t0";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t1";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t1";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t0";
- debugLog += Environment.NewLine;
- i += 4;
-
- // 0030
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t1";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tDDS size";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tTexture data offset?";
- debugLog += Environment.NewLine;
- i += 4;
-
- // 003C
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- // 0040 Filename
- debugLog += $"{i:X4}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 32).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 32;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t2";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t10";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tDDS size";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tBit output?";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tBIR size";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tDDS size 2";
- debugLog += Environment.NewLine;
- i += 4;
-
- // 0094
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += Environment.NewLine;
- i += 4;
-
- // 00A4 BIR header
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += $"\tBIR/DDS header";
- debugLog += Environment.NewLine;
- i += 4;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{Encoding.ASCII.GetString(fileBytes, i, 4).Replace('\0', ' ').Replace('\t', '?').Replace('\r', '?').Replace('\n', '?')}";
- debugLog += Environment.NewLine;
- i += 4;
-
- // 00B4
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\tTexture data {fileBytes.Length - i} bytes";
- debugLog += Environment.NewLine;
- i += 4;
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(string), "header ----------");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Compression");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Width");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Height");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Width2");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Height2");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Alpha bit depth");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "0");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "1");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "1");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "??");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "1");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "DDS size");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Texture data offset?");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Tiling?");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 32), typeof(string), "", false);
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "2");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "10");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "DDS size 2");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "Bit output?");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "DDS size 3");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "DDS size 4");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(string), "header ----------");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32));
+ debugLog += $". Texture data {fileBytes.Length - i} bytes";
return debugLog;
}
@@ -467,145 +166,34 @@ public static string AnalyzeDDS(byte[] fileBytes)
string debugLog = string.Empty;
int i = 0;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{StringFromByteArray(fileBytes, i, 4)}";
- debugLog += $"\tHeader";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwSize";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwFlags";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwHeight";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwWidth";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwPitchOrLinearSize";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwDepth";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwMipMapCount";
- debugLog += Environment.NewLine;
- i += 4;
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(string), "Header");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwSize");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwFlags");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwHeight");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwWidth");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwPitchOrLinearSize");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwDepth");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwMipMapCount");
- // 0020
for (int n = 0; n < 0x2C; n += 4)
{
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwReserved1[{n / 4}]";
- debugLog += Environment.NewLine;
- i += 4;
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), $"dwReserved[{n / 4}]");
}
- // 004C
debugLog += $". DDS_PIXELFORMAT" + Environment.NewLine;
-
- debugLog += $"| {i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwSize";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"| {i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwFlags";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"| {i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- // debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\t{StringFromByteArray(fileBytes, i, 4)}";
- debugLog += $"\tdwFourCC";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"| {i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwRGBBitCount";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"| {i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwRBitMask";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"| {i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwGBitMask";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"| {i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwBBitMask";
- debugLog += Environment.NewLine;
- i += 4;
-
- debugLog += $"' {i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwABitMask";
- debugLog += Environment.NewLine;
- i += 4;
-
- // 006C
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwCaps";
- debugLog += Environment.NewLine;
- i += 4;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwCaps2";
- debugLog += Environment.NewLine;
- i += 4;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwCaps3";
- debugLog += Environment.NewLine;
- i += 4;
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwCaps4";
- debugLog += Environment.NewLine;
- i += 4;
-
- // 007C
- debugLog += $"{i:X4}\t{fileBytes[i + 0]:X2} {fileBytes[i + 1]:X2} {fileBytes[i + 2]:X2} {fileBytes[i + 3]:X2}";
- debugLog += $"\t{BitConverter.ToInt32(fileBytes, i)}";
- debugLog += $"\tdwReserved2";
- debugLog += Environment.NewLine;
- i += 4;
-
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwSize");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwFlags");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(string), "dwFourCC");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwRGBBitCount");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwRBitMask");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwGBitMask");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwBBitMask");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwABitMask");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwCaps");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwCaps2");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwCaps3");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwCaps4");
+ debugLog += HexLine(ref i, new ArraySegment(fileBytes, i, 4), typeof(Int32), "dwReserved2");
debugLog += $". Texture data {fileBytes.Length - i} bytes";
return debugLog;
diff --git a/Utils/GameFinder.cs b/Utils/GameFinder.cs
index 74fe8c9..06933d0 100644
--- a/Utils/GameFinder.cs
+++ b/Utils/GameFinder.cs
@@ -1,5 +1,6 @@
using Microsoft.Win32;
using System;
+using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
@@ -7,6 +8,11 @@ namespace GettingUpTool
{
public static class GameFinder
{
+ public static bool IsGameRunning()
+ {
+ return Process.GetProcessesByName("GettingUp").Length != 0;
+ }
+
public static bool ValidateGamePath(DirectoryInfo path)
{
bool isValid = false;
@@ -126,7 +132,7 @@ public static DirectoryInfo LocateGamePath()
if (!dirSteamLib.Exists) continue;
// Check if this library folder contains MEGU
- path = new DirectoryInfo(Path.Combine(pathSteam, @"steamapps\common\Marc Ecko's Getting Up 2"));
+ path = new DirectoryInfo(Path.Combine(dirSteamLib.FullName, @"steamapps\common\Marc Ecko's Getting Up 2"));
if (ValidateGamePath(path)) return path;
}
}
diff --git a/Utils/UiHelpers.cs b/Utils/UiHelpers.cs
new file mode 100644
index 0000000..d38a49d
--- /dev/null
+++ b/Utils/UiHelpers.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace GettingUpTool
+{
+ static class UI
+ {
+ public const string GithubUrl = "https://github.com/Asbra/GettingUpTool";
+ public const string HelpUrl = "https://github.com/Asbra/GettingUpTool/wiki/Replacing-textures-graffiti-in-Marc-Ecko%27s-Getting-Up";
+
+ public static void BuildTree(DirectoryInfo directoryInfo, TreeNodeCollection nodes, string[] fileExtensions, bool flat = false)
+ {
+ TreeNode curNode = null;
+ if (flat && nodes.Count > 0)
+ {
+ curNode = nodes[0];
+ }
+ else
+ {
+ curNode = nodes.Add(directoryInfo.Name);
+ }
+
+ foreach (FileInfo file in directoryInfo.GetFiles())
+ {
+ string filext = file.Extension.ToLower();
+ // if (filext == ".st" || filext == ".bir" || filext == ".dds" || filext == ".st2")
+ // if (filext == ".st" || filext == ".dds")
+ if (Array.IndexOf(fileExtensions, filext) > -1)
+ {
+ curNode.Nodes.Add(file.FullName, file.Name);
+ }
+ }
+
+ foreach (DirectoryInfo subdir in directoryInfo.GetDirectories())
+ {
+ BuildTree(subdir, flat ? nodes : curNode.Nodes, fileExtensions, flat);
+ }
+ }
+
+ private static void ClearEmptyNodes(TreeNodeCollection tv, TreeNode tn)
+ {
+ if (tn.Nodes.Count > 0)
+ {
+ for (int iNode = 0; iNode < tn.Nodes.Count; iNode++)
+ {
+ ClearEmptyNodes(tv, tn.Nodes[iNode]);
+ }
+ }
+ else if (string.IsNullOrWhiteSpace(tn.Name))
+ {
+ tv.Remove(tn);
+ }
+ }
+
+ public static void RebuildFileTree(DirectoryInfo directoryInfo, TreeNodeCollection nodes, string[] fileExtensions, bool flat = false)
+ {
+ nodes.Clear();
+
+ BuildTree(directoryInfo, nodes, fileExtensions, flat);
+
+ if (nodes.Count > 0)
+ {
+ for (int i = 0; i < 30; i++)
+ ClearEmptyNodes(nodes, nodes[0]);
+
+ // Recursively delete empty nodes
+ for (int i = 0; i < nodes.Count; i++)
+ {
+ if (nodes[i].Nodes.Count == 0)
+ {
+ nodes.Remove(nodes[i]);
+
+ if (string.IsNullOrWhiteSpace(nodes[i].Name) || Directory.Exists(nodes[i].Name))
+ {
+ nodes.Remove(nodes[i]);
+ }
+ }
+ }
+
+ // Open the first node by default
+ nodes[0].Expand();
+ if (nodes[0].Nodes.Count > 0)
+ nodes[0].Nodes[0].Expand();
+ }
+ }
+ }
+}