File:  [WindowsNT SDKs] / ntddk / src / video / displays / vga256 / i386 / stretch8.asm
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

;---------------------------Module-Header------------------------------;
; Module Name: stretch.asm
;
; Copyright (c) 1992 Microsoft Corporation
;-----------------------------------------------------------------------;
;-----------------------------------------------------------------------;
; INT vStretchBlt8bpp(PPDEV ppdev, PBYTE pSrc, LONG lSrcNext,
;                     PRECTL prclSrc, PRECTL prclDest, PRECTL prclDestClip,
;                     PULONG pulXlatVector)
; Input:
;
; Performs accelerated stretch blts from 8-bit DIBs to 256-color VGA
; display memory.
;-----------------------------------------------------------------------;
; Note: Does not handle source clipping.
;
; Note: Does not yet handle expansion, only shrinking.
;-----------------------------------------------------------------------;

        comment $

***

Note: in the noxlat loop, EBX isn't altered, so it could be used for
something else, like the scan line count. This isn't done currently
because the scan-line loop is shared by the xlat and noxlat cases, and
the xlat cases do alter EBX; separate loops would be needed in order
to perform this optimization.

        commend $

;-----------------------------------------------------------------------;

                .386

ifndef  DOS_PLATFORM
        .model  small,c
else
ifdef   STD_CALL
        .model  small,c
else
        .model  small,pascal
endif;  STD_CALL
endif;  DOS_PLATFORM

        assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
        assume fs:nothing,gs:nothing

        .xlist
        include stdcall.inc             ;calling convention cmacros
        include i386\strucs.inc
        include i386\driver.inc

        .list

;-----------------------------------------------------------------------;

        .data

;-----------------------------------------------------------------------;

        .code

;-----------------------------------------------------------------------;

cProc vStretchBlt8bpp,28,< \
 uses esi edi ebx,         \
 ppdev:ptr,                \
 pSrc:ptr,                 \
 lSrcNext:dword,           \
 prclSrc:ptr,              \
 prclDest:ptr,             \
 prclDestClip:ptr,         \
 pulXlatVector:dword       >

        local   pulDDAArray:dword       ;pointer to array of n and n+1
                                        ; values generated by DDA, used to
                                        ; advance across source
        local   ulXStretchCount:dword   ;# of pixels or pixel pair to copy to
                                        ; (pixel pairs except in narrow
                                        ; cases; doesn't include leading or
                                        ; trailing single pixels in pixel
                                        ; pair cases)
        local   ulDestNext:dword         ;offset from last dest pixel on one
                                        ; scan to first on next
        local   ulSrcMinNext:dword      ;offset from start of one source scan
                                        ; to start of next scan that's skipped
                                        ; to by minimum DDA advance (basically,
                                        ; skips over n scans when DDA advances
                                        ; either n or n+1 scans)
        local   lYErrorTerm:dword       ;current error term for the DDA in Y
        local   ulYAdjUp:dword          ;error term adjust up for advancing
                                        ; DDA in Y
        local   ulYAdjDown:dword        ;error term adjust down for advancing
                                        ; DDA in Y
        local   ulDstTopScan:dword         ;top scan of dest text rect in
                                        ; current bank
        local   ulDstBottomScan :dword     ;bottom scan line of dest rectangle
        local   ulScanCount:dword       ;# of scans to stretch in current
                                        ; bank
        local   pfnRowVector:dword      ;pointer to routine to be used to
                                        ; stretch each row
        local   pfnStretchFn:dword      ;pointer to routine to do a bank's
                                        ; worth of stretching
        local   ulSrcTopScan:dword      ;top scan line of source from which
                                        ; to copy (after clipping, if needed)
        local   ulYMinStep:dword        ;minimum # of scans to skip in source
                                        ; when advancing dest one scan
        local   lXDstRight:dword        ;right edge of dest area to which to
                                        ; stretch, accounting for clipping
        local   lXDstLeft:dword         ;left edge of dest area to which to
                                        ; stretch, accounting for clipping
        local   ulXAdjUp:dword          ;X error term adjust up
        local   ulXMinStep:dword        ;X minimum step per dest 1-pixel step
        local   ulXAdjDown:dword        ;X error term adjust down
        local   lXSrcRight:dword        ;right edge of source area from which
                                        ; to stretch, accounting for clipping
        local   lXSrcLeft:dword         ;left edge of source area from which to
                                        ; stretch, accounting for clipping

;-----------------------------------------------------------------------;

        mov     esi,prclSrc
        mov     edi,prclDest

        mov     eax,[esi].xRight
        mov     edx,[esi].xLeft
        mov     lXSrcLeft,edx
        sub     eax,edx         ;EAX = source width
        mov     ecx,[edi].xRight
        mov     lXDstRight,ecx
        mov     edx,[edi].xLeft
        mov     lXDstLeft,edx
        sub     ecx,edx         ;ECX = dest width

        cmp     eax,ecx         ;shrink or stretch in X?
        jge     short x_shrink  ;shrink
                                ;stretch
;@@@
DoneFailed:
        sub     eax,eax         ;@@@shouldn't have to return a value
        jmp     done

;The destination is narrower than the source
x_shrink:
        mov     pfnStretchFn,offset shrink_8bpp_loop

;-----------------------------------------------------------------------;
; Precalculate the DDA steps for X and store them in the temp buffer. We know
; these will fit in the temp buffer, because there are only, say, 2K steps
; max across the screen, and the temp buffer is guaranteed to be more than
; 2K*4 = 8K bytes long.
;
; At this point, EAX = source width, ECX = destination width
;-----------------------------------------------------------------------;

        sub     edx,edx         ;prepare for division
        div     ecx             ;SourceDeltaX / DestDeltaX
        mov     ulXMinStep,eax  ;EAX = minimum step in source for 1 dest step

        mov     esi,edx         ;set aside SourceDeltaX % DestDeltaX
        add     edx,edx         ;scale up ulXAdjUp by 2 so we can handle a
                                ; half-pixel advance
        mov     ulXAdjUp,edx    ;ulXAdjUp = (SourceDeltaX % DestDeltaX)*2

                                ;prestep source X coord and error term by 1/2
                                ; a destination pixel, so we pick the source
                                ; pixel that most closely matches the center
                                ; of each destination pixel

                                ;step by 1/2 the whole source pixel advance
                                ; per destination step
        shr     eax,1           ;minimum step/2
        jnc     short @F        ;odd
                                ;even
        add     esi,ecx         ;advance error term for 1/2 of the source
                                ; pixel we just split (by DestDeltaX)
@@:
        add     lXSrcLeft,eax   ;advance 1/2 minimum step in source
        add     ecx,ecx         ;scale up DestDeltaX by 2 so we can handle a
                                ; half-pixel advance
        mov     ulXAdjDown,ecx  ;ulXAdjDown = DestDeltaX*2

        sub     esi,ecx         ;initial error term = -(DestDeltaX*2) + 1/2
                                ; normal error term step (for 1/2 pixel dest
                                ; advance effect on error term; note that 1/2
                                ; effect on whole source pixels has already
                                ; been accounted for)

;-----------------------------------------------------------------------;
; Clip to the dest in X, if necessary.
;-----------------------------------------------------------------------;

        mov     ebx,prclDestClip
        and     ebx,ebx                 ;any clipping?
        jz      short x_clip_done       ;no, all set
        mov     eax,[ebx].xRight        ;right clip edge
        cmp     eax,lXDstRight          ;is the right edge clipped?
        jge     short check_x_left_clip ;no
                                        ;right edge is clipped
        mov     lXDstRight,eax          ;set the clipped right edge
check_x_left_clip:
        mov     eax,[ebx].xLeft         ;left clip edge
        cmp     eax,lXDstLeft           ;is the left edge clipped?
        jle     short check_x_not_fully_clipped ;no
                                        ;left edge is clipped
        mov     edx,lXDstLeft           ;get the unclipped dest left edge
        mov     lXDstLeft,eax           ;set the clipped dest left edge
                                        ;now figure out how many source pixels
                                        ; were clipped, and advance the error
                                        ; term appropriately
        sub     eax,edx                 ;# of dest pixels clipped
        mov     ecx,eax                 ;set aside # of dest pixels to skip
        mul     ulXAdjUp                ;# of adjust ups in the course of the
                                        ; skipped pixels
        add     esi,eax                 ;EDX:ESI = error term after skipping
        adc     edx,-1                  ;(the initial error term is negative;
                                        ; this stretches it to 64 bits)
        jnc     short check_x_not_fully_clipped ;didn't turn over even once
        mov     eax,esi                 ;EDX:EAX = error term after skipping
        div     ulXAdjDown              ;EAX = # of times to adjust down
                                        ; while skipping pixels, minus 1
        sub     edx,ulXAdjDown          ;do the last adjust down, to cross
                                        ; back into negative territory where
                                        ; the error term belongs
        mov     esi,edx                 ;error term at new, clipped dest left
                                        ; edge
        inc     eax                     ;count the last adjust down (# of times
                                        ; source error turned over while
                                        ; advancing to the clipped left edge)
        imul    ecx,ulXMinStep          ;# of whole pixels skipped in source
                                        ; while advancing to dest clip left
                                        ; edge
        add     eax,ecx                 ;total # of pixels skipped in source
                                        ; while advancing to dest clip left
                                        ; edge
        add     lXSrcLeft,eax           ;advance the source left edge to match
                                        ; advancing the destination left edge
                                        ; to the left edge of the clip
                                        ; rectangle
check_x_not_fully_clipped:
        mov     eax,lXDstLeft
        cmp     lXDstRight,eax          ;is the destination fully x-clipped?
        jle     done                    ;yes, nothing to draw
x_clip_done:

;-----------------------------------------------------------------------;
; Now actually generate the (possibly clipped) X DDA skip array
;
; At this point, ESI = X error term for left edge (accounting for any
; X clipping that has occurred)
;-----------------------------------------------------------------------;

        mov     edx,ppdev
        mov     eax,ulXMinStep
        mov     edi,[edx].pdev_pvTmp ;we'll store the DDA steps in the temp
        mov     pulDDAArray,edi      ; buffer

        mov     edx,ulXAdjUp
        mov     ebx,ulXAdjDown
        mov     ecx,lXDstRight
        sub     ecx,lXDstLeft   ;ECX = # of pixels per dest scan
        push    ecx             ;remember # of dest pixels across
        push    ebp             ;preserve stack frame pointer
        lea     ebp,[eax+1]     ;maximum step
                                ;***stack frame unavailable***
x_shrink_set_dda_loop:
        add     esi,edx         ;adjust the error term up
        jnc     short x_shrink_set_dda_min ;didn't turn over, so advance
                                           ; minimum step
x_shrink_set_dda_max:
        sub     esi,ebx         ;turned over; adjust error term back down
        mov     [edi],ebp       ;advance by maximum step
        add     edi,4           ;point to next DDA array storage location
        dec     ecx             ;count down steps
        jz      short x_shrink_set_dda_done ;no more steps
        add     esi,edx         ;adjust the error term up
        jc      x_shrink_set_dda_max ;did turn over, so advance maximum step
x_shrink_set_dda_min:
        mov     [edi],eax       ;advance by minimum step
        add     edi,4           ;point to next DDA array storage location
        dec     ecx             ;count down steps
        jnz     x_shrink_set_dda_loop
x_shrink_set_dda_done:
        mov     dword ptr [edi],0 ;mark the end of the DDA
        pop     ebp             ;restore stack frame pointer
                                ;***stack frame available***
        pop     ecx             ;retrieve # of dest pixels across

        mov     edi,prclDest
        cmp     pulXlatVector,0         ;translation?
        jz      short x_shrink_noxlat   ;no
                                        ;yes
        cmp     ecx,3           ;narrow case?
        ja      short @F        ;no
        mov     pfnRowVector,offset shrink_xlat_8bpp_narrow     ;narrow case
        mov     ulXStretchCount,ecx     ;do all dest pixels one at a time
        jmp     check_y_shrink
@@:                             ;not narrow case; figure out which wide case,
                                ; based on the need to perform as many word-
                                ; aligned writes to display memory as possible
        mov     edx,ecx
        test    [edi].xLeft,1   ;starting at an odd destination address?
        jnz     short x_shrink_xlat_leading ;yes, need leading pixel
        mov     pfnRowVector,offset shrink_xlat_8bpp_nl_nt
                                        ;assume no leading or trailing pixels
        shr     edx,1                   ;destination width in pixel pairs
        mov     ulXStretchCount,edx     ;count of pixel pairs to draw
        jnc     short check_y_shrink  ;no leading or trailing pixels
        mov     pfnRowVector,offset shrink_xlat_8bpp_nl_t
                                        ;no leading pixel, is a trailing pixel
        jmp     short check_y_shrink
x_shrink_xlat_leading:                  ;there is a leading pixel
        mov     pfnRowVector,offset shrink_xlat_8bpp_l_nt
                                        ;assume no trailing pixel
        shr     edx,1                   ;destination width in pixel pairs
        mov     ulXStretchCount,edx     ;count of pixel pairs to draw
        jc      short check_y_shrink  ;no trailing pixel
        mov     pfnRowVector,offset shrink_xlat_8bpp_l_t
                                        ;both leading and trailing pixels
        dec     edx                     ;we'll do one pixel pair in the form
                                        ; of the leading/trailing pixel pair
        mov     ulXStretchCount,edx     ;count of pixel pairs to draw
        jmp     short check_y_shrink

x_shrink_noxlat:                        ;no translation
        cmp     ecx,3           ;narrow case?
        ja      short @F        ;no
        mov     pfnRowVector,offset shrink_noxlat_8bpp_narrow   ;narrow case
        mov     ulXStretchCount,ecx     ;do all dest pixels one at a time
        jmp     short check_y_shrink
@@:                             ;not narrow case; figure out which wide case,
                                ; based on the need to perform as many word-
                                ; aligned writes to display memory as possible
        mov     edx,ecx
        test    [edi].xLeft,1   ;starting at an odd destination address?
        jnz     short x_shrink_noxlat_leading ;yes, need leading pixel
        mov     pfnRowVector,offset shrink_noxlat_8bpp_nl_nt
                                        ;assume no leading or trailing pixels
        shr     edx,1                   ;destination width in pixel pairs
        mov     ulXStretchCount,edx     ;count of pixel pairs to draw
        jnc     short check_y_shrink  ;no leading or trailing pixels
        mov     pfnRowVector,offset shrink_noxlat_8bpp_nl_t
                                        ;no leading pixel, is a trailing pixel
        jmp     short check_y_shrink
x_shrink_noxlat_leading:                ;there is a leading pixel
        mov     pfnRowVector,offset shrink_noxlat_8bpp_l_nt
                                        ;assume no trailing pixel
        shr     edx,1                   ;destination width in pixel pairs
        mov     ulXStretchCount,edx     ;count of pixel pairs to draw
        jc      short check_y_shrink  ;no trailing pixel
        mov     pfnRowVector,offset shrink_noxlat_8bpp_l_t
                                        ;both leading and trailing pixels
        dec     edx                     ;we'll do one pixel pair in the form
                                        ; of the leading/trailing pixel pair
        mov     ulXStretchCount,edx     ;count of pixel pairs to draw

check_y_shrink:

        mov     esi,edi                 ;ESI->prclDest
        mov     edi,prclSrc             ;EDI->prclSrc
        mov     eax,[edi].yBottom
        mov     ecx,[edi].yTop
        mov     ulSrcTopScan,ecx
        sub     eax,ecx                 ;EAX = source height
        mov     ecx,[esi].yBottom
        mov     ulDstBottomScan,ecx
        mov     edx,[esi].yTop
        mov     ulDstTopScan,edx
        sub     ecx,edx         ;ECX = dest height

        cmp     eax,ecx         ;shrink or stretch in Y?
        jge     short y_shrink  ;shrink
                                ;stretch
;@@@
        sub     eax,eax         ;@@@shouldn't have to return a value
        jmp     done

;The destination is shorter than the source; calculate the error term values
; for advancing through the source on a per-dest-scan-line basis.
y_shrink:
        sub     edx,edx         ;prepare for division
        div     ecx             ;SourceDeltaY/DestDeltaY
        mov     ulYMinStep,eax  ;EAX = minimum step in source for 1 dest step

        mov     ebx,edx         ;set aside SourceDeltaY % DestDeltaY
        add     edx,edx         ;scale up ulYAdjUp by 2 so we can handle a
                                ; half-pixel advance
        mov     ulYAdjUp,edx    ;ulYAdjUp = (SourceDeltaY % DestDeltaY)*2

        imul    lSrcNext        ;(minimum step * source scan width in bytes)
        mov     ulSrcMinNext,eax ; = minimum offset by which to advance from
                                 ; one scan to the next

                                ;prestep source X coord and error term by 1/2
                                ; a destination pixel, so we pick the source
                                ; pixel that most closely matches the center
                                ; of each destination pixel

                                ;step by 1/2 the whole source pixel advance
                                ; per destination step
        mov     eax,ulYMinStep  ;retrieve minimum step
        shr     eax,1           ;minimum step/2
        jnc     short @F        ;odd
                                ;even
        add     ebx,ecx         ;advance error term for 1/2 of the source
                                ; pixel we just split
@@:
        add     ulSrcTopScan,eax ;advance 1/2 minimum step in source

        add     ecx,ecx         ;scale up DestDeltaY by 2 so we can handle a
                                ; half-pixel advance
        mov     ulYAdjDown,ecx  ;ulYAdjDown = DestDeltaY*2

        sub     ebx,ecx         ;initial error term = -(DestDeltaY*2) + 1/2
                                ; normal error term step (for 1/2 pixel dest
                                ; advance effect on error term; note that 1/2
                                ; effect on whole source pixels has already
                                ; been accounted for)
        mov     lYErrorTerm,ebx

;-----------------------------------------------------------------------;
; Clip in Y, if necessary.
;-----------------------------------------------------------------------;

        mov     ebx,prclDestClip
        and     ebx,ebx                 ;any clipping?
        jz      short y_clip_done       ;no, all set
        mov     eax,[ebx].yBottom       ;yes, clipping
                                        ;see if the dest is clipped off the
                                        ; bottom
        cmp     ulDstBottomScan,eax     ;is the bottom clipped?
        jle     short check_y_top_clip  ;no, check the top
        mov     ulDstBottomScan,eax     ;yes, set the new bottom
check_y_top_clip:
                                        ;see if the dest is clipped off the
                                        ; top
        mov     eax,[ebx].yTop
        cmp     ulDstTopScan,eax        ;is the top clipped?
        jge     short check_y_not_fully_clipped ;no
                                        ;yes, so advance the top scan and the
                                        ; error term accordingly
        mov     ulDstTopScan,eax        ;top of clipped destination rectangle
        sub     eax,[esi].yTop          ;# of destination scans to skip
        mov     ecx,eax                 ;set aside # of dest scans to skip
        mul     ulYAdjUp                ;# of adjust ups in the course of the
                                        ; skipped scans
        add     eax,lYErrorTerm         ;EDX:EAX = error term after skipping
        adc     edx,-1                  ;(the initial error term is negative;
                                        ; this stretches it to 64 bits)
        jnc     short check_y_not_fully_clipped ;didn't turn over even once
        div     ulYAdjDown              ;EAX = # of times to adjust down
                                        ; while skipping scans, minus 1
        sub     edx,ulYAdjDown          ;do the last adjust down, to cross
                                        ; back into negative territory where
                                        ; the error term belongs
        mov     lYErrorTerm,edx         ;error term at new, clipped dest top
        inc     eax                     ;count the last adjust down (# of
                                        ; times source error has turned over)
        imul    ecx,ulYMinStep          ;# of whole steps in source while
                                        ; advancing to dest clip top
        add     eax,ecx                 ;total # of scans skipped in source
                                        ; while advancing to dest clip top
        add     ulSrcTopScan,eax        ;advance the source top edge to match
                                        ; advancing the destination top edge to
                                        ; the top of the clip rectangle
check_y_not_fully_clipped:
        mov     eax,ulDstTopScan
        cmp     ulDstBottomScan,eax        ;is the destination fully y-clipped?
        jle     done                    ;yes, nothing to draw
y_clip_done:

;-----------------------------------------------------------------------;
; Calculate the offset of the initial destination pixel.
;-----------------------------------------------------------------------;

        mov     ebx,ppdev
        mov     eax,ulDstTopScan   ;top scan line of text
        mov     esi,[ebx].pdev_lDeltaScreen
        mul     esi
        mov     edi,lXDstLeft
        mov     ecx,lXDstRight
        sub     ecx,edi         ;dest width
        sub     esi,ecx         ;dest width - width of a dest scan to stretch
        mov     ulDestNext,esi  ;offset from end of one dest stretched
                                ; scan to start of next
        add     edi,eax

;-----------------------------------------------------------------------;
; Map in the bank containing the top scan of the text, if it's not
; mapped in already.
;-----------------------------------------------------------------------;

        mov     eax,ulDstTopScan   ;top scan line of text
        cmp     eax,[ebx].pdev_rcl1WindowClip.yTop ;is text top less than
                                                   ; current bank?
        jl      short map_init_bank                ;yes, map in proper bank
        cmp     eax,[ebx].pdev_rcl1WindowClip.yBottom ;text top greater than
                                                      ; current bank?
        jl      short init_bank_mapped        ;no, proper bank already mapped
map_init_bank:

; Map in the bank containing the top scan line of the destination.
; Preserves EBX, ESI, and EDI.

        ptrCall <dword ptr [ebx].pdev_pfnBankControl>,<ebx,eax,JustifyTop>

init_bank_mapped:

        add     edi,[ebx].pdev_pvBitmapStart    ;initial destination address

;-----------------------------------------------------------------------;
; Calculate the offset of the initial source pixel.
;-----------------------------------------------------------------------;

        mov     esi,prclSrc
        mov     eax,lSrcNext
        imul    ulSrcTopScan
        mov     esi,lXSrcLeft
        add     esi,eax
        add     esi,pSrc

;-----------------------------------------------------------------------;
; Main loop for processing stretch blt in each bank.
;
; At start of loop, EBX->ppdev, ESI->current src, EDI->current dst
;-----------------------------------------------------------------------;

bank_loop:
        mov     edx,ulDstBottomScan        ;bottom of destination rectangle
        cmp     edx,[ebx].pdev_rcl1WindowClip.yBottom
                                        ;which comes first, the bottom of the
                                        ; text rect or the bottom of the
                                        ; current bank?
        jl      short @F                ;text bottom comes first, so draw to
                                        ; that; this is the last bank in text
        mov     edx,[ebx].pdev_rcl1WindowClip.yBottom
                                        ;bank bottom comes first; draw to
                                        ; bottom of bank
@@:
        sub     edx,ulDstTopScan           ;# of scans to draw in bank
        mov     ulScanCount,edx

        call    pfnStretchFn    ;stretch the bitmap block that's in this bank

;-----------------------------------------------------------------------;
; See if there are more banks to draw.
;-----------------------------------------------------------------------;

        mov     ebx,ppdev
        mov     eax,[ebx].pdev_rcl1WindowClip.yBottom ;is the text bottom in
        cmp     ulDstBottomScan,eax                   ; the current bank?
        jnle    short do_next_bank      ;no, map in the next bank and draw
        mov     eax,1                   ;success
                                        ;@@@shouldn't return a value
done:
        cRet    vStretchBlt8bpp         ;yes, so we're done

        align   4
do_next_bank:
        mov     ulDstTopScan,eax
        sub     edi,[ebx].pdev_pvBitmapStart ;convert from address to offset
                                             ; within bitmap
        ptrCall <dword ptr [ebx].pdev_pfnBankControl>,<ebx,eax,JustifyTop>
                                             ;map in the bank (call preserves
                                             ; EBX, ESI, and EDI)
        add     edi,[ebx].pdev_pvBitmapStart ;convert from offset within bitmap
                                             ; to address (bitmap start just
                                             ; moved)
        jmp     bank_loop                    ;we're ready to draw to the new
                                             ; bank

;-----------------------------------------------------------------------;
; Shrink in X and Y, xlat or noxlat, 8-bpp source, VGA dest
;
; On entry: ESI->first source pixel to copy from
;           EDI->first dest pixel to copy to
;           pulXlatVector = pointer to color translation array (xlat cases
;                           only)
;           ulSrcMinNext = minimum offset from end of current source scan to
;                          start of next source scan to stretch
;           lSrcNext = offset from start of one source scan to start of next
;           ulDestNext = offset from end of current dest scan to start of
;                        next dest scan to stretch to
;           pfnRowVector = pointer to routine to call to stretch one scan
;           ulScanCount = # of scans to stretch
;           lYErrorTerm, ulYAdjUp, ulYAdjDown = Y DDA error term components
;
; On exit:  ESI->next source pixel to copy from
;           EDI->next dest pixel to copy to
;           lYErrorTerm advanced for next scan
;-----------------------------------------------------------------------;

shrink_8bpp_loop:
        sub     ebx,ebx         ;prepare EBX=0 for xlat-case row-drawing
                                ; routines
shrink_block_8bpp_loop:
        mov     edx,pulDDAArray ;point to array of skip values to use to scan
                                ; across the source
        mov     ecx,ulXStretchCount ;# of pixels or pixel pairs to copy to
        push    esi             ;preserve source pointer
        call    pfnRowVector    ;stretch/shrink this row
        pop     esi             ;restore source pointer
        add     esi,ulSrcMinNext ;point to start of next source row, assuming
                                 ; no extra row for error term turnover
        mov     eax,lYErrorTerm
        add     eax,ulYAdjUp    ;advance the error term
        jnc     short @F        ; didn't turn over (minimum step)
        sub     eax,ulYAdjDown  ;turned over, adjust down and...
        add     esi,lSrcNext    ; advance an extra scan (maximum step)
@@:
        mov     lYErrorTerm,eax ;remember the new error term
        add     edi,ulDestNext  ;point to start of next destination row
        dec     ulScanCount     ;count down scans
        jnz     shrink_block_8bpp_loop
        retn

;-----------------------------------------------------------------------;
; Single-row optimizations, called out of main stretch loops.
;-----------------------------------------------------------------------;

;-----------------------------------------------------------------------;
; Shrink in X
; No xlat
; 8-bit source
; Writes a word at a time
;
; Input: ECX = number of pixel pairs to do, not counting leading and trailing
;              single pixels (except in narrow case, where ECX = number of
;              pixels, not pixel pairs)
;        EDX = pointer to pre-computed skip array
;        ESI = pointer to initial source pixel
;        EDI = pointer to initial destination pixel
;
; Output: ESI = pointer after last source pixel processed
;         EDI = pointer after last source pixel processed
;
; EBX and EBP are preserved
; The contents of EAX, ECX, and EDX may be destroyed
;-----------------------------------------------------------------------;

; No leading byte, no trailing byte.

shrink_noxlat_8bpp_nl_nt:
shrink_noxlat_8bpp_nl_nt_pixel_loop:
        mov     al,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     ah,[esi]        ;get second source pixel
        add     esi,[edx+4]     ;point to next source pixel
        add     edx,8           ;point to next skip entry
        mov     [edi],ax        ;write both pixels to the destination
        add     edi,2           ;point to next destination pixel
        dec     ecx             ;count down pixel pairs
        jnz     shrink_noxlat_8bpp_nl_nt_pixel_loop
        retn

; Leading byte, no trailing byte.

shrink_noxlat_8bpp_l_nt:
                                ;do the leading pixel
        mov     al,[esi]        ;get the current source pixel
        add     esi,[edx]       ;point to next source pixel
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
                                ;now do pixel pairs across the middle
shrink_noxlat_8bpp_l_nt_pixel_loop:
        mov     al,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     ah,[esi]        ;get second source pixel
        add     esi,[edx+4]     ;point to next source pixel
        add     edx,8           ;point to next skip entry
        mov     [edi],ax        ;write both pixels to the destination
        add     edi,2           ;point to next destination pixel
        dec     ecx             ;count down pixel pairs
        jnz     shrink_noxlat_8bpp_l_nt_pixel_loop
        retn

; Leading byte, trailing byte.

shrink_noxlat_8bpp_l_t:
                                ;do the leading pixel
        mov     al,[esi]        ;get current source pixel
        add     esi,[edx]       ;point to next source pixel
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
                                ;now do pixel pairs across the middle
shrink_noxlat_8bpp_l_t_pixel_loop:
        mov     al,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     ah,[esi]        ;get second source pixel
        add     esi,[edx+4]     ;point to next source pixel
        add     edx,8           ;point to next skip entry
        mov     [edi],ax        ;write both pixels to the destination
        add     edi,2           ;point to next destination pixel
        dec     ecx             ;count down pixel pairs
        jnz     shrink_noxlat_8bpp_l_t_pixel_loop
                                ;do the trailing pixel
        mov     al,[esi]        ;get current source pixel
        add     esi,[edx]       ;point to next source pixel
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
        retn

; No leading byte, trailing byte.

shrink_noxlat_8bpp_nl_t:
shrink_noxlat_8bpp_nl_t_pixel_loop:
        mov     al,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     ah,[esi]        ;get second source pixel
        add     esi,[edx+4]     ;point to next source pixel
        add     edx,8           ;point to next skip entry
        mov     [edi],ax        ;write both pixels to the destination
        add     edi,2           ;point to next destination pixel
        dec     ecx             ;count down pixel pairs
        jnz     shrink_noxlat_8bpp_nl_t_pixel_loop
                                ;do the trailing pixel
        mov     al,[esi]        ;get current source pixel
        add     esi,[edx]       ;point to next source pixel
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
        retn

; Narrow case, a byte at a time.

shrink_noxlat_8bpp_narrow:
shrink_noxlat_8bpp_narrow_pixel_loop:
        mov     al,[esi]        ;get current source pixel
        add     esi,[edx]       ;point to next source pixel
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
        dec     ecx             ;count down pixels
        jnz     shrink_noxlat_8bpp_narrow_pixel_loop
        retn

;-----------------------------------------------------------------------;
; Shrink in X
; Xlat
; 8-bit source
; Writes a word at a time
;
; Input: EBX upper three bytes = zero (0)
;        ECX = number of pixel pairs to do, not counting leading and trailing
;              single pixels (except in narrow case, where ECX = number of
;              pixels, not pixel pairs)
;        EDX = pointer to pre-computed skip array
;        ESI = pointer to initial source pixel
;        EDI = pointer to initial destination pixel
;        pulXlatVector = pointer to color translation array
;
; Output: ESI = pointer after last source pixel processed
;         EDI = pointer after last source pixel processed
;
; EBP is preserved
; The upper three bytes of EBX are preserved
; The contents of EAX, BL, ECX, and EDX may be destroyed
;-----------------------------------------------------------------------;

; No leading byte, no trailing byte.

shrink_xlat_8bpp_nl_nt:
        push    ebp             ;***stack frame not available***
        mov     ebp,pulXlatVector ;point EBP to the translation table
shrink_xlat_8bpp_nl_nt_pixel_loop:
        mov     bl,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     eax,[ebp+ebx*4] ;translate the pixel color
        mov     bl,[esi]        ;get second source pixel
        add     esi,[edx+4]     ;point to next source pixel
        mov     ah,[ebp+ebx*4]  ;translate the pixel color
        add     edx,8           ;point to next skip entry
        mov     [edi],ax        ;write both pixels to the destination
        add     edi,2           ;point to next destination pixel
        dec     ecx             ;count down pixel pairs
        jnz     shrink_xlat_8bpp_nl_nt_pixel_loop
        pop     ebp             ;***stack frame available***
        retn

; Leading byte, no trailing byte.

shrink_xlat_8bpp_l_nt:
        push    ebp             ;***stack frame not available***
        mov     ebp,pulXlatVector ;point EBP to the translation table
                                ;do the leading pixel
        mov     bl,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     eax,[ebp+ebx*4] ;translate the pixel color
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
                                ;now do pixel pairs across the middle
shrink_xlat_8bpp_l_nt_pixel_loop:
        mov     bl,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     eax,[ebp+ebx*4] ;translate the pixel color
        mov     bl,[esi]        ;get second source pixel
        add     esi,[edx+4]     ;point to next source pixel
        mov     ah,[ebp+ebx*4]  ;translate the pixel color
        add     edx,8           ;point to next skip entry
        mov     [edi],ax        ;write both pixels to the destination
        add     edi,2           ;point to next destination pixel
        dec     ecx             ;count down pixel pairs
        jnz     shrink_xlat_8bpp_l_nt_pixel_loop
        pop     ebp             ;***stack frame available***
        retn

; Leading byte, trailing byte.

shrink_xlat_8bpp_l_t:
        push    ebp             ;***stack frame not available***
        mov     ebp,pulXlatVector ;point EBP to the translation table
                                ;do the leading pixel
        mov     bl,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     eax,[ebp+ebx*4] ;translate the pixel color
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
                                ;now do pixel pairs across the middle
shrink_xlat_8bpp_l_t_pixel_loop:
        mov     bl,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     eax,[ebp+ebx*4] ;translate the pixel color
        mov     bl,[esi]        ;get second source pixel
        add     esi,[edx+4]     ;point to next source pixel
        mov     ah,[ebp+ebx*4]  ;translate the pixel color
        add     edx,8           ;point to next skip entry
        mov     [edi],ax        ;write both pixels to the destination
        add     edi,2           ;point to next destination pixel
        dec     ecx             ;count down pixel pairs
        jnz     shrink_xlat_8bpp_l_t_pixel_loop
                                ;do the trailing pixel
        mov     bl,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     eax,[ebp+ebx*4] ;translate the pixel color
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
        pop     ebp             ;***stack frame available***
        retn

; No leading byte, trailing byte.

shrink_xlat_8bpp_nl_t:
        push    ebp             ;***stack frame not available***
        mov     ebp,pulXlatVector ;point EBP to the translation table
shrink_xlat_8bpp_nl_t_pixel_loop:
        mov     bl,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     eax,[ebp+ebx*4] ;translate the pixel color
        mov     bl,[esi]        ;get second source pixel
        add     esi,[edx+4]     ;point to next source pixel
        mov     ah,[ebp+ebx*4]  ;translate the pixel color
        add     edx,8           ;point to next skip entry
        mov     [edi],ax        ;write both pixels to the destination
        add     edi,2           ;point to next destination pixel
        dec     ecx             ;count down pixel pairs
        jnz     shrink_xlat_8bpp_nl_t_pixel_loop
                                ;do the trailing pixel
        mov     bl,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     eax,[ebp+ebx*4] ;translate the pixel color
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
        pop     ebp             ;***stack frame available***
        retn
; Narrow case, a byte at a time.

shrink_xlat_8bpp_narrow:
        push    ebp             ;***stack frame not available***
        mov     ebp,pulXlatVector ;point EBP to the translation table
shrink_xlat_8bpp_narrow_loop:
        mov     bl,[esi]        ;get first source pixel
        add     esi,[edx]       ;point to next source pixel
        mov     eax,[ebp+ebx*4] ;translate the pixel color
        add     edx,4           ;point to next skip entry
        mov     [edi],al        ;write the pixel to the destination
        inc     edi             ;point to next destination pixel
        dec     ecx             ;count down pixels
        jnz     shrink_xlat_8bpp_narrow_loop
        pop     ebp             ;***stack frame available***
        retn

endProc vStretchBlt8bpp

public DoneFailed
public x_shrink
public check_y_shrink
public x_shrink_set_dda_loop
public x_shrink_set_dda_max
public x_shrink_set_dda_min
public x_shrink_set_dda_done
public y_shrink
public map_init_bank
public init_bank_mapped
public bank_loop
public done
public do_next_bank
public shrink_8bpp_loop
public shrink_block_8bpp_loop
public shrink_noxlat_8bpp_nl_nt
public shrink_noxlat_8bpp_nl_nt_pixel_loop
public shrink_noxlat_8bpp_l_nt
public shrink_noxlat_8bpp_l_nt_pixel_loop
public shrink_noxlat_8bpp_l_t
public shrink_noxlat_8bpp_l_t_pixel_loop
public shrink_noxlat_8bpp_nl_t
public shrink_noxlat_8bpp_nl_t_pixel_loop
public shrink_noxlat_8bpp_narrow
public shrink_noxlat_8bpp_narrow_pixel_loop
public shrink_xlat_8bpp_nl_nt
public shrink_xlat_8bpp_nl_nt_pixel_loop
public shrink_xlat_8bpp_l_nt
public shrink_xlat_8bpp_l_nt_pixel_loop
public shrink_xlat_8bpp_l_t
public shrink_xlat_8bpp_l_t_pixel_loop
public shrink_xlat_8bpp_nl_t
public shrink_xlat_8bpp_nl_t_pixel_loop
public shrink_xlat_8bpp_narrow
public shrink_xlat_8bpp_narrow_loop

        end


unix.superglobalmegacorp.com

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