extract.cpp
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:7k
源码类别:

其他游戏

开发平台:

Visual C++

  1. #include <windows.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include "zlib.h"
  6. #include "explode.h"
  7. #include "mpq.h"
  8. #include "wave.h"
  9. #include "huffman.h"
  10. static DECOMPRESS_TABLE dcmp_table[] = {
  11. {0x08, libmpq_pkzip_decompress}, /* Decompression with Pkware Data Compression Library */
  12. {0x02, libmpq_zlib_decompress}, /* Decompression with the "zlib" library */
  13. {0x01, libmpq_huff_decompress}, /* Huffmann decompression */
  14. {0x80, libmpq_wave_decompress_stereo}, /* WAVE decompression for stereo waves */
  15. {0x40, libmpq_wave_decompress_mono} /* WAVE decompression for mono waves */
  16. };
  17. static unsigned int libmpq_pkzip_read_input_data(char *buf, unsigned int *size, void *param) {
  18. pkzip_data *info = (pkzip_data *)param;
  19. unsigned int max_avail = (info->in_bytes - info->in_pos);
  20. unsigned int to_read = *size;
  21. /* Check the case when not enough data available */
  22. if (to_read > max_avail) {
  23. to_read = max_avail;
  24. }
  25. /* Load data and increment offsets */
  26. memcpy(buf, info->in_buf + info->in_pos, to_read);
  27. info->in_pos += to_read;
  28. return to_read;
  29. }
  30. /*
  31.  *  Support functions for PKWARE data compression library.
  32.  *
  33.  *  Function for store output data. Used by mpq_pkzip "implode" and
  34.  *  "explode" as user-defined callback.
  35.  *
  36.  *  char * buf          - Pointer to data to be written
  37.  *  unsigned int * size - Number of bytes to write
  38.  *  void * param        - Custom pointer, parameter of implode/explode
  39.  */
  40. static void libmpq_pkzip_write_output_data(char *buf, unsigned int *size, void *param) {
  41. pkzip_data *info = (pkzip_data *)param;
  42. unsigned int max_write = (info->max_out - info->out_pos);
  43. unsigned int to_write = *size;
  44. /* Check the case when not enough space in the output buffer */
  45. if (to_write > max_write) {
  46. to_write = max_write;
  47. }
  48. /* Write output data and increments offsets */
  49. memcpy(info->out_buf + info->out_pos, buf, to_write);
  50. info->out_pos += to_write;
  51. }
  52. int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
  53. pkzip_data info; /* Data information */
  54. char *work_buf = (char*)malloc(LIBMPQ_PKZIP_EXP_BUFFER_SIZE); /* mpq_pkzip work buffer */
  55. /* Fill data information structure */
  56. info.in_buf   = in_buf;
  57. info.in_pos   = 0;
  58. info.in_bytes = in_length;
  59. info.out_buf  = out_buf;
  60. info.out_pos  = 0;
  61. info.max_out  = *out_length;
  62. /* Do the decompression */
  63. libmpq_pkzip_explode(libmpq_pkzip_read_input_data, libmpq_pkzip_write_output_data, work_buf, &info);
  64. *out_length = info.out_pos;
  65. free(work_buf);
  66. return 0;
  67. }
  68. int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length) {
  69. *out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 1);
  70. return 1;
  71. }
  72. int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length) {
  73. *out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 2);
  74. return 1;
  75. }
  76. int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
  77. z_stream z; /* Stream information for zlib */
  78. int result;
  79. /* Fill the stream structure for zlib */
  80. z.next_in   = (Bytef *)in_buf;
  81. z.avail_in  = (uInt)in_length;
  82. z.total_in  = in_length;
  83. z.next_out  = (Bytef *)out_buf;
  84. z.avail_out = *out_length;
  85. z.total_out = 0;
  86. z.zalloc    = NULL;
  87. z.zfree     = NULL;
  88. /* Initialize the decompression structure. Storm.dll uses zlib version 1.1.3 */
  89. if ((result = inflateInit(&z)) == 0) {
  90. /* Call zlib to decompress the data */
  91. result = inflate(&z, Z_FINISH);
  92. *out_length = z.total_out;
  93. inflateEnd(&z);
  94. }
  95. return result;
  96. }
  97. /*
  98.  *  Huffmann decompression routine. The in_length parameter is not used, but needs
  99.  *  to be specified due to compatibility reasons.
  100.  *
  101.  *  1500F5F0
  102.  */
  103. int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
  104. struct huffman_tree *ht = (huffman_tree*)malloc(sizeof(struct huffman_tree));
  105. struct huffman_input_stream *is = (huffman_input_stream *)malloc(sizeof(struct huffman_input_stream));
  106. struct huffman_tree_item *hi = (huffman_tree_item *)malloc(sizeof(struct huffman_tree_item));
  107. memset(ht, 0, sizeof(struct huffman_tree));
  108. memset(is, 0, sizeof(struct huffman_input_stream));
  109. memset(hi, 0, sizeof(struct huffman_tree_item));
  110. /* Initialize input stream */
  111. is->bit_buf  = *(unsigned long *)in_buf;
  112. in_buf      += sizeof(unsigned long);
  113. is->in_buf   = (unsigned char *)in_buf;
  114. is->bits     = 32;
  115. /* Initialize the Huffmann tree for decompression */
  116. libmpq_huff_init_tree(ht, hi, LIBMPQ_HUFF_DECOMPRESS);
  117. *out_length = libmpq_huff_do_decompress(ht, is, (unsigned char *)out_buf, *out_length);
  118. free(hi);
  119. free(is);
  120. free(ht);
  121. return 0;
  122. }
  123. int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length) {
  124. char *temp_buf = NULL; /* Temporary storage for decompressed data */
  125. char *work_buf = NULL; /* Where to store decompressed data */
  126. int out_length = *pout_length; /* For storage number of output bytes */
  127. unsigned fDecompressions1; /* Decompressions applied to the block */
  128. unsigned fDecompressions2; /* Just another copy of decompressions applied to the block */
  129. int count = 0; /* Counter for every use */
  130. int entries = (sizeof(dcmp_table) / sizeof(DECOMPRESS_TABLE));
  131. int i;
  132. /* If the input length is the same as output, do nothing. */
  133. if (in_length == out_length) {
  134. if (in_buf == out_buf) {
  135. return 1;
  136. }
  137. memcpy(out_buf, in_buf, in_length);
  138. return 1;
  139. }
  140. /* Get applied compression types and decrement data length */
  141. fDecompressions1 = fDecompressions2 = (unsigned char)*in_buf++;
  142. in_length--;
  143. /* Search decompression table type and get all types of compression */
  144. for (i = 0; i < entries; i++) {
  145. /* We have to apply this decompression? */
  146. if (fDecompressions1 & dcmp_table[i].mask) {
  147. count++;
  148. }
  149. /* Clear this flag from temporary variable. */
  150. fDecompressions2 &= ~dcmp_table[i].mask;
  151. }
  152. /*
  153.  *  Check if there is some method unhandled
  154.  *  (E.g. compressed by future versions)
  155.  */
  156. if (fDecompressions2 != 0) 
  157. {
  158. printf("Unknown Compressionn");
  159. return 0;
  160. }
  161. /* If there is more than only one compression, we have to allocate extra buffer */
  162. if (count >= 2) {
  163. temp_buf = (char*)malloc(out_length);
  164. }
  165. /* Apply all decompressions */
  166. for (i = 0, count = 0; i < entries; i++) {
  167. /* If not used this kind of compression, skip the loop */
  168. if (fDecompressions1 & dcmp_table[i].mask) {
  169. /* If odd case, use target buffer for output, otherwise use allocated tempbuf */
  170. work_buf = (count++ & 1) ? temp_buf : out_buf;
  171. out_length = *pout_length;
  172. /* Decompress buffer using corresponding function */
  173. dcmp_table[i].decompress(work_buf, &out_length, in_buf, in_length);
  174. /* Move output length to src length for next compression */
  175. in_length = out_length;
  176. in_buf = work_buf;
  177. }
  178. }
  179. /* If output buffer is not the same like target buffer, we have to copy data */
  180. if (work_buf != out_buf) {
  181. memcpy(out_buf, in_buf, out_length);
  182. }
  183. *pout_length = out_length;
  184. /* Delete temporary buffer, if necessary */
  185. if (temp_buf != NULL) {
  186. free(temp_buf);
  187. }
  188. return 1;
  189. }