|
|
1.1 root 1: ;---------------------------Module-Header------------------------------;
2: ; Module Name: dib2vga.asm
3: ;
4: ; Copyright (c) 1992 Microsoft Corporation
5: ;-----------------------------------------------------------------------;
6: ;-----------------------------------------------------------------------;
7: ;
8: ; VOID vDIB2VGA(DEVSURF * pdsurfDst, DEVSURF * pdsurfSrc,
9: ; RECTL * prclDst, POINTL * pptlSrc, UCHAR *pConv);
10: ;
11: ; Performs accelerated copies of DIB pixels to the VGA screen.
12: ;
13: ; pdsurfDst = pointer to dest surface, which must be the VGA
14: ;
15: ; pdsurfSrc = pointer to source surface, which must be a 4 bpp DIB. Only the
16: ; lNextScan and pvBitmapStart fields need to be set
17: ;
18: ; prclDst = pointer to rectangle describing area of VGA to be copied to
19: ;
20: ; pptlSrc = pointer to point structure describing the upper left corner
21: ; of the copy in the source DIB
22: ;
23: ; pConv = pointer to set of four 256-byte tables used for conversion
24: ; from DIB4 to VGA, created by vSetDIB4ToVGATables
25: ;
26: ;-----------------------------------------------------------------------;
27: ;-----------------------------------------------------------------------;
28: ;
29: ; VOID vSetDIB4ToVGATables(UCHAR * pucConvTable);
30: ;
31: ; Creates the four 256-byte tables used for conversion from DIB4 to VGA.
32: ;
33: ; pucConvTable = pointer to 1K of storage into which the conversion
34: ; tables are placed
35: ;
36: ;-----------------------------------------------------------------------;
37: ;-----------------------------------------------------------------------;
38: ;
39: ; Note: The general-purpose buffer attached to the PDEV that we used for
40: ; temp storage (pvBankBufferPlane0) must be at least 1K+4 bytes wide to
41: ; support
42: ;
43: ; Note: Assumes the destination rectangle has a positive height and width.
44: ; Will not work properly if this is not the case.
45: ;
46: ; Note: The source must be a standard DIB4 bitmap, and the destination
47: ; must be VGA display memory.
48: ;
49: ; Note: Performance would benefit if we did more scans at a time in each
50: ; plane on processor/VGA combinations that supported higher conversion
51: ; and display memory writing speeds.
52: ;
53: ;-----------------------------------------------------------------------;
54:
55: .386
56:
57: ifndef DOS_PLATFORM
58: .model small,c
59: else
60: ifdef STD_CALL
61: .model small,c
62: else
63: .model small,pascal
64: endif; STD_CALL
65: endif; DOS_PLATFORM
66:
67: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
68: assume fs:nothing,gs:nothing
69:
70: .xlist
71: include stdcall.inc ;calling convention cmacros
72: include i386\egavga.inc
73: include i386\strucs.inc
74:
75: .list
76:
77: ;-----------------------------------------------------------------------;
78:
79: .data
80:
81: ;-----------------------------------------------------------------------;
82: ; Masks to be applied to the source data for the 8 possible clip
83: ; alignments.
84: ;-----------------------------------------------------------------------;
85:
86: jLeftMasks db 0ffh, 07fh, 03fh, 01fh, 00fh, 007h, 003h, 001h
87: jRightMasks db 0ffh, 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0fch, 0feh
88:
89: ;-----------------------------------------------------------------------;
90: ; The following tables *must* start on 256-byte boundaries, so that a
91: ; table look-up may be accomplished by loading BL.
92: ;-----------------------------------------------------------------------;
93:
94: ;-----------------------------------------------------------------------;
95: ; Table used to multiplex bits from form accumulated from DIB4 to VGA
96: ; planar byte format for plane 0. Translation is from 64207531 source
97: ; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
98: ; format (where 7 is leftmost, 0 is rightmost).
99: if 0
100: align 256
101: ;@@@
102: db 256-20h dup (?)
103: ;@@@
104: ;DIB4_to_VGA_plane0_table label byte
105: x=0
106: rept 256
107: db ((x and 10h) shl 3)+((x and 01h) shl 6)+\
108: (x and 20h) +((x and 02h) shl 3)+\
109: ((x and 40h) shr 3)+ (x and 04h) +\
110: ((x and 80h) shr 6)+((x and 08h) shr 3)
111: x=x+1
112: endm
113: ;-----------------------------------------------------------------------;
114: ; Table used to multiplex bits from form accumulated from DIB4 to VGA
115: ; planar byte format for plane 0. Translation is from 46025713 source
116: ; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
117: ; format (where 7 is leftmost, 0 is rightmost).
118:
119: ;DIB4_to_VGA_plane1_table label byte
120: x=0
121: rept 256
122: db ((x and 20h) shl 2)+((x and 02h) shl 5)+\
123: ((x and 10h) shl 1)+((x and 01h) shl 4)+\
124: ((x and 80h) shr 4)+((x and 08h) shr 1)+\
125: ((x and 40h) shr 5)+((x and 04h) shr 2)
126: x=x+1
127: endm
128: ;-----------------------------------------------------------------------;
129: ; Table used to multiplex bits from form accumulated from DIB4 to VGA
130: ; planar byte format for plane 0. Translation is from 20643175 source
131: ; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
132: ; format (where 7 is leftmost, 0 is rightmost).
133:
134: ;DIB4_to_VGA_plane2_table label byte
135: x=0
136: rept 256
137: db ((x and 40h) shl 1)+((x and 04h) shl 4)+\
138: ((x and 80h) shr 2)+((x and 08h) shl 1)+\
139: ((x and 10h) shr 1)+((x and 01h) shl 2)+\
140: ((x and 20h) shr 4)+((x and 02h) shr 1)
141: x=x+1
142: endm
143: ;-----------------------------------------------------------------------;
144: ; Table used to multiplex bits from form accumulated from DIB4 to VGA
145: ; planar byte format for plane 0. Translation is from 02461357 source
146: ; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
147: ; format (where 7 is leftmost, 0 is rightmost).
148:
149: ;DIB4_to_VGA_plane3_table label byte
150: x=0
151: rept 256
152: db (x and 80h) +((x and 08h) shl 3)+\
153: ((x and 40h) shr 1)+((x and 04h) shl 2)+\
154: ((x and 20h) shr 2)+((x and 02h) shl 1)+\
155: ((x and 10h) shr 3)+ (x and 01h)
156: x=x+1
157: endm
158: endif
159: ;-----------------------------------------------------------------------;
160:
161: .code
162:
163: _TEXT$01 SEGMENT DWORD USE32 PUBLIC 'CODE'
164: ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
165:
166: ;-----------------------------------------------------------------------;
167:
168: cProc vSetDIB4ToVGATables,4,< \
169: uses esi edi ebx, \
170: pucConvTable : dword >
171:
172: mov ebx,pucConvTable
173:
174: ; Generate the table used to multiplex bits from form accumulated from DIB4
175: ; to VGA planar byte format for plane 0. Translation is from 64207531 source
176: ; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
177: ; format (where 7 is leftmost, 0 is rightmost).
178:
179: mov ecx,256
180: sub al,al
181: plane0_conv_table_loop:
182: sub dl,dl
183: mov ah,al
184: and ah,10h
185: shl ah,3
186: or dl,ah
187: mov ah,al
188: and ah,01h
189: shl ah,6
190: or dl,ah
191: mov ah,al
192: and ah,20h
193: or dl,ah
194: mov ah,al
195: and ah,02h
196: shl ah,3
197: or dl,ah
198: mov ah,al
199: and ah,40h
200: shr ah,3
201: or dl,ah
202: mov ah,al
203: and ah,04h
204: or dl,ah
205: mov ah,al
206: and ah,80h
207: shr ah,6
208: or dl,ah
209: mov ah,al
210: and ah,08h
211: shr ah,3
212: or dl,ah
213: mov [ebx],dl
214: inc al
215: inc ebx
216: dec ecx
217: jnz plane0_conv_table_loop
218:
219: ; Generate the table used to multiplex bits from form accumulated from DIB4
220: ; to VGA planar byte format for plane 1. Translation is from 46025713 source
221: ; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
222: ; format (where 7 is leftmost, 0 is rightmost).
223:
224: mov ecx,256
225: sub al,al
226: plane1_conv_table_loop:
227: sub dl,dl
228: mov ah,al
229: and ah,20h
230: shl ah,2
231: or dl,ah
232: mov ah,al
233: and ah,02h
234: shl ah,5
235: or dl,ah
236: mov ah,al
237: and ah,10h
238: shl ah,1
239: or dl,ah
240: mov ah,al
241: and ah,01h
242: shl ah,4
243: or dl,ah
244: mov ah,al
245: and ah,80h
246: shr ah,4
247: or dl,ah
248: mov ah,al
249: and ah,08h
250: shr ah,1
251: or dl,ah
252: mov ah,al
253: and ah,40h
254: shr ah,5
255: or dl,ah
256: mov ah,al
257: and ah,04h
258: shr ah,2
259: or dl,ah
260: mov [ebx],dl
261: inc al
262: inc ebx
263: dec ecx
264: jnz plane1_conv_table_loop
265:
266: ; Generate the table used to multiplex bits from form accumulated from DIB4
267: ; to VGA planar byte format for plane 2. Translation is from 20643175 source
268: ; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
269: ; format (where 7 is leftmost, 0 is rightmost).
270:
271: mov ecx,256
272: sub al,al
273: plane2_conv_table_loop:
274: sub dl,dl
275: mov ah,al
276: and ah,40h
277: shl ah,1
278: or dl,ah
279: mov ah,al
280: and ah,04h
281: shl ah,4
282: or dl,ah
283: mov ah,al
284: and ah,80h
285: shr ah,2
286: or dl,ah
287: mov ah,al
288: and ah,08h
289: shl ah,1
290: or dl,ah
291: mov ah,al
292: and ah,10h
293: shr ah,1
294: or dl,ah
295: mov ah,al
296: and ah,01h
297: shl ah,2
298: or dl,ah
299: mov ah,al
300: and ah,20h
301: shr ah,4
302: or dl,ah
303: mov ah,al
304: and ah,02h
305: shr ah,1
306: or dl,ah
307: mov [ebx],dl
308: inc al
309: inc ebx
310: dec ecx
311: jnz plane2_conv_table_loop
312:
313: ; Generate the table used to multiplex bits from form accumulated from DIB4
314: ; to VGA planar byte format for plane 1. Translation is from 02461357 source
315: ; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
316: ; format (where 7 is leftmost, 0 is rightmost).
317:
318: mov ecx,256
319: sub al,al
320: plane3_conv_table_loop:
321: sub dl,dl
322: mov ah,al
323: and ah,80h
324: or dl,ah
325: mov ah,al
326: and ah,08h
327: shl ah,3
328: or dl,ah
329: mov ah,al
330: and ah,40h
331: shr ah,1
332: or dl,ah
333: mov ah,al
334: and ah,04h
335: shl ah,2
336: or dl,ah
337: mov ah,al
338: and ah,20h
339: shr ah,2
340: or dl,ah
341: mov ah,al
342: and ah,02h
343: shl ah,1
344: or dl,ah
345: mov ah,al
346: and ah,10h
347: shr ah,3
348: or dl,ah
349: mov ah,al
350: and ah,01h
351: or dl,ah
352: mov [ebx],dl
353: inc al
354: inc ebx
355: dec ecx
356: jnz plane3_conv_table_loop
357:
358: cRet vSetDIB4ToVGATables ;done
359:
360: endProc vSetDIB4ToVGATables
361:
362: ;-----------------------------------------------------------------------;
363:
364: cProc vDIB2VGA,20,< \
365: uses esi edi ebx, \
366: pdsurfDst: ptr DEVSURF, \
367: pdsurfSrc: ptr DEVSURF, \
368: prclDst: ptr RECTL, \
369: pptlSrc : ptr POINTL, \
370: pConv : dword >
371:
372: local ulWholeDwordCount:dword ;# of whole VGA dwords to copy to
373: local ulSourceDwordWidth:dword ;# of DIB dwords from which to copy
374: ; (rounded up to the nearest dword)
375: local ulLeftMask:dword ;low byte = mask for new pixels at
376: ; left edge;
377: ;high byte = mask for dest at left
378: ; edge;
379: ;high word = 0ffffh
380: local ulRightMask:dword ;low byte = mask for new pixels at
381: ; partial left edge;
382: ;high byte = mask for destination at
383: ; partial right edge;
384: ;high word = 0ffffh
385: local ulPlane0Scans:dword ;# of scans to copy in plane 0 in burst
386: local ulPlane1Scans:dword ;# of scans to copy in plane 1 in burst
387: local ulPlane2Scans:dword ;# of scans to copy in plane 2 in burst
388: local ulPlane3Scans:dword ;# of scans to copy in plane 3 in burst
389: local ulSrcDelta:dword ;offset from end of one source scan to
390: ; copy to start of next in working
391: ; source (either DIB or temp buffer)
392: local ulTrueSrcDelta:dword ;offset from end of one source scan to
393: ; copy to start of next in DIB if temp
394: ; buffer is being used
395: local ulDstDelta:dword ;offset from end of one destination
396: ; scan to copy to start of next
397: local pSrc:dword ;pointer to working drawing src start
398: ; address (either DIB or temp buffer)
399: local pTrueSrc:dword ;pointer to drawing src start address
400: ; in DIB if temp buffer is being used
401: local pDst:dword ;pointer to drawing dst start address
402: local pTempBuffer:dword ;pointer to buffer used for alignment
403: local ulCurrentTopScan:dword ;top scan to copy to in current bank
404: local ulBottomScan:dword ;bottom scan line of copy rectangle
405: local ulAlignShift:dword ;# of bits to shift left (+) or right
406: ; (-) to dword align source to dest
407: local ulBurstMax:dword ;max # of scans to be done in a single
408: ; plane before switching to the next
409: ; plane (to avoid flicker)
410: local pAlignmentRoutine:dword ;pointer to routine to be used to
411: ; copy & align the source with the dest
412: local DIB4_to_VGA_plane0_table:dword ;pointers to conversion tables
413: local DIB4_to_VGA_plane1_table:dword ; for the four planes
414: local DIB4_to_VGA_plane2_table:dword
415: local DIB4_to_VGA_plane3_table:dword
416: local ulCopyControlFlags:dword ;upper bits indicate which portions of
417: ; copy are to be performed, as follows:
418: ODD_WHOLE_WORD equ 80000000h ;there are an odd # of VGA words to
419: ; copy to
420: .errnz ODD_WHOLE_WORD-80000000h ; (note that this *must* be bit 31,
421: ; because the sign status is used to
422: ; detect this case)
423: WHOLE_WORDS equ 40000000h ;whole words to be copied
424: LEADING_BYTE equ 20000000h ;leading byte should be copied
425: TRAILING_BYTE equ 10000000h ;trailing byte should be copied
426: LEADING_PARTIAL equ 08000000h ;partial leading byte should be copied
427: TRAILING_PARTIAL equ 04000000h ;partial trailing byte should be copied
428:
429: ;-----------------------------------------------------------------------;
430:
431: cld
432:
433: ;-----------------------------------------------------------------------;
434: ; Point to the source start address (nearest dword equal or less).
435: ;-----------------------------------------------------------------------;
436:
437: mov ebx,pptlSrc ;point to coords of source upper left
438: mov esi,pdsurfSrc ;point to surface to copy from (DIB4)
439: mov edi,pdsurfDst ;point to surface to copy to (VGA)
440: mov eax,[ebx].ptl_y
441: mul [esi].dsurf_lNextScan ;offset in bitmap of top src rect scan
442: mov edx,[ebx].ptl_x
443: shr edx,1 ;source byte X address
444: and edx,not 11b ;round down to nearest dword
445: add eax,edx ;offset in bitmap of first source dword
446: add eax,[esi].dsurf_pvBitmapStart ;pointer to first source dword
447: mov pSrc,eax
448:
449: ;-----------------------------------------------------------------------;
450: ; Set the pointers to the DIB->VGA conversion tables for the four
451: ; planes; those tables are created at start-up, and found via the PDEV.
452: ;-----------------------------------------------------------------------;
453:
454: mov eax,pConv ;first conversion table
455: mov DIB4_to_VGA_plane0_table,eax
456: inc ah ;add 256 to point to next table
457: mov DIB4_to_VGA_plane1_table,eax
458: inc ah ;add 256 to point to next table
459: mov DIB4_to_VGA_plane2_table,eax
460: inc ah ;add 256 to point to next table
461: mov DIB4_to_VGA_plane3_table,eax
462:
463: ;-----------------------------------------------------------------------;
464: ; Set up various variables for the copy.
465: ;
466: ; At this point, EBX = pptlSrc, EDI = pdsurfDst.
467: ;-----------------------------------------------------------------------;
468:
469: mov esi,prclDst ;point to rectangle to which to copy
470: sub ecx,ecx ;accumulate copy control flags, which
471: ; describe the various portions of the
472: ; copy we want to perform
473:
474: ;first, check for partial-byte edges
475: mov eax,[esi].xLeft
476: and eax,111b ;left edge pixel alignment
477: jz short @F ;whole byte, don't need leading mask
478: or ecx,LEADING_PARTIAL ;do need leading mask
479: @@:
480: mov edx,-1 ;set high word, so copy control bits
481: ; aren't wiped out by AND
482: mov dl,jLeftMasks[eax] ;mask to apply to source to clip
483: mov dh,dl
484: not dh ;mask to apply to dest to preserve
485: mov ulLeftMask,edx ;remember mask
486:
487: mov eax,[esi].xRight
488: and eax,111b ;right edge pixel alignment
489: jz short @F ;whole byte, don't need trailing mask
490: or ecx,TRAILING_PARTIAL ;do need trailing mask
491: @@:
492: mov edx,-1 ;set high word, so copy control bits
493: ; aren't wiped out by AND
494: mov dl,jRightMasks[eax] ;mask to apply to source to clip
495: mov dh,dl
496: not dh ;mask to apply to dest to preserve
497: mov ulRightMask,edx ;remember mask
498:
499: ;now, see if there are only partial
500: ; bytes, or maybe even only one byte
501: mov eax,[esi].xLeft
502: add eax,111b
503: and eax,not 111b ;round left up to nearest byte
504: mov edx,[esi].xRight
505: and edx,not 111b ;round right down to nearest byte
506: sub edx,eax ;# of pixels, rounded to nearest byte
507: ; boundaries (not counting partials)
508: ja short check_whole_bytes ;there's at least one whole byte
509: ;there are no whole bytes; there may be
510: ; only one partial byte, or there may
511: ; be two
512: jb short one_partial_only ;there is only one, partial byte
513: ;if the dest is left- or right-
514: ; justified, then there's only one,
515: ; partial byte, otherwise there are two
516: ; partial bytes
517: cmp byte ptr ulLeftMask,0ffh ;left-justified in byte?
518: jz short one_partial_only ;yes, so only one, partial byte
519: cmp byte ptr ulRightMask,0ffh ;right-justified in byte?
520: jnz short set_copy_control_flags ;no, so there are two partial
521: ; bytes, which is exactly what
522: ; we're already set up to do
523: one_partial_only: ;only one, partial byte, so construct a
524: ; single mask and set up to do just
525: ; one, partial byte
526: mov eax,ulLeftMask
527: and eax,ulRightMask ;intersect the masks
528: mov ah,al
529: not ah ;construct the destination mask
530: mov ulLeftMask,eax
531: mov ecx,LEADING_PARTIAL ;only one partial byte, which we'll
532: ; treat as leading
533: jmp short set_copy_control_flags ;the copy control flags are set
534:
535: align 4
536: check_whole_bytes:
537: ;check for leading and trailing odd
538: ; (non-word-aligned) whole bytes
539: mov eax,[esi].xLeft ;check for leading whole byte
540: and eax,1111b ;intra-word address
541: jz short @F ;whole leading word, so no whole byte
542: cmp eax,8 ;is start at or before second byte
543: ; start?
544: ja short @F ;no, so no whole byte
545: or ecx,LEADING_BYTE ;yes, there's a leading byte
546: @@:
547:
548: mov eax,[esi].xRight ;check for trailing whole byte
549: and eax,1111b ;intra-word address
550: jz short @F ;whole trailing word, so no whole byte
551: cmp eax,8 ;is start before second byte start?
552: jb short @F ;no, so no whole byte
553: or ecx,TRAILING_BYTE ;yes, there's a trailing byte
554: @@:
555:
556: ;finally, calculate the number of whole
557: ; aligned words and pairs thereof we'll
558: ; process
559: mov eax,[esi].xLeft
560: add eax,1111b
561: shr eax,4 ;round left up to nearest word
562: mov edx,[esi].xRight
563: shr edx,4 ;round down to nearest word
564: sub edx,eax ;# of whole aligned words
565: jz short set_copy_control_flags ;no whole aligned words
566: or ecx,WHOLE_WORDS ;mark that we have whole aligned words
567: inc edx
568: shr edx,1 ;# of whole dwords, or fractions
569: mov ulWholeDwordCount,edx ; thereof
570: jc short set_copy_control_flags ;no odd word
571: or ecx,ODD_WHOLE_WORD ;mark that we have an odd word to copy
572:
573: set_copy_control_flags:
574: mov ulCopyControlFlags,ecx
575:
576: ;-----------------------------------------------------------------------;
577: ; If we're going to have to read from display memory, set up the Graphics
578: ; Controller to point to the Read Map, so we can save some OUTs later.
579: ;
580: ; At this point, EBX = pptlSrc, ECX = ulCopyControlFlags, ESI = prclDst,
581: ; EDI = pdsurfDst.
582: ;-----------------------------------------------------------------------;
583:
584: test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
585: jz short @F
586: mov edx,VGA_BASE + GRAF_ADDR
587: mov al,GRAF_READ_MAP
588: out dx,al ;leave GRAF_ADDR pointing to Read Map
589: @@:
590:
591: ;-----------------------------------------------------------------------;
592: ; Set up the offsets to the next source and destination scans.
593: ;
594: ; At this point, EBX = pptlSrc, ESI = prclDst, EDI = pdsurfDst.
595: ;-----------------------------------------------------------------------;
596:
597: mov eax,[esi].xLeft
598: shr eax,3 ;left edge byte
599: mov edx,[esi].xRight
600: add edx,111b ;byte after right edge
601: shr edx,3
602: sub edx,eax ;# of bytes across dest
603: mov eax,[edi].dsurf_lNextScan
604: sub eax,edx ;offset from last byte dest copied to on one
605: mov ulDstDelta,eax ; scan to first dest byte copied to on next
606:
607: mov ecx,pdsurfSrc
608: mov eax,[esi].xLeft
609: mov edx,[esi].xRight
610: sub edx,eax ;width in pixels
611: push edx ;remember width in pixels
612: mov eax,[ebx].ptl_x ;source left edge
613: add edx,eax ;source right edge
614: shr eax,1 ;source left start byte
615: and eax,not 11b ;source left start rounded to nearest dword
616: inc edx
617: shr edx,1 ;source right byte after last byte copied
618: add edx,11b
619: and edx,not 11b ;round up to source right dword after last byte
620: ; copied
621: sub edx,eax ;source width in bytes, rounded to dwords
622: ; (because we always work with source dwords)
623: mov eax,[ecx].dsurf_lNextScan
624: sub eax,edx ;offset from last source byte copied from on
625: mov ulSrcDelta,eax ; one scan to first source byte copied to on
626: ; next
627:
628: ;-----------------------------------------------------------------------;
629: ; Set up the maximum burst size (# of scans to do before switching
630: ; planes).
631: ;
632: ; At this point, EBX = pptlSrc, ESI = prclDst, EDI = pdsurfDst.
633: ;-----------------------------------------------------------------------;
634:
635: pop edx ;retrieve width in pixels
636: mov eax,2 ;assume we'll only do two scans per burst
637: ; (the minimum number)
638: test edx,not 0feh ;>511 pixels?
639: jnz short @F ;yes, so do two scans at a time, to avoid
640: ; flicker as separate planes are done
641: ;***note: this is a tentative value, and
642: ; experience may indicate that it should be
643: ; increased or reduced to 1***
644: ;<512 pixels, so we can do more scans per
645: ; plane, thereby saving lots of OUTs. The exact
646: ; # of scans depends on how wide the copy is;
647: ; the wider it is, the fewer scans
648: mov al,4 ;assume we'll do four scans per plane
649: test dh,1 ;256 or more wide?
650: jnz short @F ;512>width>=256, four scans will do the job
651: mov al,8 ;assume we'll do eight scans per plane
652: add dl,dl ;128 or more wide?
653: jc short @F ;256>width>=128, eight scans is fine
654: mov al,16 ;assume we'll do sixteen scans per plane
655: js short @F ;128>width>=64, sixteen will do fine
656: mov al,32 ;<64 wide, so we'll do 32 scans per plane
657: @@:
658: mov ulBurstMax,eax ;this is the longest burst we'll do in a single
659: ; plane
660:
661: ;-----------------------------------------------------------------------;
662: ; Determine whether any shift is needed to align the source with the
663: ; destination.
664: ;
665: ; At this point, EBX = pptlSrc, ESI = prclDst, EDI = pdsurfDst.
666: ;-----------------------------------------------------------------------;
667:
668: mov eax,[ebx].ptl_x
669: and eax,111b ;source X modulo 8
670: mov edx,[esi].xLeft
671: and edx,111b ;dest X modulo 8
672: sub eax,edx ;(source X modulo 8) - (dest X modulo 8)
673: mov ulAlignShift,eax ;remember the shift
674: jz short set_initial_banking ;if it's 0, we have no alignment to
675: ; do, and are ready to roll
676:
677: ;-----------------------------------------------------------------------;
678: ; Alignment is needed, so set up the alignment variables.
679: ;
680: ; At this point, EBX = pptlSrc, ESI = prclDst, EDI = pdsurfDst,
681: ; EAX = shift, in range -7 to 7.
682: ;-----------------------------------------------------------------------;
683:
684: mov edx,ulSrcDelta ;remember the real source width; we'll fake
685: mov ulTrueSrcDelta,edx ; ulSrcDelta for the drawing routines
686:
687: ;set ulSrcDelta to either 0 or 4,
688: ; depending on whether the last dword
689: ; we rotate is needed (because we
690: ; always generate as many dest dwords as
691: ; there are source dwords on left shifts,
692: ; and we always generate dest dwords = # source
693: ; dwords + 1 on right shifts, whether we need
694: ; the last dword or not; we only need it when
695: ; the right edge shifts left)
696: mov ecx,[esi].xRight
697: sub ecx,[esi].xLeft
698: add ecx,[ebx].ptl_x ;CL = lsb of source right edge
699: dec ecx ;adjust to actual right X, rather than X+1
700: mov ch,byte ptr [esi].xRight ;CH = lsb of dest right edge
701: dec ch ;adjust to actual right X, rather than X+1
702: and ecx,0707h ;right source and dest intrabyte addresses
703: sub edx,edx ;assume we need the last byte, in which case
704: ; the source in the temp buffer (from which we
705: ; always copy after rotation) is contiguous
706: cmp ch,cl ;right or left shift at right edge?
707: jb short @F ;left shift at right edge, so every byte in the
708: ; temp buffer will be used
709: add edx,4 ;right shift at right edge, so the last byte in
710: ; the temp buffer won't be used, thus skip it
711: @@:
712: mov ulSrcDelta,edx ;delta to next scan in temp buffer
713:
714: mov ecx,[edi].dsurf_ppdev ;point to pdev for 386 flag
715: and eax,eax ;shift left or right?
716: js short @F ;shift right
717: ;shift left
718:
719: mov edx,offset align_burst_lshift_486 ;shifting left, assume 486
720: cmp [ecx].PDEV_is386,0 ;486?
721: jz short set_shift_vec ;yes
722: mov edx,offset align_burst_lshift_386 ;386
723: jmp short set_shift_vec
724:
725: align 4
726: @@: ;shifting right
727:
728: and eax,7 ;for left shift, shift value is already
729: ; correct; for right shift, this is equivalent
730: ; to 8 - right shift, since we always shift
731: ; left (remember, EAX is currently negative for
732: ; right shifts)
733: mov edx,offset align_burst_rshift_386 ;shifting right, assume 386
734: cmp [ecx].PDEV_is386,0 ;386?
735: jnz short set_shift_vec ;yes
736: mov edx,offset align_burst_rshift_486 ;486
737: set_shift_vec:
738: mov pAlignmentRoutine,edx ;routine to be used to shift into
739: ; alignment with destination
740: shl eax,2 ;multiply by 4 because we're dealing with
741: ; 4-bit pixels
742: mov ulAlignShift,eax ;remember the shift amount
743: mov eax,[esi].xRight
744: sub eax,[esi].xLeft ;pixel width of rectangle to copy
745: mov edx,[ebx].ptl_x ;left pixel of source
746: and edx,111b ;distance in pixels from left pixel to pixel at
747: ; start of left dword
748: add eax,edx ;pixel width from start of left dword to right
749: ; edge of copy in source
750: add eax,7 ;round up to nearest dword (8 pixel set)
751: shr eax,3 ;# of dwords spanned by source
752: mov ulSourceDwordWidth,eax ;always pick up this number of dwords
753: ; when aligning
754:
755: mov eax,[edi].dsurf_pvBankBufferPlane0 ;this is the general-purpose
756: mov pTempBuffer,eax ; temporary-use buffer
757:
758: mov eax,pSrc ;remember the real source pointer; we'll fake
759: mov pTrueSrc,eax ; pSrc for the drawing routines
760:
761: ;-----------------------------------------------------------------------;
762: ; Copy all banks in the destination rectangle, one at a time.
763: ;
764: ; At this point, ESI = prclDst, EDI = pdsurfDst
765: ;-----------------------------------------------------------------------;
766:
767: set_initial_banking:
768:
769: ;-----------------------------------------------------------------------;
770: ; Map in the bank containing the top scan to copy to, if it's not mapped
771: ; in already.
772: ;-----------------------------------------------------------------------;
773:
774: mov eax,[esi].yBottom
775: mov ulBottomScan,eax ;bottom scan to which to copy
776: mov eax,[esi].yTop ;top scan line of copy
777: mov ulCurrentTopScan,eax ;this will be the copy top in 1st bank
778:
779: cmp eax,[edi].dsurf_rcl1WindowClip.yTop ;is copy top less than
780: ; current bank?
781: jl short map_init_bank ;yes, map in proper bank
782: cmp eax,[edi].dsurf_rcl1WindowClip.yBottom ;copy top greater than
783: ; current bank?
784: jl short init_bank_mapped ;no, proper bank already mapped
785: map_init_bank:
786:
787: ; Map in the bank containing the top scan line of the copy dest.
788:
789: ptrCall <dword ptr [edi].dsurf_pfnBankControl>,<edi,eax,JustifyTop>
790:
791: init_bank_mapped:
792:
793: ;-----------------------------------------------------------------------;
794: ; Compute the starting address for the initial dest bank.
795: ;-----------------------------------------------------------------------;
796:
797: mov eax,ulCurrentTopScan ;top scan line to which to copy in
798: ; current bank
799: imul [edi].dsurf_lNextScan ;offset of starting scan line
800: mov edx,[esi].xLeft ;left dest X coordinate
801: shr edx,3 ;left dest byte offset in row
802: add eax,edx ;initial offset in dest bitmap
803:
804: ; Note that the start of the bitmap will change each time through the
805: ; bank loop, because the start of the bitmap is varied to map the
806: ; desired scan line to the banking window.
807:
808: add eax,[edi].dsurf_pvBitmapStart ;initial dest bitmap address
809: mov pDst,eax ;remember where to start drawing
810:
811: ;-----------------------------------------------------------------------;
812: ; Main loop for processing copying to each bank.
813: ;
814: ; At this point, EDI->pdsurfDst
815: ;-----------------------------------------------------------------------;
816:
817: bank_loop:
818:
819: ; Calculate the # of scans to do in this bank.
820:
821: mov ebx,ulBottomScan ;bottom of destination rectangle
822: cmp ebx,[edi].dsurf_rcl1WindowClip.yBottom
823: ;which comes first, the bottom of the
824: ; dest rect or the bottom of the
825: ; current bank?
826: jl short @F ;copy bottom comes first, so draw to
827: ; that; this is the last bank in copy
828: mov ebx,[edi].dsurf_rcl1WindowClip.yBottom
829: ;bank bottom comes first; draw to
830: ; bottom of bank
831: @@:
832: sub ebx,ulCurrentTopScan ;# of scans to copy in bank
833:
834: ;-----------------------------------------------------------------------;
835: ; Copy to the screen in bursts of either ulBurstMax size or remaining
836: ; number of scans in bank, whichever is less.
837: ;
838: ; At this point, EBX = # of scans remaining in bank.
839: ;-----------------------------------------------------------------------;
840:
841: copy_burst_loop:
842: mov eax,ulBurstMax ;most scans we can copy per plane
843: sub ebx,eax ;# of scans left in bank after copying that many
844: jnle short @F ;there are enough scans left to copy max #
845: add eax,ebx ;not enough scans left; copy all remaining scans
846: sub ebx,ebx ;after this, no scans remain in bank
847: @@:
848: push ebx ;# of scan lines remaining in bank after burst
849: ;EAX = # of scans in burst
850: mov ulPlane0Scans,eax ;set the scan count for each of the plane
851: mov ulPlane1Scans,eax ; loops
852: mov ulPlane2Scans,eax
853: mov ulPlane3Scans,eax
854:
855: ;-----------------------------------------------------------------------;
856: ; If necessary, align the dwords in this burst so that the left edge is
857: ; on a dword boundary.
858: ;
859: ; At this point, AL = # of scans in burst.
860: ;-----------------------------------------------------------------------;
861:
862: mov ecx,ulAlignShift
863: and ecx,ecx ;is alignment needed?
864: jz proceed_with_copy ;no, so we're ready to copy
865:
866: mov ch,al ;# of scans to copy
867: mov esi,pTrueSrc ;copy from current source location
868: mov edi,pTempBuffer ;copy to the temp buffer
869:
870: jmp pAlignmentRoutine ;perform the copy
871:
872: ;-----------------------------------------------------------------------;
873: ; Loops to align this burst's scans for 386/486, left or right shift.
874: ;
875: ; Input: CH = # of scans to copy in this burst (max burst = 256)
876: ; CL = # of bits to shift left to dword align
877: ; ESI = first dword of first DIB scan to convert
878: ; EDI = first dword of buffer into which to shift
879: ; ulSourceDwordWidth = # of dwords across source
880: ; ulTrueSrcDelta = distance from end of one source scan (rounded up to
881: ; nearest dword) to start of next
882: ;
883: ; All loops alway flush (write) the last dword, so one more dword
884: ; is written to the dest than is read from the source. This requires the
885: ; dest buffer to have room for an extra dword.
886: ;-----------------------------------------------------------------------;
887:
888: ;-----------------------------------------------------------------------;
889: ; Macro to copy and align the current burst for left shift.
890: ;-----------------------------------------------------------------------;
891:
892: ALIGN_BURST_LSHIFT macro Is486
893: local align_burst_lshift_loop,align_last_lshift,align_odd_lshift
894: local align_lshift_loop
895: align_burst_lshift_loop:
896: mov ebx,ulSourceDwordWidth ;# of dwords across source
897: mov edx,[esi] ;load the initial source dword
898: add esi,4 ;point to next source dword
899: if Is486
900: M_BSWAP edx ;make it big endian
901: else
902: M_BSWAP_386 edx
903: endif
904: dec ebx ;any more dwords to shift?
905: jz short align_last_lshift ;no, do just this one
906: inc ebx
907: shr ebx,1 ;double dword count
908: jnc short align_odd_lshift ;do odd dword
909: align 4
910: align_lshift_loop:
911: mov eax,[esi] ;get next dword to align
912: add esi,4 ;point to next source dword
913: if Is486
914: M_BSWAP eax ;make it big endian
915: else
916: M_BSWAP_386 eax
917: endif
918: shld edx,eax,cl ;shift to generate a 32-bit shifted value
919: if Is486
920: M_BSWAP edx ;make it big endian
921: else
922: M_BSWAP_386 edx
923: endif
924: mov [edi],edx ;store it
925: add edi,4 ;point to next dest dword
926: mov edx,eax ;set up for the next shift
927: align_odd_lshift:
928: mov eax,[esi] ;get next dword to align
929: add esi,4 ;point to next source dword
930: if Is486
931: M_BSWAP eax ;make it big endian
932: else
933: M_BSWAP_386 eax
934: endif
935: shld edx,eax,cl ;shift to generate a 32-bit shifted value
936: if Is486
937: M_BSWAP edx ;make it big endian
938: else
939: M_BSWAP_386 edx
940: endif
941: mov [edi],edx ;store it
942: add edi,4 ;point to next dest dword
943: mov edx,eax ;set up for the next shift
944: dec ebx ;count down dwords to shift
945: jnz align_lshift_loop ;do next dword, if any
946: align_last_lshift: ;do the last dword, which doesn't require a
947: ; new source byte
948: shl edx,cl ;shift it into position
949: if Is486
950: M_BSWAP edx ;make it big endian
951: else
952: M_BSWAP_386 edx
953: endif
954: mov [edi],edx ;store it
955: add edi,4 ;point to next dest dword
956:
957: add esi,ulTrueSrcDelta ;point to next source scan
958: dec ch ;count down scans in burst
959: jnz align_burst_lshift_loop
960: ENDM ;ALIGN_BURST_LSHIFT
961:
962: ;-----------------------------------------------------------------------;
963: ; Macro to copy and align the current burst for right shift.
964: ;-----------------------------------------------------------------------;
965:
966: ALIGN_BURST_RSHIFT macro Is486
967: local align_burst_rshift_loop,align_odd_rshift,align_rshift_loop
968: align_burst_rshift_loop:
969: mov ebx,ulSourceDwordWidth ;# of dwords across source
970: inc ebx
971: shr ebx,1 ;double dword count
972: jnc short align_odd_rshift ;do odd dword
973: align 4
974: align_rshift_loop:
975: mov eax,[esi] ;get next dword to align
976: add esi,4 ;point to next source dword
977: if Is486
978: M_BSWAP eax ;make it big endian
979: else
980: M_BSWAP_386 eax
981: endif
982: shld edx,eax,cl ;shift to generate a 32-bit shifted value
983: if Is486
984: M_BSWAP edx ;make it little endian
985: else
986: M_BSWAP_386 edx
987: endif
988: mov [edi],edx ;store it
989: add edi,4 ;point to next dest dword
990: mov edx,eax ;set up for the next shift
991: align_odd_rshift:
992: mov eax,[esi] ;get next dword to align
993: add esi,4 ;point to next source dword
994: if Is486
995: M_BSWAP eax ;make it big endian
996: else
997: M_BSWAP_386 eax
998: endif
999: shld edx,eax,cl ;shift to generate a 32-bit shifted value
1000: if Is486
1001: M_BSWAP edx ;make it little endian
1002: else
1003: M_BSWAP_386 edx
1004: endif
1005: mov [edi],edx ;store it
1006: add edi,4 ;point to next dest dword
1007: mov edx,eax ;set up for the next shift
1008: dec ebx ;count down dwords to shift
1009: jnz align_rshift_loop ;do next dword, if any
1010:
1011: ;do the trailing destination dword
1012: shl edx,cl ;shift into position
1013: if Is486
1014: M_BSWAP edx ;make it little endian
1015: else
1016: M_BSWAP_386 edx
1017: endif
1018: mov [edi],edx ;store it
1019: add edi,4 ;point to next dest dword
1020:
1021: add esi,ulTrueSrcDelta ;point to next source scan
1022: dec ch ;count down scans in burst
1023: jnz align_burst_rshift_loop
1024: ENDM ;ALIGN_BURST_RSHIFT
1025: ;-----------------------------------------------------------------------;
1026:
1027: align 4
1028: align_burst_rshift_386:
1029: ALIGN_BURST_RSHIFT 0
1030: jmp set_alignment_source
1031:
1032: align 4
1033: align_burst_lshift_386:
1034: ALIGN_BURST_LSHIFT 0
1035: jmp set_alignment_source
1036:
1037: align 4
1038: align_burst_rshift_486:
1039: ALIGN_BURST_RSHIFT 1
1040: jmp short set_alignment_source
1041:
1042: align 4
1043: align_burst_lshift_486:
1044: ALIGN_BURST_LSHIFT 1
1045:
1046: ;-----------------------------------------------------------------------;
1047: ; Set up the pointers for a copy from the temp buffer, and advance the
1048: ; real pointer.
1049: ;-----------------------------------------------------------------------;
1050: set_alignment_source:
1051: mov pTrueSrc,esi ;remember where to start next time in source
1052: mov esi,pTempBuffer ;copy from the temp buffer
1053: mov pSrc,esi ;remember where the copy source is (DIB or
1054: ; temp buffer)
1055:
1056: proceed_with_copy:
1057:
1058: ; Load ECX with the copy control flags; this stays set throughout the
1059: ; copying of this burst.
1060:
1061: mov ecx,ulCopyControlFlags
1062:
1063: ; Copy the DIB scan to VGA plane 0.
1064:
1065: mov esi,pSrc
1066: mov edi,pDst
1067:
1068: ; Map in plane 0 for writes.
1069:
1070: mov edx,VGA_BASE + SEQ_DATA
1071: mov al,MM_C0
1072: out dx,al ;map in plane 0 for writes (SEQ_ADDR points to the Map
1073: ; Mask by default)
1074:
1075: ; Map in plane 0 for reads if and only if we need to handle partial edge
1076: ; bytes, which require read/modify/write cycles.
1077:
1078: test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
1079: jz short @F
1080: mov edx,VGA_BASE + GRAF_DATA
1081: mov al,RM_C0
1082: out dx,al ;map in plane 0 for reads (GRAF_ADDR already points to
1083: ; Read Map)
1084: @@:
1085: jmp DIB4_to_VGA_plane0_copy
1086:
1087: align 4
1088: copy_burst_plane0_done:
1089:
1090: ; Copy the DIB scan to VGA plane 1.
1091:
1092: mov esi,pSrc
1093: mov edi,pDst
1094:
1095: ; Map in plane 1 for writes.
1096:
1097: mov edx,VGA_BASE + SEQ_DATA
1098: mov al,MM_C1
1099: out dx,al ;map in plane 1 for writes (SEQ_ADDR points to the Map
1100: ; Mask by default)
1101:
1102: ; Map in plane 1 for reads if and only if we need to handle partial edge
1103: ; bytes, which require read/modify/write cycles.
1104:
1105: test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
1106: jz short @F
1107: mov edx,VGA_BASE + GRAF_DATA
1108: mov al,RM_C1
1109: out dx,al ;map in plane 1 for reads (GRAF_ADDR already points to
1110: ; Read Map)
1111: @@:
1112: jmp DIB4_to_VGA_plane1_copy
1113:
1114: align 4
1115: copy_burst_plane1_done:
1116:
1117: ; Copy the DIB scan to VGA plane 2.
1118:
1119: mov esi,pSrc
1120: mov edi,pDst
1121:
1122: ; Map in plane 2 for writes.
1123:
1124: mov edx,VGA_BASE + SEQ_DATA
1125: mov al,MM_C2
1126: out dx,al ;map in plane 2 for writes (SEQ_ADDR points to the Map
1127: ; Mask by default)
1128:
1129: ; Map in plane 2 for reads if and only if we need to handle partial edge
1130: ; bytes, which require read/modify/write cycles.
1131:
1132: test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
1133: jz short @F
1134: mov edx,VGA_BASE + GRAF_DATA
1135: mov al,RM_C2
1136: out dx,al ;map in plane 2 for reads (GRAF_ADDR already points to
1137: ; Read Map)
1138: @@:
1139: jmp DIB4_to_VGA_plane2_copy
1140:
1141: align 4
1142: copy_burst_plane2_done:
1143:
1144: ; Copy the DIB scan to VGA plane 3.
1145:
1146: mov esi,pSrc
1147: mov edi,pDst
1148:
1149: ; Map in plane 3 for writes.
1150:
1151: mov edx,VGA_BASE + SEQ_DATA
1152: mov al,MM_C3
1153: out dx,al ;map in plane 3 for writes (SEQ_ADDR points to the Map
1154: ; Mask by default)
1155:
1156: ; Map in plane 3 for reads if and only if we need to handle partial edge
1157: ; bytes, which require read/modify/write cycles.
1158:
1159: test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
1160: jz short @F
1161: mov edx,VGA_BASE + GRAF_DATA
1162: mov al,RM_C3
1163: out dx,al ;map in plane 3 for reads (GRAF_ADDR already points to
1164: ; Read Map)
1165: @@:
1166: jmp DIB4_to_VGA_plane3_copy
1167:
1168: align 4
1169: copy_burst_plane3_done:
1170: mov pSrc,esi ;remember where we are, for next burst
1171: mov pDst,edi
1172:
1173: pop ebx ;get back remaining length in bank
1174: and ebx,ebx ;anything left in this bank?
1175: jnz copy_burst_loop ;continue if so
1176:
1177: ; Done with bank; are there more banks to do?
1178:
1179: mov edi,pdsurfDst
1180: mov eax,[edi].dsurf_rcl1WindowClip.yBottom ;is the copy bottom in
1181: cmp ulBottomScan,eax ; the current bank?
1182: jnle short next_bank ;no, map in the next bank and copy to
1183: ; it
1184: ;yes, we're done
1185: ;-----------------------------------------------------------------------;
1186: ; Restore default Map Mask and done.
1187: ;-----------------------------------------------------------------------;
1188: mov edx,VGA_BASE + SEQ_DATA
1189: mov al,MM_ALL
1190: out dx,al ;map in all planes
1191:
1192: cRet vDIB2VGA ;done!
1193:
1194: ;-----------------------------------------------------------------------;
1195: ; Advance to the next bank and copy to it.
1196: ;-----------------------------------------------------------------------;
1197: align 4
1198: next_bank:
1199: mov ulCurrentTopScan,eax ;remember where the top of the bank
1200: ; we're about to map in is (same as
1201: ; bottom of bank we just did)
1202: mov ecx,[edi].dsurf_pvBitmapStart
1203: sub pDst,ecx ;offset of current position in screen
1204:
1205: ptrCall <dword ptr [edi].dsurf_pfnBankControl>,<edi,eax,JustifyTop>
1206: ;map in the bank
1207:
1208: mov ecx,[edi].dsurf_pvBitmapStart
1209: add pDst,ecx ;pointer to current position in screen
1210:
1211: jmp bank_loop ;copy the next bank
1212:
1213: ;-----------------------------------------------------------------------;
1214: ; Loops for converting 1 or more scans in each of planes 0, 1, 2, and 3.
1215: ;-----------------------------------------------------------------------;
1216:
1217: ;-----------------------------------------------------------------------;
1218: ; Plane 0 DIB->VGA conversion code for a single scan line.
1219: ;-----------------------------------------------------------------------;
1220: align 4
1221: DIB4_to_VGA_plane0_copy:
1222:
1223: ;-----------------------------------------------------------------------;
1224: ; Set EBX to point to multiplexed DIB byte->planar byte conversion table
1225: ; for plane 0.
1226: ;
1227: ; Input: ECX with bits sets as described for ulCopyControlFlags, above
1228: ; ESI = DIB pointer to first two pixels
1229: ; EDI = VGA pointer to planar byte
1230: ; ulPlane0Scans = # of scan lines to copy to
1231: ; ulSrcDelta = offset from end of one source scan copied to start of next
1232: ; ulDstDelta = offset from end of one dest scan copied to start of next
1233: ; ulWholeDwordCount = # of whole, aligned dwords to copy
1234: ; ulLeftMask = mask for partial left edge, if any
1235: ; ulRightMask = mask for partial right edge, if any
1236: ; Plane 0 must be mapped in for writes
1237: ;-----------------------------------------------------------------------;
1238:
1239: mov ebx,DIB4_to_VGA_plane0_table ;stays set for all bytes/words
1240:
1241: DIB4_to_VGA_plane0_copy_loop:
1242:
1243: ;-----------------------------------------------------------------------;
1244: ; Code to convert 1-7 DIB4 pixels to a partial VGA plane 0 byte (8
1245: ; pixels in plane 0). Assumes that a full dword of DIB4 pixels (8
1246: ; pixels) is available, starting at ESI, although some of the pixels
1247: ; will be masked off. Assumes the DIB4 pixels (including masked-off
1248: ; pixels) start in the upper nibble of [ESI], and that the first
1249: ; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
1250: ;
1251: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1252: ; (must start on a 256-byte boundary)
1253: ; ECX with bits sets as described for ulCopyControlFlags, above
1254: ; ESI = DIB pointer to first two pixels (possibly masked off)
1255: ; EDI = VGA pointer to planar byte
1256: ; Plane 0 must be mapped in for writes
1257: ;-----------------------------------------------------------------------;
1258:
1259: test ecx,LEADING_PARTIAL ;handle a leading partial byte?
1260: jz short DIB4_to_VGA_plane0_copy_lbyte ;no, go straight to whole
1261: ; byte
1262: ;yes, handle leading partial byte
1263: mov edx,[esi] ;get 8 pixels to convert of DIB
1264: and edx,11111111h ;keep only the plane 0 bits of DIB dword
1265: ; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
1266: shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
1267: ; shifted left 2 (x = zero bit)
1268: ; DX = xxx2xxx3xxx0xxx1
1269: ; AX = x6xxx7xxx4xxx5xx
1270: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1271: ; x6x2x7x3x4x0x5x1
1272: mov bl,al ;BL = x4x0x5x1 of DIB dword 0
1273: add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
1274: or bl,ah ;BL = 64207531 of DIB dword 0
1275: add esi,4 ;point to next DIB dword
1276: inc edi ;point to next VGA byte (placed here
1277: ; for 486 pipelining reasons)
1278: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1279: mov ch,[edi-1] ;get the VGA destination byte
1280: and ecx,ulLeftMask ;mask off source and dest
1281: or cl,ch ;combine masked source and dest
1282: mov [edi-1],cl ;write the new pixels to the VGA
1283:
1284: ;-----------------------------------------------------------------------;
1285: ; Code to convert 8 DIB4 pixels to a single VGA plane 0 byte (8 pixels
1286: ; in plane 0). Assumes the DIB4 pixels start in the upper nibble of
1287: ; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
1288: ; [EDI].
1289: ;
1290: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1291: ; (must start on a 256-byte boundary)
1292: ; ECX with bits sets as described for ulCopyControlFlags, above
1293: ; ESI = DIB pointer to first two pixels
1294: ; EDI = VGA pointer to planar byte
1295: ; Plane 0 must be mapped in for writes
1296: ;-----------------------------------------------------------------------;
1297:
1298: DIB4_to_VGA_plane0_copy_lbyte:
1299: test ecx,LEADING_BYTE ;should we handle a leading byte?
1300: jz short DIB4_to_VGA_plane0_copy_words ;no, go straight to words
1301: ;yes, handle leading byte
1302: mov edx,[esi] ;get 8 pixels to convert of DIB
1303: and edx,11111111h ;keep only the plane 0 bits of DIB dword
1304: ; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
1305: shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
1306: ; shifted left 2 (x = zero bit)
1307: ; DX = xxx2xxx3xxx0xxx1
1308: ; AX = x6xxx7xxx4xxx5xx
1309: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1310: ; x6x2x7x3x4x0x5x1
1311: mov bl,al ;BL = x4x0x5x1 of DIB dword 0
1312: add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
1313: or bl,ah ;BL = 64207531 of DIB dword 0
1314: add esi,4 ;point to next DIB dword
1315: inc edi ;point to next VGA byte (placed here
1316: ; for 486 pipelining reasons)
1317: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1318: mov [edi-1],cl ;write 8 bits from DIB dword to VGA
1319:
1320: ;-----------------------------------------------------------------------;
1321: ; Code to convert sets of 32 DIB4 pixels to 4 VGA plane 0 bytes (32
1322: ; pixels in plane 0). Assumes the VGA destination is word aligned.
1323: ; Assumes the DIB4 pixels start in the upper nibble of [ESI], and that
1324: ; the first DIB4 pixel maps to bit 7 of the VGA at [EDI].
1325: ;
1326: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1327: ; (must start on a 256-byte boundary)
1328: ; ECX with bits sets as described for ulCopyControlFlags, above
1329: ; ESI = DIB pointer to first two pixels
1330: ; EDI = VGA pointer to two planar bytes (must be word aligned)
1331: ; ulWholeDwordCount = # of VGA dwords to convert
1332: ; Plane 0 must be mapped in for writes
1333: ;
1334: ; Note: on entry at DIB4_to_VGA_plane0_word_odd, ESI must point to the
1335: ; desired source start minus 8, and EAX must be loaded as if the following
1336: ; instructions had been performed:
1337: ; mov edx,[esi+8]
1338: ; and edx,11111111h
1339: ; shld eax,edx,16+2
1340: ; or eax,edx
1341: ;
1342: ; Note: the code is so odd because of 486 pipeline optimization.
1343: ; DO NOT CHANGE THIS CODE UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!!!
1344: ;
1345: ; Note: all 486 pipeline penalties are eliminated except for SHLD, which
1346: ; is losing 4 cycles total, and writing CX to memory (2 cycles), so far
1347: ; as I know.
1348: ;-----------------------------------------------------------------------;
1349:
1350: DIB4_to_VGA_plane0_copy_words:
1351: test ecx,ODD_WHOLE_WORD or WHOLE_WORDS ;any whole words to copy?
1352: jz DIB4_to_VGA_plane0_copy_tbyte ;no, check for trailing whole
1353: ; bytes
1354: ;yes, copy the whole words
1355: push ebp ;preserve stack frame pointer
1356: mov ebp,ulWholeDwordCount ;# of VGA dwords to copy to
1357: ;even # of DIB dwords to copy? (flags still
1358: ; set from TEST)
1359: .errnz ODD_WHOLE_WORD - 80000000h
1360: jns short DIB4_to_VGA_plane0_word_loop ;yes, start copying
1361: ;no, there's an odd word; prepare to enter loop
1362: ; in middle
1363: mov edx,[esi] ;get 8 pixels to convert of first DIB dword
1364: and edx,11111111h ;keep only the plane 0 bits of DIB dword
1365: ; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
1366: shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
1367: ; shifted left 2
1368: ; DX = xxx2xxx3xxx0xxx1
1369: ; AX = x6xxx7xxx4xxx5xx
1370: or eax,edx ;put bits 7-0 of DIB dword in AX:
1371: sub esi,8 ;compensate source back for entering in middle
1372: sub edi,2 ;compensate dest back for entering in middle
1373:
1374: jmp short DIB4_to_VGA_plane0_word_odd
1375:
1376: ;-----------------------------------------------------------------------;
1377: ; Loop to copy a word at a time to VGA plane 0 (actually, unrolled once
1378: ; so copies dwords).
1379: ;-----------------------------------------------------------------------;
1380:
1381: align 16
1382: DIB4_to_VGA_plane0_word_loop:
1383: mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
1384: and edx,11111111h ;keep only the plane 0 bits of DIB
1385: ; dword 0
1386: ; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
1387: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
1388: ; shifted left 2 (x = zero bit)
1389: ; DX = xxx2xxx3xxx0xxx1
1390: ; AX = x6xxx7xxx4xxx5xx
1391: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1392: ; x6x2x7x3x4x0x5x1
1393: mov edx,[esi+4] ;get 8 pixels to convert of DIB dword 1
1394: mov bl,al ;BL = x4x0x5x1 of DIB dword 0
1395: add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
1396: or bl,ah ;BL = 64207531 of DIB dword 0
1397: and edx,11111111h ;keep only the plane 0 bits of DIB
1398: ; dword 1
1399: ; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
1400: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 1 in AX,
1401: ; shifted left 2
1402: ; DX = xxx2xxx3xxx0xxx1
1403: ; AX = x6xxx7xxx4xxx5xx
1404: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1405: or eax,edx ;put bits 7-0 of DIB dword 1 in AX:
1406: ; x6x2x7x3x4x0x5x1
1407: mov bl,al ;BL = x4x0x5x1 of DIB dword 1
1408: mov edx,[esi+8] ;get 8 pixels to convert of DIB dword 2
1409: add ah,ah ;make AH 6x2x7x3x of DIB dword 1 (shl 1)
1410: or bl,ah ;BL = 64207531 of DIB dword 1
1411: and edx,11111111h ;keep only the plane 0 bits of DIB
1412: ; dword 2
1413: ; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
1414: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 2 in AX,
1415: ; shifted left 2
1416: ; DX = xxx2xxx3xxx0xxx1
1417: ; AX = x6xxx7xxx4xxx5xx
1418: mov ch,[ebx] ;CH = 76543210 of DIB dword 1
1419: or eax,edx ;put bits 7-0 of DIB dword 2 in AX:
1420: ; x6x2x7x3x4x0x5x1
1421: mov [edi],cx ;write 16 bits from DIB dwords 0 and 1
1422: ; to VGA
1423: DIB4_to_VGA_plane0_word_odd:
1424: mov edx,[esi+12] ;get 8 pixels to convert of DIB dword 3
1425: mov bl,al ;BL = x4x0x5x1 of DIB dword 2
1426: add ah,ah ;make AH 6x2x7x3x of DIB dword 2 (shl 1)
1427: or bl,ah ;BL = 64207531 of DIB dword 2
1428: and edx,11111111h ;keep only the plane 0 bits of DIB
1429: ; dword 3
1430: ; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
1431: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 3 in AX,
1432: ; shifted left 2
1433: ; DX = xxx2xxx3xxx0xxx1
1434: ; AX = x6xxx7xxx4xxx5xx
1435: mov cl,[ebx] ;CL = 76543210 of DIB dword 2
1436: or eax,edx ;put bits 7-0 of DIB dword 3 in AX:
1437: ; x6x2x7x3x4x0x5x1
1438: mov bl,al ;BL = x4x0x5x1 of DIB dword 3
1439: add ah,ah ;make AH 6x2x7x3x of DIB dword 3 (shl 1)
1440: or bl,ah ;BL = 64207531 of DIB dword 3
1441: add esi,16 ;point to next set of 4 DIB dwords
1442: add edi,4 ;point to next VGA dword
1443: mov ch,[ebx] ;CH = 76543210 of dword 0
1444: dec ebp ;count down VGA dwords
1445: mov [edi-2],cx ;write 16 bits from DIB dwords 2 and 3
1446: ; to VGA
1447: jnz DIB4_to_VGA_plane0_word_loop ;do next VGA dword, if any
1448:
1449: pop ebp ;restore stack frame pointer
1450:
1451:
1452: ;-----------------------------------------------------------------------;
1453: ; Code to convert 8 DIB4 pixels to a single VGA plane 0 byte (8 pixels
1454: ; in plane 0). Assumes the DIB4 pixels start in the upper nibble of
1455: ; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
1456: ; [EDI].
1457: ;
1458: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1459: ; (must start on a 256-byte boundary)
1460: ; ECX with bits sets as described for ulCopyControlFlags, above
1461: ; ESI = DIB pointer to first two pixels
1462: ; EDI = VGA pointer to planar byte
1463: ; Plane 0 must be mapped in for writes
1464: ;
1465: ;-----------------------------------------------------------------------;
1466:
1467: DIB4_to_VGA_plane0_copy_tbyte:
1468: test ecx,TRAILING_BYTE ;should we handle a trailing byte?
1469: jz short DIB4_to_VGA_plane0_copy_tpart ;no, check for trailing
1470: ; partial
1471: ;yes, handle trailing byte
1472: mov edx,[esi] ;get 8 pixels to convert of DIB
1473: and edx,11111111h ;keep only the plane 0 bits of DIB dword
1474: ; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
1475: shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
1476: ; shifted left 2 (x = zero bit)
1477: ; DX = xxx2xxx3xxx0xxx1
1478: ; AX = x6xxx7xxx4xxx5xx
1479: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1480: ; x6x2x7x3x4x0x5x1
1481: mov bl,al ;BL = x4x0x5x1 of DIB dword 0
1482: add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
1483: or bl,ah ;BL = 64207531 of DIB dword 0
1484: add esi,4 ;point to next DIB dword
1485: inc edi ;point to next VGA byte (placed here
1486: ; for 486 pipelining reasons)
1487: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1488: mov [edi-1],cl ;write 8 bits from DIB dword to VGA
1489:
1490: ;-----------------------------------------------------------------------;
1491: ; Code to convert 1-7 DIB4 pixels to a partial VGA plane 0 byte (8
1492: ; pixels in plane 0). Assumes that a full dword of DIB4 pixels (8
1493: ; pixels) is available, starting at ESI, although some of the pixels
1494: ; will be masked off. Assumes the DIB4 pixels (including masked-off
1495: ; pixels) start in the upper nibble of [ESI], and that the first
1496: ; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
1497: ;
1498: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1499: ; (must start on a 256-byte boundary)
1500: ; ECX with bits sets as described for ulCopyControlFlags, above
1501: ; ESI = DIB pointer to first two pixels (possibly masked off)
1502: ; EDI = VGA pointer to planar byte
1503: ; Plane 0 must be mapped in for writes
1504: ;-----------------------------------------------------------------------;
1505:
1506: DIB4_to_VGA_plane0_copy_tpart:
1507: test ecx,TRAILING_PARTIAL ;handle a trailing partial byte?
1508: jz short DIB4_to_VGA_plane0_copy_done ;no, done
1509: ;yes, handle trailing partial byte
1510: mov edx,[esi] ;get 8 pixels to convert of DIB
1511: and edx,11111111h ;keep only the plane 0 bits of DIB dword
1512: ; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
1513: shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
1514: ; shifted left 2 (x = zero bit)
1515: ; DX = xxx2xxx3xxx0xxx1
1516: ; AX = x6xxx7xxx4xxx5xx
1517: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1518: ; x6x2x7x3x4x0x5x1
1519: mov bl,al ;BL = x4x0x5x1 of DIB dword 0
1520: add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
1521: or bl,ah ;BL = 64207531 of DIB dword 0
1522: add esi,4 ;point to next DIB dword
1523: inc edi ;point to next VGA byte (placed here
1524: ; for 486 pipelining reasons)
1525: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1526: mov ch,[edi-1] ;get the VGA destination byte
1527: and ecx,ulRightMask ;mask off source and dest
1528: or cl,ch ;combine masked source and dest
1529: mov [edi-1],cl ;write the new pixels to the VGA
1530:
1531: DIB4_to_VGA_plane0_copy_done:
1532: add esi,ulSrcDelta ;point to start of next DIB scan
1533: add edi,ulDstDelta ;point to start of next VGA scan
1534: dec ulPlane0Scans ;count down scans in this plane
1535: jnz DIB4_to_VGA_plane0_copy_loop ;do next scan in this plane, if any
1536:
1537: jmp copy_burst_plane0_done ;return to the top of the plane-copy
1538: ; loop
1539:
1540: ;-----------------------------------------------------------------------;
1541: ; Plane 1 DIB->VGA conversion code for a single scan line.
1542: ;
1543: ; Input: ECX with bits sets as described for ulCopyControlFlags, above
1544: ; bit 30 = 1 if there are whole words to be copied, = 0 if not
1545: ; bit 29 = 1 if leading byte should be copied, = 0 if not
1546: ; bit 28 = 1 if trailing byte should be copied, = 0 if not
1547: ; bit 27 = 1 if partial leading byte should be copied, = 0 if not
1548: ; bit 26 = 1 if partial trailing byte should be copied, = 0 if not
1549: ; ESI = DIB pointer to first two pixels
1550: ; EDI = VGA pointer to planar byte
1551: ; ulPlane1Scans = # of scan lines to copy to
1552: ; ulSrcDelta = offset from end of one source scan copied to start of next
1553: ; ulDstDelta = offset from end of one dest scan copied to start of next
1554: ; ulWholeDwordCount = # of whole, aligned dwords to copy
1555: ; ulLeftMask = mask for partial left edge, if any
1556: ; ulRightMask = mask for partial right edge, if any
1557: ; Plane 1 must be mapped in for writes
1558: ;-----------------------------------------------------------------------;
1559: align 4
1560: DIB4_to_VGA_plane1_copy:
1561:
1562: ;-----------------------------------------------------------------------;
1563: ; Set EBX to point to multiplexed DIB byte->planar byte conversion table
1564: ; for plane 1.
1565: ;-----------------------------------------------------------------------;
1566:
1567: mov ebx,DIB4_to_VGA_plane1_table ;stays set for all bytes/words
1568:
1569: DIB4_to_VGA_plane1_copy_loop:
1570:
1571: ;-----------------------------------------------------------------------;
1572: ; Code to convert 1-7 DIB4 pixels to a partial VGA plane 1 byte (8
1573: ; pixels in plane 1). Assumes that a full dword of DIB4 pixels (8
1574: ; pixels) is available, starting at ESI, although some of the pixels
1575: ; will be masked off. Assumes the DIB4 pixels (including masked-off
1576: ; pixels) start in the upper nibble of [ESI], and that the first
1577: ; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
1578: ;
1579: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1580: ; (must start on a 256-byte boundary)
1581: ; ECX with bits sets as described for ulCopyControlFlags, above
1582: ; ESI = DIB pointer to first two pixels (possibly masked off)
1583: ; EDI = VGA pointer to planar byte
1584: ; plane 1 must be mapped in for writes
1585: ;-----------------------------------------------------------------------;
1586:
1587: test ecx,LEADING_PARTIAL ;handle a leading partial byte?
1588: jz short DIB4_to_VGA_plane1_copy_lbyte ;no, go straight to whole
1589: ; byte
1590: ;yes, handle leading partial byte
1591: mov edx,[esi] ;get 8 pixels to convert of DIB
1592: and edx,22222222h ;keep only the plane 1 bits of DIB
1593: ; dword 0
1594: ; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
1595: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
1596: ; shifted left 2 (x = zero bit)
1597: ; DX = xx2xxx3xxx0xxx1x
1598: ; AX = 6xxx7xxx4xxx5xxx
1599: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1600: ; 6x2x7x3x4x0x5x1x
1601: mov bl,al ;BL = 4x0x5x1x of DIB dword 0
1602: rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
1603: or bl,ah ;BL = 46025713 of DIB dword 0
1604: add esi,4 ;point to next DIB dword
1605: inc edi ;point to next VGA byte (placed here
1606: ; for 486 pipelining reasons)
1607: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1608: mov ch,[edi-1] ;get the VGA destination byte
1609: and ecx,ulLeftMask ;mask off source and dest
1610: or cl,ch ;combine masked source and dest
1611: mov [edi-1],cl ;write the new pixels to the VGA
1612:
1613: ;-----------------------------------------------------------------------;
1614: ; Code to convert 8 DIB4 pixels to a single VGA plane 1 byte (8 pixels
1615: ; in plane 1). Assumes the DIB4 pixels start in the upper nibble of
1616: ; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
1617: ; [EDI].
1618: ;
1619: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1620: ; (must start on a 256-byte boundary)
1621: ; ECX with bits sets as described for ulCopyControlFlags, above
1622: ; ESI = DIB pointer to first two pixels
1623: ; EDI = VGA pointer to planar byte
1624: ; plane 1 must be mapped in for writes
1625: ;-----------------------------------------------------------------------;
1626:
1627: DIB4_to_VGA_plane1_copy_lbyte:
1628: test ecx,LEADING_BYTE ;should we handle a leading byte?
1629: jz short DIB4_to_VGA_plane1_copy_words ;no, go straight to words
1630: ;yes, handle leading byte
1631: mov edx,[esi] ;get 8 pixels to convert of DIB
1632: and edx,22222222h ;keep only the plane 1 bits of DIB
1633: ; dword 0
1634: ; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
1635: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
1636: ; shifted left 2 (x = zero bit)
1637: ; DX = xx2xxx3xxx0xxx1x
1638: ; AX = 6xxx7xxx4xxx5xxx
1639: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1640: ; 6x2x7x3x4x0x5x1x
1641: mov bl,al ;BL = 4x0x5x1x of DIB dword 0
1642: rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
1643: or bl,ah ;BL = 46025713 of DIB dword 0
1644: add esi,4 ;point to next DIB dword
1645: inc edi ;point to next VGA byte (placed here
1646: ; for 486 pipelining reasons)
1647: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1648: mov [edi-1],cl ;write 8 bits from DIB dword to VGA
1649:
1650: ;-----------------------------------------------------------------------;
1651: ; Code for converting sets of 32 DIB4 pixels to 4 VGA plane 1 bytes (32
1652: ; pixels in plane 1). Assumes the VGA destination is word aligned.
1653: ; Assumes the DIB4 pixels start in the upper nibble of [ESI], and that
1654: ; the first DIB4 pixel maps to bit 7 of the VGA at [EDI].
1655: ;
1656: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1657: ; (must start on a 256-byte boundary)
1658: ; ECX with bits sets as described for ulCopyControlFlags, above
1659: ; ESI = DIB pointer to first two pixels
1660: ; EDI = VGA pointer to two planar bytes (must be word aligned)
1661: ; EBP = # of VGA dwords to convert
1662: ; ulWholeDwordCount = # of VGA dwords to convert
1663: ; Plane 1 must be mapped in for writes
1664: ;
1665: ; Note: on entry at DIB4_to_VGA_plane1_word_odd, ESI must point to the
1666: ; desired source start minus 8, and EAX must be loaded as if the following
1667: ; instructions had been performed:
1668: ; mov edx,[esi+8]
1669: ; and edx,22222222h
1670: ; shld eax,edx,16+2
1671: ; or eax,edx
1672: ;
1673: ; Note: ROL AH,7 is used instead of SHR AH,1 because the shift-by-1
1674: ; form is 1 cycle slower on a 486, and in this case the two forms are
1675: ; functionally identical.
1676: ;
1677: ; Note: the code is so odd because of 486 pipeline optimization.
1678: ; DO NOT CHANGE THIS CODE UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!!!
1679: ;
1680: ; Note: all 486 pipeline penalties are eliminated except for SHLD, which
1681: ; is losing 4 cycles total, and writing CX to memory (2 cycles), so far
1682: ; as I know.
1683: ;-----------------------------------------------------------------------;
1684:
1685: DIB4_to_VGA_plane1_copy_words:
1686: test ecx,ODD_WHOLE_WORD or WHOLE_WORDS ;any whole words to copy?
1687: jz DIB4_to_VGA_plane1_copy_tbyte ;no, check for trailing whole
1688: ; bytes
1689: ;yes, copy the whole words
1690: push ebp ;preserve stack frame pointer
1691: mov ebp,ulWholeDwordCount ;# of VGA dwords to copy to
1692: ;even # of DIB dwords to copy? (flags still
1693: ; set from TEST)
1694: .errnz ODD_WHOLE_WORD - 80000000h
1695: jns short DIB4_to_VGA_plane1_word_loop ;yes, start copying
1696: ;no, there's an odd word; prepare to enter loop
1697: ; in middle
1698: mov edx,[esi] ;get 8 pixels to convert of first DIB dword
1699: and edx,22222222h ;keep only the plane 1 bits of DIB dword
1700: ; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
1701: shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
1702: ; shifted left 2
1703: ; DX = xx2xxx3xxx0xxx1x
1704: ; AX = 6xxx7xxx4xxx5xxx
1705: or eax,edx ;put bits 7-0 of DIB dword in AX:
1706: ; 6x2x7x3x4x0x5x1x
1707: sub esi,8 ;compensate source back for entering in middle
1708: sub edi,2 ;compensate dest back for entering in middle
1709:
1710: jmp short DIB4_to_VGA_plane1_word_odd
1711:
1712: ;-----------------------------------------------------------------------;
1713: ; Loop to copy a word at a time to VGA plane 1 (actually, unrolled once
1714: ; so copies dwords).
1715: ;-----------------------------------------------------------------------;
1716:
1717: align 16
1718: DIB4_to_VGA_plane1_word_loop:
1719: mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
1720: and edx,22222222h ;keep only the plane 1 bits of DIB
1721: ; dword 0
1722: ; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
1723: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
1724: ; shifted left 2 (x = zero bit)
1725: ; DX = xx2xxx3xxx0xxx1x
1726: ; AX = 6xxx7xxx4xxx5xxx
1727: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1728: ; 6x2x7x3x4x0x5x1x
1729: mov edx,[esi+4] ;get 8 pixels to convert of DIB dword 1
1730: mov bl,al ;BL = 4x0x5x1x of DIB dword 0
1731: rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
1732: or bl,ah ;BL = 46025713 of DIB dword 0
1733: and edx,22222222h ;keep only the plane 1 bits of DIB
1734: ; dword 1
1735: ; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
1736: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 1 in AX,
1737: ; shifted left 2
1738: ; DX = xx2xxx3xxx0xxx1x
1739: ; AX = 6xxx7xxx4xxx5xxx
1740: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1741: or eax,edx ;put bits 7-0 of DIB dword 1 in AX:
1742: ; 6x2x7x3x4x0x5x1x
1743: mov bl,al ;BL = 4x0x5x1x of DIB dword 1
1744: mov edx,[esi+8] ;get 8 pixels to convert of DIB dword 2
1745: rol ah,7 ;make AH x6x2x7x3 of DIB dword 1 (shr 1)
1746: or bl,ah ;BL = 46025713 of DIB dword 1
1747: and edx,22222222h ;keep only the plane 1 bits of DIB
1748: ; dword 2
1749: ; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
1750: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 2 in AX,
1751: ; shifted left 2
1752: ; DX = xx2xxx3xxx0xxx1x
1753: ; AX = 6xxx7xxx4xxx5xxx
1754: mov ch,[ebx] ;CH = 76543210 of DIB dword 1
1755: or eax,edx ;put bits 7-0 of DIB dword 2 in AX:
1756: ; 6x2x7x3x4x0x5x1x
1757: mov [edi],cx ;write 16 bits from DIB dwords 0 and 1
1758: ; to VGA
1759: DIB4_to_VGA_plane1_word_odd:
1760: mov edx,[esi+12] ;get 8 pixels to convert of DIB dword 3
1761: mov bl,al ;BL = 4x0x5x1x of DIB dword 2
1762: rol ah,7 ;make AH x6x2x7x3 of DIB dword 2 (shr 1)
1763: or bl,ah ;BL = 46025713 of DIB dword 2
1764: and edx,22222222h ;keep only the plane 1 bits of DIB
1765: ; dword 3
1766: ; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
1767: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 3 in AX,
1768: ; shifted left 2
1769: ; DX = xx2xxx3xxx0xxx1x
1770: ; AX = 6xxx7xxx4xxx5xxx
1771: mov cl,[ebx] ;CL = 76543210 of DIB dword 2
1772: or eax,edx ;put bits 7-0 of DIB dword 3 in AX:
1773: ; 6x2x7x3x4x0x5x1x
1774: mov bl,al ;BL = 4x0x5x1x of DIB dword 3
1775: rol ah,7 ;make AH x6x2x7x3 of DIB dword 3 (shr 1)
1776: or bl,ah ;BL = 46025713 of DIB dword 3
1777: add esi,16 ;point to next set of 4 DIB dwords
1778: add edi,4 ;point to next VGA dword
1779: mov ch,[ebx] ;CH = 76543210 of dword 0
1780: dec ebp ;count down VGA dwords
1781: mov [edi-2],cx ;write 16 bits from DIB dwords 2 and 3
1782: ; to VGA
1783: jnz DIB4_to_VGA_plane1_word_loop ;do next VGA dword, if any
1784:
1785: pop ebp ;restore stack frame pointer
1786:
1787: ;-----------------------------------------------------------------------;
1788: ; Code to convert 8 DIB4 pixels to a single VGA plane 1 byte (8 pixels
1789: ; in plane 1). Assumes the DIB4 pixels start in the upper nibble of
1790: ; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
1791: ; [EDI].
1792: ;
1793: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1794: ; (must start on a 256-byte boundary)
1795: ; ECX with bits sets as described for ulCopyControlFlags, above
1796: ; ESI = DIB pointer to first two pixels
1797: ; EDI = VGA pointer to planar byte
1798: ; Plane 1 must be mapped in for writes
1799: ;
1800: ;-----------------------------------------------------------------------;
1801:
1802: DIB4_to_VGA_plane1_copy_tbyte:
1803: test ecx,TRAILING_BYTE ;should we handle a trailing byte?
1804: jz short DIB4_to_VGA_plane1_copy_tpart ;no, check for trailing
1805: ; partial
1806: ;yes, handle trailing byte
1807: mov edx,[esi] ;get 8 pixels to convert of DIB
1808: and edx,22222222h ;keep only the plane 1 bits of DIB
1809: ; dword 0
1810: ; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
1811: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
1812: ; shifted left 2 (x = zero bit)
1813: ; DX = xx2xxx3xxx0xxx1x
1814: ; AX = 6xxx7xxx4xxx5xxx
1815: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1816: ; 6x2x7x3x4x0x5x1x
1817: mov bl,al ;BL = 4x0x5x1x of DIB dword 0
1818: rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
1819: or bl,ah ;BL = 46025713 of DIB dword 0
1820: add esi,4 ;point to next DIB dword
1821: inc edi ;point to next VGA byte (placed here
1822: ; for 486 pipelining reasons)
1823: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1824: mov [edi-1],cl ;write 8 bits from DIB dword to VGA
1825:
1826: ;-----------------------------------------------------------------------;
1827: ; Code to convert 1-7 DIB4 pixels to a partial VGA plane 1 byte (8
1828: ; pixels in plane 1). Assumes that a full dword of DIB4 pixels (8
1829: ; pixels) is available, starting at ESI, although some of the pixels
1830: ; will be masked off. Assumes the DIB4 pixels (including masked-off
1831: ; pixels) start in the upper nibble of [ESI], and that the first
1832: ; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
1833: ;
1834: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1835: ; (must start on a 256-byte boundary)
1836: ; ECX with bits sets as described for ulCopyControlFlags, above
1837: ; ESI = DIB pointer to first two pixels (possibly masked off)
1838: ; EDI = VGA pointer to planar byte
1839: ; plane 1 must be mapped in for writes
1840: ;-----------------------------------------------------------------------;
1841:
1842: DIB4_to_VGA_plane1_copy_tpart:
1843: test ecx,TRAILING_PARTIAL ;handle a trailing partial byte?
1844: jz short DIB4_to_VGA_plane1_copy_done ;no, done
1845: ;yes, handle trailing partial byte
1846: mov edx,[esi] ;get 8 pixels to convert of DIB
1847: and edx,22222222h ;keep only the plane 1 bits of DIB
1848: ; dword 0
1849: ; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
1850: shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
1851: ; shifted left 2 (x = zero bit)
1852: ; DX = xx2xxx3xxx0xxx1x
1853: ; AX = 6xxx7xxx4xxx5xxx
1854: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1855: ; 6x2x7x3x4x0x5x1x
1856: mov bl,al ;BL = 4x0x5x1x of DIB dword 0
1857: rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
1858: or bl,ah ;BL = 46025713 of DIB dword 0
1859: add esi,4 ;point to next DIB dword
1860: inc edi ;point to next VGA byte (placed here
1861: ; for 486 pipelining reasons)
1862: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1863: mov ch,[edi-1] ;get the VGA destination byte
1864: and ecx,ulRightMask ;mask off source and dest
1865: or cl,ch ;combine masked source and dest
1866: mov [edi-1],cl ;write the new pixels to the VGA
1867:
1868: DIB4_to_VGA_plane1_copy_done:
1869: add esi,ulSrcDelta ;point to start of next DIB scan
1870: add edi,ulDstDelta ;point to start of next VGA scan
1871: dec ulPlane1Scans ;count down scans in this plane
1872: jnz DIB4_to_VGA_plane1_copy_loop ;do next scan in this plane, if any
1873:
1874: jmp copy_burst_plane1_done ;return to the top of the plane-copy
1875: ; loop
1876:
1877: ;-----------------------------------------------------------------------;
1878: ; Plane 2 DIB->VGA conversion code for a single scan line.
1879: ;
1880: ; Input: ECX with bits sets as described for ulCopyControlFlags, above
1881: ; bit 30 = 1 if there are whole words to be copied, = 0 if not
1882: ; bit 29 = 1 if leading byte should be copied, = 0 if not
1883: ; bit 28 = 1 if trailing byte should be copied, = 0 if not
1884: ; bit 27 = 1 if partial leading byte should be copied, = 0 if not
1885: ; bit 26 = 1 if partial trailing byte should be copied, = 0 if not
1886: ; ESI = DIB pointer to first two pixels
1887: ; EDI = VGA pointer to planar byte
1888: ; ulPlane2Scans = # of scan lines to copy to
1889: ; ulSrcDelta = offset from end of one source scan copied to start of next
1890: ; ulDstDelta = offset from end of one dest scan copied to start of next
1891: ; ulWholeDwordCount = # of whole, aligned dwords to copy
1892: ; ulLeftMask = mask for partial left edge, if any
1893: ; ulRightMask = mask for partial right edge, if any
1894: ; Plane 2 must be mapped in for writes
1895: ;-----------------------------------------------------------------------;
1896: align 4
1897: DIB4_to_VGA_plane2_copy:
1898:
1899: ;-----------------------------------------------------------------------;
1900: ; Set EBX to point to multiplexed DIB byte->planar byte conversion table
1901: ; for plane 2.
1902: ;-----------------------------------------------------------------------;
1903:
1904: mov ebx,DIB4_to_VGA_plane2_table ;stays set for all bytes/words
1905:
1906: DIB4_to_VGA_plane2_copy_loop:
1907:
1908: ;-----------------------------------------------------------------------;
1909: ; Code to convert 1-7 DIB4 pixels to a partial VGA plane 2 byte (8
1910: ; pixels in plane 2). Assumes that a full dword of DIB4 pixels (8
1911: ; pixels) is available, starting at ESI, although some of the pixels
1912: ; will be masked off. Assumes the DIB4 pixels (including masked-off
1913: ; pixels) start in the upper nibble of [ESI], and that the first
1914: ; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
1915: ;
1916: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1917: ; (must start on a 256-byte boundary)
1918: ; ECX with bits sets as described for ulCopyControlFlags, above
1919: ; ESI = DIB pointer to first two pixels (possibly masked off)
1920: ; EDI = VGA pointer to planar byte
1921: ; plane 2 must be mapped in for writes
1922: ;-----------------------------------------------------------------------;
1923:
1924: test ecx,LEADING_PARTIAL ;handle a leading partial byte?
1925: jz short DIB4_to_VGA_plane2_copy_lbyte ;no, go straight to whole
1926: ; byte
1927: ;yes, handle leading partial byte
1928: mov edx,[esi] ;get 8 pixels to convert of DIB
1929: and edx,44444444h ;keep only the plane 2 bits of DIB
1930: ; dword 0
1931: ; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
1932: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
1933: shr eax,16+2 ; shifted right 2 (x = zero bit)
1934: ; DX = x2xxx3xxx0xxx1xx
1935: ; AX = xxx6xxx7xxx4xxx5
1936: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1937: ; x2x6x3x7x0x4x1x5
1938: mov bl,al ;BL = x0x4x1x5 of DIB dword 0
1939: add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
1940: or bl,ah ;BL = 20643175 of DIB dword 0
1941: add esi,4 ;point to next DIB dword
1942: inc edi ;point to next VGA byte (placed here
1943: ; for 486 pipelining reasons)
1944: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1945: mov ch,[edi-1] ;get the VGA destination byte
1946: and ecx,ulLeftMask ;mask off source and dest
1947: or cl,ch ;combine masked source and dest
1948: mov [edi-1],cl ;write the new pixels to the VGA
1949:
1950: ;-----------------------------------------------------------------------;
1951: ; Code to convert 8 DIB4 pixels to a single VGA plane 2 byte (8 pixels
1952: ; in plane 2). Assumes the DIB4 pixels start in the upper nibble of
1953: ; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
1954: ; [EDI].
1955: ;
1956: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1957: ; (must start on a 256-byte boundary)
1958: ; ECX with bits sets as described for ulCopyControlFlags, above
1959: ; ESI = DIB pointer to first two pixels
1960: ; EDI = VGA pointer to planar byte
1961: ; plane 2 must be mapped in for writes
1962: ;-----------------------------------------------------------------------;
1963:
1964: DIB4_to_VGA_plane2_copy_lbyte:
1965: test ecx,LEADING_BYTE ;should we handle a leading byte?
1966: jz short DIB4_to_VGA_plane2_copy_words ;no, go straight to words
1967: ;yes, handle leading byte
1968: mov edx,[esi] ;get 8 pixels to convert of DIB
1969: and edx,44444444h ;keep only the plane 2 bits of DIB
1970: ; dword 0
1971: ; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
1972: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
1973: shr eax,16+2 ; shifted right 2 (x = zero bit)
1974: ; DX = x2xxx3xxx0xxx1xx
1975: ; AX = xxx6xxx7xxx4xxx5
1976: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
1977: ; x2x6x3x7x0x4x1x5
1978: mov bl,al ;BL = x0x4x1x5 of DIB dword 0
1979: add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
1980: or bl,ah ;BL = 20643175 of DIB dword 0
1981: add esi,4 ;point to next DIB dword
1982: inc edi ;point to next VGA byte (placed here
1983: ; for 486 pipelining reasons)
1984: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
1985: mov [edi-1],cl ;write 8 bits from DIB dword to VGA
1986:
1987: ;-----------------------------------------------------------------------;
1988: ; Code for converting sets of 32 DIB4 pixels to 4 VGA plane 2 bytes (32
1989: ; pixels in plane 2). Assumes the VGA destination is word aligned.
1990: ; Assumes the DIB4 pixels start in the upper nibble of [ESI], and that
1991: ; the first DIB4 pixel maps to bit 7 of the VGA at [EDI].
1992: ;
1993: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
1994: ; (must start on a 256-byte boundary)
1995: ; ECX with bits sets as described for ulCopyControlFlags, above
1996: ; ESI = DIB pointer to first two pixels
1997: ; EDI = VGA pointer to two planar bytes (must be word aligned)
1998: ; EBP = # of VGA dwords to convert
1999: ; ulWholeDwordCount = # of VGA dwords to convert
2000: ; Plane 2 must be mapped in for writes
2001: ;
2002: ; Note: on entry at DIB4_to_VGA_plane2_word_odd, ESI must point to the
2003: ; desired source start minus 8, and EAX must be loaded as if the following
2004: ; instructions had been performed:
2005: ; mov edx,[esi+8]
2006: ; and edx,44444444h
2007: ; mov eax,edx
2008: ; shr eax,16+2
2009: ; or eax,edx
2010: ;
2011: ; Note: the code is so odd because of 486 pipeline optimization.
2012: ; DO NOT CHANGE THIS CODE UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!!!
2013: ;
2014: ; Note: all 486 pipeline penalties are eliminated except for writing CX
2015: ; to memory (2 cycles), so far as I know.
2016: ;-----------------------------------------------------------------------;
2017:
2018: DIB4_to_VGA_plane2_copy_words:
2019: test ecx,ODD_WHOLE_WORD or WHOLE_WORDS ;any whole words to copy?
2020: jz DIB4_to_VGA_plane2_copy_tbyte ;no, check for trailing whole
2021: ; bytes
2022: ;yes, copy the whole words
2023: push ebp ;preserve stack frame pointer
2024: mov ebp,ulWholeDwordCount ;# of VGA dwords to copy to
2025: ;even # of DIB dwords to copy? (flags still
2026: ; set from TEST)
2027: .errnz ODD_WHOLE_WORD - 80000000h
2028: jns short DIB4_to_VGA_plane2_word_loop ;yes, start copying
2029: ;no, there's an odd word; prepare to enter loop
2030: ; in middle
2031: mov edx,[esi] ;get 8 pixels to convert of first DIB dword
2032: and edx,44444444h ;keep only the plane 2 bits of DIB dword
2033: ; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
2034: mov eax,edx ;put bits 7-4 of DIB dword in AX,
2035: shr eax,16+2 ; shifted right 2 (x = zero bit)
2036: ; DX = x2xxx3xxx0xxx1xx
2037: ; AX = xxx6xxx7xxx4xxx5
2038: or eax,edx ;put bits 7-0 of DIB dword in AX:
2039: ; 62xx73xx40xx51xx
2040: sub esi,8 ;compensate source back for entering in middle
2041: sub edi,2 ;compensate dest back for entering in middle
2042:
2043: jmp short DIB4_to_VGA_plane2_word_odd
2044:
2045: ;-----------------------------------------------------------------------;
2046: ; Loop to copy a word at a time to VGA plane 2 (actually, unrolled once
2047: ; so copies dwords).
2048: ;-----------------------------------------------------------------------;
2049:
2050: align 16
2051: DIB4_to_VGA_plane2_word_loop:
2052: mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
2053: and edx,44444444h ;keep only the plane 2 bits of DIB
2054: ; dword 0
2055: ; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
2056: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
2057: shr eax,16+2 ; shifted right 2 (x = zero bit)
2058: ; DX = x2xxx3xxx0xxx1xx
2059: ; AX = xxx6xxx7xxx4xxx5
2060: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
2061: ; x2x6x3x7x0x4x1x5
2062: mov edx,[esi+4] ;get 8 pixels to convert of DIB dword 1
2063: mov bl,al ;BL = x0x4x1x5 of DIB dword 0
2064: add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
2065: or bl,ah ;BL = 20643175 of DIB dword 0
2066: and edx,44444444h ;keep only the plane 2 bits of DIB
2067: ; dword 1
2068: ; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
2069: mov eax,edx ;put bits 7-4 of DIB dword 1 in AX,
2070: shr eax,16+2 ; shifted right 2 (x = zero bit)
2071: ; DX = x2xxx3xxx0xxx1xx
2072: ; AX = xxx6xxx7xxx4xxx5
2073: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
2074: or eax,edx ;put bits 7-0 of DIB dword 1 in AX:
2075: ; 62xx73xx40xx51xx
2076: mov bl,al ;BL = x0x4x1x5 of DIB dword 1
2077: mov edx,[esi+8] ;get 8 pixels to convert of DIB dword 2
2078: add ah,ah ;make AH 2x6x3x7x of DIB dword 1 (shl 1)
2079: or bl,ah ;BL = 20643175 of DIB dword 1
2080: and edx,44444444h ;keep only the plane 2 bits of DIB
2081: ; dword 2
2082: ; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
2083: mov eax,edx ;put bits 7-4 of DIB dword 2 in AX,
2084: shr eax,16+2 ; shifted right 2 (x = zero bit)
2085: ; DX = x2xxx3xxx0xxx1xx
2086: ; AX = xxx6xxx7xxx4xxx5
2087: mov ch,[ebx] ;CH = 76543210 of DIB dword 1
2088: or eax,edx ;put bits 7-0 of DIB dword 2 in AX:
2089: ; 62xx73xx40xx51xx
2090: mov [edi],cx ;write 16 bits from DIB dwords 0 and 1
2091: ; to VGA
2092: DIB4_to_VGA_plane2_word_odd:
2093: mov edx,[esi+12] ;get 8 pixels to convert of DIB dword 3
2094: mov bl,al ;BL = x0x4x1x5 of DIB dword 2
2095: add ah,ah ;make AH 2x6x3x7x of DIB dword 2 (shl 1)
2096: or bl,ah ;BL = 20643175 of DIB dword 2
2097: and edx,44444444h ;keep only the plane 2 bits of DIB
2098: ; dword 3
2099: ; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
2100: mov eax,edx ;put bits 7-4 of DIB dword 3 in AX,
2101: shr eax,16+2 ; shifted right 2 (x = zero bit)
2102: ; DX = x2xxx3xxx0xxx1xx
2103: ; AX = xxx6xxx7xxx4xxx5
2104: mov cl,[ebx] ;CL = 76543210 of DIB dword 2
2105: or eax,edx ;put bits 7-0 of DIB dword 3 in AX:
2106: ; 62xx73xx40xx51xx
2107: mov bl,al ;BL = x0x4x1x5 of DIB dword 3
2108: add ah,ah ;make AH 2x6x3x7x of DIB dword 3 (shl 1)
2109: or bl,ah ;BL = 20643175 of DIB dword 3
2110: add esi,16 ;point to next set of 4 DIB dwords
2111: add edi,4 ;point to next VGA dword
2112: mov ch,[ebx] ;CH = 76543210 of dword 0
2113: dec ebp ;count down VGA dwords
2114: mov [edi-2],cx ;write 16 bits from DIB dwords 2 and 3
2115: ; to VGA
2116: jnz DIB4_to_VGA_plane2_word_loop ;do next VGA dword, if any
2117:
2118: pop ebp ;restore stack frame pointer
2119:
2120: ;-----------------------------------------------------------------------;
2121: ; Code to convert 8 DIB4 pixels to a single VGA plane 2 byte (8 pixels
2122: ; in plane 2). Assumes the DIB4 pixels start in the upper nibble of
2123: ; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
2124: ; [EDI].
2125: ;
2126: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
2127: ; (must start on a 256-byte boundary)
2128: ; ECX with bits sets as described for ulCopyControlFlags, above
2129: ; ESI = DIB pointer to first two pixels
2130: ; EDI = VGA pointer to planar byte
2131: ; plane 2 must be mapped in for writes
2132: ;
2133: ;-----------------------------------------------------------------------;
2134:
2135: DIB4_to_VGA_plane2_copy_tbyte:
2136: test ecx,TRAILING_BYTE ;should we handle a trailing byte?
2137: jz short DIB4_to_VGA_plane2_copy_tpart ;no, check for trailing
2138: ; partial
2139: ;yes, handle trailing byte
2140: mov edx,[esi] ;get 8 pixels to convert of DIB
2141: and edx,44444444h ;keep only the plane 2 bits of DIB
2142: ; dword 0
2143: ; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
2144: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
2145: shr eax,16+2 ; shifted right 2 (x = zero bit)
2146: ; DX = x2xxx3xxx0xxx1xx
2147: ; AX = xxx6xxx7xxx4xxx5
2148: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
2149: ; x2x6x3x7x0x4x1x5
2150: mov bl,al ;BL = x0x4x1x5 of DIB dword 0
2151: add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
2152: or bl,ah ;BL = 20643175 of DIB dword 0
2153: add esi,4 ;point to next DIB dword
2154: inc edi ;point to next VGA byte (placed here
2155: ; for 486 pipelining reasons)
2156: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
2157: mov [edi-1],cl ;write 8 bits from DIB dword to VGA
2158:
2159: ;-----------------------------------------------------------------------;
2160: ; Code to convert 1-7 DIB4 pixels to a partial VGA plane 2 byte (8
2161: ; pixels in plane 2). Assumes that a full dword of DIB4 pixels (8
2162: ; pixels) is available, starting at ESI, although some of the pixels
2163: ; will be masked off. Assumes the DIB4 pixels (including masked-off
2164: ; pixels) start in the upper nibble of [ESI], and that the first
2165: ; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
2166: ;
2167: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
2168: ; (must start on a 256-byte boundary)
2169: ; ECX with bits sets as described for ulCopyControlFlags, above
2170: ; ESI = DIB pointer to first two pixels (possibly masked off)
2171: ; EDI = VGA pointer to planar byte
2172: ; plane 2 must be mapped in for writes
2173: ;-----------------------------------------------------------------------;
2174:
2175: DIB4_to_VGA_plane2_copy_tpart:
2176: test ecx,TRAILING_PARTIAL ;handle a trailing partial byte?
2177: jz short DIB4_to_VGA_plane2_copy_done ;no, done
2178: ;yes, handle trailing partial byte
2179: mov edx,[esi] ;get 8 pixels to convert of DIB
2180: and edx,44444444h ;keep only the plane 2 bits of DIB
2181: ; dword 0
2182: ; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
2183: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
2184: shr eax,16+2 ; shifted right 2 (x = zero bit)
2185: ; DX = x2xxx3xxx0xxx1xx
2186: ; AX = xxx6xxx7xxx4xxx5
2187: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
2188: ; x2x6x3x7x0x4x1x5
2189: mov bl,al ;BL = x0x4x1x5 of DIB dword 0
2190: add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
2191: or bl,ah ;BL = 20643175 of DIB dword 0
2192: add esi,4 ;point to next DIB dword
2193: inc edi ;point to next VGA byte (placed here
2194: ; for 486 pipelining reasons)
2195: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
2196: mov ch,[edi-1] ;get the VGA destination byte
2197: and ecx,ulRightMask ;mask off source and dest
2198: or cl,ch ;combine masked source and dest
2199: mov [edi-1],cl ;write the new pixels to the VGA
2200:
2201: DIB4_to_VGA_plane2_copy_done:
2202: add esi,ulSrcDelta ;point to start of next DIB scan
2203: add edi,ulDstDelta ;point to start of next VGA scan
2204: dec ulPlane2Scans ;count down scans in this plane
2205: jnz DIB4_to_VGA_plane2_copy_loop ;do next scan in this plane, if any
2206:
2207: jmp copy_burst_plane2_done ;return to the top of the plane-copy
2208: ; loop
2209:
2210: ;-----------------------------------------------------------------------;
2211: ; Plane 3 DIB->VGA conversion code for a single scan line.
2212: ;
2213: ; Input: ECX with bits sets as described for ulCopyControlFlags, above
2214: ; ESI = DIB pointer to first two pixels
2215: ; EDI = VGA pointer to planar byte
2216: ; ulPlane3Scans = # of scan lines to copy to
2217: ; ulSrcDelta = offset from end of one source scan copied to start of next
2218: ; ulDstDelta = offset from end of one dest scan copied to start of next
2219: ; ulWholeDwordCount = # of whole, aligned dwords to copy
2220: ; ulLeftMask = mask for partial left edge, if any
2221: ; ulRightMask = mask for partial right edge, if any
2222: ; Plane 3 must be mapped in for writes
2223: ;-----------------------------------------------------------------------;
2224: align 4
2225: DIB4_to_VGA_plane3_copy:
2226:
2227: ;-----------------------------------------------------------------------;
2228: ; Set EBX to point to multiplexed DIB byte->planar byte conversion table
2229: ; for plane 3.
2230: ;-----------------------------------------------------------------------;
2231:
2232: mov ebx,DIB4_to_VGA_plane3_table ;stays set for all bytes/words
2233:
2234: DIB4_to_VGA_plane3_copy_loop:
2235:
2236: ;-----------------------------------------------------------------------;
2237: ; Code to convert 1-7 DIB4 pixels to a partial VGA plane 3 byte (8
2238: ; pixels in plane 3). Assumes that a full dword of DIB4 pixels (8
2239: ; pixels) is available, starting at ESI, although some of the pixels
2240: ; will be masked off. Assumes the DIB4 pixels (including masked-off
2241: ; pixels) start in the upper nibble of [ESI], and that the first
2242: ; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
2243: ;
2244: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
2245: ; (must start on a 256-byte boundary)
2246: ; ECX with bits sets as described for ulCopyControlFlags, above
2247: ; ESI = DIB pointer to first two pixels (possibly masked off)
2248: ; EDI = VGA pointer to planar byte
2249: ; plane 3 must be mapped in for writes
2250: ;-----------------------------------------------------------------------;
2251:
2252: test ecx,LEADING_PARTIAL ;handle a leading partial byte?
2253: jz short DIB4_to_VGA_plane3_copy_lbyte ;no, go straight to whole
2254: ; byte
2255: ;yes, handle leading partial byte
2256: mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
2257: and edx,88888888h ;keep only the plane 3 bits of DIB
2258: ; dword 0
2259: ; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
2260: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
2261: shr eax,16+2 ; shifted right 2 (x = zero bit)
2262: ; DX = 2xxx3xxx0xxx1xxx
2263: ; AX = xx6xxx7xxx4xxx5x
2264: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
2265: ; 2x6x3x7x0x4x1x5x
2266: mov bl,al ;BL = 0x4x1x5x of DIB dword 0
2267: rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
2268: or bl,ah ;BL = 02461357 of DIB dword 0
2269: add esi,4 ;point to next DIB dword
2270: inc edi ;point to next VGA byte (placed here
2271: ; for 486 pipelining reasons)
2272: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
2273: mov ch,[edi-1] ;get the VGA destination byte
2274: and ecx,ulLeftMask ;mask off source and dest
2275: or cl,ch ;combine masked source and dest
2276: mov [edi-1],cl ;write the new pixels to the VGA
2277:
2278: ;-----------------------------------------------------------------------;
2279: ; Code to convert 8 DIB4 pixels to a single VGA plane 3 byte (8 pixels
2280: ; in plane 3). Assumes the DIB4 pixels start in the upper nibble of
2281: ; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
2282: ; [EDI].
2283: ;
2284: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
2285: ; (must start on a 256-byte boundary)
2286: ; ECX with bits sets as described for ulCopyControlFlags, above
2287: ; ESI = DIB pointer to first two pixels
2288: ; EDI = VGA pointer to planar byte
2289: ; plane 3 must be mapped in for writes
2290: ;-----------------------------------------------------------------------;
2291:
2292: DIB4_to_VGA_plane3_copy_lbyte:
2293: test ecx,LEADING_BYTE ;should we handle a leading byte?
2294: jz short DIB4_to_VGA_plane3_copy_words ;no, go straight to words
2295: ;yes, handle leading byte
2296: mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
2297: and edx,88888888h ;keep only the plane 3 bits of DIB
2298: ; dword 0
2299: ; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
2300: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
2301: shr eax,16+2 ; shifted right 2 (x = zero bit)
2302: ; DX = 2xxx3xxx0xxx1xxx
2303: ; AX = xx6xxx7xxx4xxx5x
2304: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
2305: ; 2x6x3x7x0x4x1x5x
2306: mov bl,al ;BL = 0x4x1x5x of DIB dword 0
2307: rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
2308: or bl,ah ;BL = 02461357 of DIB dword 0
2309: add esi,4 ;point to next DIB dword
2310: inc edi ;point to next VGA byte (placed here
2311: ; for 486 pipelining reasons)
2312: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
2313: mov [edi-1],cl ;write 8 bits from DIB dword to VGA
2314:
2315: ;-----------------------------------------------------------------------;
2316: ; Code for converting sets of 32 DIB4 pixels to 4 VGA plane 3 bytes (32
2317: ; pixels in plane 3). Assumes the VGA destination is word aligned.
2318: ; Assumes the DIB4 pixels start in the upper nibble of [ESI], and that
2319: ; the first DIB4 pixel maps to bit 7 of the VGA at [EDI].
2320: ;
2321: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
2322: ; (must start on a 256-byte boundary)
2323: ; ECX with bits sets as described for ulCopyControlFlags, above
2324: ; ESI = DIB pointer to first two pixels
2325: ; EDI = VGA pointer to two planar bytes (must be word aligned)
2326: ; EBP = # of VGA dwords to convert
2327: ; ulWholeDwordCount = # of VGA dwords to convert
2328: ; plane 3 must be mapped in for writes
2329: ;
2330: ; Note: on entry at DIB4_to_VGA_plane3_word_odd, ESI must point to the
2331: ; desired source start minus 8, and EAX must be loaded as if the following
2332: ; instructions had been performed:
2333: ; mov edx,[esi+8]
2334: ; and edx,88888888h
2335: ; mov eax,edx
2336: ; shr eax,16+2
2337: ; or eax,edx
2338: ;
2339: ; Note: ROL AH,7 is used instead of SHR AH,1 because the shift-by-1
2340: ; form is 1 cycle slower on a 486, and in this case the two forms are
2341: ; functionally identical.
2342: ;
2343: ; Note: the code is so odd because of 486 pipeline optimization.
2344: ; DO NOT CHANGE THIS CODE UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!!!
2345: ;
2346: ; Note: all 486 pipeline penalties are eliminated except for writing CX
2347: ; to memory (2 cycles), so far as I know.
2348: ;-----------------------------------------------------------------------;
2349:
2350: DIB4_to_VGA_plane3_copy_words:
2351: test ecx,ODD_WHOLE_WORD or WHOLE_WORDS ;any whole words to copy?
2352: jz DIB4_to_VGA_plane3_copy_tbyte ;no, check for trailing whole
2353: ; bytes
2354: ;yes, copy the whole words
2355: push ebp ;preserve stack frame pointer
2356: mov ebp,ulWholeDwordCount ;# of VGA dwords to copy to
2357: ;even # of DIB dwords to copy? (flags still
2358: ; set from TEST)
2359: .errnz ODD_WHOLE_WORD - 80000000h
2360: jns short DIB4_to_VGA_plane3_word_loop ;yes, start copying
2361: ;no, there's an odd word; prepare to enter loop
2362: ; in middle
2363: mov edx,[esi] ;get 8 pixels to convert of first DIB dword
2364: and edx,88888888h ;keep only the plane 3 bits of DIB dword
2365: ; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
2366: mov eax,edx ;put bits 7-4 of DIB dword in AX,
2367: shr eax,16+2 ; shifted right 2 (x = zero bit)
2368: ; DX = 2xxx3xxx0xxx1xxx
2369: ; AX = xx6xxx7xxx4xxx5x
2370: or eax,edx ;put bits 7-0 of DIB dword in AX:
2371: ; 2x6x3x7x0x4x1x5x
2372: sub esi,8 ;compensate source back for entering in middle
2373: sub edi,2 ;compensate dest back for entering in middle
2374:
2375: jmp short DIB4_to_VGA_plane3_word_odd
2376:
2377: ;-----------------------------------------------------------------------;
2378: ; Loop to copy a word at a time to VGA plane 3 (actually, unrolled once
2379: ; so copies dwords).
2380: ;-----------------------------------------------------------------------;
2381:
2382: align 16
2383: DIB4_to_VGA_plane3_word_loop:
2384: mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
2385: and edx,88888888h ;keep only the plane 3 bits of DIB
2386: ; dword 0
2387: ; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
2388: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
2389: shr eax,16+2 ; shifted right 2 (x = zero bit)
2390: ; DX = 2xxx3xxx0xxx1xxx
2391: ; AX = xx6xxx7xxx4xxx5x
2392: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
2393: ; 2x6x3x7x0x4x1x5x
2394: mov edx,[esi+4] ;get 8 pixels to convert of DIB dword 1
2395: mov bl,al ;BL = 0x4x1x5x of DIB dword 0
2396: rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
2397: or bl,ah ;BL = 02461357 of DIB dword 0
2398: and edx,88888888h ;keep only the plane 3 bits of DIB
2399: ; dword 1
2400: ; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
2401: mov eax,edx ;put bits 7-4 of DIB dword 1 in AX,
2402: shr eax,16+2 ; shifted right 2 (x = zero bit)
2403: ; DX = 2xxx3xxx0xxx1xxx
2404: ; AX = xx6xxx7xxx4xxx5x
2405: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
2406: or eax,edx ;put bits 7-0 of DIB dword 1 in AX:
2407: ; 2x6x3x7x0x4x1x5x
2408: mov bl,al ;BL = 0x4x1x5x of DIB dword 1
2409: mov edx,[esi+8] ;get 8 pixels to convert of DIB dword 2
2410: rol ah,7 ;make AH x2x6x3x7 of DIB dword 1 (shr 1)
2411: or bl,ah ;BL = 02461357 of DIB dword 1
2412: and edx,88888888h ;keep only the plane 3 bits of DIB
2413: ; dword 2
2414: ; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
2415: mov eax,edx ;put bits 7-4 of DIB dword 2 in AX,
2416: shr eax,16+2 ; shifted right 2 (x = zero bit)
2417: ; DX = 2xxx3xxx0xxx1xxx
2418: ; AX = xx6xxx7xxx4xxx5x
2419: mov ch,[ebx] ;CH = 76543210 of DIB dword 1
2420: or eax,edx ;put bits 7-0 of DIB dword 2 in AX:
2421: ; 2x6x3x7x0x4x1x5x
2422: mov [edi],cx ;write 16 bits from DIB dwords 0 and 1
2423: ; to VGA
2424: DIB4_to_VGA_plane3_word_odd:
2425: mov edx,[esi+12] ;get 8 pixels to convert of DIB dword 3
2426: mov bl,al ;BL = 0x4x1x5x of DIB dword 2
2427: rol ah,7 ;make AH x2x6x3x7 of DIB dword 2 (shr 1)
2428: or bl,ah ;BL = 02461357 of DIB dword 2
2429: and edx,88888888h ;keep only the plane 3 bits of DIB
2430: ; dword 3
2431: ; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
2432: mov eax,edx ;put bits 7-4 of DIB dword 3 in AX,
2433: shr eax,16+2 ; shifted right 2 (x = zero bit)
2434: ; DX = 2xxx3xxx0xxx1xxx
2435: ; AX = xx6xxx7xxx4xxx5x
2436: mov cl,[ebx] ;CL = 76543210 of DIB dword 2
2437: or eax,edx ;put bits 7-0 of DIB dword 3 in AX:
2438: ; 2x6x3x7x0x4x1x5x
2439: mov bl,al ;BL = 0x4x1x5x of DIB dword 3
2440: rol ah,7 ;make AH x2x6x3x7 of DIB dword 3 (shr 1)
2441: or bl,ah ;BL = 02461357 of DIB dword 3
2442: add esi,16 ;point to next set of 4 DIB dwords
2443: add edi,4 ;point to next VGA dword
2444: mov ch,[ebx] ;CH = 76543210 of dword 0
2445: dec ebp ;count down VGA dwords
2446: mov [edi-2],cx ;write 16 bits from DIB dwords 2 and 3
2447: ; to VGA
2448: jnz DIB4_to_VGA_plane3_word_loop ;do next VGA dword, if any
2449:
2450: pop ebp ;restore stack frame pointer
2451:
2452: ;-----------------------------------------------------------------------;
2453: ; Code to convert 8 DIB4 pixels to a single VGA plane 3 byte (8 pixels
2454: ; in plane 3). Assumes the DIB4 pixels start in the upper nibble of
2455: ; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
2456: ; [EDI].
2457: ;
2458: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
2459: ; (must start on a 256-byte boundary)
2460: ; ECX with bits sets as described for ulCopyControlFlags, above
2461: ; ESI = DIB pointer to first two pixels
2462: ; EDI = VGA pointer to planar byte
2463: ; plane 3 must be mapped in for writes
2464: ;
2465: ;-----------------------------------------------------------------------;
2466:
2467: DIB4_to_VGA_plane3_copy_tbyte:
2468: test ecx,TRAILING_BYTE ;should we handle a trailing byte?
2469: jz short DIB4_to_VGA_plane3_copy_tpart ;no, check for trailing
2470: ; partial
2471: ;yes, handle trailing byte
2472: mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
2473: and edx,88888888h ;keep only the plane 3 bits of DIB
2474: ; dword 0
2475: ; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
2476: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
2477: shr eax,16+2 ; shifted right 2 (x = zero bit)
2478: ; DX = 2xxx3xxx0xxx1xxx
2479: ; AX = xx6xxx7xxx4xxx5x
2480: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
2481: ; 2x6x3x7x0x4x1x5x
2482: mov bl,al ;BL = 0x4x1x5x of DIB dword 0
2483: rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
2484: or bl,ah ;BL = 02461357 of DIB dword 0
2485: add esi,4 ;point to next DIB dword
2486: inc edi ;point to next VGA byte (placed here
2487: ; for 486 pipelining reasons)
2488: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
2489: mov [edi-1],cl ;write 8 bits from DIB dword to VGA
2490:
2491: ;-----------------------------------------------------------------------;
2492: ; Code to convert 1-7 DIB4 pixels to a partial VGA plane 3 byte (8
2493: ; pixels in plane 3). Assumes that a full dword of DIB4 pixels (8
2494: ; pixels) is available, starting at ESI, although some of the pixels
2495: ; will be masked off. Assumes the DIB4 pixels (including masked-off
2496: ; pixels) start in the upper nibble of [ESI], and that the first
2497: ; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
2498: ;
2499: ; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
2500: ; (must start on a 256-byte boundary)
2501: ; ECX with bits sets as described for ulCopyControlFlags, above
2502: ; ESI = DIB pointer to first two pixels (possibly masked off)
2503: ; EDI = VGA pointer to planar byte
2504: ; plane 3 must be mapped in for writes
2505: ;-----------------------------------------------------------------------;
2506:
2507: DIB4_to_VGA_plane3_copy_tpart:
2508: test ecx,TRAILING_PARTIAL ;handle a trailing partial byte?
2509: jz short DIB4_to_VGA_plane3_copy_done ;no, done
2510: ;yes, handle trailing partial byte
2511: mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
2512: and edx,88888888h ;keep only the plane 3 bits of DIB
2513: ; dword 0
2514: ; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
2515: mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
2516: shr eax,16+2 ; shifted right 2 (x = zero bit)
2517: ; DX = 2xxx3xxx0xxx1xxx
2518: ; AX = xx6xxx7xxx4xxx5x
2519: or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
2520: ; 2x6x3x7x0x4x1x5x
2521: mov bl,al ;BL = 0x4x1x5x of DIB dword 0
2522: rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
2523: or bl,ah ;BL = 02461357 of DIB dword 0
2524: add esi,4 ;point to next DIB dword
2525: inc edi ;point to next VGA byte (placed here
2526: ; for 486 pipelining reasons)
2527: mov cl,[ebx] ;CL = 76543210 of DIB dword 0
2528: mov ch,[edi-1] ;get the VGA destination byte
2529: and ecx,ulRightMask ;mask off source and dest
2530: or cl,ch ;combine masked source and dest
2531: mov [edi-1],cl ;write the new pixels to the VGA
2532:
2533: DIB4_to_VGA_plane3_copy_done:
2534: add esi,ulSrcDelta ;point to start of next DIB scan
2535: add edi,ulDstDelta ;point to start of next VGA scan
2536: dec ulPlane3Scans ;count down scans in this plane
2537: jnz DIB4_to_VGA_plane3_copy_loop ;do next scan in this plane, if any
2538:
2539: jmp copy_burst_plane3_done ;return to the top of the plane-copy
2540: ; loop
2541:
2542: endProc vDIB2VGA
2543:
2544: public jLeftMasks
2545: public jRightMasks
2546: public one_partial_only
2547: public check_whole_bytes
2548: public set_copy_control_flags
2549: public set_shift_vec
2550: public set_initial_banking
2551: public map_init_bank
2552: public init_bank_mapped
2553: public bank_loop
2554: public copy_burst_loop
2555: public align_burst_rshift_386
2556: public align_burst_lshift_386
2557: public align_burst_rshift_486
2558: public align_burst_lshift_486
2559: public set_alignment_source
2560: public proceed_with_copy
2561: public copy_burst_plane0_done
2562: public copy_burst_plane1_done
2563: public copy_burst_plane2_done
2564: public copy_burst_plane3_done
2565: public next_bank
2566: public DIB4_to_VGA_plane0_copy
2567: public DIB4_to_VGA_plane0_copy_loop
2568: public DIB4_to_VGA_plane0_copy_lbyte
2569: public DIB4_to_VGA_plane0_copy_words
2570: public DIB4_to_VGA_plane0_word_loop
2571: public DIB4_to_VGA_plane0_word_odd
2572: public DIB4_to_VGA_plane0_copy_tbyte
2573: public DIB4_to_VGA_plane0_copy_tpart
2574: public DIB4_to_VGA_plane0_copy_done
2575: public DIB4_to_VGA_plane1_copy
2576: public DIB4_to_VGA_plane1_copy_loop
2577: public DIB4_to_VGA_plane1_copy_lbyte
2578: public DIB4_to_VGA_plane1_copy_words
2579: public DIB4_to_VGA_plane1_word_loop
2580: public DIB4_to_VGA_plane1_word_odd
2581: public DIB4_to_VGA_plane1_copy_tbyte
2582: public DIB4_to_VGA_plane1_copy_tpart
2583: public DIB4_to_VGA_plane1_copy_done
2584: public DIB4_to_VGA_plane2_copy
2585: public DIB4_to_VGA_plane2_copy_loop
2586: public DIB4_to_VGA_plane2_copy_lbyte
2587: public DIB4_to_VGA_plane2_copy_words
2588: public DIB4_to_VGA_plane2_word_loop
2589: public DIB4_to_VGA_plane2_word_odd
2590: public DIB4_to_VGA_plane2_copy_tbyte
2591: public DIB4_to_VGA_plane2_copy_tpart
2592: public DIB4_to_VGA_plane2_copy_done
2593: public DIB4_to_VGA_plane3_copy
2594: public DIB4_to_VGA_plane3_copy_loop
2595: public DIB4_to_VGA_plane3_copy_lbyte
2596: public DIB4_to_VGA_plane3_copy_words
2597: public DIB4_to_VGA_plane3_word_loop
2598: public DIB4_to_VGA_plane3_word_odd
2599: public DIB4_to_VGA_plane3_copy_tbyte
2600: public DIB4_to_VGA_plane3_copy_tpart
2601: public DIB4_to_VGA_plane3_copy_done
2602:
2603: _TEXT$01 ends
2604:
2605: end
2606:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.