lzdecomp.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. //--------------------------------------------------------------------------
  2. // LZ Decompress Routine
  3. //
  4. //---------------------------------------------------------------------------//
  5. // Copyright (C) Microsoft Corporation. All rights reserved. //
  6. //===========================================================================//
  7. //---------------------------------------------------------------------------
  8. // Static Globals
  9. #define HASH_CLEAR 256 //clear hash table command code
  10. #define HASH_EOF 257 //End Of Data command code
  11. #define HASH_FREE 258 //First Hash Table Chain Offset Value
  12. #define BASE_BITS 9
  13. #define MAX_BIT_INDEX (1 << BASE_BITS)
  14. #define NO_RAM_FOR_LZ_DECOMP 0xCBCB0002
  15. #ifndef NULL
  16. #define NULL 0
  17. #endif
  18. typedef unsigned char* MemoryPtr;
  19. struct HashStruct
  20. {
  21. unsigned short Chain;
  22. unsigned char Suffix;
  23. };
  24. typedef HashStruct *HashStructPtr;
  25. HashStructPtr LZOldChain = NULL; //Old Chain Value Found
  26. HashStructPtr LZChain = NULL; //Current Chain Value Found
  27. unsigned long LZMaxIndex = 0; //Max index value in Hash Table
  28. unsigned long LZCodeMask = 0;
  29. unsigned long LZFreeIndex = 0; //Current Free index into Hash Table
  30. MemoryPtr LZSrcBufEnd = NULL; //ptr to 3rd from last byte in src buffer
  31. MemoryPtr LZOrigDOSBuf = NULL; //original offset to start of src buffer
  32. char LZHashBuffer[16384];
  33. char LZOldSuffix = 0; //Current Suffix Value found
  34. //-----------------------------
  35. //-------------------------------------------------------------------------------
  36. // LZ DeCompress Routine
  37. // Takes a pointer to dest buffer, a pointer to source buffer and len of source.
  38. // returns length of decompressed image.
  39. long LZDecomp (MemoryPtr dest, MemoryPtr src, unsigned long srcLen)
  40. {
  41. long result = 0;
  42. __asm
  43. {
  44. mov esi,src
  45. mov ebx,srcLen
  46. mov edi,dest
  47. xor eax,eax
  48. xor ecx,ecx // CH and CL used
  49. lea ebx,[ebx+esi-3]
  50. mov LZOldChain,eax
  51. mov LZSrcBufEnd,ebx
  52. mov LZChain,eax
  53. mov LZMaxIndex,eax
  54. mov LZCodeMask,eax
  55. mov LZFreeIndex,eax
  56. mov LZCodeMask,MAX_BIT_INDEX-1
  57. mov LZMaxIndex,MAX_BIT_INDEX //max index for 9 bits == 512
  58. mov LZFreeIndex,HASH_FREE //set index to 258
  59. mov LZOldSuffix,al
  60. mov ch,BASE_BITS
  61. jmp GetCode
  62. //--------------------------------------------------------------------------
  63. //
  64. // ClearHash restarts decompression assuming that it is starting from the
  65. // beginning
  66. //
  67. //--------------------------------------------------------------------------
  68. ClearHash:
  69. mov ch,BASE_BITS //set up for nine bit codes
  70. mov LZCodeMask,MAX_BIT_INDEX-1
  71. mov LZMaxIndex,MAX_BIT_INDEX //max index for 9 bits == 512
  72. mov LZFreeIndex,HASH_FREE //set index to 258
  73. cmp esi,LZSrcBufEnd
  74. ja error
  75. mov eax,[esi+0]
  76. xor ebx,ebx
  77. shr eax,cl
  78. add cl,ch
  79. mov edx,LZCodeMask
  80. mov bl,cl
  81. and cl,07h
  82. shr ebx,3
  83. and eax,edx
  84. add esi,ebx
  85. nop
  86. mov LZOldChain,eax //previous Chain Offset.
  87. mov LZOldSuffix,al
  88. mov [edi],al
  89. inc edi
  90. //-------------------------------------------------------------------------
  91. // ReadCode gets the next hash code (9 BITS) from LZDOSBuff
  92. // this WILL ReadFile more data if the buffer is empty
  93. //-------------------------------------------------------------------------
  94. GetCode:
  95. cmp esi,LZSrcBufEnd
  96. ja error // Read Passed End?
  97. mov eax,[esi+0]
  98. xor ebx,ebx
  99. shr eax,cl
  100. add cl,ch
  101. mov edx,LZCodeMask
  102. mov bl,cl
  103. and cl,07h
  104. shr ebx,3
  105. and eax,edx
  106. add esi,ebx
  107. nop
  108. cmp eax,HASH_EOF
  109. je eof
  110. cmp eax,HASH_CLEAR //are we to clear out hash table?
  111. je ClearHash
  112. //---------------------------------------------------------------------------
  113. //
  114. // Handle Chain acts on two types of Codes, A previously tabled one and a new
  115. // one. On a previously tabled one, the chain value and suffix for that code
  116. // are preserved into OldSuffix and OldChain. The block operates on searching
  117. // backward in the chains until a chain offset of 0-255 is found (meaning the
  118. // terminal character has been reached.) Each character in the chain is saved
  119. // on the stack.
  120. //
  121. //---------------------------------------------------------------------------
  122. //HandleChain:
  123. mov edx,esp
  124. dec esp
  125. mov LZChain,eax //Save new chain as well
  126. lea ebx, [LZHashBuffer+eax+eax*2]
  127. cmp eax,LZFreeIndex //is code in HASH TABLE already?
  128. jl InTable //if yes, then process chain
  129. mov al,LZOldSuffix //get back the old suffix and plant it
  130. mov [esp],al //onto the stack for processing later
  131. dec esp
  132. mov [ebx+2],al
  133. mov eax,LZOldChain //get Old chain for creation of Old Chain
  134. mov [ebx],ax
  135. lea ebx, [LZHashBuffer+eax+eax*2]
  136. InTable:
  137. test ah,ah //(ax<255) is current chain a character?
  138. jz ChainEnd //if yes, then begin Print out
  139. mov al,[ebx+2] //push suffix onto stack
  140. mov [esp],al //onto the stack for processing later
  141. dec esp
  142. movzx eax,word ptr [ebx] //get chain to this code
  143. lea ebx, [LZHashBuffer+eax+eax*2]
  144. jmp InTable //and keep filling up
  145. ChainEnd:
  146. mov LZOldSuffix,al //save last character in chain
  147. mov [esp],al //onto the stack for processing later
  148. sub edx,esp
  149. mov ebx,LZFreeIndex //get new code number index
  150. send_bytes:
  151. mov al,[esp]
  152. inc esp
  153. mov [edi],al
  154. inc edi
  155. dec edx
  156. jnz send_bytes
  157. //---------------------------------------------------------------------------
  158. //
  159. // Here we add another chain to the hash table so that we continually use it
  160. // for more decompressions.
  161. //
  162. //---------------------------------------------------------------------------
  163. mov al,LZOldSuffix
  164. mov edx,LZOldChain
  165. mov byte ptr [LZHashBuffer+ebx+ebx*2+2],al
  166. mov word ptr [LZHashBuffer+ebx+ebx*2],dx
  167. inc ebx
  168. mov eax,LZChain
  169. mov LZFreeIndex,ebx
  170. mov edx,LZMaxIndex
  171. mov LZOldChain,eax
  172. cmp ebx,edx
  173. jl GetCode
  174. cmp ch,12
  175. je GetCode
  176. inc ch
  177. mov ebx,LZCodeMask
  178. mov eax,LZMaxIndex
  179. add ebx,ebx
  180. add eax,eax
  181. or ebx,1
  182. mov LZMaxIndex,eax
  183. mov LZCodeMask,ebx
  184. jmp GetCode
  185. error:
  186. eof:
  187. sub edi,dest
  188. mov result,edi
  189. }
  190. return(result);
  191. }