File:  [WindowsNT SDKs] / ntddk / src / video / displays / vga / i386 / cpybits.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

;!!! This is all temp crap to be replaced when the blinker is written

;---------------------------Module-Header------------------------------;
; Module Name: cpybits.asm
;
; Copyright (c) 1992 Microsoft Corporation
;-----------------------------------------------------------------------;
        page    ,132
        title   DrvCopyBits Support
        .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\egavga.inc         ;VGA register definitions
        include i386\strucs.inc
        .list


        .data

; Reuse the work area from the dib conversion code.

; BUGBUG this should be allocated memory accessed via the DEVSURF, not static

        extrn   ajConvertBuffer:byte    ;Buffer for converting to/from display

; BUGBUG this should be dynamically calculated

CJ_WORK_PLANE   equ     cj_max_scan+1   ;Width of each plane in ajConvertBuffer

        .code

; ausLo16 is used to convert the low nibble of a byte into 4bpp packed pel

ausLo16 equ this word

        dw          0000h                   ;0000
        dw          0100h                   ;0001
        dw          1000h                   ;0010
        dw          1100h                   ;0011
        dw          0001h                   ;0100
        dw          0101h                   ;0101
        dw          1001h                   ;0110
        dw          1101h                   ;0111
        dw          0010h                   ;1000
        dw          0110h                   ;1001
        dw          1010h                   ;1010
        dw          1110h                   ;1011
        dw          0011h                   ;1100
        dw          0111h                   ;1101
        dw          1011h                   ;1110
        dw          1111h                   ;1111

; aulHi16 is used to convert the hi nibble of a byte into 4bpp packed pel

aulHi16 equ this dword

        dd          00000000h               ;0000
        dd          01000000h               ;0001
        dd          10000000h               ;0010
        dd          11000000h               ;0011
        dd          00010000h               ;0100
        dd          01010000h               ;0101
        dd          10010000h               ;0110
        dd          11010000h               ;0111
        dd          00100000h               ;1000
        dd          01100000h               ;1001
        dd          10100000h               ;1010
        dd          11100000h               ;1011
        dd          00110000h               ;1100
        dd          01110000h               ;1101
        dd          10110000h               ;1110
        dd          11110000h               ;1111

; ajRightMasks turns an exclusive bit position (0-7) into a mask of bits
; to alter for the right hand side of the blt

ajRightMasks equ this byte

        db          11111111b               ;0 should never be used
        db          01111111b               ;1
        db          00111111b               ;2
        db          00011111b               ;3
        db          00001111b               ;4
        db          00000111b               ;5
        db          00000011b               ;6
        db          00000001b               ;7

; ajLeftMasks turns a bit position (0-7) into a mask of bits to alter for
; the left hand side of the blt

ajLeftMasks equ this byte

        db          11111111b               ;0 should never be used
        db          10000000b               ;1
        db          11000000b               ;2
        db          11100000b               ;3
        db          11110000b               ;4
        db          11111000b               ;5
        db          11111100b               ;6
        db          11111110b               ;7


CB_4BPP_SCAN    equ (CX_SCREEN_MAX / 2)     ;# bytes for a 4bpp screen scan

;-----------------------------Public-Routine----------------------------;
; vConvertVGAScan
;
; Converts a VGA scan into a 4bpp format with a given phase alignment,
; and returns a pointer to the converted buffer.
;
; pdsurfsrc - pointer to source surface (must be VGA display memory)
; xSrc      - X origin of the source
; ySrc      - Y origin of the source
; pjDstBase - Base address of the destination
; xDst      - X origin of the destination
; yDst      - Y origin of the destination
; cxPels    - Number of pels in X
; cyTotalScans - Number of scans in overall operation
; lDelta    - Width in bytes of a destination scan
; iFormat   - Format of destination
; pulXlate  - Color translation vector
;-----------------------------------------------------------------------;

ProcName    xxxvConvertVGA2DIB,vConvertVGA2DIB,44

xxxvConvertVGA2DIB proc uses esi edi ebx,\
        pdsurfsrc       :ptr DEVSURF,   \
        xSrc            :dword,         \
        ySrc            :dword,         \
        pjDstBase       :dword,         \
        xDst            :dword,         \
        yDst            :dword,         \
        cxPels          :dword,         \
        cyTotalScans    :dword,         \
        lDelta          :dword,         \
        iFormat         :dword,         \
        pulXlate        :dword

;-----------------------------------------------------------------------;
; Local variables and their meaning
;
; cjScreenCopy      This is the number of bytes to copy from each scan
;                   into ajConvertBuffer.
; jLeftMask         This is the left-hand side (lhs) mask used when copying
;                   the converted data to the destination
; jRightMask        This is the right-hand side (lhs) mask used when copying
;                   the converted data to the destination
; cRightShift       This is the number of bits that the converted data needs
;                   to be shifted right to align with the destination.
; cjRightShift      This is the number of bytes which must be shifted right
;                   by cRightShift
; cCopy             This is the number of full (e.g. not masked) bytes which
;                   must be copied to the destination
; pjWork            Pointer to the work area where
;                       a)  color converted data is written into
;                       b)  bits are phase-aligned if needed
;                       c)  data is read from for the final copy to the DIB
; pjSrc             Address of scan 0 in memory
; pjDst             Address of scan 0 in memory
; cyScans           Number of scans to do in current bank
; ulScanWidth       Offset from start of one scan to start of next
; ulBottomSrcScan   Bottom scan line of source rectangle (non-inclusive)
;-----------------------------------------------------------------------;

        local   cjScreenCopy    :dword
        local   jLeftMask       :byte
        local   jRightMask      :byte
        local   cRightShift     :byte
        local   cjRightShift    :dword
        local   cCopy           :dword
        local   pfnXlate        :ptr
        local   pjWork          :ptr
        local   cjSkip          :dword
        local   pjSrc           :dword
        local   pjDst           :dword
        local   cyScans         :dword
        local   ulScanWidth     :dword
        local   ulBottomSrcScan :dword

        local   ajColorConv[16]:byte
        local   ajWork[CB_4BPP_SCAN+4]:byte
        local   aj8bpp[CX_SCREEN_MAX+8]:byte


;----------------------------------------------------------------------;
; Loop through source banks, copying & converting one bank at a time.

; Calculate the bottom scan line of the source rectangle (non-inclusive).

        mov     eax,ySrc
        add     eax,cyTotalScans
        mov     ulBottomSrcScan,eax

        mov     ecx,pdsurfsrc           ;point to source surface
        mov     eax,[ecx].dsurf_lNextScan
        mov     ulScanWidth,eax         ;local copy of scan line width

; Map in the bank containing the top scan to fill, if it's not mapped in
; already.

        mov     eax,ySrc                ;top scan line of source

        cmp     eax,[ecx].dsurf_rcl1WindowClip.yTop ;is fill top less than
                                                    ; current bank?
        jl      short map_init_bank             ;yes, map in proper bank
        cmp     eax,[ecx].dsurf_rcl1WindowClip.yBottom ;fill 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 fill.

        ptrCall <dword ptr [ecx].dsurf_pfnBankControl>,<ecx,eax,JustifyTop>

init_bank_mapped:

bank_loop:

; Set the start address of the source bitmap.
; Note that the start of the bitmap will change each time through the
; bank loop, because the start of the bitmap is varied to map the
; desired scan line to the banking window.

        mov     eax,pdsurfsrc           ;point to source surface
        mov     ebx,[eax].dsurf_pvBitmapStart ;start of scan 0 in bitmap
        mov     pjSrc,ebx

; Set the start address of the destination bitmap.

        mov     ebx,pjDstBase
        mov     pjDst,ebx

; Figure out how many scan lines we'll fill in the current bank.

        mov     ebx,ulBottomSrcScan     ;bottom of destination rectangle
        cmp     ebx,[eax].dsurf_rcl1WindowClip.yBottom
                                        ;which comes first, the bottom of the
                                        ; dest rect or the bottom of the
                                        ; current bank?
        jl      short BottomScanSet     ;fill bottom comes first, so draw to
                                        ; that; this is the last bank in fill
        mov     ebx,[eax].dsurf_rcl1WindowClip.yBottom
                                        ;bank bottom comes first; draw to
                                        ; bottom of bank
BottomScanSet:
        sub     ebx,ySrc        ;# of scans to fill in bank
        mov     cyScans,ebx
        push    ebx             ;remember # of scans in bank

        call    DoOneBank       ;copy and convert within the current bank

        pop     ebx             ;restore # of scans in bank

        sub     cyTotalScans,ebx        ;count off this bank's scans from total
        jz      short banks_done        ;no more scans; done
        add     yDst,ebx                ;advance to the next destination scan
                                        ; to copy to
        mov     edi,pdsurfsrc
        mov     eax,[edi].dsurf_rcl1WindowClip.yBottom
        mov     ySrc,eax                ;remember where the top of the bank
                                        ; we're about to map in is (same as
                                        ; bottom of bank we just did)

        ptrCall <dword ptr [edi].dsurf_pfnBankControl>,<edi,eax,JustifyTop>
                                        ;map in the bank

        jmp     bank_loop               ;fill the next bank


; Done.

        align   4
banks_done:

        cRet    vConvertVGA2DIB

;----------------------------------------------------------------------;
; Copies and converts bits within a single bank.

        align   4
DoOneBank:

        cld

; Compute the number of bytes to copy from the screen, and the starting
; address of the source

        mov     eax,ySrc                ;Compute addr of first source scan
        mov     ebx,xSrc
        imul    eax,ulScanWidth
        mov     ecx,ebx
        shr     ebx,3
        add     eax,ebx
        add     pjSrc,eax

; Compute the number of bytes to actually transfer from the screen

        mov     eax,cxPels              ;Compute rhs
        add     eax,ecx
        dec     eax                     ;Make rhs inclusive
        shr     ecx,3                   ;Compute byte of lhs
        shr     eax,3                   ;Compute byte of rhs
        sub     eax,ecx                 ;Compute number of bytes for copy
        inc     eax                     ;(because rhs inclusive, always inc)
        mov     cjScreenCopy,eax

; Compute the address of the starting destination scan.

        mov     eax,yDst
        imul    lDelta
        add     pjDst,eax

; Set up for the preprocess loops and invoke the correct one.  First make
; some assumptions about defaults

        xor     eax,eax
        mov     cRightShift,al          ;No shifting needed
        mov     jLeftMask,al            ;No left masking needed
        mov     jRightMask,al           ;No right masking needed
        lea     eax,ajWork              ;Intermediate work area
        mov     pjWork,eax

        mov     esi,cxPels
        mov     ebx,xSrc
        mov     edx,xDst

        mov     eax,iFormat
        dec     eax
        jz      preproc_1bpp
        dec     eax
        jz      preproc_4bpp
        .errnz  BMF_1BPP-1
        .errnz  BMF_4BPP-2
        .errnz  BMF_8BPP-3

; Destination is 8bpp.  Copy will be phased aligned from the conversion buffer
; to the destination.

preproc_8bpp:
        add     pjDst,edx               ;Offset to first pel in DIB
        and     ebx,7                   ;Offset to first pel for final copy
        mov     cjSkip,ebx
        mov     cCopy,esi               ;Number of bytes for final copy
        lea     eax,aj8bpp              ;Intermediate work area
        mov     pjWork,eax
        mov     pfnXlate,offset FLAT:cvt_to_8bpp
        jmp     preproc_done


; Destination is 4bpp.  Copy will either be phase aligned or be off by 4 in
; which case we will phase align the entire buffer before copying.

preproc_4bpp:
        lea     eax,[esi][edx]          ;Compute rhs for later
        test    dl,1                    ;Odd if left mask needed
        jz      @F
        mov     jLeftMask,11110000b
        dec     esi                     ;One less pel in inner loop
@@:
        test    al,1                    ;Odd if right mask needed
        jz      @F
        mov     jRightMask,00001111b
        dec     esi                     ;One less pel in inner loop
@@:

        and     ebx,7                   ;Offset for final copy is xSrc mod 8

; If the source and destination have different alignments, we'll have to
; compute phase alignment stuff.

        mov     eax,ebx
        xor     eax,edx
        shr     eax,1
        jnc     @F
        mov     eax,cjScreenCopy        ;* 4 for size of data in buffer
        shl     eax,2
        inc     eax                     ;+ 1 to shift into last byte!
        mov     cjRightShift,eax
        mov     cRightShift,4           ;Shift entire buffer right 4 pels
        inc     ebx                     ;First pel just moved right
@@:

; Finish calculating the other parameters

        shr     edx,1                   ;Offset to first pel in DIB
        add     pjDst,edx
        shr     ebx,1
        mov     cjSkip,ebx
        shr     esi,1
        mov     cCopy,esi               ;# of inner bytes for final copy

        mov     eax,offset FLAT:copy_to_dest;Assume no color translation needed
        cmp     pulXlate,0
        je      @F
        mov     eax,offset FLAT:cvt_to_4bpp ;Addreess of color xlate routine
@@:
        mov     pfnXlate,eax
        jmp     preproc_done


; Destination is 1bpp.  Copy most likely will require masking and phase
; alignment.

preproc_1bpp:
        mov     edi,00000007h           ;A handy mask used a lot
        xor     ecx,ecx                 ;CL = lhs mask, CH = rhs mask
        lea     eax,[esi][edx]          ;Compute rhs for later
        test    edx,edi                 ;See if partial byte
        jz      preproc_1bpp_done_lhs   ;No partial lhs byte
        mov     ecx,edx
        neg     ecx
        and     ecx,edi                 ;CL = # bits in lhs, CH = 0
        sub     esi,ecx                 ;Compute # remaining bytes
        mov     cl,ajLeftMasks[ecx]     ;Get lhs mask
        jnc     preproc_1bpp_done_lhs   ;Didn't combine into one byte
        and     eax,edi                 ;Combine rhs mask with lhs mask
        and     cl,ajRightMasks[eax]
        xor     esi,esi                 ;No more bytes
        xor     eax,eax                 ;To show no rhs
        jmp     short preproc_1bpp_have_masks

preproc_1bpp_done_lhs:
        and     eax,edi                 ;See if partial rhs byte
        jz      preproc_1bpp_have_masks ;No partial rhs byte
        mov     ch,ajRightMasks[eax]
        sub     esi,eax                 ;Compute # remaining bytes

preproc_1bpp_have_masks:
        mov     jLeftMask,cl            ;Set left and right masks
        mov     jRightMask,ch
        shr     esi,3                   ;# of inner bytes for final copy
        mov     cCopy,esi

; Compute offset to first byte in destination DIB

        mov     eax,edx
        shr     eax,3
        add     pjDst,eax

; Compute phase alignment parameters

        xor     ecx,ecx                 ;Assume cjSkip is 0
        and     edx,edi
        and     ebx,edi
        sub     edx,ebx                 ;Determine phase alignment
        jz      preproc_finish_1bpp     ;No phase alignment needed

; We're really shifting left, so we'll set it up to shift right a lot, and
; get the first byte of the final move from byte 1 of the work area.

        adc     ecx,ecx                 ;Set cjSkip = 0 or 1
        and     edx,edi                 ;3 LSBs is shift count
        mov     cRightShift,dl          ;Phase for the shift
        mov     eax,cjScreenCopy        ;Size of data in buffer
        inc     eax                     ;+ 1 to shift into last byte!
        mov     cjRightShift,eax
preproc_finish_1bpp:
        mov     cjSkip,ecx              ;No skipping needed
        mov     esi,pulXlate            ;Copy color translation table to the
        lea     edi,ajColorConv         ;  frame because we are out of regs.
        mov     ecx,16
@@:
        lodsd
        stosb
        dec     ecx
        jnz     @B

        mov     pfnXlate,offset FLAT:cvt_to_1bpp

preproc_done:

process_next_scan:

        mov     edi,offset FLAT:ajConvertBuffer
        mov     edx,EGA_BASE + GRAF_ADDR
        mov     eax,GRAF_READ_MAP
copy_next_plane:
        mov     esi,pjSrc               ;ESI --> first Source byte
        out     dx,ax                   ;Set read plane
        mov     ecx,cjScreenCopy        ;Set number of bytes to read
        mov     ebx,edi
        rep     movsb
        lea     edi,[ebx][CJ_WORK_PLANE];EDI --> next scan in convert buf
        inc     ah                      ;Set next read plane
        cmp     ah,4
        jb      copy_next_plane

; The scan has been read in from the VGA.  Convert it into 4bpp format which
; will be needed for doing the color conversion.

        lea     edi,ajWork              ;Convert dwords into here
        mov     esi,offset FLAT:ajConvertBuffer
        mov     ecx,cjScreenCopy        ;# of source bytes to convert

cvt_next_src_byte:
        xor     eax,eax
        mov     al,[esi][CJ_WORK_PLANE*3]   ;Get data for plane C3
        mov     ebx,eax
        and     ebx,00001111b
        shr     eax,4
        mov     edx,aulHi16[ebx*4]
        or      dx,ausLo16[eax*2]
        shl     edx,1
        mov     al,[esi][CJ_WORK_PLANE*2]   ;Get data for plane C2
        mov     ebx,eax
        and     ebx,00001111b
        shr     eax,4
        or      edx,aulHi16[ebx*4]
        or      dx,ausLo16[eax*2]
        shl     edx,1
        mov     al,[esi][CJ_WORK_PLANE*1]   ;Get data for plane C1
        mov     ebx,eax
        and     ebx,00001111b
        shr     eax,4
        or      edx,aulHi16[ebx*4]
        or      dx,ausLo16[eax*2]
        shl     edx,1
        lodsb                               ;Get data for plane C0
        mov     ebx,eax
        and     ebx,00001111b
        shr     eax,4
        or      edx,aulHi16[ebx*4]
        or      dx,ausLo16[eax*2]
        mov     eax,edx
        stosd                               ;8 pels down!
        dec     ecx
        jnz     cvt_next_src_byte


; Perform the format conversion
        mov     ecx,cjScreenCopy        ;Set lopp count
        lea     esi,ajWork              ;Set source pointer
        mov     edi,pjWork              ;Set destination pointer
        mov     ebx,pulXlate            ;Set color translate vector
        xor     eax,eax                 ;Init D31:D8 to 0
        jmp     pfnXlate                ;Invoke correct conversion routine

; Convert from 4bpp to 8bpp with color translation

cvt_to_8bpp:
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        mov     al,[ebx][eax*4]
        stosb
        mov     al,[ebx][edx*4]
        stosb
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        mov     al,[ebx][eax*4]
        stosb
        mov     al,[ebx][edx*4]
        stosb
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        mov     al,[ebx][eax*4]
        stosb
        mov     al,[ebx][edx*4]
        stosb
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        mov     al,[ebx][eax*4]
        stosb
        mov     al,[ebx][edx*4]
        stosb
        dec     ecx
        jnz     cvt_to_8bpp
        jmp     copy_to_dest

; Convert from 4bpp to 4bpp with color translation.

cvt_to_4bpp:
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        mov     al,[ebx][eax*4]
        shl     al,4
        or      al,[ebx][edx*4]
        stosb
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        mov     al,[ebx][eax*4]
        shl     al,4
        or      al,[ebx][edx*4]
        stosb
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        mov     al,[ebx][eax*4]
        shl     al,4
        or      al,[ebx][edx*4]
        stosb
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        mov     al,[ebx][eax*4]
        shl     al,4
        or      al,[ebx][edx*4]
        stosb
        dec     ecx
        jnz     cvt_to_4bpp
        jmp     copy_to_dest


; Convert from 4bpp to 1bpp with color translation.


cvt_to_1bpp:
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        mov     bl,ajColorConv[eax]
        shl     bl,1
        or      bl,ajColorConv[edx]
        lodsb
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        shl     bl,1
        or      bl,ajColorConv[eax]
        shl     bl,1
        or      bl,ajColorConv[edx]
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        shl     bl,1
        or      bl,ajColorConv[eax]
        shl     bl,1
        or      bl,ajColorConv[edx]
        lodsb                           ;Get two nibbles worth
        mov     edx,eax
        shr     eax,4
        and     edx,00001111b
        shl     bl,1
        or      bl,ajColorConv[eax]
        shl     bl,1
        or      bl,ajColorConv[edx]
        mov     al,bl
        stosb
        dec     ecx
        jnz     cvt_to_1bpp


; Copy to the destination.  This unfortunately may involve phase alignment

copy_to_dest:
        movzx   ecx,cRightShift
        jecxz   copy_aligned_to_dest
        mov     edi,pjWork
        mov     ebx,cjRightShift
phase_align_it:
        mov     ah,dl                   ;Get previous unused bits
        mov     al,byte ptr [edi]
        mov     dl,al
        shr     eax,cl
        stosb
        dec     ebx
        jnz     phase_align_it

copy_aligned_to_dest:
        mov     esi,pjWork
        add     esi,cjSkip
        mov     edi,pjDst

        mov     dl,jLeftMask
        or      dl,dl
        jz      @F
        lodsb
        mov     ah,byte ptr [edi]
        xor     ah,al
        and     ah,dl
        xor     al,ah
        stosb
@@:
        mov     ecx,cCopy
        rep     movsb

        mov     dl,jRightMask
        or      dl,dl
        jz      @F
        lodsb
        mov     ah,byte ptr [edi]
        xor     ah,al
        and     ah,dl
        xor     al,ah
        stosb
@@:

        mov     eax,ulScanWidth
        add     pjSrc,eax
        mov     eax,lDelta
        add     pjDst,eax
        dec     cyScans
        jnz     process_next_scan

        PLAIN_RET       ;we're done with this bank

xxxvConvertVGA2DIB endp

        end


unix.superglobalmegacorp.com

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