using System; using System.Windows.Forms; using System.IO.Compression; using System.IO; using System.Drawing; using System.Collections.Generic; using System.Linq; using TGASharpLib; using System.Text; namespace GiantsMapTextureChanger { public partial class ChangeTextureForm : Form { public ChangeTextureForm() { InitializeComponent(); } public string map_filename { get; private set; } public string giantsPath { get; private set; } public Dictionary all_textures { get; private set; } public Dictionary map_textures { get; private set; } private void ChangeTextureForm_Load(object sender, EventArgs e) { } private Dictionary ReadAllTextures() { Dictionary all = new Dictionary(); string bin_path = Path.GetDirectoryName(this.giantsPath) + "\\Bin"; var all_files_in_bin = Directory.EnumerateFiles(bin_path); // MessageBox.Show(all_files_in_bin.Count() + " files in Bin"); foreach (string currentFile in all_files_in_bin) { if (currentFile.EndsWith(".gzp")) { // it's a .gzp toolStripStatusLabel1.Text = "Reading file " + currentFile; Application.DoEvents(); Dictionary textures_in_gzp = ReadTexturesInGzp(currentFile); textures_in_gzp.ToList().ForEach(x => { if (!all.ContainsKey(x.Key)) { all.Add(x.Key, x.Value); } }); } } return all; } private Dictionary ReadTexturesInGzp(string gzp_file) { Dictionary all = new Dictionary(); using (BinaryReader reader = new BinaryReader(File.Open(gzp_file, FileMode.Open))) { int checksum = BitConverter.ToInt32(reader.ReadBytes(4), 0); if (checksum != 0x6608F101) { throw new Exception("GZP checksum invalid: " + checksum); } int meta_info_offset = BitConverter.ToInt32(reader.ReadBytes(4), 0); reader.BaseStream.Seek(meta_info_offset, SeekOrigin.Begin); int unk = BitConverter.ToInt32(reader.ReadBytes(4), 0); int entries_count = BitConverter.ToInt32(reader.ReadBytes(4), 0); // MessageBox.Show(entries_count + " files in " + gzp_file); for (int i=0; i ReadMapTextures(string map_file) { Dictionary res = new Dictionary(); // read all files in gck file ZipArchive zip = ZipFile.OpenRead(map_file); foreach (ZipArchiveEntry file in zip.Entries) { if(file.Name.EndsWith(".tga")) { Stream rs = file.Open(); byte[] tgaData = new byte[file.Length]; rs.Read(tgaData, 0, (int)file.Length); TGA t = TGA.FromBytes(tgaData); Image img = (Image)t; res.Add(file.Name, img); rs.Close(); } } zip.Dispose(); return res; } private byte[] DecompressBytes(byte[] compressed_bytes, int original_size) { int i = 0; int j = 0; int dec_byte = 0; int dec_bits = 8; int buff_start = 0xFEE; byte[] res = new byte[original_size]; if (original_size == 0) { return res; } while (j < original_size) { if (dec_bits == 8) { dec_byte = compressed_bytes[i]; i++; dec_bits = 0; } if ((dec_byte >> dec_bits & 1) == 0) { int dec_pos = ((compressed_bytes[i] + ((compressed_bytes[i + 1] & 0xF0) << 4) - buff_start - j) & 0xFFF) - 0x1000 + j; int dec_len = (compressed_bytes[i + 1] & 0xF) + 3; i += 2; while (dec_len > 0) { if (dec_pos >= 0) { res[j] = res[dec_pos]; } else { res[j] = 32; } j++; dec_pos++; dec_len--; } } else { res[j] = compressed_bytes[i]; i++; j++; } dec_bits++; } return res; } private Image TGAToImage(byte[] data) { TGA tga = TGA.FromBytes(data); return (Image)tga; } private void textureList_SelectedIndexChanged(object sender, EventArgs e) { // texturesinmapList.SelectedIndex = -1; string selected = textureList.Text; if (this.all_textures.ContainsKey(selected)) { ThumbImage.Image = this.all_textures[selected]; ThumbImage.Tag = selected; toolStripStatusLabel1.Text = selected + ": " + this.all_textures[selected].Width + "x" + this.all_textures[selected].Height; } } private void exportButton_Click(object sender, EventArgs e) { saveTextureDialog.FileName = (string)ThumbImage.Tag; saveTextureDialog.ShowDialog(); // If the file name is not an empty string open it for saving. if (saveTextureDialog.FileName != "") { // Saves the Image via a FileStream created by the OpenFile method. System.IO.FileStream fs = (System.IO.FileStream)saveTextureDialog.OpenFile(); TGA t = (TGA)ThumbImage.Image; t.Save(fs); fs.Close(); toolStripStatusLabel1.Text = "Saved texture to "+ saveTextureDialog.FileName; } else { toolStripStatusLabel1.Text = "Error: you did not choose a file to save texture"; } } private void texturesinmapList_SelectedIndexChanged(object sender, EventArgs e) { // textureList.SelectedIndex = -1; string selected = texturesinmapList.Text; if (this.map_textures.ContainsKey(selected)) { ThumbImage.Image = this.map_textures[selected]; ThumbImage.Tag = selected; toolStripStatusLabel1.Text = selected + ": " + this.map_textures[selected].Width + "x" + this.map_textures[selected].Height; } } private void button2_Click(object sender, EventArgs e) { string selected = texturesinmapList.Text; texturesinmapList.Items.Remove(selected); map_textures.Remove(selected); } private void button1_Click(object sender, EventArgs e) { textureAddDialog.ShowDialog(); if (textureAddDialog.FileName != "") { Image img = (Image)new TGA(textureAddDialog.FileName); string name = Path.GetFileName(textureAddDialog.FileName); map_textures.Add(name, img); texturesinmapList.Items.Add(name); } } private void button3_Click(object sender, EventArgs e) { saveMapDialog.ShowDialog(); toolStripStatusLabel1.Text = "Saving map to: " + saveMapDialog.FileName; if (saveMapDialog.FileName != "") { if (this.map_filename != saveMapDialog.FileName) { File.Copy(this.map_filename, saveMapDialog.FileName, true); } ZipArchive map = ZipFile.Open(saveMapDialog.FileName, ZipArchiveMode.Update); for(int i = map.Entries.Count-1;i>=0;i--) { ZipArchiveEntry entry = map.Entries[i]; if (entry.Name.EndsWith(".tga")) { entry.Delete(); } } foreach(string texture_name in this.map_textures.Keys) { TGA texture = (TGA)map_textures[texture_name]; ZipArchiveEntry newentry = map.CreateEntry(texture_name); using (StreamWriter writer = new StreamWriter(newentry.Open())) { texture.Save(writer.BaseStream); } } toolStripStatusLabel1.Text = "Saved map to: " + Path.GetFileName(saveMapDialog.FileName); map.Dispose(); } } private void ChangeTextureForm_Shown(object sender, EventArgs e) { // Get Giants.exe location object install_dir = Microsoft.Win32.Registry.GetValue(@"HKEY_CURRENT_USER\Software\PlanetMoon\Giants", "DestDir", ""); if (install_dir != null) { this.giantsPath = install_dir.ToString(); this.giantsPath += "\\Giants.exe"; } if (this.giantsPath == null || !File.Exists(this.giantsPath)) { if (gameFileDialog.ShowDialog() != DialogResult.OK) { Application.Exit(); return; } this.giantsPath = gameFileDialog.FileName; } // Get map location if (mapFileDialog.ShowDialog() != DialogResult.OK) { Application.Exit(); return; } this.map_filename = mapFileDialog.FileName; toolStripStatusLabel1.Text = "Reading files..."; Application.DoEvents(); this.all_textures = ReadAllTextures(); foreach (string i in all_textures.Keys) { textureList.Items.Add(i); } toolStripStatusLabel1.Text = "Reading map file " + this.map_filename; Application.DoEvents(); this.map_textures = ReadMapTextures(this.map_filename); ; foreach (string i in map_textures.Keys) { texturesinmapList.Items.Add(i); } this.Activate(); toolStripStatusLabel1.Text = "Done"; button1.Enabled = true; button3.Enabled = true; textureList.Enabled = true; exportButton.Enabled = true; button2.Enabled = true; openmapButton.Enabled = true; } private void openmapButton_Click(object sender, EventArgs e) { button1.Enabled = false; button3.Enabled = false; textureList.Enabled = false; exportButton.Enabled = false; button2.Enabled = false; openmapButton.Enabled = false; Application.DoEvents(); // Get map location if (mapFileDialog.ShowDialog() != DialogResult.OK) { Application.Exit(); return; } this.map_filename = mapFileDialog.FileName; toolStripStatusLabel1.Text = "Reading map file " + this.map_filename; Application.DoEvents(); this.map_textures = ReadMapTextures(this.map_filename); texturesinmapList.Items.Clear(); foreach (string i in map_textures.Keys) { texturesinmapList.Items.Add(i); } this.Activate(); toolStripStatusLabel1.Text = "Done"; button1.Enabled = true; button3.Enabled = true; textureList.Enabled = true; exportButton.Enabled = true; button2.Enabled = true; openmapButton.Enabled = true; } } }