DRAWLINE.ASM 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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 : DRAWLINE.ASM *
  25. ;* *
  26. ;* Programmer : Phil W. Gorrow *
  27. ;* *
  28. ;* Start Date : June 16, 1994 *
  29. ;* *
  30. ;* Last Update : August 30, 1994 [IML] *
  31. ;* *
  32. ;*-------------------------------------------------------------------------*
  33. ;* Functions: *
  34. ;* VVC::Scale -- Scales a virtual viewport to another virtual viewport *
  35. ;* Normal_Draw -- jump loc for drawing scaled line of normal pixel *
  36. ;* __DRAW_LINE -- Assembly routine to draw a line *
  37. ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  38. IDEAL
  39. P386
  40. MODEL USE32 FLAT
  41. INCLUDE ".\drawbuff.inc"
  42. INCLUDE ".\gbuffer.inc"
  43. CODESEG
  44. ;***************************************************************************
  45. ;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *
  46. ;* *
  47. ;* INPUT: WORD sx_pixel - the starting x pixel position *
  48. ;* WORD sy_pixel - the starting y pixel position *
  49. ;* WORD dx_pixel - the destination x pixel position *
  50. ;* WORD dy_pixel - the destination y pixel position *
  51. ;* WORD color - the color of the line to draw *
  52. ;* *
  53. ;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel *
  54. ;* with the graphic viewport it has been assigned to. *
  55. ;* *
  56. ;* HISTORY: *
  57. ;* 06/16/1994 PWG : Created. *
  58. ;* 08/30/1994 IML : Fixed clipping bug. *
  59. ;*=========================================================================*
  60. PROC Buffer_Draw_Line C NEAR
  61. USES eax,ebx,ecx,edx,esi,edi
  62. ;*==================================================================
  63. ;* Define the arguements that the function takes.
  64. ;*==================================================================
  65. ARG this_object:DWORD ; associated graphic view port
  66. ARG x1_pixel:DWORD ; the start x pixel position
  67. ARG y1_pixel:DWORD ; the start y pixel position
  68. ARG x2_pixel:DWORD ; the dest x pixel position
  69. ARG y2_pixel:DWORD ; the dest y pixel position
  70. ARG color:DWORD ; the color we are drawing
  71. ;*==================================================================
  72. ;* Define the local variables that we will use on the stack
  73. ;*==================================================================
  74. LOCAL clip_min_x:DWORD
  75. LOCAL clip_max_x:DWORD
  76. LOCAL clip_min_y:DWORD
  77. LOCAL clip_max_y:DWORD
  78. LOCAL clip_var:DWORD
  79. LOCAL accum:DWORD
  80. LOCAL bpr:DWORD
  81. ;*==================================================================
  82. ;* Take care of find the clip minimum and maximums
  83. ;*==================================================================
  84. mov ebx,[this_object]
  85. xor eax,eax
  86. mov [clip_min_x],eax
  87. mov [clip_min_y],eax
  88. mov eax,[(GraphicViewPort ebx).GVPWidth]
  89. mov [clip_max_x],eax
  90. add eax,[(GraphicViewPort ebx).GVPXAdd]
  91. add eax,[(GraphicViewPort ebx).GVPPitch]
  92. mov [bpr],eax
  93. mov eax,[(GraphicViewPort ebx).GVPHeight]
  94. mov [clip_max_y],eax
  95. ;*==================================================================
  96. ;* Adjust max pixels as they are tested inclusively.
  97. ;*==================================================================
  98. dec [clip_max_x]
  99. dec [clip_max_y]
  100. ;*==================================================================
  101. ;* Set the registers with the data for drawing the line
  102. ;*==================================================================
  103. mov eax,[x1_pixel] ; eax = start x pixel position
  104. mov ebx,[y1_pixel] ; ebx = start y pixel position
  105. mov ecx,[x2_pixel] ; ecx = dest x pixel position
  106. mov edx,[y2_pixel] ; edx = dest y pixel position
  107. ;*==================================================================
  108. ;* This is the section that "pushes" the line into bounds.
  109. ;* I have marked the section with PORTABLE start and end to signify
  110. ;* how much of this routine is 100% portable between graphics modes.
  111. ;* It was just as easy to have variables as it would be for constants
  112. ;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used
  113. ;* to clip the line (default is the screen)
  114. ;* PORTABLE start
  115. ;*==================================================================
  116. cmp eax,[clip_min_x]
  117. jl short ??clip_it
  118. cmp eax,[clip_max_x]
  119. jg short ??clip_it
  120. cmp ebx,[clip_min_y]
  121. jl short ??clip_it
  122. cmp ebx,[clip_max_y]
  123. jg short ??clip_it
  124. cmp ecx,[clip_min_x]
  125. jl short ??clip_it
  126. cmp ecx,[clip_max_x]
  127. jg short ??clip_it
  128. cmp edx,[clip_min_y]
  129. jl short ??clip_it
  130. cmp edx,[clip_max_y]
  131. jle short ??on_screen
  132. ;*==================================================================
  133. ;* Takes care off clipping the line.
  134. ;*==================================================================
  135. ??clip_it:
  136. call NEAR PTR ??set_bits
  137. xchg eax,ecx
  138. xchg ebx,edx
  139. mov edi,esi
  140. call NEAR PTR ??set_bits
  141. mov [clip_var],edi
  142. or [clip_var],esi
  143. jz short ??on_screen
  144. test edi,esi
  145. jne short ??off_screen
  146. shl esi,2
  147. call [DWORD PTR cs:??clip_tbl+esi]
  148. jc ??clip_it
  149. xchg eax,ecx
  150. xchg ebx,edx
  151. shl edi,2
  152. call [DWORD PTR cs:??clip_tbl+edi]
  153. jmp ??clip_it
  154. ??on_screen:
  155. jmp ??draw_it
  156. ??off_screen:
  157. jmp ??out
  158. ;*==================================================================
  159. ;* Jump table for clipping conditions
  160. ;*==================================================================
  161. ??clip_tbl DD ??nada,??a_up,??a_dwn,??nada
  162. DD ??a_lft,??a_lft,??a_dwn,??nada
  163. DD ??a_rgt,??a_up,??a_rgt,??nada
  164. DD ??nada,??nada,??nada,??nada
  165. ??nada:
  166. clc
  167. retn
  168. ??a_up:
  169. mov esi,[clip_min_y]
  170. call NEAR PTR ??clip_vert
  171. stc
  172. retn
  173. ??a_dwn:
  174. mov esi,[clip_max_y]
  175. neg esi
  176. neg ebx
  177. neg edx
  178. call NEAR PTR ??clip_vert
  179. neg ebx
  180. neg edx
  181. stc
  182. retn
  183. ;*==================================================================
  184. ;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]
  185. ;*==================================================================
  186. ??clip_vert:
  187. push edx
  188. push eax
  189. mov [clip_var],edx ; clip_var = yb
  190. sub [clip_var],ebx ; clip_var = (yb-ya)
  191. neg eax ; eax=-xa
  192. add eax,ecx ; (ebx-xa)
  193. mov edx,esi ; edx=miny
  194. sub edx,ebx ; edx=(miny-ya)
  195. imul edx
  196. idiv [clip_var]
  197. pop edx
  198. add eax,edx
  199. pop edx
  200. mov ebx,esi
  201. retn
  202. ??a_lft:
  203. mov esi,[clip_min_x]
  204. call NEAR PTR ??clip_horiz
  205. stc
  206. retn
  207. ??a_rgt:
  208. mov esi,[clip_max_x]
  209. neg eax
  210. neg ecx
  211. neg esi
  212. call NEAR PTR ??clip_horiz
  213. neg eax
  214. neg ecx
  215. stc
  216. retn
  217. ;*==================================================================
  218. ;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]
  219. ;*==================================================================
  220. ??clip_horiz:
  221. push edx
  222. mov [clip_var],ecx ; clip_var = xb
  223. sub [clip_var],eax ; clip_var = (xb-xa)
  224. sub edx,ebx ; edx = (yb-ya)
  225. neg eax ; eax = -xa
  226. add eax,esi ; eax = (minx-xa)
  227. imul edx ; eax = (minx-xa)(yb-ya)
  228. idiv [clip_var] ; eax = (minx-xa)(yb-ya)/(xb-xa)
  229. add ebx,eax ; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]
  230. pop edx
  231. mov eax,esi
  232. retn
  233. ;*==================================================================
  234. ;* Sets the condition bits
  235. ;*==================================================================
  236. ??set_bits:
  237. xor esi,esi
  238. cmp ebx,[clip_min_y] ; if y >= top its not up
  239. jge short ??a_not_up
  240. or esi,1
  241. ??a_not_up:
  242. cmp ebx,[clip_max_y] ; if y <= bottom its not down
  243. jle short ??a_not_down
  244. or esi,2
  245. ??a_not_down:
  246. cmp eax,[clip_min_x] ; if x >= left its not left
  247. jge short ??a_not_left
  248. or esi,4
  249. ??a_not_left:
  250. cmp eax,[clip_max_x] ; if x <= right its not right
  251. jle short ??a_not_right
  252. or esi,8
  253. ??a_not_right:
  254. retn
  255. ;*==================================================================
  256. ;* Draw the line to the screen.
  257. ;* PORTABLE end
  258. ;*==================================================================
  259. ??draw_it:
  260. sub edx,ebx ; see if line is being draw down
  261. jnz short ??not_hline ; if not then its not a hline
  262. jmp short ??hline ; do special case h line
  263. ??not_hline:
  264. jg short ??down ; if so there is no need to rev it
  265. neg edx ; negate for actual pixel length
  266. xchg eax,ecx ; swap x's to rev line draw
  267. sub ebx,edx ; get old edx
  268. ??down:
  269. push edx
  270. push eax
  271. mov eax,[bpr]
  272. mul ebx
  273. mov ebx,eax
  274. mov eax,[this_object]
  275. add ebx,[(GraphicViewPort eax).GVPOffset]
  276. pop eax
  277. pop edx
  278. mov esi,1 ; assume a right mover
  279. sub ecx,eax ; see if line is right
  280. jnz short ??not_vline ; see if its a vertical line
  281. jmp ??vline
  282. ??not_vline:
  283. jg short ??right ; if so, the difference = length
  284. ??left:
  285. neg ecx ; else negate for actual pixel length
  286. neg esi ; negate counter to move left
  287. ??right:
  288. cmp ecx,edx ; is it a horiz or vert line
  289. jge short ??horiz ; if ecx > edx then |x|>|y| or horiz
  290. ??vert:
  291. xchg ecx,edx ; make ecx greater and edx lesser
  292. mov edi,ecx ; set greater
  293. mov [accum],ecx ; set accumulator to 1/2 greater
  294. shr [accum],1
  295. ;*==================================================================
  296. ;* at this point ...
  297. ;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
  298. ;* esi=adder; accum=accumulator
  299. ;* in a vertical loop the adder is conditional and the inc constant
  300. ;*==================================================================
  301. ??vert_loop:
  302. add ebx,eax
  303. mov eax,[color]
  304. ??v_midloop:
  305. mov [ebx],al
  306. dec ecx
  307. jl ??out
  308. add ebx,[bpr]
  309. sub [accum],edx ; sub the lesser
  310. jge ??v_midloop ; any line could be new
  311. add [accum],edi ; add greater for new accum
  312. add ebx,esi ; next pixel over
  313. jmp ??v_midloop
  314. ??horiz:
  315. mov edi,ecx ; set greater
  316. mov [accum],ecx ; set accumulator to 1/2 greater
  317. shr [accum],1
  318. ;*==================================================================
  319. ;* at this point ...
  320. ;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
  321. ;* esi=adder; accum=accumulator
  322. ;* in a vertical loop the adder is conditional and the inc constant
  323. ;*==================================================================
  324. ??horiz_loop:
  325. add ebx,eax
  326. mov eax,[color]
  327. ??h_midloop:
  328. mov [ebx],al
  329. dec ecx ; dec counter
  330. jl ??out ; end of line
  331. add ebx,esi
  332. sub [accum],edx ; sub the lesser
  333. jge ??h_midloop
  334. add [accum],edi ; add greater for new accum
  335. add ebx,[bpr] ; goto next line
  336. jmp ??h_midloop
  337. ;*==================================================================
  338. ;* Special case routine for horizontal line draws
  339. ;*==================================================================
  340. ??hline:
  341. cmp eax,ecx ; make eax < ecx
  342. jl short ??hl_ac
  343. xchg eax,ecx
  344. ??hl_ac:
  345. sub ecx,eax ; get len
  346. inc ecx
  347. push edx
  348. push eax
  349. mov eax,[bpr]
  350. mul ebx
  351. mov ebx,eax
  352. mov eax,[this_object]
  353. add ebx,[(GraphicViewPort eax).GVPOffset]
  354. pop eax
  355. pop edx
  356. add ebx,eax
  357. mov edi,ebx
  358. cmp ecx,15
  359. jg ??big_line
  360. mov al,[byte color]
  361. rep stosb ; write as many words as possible
  362. jmp short ??out ; get outt
  363. ??big_line:
  364. mov al,[byte color]
  365. mov ah,al
  366. mov ebx,eax
  367. shl eax,16
  368. mov ax,bx
  369. test edi,3
  370. jz ??aligned
  371. mov [edi],al
  372. inc edi
  373. dec ecx
  374. test edi,3
  375. jz ??aligned
  376. mov [edi],al
  377. inc edi
  378. dec ecx
  379. test edi,3
  380. jz ??aligned
  381. mov [edi],al
  382. inc edi
  383. dec ecx
  384. ??aligned:
  385. mov ebx,ecx
  386. shr ecx,2
  387. rep stosd
  388. mov ecx,ebx
  389. and ecx,3
  390. rep stosb
  391. jmp ??out
  392. ;*==================================================================
  393. ;* a special case routine for vertical line draws
  394. ;*==================================================================
  395. ??vline:
  396. mov ecx,edx ; get length of line to draw
  397. inc ecx
  398. add ebx,eax
  399. mov eax,[color]
  400. ??vl_loop:
  401. mov [ebx],al ; store bit
  402. add ebx,[bpr]
  403. dec ecx
  404. jnz ??vl_loop
  405. ??out:
  406. ret
  407. ENDP Buffer_Draw_Line
  408. END