;---------------------------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 local pvBuf:dword ;local copy of ppdev->pvTmpBuf ptr ;-----------------------------------------------------------------------; mov esi,ppdev mov edi,[esi].pdev_pvTmpBuf mov pvBuf,edi 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 eax,ulXMinStep mov edi,pvBuf ;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 , 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 do_next_bank:: mov ulDstTopScan,eax sub edi,[ebx].pdev_pvBitmapStart ;convert from address to offset ; within bitmap ptrCall , ;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