Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1641 lines
61 KiB

  1. ;---------------------------Module-Header------------------------------;
  2. ; Module Name: vgablts.asm
  3. ;
  4. ; Copyright (c) 1992-1993 Microsoft Corporation
  5. ;-----------------------------------------------------------------------;
  6. ;-----------------------------------------------------------------------;
  7. ; VOID vTrgBlt(PDEV * ppdev, ULONG culRcl, RECTL * prcl, MIX ulMix,
  8. ; ULONG ulClr, POINTL * pptlBrush)
  9. ; Input:
  10. ; ppdev - pointer to PDEV for surface to which to draw
  11. ; culRcl - # of rectangles to fill
  12. ; prcl - pointer to list of rectangles to fill
  13. ; ulMix - mix rop with which to fill
  14. ; ulClr - color with which to fill
  15. ; pptlBrush - not used
  16. ;
  17. ; Performs accelerated solid area fills for all mixes.
  18. ;
  19. ;-----------------------------------------------------------------------;
  20. ;
  21. ; Note: Assumes all rectangles have positive heights and widths. Will not
  22. ; work properly if this is not the case.
  23. ;
  24. ;-----------------------------------------------------------------------;
  25. ;
  26. ; Note: Cases where the width of the whole bytes fill is equal to the
  27. ; width of the bitmap could be sped up by using a single REP MOVS or REP
  28. ; STOS, but how often does WIN32 do a fill that's the width of the screen?
  29. ; Not very.
  30. ;
  31. ;-----------------------------------------------------------------------;
  32. comment $
  33. The overall approach of this module is to accept a list of rectangles to
  34. fill, set up the VGA hardware for the desired fill, and then fill the
  35. rectangles one at a time. Each rectangle fill is set up for everything
  36. but vertical parameters, and then decomposed into the sections that
  37. intersect each VGA bank; each section is drawn in turn. Vectors are set
  38. up so that the drawing code appropriate for the desired fill is
  39. essentially threaded together.
  40. commend $
  41. ;-----------------------------------------------------------------------;
  42. .386
  43. ifndef DOS_PLATFORM
  44. .model small,c
  45. else
  46. ifdef STD_CALL
  47. .model small,c
  48. else
  49. .model small,pascal
  50. endif; STD_CALL
  51. endif; DOS_PLATFORM
  52. assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
  53. assume fs:nothing,gs:nothing
  54. .xlist
  55. include stdcall.inc ;calling convention cmacros
  56. include i386\strucs.inc
  57. include i386\driver.inc
  58. include i386\egavga.inc
  59. include i386\ropdefs.inc
  60. .list
  61. ;-----------------------------------------------------------------------;
  62. .data
  63. ;-----------------------------------------------------------------------;
  64. ; Left edge clip masks for intrabyte start addresses 0 through 3.
  65. ; Whole byte cases are flagged as 0ffh.
  66. public jLeftMask
  67. jLeftMask label byte
  68. db 0ffh,0eh,0ch,08h
  69. ;-----------------------------------------------------------------------;
  70. ; Right edge clip masks for intrabyte end addresses (non-inclusive)
  71. ; 0 through 3. Whole byte cases are flagged as 0ffh.
  72. public jRightMask
  73. jRightMask label byte
  74. db 0ffh,01h,03h,07h
  75. ;-----------------------------------------------------------------------;
  76. ; Tables used to set up for the desired raster op. Note that entries for raster
  77. ; ops that aren't handled here are generally correct, except that they ignore
  78. ; need for inversion of the destination, which those rops require.
  79. ; Table used to force off the drawing color for R2_BLACK (0).
  80. ; The first entry is ignored; there is no mix 0.
  81. public jForceOffTable
  82. jForceOffTable db 0
  83. db 000h,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh
  84. db 0ffh,0ffh,000h,0ffh,0ffh,0ffh,0ffh,0ffh
  85. ;-----------------------------------------------------------------------;
  86. ; Table used to force on the drawing color for R2_NOT (Dn) and R2_WHITE (1).
  87. ; The first entry is ignored; there is no mix 0.
  88. public jForceOnTable
  89. jForceOnTable db 0, 0,0,0,0,0,0ffh,0,0,0,0,0,0,0,0,0,0ffh
  90. ;-----------------------------------------------------------------------;
  91. ; Table used to invert the passed-in drawing color for Pn mixes.
  92. ; The first entry is ignored; there is no mix 0.
  93. public jNotTable
  94. jNotTable db 0, 0,0ffh,0ffh,0ffh,0,0,0,0ffh,0,0ffh,0,0ffh,0,0,0,0
  95. ;-----------------------------------------------------------------------;
  96. ; Table of VGA ALU logical functions corresponding to mixes. Note that Dn is
  97. ; handled as a separate preceding inversion pass when part of a more complex
  98. ; mix.
  99. ; The first entry is ignored; there is no mix 0.
  100. public jALUFuncTable
  101. jALUFuncTable db DR_SET
  102. db DR_SET,DR_AND,DR_AND,DR_SET
  103. db DR_AND,DR_XOR,DR_XOR,DR_OR
  104. db DR_AND,DR_XOR, 0,DR_OR
  105. db DR_SET,DR_OR ,DR_OR ,DR_SET
  106. ;-----------------------------------------------------------------------;
  107. ; 1 entries mark rops that require two passes, one to invert the destination
  108. ; and then another to finish the rop.
  109. ; The first entry is ignored; there is no mix 0.
  110. public jInvertDest
  111. jInvertDest db 0, 0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0
  112. ;-----------------------------------------------------------------------;
  113. ; Table of routines to be called to draw edges, according to which edges are
  114. ; partial and which edges are whole bytes.
  115. align 4
  116. pfnEdgeDrawing label dword
  117. dd do_right_edge_bytes
  118. dd do_both_edge_bytes
  119. dd check_next_bank
  120. dd do_left_edge_bytes
  121. ;-----------------------------------------------------------------------;
  122. ; Table of pointers to tables used to find appropriate whole byte loops.
  123. align 4
  124. pfnWideWholeRep label dword
  125. dd draw_wide_w_00_loop
  126. dd draw_wide_w_01_loop
  127. dd draw_wide_w_02_loop
  128. dd draw_wide_w_03_loop
  129. dd draw_wide_w_10_loop
  130. dd draw_wide_w_11_loop
  131. dd draw_wide_w_12_loop
  132. dd draw_wide_w_13_loop
  133. dd draw_wide_w_20_loop
  134. dd draw_wide_w_21_loop
  135. dd draw_wide_w_22_loop
  136. dd draw_wide_w_23_loop
  137. dd draw_wide_w_30_loop
  138. dd draw_wide_w_31_loop
  139. dd draw_wide_w_32_loop
  140. dd draw_wide_w_33_loop
  141. ;-----------------------------------------------------------------------;
  142. ; Table of pointers to tables used to find narrow, special-cased
  143. ; non-replace whole byte loops.
  144. ; Note: The breakpoint where one should switch from special-casing to
  145. ; REP MOVSB is purely a guess on my part. 5 seemed reasonable.
  146. align 4
  147. pfnWholeBytesNonReplaceEntries label dword
  148. dd 0 ;we never get a 0-wide case
  149. dd draw_1_wide_rw_loop
  150. dd draw_2_wide_rw_loop
  151. dd draw_3_wide_rw_loop
  152. dd draw_4_wide_rw_loop
  153. MAX_NON_REPLACE_SPECIAL equ ($-pfnWholeBytesNonReplaceEntries)/4
  154. ;-----------------------------------------------------------------------;
  155. ; Table of pointers to tables used to find narrow, special-cased replace
  156. ; whole byte loops.
  157. ; Note: The breakpoint where one should switch from special-casing to
  158. ; REP STOS is purely a guess on my part. 8 seemed reasonable.
  159. ; Start address MOD 3 is 0.
  160. align 4
  161. pfnWholeBytesMod0ReplaceEntries label dword
  162. dd 0 ;we never get a 0-wide case
  163. dd draw_1_wide_w_loop
  164. dd draw_2_wide_w_loop
  165. dd draw_3_wide_w_even_loop
  166. dd draw_4_wide_w_loop
  167. dd draw_5_wide_w_even_loop
  168. dd draw_6_wide_w_mod3_0_loop
  169. dd draw_7_wide_w_mod3_0_loop
  170. dd draw_8_wide_w_mod3_0_loop
  171. MAX_REPLACE_SPECIAL equ ($-pfnWholeBytesMod0ReplaceEntries)/4
  172. ; Start address MOD 3 is 1.
  173. align 4
  174. pfnWholeBytesMod1ReplaceEntries label dword
  175. dd 0 ;we never get a 0-wide case
  176. dd draw_1_wide_w_loop
  177. dd draw_2_wide_w_loop
  178. dd draw_3_wide_w_odd_loop
  179. dd draw_4_wide_w_loop
  180. dd draw_5_wide_w_odd_loop
  181. dd draw_6_wide_w_mod3_1_loop
  182. dd draw_7_wide_w_mod3_1_loop
  183. dd draw_8_wide_w_mod3_1_loop
  184. ; Start address MOD 3 is 2.
  185. align 4
  186. pfnWholeBytesMod2ReplaceEntries label dword
  187. dd 0 ;we never get a 0-wide case
  188. dd draw_1_wide_w_loop
  189. dd draw_2_wide_w_loop
  190. dd draw_3_wide_w_even_loop
  191. dd draw_4_wide_w_loop
  192. dd draw_5_wide_w_even_loop
  193. dd draw_6_wide_w_mod3_2_loop
  194. dd draw_7_wide_w_mod3_2_loop
  195. dd draw_8_wide_w_mod3_2_loop
  196. ; Start address MOD 3 is 3.
  197. align 4
  198. pfnWholeBytesMod3ReplaceEntries label dword
  199. dd 0 ;we never get a 0-wide case
  200. dd draw_1_wide_w_loop
  201. dd draw_2_wide_w_loop
  202. dd draw_3_wide_w_odd_loop
  203. dd draw_4_wide_w_loop
  204. dd draw_5_wide_w_odd_loop
  205. dd draw_6_wide_w_mod3_1_loop
  206. dd draw_7_wide_w_mod3_3_loop
  207. dd draw_8_wide_w_mod3_3_loop
  208. ; Master MOD 3 alignment look-up table for entry tables for four possible
  209. ; alignments for narrow, special-cased replace whole byte loops.
  210. align 4
  211. pfnWholeBytesReplaceMaster label dword
  212. dd pfnWholeBytesMod0ReplaceEntries
  213. dd pfnWholeBytesMod1ReplaceEntries
  214. dd pfnWholeBytesMod2ReplaceEntries
  215. dd pfnWholeBytesMod3ReplaceEntries
  216. ;-----------------------------------------------------------------------;
  217. .code
  218. ;-----------------------------------------------------------------------;
  219. cProc vTrgBlt,24,< \
  220. uses esi edi ebx, \
  221. ppdev: ptr, \
  222. culRcl: dword, \
  223. prcl: ptr RECTL, \
  224. ulMix: dword, \
  225. ulColor: dword, \
  226. pptlBrsuh:ptr POINTL >
  227. local ulRowOffset :dword ;Offset from start of scan line of
  228. ; first byte to fill
  229. local ulWholeBytes :dword ;# of whole bytes to fill
  230. local ulWholeDwords :dword ;# of whole dwords to fill
  231. local pfnWholeFn :dword ;pointer to routine used to draw
  232. ; whole bytes
  233. local ulScanWidth :dword ;offset from start of one scan to start
  234. ; of next
  235. local ulNextScan :dword ;offset from end of one scan line's
  236. ; fill to start of next
  237. local ulCurrentTopScan :dword ;top scan line to fill in current bank
  238. local ulMasks :dword ;low byte = right mask, high byte =
  239. ; left mask
  240. local ulBottomScan :dword ;bottom scan line of fill rectangle
  241. local jALUFunc :dword ;VGA ALU logical operation (SET, AND,
  242. ; OR, or XOR)
  243. local pfnStartDrawing :dword ;pointer to function to call to start
  244. ; drawing
  245. local pfnContinueDrawing :dword ;pointer to function to call to
  246. ; continue drawing after doing whole
  247. ; bytes
  248. local ulLeftEdgeAdjust :dword ;used to bump the whole bytes start
  249. ; address past the left edge when the
  250. ; left edge is partial
  251. local pfnWholeBytes :dword ;pointer to loop for whole byte filling
  252. local jInvertDestFirst :dword ;1 if the rop requires a pass to invert
  253. ; the destination before the normal
  254. ; pass
  255. local ulDrawingColor :dword ;color byte with which to fill,
  256. ; replicated to a dword
  257. local ppfnDrawEdgeTable :dword ;points to loop to be used to draw
  258. ; edge ; bytes (draw_1_wide_rw_loop
  259. ; or draw_1_wide_w_loop)
  260. ;-----------------------------------------------------------------------;
  261. ; CLD is assumed on entry.
  262. ;-----------------------------------------------------------------------;
  263. ;-----------------------------------------------------------------------;
  264. ; Make sure there's something to draw; clip enumerations can be empty.
  265. ;-----------------------------------------------------------------------;
  266. cmp culRcl,0 ;any rects to fill?
  267. jz vTrgBlts_done ;no, we're done
  268. ;-----------------------------------------------------------------------;
  269. ; Set up variables that are constant for the entire time we're in this
  270. ; module.
  271. ;-----------------------------------------------------------------------;
  272. ;-----------------------------------------------------------------------;
  273. ; Set up for the desired raster op.
  274. ;-----------------------------------------------------------------------;
  275. sub ebx,ebx ;ignore any background mix; we're only
  276. mov bl,byte ptr ulMix ; concerned with the foreground in this
  277. ; module
  278. cmp ebx,R2_NOP ;is this NOP?
  279. jz vTrgBlts_done ;yes, we're done
  280. mov al,jInvertDest[ebx] ;remember whether we need to
  281. mov byte ptr jInvertDestFirst,al ; invert the destination before
  282. ; finishing the rop
  283. mov ah,byte ptr ulColor ;get the drawing color
  284. and ah,jForceOffTable[ebx] ;force color to 0 if necessary
  285. ; (R2_BLACK)
  286. or ah,jForceOnTable[ebx] ;force color to 0ffh if necessary
  287. ; (R2_WHITE, R2_NOT)
  288. xor ah,jNotTable[ebx] ;invert color if necessary (any Pn mix)
  289. ;at this point, CH has the color we
  290. ; want to draw with; set up the VGA
  291. ; hardware to draw with that color
  292. mov al,ah ;replicate the drawing color to a dword
  293. mov edx,eax
  294. shl eax,16
  295. mov ax,dx
  296. mov ulDrawingColor,eax ;remember drawing color
  297. mov ppfnDrawEdgeTable,offset draw_1_wide_w_loop
  298. ;assume replace-type rop, so we can
  299. ; draw edge bytes with the write-
  300. ; without-read code pointed to by this
  301. ; table
  302. mov ah,jALUFuncTable[ebx] ;get the ALU logical function
  303. and ah,ah ;is the logical function DR_SET?
  304. .errnz DR_SET
  305. jz short skip_ALU_set ;yes, don't have to set because that's
  306. ; the VGA's default state
  307. mov edx,VGA_BASE + GRAF_ADDR
  308. mov al,GRAF_DATA_ROT
  309. out dx,ax ;set the ALU logical function
  310. mov ppfnDrawEdgeTable,offset draw_1_wide_rw_loop
  311. ;draw edge bytes with this loop
  312. ; (read/write)
  313. skip_ALU_set:
  314. mov byte ptr jALUFunc,ah ;remember the ALU logical function
  315. ;-----------------------------------------------------------------------;
  316. ; Fill the current rectangle with the specified raster op and color.
  317. ;-----------------------------------------------------------------------;
  318. fill_rect_loop:
  319. ;-----------------------------------------------------------------------;
  320. ; Set up variables that are constant from bank to bank during a single
  321. ; fill.
  322. ;-----------------------------------------------------------------------;
  323. ;-----------------------------------------------------------------------;
  324. ; Set up masks and widths.
  325. ;-----------------------------------------------------------------------;
  326. mov edi,prcl ;point to rectangle to fill
  327. mov eax,[edi].yBottom
  328. mov ulBottomScan,eax ;remember the bottom scan line of fill
  329. mov ebx,[edi].xRight ;right edge of fill (non-inclusive)
  330. mov ecx,ebx
  331. and ecx,011b ;intrabyte address of right edge
  332. mov ah,jRightMask[ecx] ;right edge mask
  333. mov esi,[edi].xLeft ;left edge of fill (inclusive)
  334. mov ecx,esi
  335. shr ecx,2 ;/4 for start offset from left edge
  336. ; of scan line
  337. mov ulRowOffset,ecx ;remember offset from start of scan
  338. ; line
  339. sub ebx,esi ;width in pixels of fill
  340. and esi,011b ;intrabyte address of left edge
  341. mov al,jLeftMask[esi] ;left edge mask
  342. dec ebx ;make inclusive on right
  343. add ebx,esi ;inclusive width, starting counting at
  344. ; the beginning of the left edge byte
  345. shr ebx,2 ;width of fill in bytes touched - 1
  346. jnz short more_than_1_byte ;more than 1 byte is involved
  347. ; Only one byte will be affected. Combine first/last masks.
  348. and al,ah ;we'll use first byte mask only
  349. xor ah,ah ;want last byte mask to be 0
  350. inc ebx ;so there's one count to subtract below
  351. ; if this isn't a whole edge byte
  352. more_than_1_byte:
  353. ; If all pixels in the left edge are altered, combine the first byte into the
  354. ; whole byte count and clear the first byte mask, because we can handle solid
  355. ; edge bytes faster as part of the whole bytes. Ditto for the right edge.
  356. sub ecx,ecx ;edge whole-status accumulator
  357. cmp al,-1 ;is left edge a whole byte or partial?
  358. adc ecx,ecx ;ECX=1 if left edge partial, 0 if whole
  359. sub ebx,ecx ;if left edge partial, deduct it from
  360. ; the whole bytes count
  361. mov ulLeftEdgeAdjust,ecx ;for skipping over the left edge if
  362. ; it's partial when pointing to the
  363. ; whole bytes
  364. and ah,ah ;is right edge mask 0, meaning this
  365. ; fill is only 1 byte wide?
  366. jz short save_masks ;yes, no need to do anything
  367. cmp ah,-1 ;is right edge a whole byte or partial?
  368. jnz short save_masks ;partial
  369. add ecx,2 ;bit 1 of ECX=0 if right edge partial,
  370. ; 1 if whole;
  371. ;bit 1=0 if left edge partial, 1 whole
  372. inc ebx ;if right edge whole, include it in the
  373. ; whole bytes count
  374. save_masks:
  375. mov ulMasks,eax ;save left and right clip masks
  376. mov ulWholeBytes,ebx ;save # of whole bytes
  377. mov ecx,pfnEdgeDrawing[ecx*4] ;set address of routine to draw
  378. mov pfnContinueDrawing,ecx ; all partial (non-whole) edges
  379. and ebx,ebx ;any whole bytes?
  380. jz short start_vec_set ;no
  381. ;yes, so draw the whole bytes before
  382. ; the edge bytes
  383. ; The whole bytes loop depends on the type of operation being done. If the
  384. ; operation is one which uses DR_SET, then we can use a STOS-type operation,
  385. ; else we have to use a MOVSB-type operation (to load the latches with the
  386. ; existing contents of display memory to allow the ALUs to work).
  387. cmp byte ptr jALUFunc,DR_SET ;is it a replace-type rop?
  388. jz short is_replace_type ;yes
  389. ;no, set up for non-replace whole bytes
  390. mov ecx,offset whole_bytes_non_replace_wide
  391. ;assume too wide to special-case
  392. cmp ebx,MAX_NON_REPLACE_SPECIAL ;too wide to special case?
  393. jnb short start_vec_set ;yes
  394. mov ecx,pfnWholeBytesNonReplaceEntries[ebx*4] ;no, point to entry
  395. mov pfnWholeBytes,ecx ; table for width
  396. mov ecx,offset whole_bytes_special
  397. ;set up to call special routine to fill
  398. ; whole bytes
  399. jmp short start_vec_set
  400. is_replace_type: ;set up for replace-type rop
  401. cmp ebx,MAX_REPLACE_SPECIAL ;too wide to special case?
  402. jnb short is_wide_replace ;yes
  403. ;narrow enough to special case. Look up
  404. ; the entry table for the special case
  405. ; base on the start alignment
  406. mov ecx,ulRowOffset
  407. add ecx,ulLeftEdgeAdjust ;left edge whole bytes start offset
  408. and ecx,011b ;left edge whole bytes start alignment
  409. ; MOD 3
  410. mov ecx,pfnWholeBytesReplaceMaster[ecx*4] ;look up table of entry
  411. ; tables for alignment
  412. mov ecx,[ecx+ebx*4] ;look up entry table for width
  413. mov pfnWholeBytes,ecx ; table for width
  414. mov ecx,offset whole_bytes_special
  415. ;set up to call special routine to fill
  416. ; whole bytes
  417. jmp short start_vec_set
  418. is_wide_replace: ;set up for wide replace-type op
  419. ;Note: assumes there is at least one
  420. ; full dword involved!
  421. mov ecx,ulRowOffset
  422. add ecx,ulLeftEdgeAdjust ;left edge whole bytes start offset
  423. neg ecx
  424. and ecx,011b
  425. mov edx,ebx
  426. sub edx,ecx ;ignore odd leading bytes
  427. mov eax,edx
  428. shr edx,2 ;# of whole dwords across (not counting
  429. ; odd leading & trailing bytes)
  430. mov ulWholeDwords,edx
  431. and eax,011b ;# of odd (fractional) trailing bytes
  432. shl ecx,2
  433. or ecx,eax ;build a look-up index from the number
  434. ; of leading and trailing bytes
  435. mov ecx,pfnWideWholeRep[ecx*4] ;proper drawing handler for front/
  436. mov pfnWholeBytes,ecx ; back alignment
  437. mov ecx,offset whole_bytes_rep_wide
  438. ;set up to call routine to perform wide
  439. ; whole bytes fill
  440. start_vec_set:
  441. mov pfnStartDrawing,ecx ; all partial (non-whole) edges
  442. mov ecx,ppdev
  443. mov eax,[ecx].pdev_lPlanarNextScan
  444. mov ulScanWidth,eax ;local copy of scan line width
  445. sub eax,ebx ;EAX = delta to next scan
  446. mov ulNextScan,eax
  447. ;-----------------------------------------------------------------------;
  448. ; Fill this rectangle.
  449. ;-----------------------------------------------------------------------;
  450. cmp byte ptr jInvertDestFirst,1
  451. ;is this an invert-dest-plus-something-
  452. ; else rop that requires two passes?
  453. jz short do_invert_dest_rop ;yes, special case with two passes
  454. do_single_pass:
  455. call draw_banks
  456. ;-----------------------------------------------------------------------;
  457. ; See if there are any more rectangles to fill.
  458. ;-----------------------------------------------------------------------;
  459. add prcl,(size RECTL) ;point to the next rectangle, if there is one
  460. dec culRcl ;count down the rectangles to fill
  461. jnz fill_rect_loop
  462. ;-----------------------------------------------------------------------;
  463. ; We have filled all rectangles. Restore the VGA to its default state.
  464. ;-----------------------------------------------------------------------;
  465. cmp byte ptr jALUfunc,DR_SET ;is the logical function already SET?
  466. jnz short @F ;no, need to reset it
  467. cRet vTrgBlt ;yes, no need to reset it
  468. @@:
  469. mov edx,VGA_BASE + GRAF_ADDR
  470. mov eax,(DR_SET shl 8) + GRAF_DATA_ROT ;set the logical function to
  471. out dx,ax ; SET
  472. vTrgBlts_done:
  473. cRet vTrgBlt
  474. ;-----------------------------------------------------------------------;
  475. ; Handles rops that require two passes, the first being a destination
  476. ; inversion pass.
  477. ;-----------------------------------------------------------------------;
  478. do_invert_dest_rop:
  479. ; Set up the VGA's hardware for inversion
  480. mov eax,ulDrawingColor ;remember the normal drawing color
  481. push eax
  482. mov ulDrawingColor,-1 ;with XOR, this flips all bits
  483. mov edx,VGA_BASE + GRAF_ADDR
  484. mov eax,(DR_XOR shl 8) + GRAF_DATA_ROT
  485. out dx,ax ;logical function = XOR to invert
  486. ; Invert the destination
  487. call draw_banks
  488. ; Restore the VGA's hardware to the state required for the second pass.
  489. mov edx,VGA_BASE + GRAF_ADDR
  490. mov ah,byte ptr jALUFunc
  491. mov al,GRAF_DATA_ROT
  492. out dx,ax ;set the ALU logical function back to
  493. ; proper state for the rest of the rop
  494. pop eax
  495. mov ulDrawingColor,eax ;restore the normal drawing color
  496. ; Perform the second pass to finish the rop.
  497. jmp do_single_pass
  498. ;-----------------------------------------------------------------------;
  499. ; Fills all banks in the current fill rectangle. Called once per fill
  500. ; rectangle, except for destination-inversion-plus-something-else rops.
  501. ;-----------------------------------------------------------------------;
  502. draw_banks:
  503. ;-----------------------------------------------------------------------;
  504. ; Map in the bank containing the top scan to fill, if it's not mapped in
  505. ; already.
  506. ;-----------------------------------------------------------------------;
  507. mov edi,prcl ;point to rectangle to fill
  508. mov ecx,ppdev ;point to PDEV
  509. mov eax,[edi].yTop ;top scan line of fill
  510. mov ulCurrentTopScan,eax ;this will be the fill top in 1st bank
  511. cmp eax,[ecx].pdev_rcl1PlanarClip.yTop ;is fill top less than
  512. ; current bank?
  513. jl short map_init_bank ;yes, map in proper bank
  514. cmp eax,[ecx].pdev_rcl1PlanarClip.yBottom ;fill top greater than
  515. ; current bank?
  516. jl short init_bank_mapped ;no, proper bank already mapped
  517. map_init_bank:
  518. ; Map in the bank containing the top scan line of the fill.
  519. ptrCall <dword ptr [ecx].pdev_pfnPlanarControl>,<ecx,eax,JustifyTop>
  520. init_bank_mapped:
  521. ;-----------------------------------------------------------------------;
  522. ; Main loop for processing fill in each bank.
  523. ;-----------------------------------------------------------------------;
  524. ; Compute the starting address and scan line count for the initial bank.
  525. mov eax,ppdev ;point to PDEV
  526. mov ebx,ulBottomScan ;bottom of destination rectangle
  527. cmp ebx,[eax].pdev_rcl1PlanarClip.yBottom
  528. ;which comes first, the bottom of the
  529. ; dest rect or the bottom of the
  530. ; current bank?
  531. jl short BottomScanSet ;fill bottom comes first, so draw to
  532. ; that; this is the last bank in fill
  533. mov ebx,[eax].pdev_rcl1PlanarClip.yBottom
  534. ;bank bottom comes first; draw to
  535. ; bottom of bank
  536. BottomScanSet:
  537. mov edi,ulCurrentTopScan ;top scan line to fill in current bank
  538. sub ebx,edi ;# of scans to fill in bank
  539. imul edi,ulScanWidth ;offset of starting scan line
  540. ; Note that the start of the bitmap will change each time through the
  541. ; bank loop, because the start of the bitmap is varied to map the
  542. ; desired scan line to the banking window.
  543. add edi,[eax].pdev_pvBitmapStart ;start of scan in bitmap
  544. add edi,ulRowOffset ;EDI = start offset of fill in bitmap
  545. ; We have computed the starting address and scan count. Time to start drawing
  546. ; in the initial bank.
  547. jmp pfnStartDrawing
  548. ;-----------------------------------------------------------------------;
  549. ; Whole byte fills.
  550. ;-----------------------------------------------------------------------;
  551. ;-----------------------------------------------------------------------;
  552. ; Handles non-replace whole byte fills wider than the maximum special
  553. ; case width.
  554. ;
  555. ; The destination is not involved, so a STOS (or equivalent) can be used
  556. ; (no read needed before write).
  557. ;-----------------------------------------------------------------------;
  558. whole_bytes_rep_wide:
  559. push ebx ;save scan count
  560. push edi ;save starting address
  561. add edi,ulLeftEdgeAdjust ;point to first whole byte to fill
  562. mov esi,ulWholeDwords ;whole dwords width
  563. mov edx,ulNextScan ;offset from end of one scan line to
  564. ; start of next
  565. mov eax,ulDrawingColor ;each byte is color with which to fill
  566. call pfnWholeBytes ;draw the wide whole bytes
  567. pop edi ;restore screen pointer
  568. pop ebx ;restore fill scan count
  569. jmp pfnContinueDrawing ;either keep drawing or we're done
  570. ;-----------------------------------------------------------------------;
  571. ; Handles both replace and non-replace whole byte fills narrow enough to
  572. ; special case.
  573. ;-----------------------------------------------------------------------;
  574. whole_bytes_special:
  575. push ebx ;save scan count
  576. push edi ;save starting address
  577. add edi,ulLeftEdgeAdjust ;point to first whole byte to fill
  578. mov ecx,ulScanWidth ;offset to next scan line
  579. mov eax,ulDrawingColor ;each byte is color with which to fill
  580. call pfnWholeBytes ;draw the wide whole bytes
  581. pop edi ;restore screen pointer
  582. pop ebx ;restore fill scan count
  583. jmp pfnContinueDrawing ;either keep drawing or we're done
  584. ;-----------------------------------------------------------------------;
  585. ; Handles non-replace whole byte fills wider than the maximum special case
  586. ; width.
  587. ;
  588. ; The destination is involved, so a MOVSB (or equivalent) must be
  589. ; performed in order to do a read before write to give the ALUs something
  590. ; to work with.
  591. ;-----------------------------------------------------------------------;
  592. whole_bytes_non_replace_wide:
  593. push ebx ;save scan count
  594. push edi ;save starting address
  595. add edi,ulLeftEdgeAdjust ;point to first whole byte to fill
  596. mov esi,ulWholeBytes ;whole bytes width
  597. mov edx,ulNextScan ;offset from end of one scan line to
  598. ; start of next
  599. mov eax,ulDrawingColor ;each byte is color with which to fill
  600. ;-----------------------------------------------------------------------;
  601. ; 5-or-wider read before write loop.
  602. ;
  603. ; Entry:
  604. ; EAX = # of bytes to fill across scan line (needed only by 5-or-wider
  605. ; handler)
  606. ; EBX = loop count
  607. ; EDX = offset from end of one scan line to the start of the next next
  608. ; EDI = start offset
  609. ;
  610. ; EBX, ECX, ESI, EDI modified. All other registers preserved.
  611. ; 5-or-wider read/write.
  612. draw_wide_rw_loop:
  613. mov ecx,esi
  614. @@:
  615. mov ah,[edi] ;latch the target address. The data read
  616. ; doesn't matter
  617. mov [edi],al ;merge the drawing color with the latched
  618. ; target address according to the selected ALU
  619. ; function, and write the result to display
  620. ; memory
  621. inc edi ;point to the next byte
  622. dec ecx
  623. jnz @B
  624. add edi,edx
  625. dec ebx
  626. jnz draw_wide_rw_loop
  627. pop edi ;restore screen pointer
  628. pop ebx ;restore fill scan count
  629. jmp pfnContinueDrawing ;either keep drawing or we're done
  630. ;-----------------------------------------------------------------------;
  631. ; Process any left/right columns that that have to be done.
  632. ;
  633. ; Currently:
  634. ; EBX = height to fill, in scans
  635. ; EDI --> first byte of left edge
  636. ;-----------------------------------------------------------------------;
  637. ;-----------------------------------------------------------------------;
  638. ; Handle case where both edges are partial (non-whole) bytes. We don't
  639. ; have to read before write because we're using the Map Mask, not the
  640. ; Bit Mask.
  641. ;-----------------------------------------------------------------------;
  642. public do_both_edge_bytes
  643. do_both_edge_bytes::
  644. ; Set up variables for entering loop.
  645. mov al,byte ptr ulMasks ;this will become the clip mask for the
  646. ; left edge
  647. mov edx,VGA_BASE + SEQ_DATA ;SEQ_INDEX already points to Map Mask
  648. out dx,al ;set Map Mask for left edge
  649. mov ecx,ulScanWidth ;offset from one scan to next
  650. mov esi,ulWholeBytes ;ESI = # of whole bytes
  651. lea esi,[esi+edi+1] ;--> start for right edge
  652. mov eax,ulDrawingColor ;each byte is color with which to fill
  653. push ebx ;preserve scan line count
  654. call ppfnDrawEdgeTable ;jump into the loop to draw
  655. pop ebx ;restore scan line count
  656. mov edi,esi ;point to first right edge byte
  657. mov al,byte ptr ulMasks+1 ;this will become the Bit Mask for the
  658. ; right edge
  659. mov edx,VGA_BASE + SEQ_DATA ;SEQ_INDEX already points to Map Mask
  660. out dx,al ;set Map Mask for left edge
  661. mov eax,ulDrawingColor ;each byte is color with which to fill
  662. push offset edges_done ;return here
  663. jmp ppfnDrawEdgeTable ;jump into the loop to draw
  664. ;-----------------------------------------------------------------------;
  665. ; Handle case where only the left edge is partial (non-whole).
  666. ;-----------------------------------------------------------------------;
  667. do_left_edge_bytes::
  668. ; Set up variables for entering loop.
  669. mov ecx,ulScanWidth ;offset from one scan to next
  670. mov al,byte ptr ulMasks ;this will become the Bit Mask for the
  671. ; left edge
  672. mov edx,VGA_BASE + SEQ_DATA ;SEQ_INDEX already points to Map Mask
  673. out dx,al ;set Map Mask for left edge
  674. mov eax,ulDrawingColor ;each byte is color with which to fill
  675. push offset edges_done ;return here
  676. jmp ppfnDrawEdgeTable ;jump into the loop to draw
  677. ;-----------------------------------------------------------------------;
  678. ; Handle case where only the right edge is partial (non-whole).
  679. ;-----------------------------------------------------------------------;
  680. do_right_edge_bytes::
  681. ; Set up variables for entering loop.
  682. mov ecx,ulScanWidth ;offset from one scan to next
  683. add edi,ulWholeBytes ;--> start for right edge (remember,
  684. ; left edge is whole, so the left edge
  685. ; byte is included in the whole byte
  686. ; count)
  687. mov al,byte ptr ulMasks+1 ;this will become the Bit Mask for the
  688. ; right edge
  689. mov edx,VGA_BASE + SEQ_DATA ;SEQ_INDEX already points to Map Mask
  690. out dx,al ;set Map Mask for right edge
  691. mov eax,ulDrawingColor ;each byte is color with which to fill
  692. call ppfnDrawEdgeTable ;jump into the loop to draw
  693. ;-----------------------------------------------------------------------;
  694. ; We have done all partial edges.
  695. ;-----------------------------------------------------------------------;
  696. edges_done:
  697. mov edx,VGA_BASE + SEQ_DATA ;SEQ_INDEX already points to Map Mask
  698. mov al,MM_ALL ;restore the default Map Mask of all
  699. out dx,al ; planes enabled
  700. ;-----------------------------------------------------------------------;
  701. ; See if there are any more banks to process.
  702. ;-----------------------------------------------------------------------;
  703. check_next_bank::
  704. mov edi,ppdev
  705. mov eax,[edi].pdev_rcl1PlanarClip.yBottom ;is the fill bottom in
  706. cmp ulBottomScan,eax ; the current bank?
  707. jle short banks_done ;yes, so we're done
  708. ;no, map in the next bank and fill it
  709. mov ulCurrentTopScan,eax ;remember where the top of the bank
  710. ; we're about to map in is (same as
  711. ; bottom of bank we just did)
  712. ptrCall <dword ptr [edi].pdev_pfnPlanarControl>,<edi,eax,JustifyTop>
  713. ;map in the bank
  714. ; Compute the starting address and scan line count in this bank.
  715. mov eax,ppdev ;EAX->target surface
  716. mov ebx,ulBottomScan ;bottom of destination rectangle
  717. cmp ebx,[eax].pdev_rcl1PlanarClip.yBottom
  718. ;which comes first, the bottom of the
  719. ; dest rect or the bottom of the
  720. ; current bank?
  721. jl short BottomScanSet2 ;fill bottom comes first, so draw to
  722. ; that; this is the last bank in fill
  723. mov ebx,[eax].pdev_rcl1PlanarClip.yBottom
  724. ;bank bottom comes first; draw to
  725. ; bottom of bank
  726. BottomScanSet2:
  727. mov edi,ulCurrentTopScan ;top scan line to fill in current bank
  728. sub ebx,edi ;# of scans to fill in bank
  729. imul edi,ulScanWidth ;offset of starting scan line
  730. ; Note that the start of the bitmap will change each time through the
  731. ; bank loop, because the start of the bitmap is varied to map the
  732. ; desired scan line to the banking window.
  733. add edi,[eax].pdev_pvBitmapStart ;start of scan in bitmap
  734. add edi,ulRowOffset ;EDI = start offset of fill in bitmap
  735. ; Draw in the new bank.
  736. jmp pfnStartDrawing
  737. ;-----------------------------------------------------------------------;
  738. ; Done with all banks in this fill.
  739. banks_done:
  740. retn
  741. endProc vTrgBlt
  742. ;-----------------------------------------------------------------------;
  743. ; Drawing loops.
  744. ; There are two kinds of drawing loops: read-before-write (to load the
  745. ; latches), and write-only (for replace-type rops).
  746. ;-----------------------------------------------------------------------;
  747. ;-----------------------------------------------------------------------;
  748. ; Drawing stuff for cases where read before write is required,
  749. ; to load the latches.
  750. ;-----------------------------------------------------------------------;
  751. ;-----------------------------------------------------------------------;
  752. ; 1-, 2-, 3-, and 4-wide read before write drawing loops.
  753. ;
  754. ; Entry:
  755. ; AL = drawing color
  756. ; EBX = loop count
  757. ; ECX = scan line width in bytes
  758. ; EDI = start offset
  759. ;
  760. ; EBX, EDI modified. All other registers preserved.
  761. ; 1-wide read/write.
  762. draw_1_wide_rw_loop proc near
  763. mov ah,[edi] ;latch the target address. The data read
  764. ; doesn't matter
  765. mov [edi],al ;merge the drawing color with the latched
  766. ; target address according to the selected ALU
  767. ; function, and write the result to display
  768. ; memory
  769. add edi,ecx ;point to the next scan line
  770. dec ebx
  771. jnz draw_1_wide_rw_loop
  772. ret
  773. draw_1_wide_rw_loop endp
  774. ; 2-wide read/write.
  775. draw_2_wide_rw_loop proc near
  776. mov ah,[edi] ;see 1-wide RW case for comments
  777. mov [edi],al
  778. mov ah,[edi+1]
  779. mov [edi+1],al
  780. add edi,ecx ;point to the next scan line
  781. dec ebx
  782. jnz draw_2_wide_rw_loop
  783. ret
  784. draw_2_wide_rw_loop endp
  785. ; 3-wide read/write.
  786. draw_3_wide_rw_loop proc near
  787. mov ah,[edi] ;see 1-wide RW case for comments
  788. mov [edi],al
  789. mov ah,[edi+1]
  790. mov [edi+1],al
  791. mov ah,[edi+2]
  792. mov [edi+2],al
  793. add edi,ecx ;point to the next scan line
  794. dec ebx
  795. jnz draw_3_wide_rw_loop
  796. ret
  797. draw_3_wide_rw_loop endp
  798. ; 4-wide read/write.
  799. draw_4_wide_rw_loop proc near
  800. mov ah,[edi] ;see 1-wide RW case for comments
  801. mov [edi],al
  802. mov ah,[edi+1]
  803. mov [edi+1],al
  804. mov ah,[edi+2]
  805. mov [edi+2],al
  806. mov ah,[edi+3]
  807. mov [edi+3],al
  808. add edi,ecx ;point to the next scan line
  809. dec ebx
  810. jnz draw_4_wide_rw_loop
  811. ret
  812. draw_4_wide_rw_loop endp
  813. ;-----------------------------------------------------------------------;
  814. ; Drawing stuff for cases where read before write is NOT required.
  815. ;-----------------------------------------------------------------------;
  816. ;-----------------------------------------------------------------------;
  817. ; 1-, 2-, 3-, and 4-wide write-only edge-drawing loops.
  818. ;
  819. ; Entry:
  820. ; EAX = fill color, replicated four times
  821. ; EBX = loop count
  822. ; ECX = scan line width in bytes
  823. ; EDI = start offset
  824. ;
  825. ; EBX, EDI modified. All other registers preserved.
  826. ; 1-wide write-only.
  827. draw_1_wide_w_loop proc near
  828. mov [edi],al ;draw the pixel
  829. add edi,ecx ;point to the next scan line
  830. dec ebx
  831. jnz draw_1_wide_w_loop
  832. ret
  833. draw_1_wide_w_loop endp
  834. ; 2-wide write-only.
  835. draw_2_wide_w_loop proc near
  836. mov [edi],ax
  837. add edi,ecx ;point to the next scan line
  838. dec ebx
  839. jnz draw_2_wide_w_loop
  840. ret
  841. draw_2_wide_w_loop endp
  842. ; 3-wide write-only, starting at an even address.
  843. draw_3_wide_w_even_loop proc near
  844. mov [edi],ax
  845. mov [edi+2],al
  846. add edi,ecx ;point to the next scan line
  847. dec ebx
  848. jnz draw_3_wide_w_even_loop
  849. ret
  850. draw_3_wide_w_even_loop endp
  851. ; 3-wide write-only, starting at an odd address.
  852. draw_3_wide_w_odd_loop proc near
  853. mov [edi],al
  854. mov [edi+1],ax
  855. add edi,ecx ;point to the next scan line
  856. dec ebx
  857. jnz draw_3_wide_w_odd_loop
  858. ret
  859. draw_3_wide_w_odd_loop endp
  860. ; 4-wide write-only.
  861. draw_4_wide_w_loop proc near
  862. mov [edi],eax
  863. add edi,ecx ;point to the next scan line
  864. dec ebx
  865. jnz draw_4_wide_w_loop
  866. ret
  867. draw_4_wide_w_loop endp
  868. ; 5-wide write-only, starting at an even address.
  869. draw_5_wide_w_even_loop proc near
  870. mov [edi],eax
  871. mov [edi+4],al
  872. add edi,ecx ;point to the next scan line
  873. dec ebx
  874. jnz draw_5_wide_w_even_loop
  875. ret
  876. draw_5_wide_w_even_loop endp
  877. ; 5-wide write-only, starting at an odd address.
  878. draw_5_wide_w_odd_loop proc near
  879. mov [edi],al
  880. mov [edi+1],eax
  881. add edi,ecx ;point to the next scan line
  882. dec ebx
  883. jnz draw_5_wide_w_odd_loop
  884. ret
  885. draw_5_wide_w_odd_loop endp
  886. ; 6-wide write-only, starting at MOD 3 == 0.
  887. draw_6_wide_w_mod3_0_loop proc near
  888. mov [edi],eax
  889. mov [edi+4],ax
  890. add edi,ecx ;point to the next scan line
  891. dec ebx
  892. jnz draw_6_wide_w_mod3_0_loop
  893. ret
  894. draw_6_wide_w_mod3_0_loop endp
  895. ; 6-wide write-only, starting at MOD 3 == 1 or 3.
  896. draw_6_wide_w_mod3_1_loop proc near
  897. mov [edi],al
  898. mov [edi+1],eax
  899. mov [edi+5],al
  900. add edi,ecx ;point to the next scan line
  901. dec ebx
  902. jnz draw_6_wide_w_mod3_1_loop
  903. ret
  904. draw_6_wide_w_mod3_1_loop endp
  905. ; 6-wide write-only, starting at MOD 3 == 2.
  906. draw_6_wide_w_mod3_2_loop proc near
  907. mov [edi],ax
  908. mov [edi+2],eax
  909. add edi,ecx ;point to the next scan line
  910. dec ebx
  911. jnz draw_6_wide_w_mod3_2_loop
  912. ret
  913. draw_6_wide_w_mod3_2_loop endp
  914. ; 7-wide write-only, starting at MOD 3 == 0.
  915. draw_7_wide_w_mod3_0_loop proc near
  916. mov [edi],eax
  917. mov [edi+4],ax
  918. mov [edi+6],al
  919. add edi,ecx ;point to the next scan line
  920. dec ebx
  921. jnz draw_7_wide_w_mod3_0_loop
  922. ret
  923. draw_7_wide_w_mod3_0_loop endp
  924. ; 7-wide write-only, starting at MOD 3 == 0.
  925. draw_7_wide_w_mod3_1_loop proc near
  926. mov [edi],al
  927. mov [edi+1],ax
  928. mov [edi+3],eax
  929. add edi,ecx ;point to the next scan line
  930. dec ebx
  931. jnz draw_7_wide_w_mod3_1_loop
  932. ret
  933. draw_7_wide_w_mod3_1_loop endp
  934. ; 7-wide write-only, starting at MOD 3 == 2.
  935. draw_7_wide_w_mod3_2_loop proc near
  936. mov [edi],ax
  937. mov [edi+2],eax
  938. mov [edi+6],al
  939. add edi,ecx ;point to the next scan line
  940. dec ebx
  941. jnz draw_7_wide_w_mod3_2_loop
  942. ret
  943. draw_7_wide_w_mod3_2_loop endp
  944. ; 7-wide write-only, starting at MOD 3 == 3.
  945. draw_7_wide_w_mod3_3_loop proc near
  946. mov [edi],al
  947. mov [edi+1],eax
  948. mov [edi+5],ax
  949. add edi,ecx ;point to the next scan line
  950. dec ebx
  951. jnz draw_7_wide_w_mod3_3_loop
  952. ret
  953. draw_7_wide_w_mod3_3_loop endp
  954. ; 8-wide write-only, starting at MOD 3 == 0.
  955. draw_8_wide_w_mod3_0_loop proc near
  956. mov [edi],eax
  957. mov [edi+4],eax
  958. add edi,ecx ;point to the next scan line
  959. dec ebx
  960. jnz draw_8_wide_w_mod3_0_loop
  961. ret
  962. draw_8_wide_w_mod3_0_loop endp
  963. ; 8-wide write-only, starting at MOD 3 == 0.
  964. draw_8_wide_w_mod3_1_loop proc near
  965. mov [edi],al
  966. mov [edi+1],ax
  967. mov [edi+3],eax
  968. mov [edi+7],al
  969. add edi,ecx ;point to the next scan line
  970. dec ebx
  971. jnz draw_8_wide_w_mod3_1_loop
  972. ret
  973. draw_8_wide_w_mod3_1_loop endp
  974. ; 8-wide write-only, starting at MOD 3 == 2.
  975. draw_8_wide_w_mod3_2_loop proc near
  976. mov [edi],ax
  977. mov [edi+2],eax
  978. mov [edi+6],ax
  979. add edi,ecx ;point to the next scan line
  980. dec ebx
  981. jnz draw_8_wide_w_mod3_2_loop
  982. ret
  983. draw_8_wide_w_mod3_2_loop endp
  984. ; 8-wide write-only, starting at MOD 3 == 3.
  985. draw_8_wide_w_mod3_3_loop proc near
  986. mov [edi],al
  987. mov [edi+1],eax
  988. mov [edi+5],ax
  989. mov [edi+7],al
  990. add edi,ecx ;point to the next scan line
  991. dec ebx
  992. jnz draw_8_wide_w_mod3_3_loop
  993. ret
  994. draw_8_wide_w_mod3_3_loop endp
  995. ;-----------------------------------------------------------------------;
  996. ; Loop stuff for wide replace-type rops (arbitrary width).
  997. ;-----------------------------------------------------------------------;
  998. ; N-wide write-only, 0 leading bytes, 0 trailing bytes.
  999. ; EAX = 0ffffh
  1000. ; EBX = count of scans to fill
  1001. ; EDX = offset from end of one scan's fill to start of next
  1002. ; ESI = # of dwords to fill
  1003. ; EDI = target address to fill
  1004. draw_wide_w_00_loop proc near
  1005. mov ecx,esi ;# of whole dwords
  1006. rep stosd ;fill all whole bytes as dwords
  1007. add edi,edx ;point to the next scan line
  1008. dec ebx
  1009. jnz draw_wide_w_00_loop
  1010. ret
  1011. draw_wide_w_00_loop endp
  1012. ; N-wide write-only, 0 leading bytes, 1 trailing byte.
  1013. ; EAX = # of dwords to fill
  1014. ; EBX = count of scans to fill
  1015. ; EDX = offset from end of one scan's fill to start of next
  1016. ; ESI = # of dwords to fill
  1017. ; EDI = target address to fill
  1018. draw_wide_w_01_loop proc near
  1019. mov ecx,esi ;# of whole dwords
  1020. rep stosd ;fill whole bytes as dwords
  1021. mov [edi],al ;fill the trailing byte
  1022. inc edi
  1023. add edi,edx ;point to the next scan line
  1024. dec ebx
  1025. jnz draw_wide_w_01_loop
  1026. ret
  1027. draw_wide_w_01_loop endp
  1028. ; N-wide write-only, 0 leading bytes, 2 trailing byte.
  1029. ; EAX = # of dwords to fill
  1030. ; EBX = count of scans to fill
  1031. ; EDX = offset from end of one scan's fill to start of next
  1032. ; ESI = # of dwords to fill
  1033. ; EDI = target address to fill
  1034. draw_wide_w_02_loop proc near
  1035. mov ecx,esi ;# of whole dwords
  1036. rep stosd ;fill whole bytes as dwords
  1037. mov [edi],ax ;fill the trailing word
  1038. add edi,2
  1039. add edi,edx ;point to the next scan line
  1040. dec ebx
  1041. jnz draw_wide_w_02_loop
  1042. ret
  1043. draw_wide_w_02_loop endp
  1044. ; N-wide write-only, 0 leading bytes, 3 trailing bytes.
  1045. ; EAX = # of dwords to fill
  1046. ; EBX = count of scans to fill
  1047. ; EDX = offset from end of one scan's fill to start of next
  1048. ; ESI = # of dwords to fill
  1049. ; EDI = target address to fill
  1050. draw_wide_w_03_loop proc near
  1051. mov ecx,esi ;# of whole dwords
  1052. rep stosd ;fill whole bytes as dwords
  1053. mov [edi],ax ;fill the leading word
  1054. mov [edi+2],al ;fill the trailing byte
  1055. add edi,3
  1056. add edi,edx ;point to the next scan line
  1057. dec ebx
  1058. jnz draw_wide_w_03_loop
  1059. ret
  1060. draw_wide_w_03_loop endp
  1061. ; N-wide write-only, 1 leading byte, 0 trailing bytes.
  1062. ; EAX = # of dwords to fill
  1063. ; EBX = count of scans to fill
  1064. ; EDX = offset from end of one scan's fill to start of next
  1065. ; ESI = # of dwords to fill
  1066. ; EDI = target address to fill
  1067. draw_wide_w_10_loop proc near
  1068. mov [edi],al ;fill the leading byte
  1069. inc edi
  1070. mov ecx,esi ;# of whole dwords
  1071. rep stosd ;fill all whole bytes as dwords
  1072. add edi,edx ;point to the next scan line
  1073. dec ebx
  1074. jnz draw_wide_w_10_loop
  1075. ret
  1076. draw_wide_w_10_loop endp
  1077. ; N-wide write-only, 1 leading bytes, 1 trailing byte.
  1078. ; EAX = # of dwords to fill
  1079. ; EBX = count of scans to fill
  1080. ; EDX = offset from end of one scan's fill to start of next
  1081. ; ESI = # of dwords to fill
  1082. ; EDI = target address to fill
  1083. draw_wide_w_11_loop proc near
  1084. mov [edi],al ;fill the leading byte
  1085. inc edi
  1086. mov ecx,esi ;# of whole dwords
  1087. rep stosd ;fill whole bytes as dwords
  1088. mov [edi],al ;fill the trailing byte
  1089. inc edi
  1090. add edi,edx ;point to the next scan line
  1091. dec ebx
  1092. jnz draw_wide_w_11_loop
  1093. ret
  1094. draw_wide_w_11_loop endp
  1095. ; N-wide write-only, 1 leading bytes, 2 trailing byte.
  1096. ; EAX = # of dwords to fill
  1097. ; EBX = count of scans to fill
  1098. ; EDX = offset from end of one scan's fill to start of next
  1099. ; ESI = # of dwords to fill
  1100. ; EDI = target address to fill
  1101. draw_wide_w_12_loop proc near
  1102. mov [edi],al ;fill the leading byte
  1103. inc edi
  1104. mov ecx,esi ;# of whole dwords
  1105. rep stosd ;fill whole bytes as dwords
  1106. mov [edi],ax ;fill the trailing word
  1107. add edi,2
  1108. add edi,edx ;point to the next scan line
  1109. dec ebx
  1110. jnz draw_wide_w_12_loop
  1111. ret
  1112. draw_wide_w_12_loop endp
  1113. ; N-wide write-only, 0 leading bytes, 3 trailing bytes.
  1114. ; EAX = # of dwords to fill
  1115. ; EBX = count of scans to fill
  1116. ; EDX = offset from end of one scan's fill to start of next
  1117. ; ESI = # of dwords to fill
  1118. ; EDI = target address to fill
  1119. draw_wide_w_13_loop proc near
  1120. mov [edi],al ;fill the leading byte
  1121. inc edi
  1122. mov ecx,esi ;# of whole dwords
  1123. rep stosd ;fill whole bytes as dwords
  1124. mov [edi],ax ;fill the trailing word
  1125. mov [edi+2],al ;fill the trailing byte
  1126. add edi,3
  1127. add edi,edx ;point to the next scan line
  1128. dec ebx
  1129. jnz draw_wide_w_13_loop
  1130. ret
  1131. draw_wide_w_13_loop endp
  1132. ; N-wide write-only, 2 leading bytes, 0 trailing bytes.
  1133. ; EAX = # of dwords to fill
  1134. ; EBX = count of scans to fill
  1135. ; EDX = offset from end of one scan's fill to start of next
  1136. ; ESI = # of dwords to fill
  1137. ; EDI = target address to fill
  1138. draw_wide_w_20_loop proc near
  1139. mov [edi],ax ;fill the leading word
  1140. add edi,2
  1141. mov ecx,esi ;# of whole dwords
  1142. rep stosd ;fill all whole bytes as dwords
  1143. add edi,edx ;point to the next scan line
  1144. dec ebx
  1145. jnz draw_wide_w_20_loop
  1146. ret
  1147. draw_wide_w_20_loop endp
  1148. ; N-wide write-only, 2 leading bytess, 1 trailing byte.
  1149. ; EAX = # of dwords to fill
  1150. ; EBX = count of scans to fill
  1151. ; EDX = offset from end of one scan's fill to start of next
  1152. ; ESI = # of dwords to fill
  1153. ; EDI = target address to fill
  1154. draw_wide_w_21_loop proc near
  1155. mov [edi],ax ;fill the leading word
  1156. add edi,2
  1157. mov ecx,esi ;# of whole dwords
  1158. rep stosd ;fill whole bytes as dwords
  1159. mov [edi],al ;fill the trailing byte
  1160. inc edi
  1161. add edi,edx ;point to the next scan line
  1162. dec ebx
  1163. jnz draw_wide_w_21_loop
  1164. ret
  1165. draw_wide_w_21_loop endp
  1166. ; N-wide write-only, 2 leading bytess, 2 trailing byte.
  1167. ; EAX = # of dwords to fill
  1168. ; EBX = count of scans to fill
  1169. ; EDX = offset from end of one scan's fill to start of next
  1170. ; ESI = # of dwords to fill
  1171. ; EDI = target address to fill
  1172. draw_wide_w_22_loop proc near
  1173. mov [edi],ax ;fill the leading word
  1174. add edi,2
  1175. mov ecx,esi ;# of whole dwords
  1176. rep stosd ;fill whole bytes as dwords
  1177. mov [edi],ax ;fill the trailing word
  1178. add edi,2
  1179. add edi,edx ;point to the next scan line
  1180. dec ebx
  1181. jnz draw_wide_w_22_loop
  1182. ret
  1183. draw_wide_w_22_loop endp
  1184. ; N-wide write-only, 0 leading bytes, 3 trailing bytes.
  1185. ; EAX = # of dwords to fill
  1186. ; EBX = count of scans to fill
  1187. ; EDX = offset from end of one scan's fill to start of next
  1188. ; ESI = # of dwords to fill
  1189. ; EDI = target address to fill
  1190. draw_wide_w_23_loop proc near
  1191. mov [edi],ax ;fill the leading word
  1192. add edi,2
  1193. mov ecx,esi ;# of whole dwords
  1194. rep stosd ;fill whole bytes as dwords
  1195. mov [edi],ax ;fill the trailing word
  1196. mov [edi+2],al ;fill the trailing byte
  1197. add edi,3
  1198. add edi,edx ;point to the next scan line
  1199. dec ebx
  1200. jnz draw_wide_w_23_loop
  1201. ret
  1202. draw_wide_w_23_loop endp
  1203. ; N-wide write-only, 3 leading bytes, 0 trailing bytes.
  1204. ; EAX = # of dwords to fill
  1205. ; EBX = count of scans to fill
  1206. ; EDX = offset from end of one scan's fill to start of next
  1207. ; ESI = # of dwords to fill
  1208. ; EDI = target address to fill
  1209. draw_wide_w_30_loop proc near
  1210. mov [edi],al ;fill the leading byte
  1211. mov [edi+1],ax ;fill the leading word
  1212. add edi,3
  1213. mov ecx,esi ;# of whole dwords
  1214. rep stosd ;fill all whole bytes as dwords
  1215. add edi,edx ;point to the next scan line
  1216. dec ebx
  1217. jnz draw_wide_w_30_loop
  1218. ret
  1219. draw_wide_w_30_loop endp
  1220. ; N-wide write-only, 3 leading bytess, 1 trailing byte.
  1221. ; EAX = # of dwords to fill
  1222. ; EBX = count of scans to fill
  1223. ; EDX = offset from end of one scan's fill to start of next
  1224. ; ESI = # of dwords to fill
  1225. ; EDI = target address to fill
  1226. draw_wide_w_31_loop proc near
  1227. mov [edi],al ;fill the leading byte
  1228. mov [edi+1],ax ;fill the leading word
  1229. add edi,3
  1230. mov ecx,esi ;# of whole dwords
  1231. rep stosd ;fill whole bytes as dwords
  1232. mov [edi],al ;fill the trailing byte
  1233. inc edi
  1234. add edi,edx ;point to the next scan line
  1235. dec ebx
  1236. jnz draw_wide_w_31_loop
  1237. ret
  1238. draw_wide_w_31_loop endp
  1239. ; N-wide write-only, 3 leading bytess, 2 trailing byte.
  1240. ; EAX = # of dwords to fill
  1241. ; EBX = count of scans to fill
  1242. ; EDX = offset from end of one scan's fill to start of next
  1243. ; ESI = # of dwords to fill
  1244. ; EDI = target address to fill
  1245. draw_wide_w_32_loop proc near
  1246. mov [edi],al ;fill the leading byte
  1247. mov [edi+1],ax ;fill the leading word
  1248. add edi,3
  1249. mov ecx,esi ;# of whole dwords
  1250. rep stosd ;fill whole bytes as dwords
  1251. mov [edi],ax ;fill the trailing word
  1252. add edi,2
  1253. add edi,edx ;point to the next scan line
  1254. dec ebx
  1255. jnz draw_wide_w_32_loop
  1256. ret
  1257. draw_wide_w_32_loop endp
  1258. ; N-wide write-only, 0 leading bytes, 3 trailing bytes.
  1259. ; EAX = # of dwords to fill
  1260. ; EBX = count of scans to fill
  1261. ; EDX = offset from end of one scan's fill to start of next
  1262. ; ESI = # of dwords to fill
  1263. ; EDI = target address to fill
  1264. draw_wide_w_33_loop proc near
  1265. mov [edi],al ;fill the leading byte
  1266. mov [edi+1],ax ;fill the leading word
  1267. add edi,3
  1268. mov ecx,esi ;# of whole dwords
  1269. rep stosd ;fill whole bytes as dwords
  1270. mov [edi],ax ;fill the trailing word
  1271. mov [edi+2],al ;fill the trailing byte
  1272. add edi,3
  1273. add edi,edx ;point to the next scan line
  1274. dec ebx
  1275. jnz draw_wide_w_33_loop
  1276. ret
  1277. draw_wide_w_33_loop endp
  1278. end