|
|
1.1 root 1: ;---------------------------Module-Header------------------------------;
2: ; Module Name: monopat.asm
3: ;
4: ; Copyright (c) 1992-1993 Microsoft Corporation. All rights reserved.
5: ;-----------------------------------------------------------------------;
6:
7: ;-----------------------------------------------------------------------;
8: ; VOID vMonoPat(ppdev, culRcl, prcl, ulMix, prb, pptlBrush)
9: ;
10: ; Input:
11: ;
12: ; ppdev - surface on which to draw
13: ; culRcl - number of rectangles
14: ; prcl - pointer to rectangles
15: ; ulMix - mix mode (i.e., ROP)
16: ; prb - pointer to realized brush
17: ; pptlBrush - brush alignment
18: ;
19: ; Draws two color patterns using the VGA hardware. If the ROP is a
20: ; PATCOPY ROP, we can light 8 pixels on every word write to VGA memory.
21: ;
22: ; We special case black & white patterns because we can do slightly less
23: ; initialization, and we can handle arbitrary ROPs (although if the ROP
24: ; has to read video memory, we can only do 4 pixels on every read/write
25: ; operation).
26: ;
27: ;-----------------------------------------------------------------------;
28: ;
29: ; NOTE: Assumes all rectangles have positive heights and widths. Will
30: ; not work properly if this is not the case.
31: ;
32: ;-----------------------------------------------------------------------;
33:
34: ;-----------------------------------------------------------------------;
35: ; Set LOOP_UNROLL_SHIFT to the log2 of the number of times you want loops in
36: ; this module unrolled. For example, LOOP_UNROLL_SHIFT of 3 yields 2**3 = 8
37: ; times unrolling. This is the only thing you need to change to control
38: ; unrolling.
39:
40: LOOP_UNROLL_SHIFT equ 2
41:
42: ;-----------------------------------------------------------------------;
43:
44: .386
45:
46: .model small,c
47:
48: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
49: assume fs:nothing,gs:nothing
50:
51: .xlist
52: include stdcall.inc ;calling convention cmacros
53: include i386\strucs.inc
54: include i386\driver.inc
55: include i386\unroll.inc
56: include i386\egavga.inc
57: include i386\ropdefs.inc
58:
59: .list
60:
61: ;-----------------------------------------------------------------------;
62:
63: .data
64:
65: ; vTrgBlt is used for 2-pass ROPs:
66:
67: EXTRNP vTrgBlt,24
68:
69: ; Tables shared with vgablts.asm:
70:
71: extrn jALUFuncTable: byte
72: extrn jInvertDest: byte
73:
74: ;-----------------------------------------------------------------------;
75: ; Bits for drawing routine look-ups.
76:
77: BLOCK_LEFT_EDGE equ 010000b
78: BLOCK_RIGHT_EDGE equ 001000b
79: BLOCK_MIDDLE_STARTS_UNALIGNED equ 000100b
80: BLOCK_NO_MIDDLE equ 000010b
81: BLOCK_MIDDLE_ENDS_UNALIGNED equ 000001b
82:
83: ;-----------------------------------------------------------------------;
84: ; Table of drawing routines, with the look-up index a 5 bit field as
85: ; follows:
86: ;
87: ; Bit 4 = 1 if a left edge must be drawn
88: ; Bit 3 = 1 if a right edge must be drawn
89: ; Bit 2 = 1 if middle block starts unaligned word-wise
90: ; Bit 1 = 1 if no middle block
91: ; Bit 0 = 1 if middle block is an odd number of bytes in length
92:
93: align 4
94: gapfnSetTable label dword
95: dd dual_wide_00_w ;00000
96: dd dual_wide_01_w ;00001
97: dd 0 ;00010
98: dd 0 ;00011
99: dd dual_wide_11_w ;00100
100: dd dual_wide_10_w ;00101
101: dd 0 ;00110
102: dd 0 ;00111
103: dd Block_01000_w ;01000
104: dd Block_01001_w ;01001
105: dd dual_right_0_w ;01010
106: dd dual_right_1_w ;01011
107: dd Block_01100_w ;01100
108: dd Block_01101_w ;01101
109: dd dual_right_1_w ;01110
110: dd dual_right_0_w ;01111
111: dd Block_10000_w ;10000
112: dd Block_10001_w ;10001
113: dd dual_left_0_w ;10010
114: dd dual_left_0_w ;10011
115: dd Block_10100_w ;10100
116: dd Block_10101_w ;10101
117: dd dual_left_1_w ;10110
118: dd dual_left_1_w ;10111
119: dd Block_11000_w ;11000
120: dd Block_11001_w ;11001
121: dd Block_11010_w ;11010
122: dd 0 ;11011 - can never happen
123: dd Block_11100_w ;11100
124: dd Block_11101_w ;11101
125: dd Block_11110_w ;11110
126: dd 0 ;11111 - can never happen
127:
128: gapfnROPTable label dword
129: dd dual_wide_00_rw ;00000
130: dd dual_wide_01_rw ;00001
131: dd 0 ;00010
132: dd 0 ;00011
133: dd dual_wide_11_rw ;00100
134: dd dual_wide_10_rw ;00101
135: dd 0 ;00110
136: dd 0 ;00111
137: dd Block_01000_rw ;01000
138: dd Block_01001_rw ;01001
139: dd dual_right_0_rw ;01010
140: dd dual_right_1_rw ;01011
141: dd Block_01100_rw ;01100
142: dd Block_01101_rw ;01101
143: dd dual_right_1_rw ;01110
144: dd dual_right_0_rw ;01111
145: dd Block_10000_rw ;10000
146: dd Block_10001_rw ;10001
147: dd dual_left_0_rw ;10010
148: dd dual_left_0_rw ;10011
149: dd Block_10100_rw ;10100
150: dd Block_10101_rw ;10101
151: dd dual_left_1_rw ;10110
152: dd dual_left_1_rw ;10111
153: dd Block_11000_rw ;11000
154: dd Block_11001_rw ;11001
155: dd Block_11010_rw ;11010
156: dd 0 ;11011 - can never happen
157: dd Block_11100_rw ;11100
158: dd Block_11101_rw ;11101
159: dd Block_11110_rw ;11110
160: dd 0 ;11111 - can never happen
161:
162: gaulForceOffTable label dword
163: dd 0 ;ignored - there is no mix 0
164: dd 0
165: dd 0ffffffffh
166: dd 0ffffffffh
167: dd 0ffffffffh
168: dd 0ffffffffh
169: dd 0ffffffffh
170: dd 0ffffffffh
171: dd 0ffffffffh
172: dd 0ffffffffh
173: dd 0ffffffffh
174: dd 0
175: dd 0ffffffffh
176: dd 0ffffffffh
177: dd 0ffffffffh
178: dd 0ffffffffh
179: dd 0ffffffffh
180:
181: gaulForceOnTable label dword
182: dd 0 ;ignored - there is no mix 0
183: dd 0
184: dd 0
185: dd 0
186: dd 0
187: dd 0
188: dd 0ffffffffh
189: dd 0
190: dd 0
191: dd 0
192: dd 0
193: dd 0
194: dd 0
195: dd 0
196: dd 0
197: dd 0
198: dd 0ffffffffh
199:
200: gaulForceNotTable label dword
201: dd 0 ;ignored - there is no mix 0
202: dd 0
203: dd 0ffffffffh
204: dd 0ffffffffh
205: dd 0ffffffffh
206: dd 0
207: dd 0
208: dd 0
209: dd 0ffffffffh
210: dd 0
211: dd 0ffffffffh
212: dd 0
213: dd 0ffffffffh
214: dd 0
215: dd 0
216: dd 0
217: dd 0
218:
219: ;-----------------------------------------------------------------------;
220:
221: .code
222: ;-----------------------------------------------------------------------;
223: ; Write thunks (for set ROPs)
224: ;-----------------------------------------------------------------------;
225:
226: align 4
227: Block_01000_w:
228: push offset dual_right_0_w
229: jmp dual_wide_00_w
230:
231: align 4
232: Block_01001_w:
233: push offset dual_right_1_w
234: jmp dual_wide_01_w
235:
236: align 4
237: Block_01100_w:
238: push offset dual_right_1_w
239: jmp dual_wide_11_w
240:
241: align 4
242: Block_01101_w:
243: push offset dual_right_0_w
244: jmp dual_wide_10_w
245:
246: align 4
247: Block_11000_w:
248: push offset dual_right_0_w
249: Block_10000_w:
250: push offset dual_left_0_w
251: jmp dual_wide_00_w
252:
253: align 4
254: Block_11001_w:
255: push offset dual_right_1_w
256: Block_10001_w:
257: push offset dual_left_0_w
258: jmp dual_wide_01_w
259:
260: align 4
261: Block_11100_w:
262: push offset dual_right_1_w
263: Block_10100_w:
264: push offset dual_left_1_w
265: jmp dual_wide_11_w
266:
267: align 4
268: Block_11101_w:
269: push offset dual_right_0_w
270: Block_10101_w:
271: push offset dual_left_1_w
272: jmp dual_wide_10_w
273:
274: align 4
275: Block_11010_w:
276: push offset dual_right_0_w
277: jmp dual_left_0_w
278:
279: align 4
280: Block_11110_w:
281: push offset dual_right_1_w
282: jmp dual_left_1_w
283:
284: ;-----------------------------------------------------------------------;
285: ; Read/write thunks (for arbitrary ROPs)
286: ;-----------------------------------------------------------------------;
287:
288: Block_01000_rw:
289: push offset dual_right_0_rw
290: jmp dual_wide_00_rw
291:
292: Block_01001_rw:
293: push offset dual_right_1_rw
294: jmp dual_wide_01_rw
295:
296: Block_01100_rw:
297: push offset dual_right_1_rw
298: jmp dual_wide_11_rw
299:
300: Block_01101_rw:
301: push offset dual_right_0_rw
302: jmp dual_wide_10_rw
303:
304: Block_11000_rw:
305: push offset dual_right_0_rw
306: Block_10000_rw:
307: push offset dual_left_0_rw
308: jmp dual_wide_00_rw
309:
310: Block_11001_rw:
311: push offset dual_right_1_rw
312: Block_10001_rw:
313: push offset dual_left_0_rw
314: jmp dual_wide_01_rw
315:
316: Block_11100_rw:
317: push offset dual_right_1_rw
318: Block_10100_rw:
319: push offset dual_left_1_rw
320: jmp dual_wide_11_rw
321:
322: Block_11101_rw:
323: push offset dual_right_0_rw
324: Block_10101_rw:
325: push offset dual_left_1_rw
326: jmp dual_wide_10_rw
327:
328: Block_11010_rw:
329: push offset dual_right_0_rw
330: jmp dual_left_0_rw
331:
332: Block_11110_rw:
333: push offset dual_right_1_rw
334: jmp dual_left_1_rw
335:
336: ;-----------------------------------------------------------------------;
337:
338: cProc vMonoPat,24,< \
339: uses esi edi ebx, \
340: ppdev: ptr PDEV, \
341: culRcl: dword, \
342: prcl: ptr RECTL, \
343: ulMix: dword, \
344: prb: ptr RBRUSH,\
345: pptlBrush: ptr POINTL >
346:
347: ; Variables used in block drawers:
348:
349: local ppfnDraw: ptr ;pointer to array of draw routines
350: local pfnDraw: ptr ;pointer to draw routines
351:
352: local yBrush: dword ;current y brush alignment
353: local yBrushOrg: dword ;original y brush alignment
354: local ulMiddleDest: dword ;bitmap offset to middle
355: local lMiddleDelta: dword ;delta from end of middle scan to next
356: local ulBlockHeight: dword ;# of scans to be drawn in block
357: local cwMiddle: dword ;# of words to be written in middle
358:
359: local ulLeftDest: dword ;bitmap offset to left edge
360: local ulLeftMask: dword ;plane mask for left-edge drawing
361: local ulRightDest: dword ;bitmap offset to right edge
362: local ulRightMask: dword ;plane mask for right-edge drawing
363: local lDelta: dword ;delta between scans
364:
365: local ulCurrentDestScan: dword ;current destination scan
366: local ulLastDestScan: dword ;last destination scan
367:
368: local ulSaveEsp: dword ;for when we really need a register
369: local pulPattern: ptr ;pointer to working pattern buffer
370: ; (to account for brush inversions)
371: local aulPatternBuffer[8]: dword ;pattern buffer
372:
373: local cUnrolledLoops: dword ;number of unrolled loops to do
374: local pfnUnroll: ptr ;points to start point in unroll table
375:
376: mov esi,pptlBrush
377: mov edi,prb
378: mov ecx,[esi].ptl_y
379: mov yBrushOrg,ecx ;yBrushOrg = pptlBrush->y
380: mov ecx,[esi].ptl_x
381: mov eax,[edi].rb_xBrush
382: and ecx,7
383: cmp eax,ecx
384: jne dual_align_brush ;only align if we really have to
385:
386: dual_done_align_brush:
387: test [edi].rb_fl,RBRUSH_2COLOR
388: jnz col2_colors
389:
390: ; Set VGA to read mode 1 and write mode 2:
391:
392: mov esi,ppdev
393: mov edx,VGA_BASE + GRAF_ADDR
394: mov ah,byte ptr [esi].pdev_ulrm0_wmX[2]
395: or ah,M_COLOR_READ
396: mov al,GRAF_MODE
397: out dx,ax ;write mode 2 to expand pattern bits to
398: ; 0 or 0ffh per plane, read mode 1 so
399: ; we can read 0xFF from memory always,
400: ; for ANDing (because Color Don't Care
401: ; is all zeros)
402:
403: ;-----------------------------------------------------------------------;
404: ; Handle only black/white patterns.
405: ;-----------------------------------------------------------------------;
406:
407: lea eax,[edi].rb_aulPattern
408: mov pulPattern,eax ;pulPattern = &pbr.rb_aulPattern[0]
409: lea eax,gapfnSetTable
410: mov ppfnDraw,eax ;ppfnDraw = gapfnSetTable
411:
412: mov ecx,ulMix
413: and ecx,0fh
414: cmp ecx,R2_COPYPEN
415: jne bw_init_rop ;do some more work if not copy ROP
416:
417: bw_done_init_rop:
418:
419: call dual_draw_rectangles ;draw those puppies
420:
421: ; All done! Restore read mode 0, write mode 0:
422:
423: mov esi,ppdev
424: mov edx,VGA_BASE + GRAF_ADDR
425: mov ah,byte ptr [esi].pdev_ulrm0_wmX[0]
426: mov al,GRAF_MODE
427: out dx,ax
428:
429: ; Enable all planes:
430:
431: mov edx,VGA_BASE + SEQ_DATA
432: mov al,MM_ALL
433: out dx,al
434:
435: cmp ulMix,R2_COPYPEN
436: jne short bw_enable_set_mode
437: cRet vMonoPat
438:
439: ; Set ALU function to Set mode (we don't have to bother if we had a
440: ; COPYPEN ROP):
441:
442: bw_enable_set_mode:
443: mov eax,GRAF_DATA_ROT + (DR_SET shl 8)
444: mov edx,VGA_BASE + GRAF_ADDR
445: out dx,ax
446: cRet vMonoPat
447:
448: ;-----------------------------------------------------------------------;
449: ; Draw both black and white and 2 color rectangles.
450: ;-----------------------------------------------------------------------;
451:
452: align 4
453: public dual_draw_rectangles
454: dual_draw_rectangles:
455:
456: mov edi,prcl ;edi = prcl
457: mov edx,ppdev
458: mov eax,[edi].yBottom
459: mov ebx,[edi].yTop
460: mov edx,[edx].pdev_lPlanarNextScan
461:
462: mov lDelta,edx ;lDelta = ppdev->lPlanarNextScan
463: mov ulLastDestScan,eax ;ulLastDestScan = prcl->bottom
464: mov ulCurrentDestScan,ebx ;ulCurrentDestScan = prcl->top
465:
466: mov ecx,edx
467: imul ecx,ebx
468:
469: sub ebx,yBrushOrg
470: and ebx,7
471: mov yBrush,ebx ;yBrush = (prcl->top - pptlBrush->y) & 7
472: ; (our current index into the pattern
473: ; array)
474:
475: mov ebx,[edi].xLeft
476: shr ebx,2
477: add ebx,ecx ;ebx = prcl->top * lDelta +
478: ; (prcl->left >> 2)
479: ; (offset into bitmap of left side)
480:
481: mov eax,[edi].xRight
482: shr eax,2
483: add eax,ecx
484: mov ulRightDest,eax ;ulRightDest = prcl->top * lDelta +
485: ; (prcl->right >> 2)
486: ; (offset into bitmap of right side)
487:
488: xor esi,esi ;zero our flags
489:
490: mov ecx,[edi].xLeft
491: and ecx,3
492: jz short dual_done_left ;skip if we don't need a left edge
493:
494: mov esi,0fh ;compute the plane mask for the left
495: shl esi,cl ; edge. we don't use a look-up table
496: mov ulLeftMask,esi ; 'cause it won't be in the cache.
497:
498: mov esi,(BLOCK_LEFT_EDGE shr 2)
499: ;set our flag (we soon shift left by 2)
500:
501: mov ulLeftDest,ebx ;ulLeftDest = prcl->top * lDelta +
502: ; (prcl->left >> 2)
503: inc ebx ;ebx = ulMiddleDest = ulLeftDest + 1
504: ; (we have to adjust our offset to
505: ; the first whole byte)
506:
507: dual_done_left:
508: sub eax,ebx ;eax = cjMiddle =
509: ; ulRightDest - ulMiddleDest
510: mov ulMiddleDest,ebx ;ulMiddleDest
511:
512: .errnz (BLOCK_MIDDLE_STARTS_UNALIGNED shr 2) - 1
513: and ebx,1 ;set bit if middle doesn't start
514: or esi,ebx ; word aligned (remembering we'll
515: ; soon shift flags left by 2)
516:
517: mov ecx,[edi].xRight
518: and ecx,3
519: jz short dual_done_right ;skip if we don't need a right edge
520:
521: mov ebx,0f0h ;compute the plane mask for the right
522: rol bl,cl ; edge. we don't use a look-up table
523: mov ulRightMask,ebx ; 'cause it won't be in the cache.
524:
525: or esi,(BLOCK_RIGHT_EDGE shr 2)
526: ;set our flag (we soon shift left by 2)
527:
528: ; If the count of whole bytes is negative, that means that the pattern
529: ; starts and ends in the same quadpixel, so we do some more work:
530:
531: cmp eax,0
532: jge short dual_done_right
533:
534: ; It starts and ends in the same quadpixel:
535:
536: and esi,not (BLOCK_RIGHT_EDGE shr 2)
537: ;turn off right edge
538: and ebx,ulLeftMask
539: mov ulLeftMask,ebx
540: xor eax,eax ;we do zero middle bytes
541:
542: align 4
543: public dual_done_right
544: dual_done_right:
545: mov ebx,ppfnDraw
546:
547: ; We're going to do two 'adc esi,esi' instructions here, effectively
548: ; shifting our flags left by 2, and setting the low bits:
549:
550: .errnz (BLOCK_NO_MIDDLE shr 1) - 1
551: cmp eax,1 ;shift flags left one, and set low
552: adc esi,esi ; bit if we don't need to do a middle
553:
554: .errnz (BLOCK_MIDDLE_ENDS_UNALIGNED) - 1
555: shr eax,1
556: adc esi,esi ;shift flags left one, and set low
557: ; bit if the middle isn't an even
558: ; number of bytes in length
559: mov cwMiddle,eax ;cwMiddle = cjMiddle / 2
560:
561: sub edx,eax
562: sub edx,eax
563: mov lMiddleDelta,edx ;lMiddleDelta = lDelta - 2 * cwMiddle
564:
565: mov eax,[ebx+esi*4]
566: mov pfnDraw,eax ;pointer to function that draws
567: ; everything in the bank
568:
569: mov ebx,ppdev
570: mov edi,[edi].yTop
571:
572: cmp edi,[ebx].pdev_rcl1PlanarClip.yTop
573: jl short dual_map_init_bank
574:
575: cmp edi,[ebx].pdev_rcl1PlanarClip.yBottom
576: jl short dual_init_bank_mapped
577:
578: dual_map_init_bank:
579: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
580: <ebx,edi,JustifyTop>
581:
582: dual_init_bank_mapped:
583: mov eax,ulLastDestScan
584: mov ebx,[ebx].pdev_rcl1PlanarClip.yBottom
585:
586: sub eax,ebx
587: sbb ecx,ecx
588: and ecx,eax
589: add ebx,ecx ;ebx = min(ulLastDestScan,
590: ; ppdev->rcl1PlanarClip.yBottom)
591: mov ulCurrentDestScan,ebx
592:
593: sub ebx,edi
594: mov ulBlockHeight,ebx ;ulBlockHeight = ebx - ulCurrentDestScan
595:
596: ; Draw everything in this bank:
597:
598: call pfnDraw
599:
600: dual_done_pfnDraw:
601: mov edi,ulCurrentDestScan
602: cmp edi,ulLastDestScan
603: jge short dual_next_rectangle
604:
605: ; Get the next bank:
606:
607: mov ebx,ppdev
608: mov yBrush,esi ;make sure we record the new brush
609: ; alignment
610:
611: ; Map the next bank into window.
612: ; Note: EBX, ESI, and EDI are preserved, according to C calling conventions.
613:
614: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
615: <ebx,edi,JustifyTop>
616:
617: jmp short dual_init_bank_mapped
618:
619: ;-----------------------------------------------------------------------;
620: ; Done rectangle.
621: ;-----------------------------------------------------------------------;
622:
623: align 4
624: public dual_next_rectangle
625: dual_next_rectangle:
626: add prcl, size RECTL
627: dec culRcl
628: jg dual_draw_rectangles ;do more rectangles
629:
630: PLAIN_RET ;return
631:
632: ;-----------------------------------------------------------------------;
633: ; Handle x-brush alignment.
634: ;-----------------------------------------------------------------------;
635:
636: align 4
637: public dual_align_brush
638: dual_align_brush:
639:
640: ; Align the pattern on x. Remember it in the realized brush, because if
641: ; the brush is used again, it's likely to have the same alignment...
642:
643: mov [edi].rb_xBrush,ecx ;remember our new alignment
644: sub ecx,eax ;rotate pattern left by
645: ; pptlBrush->x - prb->xBrush
646:
647: ; We keep each row of the pattern in the low word of each dword. If the
648: ; bits are to appear on the screen as 01234567, the word of our pattern
649: ; has the bits 32107654|76543210 -- we're in write mode 3, and when
650: ; written as a word, this results in 3210 being written in the first
651: ; byte, and 7654 in the second byte.
652: ;
653: ; For brush alignment, we would want to rotate 01234567 right by 'cl'.
654: ; For our funky plaanr format, we just rotate each byte of the word left by
655: ; 'cl' to get the desired result.
656:
657: rol byte ptr [edi][0].rb_aulPattern,cl ;0
658: rol byte ptr [edi][1].rb_aulPattern,cl
659: rol byte ptr [edi][4].rb_aulPattern,cl ;1
660: rol byte ptr [edi][5].rb_aulPattern,cl
661: rol byte ptr [edi][8].rb_aulPattern,cl ;2
662: rol byte ptr [edi][9].rb_aulPattern,cl
663: rol byte ptr [edi][12].rb_aulPattern,cl ;3
664: rol byte ptr [edi][13].rb_aulPattern,cl
665: rol byte ptr [edi][16].rb_aulPattern,cl ;4
666: rol byte ptr [edi][17].rb_aulPattern,cl
667: rol byte ptr [edi][20].rb_aulPattern,cl ;5
668: rol byte ptr [edi][21].rb_aulPattern,cl
669: rol byte ptr [edi][24].rb_aulPattern,cl ;6
670: rol byte ptr [edi][25].rb_aulPattern,cl
671: rol byte ptr [edi][28].rb_aulPattern,cl ;7
672: rol byte ptr [edi][29].rb_aulPattern,cl
673:
674: jmp dual_done_align_brush
675:
676: ;-----------------------------------------------------------------------;
677: ; Handle arbitrary ROPs for black/white patterns.
678: ;-----------------------------------------------------------------------;
679:
680: ; Expect:
681: ;
682: ; ecx = ulMix
683:
684: align 4
685: public bw_init_rop
686: bw_init_rop:
687: cmp jInvertDest[ecx],0
688: je short bw_set_that_ALU ;skip if don't need 2 passes
689:
690: ; For some ROPs, we have to invert the destination first, then do another
691: ; operation (that is, it's a 2-pass ROP). We handle the inversion here:
692:
693: cCall vTrgBlt,<ppdev, culRcl, prcl, R2_NOT, 0, 0>
694: mov ecx,ulMix
695:
696: bw_set_that_ALU:
697: mov ah,jALUFuncTable[ecx]
698: cmp ah,DR_SET
699: je short bw_that_ALU_is_set
700: ;we're already in Set mode
701:
702: mov edx,VGA_BASE + GRAF_ADDR
703: mov al,GRAF_DATA_ROT
704: out dx,ax ;set the ALU logical function
705: lea ebx,gapfnROPTable
706: mov ppfnDraw,ebx
707:
708: bw_that_ALU_is_set:
709: lea esi,aulPatternBuffer
710: mov pulPattern,esi ;we're using the temporary buffer
711:
712: mov ebx,gaulForceOffTable[ecx*4]
713: mov edx,gaulForceOnTable[ecx*4]
714: mov esi,gaulForceNotTable[ecx*4]
715:
716: mov eax,[edi][0].rb_aulPattern ;0
717: and eax,ebx
718: or eax,edx
719: xor eax,esi
720: mov [aulPatternBuffer][0],eax
721: mov eax,[edi][4].rb_aulPattern ;1
722: and eax,ebx
723: or eax,edx
724: xor eax,esi
725: mov [aulPatternBuffer][4],eax
726: mov eax,[edi][8].rb_aulPattern ;2
727: and eax,ebx
728: or eax,edx
729: xor eax,esi
730: mov [aulPatternBuffer][8],eax
731: mov eax,[edi][12].rb_aulPattern ;3
732: and eax,ebx
733: or eax,edx
734: xor eax,esi
735: mov [aulPatternBuffer][12],eax
736: mov eax,[edi][16].rb_aulPattern ;4
737: and eax,ebx
738: or eax,edx
739: xor eax,esi
740: mov [aulPatternBuffer][16],eax
741: mov eax,[edi][20].rb_aulPattern ;5
742: and eax,ebx
743: or eax,edx
744: xor eax,esi
745: mov [aulPatternBuffer][20],eax
746: mov eax,[edi][24].rb_aulPattern ;6
747: and eax,ebx
748: or eax,edx
749: xor eax,esi
750: mov [aulPatternBuffer][24],eax
751: mov eax,[edi][28].rb_aulPattern ;7
752: and eax,ebx
753: or eax,edx
754: xor eax,esi
755: mov [aulPatternBuffer][28],eax
756:
757: jmp bw_done_init_rop
758:
759: ;-----------------------------------------------------------------------;
760: ; Handle 2-color patterns.
761: ;-----------------------------------------------------------------------;
762:
763: align 4
764: public col2_colors
765: col2_colors:
766: lea eax,[edi].rb_aulPattern
767: mov pulPattern,eax ;pulPattern = &pbr.rb_aulPattern[0]
768: lea eax,gapfnSetTable
769: mov ppfnDraw,eax ;ppfnDraw = gapfnSetTable
770:
771: call col2_first_rectangle
772:
773: ; Restore VGA hardware to its default state:
774:
775: mov edx,VGA_BASE + GRAF_DATA
776: mov al,0ffh
777: out dx,al ;enable all bits through the Bit Mask
778:
779: mov esi,ppdev
780: dec edx ;point back to the Graphics Index reg
781: mov ah,byte ptr [esi].pdev_ulrm0_wmX[0]
782: ;write mode 0 setting for Graphics Mode
783: mov al,GRAF_MODE
784: out dx,ax ;write mode 0, read mode 0
785:
786: mov eax,GRAF_DATA_ROT + (DR_SET SHL 8)
787: out dx,ax ;replace mode, no rotate
788:
789: mov edx,VGA_BASE + SEQ_DATA
790: mov al,MM_ALL
791: out dx,al ;enable all planes
792:
793: cRet vMonoPat
794:
795: ;-----------------------------------------------------------------------;
796: ; Handle first rectangle for 2-color patterns.
797: ;-----------------------------------------------------------------------;
798:
799: ; We have to special case the first rectangle because we have to load
800: ; the latches with the background color after mapping the bank but before
801: ; doing any drawing.
802:
803: align 4
804: public col2_first_rectangle
805: col2_first_rectangle:
806: mov edi,prcl ;edi = prcl
807: mov edx,ppdev
808: mov eax,[edi].yBottom
809: mov ebx,[edi].yTop
810: mov edx,[edx].pdev_lPlanarNextScan
811:
812: mov lDelta,edx ;lDelta = ppdev->lPlanarNextScan
813: mov ulLastDestScan,eax ;ulLastDestScan = prcl->bottom
814: mov ulCurrentDestScan,ebx ;ulCurrentDestScan = prcl->top
815:
816: mov ecx,edx
817: imul ecx,ebx
818:
819: sub ebx,yBrushOrg
820: and ebx,7
821: mov yBrush,ebx ;yBrush = (prcl->top - pptlBrush->y) & 7
822: ; (our current index into the pattern
823: ; array)
824:
825: mov ebx,[edi].xLeft
826: shr ebx,2
827: add ebx,ecx ;ebx = prcl->top * lDelta +
828: ; (prcl->left >> 2)
829: ; (offset into bitmap of left side)
830:
831: mov eax,[edi].xRight
832: shr eax,2
833: add eax,ecx
834: mov ulRightDest,eax ;ulRightDest = prcl->top * lDelta +
835: ; (prcl->right >> 2)
836: ; (offset into bitmap of right side)
837:
838: xor esi,esi ;zero our flags
839:
840: mov ecx,[edi].xLeft
841: and ecx,3
842: jz short col2_done_left ;skip if we don't need a left edge
843:
844: mov esi,0fh ;compute the plane mask for the left
845: shl esi,cl ; edge. we don't use a look-up table
846: mov ulLeftMask,esi ; 'cause it won't be in the cache.
847:
848: mov esi,(BLOCK_LEFT_EDGE shr 2)
849: ;set our flag (we soon shift left by 2)
850:
851: mov ulLeftDest,ebx ;ulLeftDest = prcl->top * lDelta +
852: ; (prcl->left >> 2)
853: inc ebx ;ebx = ulMiddleDest = ulLeftDest + 1
854: ; (we have to adjust our offset to
855: ; the first whole byte)
856:
857: col2_done_left:
858: sub eax,ebx ;eax = cjMiddle =
859: ; ulRightDest - ulMiddleDest
860: mov ulMiddleDest,ebx ;ulMiddleDest
861:
862: .errnz (BLOCK_MIDDLE_STARTS_UNALIGNED shr 2) - 1
863: and ebx,1 ;set bit if middle doesn't start
864: or esi,ebx ; word aligned (remembering we'll
865: ; soon shift flags left by 2)
866:
867: mov ecx,[edi].xRight
868: and ecx,3
869: jz short col2_done_right ;skip if we don't need a right edge
870:
871: mov ebx,0f0h ;compute the plane mask for the right
872: rol bl,cl ; edge. we don't use a look-up table
873: mov ulRightMask,ebx ; 'cause it won't be in the cache.
874:
875: or esi,(BLOCK_RIGHT_EDGE shr 2)
876: ;set our flag (we soon shift left by 2)
877:
878: ; If the count of whole bytes is negative, that means that the pattern
879: ; starts and ends in the same quadpixel, so we do some more work:
880:
881: cmp eax,0
882: jge short col2_done_right
883:
884: ; It starts and ends in the same quadpixel:
885:
886: and esi,not (BLOCK_RIGHT_EDGE shr 2)
887: ;turn off right edge
888: and ebx,ulLeftMask
889: mov ulLeftMask,ebx
890: xor eax,eax ;we do zero middle bytes
891:
892: align 4
893: public col2_done_right
894: col2_done_right:
895: mov ebx,ppfnDraw
896:
897: ; We're going to do two 'adc esi,esi' instructions here, effectively
898: ; shifting our flags left by 2, and setting the low bits:
899:
900: .errnz (BLOCK_NO_MIDDLE shr 1) - 1
901: cmp eax,1 ;shift flags left one, and set low
902: adc esi,esi ; bit if we don't need to do a middle
903:
904: .errnz (BLOCK_MIDDLE_ENDS_UNALIGNED) - 1
905: shr eax,1
906: mov cwMiddle,eax ;cwMiddle = cjMiddle / 2
907: adc esi,esi ;shift flags left one, and set low
908: ; bit if the middle isn't an even
909: ; number of bytes in length
910:
911: sub edx,eax
912: sub edx,eax
913: mov lMiddleDelta,edx ;lMiddleDelta = lDelta - 2 * cwMiddle
914:
915: mov eax,[ebx+esi*4]
916: mov pfnDraw,eax ;pointer to function that draws
917: ; everything in the bank
918:
919: mov ebx,ppdev
920: test esi,BLOCK_NO_MIDDLE
921: jz short col2_have_a_middle
922:
923: ;-----------------------------------------;
924:
925: ; Handle case where there isn't a whole quadpixel that will be overwritten
926: ; by the pattern, and so we don't have a convenient place for loading the
927: ; latches. For this case, we'll use off-screen memory.
928:
929: mov esi,[ebx].pdev_pbceCache
930: mov eax,[esi].bce_yCache
931:
932: cmp eax,[ebx].pdev_rcl1PlanarClip.yTop
933: jl short col2_no_middle_map_brush_bank
934:
935: cmp eax,[ebx].pdev_rcl1PlanarClip.yBottom
936: jl short col2_no_middle_brush_bank_mapped
937:
938: col2_no_middle_map_brush_bank:
939: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
940: <ebx,eax,JustifyBottom>
941:
942: col2_no_middle_brush_bank_mapped:
943: mov ecx,prb ;ecx = prb
944: mov esi,[esi].bce_ulCache
945: add esi,[ebx].pdev_pvBitmapStart
946:
947: mov eax,[ecx].rb_ulBkColor
948: mov [esi],al
949: mov al,[esi] ;latches now laoded with bk color
950:
951: mov edi,[edi].yTop
952:
953: cmp edi,[ebx].pdev_rcl1PlanarClip.yTop
954: jl short col2_no_middle_map_init_bank
955:
956: cmp edi,[ebx].pdev_rcl1PlanarClip.yBottom
957: jl col2_latches_loaded
958:
959: col2_no_middle_map_init_bank:
960: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
961: <ebx,edi,JustifyTop>
962:
963: mov ecx,prb ;reload ecx = prb
964: jmp col2_latches_loaded
965:
966: ;-----------------------------------------;
967:
968: col2_have_a_middle:
969: mov edi,[edi].yTop
970:
971: cmp edi,[ebx].pdev_rcl1PlanarClip.yTop
972: jl short col2_map_init_bank
973:
974: cmp edi,[ebx].pdev_rcl1PlanarClip.yBottom
975: jl short col2_init_bank_mapped
976:
977: col2_map_init_bank:
978: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
979: <ebx,edi,JustifyTop>
980:
981: col2_init_bank_mapped:
982: mov ecx,prb ;ecx = prb
983: mov esi,ulMiddleDest
984: add esi,[ebx].pdev_pvBitmapStart
985: ;pointer to the first whole quadpixel
986: ; that will be overwritten by the
987: ; pattern, and so which is a great
988: ; place to use to load the latches
989:
990: mov eax,[ecx].rb_ulBkColor
991: mov [esi],al
992: mov al,[esi] ;latches now loaded with bk color
993:
994: ; Set VGA to read mode 0 and write mode 2:
995:
996: col2_latches_loaded:
997:
998: ; ebx = ppdev
999: ; ecx = prb
1000: ; edi = top line of rectangle
1001:
1002: mov esi,ppdev
1003: mov edx,VGA_BASE + GRAF_ADDR
1004: mov ah,byte ptr [esi].pdev_ulrm0_wmX[2]
1005: mov al,GRAF_MODE
1006: out dx,ax
1007:
1008: mov eax,GRAF_DATA_ROT + (DR_XOR SHL 8)
1009: out dx,ax ;XOR to flip latched data to make ~bk
1010:
1011: mov ah,byte ptr [ecx].rb_ulBkColor
1012: xor ah,byte ptr [ecx].rb_ulFgColor
1013: mov al,GRAF_BIT_MASK
1014: out dx,ax ;pass through common fg & bk bits
1015: ; unchanged from bk color in latches;
1016: ; non-common bits come from XOR in the
1017: ; ALUs, flipped from the bk to the fg
1018: ; state if the glyph bit for the pixel
1019: ; in that plane is 1, still in bk state
1020: ; if the glyph bit for that plane is 0
1021:
1022: ; All done hardware initialization. Do rest of this boring stuff:
1023:
1024: mov eax,ulLastDestScan
1025: mov ebx,[ebx].pdev_rcl1PlanarClip.yBottom
1026:
1027: sub eax,ebx
1028: sbb ecx,ecx
1029: and ecx,eax
1030: add ebx,ecx ;ebx = min(ulLastDestScan,
1031: ; ppdev->rcl1PlanarClip.yBottom)
1032: mov ulCurrentDestScan,ebx
1033:
1034: sub ebx,edi
1035: mov ulBlockHeight,ebx ;ulBlockHeight = ebx - ulCurrentDestScan
1036:
1037: ; Draw everything in this bank:
1038:
1039: CALL_AND_JUMP pfnDraw,dual_done_pfnDraw
1040:
1041: ;=======================================================================;
1042: ;========================= Set Block Drawers ===========================;
1043: ;=======================================================================;
1044:
1045: ;-----------------------------------------------------------------------;
1046: ; dual_wide_11_w
1047: ;
1048: ; Draws middle words with 1 leading byte and 1 trailing byte.
1049: ;
1050: ; Input:
1051: ; ppdev - pointer to physical device structure
1052: ; ulBlockHeight - # of scans to draw
1053: ; lMiddleDelta - distance from end of current scan to start of next
1054: ; ulMiddleDest - offset in bitmap at which to start drawing
1055: ; yBrush - current y brush alignment
1056: ; cwMiddle - # of words to draw on each scan
1057: ;
1058: ; Output:
1059: ; esi - new y brush alignment
1060: ; ulMiddleDest - new bitmap offset
1061: ;-----------------------------------------------------------------------;
1062:
1063: align 4
1064: public dual_wide_11_w
1065: dual_wide_11_w:
1066:
1067: ; We only have to reset which planes are enabled if we do edges too:
1068:
1069: mov edx,VGA_BASE + SEQ_DATA
1070: mov al,MM_ALL
1071: out dx,al
1072:
1073: ; Calculate full start addresses:
1074:
1075: mov ulSaveEsp,esp
1076: mov edi,ppdev
1077: mov ebx,ulBlockHeight
1078: mov esp,pulPattern
1079: mov edx,lMiddleDelta
1080: add edx,2 ;account for first and last
1081: ; bytes
1082: mov esi,yBrush
1083: mov edi,[edi].pdev_pvBitmapStart
1084: add edi,ulMiddleDest
1085: inc edi ;align to word
1086:
1087: SET_UP_UNROLL_AND_BRANCH ebx,ecx,pfnMonoWide11,LOOP_UNROLL_SHIFT
1088:
1089: UNROLL_LOOP_ENTRY_TABLE pfnMonoWide11,W11,LOOP_UNROLL_COUNT
1090:
1091: MONO_WIDE_11_W_M macro ENTRY_LABEL,ENTRY_INDEX
1092: &ENTRY_LABEL&ENTRY_INDEX&:
1093:
1094: ; We aim to overdrive.
1095:
1096: mov eax,[esp+esi * 4] ;load pattern for this scan
1097: mov [edi-1],ah ;write the first byte
1098:
1099: mov ecx,cwMiddle
1100: dec ecx ;account for first and last
1101: ; bytes
1102: rep stosw ;light 8 pels on every write
1103:
1104: inc esi ;advance to next scan of pattern
1105: and esi,7
1106: mov [edi],al ;write that last byte
1107:
1108: add edi,edx ;advance to next scan
1109: endm ;-----------------------------------;
1110:
1111: ; EBX = count of unrolled loop iterations
1112: ; EDX = offset from end of scan to start of next
1113: ; ESI = current offset into pattern
1114: ; EDI = target address to which to write
1115: ; ESP = pointer to start of pattern
1116:
1117: align 4
1118: dual_wide_11_w_loop:
1119: UNROLL_LOOP MONO_WIDE_11_W_M,W11,LOOP_UNROLL_COUNT
1120: dec ebx
1121: jnz short dual_wide_11_w_loop
1122:
1123: ; get ready for next time:
1124:
1125: mov ecx,ppdev
1126: mov esp,ulSaveEsp
1127: sub edi,[ecx].pdev_pvBitmapStart
1128: dec edi ;undo our word alignment
1129: mov ulMiddleDest,edi
1130:
1131: PLAIN_RET
1132:
1133: ;-----------------------------------------------------------------------;
1134: ; dual_wide_10_w
1135: ;
1136: ; Draws middle words with 1 leading byte and 0 trailing bytes.
1137: ;
1138: ; Input:
1139: ; ppdev - pointer to physical device structure
1140: ; ulBlockHeight - # of scans to draw
1141: ; lMiddleDelta - distance from end of current scan to start of next
1142: ; ulMiddleDest - offset in bitmap at which to start drawing
1143: ; yBrush - current y brush alignment
1144: ; cwMiddle - # of words to draw on each scan
1145: ;
1146: ; Output:
1147: ; esi - new y brush alignment
1148: ; ulMiddleDest - new bitmap offset
1149: ;-----------------------------------------------------------------------;
1150:
1151: align 4
1152: public dual_wide_10_w
1153: dual_wide_10_w:
1154:
1155: ; We only have to reset which planes are enabled if we do edges too:
1156:
1157: mov edx,VGA_BASE + SEQ_DATA
1158: mov al,MM_ALL
1159: out dx,al
1160:
1161: ; Calculate full start addresses:
1162:
1163: mov ulSaveEsp,esp
1164: mov edi,ppdev
1165: mov ebx,ulBlockHeight
1166: mov esp,pulPattern
1167: mov edx,lMiddleDelta
1168: mov esi,yBrush
1169: mov edi,[edi].pdev_pvBitmapStart
1170: add edi,ulMiddleDest
1171: inc edi ;align to word
1172:
1173: SET_UP_UNROLL_AND_BRANCH ebx,ecx,pfnMonoWide10,LOOP_UNROLL_SHIFT
1174:
1175: UNROLL_LOOP_ENTRY_TABLE pfnMonoWide10,W10,LOOP_UNROLL_COUNT
1176:
1177: MONO_WIDE_10_W_M macro ENTRY_LABEL,ENTRY_INDEX
1178: &ENTRY_LABEL&ENTRY_INDEX&:
1179:
1180: mov eax,[esp+esi * 4] ;load pattern for this scan
1181: mov [edi-1],ah ;write the first byte
1182:
1183: mov ecx,cwMiddle
1184: rep stosw ;light 8 pels on every write
1185:
1186: inc esi ;advance to next scan of pattern
1187: and esi,7
1188:
1189: add edi,edx ;advance to next scan
1190: endm ;-----------------------------------;
1191:
1192: ; EBX = count of unrolled loop iterations
1193: ; EDX = offset from end of scan to start of next
1194: ; ESI = current offset into pattern
1195: ; EDI = target address to which to write
1196: ; ESP = pointer to start of pattern
1197:
1198: align 4
1199: dual_wide_10_w_loop:
1200: UNROLL_LOOP MONO_WIDE_10_W_M,W10,LOOP_UNROLL_COUNT
1201: dec ebx
1202: jnz short dual_wide_10_w_loop
1203:
1204: ; get ready for next time:
1205:
1206: mov ecx,ppdev
1207: mov esp,ulSaveEsp
1208: sub edi,[ecx].pdev_pvBitmapStart
1209: dec edi ;undo our word alignment
1210: mov ulMiddleDest,edi
1211:
1212: PLAIN_RET
1213:
1214: ;-----------------------------------------------------------------------;
1215: ; dual_wide_01_w
1216: ;
1217: ; Draws middle words with 0 leading bytes and 1 trailing byte.
1218: ;
1219: ; Input:
1220: ; ppdev - pointer to physical device structure
1221: ; ulBlockHeight - # of scans to draw
1222: ; lMiddleDelta - distance from end of current scan to start of next
1223: ; ulMiddleDest - offset in bitmap at which to start drawing
1224: ; yBrush - current y brush alignment
1225: ; cwMiddle - # of words to draw on each scan
1226: ;
1227: ; Output:
1228: ; esi - new y brush alignment
1229: ; ulMiddleDest - new bitmap offset
1230: ;-----------------------------------------------------------------------;
1231:
1232: align 4
1233: public dual_wide_01_w
1234: dual_wide_01_w:
1235:
1236: ; We only have to reset which planes are enabled if we do edges too:
1237:
1238: mov edx,VGA_BASE + SEQ_DATA
1239: mov al,MM_ALL
1240: out dx,al
1241:
1242: ; Calculate full start addresses:
1243:
1244: mov ulSaveEsp,esp
1245: mov edi,ppdev
1246: mov ebx,ulBlockHeight
1247: mov esp,pulPattern
1248: mov edx,lMiddleDelta
1249: mov esi,yBrush
1250: mov edi,[edi].pdev_pvBitmapStart
1251: add edi,ulMiddleDest
1252:
1253: SET_UP_UNROLL_AND_BRANCH ebx,ecx,pfnMonoWide01,LOOP_UNROLL_SHIFT
1254:
1255: UNROLL_LOOP_ENTRY_TABLE pfnMonoWide01,W01,LOOP_UNROLL_COUNT
1256:
1257: MONO_WIDE_01_W_M macro ENTRY_LABEL,ENTRY_INDEX
1258: &ENTRY_LABEL&ENTRY_INDEX&:
1259:
1260: mov eax,[esp+esi*4] ;load pattern for this scan
1261:
1262: mov ecx,cwMiddle
1263: rep stosw ;light 8 pels on every write
1264:
1265: inc esi ;advance to next scan of pattern
1266: and esi,7
1267: mov [edi],al ;write that last byte
1268:
1269: add edi,edx ;advance to next scan
1270: endm ;-----------------------------------;
1271:
1272: ; EBX = count of unrolled loop iterations
1273: ; EDX = offset from end of scan to start of next
1274: ; ESI = current offset into pattern
1275: ; EDI = target address to which to write
1276: ; ESP = pointer to start of pattern
1277:
1278: align 4
1279: dual_wide_01_w_loop:
1280: UNROLL_LOOP MONO_WIDE_01_W_M,W01,LOOP_UNROLL_COUNT
1281: dec ebx
1282: jnz short dual_wide_01_w_loop
1283:
1284: ; get ready for next time:
1285:
1286: mov ecx,ppdev
1287: mov esp,ulSaveEsp
1288: sub edi,[ecx].pdev_pvBitmapStart
1289: mov ulMiddleDest,edi
1290:
1291: PLAIN_RET
1292:
1293: ;-----------------------------------------------------------------------;
1294: ; dual_wide_00_w
1295: ;
1296: ; Draws middle words with 0 leading bytes and 1 trailing byte.
1297: ;
1298: ; Input:
1299: ; ppdev - pointer to physical device structure
1300: ; ulBlockHeight - # of scans to draw
1301: ; lMiddleDelta - distance from end of current scan to start of next
1302: ; ulMiddleDest - offset in bitmap at which to start drawing
1303: ; yBrush - current y brush alignment
1304: ; cwMiddle - # of words to draw on each scan
1305: ;
1306: ; Output:
1307: ; esi - new y brush alignment
1308: ; ulMiddleDest - new bitmap offset
1309: ;-----------------------------------------------------------------------;
1310:
1311: align 4
1312: public dual_wide_00_w
1313: dual_wide_00_w:
1314:
1315: ; We only have to reset which planes are enabled if we do edges too:
1316:
1317: mov edx,VGA_BASE + SEQ_DATA
1318: mov al,MM_ALL
1319: out dx,al
1320:
1321: ; Calculate full start addresses:
1322:
1323: mov ulSaveEsp,esp
1324: mov edi,ppdev
1325: mov ebx,ulBlockHeight
1326: mov esp,pulPattern
1327: mov edx,lMiddleDelta
1328: mov esi,yBrush
1329: mov edi,[edi].pdev_pvBitmapStart
1330: add edi,ulMiddleDest
1331:
1332: SET_UP_UNROLL_AND_BRANCH ebx,ecx,pfnMonoWide00,LOOP_UNROLL_SHIFT
1333:
1334: UNROLL_LOOP_ENTRY_TABLE pfnMonoWide00,W00,LOOP_UNROLL_COUNT
1335:
1336: MONO_WIDE_00_W_M macro ENTRY_LABEL,ENTRY_INDEX
1337: &ENTRY_LABEL&ENTRY_INDEX&:
1338:
1339: mov eax,[esp+esi*4] ;load pattern for this scan
1340:
1341: mov ecx,cwMiddle
1342: rep stosw ;light 8 pels on every write
1343:
1344: inc esi ;advance to next scan of pattern
1345: and esi,7
1346:
1347: add edi,edx ;advance to next scan
1348: endm ;-----------------------------------;
1349:
1350: ; EBX = count of unrolled loop iterations
1351: ; EDX = offset from end of scan to start of next
1352: ; ESI = current offset into pattern
1353: ; EDI = target address to which to write
1354: ; ESP = pointer to start of pattern
1355:
1356: align 4
1357: dual_wide_00_w_loop:
1358: UNROLL_LOOP MONO_WIDE_00_W_M,W00,LOOP_UNROLL_COUNT
1359: dec ebx
1360: jnz short dual_wide_00_w_loop
1361:
1362: ; get ready for next time:
1363:
1364: mov ecx,ppdev
1365: mov esp,ulSaveEsp
1366: sub edi,[ecx].pdev_pvBitmapStart
1367: mov ulMiddleDest,edi
1368:
1369: PLAIN_RET
1370:
1371: ;-----------------------------------------------------------------------;
1372: ; dual_left_1_w
1373: ;
1374: ; Draws a left edge when the next byte is not word aligned.
1375: ;
1376: ; Input:
1377: ; ppdev - pointer to physical device structure
1378: ; ulBlockHeight - # of scans to draw
1379: ; lDelta - distance from end of current scan to start of next
1380: ; ulLeftDest - offset in bitmap at which to start drawing
1381: ; yBrush - current y brush alignment
1382: ;
1383: ; Output:
1384: ; esi - new y brush alignment
1385: ; ulLeftDest - new bitmap offset
1386: ;-----------------------------------------------------------------------;
1387:
1388: align 4
1389: public dual_left_1_w
1390: dual_left_1_w:
1391:
1392: ; Set left mask by disabling some planes:
1393:
1394: mov edx,VGA_BASE + SEQ_DATA
1395: mov eax,ulLeftMask
1396: out dx,al
1397:
1398: ; Calculate full start addresses:
1399:
1400: mov edi,ppdev
1401: mov ebx,ulBlockHeight
1402: mov ecx,pulPattern
1403: mov edx,lDelta
1404: mov esi,yBrush
1405: mov edi,[edi].pdev_pvBitmapStart
1406: add edi,ulLeftDest
1407:
1408: SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoLeft1,LOOP_UNROLL_SHIFT
1409:
1410: UNROLL_LOOP_ENTRY_TABLE pfnMonoLeft1,LEFT_W1,LOOP_UNROLL_COUNT
1411:
1412: MONO_LEFT_1_W_M macro ENTRY_LABEL,ENTRY_INDEX
1413: &ENTRY_LABEL&ENTRY_INDEX&:
1414:
1415: mov eax,[ecx+esi*4] ;load pattern for this scan
1416: mov [edi],al ;write the low byte
1417: inc esi ;advance to next scan of pattern
1418: and esi,7
1419: add edi,edx ;advance to next scan
1420: endm ;-----------------------------------;
1421:
1422: ; EBX = count of unrolled loop iterations
1423: ; ECX = pointer to start of pattern
1424: ; EDX = offset to next scan
1425: ; ESI = current offset into pattern
1426: ; EDI = target address to which to write
1427:
1428: align 4
1429: dual_left_1_w_loop:
1430: UNROLL_LOOP MONO_LEFT_1_W_M,LEFT_W1,LOOP_UNROLL_COUNT
1431: dec ebx
1432: jnz short dual_left_1_w_loop
1433:
1434: ; get ready for next time:
1435:
1436: mov ecx,ppdev
1437: sub edi,[ecx].pdev_pvBitmapStart
1438: mov ulLeftDest,edi
1439:
1440: PLAIN_RET
1441:
1442: ;-----------------------------------------------------------------------;
1443: ; dual_left_0_w
1444: ;
1445: ; Draws a left edge when the next byte is word aligned.
1446: ;
1447: ; Input:
1448: ; ppdev - pointer to physical device structure
1449: ; ulBlockHeight - # of scans to draw
1450: ; lDelta - distance from end of current scan to start of next
1451: ; ulLeftDest - offset in bitmap at which to start drawing
1452: ; yBrush - current y brush alignment
1453: ;
1454: ; Output:
1455: ; esi - new y brush alignment
1456: ; ulLeftDest - new bitmap offset
1457: ;-----------------------------------------------------------------------;
1458:
1459: align 4
1460: public dual_left_0_w
1461: dual_left_0_w:
1462:
1463: ; Set left mask by disabling some planes:
1464:
1465: mov edx,VGA_BASE + SEQ_DATA
1466: mov eax,ulLeftMask
1467: out dx,al
1468:
1469: ; Calculate full start addresses:
1470:
1471: mov edi,ppdev
1472: mov ebx,ulBlockHeight
1473: mov ecx,pulPattern
1474: mov edx,lDelta
1475: mov esi,yBrush
1476: mov edi,[edi].pdev_pvBitmapStart
1477: add edi,ulLeftDest
1478:
1479: SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoLeft0,LOOP_UNROLL_SHIFT
1480:
1481: UNROLL_LOOP_ENTRY_TABLE pfnMonoLeft0,LEFT_W0,LOOP_UNROLL_COUNT
1482:
1483: MONO_LEFT_0_W_M macro ENTRY_LABEL,ENTRY_INDEX
1484: &ENTRY_LABEL&ENTRY_INDEX&:
1485:
1486: mov eax,[ecx+esi*4] ;load pattern for this scan
1487: mov [edi],ah ;write the high byte
1488: inc esi ;advance to next scan of pattern
1489: and esi,7
1490: add edi,edx ;advance to next scan
1491: endm ;-----------------------------------;
1492:
1493: ; EBX = count of unrolled loop iterations
1494: ; ECX = pointer to start of pattern
1495: ; EDX = offset to next scan
1496: ; ESI = current offset into pattern
1497: ; EDI = target address to which to write
1498:
1499: align 4
1500: dual_left_0_w_loop:
1501: UNROLL_LOOP MONO_LEFT_0_W_M,LEFT_W0,LOOP_UNROLL_COUNT
1502: dec ebx
1503: jnz short dual_left_0_w_loop
1504:
1505: ; get ready for next time:
1506:
1507: mov ecx,ppdev
1508: sub edi,[ecx].pdev_pvBitmapStart
1509: mov ulLeftDest,edi
1510:
1511: PLAIN_RET
1512:
1513: ;-----------------------------------------------------------------------;
1514: ; dual_right_1_w
1515: ;
1516: ; Draws a right edge when not word aligned.
1517: ;
1518: ; Input:
1519: ; ppdev - pointer to physical device structure
1520: ; ulBlockHeight - # of scans to draw
1521: ; lDelta - distance from end of current scan to start of next
1522: ; ulRightDest - offset in bitmap at which to start drawing
1523: ; yBrush - current y brush alignment
1524: ;
1525: ; Output:
1526: ; esi - new y brush alignment
1527: ; ulRightDest - new bitmap offset
1528: ;-----------------------------------------------------------------------;
1529:
1530: align 4
1531: public dual_right_1_w
1532: dual_right_1_w:
1533:
1534: ; Set right mask by disabling some planes:
1535:
1536: mov edx,VGA_BASE + SEQ_DATA
1537: mov eax,ulRightMask
1538: out dx,al
1539:
1540: ; Calculate full start addresses:
1541:
1542: mov edi,ppdev
1543: mov ebx,ulBlockHeight
1544: mov ecx,pulPattern
1545: mov edx,lDelta
1546: mov esi,yBrush
1547: mov edi,[edi].pdev_pvBitmapStart
1548: add edi,ulRightDest
1549:
1550: SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoRight1,LOOP_UNROLL_SHIFT
1551:
1552: UNROLL_LOOP_ENTRY_TABLE pfnMonoRight1,RIGHT_W1,LOOP_UNROLL_COUNT
1553:
1554: MONO_RIGHT_1_W_M macro ENTRY_LABEL,ENTRY_INDEX
1555: &ENTRY_LABEL&ENTRY_INDEX&:
1556:
1557: mov eax,[ecx+esi*4] ;load pattern for this scan
1558: mov [edi],ah ;write the high byte
1559: inc esi ;advance to next scan of pattern
1560: and esi,7
1561: add edi,edx ;advance to next scan
1562: endm ;-----------------------------------;
1563:
1564: ; EBX = count of unrolled loop iterations
1565: ; ECX = pointer to start of pattern
1566: ; EDX = offset to next scan
1567: ; ESI = current offset into pattern
1568: ; EDI = target address to which to write
1569:
1570: align 4
1571: dual_right_1_w_loop:
1572: UNROLL_LOOP MONO_RIGHT_1_W_M,RIGHT_W1,LOOP_UNROLL_COUNT
1573: dec ebx
1574: jnz short dual_right_1_w_loop
1575:
1576: ; get ready for next time:
1577:
1578: mov ecx,ppdev
1579: sub edi,[ecx].pdev_pvBitmapStart
1580: mov ulRightDest,edi
1581:
1582: PLAIN_RET
1583:
1584: ;-----------------------------------------------------------------------;
1585: ; dual_right_0_w
1586: ;
1587: ; Draws a right edge when word aligned.
1588: ;
1589: ; Input:
1590: ; ppdev - pointer to physical device structure
1591: ; ulBlockHeight - # of scans to draw
1592: ; lDelta - distance from end of current scan to start of next
1593: ; ulRightDest - offset in bitmap at which to start drawing
1594: ; yBrush - current y brush alignment
1595: ;
1596: ; Output:
1597: ; esi - new y brush alignment
1598: ; ulRightDest - new bitmap offset
1599: ;-----------------------------------------------------------------------;
1600:
1601: align 4
1602: public dual_right_0_w
1603: dual_right_0_w:
1604:
1605: ; Set right mask by disabling some planes:
1606:
1607: mov edx,VGA_BASE + SEQ_DATA
1608: mov eax,ulRightMask
1609: out dx,al
1610:
1611: ; Calculate full start addresses:
1612:
1613: mov edi,ppdev
1614: mov ebx,ulBlockHeight
1615: mov ecx,pulPattern
1616: mov edx,lDelta
1617: mov esi,yBrush
1618: mov edi,[edi].pdev_pvBitmapStart
1619: add edi,ulRightDest
1620:
1621: SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoRight0,LOOP_UNROLL_SHIFT
1622:
1623: UNROLL_LOOP_ENTRY_TABLE pfnMonoRight0,RIGHT_W0,LOOP_UNROLL_COUNT
1624:
1625: MONO_RIGHT_0_W_M macro ENTRY_LABEL,ENTRY_INDEX
1626: &ENTRY_LABEL&ENTRY_INDEX&:
1627:
1628: mov eax,[ecx+esi*4] ;load pattern for this scan
1629: mov [edi],al ;write the low byte
1630: inc esi ;advance to next scan of pattern
1631: and esi,7
1632: add edi,edx ;advance to next scan
1633: endm ;-----------------------------------;
1634:
1635: ; EBX = count of unrolled loop iterations
1636: ; ECX = pointer to start of pattern
1637: ; EDX = offset to next scan
1638: ; ESI = current offset into pattern
1639: ; EDI = target address to which to write
1640:
1641: align 4
1642: dual_right_0_w_loop:
1643: UNROLL_LOOP MONO_RIGHT_0_W_M,RIGHT_W0,LOOP_UNROLL_COUNT
1644: dec ebx
1645: jnz short dual_right_0_w_loop
1646:
1647: ; get ready for next time:
1648:
1649: mov ecx,ppdev
1650: sub edi,[ecx].pdev_pvBitmapStart
1651: mov ulRightDest,edi
1652:
1653: PLAIN_RET
1654:
1655: ;=======================================================================;
1656: ;========================= ROP Block Drawers ===========================;
1657: ;=======================================================================;
1658:
1659: ;-----------------------------------------------------------------------;
1660: ; dual_wide_11_rw
1661: ;
1662: ; Draws middle words with 1 leading byte and 1 trailing byte.
1663: ;
1664: ; Input:
1665: ; ppdev - pointer to physical device structure
1666: ; ulBlockHeight - # of scans to draw
1667: ; lMiddleDelta - distance from end of current scan to start of next
1668: ; ulMiddleDest - offset in bitmap at which to start drawing
1669: ; yBrush - current y brush alignment
1670: ; cwMiddle - # of words to draw on each scan
1671: ;
1672: ; Output:
1673: ; esi - new y brush alignment
1674: ; ulMiddleDest - new bitmap offset
1675: ;-----------------------------------------------------------------------;
1676:
1677: UNROLL_LOOP_ENTRY_TABLE pfnMonoWide_rw_11,RW11,LOOP_UNROLL_COUNT
1678:
1679: align 4
1680: public dual_wide_11_rw
1681: dual_wide_11_rw:
1682:
1683: ; We only have to reset which planes are enabled if we do edges too:
1684:
1685: mov edx,VGA_BASE + SEQ_DATA
1686: mov al,MM_ALL
1687: out dx,al
1688:
1689: mov ulSaveEsp,esp
1690: mov edi,ppdev
1691:
1692: mov esp,pulPattern ;load those registers
1693: mov edi,[edi].pdev_pvBitmapStart
1694: add edi,ulMiddleDest
1695: mov esi,yBrush
1696: mov edx,ulBlockHeight
1697: mov ebx,cwMiddle
1698:
1699: mov eax,[esp+esi*4] ;load pattern for this scan
1700: inc esi
1701: and esi,7
1702:
1703: SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnMonoWide_rw_11,LOOP_UNROLL_SHIFT
1704:
1705: mov pfnUnroll,ecx
1706: mov cUnrolledLoops,ebx
1707:
1708: jmp ecx
1709:
1710: MONO_RWIDE_11_RW_M macro ENTRY_LABEL,ENTRY_INDEX
1711: &ENTRY_LABEL&ENTRY_INDEX&:
1712: and [edi],ah
1713: and [edi+1],al
1714: add edi,2 ;the write will overlap this
1715: endm ;-----------------------------------;
1716:
1717: ; EAX = pattern for this scan
1718: ; EBX = count of unrolled loop iterations
1719: ; EDX = number of scans to do
1720: ; ESI = current offset into pattern
1721: ; EDI = target address to which to write
1722: ; ESP = pointer to start of pattern
1723:
1724: align 4
1725: dual_wide_11_rw_loop:
1726: UNROLL_LOOP MONO_RWIDE_11_RW_M,RW11,LOOP_UNROLL_COUNT
1727: dec ebx
1728: jnz short dual_wide_11_rw_loop
1729:
1730: add edi,lMiddleDelta
1731: dec edx
1732: jz short dual_wide_11_rw_done
1733:
1734: mov eax,[esp+esi*4] ;load pattern for this scan
1735: inc esi
1736: and esi,7
1737:
1738: mov ebx,cUnrolledLoops
1739: jmp pfnUnroll
1740:
1741: dual_wide_11_rw_done:
1742: mov ecx,ppdev
1743: mov esp,ulSaveEsp
1744: sub edi,[ecx].pdev_pvBitmapStart
1745: mov ulMiddleDest,edi
1746:
1747: PLAIN_RET
1748:
1749: ;-----------------------------------------------------------------------;
1750: ; dual_wide_10_rw
1751: ;
1752: ; Draws middle words with 1 leading byte and 0 trailing bytes.
1753: ;
1754: ; Input:
1755: ; ppdev - pointer to physical device structure
1756: ; ulBlockHeight - # of scans to draw
1757: ; lMiddleDelta - distance from end of current scan to start of next
1758: ; ulMiddleDest - offset in bitmap at which to start drawing
1759: ; yBrush - current y brush alignment
1760: ; cwMiddle - # of words to draw on each scan
1761: ;
1762: ; Output:
1763: ; esi - new y brush alignment
1764: ; ulMiddleDest - new bitmap offset
1765: ;-----------------------------------------------------------------------;
1766:
1767: UNROLL_LOOP_ENTRY_TABLE pfnMonoWide_rw_10,RW10,LOOP_UNROLL_COUNT
1768:
1769: align 4
1770: public dual_wide_10_rw
1771: dual_wide_10_rw:
1772:
1773: ; We only have to reset which planes are enabled if we do edges too:
1774:
1775: mov edx,VGA_BASE + SEQ_DATA
1776: mov al,MM_ALL
1777: out dx,al
1778:
1779: mov ulSaveEsp,esp
1780: mov edi,ppdev
1781:
1782: mov esp,pulPattern ;load those registers
1783: mov edi,[edi].pdev_pvBitmapStart
1784: add edi,ulMiddleDest
1785: mov esi,yBrush
1786: mov edx,ulBlockHeight
1787: mov ebx,cwMiddle
1788:
1789: mov eax,[esp+esi*4] ;load pattern for this scan
1790: inc esi
1791: and esi,7
1792:
1793: or ebx,ebx ;have to watch for zero words
1794: jz short dual_wide_10_rw_only_one_byte
1795:
1796: SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnMonoWide_rw_10,LOOP_UNROLL_SHIFT
1797:
1798: mov pfnUnroll,ecx
1799: mov cUnrolledLoops,ebx
1800:
1801: jmp ecx
1802:
1803: dual_wide_10_rw_only_one_byte:
1804: mov pfnUnroll,offset dual_wide_10_rw_odd_byte
1805: jmp short dual_wide_10_rw_odd_byte
1806:
1807: MONO_RWIDE_10_RW_M macro ENTRY_LABEL,ENTRY_INDEX
1808: &ENTRY_LABEL&ENTRY_INDEX&:
1809: and [edi],ah
1810: and [edi+1],al
1811: add edi,2 ;the write will overlap this
1812: endm ;-----------------------------------;
1813:
1814: ; EAX = pattern for this scan
1815: ; EBX = count of unrolled loop iterations
1816: ; EDX = number of scans to do
1817: ; ESI = current offset into pattern
1818: ; EDI = target address to which to write
1819: ; ESP = pointer to start of pattern
1820:
1821: align 4
1822: dual_wide_10_rw_loop:
1823: UNROLL_LOOP MONO_RWIDE_10_RW_M,RW10,LOOP_UNROLL_COUNT
1824: dec ebx
1825: jnz short dual_wide_10_rw_loop
1826:
1827: dual_wide_10_rw_odd_byte:
1828: and [edi],ah ;write that odd byte
1829:
1830: add edi,lMiddleDelta
1831: dec edx
1832: jz short dual_wide_10_rw_done
1833:
1834: mov eax,[esp+esi*4] ;load pattern for this scan
1835: inc esi
1836: and esi,7
1837:
1838: mov ebx,cUnrolledLoops
1839: jmp pfnUnroll
1840:
1841: dual_wide_10_rw_done:
1842: mov ecx,ppdev
1843: mov esp,ulSaveEsp
1844: sub edi,[ecx].pdev_pvBitmapStart
1845: mov ulMiddleDest,edi
1846:
1847: PLAIN_RET
1848:
1849: ;-----------------------------------------------------------------------;
1850: ; dual_wide_01_rw
1851: ;
1852: ; Draws middle words with 0 leading bytes and 1 trailing byte.
1853: ;
1854: ; Input:
1855: ; ppdev - pointer to physical device structure
1856: ; ulBlockHeight - # of scans to draw
1857: ; lMiddleDelta - distance from end of current scan to start of next
1858: ; ulMiddleDest - offset in bitmap at which to start drawing
1859: ; yBrush - current y brush alignment
1860: ; cwMiddle - # of words to draw on each scan
1861: ;
1862: ; Output:
1863: ; esi - new y brush alignment
1864: ; ulMiddleDest - new bitmap offset
1865: ;-----------------------------------------------------------------------;
1866:
1867: UNROLL_LOOP_ENTRY_TABLE pfnMonoWide_rw_01,RW01,LOOP_UNROLL_COUNT
1868:
1869: align 4
1870: public dual_wide_01_rw
1871: dual_wide_01_rw:
1872:
1873: ; We only have to reset which planes are enabled if we do edges too:
1874:
1875: mov edx,VGA_BASE + SEQ_DATA
1876: mov al,MM_ALL
1877: out dx,al
1878:
1879: mov ulSaveEsp,esp
1880: mov edi,ppdev
1881:
1882: mov esp,pulPattern ;load those registers
1883: mov edi,[edi].pdev_pvBitmapStart
1884: add edi,ulMiddleDest
1885: mov esi,yBrush
1886: mov edx,ulBlockHeight
1887: mov ebx,cwMiddle
1888:
1889: mov eax,[esp+esi*4] ;load pattern for this scan
1890: inc esi
1891: and esi,7
1892:
1893: or ebx,ebx
1894: jz short dual_wide_01_rw_only_one_byte
1895:
1896: SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnMonoWide_rw_01,LOOP_UNROLL_SHIFT
1897:
1898: mov pfnUnroll,ecx
1899: mov cUnrolledLoops,ebx
1900:
1901: jmp ecx
1902:
1903: dual_wide_01_rw_only_one_byte:
1904: mov pfnUnroll,offset dual_wide_01_rw_odd_byte
1905: jmp short dual_wide_01_rw_odd_byte
1906:
1907: MONO_RWIDE_01_RW_M macro ENTRY_LABEL,ENTRY_INDEX
1908: &ENTRY_LABEL&ENTRY_INDEX&:
1909: and [edi],al
1910: and [edi+1],ah
1911: add edi,2 ;the write will overlap this
1912: endm ;-----------------------------------;
1913:
1914: ; EAX = pattern for this scan
1915: ; EBX = count of unrolled loop iterations
1916: ; EDX = number of scans to do
1917: ; ESI = current offset into pattern
1918: ; EDI = target address to which to write
1919: ; ESP = pointer to start of pattern
1920:
1921: align 4
1922: dual_wide_01_rw_loop:
1923: UNROLL_LOOP MONO_RWIDE_01_RW_M,RW01,LOOP_UNROLL_COUNT
1924: dec ebx
1925: jnz short dual_wide_01_rw_loop
1926:
1927: dual_wide_01_rw_odd_byte:
1928: and [edi],al ;write that odd byte
1929:
1930: add edi,lMiddleDelta
1931: dec edx
1932: jz short dual_wide_01_rw_done
1933:
1934: mov eax,[esp+esi*4] ;load pattern for this scan
1935: inc esi
1936: and esi,7
1937:
1938: mov ebx,cUnrolledLoops
1939: jmp pfnUnroll
1940:
1941: dual_wide_01_rw_done:
1942: mov ecx,ppdev
1943: mov esp,ulSaveEsp
1944: sub edi,[ecx].pdev_pvBitmapStart
1945: mov ulMiddleDest,edi
1946:
1947: PLAIN_RET
1948:
1949: ;-----------------------------------------------------------------------;
1950: ; dual_wide_00_rw
1951: ;
1952: ; Draws middle words with 0 leading bytes and 0 trailing bytes.
1953: ;
1954: ; Input:
1955: ; ppdev - pointer to physical device structure
1956: ; ulBlockHeight - # of scans to draw
1957: ; lMiddleDelta - distance from end of current scan to start of next
1958: ; ulMiddleDest - offset in bitmap at which to start drawing
1959: ; yBrush - current y brush alignment
1960: ; cwMiddle - # of words to draw on each scan
1961: ;
1962: ; Output:
1963: ; esi - new y brush alignment
1964: ; ulMiddleDest - new bitmap offset
1965: ;-----------------------------------------------------------------------;
1966:
1967: UNROLL_LOOP_ENTRY_TABLE pfnMonoWide_rw_00,RW00,LOOP_UNROLL_COUNT
1968:
1969: align 4
1970: public dual_wide_00_rw
1971: dual_wide_00_rw:
1972:
1973: ; We only have to reset which planes are enabled if we do edges too:
1974:
1975: mov edx,VGA_BASE + SEQ_DATA
1976: mov al,MM_ALL
1977: out dx,al
1978:
1979: mov ulSaveEsp,esp
1980: mov edi,ppdev
1981:
1982: mov esp,pulPattern ;load those registers
1983: mov edi,[edi].pdev_pvBitmapStart
1984: add edi,ulMiddleDest
1985: mov esi,yBrush
1986: mov edx,ulBlockHeight
1987: mov ebx,cwMiddle
1988:
1989: mov eax,[esp+esi*4] ;load pattern for this scan
1990: inc esi
1991: and esi,7
1992:
1993: SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnMonoWide_rw_00,LOOP_UNROLL_SHIFT
1994:
1995: mov pfnUnroll,ecx
1996: mov cUnrolledLoops,ebx
1997:
1998: jmp ecx
1999:
2000: MONO_RWIDE_00_RW_M macro ENTRY_LABEL,ENTRY_INDEX
2001: &ENTRY_LABEL&ENTRY_INDEX&:
2002: and [edi],al
2003: and [edi+1],ah
2004: add edi,2 ;the write will overlap this
2005: endm ;-----------------------------------;
2006:
2007: ; EAX = pattern for this scan
2008: ; EBX = count of unrolled loop iterations
2009: ; EDX = number of scans to do
2010: ; ESI = current offset into pattern
2011: ; EDI = target address to which to write
2012: ; ESP = pointer to start of pattern
2013:
2014: align 4
2015: dual_wide_00_rw_loop:
2016: UNROLL_LOOP MONO_RWIDE_00_RW_M,RW00,LOOP_UNROLL_COUNT
2017: dec ebx
2018: jnz short dual_wide_00_rw_loop
2019:
2020: add edi,lMiddleDelta
2021: dec edx
2022: jz short dual_wide_00_rw_done
2023:
2024: mov eax,[esp+esi*4] ;load pattern for this scan
2025: inc esi
2026: and esi,7
2027:
2028: mov ebx,cUnrolledLoops
2029: jmp pfnUnroll
2030:
2031: dual_wide_00_rw_done:
2032: mov ecx,ppdev
2033: mov esp,ulSaveEsp
2034: sub edi,[ecx].pdev_pvBitmapStart
2035: mov ulMiddleDest,edi
2036:
2037: PLAIN_RET
2038:
2039: ;-----------------------------------------------------------------------;
2040: ; dual_left_1_rw
2041: ;
2042: ; Draws a left edge when the next byte is not word aligned.
2043: ;
2044: ; Input:
2045: ; ppdev - pointer to physical device structure
2046: ; ulBlockHeight - # of scans to draw
2047: ; lDelta - distance from end of current scan to start of next
2048: ; ulLeftDest - offset in bitmap at which to start drawing
2049: ; yBrush - current y brush alignment
2050: ;
2051: ; Output:
2052: ; esi - new y brush alignment
2053: ; ulLeftDest - new bitmap offset
2054: ;-----------------------------------------------------------------------;
2055:
2056: align 4
2057: public dual_left_1_rw
2058: dual_left_1_rw:
2059:
2060: ; Set left mask by disabling some planes:
2061:
2062: mov edx,VGA_BASE + SEQ_DATA
2063: mov eax,ulLeftMask
2064: out dx,al
2065:
2066: ; Calculate full start addresses:
2067:
2068: mov edi,ppdev
2069: mov ebx,ulBlockHeight
2070: mov ecx,pulPattern
2071: mov edx,lDelta
2072: mov esi,yBrush
2073: mov edi,[edi].pdev_pvBitmapStart
2074: add edi,ulLeftDest
2075:
2076: SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoLeft_rw_1,LOOP_UNROLL_SHIFT
2077:
2078: UNROLL_LOOP_ENTRY_TABLE pfnMonoLeft_rw_1,LEFT_RW1,LOOP_UNROLL_COUNT
2079:
2080: MONO_LEFT_1_RW_M macro ENTRY_LABEL,ENTRY_INDEX
2081: &ENTRY_LABEL&ENTRY_INDEX&:
2082:
2083: mov eax,[ecx+esi*4] ;load pattern for this scan
2084: and [edi],al ;write the low byte
2085: inc esi ;advance to next scan of pattern
2086: and esi,7
2087: add edi,edx ;advance to next scan
2088: endm ;-----------------------------------;
2089:
2090: ; EBX = count of unrolled loop iterations
2091: ; ECX = pointer to start of pattern
2092: ; EDX = offset to next scan
2093: ; ESI = current offset into pattern
2094: ; EDI = target address to which to write
2095:
2096: align 4
2097: dual_left_1_rw_loop:
2098: UNROLL_LOOP MONO_LEFT_1_RW_M,LEFT_RW1,LOOP_UNROLL_COUNT
2099: dec ebx
2100: jnz short dual_left_1_rw_loop
2101:
2102: ; get ready for next time:
2103:
2104: mov ecx,ppdev
2105: sub edi,[ecx].pdev_pvBitmapStart
2106: mov ulLeftDest,edi
2107:
2108: PLAIN_RET
2109:
2110: ;-----------------------------------------------------------------------;
2111: ; dual_left_0_rw
2112: ;
2113: ; Draws a left edge when the next byte is word aligned.
2114: ;
2115: ; Input:
2116: ; ppdev - pointer to physical device structure
2117: ; ulBlockHeight - # of scans to draw
2118: ; lDelta - distance from end of current scan to start of next
2119: ; ulLeftDest - offset in bitmap at which to start drawing
2120: ; yBrush - current y brush alignment
2121: ;
2122: ; Output:
2123: ; esi - new y brush alignment
2124: ; ulLeftDest - new bitmap offset
2125: ;-----------------------------------------------------------------------;
2126:
2127: align 4
2128: public dual_left_0_rw
2129: dual_left_0_rw:
2130:
2131: ; Set left mask by disabling some planes:
2132:
2133: mov edx,VGA_BASE + SEQ_DATA
2134: mov eax,ulLeftMask
2135: out dx,al
2136:
2137: ; Calculate full start addresses:
2138:
2139: mov edi,ppdev
2140: mov ebx,ulBlockHeight
2141: mov ecx,pulPattern
2142: mov edx,lDelta
2143: mov esi,yBrush
2144: mov edi,[edi].pdev_pvBitmapStart
2145: add edi,ulLeftDest
2146:
2147: SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoLeft_rw_0,LOOP_UNROLL_SHIFT
2148:
2149: UNROLL_LOOP_ENTRY_TABLE pfnMonoLeft_rw_0,LEFT_RW0,LOOP_UNROLL_COUNT
2150:
2151: MONO_LEFT_0_RW_M macro ENTRY_LABEL,ENTRY_INDEX
2152: &ENTRY_LABEL&ENTRY_INDEX&:
2153:
2154: mov eax,[ecx+esi*4] ;load pattern for this scan
2155: and [edi],ah ;write the high byte
2156: inc esi ;advance to next scan of pattern
2157: and esi,7
2158: add edi,edx ;advance to next scan
2159: endm ;-----------------------------------;
2160:
2161: ; EBX = count of unrolled loop iterations
2162: ; ECX = pointer to start of pattern
2163: ; EDX = offset to next scan
2164: ; ESI = current offset into pattern
2165: ; EDI = target address to which to write
2166:
2167: align 4
2168: dual_left_0_rw_loop:
2169: UNROLL_LOOP MONO_LEFT_0_RW_M,LEFT_RW0,LOOP_UNROLL_COUNT
2170: dec ebx
2171: jnz short dual_left_0_rw_loop
2172:
2173: ; get ready for next time:
2174:
2175: mov ecx,ppdev
2176: sub edi,[ecx].pdev_pvBitmapStart
2177: mov ulLeftDest,edi
2178:
2179: PLAIN_RET
2180:
2181: ;-----------------------------------------------------------------------;
2182: ; dual_right_1_rw
2183: ;
2184: ; Draws a right edge when not word aligned.
2185: ;
2186: ; Input:
2187: ; ppdev - pointer to physical device structure
2188: ; ulBlockHeight - # of scans to draw
2189: ; lDelta - distance from end of current scan to start of next
2190: ; ulRightDest - offset in bitmap at which to start drawing
2191: ; yBrush - current y brush alignment
2192: ;
2193: ; Output:
2194: ; esi - new y brush alignment
2195: ; ulRightDest - new bitmap offset
2196: ;-----------------------------------------------------------------------;
2197:
2198: align 4
2199: public dual_right_1_rw
2200: dual_right_1_rw:
2201:
2202: ; Set right mask by disabling some planes:
2203:
2204: mov edx,VGA_BASE + SEQ_DATA
2205: mov eax,ulRightMask
2206: out dx,al
2207:
2208: ; Calculate full start addresses:
2209:
2210: mov edi,ppdev
2211: mov ebx,ulBlockHeight
2212: mov ecx,pulPattern
2213: mov edx,lDelta
2214: mov esi,yBrush
2215: mov edi,[edi].pdev_pvBitmapStart
2216: add edi,ulRightDest
2217:
2218: SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoRight_rw_1,LOOP_UNROLL_SHIFT
2219:
2220: UNROLL_LOOP_ENTRY_TABLE pfnMonoRight_rw_1,RIGHT_RW1,LOOP_UNROLL_COUNT
2221:
2222: MONO_RIGHT_1_RW_M macro ENTRY_LABEL,ENTRY_INDEX
2223: &ENTRY_LABEL&ENTRY_INDEX&:
2224:
2225: mov eax,[ecx+esi*4] ;load pattern for this scan
2226: and [edi],ah ;write the high byte
2227: inc esi ;advance to next scan of pattern
2228: and esi,7
2229: add edi,edx ;advance to next scan
2230: endm ;-----------------------------------;
2231:
2232: ; EBX = count of unrolled loop iterations
2233: ; ECX = pointer to start of pattern
2234: ; EDX = offset to next scan
2235: ; ESI = current offset into pattern
2236: ; EDI = target address to which to write
2237:
2238: align 4
2239: dual_right_1_rw_loop:
2240: UNROLL_LOOP MONO_RIGHT_1_RW_M,RIGHT_RW1,LOOP_UNROLL_COUNT
2241: dec ebx
2242: jnz short dual_right_1_rw_loop
2243:
2244: ; get ready for next time:
2245:
2246: mov ecx,ppdev
2247: sub edi,[ecx].pdev_pvBitmapStart
2248: mov ulRightDest,edi
2249:
2250: PLAIN_RET
2251:
2252: ;-----------------------------------------------------------------------;
2253: ; dual_right_0_rw
2254: ;
2255: ; Draws a right edge when word aligned.
2256: ;
2257: ; Input:
2258: ; ppdev - pointer to physical device structure
2259: ; ulBlockHeight - # of scans to draw
2260: ; lDelta - distance from end of current scan to start of next
2261: ; ulRightDest - offset in bitmap at which to start drawing
2262: ; yBrush - current y brush alignment
2263: ;
2264: ; Output:
2265: ; esi - new y brush alignment
2266: ; ulRightDest - new bitmap offset
2267: ;-----------------------------------------------------------------------;
2268:
2269: align 4
2270: public dual_right_0_rw
2271: dual_right_0_rw:
2272:
2273: ; Set right mask by disabling some planes:
2274:
2275: mov edx,VGA_BASE + SEQ_DATA
2276: mov eax,ulRightMask
2277: out dx,al
2278:
2279: ; Calculate full start addresses:
2280:
2281: mov edi,ppdev
2282: mov ebx,ulBlockHeight
2283: mov ecx,pulPattern
2284: mov edx,lDelta
2285: mov esi,yBrush
2286: mov edi,[edi].pdev_pvBitmapStart
2287: add edi,ulRightDest
2288:
2289: SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoRight_rw_0,LOOP_UNROLL_SHIFT
2290:
2291: UNROLL_LOOP_ENTRY_TABLE pfnMonoRight_rw_0,RIGHT_RW0,LOOP_UNROLL_COUNT
2292:
2293: MONO_RIGHT_0_RW_M macro ENTRY_LABEL,ENTRY_INDEX
2294: &ENTRY_LABEL&ENTRY_INDEX&:
2295:
2296: mov eax,[ecx+esi*4] ;load pattern for this scan
2297: and [edi],al ;write the low byte
2298: inc esi ;advance to next scan of pattern
2299: and esi,7
2300: add edi,edx ;advance to next scan
2301: endm ;-----------------------------------;
2302:
2303: ; EBX = count of unrolled loop iterations
2304: ; ECX = pointer to start of pattern
2305: ; EDX = offset to next scan
2306: ; ESI = current offset into pattern
2307: ; EDI = target address to which to write
2308:
2309: align 4
2310: dual_right_0_rw_loop:
2311: UNROLL_LOOP MONO_RIGHT_0_RW_M,RIGHT_RW0,LOOP_UNROLL_COUNT
2312: dec ebx
2313: jnz short dual_right_0_rw_loop
2314:
2315: ; get ready for next time:
2316:
2317: mov ecx,ppdev
2318: sub edi,[ecx].pdev_pvBitmapStart
2319: mov ulRightDest,edi
2320:
2321: PLAIN_RET
2322:
2323: ;-----------------------------------------------------------------------;
2324:
2325: endProc vMonoPat
2326:
2327: ;-----------------------------------------------------------------------;
2328: ; BOOL b2ColorBrush(pjBits, pjFgColor, pjBkColor)
2329: ;
2330: ; Determines if the 8x8x8bpp packed brush pointed to by pjBits has only
2331: ; two colors, and if so returns the 1bpp bitmap.
2332: ;
2333: ; Returns:
2334: ; eax = 1 if two (or one) color brush, 0 otherwise
2335: ; pjBits = pointer to packed 1bpp bitmap if a 2-color brush
2336: ; *pjFgColor = foreground color for returned 1bpp bitmap (i.e.,
2337: ; used to color-expand '1' bits)
2338: ; *pjBkColor = backgroun color for returned 1bpp bitmap (i.e.,
2339: ; used to color-expand '0' bits)
2340: ;-----------------------------------------------------------------------;
2341:
2342: cProc b2ColorBrush,12,< \
2343: uses esi edi ebx, \
2344: pjBits: ptr BYTE, \
2345: pjFgColor: ptr BYTE, \
2346: pjBkColor: ptr BYTE >
2347:
2348: ; al = first color
2349: ; ah = second color
2350: ; ecx = number of unrolled loops
2351:
2352: mov esi,pjBits
2353: mov ecx,(BRUSH_SIZE shr 1)
2354: mov al,[esi]
2355:
2356: align 4
2357: b2col_find_2nd_color_loop:
2358: mov ah,[esi+1]
2359: cmp ah,al
2360: jne short b2col_find_consecutive_2nd_color_loop_part_1
2361:
2362: add esi,2
2363: dec ecx
2364: jz short b2col_is_2_colors ;actually, it's only one color
2365:
2366: mov ah,[esi]
2367: cmp ah,al
2368: jne short b2col_find_consecutive_2nd_color_loop_part_2
2369: jmp short b2col_find_2nd_color_loop
2370:
2371: ;------------------------------------;
2372:
2373: align 4
2374: b2col_find_consecutive_1st_color_loop_part_1:
2375: add esi,2
2376: dec ecx
2377: jz short b2col_is_2_colors
2378:
2379: mov bl,[esi]
2380: cmp bl,ah
2381: je short b2col_find_consecutive_2nd_color_loop_part_2
2382: cmp bl,al
2383: jne short b2col_isnt_2_colors
2384:
2385: b2col_find_consecutive_1st_color_loop_part_2:
2386: mov bl,[esi+1]
2387: cmp bl,ah
2388: je short b2col_find_consecutive_2nd_color_loop_part_1
2389: cmp bl,al
2390: je short b2col_find_consecutive_1st_color_loop_part_1
2391:
2392: xor eax,eax
2393: cRet b2ColorBrush ;return FALSE
2394:
2395: ;------------------------------------;
2396:
2397: align 4
2398: b2col_find_consecutive_2nd_color_loop_part_1:
2399: add esi,2
2400: dec ecx
2401: jz short b2col_is_2_colors
2402:
2403: mov bl,[esi]
2404: cmp bl,al
2405: je short b2col_find_consecutive_1st_color_loop_part_2
2406: cmp bl,ah
2407: jne short b2col_isnt_2_colors
2408:
2409: b2col_find_consecutive_2nd_color_loop_part_2:
2410: mov bl,[esi+1]
2411: cmp bl,al
2412: je short b2col_find_consecutive_1st_color_loop_part_1
2413: cmp bl,ah
2414: je short b2col_find_consecutive_2nd_color_loop_part_1
2415:
2416: b2col_isnt_2_colors:
2417: xor eax,eax
2418: cRet b2ColorBrush ;return FALSE
2419:
2420: ;------------------------------------;
2421:
2422: public b2col_is_2_colors
2423: b2col_is_2_colors:
2424:
2425: ; Here, we want the color with the lesser value to be in 'al', and the
2426: ; other to be in 'ah'.
2427:
2428: cmp al,ah
2429: jb short b2col_ordered_colors
2430: xchg al,ah
2431:
2432: b2col_ordered_colors:
2433: mov ecx,(BRUSH_SIZE shr 3)
2434: mov esi,pjBits
2435: mov edi,esi
2436:
2437: ; Colors matching 'al' will get mapped to '1' bits, and colors matching
2438: ; 'ah' will get mapped to '0' bits:
2439:
2440: b2col_monochrome_bitmap_loop:
2441: cmp [esi+7],ah
2442: adc bl,bl
2443: cmp [esi+6],ah
2444: adc bl,bl
2445: cmp [esi+5],ah
2446: adc bl,bl
2447: cmp [esi+4],ah
2448: adc bl,bl
2449: cmp [esi+3],ah
2450: adc bl,bl
2451: cmp [esi+2],ah
2452: adc bl,bl
2453: cmp [esi+1],ah
2454: adc bl,bl
2455: cmp [esi],ah
2456: adc bl,bl
2457:
2458: ; At this point, where the 8 bytes of the bitmap were ordered 0 1 2 3 4 5 6 7,
2459: ; we've got the monochrome byte in 'bl' ordered 7 6 5 4 3 2 1 0. We want
2460: ; the word ordered '3 2 1 0 7 6 5 4 | 7 6 5 4 3 2 1 0' where the lower 4 bits
2461: ; of every bit are the planes mask, and the upper 4 bits are ordered to
2462: ; facilitate easy rotating.
2463: ;
2464: ; The word is actually written into a dword in the destination buffer.
2465:
2466: mov bh,bl
2467: ror bh,4
2468: mov [edi],ebx ;save this dword of monochrome bitmap
2469: add edi,4
2470: add esi,8
2471: dec ecx
2472: jnz b2col_monochrome_bitmap_loop
2473:
2474: ; Aside: because of the way this is written, if the two colors are black
2475: ; and white (i.e., 0x00 and 0xff), the foreground color will be black (0x00),
2476: ; and the background will be white (0xff).
2477:
2478: mov esi,pjFgColor
2479: mov edi,pjBkColor
2480: mov [esi],al ;save foreground color
2481: mov [edi],ah ;save background color
2482: mov eax,1
2483: cRet b2ColorBrush
2484:
2485: endProc b2ColorBrush
2486:
2487: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.