Exemplo n.º 1
0
        // MIO0 decompression code by HyperHacker (adapted from SF64Toolkit)
        public static bool DecompressMIO0(byte[] data, out byte[] outputData)
        {
            MIO0Header Header;
            byte       MapByte = 0x80, CurMapByte, Length;
            ushort     SData, Dist;
            uint       NumBytesOutput = 0;
            uint       MapLoc         = 0; // current compression map position
            uint       CompLoc        = 0; // current compressed data position
            uint       RawLoc         = 0; // current raw data position
            uint       OutLoc         = 0; // current output position

            outputData = null;

            int i;

            Header.ID         = ByteHelper.ReadUInt(data, 0);
            Header.OutputSize = ByteHelper.ReadUInt(data, 4);
            Header.CompLoc    = ByteHelper.ReadUInt(data, 8);
            Header.RawLoc     = ByteHelper.ReadUInt(data, 12);

            // "MIO0"
            if (Header.ID != 0x4D494F30)
            {
                return(false);
            }

            byte[] MIO0Buffer = new byte[Header.OutputSize];

            MapLoc  = 0x10;
            CompLoc = Header.CompLoc;
            RawLoc  = Header.RawLoc;

            CurMapByte = data[MapLoc];

            while (NumBytesOutput < Header.OutputSize)
            {
                // raw
                if ((CurMapByte & MapByte) != 0x0)
                {
                    MIO0Buffer[OutLoc] = data[RawLoc]; // copy a byte to output.
                    OutLoc++;
                    RawLoc++;
                    NumBytesOutput++;
                }

                // compressed
                else
                {
                    SData  = ByteHelper.ReadUShort(data, CompLoc); // get compressed data
                    Length = (byte)((SData >> 12) + 3);
                    Dist   = (ushort)((SData & 0xFFF) + 1);

                    // sanity check: can't copy from before first byte
                    if (((int)OutLoc - Dist) < 0)
                    {
                        return(false);
                    }

                    // copy from output
                    for (i = 0; i < Length; i++)
                    {
                        MIO0Buffer[OutLoc] = MIO0Buffer[OutLoc - Dist];
                        OutLoc++;
                        NumBytesOutput++;
                        if (NumBytesOutput >= Header.OutputSize)
                        {
                            break;
                        }
                    }
                    CompLoc += 2;
                }

                MapByte >>= 1; // next map bit

                // if we did them all, get the next map byte
                if (MapByte == 0x0)
                {
                    MapByte = 0x80;
                    MapLoc++;
                    CurMapByte = data[MapLoc];

                    // sanity check: map pointer should never reach this
                    int Check = (int)CompLoc;
                    if (RawLoc < CompLoc)
                    {
                        Check = (int)RawLoc;
                    }

                    if (MapLoc > Check)
                    {
                        return(false);
                    }
                }
            }

            outputData = MIO0Buffer;

            return(true);
        }