Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

pp_.cpp

Go to the documentation of this file.
00001 //
00002 // /home/ms/sidplay/libsidplay/fformat/RCS/pp_.cpp,v
00003 //
00004 // For more info get ``depp.cpp'' and ``ppcl.cpp''.
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(); // return the length of the uncompressed data
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;       // compressed data longword
00042 static int bits;             // number of bits in 'current' to evaluate
00043 static ubyte efficiency[4];
00044 static udword outputlen;
00045 static char globalerror;
00046 
00047 
00048 // returns: FALSE = file is not in (supported) PowerPacker format
00049 //          TRUE = successful return           
00050 //          (-1) = error during decompression
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         // Check for header signature
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         // Read in efficiency table.
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   // move file pointer to end of file
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   // allocate memory for input file
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   // for 16-bit segmented Windows we would have to change this
00106   // to be able to load beyond the 64KB segment boundaries
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   // reset file pointer
00117   source.seekg( 0, ios::beg );
00118 
00119   // backwards decompression
00120   readptr = sourcebuf + inputlen -4;
00121 
00122   // uncompressed length in bits 31-8 of last dword
00123   outputlen = readEndian(0,*readptr,*(readptr+1),*(readptr+2));
00124 
00125   // Free any previously existing destination buffer.
00126   if ( *destRef != 0 )
00127   {
00128         delete[] *destRef;
00129   }
00130   // Allocate memory for output data.
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   // put destptr to end of uncompressed data
00164   writeptr = *destRef + outputlen;
00165   // lowest dest. address for range-checks
00166   startptr = *destRef;
00167 
00168   // read number of unused bits in 1st data dword
00169   // from lowest bits 7-0 of last dword
00170   bits = 32 - *(sourcebuf + inputlen -1);
00171 
00172   // decompress data
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   // read 'count' bits of packed data
00217   for ( ; count > 0; count-- )  {
00218         // equal to shift left
00219         data += data;
00220         // merge bit 0
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 );       // length -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 // moves four bytes to Motorola big-endian double-word
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 }

Generated on Tue Feb 8 04:13:59 2005 for Esidplay by doxygen 1.3.3