BITBLIT.ASM 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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. ;** 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 **
  20. ;***************************************************************************
  21. ;* *
  22. ;* Project Name : Westwood 32 bit Library *
  23. ;* *
  24. ;* File Name : BITBLIT.ASM *
  25. ;* *
  26. ;* Programmer : Julio R. Jerez *
  27. ;* *
  28. ;* Start Date : Feb 6, 1995 *
  29. ;* *
  30. ;* *
  31. ;*-------------------------------------------------------------------------*
  32. ;* Functions: *
  33. ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  34. IDEAL
  35. P386
  36. MODEL USE32 FLAT
  37. LOCALS ??
  38. INCLUDE ".\drawbuff.inc"
  39. INCLUDE ".\gbuffer.inc"
  40. CODESEG
  41. PROC Linear_Blit_To_Linear C near
  42. USES ebx,ecx,edx,esi,edi
  43. ;*===================================================================
  44. ;* define the arguements that our function takes.
  45. ;*===================================================================
  46. ARG this_object :DWORD ; this is a member function
  47. ARG dest :DWORD ; what are we blitting to
  48. ARG x_pixel :DWORD ; x pixel position in source
  49. ARG y_pixel :DWORD ; y pixel position in source
  50. ARG dest_x0 :dword
  51. ARG dest_y0 :dword
  52. ARG pixel_width :DWORD ; width of rectangle to blit
  53. ARG pixel_height:DWORD ; height of rectangle to blit
  54. ARG trans :DWORD ; do we deal with transparents?
  55. ;*===================================================================
  56. ; Define some locals so that we can handle things quickly
  57. ;*===================================================================
  58. LOCAL x1_pixel :dword
  59. LOCAL y1_pixel :dword
  60. LOCAL dest_x1 : dword
  61. LOCAL dest_y1 : dword
  62. LOCAL scr_ajust_width:DWORD
  63. LOCAL dest_ajust_width:DWORD
  64. LOCAL source_area : dword
  65. LOCAL dest_area : dword
  66. ;This Clipping algorithm is a derivation of the very well known
  67. ;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency
  68. ;it is probably the most commontly implemented algorithm both in software
  69. ;and hardware for clipping lines, rectangles, and convex polygons against
  70. ;a rectagular clipping window. For reference see
  71. ;"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes
  72. ; pages 113 to 177".
  73. ; Briefly consist in computing the Sutherland code for both end point of
  74. ; the rectangle to find out if the rectangle is:
  75. ; - trivially accepted (no further clipping test, display rectangle)
  76. ; - trivially rejected (return with no action)
  77. ; - retangle must be iteratively clipped again edges of the clipping window
  78. ; and the remaining retangle is display.
  79. ; Clip Source Rectangle against source Window boundaries.
  80. mov esi,[this_object] ; get ptr to src
  81. xor ecx,ecx ; Set sutherland code to zero
  82. xor edx,edx ; Set sutherland code to zero
  83. ; compute the difference in the X axis and get the bit signs into ecx , edx
  84. mov edi,[(GraphicViewPort esi).GVPWidth] ; get width into register
  85. mov ebx,[x_pixel] ; Get first end point x_pixel into register
  86. mov eax,[x_pixel] ; Get second end point x_pixel into register
  87. add ebx,[pixel_width] ; second point x1_pixel = x + width
  88. shld ecx, eax,1 ; the sign bit of x_pixel is sutherland code0 bit4
  89. mov [x1_pixel],ebx ; save second for future use
  90. inc edi ; move the right edge by one unit
  91. shld edx,ebx,1 ; the sign bit of x1_pixel is sutherland code0 bit4
  92. sub eax,edi ; compute the difference x0_pixel - width
  93. sub ebx,edi ; compute the difference x1_pixel - width
  94. shld ecx,eax,1 ; the sign bit of the difference is sutherland code0 bit3
  95. shld edx,ebx,1 ; the sign bit of the difference is sutherland code0 bit3
  96. ; the following code is just a repeticion of the above code
  97. ; in the Y axis.
  98. mov edi,[(GraphicViewPort esi).GVPHeight] ; get height into register
  99. mov ebx,[y_pixel]
  100. mov eax,[y_pixel]
  101. add ebx,[pixel_height]
  102. shld ecx,eax,1
  103. mov [y1_pixel ],ebx
  104. inc edi
  105. shld edx,ebx,1
  106. sub eax,edi
  107. sub ebx,edi
  108. shld ecx,eax,1
  109. shld edx,ebx,1
  110. ; Here we have the to Sutherland code into cl and dl
  111. xor cl,5 ; bit 2 and 0 are complented, reverse then
  112. xor dl,5 ; bit 2 and 0 are complented, reverse then
  113. mov al,cl ; save code1 in case we have to clip iteratively
  114. test dl,cl ; if any bit in code0 and its counter bit
  115. jnz ??real_out ; in code1 is set then the rectangle in outside
  116. or al,dl ; if all bit of code0 the counter bit in
  117. jz ??clip_against_dest ; in code1 is set to zero, then all
  118. ; end points of the rectangle are
  119. ; inside the clipping window
  120. ; if we are here the polygon have to be clip iteratively
  121. test cl,1000b ; if bit 4 in code0 is set then
  122. jz ??scr_left_ok ; x_pixel is smaller than zero
  123. mov [x_pixel],0 ; set x_pixel to cero.
  124. ??scr_left_ok:
  125. test cl,0010b ; if bit 2 in code0 is set then
  126. jz ??scr_bottom_ok ; y_pixel is smaller than zero
  127. mov [ y_pixel ],0 ; set y_pixel to cero.
  128. ??scr_bottom_ok:
  129. test dl,0100b ; if bit 3 in code1 is set then
  130. jz ??scr_right_ok ; x1_pixel is greater than the width
  131. mov eax,[(GraphicViewPort esi).GVPWidth] ; get width into register
  132. mov [ x1_pixel ],eax ; set x1_pixel to width.
  133. ??scr_right_ok:
  134. test dl,0001b ; if bit 0 in code1 is set then
  135. jz ??clip_against_dest ; y1_pixel is greater than the width
  136. mov eax,[(GraphicViewPort esi).GVPHeight] ; get height into register
  137. mov [ y1_pixel ],eax ; set y1_pixel to height.
  138. ; Clip Source Rectangle against destination Window boundaries.
  139. ??clip_against_dest:
  140. ; build the destination rectangle before clipping
  141. ; dest_x1 = dest_x0 + ( x1_pixel - x_pixel )
  142. ; dest_y1 = dest_y0 + ( y1_pixel - y_pixel )
  143. mov eax,[dest_x0] ; get dest_x0 into eax
  144. mov ebx,[dest_y0] ; get dest_y0 into ebx
  145. sub eax,[x_pixel] ; subtract x_pixel from eax
  146. sub ebx,[y_pixel] ; subtract y_pixel from ebx
  147. add eax,[x1_pixel] ; add x1_pixel to eax
  148. add ebx,[y1_pixel] ; add y1_pixel to ebx
  149. mov [dest_x1],eax ; save eax into dest_x1
  150. mov [dest_y1],ebx ; save eax into dest_y1
  151. ; The followin code is a repeticion of the Sutherland clipping
  152. ; descrived above.
  153. mov esi,[dest] ; get ptr to src
  154. xor ecx,ecx
  155. xor edx,edx
  156. mov edi,[(GraphicViewPort esi).GVPWidth] ; get width into register
  157. mov eax,[dest_x0]
  158. mov ebx,[dest_x1]
  159. shld ecx,eax,1
  160. inc edi
  161. shld edx,ebx,1
  162. sub eax,edi
  163. sub ebx,edi
  164. shld ecx,eax,1
  165. shld edx,ebx,1
  166. mov edi,[( GraphicViewPort esi) . GVPHeight ] ; get height into register
  167. mov eax,[dest_y0]
  168. mov ebx,[dest_y1]
  169. shld ecx,eax,1
  170. inc edi
  171. shld edx,ebx,1
  172. sub eax,edi
  173. sub ebx,edi
  174. shld ecx,eax,1
  175. shld edx,ebx,1
  176. xor cl,5
  177. xor dl,5
  178. mov al,cl
  179. test dl,cl
  180. jnz ??real_out
  181. or al,dl
  182. jz ??do_blit
  183. test cl,1000b
  184. jz ??dest_left_ok
  185. mov eax,[ dest_x0 ]
  186. mov [ dest_x0 ],0
  187. sub [ x_pixel ],eax
  188. ??dest_left_ok:
  189. test cl,0010b
  190. jz ??dest_bottom_ok
  191. mov eax,[ dest_y0 ]
  192. mov [ dest_y0 ],0
  193. sub [ y_pixel ],eax
  194. ??dest_bottom_ok:
  195. test dl,0100b
  196. jz ??dest_right_ok
  197. mov ebx,[ (GraphicViewPort esi) . GVPWidth ] ; get width into register
  198. mov eax,[ dest_x1 ]
  199. mov [ dest_x1 ],ebx
  200. sub eax,ebx
  201. sub [ x1_pixel ],eax
  202. ??dest_right_ok:
  203. test dl,0001b
  204. jz ??do_blit
  205. mov ebx,[ (GraphicViewPort esi) . GVPHeight ] ; get width into register
  206. mov eax,[ dest_y1 ]
  207. mov [ dest_y1 ],ebx
  208. sub eax,ebx
  209. sub [ y1_pixel ],eax
  210. ; Here is where we do the actual blit
  211. ??do_blit:
  212. cld
  213. mov ebx,[this_object]
  214. mov esi,[(GraphicViewPort ebx).GVPOffset]
  215. mov eax,[(GraphicViewPort ebx).GVPXAdd]
  216. add eax,[(GraphicViewPort ebx).GVPWidth]
  217. add eax,[(GraphicViewPort ebx).GVPPitch]
  218. mov ecx,eax
  219. mul [y_pixel]
  220. add esi,[x_pixel]
  221. mov [source_area],ecx
  222. add esi,eax
  223. add ecx,[x_pixel ]
  224. sub ecx,[x1_pixel ]
  225. mov [scr_ajust_width ],ecx
  226. mov ebx,[dest]
  227. mov edi,[(GraphicViewPort ebx).GVPOffset]
  228. mov eax,[(GraphicViewPort ebx).GVPXAdd]
  229. add eax,[(GraphicViewPort ebx).GVPWidth]
  230. add eax,[(GraphicViewPort ebx).GVPPitch]
  231. mov ecx,eax
  232. mul [ dest_y0 ]
  233. add edi,[ dest_x0 ]
  234. mov [ dest_area ],ecx
  235. add edi,eax
  236. mov eax,[ dest_x1 ]
  237. sub eax,[ dest_x0 ]
  238. jle ??real_out
  239. sub ecx,eax
  240. mov [ dest_ajust_width ],ecx
  241. mov edx,[ dest_y1 ]
  242. sub edx,[ dest_y0 ]
  243. jle ??real_out
  244. cmp esi,edi
  245. jz ??real_out
  246. jl ??backupward_blit
  247. ; ********************************************************************
  248. ; Forward bitblit
  249. test [ trans ],1
  250. jnz ??forward_Blit_trans
  251. ; the inner loop is so efficient that
  252. ; the optimal consept no longer apply because
  253. ; the optimal byte have to by a number greather than 9 bytes
  254. cmp eax,10
  255. jl ??forward_loop_bytes
  256. ??forward_loop_dword:
  257. mov ecx,edi
  258. mov ebx,eax
  259. neg ecx
  260. and ecx,3
  261. sub ebx,ecx
  262. rep movsb
  263. mov ecx,ebx
  264. shr ecx,2
  265. rep movsd
  266. mov ecx,ebx
  267. and ecx,3
  268. rep movsb
  269. add esi,[ scr_ajust_width ]
  270. add edi,[ dest_ajust_width ]
  271. dec edx
  272. jnz ??forward_loop_dword
  273. ret
  274. ??forward_loop_bytes:
  275. mov ecx,eax
  276. rep movsb
  277. add esi,[ scr_ajust_width ]
  278. add edi,[ dest_ajust_width ]
  279. dec edx
  280. jnz ??forward_loop_bytes
  281. ret
  282. ??forward_Blit_trans:
  283. mov ecx,eax
  284. and ecx,01fh
  285. lea ecx,[ ecx + ecx * 4 ]
  286. neg ecx
  287. shr eax,5
  288. lea ecx,[ ??transp_reference + ecx * 2 ]
  289. mov [ y1_pixel ],ecx
  290. ??forward_loop_trans:
  291. mov ecx,eax
  292. jmp [ y1_pixel ]
  293. ??forward_trans_line:
  294. REPT 32
  295. local transp_pixel
  296. mov bl,[ esi ]
  297. test bl,bl
  298. jz transp_pixel
  299. mov [ edi ],bl
  300. transp_pixel:
  301. inc esi
  302. inc edi
  303. ENDM
  304. ??transp_reference:
  305. dec ecx
  306. jge ??forward_trans_line
  307. add esi,[ scr_ajust_width ]
  308. add edi,[ dest_ajust_width ]
  309. dec edx
  310. jnz ??forward_loop_trans
  311. ret
  312. ; ************************************************************************
  313. ; backward bitblit
  314. ??backupward_blit:
  315. mov ebx,[ source_area ]
  316. dec edx
  317. add esi,eax
  318. imul ebx,edx
  319. std
  320. lea esi,[ esi + ebx - 1 ]
  321. mov ebx,[ dest_area ]
  322. add edi,eax
  323. imul ebx,edx
  324. lea edi,[ edi + ebx - 1]
  325. test [ trans ],1
  326. jnz ??backward_Blit_trans
  327. cmp eax,15
  328. jl ??backward_loop_bytes
  329. ??backward_loop_dword:
  330. push edi
  331. push esi
  332. lea ecx,[edi+1]
  333. mov ebx,eax
  334. and ecx,3 ; Get non aligned bytes.
  335. sub ebx,ecx ; remove that from the total size to be copied later.
  336. rep movsb ; do the copy.
  337. sub esi,3
  338. mov ecx,ebx ; Get number of bytes left.
  339. sub edi,3
  340. shr ecx,2 ; Do 4 bytes at a time.
  341. rep movsd ; do the dword copy.
  342. mov ecx,ebx
  343. add esi,3
  344. add edi,3
  345. and ecx,03h
  346. rep movsb ; finnish the remaining bytes.
  347. pop esi
  348. pop edi
  349. sub esi,[ source_area ]
  350. sub edi,[ dest_area ]
  351. dec edx
  352. jge ??backward_loop_dword
  353. cld
  354. ret
  355. ??backward_loop_bytes:
  356. push edi
  357. mov ecx,eax ; remove that from the total size to be copied later.
  358. push esi
  359. rep movsb ; do the copy.
  360. pop esi
  361. pop edi
  362. sub esi,[ source_area ]
  363. sub edi,[ dest_area ]
  364. dec edx
  365. jge ??backward_loop_bytes
  366. cld
  367. ret
  368. ??backward_Blit_trans:
  369. mov ecx,eax
  370. and ecx,01fh
  371. lea ecx,[ ecx + ecx * 4 ]
  372. neg ecx
  373. shr eax,5
  374. lea ecx,[ ??back_transp_reference + ecx * 2 ]
  375. mov [ y1_pixel ],ecx
  376. ??backward_loop_trans:
  377. mov ecx,eax
  378. push edi
  379. push esi
  380. jmp [ y1_pixel ]
  381. ??backward_trans_line:
  382. REPT 32
  383. local transp_pixel
  384. mov bl,[ esi ]
  385. test bl,bl
  386. jz transp_pixel
  387. mov [ edi ],bl
  388. transp_pixel:
  389. dec esi
  390. dec edi
  391. ENDM
  392. ??back_transp_reference:
  393. dec ecx
  394. jge ??backward_trans_line
  395. pop esi
  396. pop edi
  397. sub esi,[ source_area ]
  398. sub edi,[ dest_area ]
  399. dec edx
  400. jge ??backward_loop_trans
  401. cld
  402. ret
  403. ??real_out:
  404. ret
  405. ENDP Linear_Blit_To_Linear
  406. END