LCWUNCMP.ASM 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. ;
  2. ; Command & Conquer Red Alert(tm)
  3. ; Copyright 2025 Electronic Arts Inc.
  4. ;
  5. ; This program is free software: you can redistribute it and/or modify
  6. ; it under the terms of the GNU General Public License as published by
  7. ; the Free Software Foundation, either version 3 of the License, or
  8. ; (at your option) any later version.
  9. ;
  10. ; This program is distributed in the hope that it will be useful,
  11. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ; GNU General Public License for more details.
  14. ;
  15. ; You should have received a copy of the GNU General Public License
  16. ; along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. ;
  18. ;****************************************************************************
  19. ;*
  20. ;* C O N F I D E N T I A L -- W E S T W O O D S T U D I O S
  21. ;*
  22. ;*---------------------------------------------------------------------------
  23. ;*
  24. ;* FILE
  25. ;* lcwuncmp.asm
  26. ;*
  27. ;* DESCRIPTION
  28. ;* LCW uncompress routine. (32-Bit protected mode)
  29. ;*
  30. ;* PROGRAMMER
  31. ;* Chris Yates
  32. ;* Denzil E. Long, Jr.
  33. ;*
  34. ;* DATE
  35. ;* January 26, 1995
  36. ;*
  37. ;*---------------------------------------------------------------------------
  38. ;*
  39. ;* PUBLIC
  40. ;* LCW_Uncompress - Uncompress LCW encoded data.
  41. ;*
  42. ;****************************************************************************
  43. IDEAL
  44. P386
  45. MODEL USE32 FLAT
  46. LOCALS ??
  47. CODESEG
  48. ;****************************************************************************
  49. ;*
  50. ;* NAME
  51. ;* LCW_Uncompress - Uncompress LCW encoded data.
  52. ;*
  53. ;* SYNOPSIS
  54. ;* Size = LCW_Uncompress(Source, Dest, Length)
  55. ;*
  56. ;* LONG LCW_Uncompress(void *, void *, long);
  57. ;*
  58. ;* FUNCTION
  59. ;* Uncompress data to the following codes in the format b = byte,
  60. ;* w = word, n = byte code pulled from compressed data.
  61. ;*
  62. ;* Bit field of n Command Description
  63. ;* ------------------------------------------------------------------
  64. ;* n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3
  65. ;* n=10xxxxxx,n1,n2,..,nx+1 med length copy the next x+1 bytes
  66. ;* n=11xxxxxx,w1 med run run x+3 bytes from offset w1
  67. ;* n=11111111,w1,w2 long copy copy w1 bytes from offset w2
  68. ;* n=11111110,w1,b1 long run run byte b1 for w1 bytes
  69. ;* n=10000000 end end of data reached
  70. ;*
  71. ;* INPUTS
  72. ;* Source - Pointer to LCW encoded data.
  73. ;* Dest - Pointer to buffer to uncompress into.
  74. ;* Length -
  75. ;*
  76. ;* RESULT
  77. ;* Size - Size of uncompressed data in bytes.
  78. ;*
  79. ;****************************************************************************
  80. GLOBAL C LCW_Uncompress:NEAR
  81. PROC LCW_Uncompress C NEAR USES ebx ecx edx esi edi
  82. ARG source:DWORD
  83. ARG dest:DWORD
  84. ARG length:DWORD
  85. LOCAL a1stdest:DWORD
  86. LOCAL maxlen:DWORD
  87. LOCAL lastbyte:DWORD
  88. LOCAL lastcom:DWORD
  89. LOCAL lastcom1:DWORD
  90. mov esi,[source] ;ESI - Source address
  91. mov edi,[dest] ;EDI - Destination address
  92. mov edx,[length] ;EDX - Maximum length
  93. mov [a1stdest],edi ;Save dest address
  94. add edx,edi ;Last address (Dest + length)
  95. mov [lastbyte],edx
  96. cld ;Forward direction
  97. mov ebx,esi ;Save source address
  98. ??loop:
  99. ; Exit if no bytes are remaining.
  100. mov eax,[lastbyte]
  101. sub eax,edi
  102. jz short ??out
  103. mov [maxlen],eax ;Save for string commands
  104. mov esi,ebx ;Restore source address
  105. lodsb
  106. or al,al ;See if its a short run
  107. js short ??notshort
  108. mov ah,al ;Put rel offset high nibble in ah
  109. and ah,0Fh ; Only 4 bits count
  110. sub ecx,ecx
  111. mov ch,al ;Put count nibble in ch
  112. shr ch,4
  113. mov cl,ch
  114. xor ch,ch
  115. add ecx,3 ;Get actual run length
  116. cmp ecx,[maxlen] ;Is it too big to fit?
  117. jbe short ??rsok ;If not, its ok
  118. mov ecx,[maxlen] ;If so, max it out so it dosen't overrun
  119. ??rsok:
  120. lodsb ;Get rel offset low byte
  121. mov ebx,esi ;Save the source address
  122. mov esi,edi ;Get the current dest
  123. sub esi,eax ;Get relative offset
  124. rep movsb
  125. jmp ??loop
  126. ??notshort:
  127. test al,40h ;Is it a length?
  128. jne short ??notlength ;If not it could be med or long run
  129. ; If end code then exit.
  130. cmp al,80h
  131. je short ??out
  132. mov cl,al ;Put the byte in count register
  133. and ecx,3Fh ;Mask off the extra bits
  134. cmp ecx,[maxlen] ;Is it too big to fit?
  135. jbe short ??lenok ;If not, its ok
  136. mov ecx,[maxlen] ;If so, max it out so it dosen't overrun
  137. ??lenok:
  138. rep movsb
  139. mov ebx,esi ;Save the source offset
  140. jmp ??loop
  141. ??out:
  142. mov eax,edi
  143. sub eax,[a1stdest]
  144. jmp short ??exit
  145. ??notlength:
  146. mov cl,al ;Get the entire code
  147. and ecx,3Fh ;Mask off all but the size -3
  148. add ecx,3 ;Add 3 for byte count
  149. cmp al,0FEh
  150. jne short ??notrunlength
  151. sub eax,eax
  152. lodsw
  153. mov ecx,eax
  154. sub eax,eax
  155. lodsb
  156. mov ebx,esi ;Save the source offset
  157. cmp ecx,[maxlen] ;Is it too big to fit?
  158. jbe short ??runlenok ;If not, its ok
  159. mov ecx,[maxlen] ;If so, max it out so it dosen't overrun
  160. ??runlenok:
  161. rep stosb
  162. jmp ??loop
  163. ??notrunlength:
  164. cmp al,0FFh ;Is it a long run?
  165. jne short ??notlong ;If not use the code as the size
  166. sub eax,eax
  167. lodsw ;If so, get the size
  168. mov ecx,eax ;Put int the count byte
  169. ??notlong:
  170. lodsw ;Get the rel index
  171. mov ebx,esi ;Save the source offset
  172. add eax,[a1stdest] ;Add in the first index
  173. mov esi,eax ;Use this as a source
  174. cmp ecx,[maxlen] ;Is it too big to fit?
  175. jbe short ??runok ;If not, its ok
  176. mov ecx,[maxlen] ;If so, max it out so it dosen't overrun
  177. ??runok:
  178. rep movsb
  179. jmp ??loop
  180. ??exit:
  181. mov eax,edi
  182. mov ebx,[dest]
  183. sub eax,ebx ;Calculate bytes uncompressed.
  184. ret
  185. ENDP LCW_Uncompress
  186. END