LCWCOMP.ASM 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. ;* lcwcomp.asm
  26. ;*
  27. ;* DESCRIPTION
  28. ;* LCW compression code. (32-Bit protected mode)
  29. ;*
  30. ;* PROGRAMMER
  31. ;* Louis Castle
  32. ;* Denzil E. Long, Jr.
  33. ;*
  34. ;* DATE
  35. ;* January 26, 1995
  36. ;*
  37. ;*---------------------------------------------------------------------------
  38. ;*
  39. ;* PUBLIC
  40. ;* LCW_Compress - LCW compress a buffer of memory.
  41. ;*
  42. ;****************************************************************************
  43. IDEAL
  44. P386
  45. MODEL USE32 FLAT
  46. LOCALS ??
  47. CODESEG
  48. ;****************************************************************************
  49. ;*
  50. ;* NAME
  51. ;* LCW_Compress - LCW compress a buffer of memory.
  52. ;*
  53. ;* SYNOPSIS
  54. ;* Size = LCW_Compress(Source, Dest, Length)
  55. ;*
  56. ;* long LCW_Compress(void *, void *, long);
  57. ;*
  58. ;* FUNCTION
  59. ;*
  60. ;* INPUTS
  61. ;* Source - Pointer to data to compress.
  62. ;* Dest - Pointer to buffer to put compressed data.
  63. ;* Length - Length in bytes of data to compress.
  64. ;*
  65. ;* RESULT
  66. ;* Size - Size in bytes of compresed data.
  67. ;*
  68. ;****************************************************************************
  69. GLOBAL C LCW_Compress:NEAR
  70. PROC LCW_Compress C NEAR USES ebx ecx edx esi edi
  71. ARG source:DWORD
  72. ARG dest:DWORD
  73. ARG datasize:DWORD
  74. LOCAL inlen:DWORD
  75. LOCAL a1stdest:DWORD
  76. LOCAL a1stsrc:DWORD
  77. LOCAL lenoff:DWORD
  78. LOCAL ndest:DWORD
  79. LOCAL count:DWORD
  80. LOCAL matchoff:DWORD
  81. LOCAL end_of_data:DWORD
  82. mov esi,[source]
  83. mov edi,[dest]
  84. mov edx,[datasize]
  85. cld ;Forward direction
  86. mov ebx,esi
  87. add ebx,edx
  88. mov [end_of_data],ebx ;Save end of source address
  89. mov [inlen],1 ;Set the in-length flag
  90. mov [a1stdest],edi ;Save original dest
  91. mov [a1stsrc],esi ;Save original source
  92. mov [lenoff],edi ;Save offset length
  93. mov al,081h ;First byte is always a len
  94. stosb ;Write out a len of 1
  95. lodsb ;Get the byte
  96. stosb ;Save it
  97. ??loop:
  98. mov [ndest],edi ;Save offset of compressed data
  99. mov edi,[a1stsrc] ;Get address of first byte
  100. mov [count],1 ;Set the count of run to 0
  101. ??searchloop:
  102. sub eax,eax
  103. mov al,[esi] ;Get the current byte of data
  104. cmp al,[esi + 64]
  105. jne short ??notrunlength
  106. mov ebx,edi
  107. mov edi,esi
  108. mov ecx,[end_of_data]
  109. sub ecx,edi
  110. repe scasb
  111. dec edi
  112. mov ecx,edi
  113. sub ecx,esi
  114. cmp ecx,65
  115. jb short ??notlongenough
  116. mov [inlen],0 ;Clear the in-length flag
  117. mov esi,edi
  118. mov edi,[ndest]
  119. mov ah,al
  120. mov al,0FEh
  121. stosb
  122. xchg ecx,eax
  123. stosw
  124. mov al,ch
  125. stosb
  126. mov [ndest],edi ;Save offset of compressed data
  127. mov edi,ebx
  128. jmp ??searchloop
  129. ??notlongenough:
  130. mov edi,ebx
  131. ??notrunlength:
  132. ??oploop:
  133. mov ecx,esi ;Address of the last byte +1
  134. sub ecx,edi ;Total number of bytes left
  135. jz short ??searchdone
  136. repne scasb ;Look for a match
  137. jne short ??searchdone ;If we don't find one we're done
  138. mov ebx,[count]
  139. mov ah,[esi+ebx-1]
  140. cmp ah,[edi+ebx-2]
  141. jne ??oploop
  142. mov edx,esi ;Save address for the next search
  143. mov ebx,edi ;Save address for the length calc
  144. dec edi ;Back up one for compare
  145. mov ecx,[end_of_data] ;Get the end of data
  146. sub ecx,esi ;Sub current source for max len
  147. repe cmpsb ;See how many bytes match
  148. jne short ??notend
  149. inc edi
  150. ??notend:
  151. mov esi,edx
  152. mov eax,edi ;Get the dest
  153. sub eax,ebx ;Sub the start for total bytes that match
  154. mov edi,ebx ;Restore dest
  155. cmp eax,[count] ;See if its better than before
  156. jb ??searchloop ;If not keep looking
  157. mov [count],eax ;If so keep the count
  158. dec ebx ;Back it up for the actual match offset
  159. mov [matchoff],ebx ;Save the offset for later
  160. jmp ??searchloop ;Loop until we searched it all
  161. ??searchdone:
  162. mov ecx,[count] ;Get the count of the longest run
  163. mov edi,[ndest] ;Get the paragraph of our compressed data
  164. cmp ecx,2 ;See if its not enough run to matter
  165. jbe short ??lenin ;If its 0,1, or 2 its too small
  166. cmp ecx,10 ;If not, see if it would fit in a short
  167. ja short ??medrun ;If not, see if its a medium run
  168. mov eax,esi ;If its short get the current address
  169. sub eax,[matchoff] ;Sub the offset of the match
  170. cmp eax,0FFFh ;If its less than 12 bits its a short
  171. ja short ??medrun ;If its not, its a medium
  172. ??shortrun:
  173. mov bl,cl ;Get the length (3-10)
  174. sub bl,3 ;Sub 3 for a 3 bit number 0-7
  175. shl bl,4
  176. add ah,bl
  177. xchg ah,al
  178. jmp short ??srunnxt ;Do the run fixup code
  179. ??medrun:
  180. cmp ecx,64 ;See if its a short run
  181. ja short ??longrun ;If not, oh well at least its long
  182. sub cl,3 ;Back down 3 to keep it in 6 bits
  183. or cl,0C0h ;The highest bits are always on
  184. mov al,cl ;Put it in al for the stosb
  185. stosb ;Store it
  186. jmp short ??medrunnxt ;Do the run fixup code
  187. ??lenin:
  188. cmp [inlen],0 ;Is it doing a length?
  189. jnz short ??len ;If so, skip code
  190. ??lenin1:
  191. mov [lenoff],edi ;Save the length code offset
  192. mov al,80h ;Set the length to 0
  193. stosb ;Save it
  194. ??len:
  195. mov ebx,[lenoff] ;Get the offset of the length code
  196. cmp [BYTE PTR ebx],0BFh ;See if its maxed out
  197. je ??lenin1 ;If so put out a new len code
  198. ??stolen:
  199. inc [BYTE PTR ebx] ;Inc the count code
  200. lodsb ;Get the byte
  201. stosb ;Store it
  202. mov [inlen],1 ;We are now in a length so save it
  203. jmp short ??nxt ;Do the next code
  204. ??longrun:
  205. mov al,0FFh ;Its a long so set a code of FF
  206. stosb ;Store it
  207. mov eax,[count] ;Send out the count
  208. stosw ;Store it
  209. ??medrunnxt:
  210. mov eax,[matchoff] ;Get the offset
  211. sub eax,[a1stsrc] ;Make it relative tot he start of data
  212. ??srunnxt:
  213. stosw ;Store it
  214. add esi,[count] ;Add in the length of the run to the source
  215. mov [inlen],0 ;Set the in leght flag to false
  216. ??nxt:
  217. cmp esi,[end_of_data] ;See if we did the whole pic
  218. jae short ??out ;If so, cool! were done
  219. jmp ??loop
  220. ??out:
  221. mov eax,080h ;Remember to send an end of data code
  222. stosb ;Store it
  223. mov eax,edi ;Get the last compressed address
  224. sub eax,[a1stdest] ;Sub the first for the compressed size
  225. ret
  226. ENDP LCW_Compress
  227. END