Annotation of ntddk/src/video/displays/vga/i386/dib2vga.asm, revision 1.1.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.