From c6d0e39c725306a1c008db9cf4c1c02a12929195 Mon Sep 17 00:00:00 2001 From: Oliver Bevan Date: Thu, 1 Aug 2024 22:09:01 +0100 Subject: [PATCH] Complete gamecube banner editor #74 --- IndustrialPark/IndustrialPark.csproj | 2 + .../MainForm/CreateGameCubeBanner.Designer.cs | 285 ++++++++++-------- .../MainForm/CreateGameCubeBanner.cs | 119 ++++++++ .../MainForm/CreateGameCubeBanner.resx | 24 -- IndustrialPark/Other/GameCubeBanner.cs | 277 +++++++++++++++++ .../Properties/Resources.Designer.cs | 11 +- IndustrialPark/Properties/Resources.resx | 67 +--- .../Resources/PlaceholderBanner1.png | Bin 0 -> 1063 bytes 8 files changed, 568 insertions(+), 217 deletions(-) create mode 100644 IndustrialPark/Other/GameCubeBanner.cs create mode 100644 IndustrialPark/Resources/PlaceholderBanner1.png diff --git a/IndustrialPark/IndustrialPark.csproj b/IndustrialPark/IndustrialPark.csproj index d5390a5e..faf813a8 100644 --- a/IndustrialPark/IndustrialPark.csproj +++ b/IndustrialPark/IndustrialPark.csproj @@ -485,6 +485,7 @@ OpenLevel.cs + @@ -939,6 +940,7 @@ PreserveNewest + PreserveNewest diff --git a/IndustrialPark/MainForm/CreateGameCubeBanner.Designer.cs b/IndustrialPark/MainForm/CreateGameCubeBanner.Designer.cs index 69032117..9189183d 100644 --- a/IndustrialPark/MainForm/CreateGameCubeBanner.Designer.cs +++ b/IndustrialPark/MainForm/CreateGameCubeBanner.Designer.cs @@ -35,32 +35,33 @@ private void InitializeComponent() this.label1 = new System.Windows.Forms.Label(); this.saveButton = new System.Windows.Forms.Button(); this.cancelButton = new System.Windows.Forms.Button(); - this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.bannerPictureBox = new System.Windows.Forms.PictureBox(); this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.label2 = new System.Windows.Forms.Label(); - this.textBox1 = new System.Windows.Forms.TextBox(); - this.button1 = new System.Windows.Forms.Button(); - this.textBox2 = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); - this.label4 = new System.Windows.Forms.Label(); - this.textBox3 = new System.Windows.Forms.TextBox(); - this.textBox4 = new System.Windows.Forms.TextBox(); - this.label5 = new System.Windows.Forms.Label(); - this.label6 = new System.Windows.Forms.Label(); - this.textBox5 = new System.Windows.Forms.TextBox(); + this.descriptionTextBox = new System.Windows.Forms.TextBox(); this.label7 = new System.Windows.Forms.Label(); - this.textBox6 = new System.Windows.Forms.TextBox(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.creatorFullTextBox = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.titleFullTextBox = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.creatorTextBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.titleTextBox = new System.Windows.Forms.TextBox(); + this.selectImageButton = new System.Windows.Forms.Button(); + this.imagePathTextBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.importBnrButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.bannerPictureBox)).BeginInit(); this.groupBox1.SuspendLayout(); this.SuspendLayout(); // // label1 // this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Location = new System.Drawing.Point(147, 9); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(506, 46); - this.label1.TabIndex = 0; + this.label1.Size = new System.Drawing.Size(371, 46); + this.label1.TabIndex = 1; this.label1.Text = resources.GetString("label1.Text"); // // saveButton @@ -70,9 +71,10 @@ private void InitializeComponent() this.saveButton.Location = new System.Drawing.Point(323, 306); this.saveButton.Name = "saveButton"; this.saveButton.Size = new System.Drawing.Size(97, 23); - this.saveButton.TabIndex = 9; + this.saveButton.TabIndex = 16; this.saveButton.Text = "Save Banner"; this.saveButton.UseVisualStyleBackColor = true; + this.saveButton.Click += new System.EventHandler(this.saveButton_Click); // // cancelButton // @@ -81,160 +83,177 @@ private void InitializeComponent() this.cancelButton.Location = new System.Drawing.Point(426, 306); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(92, 23); - this.cancelButton.TabIndex = 10; + this.cancelButton.TabIndex = 17; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); // - // pictureBox1 + // bannerPictureBox // - this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image"))); - this.pictureBox1.InitialImage = null; - this.pictureBox1.Location = new System.Drawing.Point(90, 22); - this.pictureBox1.Name = "pictureBox1"; - this.pictureBox1.Size = new System.Drawing.Size(96, 32); - this.pictureBox1.TabIndex = 3; - this.pictureBox1.TabStop = false; + this.bannerPictureBox.Image = global::IndustrialPark.Properties.Resources.PlaceholderBanner; + this.bannerPictureBox.InitialImage = null; + this.bannerPictureBox.Location = new System.Drawing.Point(90, 22); + this.bannerPictureBox.Name = "bannerPictureBox"; + this.bannerPictureBox.Size = new System.Drawing.Size(96, 32); + this.bannerPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.bannerPictureBox.TabIndex = 3; + this.bannerPictureBox.TabStop = false; // // groupBox1 // this.groupBox1.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.groupBox1.Controls.Add(this.textBox6); + this.groupBox1.Controls.Add(this.descriptionTextBox); this.groupBox1.Controls.Add(this.label7); - this.groupBox1.Controls.Add(this.textBox5); + this.groupBox1.Controls.Add(this.creatorFullTextBox); this.groupBox1.Controls.Add(this.label6); - this.groupBox1.Controls.Add(this.textBox4); + this.groupBox1.Controls.Add(this.titleFullTextBox); this.groupBox1.Controls.Add(this.label5); - this.groupBox1.Controls.Add(this.textBox3); + this.groupBox1.Controls.Add(this.creatorTextBox); this.groupBox1.Controls.Add(this.label4); this.groupBox1.Controls.Add(this.label3); - this.groupBox1.Controls.Add(this.textBox2); - this.groupBox1.Controls.Add(this.button1); - this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.titleTextBox); + this.groupBox1.Controls.Add(this.selectImageButton); + this.groupBox1.Controls.Add(this.imagePathTextBox); this.groupBox1.Controls.Add(this.label2); - this.groupBox1.Controls.Add(this.pictureBox1); + this.groupBox1.Controls.Add(this.bannerPictureBox); this.groupBox1.Location = new System.Drawing.Point(12, 58); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(506, 242); - this.groupBox1.TabIndex = 1; + this.groupBox1.TabIndex = 2; this.groupBox1.TabStop = false; this.groupBox1.Text = "Banner Metadata"; // - // label2 + // descriptionTextBox // - this.label2.Location = new System.Drawing.Point(18, 22); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(66, 32); - this.label2.TabIndex = 4; - this.label2.Text = "Image"; - this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.descriptionTextBox.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.descriptionTextBox.Location = new System.Drawing.Point(90, 178); + this.descriptionTextBox.MaxLength = 128; + this.descriptionTextBox.Multiline = true; + this.descriptionTextBox.Name = "descriptionTextBox"; + this.descriptionTextBox.Size = new System.Drawing.Size(407, 47); + this.descriptionTextBox.TabIndex = 15; + this.descriptionTextBox.TextChanged += new System.EventHandler(this.metadataTextChanged); // - // textBox1 + // label7 // - this.textBox1.Location = new System.Drawing.Point(192, 29); - this.textBox1.Name = "textBox1"; - this.textBox1.ReadOnly = true; - this.textBox1.Size = new System.Drawing.Size(204, 20); - this.textBox1.TabIndex = 2; + this.label7.Location = new System.Drawing.Point(3, 178); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(81, 47); + this.label7.TabIndex = 14; + this.label7.Text = "Description"; + this.label7.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // button1 + // creatorFullTextBox // - this.button1.Location = new System.Drawing.Point(402, 25); - this.button1.Name = "button1"; - this.button1.Size = new System.Drawing.Size(98, 26); - this.button1.TabIndex = 3; - this.button1.Text = "Select Image"; - this.button1.UseVisualStyleBackColor = true; + this.creatorFullTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.creatorFullTextBox.Location = new System.Drawing.Point(90, 139); + this.creatorFullTextBox.MaxLength = 64; + this.creatorFullTextBox.Name = "creatorFullTextBox"; + this.creatorFullTextBox.Size = new System.Drawing.Size(410, 20); + this.creatorFullTextBox.TabIndex = 13; + this.creatorFullTextBox.TextChanged += new System.EventHandler(this.metadataTextChanged); // - // textBox2 + // label6 // - this.textBox2.Location = new System.Drawing.Point(90, 67); - this.textBox2.MaxLength = 32; - this.textBox2.Name = "textBox2"; - this.textBox2.Size = new System.Drawing.Size(203, 20); - this.textBox2.TabIndex = 4; + this.label6.Location = new System.Drawing.Point(3, 132); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(81, 32); + this.label6.TabIndex = 12; + this.label6.Text = "Creator (Full)"; + this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // label3 + // titleFullTextBox // - this.label3.Location = new System.Drawing.Point(3, 60); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(78, 32); - this.label3.TabIndex = 8; - this.label3.Text = "Game Name"; - this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.titleFullTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.titleFullTextBox.Location = new System.Drawing.Point(90, 104); + this.titleFullTextBox.MaxLength = 64; + this.titleFullTextBox.Name = "titleFullTextBox"; + this.titleFullTextBox.Size = new System.Drawing.Size(410, 20); + this.titleFullTextBox.TabIndex = 11; + this.titleFullTextBox.TextChanged += new System.EventHandler(this.metadataTextChanged); + // + // label5 + // + this.label5.Location = new System.Drawing.Point(3, 100); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(81, 32); + this.label5.TabIndex = 10; + this.label5.Text = "Game Title (Full)\r\n"; + this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // creatorTextBox + // + this.creatorTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.creatorTextBox.Location = new System.Drawing.Point(358, 67); + this.creatorTextBox.MaxLength = 32; + this.creatorTextBox.Name = "creatorTextBox"; + this.creatorTextBox.Size = new System.Drawing.Size(142, 20); + this.creatorTextBox.TabIndex = 9; + this.creatorTextBox.TextChanged += new System.EventHandler(this.metadataTextChanged); // // label4 // this.label4.Location = new System.Drawing.Point(299, 60); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(53, 32); - this.label4.TabIndex = 9; + this.label4.TabIndex = 8; this.label4.Text = "Creator"; this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // textBox3 - // - this.textBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBox3.Location = new System.Drawing.Point(358, 67); - this.textBox3.MaxLength = 32; - this.textBox3.Name = "textBox3"; - this.textBox3.Size = new System.Drawing.Size(142, 20); - this.textBox3.TabIndex = 5; - // - // textBox4 + // label3 // - this.textBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBox4.Location = new System.Drawing.Point(90, 104); - this.textBox4.MaxLength = 64; - this.textBox4.Name = "textBox4"; - this.textBox4.Size = new System.Drawing.Size(410, 20); - this.textBox4.TabIndex = 6; + this.label3.Location = new System.Drawing.Point(3, 60); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(78, 32); + this.label3.TabIndex = 6; + this.label3.Text = "Game Name"; + this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // label5 + // titleTextBox // - this.label5.Location = new System.Drawing.Point(3, 100); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(81, 32); - this.label5.TabIndex = 11; - this.label5.Text = "Game Title (Full)\r\n"; - this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.titleTextBox.Location = new System.Drawing.Point(90, 67); + this.titleTextBox.MaxLength = 32; + this.titleTextBox.Name = "titleTextBox"; + this.titleTextBox.Size = new System.Drawing.Size(203, 20); + this.titleTextBox.TabIndex = 7; + this.titleTextBox.TextChanged += new System.EventHandler(this.metadataTextChanged); // - // label6 + // selectImageButton // - this.label6.Location = new System.Drawing.Point(3, 132); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(81, 32); - this.label6.TabIndex = 13; - this.label6.Text = "Creator (Full)"; - this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.selectImageButton.Location = new System.Drawing.Point(402, 25); + this.selectImageButton.Name = "selectImageButton"; + this.selectImageButton.Size = new System.Drawing.Size(98, 26); + this.selectImageButton.TabIndex = 5; + this.selectImageButton.Text = "Select Image..."; + this.selectImageButton.UseVisualStyleBackColor = true; + this.selectImageButton.Click += new System.EventHandler(this.selectImageButton_Click); // - // textBox5 + // imagePathTextBox // - this.textBox5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBox5.Location = new System.Drawing.Point(90, 139); - this.textBox5.MaxLength = 64; - this.textBox5.Name = "textBox5"; - this.textBox5.Size = new System.Drawing.Size(410, 20); - this.textBox5.TabIndex = 7; + this.imagePathTextBox.Location = new System.Drawing.Point(192, 29); + this.imagePathTextBox.Name = "imagePathTextBox"; + this.imagePathTextBox.ReadOnly = true; + this.imagePathTextBox.Size = new System.Drawing.Size(204, 20); + this.imagePathTextBox.TabIndex = 4; // - // label7 + // label2 // - this.label7.Location = new System.Drawing.Point(3, 178); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(81, 47); - this.label7.TabIndex = 15; - this.label7.Text = "Description"; - this.label7.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.label2.Location = new System.Drawing.Point(18, 22); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(66, 32); + this.label2.TabIndex = 3; + this.label2.Text = "Image"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // textBox6 + // importBnrButton // - this.textBox6.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.textBox6.Location = new System.Drawing.Point(90, 178); - this.textBox6.MaxLength = 128; - this.textBox6.Multiline = true; - this.textBox6.Name = "textBox6"; - this.textBox6.Size = new System.Drawing.Size(407, 47); - this.textBox6.TabIndex = 8; + this.importBnrButton.Location = new System.Drawing.Point(12, 16); + this.importBnrButton.Name = "importBnrButton"; + this.importBnrButton.Size = new System.Drawing.Size(129, 26); + this.importBnrButton.TabIndex = 0; + this.importBnrButton.Text = "Import from BNR..."; + this.importBnrButton.UseVisualStyleBackColor = true; + this.importBnrButton.Click += new System.EventHandler(this.importBnrButton_Click); // // CreateGameCubeBanner // @@ -244,6 +263,7 @@ private void InitializeComponent() this.BackColor = System.Drawing.SystemColors.Control; this.CancelButton = this.cancelButton; this.ClientSize = new System.Drawing.Size(530, 341); + this.Controls.Add(this.importBnrButton); this.Controls.Add(this.groupBox1); this.Controls.Add(this.cancelButton); this.Controls.Add(this.saveButton); @@ -253,34 +273,37 @@ private void InitializeComponent() this.MaximizeBox = false; this.Name = "CreateGameCubeBanner"; this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Create GameCube Banner"; - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.bannerPictureBox)).EndInit(); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.ResumeLayout(false); } - private System.Windows.Forms.TextBox textBox6; + private System.Windows.Forms.Button importBnrButton; + + private System.Windows.Forms.TextBox descriptionTextBox; - private System.Windows.Forms.TextBox textBox5; + private System.Windows.Forms.TextBox creatorFullTextBox; private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label6; - private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.TextBox titleFullTextBox; private System.Windows.Forms.Label label5; - private System.Windows.Forms.TextBox textBox1; - private System.Windows.Forms.Button button1; - private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox imagePathTextBox; + private System.Windows.Forms.Button selectImageButton; + private System.Windows.Forms.TextBox titleTextBox; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label4; - private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.TextBox creatorTextBox; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.Label label2; - private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.PictureBox bannerPictureBox; private System.Windows.Forms.Button saveButton; private System.Windows.Forms.Button cancelButton; diff --git a/IndustrialPark/MainForm/CreateGameCubeBanner.cs b/IndustrialPark/MainForm/CreateGameCubeBanner.cs index 6f96f0d3..73f39334 100644 --- a/IndustrialPark/MainForm/CreateGameCubeBanner.cs +++ b/IndustrialPark/MainForm/CreateGameCubeBanner.cs @@ -1,5 +1,10 @@ using System; +using System.Diagnostics; +using System.Drawing; +using System.IO; using System.Windows.Forms; +using IndustrialPark.Other; +using Image = System.Web.UI.WebControls.Image; namespace IndustrialPark { @@ -14,5 +19,119 @@ private void cancelButton_Click(object sender, EventArgs e) { Close(); } + + private void saveButton_Click(object sender, EventArgs e) + { + Bitmap image = new Bitmap(GameCubeBanner.IMAGE_WIDTH, GameCubeBanner.IMAGE_HEIGHT); + bannerPictureBox.DrawToBitmap(image, bannerPictureBox.ClientRectangle); + + GameCubeBanner banner = new GameCubeBanner + { + Image = image, + Creator = creatorTextBox.Text, + CreatorFull = creatorFullTextBox.Text, + Description = descriptionTextBox.Text, + Title = titleTextBox.Text, + TitleFull = titleFullTextBox.Text + }; + + // Get save location from dialog + + SaveFileDialog dialog = new SaveFileDialog + { + Filter = "GameCube Banner (*.bnr)|*.bnr", + Title = "Save GameCube Banner", + FileName = GameCubeBanner.DEFAULT_FILENAME, + AddExtension = true, + DefaultExt = "bnr" + }; + + if (dialog.ShowDialog() == DialogResult.OK) + { + // Save banner to file + if (banner.SaveToFile(dialog.FileName)) + { + MessageBox.Show("Banner saved successfully.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + MessageBox.Show("Failed to save banner.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private void selectImageButton_Click(object sender, EventArgs e) + { + // Open file dialog to select image + OpenFileDialog dialog = new OpenFileDialog + { + Filter = "Image Files|*.bmp;*.jpg;*.jpeg;*.png;*.gif;*.tif;*.tiff", + Title = "Select an image file" + }; + + if (dialog.ShowDialog() == DialogResult.OK) + { + imagePathTextBox.Text = dialog.FileName; + metadataTextChanged(null, null); + + // Update PictureBox with image + try + { + bannerPictureBox.Image = new Bitmap(dialog.FileName); + } + catch (Exception ex) + { + MessageBox.Show("Failed to load image: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private void metadataTextChanged(object sender, EventArgs e) + { + // Enable save button if all metadata fields are filled + saveButton.Enabled = !string.IsNullOrWhiteSpace(titleTextBox.Text) && + !string.IsNullOrWhiteSpace(creatorTextBox.Text) && + !string.IsNullOrWhiteSpace(titleFullTextBox.Text) && + !string.IsNullOrWhiteSpace(creatorFullTextBox.Text) && + !string.IsNullOrWhiteSpace(descriptionTextBox.Text); + + } + + private void importBnrButton_Click(object sender, EventArgs e) + { + // Open file dialog to select BNR file + + OpenFileDialog dialog = new OpenFileDialog + { + Filter = "GameCube Banner (*.bnr)|*.bnr", + Title = "Select a GameCube Banner file" + }; + + if (dialog.ShowDialog() == DialogResult.OK) + { + // Import banner from file + GameCubeBanner banner = GameCubeBanner.ImportFromFile(dialog.FileName); + + if (banner != null) + { + // Set metadata fields + titleTextBox.Text = banner.Title; + creatorTextBox.Text = banner.Creator; + titleFullTextBox.Text = banner.TitleFull; + creatorFullTextBox.Text = banner.CreatorFull; + descriptionTextBox.Text = banner.Description; + + // Convert image to PictureBox + bannerPictureBox.Image = banner.Image; + + // Update image path text box + imagePathTextBox.Text = dialog.FileName; + } + else + { + MessageBox.Show("Failed to import banner.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } } } \ No newline at end of file diff --git a/IndustrialPark/MainForm/CreateGameCubeBanner.resx b/IndustrialPark/MainForm/CreateGameCubeBanner.resx index 32e32f96..5641466c 100644 --- a/IndustrialPark/MainForm/CreateGameCubeBanner.resx +++ b/IndustrialPark/MainForm/CreateGameCubeBanner.resx @@ -120,28 +120,4 @@ GameCube banners, named "opening.bnr", contain metadata about the game, including its title and creator, and a 96px x 32px banner image which is displayed in menu mode. It is also displayed in Dolphin's game list. - - - - iVBORw0KGgoAAAANSUhEUgAAAGAAAAAgCAYAAADtwH1UAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAACxMAAAsTAQCanBgAAAPpSURBVGhD7ZfpKzdRFMefP+pnl2xRtlKWCAlZsiZCIkmJ - LIUi8sIaUpZs2UO2f+o+fU7daWbMz7OY6b65Lz5xz5zfnXvP99xzz/yKxWLKYg4rgGGsAIaxAhjGCmAY - K4BhrACGsQIYxgpgGCuAYSIVoLGxUe3t7anr62t1eHioBgcHVUJCQqBvcnKymp+fF7/e3t5An5+QkpKi - hoaG1P7+vrq8vFQbGxuqvr7e48PaWltb1fb2trq6ulK7u7uylnhrDoPIBBgZGVGfn5/q8fFR7ezsqLu7 - OxkvLCwE+s/OzspzNo0YQT7/S2JiolpfX5f5WQciv7+/y7ipqcnxGx0dFdvz87M6ODhQLy8vMp6cnPTM - FyaRCJCbm6ve3t5ks9nZ2WJLS0tTp6ensqGCggKPf0tLi9jJuqysLM+zINLT07/YmN9v09TW1sr8bnHJ - dGxbW1syzsjIcNack5MjNtb5+voqYqWmpjrzhUkkAlB62Nzi4qLHPjExIfbm5mbHxiafnp4k20pLSz3+ - QdTV1amHhwdVUVHh2EpKStTt7a0E1e2rqa6ulhNWXFzs2EgS1sJpYJyfn6+mp6dVQ0OD4wMkBX7+pAmL - SAWg9Ljtq6urYm9ra5MxpYGjjo0A9fT0SLZid//ODSfk6OhIykRlZaUEn6ylrhPEoN/4SUpKUuPj4/Je - yk6QD2RmZsqp4F3cIUE+PyUSASgRXLw6sO3t7Wpubk59fHyITWdTZ2enjP0QYDbvn1fjFuFfgz88POzU - 9qmpqW/FnpmZET9ObtDzMIjsEi4vL1dnZ2eyAQJPieB/XXNBP6f7IYBFRUXSnWBbWlryzOeHsoIfxCs9 - QVD+VlZWpOxR2zs6OgL96H6Ymy4uquyHyATQUGsLCwullnKhEWTsXHps8P7+3pOFeXl5YqfOa5sfd9lx - l6Mg33ggOALQpflPQXd3tzxjbtbpfhY2kQvA5sh6gjowMODYKVOcDE6B218LE08ALlIdfMSiVP1JBC7W - sbGxL+0twedd7iB3dXVJ8I+Pj/+qI/spkQtAD80mNzc3v3zQ6H68qqpKxjzXl+Py8rLHV8N9cnFxIcHX - Ni1CX1+fx1fDtwdzums+pQjbzc2Nsy4dfNpl5kcY+K7F/SmRCkC3wybJZt1bu6GOU5boNKi1+jvB3YsH - EVSTv6vTBJM5mZuTQ3Zz+kDfH3wVE3x8OE381eDn/2oOi8gEIIB8+EBNTU2gD5SVlam1tTW5I87Pz6Vr - cmd3WNB5cRJOTk6k7PFOGgX9vL+/X05kPGit3fOFReQlyPI9VgDDWAEMYwUwjBXAMFYAw1gBDGMFMIwV - wDBWAKPE1G/YBaLgvglMKQAAAABJRU5ErkJggg== - - \ No newline at end of file diff --git a/IndustrialPark/Other/GameCubeBanner.cs b/IndustrialPark/Other/GameCubeBanner.cs new file mode 100644 index 00000000..65f47af3 --- /dev/null +++ b/IndustrialPark/Other/GameCubeBanner.cs @@ -0,0 +1,277 @@ +using System; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Text; + +namespace IndustrialPark.Other +{ + /// + /// Represents a GameCube banner (BNR1). + /// + /// Contains a 96x32 image, a title, a creator, a full title, a full creator, and a description. + /// It appears in the GameCube system menu when a game disc is inserted. + /// + public class GameCubeBanner + { + public const int IMAGE_WIDTH = 96; + public const int IMAGE_HEIGHT = 32; + public const string MAGIC = "BNR1"; + public const string DEFAULT_FILENAME = "opening.bnr"; + + public Bitmap Image { get; set; } // 96x32 image + public string Title { get; set; } + public string Creator { get; set; } + public string TitleFull { get; set; } + public string CreatorFull { get; set; } + public string Description { get; set; } + + + public GameCubeBanner() + { + Image = new Bitmap(IMAGE_WIDTH, IMAGE_HEIGHT); + Title = ""; + Creator = ""; + TitleFull = ""; + CreatorFull = ""; + Description = ""; + } + + public GameCubeBanner(Bitmap image, string title, string creator, string titleFull, string creatorFull, string description) + { + Image = image; + Title = title; + Creator = creator; + TitleFull = titleFull; + CreatorFull = creatorFull; + Description = description; + } + + public static GameCubeBanner ImportFromFile(string filePath) + { + // Import a GameCube banner by reading from a file + GameCubeBanner banner = new GameCubeBanner(); + + // Open filestream + var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); + + // Read magic "BNR1" + var magic = new byte[4]; + fileStream.Read(magic, 0, 4); + + // If magic is not "BNR1", return null + if (Encoding.ASCII.GetString(magic) != MAGIC) + { + fileStream.Close(); + return null; + } + // Skip padding zeroes from 0x04 to 0x1f + fileStream.Seek(0x20, SeekOrigin.Begin); + + // Read image data + var imageData = new byte[IMAGE_WIDTH * IMAGE_HEIGHT * 2]; + fileStream.Read(imageData, 0, imageData.Length); + + // Convert image data to bitmap + banner.Image = ConvertRGB5A1ToImage(imageData); + + // Read game name + Debug.WriteLine("Position of metadata: " + fileStream.Position); + var title = new byte[0x20]; + fileStream.Read(title, 0, 0x20); + banner.Title = Encoding.ASCII.GetString(title).TrimEnd('\0'); + + // Read creator name + var creator = new byte[0x20]; + fileStream.Read(creator, 0, 0x20); + banner.Creator = Encoding.ASCII.GetString(creator).TrimEnd('\0'); + + // Read full game name + var titleFull = new byte[0x40]; + fileStream.Read(titleFull, 0, 0x40); + banner.TitleFull = Encoding.ASCII.GetString(titleFull).TrimEnd('\0'); + + // Read full creator name + var creatorFull = new byte[0x40]; + fileStream.Read(creatorFull, 0, 0x40); + banner.CreatorFull = Encoding.ASCII.GetString(creatorFull).TrimEnd('\0'); + + // Read description + var description = new byte[0x80]; + fileStream.Read(description, 0, 0x80); + banner.Description = Encoding.ASCII.GetString(description).TrimEnd('\0'); + + // Close filestream + fileStream.Close(); + + return banner; + } + + private static Bitmap ConvertRGB5A1ToImage(byte[] imageData) + { + // Convert bytes into a bitmage image + // Each pixel is 2 bytes (5 bits for R, 5 bits for G, 5 bits for B, 1 bit for A) + var bitmap = new Bitmap(IMAGE_WIDTH, IMAGE_HEIGHT); + + int gridSize = 4; + int gridWidth = IMAGE_WIDTH / gridSize; + int gridHeight = IMAGE_HEIGHT / gridSize; + + int index = 0; + + // Read each 16 pixels in a 4x4 tile, then move to the next tile + for (int gridY = 0; gridY < gridHeight; gridY++) + { + for (int gridX = 0; gridX < gridWidth; gridX++) + { + for (int y = 0; y < gridSize; y++) + { + for (int x = 0; x < gridSize; x++) + { + // Read two bytes + byte upperByte = imageData[index++]; + byte lowerByte = imageData[index++]; + + // Extract color components + // format: ARRR RRGG GGGB BBBB + int a = (upperByte & 0x80) >> 7; + int r = ((upperByte & 0x7C) >> 2); + int g = (((upperByte & 0x03) << 3) | ((lowerByte & 0xE0) >> 5)); + int b = (lowerByte & 0x1F); + + // Combine color components + Color pixel = Color.FromArgb(a * 255, r * 8, g * 8, b * 8); + + // Set pixel in bitmap + bitmap.SetPixel(gridX * gridSize + x, gridY * gridSize + y, pixel); + } + } + } + } + + return bitmap; + } + + private static byte[] ConvertImageToRGB5A1(Bitmap image) + { + // Convert image to RGB5A1 format + // Each pixel is 2 bytes (5 bits for R, 5 bits for G, 5 bits for B, 1 bit for A) + + byte[] rgb5a1Bytes = new byte[IMAGE_WIDTH * IMAGE_HEIGHT * 2]; + + int gridSize = 4; + int gridWidth = IMAGE_WIDTH / gridSize; + int gridHeight = IMAGE_HEIGHT / gridSize; + + int index = 0; + int pixelX, pixelY; + + // Store each 16 pixels in a 4x4 tile, then move to the next tile + for (int gridY = 0; gridY < gridHeight; gridY++) + { + for (int gridX = 0; gridX < gridWidth; gridX++) + { + for (int y = 0; y < gridSize; y++) + { + for (int x = 0; x < gridSize; x++) + { + + pixelX = gridX * gridSize + x; + pixelY = gridY * gridSize + y; + + Color pixel = image.GetPixel(pixelX, pixelY); + + // Extract color components + int r = pixel.R >> 3; // 5 bits + int g = pixel.G >> 3; // 5 bits + int b = pixel.B >> 3; // 5 bits + int a = (pixel.A >= 128) ? 1 : 0; // 1 bit + + // Combine into two bytes + // format: ARRR RRGG GGGB BBBB + ushort rgb5a1 = (ushort)((a << 15) | (r << 10) | (g << 5) | b); + + + // Store the two bytes in the byte array + // Upper byte first + rgb5a1Bytes[index++] = (byte)(rgb5a1 >> 8); + rgb5a1Bytes[index++] = (byte)(rgb5a1 & 0xFF); + } + } + } + } + + + + // FIXME: The pixels need to be in 4x4 tiles + return rgb5a1Bytes; + } + + /// + /// Saves the banner to a file. + /// + /// The file path + /// true if the file was saved, otherwise false + public bool SaveToFile(string filename) + { + // Save this banner to a file + + try + { + // Convert image to RGB5A1 format + // Each pixel is 2 bytes (5 bits for R, 5 bits for G, 5 bits for B, 1 bit for A) + byte[] imageData = ConvertImageToRGB5A1(Image); + + // Write byte stream to file + var fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write); + + // Write magic "BNR1" + var magic = Encoding.ASCII.GetBytes(MAGIC); + fileStream.Write(magic, 0, magic.Length); + + // Write padding zeroes from 0x04 to 0x1f + fileStream.Write(new byte[0x1f - 0x04 + 1], 0, 0x1f - 0x04 + 1); + + // Write image data + fileStream.Write(imageData, 0, imageData.Length); + + // Write game name + var title = Encoding.ASCII.GetBytes(Title); + fileStream.Write(title, 0, title.Length); + + // Write the creator name + fileStream.Position = 0x1840; + var creator = Encoding.ASCII.GetBytes(Creator); + fileStream.Write(creator, 0, creator.Length); + + fileStream.Position = 0x1860; + // Write the full game name + var titleFull = Encoding.ASCII.GetBytes(TitleFull); + fileStream.Write(titleFull, 0, titleFull.Length); + + // Write the full creator name + fileStream.Position = 0x18A0; + var creatorFull = Encoding.ASCII.GetBytes(CreatorFull); + fileStream.Write(creatorFull, 0, creatorFull.Length); + + // Write the description + fileStream.Position = 0x18E0; + var description = Encoding.ASCII.GetBytes(Description); + fileStream.Write(description, 0, description.Length); + + // Ensure file length is 0x195F + fileStream.Position = 0x195F; + fileStream.WriteByte(0); + + // Close file + fileStream.Close(); + + return true; + } + catch (Exception) + { + return false; + } + } + } +} \ No newline at end of file diff --git a/IndustrialPark/Properties/Resources.Designer.cs b/IndustrialPark/Properties/Resources.Designer.cs index 5f035fa2..37aae358 100644 --- a/IndustrialPark/Properties/Resources.Designer.cs +++ b/IndustrialPark/Properties/Resources.Designer.cs @@ -1,7 +1,6 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -59,5 +58,15 @@ internal Resources() { resourceCulture = value; } } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap PlaceholderBanner { + get { + object obj = ResourceManager.GetObject("PlaceholderBanner", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } } diff --git a/IndustrialPark/Properties/Resources.resx b/IndustrialPark/Properties/Resources.resx index 1af7de15..0746ded9 100644 --- a/IndustrialPark/Properties/Resources.resx +++ b/IndustrialPark/Properties/Resources.resx @@ -1,64 +1,5 @@  - @@ -112,9 +53,13 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\PlaceholderBanner1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/IndustrialPark/Resources/PlaceholderBanner1.png b/IndustrialPark/Resources/PlaceholderBanner1.png new file mode 100644 index 0000000000000000000000000000000000000000..8b5b701b82932619ace3f2f5af0f785409a86216 GIT binary patch literal 1063 zcmV+?1laqDP)G}DYj*pM&;o*Uw*Vorg*9U_^evd93-H#b>-#d-|k;pTAJp={#NVT+uPH~MW(}dczDRqZns;Dxw5j7 zeTXw2k26^%B_+8-0HgT_^tLvg+w9|mWk%(W(FTw3tb0@KZ&ofu#o2G=lQ>o z9jkR^Wo29y_!oLe&JX~JK;xCb4h#&?>gp;b5(z^#4Gs?SbE*Mg9R4RH{1*J_>1j>d zmzI_?lD)FB!s}4EcHm?i0kFo#MvBE^d;kCsiO_2cwt*zzh1isD9&5Zj) zRwQ9o(qm?jzwPa9mOW^DAP_KJhv^4WBq!N6P1*!Uu1T@yUxw*9Q7U1JwdXR^Ph8X0Mm}lW;t7@>UcaJ=Sc%vEAI*VS=`LbG&z$_159}lMCBm6QGGDkKX5CS zmorq8ekj1Y)LV1b6952l@qx9qwOOufXlS6_-CgbxmzS43HR-eauMCqHDj^z;vh3lX z7!>6D@$qr4NGro=ol^uT6N&(l1Bsw2KqvypX%JKe2