public void UpdateControl() { cb1MIO0Data.Items.Clear(); if (RomProject.Instance.Files.Count > 0) { btnResizeRom.Enabled = true; txtRomSize.Enabled = true; txtRomSize.Text = ((int)Math.Round(RomProject.Instance.Files[0].FileLength / 1048576.0)).ToString(); //Update the MIO0 stuff foreach (N64DataElement element in RomProject.Instance.Files[0].Elements) { if (element is MIO0Block) { MIO0Block block = (MIO0Block)element; if (block.Elements.Count > 1) { cb1MIO0Data.Items.Add(block); } } } bool mioEnabled = cb1MIO0Data.Items.Count > 0; btnExportMIO0.Enabled = mioEnabled; cb1MIO0Data.Enabled = mioEnabled; if (mioEnabled) { cb1MIO0Data.SelectedIndex = 0; } } else { btnResizeRom.Enabled = false; txtRomSize.Enabled = false; txtRomSize.Text = string.Empty; btnExportMIO0.Enabled = false; cb1MIO0Data.Enabled = false; } }
private void ReplaceMIO0() { //Attempt to load in a new texture and replace. Will not work if the texture size is larger than the one it's replacing if (openFileDialog.ShowDialog() == DialogResult.OK) { Bitmap bmp = (Bitmap)Bitmap.FromFile(openFileDialog.FileName); if (bmp == null) { MessageBox.Show("Error: Couldn't load image file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (bmp.Height != _image.Height || bmp.Width != _image.Width) { MessageBox.Show("Error: New image must be same size!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //Think hard about this. If you're compressing the image and/or palette into MIO0, you need to test against that. // Also a form if there's more than one image being affected by this change? Before/afters? //So we need some way to change an F3DEXImage to a new bitmap. but it needs to change texture and palette appropriately, // and most importantly it needs to be able to stop halfway to see how it will affect other images. But if we want to change // the lakitu images, which will change the palette, you'd have to change all of the images at once, right? So how the hell // is this going to work out?? //Also palette editing byte[] newData; byte[] newPaletteData = null; if (_image.Format == Texture.ImageFormat.CI) { Palette palette = new Palette(-1, new byte[(_image.ImageReference.WorkingPalette.Colors.Length * 2) - 200]); newData = TextureConversion.ImageToBinary(_image.Format, _image.PixelSize, bmp, ref palette); newPaletteData = palette.RawData; if (newPaletteData.Length < (_image.ImageReference.WorkingPalette.Colors.Length * 2)) { newPaletteData = Cereal64.Common.Utils.ByteHelper.CombineIntoBytes(newPaletteData, new byte[(_image.ImageReference.WorkingPalette.Colors.Length * 2) - newPaletteData.Length]); } } else { newData = TextureConversion.ImageToBinary(_image.Format, _image.PixelSize, bmp); } if (newData == null || newData.Length == 0) { MessageBox.Show("Error: Couldn't convert image file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } byte[] oldData = _image.ImageReference.Texture.RawData; byte[] oldPaletteData = null; if (_image.Format == Texture.ImageFormat.CI) { oldPaletteData = _image.ImageReference.BasePalettes[0].RawData; } _image.ImageReference.Texture.RawData = newData; if (_image.Format == Texture.ImageFormat.CI) { _image.ImageReference.BasePalettes[0].RawData = newPaletteData; } _image.ImageReference.UpdateImage(); if (!_image.IsValidImage) { _image.ImageReference.Texture.RawData = oldData; _image.ImageReference.UpdateImage(); MessageBox.Show("Error: Couldn't set image file! File might be too large to load in", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } byte[] oldMIO0RefData = null; N64DataElement el; if (_image.TextureEncoding == MK64Image.MK64ImageEncoding.MIO0) { if (!RomProject.Instance.Files[0].HasElementAt(_image.TextureOffset, out el)) { MessageBox.Show("Error: Couldn't set image file! Could not find MIO0 block.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } MIO0Block block = (MIO0Block)el; byte[] oldMIO0Data = block.DecodedData; oldMIO0RefData = oldMIO0Data; if (_specialMIO0Length == -1 && block.FileOffset == 0x132B50) { _specialMIO0Length = block.RawDataSize; } Array.Copy(newData, 0, oldMIO0Data, _image.TextureBlockOffset, newData.Length); byte[] compressedNewMIO0 = MIO0.Encode(oldMIO0Data); int sizeCompare = (_specialMIO0Length != -1 && block.FileOffset == 0x132B50 ? _specialMIO0Length : block.RawDataSize); if (compressedNewMIO0.Length > sizeCompare) { _image.ImageReference.Texture.RawData = oldData; if (_image.Format == Texture.ImageFormat.CI) { _image.ImageReference.BasePalettes[0].RawData = oldPaletteData; } _image.ImageReference.UpdateImage(); MessageBox.Show("Error: Couldn't set image file! File might be too large to load in", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } block.RawData = compressedNewMIO0; } if (_image.Format == Texture.ImageFormat.CI && _image.PaletteEncoding[0] == MK64Image.MK64ImageEncoding.MIO0) { if (!RomProject.Instance.Files[0].HasElementAt(_image.TextureOffset, out el)) { MessageBox.Show("Error: Couldn't set image file! Could not find MIO0 block.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } MIO0Block block = (MIO0Block)el; byte[] oldMIO0Data = block.DecodedData; Array.Copy(newPaletteData, 0, oldMIO0Data, _image.PaletteBlockOffset[0], newPaletteData.Length); byte[] compressedNewMIO0 = MIO0.Encode(oldMIO0Data); int sizeCompare = (_specialMIO0Length != -1 && block.FileOffset == 0x132B50 ? _specialMIO0Length : block.RawDataSize); if (compressedNewMIO0.Length > sizeCompare) { _image.ImageReference.Texture.RawData = oldData; if (_image.Format == Texture.ImageFormat.CI) { _image.ImageReference.BasePalettes[0].RawData = oldPaletteData; } _image.ImageReference.UpdateImage(); //Revert texture if (_image.TextureEncoding == MK64Image.MK64ImageEncoding.MIO0) { N64DataElement element; if (!RomProject.Instance.Files[0].HasElementExactlyAt(_image.TextureOffset, out element)) { throw new Exception(); } MIO0Block blockText = (MIO0Block)element; blockText.RawData = oldMIO0RefData; } MessageBox.Show("Error: Couldn't set image file! File might be too large to load in", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } block.RawData = compressedNewMIO0; } Image = _image; //Reset it ImageUpdated(); } }
public void SaveKartInfo() { if (KartGraphicsBlock == null) { return; } //These hold the palette blocks associated with each animation Dictionary <KartAnimationSeries, KartPaletteBlock> TurnPaletteBlocks = new Dictionary <KartAnimationSeries, KartPaletteBlock>(); Dictionary <KartAnimationSeries, KartPaletteBlock> SpinPaletteBlocks = new Dictionary <KartAnimationSeries, KartPaletteBlock>(); int turnPaletteBlockIndex = 0; int spinPaletteBlockIndex = 0; for (int i = 0; i < MarioKart64ElementHub.Instance.SelectedKarts.Length; i++) { KartInfo kart = MarioKart64ElementHub.Instance.SelectedKarts[i]; //Save the main palette if (kart.KartImages.ImagePalette.FileOffset == -1) { kart.KartImages.ImagePalette.FileOffset = NewElementOffset; AdvanceNewElementOffset(kart.KartImages.ImagePalette); RomProject.Instance.Files[0].AddElement(kart.KartImages.ImagePalette); } KartGraphicsBlock.CharacterPaletteReferences[i] = new DmaAddress(0x0F, kart.KartImages.ImagePalette.FileOffset - KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET); KartGraphicsBlock.CharacterPaletteReferences[i].ReferenceElement = kart.KartImages.ImagePalette; //Save the kart palettes in BLOCKS! //but first, assign each unique animation its own PaletteBlock, adding new ones as necessary //Backwards, so the order is preserved for (int h = kart.KartAnimations.Count - 1; h >= 0; h--) { KartAnimationSeries anim = kart.KartAnimations[h]; if (anim.IsTurnAnim) { if (!TurnPaletteBlocks.ContainsKey(anim)) { while (this.TurnKartPaletteBlocks.Count <= turnPaletteBlockIndex) { byte[] newPaletteBlockData = new byte[0x40 * 2 * 20 * 4]; KartPaletteBlock block = new KartPaletteBlock(this.NewElementOffset, newPaletteBlockData); foreach (Palette palette in block.Palettes) { RomProject.Instance.Files[0].AddElement(palette); } this.AdvanceNewElementOffset(block); this.TurnKartPaletteBlocks.Add(block); } TurnPaletteBlocks.Add(anim, this.TurnKartPaletteBlocks[turnPaletteBlockIndex]); turnPaletteBlockIndex++; byte[] testingBytes = anim.GenerateKartAnimationPaletteData( kart.KartImages, true); TurnPaletteBlocks[anim].RawData = testingBytes; } } if (anim.IsSpinAnim) { if (!SpinPaletteBlocks.ContainsKey(anim)) { while (this.SpinKartPaletteBlocks.Count <= spinPaletteBlockIndex) { byte[] newPaletteBlockData = new byte[0x40 * 2 * 20 * 4]; KartPaletteBlock block = new KartPaletteBlock(this.NewElementOffset, newPaletteBlockData); foreach (Palette palette in block.Palettes) { RomProject.Instance.Files[0].AddElement(palette); } this.AdvanceNewElementOffset(block); this.SpinKartPaletteBlocks.Add(block); } SpinPaletteBlocks.Add(anim, this.SpinKartPaletteBlocks[spinPaletteBlockIndex]); spinPaletteBlockIndex++; SpinPaletteBlocks[anim].RawData = anim.GenerateKartAnimationPaletteData( kart.KartImages, false); } } } List <int> setAnimPaletteBlock = new List <int>(); for (int j = 0; j < KartGraphicsBlock.CharacterTurnReferences[i].Length; j++) { int animFlag; int frameIndex; //Theres a function for this in KartReader? bool isTurnAnim = true; if (j < KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT * KartGraphicsReferenceBlock.FULL_TURN_REF_COUNT) { animFlag = (int)Math.Round(Math.Pow(2, j / KartGraphicsReferenceBlock.FULL_TURN_REF_COUNT)); frameIndex = j - (j / KartGraphicsReferenceBlock.FULL_TURN_REF_COUNT) * KartGraphicsReferenceBlock.FULL_TURN_REF_COUNT; //The last 14 values of the turn animation are from the spin one, actually if (frameIndex >= KartGraphicsReferenceBlock.HALF_TURN_REF_COUNT) { animFlag <<= 9; //Make it spin anim, not turn anim frameIndex -= 15; isTurnAnim = false; //Don't do palette block stuff for this one } } else { animFlag = (int)Math.Round(Math.Pow(2, (j - KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT * KartGraphicsReferenceBlock.FULL_TURN_REF_COUNT) / KartGraphicsReferenceBlock.FULL_SPIN_REF_COUNT + KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT)); frameIndex = j - (KartGraphicsReferenceBlock.FULL_TURN_REF_COUNT * KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT) - ((j - KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT * KartGraphicsReferenceBlock.FULL_TURN_REF_COUNT) / KartGraphicsReferenceBlock.FULL_SPIN_REF_COUNT) * KartGraphicsReferenceBlock.FULL_SPIN_REF_COUNT; isTurnAnim = false; } KartAnimationSeries anim = kart.KartAnimations.FirstOrDefault(f => (f.KartAnimationType & animFlag) != 0); if (anim != null) { //Need to replace animIndex with GetIndexfor(animIndex), but we need a better spin/turn/crash test string imageName; if (anim.IsTurnAnim) { imageName = anim.OrderedImageNames[anim.GetImageIndexForTurnFrame(frameIndex)]; } else //if (anim.IsSpinAnim) { imageName = anim.OrderedImageNames[anim.GetImageIndexForSpinFrame(frameIndex)]; } MK64Image mkImage = kart.KartImages.Images[imageName].Images[0]; //Save the image if (mkImage.TextureOffset == -1) { //It has to be an MIO0 block foreach (MK64Image editThisImage in kart.KartImages.Images[imageName].Images) { editThisImage.TextureBlockOffset = 0; editThisImage.TextureOffset = NewElementOffset; } mkImage.ImageReference.Texture.FileOffset = 0; MIO0Block newBlock = new MIO0Block(NewElementOffset, mkImage.ImageReference.Texture.RawData); AdvanceNewElementOffset(newBlock); RomProject.Instance.Files[0].AddElement(newBlock); } DmaAddress address = new DmaAddress(0x0F, mkImage.TextureOffset - KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET); N64DataElement blockEl; if (!RomProject.Instance.Files[0].HasElementAt(mkImage.TextureOffset, out blockEl)) { throw new Exception(); } MIO0Block block = (MIO0Block)blockEl; address.ReferenceElement = block; KartGraphicsBlock.CharacterTurnReferences[i][j] = address; int animIndex; if (animFlag == 0) { animIndex = 0; } else { animIndex = (int)Math.Round(Math.Log(animFlag, 2)); } //inverse the animation index if (animIndex < 9) { animIndex = 8 - animIndex; } else { animIndex = (8 - (animIndex - 9)) + 9; } if (!setAnimPaletteBlock.Contains(animIndex)) { if (isTurnAnim) { KartGraphicsBlock.WheelPaletteReferences[i][animIndex] = new DmaAddress(0x0F, TurnPaletteBlocks[anim].FileOffset - KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET); } else { KartGraphicsBlock.WheelPaletteReferences[i][animIndex] = new DmaAddress(0x0F, SpinPaletteBlocks[anim].FileOffset - KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET); } setAnimPaletteBlock.Add(animIndex); } } } for (int j = 0; j < KartGraphicsBlock.CharacterCrashReferences[i].Length; j++) { KartAnimationSeries anim = kart.KartAnimations.FirstOrDefault(f => (f.KartAnimationType & (int)KartAnimationSeries.KartAnimationTypeFlag.Crash) != 0); if (anim != null) { MK64Image mkImage = kart.KartImages.Images[anim.OrderedImageNames[anim.GetImageIndexForCrashFrame(j)]].Images[0]; if (mkImage.TextureOffset == -1) { foreach (MK64Image editThisImage in kart.KartImages.Images[anim.OrderedImageNames[anim.GetImageIndexForCrashFrame(j)]].Images) { editThisImage.TextureBlockOffset = 0; editThisImage.TextureOffset = NewElementOffset; } mkImage.ImageReference.Texture.FileOffset = 0; MIO0Block newBlock = new MIO0Block(NewElementOffset, mkImage.ImageReference.Texture.RawData); AdvanceNewElementOffset(newBlock); RomProject.Instance.Files[0].AddElement(newBlock); } N64DataElement element; if (!RomProject.Instance.Files[0].HasElementExactlyAt(mkImage.TextureOffset, out element)) { throw new Exception(); } MIO0Block block = (MIO0Block)element; //Save the image if (block.FileOffset == -1) { block.FileOffset = NewElementOffset; AdvanceNewElementOffset(block); RomProject.Instance.Files[0].AddElement(block); } DmaAddress address = new DmaAddress(0x0F, block.FileOffset - KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET); address.ReferenceElement = block; KartGraphicsBlock.CharacterCrashReferences[i][j] = address; } } for (int j = 0; j < kart.KartPortraits.Count; j++) { if (kart.KartPortraits[j].TextureOffset == -1) { kart.KartPortraits[j].TextureBlockOffset = 0; kart.KartPortraits[j].TextureOffset = NewElementOffset; kart.KartPortraits[j].ImageReference.Texture.FileOffset = 0; MIO0Block newBlock = new MIO0Block(NewElementOffset, kart.KartPortraits[j].ImageReference.Texture.RawData); AdvanceNewElementOffset(newBlock); RomProject.Instance.Files[0].AddElement(newBlock); } KartPortraitTableEntry entry = new KartPortraitTableEntry(kart.KartPortraits[j].TextureOffset, kart.KartPortraits[j]); KartPortraitsTable.Entries[i][j] = entry; } N64DataElement tkmk; if (RomProject.Instance.Files[0].HasElementExactlyAt(MarioKartRomInfo.CharacterNameplateReference[i], out tkmk) && tkmk is TKMK00Block) { TKMK00Block oldTkmk = (TKMK00Block)tkmk; oldTkmk.ImageAlphaColor = kart.KartNamePlate.TKMKAlphaColor; oldTkmk.SetImage(kart.KartNamePlate.Image); } } }
private void btnApply_Click(object sender, EventArgs e) { bool hasChanges = false; for (int i = 0; i < lbBefore.Items.Count; i++) { if (lbBefore.Items[i] != lbAfter.Items[i]) { hasChanges = true; break; } } if (!hasChanges) //Quit out if no changes { this.DialogResult = System.Windows.Forms.DialogResult.Cancel; return; } //if the mode is texture, then do something new. //if the mode is palette, then generate the palette BEFORE making the image if (Mode == SharedMode.Texture) { //IDEA: AVERAGE ALL THE IMAGES TOGETHER, THEN MAKE A CI PALETTE/TEXTURE FROM THAT. THEN WE HAVE OUR TEXTURE. // AFTER THAT, WE NEED TO ASSIGN PALETTES TO IT. I GUESS WE CAN AVERAGE ALL COLORS THAT HIT EACH POINT // FOR EACH IMAGE //Slow process Bitmap refImage = new Bitmap(Images[0].Image); int width = Images[0].Image.Width; int height = Images[0].Height; int pixelCount = width * height; int imageCount = lbAfter.Items.Count; int colorCount = Images[0].ImageReference.BasePalettes[0].Colors.Length; int[] redCount = new int[pixelCount]; int[] blueCount = new int[pixelCount]; int[] greenCount = new int[pixelCount]; int[] alphaCount = new int[pixelCount]; foreach (BitmapWrapper wrapper in lbAfter.Items) { for (int j = 0; j < width; j++) { for (int i = 0; i < height; i++) { Color pixel = wrapper.BMP.GetPixel(i, j); redCount[i + j * wrapper.BMP.Width] += pixel.R; greenCount[i + j * wrapper.BMP.Width] += pixel.G; blueCount[i + j * wrapper.BMP.Width] += pixel.B; alphaCount[i + j * wrapper.BMP.Width] += pixel.A; } } } for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { refImage.SetPixel(i, j, Color.FromArgb(alphaCount[i + j * width] / imageCount, redCount[i + j * width] / imageCount, greenCount[i + j * width] / imageCount, blueCount[i + j * width] / imageCount)); } } //Now do the set-texture palette search method Palette tempPalette = new Palette(-1, new byte[colorCount * 2]); byte[] finalTextureData = TextureConversion.ImageToBinary(Images[0].Format, Images[0].PixelSize, refImage, ref tempPalette, true); Images[0].ImageReference.Texture.RawData = finalTextureData; //Now take this and do some stupid shit for (int k = 0; k < imageCount; k++) { redCount = new int[colorCount]; greenCount = new int[colorCount]; blueCount = new int[colorCount]; alphaCount = new int[colorCount]; Bitmap img = (Bitmap)lbAfter.Items[k]; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { Color color = img.GetPixel(i, j); int textureNum = 0; if (Images[k].PixelSize == Texture.PixelInfo.Size_8b) { textureNum = finalTextureData[i + j * height]; } else { byte val = finalTextureData[(i + j * height) / 2]; if ((i + j * height) % 2 == 0) { textureNum = val >> 4; } else { textureNum = val & 0xF; } } redCount[textureNum] += color.R; greenCount[textureNum] += color.G; blueCount[textureNum] += color.B; alphaCount[textureNum] += color.A; } } //Now that we have the colors added up, we calculate the new colors and that's our new palette! Color[] colors = new Color[colorCount]; for (int i = 0; i < colorCount; i++) { colors[i] = Color.FromArgb(alphaCount[i] / imageCount, redCount[i] / imageCount, greenCount[i] / imageCount, blueCount[i] / imageCount); } byte[] newPaletteData = TextureConversion.PaletteToBinary(colors); Images[k].ImageReference.BasePalettes[0].RawData = newPaletteData; } } else { PaletteMedianCutAnalyzer paletteMaker = new PaletteMedianCutAnalyzer(); foreach (BitmapWrapper wrapper in lbAfter.Items) { for (int i = 0; i < wrapper.BMP.Width; i++) { for (int j = 0; j < wrapper.BMP.Height; j++) { paletteMaker.AddColor(wrapper.BMP.GetPixel(i, j)); } } } Color[] colors = paletteMaker.GetPalette(Images[0].ImageReference.BasePalettes[0].Colors.Length); byte[] paletteData = TextureConversion.PaletteToBinary(colors); Palette palette = new Palette(-1, paletteData); byte[] newPaletteData = palette.RawData; Images[0].ImageReference.BasePalettes[0].RawData = newPaletteData; if (Images[0].PaletteEncoding[0] == MK64Image.MK64ImageEncoding.MIO0) { N64DataElement element; if (!RomProject.Instance.Files[0].HasElementExactlyAt(Images[0].PaletteOffset[0], out element)) { throw new Exception(); } MIO0Block block = (MIO0Block)element; byte[] oldMIO0Data = block.DecodedData; Array.Copy(newPaletteData, 0, oldMIO0Data, Images[0].PaletteBlockOffset[0], newPaletteData.Length); byte[] compressedNewMIO0 = MIO0.Encode(oldMIO0Data); block.RawData = compressedNewMIO0; } //Now generate the images for (int i = 0; i < Images.Count; i++) { MK64Image image = Images[i]; Bitmap bmp = ((BitmapWrapper)lbAfter.Items[i]).BMP; byte[] newData = TextureConversion.ImageToBinary(image.Format, image.PixelSize, bmp, ref palette, false); if (newData == null || newData.Length == 0) { MessageBox.Show("Error: Couldn't convert image file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } image.ImageReference.Texture.RawData = newData; image.ImageReference.UpdateImage(); if (image.TextureEncoding == MK64Image.MK64ImageEncoding.MIO0) { N64DataElement element; if (!RomProject.Instance.Files[0].HasElementExactlyAt(image.TextureOffset, out element)) { throw new Exception(); } MIO0Block block = (MIO0Block)element; byte[] MIO0Data = block.DecodedData; Array.Copy(newData, 0, MIO0Data, image.TextureBlockOffset, newData.Length); byte[] compressedNewMIO0 = MIO0.Encode(MIO0Data); block.RawData = compressedNewMIO0; } } } }
private void LoadImageData(byte[] rawData = null) { IsValidImage = false; //Check that the format is correct (ex. CI & palette offsets are valid) int maxTextureLocation = (rawData != null ? rawData.Length - 1 : RomProject.Instance.Files[0].FileLength - 1); if (TextureOffset < 0 || TextureOffset > maxTextureLocation || (Format == Texture.ImageFormat.CI && PaletteOffset.Count == 0)) { return; } if (!TextureConversion.IsValidFormatCombo(Format, PixelSize)) { return; } //Try to load the texture, palette & image here N64DataElement element; Palette paletteRef = null; List <Palette> paletteRefs = new List <Palette>(); if (Format == Texture.ImageFormat.CI) //If CI format, we need to get the palette too { for (int i = 0; i < PaletteOffset.Count; i++) { paletteRef = null; if (RomProject.Instance.Files[0].HasElementExactlyAt(PaletteOffset[i], out element) && element.FileOffset == PaletteOffset[i] && !(element is UnknownData)) { switch (PaletteEncoding[i]) { case MK64ImageEncoding.Raw: //Needs to be a raw palette if (!(element is Palette)) { return; } paletteRef = (Palette)element; break; case MK64ImageEncoding.MIO0: //Needs to be a mio0 block if (!(element is MIO0Block)) { return; } MIO0Block block = (MIO0Block)element; //System.IO.File.WriteAllBytes("test.bin",block.DecodedData); //now to search inside if (block.Elements.FirstOrDefault(e => e.FileOffset == PaletteBlockOffset[i]) != null) { N64DataElement paletteEl = block.Elements.First(e => e.FileOffset == PaletteBlockOffset[i]); if (paletteEl is Palette) { paletteRef = (Palette)paletteEl; } } else { //Create the palette! byte[] data = new byte[PaletteColorCount[i] * 2]; Array.Copy(block.DecodedData, PaletteBlockOffset[i], data, 0, data.Length); Palette pal = new Palette(PaletteBlockOffset[i], data); if (block.AddElement(pal)) { paletteRef = pal; } } break; } } else { //AVOID THIS AS MUCH AS POSSIBLE, IT WILL SLOW EVERYTHING DOWN TREMENDOUSLY!! if (rawData == null) { rawData = RomProject.Instance.Files[0].GetAsBytes(); } //Create the palette! switch (PaletteEncoding[i]) { case MK64ImageEncoding.Raw: //Create the palette! byte[] data = new byte[PaletteColorCount[i] * 2]; Array.Copy(rawData, PaletteOffset[i], data, 0, data.Length); Palette pal = new Palette(PaletteOffset[i], data); if (RomProject.Instance.Files[0].AddElement(pal)) { paletteRef = pal; } break; case MK64ImageEncoding.MIO0: //Create the MIO0 block! MIO0Block block = MIO0Block.ReadMIO0BlockFrom(rawData, PaletteOffset[i]); //System.IO.File.WriteAllBytes("test.bin",block.DecodedData); if (RomProject.Instance.Files[0].AddElement(block)) { //Create the palette in the MIO0 block! byte[] mioData = new byte[PaletteColorCount[i] * 2]; Array.Copy(block.DecodedData, PaletteBlockOffset[i], mioData, 0, mioData.Length); Palette palette = new Palette(PaletteBlockOffset[i], mioData); if (block.AddElement(palette)) { paletteRef = palette; } else { throw new Exception(); } } break; } } paletteRefs.Add(paletteRef); } } Texture textureRef = null; TKMK00Block tkmkRef = null; if (RomProject.Instance.Files[0].HasElementExactlyAt(TextureOffset, out element) && element.FileOffset == TextureOffset && !(element is UnknownData)) { switch (TextureEncoding) { case MK64ImageEncoding.Raw: //Needs to be a raw texture if (!(element is Texture)) { return; } textureRef = (Texture)element; break; case MK64ImageEncoding.MIO0: //Needs to be a mio0 block if (!(element is MIO0Block)) { return; } MIO0Block block = (MIO0Block)element; //now to search inside if (block.Elements.FirstOrDefault(e => e.FileOffset == TextureBlockOffset) != null) { N64DataElement textureEl = block.Elements.First(e => e.FileOffset == TextureBlockOffset); if (textureEl is Texture) { textureRef = (Texture)textureEl; } } else { //Create the texture here //Create the palette! double byteSize = 1; switch (PixelSize) { case Texture.PixelInfo.Size_4b: byteSize = 0.5; break; case Texture.PixelInfo.Size_16b: byteSize = 2; break; case Texture.PixelInfo.Size_32b: byteSize = 4; break; } byte[] data = new byte[(int)Math.Round(Width * Height * byteSize)]; Array.Copy(block.DecodedData, TextureBlockOffset, data, 0, data.Length); Texture text = new Texture(TextureBlockOffset, data, Format, PixelSize, Width, Height); if (block.AddElement(text)) { textureRef = text; } } break; case MK64ImageEncoding.TKMK00: //Needs to be a tkmk00 block if (!(element is TKMK00Block)) { return; } tkmkRef = (TKMK00Block)element; break; } } else //NEED TO CREATE IT HERE! { //AVOID THIS AS MUCH AS POSSIBLE, IT WILL SLOW EVERYTHING DOWN TREMENDOUSLY!! if (rawData == null) { rawData = RomProject.Instance.Files[0].GetAsBytes(); } switch (TextureEncoding) { case MK64ImageEncoding.Raw: //Just create the new texture image! double byteSize = 1; switch (PixelSize) { case Texture.PixelInfo.Size_4b: byteSize = 0.5; break; case Texture.PixelInfo.Size_16b: byteSize = 2; break; case Texture.PixelInfo.Size_32b: byteSize = 4; break; } byte[] data = new byte[(int)Math.Round(Width * Height * byteSize)]; Array.Copy(rawData, TextureOffset, data, 0, data.Length); Texture texture = new Texture(TextureOffset, data, Format, PixelSize, Width, Height); //Add to the rom project if (RomProject.Instance.Files[0].AddElement(texture)) { textureRef = texture; } break; case MK64ImageEncoding.MIO0: //Since no MIO0 block was found, it needs to be created MIO0Block block = MIO0Block.ReadMIO0BlockFrom(rawData, TextureOffset); if (RomProject.Instance.Files[0].AddElement(block)) { double ByteSize = 1; switch (PixelSize) { case Texture.PixelInfo.Size_4b: ByteSize = 0.5; break; case Texture.PixelInfo.Size_16b: ByteSize = 2; break; case Texture.PixelInfo.Size_32b: ByteSize = 4; break; } byte[] textData = new byte[(int)Math.Round(Width * Height * ByteSize)]; Array.Copy(block.DecodedData, TextureBlockOffset, textData, 0, textData.Length); Texture text = new Texture(TextureBlockOffset, textData, Format, PixelSize, Width, Height); if (block.AddElement(text)) { textureRef = text; } } break; case MK64ImageEncoding.TKMK00: //Need to create the TKMK00Block, and it'll handle the rest TKMK00Block tkmk; byte[] bytes = new byte[TKMKLength]; Array.Copy(rawData, TextureOffset, bytes, 0, TKMKLength); tkmk = new TKMK00Block(TextureOffset, bytes, TKMKAlphaColor); if (RomProject.Instance.Files[0].AddElement(tkmk)) { tkmkRef = tkmk; } break; } } if ((textureRef == null && tkmkRef == null) || (Format == Texture.ImageFormat.CI && (paletteRefs.Count == 0 || paletteRefs.Contains(null)))) { return; } //Test to make sure the texture matches the format and such if (textureRef != null && Format != textureRef.Format) { return; } //Successfully found the palette, set the references TKMKReference = tkmkRef; if (TextureEncoding == MK64ImageEncoding.TKMK00) { IsValidImage = (TKMKReference != null); return; } F3DEXImage image = new F3DEXImage(textureRef, paletteRefs); ImageReference = image; IsValidImage = image.ValidImage; }
private bool FindExistingF3DEXImage(Texture newTexture, List <Palette> newPalettes) { if (RomProject.Instance.Files.Count == 0) { return(false); } //Look for the TKMK00 bool changesMade = false; N64DataElement element; Palette paletteRef = null; List <Palette> paletteRefs = new List <Palette>(); if (Format == Texture.ImageFormat.CI) //If CI format, we need to get the palette too { for (int i = 0; i < PaletteOffset.Count; i++) { paletteRef = null; if (RomProject.Instance.Files[0].HasElementExactlyAt(PaletteOffset[i], out element) && element.FileOffset == TextureOffset && !(element is UnknownData)) { switch (PaletteEncoding[i]) { case MK64ImageEncoding.Raw: //Needs to be a raw palette if (!(element is Palette)) { break; } paletteRef = (Palette)element; break; case MK64ImageEncoding.MIO0: //Needs to be a mio0 block if (!(element is MIO0Block)) { break; } MIO0Block block = (MIO0Block)element; //System.IO.File.WriteAllBytes("test.bin",block.DecodedData); //now to search inside if (block.Elements.FirstOrDefault(e => e.FileOffset == PaletteBlockOffset[i]) != null) { N64DataElement paletteEl = block.Elements.First(e => e.FileOffset == PaletteBlockOffset[i]); if (paletteEl is Palette) { paletteRef = (Palette)paletteEl; } } break; } } if (paletteRef != null) { newPalettes[i] = paletteRef; changesMade = true; } } } //Now texture Texture textureRef = null; if (RomProject.Instance.Files[0].HasElementExactlyAt(TextureOffset, out element) && element.FileOffset == TextureOffset && !(element is UnknownData)) { switch (TextureEncoding) { case MK64ImageEncoding.Raw: //Needs to be a raw texture if (!(element is Texture)) { break; } textureRef = (Texture)element; break; case MK64ImageEncoding.MIO0: //Needs to be a mio0 block if (!(element is MIO0Block)) { break; } MIO0Block block = (MIO0Block)element; //now to search inside if (block.Elements.FirstOrDefault(e => e.FileOffset == TextureBlockOffset) != null) { N64DataElement textureEl = block.Elements.First(e => e.FileOffset == TextureBlockOffset); if (textureEl is Texture) { textureRef = (Texture)textureEl; } } break; } } if (textureRef != null) { newTexture = textureRef; changesMade = true; } if (changesMade) { ImageReference = new F3DEXImage(newTexture, newPalettes); IsValidImage = ImageReference.ValidImage; return(true); } return(false); }
private static void LoadKartInfo(KartGraphicsReferenceBlock block, KartPortraitTable portraits, BackgroundWorker worker, byte[] data, TextureReaderResults textureResults, KartReaderResults results) { for (int i = 0; i < KartGraphicsReferenceBlock.CHARACTER_COUNT; i++) { string kartName = Enum.GetName(typeof(MarioKartRomInfo.OriginalCharacters), i); KartInfo newKart = new KartInfo(kartName, (Palette)block.CharacterPaletteReferences[i].ReferenceElement, true); KartAnimationSeries[] turnAnims = new KartAnimationSeries[KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT]; KartAnimationSeries[] spinAnims = new KartAnimationSeries[KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT]; KartAnimationSeries crashAnim; MIO0Block[][] turnBlocks = new MIO0Block[KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT][]; for (int k = 0; k < KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT; k++) { turnBlocks[k] = new MIO0Block[KartGraphicsReferenceBlock.HALF_TURN_REF_COUNT]; } MIO0Block[][] spinBlocks = new MIO0Block[KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT][]; for (int k = 0; k < KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT; k++) { spinBlocks[k] = new MIO0Block[KartGraphicsReferenceBlock.FULL_SPIN_REF_COUNT]; } DmaAddress[] wheelPaletteReferences = block.WheelPaletteReferences[i]; turnAnims[0] = new KartAnimationSeries(kartName + " Turn Down 25"); turnAnims[0].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.RearTurnDown25; turnAnims[1] = new KartAnimationSeries(kartName + " Turn Down 19"); turnAnims[1].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.RearTurnDown19; turnAnims[2] = new KartAnimationSeries(kartName + " Turn Down 12"); turnAnims[2].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.RearTurnDown12; turnAnims[3] = new KartAnimationSeries(kartName + " Turn Down 6"); turnAnims[3].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.RearTurnDown6; turnAnims[4] = new KartAnimationSeries(kartName + " Turn 0"); turnAnims[4].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.RearTurn0; turnAnims[5] = new KartAnimationSeries(kartName + " Turn Up 6"); turnAnims[5].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.RearTurnUp6; turnAnims[6] = new KartAnimationSeries(kartName + " Turn Up 12"); turnAnims[6].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.RearTurnUp12; turnAnims[7] = new KartAnimationSeries(kartName + " Turn Up 19"); turnAnims[7].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.RearTurnUp19; turnAnims[8] = new KartAnimationSeries(kartName + " Turn Up 25"); turnAnims[8].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.RearTurnUp25; spinAnims[0] = new KartAnimationSeries(kartName + " Spin Down 25"); spinAnims[0].KartAnimationType = (int)(KartAnimationSeries.KartAnimationTypeFlag.FullSpinDown25 | KartAnimationSeries.KartAnimationTypeFlag.FullSpinDown19); spinAnims[1] = spinAnims[0]; spinAnims[2] = new KartAnimationSeries(kartName + " Spin Down 12"); spinAnims[2].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.FullSpinDown12; spinAnims[3] = new KartAnimationSeries(kartName + " Spin 0"); spinAnims[3].KartAnimationType = (int)(KartAnimationSeries.KartAnimationTypeFlag.FullSpinDown6 | KartAnimationSeries.KartAnimationTypeFlag.FullSpin0 | KartAnimationSeries.KartAnimationTypeFlag.FullSpinUp6); spinAnims[4] = spinAnims[3]; spinAnims[5] = spinAnims[3]; spinAnims[6] = new KartAnimationSeries(kartName + " Spin Up 12"); spinAnims[6].KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.FullSpinUp12; spinAnims[7] = new KartAnimationSeries(kartName + " Spin Up 25"); spinAnims[7].KartAnimationType = (int)(KartAnimationSeries.KartAnimationTypeFlag.FullSpinUp19 | KartAnimationSeries.KartAnimationTypeFlag.FullSpinUp25); spinAnims[8] = spinAnims[7]; crashAnim = new KartAnimationSeries(kartName + " Crash"); crashAnim.KartAnimationType = (int)KartAnimationSeries.KartAnimationTypeFlag.Crash; //use to generate the ordered image names Dictionary <MIO0Block, string> MioToImageName = new Dictionary <MIO0Block, string>(); //Work backwards, to help with image naming for (short j = 0; j < KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT * KartGraphicsReferenceBlock.FULL_TURN_REF_COUNT + KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT * KartGraphicsReferenceBlock.FULL_SPIN_REF_COUNT; j++) { MIO0Block imageBlock = (MIO0Block)block.CharacterTurnReferences[i][j].ReferenceElement; Texture texture = (Texture)imageBlock.Element; List <MK64Image> images; if (textureResults.ImagesByTexture.ContainsKey(texture)) { images = new List <MK64Image>(textureResults.ImagesByTexture[texture]); } else if (MarioKart64ElementHub.Instance.TextureHub.HasImagesForTexture(texture)) { images = MarioKart64ElementHub.Instance.TextureHub.ImagesForTexture(texture); } else { throw new Exception(); } string imageName = images[0].ImageName; //Jump out if the image block has already been handled if (!string.IsNullOrWhiteSpace(imageName) && newKart.KartImages.Images.ContainsKey(imageName)) { continue; } int animIndex, frameIndex; bool isTurnAnim; GetAnimationFrameIndices(j, out animIndex, out frameIndex, out isTurnAnim); if (isTurnAnim) { if (turnBlocks[animIndex][frameIndex] == null) { turnBlocks[animIndex][frameIndex] = imageBlock; } } else { if (spinBlocks[animIndex][frameIndex] == null) { spinBlocks[animIndex][frameIndex] = imageBlock; } } if (!newKart.KartImages.Images.ContainsKey(imageName)) { newKart.KartImages.Images.Add(imageName, new KartImage(images)); } MioToImageName.Add(imageBlock, imageName); } for (int j = 0; j < spinBlocks.Length; j++) { //Don't deal with duplicate animations if (j != 0 && spinAnims[j] == spinAnims[j - 1]) { continue; } for (int k = 0; k < spinBlocks[j].Length; k++) { if (spinBlocks[j][k] != null) { spinAnims[j].OrderedImageNames.Add(MioToImageName[spinBlocks[j][k]]); } } } for (int j = 0; j < turnBlocks.Length; j++) { for (int k = 0; k < turnBlocks[j].Length; k++) { if (turnBlocks[j][k] != null) { turnAnims[j].OrderedImageNames.Add(MioToImageName[turnBlocks[j][k]]); } } } for (int j = 0; j < block.CharacterCrashReferences[i].Length; j++) { MIO0Block imageBlock = (MIO0Block)block.CharacterCrashReferences[i][j].ReferenceElement; Texture texture = (Texture)imageBlock.Element; List <MK64Image> images; if (textureResults.ImagesByTexture.ContainsKey(texture)) { images = new List <MK64Image>(textureResults.ImagesByTexture[texture]); } else if (MarioKart64ElementHub.Instance.TextureHub.HasImagesForTexture(texture)) { images = MarioKart64ElementHub.Instance.TextureHub.ImagesForTexture(texture); } else { throw new Exception(); } string imageName = images[0].ImageName; crashAnim.OrderedImageNames.Add(imageName); if (!newKart.KartImages.Images.ContainsKey(imageName)) { newKart.KartImages.Images.Add(imageName, new KartImage(images)); } } for (int j = 0; j < turnAnims.Length; j++) { newKart.KartAnimations.Add(turnAnims[j]); } for (int j = 0; j < spinAnims.Length; j++) { //Don't store duplicate animations if (j != 0 && spinAnims[j] == spinAnims[j - 1]) { continue; } newKart.KartAnimations.Add(spinAnims[j]); } newKart.KartAnimations.Add(crashAnim); for (int j = 0; j < portraits.Entries[i].Count; j++) { newKart.KartPortraits.Add(portraits.Entries[i][j].ImageReference); } //Find the tkmk block in either the new images or in the hub MK64Image img; if ((img = MarioKart64ElementHub.Instance.TextureHub.Images.SingleOrDefault(im => im.ImageName == TextureNames.PORTAIT_NAME_ARRAY[i])) != null) { newKart.KartNamePlate = img; } else if ((img = textureResults.NewImages.SingleOrDefault(im => im.ImageName == TextureNames.PORTAIT_NAME_ARRAY[i])) != null) { newKart.KartNamePlate = img; } else { throw new Exception(); } MarioKart64ElementHub.Instance.Karts.Add(newKart); MarioKart64ElementHub.Instance.SelectedKarts[i] = newKart; RomProject.Instance.AddRomItem(newKart); } }
private void btnAddImage_Click(object sender, EventArgs e) { if (_newImageForm == null) { _newImageForm = new NewMK64ImageForm(); } if (_newImageForm.ShowDialog() == DialogResult.OK) { List <MK64Image> newImages = new List <MK64Image>(); foreach (string FileName in _newImageForm.FileNames) { //To do: make it load multiple at a time! Bitmap bmp = (Bitmap)Bitmap.FromFile(FileName); if (bmp == null) { MessageBox.Show("Could not load image:\n" + FileName, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); continue; } byte[] imageData; Texture texture; Palette palette = null; if (_newImageForm.Format == Texture.ImageFormat.CI) { byte[] paletteData = new byte[2 * _newImageForm.PaletteColorCount]; palette = new Palette(-1, paletteData); imageData = TextureConversion.ImageToBinary(_newImageForm.Format, _newImageForm.PixelSize, bmp, ref palette, true); } else { imageData = TextureConversion.ImageToBinary(_newImageForm.Format, _newImageForm.PixelSize, bmp); } texture = new Texture(-1, imageData, _newImageForm.Format, _newImageForm.PixelSize, bmp.Width, bmp.Height); //Now, if necessary, encode the texture!! MIO0Block textureBlock = null, paletteBlock = null; if (_newImageForm.EncodeTexture) { byte[] encodedData = MIO0.Encode(texture.RawData); textureBlock = new MIO0Block(-1, encodedData); textureBlock.AddElement(texture); texture.FileOffset = 0; } if (palette != null && _newImageForm.EncodePalette) { byte[] encodedData = MIO0.Encode(palette.RawData); paletteBlock = new MIO0Block(-1, encodedData); paletteBlock.AddElement(palette); palette.FileOffset = 0; } //Add in the texture/palette to the new data location if (textureBlock != null) { textureBlock.FileOffset = MarioKart64ElementHub.Instance.NewElementOffset; RomProject.Instance.Files[0].AddElement(textureBlock); MarioKart64ElementHub.Instance.AdvanceNewElementOffset(textureBlock); } else { texture.FileOffset = MarioKart64ElementHub.Instance.NewElementOffset; RomProject.Instance.Files[0].AddElement(texture); MarioKart64ElementHub.Instance.AdvanceNewElementOffset(texture); } if (palette != null) { if (paletteBlock != null) { paletteBlock.FileOffset = MarioKart64ElementHub.Instance.NewElementOffset; RomProject.Instance.Files[0].AddElement(paletteBlock); MarioKart64ElementHub.Instance.AdvanceNewElementOffset(paletteBlock); } else { palette.FileOffset = MarioKart64ElementHub.Instance.NewElementOffset; RomProject.Instance.Files[0].AddElement(palette); MarioKart64ElementHub.Instance.AdvanceNewElementOffset(palette); } } //Add in the new MK64Image int tFileOffset = (textureBlock == null ? texture.FileOffset : textureBlock.FileOffset); MK64Image.MK64ImageEncoding tEncoding = (textureBlock == null ? MK64Image.MK64ImageEncoding.Raw : MK64Image.MK64ImageEncoding.MIO0); int tBlockOffset = (textureBlock == null ? -1 : texture.FileOffset); List <int> PaletteOffset = new List <int>(); List <MK64Image.MK64ImageEncoding> PaletteEncodings = new List <MK64Image.MK64ImageEncoding>(); List <int> PaletteBlockOffset = new List <int>(); List <int> PaletteColorCount = new List <int>(); List <int> PaletteColorOffset = new List <int>(); if (palette != null) { PaletteOffset.Add(paletteBlock == null ? palette.FileOffset : paletteBlock.FileOffset); PaletteEncodings.Add(paletteBlock == null ? MK64Image.MK64ImageEncoding.Raw : MK64Image.MK64ImageEncoding.MIO0); PaletteBlockOffset.Add(paletteBlock == null ? -1 : palette.FileOffset); PaletteColorCount.Add(palette.Colors.Length); PaletteColorOffset.Add(0); } MK64Image newImage = new MK64Image(tFileOffset, tEncoding, tBlockOffset, _newImageForm.Format, _newImageForm.PixelSize, bmp.Width, bmp.Height, false, PaletteOffset, PaletteEncodings, PaletteBlockOffset, PaletteColorCount, PaletteColorOffset, 0, 0, Path.GetFileNameWithoutExtension(FileName)); MarioKart64ElementHub.Instance.TextureHub.AddImage(newImage); newImages.Add(newImage); } if (newImages.Count > 1) { MessageBox.Show(string.Format("{0} images loaded!", newImages.Count), "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); } if (newImages.Count > 0) { int newSelectedIndex = lbImages.Items.Count; lbImages.Items.AddRange(newImages.ToArray()); //Update the image count & selected lbImages.SelectedIndex = newSelectedIndex; UpdateImageCount(); } } }