00001
00002
00003
00004
00005
00006 #include "pp_.h"
00007
00008
00009 const char PP_ID[] = "PP20";
00010
00011 const udword PP_BITS_FAST = 0x09090909;
00012 const udword PP_BITS_MEDIOCRE = 0x090a0a0a;
00013 const udword PP_BITS_GOOD = 0x090a0b0b;
00014 const udword PP_BITS_VERYGOOD = 0x090a0c0c;
00015 const udword PP_BITS_BEST = 0x090a0c0d;
00016
00017 const char text_packeddatacorrupt[] = "PowerPacker: Packed data is corrupt";
00018 const char text_unrecognized[] = "PowerPacker: Unrecognized compression method";
00019 const char text_unknownformat[] = "Not compressed with PowerPacker";
00020 const char text_notenoughmemory[] = "Not enough free memory";
00021 const char text_fast[] = "PowerPacker: fast compression";
00022 const char text_mediocre[] = "PowerPacker: mediocre compression";
00023 const char text_good[] = "PowerPacker: good compression";
00024 const char text_verygood[] = "PowerPacker: very good compression";
00025 const char text_best[] = "PowerPacker: best compression";
00026
00027 const char* ppErrorString;
00028
00029 extern udword ppUncompressedLen();
00030
00031 static void ppfreemem();
00032 inline udword ppread( int );
00033 inline void ppbytes();
00034 inline void ppsequence();
00035 inline void bytestodword();
00036
00037 static ubyte* sourcebuf;
00038 static ubyte* readptr;
00039 static ubyte* writeptr;
00040 static ubyte* startptr;
00041 static udword current;
00042 static int bits;
00043 static ubyte efficiency[4];
00044 static udword outputlen;
00045 static char globalerror;
00046
00047
00048
00049
00050
00051
00052 #if 0 //ALFRED - TODO
00053 int depp( ifstream& source, ubyte** destRef )
00054 {
00055 ppErrorString = text_unknownformat;
00056 globalerror = FALSE;
00057 outputlen = 0;
00058
00059
00060 source.seekg(0,ios::beg);
00061 char sig[5];
00062 source.read(sig,4);
00063 sig[4] = 0;
00064 if ( strcmp(sig,PP_ID) != 0 )
00065 {
00066 return FALSE;
00067 }
00068
00069
00070 source.read(efficiency,4);
00071 udword eff = readEndian(efficiency[0],efficiency[1],efficiency[2],efficiency[3]);
00072 if (( eff != PP_BITS_FAST ) &&
00073 ( eff != PP_BITS_MEDIOCRE ) &&
00074 ( eff != PP_BITS_GOOD ) &&
00075 ( eff != PP_BITS_VERYGOOD ) &&
00076 ( eff != PP_BITS_BEST ))
00077 {
00078 ppErrorString = text_unrecognized;
00079 return (-1);
00080 }
00081
00082
00083 source.seekg( 0, ios::end );
00084 #if defined(__POWERPC__)
00085 udword inputlen = (source.seekg(0,ios::end)).offset();
00086 #else
00087 udword inputlen = (udword)source.tellg();
00088 #endif
00089 source.seekg( 0, ios::beg );
00090
00091
00092 #if defined(_Windows) && !defined(__WIN32__)
00093 if (( sourcebuf = (ubyte *)GlobalAllocPtr ( GPTR, inputlen )) == 0 ) {
00094 ppErrorString = text_notenoughmemory;
00095 return(-1);
00096 }
00097 #else
00098 if (( sourcebuf = new ubyte[inputlen]) == 0 ) {
00099 ppErrorString = text_notenoughmemory;
00100 return(-1);
00101 }
00102 #endif
00103
00104 #if defined(__BORLANDC__) && !defined(__WIN32__)
00105
00106
00107 #endif
00108 udword restfilelen = inputlen;
00109 while ( restfilelen > INT_MAX ) {
00110 source.read( (ubyte*)sourcebuf + (inputlen - restfilelen), INT_MAX );
00111 restfilelen -= INT_MAX;
00112 }
00113 if ( restfilelen > 0 )
00114 source.read( (ubyte*)sourcebuf + (inputlen - restfilelen), restfilelen );
00115
00116
00117 source.seekg( 0, ios::beg );
00118
00119
00120 readptr = sourcebuf + inputlen -4;
00121
00122
00123 outputlen = readEndian(0,*readptr,*(readptr+1),*(readptr+2));
00124
00125
00126 if ( *destRef != 0 )
00127 {
00128 delete[] *destRef;
00129 }
00130
00131 #if defined(_Windows) && !defined(__WIN32__)
00132 if (( *destRef = (ubyte *)GlobalAllocPtr ( GPTR, outputlen )) == 0 )
00133 {
00134 ppErrorString = text_notenoughmemory;
00135 return(-1);
00136 }
00137 #else
00138 if (( *destRef = new ubyte[outputlen]) == 0 )
00139 {
00140 ppErrorString = text_notenoughmemory;
00141 return(-1);
00142 }
00143 #endif
00144
00145 switch ( eff) {
00146 case PP_BITS_FAST:
00147 ppErrorString = text_fast;
00148 break;
00149 case PP_BITS_MEDIOCRE:
00150 ppErrorString = text_mediocre;
00151 break;
00152 case PP_BITS_GOOD:
00153 ppErrorString = text_good;
00154 break;
00155 case PP_BITS_VERYGOOD:
00156 ppErrorString = text_verygood;
00157 break;
00158 case PP_BITS_BEST:
00159 ppErrorString = text_best;
00160 break;
00161 }
00162
00163
00164 writeptr = *destRef + outputlen;
00165
00166 startptr = *destRef;
00167
00168
00169
00170 bits = 32 - *(sourcebuf + inputlen -1);
00171
00172
00173
00174 bytestodword();
00175
00176 if ( bits != 32 )
00177 current = ( current >> ( 32 - bits ));
00178
00179 do {
00180 if ( ppread( 1) == 0 )
00181 ppbytes();
00182 if ( writeptr > *destRef )
00183 ppsequence();
00184 if ( globalerror ) {
00185 ppfreemem();
00186 return(-1);
00187 }
00188 } while ( writeptr > *destRef );
00189
00190 ppfreemem();
00191 return TRUE;
00192 }
00193 #endif //ALFRED - TODO
00194
00195
00196 void ppfreemem() {
00197 #if defined(_Windows) && !defined(__WIN32__)
00198 if ( sourcebuf != 0 )
00199 GlobalFreePtr ( sourcebuf );
00200 sourcebuf = 0;
00201 #else
00202 if ( sourcebuf != 0 )
00203 delete[] sourcebuf;
00204 sourcebuf = 0;
00205 #endif
00206 }
00207
00208
00209 udword ppUncompressedLen() {
00210 return(outputlen);
00211 }
00212
00213
00214 inline udword ppread( int count ) {
00215 udword data = 0;
00216
00217 for ( ; count > 0; count-- ) {
00218
00219 data += data;
00220
00221 data = ( data | (current & 1) );
00222 current = ( current >> 1 );
00223 if ( (--bits) == 0 ) {
00224 bytestodword();
00225 bits = 32;
00226 }
00227 }
00228 return data;
00229 }
00230
00231
00232 inline void ppbytes() {
00233 udword count, add;
00234 count = ( add = ppread( 2 ) );
00235 while ( add == 3 ) {
00236 add = ppread( 2);
00237 count += add;
00238 }
00239 count++;
00240 if ( writeptr > startptr ) {
00241 for ( ; count > 0 ; count-- )
00242 *(--writeptr) = (ubyte)ppread( 8 );
00243 }
00244 }
00245
00246
00247 inline void ppsequence() {
00248 udword offset, length, add;
00249 int offsetbitlen;
00250 length = ppread( 2 );
00251 offsetbitlen = (int)efficiency[length];
00252 length += 2;
00253 if ( length != 5 )
00254 offset = ppread( offsetbitlen );
00255 else {
00256 if ( ppread( 1 ) == 0 )
00257 offsetbitlen = 7;
00258 offset = ppread( offsetbitlen );
00259 add = ppread( 3 );
00260 length += add;
00261 while ( add == 7 ) {
00262 add = ppread(3);
00263 length += add;
00264 }
00265 }
00266 if ( writeptr > startptr ) {
00267 for ( ; length > 0 ; length-- ) {
00268 --writeptr;
00269 *writeptr = *(writeptr + 1 + offset);
00270 }
00271 }
00272 }
00273
00274
00275 inline void bytestodword() {
00276 readptr -= 4;
00277 if ( readptr < sourcebuf ) {
00278 ppErrorString = text_packeddatacorrupt;
00279 globalerror = TRUE;
00280 }
00281 else
00282 current = readEndian(*readptr,*(readptr+1),*(readptr+2),*(readptr+3));
00283 }