public void LoadFromXML() { //TextBank/TextReferences - Only use the offset currently being used //KartReference - Only use the names of the karts selected //MIOBlocks/TKMK00Bocks - Offsets for each one //Karts - Full listing of information //Elements should already have been cleared //ClearElements(); NewElementOffset = int.Parse(_loadedXml.Attribute(NEW_ELEMENT_OFFSET).Value); //Before we start, load up all saved karts and tracks ProgressService.SetMessage("Loading Kart Resources"); foreach (RomItem item in RomProject.Instance.Items) { //If the same name kart hasn't been loaded yet if (item is KartInfo && Karts.FirstOrDefault(k => k.KartName == ((KartInfo)item).KartName) == null) { this.Karts.Add((KartInfo)item); } //else if is trackinfo } //Also the text bank is all elements, so we don't need an xml in here for it ProgressService.SetMessage("Loading Text Blocks"); N64DataElement textRefEl, textBlockEl; if (RomProject.Instance.Files[0].HasElementExactlyAt(TextReferenceBlock.TEXT_REFERENCE_SECTION_1, out textRefEl) && RomProject.Instance.Files[0].HasElementExactlyAt(TextBankBlock.TEXT_BLOCK_START, out textBlockEl)) { TextReferenceBlock refBlock = (TextReferenceBlock)textRefEl; TextBankBlock bankBlock = (TextBankBlock)textBlockEl; TextBank = new TextBank(bankBlock, refBlock, true); } int offset; int count = 0; int fullCount = _loadedXml.Elements().Count(); N64DataElement n64Element; foreach (XElement element in _loadedXml.Elements()) { ProgressService.SetMessage(string.Format("Storing Special Elements {0:0.0}%", (double)count / fullCount)); switch (element.Name.ToString()) { case TURN_PALETTE_BLOCK: foreach (XElement el in element.Elements()) { offset = int.Parse(el.Value); if (RomProject.Instance.Files[0].HasElementExactlyAt(offset, out n64Element)) { int paletteOffset = offset; List <Palette> palettes = new List <Palette>(); palettes.Add((Palette)n64Element); paletteOffset += 0x40 * 2; for (int i = 1; i < 84; i++) //Make not hardcoded later { if (!RomProject.Instance.Files[0].HasElementAt(paletteOffset, out n64Element)) { throw new Exception(); } palettes.Add((Palette)n64Element); paletteOffset += 0x40 * 2; } KartPaletteBlock block = new KartPaletteBlock(offset, palettes); TurnKartPaletteBlocks.Add(block); } } break; case SPIN_PALETTE_BLOCK: foreach (XElement el in element.Elements()) { offset = int.Parse(el.Value); if (RomProject.Instance.Files[0].HasElementExactlyAt(offset, out n64Element)) { int paletteOffset = offset; List <Palette> palettes = new List <Palette>(); palettes.Add((Palette)n64Element); paletteOffset += 0x40 * 2; for (int i = 1; i < 80; i++) //Make not hardcoded later { if (!RomProject.Instance.Files[0].HasElementAt(paletteOffset, out n64Element)) { throw new Exception(); } palettes.Add((Palette)n64Element); paletteOffset += 0x40 * 2; } KartPaletteBlock block = new KartPaletteBlock(offset, palettes); SpinKartPaletteBlocks.Add(block); } } break; case KARTS_GRAPHICS_REFERENCE_BLOCK: offset = int.Parse(element.Value); if (RomProject.Instance.Files[0].HasElementExactlyAt(offset, out n64Element)) { if (n64Element is KartGraphicsReferenceBlock) { KartGraphicsBlock = (KartGraphicsReferenceBlock)n64Element; //KartReader.LoadKartGraphicDmaReferences(KartGraphicsBlock); } } break; case KARTS_PORTRAITS_REFERENCE_TABLE: offset = int.Parse(element.Value); if (RomProject.Instance.Files[0].HasElementExactlyAt(offset, out n64Element)) { if (n64Element is KartPortraitTable) { KartPortraitsTable = (KartPortraitTable)n64Element; //KartReader.LoadKartPortraitDmaReferences(KartPortraitsTable); } } break; case SELECTED_KARTS: int kartIndex = 0; foreach (XElement selKart in element.Elements()) { KartInfo selectedKart = Karts.SingleOrDefault(k => k.KartName == selKart.Name); if (selectedKart != null) { SelectedKarts[kartIndex] = selectedKart; } kartIndex++; } break; case TextureHub.TEXTURE_HUB: TextureHub.LoadReferencesFromXML(element); break; } count++; } }
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 static void LoadKartGraphicDmaReferences(KartGraphicsReferenceBlock block, byte[] rawData, KartReaderResults results, BackgroundWorker worker) { int mioOffset; //Anim palettes for (int i = 0; i < KartGraphicsReferenceBlock.CHARACTER_COUNT; i++) { for (int j = 0; j < KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT; j++) { if (block.WheelPaletteReferences[i][j].ReferenceElement == null) { //Load the palette block int paletteOffset = block.WheelPaletteReferences[i][j].Offset + KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET; N64DataElement existingPalette; //Don't double up on duplicates if (results.KartPaletteBlocks.SingleOrDefault(b => b.FileOffset == paletteOffset) == null) { if (RomProject.Instance.Files[0].HasElementExactlyAt(paletteOffset, out existingPalette) && existingPalette is Palette) { List <Palette> palettes = new List <Palette>(); int foundPaletteOffset = paletteOffset; for (int k = 0; k < KartGraphicsReferenceBlock.HALF_TURN_REF_COUNT * 4; k++) { if (RomProject.Instance.Files[0].HasElementExactlyAt(foundPaletteOffset, out existingPalette) && existingPalette is Palette) { palettes.Add((Palette)existingPalette); } foundPaletteOffset += 0x40 * 2; } KartPaletteBlock newBlock = new KartPaletteBlock(paletteOffset, palettes); block.WheelPaletteReferences[i][j].ReferenceElement = newBlock; results.KartPaletteBlocks.Add(newBlock); } else { //ERROR: COULD NOT FIND THE PALETTE INFORMATION! throw new Exception(); } } else { block.WheelPaletteReferences[i][j].ReferenceElement = results.KartPaletteBlocks.SingleOrDefault(b => b.FileOffset == paletteOffset); } } int j2 = j + KartGraphicsReferenceBlock.ANIMATION_ANGLE_COUNT; if (block.WheelPaletteReferences[i][j2].ReferenceElement == null) { //Load the palette block int paletteOffset = block.WheelPaletteReferences[i][j2].Offset + KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET; N64DataElement existingPalette; //Don't double up on duplicates if (results.KartPaletteBlocks.SingleOrDefault(b => b.FileOffset == paletteOffset) == null) { if (RomProject.Instance.Files[0].HasElementExactlyAt(paletteOffset, out existingPalette) && existingPalette is Palette) { List <Palette> palettes = new List <Palette>(); palettes.Add((Palette)existingPalette); int foundPaletteOffset = paletteOffset + 0x40 * 2; for (int k = 1; k < KartGraphicsReferenceBlock.FULL_SPIN_REF_COUNT * 4; k++) { if (RomProject.Instance.Files[0].HasElementExactlyAt(foundPaletteOffset, out existingPalette) && existingPalette is Palette) { palettes.Add((Palette)existingPalette); } foundPaletteOffset += 0x40 * 2; } KartPaletteBlock newBlock = new KartPaletteBlock(paletteOffset, palettes); block.WheelPaletteReferences[i][j2].ReferenceElement = newBlock; results.KartPaletteBlocks.Add(newBlock); } else { //ERROR: COULD NOT FIND THE PALETTE INFORMATION! throw new Exception(); } } else { block.WheelPaletteReferences[i][j2].ReferenceElement = results.KartPaletteBlocks.SingleOrDefault(b => b.FileOffset == paletteOffset); } } } } //Base palettes for (int i = 0; i < KartGraphicsReferenceBlock.CHARACTER_COUNT; i++) { string kartName = Enum.GetName(typeof(MarioKartRomInfo.OriginalCharacters), i); if (block.CharacterPaletteReferences[i].ReferenceElement == null) { int paletteOffset = block.CharacterPaletteReferences[i].Offset + KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET; N64DataElement existingPalette; if (RomProject.Instance.Files[0].HasElementExactlyAt(paletteOffset, out existingPalette) && existingPalette is Palette) { block.CharacterPaletteReferences[i].ReferenceElement = (Palette)existingPalette; } else if (rawData != null) { //ERROR: COULD NOT FIND THE PALETTE INFORMATION! throw new Exception(); } } //OKAY, Instructions for the next step: // Use the RomImageOrder to split up images the way you need to, then whatever. //Dictionary to speed up the searching algorithm Dictionary <int, MIO0Block> foundOffsets = new Dictionary <int, MIO0Block>(); for (int j = 0; j < block.CharacterTurnReferences[i].Length; j++) { if (block.CharacterTurnReferences[i][j].ReferenceElement == null) { mioOffset = block.CharacterTurnReferences[i][j].Offset + KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET; MIO0Block mio; N64DataElement elem; if (foundOffsets.TryGetValue(mioOffset, out mio)) { block.CharacterTurnReferences[i][j].ReferenceElement = mio; continue; } else if (RomProject.Instance.Files[0].HasElementExactlyAt(mioOffset, out elem) && elem is MIO0Block) { mio = (MIO0Block)elem; block.CharacterTurnReferences[i][j].ReferenceElement = mio; } else { //COULD NOT FIND THE MIO0!! throw new Exception(); } } } foundOffsets.Clear(); for (int j = 0; j < block.CharacterCrashReferences[i].Length; j++) { if (block.CharacterCrashReferences[i][j].ReferenceElement == null) { mioOffset = block.CharacterCrashReferences[i][j].Offset + KartGraphicsReferenceBlock.DMA_SEGMENT_OFFSET; MIO0Block mio; N64DataElement elem; if (foundOffsets.TryGetValue(mioOffset, out mio)) { block.CharacterCrashReferences[i][j].ReferenceElement = mio; continue; } else if (RomProject.Instance.Files[0].HasElementExactlyAt(mioOffset, out elem) && elem is MIO0Block) { mio = (MIO0Block)elem; block.CharacterCrashReferences[i][j].ReferenceElement = mio; } else { //COULD NOT FIND THE MIO0!! throw new Exception(); } } } } }