LCWCOMP.ASM 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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. ; $Header: F:\projects\c&c0\vcs\code\lcwcomp.asv 5.0 11 Nov 1996 09:40:34 JOE_BOSTIC $
  19. ;***************************************************************************
  20. ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
  21. ;***************************************************************************
  22. ;* *
  23. ;* Project Name : Library routine *
  24. ;* *
  25. ;* File Name : COMPRESS.ASM *
  26. ;* *
  27. ;* Programmer : Louis Castle *
  28. ;* *
  29. ;* Last Update : 20 August, 1990 [CY] *
  30. ;* *
  31. ;*-------------------------------------------------------------------------*
  32. ;* Functions: *
  33. ;* *
  34. ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  35. IDEAL
  36. P386
  37. MODEL USE32 FLAT
  38. GLOBAL C LCW_Comp :NEAR
  39. CODESEG
  40. ; ----------------------------------------------------------------
  41. ;
  42. ; Here are prototypes for the routines defined within this module:
  43. ;
  44. ; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);
  45. ;
  46. ; ----------------------------------------------------------------
  47. ;***********************************************************
  48. ;
  49. ; ULONG LCW_Compress(BYTE *source, BYTE *dest, ULONG length)
  50. ;
  51. ; returns the size of the compressed data in bytes
  52. ;
  53. ;*
  54. PROC LCW_Comp C near
  55. USES ebx,ecx,edx,edi,esi
  56. ARG source:DWORD
  57. ARG dest:DWORD
  58. ARG datasize:DWORD
  59. LOCAL inlen:DWORD
  60. LOCAL a1stdest:DWORD
  61. LOCAL a1stsrc:DWORD
  62. LOCAL lenoff:DWORD
  63. LOCAL ndest:DWORD
  64. LOCAL count:DWORD
  65. LOCAL matchoff:DWORD
  66. LOCAL end_of_data:DWORD
  67. cld
  68. mov edi,[dest]
  69. mov esi,[source]
  70. mov edx,[datasize] ; get length of data to compress
  71. ; mov ax,ds
  72. ; mov es,ax
  73. ;
  74. ; compress data to the following codes in the format b = byte, w = word
  75. ; n = byte code pulled from compressed data
  76. ; Bit field of n command description
  77. ; n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3
  78. ; n=10xxxxxx,n1,n2,...,nx+1 med length copy the next x+1 bytes
  79. ; n=11xxxxxx,w1 med run run x+3 bytes from offset w1
  80. ; n=11111111,w1,w2 long run run w1 bytes from offset w2
  81. ; n=10000000 end end of data reached
  82. ;
  83. cld ; make sure all string commands are forward
  84. mov ebx,esi
  85. add ebx,edx
  86. mov [end_of_data],ebx
  87. mov [inlen],1 ; set the in-length flag
  88. mov [a1stdest],edi ; save original dest offset for size calc
  89. mov [a1stsrc],esi ; save offset of first byte of data
  90. mov [lenoff],edi ; save the offset of the legth of this len
  91. sub eax,eax
  92. mov al,081h ; the first byte is always a len
  93. stosb ; write out a len of 1
  94. lodsb ; get the byte
  95. stosb ; save it
  96. ??loop:
  97. mov [ndest],edi ; save offset of compressed data
  98. mov edi,[a1stsrc] ; get the offset to the first byte of data
  99. mov [count],1 ; set the count of run to 0
  100. ??searchloop:
  101. sub eax,eax
  102. mov al,[esi] ; get the current byte of data
  103. cmp al,[esi+64]
  104. jne short ??notrunlength
  105. mov ebx,edi
  106. mov edi,esi
  107. mov ecx,[end_of_data]
  108. sub ecx,edi
  109. repe scasb
  110. dec edi
  111. mov ecx,edi
  112. sub ecx,esi
  113. cmp ecx,65
  114. jb short ??notlongenough
  115. mov [DWORD PTR inlen],0 ; clear the in-length flag
  116. mov esi,edi
  117. mov edi,[ndest] ; get the offset of our compressed data
  118. mov ah,al
  119. mov al,0FEh
  120. stosb
  121. xchg ecx,eax
  122. stosw
  123. mov al,ch
  124. stosb
  125. mov [ndest],edi ; save offset of compressed data
  126. mov edi,ebx
  127. jmp ??searchloop
  128. ??notlongenough:
  129. mov edi,ebx
  130. ??notrunlength:
  131. ??oploop:
  132. mov ecx,esi ; get the address of the last byte +1
  133. sub ecx,edi ; get the total number of bytes left to comp
  134. jz short ??searchdone
  135. repne scasb ; look for a match
  136. jne short ??searchdone ; if we don't find one we're done
  137. mov ebx,[count]
  138. mov ah,[esi+ebx-1]
  139. cmp ah,[edi+ebx-2]
  140. jne ??oploop
  141. mov edx,esi ; save this spot for the next search
  142. mov ebx,edi ; save this spot for the length calc
  143. dec edi ; back up one for compare
  144. mov ecx,[end_of_data] ; get the end of data
  145. sub ecx,esi ; sub current source for max len
  146. repe cmpsb ; see how many bytes match
  147. ; start of change MH 9-24-91
  148. jne short ??notend ; if found mismatch then di - bx = match count
  149. inc edi ; else cx = 0 and di + 1 - bx = match count
  150. ??notend:
  151. ; end of change MH 9-24-91
  152. mov esi,edx ; restore si
  153. mov eax,edi ; get the dest
  154. sub eax,ebx ; sub the start for total bytes that match
  155. mov edi,ebx ; restore dest
  156. cmp eax,[count] ; see if its better than before
  157. jb ??searchloop ; if not keep looking
  158. mov [count],eax ; if so keep the count
  159. dec ebx ; back it up for the actual match offset
  160. mov [matchoff],ebx ; save the offset for later
  161. jmp ??searchloop ; loop until we searched it all
  162. ??searchdone:
  163. mov ecx,[count] ; get the count of the longest run
  164. mov edi,[ndest] ; get the offset of our compressed data
  165. cmp ecx,2 ; see if its not enough run to matter
  166. jbe short ??lenin ; if its 0,1, or 2 its too small
  167. cmp ecx,10 ; if not, see if it would fit in a short
  168. ja short ??medrun ; if not, see if its a medium run
  169. mov eax,esi ; if its short get the current address
  170. sub eax,[matchoff] ; sub the offset of the match
  171. cmp eax,0FFFh ; if its less than 12 bits its a short
  172. ja short ??medrun ; if its not, its a medium
  173. ??shortrun:
  174. sub ebx,ebx
  175. mov bl,cl ; get the length (3-10)
  176. sub bl,3 ; sub 3 for a 3 bit number 0-7
  177. shl bl,4 ; shift it left 4
  178. add ah,bl ; add in the length for the high nibble
  179. xchg ah,al ; reverse the bytes for a word store
  180. jmp short ??srunnxt ; do the run fixup code
  181. ??medrun:
  182. cmp ecx,64 ; see if its a short run
  183. ja short ??longrun ; if not, oh well at least its long
  184. sub cl,3 ; back down 3 to keep it in 6 bits
  185. or cl,0C0h ; the highest bits are always on
  186. mov al,cl ; put it in al for the stosb
  187. stosb ; store it
  188. jmp short ??medrunnxt ; do the run fixup code
  189. ??lenin:
  190. cmp [DWORD PTR inlen],0 ; is it doing a length?
  191. jnz short ??len ; if so, skip code
  192. ??lenin1:
  193. mov [lenoff],edi ; save the length code offset
  194. mov al,80h ; set the length to 0
  195. stosb ; save it
  196. ??len:
  197. mov ebx,[lenoff] ; get the offset of the length code
  198. cmp [BYTE PTR ebx],0BFh ; see if its maxed out
  199. je ??lenin1 ; if so put out a new len code
  200. ??stolen:
  201. inc [BYTE PTR ebx] ; inc the count code
  202. lodsb ; get the byte
  203. stosb ; store it
  204. mov [DWORD PTR inlen],1 ; we are now in a length so save it
  205. jmp short ??nxt ; do the next code
  206. ??longrun:
  207. mov al,0ffh ; its a long so set a code of FF
  208. stosb ; store it
  209. mov eax,[count] ; send out the count
  210. stosw ; store it
  211. ??medrunnxt:
  212. mov eax,[matchoff] ; get the offset
  213. sub eax,[a1stsrc] ; make it relative tot he start of data
  214. ??srunnxt:
  215. stosw ; store it
  216. ; this code common to all runs
  217. add esi,[count] ; add in the length of the run to the source
  218. mov [DWORD PTR inlen],0 ; set the in leght flag to false
  219. ;=======================================================================
  220. ??nxt:
  221. cmp esi,[end_of_data] ; see if we did the whole pic
  222. jae short ??out ; if so, cool! were done
  223. jmp ??loop
  224. ??out:
  225. mov ax,080h ; remember to send an end of data code
  226. stosb ; store it
  227. mov eax,edi ; get the last compressed address
  228. sub eax,[a1stdest] ; sub the first for the compressed size
  229. ret
  230. ENDP LCW_Comp
  231. END
  232.