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

1.1     ! root        1: ;---------------------------Module-Header------------------------------;
        !             2: ; Module Name: restscrn.asm
        !             3: ;
        !             4: ; Copyright (c) 1992 Microsoft Corporation
        !             5: ;-----------------------------------------------------------------------;
        !             6: ;-----------------------------------------------------------------------;
        !             7: ; VOID vRestoreScreenBitsFromMemory(PDEVSURF pdsurf, PRECTL prcl,
        !             8: ;                              PVOID pjSrcBuffer, ULONG ulRestoreWidthInBytes,
        !             9: ;                              ULONG ulSrcDelta);
        !            10: ; Input:
        !            11: ;  pdsurf - surface to which to copy
        !            12: ;  prcl - pointer to rectangle to which to copy
        !            13: ;  pjSrcBuffer - pointer to source memory buffer. Should have the same
        !            14: ;                 dword alignment as the dest rect left edge does in screen
        !            15: ;                 memory
        !            16: ;  ulRestoreWidthInBytes - # of bytes to restore per scan (including any
        !            17: ;                 partial edges)
        !            18: ;  ulSrcDelta - distance from end of one source scan to start of next.
        !            19: ;                 together with ulRestoreWidthInBytes, should maintain
        !            20: ;                 dword alignment between source and dest
        !            21: ;
        !            22: ; Copies a rectangle from a memory buffer to VGA memory.
        !            23: ;
        !            24: ;-----------------------------------------------------------------------;
        !            25: ;
        !            26: ; Note: Assumes all rectangles have positive heights and widths. Will not
        !            27: ; work properly if this is not the case.
        !            28: ;
        !            29: ;-----------------------------------------------------------------------;
        !            30: ;
        !            31: ; Note: The rectangle is restored from interleaved-scan format; all four planes
        !            32: ; of one scan are saved together, then all four planes of the next scan,
        !            33: ; and so on. This is done for maximum restoration efficiency. Planes are
        !            34: ; saved in order 3, 2, 1, 0:
        !            35: ;
        !            36: ;  Scan n, plane 3
        !            37: ;  Scan n, plane 2
        !            38: ;  Scan n, plane 1
        !            39: ;  Scan n, plane 0
        !            40: ;  Scan n+1, plane 3
        !            41: ;  Scan n+1, plane 2
        !            42: ;  Scan n+1, plane 1
        !            43: ;  Scan n+1, plane 0
        !            44: ;          :
        !            45: ;
        !            46: ; There may be padding on either edge of the saved bits in the destination
        !            47: ; buffer, so that the destination can be dword aligned with the source.
        !            48: ;
        !            49: ;-----------------------------------------------------------------------;
        !            50: ;Additional optimizations:
        !            51: ;
        !            52: ; Could break out separate scan copy code with and without edge handling.
        !            53: ; (Possibly by threading the desired operations, or by having many separate
        !            54: ; optimizations.)
        !            55: ;
        !            56: ; Could handle odd bytes to dword align more efficiently, by having separate
        !            57: ; optimizations for various alignment widths, thereby avoiding starting REP
        !            58: ; and getting word accesses for 2 and 3 wide cases. Most VGAs are 8 or 16
        !            59: ; bit devices, and for them, using MOVSB/REP MOVSW/MOVSB might actually be
        !            60: ; faster, especially because it's easier to break out optimizations.
        !            61: ;
        !            62: ; Could end all scan handlers with loop bottom code.
        !            63: ;
        !            64: ; Could do more scans in one plane before doing next plane, to avoid
        !            65: ; slow OUTs. This could cause color effects, but that might be avoidable
        !            66: ; by scaling the # of scans done per plane to the width of the rectangle.
        !            67: ;
        !            68: ;-----------------------------------------------------------------------;
        !            69: 
        !            70: 
        !            71:                 .386
        !            72: 
        !            73: ifndef  DOS_PLATFORM
        !            74:         .model  small,c
        !            75: else
        !            76: ifdef   STD_CALL
        !            77:         .model  small,c
        !            78: else
        !            79:         .model  small,pascal
        !            80: endif;  STD_CALL
        !            81: endif;  DOS_PLATFORM
        !            82: 
        !            83:         assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
        !            84:         assume fs:nothing,gs:nothing
        !            85: 
        !            86:         .xlist
        !            87:         include stdcall.inc             ;calling convention cmacros
        !            88:         include i386\egavga.inc
        !            89:         include i386\strucs.inc
        !            90: 
        !            91:         .list
        !            92: 
        !            93:         .data
        !            94: 
        !            95: ;-----------------------------------------------------------------------;
        !            96: ; Masks used to do left and right edge clipping for various alignments.
        !            97: ; Low byte = destination mask, high byte = source mask.
        !            98: ;-----------------------------------------------------------------------;
        !            99:         align   2
        !           100: usLeftMasks     label   word
        !           101:         dw      0ff00h, 07f80h, 03fc0h, 01fe0h, 00ff0h, 007f8h, 003fch, 001feh
        !           102: 
        !           103: usRightMasks    label   word
        !           104:         dw      0ff00h, 0807fh, 0c03fh, 0e01fh, 0f00fh, 0f807h, 0fc03h, 0fe01h
        !           105: 
        !           106: ;-----------------------------------------------------------------------;
        !           107: ; Same as above, but dest masks only, and whole byte case is represented
        !           108: ; as 0ffh rather than 0. Used for 1-byte-wide cases.
        !           109: ;-----------------------------------------------------------------------;
        !           110: jLeftMasks      label   byte
        !           111:         db      0ffh, 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0fch, 0feh
        !           112: 
        !           113: jRightMasks     label   byte
        !           114:         db      0ffh, 07fh, 03fh, 01fh, 00fh, 007h, 003h, 001h
        !           115: 
        !           116:         .code
        !           117: 
        !           118: _TEXT$03   SEGMENT DWORD USE32 PUBLIC 'CODE'
        !           119:            ASSUME  CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
        !           120: 
        !           121: ;-----------------------------------------------------------------------;
        !           122: 
        !           123: cProc   vRestoreScreenBitsFromMemory,20,< \
        !           124:         uses    esi edi ebx,         \
        !           125:         pdsurf:ptr,                  \
        !           126:         prcl:ptr,                    \
        !           127:         pjSrcBuffer:ptr,             \
        !           128:         ulRestoreWidthInBytes:dword, \
        !           129:         ulSrcDelta:dword             >
        !           130: 
        !           131:         local   ulCurrentTopScan :dword ;top scan line to copy to in current
        !           132:                                         ; bank
        !           133:         local   ulBottomScan :dword     ;bottom scan line of rectangle to which
        !           134:                                         ; to copy
        !           135:         local   pjDstStart :dword       ;destination address
        !           136:         local   ulDstDelta :dword       ;distance from end of dest scan to
        !           137:                                         ; start of next
        !           138:         local   ulBlockHeight :dword    ;# of scans to copy in block
        !           139:         local   ulLeadingBytes :dword   ;# of leading bytes to copy per scan
        !           140:         local   ulMiddleDwords :dword   ;# of dwords to copy per scan
        !           141:         local   ulTrailingBytes :dword  ;# of trailing bytes to copy per scan
        !           142:         local   pfnCopyVector :dword    ;pointer to inner loop routine to copy
        !           143:                                         ; from buffer to screen
        !           144:         local   ulLeftMask :dword       ;2 byte masks for left edge clipping
        !           145:                                         ; (low byte = dest mask,
        !           146:                                         ;  high byte = src mask)
        !           147:         local   ulRightMask :dword      ;2 byte masks for right edge clipping
        !           148: 
        !           149: ;-----------------------------------------------------------------------;
        !           150: ; Leave the GC Index pointing to the Read Map for the rest of this routine.
        !           151: ;-----------------------------------------------------------------------;
        !           152: 
        !           153:         mov     edx,VGA_BASE + GRAF_ADDR
        !           154:         mov     al,GRAF_READ_MAP
        !           155:         out     dx,al
        !           156: 
        !           157: ;-----------------------------------------------------------------------;
        !           158: ; Set up local variables.
        !           159: ;-----------------------------------------------------------------------;
        !           160: 
        !           161:         mov     edi,prcl                ;point to rectangle from which to copy
        !           162:         mov     esi,pdsurf              ;point to surface from which to copy
        !           163: 
        !           164:         mov     eax,[edi].yBottom
        !           165:         mov     ulBottomScan,eax        ;bottom scan line of source rect
        !           166: 
        !           167:         mov     eax,[esi].dsurf_lNextScan
        !           168:         sub     eax,ulRestoreWidthInBytes
        !           169:         mov     ulDstDelta,eax  ;distance from end of one scan's bits to save
        !           170:                                 ; to start of next scan's in display memory
        !           171: 
        !           172: ;-----------------------------------------------------------------------;
        !           173: ; Figure out the left and right clip masks. If either or both edges are
        !           174: ; solid, add them into the whole bytes.
        !           175: ;-----------------------------------------------------------------------;
        !           176: 
        !           177:         mov     ebx,[edi].xLeft
        !           178:         mov     ecx,[edi].xRight
        !           179:         mov     edx,ebx
        !           180:         lea     eax,[ecx-1]
        !           181:         and     ebx,0111b
        !           182:         and     ecx,0111b
        !           183: 
        !           184:         and     edx,not 0111b
        !           185:         sub     eax,edx
        !           186:         shr     eax,3           ;width in bytes - 1
        !           187:                                 ;only 1 byte wide?
        !           188:         jnz     short @F        ;no
        !           189:                                 ;1 byte wide; special case
        !           190:         mov     al,jLeftMasks[ebx]      ;look up left dest mask
        !           191:         and     al,jRightMasks[ecx]     ;factor in right dest mask
        !           192:         mov     ah,0ffh
        !           193:         mov     ebx,offset copy_from_buffer_l_whole_only ;assume whole byte
        !           194:         xor     ah,al                   ;calculate matching dest mask
        !           195:                                 ;is this single byte a whole byte?
        !           196:         jz      set_copy_vector ;yes, select whole byte optimization
        !           197:                                 ;no, select partial byte optimization
        !           198:         mov     ebx,offset copy_from_buffer_l_partial_only
        !           199:         mov     ulLeftMask,eax
        !           200:         jmp     set_copy_vector
        !           201: 
        !           202:         align   4
        !           203: @@:                                     ;more than 1 byte wide
        !           204: 
        !           205:         mov     edx,ulRestoreWidthInBytes
        !           206: 
        !           207:         mov     ax,usLeftMasks[ebx*2]   ;look up left masks
        !           208:         mov     ulLeftMask,eax
        !           209:         and     al,al                   ;any left clipping?
        !           210:         jz      short @F                ;no, do as part of whole bytes
        !           211:         dec     edx                     ;yes, don't count as whole byte
        !           212: @@:
        !           213: 
        !           214: 
        !           215:         mov     ax,usRightMasks[ecx*2]  ;look up right masks
        !           216:         mov     ulRightMask,eax
        !           217:         and     al,al                   ;any right clipping?
        !           218:         jz      short @F                ;no, do as part of whole bytes
        !           219:         dec     edx                     ;yes, don't count as whole byte
        !           220: @@:
        !           221: 
        !           222: ;-----------------------------------------------------------------------;
        !           223: ; Set up for copying as much as possible via aligned dwords, and
        !           224: ; select the most efficient loop for doing the copy, based on the copy
        !           225: ; width, and on the necessity for leading and/or trailing bytes to
        !           226: ; dword align.
        !           227: ;-----------------------------------------------------------------------;
        !           228: 
        !           229:         cmp     edx,8                   ;if it's less than 8 bytes, just do a
        !           230:                                         ; straight byte copy. This means we
        !           231:                                         ; we only have to start 1 REP per line,
        !           232:                                         ; and performing this check guarantees
        !           233:                                         ; that we have at least 1 aligned dword
        !           234:                                         ; to copy in the dword loops
        !           235:         jb      short copy_all_as_bytes ;do straight byte copy
        !           236:         mov     eax,pjSrcBuffer
        !           237:         neg     eax
        !           238:         and     eax,3           ;# of bytes that have to be done as leading
        !           239:                                 ; bytes to dword align with source (note that
        !           240:                                 ; for performance, the source should be dword
        !           241:                                 ; aligned with the destination)
        !           242:         jz      short copy_no_leading_bytes     ;no leading bytes
        !           243:                                 ;leading bytes
        !           244:         mov     ulLeadingBytes,eax
        !           245:         mov     ebx,offset copy_from_buffer_l ;assume no trailing bytes
        !           246:         sub     edx,eax         ;# of bytes after leading bytes
        !           247:         mov     eax,edx
        !           248:         shr     eax,2           ;# of dwords that can be handled as aligned
        !           249:                                 ; dwords
        !           250:         mov     ulMiddleDwords,eax
        !           251:         and     edx,3           ;# of trailing bytes left after aligned dwords
        !           252:                                 ; copied
        !           253:         jz      short set_copy_vector ;no trailing bytes
        !           254:         mov     ulTrailingBytes,edx
        !           255:         mov     ebx,offset copy_from_buffer_lt  ;there are both leading and
        !           256:                                                 ; trailing bytes
        !           257:         jmp     short set_copy_vector
        !           258: 
        !           259:         align   4
        !           260: copy_no_leading_bytes:
        !           261:         mov     ebx,offset copy_from_buffer ;assume no trailing bytes
        !           262:         mov     eax,edx
        !           263:         shr     eax,2           ;# of dwords that can be handled as aligned
        !           264:                                 ; dwords
        !           265:         mov     ulMiddleDwords,eax
        !           266:         and     edx,3           ;# of trailing bytes left after aligned dwords
        !           267:                                 ; copied
        !           268:         jz      short set_copy_vector ;no trailing bytes
        !           269:         mov     ulTrailingBytes,edx
        !           270:         mov     ebx,offset copy_from_buffer_t     ;there are trailing bytes
        !           271:         jmp     short set_copy_vector
        !           272: 
        !           273: ; It's so narrow that we'll forget about aligned dwords, and just do a straight
        !           274: ; byte copy, which we'll handle by treating the entire copy as leading bytes.
        !           275:         align   4
        !           276: copy_all_as_bytes:
        !           277:         mov     ulLeadingBytes,edx
        !           278:         mov     ebx,offset copy_from_buffer_lonly
        !           279: 
        !           280: set_copy_vector:
        !           281:         mov     pfnCopyVector,ebx
        !           282: 
        !           283: ;-----------------------------------------------------------------------;
        !           284: ; Map in the bank containing the top scan to copy, if it's not mapped in
        !           285: ; already.
        !           286: ;-----------------------------------------------------------------------;
        !           287: 
        !           288:         mov     eax,[edi].yTop          ;top scan line of copy
        !           289:         mov     ulCurrentTopScan,eax    ;this will be the copy top in 1st bank
        !           290: 
        !           291:         cmp     eax,[esi].dsurf_rcl1WindowClip.yTop ;is copy top less than
        !           292:                                                     ; current bank?
        !           293:         jl      short map_init_bank             ;yes, map in proper bank
        !           294:         cmp     eax,[esi].dsurf_rcl1WindowClip.yBottom ;copy top greater than
        !           295:                                                        ; current bank?
        !           296:         jl      short init_bank_mapped          ;no, proper bank already mapped
        !           297: map_init_bank:
        !           298: 
        !           299: ; Map in the bank containing the top scan line of the copy.
        !           300: 
        !           301:         ptrCall   <dword ptr [esi].dsurf_pfnBankControl>,<esi,eax,JustifyTop>
        !           302: 
        !           303: init_bank_mapped:
        !           304: 
        !           305: ;-----------------------------------------------------------------------;
        !           306: ; Calculate the initial start address to which to copy.
        !           307: ;-----------------------------------------------------------------------;
        !           308: 
        !           309:         mov     eax,ulCurrentTopScan    ;top scan line to copy to in current
        !           310:                                         ; bank
        !           311:         imul    [esi].dsurf_lNextScan   ;offset of starting scan line in bitmap
        !           312:         add     eax,[esi].dsurf_pvBitmapStart ;start address of scan
        !           313:         mov     ebx,[edi].xLeft
        !           314:         shr     ebx,3                   ;convert from pixel to byte address
        !           315:         add     eax,ebx                 ;start dest address
        !           316:         mov     pjDstStart,eax
        !           317: 
        !           318: ;-----------------------------------------------------------------------;
        !           319: ; Loop through and copy all bank blocks spanned by the destination
        !           320: ; rectangle.
        !           321: ;
        !           322: ; Input:
        !           323: ;  ESI = pdsurf
        !           324: ;-----------------------------------------------------------------------;
        !           325: 
        !           326: copy_from_buffer_bank_loop:
        !           327: 
        !           328: ; Copy this bank block to the buffer.
        !           329: 
        !           330: ; Calculate # of scans in this bank.
        !           331: 
        !           332:         mov     ebx,ulBottomScan        ;bottom of dest rectangle
        !           333:         cmp     ebx,[esi].dsurf_rcl1WindowClip.yBottom
        !           334:                                         ;which comes first, the bottom of the
        !           335:                                         ; dest rect or the bottom of the
        !           336:                                         ; current bank?
        !           337:         jl      short @F                ;dest bottom comes first, so copy to
        !           338:                                         ; that; this is the last bank in copy
        !           339:         mov     ebx,[esi].dsurf_rcl1WindowClip.yBottom
        !           340:                                         ;bank bottom comes first; copy to
        !           341:                                         ; bottom of bank
        !           342: @@:
        !           343:         sub     ebx,ulCurrentTopScan    ;# of scans to copy in this bank
        !           344:         mov     ulBlockHeight,ebx
        !           345: 
        !           346:         mov     esi,pjSrcBuffer ;point to start of source rect
        !           347: 
        !           348:         mov     dh,VGA_BASE SHR 8       ;leave DH pointing to VGA_BASE
        !           349: 
        !           350: ;-----------------------------------------------------------------------;
        !           351: ; Loop through all scans in this block, copying all four planes of each
        !           352: ; scan in turn, then doing the next scan.
        !           353: ;-----------------------------------------------------------------------;
        !           354: copy_to_buffer_scan_loop:
        !           355: 
        !           356:         mov     bl,MM_C3        ;start by copying to plane 3
        !           357: 
        !           358: ;-----------------------------------------------------------------------;
        !           359: ; Loop through all four planes, copying all scans in this block for each
        !           360: ; plane in turn.
        !           361: ;-----------------------------------------------------------------------;
        !           362: 
        !           363: copy_to_buffer_plane_loop:
        !           364: 
        !           365:         mov     dl,SEQ_DATA
        !           366:         mov     al,bl
        !           367:         out     dx,al           ;set Map Mask to plane to which we're copying
        !           368: 
        !           369:         mov     dl,GRAF_DATA
        !           370:         shr     al,1
        !           371:         cmp     al,3
        !           372:         adc     al,-1
        !           373:         out     dx,al
        !           374: 
        !           375:         mov     edi,pjDstStart  ;point to start of dest buffer (scan starts
        !           376:                                 ; at same address in all planes)
        !           377:         jmp     pfnCopyVector   ;jump to the appropriate loop to copy plane
        !           378: 
        !           379: ;-----------------------------------------------------------------------;
        !           380: ; Copy loops, broken out by leading and trailing bytes needed for dword
        !           381: ; alignment, plus one loop to perform a straight byte copy.
        !           382: ;
        !           383: ; Input:
        !           384: ;  ESI = initial source copy address
        !           385: ;  EDI = initial dest copy address
        !           386: ;-----------------------------------------------------------------------;
        !           387: 
        !           388: ; All bytes can be copied as aligned dwords (no leading or trailing whole
        !           389: ; bytes).
        !           390:         align   4
        !           391: copy_from_buffer:
        !           392: 
        !           393: ; Do the left edge byte, if there's a partial left edge byte.
        !           394: 
        !           395:         mov     eax,ulLeftMask  ;AL = dest mask, AH = source mask
        !           396:         and     al,al           ;any left mask?
        !           397:         jz      short @F        ;left edge is whole
        !           398:         and     al,[edi]        ;mask the dest
        !           399:         and     ah,[esi]        ;mask the source
        !           400:         inc     esi             ;point to next source byte
        !           401:         or      al,ah           ;combine the source and dest
        !           402:         stosb                   ;store the new byte
        !           403: @@:
        !           404: 
        !           405: ; Do the middle (whole) bytes.
        !           406: 
        !           407:         mov     ecx,ulMiddleDwords
        !           408:         rep     movsd
        !           409: 
        !           410: ; Do the right edge byte, if there's a partial right edge byte.
        !           411: 
        !           412:         mov     eax,ulRightMask ;AL = dest mask, AH = source mask
        !           413:         and     al,al           ;any left mask?
        !           414:         jz      short @F        ;right edge is whole
        !           415:         and     al,[edi]        ;mask the dest
        !           416:         and     ah,[esi]        ;mask the source
        !           417:         inc     esi             ;point to next source byte
        !           418:         or      al,ah           ;combine the source and dest
        !           419:         stosb                   ;store the new byte
        !           420: @@:
        !           421: 
        !           422:         jmp     copy_from_buffer_scan_done
        !           423: 
        !           424: ; Leading odd whole bytes, but no trailing whole bytes.
        !           425:         align   4
        !           426: copy_from_buffer_l:
        !           427: 
        !           428: ; Do the left edge byte, if there's a partial left edge byte.
        !           429: 
        !           430:         mov     eax,ulLeftMask  ;AL = dest mask, AH = source mask
        !           431:         and     al,al           ;any left mask?
        !           432:         jz      short @F        ;left edge is whole
        !           433:         and     al,[edi]        ;mask the dest
        !           434:         and     ah,[esi]        ;mask the source
        !           435:         inc     esi             ;point to next source byte
        !           436:         or      al,ah           ;combine the source and dest
        !           437:         stosb                   ;store the new byte
        !           438: @@:
        !           439: 
        !           440: ; Do the middle (whole) bytes.
        !           441: 
        !           442:         mov     ecx,ulLeadingBytes
        !           443:         rep     movsb
        !           444:         mov     ecx,ulMiddleDwords
        !           445:         rep     movsd
        !           446: 
        !           447: ; Do the right edge byte, if there's a partial right edge byte.
        !           448: 
        !           449:         mov     eax,ulRightMask ;AL = dest mask, AH = source mask
        !           450:         and     al,al           ;any left mask?
        !           451:         jz      short @F        ;right edge is whole
        !           452:         and     al,[edi]        ;mask the dest
        !           453:         and     ah,[esi]        ;mask the source
        !           454:         inc     esi             ;point to next source byte
        !           455:         or      al,ah           ;combine the source and dest
        !           456:         stosb                   ;store the new byte
        !           457: @@:
        !           458: 
        !           459:         jmp     copy_from_buffer_scan_done
        !           460: 
        !           461: ; Trailing odd whole bytes, but no leading whole bytes.
        !           462:         align   4
        !           463: copy_from_buffer_t:
        !           464: 
        !           465: ; Do the left edge byte, if there's a partial left edge byte.
        !           466: 
        !           467:         mov     eax,ulLeftMask  ;AL = dest mask, AH = source mask
        !           468:         and     al,al           ;any left mask?
        !           469:         jz      short @F        ;left edge is whole
        !           470:         and     al,[edi]        ;mask the dest
        !           471:         and     ah,[esi]        ;mask the source
        !           472:         inc     esi             ;point to next source byte
        !           473:         or      al,ah           ;combine the source and dest
        !           474:         stosb                   ;store the new byte
        !           475: @@:
        !           476: 
        !           477: ; Do the middle (whole) bytes.
        !           478: 
        !           479:         mov     ecx,ulMiddleDwords
        !           480:         rep     movsd
        !           481:         mov     ecx,ulTrailingBytes
        !           482:         rep     movsb
        !           483: 
        !           484: ; Do the right edge byte, if there's a partial right edge byte.
        !           485: 
        !           486:         mov     eax,ulRightMask ;AL = dest mask, AH = source mask
        !           487:         and     al,al           ;any left mask?
        !           488:         jz      short @F        ;right edge is whole
        !           489:         and     al,[edi]        ;mask the dest
        !           490:         and     ah,[esi]        ;mask the source
        !           491:         inc     esi             ;point to next source byte
        !           492:         or      al,ah           ;combine the source and dest
        !           493:         stosb                   ;store the new byte
        !           494: @@:
        !           495: 
        !           496:         jmp     copy_from_buffer_scan_done
        !           497: 
        !           498: ; Only leading whole bytes (straight whole byte copy; no aligned dwords).
        !           499:         align   4
        !           500: copy_from_buffer_lonly:
        !           501: 
        !           502: ; Do the left edge byte, if there's a partial left edge byte.
        !           503: 
        !           504:         mov     eax,ulLeftMask  ;AL = dest mask, AH = source mask
        !           505:         and     al,al           ;any left mask?
        !           506:         jz      short @F        ;left edge is whole
        !           507:         and     al,[edi]        ;mask the dest
        !           508:         and     ah,[esi]        ;mask the source
        !           509:         inc     esi             ;point to next source byte
        !           510:         or      al,ah           ;combine the source and dest
        !           511:         stosb                   ;store the new byte
        !           512: @@:
        !           513: 
        !           514: ; Do the middle (whole) bytes.
        !           515: 
        !           516:         mov     ecx,ulLeadingBytes
        !           517:         rep     movsb
        !           518: 
        !           519: ; Do the right edge byte, if there's a partial right edge byte.
        !           520: 
        !           521:         mov     eax,ulRightMask ;AL = dest mask, AH = source mask
        !           522:         and     al,al           ;any left mask?
        !           523:         jz      short @F        ;right edge is whole
        !           524:         and     al,[edi]        ;mask the dest
        !           525:         and     ah,[esi]        ;mask the source
        !           526:         inc     esi             ;point to next source byte
        !           527:         or      al,ah           ;combine the source and dest
        !           528:         stosb                   ;store the new byte
        !           529: @@:
        !           530: 
        !           531:         jmp     short copy_from_buffer_scan_done
        !           532: 
        !           533: ; Only one masked byte; no whole bytes and no right byte.
        !           534:         align   4
        !           535: copy_from_buffer_l_partial_only:
        !           536: 
        !           537:         mov     eax,ulLeftMask  ;AL = dest mask, AH = source mask
        !           538:         and     al,[edi]        ;mask the dest
        !           539:         and     ah,[esi]        ;mask the source
        !           540:         inc     esi             ;point to next source byte
        !           541:         or      al,ah           ;combine the source and dest
        !           542:         stosb                   ;store the new byte
        !           543:         jmp     short copy_from_buffer_scan_done
        !           544: 
        !           545: ; Only one whole byte; no left byte and no right byte.
        !           546:         align   4
        !           547: copy_from_buffer_l_whole_only:
        !           548: 
        !           549:         movsb                   ;copy the one byte
        !           550:         jmp     short copy_from_buffer_scan_done
        !           551: 
        !           552: ; Leading and trailing odd whole bytes.
        !           553:         align   4
        !           554: copy_from_buffer_lt:
        !           555: 
        !           556: ; Do the left edge byte, if there's a partial left edge byte.
        !           557: 
        !           558:         mov     eax,ulLeftMask  ;AL = dest mask, AH = source mask
        !           559:         and     al,al           ;any left mask?
        !           560:         jz      short @F        ;left edge is whole
        !           561:         and     al,[edi]        ;mask the dest
        !           562:         and     ah,[esi]        ;mask the source
        !           563:         inc     esi             ;point to next source byte
        !           564:         or      al,ah           ;combine the source and dest
        !           565:         stosb                   ;store the new byte
        !           566: @@:
        !           567: 
        !           568: ; Do the middle (whole) bytes.
        !           569: 
        !           570:         mov     ecx,ulLeadingBytes
        !           571:         rep     movsb
        !           572:         mov     ecx,ulMiddleDwords
        !           573:         rep     movsd
        !           574:         mov     ecx,ulTrailingBytes
        !           575:         rep     movsb
        !           576: 
        !           577: ; Do the right edge byte, if there's a partial right edge byte.
        !           578: 
        !           579:         mov     eax,ulRightMask ;AL = dest mask, AH = source mask
        !           580:         and     al,al           ;any left mask?
        !           581:         jz      short @F        ;right edge is whole
        !           582:         and     al,[edi]        ;mask the dest
        !           583:         and     ah,[esi]        ;mask the source
        !           584:         inc     esi             ;point to next source byte
        !           585:         or      al,ah           ;combine the source and dest
        !           586:         stosb                   ;store the new byte
        !           587: @@:
        !           588: 
        !           589: copy_from_buffer_scan_done:
        !           590: 
        !           591:         add     esi,ulSrcDelta  ;point to next source scan
        !           592:         shr     bl,1            ;count down planes
        !           593:         jnz     copy_to_buffer_plane_loop
        !           594: 
        !           595:         add     edi,ulDstDelta  ;point to next dest scan
        !           596:         mov     pjDstStart,edi
        !           597:         dec     ulBlockHeight   ;count down scans
        !           598:         jnz     copy_to_buffer_scan_loop
        !           599: 
        !           600: ; Remember where we left off, for the next block.
        !           601: 
        !           602:         mov     pjSrcBuffer,esi
        !           603: 
        !           604: ;-----------------------------------------------------------------------;
        !           605: ; See if there are more banks to do
        !           606: ;-----------------------------------------------------------------------;
        !           607: 
        !           608:         mov     esi,pdsurf
        !           609:         mov     eax,[esi].dsurf_rcl1WindowClip.yBottom ;is the copy bottom in
        !           610:         cmp     ulBottomScan,eax                       ; the current bank?
        !           611:         jle     short copy_from_buffer_banks_done        ;yes, so we're done
        !           612:                                         ;no, map in the next bank and copy it
        !           613:         mov     ulCurrentTopScan,eax    ;remember where the top of the bank
        !           614:                                         ; we're about to map in is (same as
        !           615:                                         ; bottom of bank we just did)
        !           616:         mov     edx,[esi].dsurf_pvBitmapStart
        !           617:         sub     pjDstStart,edx  ;convert from address to offset within bitmap
        !           618: 
        !           619:         ptrCall   <dword ptr [esi].dsurf_pfnBankControl>,<esi,eax,JustifyTop>
        !           620:                                         ;map in the bank
        !           621: 
        !           622: ; Compute the starting address in this bank.
        !           623: ; Note that the start of the bitmap will change each time through the
        !           624: ; bank loop, because the start of the bitmap is varied to map the
        !           625: ; desired scan line to the banking window.
        !           626: 
        !           627:         mov     eax,[esi].dsurf_pvBitmapStart
        !           628:         add     pjDstStart,eax  ;address of next scan to draw
        !           629: 
        !           630: ; Copy the new bank.
        !           631: 
        !           632:         jmp     copy_from_buffer_bank_loop
        !           633: 
        !           634: 
        !           635: ;-----------------------------------------------------------------------;
        !           636: ; Done with all banks.
        !           637: ;
        !           638: ; At this point:
        !           639: ;  DX = VGA_BASE + GRAF_DATA
        !           640: ;-----------------------------------------------------------------------;
        !           641:         align 4
        !           642: copy_from_buffer_banks_done:
        !           643: 
        !           644:         mov     ax,(MM_ALL shl 8)+SEQ_MAP_MASK  ;restore writability for all planes
        !           645:         mov     dx,VGA_BASE+SEQ_ADDR
        !           646:         out     dx,ax
        !           647: 
        !           648:         cRet    vRestoreScreenBitsFromMemory ;done
        !           649: 
        !           650: ;-----------------------------------------------------------------------;
        !           651: 
        !           652: endProc vRestoreScreenBitsFromMemory
        !           653: 
        !           654: _TEXT$03   ends
        !           655: 
        !           656:         end
        !           657: 
        !           658: 

unix.superglobalmegacorp.com

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