ArchiveFile.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #include "ArchiveFile.h"
  2. ArchiveFile::ArchiveFile( const Ogre::String& file ):
  3. File( file )
  4. {
  5. Extract();
  6. }
  7. ArchiveFile::ArchiveFile(File* file, const u32& offset, const u32& length ):
  8. File( file, offset, length )
  9. {
  10. Extract();
  11. }
  12. ArchiveFile::ArchiveFile( u8* buffer, const u32& offset, const u32& length ):
  13. File( buffer, offset, length )
  14. {
  15. Extract();
  16. }
  17. ArchiveFile::ArchiveFile( File *file ):
  18. File( file )
  19. {
  20. Extract();
  21. }
  22. ArchiveFile::~ArchiveFile()
  23. {
  24. }
  25. void
  26. ArchiveFile::Extract()
  27. {
  28. u16 circle_size = 4096;
  29. u16 F = 18;
  30. u8 circle_buffer[ 4096 ];
  31. int r = 0;
  32. for( u16 i = 0; i < circle_size - F; ++i )
  33. {
  34. circle_buffer[ i ] = 0;
  35. }
  36. r = circle_size - F;
  37. // current position in mBuffer (compressed)
  38. u32 comp_position = 0;
  39. u32 decomp_length = GetU32LE( comp_position );
  40. comp_position += 0x04;
  41. u8 *decomp_buffer = ( u8* )malloc( sizeof( u8 ) * decomp_length );
  42. // current position in decomp_buffer
  43. u32 decomp_position = 0;
  44. // decompression
  45. while( decomp_position < decomp_length )
  46. {
  47. // Control byte
  48. u8 control_byte = GetU8( comp_position++ );
  49. for( u8 shift = 0; shift < 8; ++shift )
  50. {
  51. if( ( control_byte & ( 1 << shift ) ) == 0 )
  52. {
  53. // not compressed
  54. // copy byte in circle burrer and in decomp_buffer
  55. u8 temp = GetU8( comp_position++ );
  56. decomp_buffer[ decomp_position++ ] = temp;
  57. circle_buffer[ r++ ] = temp;
  58. r &= circle_size - 1;
  59. }
  60. else
  61. {
  62. // compressed
  63. // get 2 bytes
  64. u8 reference1 = GetU8( comp_position++ );
  65. u8 reference2 = GetU8( comp_position++ );
  66. // offset for circle_buffer
  67. u16 reference_offset = reference1 | ( ( reference2 & 0x0f ) << 8 );
  68. // length are always lesser than real by 3
  69. u8 reference_length = ( ( reference2 & 0xf0 ) >> 4 ) + 3;
  70. // copy bytes
  71. for( int i = 0; i < reference_length; ++i )
  72. {
  73. u8 temp = circle_buffer[ ( r - reference_offset ) & ( circle_size - 1 ) ];
  74. decomp_buffer[ decomp_position++ ] = temp;
  75. circle_buffer[ r++ ] = temp;
  76. r &= circle_size - 1;
  77. }
  78. }
  79. }
  80. }
  81. free( m_Buffer );
  82. m_Buffer = decomp_buffer;
  83. m_BufferSize = decomp_length;
  84. }