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);
                }
            }
        }
示例#3
0
        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();
                        }
                    }
                }
            }
        }