/*- * Copyright (C) 2006 Erik Larsson * * All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package org.catacombae.rarx; //import org.catacombae.rarx.*; import java.math.BigInteger; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; import java.util.zip.CRC32; public class DecompressionCode { private static final int MAXWINSIZE = 0x100000; private static final int MAXWINMASK = (MAXWINSIZE-1); private static final int UNP_MEMORY = MAXWINSIZE; public static final short NC = 298; /* alphabet = {0,1,2, .,NC - 1} */ public static final short DC = 48; public static final short RC = 28; public static final short BC = 19; public static final short MC = 257; public static final int CODE_HUFFMAN = 0; public static final int CODE_LZ = 1; public static final int CODE_LZ2 = 2; public static final int CODE_REPEATLZ = 3; public static final int CODE_CACHELZ = 4; public static final int CODE_STARTFILE = 5; public static final int CODE_ENDFILE = 6; public static final int CODE_ENDMM = 7; public static final int CODE_STARTMM = 8; public static final int CODE_MMDELTA = 9; public static final int LHD_SPLIT_BEFORE = 1; //flag bit 0 public static final int LHD_SPLIT_AFTER = 2; //flag bit 1 public static final int LHD_PASSWORD = 4; //flag bit 2 public static final int LHD_COMMENT = 8; //flag bit 3 public static final int LHD_SOLID = 16; //flag bit 4 public static final int LHD_WINDOWMASK = 0x00e0; public static final int LHD_WINDOW64 = 0; public static final int LHD_WINDOW128 = 32; public static final int LHD_WINDOW256 = 64; public static final int LHD_WINDOW512 = 96; public static final int LHD_WINDOW1024 = 128; public static final int LHD_DIRECTORY = 0x00e0; public static final int NROUNDS = 32; /* Static variables belonging to the function Unpack. */ private static final short[] LDecode = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224}; //unsigned char[14] private static final byte[] LBits = {0,0,0,0,0,0,0,0,1,1,1,1,2,2, //unsigned char[14] 2,2,3,3,3,3,4,4,4,4,5,5,5,5}; private static final int[] DDecode = {0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152, 65536, 98304, 131072,196608,262144,327680,393216,458752, 524288,589824,655360,720896,786432,851968,917504,983040}; //int[48] private static final byte[] DBits = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,10,11,11,12,12,13,13,14,14, 15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; //unsigned char[48] private static final short[] SDDecode = {0,4,8,16,32,64,128,192}; //unsigned char[8] private static final byte[] SDBits = {2,2,3,4,5,6,6,6}; //unsigned char[8] public static final /*UBYTE*/ short[] InitSubstTable = { 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42 ,232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137 ,255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6 , 71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235 ,107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36 ,158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251 , 97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11 ,164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51 ,207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7 ,122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80 ,131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129 ,224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10 ,118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108 ,161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225 , 0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52 ,116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84 }; // UBYTE[256] public static final /*UDWORD*/ int[] CRCTab = new int[256]; // Initialized in static constructor static { // Perform initialization of static structures and variables. //CRCTab = new int[256]; InitCRC(CRCTab); } private CRC32 crc = new CRC32(); public final /*UBYTE*/ short[] SubstTable = new short[256]; private /*unsigned*/ byte PN1, PN2, PN3; /* Note: temp_output_buffer is allocated when a file is about to be extracted. It is allocated to NewLhd.UnpSize, which can be quite large. The assumption that the unpacked file can be stored in memory is awkward and must immediately be replaced with an output stream. */ private /* unsigned char* */ byte[] temp_output_buffer; /* extract files to this pointer*/ private /* unsigned long* */ int temp_output_buffer_offset; /* size of temp. extract buffer */ //private /*unsigned int*/ int UnpPtr,WrPtr; private final /*unsigned short*/ short[] OldKey = new short[4]; private static class Decode { public int MaxNum; // unsigned int public final int[] DecodeLen = new int[16]; // unsigned int[16] public final int[] DecodePos = new int[16]; // unsigned int[16] public final int[] DecodeNum; // unsigned int[] public Decode() { this(2); } protected Decode(int decodeNumSize) { DecodeNum = new int[decodeNumSize]; } } private static class LitDecode extends Decode { public LitDecode() { super(NC); } } private static class DistDecode extends Decode { public DistDecode() { super(DC); } } private static class RepDecode extends Decode { public RepDecode() { super(RC); } } private static class MultDecode extends Decode { public MultDecode() { super(MC); } } private static class BitDecode extends Decode { public BitDecode() { super(BC); } } private final LitDecode LD = new LitDecode(); private final DistDecode DD = new DistDecode(); private final RepDecode RD = new RepDecode(); private final MultDecode[] MD = { new MultDecode(), new MultDecode(), new MultDecode(), new MultDecode() }; //new MultDecode[4]; private final BitDecode BD = new BitDecode(); private final MultDecode[] MDPtr = { MD[0], MD[1], MD[2], MD[3] }; /* ***************************** * ** unpack stored RAR files ** * *****************************/ // BOOL UnstoreFile(void) // { // if ((long)(*temp_output_buffer_offset=UnpRead(temp_output_buffer, // NewLhd.UnpSize))==-1) // { // debug_log("Read error of stored file!"); // return FALSE; // } // return TRUE; // } /* **************************************** * ** RAR decompression code starts here ** * ****************************************/ /* #define statements */ public static class AudioVariables { public int K1,K2,K3,K4,K5; // Should be short...? public int D1,D2,D3,D4; public int LastDelta; public final int[] Dif = new int[11]; //unsigned public int ByteCount; //unsigned public int LastChar; public void zero() { K1 = 0; K2 = 0; K3 = 0; K4 = 0; K5 = 0; D1 = 0; D2 = 0; D3 = 0; D4 = 0; LastDelta = 0; Util.zero(Dif); ByteCount = 0; LastChar = 0; } } public AudioVariables[] AudV = { new AudioVariables(), new AudioVariables(), new AudioVariables(), new AudioVariables() }; /* #define GetBits() \ BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \ ( (UWORD) InBuf[InAddr+1] << 8 ) | \ ( InBuf[InAddr+2] ) ) \ >> (8-InBit) ) & 0xffff; */ private static int GetBits(byte[] inBuf, int inAddr, int inBit) { return ( ( ( (int) (inBuf[inAddr]&0xFF) << 16 ) | ( (short) (inBuf[inAddr+1]&0xFF) << 8 ) | ( (inBuf[inAddr+2]&0xFF) ) ) >>> (8-unsign(inBit)) ) & 0xffff; } /* #define AddBits(Bits) \ InAddr += ( InBit + (Bits) ) >> 3; \ InBit = ( InBit + (Bits) ) & 7; */ /** * Adds Bits to the address specifiers. * InAddr is the high 32 bits of the 35-bit address (?) while InBit is the low 3 bits (?). * Modifies: InAddr, InBit * @param Bits the bits to add (interpreted as unsigned int) */ private void AddBits(int Bits) { InAddr += (int)(( unsign(InBit) + unsign(Bits) ) >>> 3); // (InBit + Bits) / 8 InBit = (int)(( unsign(InBit) + unsign(Bits) ) & 7); } public static int unsign(byte i) { return i & 0xFF; } public static int unsign(short i) { return i & 0xFFFF; } public static long unsign(int i) { return i & 0xFFFFFFFFL; } public static BigInteger unsign(long i) { return new BigInteger(1, Util.toByteArrayBE(i)); } private static class Struct_NewFileHeader { short HeadCRC; byte HeadType; short Flags; short HeadSize; int PackSize; int UnpSize; byte HostOS; int FileCRC; int FileTime; byte UnpVer; byte Method; short NameSize; int FileAttr; }; private NewFileHeader NewLhd;// = new NewFileHeader(); private RARFileEntryStream ArcPtr = null; private int Encryption; private long UnpPackedSize; private /*unsigned long*/ int CurUnpRead, CurUnpWrite; //private byte[] UnpBuf; private int BitField; //unsigned int //private int Number; //unsigned int public final byte[] InBuf = new byte[8192]; /* input read buffer */ public final byte[] UnpOldTable = new byte[MC*4]; public int InAddr,InBit,ReadTop; //unsigned int //public int LastDist,LastLength; //unsigned int //private int Length,Distance; //unsigned int //public final int[] OldDist = new int[4]; //unsigned int //public int OldDistPtr; //unsigned int public int UnpAudioBlock; public int UnpChannels; public int CurChannel; public int ChannelDelta; private boolean FileFound; /* *** 38.3% of all CPU time is spent within this function!!! */ /** * Unpacks stuff.

* *

     * Global read set (constants):
     *       DBits                      (final byte[48])
     *       DDecode                    (final int[48])
     *       LBits                      (final byte[14])
     *       LDecode                    (final short[14])
     *       LHD_SOLID                  (final int)
     *       MAXWINMASK                 (final int)
     *       MDPtr                      (final {@link MultDecode}[4])
     *       SDBits                     (final byte[8])
     *       SDDecode                   (final short[8])
     *
     * Global read set (variables):
     *       FileFound                  (boolean)
     *       NewLhd                     ({@link Struct_NewFileHeader})
     *
     * Global modify set:
     *       BitField                   (int)
     *       CurChannel                 (int)
     *       DD                         (final {@link DistDecode})
     *       InAddr                     (int)
     *       InBit                      (int)
     *       InBuf                      (final byte[8192])
     *       LD                         (final {@link LitDecode})
     *       temp_output_buffer         (byte[])
     *       temp_output_buffer_offset  (int)
     *       UnpAudioBlock              (int)
     *       UnpChannels                (int)
     *
     * Local use set:
     *       Bits                       (int)
     * (in)  DestUnpSize                (long)
     *       Distance                   (int)
     *       LastDist                   (int)
     *       LastLength                 (int)
     *       Length                     (int)
     *       Number                     (int)
     *       OldDist                    (final int[4])
     *       OldDistPtr                 (int)
     * (in)  UnpAddr                    (byte[])
     *       UnpBuf                     (byte[])
     *       UnpPtr                     (int)
     *       WrPtr                      (int)
     *
     * Call set:
     *       {@link #UnpInitData}
     *       {@link #UnpReadBuf}
     *       {@link #ReadTables}
     *       {@link #debug_log}
     *       {@link System#arraycopy}
     *       {@link #DecodeNumber}
     *       {@link #DecodeAudio}
     *       {@link #GetBits}
     *       {@link #AddBits}
     *       {@link #ReadLastTables}
     * 
*/ public void Unpack(/*unsigned char*/ byte[] UnpAddr, /*long DestUnpSize, */RARFileEntryStream i_ArcPtr, OutputStream dataOut, NewFileHeader i_NewLhd) throws IOException { // catacombae ArcPtr = i_ArcPtr; NewLhd = i_NewLhd; long DestUnpSize = NewLhd.getUnpSize(); UnpPackedSize = NewLhd.getPackSize(); FileFound = true; //Otherwise no data will be written, just uncompressed and skipped (for the purpose of extracting solid archives). Encryption = 0; CurUnpRead = CurUnpWrite = 0; // /catacombae int Bits; // unsigned int byte[] UnpBuf=UnpAddr; /* UnpAddr is a pointer to the unpack buffer */ int UnpPtr = 0; // Pointer to where in the buffer we are at present int WrPtr = 0; // Pointer to where in the buffer UnpBuf we were at the last write int Length = 0; int Distance = 0; int LastDist = 0; int LastLength = 0; int Number = 0; final int[] OldDist = new int[4]; int OldDistPtr = 0; System.out.println("UnpInitData"); UnpInitData(UnpBuf); System.out.println("UnpReadBuf"); UnpReadBuf(true); if((NewLhd.getFlags() & LHD_SOLID) == 0) { System.out.println("ReadTables"); ReadTables(); } DestUnpSize--; int l256 = 0, g269 = 0, e269 = 0, e256 = 0, l261 = 0, l270 = 0; // debug / understanding while(DestUnpSize>=0) { System.out.println("Looping (DestUnpSize=" + DestUnpSize + ")"); UnpPtr &= MAXWINMASK; if(unsign(InAddr) > InBuf.length-30) UnpReadBuf(false); if(((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr) { System.out.println("YO"); if(FileFound) { // Flush extracted data to file if(!writeData(UnpBuf, UnpPtr, WrPtr, dataOut)) DestUnpSize = -1; } WrPtr=UnpPtr; } else { //System.out.println("((" + WrPtr + "-" + UnpPtr + ") & MAXWINMASK) >= 270"); //System.out.println(((WrPtr-UnpPtr) & MAXWINMASK) + "<270"); } if(UnpAudioBlock != 0) { Number = DecodeNumber(MDPtr[CurChannel]); if (Number==256) { ReadTables(); } else { UnpBuf[UnpPtr++]=DecodeAudio(Number); if (++CurChannel==UnpChannels) CurChannel=0; DestUnpSize--; } //continue; } else { Number = DecodeNumber(LD); if(Number<256) { // stored System.out.println(Number); ++l256; UnpBuf[UnpPtr++]=(byte)Number; DestUnpSize--; //continue; } else if(Number>269) { ++g269; Length = LDecode[Number-=270]+3; if ((Bits=LBits[Number])>0) { BitField = GetBits(InBuf, InAddr, InBit); Length+=BitField>>>(16-Bits); AddBits(Bits); } Number = DecodeNumber(DD); Distance = DDecode[Number]+1; if ((Bits=DBits[Number])>0) { BitField = GetBits(InBuf, InAddr, InBit); Distance += BitField >>> (16-Bits); AddBits(Bits); } if (Distance>=0x40000) Length++; if (Distance>=0x2000) Length++; LastDist=OldDist[OldDistPtr++ & 3]=Distance; DestUnpSize-=(LastLength=Length); while (Length-- != 0) { UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK]; UnpPtr=(UnpPtr+1) & MAXWINMASK; } //continue; } else if(Number==269) { ++e269; ReadTables(); //continue; } else if(Number==256) { ++e256; Length = LastLength; Distance = LastDist; LastDist = OldDist[OldDistPtr++ & 3] = Distance; DestUnpSize -= (LastLength=Length); while(Length-- != 0) { UnpBuf[UnpPtr] = UnpBuf[(UnpPtr-Distance) & MAXWINMASK]; UnpPtr = (UnpPtr+1) & MAXWINMASK; } //continue; } else if(Number<261) { ++l261; Distance=OldDist[(OldDistPtr-(Number-256)) & 3]; Number = DecodeNumber(RD); Length=LDecode[Number]+2; if ((Bits=LBits[Number])>0) { BitField = GetBits(InBuf, InAddr, InBit); Length+=BitField>>>(16-Bits); AddBits(Bits); } if (Distance>=0x40000) Length++; if (Distance>=0x2000) Length++; if (Distance>=0x101) Length++; LastDist=OldDist[OldDistPtr++ & 3]=Distance; DestUnpSize-=(LastLength=Length); while (Length-- != 0) { UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK]; UnpPtr=(UnpPtr+1) & MAXWINMASK; } //continue; } else if(Number<270) { ++l270; Distance=SDDecode[Number-=261]+1; if ((Bits=SDBits[Number])>0) { BitField = GetBits(InBuf, InAddr, InBit); Distance+=BitField>>>(16-Bits); AddBits(Bits); } Length=2; LastDist=OldDist[OldDistPtr++ & 3]=Distance; DestUnpSize-=(LastLength=Length); while (Length-- != 0) { UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK]; UnpPtr=(UnpPtr+1) & MAXWINMASK; } //continue; } else debug_log("This message will NEVER be printed. If it is printed anyway, kick the programmer."); } } System.out.println("x < 256: " + l256); System.out.println("x > 269: " + g269); System.out.println("x = 269: " + e269); System.out.println("x = 256: " + e256); System.out.println("x < 261: " + l261); System.out.println("x < 270: " + l270); System.out.println("Total: " + (l256+g269+e269+e256+l261+l270)); System.out.println("LD.DecodeLen: 0x" + Util.toHexStringBE(LD.DecodeLen)); System.out.println("LD.DecodeNum: 0x" + Util.toHexStringBE(LD.DecodeNum)); System.out.println("LD.DecodePos: 0x" + Util.toHexStringBE(LD.DecodePos)); System.out.println("LD.MaxNum: 0x" + Util.toHexStringBE(LD.MaxNum)); ReadLastTables(); if (FileFound) { /* flush buffer */ // Flush extracted data to file if(!writeData(UnpBuf, UnpPtr, WrPtr, dataOut)) DestUnpSize = -1; } WrPtr=UnpPtr; } /** * Writes the data in UnpBuf to dataOut according to some rules.

*

     * Global read set:
     *       {@link #NewLhd}            ({@link NewFileHeader})
     *
     * Global modify set:
     *      *temp_output_buffer         (byte[])
     *       temp_output_buffer_offset  (int)
     *
     * Local use set:
     * (in)  UnpBuf                     (byte[])
     * 
*/ private boolean writeData(byte[] UnpBuf, int UnpPtr, int WrPtr, OutputStream dataOut) throws IOException { if (UnpPtr NewLhd.getUnpSize()) { debug_log("Fatal! Buffer overrun during decompression!"); return false; //DestUnpSize=-1; } else if(true) { int firstOutLengthOld = (0-WrPtr) & MAXWINMASK; // Don't understand... int firstOutLength = (UnpBuf.length-1) - WrPtr; //This should be equivalent to the above if(firstOutLengthOld != firstOutLength) debug_log("Assumption broken for firstOutLength :("); dataOut.write(UnpBuf, WrPtr, firstOutLength); dataOut.write(UnpBuf, 0, UnpPtr); temp_output_buffer_offset += firstOutLength+UnpPtr; } else { int firstOutLength = (0-WrPtr) & MAXWINMASK; // Don't understand... /* copy extracted data to output buffer */ System.arraycopy(UnpBuf, WrPtr, temp_output_buffer, temp_output_buffer_offset, firstOutLength); /* update offset within buffer */ temp_output_buffer_offset += firstOutLength; /* copy extracted data to output buffer */ System.arraycopy(UnpBuf, 0, temp_output_buffer, temp_output_buffer_offset, UnpPtr); /* update offset within buffer */ temp_output_buffer_offset += UnpPtr; } } else { debug_log("UnpPtr>WrPtr (" + UnpPtr + ">" + WrPtr + ")"); if((temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.getUnpSize()) { debug_log("Fatal! Buffer overrun during decompression!"); //DestUnpSize=-1; return false; } else if(true) { dataOut.write(UnpBuf, WrPtr, UnpPtr-WrPtr); temp_output_buffer_offset += UnpPtr-WrPtr; } else { /* copy extracted data to output buffer */ System.arraycopy(UnpBuf, WrPtr, temp_output_buffer, temp_output_buffer_offset, UnpPtr-WrPtr); temp_output_buffer_offset+=UnpPtr-WrPtr; /* update offset within buffer */ } } return true; } /** * Reads into the buffer InBuf from the archive stream. If the flag FirstBuf * is set, the method preserves the last 32 bytes of InBuf and copies them to the front * of the buffer, filling the buffer with only InBuf.length-32 bytes.

*

     * Global modify set:
     *       ReadTop                    (int)
     *       InAddr                     (int)
     *       Through UnpRead:
     *         UnpPackedSize            (int)
     *         CurUnpRead               (int)
     * 
     * Global read set:
     *       InBuf                      (byte[])          (contents modified in UnpRead)
     *
     * Local use set:
     * (in)  FirstBuf                   (boolean)
     *       RetCode                    (int)
     *
     * Call set:
     *       {@link UnpRead}
     * 
* @param FirstBuf flag indicating whether or not we will treat this read as the first read * to the buffer, thus destroying any previous content */ private void UnpReadBuf(boolean FirstBuf) { int RetCode; if(FirstBuf) { ReadTop = UnpRead(InBuf, 0, InBuf.length); InAddr = 0; } else { System.arraycopy(InBuf, InBuf.length-32, InBuf, 0, 32); InAddr &= 0x1f; // discard all but the five least significant bytes... is this modulo 32? think so. RetCode = UnpRead(InBuf, 32, InBuf.length-32); if(RetCode > 0) ReadTop=RetCode+32; else ReadTop=InAddr; } } /** * Reads Count bytes from the stream ArcPtr into * the buffer Addr at position offset. If the * data is encrypted, it is automatically decrypted. (The variable * Encryption tells the function whether is shall consider * the data to be encrypted.)

*

     * Global read set:
     *       ArcPtr                     ({@link java.io.InputStream})
     *       Encryption                 (int)
     *       
     * Global modify set:
     *       UnpPackedSize              (int)
     *       CurUnpRead                 (int)
     * 
     * Local use set:
     * (in)  Addr                       (byte[])
     * (in)  offset                     (int)
     * (in)  Count                      (int)
     *       RetCode                    (int)
     *       I                          (int)
     *       ReadSize                   (int)
     *       TotalRead                  (int)
     *       ReadAddr                   (byte[])
     *       readAddrPointer            (int)
     *
     * Call set:
     *       tread(File, byte[], int, int)
     *       debug_log(String)
     *       DecryptBlock(byte[], int, int)
     * 
* @return the number of bytes read, or -1 if an error occurred. */ private /*unsigned int*/ int UnpRead(/*unsigned char **/ byte[] Addr, int offset, /*unsigned int*/ int Count) { int RetCode=0; /*unsigned int*/ int I,ReadSize,TotalRead=0; /*unsigned char **/ byte[] ReadAddr; int readAddrPointer = offset; // catacombae ReadAddr=Addr; while(Count > 0) { ReadSize=(/*unsigned int*/ int)((Count>(/*unsigned long*/ int)UnpPackedSize) ? UnpPackedSize : Count); if (ArcPtr==null) return(0); RetCode=tread(ArcPtr,ReadAddr,readAddrPointer,ReadSize); debug_log("Read " + RetCode + " from file."); CurUnpRead+=RetCode; readAddrPointer+=RetCode; TotalRead+=RetCode; Count-=RetCode; UnpPackedSize-=RetCode; break; // Why the while-loop? if would work just as well. } if (RetCode!= -1) { RetCode=TotalRead; if (Encryption != 0) { if (Encryption<20) { debug_log("Old Crypt() not supported!"); } else { for (I=0;I<(/*unsigned int*/ short)RetCode;I+=16) DecryptBlock(/*&Addr[I]*/Addr, I); } } } return(RetCode); } /** * Reads and initializes the decompression tables.

*

     * Global read set (constants):
     *       BC                         (final short)
     *       DC                         (final short)
     *       MC                         (final short)
     *       NC                         (final short)
     *       RC                         (final short)
     *
     * Global read set (variables):
     *
     * Global modify set:
     *       BD                         (BitDecode)
     *       BitField                   (int)
     *       CurChannel                 (int)
     *       DD                         (DistDecode)
     *       InAddr                     (int)
     *       InBit                      (int) (through AddBits)
     *       InBuf                      (final byte[8192])
     *       MDPtr                      (final MultDecode[4])
     *       RD                         (RepDecode)
     *       UnpAudioBlock              (int)
     *       UnpChannels                (int)
     *       UnpOldTable                (final byte[MC*4])
     *
     *
     * Local use set:
     *       BitLength                  (final byte[BC])
     *       Table                      (final byte[MC*4])
     *       TableSize                  (int)
     *       N                          (int)
     *       I                          (int)
     *
     * Call set:
     *       UnpReadBuf
     *       GetBits
     *       Util.zero
     *       AddBits
     *       MakeDecodeTables
     *       DecodeNumber
     *       System.arraycopy
     * 
*/ private void ReadTables() { System.out.println("ReadTables():"); final /*UBYTE*/ byte[] BitLength = new byte[BC]; final /*unsigned char*/ byte[] Table = new byte[MC*4]; /*int*/ int TableSize,N,I; if(InAddr>InBuf.length-25) { System.out.println("InAddr == " + InAddr); UnpReadBuf(false); } BitField = GetBits(InBuf, InAddr, InBit); UnpAudioBlock = (BitField & 0x8000); if((BitField & 0x4000) == 0) Util.zero(UnpOldTable); AddBits(2); if(UnpAudioBlock != 0) { UnpChannels=((BitField >>> 12) & 3)+1; debug_log("WARNING: UnpChannels = " + UnpChannels); if (CurChannel>=UnpChannels) CurChannel=0; AddBits(2); TableSize=(short)(MC*UnpChannels); } else TableSize=NC+DC+RC; for (I=0;I>> 12); AddBits(4); } MakeDecodeTables(BitLength, BD, 0, BC); I=0; while(IInBuf.length-5) UnpReadBuf(false); int number = DecodeNumber(BD); if(number<16) Table[I++]=(byte)((number+UnpOldTable[I]) & 0xf); else if(number==16) { BitField = GetBits(InBuf, InAddr, InBit); N=((BitField >>> 14)+3); AddBits(2); while(N-- > 0 && I>> 13)+3); AddBits(3); } else { BitField = GetBits(InBuf, InAddr, InBit); N=((BitField >>> 9)+11); AddBits(7); } while(N-- > 0 && I=InAddr+5) { if (UnpAudioBlock != 0) { int number = DecodeNumber(MDPtr[CurChannel]); if (number==256) ReadTables(); } else { int number = DecodeNumber(LD); if (number==269) ReadTables(); } } } /** * Modifies the Decode object Dec supplied as parameter * according to the data in LenTab. Initializes Dec for * further use in decompression.

*

     * Global modify set:
     *       
     *
     * Global read set:
     *       
     * 
     * Local use set:
     * (in)  LenTab                     (byte[])
     * (i/o) Dec                        ({@link Decode})
     * (in)  offset                     (int)
     * (in)  Size                       (int)
     *       LenCount                   (final int[16])
     *       TmpPos                     (final int[16])
     *       I                          (int)
     *       M                          (int)
     *       N                          (int)
     * 
*/ private void MakeDecodeTables(/*unsigned char **/ byte[] LenTab, Decode Dec, int offset, int Size) { final /*int*/int[] LenCount = new int[16]; final /*int*/int[] TmpPos = new int[16]; /*int*/int I; /*long*/int M, N; //memset(LenCount,0,sizeof(LenCount)); // Java does this automatically for(I=offset; I0xFFFF) M=0xFFFF; Dec.DecodeLen[I]=(/*unsigned int*/int)M; TmpPos[I]=Dec.DecodePos[I]=((Dec.DecodePos[I-1] & 0xFFFF)+LenCount[I-1]); } for(I=offset; IDecode object.

*

     * Global modify set:
     *       BitField                   (int)
     *       In AddBits:
     *         InAddr                   (int)
     *         InBit                    (int)
     *
     * Local use set:
     * (in)  Deco                       ({@link Decode})
     *       I                          (int)
     *       N                          (int)
     *
     * Call set:
     *       GetBits
     *       AddBits
     * 
* * @return the decoded number...? */ private int DecodeNumber(Decode Deco) { /*unsigned int*/ int I; /*register unsigned int*/ int N; System.out.println("GetBits(" + InBuf + ", " + InAddr + ", " + InBit + ");"); BitField = GetBits(InBuf, InAddr, InBit); N=(BitField & 0xFFFE); System.out.println("(1) N == " + N + " (BitField == " + BitField + ")"); if(N>> (16-I)); System.out.println("(2) N == " + N); if(N >= Deco.MaxNum) N=0; System.out.println("(3) N == " + N); System.out.println("Deco.DecodeNum[" + N + "] == " + Deco.DecodeNum[N]); return Deco.DecodeNum[N]; } /** * Intializes data for the unpack process by setting the variables InAddr and InBit to 0.
* If the archive is a solid archive the method also does the following:
*
    *
  • Set ChannelDelta and CurChannel to 0.
  • *
  • Zero all AudioVariables objects in AudV through {@link AudioVariables#zero}.
  • *
  • Zero the arrays unpBuf and UnpOldTable.
  • *

*

     * Global read set:
     *       NewLhd                     ({@link Struct_NewFileHeader})
     *       LHD_SOLID                  (final int)
     *       MAXWINSIZE                 (final int)
     *
     * Global modify set:
     *       InAddr                     (int)
     *       InBit                      (int)
     *       ChannelDelta               (int)
     *       CurChannel                 (int)
     *       AudV                       ({@link AudioVariables})
     *       
     * Local use set:
     * (in)  unpBuf                     (byte[])
     * 
*/ private void UnpInitData(byte[] unpBuf) { InAddr=InBit=0; if(!((NewLhd.getFlags() & LHD_SOLID) != 0)) { System.out.println("1"); ChannelDelta=CurChannel=0; //memset(AudV,0,sizeof(AudV)); System.out.println("2"); for(AudioVariables av : AudV) av.zero(); //memset(OldDist,0,sizeof(OldDist)); //Util.zero(OldDist); //OldDistPtr=0; //LastDist=LastLength=0; //memset(UnpBuf,0,MAXWINSIZE); System.out.println("3"); Util.zero(unpBuf, 0, MAXWINSIZE); //memset(UnpOldTable,0,sizeof(UnpOldTable)); System.out.println("4"); Util.zero(UnpOldTable); //UnpPtr=WrPtr=0; } } /** * Does some kind of audio decoding that I'm not familiar with conceptually.

*

 
     * Global read set:
     *       CurChannel                 (int)
     *
     * Global modify set:
     *       AudV                       ({@link AudioVariables}[])
     *       ChannelDelta               (int)
     *
     * Local use set:
     * (in)  Delta                      (int)
     *       V                          ({@link AudioVariables})
     *       Ch                         (int)
     *       NumMinDif                  (int)
     *       MinDif                     (int)
     *       PCh                        (int)
     *       I                          (int)
     * 
*/ private /*UBYTE*/ byte DecodeAudio(int Delta) { AudioVariables V; /*unsigned */int Ch; /*unsigned */int NumMinDif,MinDif; int PCh,I; V=AudV[CurChannel]; V.ByteCount++; V.D4=V.D3; V.D3=V.D2; V.D2=V.LastDelta-V.D1; V.D1=V.LastDelta; PCh=8*V.LastChar+V.K1*V.D1+V.K2*V.D2+ V.K3*V.D3+V.K4*V.D4+V.K5*ChannelDelta; PCh=(PCh>>3) & 0xFF; Ch=PCh-Delta; I=((/*signed char*/byte)Delta)<<3; V.Dif[0]+=Math.abs(I); V.Dif[1]+=Math.abs(I-V.D1); V.Dif[2]+=Math.abs(I+V.D1); V.Dif[3]+=Math.abs(I-V.D2); V.Dif[4]+=Math.abs(I+V.D2); V.Dif[5]+=Math.abs(I-V.D3); V.Dif[6]+=Math.abs(I+V.D3); V.Dif[7]+=Math.abs(I-V.D4); V.Dif[8]+=Math.abs(I+V.D4); V.Dif[9]+=Math.abs(I-ChannelDelta); V.Dif[10]+=Math.abs(I+ChannelDelta); ChannelDelta=V.LastDelta=(/*signed char*/byte)(Ch-V.LastChar); V.LastChar=Ch; if((V.ByteCount & 0x1F)==0) { MinDif=V.Dif[0]; NumMinDif=0; V.Dif[0]=0; for (I=1;(/*unsigned */int)I=-16) V.K1--; break; case 2: if(V.K1<16) V.K1++; break; case 3: if(V.K2>=-16) V.K2--; break; case 4: if(V.K2<16) V.K2++; break; case 5: if(V.K3>=-16) V.K3--; break; case 6: if(V.K3<16) V.K3++; break; case 7: if(V.K4>=-16) V.K4--; break; case 8: if(V.K4<16) V.K4++; break; case 9: if(V.K5>=-16) V.K5--; break; case 10: if(V.K5<16) V.K5++; break; } } return((/*UBYTE*/byte)Ch); } /* *************************************************** * ** CRCCrypt Code - decryption engine starts here ** * ***************************************************/ /* #define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n)))) */ /** Rotate left. Pure functional behavior, no side effects. */ private static byte rol(byte value, int shift) { return (byte) (((value)<<(shift)) | ((value)>>>(8*1-(shift)))); } /** @see #rol(byte,int) */ private static short rol(short value, int shift) { return (short)(((value)<<(shift)) | ((value)>>>(8*2-(shift)))); } /** @see #rol(byte,int) */ private static int rol(int value, int shift) { return (((value)<<(shift)) | ((value)>>>(8*4-(shift)))); } /** @see #rol(byte,int) */ private static long rol(long value, int shift) { return (((value)<<(shift)) | ((value)>>>(8*8-(shift)))); } /* #define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n)))) */ /** Rotate right. Pure functional behavior, no side effects. */ private static byte ror(byte value, int shift) { return (byte) (((value)>>>(shift)) | ((value)<<(8*1-(shift)))); } /** @see #ror(byte,int) */ private static short ror(short value, int shift) { return (short)(((value)>>>(shift)) | ((value)<<(8*2-(shift)))); } /** @see #ror(byte,int) */ private static int ror(int value, int shift) { return (((value)>>>(shift)) | ((value)<<(8*4-(shift)))); } /** @see #ror(byte,int) */ private static long ror(long value, int shift) { return (((value)>>>(shift)) | ((value)<<(8*8-(shift)))); } /* #define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \ ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \ ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \ ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) ) */ private int substLong(int t) { return ( ((/*UDWORD*/int)SubstTable[(int)(t>> 0)&255]<< 0) | ((/*UDWORD*/int)SubstTable[(int)(t>> 8)&255]<< 8) | ((/*UDWORD*/int)SubstTable[(int)(t>>16)&255]<<16) | ((/*UDWORD*/int)SubstTable[(int)(t>>24)&255]<<24) ); } // public static final /*UDWORD*/ int[] CRCTab = new int[256]; // Initialized in static constructor public /*UDWORD*/ int[] Key = new int[4]; public void EncryptBlock(/*UBYTE*/byte[] Buf) { //int I; int /*UDWORD*/ A,B,C,D,T,TA,TB; // #ifdef NON_INTEL_BYTE_ORDER if(true) { A = ((0xFF & Buf[0] ) | ((0xFF & Buf[1] )<<8) | ((0xFF & Buf[2] )<<16) | ((0xFF & Buf[3] )<<24))^Key[0]; B = ((0xFF & Buf[4] ) | ((0xFF & Buf[5] )<<8) | ((0xFF & Buf[6] )<<16) | ((0xFF & Buf[7] )<<24))^Key[1]; C = ((0xFF & Buf[8] ) | ((0xFF & Buf[9] )<<8) | ((0xFF & Buf[10])<<16) | ((0xFF & Buf[11])<<24))^Key[2]; D = ((0xFF & Buf[12]) | ((0xFF & Buf[13])<<8) | ((0xFF & Buf[14])<<16) | ((0xFF & Buf[15])<<24))^Key[3]; } else { // The above code should yield the same result as these lines. Test this assumption. A = Util.readIntLE(Buf, 0 )^Key[0]; B = Util.readIntLE(Buf, 4 )^Key[1]; C = Util.readIntLE(Buf, 8 )^Key[2]; D = Util.readIntLE(Buf, 12)^Key[3]; } // #else // UDWORD *BufPtr; // BufPtr=(UDWORD *)Buf; // A=BufPtr[0]^Key[0]; // B=BufPtr[1]^Key[1]; // C=BufPtr[2]^Key[2]; // D=BufPtr[3]^Key[3]; // #endif for(int I=0;I>>8)); Buf[2]=(byte)(0xFF & (C>>>16)); Buf[3]=(byte)(0xFF & (C>>>24)); D ^= Key[1]; Buf[4]=(byte)(0xFF & D); Buf[5]=(byte)(0xFF & (D>>>8)); Buf[6]=(byte)(0xFF & (D>>>16)); Buf[7]=(byte)(0xFF & (D>>>24)); A ^= Key[2]; Buf[8]=(byte)(0xFF & A); Buf[9]=(byte)(0xFF & (A>>>8)); Buf[10]=(byte)(0xFF & (A>>>16)); Buf[11]=(byte)(0xFF & (A>>>24)); B ^= Key[3]; Buf[12]=(byte)(0xFF & B); Buf[13]=(byte)(0xFF & (B>>>8)); Buf[14]=(byte)(0xFF & (B>>>16)); Buf[15]=(byte)(0xFF & (B>>>24)); } else { System.arraycopy(Util.toByteArrayLE(C^Key[0]), 0, Buf, 0, 4); System.arraycopy(Util.toByteArrayLE(D^Key[1]), 4, Buf, 0, 4); System.arraycopy(Util.toByteArrayLE(A^Key[2]), 8, Buf, 0, 4); System.arraycopy(Util.toByteArrayLE(B^Key[3]), 12, Buf, 0, 4); } // #else // BufPtr[0]=C^Key[0]; // BufPtr[1]=D^Key[1]; // BufPtr[2]=A^Key[2]; // BufPtr[3]=B^Key[3]; // #endif UpdKeys(Buf); } /** * Decrypts a 16 byte block in the buffer Buf at position offset. * The decrypted data is stored at the same place in Buf, thus overwriting the * encrypted contents.

*

     * Global read set:
     *
     * Global modify set:
     *       In UpdKeys:
     *         Key                      (final int[4])
     *
     * Local use set:
     * (in)  Buf                        (byte[])
     * (in)  offset                     (int)
     *       InBuf                      (byte[])
     *       A                          (int)
     *       B                          (int)
     *       C                          (int)
     *       D                          (int)
     *       T                          (int)
     *       TA                         (int)
     *       TB                         (int)
     * 
*/ public void DecryptBlock(/*UBYTE*/byte[] Buf, int offset) { //int I; final int n = offset; byte[] /*UBYTE*/ InBuf = new byte[16]; int /*UDWORD*/ A,B,C,D,T,TA,TB; System.arraycopy(Buf, n, InBuf, 0, InBuf.length); // memcpy(InBuf,Buf,sizeof(InBuf)); // Swap all bytes since data is stored in little endian format. // if(true) { A = ((0xFF & Buf[n+0] ) | ((0xFF & Buf[n+1] )<<8) | ((0xFF & Buf[n+2] )<<16) | ((0xFF & Buf[n+3] )<<24))^Key[0]; B = ((0xFF & Buf[n+4] ) | ((0xFF & Buf[n+5] )<<8) | ((0xFF & Buf[n+6] )<<16) | ((0xFF & Buf[n+7] )<<24))^Key[1]; C = ((0xFF & Buf[n+8] ) | ((0xFF & Buf[n+9] )<<8) | ((0xFF & Buf[n+10])<<16) | ((0xFF & Buf[n+11])<<24))^Key[2]; D = ((0xFF & Buf[n+12]) | ((0xFF & Buf[n+13])<<8) | ((0xFF & Buf[n+14])<<16) | ((0xFF & Buf[n+15])<<24))^Key[3]; // } // else { // The above code should yield the same result as these lines. Test this assumption. int A2 = Util.readIntLE(Buf, n+0 )^Key[0]; int B2 = Util.readIntLE(Buf, n+4 )^Key[1]; int C2 = Util.readIntLE(Buf, n+8 )^Key[2]; int D2 = Util.readIntLE(Buf, n+12)^Key[3]; // } if(A != A2 || B != B2 || C != C2 || D != D2) { System.out.println("Assumption broken!"); System.out.println(" A: 0x" + Util.toHexStringBE(A) + " A2: 0x" + Util.toHexStringBE(A2)); System.out.println(" B: 0x" + Util.toHexStringBE(B) + " B2: 0x" + Util.toHexStringBE(B2)); System.out.println(" C: 0x" + Util.toHexStringBE(C) + " C2: 0x" + Util.toHexStringBE(C2)); System.out.println(" D: 0x" + Util.toHexStringBE(D) + " D2: 0x" + Util.toHexStringBE(D2)); } else System.out.println("Assumption correct!"); for(int I=NROUNDS-1; I>=0; I--) { T=((C+rol(D,11))^Key[I&3]); TA=A^substLong(T); T=((D^rol(C,17))+Key[I&3]); TB=B^substLong(T); A=C; B=D; C=TA; D=TB; } if(true) { C ^= Key[0]; Buf[n+0 ]=(byte)(0xFF & C); Buf[n+1 ]=(byte)(0xFF & (C>>>8)); Buf[n+2 ]=(byte)(0xFF & (C>>>16)); Buf[n+3 ]=(byte)(0xFF & (C>>>24)); D ^= Key[1]; Buf[n+4 ]=(byte)(0xFF & D); Buf[n+5 ]=(byte)(0xFF & (D>>>8)); Buf[n+6 ]=(byte)(0xFF & (D>>>16)); Buf[n+7 ]=(byte)(0xFF & (D>>>24)); A ^= Key[2]; Buf[n+8 ]=(byte)(0xFF & A); Buf[n+9 ]=(byte)(0xFF & (A>>>8)); Buf[n+10]=(byte)(0xFF & (A>>>16)); Buf[n+11]=(byte)(0xFF & (A>>>24)); B ^= Key[3]; Buf[n+12]=(byte)(0xFF & B); Buf[n+13]=(byte)(0xFF & (B>>>8)); Buf[n+14]=(byte)(0xFF & (B>>>16)); Buf[n+15]=(byte)(0xFF & (B>>>24)); } else { System.arraycopy(Util.toByteArrayLE(C^Key[0]), 0, Buf, n+0 , 4); System.arraycopy(Util.toByteArrayLE(D^Key[1]), 0, Buf, n+4 , 4); System.arraycopy(Util.toByteArrayLE(A^Key[2]), 0, Buf, n+8 , 4); System.arraycopy(Util.toByteArrayLE(B^Key[3]), 0, Buf, n+12, 4); } UpdKeys(InBuf); } /* * As we can't use unsigned data types in Java, we'll have to unsign the data * every time we use it. Modifications: unsign the usage of Buf[I] by "& 0xFF". */ /** * Updates keys. ;) *
     * Global modify set:
     *       Key                        (int[4])
     * Global read set:
     *       CRCTab                     (int[256])
     * Local use set:
     * (in)  Buf                        (byte[])
     *       I                          (int)
     * 
*/ public void UpdKeys(byte[]/*UBYTE*/ Buf) { for(int I=0; I<16; I+=4) { Key[0]^=CRCTab[Buf[I] & 0xFF]; /* xxx may be I'll rewrite this */ Key[1]^=CRCTab[Buf[I+1] & 0xFF]; /* in asm for speedup */ Key[2]^=CRCTab[Buf[I+2] & 0xFF]; Key[3]^=CRCTab[Buf[I+3] & 0xFF]; } } /* Password is supposed to be trimmed to the actual password length and not zero-terminated. */ /** * Sets crypt keys. ;)
* Password is supposed to be trimmed to the actual * password length and not zero-terminated.

*

     * Global read set:
     *       InitSubstTable             (final short[256])
     *       CRCTab
     *
     * Global modify set:
     *       Key                        (final int[4])
     *       SubstTable                 (final short[256])
     *       In SetOldKeys:
     *         OldKey                   (final short[4])
     *         PN1                      (byte)
     *         PN2                      (byte)
     *         PN3                      (byte)
     *
     * Local use set:
     *       Password                   (byte[])
     *       I                          (int)
     *       J                          (int)
     *       K                          (int)
     *       N1                         (short)
     *       N2                         (short)
     *       Psw                        (final byte[256])
     *       Ch                         (short)
     *
     * Call set:
     *       SetOldKeys
     *       System.arraycopy
     *       EncryptBlock
     * 
*/ public void SetCryptKeys(byte[] Password) { /*unsigned int*/ int I,J,K, PswLength; /*unsigned char*/ short N1,N2; final /*unsigned char*/ byte[] Psw = new byte[256]; /*UBYTE*/ short Ch; SetOldKeys(Password); Key[0]=0xD3A3B879; // Removed the L at the end (indicates 32 bits in C, 64 in Java) Key[1]=0x3F6D12F7; // -||- Key[2]=0x7515A235; // -||- Key[3]=0xA4E7F123; // -||- //memset(Psw,0,sizeof(Psw)); // Arrays are automatically initialized to 0 in Java. System.arraycopy(Password, 0, Psw, 0, (Password.length * Global read set: * CRCTab (final int[256]) * * Global modify set: * OldKey (final short[4]) * PN1 (byte) * PN2 (byte) * PN3 (byte) * * Local use set: * (in) Password (byte[]) * PswCRC (int) * Ch (byte) * * Call set: * //CalcCRC32 * rol * */ private void SetOldKeys(/*char **/byte[] Password) { /*UDWORD*/int PswCRC; /*UBYTE*/byte Ch; crc.reset(); crc.update(Password); PswCRC=(int)crc.getValue();//CalcCRC32(0xFFFFFFFF,/*(UBYTE*)*/Password,0,Util.strlen(Password)); OldKey[0]=(/*UWORD*/short)PswCRC; OldKey[1]=(/*UWORD*/short)(PswCRC>>>16); OldKey[2]=OldKey[3]=0; PN1=PN2=PN3=0; //while ((Ch=*Password)!=0) { for(int i = 0; (Ch=Password[i])!=0; ++i) { PN1+=Ch; PN2^=Ch; PN3+=Ch; PN3=(/*UBYTE*/byte)rol(PN3,1); OldKey[2]^=((/*UWORD*/short)(Ch^CRCTab[Ch])); OldKey[3]+=((/*UWORD*/short)(Ch+(CRCTab[Ch]>>>16))); //Password++; } } /** * Initializes the CRC table crcTab, which has to have a length of 256 elements. * @param crcTab the array where the initialized CRC table is to be stored * @return the same array that was given as input parameter (for convenience) */ static int[] InitCRC(int[] crcTab) { int I, J; /*UDWORD*/int C; for (I=0;I<256;I++) { for (C=I,J=0;J<8;J++) C=(C & 1)!=0 ? (C>>>1)^0xEDB88320 : (C>>>1); crcTab[I]=C; } return crcTab; } /** * Calculates the CRC32 checksum from its arguments. *
     * Global read set:
     *       CRCTab                     ([256])
     *
     * Local use set:
     * (in) StartCRC                   (int)
     * (in)  Addr                       (byte[])
     * (in)  offset                     (int)
     * (in)  Size                       (int)
     *       I                          (int)
     *
     * Purely functional behavior, no side effects.
     * 
* @return the updated sum */ static int CalcCRC32(int StartCRC, byte[] Addr, int offset, int Size) { /*unsigned */int I; for (I=offset; I>> 8); return(StartCRC); } /* No side effects. */ private static void debug_log(String s) { System.err.println("DEBUG: " + s); } /** No side effects (except position in f increasing). */ private static int tread(RARFileEntryStream f, byte[] buffer, int offset, int length) { try { return f.read(buffer, offset, length); } catch(Exception e) { e.printStackTrace(); return -1; } } } /* ************************************************************************** **************************************************************************** **************************************************************************** ************************************************************************** */ /* ************************************************************************** **************************************************************************** **************************************************************************** **************************************************************************** ******* ******* ******* ******* ******* ******* ******* D E B U G F U N C T I O N S ******* ******* ******* ******* ******* ******* ******* **************************************************************************** **************************************************************************** **************************************************************************** ************************************************************************** */ // #ifdef _DEBUG_LOG // /* -- global stuff -------------------------------------------------------- */ // char log_file_name[256]; /* file name for the log file */ // DWORD debug_start_time; /* starttime of debug */ // BOOL debug_started = FALSE; /* debug_log writes only if */ // /* this is TRUE */ // /* ------------------------------------------------------------------------ */ // /* -- global functions ---------------------------------------------------- */ // void debug_init_proc(char *file_name) // /* Create/Rewrite a log file */ // { // FILE *fp; // char date[] = __DATE__; // char time[] = __TIME__; // debug_start_time = GetTickCount(); /* get start time */ // strcpy(log_file_name, file_name); /* save file name */ // if((fp = fopen(log_file_name, CREATETEXT)) != NULL) // { // debug_started = TRUE; /* enable debug */ // fprintf(fp, "Debug log of UniquE's RARFileLib\n"\ // "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n"); // fprintf(fp, "(executable compiled on %s at %s)\n\n", date, time); // fclose(fp); // } // } // void debug_log_proc(char *text, char *sourcefile, int sourceline) // /* add a line to the log file */ // { // FILE *fp; // if(debug_started == FALSE) return; /* exit if not initialized */ // if((fp = fopen(log_file_name, APPENDTEXT)) != NULL) /* append to logfile */ // { // fprintf(fp, " %8u ms (line %u in %s):\n - %s\n", // (/*unsigned */int)(GetTickCount() - debug_start_time), // sourceline, sourcefile, text); // fclose(fp); // } // } // /* ------------------------------------------------------------------------ */ // #endif /* ************************************************************************** **************************************************************************** **************************************************************************** ************************************************************************** */