Exemplo n.º 1
0
        /// <summary>
        /// a lookahead encoding scheme for ngc Yaz0
        /// </summary>
        /// <param name="src"></param>
        /// <param name="size"></param>
        /// <param name="pos"></param>
        /// <param name="pMatchPos"></param>
        /// <returns></returns>
        static UInt32 nintendoEnc(byte[] src, int size, int pos, ref uint pMatchPos, StaticEncodeVars var)
        //u32 nintendoEnc(u8* src, int size, int pos, u32 *pMatchPos)
        {
            //int startPos = pos - 0x1000;
            uint numBytes = 1;

            // if prevFlag is set, it means that the previous position was determined by look-ahead try.
            // so just use it. this is not the best optimization, but nintendo's choice for speed.
            if (var.prevFlag == 1)
            {
                pMatchPos    = var.matchPos; //*pMatchPos = matchPos;
                var.prevFlag = 0;
                return(var.numBytes1);
            }
            var.prevFlag = 0;
            numBytes     = simpleEnc(src, size, pos, ref var.matchPos); //numBytes = simpleEnc(src, size, pos, &matchPos);
            pMatchPos    = var.matchPos;                                //*pMatchPos = matchPos;

            // if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding
            if (numBytes >= 3)
            {
                var.numBytes1 = simpleEnc(src, size, pos + 1, ref var.matchPos); //numBytes1 = simpleEnc(src, size, pos+1, &matchPos);
                // if the next position encoding is +2 longer than current position, choose it.
                // this does not guarantee the best optimization, but fairly good optimization with speed.
                if (var.numBytes1 >= numBytes + 2)
                {
                    numBytes     = 1;
                    var.prevFlag = 1;
                }
            }
            return(numBytes);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Writes compressed file to given stream, starting at stream's position.
        /// </summary>
        /// <param name="src"></param>
        /// <param name="srcSize"></param>
        /// <param name="dstFile"></param>
        /// <returns></returns>
        public static int Encode(byte[] src, int srcSize, Stream dstFile)
        {
            Ret r = new Ret(0, 0);

            byte[] dst     = new byte[24]; // 8 codes * 3 bytes maximum
            int    dstSize = 0;

            uint validBitCount = 0; //number of valid bits left in "code" byte
            byte currCodeByte  = 0;

            uint numBytes;
            uint matchPos = 0;

            StaticEncodeVars var = new StaticEncodeVars();

            //Write Header
            byte[] srcSizeArr = BitConverter.GetBytes(srcSize);
            byte[] header     = new byte[] { 0x59, 0x61, 0x7A, 0x30 }; //Yaz0
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(srcSizeArr);
            }

            dstFile.Write(header, 0, 4);
            dstFile.Write(srcSizeArr, 0, 4);
            for (int i = 0; i < 8; i++)
            {
                dstFile.WriteByte(0);
            }

            while (r.srcPos < srcSize)
            {
                numBytes = nintendoEnc(src, srcSize, r.srcPos, ref matchPos, var); //matchPos passed ref &matchpos

                if (numBytes < 3)
                {
                    //straight copy
                    dst[r.dstPos] = src[r.srcPos];
                    r.dstPos++;
                    r.srcPos++;
                    //set flag for straight copy
                    currCodeByte |= (byte)(0x80 >> (int)validBitCount);
                }
                else
                {
                    //RLE part
                    UInt32 dist = (UInt32)r.srcPos - matchPos - 1;
                    byte   byte1, byte2, byte3;

                    if (numBytes >= 0x12)  // 3 byte encoding
                    {
                        byte1           = (byte)(0 | (dist >> 8));
                        byte2           = (byte)(dist & 0xff);
                        dst[r.dstPos++] = byte1;
                        dst[r.dstPos++] = byte2;
                        // maximum runlength for 3 byte encoding
                        if (numBytes > 0xff + 0x12)
                        {
                            numBytes = 0xff + 0x12;
                        }
                        byte3           = (byte)(numBytes - 0x12);
                        dst[r.dstPos++] = byte3;
                    }
                    else  // 2 byte encoding
                    {
                        byte1           = (byte)(((numBytes - 2) << 4) | (dist >> 8));
                        byte2           = (byte)(dist & 0xff);
                        dst[r.dstPos++] = byte1;
                        dst[r.dstPos++] = byte2;
                    }
                    r.srcPos += (int)numBytes;
                }
                validBitCount++;
                //write eight codes
                if (validBitCount == 8)
                {
                    dstFile.WriteByte(currCodeByte);
                    dstFile.Write(dst, 0, r.dstPos);

                    dstSize += r.dstPos + 1;

                    currCodeByte  = 0;
                    validBitCount = 0;
                    r.dstPos      = 0;
                }
            }
            if (validBitCount > 0)
            {
                dstFile.WriteByte(currCodeByte);
                dstFile.Write(dst, 0, r.dstPos);
                dstSize += r.dstPos + 1;

                currCodeByte  = 0;
                validBitCount = 0;
                r.dstPos      = 0;
            }
            return(dstSize);
        }