|
|
1.1 root 1: page ,132
2: ;---------------------------Module-Header------------------------------;
3: ; Module Name: special.asm
4: ;
5: ; Copyright (c) 1992 Microsoft Corporation
6: ;-----------------------------------------------------------------------;
7: title Special
8: .386
9:
10: ifndef DOS_PLATFORM
11: .model small,c
12: else
13: ifdef STD_CALL
14: .model small,c
15: else
16: .model small,pascal
17: endif; STD_CALL
18: endif; DOS_PLATFORM
19:
20: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
21: assume fs:nothing,gs:nothing
22:
23: .data
24:
25: ;BUGBUG this should be obtained from the surface
26:
27: extrn ulNextScan_global:dword
28:
29: .code
30:
31: _TEXT$01 SEGMENT DWORD USE32 PUBLIC 'CODE'
32: ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
33:
34: .xlist
35: include stdcall.inc ;calling convention cmacros
36: include i386\cmacFLAT.inc ; FLATland cmacros
37: include i386\display.inc ; Display specific structures
38: include i386\ppc.inc ; Pack pel conversion structure
39: include i386\bitblt.inc ; General definitions
40: include i386\ropdefs.inc ; Rop definitions
41: include i386\egavga.inc ; EGA register definitions
42: include i386\strucs.inc
43: .list
44:
45: ; Rops we use in this code
46:
47: ROP_P equ 0F0h
48: ROP_Pn equ 0Fh
49: ROP_S equ 0CCh
50: ROP_DDx equ 0
51: ROP_DDxn equ 0FFh
52: ROP_Dn equ 055h
53: ROP_DPx equ 05Ah
54:
55: ; Other values used in this code
56:
57: fr equ [ebp] ; Access to bitblt frame
58: bptr equ byte ptr
59:
60: ;----------------------------Public Routine----------------------------;
61: ; check_device_special_cases
62: ;
63: ; Check for fast special cases of BLT.
64: ;
65: ; Determine if the BLT is a special case which can be performed with
66: ; static code as opposed to code compiled on the stack, and, if so,
67: ; dispatch to the proper static code.
68: ;
69: ; The parameters needed for the BLT (phase alignment, directions of
70: ; movement, ...) have been computed and saved. These parameters will
71: ; now be interpreted and a BLT created on the stack.
72: ;
73: ; If the raster op is source copy, both devices are the screen, and the
74: ; phase alignment is 0, then the copy can be performed by the static
75: ; code using the EGA's write mode 1.
76: ;
77: ; If the rasterop is P, Pn, DDx (0), DDxn (1), and the brush is solid
78: ; or grey (for P and Pn), and the destination device is the screen,
79: ; then the operation can be performed by the static code using the EGA's
80: ; write mode 2 (write mode 0 for greys).
81: ;
82: ; Entry:
83: ; EDI --> pointer to target surface
84: ; EBP --> frame of BitBLT local variables
85: ; EGA registers in default state
86: ; Returns:
87: ; Carry set if BLT was performed with static code.
88: ; Error Returns:
89: ; Carry clear if BLT was not a special case.
90: ; Registers Destroyed:
91: ; AX,BX,CX,DX,SI,DI,DS,ES,flags
92: ; Registers Preserved:
93: ; EBP
94: ; Calls:
95: ;-----------------------------------------------------------------------;
96:
97: cProc check_device_special_cases
98:
99: xor cx,cx ;This is used, what is it????!!!
100: mov dh,fr.the_flags ;Keep the flags in DH for a while
101: test dh,F0_DEST_IS_DEV ;Is the destination a device?
102: jz cdsc_blt_not_special_cased ;Not device, cannot special case it
103: mov edi,fr.dest.next_scan ;Special case code expects this
104: mov al,byte ptr fr.Rop[0] ;Get the raster op
105: cmp al,ROP_S ;Is it src copy?
106: je cdsc_its_src_copy ; Yes, go check it out
107: cmp al,ROP_P
108: je short cdsc_its_patblt
109:
110: cdsc_not_s_or_p:
111: xor bl,bl ;Color for 0 fill
112: cmp al,ROP_DDx
113: je short cdsc_its_1_or_0
114: cmp al,ROP_Pn
115: je short cdsc_its_inverse_patblt
116: cmp al,ROP_Dn
117: je short cdsc_its_dn
118: cmp al,ROP_DPx
119: je short cdsc_its_dpx
120: cmp al,ROP_DDxn
121: jne cdsc_blt_not_special_cased
122: mov bl,0FFh ;Color for 1 fill
123:
124: ; It's "1" (DDxn) or "0" (DDx)
125: cdsc_its_1_or_0:
126: mov fr.brush_accel,SOLID_BRUSH ;(no brush given for DDx or DDxn)
127: call ega_solid_pat
128: jmp cdsc_exit
129:
130: cdsc_its_patblt:
131: mov bl,fr.brush_accel ;Ccolor in lower bits, flags in upper
132: test bl,SOLID_BRUSH
133: jnz short cdsc_its_a_solid_color
134: test bl,GREY_SCALE
135: jz short cdsc_not_solid_nor_grey
136: xor bl,bl ;It's grey. !!! what is this flag
137: call ega_solid_pat
138: jmp cdsc_exit
139:
140: cdsc_not_solid_nor_grey:
141: call do_wes_patblt
142: jmp cdsc_exit
143:
144: cdsc_its_inverse_solid_color:
145: not bl
146: cdsc_its_a_solid_color:
147: mov cx,2
148: call do_solid_patcopy ;color and accl. flags already in BL
149: jmp short cdsc_exit
150:
151: cdsc_its_inverse_patblt:
152: mov bl,fr.brush_accel ;color in lower bits, flags in upper
153: test bl,SOLID_BRUSH
154: jnz short cdsc_its_inverse_solid_color
155: test bl,GREY_SCALE
156: jz short cdsc_blt_not_special_cased
157: mov bl,-1 ;It's grey. !!! What is this flag
158: call ega_solid_pat
159: jmp short cdsc_exit
160:
161: cdsc_its_dn:
162: call do_wes_invert
163: jmp short cdsc_exit
164:
165: cdsc_its_dpx:
166: mov ah,fr.brush_accel ;color in lower bits, flags in upper
167: test ah,SOLID_BRUSH
168: jnz cdsc_its_solid_dpx ;dpx with solid brush
169: test ah,GREY_SCALE ;Otherwise must be a grey brush
170: jz short cdsc_blt_not_special_cased
171: call do_grey_dpx
172: jmp short cdsc_exit
173:
174: cdsc_its_solid_dpx:
175: call do_wes_dpx_solidpat ;solid color => can special case
176: jmp short cdsc_exit
177:
178:
179: ;-----------------------------------------------------------------------;
180: ; This is a source copy. The phase must be zero to special case the
181: ; source copy, and both devices must be the screen.
182: ;
183: ; errnz F0_SRC_IS_DEV - 00001000b
184: ; errnz F0_SRC_IS_COLOR - 00000100b
185: ;
186: ; its_src_copy:
187: ; and dh,F0_SRC_IS_DEV + F0_SRC_IS_COLOR
188: ; shiftr dh,2
189: ; cmp fr.phase_h,1 ; Gives CF if horizontal phase = zero
190: ; rcl dh,1
191: ; Now we have the needed flags in the lower 3 bits of DH
192: ; ; Src=EGA Src=Color Phase0
193: ;
194: ; dw do_wes_mono_trick ; 0 0 0
195: ; dw blt_not_a_special_case ; 0 0 1
196: ; dw blt_not_a_special_case ; 0 1 0
197: ; dw blt_not_a_special_case ; 0 1 1
198: ; dw do_wes_mono_trick ; 1 0 0
199: ; dw blt_not_a_special_case ; 1 0 1
200: ; dw blt_not_a_special_case ; 1 1 0
201: ; dw ega_src_copy ; 1 1 1
202: ;-----------------------------------------------------------------------;
203:
204: cdsc_its_src_copy:
205: test dh,F0_SRC_IS_DEV
206: jnz short cdsc_exit
207:
208: cdsc_source_is_memory:
209: test dh,F0_SRC_IS_COLOR ;mono-mem to color-EGA conversion?
210: jnz cdsc_blt_not_special_cased ;color to color, cannot special case it
211: call do_wes_mono_trick
212: jmp short cdsc_exit
213:
214: cdsc_blt_not_special_cased:
215: clc
216: cRet check_device_special_cases
217:
218: cdsc_exit:
219: stc
220: cRet check_device_special_cases
221:
222:
223: ;----------------------------Private-Routine----------------------------;
224: ; calc_parms
225: ;
226: ; Calculate the parameters needed for the output functions contained
227: ; in this file.
228: ;
229: ; To avoid conditional jumps we will use some sick optimizations.
230: ; Remember this:
231: ; adc ax,-1 ; DEC AX if carry clear
232: ; sbb ax,0 ; DEC AX if carry set
233: ; sbb ax,-1 ; INC AX if carry clear
234: ; adc ax,0 ; INC AX if carry set
235: ;
236: ; Entry:
237: ; EBP --> BitBLT local frame
238: ; Returns:
239: ; ESI set to upper left of bitmap or pattern
240: ; EDI set to upper left
241: ; EDX = src bitmap width (if present)
242: ; ECX = fr.yExt
243: ; EBX = offset into pattern (if pat present)
244: ; sets dest_right_edge
245: ; sets start_mask[0]
246: ; sets last_mask[0]
247: ; sets inner_loop_count
248: ; Registers Destroyed:
249: ; EAX,flags
250: ; Registers Preserved:
251: ; EBP
252: ; Alters:
253: ;
254: ; Calls:
255: ; None
256: ;-----------------------------------------------------------------------;
257:
258: .errnz SIZE_PATTERN - 8 ; any power of 2 will work
259:
260: align 4
261: calc_parms:
262:
263: ; Left edge.
264:
265: movzx edi,fr.DestxOrg ;X origin in pixels, must be positive
266: mov ebx,edi
267: mov cl,7
268: and ecx,edi ;Save lower 3 bits
269: mov fr.phase_h,cl
270: shr edi,3 ;EDI set for left edge
271: mov al,0FFh
272: shr al,cl
273: mov byte ptr fr.start_mask[0],al
274:
275: ; Right edge.
276:
277: movzx eax,fr.xExt
278: add ebx,eax ;Right edge in pixels
279: mov cl,7
280: and cl,bl ;save lower 3 bits
281: shr ebx,3 ;convert to bytes
282: mov fr.start_fl,ebx ;dest_right_edge (reuse stk variable)
283: mov al,0FFh
284: shr al,cl
285: not al
286:
287: ; Check if the BLT does not cross any byte boundaries.
288:
289: sub ebx,edi ;make EBX # bytes including left edge
290: jnz crosses_byte_boundary
291: and byte ptr fr.start_mask[0],al
292: xor al,al
293:
294: ; There are 2 cases where we get zero for fr.inner_loop_count:
295: ; When the start and end bytes are adjacent and when they are
296: ; the same byte. In the latter case we get -1 for
297: ; fr.inner_loop_count so INC BX now so it will be zero.
298:
299: inc ebx
300: crosses_byte_boundary:
301:
302: cmp al,0FFh
303: sbb al,-1 ;AL=FF -> AL=0 (put in innerloop)
304: mov byte ptr fr.last_mask[0],al
305:
306: ; Inner loop -- combine edge bytes into inner loop if they are
307: ; full bytes.
308:
309: mov fr.end_fl,ebx ;src_right_edge (reuse stk variable)
310: mov al,byte ptr fr.start_mask[0]
311: cmp al,0FFh
312:
313: ; If gl_start_mask = FF the carry is clear, otherwise carry is set.
314: ; We want to DEC BX if carry set because we have already included
315: ; the left edge byte in BX, but we shouldn't have included it if
316: ; it's only a partial byte.
317:
318: sbb ebx,0
319: cmp al,0FFh
320:
321: ; If gl_start_mask = FF the carry is clear, otherwise carry is set.
322: ; We want to INC AL (zero it) if it is FF (carry clear) because we
323: ; will do this edge as part of the innerloop.
324:
325: sbb al,-1
326: mov byte ptr fr.start_mask[0],al
327: mov fr.inner_loop_count,ebx
328: movzx eax,fr.DestyOrg
329: imul eax,ulNextScan_global
330: add edi,eax
331: mov esi,fr.pdsurfDst
332: add edi,[esi].dsurf_pvBitmapStart
333:
334: ; The source.
335:
336: test fr.the_flags,F0_SRC_PRESENT
337: jz no_source
338: mov esi,fr.pdsurfSrc
339: mov ecx,[esi].dsurf_lNextScan ;!!! will this be correct ??
340: mov esi,[esi].dsurf_pvBitmapStart
341:
342: ; Left edge.
343:
344: movzx ebx,fr.SrcxOrg
345: mov dl,7
346: and dl,bl ;get lower 3 bits ( Src Mod 8 )
347: sub fr.phase_h,dl ;phase def'd as Mod8[gl_dest]-
348: shr ebx,3 ; Mod8[gl_src]
349: add esi,ebx ;ESI set for left edge
350: movzx eax,fr.SrcyOrg
351: mul ecx
352: add esi,eax
353: add fr.end_fl,esi ;src_right_edge (reuse stack variable)
354: mov edx,ecx
355: jmp short no_pattern
356: no_source:
357: test fr.the_flags,F0_PAT_PRESENT ; assuming P or S but not both
358: jz no_pattern
359: mov esi,fr.lpPBrush
360: movzx ebx,fr.DestyOrg
361: and ebx,SIZE_PATTERN - 1
362: no_pattern:
363: movzx ecx,fr.yExt
364: PLAIN_RET
365:
366:
367: ;----------------------------Private-Routine----------------------------;
368: ; ega_solid_pat
369: ;
370: ; EGA special case for solid color pattern copy.
371: ;
372: ; The following routine is invoked instead of generating code for a
373: ; pattern copy. The actual time involved in executing the pattern
374: ; copy as static code as compared to compiled code is a win.
375: ;
376: ; This code can only be used if the pattern is a solid color or a grey,
377: ; and the operation is to the screen. In this case, the three bits of
378: ; color stored in the accelerator byte of the brush will be used, or the
379: ; bits of the grey brush.
380: ;
381: ; The logic operations which will invoke this routine are:
382: ;
383: ; P
384: ; Pn
385: ; DDx
386: ; DDxn
387: ;
388: ; Entry:
389: ; BL = color to write or xor value for a grey pattern
390: ; CX = Mode register value (sort of)
391: ; EBP = BitBLT local variable frame
392: ; Returns:
393: ; Nothing
394: ; Registers Destroyed:
395: ; ALL except EBP
396: ; Registers Preserved:
397: ; EBP
398: ; Calls:
399: ; None
400: ;-----------------------------------------------------------------------;
401:
402: align 4
403: ega_solid_pat:
404:
405: ; Instead of pushing and popping the destination pointer and adding in
406: ; the fr.dest.Incr, the bias needed for adjusting the pointer at the
407: ; end of a scan line will be computed and used.
408: ;
409: ; Since this is a pattern copy, the fr.dest.Incr will be positive.
410:
411: ; mov esi,edi ;Get destination increment
412: ; sub esi,1 ;Adjust for first byte
413: lea esi,-1[edi]
414: sub esi,fr.inner_loop_count ;Compute number of bytes to copy
415:
416: ; Put color in Set/Reset if it is a solid color.
417:
418: mov dx,EGA_BASE + GRAF_ADDR
419: or cx,cx
420: jz not_solid_color
421: mov ax,MM_ALL * 256 + GRAF_ENAB_SR
422: out dx,ax
423: mov ah,bl
424: mov al,GRAF_SET_RESET
425: out dx,ax
426: not_solid_color:
427: mov al,GRAF_BIT_MASK ;Leave graphics controller pointing
428: out dx,al ; to the bitmask register, which
429: inc dx ; is where cursor leaves it too
430:
431: ; Set up for the loop.
432:
433: mov edi,fr.dest.lp_bits ;--> destination
434: mov fr.phase_h,bl ;Save color to write or grey XOR mask
435:
436: ega_solid_pat_20:
437: mov al,fr.phase_h ;Get the color to write
438: test fr.brush_accel,SOLID_BRUSH ;Grey scale brush?
439: jnz ega_solid_pat_30 ; No, a solid color
440: mov bl,fr.pat_row ;Get scan of brush
441: inc bl ; and update brush pointer
442: mov fr.pat_row,bl
443: dec bl
444: and ebx,00000111b
445: add ebx,fr.lpPBrush
446: xor al,bptr [ebx] ;Invert if needed
447:
448: ega_solid_pat_30:
449: mov bl,al
450: mov al,bptr fr.start_mask[1] ;Set bitmask for first byte
451: out dx,al
452: mov al,bl
453: xchg al,[edi] ;xchg to load EGA's latches first
454: inc edi ;PAT_COPY step +X always!
455:
456: mov ecx,fr.inner_loop_count ;Set count for innerloop
457: jecxz ega_solid_pat_40 ;No innerloop or last byte
458: mov al,0FFh ;Inner loop alters all bits
459: out dx,al
460: mov al,bl
461: rep stosb
462:
463: ega_solid_pat_40:
464: mov al,bptr fr.last_mask[1] ;Last byte?
465: or al,al
466: jz ega_solid_pat_50 ;No last byte
467: out dx,al
468: xchg bl,[edi]
469:
470: ega_solid_pat_50:
471: add edi,esi ;--> next destination
472: dec fr.yExt ;Any more scans to process?
473: jnz ega_solid_pat_20 ; Yes
474: PLAIN_RET
475:
476:
477: ;----------------------------Private-Routine----------------------------;
478: ; do_wes_invert
479: ; do_wes_dpx_solidpat
480: ;
481: ; Entry:
482: ; EBP --> BitBLT local variable frame
483: ; AH = color of solid-pat.
484: ; Returns:
485: ; Nothing
486: ; Registers Destroyed:
487: ; ALL but EBP
488: ; Registers Preserved:
489: ; EBP
490: ; Calls:
491: ; calc_parms
492: ; edge_invert
493: ; invert
494: ;-----------------------------------------------------------------------;
495:
496: align 4
497: do_wes_invert:
498:
499: mov ah,0Fh ; black
500:
501: do_wes_dpx_solidpat label near
502:
503: ; Setup SET_RESET.
504:
505: mov dx,EGA_BASE + GRAF_ADDR
506: mov al,GRAF_SET_RESET
507: out dx,ax
508: mov ax,0F00h + GRAF_ENAB_SR ; enable all planes
509: out dx,ax
510:
511: ; Go to XOR mode.
512:
513: mov ax,GRAF_DATA_ROT + 256 * DR_XOR
514: out dx,ax
515:
516: call calc_parms
517: mov ah,byte ptr fr.start_mask[0]
518: or ah,ah
519: jz no_left_invert_edge
520: push edi
521: call edge_invert
522: pop edi
523: inc edi
524:
525: no_left_invert_edge:
526: mov ebx,fr.inner_loop_count
527: or ebx,ebx
528: jz no_inner_invert_loop
529: movzx ecx,fr.yExt
530: push edi
531: call invert
532: pop edi
533: add edi,fr.inner_loop_count
534:
535: no_inner_invert_loop:
536: mov ah,byte ptr fr.last_mask[0]
537: or ah,ah
538: jz no_last_invert_edge
539: movzx ecx,fr.yExt
540: call edge_invert
541:
542: no_last_invert_edge:
543: PLAIN_RET
544:
545:
546: ;----------------------------Private-Routine----------------------------;
547: ;do_solid_patcopy() is called to copy (PatCopy) a solid brush directly to
548: ;the screen.
549: ;
550: ;Entry:
551: ; BL color to write with
552: ; EDI fr.dest.next_scan which is equal to width_b
553: ; EBP local varible frame
554: ;
555: ;-----------------------------------------------------------------------;
556:
557: align 4
558: do_solid_patcopy:
559:
560: cmp fr.inner_loop_count,0 ;if zero, let ega_solid_pat do the work
561: jne dsp_do_it
562: call ega_solid_pat
563: PLAIN_RET
564:
565: dsp_do_it:
566: sub eax,eax ;accumulate flags in AL
567: mov esi,edi ;SI: fr.dest.next_scan (must be > 0)
568: mov edi,fr.dest.lp_bits ;EDI-->first byte to write to
569: mov bh,bptr fr.start_mask[1]
570: cmp ah,bh ;is there a left edge?
571: rcl al,1 ;CY if there is an edge to draw
572: sub bh,0ffh ;is the left edge an entire byte wide?
573: neg bh ;CY if less than a byte
574: rcl al,1 ;accumulate flag into AL
575: mov bh,bptr fr.last_mask[1]
576: cmp ah,bh ;is there a right edge?
577: rcl al,1 ;CY if there is an edge to draw
578: sub bh,0ffh ;is right edge an entire byte wide?
579: neg bh ;CY if less than a byte
580: rcl al,1 ;accumulate flag into AL
581: test al,04h ;set all pixels in left byte?
582: jnz dsp_keep_left_edge ;no. Do normal stuff
583: inc fr.inner_loop_count ;left edge is an entire byte. INC inner
584: and al,0f7h ;loop cnt and draw it the fast way
585:
586: dsp_keep_left_edge:
587: test al,01h ;set all pixels in right byte?
588: jnz dsp_keep_right_edge ;no. Do normal stuff
589: inc fr.inner_loop_count ;need to set all pixels in right byte.
590: and al,0fdh ;inc inner loop cnt do it the fast way
591:
592: dsp_keep_right_edge:
593: test al,0ah ;any edges to draw?
594: jz dsp_draw_core_piece ;no, just do the main chunk
595:
596: dsp_draw_edges:
597: mov bh,al ;save flags in BH
598: mov dx,EGA_BASE + GRAF_ADDR
599: mov ax,MM_ALL * 256 + GRAF_ENAB_SR
600: out dx,ax ;enable writing to all planes at once
601: mov ah,bl
602: mov al,GRAF_SET_RESET
603: out dx,ax ;program to color value to write
604: mov al,GRAF_BIT_MASK ;Leave graphics controller pointing
605: out dx,al ; to the bitmask register, which
606: inc dx ; is where cursor leaves it too
607:
608: test bh,08h ;need to draw the left edge?
609: jz dsp_draw_right_edge
610:
611: push edi ;save destination offset
612: mov al,bptr fr.start_mask[1]
613: out dx,al ;get it to the board
614: movzx ecx,fr.yExt
615:
616: dsp_left_edge_draw_loop:
617: mov al,bl ;copy color index into AL
618: xchg al,[edi] ;load latches, copy color index
619: add edi,esi
620: loop dsp_left_edge_draw_loop
621: pop edi ;restore dest offset
622: inc edi ;update to new draw position
623:
624:
625: dsp_draw_right_edge:
626: test bh,02h ;is there a right edge to draw?
627: jz dsp_reset_registers ;no. Restore default settings
628: push edi ;save updated dest offset
629: add edi,fr.inner_loop_count ;go to the right hand edge
630: mov al,bptr fr.last_mask[1]
631: out dx,al ;get it to the board
632: movzx ecx,fr.yExt
633:
634: dsp_right_edge_draw_loop:
635: mov al,bl ;copy color index into AL
636: xchg al,[edi] ;load latches, copy color index
637: add edi,esi
638: loop dsp_right_edge_draw_loop
639: pop edi ;restore dest offset
640:
641:
642: dsp_reset_registers:
643: mov al,0ffh ;allow writing to all bits in the byte
644: out dx,al ;this is the default value
645:
646: dsp_draw_core_piece:
647: sub esi,fr.inner_loop_count ;account for EDI being incr. by stosb
648: mov dx,EGA_BASE+SEQ_DATA ;time to copy pattern to board DX=3C5h
649: mov al,01h
650: mov ecx,4
651:
652: dsp_load_latches_loop:
653: out dx,al ;select the next plane to write to
654: shr bl,1 ;move plane bit into carry
655: sbb ah,ah ;expand into AH
656: mov [edi],ah ;copy it to the bit plane
657: shl al,1 ;update plane selector
658: loop dsp_load_latches_loop ;do all 4 planes
659:
660: mov al,MM_ALL ;to enable all four planes
661: out dx,al ;enable all planes
662: mov dx,EGA_BASE+GRAF_ADDR ;DX=3CEh
663: mov ax,GRAF_BIT_MASK ;AH=0 ie., copy data from latches, AL=8
664: out dx,ax ;ignore CPU data on write to board
665:
666: mov al,[edi] ;load the latches
667: movzx eax,fr.yExt ;initialize loop counter
668: mov ebx,fr.inner_loop_count ;initialize rep counter value
669:
670: align 4
671: dsp_pat_blt_loop:
672: mov ecx,ebx ;ECX: repeat count
673: test edi,1
674: jz short dsp_pat_blt_aligned2
675: stosb
676: dec ecx
677: dsp_pat_blt_aligned2:
678: shr ecx,1
679: rep stosw
680: adc ecx,ecx
681: rep stosb
682: add edi,esi ;point to next scanline
683: dec eax
684: jnz dsp_pat_blt_loop
685:
686: PLAIN_RET
687:
688:
689: ;----------------------------Private-Routine----------------------------;
690: ; do_wes_patblt
691: ;
692: ; Entry:
693: ; EBP --> BitBLT local variable frame
694: ; Returns:
695: ; Nothing
696: ; Registers Destroyed:
697: ; All but EBP
698: ; Registers Preserved:
699: ; EBP
700: ; Calls:
701: ; calc_parms
702: ; edge_pat_blt
703: ; pat_blt
704: ;-----------------------------------------------------------------------;
705:
706: align 4
707: do_wes_patblt:
708:
709: call calc_parms
710: mov ah,byte ptr fr.start_mask[0]
711: or ah,ah
712: jz no_left_pat_edge
713: push esi
714: push ebx
715: call edge_pat_blt ; preserves DI
716: pop ebx
717: pop esi
718: inc edi
719:
720: no_left_pat_edge:
721: mov edx,fr.inner_loop_count
722: or edx,edx
723: jz no_inner_pat_loop
724: movzx ecx,fr.yExt
725: push edi
726: push esi
727: push ebx
728: call pat_blt
729: pop ebx
730: pop esi
731: pop edi
732: add edi,fr.inner_loop_count
733:
734: no_inner_pat_loop:
735: mov ah,byte ptr fr.last_mask[0]
736: or ah,ah
737: jz no_last_pat_edge
738: movzx ecx,fr.yExt
739: call edge_pat_blt
740:
741: no_last_pat_edge:
742: PLAIN_RET
743:
744:
745: ;----------------------------Private-Routine----------------------------;
746: ; do_wes_mono_trick
747: ;
748: ; Entry:
749: ; EBP --> BitBLT local variable frame
750: ; Returns:
751: ; Nothing
752: ; Registers Preserved:
753: ; EBP
754: ; Registers Destroyed:
755: ; All but EBP
756: ; Calls:
757: ; calc_parms
758: ; left_edge_mono_to_color_blt
759: ; right_edge_mono_to_color_blt
760: ; mono_to_color_blt
761: ;-----------------------------------------------------------------------;
762:
763: align 4
764: do_wes_mono_trick:
765:
766: call calc_parms
767: push edx
768: mov ah,byte ptr fr.start_mask[0]
769: or ah,ah
770: jz no_left_edge
771: push edi
772: push esi
773: push edx
774: mov al,fr.phase_h
775: mov bx,fr.both_colors
776: ;- mov ecx,fr.yExt
777: call left_edge_mono_to_color_blt
778: pop edx
779: pop esi
780: pop edi
781: inc esi
782: inc edi
783: no_left_edge:
784: mov ebx,edx
785: mov edx,fr.inner_loop_count
786: mov ecx,edi ; compute/save the right-hand edge
787: add ecx,edx
788: push ecx
789: or edx,edx
790: jz no_inner_loop
791: sub ebx,edx
792: movzx ecx,fr.yExt
793: mov al,fr.phase_h
794: cbw
795: push ebp
796: mov bp,fr.both_colors
797: xchg bp,ax
798: call mono_to_color_blt
799: pop ebp
800:
801: no_inner_loop:
802: pop edi
803: pop edx
804: mov ah,byte ptr fr.last_mask[0]
805: or ah,ah
806: jz no_last_edge
807:
808: mov ecx,fr.inner_loop_count
809: mov esi,fr.end_fl ; src_right_edge (reuse stk variable)
810: movzx ecx,fr.yExt
811: mov bx,fr.both_colors
812: mov al,fr.phase_h
813: call right_edge_mono_to_color_blt
814:
815: no_last_edge:
816: PLAIN_RET
817:
818:
819: ;----------------------------Private-Routine----------------------------;
820: ; mono_to_color_blt
821: ;
822: ; This does phase-0, byte-aligned, mem-mono to ega-color blt.
823: ;
824: ; The Problem: copy to the ega a bitmap where "0"s in the bitmap mean
825: ; color1 and "1"s in the bitmap mean color2, where color1 and color2
826: ; are arbitrary colors.
827: ;
828: ; The solution:
829: ;
830: ; plane0 plane1 plane2 plane3
831: ;
832: ; color1 1 1 0 0
833: ; color2 1 0 1 0
834: ; SetResetEnable 1 0 0 1
835: ; SetReset 0 x x 0
836: ; latches 1 1 0 0 (=color1)
837: ;
838: ; Now with datarot = XOR we get
839: ;
840: ; when databit=0 1 1 0 0 (=color1)
841: ; when databit=1 1 0 1 0 (=color2)
842: ;
843: ;
844: ; Entry:
845: ; BP = phase ( -7 to 7) (high byte ignored)
846: ; AL = background color ( "1" bits in mono-bitmap )
847: ; AH = foreground color
848: ; EBX = SI wrap
849: ; ESI = Mono Bitmap first byte
850: ; EDI = First EGA Byte
851: ; ECX = Number of scan lines
852: ; EDX = bytes per scan line
853: ; GRAF_DATA_ROT = DR_SET
854: ; All Planes Enabled
855: ; Returns:
856: ; Nothing
857: ; Registers Destroyed:
858: ; ALL
859: ; Registers Preserved:
860: ; None
861: ; Alters:
862: ; GRAF_SET_RESET
863: ; GRAF_ENAB_SR
864: ; GRAF_BIT_MASK
865: ; Calls:
866: ; None
867: ;-----------------------------------------------------------------------;
868:
869: align 4
870: mono_to_color_blt:
871:
872: push ebp ; phase
873: push edx ; bytes per scan line
874: push ebx ; wrap for SI
875: mov ebx,eax ; colors
876:
877: ; First we put the foreground color into the latches. We do this
878: ; by putting this color into SET_RESET, writing it, then reading it.
879: ; The memory location we will use is the first byte where we will blt.
880:
881: mov dx,EGA_BASE + GRAF_ADDR
882: mov al,GRAF_SET_RESET
883: out dx,ax
884: mov ax,0F00h + GRAF_ENAB_SR
885: out dx,ax
886:
887: ; Set bit mask = FF.
888: mov ax,0FF00h + GRAF_BIT_MASK
889: out dx,ax
890:
891: ; Fill the latches.
892: mov [edi],al ; color in SetReset is written, not AL
893: mov al,[edi] ; read to fill latches
894:
895: ; Go to XOR mode.
896: mov ax,GRAF_DATA_ROT + 256 * DR_XOR
897: out dx,ax
898:
899: ; Now setup SET_RESET.
900:
901: mov eax,ebx ; restore colors
902: xor ah,al ; gives 0 where colors match
903: mov al,GRAF_SET_RESET
904: out dx,ax
905: not ah
906: mov al,GRAF_ENAB_SR
907: out dx,ax ; enable Set/Reset where colors match
908:
909: pop ebp ; wrap for ESI
910: pop edx ; bytes per scan
911: mov ebx,ulNextScan_global
912: sub ebx,edx ; BX = wrap
913:
914: mov eax,ecx ; loop count
915: pop ecx ; phase
916: or cl,cl
917: js phase_neg
918: jz phase_zero
919: dec esi
920: ;* dec ebp
921: pmono_to_color_loop:
922: push eax
923: push edx
924: pnext_byte:
925: lodsw
926: dec esi
927: xchg al,ah
928: shr ax,cl
929: ;+ shl ax,cl
930: stosb
931: dec edx
932: jnz pnext_byte
933: pop edx
934: pop eax
935: add edi,ebx
936: add esi,ebp
937: dec eax
938: jnz pmono_to_color_loop
939: jmp leave_in_set_mode
940:
941: phase_zero:
942: zmono_to_color_loop:
943: mov ecx,edx
944: shr ecx,1
945: rep movsw
946: rcl ecx,1
947: rep movsb
948: add edi,ebx
949: add esi,ebp
950: dec eax
951: jnz zmono_to_color_loop
952: jmp leave_in_set_mode
953:
954: phase_neg:
955: neg cl ; make CX = abs phase
956: nmono_to_color_loop:
957: push eax
958: push edx
959: nnext_byte:
960: lodsw
961: dec esi
962: rol ax,cl
963: ;+ shr ax,cl
964: stosb
965: dec edx
966: jnz nnext_byte
967: pop edx
968: pop eax
969: add edi,ebx
970: add esi,ebp
971: dec eax
972: jnz nmono_to_color_loop
973:
974: leave_in_set_mode:
975: mov dx,EGA_BASE + GRAF_ADDR
976: mov ax,GRAF_DATA_ROT + 256 * DR_SET
977: out dx,ax
978: PLAIN_RET
979:
980:
981: ;----------------------------Private-Routine----------------------------;
982: ; left_edge_mono_to_color_blt
983: ; right_edge_mono_to_color_blt
984: ;
985: ; This problem here is the same as in mono_to_color_blt, except it
986: ; is complicated by the need to preserve what is already in EGA memory
987: ; for part of the byte which we are writing.
988: ;
989: ; We will set the BIT MASK to preserve these bytes. We will then read
990: ; the data from memory, and write it to the EGA using an XCHG so the
991: ; latches are filled before the write -- so the appropriate EGA bits
992: ; are preserved.
993: ;
994: ; The method for writing the data involves two passes. The first pass
995: ; writes the data to some of the planes, the second pass writes NOT the
996: ; data to the other planes. Depending on the two colors involved we
997: ; may be able to skip one of the two passes.
998: ;
999: ; Define BkColor = the color corresponding to "1" bits in the data.
1000: ; Define TextColor = the color corresponding to "0" bits in the data.
1001: ;
1002: ; We will use the Set/Reset register to take care of the planes where
1003: ; the colors match. These planes will be ignored in the rest of this
1004: ; comment block.
1005: ;
1006: ; The first pass writes "1"s where the data is "1". Therefore, the
1007: ; condition for doing the first pass is that the BkColor has a "1"
1008: ; somewhere (ignoring those planes taken care of by Set/Reset).
1009: ; The second pass does whatever planes remain. We can skip this pass
1010: ; if no planes remain. To maximize to likelihood of this we make sure
1011: ; that all "Set/Reset" planes are enabled on the first pass (if the
1012: ; first pass occurs).
1013: ;
1014: ; Entry:
1015: ; AH = bitmask
1016: ; AL = phase (-7 to +7)
1017: ; BH = foreground color
1018: ; BL = background color
1019: ; EDX = src bitmap width in bytes
1020: ; ESI = Mono Bitmap first byte
1021: ; EDI = First EGA Byte
1022: ; ECX = Number of scan lines
1023: ; DATA_ROT = DR_SET
1024: ; Returns:
1025: ; Nothing
1026: ; Registers Destroyed:
1027: ; ALL but EBP
1028: ; Registers Preserved:
1029: ; EBP
1030: ; Alters:
1031: ; GRAF_SET_RESET
1032: ; GRAF_BIT_MASK
1033: ; GRAF_ENAB_SR
1034: ; Calls:
1035: ; None
1036: ;-----------------------------------------------------------------------;
1037:
1038: ; Does left edge, which never requires more than 1 byte, and can fault with
1039: ; the 2-byte approach used by the right edge.
1040:
1041: align 4
1042: left_edge_mono_to_color_blt:
1043:
1044: push ebp
1045: push eax ; AL = phase
1046: mov ebp,edx
1047:
1048: ; Set bit mask.
1049:
1050: mov dx,EGA_BASE + GRAF_ADDR
1051: mov al,GRAF_BIT_MASK
1052: out dx,ax
1053:
1054: ; Put foreground color in Set/Reset and enable planes where colors
1055: ; match.
1056:
1057: mov ah,bh
1058: mov al,GRAF_SET_RESET
1059: out dx,ax
1060: xor ah,bl
1061: not ah ; gives 1 where colors match
1062: mov al,GRAF_ENAB_SR
1063: out dx,ax
1064: mov dx,EGA_BASE + SEQ_DATA ; The rest of the OUTs are here.
1065: mov al,ah
1066: not ah ; Gives 1 where colors mismatch.
1067:
1068: ; The following AND leaves 1 bits in AH for the planes which
1069: ; CANNOT be done on the second pass. So if this is zero we can
1070: ; skip the first pass.
1071:
1072: and ah,bl ; BL = BkColor = color where data is 1
1073: or ah,bl ; planes to enable
1074: mov ebx,ecx ; we're done with the colors in BX
1075: pop ecx ; phase
1076: jz short left_skip_first_pass
1077: or al,ah ; Include "Set/Reset" planes.
1078: out dx,al ; Enable planes for first pass.
1079:
1080: push ecx
1081: push esi
1082: push edi
1083: push eax
1084: push ebx
1085: or cl,cl
1086: js short left_phase_is_negative1
1087: left_pfirst_pass:
1088: mov ah,[esi]
1089: shr ah,cl
1090: xchg ah,[edi]
1091: add esi,ebp
1092: add edi,ulNextScan_global
1093: dec ebx
1094: jnz left_pfirst_pass
1095: jmp short left_end_pass_one
1096:
1097: left_phase_is_negative1:
1098: neg cl ; make CL = abs phase
1099: left_nfirst_pass:
1100: mov ax,[esi]
1101: rol ax,cl
1102: xchg al,[edi]
1103: add esi,ebp
1104: add edi,ulNextScan_global
1105: dec ebx
1106: jnz left_nfirst_pass
1107: left_end_pass_one:
1108: pop ebx
1109: pop eax
1110: pop edi
1111: pop esi
1112: pop ecx
1113:
1114: left_skip_first_pass:
1115:
1116: ; Enable the other planes.
1117:
1118: not ah
1119: and ah,MM_ALL
1120: jz short left_no_planes_left
1121: mov al,ah
1122: out dx,al
1123: or cl,cl
1124: js short left_phase_is_negative2
1125: left_psecond_pass:
1126: mov ah,[esi]
1127: not ah
1128: shr ah,cl
1129: xchg ah,[edi]
1130: add esi,ebp
1131: add edi,ulNextScan_global
1132: dec ebx
1133: jnz left_psecond_pass
1134: jmp short left_no_planes_left
1135:
1136: left_phase_is_negative2:
1137: neg cl ; make CL = abs phase
1138: left_nsecond_pass:
1139: mov ax,[esi]
1140: not ax
1141: rol ax,cl
1142: xchg al,[edi]
1143: add esi,ebp
1144: add edi,ulNextScan_global
1145: dec ebx
1146: jnz left_nsecond_pass
1147:
1148: left_no_planes_left:
1149: mov al,MM_ALL
1150: out dx,al
1151: pop ebp
1152: PLAIN_RET
1153:
1154: ; Does right edge, which may require 2 bytes. 2 bytes are always available,
1155: ; because if there was only 1 byte across, the left edge would handle it,
1156: ; so we don't have to worry about faulting.
1157:
1158: align 4
1159: right_edge_mono_to_color_blt:
1160:
1161: push ebp
1162: push eax ; AL = phase
1163: mov ebp,edx
1164:
1165: ; Set bit mask.
1166:
1167: mov dx,EGA_BASE + GRAF_ADDR
1168: mov al,GRAF_BIT_MASK
1169: out dx,ax
1170:
1171: ; Put foreground color in Set/Reset and enable planes where colors
1172: ; match.
1173:
1174: mov ah,bh
1175: mov al,GRAF_SET_RESET
1176: out dx,ax
1177: xor ah,bl
1178: not ah ; gives 1 where colors match
1179: mov al,GRAF_ENAB_SR
1180: out dx,ax
1181: mov dx,EGA_BASE + SEQ_DATA ; The rest of the OUTs are here.
1182: mov al,ah
1183: not ah ; Gives 1 where colors mismatch.
1184:
1185: ; The following AND leaves 1 bits in AH for the planes which
1186: ; CANNOT be done on the second pass. So if this is zero we can
1187: ; skip the first pass.
1188:
1189: and ah,bl ; BL = BkColor = color where data is 1
1190: or ah,bl ; planes to enable
1191: mov ebx,ecx ; we're done with the colors in BX
1192: pop ecx ; phase
1193: jz short right_skip_first_pass
1194: or al,ah ; Include "Set/Reset" planes.
1195: out dx,al ; Enable planes for first pass.
1196:
1197: push ecx
1198: push esi
1199: push edi
1200: push eax
1201: push ebx
1202: or cl,cl
1203: js short right_phase_is_negative1
1204: dec esi
1205: right_pfirst_pass:
1206: mov ax,[esi]
1207: ror ax,cl
1208: xchg ah,[edi]
1209: add esi,ebp
1210: add edi,ulNextScan_global
1211: dec ebx
1212: jnz right_pfirst_pass
1213: jmp short right_end_pass_one
1214:
1215: right_phase_is_negative1:
1216: neg cl ; make CL = abs phase
1217: right_nfirst_pass:
1218: mov ax,[esi]
1219: rol ax,cl
1220: xchg al,[edi]
1221: add esi,ebp
1222: add edi,ulNextScan_global
1223: dec ebx
1224: jnz right_nfirst_pass
1225: right_end_pass_one:
1226: pop ebx
1227: pop eax
1228: pop edi
1229: pop esi
1230: pop ecx
1231:
1232: right_skip_first_pass:
1233:
1234: ; Enable the other planes.
1235:
1236: not ah
1237: and ah,MM_ALL
1238: jz short right_no_planes_left
1239: mov al,ah
1240: out dx,al
1241: or cl,cl
1242: js short right_phase_is_negative2
1243: dec esi
1244: right_psecond_pass:
1245: mov ax,[esi]
1246: not ax
1247: ror ax,cl
1248: xchg ah,[edi]
1249: add esi,ebp
1250: add edi,ulNextScan_global
1251: dec ebx
1252: jnz right_psecond_pass
1253: jmp short right_no_planes_left
1254:
1255: right_phase_is_negative2:
1256: neg cl ; make CL = abs phase
1257: right_nsecond_pass:
1258: mov ax,[esi]
1259: not ax
1260: rol ax,cl
1261: xchg al,[edi]
1262: add esi,ebp
1263: add edi,ulNextScan_global
1264: dec ebx
1265: jnz right_nsecond_pass
1266:
1267: right_no_planes_left:
1268: mov al,MM_ALL
1269: out dx,al
1270: pop ebp
1271: PLAIN_RET
1272:
1273:
1274: ;----------------------------Private-Routine----------------------------;
1275: ; pat_blt
1276: ; XOR mode with data = FF for Pn?
1277: ;
1278: ; This BLTs an arbitrary 8x8 bit pattern (3 or 4 planes deep) to EGA.
1279: ;
1280: ; The method is simple. Load the latches with the pattern for a
1281: ; particular scan line, then REP STOS this with the BIT MASK = 0
1282: ; so that only the latches get written. Before putting the pattern
1283: ; for the next scan line into the latches we will do all other scan
1284: ; lines with the same pattern.
1285: ;
1286: ; Entry:
1287: ; ESI = pattern bytes
1288: ; EDI = First EGA Byte
1289: ; ECX = Number of scan lines (yExt)
1290: ; EBX = offset into pattern
1291: ; EDX = bytes per scan line (scan_len)
1292: ; GRAF_DATA_ROT = DR_SET
1293: ; BIT_MASK = FF
1294: ; Returns:
1295: ; Nothing
1296: ; Registers Destroyed:
1297: ; ALL but EBP
1298: ; Registers Preserved:
1299: ; EBP
1300: ; Alters:
1301: ; GRAF_BIT_MASK (leaves it 00)
1302: ; Calls:
1303: ; None
1304: ;-----------------------------------------------------------------------;
1305:
1306: .errnz SIZE_PATTERN - 8 ; actually any power of 2 is okay.
1307:
1308: align 4
1309: pat_blt:
1310:
1311: push ebp
1312: push edx ; scan_len
1313: push ecx ; yExt
1314: mov ah,11h ; left nibble gives carry to end loop
1315:
1316: ; Set EBP = min(yExt, scans/pattern).
1317:
1318: sub ecx,SIZE_PATTERN ; SIZE_PATTERN = 8 = yExt of pattern
1319: sbb ebp,ebp
1320: and ebp,ecx
1321: add ebp,SIZE_PATTERN
1322:
1323: mov dx,EGA_BASE + SEQ_DATA
1324: set_next_plane:
1325: push ebx
1326: push edi
1327:
1328: ; Enable next plane.
1329:
1330: mov al,MM_ALL
1331: and al,ah
1332: out dx,al
1333: mov ecx,ebp
1334:
1335: hit_next_byte:
1336: mov al,[esi][ebx] ; Next pattern byte
1337: inc ebx
1338: and ebx,SIZE_PATTERN - 1
1339: mov [edi],al
1340: add edi,ulNextScan_global
1341: loop hit_next_byte
1342: add esi,SIZE_PATTERN
1343: pop edi
1344: pop ebx
1345: shl ah,1
1346: jnc set_next_plane
1347:
1348: ; Set bit mask = 00.
1349:
1350: mov dx,EGA_BASE + GRAF_ADDR
1351: mov ax,0000h + GRAF_BIT_MASK
1352: out dx,ax
1353:
1354: ; Enable all planes.
1355:
1356: mov al,MM_ALL
1357: mov dx,EGA_BASE + SEQ_DATA
1358: out dx,al
1359:
1360: mov ecx,ebp ; MIN(yExt,SIZE_PATTERN)
1361: pop ebp ; yExt
1362: pop eax ; scan_len
1363: mov esi,ulNextScan_global ; ESI = scan_width
1364:
1365: .errnz (SIZE_PATTERN - 8)
1366: ;------------------------------------------------;
1367: ; mov ebx,(SIZE_PATTERN - 1) * scan_width
1368: ;------------------------------------------------;
1369: lea ebx,[esi*2+esi] ; scan_width * 3
1370: lea ebx,[ebx+esi*4] ; scan_width * 7
1371:
1372: sub esi,eax ; ESI = scan_width
1373: add ebx,esi ; EBX = (scan_width * 7) + next_scan
1374:
1375: pat_blt_next_scan:
1376: push ecx
1377: mov esi,edi ; save ESI
1378: mov edx,ebp ; save yExt
1379: mov cl,[edi] ; load latches
1380:
1381: pat_blt_loop:
1382: mov ecx,eax ; EAX = scan_len
1383: rep stosb
1384: add edi,ebx ; EBX = (scan_width * 7) + next_scan
1385: sub ebp,SIZE_PATTERN
1386: jg pat_blt_loop
1387:
1388: mov ebp,edx
1389: dec ebp
1390: mov edi,esi
1391: add edi,ulNextScan_global
1392: pop ecx
1393: loop pat_blt_next_scan
1394:
1395: pop ebp
1396: PLAIN_RET
1397:
1398:
1399: ;----------------------------Private-Routine----------------------------;
1400: ; edge_pat_blt
1401: ;
1402: ; Entry:
1403: ; AH = bitmask
1404: ; ESI = pattern bytes
1405: ; EDI = First EGA Byte
1406: ; ECX = Number of scan lines (yExt)
1407: ; EBX = offset into pattern
1408: ; DATA_ROT = DR_SET
1409: ; Returns:
1410: ; Nothing
1411: ; Registers Destroyed:
1412: ; EAX,ECX,EDX,ESI,flags
1413: ; Registers Preserved:
1414: ; EBX,EDI,EBP
1415: ; Alters:
1416: ; GRAF_BIT_MASK (leaves it FF)
1417: ; Calls:
1418: ; None
1419: ;-----------------------------------------------------------------------;
1420:
1421: align 4
1422: edge_pat_blt:
1423:
1424: push ebp
1425:
1426: ; Set bit mask.
1427:
1428: mov dx,EGA_BASE + GRAF_ADDR
1429: mov al,GRAF_BIT_MASK
1430: out dx,ax
1431: mov ah,11h ; left nibble gives carry to end loop
1432: mov dx,EGA_BASE + SEQ_DATA
1433: sub si,SIZE_PATTERN
1434: mov ebp,ecx
1435:
1436: enable_next_plane:
1437: push ebx
1438: push edi
1439: mov ecx,ebp ; yExt
1440: mov al,MM_ALL
1441: and al,ah
1442: out dx,al
1443: add esi,SIZE_PATTERN
1444:
1445: over_scans:
1446: mov al,[ebx][esi] ; pattern fetch
1447: inc ebx
1448: and ebx,SIZE_PATTERN - 1 ; 7
1449: .errnz SIZE_PATTERN - 8 ; any power of 2 works
1450: xchg [edi],al
1451: add edi,ulNextScan_global
1452: loop over_scans
1453:
1454: pop edi
1455: pop ebx
1456: shl ah,1
1457: jnc enable_next_plane
1458:
1459: ; Restore bitmask to default.
1460:
1461: mov dx,EGA_BASE + GRAF_ADDR
1462: mov ax,0FF00h + GRAF_BIT_MASK
1463: out dx,ax
1464:
1465: pop ebp
1466: PLAIN_RET
1467:
1468:
1469: ;----------------------------Private-Routine----------------------------;
1470: ; invert
1471: ;
1472: ; Inverts pixels in a rectangle on the display, by simply writing the
1473: ; memory to itself, letting the EGA hardware perform the XORing.
1474: ;
1475: ; Entry:
1476: ; EDI = First EGA Byte
1477: ; ECX = Number of scan lines (yExt)
1478: ; EBX = scan line length in bytes
1479: ; DATA_ROT = DR_XOR
1480: ; GRAF_SET_RESET = color to xor DEST with
1481: ; GRAF_SR_ENAB = MM_ALL
1482: ; Returns:
1483: ; Nothing
1484: ; Registers Destroyed:
1485: ; EAX,ECX,EDX,ESI,EDI,flags
1486: ; Registers Preserved:
1487: ; EBX,EBP
1488: ; Alters:
1489: ; GRAF_BIT_MASK (leaves it FF)
1490: ; Calls:
1491: ; None
1492: ;-----------------------------------------------------------------------;
1493:
1494: align 4
1495: invert:
1496:
1497: ; Set bit mask.
1498:
1499: mov dx,EGA_BASE + GRAF_ADDR
1500: mov ax,0FF00h + GRAF_BIT_MASK
1501: out dx,ax
1502: mov edx,ulNextScan_global
1503: sub edx,ebx
1504: mov eax,ecx ; save height
1505:
1506: invert_next_scan:
1507: mov esi,edi
1508: mov ecx,ebx ; scan len in bytes
1509: rep movsb
1510: add edi,edx
1511: dec eax
1512: jnz invert_next_scan
1513: PLAIN_RET
1514:
1515:
1516: ;----------------------------Private-Routine----------------------------;
1517: ; edge_invert
1518: ;
1519: ; Inverts one byte on each scan line vertically according to the mask
1520: ; in AH.
1521: ;
1522: ; Entry:
1523: ; AH = bitmask
1524: ; EDI = First EGA Byte
1525: ; ECX = Number of scan lines (yExt)
1526: ; DATA_ROT = DR_XOR
1527: ; GRAF_SET_RESET = color to xor DEST with
1528: ; GRAF_ENAB_SR = MM_ALL
1529: ; Returns:
1530: ; Nothing
1531: ; Registers Destroyed:
1532: ; AL,ECX,EDX,EDI,flags
1533: ; Registers Preserved:
1534: ; AH,EBX,ESI,EBP
1535: ; Alters:
1536: ; GRAF_BIT_MASK
1537: ; Calls:
1538: ; None
1539: ;-----------------------------------------------------------------------;
1540:
1541: align 4
1542: edge_invert:
1543:
1544: ; Set bit mask.
1545:
1546: mov dx,EGA_BASE + GRAF_ADDR
1547: mov al,GRAF_BIT_MASK
1548: out dx,ax
1549:
1550: edge_invert_next_scan:
1551: xchg [edi],al
1552: add edi,ulNextScan_global
1553: loop edge_invert_next_scan
1554: PLAIN_RET
1555:
1556:
1557: ;----------------------------Private-Routine----------------------------;
1558: ; edge_grey_dpx
1559: ;
1560: ; Inverts one or two bytes on each scan line vertically according
1561: ; to the grey pattern given, under the passed clipping mask.
1562: ;
1563: ; Entry:
1564: ; EBX = brush index (0-7)
1565: ; ECX = number of scan lines (cyExt)
1566: ; DL = lhs clipping mask
1567: ; DH = rhs clipping mask
1568: ; ESI --> base address of brush
1569: ; EDI --> rhs EGA
1570: ; EBP --> lhs EGA
1571: ; Returns:
1572: ; Nothing
1573: ; Registers Destroyed:
1574: ; All
1575: ; Registers Preserved:
1576: ; None
1577: ; Alters:
1578: ; None
1579: ; Calls:
1580: ; None
1581: ;-----------------------------------------------------------------------;
1582:
1583: align 4
1584: edge_grey_dpx:
1585:
1586: sub ebp,edi ;Compute delta to lhs
1587: and ebx,00000111b ;Make sure brush is valid
1588: .errnz SIZE_PATTERN - 8
1589: or dh,dh ;Dispatch based on one or two edges
1590: jz edge_grey_dpx_one_loop
1591:
1592: edge_grey_dpx_both_loop:
1593: mov al,[esi][ebx] ;Get next byte of brush
1594: mov ah,al
1595: and al,dl ;Mask with lhs clipping mask
1596: xchg al,[edi] ;Invert necessary bits
1597: inc ebx ;--> next brush byte
1598: and bl,00000111b ;Handle any wrap
1599: .errnz SIZE_PATTERN - 8
1600: and ah,dh ;Mask with rhs clipping mask
1601: xchg ah,[edi][ebp] ;Invert necessary bits
1602: add edi,ulNextScan_global ;--> next destination byte
1603: loop edge_grey_dpx_both_loop
1604: PLAIN_RET
1605:
1606: edge_grey_dpx_one_loop:
1607: mov al,[esi][ebx] ;Get next byte of brush
1608: and al,dl ;Mask with lhs clipping mask
1609: xchg al,[edi] ;Invert necessary bits
1610: inc ebx ;--> next brush byte
1611: and bl,00000111b ;Handle any wrap
1612: .errnz SIZE_PATTERN - 8
1613: add edi,ulNextScan_global ;--> next destination byte
1614: loop edge_grey_dpx_one_loop
1615: PLAIN_RET
1616:
1617:
1618: ;----------------------------Private-Routine----------------------------;
1619: ; middle_grey_dpx
1620: ;
1621: ; Inverts a rectangle on the display using the passed grey pattern.
1622: ;
1623: ; Entry:
1624: ; EBX = brush index (0-7)
1625: ; ECX = # byte to invert on the scan
1626: ; EDX = EGA_BASE + GRAF_ADDR
1627: ; ESI --> base address of brush
1628: ; EDI --> starting byte
1629: ; EBP = number of scan lines (cyExt)
1630: ; DATA_ROT = DR_XOR
1631: ; GRAF_SET_RESET = All 1
1632: ; GRAF_ENAB_SR = MM_ALL
1633: ; Returns:
1634: ; Nothing
1635: ; Registers Destroyed:
1636: ; EAX,ECX,EDX,ESI,EDI,flags
1637: ; Registers Preserved:
1638: ; EBX,EBP
1639: ; Alters:
1640: ; GRAF_BIT_MASK (leaves it FF)
1641: ; Calls:
1642: ; None
1643: ;-----------------------------------------------------------------------;
1644:
1645: align 4
1646: middle_grey_dpx:
1647:
1648: ; mov dx,EGA_BASE + GRAF_ADDR ; Leave the Graphics controller
1649: mov al,GRAF_BIT_MASK ; address register pointing to
1650: out dx,al ; the bitmask register
1651: inc edx ; --> Graphics controller data register
1652: .errnz GRAF_DATA - GRAF_ADDR - 1
1653:
1654: mov ah,bl ; Keep brush index here
1655: mov ebx,ecx ; Save a copy of inner loop count here
1656:
1657: middle_grey_dpx_loop:
1658: xchg eax,ebx
1659: xchg bl,bh
1660: and ebx,00000111b
1661: errnz SIZE_PATTERN-8
1662: mov bh,[esi][ebx] ; Get next byte of brush
1663: inc bl ; --> byte of the brush
1664: xchg bh,bl
1665: xchg eax,ebx
1666: out dx,al
1667: mov ecx,ebx
1668: push esi
1669: mov esi,edi
1670: rep movsb
1671: pop esi
1672: sub edi,ebx
1673: add edi,ulNextScan_global ;next scan on screen
1674: dec ebp
1675: jnz middle_grey_dpx_loop
1676: PLAIN_RET
1677:
1678:
1679: ;----------------------------Private-Routine----------------------------;
1680: ; do_grey_dpx
1681: ;
1682: ; This is EGA special cased code for the dpx raster op in the case where
1683: ; the pattern (p) is grey (the same on all planes). We also come here
1684: ; for the special graying pattern rop. This is not a normal P,S, and D rop,
1685: ; but a hack for pmwin. It allows graying of things on the screen, meaning
1686: ; the background color is stuffed everywhere the pattern has a "1" bit.
1687: ;
1688: ; Entry:
1689: ; EBP --> BitBLT local variable frame
1690: ; Returns:
1691: ; Nothing
1692: ; Registers Destroyed:
1693: ; ALL but EBP
1694: ; Registers Preserved:
1695: ; EBP
1696: ; Calls:
1697: ; calc_parms
1698: ; edge_grey_dpx
1699: ; middle_grey_dpx
1700: ;-----------------------------------------------------------------------;
1701:
1702: align 4
1703: do_grey_dpx:
1704:
1705: call calc_parms
1706: mov dx,EGA_BASE + GRAF_ADDR
1707: mov ax,DR_XOR shl 8 + GRAF_DATA_ROT ; XOR mode for grey dpx
1708: out dx,ax
1709: mov dl,byte ptr fr.start_mask[0]
1710: mov dh,byte ptr fr.last_mask[0]
1711: or dx,dx
1712: jz do_grey_dpx_middle ;Only middle bytes exist
1713:
1714: mov eax,edi ;Assume we have a left edge
1715: inc eax ;+1 to get to start of middle bytes
1716: or dl,dl ;Is there really a left edge?
1717: jnz do_grey_dpx_have_lhs ; Yes, AX = correct middle byte start
1718: dec eax ; No, restore middle byte start
1719: xchg dl,dh ; Pretend only a lhs edge
1720: add edi,fr.inner_loop_count ; but make it be the rhs
1721:
1722: do_grey_dpx_have_lhs:
1723: push eax ;Save middle bytes start
1724: push ebx
1725: push ecx
1726: push esi
1727: push ebp
1728: add eax,fr.inner_loop_count ;--> possible rhs
1729: xchg eax,ebp
1730: call edge_grey_dpx
1731: did_gray_pat_edge:
1732: pop ebp
1733: pop esi
1734: pop ecx
1735: pop ebx
1736: pop edi ;Restore middle bytes start
1737:
1738: do_grey_dpx_middle:
1739: mov eax,fr.inner_loop_count
1740: or eax,eax
1741: jz do_grey_dpx_exit
1742: push ebp
1743: mov ebp,ecx
1744: xchg eax,ecx
1745: mov dx,EGA_BASE + GRAF_ADDR ;
1746: mov ax,MM_ALL shl 8 + GRAF_ENAB_SR ; Set Set/Reset to all "1" bits
1747: out dx,ax ; and Enable all planes (for
1748: .errnz MM_ALL - 0Fh ; grey_dpx)
1749: mov al,GRAF_SET_RESET ;
1750: out dx,ax ;
1751:
1752: gray_pat:
1753: call middle_grey_dpx
1754: pop ebp
1755:
1756: do_grey_dpx_exit:
1757: PLAIN_RET
1758:
1759:
1760: endProc check_device_special_cases
1761:
1762: _TEXT$01 ends
1763:
1764: end
1765:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.