|
|
1.1 root 1: page ,132
2: title BitBLT
3: ;---------------------------Module-Header------------------------------;
4: ; Module Name: cblt.asm
5: ;
6: ; Copyright (c) 1992 Microsoft Corporation
7: ;-----------------------------------------------------------------------;
8: .386
9:
10: ;!!! All the code to convert from color to mono in this file needs to
11: ;!!! be deleted. We don't need to do it anymore.
12:
13:
14:
15:
16: ifndef DOS_PLATFORM
17: .model small,c
18: else
19: ifdef STD_CALL
20: .model small,c
21: else
22: .model small,pascal
23: endif; STD_CALL
24: endif; DOS_PLATFORM
25:
26: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
27: assume fs:nothing,gs:nothing
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:
37: include i386\cmacFLAT.inc ; FLATland cmacros
38: include i386\display.inc ; Display specific structures
39: include i386\ppc.inc ; Pack pel conversion structure
40: include i386\bitblt.inc ; General definitions
41: include i386\ropdefs.inc ; Rop definitions
42: include i386\egavga.inc ; EGA register definitions
43: include i386\devdata.inc
44: .list
45:
46: extrn roptable:byte
47: ;-----------------------------Public-Routine----------------------------;
48: ; CBLT
49: ;
50: ; Compile a BLT onto the stack.
51: ;
52: ; Entry:
53: ; EDI --> memory on stack to receive BLT program
54: ; EBP --> fr structure
55: ; Returns:
56: ; Nothing
57: ;-----------------------------------------------------------------------;
58:
59: fr equ [ebp] ;For consistancy with other sources
60:
61: cProc cblt
62:
63: subttl Compile - Outer Loop
64: page
65:
66: ; If converting a packed pel format to planer format, add the code
67: ; to convert one source scan into planer format
68:
69: test fr.ppcBlt.fb,PPC_NEEDED
70: jz no_pack_pel_conversion
71: mov al,I_MOV_EBP_DWORD_I ;Give conversion routine access
72: stosb ; to conversion data
73: lea eax,fr.ppcBlt
74: stosd
75: mov al,I_CALL_DISP32 ;Call the static conversion code
76: stosb
77: mov eax,fr.ppcBlt.pfnConvert
78: sub eax,edi
79: sub eax,4 ;4 for length of displacement
80: stosd
81: no_pack_pel_conversion:
82:
83: ; Initialize plane indicator.
84:
85: mov ax,(PLANE_1*256)+I_MOV_BL_BYTE_I
86: stosw
87:
88: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
89: ; Create the outerloop code. The first part of this code will save
90: ; the scan line count register, destination pointer, and the source
91: ; pointer (if there is a source).
92: ;
93: ; The generated code should look like:
94: ;
95: ; push ecx ;Save scan line count
96: ; push edi ;Save destination pointer
97: ; < push esi > ;Save source pointer
98: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
99:
100: mov fr.pNextPlane,edi ;Save address of next plane code
101: mov bl,fr.the_flags
102: mov ax,I_PUSH_ECX_PUSH_EDI ;Save scan line count, destination ptr
103: stosw
104: test bl,F0_SRC_PRESENT ;Is a source needed?
105: jz cblt_2020 ; No
106: mov al,I_PUSH_ESI ; Yes, save source pointer
107: stosb
108: cblt_2020:
109:
110: subttl Compile - Plane Selection
111: page
112: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
113: ; If the destination device is color and the display is involved in
114: ; the blt, then the color plane selection logic must be added in.
115: ; If the destination is monochrome, then no plane logic is needed.
116: ; Two color memory bitmaps will not cause the plane selection logic
117: ; to be copied.
118: ;
119: ; The generated code should look like:
120: ;
121: ; < push ebx > ;Save plane index
122: ; < plane selection > ;Select plane
123: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
124:
125: test bl,F0_DEST_IS_COLOR ;Is the destination color?
126: jz cblt_pattern_fetch ; No
127: mov al,I_PUSH_EBX ;Save plane index
128: stosb
129: test bl,F0_DEST_IS_DEV+F0_SRC_IS_DEV ;Is the device involved?
130: jz cblt_pattern_fetch ; No
131:
132: ; The device is involved for a color blt. Copy the logic for selecting
133: ; the read/write plane
134:
135: mov esi,offset FLAT:cps ;--> plane select logic
136: mov ecx,LENGTH_CPS
137: rep movsb
138:
139: subttl Compile - Pattern Fetch
140: page
141:
142: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
143: ; Set up any pattern fetch code that might be needed.
144: ; The pattern code has many fixups, so it isn't taken from a
145: ; template. It is just stuffed as it is created.
146: ;
147: ; Entry: None
148: ;
149: ; Exit: DH = pattern
150: ;
151: ; Uses: AX,BX,CX,DH,flags
152: ;
153: ; For solid color brushes:
154: ;
155: ; mov dh,color
156: ;
157: ; For monochrome brushes:
158: ;
159: ; mov ebx,12345678h ;Load address of the brush
160: ; mov dh,7[ebx] ;Get next brush byte
161: ; mov al,[12345678h] ;Get brush index
162: ; add al,direction ;Add displacement to next byte (+1/-1)
163: ; and al,00000111b ;Keep it in range
164: ; mov [12345678h],al ;Store displacement to next plane's bits
165: ;
166: ; For color brushes:
167: ;
168: ; mov ebx,12345678h ;Load address of the brush
169: ; mov dh,7[bx] ;Get next brush byte
170: ; mov al,[12345678h] ;Get brush index
171: ; add al,SIZE Pattern ;Add displacement to next plane's bits
172: ; and al,00011111b ;Keep it within the brush
173: ; mov [12345678h],al ;Store displacement to next plane's bits
174: ;
175: ; The address of the increment for the brush is saved for
176: ; the plane looping logic if the destination is a three plane
177: ; color device. For a four plane color device, the AND
178: ; automatically handles the wrap and no fixup is needed at
179: ; the end of the plane loop.
180: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
181:
182: cblt_pattern_fetch:
183: test bl,F0_PAT_PRESENT ;Is a pattern needed?
184: jz cblt_initial_byte_fetch ; No, skip pattern code
185: mov al,fr.brush_accel ;Solid color needs no fetch logic
186: test al,SOLID_BRUSH
187: jz cblt_nonsolid_brush
188: and al,MM_ALL
189: shl eax,16
190: mov ax,I_TEST_BL_BYTE_I
191: stosd
192: dec edi ;Was only a three byte instruction
193: mov eax,I_SETNZ_DH
194: stosd
195: dec edi ;Was only a three byte instruction
196: mov ax,I_NEG_DH
197: stosw
198: jmp short cblt_initial_byte_fetch
199:
200: cblt_nonsolid_brush:
201: mov al,I_MOV_EBX_DWORD_I ;mov ebx,lpPBrush
202: stosb
203: mov eax,fr.lpPBrush
204: stosd
205: mov ax,I_MOV_DH_EBX_DISP8 ;mov dh,pat_row[ebx]
206: stosw
207: mov edx,edi ;Save address of the brush index
208: mov al,fr.pat_row ;Set initial pattern row
209: mov bh,00000111b ;Set brush index mask
210: and al,bh ;Make sure it's legal at start
211: stosb
212: mov al,I_MOV_AL_MEM
213: stosb ;mov al,[xxxxxxxx]
214: mov eax,edx
215: stosd
216: mov al,I_ADD_AL_BYTE_I
217: mov ah,direction ;Set brush index
218: errnz INCREASE-1 ;Must be a 1
219: errnz DECREASE+1 ;Must be a -1
220:
221: test bl,F0_COLOR_PAT ;Color pattern required?
222: jz cblt_2060 ; No
223: mov fr.addr_brush_index,edx ;Save address of brush index
224: mov ah,SIZE_PATTERN ;Set increment to next plane
225: mov bh,00011111b ;Set brush index mask
226:
227: cblt_2060:
228: stosw
229: mov ah,bh ;and al,BrushIndexMask
230: mov al,I_AND_AL_BYTE_I
231: stosw
232: mov al,I_MOV_MEM_AL
233: stosb ;mov [xxxxxxxx],al
234: mov eax,edx
235: stosd
236:
237:
238: subttl Compile - Initial Byte Fetch
239: page
240: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
241: ; Create the initial byte code. This may consist of one or two
242: ; initial fetches (if there is a source), followed by the required
243: ; logic action. The code should look something like:
244: ;
245: ; BLTouterloop:
246: ; < mov bp,mask_p > ;Load phase mask for entire loop
247: ; < xor bh,bh > ;Clear previous unused bits
248: ;
249: ; ; Perform first byte fetch
250: ;
251: ; < lodsb > ;Get source byte
252: ; < color<==>mono munge > ;Color <==> mono conversion
253: ; < phase alignment > ;Align bits as needed
254: ;
255: ; ; If an optional second fetch is needed, perform one
256: ;
257: ; < lodsb > ;Get source byte
258: ; < color to mono munge > ;Color to mono munging
259: ; < phase alignment > ;Align bits as needed
260: ;
261: ; logical action ;Perform logical action required
262: ;
263: ; mov ah,[edi] ;Get destination
264: ; and ax,cx ;Saved unaltered bits
265: ; or al,ah ; and mask in altered bits
266: ; stosb ;Save the result
267: ;
268: ; The starting address of the first fetch/logical combination will be
269: ; saved so that the code can be copied later instead of recreating it
270: ; (if there are two fecthes, the first fetch will not be copied)
271: ;
272: ; The length of the code up to the masking for altered/unaltered bits
273: ; will be saved so the code can be copied into the inner loop.
274: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
275:
276: cblt_initial_byte_fetch:
277: xor dx,dx
278: or dh,fr.phase_h ;Is the phase 0? (also get the phase)
279: jz cblt_3020 ; Yes, so no phase alignment needed
280: mov al,I_SIZE_OVERRIDE
281: stosb
282: mov al,I_MOV_BP_WORD_I ;Set up the phase mask
283: stosb
284: mov ax,fr.mask_p ;Place the mask into the instruction
285: stosw
286: mov ax,I_XOR_BH_BH ;Clear previous unused bits
287: stosw
288:
289: cblt_3020:
290: mov fr.start_fl,edi ;Save starting address of action
291: test fr.the_flags,F0_SRC_PRESENT ;Is there a source?
292: jz cblt_4000 ; No, don't generate fetch code
293:
294:
295: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
296: ; Generate the required sequence of instructions for a fetch
297: ; sequence. Only the minimum code required is generated.
298: ;
299: ; The code generated will look something like the following:
300: ;
301: ; BLTfetch:
302: ; < lodsb > ;Get the next byte
303: ; < color munging > ;Mono <==> color munging
304: ;
305: ; ; If the phase alignment isn't zero, then generate the minimum
306: ; ; phase alignment needed. RORs or ROLs will be generated,
307: ; ; depending on the fastest sequence. If the phase alignment
308: ; ; is zero, than no phase alignment code will be generated.
309: ;
310: ; < ror al,n > ;Rotate as needed
311: ; < mov ah,al > ;Mask used, unused bits
312: ; < and ax,bp > ;(BP) = phase mask
313: ; < or al,bh > ;Mask in old unused bits
314: ; < mov bh,ah > ;Save new unused bits
315: ;
316: ;
317: ; The nice thing about the above is it is possible for the fetch to
318: ; degenerate into a simple LODSB instruction.
319: ;
320: ; Currently: BL = the_flags
321: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
322:
323: cblt_3040:
324: mov fr.moore_flags,0 ;Assume REP cannot be used
325: shl bl,1 ;Color conversion?
326: jnc cblt_3180 ; No, we were lucky this time
327: errnz F0_GAG_CHOKE-10000000b
328: js cblt_3100 ;Mono ==> color
329: errnz F0_COLOR_PAT-01000000b
330:
331: subttl Compile - Initial Byte Fetch, Color ==> Mono
332: page
333:
334: ; !!! Color to mono should not be needed anymore since the Engine will
335: ; !!! not be calling me to do it! Let's remove this code!
336:
337:
338: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
339: ; Generate the code to go from color to mono. Color to mono
340: ; should map all colors that are background to 1's (white), and
341: ; all colors which aren't background to 0's (black). If the source
342: ; is the display, then the color compare register will be used.
343: ; If the source is a memory bitmap, each byte of the plane will be
344: ; XORed with the color from that plane, with the results all ORed
345: ; together. The final result will then be complemented, giving
346: ; the desired result.
347: ;
348: ; The generated code for bitmaps should look something like:
349: ;
350: ; mov al,next_plane[esi] ;Get C1 byte of source
351: ; mov ah,2*next_plane[esi] ;Get C2 byte of source
352: ; xor ax,C1BkColor+(C2BkColor*256) ;XOR with plane's color
353: ; or ah,al ;OR the result
354: ; mov al,3*next_plane[esi] ;Get C3 byte of source
355: ; xor al,C3BkColor
356: ; or ah,al
357: ; lodsb ;Get C0 source
358: ; xor al,C0BkColor ;XOR with C0BkColor
359: ; or al,ah ;OR with previous result
360: ; not al ;NOT to give 1's where background
361: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
362:
363: cblt_3070:
364: test bl,F0_SRC_IS_DEV SHL 1 ;If device, use color compare register
365: jz cblt_3080 ;It's a memory bitmap
366:
367: ; We're in luck, the color compare register can be used. Set up
368: ; for a color read, and use the normal mono fetch code. Show the
369: ; innerloop code that the REP instruction can be used if this is
370: ; a source copy.
371:
372: mov fr.moore_flags,F1_REP_OK
373: mov ecx,edx ;Save dx
374: mov ah,fr.bkColor.SPECIAL ;Get SPECIAL byte of color
375: and ah,MM_ALL
376: mov al,GRAF_COL_COMP ;Stuff color into compare register
377: mov dx,EGA_BASE+GRAF_ADDR
378: out dx,ax
379: mov ax,GRAF_CDC ;Set Color Don't Care register
380: out dx,ax
381: mov ax,M_COLOR_READ SHL 8 + GRAF_MODE
382: out dx,ax
383: mov edx,ecx
384: jmp cblt_3180 ;Go generate mono fetch code
385:
386: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
387: ; The source is a memory bitmap. Generate the code to compute
388: ; the result of the four planes:
389: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
390:
391: cblt_3080:
392: mov ax,I_MOV_AL_ESI_DISP32
393: stosw
394: mov eax,fr.src.next_plane
395: stosd
396: mov ebx,eax ;Save plane width
397: mov ax,I_MOV_AH_ESI_DISP32
398: stosw
399: lea eax,[ebx*2]
400: stosd
401: mov al,I_SIZE_OVERRIDE
402: stosb
403: mov al,I_XOR_AX_WORD_I
404: stosb
405: mov al,fr.bkColor.SPECIAL ;get the color index byte
406: mov ah,al ;have the same in AH
407: and ax,(C2_BIT shl 8) or C1_BIT
408: neg al
409: sbb al,al ;al will be 0ffh if plane bit is 1
410: neg ah
411: sbb ah,ah ;ah wil be 0ffh if plane bit is 1
412: stosw
413: mov ax,I_OR_AH_AL
414: stosw
415:
416: mov ax,I_MOV_AL_ESI_DISP32
417: stosw
418: lea eax,[ebx*2][ebx]
419: stosd
420: mov al,I_XOR_AL_BYTE_I
421: mov ah,fr.bkColor.SPECIAL
422: and ah,C3_BIT
423: neg ah
424: sbb ah,ah
425: stosw
426: mov ax,I_OR_AH_AL
427: stosw
428:
429: mov ax,I_LODSB+(I_XOR_AL_BYTE_I*256)
430: stosw
431: mov al,fr.bkColor.SPECIAL
432: shr al,1 ;get C0_BIT into carry
433: sbb al,al ;make it 0ffh if bit was set
434: .errnz C0_BIT - 00000001b
435: stosb ;save the modified value
436: errnz pcol_C0
437: mov ax,I_OR_AL_AH
438: stosw
439: mov ax,I_NOT_AL
440: stosw
441: jmp cblt_3240 ;Go create logic code
442:
443: subttl Compile - Initial Byte Fetch, Mono ==> Color
444: page
445: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
446: ; The conversion is mono to color. Generate the code to
447: ; do the conversion, and generate the table which will
448: ; have the conversion values in it.
449: ;
450: ; When going from mono to color, 1 bits are considered to be
451: ; the background color, and 0 bits are considered to be the
452: ; foreground color.
453: ;
454: ; For each plane:
455: ;
456: ; If the foreground=background=1, then 1 can be used in
457: ; place of the source.
458: ;
459: ; If the foreground=background=0, then 0 can be used in
460: ; place of the source.
461: ;
462: ; If the foreground=0 and background=1, then the source
463: ; can be used as is.
464: ;
465: ; If the foreground=1 and background=0, then the source
466: ; must be complemented before using.
467: ;
468: ; Looks like a boolean function to me.
469: ;
470: ; An AND mask and an XOR mask will be computed for each plane,
471: ; based on the above. The source will then be processed against
472: ; the table. The generated code should look like
473: ;
474: ; lodsb
475: ; and al,[xxxx]
476: ; xor al,[xxxx+1]
477: ;
478: ; The table for munging the colors as stated above should look like:
479: ;
480: ; BackGnd ForeGnd Result AND XOR
481: ; 1 1 1 00 FF
482: ; 0 0 0 00 00
483: ; 1 0 S FF 00
484: ; 0 1 not S FF FF
485: ;
486: ; From this, it can be seen that the XOR mask is the same as the
487: ; foreground color. The AND mask is the XOR of the foreground
488: ; and the background color. Not too hard to compute
489: ;
490: ; It can also be seen that if the background color is white and the
491: ; foreground (text) color is black, then the conversion needn't be
492: ; generated (it just gives the source). This is advantageous since
493: ; it will allow phased aligned source copies to use REP MOVSW.
494: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
495:
496: ; Check to see if the background color is black, and the
497: ; foreground color is white. This can be determined by
498: ; looking at the accelerator flags in the physical color.
499:
500: cblt_3100:
501: mov ah,fr.TextColor.SPECIAL
502: xor ah,MONO_BIT ;Map black to white
503: and ah,fr.bkColor.SPECIAL ;AND in background color
504: cmp ah,MONO_BIT+ONES_OR_ZEROS
505: jne cblt_3110 ;Not black
506: mov fr.moore_flags,F1_REP_OK+F1_NO_MUNGE ;Show reps as ok, no color munge table
507: jmp short cblt_3180 ;Normal fetch required
508:
509: ; No way around it. The color conversion table and code
510: ; must be generated.
511:
512: cblt_3110:
513: mov cl,fr.bkColor.SPECIAL ;Get BackGround Colors
514: mov ch,fr.TextColor.SPECIAL ;Get ForeGround Colors
515: xor cl,ch
516: shr cl,1
517: sbb al,al
518: shr ch,1
519: sbb ah,ah
520: mov word ptr fr.ajM2C.(pcol_C0 * 2),ax
521: shr cl,1
522: sbb al,al
523: shr ch,1
524: sbb ah,ah
525: mov word ptr fr.ajM2C.(pcol_C1 * 2),ax
526: shr cl,1
527: sbb al,al
528: shr ch,1
529: sbb ah,ah
530: mov word ptr fr.ajM2C.(pcol_C2 * 2),ax
531: shr cl,1
532: sbb al,al
533: shr ch,1
534: sbb ah,ah
535: mov word ptr fr.ajM2C.(pcol_C3 * 2),ax
536: errnz <TextColor - bkColor - 4>
537:
538: ; Generate the code for munging the color as stated above.
539:
540: mov ax,I_LODSB
541: stosb ;lodsb
542: mov ax,I_AND_AL_MEM ;and al,[xxxx]
543: stosw
544: lea eax,fr.ajM2C ; Set address of color munge
545: stosd
546: mov ebx,eax ; Save address
547: mov ax,I_XOR_AL_MEM ;xor al,[xxxx]
548: stosw
549: lea eax,1[ebx] ; Set address of XOR mask
550: stosd
551: jmp short cblt_3240
552:
553: ; Just need to generate the normal fetch sequence (lodsb)
554:
555: cblt_3180:
556: mov al,I_LODSB ;Generate source fetch
557: stosb
558:
559: subttl Compile - Phase Alignment
560: page
561: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
562: ; Generate the phase alignment if any.
563: ;
564: ; It is assumed that AL contains the source byte
565: ;
566: ; Currently:
567: ; DH = phase alignment
568: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
569:
570: cblt_3240:
571: mov ecx,edi ;end of fetch code
572: sub ecx,fr.start_fl ;start of fetch code
573: mov fr.cFetchCode,ecx ;save size of fetch code
574: xor ecx,ecx ;Might have garbage in it
575: or dh,dh ;Any phase alignment?
576: jz cblt_3280 ; No, so skip alignment
577: mov cl,dh ;Get horizontal phase for rotating
578: mov ax,I_ROL_AL_N ;Assume rotate left n times
579: cmp cl,5 ;4 or less rotates?
580: jc cblt_3260 ; Yes
581: neg cl ; No, compute ROR count
582: add cl,8
583: mov ah,HIGH I_ROR_AL_N
584: errnz <(LOW I_ROL_AL_N)-(LOW I_ROR_AL_N)>
585:
586: cblt_3260:
587: stosw ;Stuff the phase alignment rotates
588: mov al,cl ; then the phase alignment code
589: stosb
590:
591: ; Do not generate phase masking if there is only 1 src And only 1 dest byte.
592: ; This is not just an optimization, see comments where these flags are set.
593:
594: xor ch,ch
595: mov al,fr.first_fetch
596: and al,FF_ONLY_1_SRC_BYTE or FF_ONLY_1_DEST_BYTE
597: xor al,FF_ONLY_1_SRC_BYTE or FF_ONLY_1_DEST_BYTE
598: jz cblt_3280
599: mov esi,offset FLAT:phase_align
600: mov ecx,PHASE_ALIGN_LEN
601: rep movsb
602:
603: cblt_3280:
604: test fr.first_fetch,FF_TWO_INIT_FETCHES ;Generate another fetch?
605: jz cblt_4000 ; No
606:
607: ; A second fetch needs to be stuffed. Copy the one just created.
608:
609: mov esi,edi ;Get start of fetch logic
610: xchg esi,fr.start_fl ;Set new start, get old
611: mov ecx,edi ;Compute how long fetch is
612: sub ecx,esi ; and move the bytes
613: rep movsb
614:
615: subttl Compile - ROP Generation
616: page
617: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
618: ; Create the logic action code
619: ;
620: ; The given ROP will be converted into the actual code that
621: ; performs the ROP.
622: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
623:
624: ; Copy the ROP template into the BLT
625:
626: cblt_4000:
627: mov ax,fr.operands ;Get back rop data
628: mov bl,ah ;Get count of number of bits to move
629: and ebx,HIGH ROPLength
630: shr ebx,2
631: movzx ecx,roptable+256[ebx] ;Get length into cx
632: errnz ROPLength-0001110000000000b
633:
634: mov ebx,eax ;Get offset of the template
635: and ebx,ROPOffset
636: lea esi,roptable[ebx] ;--> the template
637: rep movsb ;Move the template
638:
639: cblt_4020:
640: mov bx,ax ;Keep rop around
641: or ah,ah ;Generate a negate?
642: jns cblt_4040 ; No
643: mov ax,I_NOT_AL
644: stosw
645:
646: public cblt_4040
647: cblt_4040:
648: mov fr.end_fl,edi ;Save end of fetch/logic operation
649:
650: subttl Compile - Mask And Save
651: page
652: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
653: ; Generate code to mask and save the result. If the destination
654: ; isn't in a register, it will be loaded from ES:[DI] first. The
655: ; mask operation will then be performed, and the result stored.
656: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
657:
658: mov ax,I_MOV_AH_DEST ; ah,[edi]
659: stosw
660:
661: mov esi,offset FLAT:masked_store;Move rest of masked store template
662: movsb ;Move size override
663: movsd
664: movsw
665: errnz MASKED_STORE_LEN-7 ;Must be seven bytes long
666: mov ax,fr.start_mask ;Stuff start mask into
667: xchg ah,al ; the template
668:
669: mov [edi][MASKED_STORE_MASK],ax
670:
671: mov fr.end_fls,edi ;Save end of fetch/logic/store operation
672:
673: subttl Compile - Inner Loop Generation
674: page
675: ;-----------------------------------------------------------------------;
676: ; Now for the hard stuff; The inner loop (said with a "gasp!").
677: ;
678: ; If there is no innerloop, then no code will be generated
679: ; (now that's fast!).
680: ;-----------------------------------------------------------------------;
681:
682: cblt_5000:
683: mov edx,fr.inner_loop_count ;Get the loop count
684: or dx,dx ;If the count is null
685: jz cblt_6000 ; don't generate any code
686:
687: ;!!! Since we no longer pass in the old style rops, we can;t enable this code
688: ;!!! and shold remove/alter it someday. Besides, most of it is in special.asm
689: if 0 ;!!!
690:
691: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
692: ; We have something for a loop count. If this just happens to be
693: ; a source copy (S) with a phase of zero, then the innerloop degenerates
694: ; to a repeated MOVSB instruction. This little special case is
695: ; worth checking for and handling!
696: ;
697: ; Also, if this is one of the special cases {P, Pn, DDx, DDxn}, then it
698: ; will also be special cased since these are all pattern fills (pattern,
699: ; not pattern, 0, 1).
700: ;
701: ; The same code can be shared for these routines, with the exception
702: ; that patterns use a STOSx instruction instead of a MOVSx instruction
703: ; and need a value loaded in AX
704: ;
705: ; So we lied a little. If a color conversion is going on, then the
706: ; REP MOVSB might not be usable. If the F1_REP_OK flag has been set, then
707: ; we can use it. The F1_REP_OK flag will be set for a mono ==> color
708: ; conversion where the background color is white and the foreground
709: ; color is black, or for a color ==> mono conversion with the screen
710: ; as the source (the color compare register will be used).
711: ;
712: ; For the special cases {P, Pn, DDx, DDxn}, color conversion is
713: ; not possible, so ignore it for them.
714: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
715:
716: mov bl,byte ptr fr.Rop ;Get the raster op
717: test bl,EPS_INDEX ;Can this be special cased?
718: jnz cblt_5500 ; No
719: errnz <HIGH EPS_INDEX>
720: errnz SPEC_PARSE_STR_INDEX ;The special case index must be 0
721:
722: test bl,EPS_OFF ;Is this a source copy
723: jz cblt_5040 ; Yes
724: errnz <SOURCE_COPY AND 11b> ;Offset for source copy must be 0
725:
726: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
727: ; We should have one of the following fill operations:
728: ;
729: ; P - Pattern
730: ; Pn - NOT pattern
731: ; DDx - 0 fill
732: ; DDxn - 1 fill
733: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
734:
735: mov ax,I_MOV_AL_0FFH ;Assume this is a 0 or 1 fill
736: test bl,01h ;Is it 0 or 1 fill?
737: jz cblt_5020 ; Yes, initialize AX with 0FFh
738: mov ax,I_MOV_AL_DH ; No, initialize AX with pattern
739:
740: errnz PAT_COPY-0000000000100001b
741: errnz NOTPAT_COPY-0000000000000001b
742: errnz FILL_BLACK-0000000001000010b
743: errnz FILL_WHITE-0000000001100010b
744:
745: cblt_5020:
746: stosw
747: mov ax,I_MOV_AH_AL
748: stosw
749: mov si,I_STOSB ;Set up for repeated code processor
750: test bl,LogPar ;If Pn or 0, then complement pattern
751: jnz cblt_5060 ; Is just P or 1
752: errnz <HIGH LogPar>
753: mov al,I_SIZE_OVERRIDE
754: stosb
755: mov ax,I_NOT_AX ; Is Pn or 0, complement AX
756: stosw
757: jmp short cblt_5060
758:
759: errnz PAT_COPY-00100001b
760: errnz NOTPAT_COPY-00000001b
761: errnz FILL_BLACK-01000010b
762: errnz FILL_WHITE-01100010b
763:
764:
765: ; This is a source copy. The phase must be zero for a source copy
766: ; to be condensed into a REP MOVSx.
767:
768: cblt_5040:
769: test fr.phase_h,0FFh ;Is horizontal phase zero?
770: jnz cblt_5500 ; No, can't condense source copy
771: mov si,I_MOVSB ;Set register for moving bytes
772:
773: ; For a color conversion, F1_REP_OK must be set.
774:
775: test fr.the_flags,F0_GAG_CHOKE ;Color conversion?
776: jz cblt_5060 ; No, rep is OK to use
777: test fr.moore_flags,F1_REP_OK ; Yes, can we rep it?
778: jz cblt_5500 ; No, do it the hard way
779:
780:
781: ;-----------------------------------------------------------------------;
782: ; This is a source copy or pattern fill. Process an odd byte with
783: ; a MOVSB or STOSB, then process the rest of the bytes with a REP
784: ; MOVSW or a REP STOSW. If the REP isn't needed, leave it out.
785: ;
786: ; Don't get caught on this like I did! If the direction of the
787: ; BLT is from right to left (decrementing addresses), then both
788: ; the source and destination pointers must be decremented by one
789: ; so that the next two bytes are processed, not the next byte and
790: ; the byte just processed. Also, after all words have been processed,
791: ; the source and destination pointers must be incremented by one to
792: ; point to the last byte (since the last MOVSW or STOSW would have
793: ; decremented both pointers by 2).
794: ;
795: ; If the target machine is an 8086, then it would be well worth the
796: ; extra logic to align the fields on word boundaries before the MOVSxs
797: ; if at all possible.
798: ;
799: ; The generated code should look something like:
800: ;
801: ; WARP8: ;This code for moving left to right
802: ; movsb ;Process an odd byte
803: ; mov ecx,gl_inner_loop_count/2 ;Set word count
804: ; rep ;If a count, then repeat is needed
805: ; movsw ;Move words until done
806: ;
807: ;
808: ; WARP8: ;This code for moving left to right
809: ; movsb ;Process an odd byte
810: ; dec si ;adjust pointer for moving words
811: ; dec di
812: ; mov ecx,gl_inner_loop_count/2 ;Set word count
813: ; rep ;If a count, then repeat is needed
814: ; movsw ;Move words until done
815: ; inc si ;adjust since words were moved
816: ; inc di
817: ;
818: ;
819: ; Of course, if any part of the above routine isn't needed, it isn't
820: ; generated (i.e. the generated code might just be a single MOVSB)
821: ;-----------------------------------------------------------------------;
822:
823: cblt_5060:
824: shr edx,1 ;Byte count / 2 for words
825: jnc cblt_5080 ; No odd byte to move
826: mov ax,si ; Odd byte, move it
827: stosb
828:
829: cblt_5080:
830: jz cblt_5140 ;No more bytes to move
831: xor bx,bx ;Flag as stepping from left to right
832: cmp bl,fr.step_direction ;Moving from the right to the left?
833: errnz STEPLEFT ; (left direction must be zero)
834: jnz cblt_5100 ; No
835: mov ax,I_DEC_ESI_DEC_EDI ; Yes, decrement both pointers
836: stosw
837: mov bx,I_INC_ESI_INC_EDI ;Set up to increment the pointers later
838:
839: 0cblt_5100:
840: cmp edx,1 ;Move one word or many words?
841: jz cblt_5120 ; Only one word
842: mov al,I_MOV_ECX_DWORD_I ; Many words, load count
843: stosb
844: mov eax,edx
845: stosd
846: mov al,I_REP ;a repeat instruction
847: stosb
848:
849: cblt_5120:
850: mov al,I_SIZE_OVERRIDE
851: stosb
852: mov ax,si ;Set the word instruction
853: inc ax
854: stosb
855: errnz I_MOVSW-I_MOVSB-1 ;The word form of the instruction
856: errnz I_STOSW-I_STOSB-1 ; must be the byte form + 1
857:
858: or bx,bx ;Need to increment the pointers?
859: jz cblt_5140 ; No
860: mov ax,bx ; Yes, increment both pointers
861: stosw
862:
863: cblt_5140:
864: jmp cblt_6000 ;Done setting up the innerloop
865: page
866:
867: endif
868:
869: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
870: ; There is some count for the innerloop of the BLT. Generate the
871: ; required BLT. Two or four copies of the BLT will be placed on the
872: ; stack. This allows the LOOP instruction at the end to be distributed
873: ; over two or four bytes instead of 1, saving 11 or 12 clocks for each
874: ; byte (for 4). Multiply 12 clocks by ~ 16K and you save a lot of
875: ; clocks!
876: ;
877: ; If there are less than four (two) bytes to be BLTed, then no looping
878: ; instructions will be generated. If there are more than four (two)
879: ; bytes, then there is the possibility of an initial jump instruction
880: ; to enter the loop to handle the modulo n result of the loop count.
881: ;
882: ; The innerloop code will look something like:
883: ;
884: ; < mov cx,loopcount/n> ;load count if >n innerloop bytes
885: ; < jmp short ??? > ;If a first jump is needed, do one
886: ;
887: ; BLTloop:
888: ; replicate initial byte BLT code up to n times
889: ;
890: ; < loop BLTloop > ;Loop until all bytes processed
891: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
892:
893: cblt_5500:
894: mov ebx,fr.end_fl ;Compute size of the fetch code
895: sub ebx,fr.start_fl
896: inc ebx ;A stosb will be appended
897: mov esi,4 ;Assume replication 4 times
898: mov cl,2 ; (shift count two bits left)
899: cmp ebx,32 ;Small enough for 4 times?
900: jc cblt_5520 ; Yes, replicate 4 times
901: shr esi,1 ; No, replicate 2 times
902: dec ecx
903:
904: cblt_5520:
905: cmp edx,esi ;Generate a loop? (edx = loopcount)
906: jle cblt_5540 ; No, just copy code
907: mov al,I_MOV_ECX_DWORD_I
908: stosb ;mov cx,loopcount/n
909: mov eax,edx ;Compute loop count
910: shr eax,cl
911: stosd
912: shl eax,cl ;See if loopcount MOD n is 0
913: sub eax,edx
914: jz cblt_5540 ;Zero, no odd count to handle
915:
916: page
917: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
918: ; There is an odd portion of bytes to be processed. Increment
919: ; the loop counter for the odd pass through the loop and then
920: ; compute the displacement for entering the loop.
921: ;
922: ; To compute the displacement, subtract the number of odd bytes
923: ; from the modulus being used (i.e. 4-3=1). This gives the
924: ; number of bytes to skip over the first time through the loop.
925: ;
926: ; Multiply this by the number of bytes for a logic sequence,
927: ; and the result will be the displacement for the jump.
928: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
929:
930: inc dword ptr [edi][-4] ;Not zero, adjust for partial loop
931: add eax,esi ;Compute where to enter the loop at
932: push edx
933: mul ebx
934: pop edx
935: mov ecx,eax
936: mov al,I_JMP_DISP32 ;Stuff jump instruction
937: stosb
938: mov eax,ecx ;Stuff displacement for jump
939: stosd
940:
941: ;-----------------------------------------------------------------------;
942: ; Currently: EDX = loop count
943: ; ESI = loop modulus
944: ; EBX = size of one logic operation
945: ; EDI --> next location in the loop
946: ;-----------------------------------------------------------------------;
947:
948: cblt_5540:
949: mov ecx,ebx ;Set move count
950: mov ebx,edx ;Set maximum for move
951: cmp ebx,esi ;Is the max > what's left?
952: jle cblt_5560 ; No, just use what's left
953: mov ebx,esi ; Yes, copy the max
954:
955: cblt_5560:
956: sub edx,esi ;If dx > 0, then loop logic needed
957: mov esi,fr.start_fl ;--> fetch code to copy
958: mov eax,ecx ;Save a copy of fetch length
959: rep movsb ;Move fetch code and stuff stosb
960: mov esi,edi ;--> new source (and top of loop)
961: sub esi,eax
962: mov byte ptr [edi][-1],I_STOSB
963: dec ebx ;One copy has been made
964: push edx
965: mul ebx ;Compute # bytes left to move
966: pop edx
967: mov ecx,eax ;Set move count
968: rep movsb ;Move the fetches
969: sub esi,eax ;Restore pointer to start of loop
970:
971: page
972:
973: ; The innermost BLT code has been created and needs the looping
974: ; logic added to it. If there is any looping to be done, then
975: ; generate the loop code. The code within the innerloop may be
976: ; greater than 126 bytes, so a LOOP instruction may not be used
977: ; in this case.
978:
979: cblt_5580:
980: or edx,edx ;Need a loop?
981: jle cblt_6000 ; No, don't generate one
982: mov al,I_DEC_ECX
983: stosb
984: mov ax,I_JNZ_DISP32
985: stosw
986: mov eax,esi ;Compute offset of loop
987: sub eax,edi
988: sub eax,4 ;Bias by DISP32
989: stosd
990:
991:
992: subttl Compile - Last Byte Processing
993: page
994: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
995: ; All the innerloop stuff has been processed. Now generate the code for
996: ; the final byte if there is one. This code is almost identical to the
997: ; code for the first byte except there will only be one fetch (if a
998: ; fetch is needed at all).
999: ;
1000: ; The code generated will look something like:
1001: ;
1002: ; < fetch > ;Get source byte
1003: ; < align > ;Align source if needed
1004: ; action ;Perform desired action
1005: ; mask and store
1006: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1007:
1008: cblt_6000:
1009: mov dx,fr.last_mask ;Get last byte mask
1010: or dh,dh ;Is there a last byte to be processed?
1011: jz cblt_6100 ; No.
1012:
1013: mov ecx,fr.end_fls ;Get end of fetch/logic/store operation
1014: mov esi,fr.start_fl ;Get start of fetch/logic sequence
1015: sub ecx,esi ;Compute length of the code
1016: test fr.first_fetch,FF_NO_LAST_FETCH
1017: jz cblt_include_fetch
1018: test fr.the_flags,F0_SRC_PRESENT ; was there a fetch?
1019: jz cblt_was_no_fetch
1020: cmp fr.phase_h,0 ; Phase zero case is not combined
1021: ; into innerloop as it should be.
1022: ; If the final byte is full then we
1023: ; better not remove the lodsb ( i.e.
1024: je cblt_include_fetch ; 0 - 0 = 0 would make us think we could)
1025:
1026: mov eax,fr.cFetchCode ; don't copy the fetch (lodsb)
1027: add esi,eax
1028: sub ecx,eax
1029:
1030: cblt_was_no_fetch:
1031: cblt_include_fetch:
1032:
1033: rep movsb ;Copy the fetch/action/store code
1034: xchg dh,dl
1035: mov [edi][MASKED_STORE_MASK],dx ;Stuff last byte mask into the code
1036: skip_save:
1037: subttl Compile - Looping Logic
1038: page
1039:
1040: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1041: ; Looping logic.
1042: ;
1043: ; The looping logic must handle monochrome bitmaps, color bitmaps,
1044: ; huge bitmaps, the device, the presence or absence of a source
1045: ; or pattern, and mono <==> color interactions.
1046: ;
1047: ; The type of looping logic is always based on the destination.
1048: ;
1049: ; Plane Update Facts:
1050: ;
1051: ; 1) If the destination device is color, then there will be
1052: ; logic for plane selection. Plane selection is performed
1053: ; at the start of the loop for the display. Plane selection
1054: ; for bitmaps is performed at the end of the loop in anticipation
1055: ; of the next plane.
1056: ;
1057: ; The following applies when the destination is color:
1058: ;
1059: ; a) The destination update consists of:
1060: ;
1061: ; 1) If the destination is the display, the next plane will
1062: ; be selected by the plane selection code at the start
1063: ; of the scan line loop.
1064: ;
1065: ; 2) If not the display, then the PDevice must a bitmap.
1066: ; The next plane will be selected by updating the
1067: ; destination offset by the next_plane value.
1068: ;
1069: ;
1070: ; b) If F0_GAG_CHOKE isn't specified, then there may be a source.
1071: ; If there is a source, it must be color, and the update
1072: ; consists of:
1073: ;
1074: ; 1) If the source is the display, the next plane will be
1075: ; selected by the plane selection code at the start of
1076: ; the loop.
1077: ;
1078: ; 2) If not the display, then the PDevice must a bitmap.
1079: ; The next plane will be selected by updating the
1080: ; destination offset by the next_plane value.
1081: ;
1082: ;
1083: ; c) If F0_GAG_CHOKE is specified, then the source must be a
1084: ; monochrome bitmap which is undergoing mono to color
1085: ; conversion. The AND & XOR mask table which is used
1086: ; for the conversion will have to be updated, unless
1087: ; the F1_NO_MUNGE flag is set indicating that the color
1088: ; conversion really wasn't needed.
1089: ;
1090: ; The source's pointer will not be updated. It will
1091: ; remain pointing to the same scan of the source until
1092: ; all planes of the destination have been processed.
1093: ;
1094: ;
1095: ; d) In all cases, the plane mask rotation code will be
1096: ; generated. If the plane indicator doesn't overflow,
1097: ; then start at the top of the scan line loop for the
1098: ; next plane.
1099: ;
1100: ; If the plane indicator overflows, then:
1101: ;
1102: ; 1) If there is a pattern present, it's a color
1103: ; pattern fetch. The index of which scan of
1104: ; the brush to use will have to be updated.
1105: ;
1106: ; 2) Enter the scan line update routine
1107: ;
1108: ;
1109: ; 2) If the destination is monochrome, then there will be no
1110: ; plane selection logic.
1111: ;
1112: ; If F0_GAG_CHOKE is specified, then color ==> mono conversion
1113: ; is taking place. Any plane selection logic is internal
1114: ; to the ROP byte fetch code. Any color brush was pre-
1115: ; processed into a monochrome brush, so no brush updating
1116: ; need be done
1117: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1118:
1119: subttl Looping Logic - Plane Selection
1120: page
1121:
1122: ; Get saved parameters off of the stack.
1123: ;
1124: ; < pop ebx > ;Get plane indicator
1125: ; < pop esi > ;Get source pointer
1126: ; pop edi ;Get destination pointer
1127: ; pop ecx ;Get loop count
1128:
1129: cblt_6100:
1130: mov bh,fr.the_flags ;These flags will be used a lot
1131: test bh,F0_DEST_IS_COLOR ;Is the destination color?
1132: jz cblt_6120 ; No
1133: mov al,I_POP_EBX ;Restore plane index
1134: stosb
1135:
1136: cblt_6120:
1137: test bh,F0_SRC_PRESENT ;Is a source needed?
1138: jz cblt_6140 ; No
1139: mov al,I_POP_ESI ; Yes, get source pointer
1140: stosb
1141:
1142: cblt_6140:
1143: mov ax,I_POP_EDI_POP_ECX ;Get destination pointer
1144: stosw ;Get loop count
1145: test bh,F0_DEST_IS_COLOR ;Color scanline update?
1146: jz cblt_6300 ; No, just do the mono scanline update
1147:
1148: ; The scanline update is for color. Generate the logic to update
1149: ; a brush, perform plane selection, process mono ==> color conversion,
1150: ; and test for plane overflow.
1151:
1152: cblt_6160:
1153: or bh,bh ;Color conversion?
1154: jns cblt_6180 ; No
1155: errnz F0_GAG_CHOKE-10000000b
1156:
1157: page
1158: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1159: ; The source is monochrome. Handle mono ==> color conversion.
1160: ; The AND & XOR mask table will need to be rotated for the next
1161: ; pass over the source.
1162: ;
1163: ; The source scanline pointer will not be updated until all planes
1164: ; have been processed for the current scan.
1165: ;
1166: ; If F1_NO_MUNGE has been specified, then the color conversion table
1167: ; and the color conversion code was not generated, and no update
1168: ; code will be needed.
1169: ;
1170: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1171:
1172: test fr.moore_flags,F1_NO_MUNGE ;Is there really a conversion table?
1173: jnz short cblt_6200 ; No, so skip the code
1174:
1175: mov al,I_MOV_EBP_DWORD_I ;lea ebp,fr.ajM2C
1176: stosb
1177: lea eax,fr.ajM2c ;Get address of table
1178: stosd
1179: mov esi,offset FLAT:rot_and_xor ;--> rotate code
1180: mov cx,LEN_ROT_AND_XOR
1181: rep movsb
1182: jmp short cblt_6200
1183:
1184: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1185: ; If there is a source, it must be color. If it is a memory
1186: ; bitmap, then the next plane must be selected, else it is
1187: ; the display and the next plane will be selected through
1188: ; the hardware registers.
1189: ;
1190: ; < add si,next_plane>
1191: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1192:
1193: cblt_6180:
1194: test bh,F0_SRC_PRESENT ;Is there really a source?
1195: jz cblt_6200 ;No source.
1196: test bh,F0_SRC_IS_DEV ;Is the source the display?
1197: jnz cblt_6200 ; Yes, use hardware plane selection
1198: mov ax,I_ADD_ESI_DWORD_I ; No, generate plane update
1199: stosw ;Add si,next_plane
1200: mov eax,fr.src.next_plane
1201: stosd
1202:
1203: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1204: ; If the destination isn't the device, then it must be a color
1205: ; memory bitamp, and it's pointer will have to be updated by
1206: ; bmWidthPlanes. If it is the display, then the next plane
1207: ; will be selected through the hardware registers.
1208: ;
1209: ; < add di,next_plane>
1210: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1211:
1212: cblt_6200:
1213: test bh,F0_DEST_IS_DEV ;Is the destination the display
1214: jnz cblt_6220 ; Yes, don't generate update code
1215: mov ax,I_ADD_EDI_DWORD_I ; No, update bitmap to the next plane
1216: stosw
1217: mov eax,fr.dest.next_plane
1218: stosd
1219:
1220:
1221: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1222: ; The source and destination pointers have been updated.
1223: ; Now generate the plane looping logic.
1224: ;
1225: ; < shl bl,1 > ;Select next plane
1226: ; < jnc StartOfLoop > ; Yes, go process next
1227: ; < mov bl,PLANE_1 > ;Reset plane indicator
1228: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1229:
1230: cblt_6220:
1231: mov ax,I_SHL_BL_1 ;Stuff plane looping logic
1232: stosw
1233:
1234: mov edx,fr.pNextPlane ;Compute relative offset of
1235: sub edx,edi ; start of loop
1236: sub edx,6 ;Bias offset by length of jnc inst.
1237: mov ax,I_JNC_DISP32
1238: stosw ;jnc StartOfLoop
1239: mov eax,edx
1240: stosd
1241:
1242: subttl Looping Logic - Color Brush Update
1243: page
1244:
1245: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1246: ; The plane update logic has been copied. If a pattern was
1247: ; involved for a color BLT, then the pattern index will need
1248: ; to be updated to the next scanline for three plane mode.
1249: ;
1250: ; This will involve subtracting off 3*SIZE_PATTERN (MonoPlane),
1251: ; and adding in the increment. The result must be masked with
1252: ; 00000111b to select the correct source. Note that the update
1253: ; can be done with an add instruction and a mask operation.
1254: ;
1255: ; inc index+MonoPlane inc-MonoPlane result AND 07h
1256: ;
1257: ; 1 0+32 = 32 1-32 = -31 1 1
1258: ; 1 7+32 = 39 1-32 = -31 8 0
1259: ; -1 0+32 = 32 -1-32 = -33 FF 7
1260: ; -1 7+32 = 39 -1-32 = -33 6 6
1261: ;
1262: ; < mov al,[12345678] > ;Get brush index
1263: ; < add al,n > ;Add displacement to next byte
1264: ; < and al,00000111b > ;Keep it in range
1265: ; < mov [12345678],al > ;Store displacement to next byte
1266: ;
1267: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1268:
1269: test bh,F0_PAT_PRESENT ;Is a pattern involved?
1270: jz cblt_6300 ; No
1271: test fr.brush_accel,SOLID_BRUSH
1272: jnz cblt_6300 ;Solid color fetch needs no updating
1273: mov al,I_MOV_AL_MEM
1274: stosb ;mov al,[xxxxxxxx]
1275: mov edx,fr.addr_brush_index
1276: mov eax,edx
1277: stosd
1278: mov al,I_ADD_AL_BYTE_I
1279: mov ah,fr.direction ;add al,bais
1280: sub ah,oem_brush_mono ;Anybody ever fly one of these things?
1281: errnz INCREASE-1 ;Must be a 1
1282: errnz DECREASE+1 ;Must be a -1
1283: stosw
1284: mov ax,0700h+I_AND_AL_BYTE_I ;and al,00000111b
1285: stosw
1286: mov al,I_MOV_MEM_AL
1287: stosb ;mov [xxxxxxxx],al
1288: mov eax,edx
1289: stosd
1290:
1291: subttl Looping Logic - Scan Line Update
1292: page
1293: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1294: ; Generate the next scanline code. The next scan line code must
1295: ; handle monochrome bitmaps, the device, the presence or absence
1296: ; of a source.
1297: ;
1298: ; Also color bitmaps, and mono <==> color interactions.
1299: ;
1300: ; < add si,gl_src.next_scan> ;Normal source scan line update
1301: ; add di,gl_dest.next_scan ;Normal destination scan line update
1302: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
1303:
1304: ;!!! We have the problem in that this code assumes that cPlanes*cjBytesScan
1305: ;!!! is the same as next_scan. This might not always be the case, and we
1306: ;!!! should do somehting about fixing this. This would require pushing an
1307: ;!!! extra copy of pScan_n_Plane0 and then adding next-scan to this when we
1308: ;!!! have exhausted the planes for scan n
1309:
1310: cblt_6300:
1311: test bh,F0_SRC_PRESENT ;Is there a source?
1312: jz cblt_6340 ; No, skip source processing
1313: mov ax,I_ADD_ESI_DWORD_I ;add esi,increment
1314: stosw
1315: mov eax,fr.src.next_scan
1316: stosd
1317:
1318: cblt_6340:
1319: mov ax,I_ADD_EDI_DWORD_I ;add edi,increment
1320: stosw
1321: mov eax,fr.dest.next_scan
1322: stosd
1323:
1324: ; Compile the scan line loop. The code simply jumps to the start
1325: ; of the outer loop if more scans exist to be processed.
1326:
1327: cblt_6380:
1328: mov al,I_DEC_ECX
1329: stosb
1330: mov ax,I_JNZ_DISP32
1331: stosw
1332: mov eax,fr.blt_addr ;Compute relative offset of
1333: sub eax,edi ; start of loop
1334: sub eax,4 ;Adjust jump bias for DISP32
1335: stosd ; and store it into jump
1336:
1337: cblt_6420:
1338: mov al,I_RET ;Stuff the far return instruction
1339: stosb
1340:
1341: cRet cblt
1342: endProc cblt
1343:
1344: _TEXT$01 ends
1345:
1346: end
1347:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.