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

1.1     ! root        1: ;---------------------------Module-Header------------------------------;
        !             2: ; Module Name: rleblts.asm
        !             3: ;
        !             4: ; Copyright (c) 1992 Microsoft Corporation
        !             5: ;-----------------------------------------------------------------------;
        !             6:         .386
        !             7: 
        !             8: ifndef  DOS_PLATFORM
        !             9:         .model  small,c
        !            10: else
        !            11: ifdef   STD_CALL
        !            12:         .model  small,c
        !            13: else
        !            14:         .model  small,pascal
        !            15: endif;  STD_CALL
        !            16: endif;  DOS_PLATFORM
        !            17: 
        !            18:         assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
        !            19:         assume fs:nothing,gs:nothing
        !            20: 
        !            21:         .xlist
        !            22:         include stdcall.inc             ;calling convention cmacros
        !            23:         include i386\egavga.inc
        !            24:         include i386\strucs.inc
        !            25:         .list
        !            26: 
        !            27:         .code
        !            28: 
        !            29: ;-------------------------------Macro-----------------------------------;
        !            30: ; RleSetUp
        !            31: ;
        !            32: ;   Set the EGA\VGA to write mode 2 (M_COLOR_WRITE).  Initialize local vars
        !            33: ;
        !            34: ; Entry:
        !            35: ;       None
        !            36: ; Returns:
        !            37: ;       ESI = pointer to the source bitmap
        !            38: ;
        !            39: ;-----------------------------------------------------------------------;
        !            40: 
        !            41: RleSetUp    macro
        !            42: 
        !            43:         cld
        !            44: 
        !            45:         mov     dx,VGA_BASE + GRAF_ADDR
        !            46:         mov     ax,(M_COLOR_WRITE shl 8) + GRAF_MODE
        !            47:         out     dx,ax
        !            48: 
        !            49:         mov     esi,pRleInfo
        !            50:         mov     edi,[esi].RLE_prctlTrg
        !            51:         mov     eax,[edi].xLeft
        !            52:         mov     xStart,eax
        !            53:         mov     eax,[esi].RLE_xBegin
        !            54:         mov     xCurr,eax
        !            55:         mov     eax,[edi].yBottom
        !            56:         dec     eax
        !            57:         mov     yCurr,eax
        !            58: 
        !            59:         mov     eax,[esi].RLE_pulTranslate
        !            60:         mov     pulXlate,eax
        !            61:         mov     eax,[esi].RLE_prctlClip
        !            62:         mov     prclClip,eax
        !            63:         mov     eax,[esi].RLE_pjSrcBitsMax
        !            64:         mov     pjSrcEnd,eax
        !            65:         mov     ebx,[esi].RLE_pjTrg
        !            66: 
        !            67:         mov     pjDst,ebx
        !            68:         mov     esi,[esi].RLE_pjSrcBits
        !            69: endm
        !            70: 
        !            71: ;-------------------------------Macro-----------------------------------;
        !            72: ; RleDelta
        !            73: ;
        !            74: ;   Handle the Delta case.
        !            75: ;
        !            76: ; Entry:
        !            77: ;       ESI = pointer to the horz/vert offset of the source bitmap
        !            78: ; Returns:
        !            79: ;       None
        !            80: ;
        !            81: ;-----------------------------------------------------------------------;
        !            82: 
        !            83: RleDelta    macro   dest
        !            84: 
        !            85:         lodsw
        !            86:         movzx   ecx,al
        !            87:         add     xCurr,ecx               ;x adjustment
        !            88: 
        !            89:         movzx   eax,ah
        !            90:         sub     yCurr,eax               ;y adjustment
        !            91: 
        !            92:         mul     lNextScan
        !            93:         sub     pjDst,eax
        !            94:         jmp     dest
        !            95: endm
        !            96: 
        !            97: ;-------------------------------Macro-----------------------------------;
        !            98: ; RleExit
        !            99: ;
        !           100: ;   Prepare the Rle routine to exit.  Set the EGA/VGA to default write
        !           101: ;   mode.  Save the current status in the RleInfo so we can continue
        !           102: ;   from where we left off if a complex clipping is encountered.
        !           103: ;
        !           104: ; Entry:
        !           105: ;       ESI = pointer pass the first run above the clipping rect
        !           106: ;       EBX = yCurr(y value of the first run above the clipping rect)
        !           107: ;       ECX = xCurr(x value of the first run above the clipping rect)
        !           108: ; Returns:
        !           109: ;       None
        !           110: ;
        !           111: ;-----------------------------------------------------------------------;
        !           112: 
        !           113: RleExit macro
        !           114: 
        !           115:         mov     dx,VGA_BASE + GRAF_ADDR
        !           116:         mov     ax,(M_PROC_WRITE shl 8) + GRAF_MODE
        !           117:         out     dx,ax
        !           118: 
        !           119:         mov     ax,0FF00h + GRAF_BIT_MASK
        !           120:         out     dx,ax                   ;no mask
        !           121: 
        !           122:         mov     edi,pRleInfo            ;update for next call
        !           123:         dec     esi
        !           124:         dec     esi
        !           125:         mov     [edi].RLE_pjSrcBits,esi
        !           126:         mov     esi,[edi].RLE_prctlTrg
        !           127:         inc     ebx                     ;make it exclusive
        !           128:         mov     [esi].yBottom,ebx
        !           129:         mov     eax,pjDst
        !           130:         mov     [edi].RLE_pjTrg,eax
        !           131:         mov     [edi].RLE_xBegin,ecx
        !           132: endm
        !           133: 
        !           134: ;-------------------------------Macro-----------------------------------;
        !           135: ; Clip_Encoded
        !           136: ;
        !           137: ;   Clip the current run in encoded mode against the clipping rect.
        !           138: ;
        !           139: ; Entry:
        !           140: ;       AH = pel color of this run
        !           141: ;       AL = number of pels of this run
        !           142: ; Returns:
        !           143: ;       EAX = left coordinate if no clipping
        !           144: ;       ECX = left coordinate of the clipped run
        !           145: ;       EBX = right coordinate of the clipped run
        !           146: ;
        !           147: ;-----------------------------------------------------------------------;
        !           148: 
        !           149: Clip_Encoded    macro   done, loop_start
        !           150: 
        !           151:         movzx   edx,ah                  ;EDX = pel color
        !           152:         movzx   eax,al                  ;EAX = number of pels
        !           153:         mov     ecx,xCurr               ;ECX = left coordinate
        !           154:         add     xCurr,eax               ;compute new x position
        !           155:         mov     ebx,yCurr
        !           156: 
        !           157: ; Check if y is inside the clipping range.
        !           158: 
        !           159:         mov     edi,prclClip
        !           160:         cmp     ebx,[edi].yTop
        !           161:         jb      done
        !           162:         cmp     ebx,[edi].yBottom
        !           163:         jae short loop_start
        !           164: 
        !           165: ; Clip to the passed in clip rectangle.
        !           166: 
        !           167:         mov     eax,ecx
        !           168:         cmp     ecx,[edi].xLeft
        !           169:         jae short @F
        !           170:         mov     ecx,[edi].xLeft
        !           171: 
        !           172: @@:
        !           173:         mov     ebx,xCurr
        !           174:         cmp     ebx,[edi].xRight
        !           175:         jbe short @F
        !           176:         mov     ebx,[edi].xRight
        !           177: 
        !           178: @@:
        !           179:         cmp     ebx,ecx                 ;clipped out if left and right crossed
        !           180:         jbe short loop_start
        !           181: endm
        !           182: 
        !           183: ;-------------------------------Macro-----------------------------------;
        !           184: ; Draw_Encoded
        !           185: ;
        !           186: ;   Write the current encoded run to the EGA/VGA.
        !           187: ;
        !           188: ; Entry:
        !           189: ;       EBX = right coordinate (exclusive)
        !           190: ;       ECX = left coordinate  (inclusive)
        !           191: ;       EDX = pel color
        !           192: ; Returns:
        !           193: ;       None
        !           194: ;
        !           195: ;-----------------------------------------------------------------------;
        !           196: 
        !           197: Draw_Encoded    macro   loop_start
        !           198: 
        !           199:         call    comp_masks              ;compute bit masks
        !           200: 
        !           201:         shl     eax,8                   ;save right mask in high word
        !           202:         add     edi,pjDst
        !           203: 
        !           204:         mov     ebx,pulXlate
        !           205:         mov     ebx,[ebx][edx*4]
        !           206: 
        !           207:         mov     dx,VGA_BASE + GRAF_ADDR
        !           208: 
        !           209:         or      ah,ah                   ;AH = left mask
        !           210:         jz short @F
        !           211: 
        !           212:         mov     al,GRAF_BIT_MASK        ;Set bitmask for altered bits
        !           213:         out     dx,ax
        !           214: 
        !           215:         mov     al,bl                   ;write color
        !           216:         xchg    [edi],al
        !           217:         inc     edi                     ;update destination pointer
        !           218: 
        !           219: @@:
        !           220:         or      ecx,ecx                 ;ECX = inner loop count
        !           221:         jz short @F
        !           222: 
        !           223:         mov     ax,0FF00h + GRAF_BIT_MASK
        !           224:         out     dx,ax                   ;no mask
        !           225: 
        !           226:         mov     al,bl
        !           227:         rep     stosb                   ;write color
        !           228: 
        !           229: @@:
        !           230:         shr     eax,8                   ;AH = right mask
        !           231:         or      ah,ah
        !           232:         jz      loop_start
        !           233: 
        !           234:         mov     al,GRAF_BIT_MASK        ;Set bitmask for altered bits
        !           235:         out     dx,ax
        !           236:         xchg    [edi],bl                ;write color
        !           237: 
        !           238:         jmp     loop_start
        !           239: endm
        !           240: 
        !           241: ;-------------------------------Macro-----------------------------------;
        !           242: ; Clip_Absolute
        !           243: ;
        !           244: ;   Clip the current run in absolute mode against the clipping rect.
        !           245: ;   Compute initial bit mask and other vars for subsequent loop.
        !           246: ;
        !           247: ; Entry:
        !           248: ;       AH = number of pels of this run
        !           249: ; Returns:
        !           250: ;       AL = GRAF_BIT_MASK
        !           251: ;       AH = bitmap for the first pel
        !           252: ;       EBX = pulXlate (pointer to the xlate table)
        !           253: ;       CH = 01000001b
        !           254: ;       EDI = pointer to destination byte to be altered
        !           255: ;       loop_count = loop count (number of pels to be altered)
        !           256: ;
        !           257: ;-----------------------------------------------------------------------;
        !           258: 
        !           259: Clip_Absolute   macro   done,loop_end,loop_count
        !           260: 
        !           261:         movzx   eax,ah                  ;EAX = number of pels
        !           262:         mov     ecx,xCurr               ;ECX = left coordinate
        !           263:         add     xCurr,eax
        !           264: 
        !           265:         mov     ebx,yCurr
        !           266: 
        !           267: ; Check if y is inside the clipping range.
        !           268: 
        !           269:         mov     edi,prclClip
        !           270:         cmp     ebx,[edi].yTop
        !           271:         jb      done
        !           272:         cmp     ebx,[edi].yBottom
        !           273:         jae     loop_end
        !           274: 
        !           275: ; Check if x is inside the clipping range.
        !           276: 
        !           277:         cmp     ecx,[edi].xRight        ;check if x is in range
        !           278:         jae     loop_end
        !           279: 
        !           280:         mov     ebx,xCurr               ;EBX = right coordinate
        !           281:         cmp     ebx,[edi].xLeft         ;can I not jump???!!!
        !           282:         jbe     loop_end
        !           283: 
        !           284: ; Clip to the passed in clip rectangle.
        !           285: 
        !           286:         cmp     ecx,[edi].xLeft
        !           287:         mov     cPreSrcAdv,0
        !           288:         jae short @F
        !           289:         mov     eax,[edi].xLeft
        !           290:         sub     eax,ecx                 ;diff of left coor and prclClip->xLeft
        !           291:         mov     cPreSrcAdv,eax
        !           292:         add     ecx,eax                 ;ECX = left coordinate = prclClip->xLeft
        !           293: 
        !           294: @@:
        !           295:         xor     eax,eax                 ;diff of right coor and prclClip->xRight
        !           296:         cmp     ebx,[edi].xRight
        !           297:         jbe short @F
        !           298:         mov     eax,ebx
        !           299:         mov     ebx,[edi].xRight        ;EBX = right coor = prclClip->xRight
        !           300:         sub     eax,ebx
        !           301: 
        !           302: @@:
        !           303:         mov     cPostSrcAdv,eax
        !           304:         sub     ebx,ecx                 ;loop count
        !           305: 
        !           306:         mov     edi,ecx
        !           307:         shr     edi,3
        !           308:         add     edi,pjDst               ;point to the first byte to write
        !           309: 
        !           310:         and     ecx,00000111b           ;Compute bit index for left side
        !           311:         mov     ah,080h                 ;Compute bit mask
        !           312:         shr     ah,cl                   ;AL = first pel bit mask
        !           313:         mov     al,GRAF_BIT_MASK
        !           314:         mov     loop_count,bl           ;loop count < 0FFh
        !           315:         mov     ch,01000001b            ;for later use
        !           316:         mov     ebx,pulXlate
        !           317: endm
        !           318: 
        !           319: ;-------------------------------Macro-----------------------------------;
        !           320: ; RleEOL
        !           321: ;
        !           322: ;   Handle the End of line case.
        !           323: ;
        !           324: ; Entry:
        !           325: ;       None.
        !           326: ; Returns:
        !           327: ;       None.
        !           328: ;
        !           329: ;-----------------------------------------------------------------------;
        !           330: 
        !           331: RleEOL  macro   loop_start
        !           332: 
        !           333:         mov     eax,lNextScan
        !           334:         sub     pjDst,eax               ;adjust pjDst
        !           335:         dec     yCurr                   ;adjust yCurr
        !           336:         mov     eax,xStart              ;adjust xCurr
        !           337:         mov     xCurr,eax
        !           338:         jmp     loop_start
        !           339: endm
        !           340: 
        !           341: 
        !           342: ;-------------------------------Macro-----------------------------------;
        !           343: ; Set up banking-related variables, and make sure the bank for the
        !           344: ; initial (bottom) scan line is mapped in.
        !           345: ;
        !           346: ; Entry:
        !           347: ;       None.
        !           348: ; Returns:
        !           349: ;       EBX = pdsurf
        !           350: ;       ESI = pRleInfo
        !           351: ;       EDI = RLE_prctlClip
        !           352: ;
        !           353: ;-------------------------------Macro-----------------------------------;
        !           354: 
        !           355: RleBankSetUp macro
        !           356:         local   map_bank,bank_mapped
        !           357: 
        !           358:         mov     esi,pRleInfo
        !           359:         mov     ebx,[esi].Rle_pdsurfTrg
        !           360:         mov     pdsurf,ebx
        !           361: 
        !           362:         mov     eax,[ebx].dsurf_lNextScan
        !           363:         mov     lNextScan,eax
        !           364: 
        !           365:         mov     edi,[esi].RLE_prctlClip
        !           366:         mov     eax,[edi].yTop
        !           367:         mov     ulTrueClipTop,eax       ;we blt until we reach this scan line
        !           368: 
        !           369: ; Map in the bottom scan line of the clip rect.
        !           370: 
        !           371:         mov     eax,[edi].yBottom       ;bottom clip scan, exclusive
        !           372:         dec     eax                     ;make it inclusive
        !           373:         cmp     eax,[ebx].dsurf_rcl1WindowClip.yTop
        !           374:         jl      short map_bank
        !           375:         cmp     eax,[ebx].dsurf_rcl1WindowClip.yBottom
        !           376:         jl      short bank_mapped
        !           377: map_bank:
        !           378:         ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,eax,JustifyBottom>
        !           379: bank_mapped:
        !           380: 
        !           381:         endm
        !           382: 
        !           383: 
        !           384: ;-------------------------------Macro-----------------------------------;
        !           385: ; Set up the screen pointer and clip the clip rect to the current bank.
        !           386: ;
        !           387: ; Entry:
        !           388: ;       EBX = pdsurf
        !           389: ;       ESI = pRleInfo
        !           390: ;       EDI = RLE_prctlClip
        !           391: ; Returns:
        !           392: ;       None.
        !           393: ;
        !           394: ;-------------------------------Macro-----------------------------------;
        !           395: 
        !           396: RleBankTop macro
        !           397: 
        !           398: ; Convert the screen pointer from an offset within the bitmap to a virtual
        !           399: ; address.
        !           400: 
        !           401:         mov     eax,[ebx].dsurf_pvBitmapStart
        !           402:         add     [esi].RLE_pjTrg,eax
        !           403: 
        !           404: ; Set the clip rect top to MAX(top_of_bank,top_of_clip), to confine drawing to
        !           405: ; this bank.
        !           406: 
        !           407:         mov     eax,[ebx].dsurf_rcl1WindowClip.yTop
        !           408:         cmp     ulTrueClipTop,eax
        !           409:         jl      short @F
        !           410:         mov     eax,ulTrueClipTop
        !           411: @@:
        !           412:         mov     [edi].yTop,eax
        !           413: 
        !           414:         endm
        !           415: 
        !           416: 
        !           417: ;-------------------------------Macro-----------------------------------;
        !           418: ; Check whether we've done the last bank spanned by this clip rect; exit
        !           419: ; if so, map in the bank and continue if not.
        !           420: ;
        !           421: ; Entry:
        !           422: ;       None.
        !           423: ; Returns:
        !           424: ;       EBX = pdsurf
        !           425: ;       ESI = pRleInfo
        !           426: ;       EDI = RLE_prctlClip
        !           427: ;
        !           428: ;-------------------------------Macro-----------------------------------;
        !           429: 
        !           430: RleBankBottom macro     loop_top,done
        !           431: 
        !           432: ; Convert the screen pointer back to an offset within the bitmap.
        !           433: 
        !           434:         mov     ebx,pdsurf
        !           435:         mov     esi,pRleInfo
        !           436:         mov     eax,[ebx].dsurf_pvBitmapStart
        !           437:         sub     [esi].RLE_pjTrg,eax
        !           438: 
        !           439: ; Have we reached the top bank involved in this blt? If so, done; if not, map
        !           440: ; it in and blt the next bank.
        !           441: 
        !           442:         mov     eax,[ebx].dsurf_rcl1WindowClip.yTop
        !           443:         cmp     eax,ulTrueClipTop
        !           444:         jle     &done
        !           445:         dec     eax     ;map in the bank above the current one
        !           446:         ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,eax,JustifyBottom>
        !           447: 
        !           448:         mov     edi,[esi].RLE_prctlClip ;for RleBankTop
        !           449: 
        !           450:         jmp     &loop_top
        !           451: 
        !           452:         endm
        !           453: 
        !           454: 
        !           455: ;--------------------------Public-Routine-------------------------------;
        !           456: ; vRle8ToVga
        !           457: ;
        !           458: ;   Write an RLE8 bitmap onto the VGA device.
        !           459: ;
        !           460: ; Entry:
        !           461: ;       None.
        !           462: ; Returns:
        !           463: ;       None
        !           464: ;
        !           465: ;-----------------------------------------------------------------------;
        !           466: 
        !           467: cProc   vRle8ToVga,4,<       \
        !           468:         uses    esi edi ebx,  \
        !           469:         pRleInfo: ptr RLEINFO >
        !           470: 
        !           471:         local   pjDst       :ptr
        !           472:         local   pulXlate    :ptr
        !           473:         local   xCurr       :dword
        !           474:         local   yCurr       :dword
        !           475:         local   xStart      :dword
        !           476:         local   cPreSrcAdv  :dword
        !           477:         local   cPostSrcAdv :dword
        !           478:         local   prclClip    :ptr RECTL
        !           479:         local   pjSrcEnd    :ptr
        !           480:         local   pdsurf      :ptr DEVSURF
        !           481:         local   ulTrueClipTop :dword
        !           482:         local   lNextScan   : dword
        !           483: 
        !           484:         RleBankSetUp    ;wrap a banking loop around everything
        !           485: 
        !           486: rle8_bank_loop:
        !           487: 
        !           488:         RleBankTop
        !           489: 
        !           490:         RleSetUp
        !           491: 
        !           492: rle8_loop:
        !           493:         cmp     esi,pjSrcEnd
        !           494:         jae     rle8_done
        !           495:         lodsw                           ;fetch a word from src RLE bitmap
        !           496: 
        !           497:         or      al,al
        !           498:         jz      rle8_escape
        !           499: 
        !           500: rle8_encoded:
        !           501:         Clip_Encoded    rle8_done,rle8_loop
        !           502:         Draw_Encoded    rle8_loop
        !           503: 
        !           504: rle8_escape:
        !           505:         cmp     ah,2                    ; First byte is 0, check the second byte.
        !           506:         ja      short rle8_absolute
        !           507:         jb      rle8_end_of_line_or_bitmap
        !           508: 
        !           509: rle8_delta:
        !           510:         RleDelta    rle8_loop
        !           511: 
        !           512: rle8_absolute:
        !           513:         Clip_Absolute   rle8_done,rle8_absolute_advance_src,cl
        !           514:         add     esi,cPreSrcAdv          ;advance esi to point to the clipped run
        !           515: 
        !           516: ; I am doing a per pel loop rather than a per byte loop which writes 1 plane
        !           517: ; at a time because it appears to me that most of the time we output 2 or
        !           518: ; 3 pels per encounter of absolute mode.  The logic here is simple and we can
        !           519: ; stay with M_COLOR_WRITE mode all the time.
        !           520: 
        !           521: rle8_absolute_loop:
        !           522:         mov     dx,VGA_BASE + GRAF_ADDR
        !           523:         out     dx,ax                   ;Set bitmask for altered bit
        !           524: 
        !           525:         movzx   edx,byte ptr [esi]      ;grab color for this pel
        !           526:         inc     esi
        !           527: 
        !           528:         mov     edx,[ebx][edx*4]
        !           529:         xchg    [edi],dl                ;write to destination
        !           530: 
        !           531:         ror     ah,1                    ;rotate bit mask for next pel
        !           532:         cmp     ch,ah                   ;cmp bitmask with 01000001b
        !           533:         adc     edi,0                   ;advance edi if bitmask is 10000000b
        !           534: 
        !           535:         dec     cl                      ;per pel loop
        !           536:         jnz short rle8_absolute_loop
        !           537:         mov     eax,cPostSrcAdv
        !           538: 
        !           539: rle8_absolute_advance_src:
        !           540:         add     esi,eax                 ;advance src ptr for clipped out pels
        !           541:         bt      esi,0                   ;add 1 if not word aligned
        !           542:         adc     esi,0
        !           543:         jmp     rle8_loop
        !           544: 
        !           545: rle8_end_of_line_or_bitmap:
        !           546:         or      ah,ah
        !           547:         jnz short rle8_end_of_bitmap
        !           548: 
        !           549: rle8_end_of_line:
        !           550: 
        !           551:         RleEOL  rle8_loop
        !           552: 
        !           553: rle8_done:
        !           554:         RleExit
        !           555: 
        !           556:         RleBankBottom   rle8_bank_loop,rle8_exit ;see if there are more banks
        !           557:                                                  ; to do
        !           558:         align   4
        !           559: rle8_end_of_bitmap:
        !           560:         RleExit
        !           561: rle8_exit:
        !           562:         cRet    vRle8ToVga
        !           563: 
        !           564: endProc vRle8ToVga
        !           565: 
        !           566: 
        !           567: ;--------------------------Public-Routine-------------------------------;
        !           568: ; vRle4ToVga
        !           569: ;
        !           570: ;   Write an RLE4 bitmap onto the VGA device.
        !           571: ;
        !           572: ; Entry:
        !           573: ;       None
        !           574: ; Returns:
        !           575: ;       None
        !           576: ;
        !           577: ;-----------------------------------------------------------------------;
        !           578: 
        !           579: cProc   vRle4ToVga,4,<       \
        !           580:         uses    esi edi ebx,  \
        !           581:         pRleInfo: ptr RLEINFO >
        !           582: 
        !           583:         local   pjDst       :ptr
        !           584:         local   pulXlate    :ptr
        !           585:         local   xCurr       :dword
        !           586:         local   yCurr       :dword
        !           587:         local   xStart      :dword
        !           588:         local   cPreSrcAdv  :dword
        !           589:         local   cPostSrcAdv :dword
        !           590:         local   pjDstStart  :ptr
        !           591:         local   iPels       :dword
        !           592:         local   xMask       :dword
        !           593:         local   nPels       :byte
        !           594:         local   prclClip    :ptr RECTL
        !           595:         local   pjSrcEnd    :ptr
        !           596:         local   pdsurf      :ptr DEVSURF
        !           597:         local   ulTrueClipTop :dword
        !           598:         local   lNextScan   : dword
        !           599: 
        !           600:         RleBankSetUp    ;wrap a banking loop around everything
        !           601: 
        !           602: rle4_bank_loop:
        !           603: 
        !           604:         RleBankTop
        !           605: 
        !           606:         RleSetUp
        !           607: 
        !           608: rle4_loop:
        !           609:         cmp     esi,pjSrcEnd
        !           610:         jae     rle4_done
        !           611:         lodsw                           ;fetch a word
        !           612: 
        !           613:         or      al,al
        !           614:         jz      rle4_escape
        !           615: 
        !           616: rle4_encoded:
        !           617:         Clip_Encoded    rle4_done,rle4_loop
        !           618: 
        !           619:         mov     dh,dl                   ;separate two colors into dl, dh
        !           620:         and     dl,0Fh
        !           621:         shr     dh,4
        !           622:         cmp     dh,dl
        !           623:         jnz short encoded_diff_color
        !           624:         xor     dh,dh                   ;Draw_Encoded use edx as color index
        !           625:         Draw_Encoded    rle4_loop
        !           626: 
        !           627: encoded_diff_color:
        !           628:         sub     eax,ecx                 ;-eax = #pels clipped away
        !           629:         bt      eax,0
        !           630:         jnc short @F
        !           631:         xchg    dl,dh                   ;xchg colors if odd #pels clipped
        !           632: @@:
        !           633:         mov     iPels,edx               ;save color index
        !           634:         sub     ebx,ecx                 ;Compute extent of interval
        !           635:         dec     ebx                     ;Make interval inclusive
        !           636:         mov     edi,ecx                 ;Don't destroy starting X
        !           637:         shr     edi,3                   ;/8 for byte address
        !           638:         add     edi,pjDst
        !           639: 
        !           640:         and     ecx,00000111b           ;Compute bit index for first byte
        !           641:         mov     eax,00AAAAAAh           ;Compute altered bits mask
        !           642:         shr     eax,cl                  ;AL = left side altered bytes mask
        !           643: 
        !           644:         add     ebx,ecx                 ;Compute bit index for last byte
        !           645:         mov     ecx,ebx                 ;(save for inner loop count)
        !           646:         and     ecx,00000111b
        !           647:         mov     ch,80h
        !           648:         sar     ch,cl
        !           649:         and     al,ch                   ;AL = last byte altered bits mask
        !           650: 
        !           651:         mov     edx,eax
        !           652:         shr     edx,1
        !           653:         and     dl,ch                   ;EDX = mask for 2nd pel
        !           654: 
        !           655:         mov     ecx,ebx
        !           656:         shr     ecx,3                   ;Compute inner byte count
        !           657:         jnz     short comp_byte_dont_combine ;loop count + 1 > 0, check it out
        !           658: 
        !           659: ; Only one byte will be affected.  Combine first/last masks, set loop count = 0
        !           660: 
        !           661:         mov     ebx,eax
        !           662:         shl     eax,16                  ;Will use first byte mask only
        !           663:         and     eax,ebx                 ;AH = first mask. Rest of the bits = 0
        !           664: 
        !           665:         mov     ebx,edx
        !           666:         shl     edx,16                  ;Will use first byte mask only
        !           667:         and     edx,ebx                 ;DH = first mask. Rest of the bits = 0
        !           668:         inc     ecx                     ;Fall through to set 0
        !           669: 
        !           670: comp_byte_dont_combine:
        !           671:         dec     ecx                     ;Dec inner loop count (might become 0)
        !           672: 
        !           673:         xchg    al,ah
        !           674:         ror     eax,16                  ;EAX = last mask:inter mask:first mask:0
        !           675:         xchg    al,ah                   ;for first pel
        !           676:         xchg    dl,dh
        !           677:         ror     edx,16                  ;EDX = last mask:inter mask:first mask:0
        !           678:         xchg    dl,dh                   ;for second pel
        !           679: 
        !           680:         mov     pjDstStart,edi
        !           681:         mov     xMask,edx                ;save mask for the 2nd round
        !           682: 
        !           683:         mov     ebx,pulXlate
        !           684:         mov     edx,iPels
        !           685:         shr     edx,8                   ;index for the first pel
        !           686:         mov     ebx,[ebx][edx*4]
        !           687:         inc     bh                      ;BH = rle4_encoded_diff_color_loop count
        !           688:         inc     bh
        !           689:         mov     dx,VGA_BASE + GRAF_ADDR
        !           690:                                         ;BL = color for first pel
        !           691: rle4_encoded_diff_color_loop:
        !           692:         or      ah,ah                   ;AH = first mask
        !           693:         jz short encoded_inner_diff_color
        !           694: 
        !           695:         mov     al,GRAF_BIT_MASK        ;Set bitmask for altered bits
        !           696:         out     dx,ax
        !           697: 
        !           698:         mov     al,bl
        !           699:         xchg    [edi],al                ;write color
        !           700: encoded_inner_diff_color:
        !           701:         inc     edi                     ;update destination pointer
        !           702:         shr     eax,8                   ;AH = internal mask
        !           703:         or      cl,cl                   ;ECX = inner loop count
        !           704:         jz short encoded_last_byte_diff_color
        !           705: 
        !           706:         mov     ch,cl                   ;save loop count in ch
        !           707:                                         ;loop count always fit in a byte
        !           708:         mov     al,GRAF_BIT_MASK
        !           709:         out     dx,ax                   ;no mask
        !           710: 
        !           711: encoded_loop_diff_color:
        !           712:         mov     al,bl
        !           713:         xchg    [edi],al                ;write color
        !           714:         inc     edi
        !           715:         dec     cl
        !           716:         jnz     encoded_loop_diff_color
        !           717: 
        !           718: encoded_last_byte_diff_color:
        !           719:         shr     eax,8                   ;AH = last mask
        !           720:         or      ah,ah
        !           721:         jz      encoded_this_run_maybe_done
        !           722: 
        !           723:         mov     al,GRAF_BIT_MASK        ;Set bitmask for altered bits
        !           724:         out     dx,ax
        !           725: 
        !           726: encoded_write:
        !           727:         xchg    [edi],bl                ;write color
        !           728: 
        !           729: encoded_this_run_maybe_done:
        !           730:         dec     bh
        !           731:         jz      rle4_loop
        !           732: 
        !           733:         mov     edi,pulXlate
        !           734:         mov     eax,iPels               ;index of the second pel
        !           735:         xor     ah,ah
        !           736:         mov     bl,byte ptr [edi][eax*4]
        !           737:         mov     edi,pjDstStart
        !           738:         mov     eax,xMask               ;load mask
        !           739:         mov     cl,ch                   ;loop count
        !           740: 
        !           741:         jmp     rle4_encoded_diff_color_loop
        !           742: 
        !           743: rle4_escape:
        !           744:         cmp     ah,2                    ; First byte is 0, check the second byte.
        !           745:         ja      rle4_absolute
        !           746:         jb      rle4_end_of_line_or_bitmap
        !           747: 
        !           748: rle4_delta:
        !           749: 
        !           750:         RleDelta    rle4_loop
        !           751: 
        !           752: rle4_absolute:
        !           753:         Clip_Absolute   rle4_done,rle4_absolute_advance_src,nPels
        !           754: 
        !           755: ;advance esi to point to the clipped run
        !           756: 
        !           757:         mov     edx,cPreSrcAdv          ;number of pels to advance
        !           758:         shr     edx,1                   ;number of bytes
        !           759:         jnc     @F
        !           760: 
        !           761:         add     esi,edx                 ;odd number of pels to advance
        !           762:         movzx   edx,byte ptr [esi]      ;grab color for prev and this pels
        !           763:         inc     esi
        !           764:         mov     iPels,edx
        !           765: 
        !           766:         inc     nPels                   ;inc loop count since we start from 1
        !           767:         mov     cl,1
        !           768:         jmp short absolute_loop
        !           769: 
        !           770: @@:                                     ;even number of pels to advance
        !           771:         add     esi,edx
        !           772: 
        !           773: ; I am doing a per pel loop rather than a per byte loop which writes 1 plane
        !           774: ; at a time because it appears to me that most of the time we output 2 or
        !           775: ; 3 pels per encounter of absolute mode.  The logic here is simple and we can
        !           776: ; stay with M_COLOR_WRITE mode all the time.
        !           777: 
        !           778:         xor     cl,cl                   ;initialize loop count
        !           779: 
        !           780: absolute_loop:
        !           781:         mov     dx,VGA_BASE + GRAF_ADDR
        !           782:         out     dx,ax                   ;Set bitmask for altered bit
        !           783: 
        !           784:         bt      cl,0
        !           785:         jc      @F
        !           786: 
        !           787:         movzx   edx,byte ptr [esi]      ;grab color for this and next pels
        !           788:         inc     esi
        !           789: 
        !           790:         mov     iPels,edx               ;save for next pel
        !           791:         shr     dl,4
        !           792:         jmp short   ready_to_draw
        !           793: @@:
        !           794:         mov     edx,iPels               ;second pel
        !           795:         and     dl,0Fh                  ;mask out the second pel
        !           796: 
        !           797: ready_to_draw:
        !           798:         mov     edx,[ebx][edx*4]        ;look up for VGA color
        !           799:         xchg    [edi],dl                ;write to destination
        !           800: 
        !           801:         ror     ah,1                    ;rotate bit mask for next pel
        !           802:         cmp     ch,ah                   ;cmp bitmask with 01000001b
        !           803:         adc     edi,0                   ;advance edi if bitmask is 10000000b
        !           804: 
        !           805:         inc     cl
        !           806:         cmp     cl,nPels
        !           807:         jnz short absolute_loop
        !           808: 
        !           809:         mov     eax,cPostSrcAdv
        !           810: 
        !           811: rle4_absolute_advance_src:
        !           812:         shr     eax,1                   ;2 pels for one byte
        !           813:         add     esi,eax                 ;advance src ptr for clipped out pels
        !           814:         bt      esi,0                   ;add 1 if not word aligned
        !           815:         adc     esi,0
        !           816:         jmp     rle4_loop
        !           817: 
        !           818: 
        !           819: rle4_end_of_line_or_bitmap:
        !           820:         or      ah,ah
        !           821:         jnz short rle4_end_of_bitmap
        !           822: 
        !           823: rle4_end_of_line:
        !           824:         RleEOL  rle4_loop
        !           825: 
        !           826: rle4_done:
        !           827:         RleExit
        !           828: 
        !           829:         RleBankBottom   rle4_bank_loop,rle4_exit ;see if there are more banks
        !           830:                                                  ; to do
        !           831:         align   4
        !           832: rle4_end_of_bitmap:
        !           833:         RleExit
        !           834: rle4_exit:
        !           835:         cRet    vRle4ToVga
        !           836: 
        !           837: endProc vRle4ToVga
        !           838: 
        !           839: ;--------------------------Private-Routine------------------------------;
        !           840: ; comp_byte_interval
        !           841: ;
        !           842: ;   An interval will be computed for byte boundaries.
        !           843: ;
        !           844: ;   A first mask and a last mask will be calculated, and possibly
        !           845: ;   combined into the inner loop count.  If no first byte exists,
        !           846: ;   the start address will be incremented to adjust for it.
        !           847: ;
        !           848: ; Entry:
        !           849: ;       EBX = right coordinate (exclusive)
        !           850: ;       ECX = left coordinate  (inclusive)
        !           851: ; Returns:
        !           852: ;       EDI = offset to first byte to be altered in the scan
        !           853: ;       ECX = inner loop count
        !           854: ;       AL  = first byte mask (possibly 0)
        !           855: ;       AH  = last  byte mask (possibly 0)
        !           856: ; Error Returns:
        !           857: ;       None
        !           858: ; Registers Preserved:
        !           859: ;       ES,BP
        !           860: ; Registers Destroyed:
        !           861: ;       AX,BX,CX,DI,FLAGS
        !           862: ; Calls:
        !           863: ;       None
        !           864: ;
        !           865: ;-----------------------------------------------------------------------;
        !           866: 
        !           867: comp_masks      proc
        !           868: 
        !           869:         sub     ebx,ecx                 ;Compute extent of interval
        !           870:         dec     ebx                     ;Make interval inclusive
        !           871:         mov     edi,ecx                 ;Don't destroy starting X
        !           872:         shr     edi,3                   ;/8 for byte address
        !           873: 
        !           874:         and     ecx,00000111b           ;Compute bit index for left side
        !           875:         mov     al,0FFh                 ;Compute left side altered bits mask
        !           876:         shr     al,cl                   ;AL = left side altered bytes mask
        !           877: 
        !           878:         add     ebx,ecx                 ;Compute bit index for right side
        !           879:         mov     ecx,ebx                 ;(save for inner loop count)
        !           880:         and     ecx,00000111b
        !           881:         mov     ah,80h
        !           882:         sar     ah,cl                   ;AH = right side altered bits mask
        !           883: 
        !           884:         shr     ebx,3                   ;Compute inner byte count
        !           885:         jnz     short comp_byte_dont_combine ;loop count + 1 > 0, check it out
        !           886: 
        !           887: ; Only one byte will be affected.  Combine first/last masks, set loop count = 0
        !           888: 
        !           889:         and     al,ah                   ;Will use first byte mask only
        !           890:         xor     ah,ah                   ;Want last byte mask to be 0
        !           891:         inc     ebx                     ;Fall through to set 0
        !           892: 
        !           893: comp_byte_dont_combine:
        !           894:         dec     ebx                     ;Dec inner loop count (might become 0)
        !           895: 
        !           896: ; If all pixels in the first byte are altered, combine the first byte into the
        !           897: ; inner loop and clear the first byte mask.  Ditto for the last byte mask.
        !           898: 
        !           899:         mov     ecx,0FFFFFFFFh
        !           900:         cmp     al,cl                   ;Set 'C' if not all pixels 1
        !           901:         sbb     ebx,ecx                 ;If no 'C', sub -1 (add 1), else sub 0
        !           902:         cmp     al,cl                   ;Set 'C' if not all pixels 1
        !           903:         sbb     al,cl                   ;If no 'C', sub -1 (add 1), else sub 0
        !           904: 
        !           905:         cmp     ah,cl                   ;Set 'C' if not all pixels 1
        !           906:         sbb     ebx,ecx                 ;If no 'C', sub -1 (add 1), else sub 0
        !           907:         cmp     ah,cl                   ;Set 'C' if not all pixels 1
        !           908:         sbb     ah,cl                   ;If no 'C', sub -1 (add 1), else sub 0
        !           909: 
        !           910:         mov     ecx,ebx                 ;Return inner loop count in ECX
        !           911: 
        !           912:         ret
        !           913: 
        !           914: comp_masks endp
        !           915: 
        !           916:         end
        !           917: 

unix.superglobalmegacorp.com

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