Annotation of ntddk/src/video/displays/vga/i386/dib2vga.asm, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.