private void save() { using (FileStream data = new FileStream(currentFile, FileMode.Open)) { BinaryReader input = new BinaryReader(data); BinaryWriter output = new BinaryWriter(data); for (int i = 0; i < bch.mips[mipSel].textures.Count; i++) { loadedTexture tex = bch.mips[mipSel].textures[i]; if (tex.modified) { byte[] buffer = align(TextureCodec.encode(tex.texture.texture, tex.type)); int diff = buffer.Length - tex.length; replaceData(data, tex.offset, returnSize(tex.type, tex.texture.texture.Width, tex.texture.texture.Height), buffer); tex.modified = false; updateTexture(i, tex); } } } MessageBox.Show("Done!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); }
private void save() { using (FileStream data = new FileStream(currentFile, FileMode.Open)) { BinaryReader input = new BinaryReader(data); BinaryWriter output = new BinaryWriter(data); for (int i = 0; i < bch.textures.Count; i++) { loadedTexture tex = bch.textures[i]; if (tex.modified) { byte[] buffer = align(TextureCodec.encode(tex.texture.texture, RenderBase.OTextureFormat.rgba8)); int diff = buffer.Length - tex.length; replaceData(data, tex.offset, tex.length, buffer); //Update offsets of next textures tex.length = buffer.Length; tex.modified = false; updateTexture(i, tex); for (int j = i; j < bch.textures.Count; j++) { loadedTexture next = bch.textures[j]; next.offset = (uint)(next.offset + diff); updateTexture(j, next); } //Update all addresses poiting after the replaced data bch.relocationTableOffset = (uint)(bch.relocationTableOffset + diff); for (int index = 0; index < bch.relocationTableLength; index += 4) { data.Seek(bch.relocationTableOffset + index, SeekOrigin.Begin); uint value = input.ReadUInt32(); uint offset = value & 0x1ffffff; byte flags = (byte)(value >> 25); if ((flags & 0x20) > 0 || flags == 7 || flags == 0xc) { if ((flags & 0x20) > 0) { data.Seek((offset * 4) + bch.gpuCommandsOffset, SeekOrigin.Begin); } else { data.Seek((offset * 4) + bch.mainHeaderOffset, SeekOrigin.Begin); } uint address = input.ReadUInt32(); if (address + bch.dataOffset > tex.offset) { address = (uint)(address + diff); data.Seek(-4, SeekOrigin.Current); output.Write(address); } } } uint newSize = (uint)((tex.texture.texture.Width << 16) | tex.texture.texture.Height); //Update texture format data.Seek(tex.gpuCommandsOffset, SeekOrigin.Begin); for (int index = 0; index < tex.gpuCommandsWordCount * 3; index++) { uint command = input.ReadUInt32(); switch (command) { case 0xf008e: case 0xf0096: case 0xf009e: replaceCommand(data, output, 0); //Set texture format to 0 = RGBA8888 break; case 0xf0082: case 0xf0092: case 0xf009a: replaceCommand(data, output, newSize); //Set new texture size break; } } //Update material texture format foreach (loadedMaterial mat in bch.materials) { data.Seek(mat.gpuCommandsOffset, SeekOrigin.Begin); for (int index = 0; index < mat.gpuCommandsWordCount; index++) { uint command = input.ReadUInt32(); switch (command) { case 0xf008e: if (mat.texture0 == tex.texture.name || mat.texture0 == "") { replaceCommand(data, output, 0); } break; case 0xf0096: if (mat.texture1 == tex.texture.name || mat.texture1 == "") { replaceCommand(data, output, 0); } break; case 0xf009e: if (mat.texture2 == tex.texture.name || mat.texture2 == "") { replaceCommand(data, output, 0); } break; } } } //Patch up BCH header for new offsets and lengths data.Seek(4, SeekOrigin.Begin); byte backwardCompatibility = input.ReadByte(); byte forwardCompatibility = input.ReadByte(); //Update Data Extended and Relocation Table offsets data.Seek(18, SeekOrigin.Current); if (backwardCompatibility > 0x20) { updateAddress(data, input, output, diff); } updateAddress(data, input, output, diff); //Update data length data.Seek(12, SeekOrigin.Current); updateAddress(data, input, output, diff); } } } MessageBox.Show("Done!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); }