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.

2251 lines
74 KiB

  1. ;---------------------------Module-Header------------------------------;
  2. ; Module Name: monopat.asm
  3. ;
  4. ; Copyright (c) 1992-1993 Microsoft Corporation. All rights reserved.
  5. ;-----------------------------------------------------------------------;
  6. ;-----------------------------------------------------------------------;
  7. ; VOID vMonoPat(ppdev, culRcl, prcl, ulMix, prb, pptlBrush)
  8. ;
  9. ; Input:
  10. ;
  11. ; ppdev - surface on which to draw
  12. ; culRcl - number of rectangles
  13. ; prcl - pointer to rectangles
  14. ; ulMix - mix mode (i.e., ROP)
  15. ; prb - pointer to realized brush
  16. ; pptlBrush - brush alignment
  17. ;
  18. ; Draws two color patterns using the VGA hardware. If the ROP is a
  19. ; PATCOPY ROP, we can light 8 pixels on every word write to VGA memory.
  20. ;
  21. ; We special case black & white patterns because we can do slightly less
  22. ; initialization, and we can handle arbitrary ROPs (although if the ROP
  23. ; has to read video memory, we can only do 4 pixels on every read/write
  24. ; operation).
  25. ;
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ; NOTE: Assumes all rectangles have positive heights and widths. Will
  29. ; not work properly if this is not the case.
  30. ;
  31. ;-----------------------------------------------------------------------;
  32. ;-----------------------------------------------------------------------;
  33. .386
  34. .model small,c
  35. assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
  36. assume fs:nothing,gs:nothing
  37. .xlist
  38. include stdcall.inc ;calling convention cmacros
  39. include i386\strucs.inc
  40. include i386\driver.inc
  41. include i386\egavga.inc
  42. include i386\ropdefs.inc
  43. .list
  44. ;-----------------------------------------------------------------------;
  45. .code
  46. ; vTrgBlt is used for 2-pass ROPs:
  47. EXTRNP vTrgBlt,24
  48. .data
  49. ; Tables shared with vgablts.asm:
  50. extrn jALUFuncTable: byte
  51. extrn jInvertDest: byte
  52. ;-----------------------------------------------------------------------;
  53. ; Bits for drawing routine look-ups.
  54. BLOCK_LEFT_EDGE equ 010000b
  55. BLOCK_RIGHT_EDGE equ 001000b
  56. BLOCK_MIDDLE_STARTS_UNALIGNED equ 000100b
  57. BLOCK_NO_MIDDLE equ 000010b
  58. BLOCK_MIDDLE_ENDS_UNALIGNED equ 000001b
  59. ;-----------------------------------------------------------------------;
  60. ; Table of drawing routines, with the look-up index a 5 bit field as
  61. ; follows:
  62. ;
  63. ; Bit 4 = 1 if a left edge must be drawn
  64. ; Bit 3 = 1 if a right edge must be drawn
  65. ; Bit 2 = 1 if middle block starts unaligned word-wise
  66. ; Bit 1 = 1 if no middle block
  67. ; Bit 0 = 1 if middle block is an odd number of bytes in length
  68. align 4
  69. gapfnSetTable label dword
  70. dd dual_wide_00_w ;00000
  71. dd dual_wide_01_w ;00001
  72. dd 0 ;00010
  73. dd 0 ;00011
  74. dd dual_wide_11_w ;00100
  75. dd dual_wide_10_w ;00101
  76. dd 0 ;00110
  77. dd 0 ;00111
  78. dd Block_01000_w ;01000
  79. dd Block_01001_w ;01001
  80. dd dual_right_0_w ;01010
  81. dd dual_right_1_w ;01011
  82. dd Block_01100_w ;01100
  83. dd Block_01101_w ;01101
  84. dd dual_right_1_w ;01110
  85. dd dual_right_0_w ;01111
  86. dd Block_10000_w ;10000
  87. dd Block_10001_w ;10001
  88. dd dual_left_0_w ;10010
  89. dd dual_left_0_w ;10011
  90. dd Block_10100_w ;10100
  91. dd Block_10101_w ;10101
  92. dd dual_left_1_w ;10110
  93. dd dual_left_1_w ;10111
  94. dd Block_11000_w ;11000
  95. dd Block_11001_w ;11001
  96. dd Block_11010_w ;11010
  97. dd 0 ;11011 - can never happen
  98. dd Block_11100_w ;11100
  99. dd Block_11101_w ;11101
  100. dd Block_11110_w ;11110
  101. dd 0 ;11111 - can never happen
  102. gapfnROPTable label dword
  103. dd dual_wide_00_rw ;00000
  104. dd dual_wide_01_rw ;00001
  105. dd 0 ;00010
  106. dd 0 ;00011
  107. dd dual_wide_11_rw ;00100
  108. dd dual_wide_10_rw ;00101
  109. dd 0 ;00110
  110. dd 0 ;00111
  111. dd Block_01000_rw ;01000
  112. dd Block_01001_rw ;01001
  113. dd dual_right_0_rw ;01010
  114. dd dual_right_1_rw ;01011
  115. dd Block_01100_rw ;01100
  116. dd Block_01101_rw ;01101
  117. dd dual_right_1_rw ;01110
  118. dd dual_right_0_rw ;01111
  119. dd Block_10000_rw ;10000
  120. dd Block_10001_rw ;10001
  121. dd dual_left_0_rw ;10010
  122. dd dual_left_0_rw ;10011
  123. dd Block_10100_rw ;10100
  124. dd Block_10101_rw ;10101
  125. dd dual_left_1_rw ;10110
  126. dd dual_left_1_rw ;10111
  127. dd Block_11000_rw ;11000
  128. dd Block_11001_rw ;11001
  129. dd Block_11010_rw ;11010
  130. dd 0 ;11011 - can never happen
  131. dd Block_11100_rw ;11100
  132. dd Block_11101_rw ;11101
  133. dd Block_11110_rw ;11110
  134. dd 0 ;11111 - can never happen
  135. gaulForceOffTable label dword
  136. dd 0 ;ignored - there is no mix 0
  137. dd 0
  138. dd 0ffffffffh
  139. dd 0ffffffffh
  140. dd 0ffffffffh
  141. dd 0ffffffffh
  142. dd 0ffffffffh
  143. dd 0ffffffffh
  144. dd 0ffffffffh
  145. dd 0ffffffffh
  146. dd 0ffffffffh
  147. dd 0
  148. dd 0ffffffffh
  149. dd 0ffffffffh
  150. dd 0ffffffffh
  151. dd 0ffffffffh
  152. dd 0ffffffffh
  153. gaulForceOnTable label dword
  154. dd 0 ;ignored - there is no mix 0
  155. dd 0
  156. dd 0
  157. dd 0
  158. dd 0
  159. dd 0
  160. dd 0ffffffffh
  161. dd 0
  162. dd 0
  163. dd 0
  164. dd 0
  165. dd 0
  166. dd 0
  167. dd 0
  168. dd 0
  169. dd 0
  170. dd 0ffffffffh
  171. gaulForceNotTable label dword
  172. dd 0 ;ignored - there is no mix 0
  173. dd 0
  174. dd 0ffffffffh
  175. dd 0ffffffffh
  176. dd 0ffffffffh
  177. dd 0
  178. dd 0
  179. dd 0
  180. dd 0ffffffffh
  181. dd 0
  182. dd 0ffffffffh
  183. dd 0
  184. dd 0ffffffffh
  185. dd 0
  186. dd 0
  187. dd 0
  188. dd 0
  189. ;-----------------------------------------------------------------------;
  190. .code
  191. ;-----------------------------------------------------------------------;
  192. ; Write thunks (for set ROPs)
  193. ;-----------------------------------------------------------------------;
  194. Block_01000_w:
  195. push offset dual_right_0_w
  196. jmp dual_wide_00_w
  197. Block_01001_w:
  198. push offset dual_right_1_w
  199. jmp dual_wide_01_w
  200. Block_01100_w:
  201. push offset dual_right_1_w
  202. jmp dual_wide_11_w
  203. Block_01101_w:
  204. push offset dual_right_0_w
  205. jmp dual_wide_10_w
  206. Block_11000_w:
  207. push offset dual_right_0_w
  208. Block_10000_w:
  209. push offset dual_left_0_w
  210. jmp dual_wide_00_w
  211. Block_11001_w:
  212. push offset dual_right_1_w
  213. Block_10001_w:
  214. push offset dual_left_0_w
  215. jmp dual_wide_01_w
  216. Block_11100_w:
  217. push offset dual_right_1_w
  218. Block_10100_w:
  219. push offset dual_left_1_w
  220. jmp dual_wide_11_w
  221. Block_11101_w:
  222. push offset dual_right_0_w
  223. Block_10101_w:
  224. push offset dual_left_1_w
  225. jmp dual_wide_10_w
  226. Block_11010_w:
  227. push offset dual_right_0_w
  228. jmp dual_left_0_w
  229. Block_11110_w:
  230. push offset dual_right_1_w
  231. jmp dual_left_1_w
  232. ;-----------------------------------------------------------------------;
  233. ; Read/write thunks (for arbitrary ROPs)
  234. ;-----------------------------------------------------------------------;
  235. Block_01000_rw:
  236. push offset dual_right_0_rw
  237. jmp dual_wide_00_rw
  238. Block_01001_rw:
  239. push offset dual_right_1_rw
  240. jmp dual_wide_01_rw
  241. Block_01100_rw:
  242. push offset dual_right_1_rw
  243. jmp dual_wide_11_rw
  244. Block_01101_rw:
  245. push offset dual_right_0_rw
  246. jmp dual_wide_10_rw
  247. Block_11000_rw:
  248. push offset dual_right_0_rw
  249. Block_10000_rw:
  250. push offset dual_left_0_rw
  251. jmp dual_wide_00_rw
  252. Block_11001_rw:
  253. push offset dual_right_1_rw
  254. Block_10001_rw:
  255. push offset dual_left_0_rw
  256. jmp dual_wide_01_rw
  257. Block_11100_rw:
  258. push offset dual_right_1_rw
  259. Block_10100_rw:
  260. push offset dual_left_1_rw
  261. jmp dual_wide_11_rw
  262. Block_11101_rw:
  263. push offset dual_right_0_rw
  264. Block_10101_rw:
  265. push offset dual_left_1_rw
  266. jmp dual_wide_10_rw
  267. Block_11010_rw:
  268. push offset dual_right_0_rw
  269. jmp dual_left_0_rw
  270. Block_11110_rw:
  271. push offset dual_right_1_rw
  272. jmp dual_left_1_rw
  273. ;-----------------------------------------------------------------------;
  274. cProc vMonoPat,24,< \
  275. uses esi edi ebx, \
  276. ppdev: ptr PDEV, \
  277. culRcl: dword, \
  278. prcl: ptr RECTL, \
  279. ulMix: dword, \
  280. prb: ptr RBRUSH,\
  281. pptlBrush: ptr POINTL >
  282. ; Variables used in block drawers:
  283. local ppfnDraw: ptr ;pointer to array of draw routines
  284. local pfnDraw: ptr ;pointer to draw routines
  285. local yBrush: dword ;current y brush alignment
  286. local yBrushOrg: dword ;original y brush alignment
  287. local ulMiddleDest: dword ;bitmap offset to middle
  288. local lMiddleDelta: dword ;delta from end of middle scan to next
  289. local ulBlockHeight: dword ;# of scans to be drawn in block
  290. local ulBlockHeightTmp: dword ;scratch copy of ulBlockHeight
  291. local cwMiddle: dword ;# of words to be written in middle
  292. local ulLeftDest: dword ;bitmap offset to left edge
  293. local ulLeftMask: dword ;plane mask for left-edge drawing
  294. local ulRightDest: dword ;bitmap offset to right edge
  295. local ulRightMask: dword ;plane mask for right-edge drawing
  296. local lDelta: dword ;delta between scans
  297. local ulCurrentDestScan: dword ;current destination scan
  298. local ulLastDestScan: dword ;last destination scan
  299. local pulPattern: ptr ;pointer to working pattern buffer
  300. ; (to account for brush inversions)
  301. local aulPatternBuffer[8]: dword ;pattern buffer
  302. local pfnLoopTop: ptr ;points to desired loop top
  303. mov esi,pptlBrush
  304. mov edi,prb
  305. mov ecx,[esi].ptl_y
  306. mov yBrushOrg,ecx ;yBrushOrg = pptlBrush->y
  307. mov ecx,[esi].ptl_x
  308. mov eax,[edi].rb_xBrush
  309. and ecx,7
  310. cmp eax,ecx
  311. jne dual_align_brush ;only align if we really have to
  312. dual_done_align_brush:
  313. test [edi].rb_fl,RBRUSH_2COLOR
  314. jnz col2_colors
  315. ; Set VGA to read mode 1 and write mode 2:
  316. mov esi,ppdev
  317. mov edx,VGA_BASE + GRAF_ADDR
  318. mov ah,byte ptr [esi].pdev_ulrm0_wmX[2]
  319. or ah,M_COLOR_READ
  320. mov al,GRAF_MODE
  321. out dx,ax ;write mode 2 to expand pattern bits to
  322. ; 0 or 0ffh per plane, read mode 1 so
  323. ; we can read 0xFF from memory always,
  324. ; for ANDing (because Color Don't Care
  325. ; is all zeros)
  326. ;-----------------------------------------------------------------------;
  327. ; Handle only black/white patterns.
  328. ;-----------------------------------------------------------------------;
  329. lea eax,[edi].rb_aulPattern
  330. mov pulPattern,eax ;pulPattern = &pbr.rb_aulPattern[0]
  331. lea eax,gapfnSetTable
  332. mov ppfnDraw,eax ;ppfnDraw = gapfnSetTable
  333. mov ecx,ulMix
  334. and ecx,0fh
  335. cmp ecx,R2_COPYPEN
  336. jne bw_init_rop ;do some more work if not copy ROP
  337. bw_done_init_rop:
  338. call dual_draw_rectangles ;draw those puppies
  339. ; All done! Restore read mode 0, write mode 0:
  340. mov esi,ppdev
  341. mov edx,VGA_BASE + GRAF_ADDR
  342. mov ah,byte ptr [esi].pdev_ulrm0_wmX[0]
  343. mov al,GRAF_MODE
  344. out dx,ax
  345. ; Enable all planes:
  346. mov edx,VGA_BASE + SEQ_DATA
  347. mov al,MM_ALL
  348. out dx,al
  349. cmp ulMix,R2_COPYPEN
  350. jne short bw_enable_set_mode
  351. cRet vMonoPat
  352. ; Set ALU function to Set mode (we don't have to bother if we had a
  353. ; COPYPEN ROP):
  354. bw_enable_set_mode:
  355. mov eax,GRAF_DATA_ROT + (DR_SET shl 8)
  356. mov edx,VGA_BASE + GRAF_ADDR
  357. out dx,ax
  358. cRet vMonoPat
  359. ;-----------------------------------------------------------------------;
  360. ; Draw both black and white and 2 color rectangles.
  361. ;-----------------------------------------------------------------------;
  362. public dual_draw_rectangles
  363. dual_draw_rectangles::
  364. mov edi,prcl ;edi = prcl
  365. mov edx,ppdev
  366. mov eax,[edi].yBottom
  367. mov ebx,[edi].yTop
  368. mov edx,[edx].pdev_lPlanarNextScan
  369. mov lDelta,edx ;lDelta = ppdev->lPlanarNextScan
  370. mov ulLastDestScan,eax ;ulLastDestScan = prcl->bottom
  371. mov ulCurrentDestScan,ebx ;ulCurrentDestScan = prcl->top
  372. mov ecx,edx
  373. imul ecx,ebx
  374. sub ebx,yBrushOrg
  375. and ebx,7
  376. mov yBrush,ebx ;yBrush = (prcl->top - pptlBrush->y) & 7
  377. ; (our current index into the pattern
  378. ; array)
  379. mov ebx,[edi].xLeft
  380. shr ebx,2
  381. add ebx,ecx ;ebx = prcl->top * lDelta +
  382. ; (prcl->left >> 2)
  383. ; (offset into bitmap of left side)
  384. mov eax,[edi].xRight
  385. shr eax,2
  386. add eax,ecx
  387. mov ulRightDest,eax ;ulRightDest = prcl->top * lDelta +
  388. ; (prcl->right >> 2)
  389. ; (offset into bitmap of right side)
  390. xor esi,esi ;zero our flags
  391. mov ecx,[edi].xLeft
  392. and ecx,3
  393. jz short dual_done_left ;skip if we don't need a left edge
  394. mov esi,0fh ;compute the plane mask for the left
  395. shl esi,cl ; edge. we don't use a look-up table
  396. mov ulLeftMask,esi ; 'cause it won't be in the cache.
  397. mov esi,(BLOCK_LEFT_EDGE shr 2)
  398. ;set our flag (we soon shift left by 2)
  399. mov ulLeftDest,ebx ;ulLeftDest = prcl->top * lDelta +
  400. ; (prcl->left >> 2)
  401. inc ebx ;ebx = ulMiddleDest = ulLeftDest + 1
  402. ; (we have to adjust our offset to
  403. ; the first whole byte)
  404. dual_done_left:
  405. sub eax,ebx ;eax = cjMiddle =
  406. ; ulRightDest - ulMiddleDest
  407. mov ulMiddleDest,ebx ;ulMiddleDest
  408. .errnz (BLOCK_MIDDLE_STARTS_UNALIGNED shr 2) - 1
  409. and ebx,1 ;set bit if middle doesn't start
  410. or esi,ebx ; word aligned (remembering we'll
  411. ; soon shift flags left by 2)
  412. mov ecx,[edi].xRight
  413. and ecx,3
  414. jz short dual_done_right ;skip if we don't need a right edge
  415. mov ebx,0f0h ;compute the plane mask for the right
  416. rol bl,cl ; edge. we don't use a look-up table
  417. mov ulRightMask,ebx ; 'cause it won't be in the cache.
  418. or esi,(BLOCK_RIGHT_EDGE shr 2)
  419. ;set our flag (we soon shift left by 2)
  420. ; If the count of whole bytes is negative, that means that the pattern
  421. ; starts and ends in the same quadpixel, so we do some more work:
  422. cmp eax,0
  423. jge short dual_done_right
  424. ; It starts and ends in the same quadpixel:
  425. and esi,not (BLOCK_RIGHT_EDGE shr 2)
  426. ;turn off right edge
  427. and ebx,ulLeftMask
  428. mov ulLeftMask,ebx
  429. xor eax,eax ;we do zero middle bytes
  430. public dual_done_right
  431. dual_done_right::
  432. mov ebx,ppfnDraw
  433. ; We're going to do two 'adc esi,esi' instructions here, effectively
  434. ; shifting our flags left by 2, and setting the low bits:
  435. .errnz (BLOCK_NO_MIDDLE shr 1) - 1
  436. cmp eax,1 ;shift flags left one, and set low
  437. adc esi,esi ; bit if we don't need to do a middle
  438. .errnz (BLOCK_MIDDLE_ENDS_UNALIGNED) - 1
  439. shr eax,1
  440. adc esi,esi ;shift flags left one, and set low
  441. ; bit if the middle isn't an even
  442. ; number of bytes in length
  443. mov cwMiddle,eax ;cwMiddle = cjMiddle / 2
  444. sub edx,eax
  445. sub edx,eax
  446. mov lMiddleDelta,edx ;lMiddleDelta = lDelta - 2 * cwMiddle
  447. mov eax,[ebx+esi*4]
  448. mov pfnDraw,eax ;pointer to function that draws
  449. ; everything in the bank
  450. mov ebx,ppdev
  451. mov edi,[edi].yTop
  452. cmp edi,[ebx].pdev_rcl1PlanarClip.yTop
  453. jl short dual_map_init_bank
  454. cmp edi,[ebx].pdev_rcl1PlanarClip.yBottom
  455. jl short dual_init_bank_mapped
  456. dual_map_init_bank:
  457. ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
  458. <ebx,edi,JustifyTop>
  459. dual_init_bank_mapped:
  460. mov eax,ulLastDestScan
  461. mov ebx,[ebx].pdev_rcl1PlanarClip.yBottom
  462. sub eax,ebx
  463. sbb ecx,ecx
  464. and ecx,eax
  465. add ebx,ecx ;ebx = min(ulLastDestScan,
  466. ; ppdev->rcl1PlanarClip.yBottom)
  467. mov ulCurrentDestScan,ebx
  468. sub ebx,edi
  469. mov ulBlockHeight,ebx ;ulBlockHeight = ebx - ulCurrentDestScan
  470. ; Draw everything in this bank:
  471. call pfnDraw
  472. dual_done_pfnDraw:
  473. mov edi,ulCurrentDestScan
  474. cmp edi,ulLastDestScan
  475. jge short dual_next_rectangle
  476. ; Get the next bank:
  477. mov ebx,ppdev
  478. mov yBrush,esi ;make sure we record the new brush
  479. ; alignment
  480. ; Map the next bank into window.
  481. ; Note: EBX, ESI, and EDI are preserved, according to C calling conventions.
  482. ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
  483. <ebx,edi,JustifyTop>
  484. jmp short dual_init_bank_mapped
  485. ;-----------------------------------------------------------------------;
  486. ; Done rectangle.
  487. ;-----------------------------------------------------------------------;
  488. public dual_next_rectangle
  489. dual_next_rectangle::
  490. add prcl, size RECTL
  491. dec culRcl
  492. jg dual_draw_rectangles ;do more rectangles
  493. PLAIN_RET ;return
  494. ;-----------------------------------------------------------------------;
  495. ; Handle x-brush alignment.
  496. ;-----------------------------------------------------------------------;
  497. public dual_align_brush
  498. dual_align_brush::
  499. ; Align the pattern on x. Remember it in the realized brush, because if
  500. ; the brush is used again, it's likely to have the same alignment...
  501. mov [edi].rb_xBrush,ecx ;remember our new alignment
  502. sub ecx,eax ;rotate pattern left by
  503. ; pptlBrush->x - prb->xBrush
  504. ; We keep each row of the pattern in the low word of each dword. If the
  505. ; bits are to appear on the screen as 01234567, the word of our pattern
  506. ; has the bits 32107654|76543210 -- we're in write mode 3, and when
  507. ; written as a word, this results in 3210 being written in the first
  508. ; byte, and 7654 in the second byte.
  509. ;
  510. ; For our funky plaanr format, we just rotate each byte of the word left by
  511. ; 'cl' to get the desired result.
  512. rol byte ptr [edi][0].rb_aulPattern,cl ;0
  513. rol byte ptr [edi][1].rb_aulPattern,cl
  514. rol byte ptr [edi][4].rb_aulPattern,cl ;1
  515. rol byte ptr [edi][5].rb_aulPattern,cl
  516. rol byte ptr [edi][8].rb_aulPattern,cl ;2
  517. rol byte ptr [edi][9].rb_aulPattern,cl
  518. rol byte ptr [edi][12].rb_aulPattern,cl ;3
  519. rol byte ptr [edi][13].rb_aulPattern,cl
  520. rol byte ptr [edi][16].rb_aulPattern,cl ;4
  521. rol byte ptr [edi][17].rb_aulPattern,cl
  522. rol byte ptr [edi][20].rb_aulPattern,cl ;5
  523. rol byte ptr [edi][21].rb_aulPattern,cl
  524. rol byte ptr [edi][24].rb_aulPattern,cl ;6
  525. rol byte ptr [edi][25].rb_aulPattern,cl
  526. rol byte ptr [edi][28].rb_aulPattern,cl ;7
  527. rol byte ptr [edi][29].rb_aulPattern,cl
  528. jmp dual_done_align_brush
  529. ;-----------------------------------------------------------------------;
  530. ; Handle arbitrary ROPs for black/white patterns.
  531. ;-----------------------------------------------------------------------;
  532. ; Expect:
  533. ;
  534. ; ecx = ulMix
  535. public bw_init_rop
  536. bw_init_rop::
  537. cmp jInvertDest[ecx],0
  538. je short bw_set_that_ALU ;skip if don't need 2 passes
  539. ; For some ROPs, we have to invert the destination first, then do another
  540. ; operation (that is, it's a 2-pass ROP). We handle the inversion here:
  541. cCall vTrgBlt,<ppdev, culRcl, prcl, R2_NOT, 0, 0>
  542. mov ecx,ulMix
  543. and ecx,0fh
  544. bw_set_that_ALU:
  545. mov ah,jALUFuncTable[ecx]
  546. cmp ah,DR_SET
  547. je short bw_that_ALU_is_set
  548. ;we're already in Set mode
  549. mov edx,VGA_BASE + GRAF_ADDR
  550. mov al,GRAF_DATA_ROT
  551. out dx,ax ;set the ALU logical function
  552. lea ebx,gapfnROPTable
  553. mov ppfnDraw,ebx
  554. bw_that_ALU_is_set:
  555. lea esi,aulPatternBuffer
  556. mov pulPattern,esi ;we're using the temporary buffer
  557. mov ebx,gaulForceOffTable[ecx*4]
  558. mov edx,gaulForceOnTable[ecx*4]
  559. mov esi,gaulForceNotTable[ecx*4]
  560. mov eax,[edi][0].rb_aulPattern ;0
  561. and eax,ebx
  562. or eax,edx
  563. xor eax,esi
  564. mov [aulPatternBuffer][0],eax
  565. mov eax,[edi][4].rb_aulPattern ;1
  566. and eax,ebx
  567. or eax,edx
  568. xor eax,esi
  569. mov [aulPatternBuffer][4],eax
  570. mov eax,[edi][8].rb_aulPattern ;2
  571. and eax,ebx
  572. or eax,edx
  573. xor eax,esi
  574. mov [aulPatternBuffer][8],eax
  575. mov eax,[edi][12].rb_aulPattern ;3
  576. and eax,ebx
  577. or eax,edx
  578. xor eax,esi
  579. mov [aulPatternBuffer][12],eax
  580. mov eax,[edi][16].rb_aulPattern ;4
  581. and eax,ebx
  582. or eax,edx
  583. xor eax,esi
  584. mov [aulPatternBuffer][16],eax
  585. mov eax,[edi][20].rb_aulPattern ;5
  586. and eax,ebx
  587. or eax,edx
  588. xor eax,esi
  589. mov [aulPatternBuffer][20],eax
  590. mov eax,[edi][24].rb_aulPattern ;6
  591. and eax,ebx
  592. or eax,edx
  593. xor eax,esi
  594. mov [aulPatternBuffer][24],eax
  595. mov eax,[edi][28].rb_aulPattern ;7
  596. and eax,ebx
  597. or eax,edx
  598. xor eax,esi
  599. mov [aulPatternBuffer][28],eax
  600. jmp bw_done_init_rop
  601. ;-----------------------------------------------------------------------;
  602. ; Handle 2-color patterns.
  603. ;-----------------------------------------------------------------------;
  604. public col2_colors
  605. col2_colors::
  606. lea eax,[edi].rb_aulPattern
  607. mov pulPattern,eax ;pulPattern = &pbr.rb_aulPattern[0]
  608. lea eax,gapfnSetTable
  609. mov ppfnDraw,eax ;ppfnDraw = gapfnSetTable
  610. call col2_first_rectangle
  611. ; Restore VGA hardware to its default state:
  612. mov edx,VGA_BASE + GRAF_DATA
  613. mov al,0ffh
  614. out dx,al ;enable all bits through the Bit Mask
  615. mov esi,ppdev
  616. dec edx ;point back to the Graphics Index reg
  617. mov ah,byte ptr [esi].pdev_ulrm0_wmX[0]
  618. ;write mode 0 setting for Graphics Mode
  619. mov al,GRAF_MODE
  620. out dx,ax ;write mode 0, read mode 0
  621. mov eax,GRAF_DATA_ROT + (DR_SET SHL 8)
  622. out dx,ax ;replace mode, no rotate
  623. mov edx,VGA_BASE + SEQ_DATA
  624. mov al,MM_ALL
  625. out dx,al ;enable all planes
  626. cRet vMonoPat
  627. ;-----------------------------------------------------------------------;
  628. ; Handle first rectangle for 2-color patterns.
  629. ;-----------------------------------------------------------------------;
  630. ; We have to special case the first rectangle because we have to load
  631. ; the latches with the background color after mapping the bank but before
  632. ; doing any drawing.
  633. public col2_first_rectangle
  634. col2_first_rectangle::
  635. mov edi,prcl ;edi = prcl
  636. mov edx,ppdev
  637. mov eax,[edi].yBottom
  638. mov ebx,[edi].yTop
  639. mov edx,[edx].pdev_lPlanarNextScan
  640. mov lDelta,edx ;lDelta = ppdev->lPlanarNextScan
  641. mov ulLastDestScan,eax ;ulLastDestScan = prcl->bottom
  642. mov ulCurrentDestScan,ebx ;ulCurrentDestScan = prcl->top
  643. mov ecx,edx
  644. imul ecx,ebx
  645. sub ebx,yBrushOrg
  646. and ebx,7
  647. mov yBrush,ebx ;yBrush = (prcl->top - pptlBrush->y) & 7
  648. ; (our current index into the pattern
  649. ; array)
  650. mov ebx,[edi].xLeft
  651. shr ebx,2
  652. add ebx,ecx ;ebx = prcl->top * lDelta +
  653. ; (prcl->left >> 2)
  654. ; (offset into bitmap of left side)
  655. mov eax,[edi].xRight
  656. shr eax,2
  657. add eax,ecx
  658. mov ulRightDest,eax ;ulRightDest = prcl->top * lDelta +
  659. ; (prcl->right >> 2)
  660. ; (offset into bitmap of right side)
  661. xor esi,esi ;zero our flags
  662. mov ecx,[edi].xLeft
  663. and ecx,3
  664. jz short col2_done_left ;skip if we don't need a left edge
  665. mov esi,0fh ;compute the plane mask for the left
  666. shl esi,cl ; edge. we don't use a look-up table
  667. mov ulLeftMask,esi ; 'cause it won't be in the cache.
  668. mov esi,(BLOCK_LEFT_EDGE shr 2)
  669. ;set our flag (we soon shift left by 2)
  670. mov ulLeftDest,ebx ;ulLeftDest = prcl->top * lDelta +
  671. ; (prcl->left >> 2)
  672. inc ebx ;ebx = ulMiddleDest = ulLeftDest + 1
  673. ; (we have to adjust our offset to
  674. ; the first whole byte)
  675. col2_done_left:
  676. sub eax,ebx ;eax = cjMiddle =
  677. ; ulRightDest - ulMiddleDest
  678. mov ulMiddleDest,ebx ;ulMiddleDest
  679. .errnz (BLOCK_MIDDLE_STARTS_UNALIGNED shr 2) - 1
  680. and ebx,1 ;set bit if middle doesn't start
  681. or esi,ebx ; word aligned (remembering we'll
  682. ; soon shift flags left by 2)
  683. mov ecx,[edi].xRight
  684. and ecx,3
  685. jz short col2_done_right ;skip if we don't need a right edge
  686. mov ebx,0f0h ;compute the plane mask for the right
  687. rol bl,cl ; edge. we don't use a look-up table
  688. mov ulRightMask,ebx ; 'cause it won't be in the cache.
  689. or esi,(BLOCK_RIGHT_EDGE shr 2)
  690. ;set our flag (we soon shift left by 2)
  691. ; If the count of whole bytes is negative, that means that the pattern
  692. ; starts and ends in the same quadpixel, so we do some more work:
  693. cmp eax,0
  694. jge short col2_done_right
  695. ; It starts and ends in the same quadpixel:
  696. and esi,not (BLOCK_RIGHT_EDGE shr 2)
  697. ;turn off right edge
  698. and ebx,ulLeftMask
  699. mov ulLeftMask,ebx
  700. xor eax,eax ;we do zero middle bytes
  701. public col2_done_right
  702. col2_done_right::
  703. mov ebx,ppfnDraw
  704. ; We're going to do two 'adc esi,esi' instructions here, effectively
  705. ; shifting our flags left by 2, and setting the low bits:
  706. .errnz (BLOCK_NO_MIDDLE shr 1) - 1
  707. cmp eax,1 ;shift flags left one, and set low
  708. adc esi,esi ; bit if we don't need to do a middle
  709. .errnz (BLOCK_MIDDLE_ENDS_UNALIGNED) - 1
  710. shr eax,1
  711. mov cwMiddle,eax ;cwMiddle = cjMiddle / 2
  712. adc esi,esi ;shift flags left one, and set low
  713. ; bit if the middle isn't an even
  714. ; number of bytes in length
  715. sub edx,eax
  716. sub edx,eax
  717. mov lMiddleDelta,edx ;lMiddleDelta = lDelta - 2 * cwMiddle
  718. mov eax,[ebx+esi*4]
  719. mov pfnDraw,eax ;pointer to function that draws
  720. ; everything in the bank
  721. mov ebx,ppdev
  722. test esi,BLOCK_NO_MIDDLE
  723. jz short col2_have_a_middle
  724. ;-----------------------------------------;
  725. ; Handle case where there isn't a whole quadpixel that will be overwritten
  726. ; by the pattern, and so we don't have a convenient place for loading the
  727. ; latches. For this case, we'll use off-screen memory.
  728. mov esi,[ebx].pdev_pbceCache
  729. mov eax,[esi].bce_yCache
  730. cmp eax,[ebx].pdev_rcl1PlanarClip.yTop
  731. jl short col2_no_middle_map_brush_bank
  732. cmp eax,[ebx].pdev_rcl1PlanarClip.yBottom
  733. jl short col2_no_middle_brush_bank_mapped
  734. col2_no_middle_map_brush_bank:
  735. ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
  736. <ebx,eax,JustifyBottom>
  737. col2_no_middle_brush_bank_mapped:
  738. mov ecx,prb ;ecx = prb
  739. mov esi,[esi].bce_ulCache
  740. add esi,[ebx].pdev_pvBitmapStart
  741. mov eax,[ecx].rb_ulBkColor
  742. mov [esi],al
  743. mov al,[esi] ;latches now laoded with bk color
  744. mov edi,[edi].yTop
  745. cmp edi,[ebx].pdev_rcl1PlanarClip.yTop
  746. jl short col2_no_middle_map_init_bank
  747. cmp edi,[ebx].pdev_rcl1PlanarClip.yBottom
  748. jl col2_latches_loaded
  749. col2_no_middle_map_init_bank:
  750. ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
  751. <ebx,edi,JustifyTop>
  752. mov ecx,prb ;reload ecx = prb
  753. jmp col2_latches_loaded
  754. ;-----------------------------------------;
  755. col2_have_a_middle:
  756. mov edi,[edi].yTop
  757. cmp edi,[ebx].pdev_rcl1PlanarClip.yTop
  758. jl short col2_map_init_bank
  759. cmp edi,[ebx].pdev_rcl1PlanarClip.yBottom
  760. jl short col2_init_bank_mapped
  761. col2_map_init_bank:
  762. ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
  763. <ebx,edi,JustifyTop>
  764. col2_init_bank_mapped:
  765. mov ecx,prb ;ecx = prb
  766. mov esi,ulMiddleDest
  767. add esi,[ebx].pdev_pvBitmapStart
  768. ;pointer to the first whole quadpixel
  769. ; that will be overwritten by the
  770. ; pattern, and so which is a great
  771. ; place to use to load the latches
  772. mov eax,[ecx].rb_ulBkColor
  773. mov [esi],al
  774. mov al,[esi] ;latches now loaded with bk color
  775. ; Set VGA to read mode 0 and write mode 2:
  776. col2_latches_loaded:
  777. ; ebx = ppdev
  778. ; ecx = prb
  779. ; edi = top line of rectangle
  780. mov esi,ppdev
  781. mov edx,VGA_BASE + GRAF_ADDR
  782. mov ah,byte ptr [esi].pdev_ulrm0_wmX[2]
  783. mov al,GRAF_MODE
  784. out dx,ax
  785. mov eax,GRAF_DATA_ROT + (DR_XOR SHL 8)
  786. out dx,ax ;XOR to flip latched data to make ~bk
  787. mov ah,byte ptr [ecx].rb_ulBkColor
  788. xor ah,byte ptr [ecx].rb_ulFgColor
  789. mov al,GRAF_BIT_MASK
  790. out dx,ax ;pass through common fg & bk bits
  791. ; unchanged from bk color in latches;
  792. ; non-common bits come from XOR in the
  793. ; ALUs, flipped from the bk to the fg
  794. ; state if the glyph bit for the pixel
  795. ; in that plane is 1, still in bk state
  796. ; if the glyph bit for that plane is 0
  797. ; All done hardware initialization. Do rest of this boring stuff:
  798. mov eax,ulLastDestScan
  799. mov ebx,[ebx].pdev_rcl1PlanarClip.yBottom
  800. sub eax,ebx
  801. sbb ecx,ecx
  802. and ecx,eax
  803. add ebx,ecx ;ebx = min(ulLastDestScan,
  804. ; ppdev->rcl1PlanarClip.yBottom)
  805. mov ulCurrentDestScan,ebx
  806. sub ebx,edi
  807. mov ulBlockHeight,ebx ;ulBlockHeight = ebx - ulCurrentDestScan
  808. ; Draw everything in this bank:
  809. CALL_AND_JUMP pfnDraw,dual_done_pfnDraw
  810. ;=======================================================================;
  811. ;========================= Set Block Drawers ===========================;
  812. ;=======================================================================;
  813. ;-----------------------------------------------------------------------;
  814. ; dual_wide_11_w
  815. ;
  816. ; Draws middle words with 1 leading byte and 1 trailing byte.
  817. ;
  818. ; Input:
  819. ; ppdev - pointer to physical device structure
  820. ; ulBlockHeight - # of scans to draw
  821. ; lMiddleDelta - distance from end of current scan to start of next
  822. ; ulMiddleDest - offset in bitmap at which to start drawing
  823. ; yBrush - current y brush alignment
  824. ; cwMiddle - # of words to draw on each scan
  825. ;
  826. ; Output:
  827. ; esi - new y brush alignment
  828. ; ulMiddleDest - new bitmap offset
  829. ;-----------------------------------------------------------------------;
  830. public dual_wide_11_w
  831. dual_wide_11_w::
  832. ; We only have to reset which planes are enabled if we do edges too:
  833. mov edx,VGA_BASE + SEQ_DATA
  834. mov al,MM_ALL
  835. out dx,al
  836. ; Calculate full start addresses:
  837. mov edi,ppdev
  838. mov ebx,ulBlockHeight
  839. mov ulBlockHeightTmp,ebx
  840. mov ebx,pulPattern
  841. mov edx,lMiddleDelta
  842. add edx,2 ;account for first and last
  843. ; bytes
  844. mov esi,yBrush
  845. mov edi,[edi].pdev_pvBitmapStart
  846. add edi,ulMiddleDest
  847. inc edi ;align to word
  848. ; EBX = pointer to start of pattern
  849. ; EDX = offset from end of scan to start of next
  850. ; ESI = current offset into pattern
  851. ; EDI = target address to which to write
  852. dual_wide_11_w_loop:
  853. ; We aim to overdrive.
  854. mov eax,[ebx+esi * 4] ;load pattern for this scan
  855. mov [edi-1],ah ;write the first byte
  856. mov ecx,cwMiddle
  857. dec ecx ;account for first and last
  858. ; bytes
  859. rep stosw ;light 8 pels on every write
  860. inc esi ;advance to next scan of pattern
  861. and esi,7
  862. mov [edi],al ;write that last byte
  863. add edi,edx ;advance to next scan
  864. dec ulBlockHeightTmp
  865. jnz short dual_wide_11_w_loop
  866. ; get ready for next time:
  867. mov ecx,ppdev
  868. sub edi,[ecx].pdev_pvBitmapStart
  869. dec edi ;undo our word alignment
  870. mov ulMiddleDest,edi
  871. PLAIN_RET
  872. ;-----------------------------------------------------------------------;
  873. ; dual_wide_10_w
  874. ;
  875. ; Draws middle words with 1 leading byte and 0 trailing bytes.
  876. ;
  877. ; Input:
  878. ; ppdev - pointer to physical device structure
  879. ; ulBlockHeight - # of scans to draw
  880. ; lMiddleDelta - distance from end of current scan to start of next
  881. ; ulMiddleDest - offset in bitmap at which to start drawing
  882. ; yBrush - current y brush alignment
  883. ; cwMiddle - # of words to draw on each scan
  884. ;
  885. ; Output:
  886. ; esi - new y brush alignment
  887. ; ulMiddleDest - new bitmap offset
  888. ;-----------------------------------------------------------------------;
  889. public dual_wide_10_w
  890. dual_wide_10_w::
  891. ; We only have to reset which planes are enabled if we do edges too:
  892. mov edx,VGA_BASE + SEQ_DATA
  893. mov al,MM_ALL
  894. out dx,al
  895. ; Calculate full start addresses:
  896. mov edi,ppdev
  897. mov ebx,ulBlockHeight
  898. mov ulBlockHeightTmp,ebx
  899. mov ebx,pulPattern
  900. mov edx,lMiddleDelta
  901. mov esi,yBrush
  902. mov edi,[edi].pdev_pvBitmapStart
  903. add edi,ulMiddleDest
  904. inc edi ;align to word
  905. ; EBX = pointer to start of pattern
  906. ; EDX = offset from end of scan to start of next
  907. ; ESI = current offset into pattern
  908. ; EDI = target address to which to write
  909. dual_wide_10_w_loop:
  910. mov eax,[ebx+esi * 4] ;load pattern for this scan
  911. mov [edi-1],ah ;write the first byte
  912. mov ecx,cwMiddle
  913. rep stosw ;light 8 pels on every write
  914. inc esi ;advance to next scan of pattern
  915. and esi,7
  916. add edi,edx ;advance to next scan
  917. dec ulBlockHeightTmp
  918. jnz short dual_wide_10_w_loop
  919. ; get ready for next time:
  920. mov ecx,ppdev
  921. sub edi,[ecx].pdev_pvBitmapStart
  922. dec edi ;undo our word alignment
  923. mov ulMiddleDest,edi
  924. PLAIN_RET
  925. ;-----------------------------------------------------------------------;
  926. ; dual_wide_01_w
  927. ;
  928. ; Draws middle words with 0 leading bytes and 1 trailing byte.
  929. ;
  930. ; Input:
  931. ; ppdev - pointer to physical device structure
  932. ; ulBlockHeight - # of scans to draw
  933. ; lMiddleDelta - distance from end of current scan to start of next
  934. ; ulMiddleDest - offset in bitmap at which to start drawing
  935. ; yBrush - current y brush alignment
  936. ; cwMiddle - # of words to draw on each scan
  937. ;
  938. ; Output:
  939. ; esi - new y brush alignment
  940. ; ulMiddleDest - new bitmap offset
  941. ;-----------------------------------------------------------------------;
  942. public dual_wide_01_w
  943. dual_wide_01_w::
  944. ; We only have to reset which planes are enabled if we do edges too:
  945. mov edx,VGA_BASE + SEQ_DATA
  946. mov al,MM_ALL
  947. out dx,al
  948. ; Calculate full start addresses:
  949. mov edi,ppdev
  950. mov ebx,ulBlockHeight
  951. mov ulBlockHeightTmp,ebx
  952. mov ebx,pulPattern
  953. mov edx,lMiddleDelta
  954. mov esi,yBrush
  955. mov edi,[edi].pdev_pvBitmapStart
  956. add edi,ulMiddleDest
  957. ; EBX = pointer to start of pattern
  958. ; EDX = offset from end of scan to start of next
  959. ; ESI = current offset into pattern
  960. ; EDI = target address to which to write
  961. dual_wide_01_w_loop:
  962. mov eax,[ebx+esi*4] ;load pattern for this scan
  963. mov ecx,cwMiddle
  964. rep stosw ;light 8 pels on every write
  965. inc esi ;advance to next scan of pattern
  966. and esi,7
  967. mov [edi],al ;write that last byte
  968. add edi,edx ;advance to next scan
  969. dec ulBlockHeightTmp
  970. jnz short dual_wide_01_w_loop
  971. ; get ready for next time:
  972. mov ecx,ppdev
  973. sub edi,[ecx].pdev_pvBitmapStart
  974. mov ulMiddleDest,edi
  975. PLAIN_RET
  976. ;-----------------------------------------------------------------------;
  977. ; dual_wide_00_w
  978. ;
  979. ; Draws middle words with 0 leading bytes and 1 trailing byte.
  980. ;
  981. ; Input:
  982. ; ppdev - pointer to physical device structure
  983. ; ulBlockHeight - # of scans to draw
  984. ; lMiddleDelta - distance from end of current scan to start of next
  985. ; ulMiddleDest - offset in bitmap at which to start drawing
  986. ; yBrush - current y brush alignment
  987. ; cwMiddle - # of words to draw on each scan
  988. ;
  989. ; Output:
  990. ; esi - new y brush alignment
  991. ; ulMiddleDest - new bitmap offset
  992. ;-----------------------------------------------------------------------;
  993. public dual_wide_00_w
  994. dual_wide_00_w::
  995. ; We only have to reset which planes are enabled if we do edges too:
  996. mov edx,VGA_BASE + SEQ_DATA
  997. mov al,MM_ALL
  998. out dx,al
  999. ; Calculate full start addresses:
  1000. mov edi,ppdev
  1001. mov ebx,ulBlockHeight
  1002. mov ulBlockHeightTmp,ebx
  1003. mov ebx,pulPattern
  1004. mov edx,lMiddleDelta
  1005. mov esi,yBrush
  1006. mov edi,[edi].pdev_pvBitmapStart
  1007. add edi,ulMiddleDest
  1008. ; EBX = pointer to start of pattern
  1009. ; EDX = offset from end of scan to start of next
  1010. ; ESI = current offset into pattern
  1011. ; EDI = target address to which to write
  1012. dual_wide_00_w_loop:
  1013. mov eax,[ebx+esi*4] ;load pattern for this scan
  1014. mov ecx,cwMiddle
  1015. rep stosw ;light 8 pels on every write
  1016. inc esi ;advance to next scan of pattern
  1017. and esi,7
  1018. add edi,edx ;advance to next scan
  1019. dec ulBlockHeightTmp
  1020. jnz short dual_wide_00_w_loop
  1021. ; get ready for next time:
  1022. mov ecx,ppdev
  1023. sub edi,[ecx].pdev_pvBitmapStart
  1024. mov ulMiddleDest,edi
  1025. PLAIN_RET
  1026. ;-----------------------------------------------------------------------;
  1027. ; dual_left_1_w
  1028. ;
  1029. ; Draws a left edge when the next byte is not word aligned.
  1030. ;
  1031. ; Input:
  1032. ; ppdev - pointer to physical device structure
  1033. ; ulBlockHeight - # of scans to draw
  1034. ; lDelta - distance from end of current scan to start of next
  1035. ; ulLeftDest - offset in bitmap at which to start drawing
  1036. ; yBrush - current y brush alignment
  1037. ;
  1038. ; Output:
  1039. ; esi - new y brush alignment
  1040. ; ulLeftDest - new bitmap offset
  1041. ;-----------------------------------------------------------------------;
  1042. public dual_left_1_w
  1043. dual_left_1_w::
  1044. ; Set left mask by disabling some planes:
  1045. mov edx,VGA_BASE + SEQ_DATA
  1046. mov eax,ulLeftMask
  1047. out dx,al
  1048. ; Calculate full start addresses:
  1049. mov edi,ppdev
  1050. mov ebx,ulBlockHeight
  1051. mov ecx,pulPattern
  1052. mov edx,lDelta
  1053. mov esi,yBrush
  1054. mov edi,[edi].pdev_pvBitmapStart
  1055. add edi,ulLeftDest
  1056. ; EBX = count of loop iterations
  1057. ; ECX = pointer to start of pattern
  1058. ; EDX = offset to next scan
  1059. ; ESI = current offset into pattern
  1060. ; EDI = target address to which to write
  1061. dual_left_1_w_loop:
  1062. mov eax,[ecx+esi*4] ;load pattern for this scan
  1063. mov [edi],al ;write the low byte
  1064. inc esi ;advance to next scan of pattern
  1065. and esi,7
  1066. add edi,edx ;advance to next scan
  1067. dec ebx
  1068. jnz short dual_left_1_w_loop
  1069. ; get ready for next time:
  1070. mov ecx,ppdev
  1071. sub edi,[ecx].pdev_pvBitmapStart
  1072. mov ulLeftDest,edi
  1073. PLAIN_RET
  1074. ;-----------------------------------------------------------------------;
  1075. ; dual_left_0_w
  1076. ;
  1077. ; Draws a left edge when the next byte is word aligned.
  1078. ;
  1079. ; Input:
  1080. ; ppdev - pointer to physical device structure
  1081. ; ulBlockHeight - # of scans to draw
  1082. ; lDelta - distance from end of current scan to start of next
  1083. ; ulLeftDest - offset in bitmap at which to start drawing
  1084. ; yBrush - current y brush alignment
  1085. ;
  1086. ; Output:
  1087. ; esi - new y brush alignment
  1088. ; ulLeftDest - new bitmap offset
  1089. ;-----------------------------------------------------------------------;
  1090. public dual_left_0_w
  1091. dual_left_0_w::
  1092. ; Set left mask by disabling some planes:
  1093. mov edx,VGA_BASE + SEQ_DATA
  1094. mov eax,ulLeftMask
  1095. out dx,al
  1096. ; Calculate full start addresses:
  1097. mov edi,ppdev
  1098. mov ebx,ulBlockHeight
  1099. mov ecx,pulPattern
  1100. mov edx,lDelta
  1101. mov esi,yBrush
  1102. mov edi,[edi].pdev_pvBitmapStart
  1103. add edi,ulLeftDest
  1104. ; EBX = count of loop iterations
  1105. ; ECX = pointer to start of pattern
  1106. ; EDX = offset to next scan
  1107. ; ESI = current offset into pattern
  1108. ; EDI = target address to which to write
  1109. dual_left_0_w_loop:
  1110. mov eax,[ecx+esi*4] ;load pattern for this scan
  1111. mov [edi],ah ;write the high byte
  1112. inc esi ;advance to next scan of pattern
  1113. and esi,7
  1114. add edi,edx ;advance to next scan
  1115. dec ebx
  1116. jnz short dual_left_0_w_loop
  1117. ; get ready for next time:
  1118. mov ecx,ppdev
  1119. sub edi,[ecx].pdev_pvBitmapStart
  1120. mov ulLeftDest,edi
  1121. PLAIN_RET
  1122. ;-----------------------------------------------------------------------;
  1123. ; dual_right_1_w
  1124. ;
  1125. ; Draws a right edge when not word aligned.
  1126. ;
  1127. ; Input:
  1128. ; ppdev - pointer to physical device structure
  1129. ; ulBlockHeight - # of scans to draw
  1130. ; lDelta - distance from end of current scan to start of next
  1131. ; ulRightDest - offset in bitmap at which to start drawing
  1132. ; yBrush - current y brush alignment
  1133. ;
  1134. ; Output:
  1135. ; esi - new y brush alignment
  1136. ; ulRightDest - new bitmap offset
  1137. ;-----------------------------------------------------------------------;
  1138. public dual_right_1_w
  1139. dual_right_1_w::
  1140. ; Set right mask by disabling some planes:
  1141. mov edx,VGA_BASE + SEQ_DATA
  1142. mov eax,ulRightMask
  1143. out dx,al
  1144. ; Calculate full start addresses:
  1145. mov edi,ppdev
  1146. mov ebx,ulBlockHeight
  1147. mov ecx,pulPattern
  1148. mov edx,lDelta
  1149. mov esi,yBrush
  1150. mov edi,[edi].pdev_pvBitmapStart
  1151. add edi,ulRightDest
  1152. ; EBX = count of loop iterations
  1153. ; ECX = pointer to start of pattern
  1154. ; EDX = offset to next scan
  1155. ; ESI = current offset into pattern
  1156. ; EDI = target address to which to write
  1157. dual_right_1_w_loop:
  1158. mov eax,[ecx+esi*4] ;load pattern for this scan
  1159. mov [edi],ah ;write the high byte
  1160. inc esi ;advance to next scan of pattern
  1161. and esi,7
  1162. add edi,edx ;advance to next scan
  1163. dec ebx
  1164. jnz short dual_right_1_w_loop
  1165. ; get ready for next time:
  1166. mov ecx,ppdev
  1167. sub edi,[ecx].pdev_pvBitmapStart
  1168. mov ulRightDest,edi
  1169. PLAIN_RET
  1170. ;-----------------------------------------------------------------------;
  1171. ; dual_right_0_w
  1172. ;
  1173. ; Draws a right edge when word aligned.
  1174. ;
  1175. ; Input:
  1176. ; ppdev - pointer to physical device structure
  1177. ; ulBlockHeight - # of scans to draw
  1178. ; lDelta - distance from end of current scan to start of next
  1179. ; ulRightDest - offset in bitmap at which to start drawing
  1180. ; yBrush - current y brush alignment
  1181. ;
  1182. ; Output:
  1183. ; esi - new y brush alignment
  1184. ; ulRightDest - new bitmap offset
  1185. ;-----------------------------------------------------------------------;
  1186. public dual_right_0_w
  1187. dual_right_0_w::
  1188. ; Set right mask by disabling some planes:
  1189. mov edx,VGA_BASE + SEQ_DATA
  1190. mov eax,ulRightMask
  1191. out dx,al
  1192. ; Calculate full start addresses:
  1193. mov edi,ppdev
  1194. mov ebx,ulBlockHeight
  1195. mov ecx,pulPattern
  1196. mov edx,lDelta
  1197. mov esi,yBrush
  1198. mov edi,[edi].pdev_pvBitmapStart
  1199. add edi,ulRightDest
  1200. ; EBX = count of loop iterations
  1201. ; ECX = pointer to start of pattern
  1202. ; EDX = offset to next scan
  1203. ; ESI = current offset into pattern
  1204. ; EDI = target address to which to write
  1205. dual_right_0_w_loop:
  1206. mov eax,[ecx+esi*4] ;load pattern for this scan
  1207. mov [edi],al ;write the low byte
  1208. inc esi ;advance to next scan of pattern
  1209. and esi,7
  1210. add edi,edx ;advance to next scan
  1211. dec ebx
  1212. jnz short dual_right_0_w_loop
  1213. ; get ready for next time:
  1214. mov ecx,ppdev
  1215. sub edi,[ecx].pdev_pvBitmapStart
  1216. mov ulRightDest,edi
  1217. PLAIN_RET
  1218. ;=======================================================================;
  1219. ;========================= ROP Block Drawers ===========================;
  1220. ;=======================================================================;
  1221. ;-----------------------------------------------------------------------;
  1222. ; dual_wide_11_rw
  1223. ;
  1224. ; Draws middle words with 1 leading byte and 1 trailing byte.
  1225. ;
  1226. ; Input:
  1227. ; ppdev - pointer to physical device structure
  1228. ; ulBlockHeight - # of scans to draw
  1229. ; lMiddleDelta - distance from end of current scan to start of next
  1230. ; ulMiddleDest - offset in bitmap at which to start drawing
  1231. ; yBrush - current y brush alignment
  1232. ; cwMiddle - # of words to draw on each scan
  1233. ;
  1234. ; Output:
  1235. ; esi - new y brush alignment
  1236. ; ulMiddleDest - new bitmap offset
  1237. ;-----------------------------------------------------------------------;
  1238. public dual_wide_11_rw
  1239. dual_wide_11_rw::
  1240. ; We only have to reset which planes are enabled if we do edges too:
  1241. mov edx,VGA_BASE + SEQ_DATA
  1242. mov al,MM_ALL
  1243. out dx,al
  1244. mov edi,ppdev
  1245. mov edx,ulBlockHeight
  1246. mov ulBlockHeightTmp,edx
  1247. mov edx,pulPattern ;load those registers
  1248. mov edi,[edi].pdev_pvBitmapStart
  1249. add edi,ulMiddleDest
  1250. mov esi,yBrush
  1251. mov ebx,cwMiddle
  1252. mov eax,[edx+esi*4] ;load pattern for this scan
  1253. inc esi
  1254. and esi,7
  1255. ; EAX = pattern for this scan
  1256. ; EBX = count of loop iterations
  1257. ; EDX = pointer to start of pattern
  1258. ; ESI = current offset into pattern
  1259. ; EDI = target address to which to write
  1260. dual_wide_11_rw_loop:
  1261. and [edi],ah
  1262. and [edi+1],al
  1263. add edi,2 ;the write will overlap this
  1264. dec ebx
  1265. jnz short dual_wide_11_rw_loop
  1266. add edi,lMiddleDelta
  1267. dec ulBlockHeightTmp
  1268. jz short dual_wide_11_rw_done
  1269. mov eax,[edx+esi*4] ;load pattern for this scan
  1270. inc esi
  1271. and esi,7
  1272. mov ebx,cwMiddle
  1273. jmp dual_wide_11_rw_loop
  1274. dual_wide_11_rw_done:
  1275. mov ecx,ppdev
  1276. sub edi,[ecx].pdev_pvBitmapStart
  1277. mov ulMiddleDest,edi
  1278. PLAIN_RET
  1279. ;-----------------------------------------------------------------------;
  1280. ; dual_wide_10_rw
  1281. ;
  1282. ; Draws middle words with 1 leading byte and 0 trailing bytes.
  1283. ;
  1284. ; Input:
  1285. ; ppdev - pointer to physical device structure
  1286. ; ulBlockHeight - # of scans to draw
  1287. ; lMiddleDelta - distance from end of current scan to start of next
  1288. ; ulMiddleDest - offset in bitmap at which to start drawing
  1289. ; yBrush - current y brush alignment
  1290. ; cwMiddle - # of words to draw on each scan
  1291. ;
  1292. ; Output:
  1293. ; esi - new y brush alignment
  1294. ; ulMiddleDest - new bitmap offset
  1295. ;-----------------------------------------------------------------------;
  1296. public dual_wide_10_rw
  1297. dual_wide_10_rw::
  1298. ; We only have to reset which planes are enabled if we do edges too:
  1299. mov edx,VGA_BASE + SEQ_DATA
  1300. mov al,MM_ALL
  1301. out dx,al
  1302. mov edi,ppdev
  1303. mov edx,ulBlockHeight
  1304. mov ulBlockHeightTmp,edx
  1305. mov edx,pulPattern ;load those registers
  1306. mov edi,[edi].pdev_pvBitmapStart
  1307. add edi,ulMiddleDest
  1308. mov esi,yBrush
  1309. mov ebx,cwMiddle
  1310. mov eax,[edx+esi*4] ;load pattern for this scan
  1311. inc esi
  1312. and esi,7
  1313. or ebx,ebx ;have to watch for zero words
  1314. jz short dual_wide_10_rw_only_one_byte
  1315. mov pfnLoopTop,offset dual_wide_10_rw_loop
  1316. ; EAX = pattern for this scan
  1317. ; EBX = count of loop iterations
  1318. ; EDX = pointer to start of pattern
  1319. ; ESI = current offset into pattern
  1320. ; EDI = target address to which to write
  1321. dual_wide_10_rw_loop:
  1322. and [edi],ah
  1323. and [edi+1],al
  1324. add edi,2 ;the write will overlap this
  1325. dec ebx
  1326. jnz short dual_wide_10_rw_loop
  1327. dual_wide_10_rw_odd_byte:
  1328. and [edi],ah ;write that odd byte
  1329. add edi,lMiddleDelta
  1330. dec ulBlockHeightTmp
  1331. jz short dual_wide_10_rw_done
  1332. mov eax,[edx+esi*4] ;load pattern for this scan
  1333. inc esi
  1334. and esi,7
  1335. mov ebx,cwMiddle
  1336. jmp pfnLoopTop
  1337. dual_wide_10_rw_only_one_byte:
  1338. mov pfnLoopTop,offset dual_wide_10_rw_odd_byte
  1339. jmp short dual_wide_10_rw_odd_byte
  1340. dual_wide_10_rw_done:
  1341. mov ecx,ppdev
  1342. sub edi,[ecx].pdev_pvBitmapStart
  1343. mov ulMiddleDest,edi
  1344. PLAIN_RET
  1345. ;-----------------------------------------------------------------------;
  1346. ; dual_wide_01_rw
  1347. ;
  1348. ; Draws middle words with 0 leading bytes and 1 trailing byte.
  1349. ;
  1350. ; Input:
  1351. ; ppdev - pointer to physical device structure
  1352. ; ulBlockHeight - # of scans to draw
  1353. ; lMiddleDelta - distance from end of current scan to start of next
  1354. ; ulMiddleDest - offset in bitmap at which to start drawing
  1355. ; yBrush - current y brush alignment
  1356. ; cwMiddle - # of words to draw on each scan
  1357. ;
  1358. ; Output:
  1359. ; esi - new y brush alignment
  1360. ; ulMiddleDest - new bitmap offset
  1361. ;-----------------------------------------------------------------------;
  1362. public dual_wide_01_rw
  1363. dual_wide_01_rw::
  1364. ; We only have to reset which planes are enabled if we do edges too:
  1365. mov edx,VGA_BASE + SEQ_DATA
  1366. mov al,MM_ALL
  1367. out dx,al
  1368. mov edi,ppdev
  1369. mov edx,ulBlockHeight
  1370. mov ulBlockHeightTmp,edx
  1371. mov edx,pulPattern ;load those registers
  1372. mov edi,[edi].pdev_pvBitmapStart
  1373. add edi,ulMiddleDest
  1374. mov esi,yBrush
  1375. mov ebx,cwMiddle
  1376. mov eax,[edx+esi*4] ;load pattern for this scan
  1377. inc esi
  1378. and esi,7
  1379. or ebx,ebx
  1380. jz short dual_wide_01_rw_only_one_byte
  1381. mov pfnLoopTop,offset dual_wide_01_rw_loop
  1382. ; EAX = pattern for this scan
  1383. ; EBX = count of loop iterations
  1384. ; EDX = pointer to start of pattern
  1385. ; ESI = current offset into pattern
  1386. ; EDI = target address to which to write
  1387. dual_wide_01_rw_loop:
  1388. and [edi],al
  1389. and [edi+1],ah
  1390. add edi,2 ;the write will overlap this
  1391. dec ebx
  1392. jnz short dual_wide_01_rw_loop
  1393. dual_wide_01_rw_odd_byte:
  1394. and [edi],al ;write that odd byte
  1395. add edi,lMiddleDelta
  1396. dec ulBlockHeightTmp
  1397. jz short dual_wide_01_rw_done
  1398. mov eax,[edx+esi*4] ;load pattern for this scan
  1399. inc esi
  1400. and esi,7
  1401. mov ebx,cwMiddle
  1402. jmp pfnLoopTop
  1403. dual_wide_01_rw_only_one_byte:
  1404. mov pfnLoopTop,offset dual_wide_01_rw_odd_byte
  1405. jmp short dual_wide_01_rw_odd_byte
  1406. dual_wide_01_rw_done:
  1407. mov ecx,ppdev
  1408. sub edi,[ecx].pdev_pvBitmapStart
  1409. mov ulMiddleDest,edi
  1410. PLAIN_RET
  1411. ;-----------------------------------------------------------------------;
  1412. ; dual_wide_00_rw
  1413. ;
  1414. ; Draws middle words with 0 leading bytes and 0 trailing bytes.
  1415. ;
  1416. ; Input:
  1417. ; ppdev - pointer to physical device structure
  1418. ; ulBlockHeight - # of scans to draw
  1419. ; lMiddleDelta - distance from end of current scan to start of next
  1420. ; ulMiddleDest - offset in bitmap at which to start drawing
  1421. ; yBrush - current y brush alignment
  1422. ; cwMiddle - # of words to draw on each scan
  1423. ;
  1424. ; Output:
  1425. ; esi - new y brush alignment
  1426. ; ulMiddleDest - new bitmap offset
  1427. ;-----------------------------------------------------------------------;
  1428. public dual_wide_00_rw
  1429. dual_wide_00_rw::
  1430. ; We only have to reset which planes are enabled if we do edges too:
  1431. mov edx,VGA_BASE + SEQ_DATA
  1432. mov al,MM_ALL
  1433. out dx,al
  1434. mov edi,ppdev
  1435. mov edx,ulBlockHeight
  1436. mov ulBlockHeightTmp,edx
  1437. mov edx,pulPattern ;load those registers
  1438. mov edi,[edi].pdev_pvBitmapStart
  1439. add edi,ulMiddleDest
  1440. mov esi,yBrush
  1441. dual_wide_00_rw_scan_loop:
  1442. mov ebx,cwMiddle
  1443. mov eax,[edx+esi*4] ;load pattern for this scan
  1444. inc esi
  1445. and esi,7
  1446. ; EAX = pattern for this scan
  1447. ; EBX = count of loop iterations
  1448. ; EDX = pointer to start of pattern
  1449. ; ESI = current offset into pattern
  1450. ; EDI = target address to which to write
  1451. dual_wide_00_rw_loop:
  1452. and [edi],al
  1453. and [edi+1],ah
  1454. add edi,2 ;the write will overlap this
  1455. dec ebx
  1456. jnz short dual_wide_00_rw_loop
  1457. add edi,lMiddleDelta
  1458. dec ulBlockHeightTmp
  1459. jnz dual_wide_00_rw_scan_loop
  1460. mov ecx,ppdev
  1461. sub edi,[ecx].pdev_pvBitmapStart
  1462. mov ulMiddleDest,edi
  1463. PLAIN_RET
  1464. ;-----------------------------------------------------------------------;
  1465. ; dual_left_1_rw
  1466. ;
  1467. ; Draws a left edge when the next byte is not word aligned.
  1468. ;
  1469. ; Input:
  1470. ; ppdev - pointer to physical device structure
  1471. ; ulBlockHeight - # of scans to draw
  1472. ; lDelta - distance from end of current scan to start of next
  1473. ; ulLeftDest - offset in bitmap at which to start drawing
  1474. ; yBrush - current y brush alignment
  1475. ;
  1476. ; Output:
  1477. ; esi - new y brush alignment
  1478. ; ulLeftDest - new bitmap offset
  1479. ;-----------------------------------------------------------------------;
  1480. public dual_left_1_rw
  1481. dual_left_1_rw::
  1482. ; Set left mask by disabling some planes:
  1483. mov edx,VGA_BASE + SEQ_DATA
  1484. mov eax,ulLeftMask
  1485. out dx,al
  1486. ; Calculate full start addresses:
  1487. mov edi,ppdev
  1488. mov ebx,ulBlockHeight
  1489. mov ecx,pulPattern
  1490. mov edx,lDelta
  1491. mov esi,yBrush
  1492. mov edi,[edi].pdev_pvBitmapStart
  1493. add edi,ulLeftDest
  1494. ; EBX = count of loop iterations
  1495. ; ECX = pointer to start of pattern
  1496. ; EDX = offset to next scan
  1497. ; ESI = current offset into pattern
  1498. ; EDI = target address to which to write
  1499. dual_left_1_rw_loop:
  1500. mov eax,[ecx+esi*4] ;load pattern for this scan
  1501. and [edi],al ;write the low byte
  1502. inc esi ;advance to next scan of pattern
  1503. and esi,7
  1504. add edi,edx ;advance to next scan
  1505. dec ebx
  1506. jnz short dual_left_1_rw_loop
  1507. ; get ready for next time:
  1508. mov ecx,ppdev
  1509. sub edi,[ecx].pdev_pvBitmapStart
  1510. mov ulLeftDest,edi
  1511. PLAIN_RET
  1512. ;-----------------------------------------------------------------------;
  1513. ; dual_left_0_rw
  1514. ;
  1515. ; Draws a left edge when the next byte is word aligned.
  1516. ;
  1517. ; Input:
  1518. ; ppdev - pointer to physical device structure
  1519. ; ulBlockHeight - # of scans to draw
  1520. ; lDelta - distance from end of current scan to start of next
  1521. ; ulLeftDest - offset in bitmap at which to start drawing
  1522. ; yBrush - current y brush alignment
  1523. ;
  1524. ; Output:
  1525. ; esi - new y brush alignment
  1526. ; ulLeftDest - new bitmap offset
  1527. ;-----------------------------------------------------------------------;
  1528. public dual_left_0_rw
  1529. dual_left_0_rw::
  1530. ; Set left mask by disabling some planes:
  1531. mov edx,VGA_BASE + SEQ_DATA
  1532. mov eax,ulLeftMask
  1533. out dx,al
  1534. ; Calculate full start addresses:
  1535. mov edi,ppdev
  1536. mov ebx,ulBlockHeight
  1537. mov ecx,pulPattern
  1538. mov edx,lDelta
  1539. mov esi,yBrush
  1540. mov edi,[edi].pdev_pvBitmapStart
  1541. add edi,ulLeftDest
  1542. ; EBX = count of loop iterations
  1543. ; ECX = pointer to start of pattern
  1544. ; EDX = offset to next scan
  1545. ; ESI = current offset into pattern
  1546. ; EDI = target address to which to write
  1547. dual_left_0_rw_loop:
  1548. mov eax,[ecx+esi*4] ;load pattern for this scan
  1549. and [edi],ah ;write the high byte
  1550. inc esi ;advance to next scan of pattern
  1551. and esi,7
  1552. add edi,edx ;advance to next scan
  1553. dec ebx
  1554. jnz short dual_left_0_rw_loop
  1555. ; get ready for next time:
  1556. mov ecx,ppdev
  1557. sub edi,[ecx].pdev_pvBitmapStart
  1558. mov ulLeftDest,edi
  1559. PLAIN_RET
  1560. ;-----------------------------------------------------------------------;
  1561. ; dual_right_1_rw
  1562. ;
  1563. ; Draws a right edge when not word aligned.
  1564. ;
  1565. ; Input:
  1566. ; ppdev - pointer to physical device structure
  1567. ; ulBlockHeight - # of scans to draw
  1568. ; lDelta - distance from end of current scan to start of next
  1569. ; ulRightDest - offset in bitmap at which to start drawing
  1570. ; yBrush - current y brush alignment
  1571. ;
  1572. ; Output:
  1573. ; esi - new y brush alignment
  1574. ; ulRightDest - new bitmap offset
  1575. ;-----------------------------------------------------------------------;
  1576. public dual_right_1_rw
  1577. dual_right_1_rw::
  1578. ; Set right mask by disabling some planes:
  1579. mov edx,VGA_BASE + SEQ_DATA
  1580. mov eax,ulRightMask
  1581. out dx,al
  1582. ; Calculate full start addresses:
  1583. mov edi,ppdev
  1584. mov ebx,ulBlockHeight
  1585. mov ecx,pulPattern
  1586. mov edx,lDelta
  1587. mov esi,yBrush
  1588. mov edi,[edi].pdev_pvBitmapStart
  1589. add edi,ulRightDest
  1590. ; EBX = count of loop iterations
  1591. ; ECX = pointer to start of pattern
  1592. ; EDX = offset to next scan
  1593. ; ESI = current offset into pattern
  1594. ; EDI = target address to which to write
  1595. dual_right_1_rw_loop:
  1596. mov eax,[ecx+esi*4] ;load pattern for this scan
  1597. and [edi],ah ;write the high byte
  1598. inc esi ;advance to next scan of pattern
  1599. and esi,7
  1600. add edi,edx ;advance to next scan
  1601. dec ebx
  1602. jnz short dual_right_1_rw_loop
  1603. ; get ready for next time:
  1604. mov ecx,ppdev
  1605. sub edi,[ecx].pdev_pvBitmapStart
  1606. mov ulRightDest,edi
  1607. PLAIN_RET
  1608. ;-----------------------------------------------------------------------;
  1609. ; dual_right_0_rw
  1610. ;
  1611. ; Draws a right edge when word aligned.
  1612. ;
  1613. ; Input:
  1614. ; ppdev - pointer to physical device structure
  1615. ; ulBlockHeight - # of scans to draw
  1616. ; lDelta - distance from end of current scan to start of next
  1617. ; ulRightDest - offset in bitmap at which to start drawing
  1618. ; yBrush - current y brush alignment
  1619. ;
  1620. ; Output:
  1621. ; esi - new y brush alignment
  1622. ; ulRightDest - new bitmap offset
  1623. ;-----------------------------------------------------------------------;
  1624. public dual_right_0_rw
  1625. dual_right_0_rw::
  1626. ; Set right mask by disabling some planes:
  1627. mov edx,VGA_BASE + SEQ_DATA
  1628. mov eax,ulRightMask
  1629. out dx,al
  1630. ; Calculate full start addresses:
  1631. mov edi,ppdev
  1632. mov ebx,ulBlockHeight
  1633. mov ecx,pulPattern
  1634. mov edx,lDelta
  1635. mov esi,yBrush
  1636. mov edi,[edi].pdev_pvBitmapStart
  1637. add edi,ulRightDest
  1638. ; EBX = count of loop iterations
  1639. ; ECX = pointer to start of pattern
  1640. ; EDX = offset to next scan
  1641. ; ESI = current offset into pattern
  1642. ; EDI = target address to which to write
  1643. dual_right_0_rw_loop:
  1644. mov eax,[ecx+esi*4] ;load pattern for this scan
  1645. and [edi],al ;write the low byte
  1646. inc esi ;advance to next scan of pattern
  1647. and esi,7
  1648. add edi,edx ;advance to next scan
  1649. dec ebx
  1650. jnz short dual_right_0_rw_loop
  1651. ; get ready for next time:
  1652. mov ecx,ppdev
  1653. sub edi,[ecx].pdev_pvBitmapStart
  1654. mov ulRightDest,edi
  1655. PLAIN_RET
  1656. ;-----------------------------------------------------------------------;
  1657. endProc vMonoPat
  1658. ;-----------------------------------------------------------------------;
  1659. ; BOOL b2ColorBrush(pjBits, pjFgColor, pjBkColor)
  1660. ;
  1661. ; Determines if the 8x8x8bpp packed brush pointed to by pjBits has only
  1662. ; two colors, and if so returns the 1bpp bitmap.
  1663. ;
  1664. ; Returns:
  1665. ; eax = 1 if two (or one) color brush, 0 otherwise
  1666. ; pjBits = pointer to packed 1bpp bitmap if a 2-color brush
  1667. ; *pjFgColor = foreground color for returned 1bpp bitmap (i.e.,
  1668. ; used to color-expand '1' bits)
  1669. ; *pjBkColor = backgroun color for returned 1bpp bitmap (i.e.,
  1670. ; used to color-expand '0' bits)
  1671. ;-----------------------------------------------------------------------;
  1672. cProc b2ColorBrush,12,< \
  1673. uses esi edi ebx, \
  1674. pjBits: ptr BYTE, \
  1675. pjFgColor: ptr BYTE, \
  1676. pjBkColor: ptr BYTE >
  1677. ; al = first color
  1678. ; ah = second color
  1679. ; ecx = number of unrolled loops
  1680. mov esi,pjBits
  1681. mov ecx,(BRUSH_SIZE shr 1)
  1682. mov al,[esi]
  1683. b2col_find_2nd_color_loop:
  1684. mov ah,[esi+1]
  1685. cmp ah,al
  1686. jne short b2col_find_consecutive_2nd_color_loop_part_1
  1687. add esi,2
  1688. dec ecx
  1689. jz short b2col_is_2_colors ;actually, it's only one color
  1690. mov ah,[esi]
  1691. cmp ah,al
  1692. jne short b2col_find_consecutive_2nd_color_loop_part_2
  1693. jmp short b2col_find_2nd_color_loop
  1694. ;------------------------------------;
  1695. b2col_find_consecutive_1st_color_loop_part_1:
  1696. add esi,2
  1697. dec ecx
  1698. jz short b2col_is_2_colors
  1699. mov bl,[esi]
  1700. cmp bl,ah
  1701. je short b2col_find_consecutive_2nd_color_loop_part_2
  1702. cmp bl,al
  1703. jne short b2col_isnt_2_colors
  1704. b2col_find_consecutive_1st_color_loop_part_2:
  1705. mov bl,[esi+1]
  1706. cmp bl,ah
  1707. je short b2col_find_consecutive_2nd_color_loop_part_1
  1708. cmp bl,al
  1709. je short b2col_find_consecutive_1st_color_loop_part_1
  1710. xor eax,eax
  1711. cRet b2ColorBrush ;return FALSE
  1712. ;------------------------------------;
  1713. b2col_find_consecutive_2nd_color_loop_part_1:
  1714. add esi,2
  1715. dec ecx
  1716. jz short b2col_is_2_colors
  1717. mov bl,[esi]
  1718. cmp bl,al
  1719. je short b2col_find_consecutive_1st_color_loop_part_2
  1720. cmp bl,ah
  1721. jne short b2col_isnt_2_colors
  1722. b2col_find_consecutive_2nd_color_loop_part_2:
  1723. mov bl,[esi+1]
  1724. cmp bl,al
  1725. je short b2col_find_consecutive_1st_color_loop_part_1
  1726. cmp bl,ah
  1727. je short b2col_find_consecutive_2nd_color_loop_part_1
  1728. b2col_isnt_2_colors:
  1729. xor eax,eax
  1730. cRet b2ColorBrush ;return FALSE
  1731. ;------------------------------------;
  1732. public b2col_is_2_colors
  1733. b2col_is_2_colors::
  1734. ; Here, we want the color with the lesser value to be in 'al', and the
  1735. ; other to be in 'ah'.
  1736. cmp al,ah
  1737. jb short b2col_ordered_colors
  1738. xchg al,ah
  1739. b2col_ordered_colors:
  1740. mov ecx,(BRUSH_SIZE shr 3)
  1741. mov esi,pjBits
  1742. mov edi,esi
  1743. ; Colors matching 'al' will get mapped to '1' bits, and colors matching
  1744. ; 'ah' will get mapped to '0' bits:
  1745. b2col_monochrome_bitmap_loop:
  1746. cmp [esi+7],ah
  1747. adc bl,bl
  1748. cmp [esi+6],ah
  1749. adc bl,bl
  1750. cmp [esi+5],ah
  1751. adc bl,bl
  1752. cmp [esi+4],ah
  1753. adc bl,bl
  1754. cmp [esi+3],ah
  1755. adc bl,bl
  1756. cmp [esi+2],ah
  1757. adc bl,bl
  1758. cmp [esi+1],ah
  1759. adc bl,bl
  1760. cmp [esi],ah
  1761. adc bl,bl
  1762. ; At this point, where the 8 bytes of the bitmap were ordered 0 1 2 3 4 5 6 7,
  1763. ; we've got the monochrome byte in 'bl' ordered 7 6 5 4 3 2 1 0. We want
  1764. ; the word ordered '3 2 1 0 7 6 5 4 | 7 6 5 4 3 2 1 0' where the lower 4 bits
  1765. ; of every bit are the planes mask, and the upper 4 bits are ordered to
  1766. ; facilitate easy rotating.
  1767. ;
  1768. ; The word is actually written into a dword in the destination buffer.
  1769. mov bh,bl
  1770. ror bh,4
  1771. mov [edi],ebx ;save this dword of monochrome bitmap
  1772. add edi,4
  1773. add esi,8
  1774. dec ecx
  1775. jnz b2col_monochrome_bitmap_loop
  1776. ; Aside: because of the way this is written, if the two colors are black
  1777. ; and white (i.e., 0x00 and 0xff), the foreground color will be black (0x00),
  1778. ; and the background will be white (0xff).
  1779. mov esi,pjFgColor
  1780. mov edi,pjBkColor
  1781. mov [esi],al ;save foreground color
  1782. mov [edi],ah ;save background color
  1783. mov eax,1
  1784. cRet b2ColorBrush
  1785. endProc b2ColorBrush
  1786. end