Пример #1
0
        public void setSegment(uint index, uint segmentStart, uint segmentEnd, bool isMIO0, bool fakeMIO0, uint uncompressedOffset)
        {
            if (segmentStart > segmentEnd)
            {
                return;
            }

            if (!isMIO0)
            {
                segStart[index]  = segmentStart;
                segIsMIO0[index] = false;
                uint size = segmentEnd - segmentStart;
                segData[index] = new byte[size];
                for (uint i = 0; i < size; i++)
                {
                    segData[index][i] = bytes[segmentStart + i];
                }
            }
            else
            {
                if (fakeMIO0)
                {
                    segStart[index]  = segmentStart + uncompressedOffset;
                    segIsMIO0[index] = false;
                }
                else
                {
                    segIsMIO0[index] = true;
                }
                segData[index] = MIO0.mio0_decode(getSubArray(bytes, segmentStart, segmentEnd - segmentStart));
            }
        }
Пример #2
0
        public static ImageMIO0BlockINVALID ReadImageMIO0BlockFrom(byte[] data, int offset)
        {
            int mio0Length = MIO0.FindLengthOfMIO0Block(data, offset);

            byte[] mio0Data = new byte[mio0Length];
            Array.Copy(data, offset, mio0Data, 0, mio0Length);

            return(new ImageMIO0BlockINVALID(offset.ToString("X8"), offset, mio0Data));
        }
Пример #3
0
        static void Test(byte[] bytes, Method method)
        {
            byte[] bytes2 = new byte[bytes.Length];

            switch (method)
            {
            case Method.LZ10:
                bytes2 = LZ10.Decompress(new MemoryStream(LZ10.Compress(new MemoryStream(bytes))), bytes.Length);
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.LZ11:
                bytes2 = LZ11.Decompress(new MemoryStream(LZ11.Compress(new MemoryStream(bytes))), bytes.Length);
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.LZ40:
                bytes2 = LZ40.Decompress(new MemoryStream(LZ40.Compress(new MemoryStream(bytes))), bytes.Length);
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.LZ77:
                bytes2 = LZ77.Decompress(new MemoryStream(LZ77.Compress(new MemoryStream(bytes))));
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.RevLZ77:
                bytes2 = RevLZ77.Decompress(new MemoryStream(RevLZ77.Compress(new MemoryStream(bytes))));
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.LZ4:
                bytes2 = LZ4.Decompress(new MemoryStream(LZ4.Compress(new MemoryStream(bytes))));
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.LZECD:
                bytes2 = LZECD.Decompress(new MemoryStream(LZECD.Compress(new MemoryStream(bytes))));
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.LZOvl:
                bytes2 = LZOvl.Decompress(new MemoryStream(LZOvl.Compress(new MemoryStream(bytes))));
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.MIO0:
                bytes2 = MIO0.Decompress(new MemoryStream(MIO0.Compress(new MemoryStream(bytes), ByteOrder.LittleEndian)), ByteOrder.LittleEndian);
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;
            }
        }
Пример #4
0
        public void setSegment(uint index, uint segmentStart, uint segmentEnd, bool isMIO0, bool fakeMIO0, uint uncompressedOffset, byte?areaID)
        {
            if (segmentStart > segmentEnd)
            {
                return;
            }

            SegBank seg = new SegBank();

            seg.SegID = (byte)index;

            if (!isMIO0)
            {
                seg.SegStart = segmentStart;
                seg.IsMIO0   = false;
                uint size = segmentEnd - segmentStart;
                seg.Data = new byte[size];
                for (uint i = 0; i < size; i++)
                {
                    seg.Data[i] = bytes[segmentStart + i];
                }
            }
            else
            {
                if (fakeMIO0)
                {
                    seg.SegStart = segmentStart + uncompressedOffset;
                    seg.IsMIO0   = false;
                }
                else
                {
                    seg.IsMIO0 = true;
                }
                seg.Data = MIO0.mio0_decode(getSubArray_safe(bytes, segmentStart, segmentEnd - segmentStart));
            }

            setSegment(index, seg, areaID);
        }
Пример #5
0
        public static void Compress(object sender, EventArgs e)
        {
            var tsi = sender as ToolStripMenuItem;

            if (!Shared.PrepareFiles("Open a decompressed " + tsi?.Tag + "file...", "Save your compressed file...", ".decomp", out var openFile, out var saveFile, true))
            {
                return;
            }

            try
            {
                using (openFile)
                    using (var outFs = new BinaryWriterX(saveFile))
                        switch (tsi?.Tag)
                        {
                        case Compression.L5LZ10:
                            outFs.Write(Level5.Compress(openFile, Level5.Method.LZ10));
                            break;

                        case Compression.L5Huff4:
                            outFs.Write(Level5.Compress(openFile, Level5.Method.Huffman4Bit));
                            break;

                        case Compression.L5Huff8:
                            outFs.Write(Level5.Compress(openFile, Level5.Method.Huffman8Bit));
                            break;

                        case Compression.L5RLE:
                            outFs.Write(Level5.Compress(openFile, Level5.Method.RLE));
                            break;

                        case Compression.NLZ10:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.LZ10));
                            break;

                        case Compression.NLZ11:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.LZ11));
                            break;

                        case Compression.NLZ60:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.LZ60));
                            break;

                        case Compression.NHuff4:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.Huff4));
                            break;

                        case Compression.NHuff8:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.Huff8));
                            break;

                        case Compression.NRLE:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.RLE));
                            break;

                        case Compression.LZ77:
                            outFs.Write(LZ77.Compress(openFile));
                            break;

                        case Compression.RevLZ77:
                            outFs.Write(RevLZ77.Compress(openFile));
                            break;

                        case Compression.LZOvl:
                            outFs.Write(LZOvl.Compress(openFile));
                            break;

                        case Compression.LZ4:
                            outFs.Write(Kontract.Compression.LZ4.Compress(openFile));
                            break;

                        case Compression.MIO0LE:
                            outFs.Write(MIO0.Compress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.MIO0BE:
                            outFs.Write(MIO0.Compress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.Yay0LE:
                            outFs.Write(Yay0.Compress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.Yay0BE:
                            outFs.Write(Yay0.Compress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.Yaz0LE:
                            outFs.Write(Yaz0.Compress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.Yaz0BE:
                            outFs.Write(Yaz0.Compress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.GZip:
                            outFs.Write(GZip.Compress(openFile));
                            break;

                        case Compression.ZLib:
                            outFs.Write(ZLib.Compress(openFile));
                            break;

                        case Compression.PSVSpikeChun:
                            outFs.Write(PSVSpikeChun.Compress(openFile));
                            break;
                        }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), tsi?.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            MessageBox.Show($"Successfully compressed {Path.GetFileName(openFile.Name)}.", tsi.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
Пример #6
0
        public static void Decompress(object sender, EventArgs e)
        {
            var tsi = sender as ToolStripMenuItem;

            if (!Shared.PrepareFiles("Open a " + tsi?.Tag + " compressed file...", "Save your decompressed file...", ".decomp", out var openFile, out var saveFile))
            {
                return;
            }

            try
            {
                using (openFile)
                    using (var outFs = new BinaryWriterX(saveFile))
                        switch (tsi?.Tag)
                        {
                        case Compression.Level5:
                            outFs.Write(Level5.Decompress(openFile));
                            break;

                        case Compression.Nintendo:
                            outFs.Write(Nintendo.Decompress(openFile));
                            break;

                        case Compression.LZ77:
                            outFs.Write(LZ77.Decompress(openFile));
                            break;

                        case Compression.RevLZ77:
                            outFs.Write(RevLZ77.Decompress(openFile));
                            break;

                        case Compression.LZOvl:
                            outFs.Write(LZOvl.Decompress(openFile));
                            break;

                        case Compression.LZ4:
                            outFs.Write(Kontract.Compression.LZ4.Decompress(openFile));
                            break;

                        case Compression.MIO0LE:
                            outFs.Write(MIO0.Decompress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.MIO0BE:
                            outFs.Write(MIO0.Decompress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.Yay0LE:
                            outFs.Write(Yay0.Decompress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.Yay0BE:
                            outFs.Write(Yay0.Decompress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.Yaz0LE:
                            outFs.Write(Yaz0.Decompress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.Yaz0BE:
                            outFs.Write(Yaz0.Decompress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.LZECD:
                            outFs.Write(LZECD.Decompress(openFile));
                            break;

                        case Compression.LZ10VLE:
                            outFs.Write(LZSSVLE.Decompress(openFile));
                            break;

                        case Compression.GZip:
                            outFs.Write(GZip.Decompress(openFile));
                            break;

                        case Compression.ZLib:
                            outFs.Write(ZLib.Decompress(openFile));
                            break;

                        case Compression.PSVSpikeChun:
                            outFs.Write(PSVSpikeChun.Decompress(openFile));
                            break;
                        }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), tsi?.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            MessageBox.Show($"Successfully decompressed {Path.GetFileName(openFile.Name)}.", tsi.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
Пример #7
0
        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();
            }
        }
Пример #8
0
        private int parseLevelScriptTemporarlyForSegments(byte[][] segments, uint[] segmentStarts, bool[] segmentsAreMIO0, byte seg, uint off)
        {
            ROM rom = ROM.Instance;

            byte[] data   = segments[seg];
            bool   end    = false;
            int    endCmd = 0;
            byte   l_seg;
            uint   l_start, l_end, l_off;

            while (!end)
            {
                byte   cmdLen = data[off + 1];
                byte[] cmd    = rom.getSubArray_safe(data, off, cmdLen);
                //rom.printArray(cmd, cmdLen);
                switch (cmd[0])
                {
                case 0x00:
                case 0x01:
                {
                    l_seg   = cmd[3];
                    l_start = bytesToInt(cmd, 4, 4);
                    l_end   = bytesToInt(cmd, 8, 4);
                    l_off   = bytesToInt(cmd, 13, 3);
                    segmentStarts[l_seg] = l_start;
                    segments[l_seg]      = rom.getROMSection(l_start, l_end);
                    int end_r = parseLevelScriptTemporarlyForSegments(segments, segmentStarts, segmentsAreMIO0, l_seg, l_off);
                    if (end_r == 0x02)
                    {
                        end    = true;
                        endCmd = 2;
                    }
                }
                break;

                case 0x02:
                    endCmd = 2;
                    end    = true;
                    break;

                case 0x05:
                    l_seg = cmd[4];
                    l_off = bytesToInt(cmd, 5, 3);
                    if (l_seg == seg)
                    {
                        if ((long)l_off - (long)off == -4)
                        {
                            //Console.WriteLine("Infinite loop detected!");
                            return(0x02);
                        }
                    }
                    endCmd = parseLevelScriptTemporarlyForSegments(segments, segmentStarts, segmentsAreMIO0, l_seg, l_off);
                    end    = true;
                    break;

                case 0x06:
                    l_seg = cmd[4];
                    l_off = bytesToInt(cmd, 5, 3);
                    int end_ret = parseLevelScriptTemporarlyForSegments(segments, segmentStarts, segmentsAreMIO0, l_seg, l_off);
                    if (end_ret == 0x02)
                    {
                        end    = true;
                        endCmd = 2;
                    }
                    break;

                case 0x07:
                    end    = true;
                    endCmd = 0x07;
                    break;

                case 0x17:
                    l_seg   = cmd[3];
                    l_start = bytesToInt(cmd, 4, 4);
                    l_end   = bytesToInt(cmd, 8, 4);
                    if (l_start < l_end)
                    {
                        segmentStarts[l_seg] = l_start;
                        segments[l_seg]      = rom.getROMSection(l_start, l_end);
                    }
                    //rom.setSegment(seg, start, end, false);
                    break;

                case 0x18:
                case 0x1A:
                    l_seg   = cmd[3];
                    l_start = bytesToInt(cmd, 4, 4);
                    l_end   = bytesToInt(cmd, 8, 4);
                    if (l_start < l_end)
                    {
                        byte[] MIO0_header = rom.getSubArray_safe(rom.Bytes, l_start, 0x10);
                        if (bytesToInt(MIO0_header, 0, 4) == 0x4D494F30)     // Check MIO0 signature
                        {
                            int  compressedOffset   = (int)bytesToInt(MIO0_header, 0x8, 4);
                            int  uncompressedOffset = (int)bytesToInt(MIO0_header, 0xC, 4);
                            bool isFakeMIO0         = rom.testIfMIO0IsFake(l_start, compressedOffset, uncompressedOffset);
                            segmentsAreMIO0[l_seg] = !isFakeMIO0;
                            if (isFakeMIO0)
                            {
                                segmentStarts[l_seg] = l_start + (uint)uncompressedOffset;
                            }
                            segments[l_seg] = MIO0.mio0_decode(rom.getROMSection(l_start, l_end));
                        }
                    }
                    break;

                case 0x1D:
                    end    = true;
                    endCmd = 0x02;
                    break;
                }
                off += cmdLen;
            }
            return(endCmd);
        }
Пример #9
0
        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;
                    }
                }
            }
        }
Пример #10
0
        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();
                }
            }
        }