.386p

INCL_DOSMISC    EQU     1
INCL_DOSERRORS  EQU     1
INCL_TYPES      EQU     1
INCL_DEF        EQU     1

;*********************************************
; Define the C calling macros
LBegin  macro len
        push    ebp
        mov     ebp,esp
        sub     esp,len
        endm
LEnd    macro
        mov     esp,ebp
        pop     ebp
        endm
;*********************************************


include devsym.inc
include basemaca.inc
include basedef.inc


DATA   SEGMENT  DWORD USE16 PUBLIC 'DATA'      ; changed from code to data
;        ASSUME   CS: FLAT, DS: FLAT, SS: FLAT, ES: FLAT

ALIGN 4
espsave           dd    0       ; ESP (stack pointer) save variable
eolskipbytes      dd    0       ; number of bytes to skip at end of line
pelsperlineover4  dw    0       ; pels per output line/4
Pelsperline       dw    0       ; Bytes per output line
BytesToBankEnd    dd    0       ; Byte to the end of current Bank
SourceBuffStart   dd    0       ; Start of Source Buffer for multiple pages
SourceBuffCur     dd    0       ; Current Postion in Source Buffer
Iwidth            dd    0       ; Width of the image before scaling
Iscale            dd    0       ; Scale the image down by this factor (in bytes not PELs)
PELsToCopyB2      dd    0       ; PELs to copy from 2nd Bank
PELsRemianB2      dd    0       ; Offset in PELs into the second Bank
CurBankNum        dd    0       ; Current Bank Number
LinesToCopy       dd    0       ; Number of Lines to Copy
Double            dd    0       ; Double each scanline if set to 1

both   equ 00000000B            ; Both Field 1 and 2 are valid
field2 equ 00000001B            ; only Field 2 is valid

EXTRN    TotalBytesinBank:DWORD ; Number of Bytes in the current VCA Bank configuration
EXTRN    REG12:BYTE             ; Info on Valid Field captured into VCA Memory
DATA   ENDS


_TEXT   SEGMENT  DWORD USE16 PUBLIC 'CODE'
        ASSUME   CS: FLAT, DS: FLAT, SS: FLAT, ES: FLAT

        EXTRN   SETBANKNUM:NEAR


;**************************************************************************
; Procedure Name  :     _VCACopyBuf
;
; Description     :     Copies RGB16 data from the VCA buffer to the copy
;                       buffer.  Speed is of the essence.
;                       This Routine works with VCA single page Memory configuration only.
;
; Input Parameters:     SrcBuf       : pointer to source buffer (VCA)
;                       DestBuf      : pointer to destination buffer
;                       left         : Xrect to copy in video coordinates
;                       top          : (Ymax - Yrect) to copy in video coords
;                       width        : rect width in video coordinates
;                       height       : rect height in video coodinates
;                       scale        : scaling factor (1=640, 2=320, 4=160)
;
; Register status :     All registers trashed
;
; Notes:
;                       The Y/Top start address is truncated to an even number
;                        this simpilifies field 1 or 2 address calculations
;                       Height must be a multiple of 2
;                       Weight must be a multiple of 4
;
;**************************************************************************
ALIGN 4
Procedure _VCACopyBuf, FAR
         ASSUME cs:_TEXT,ds:DATA,es:NOTHING,ss:NOTHING
   ;*********************************************
   ; Parameters on stack
        SrcBuf                  equ ebp+8
        DestBuf                 equ ebp+12
        rleft                   equ ebp+16
        rtop                    equ ebp+20
        rwidth                  equ ebp+24
        rheight                 equ ebp+28
        scale                   equ ebp+32
        X2                      equ ebp+36
   ;*********************************************
   ; Local Variables on stack

           LBegin 20h

           CLD
           PUSH EBP                     ; save EBP
           MOV  eax,[X2]                ; Is Scanline Double requested
           MOV  Double,eax              ; Save Double Scanline Info
           MOV  ESI,[SrcBuf]            ; HW buffer to copy from
           MOV  EDI,[DestBuf]           ; get pointer to copy buffer
           MOV  AX,FS                   ; Load ES with FS the Flat Selector
           MOV  ES,AX                   ; Load ES with FS the Flat Selector
; determine number of lines to copy
           MOV  EAX,[rheight]           ; get the image height
           XOR  EDX,EDX                 ; clear EDX for divide
           MOV  EBX,[scale]             ; get the scaling factor
           DIV  BX                      ; AX = number of lines to copy
           MOV  CX,AX                   ; save in CX for now
; determine number of pels per line to copy
           MOV  EAX,[rwidth]            ; get the image width
           XOR  EDX,EDX                 ; clear EDX for divide
           MOV  EBX,[scale]             ; get the scaling factor
           DIV  BX                      ; AX = lines pels/lines to skip
           SHR  AX,2                    ; convert to pels/4
           MOV  pelsperlineover4,AX     ; save pels per row to copy
; determine the initial starting address
           MOV  EAX,[rtop]              ; get the rectangle top edge
           MOV  DL,reg12                ; Which Fields are valid
           AND  DL,11100000B            ; Only the Field Info Need
           JZ   Found_fields            ; Both Fields were captured
           AND  DL,00100000B            ; Was Field 2 captured
           JNZ  only_field2             ; Only Field 2 was captured
           AND  EAX,0FFFFFFFEh          ; Make it even (only Field 1 captured)
           jmp  found_fields            ;
only_field2:                            ; Only Field 2 was captured
           OR   EAX,000000001h          ; Make it odd (only Field 2 captured)
Found_fields:                           ;
           XOR  EDX,EDX                 ; clear EDX for multiply
           MOV  EBX,1280                ; number of bytes/VCA line
           MUL  EBX                     ; get address of first scan line
           ADD  ESI,EAX                 ; advance source pointer to first line
           MOV  EAX,[rleft]             ; get the rectangle left edge
           SHL  EAX,1                   ; convert to number of bytes
           ADD  ESI,EAX                 ; advance source pointer to first pel
; determine the number of bytes to skip at end-of-line
           MOV  EAX,[scale]             ; get the rectangle top edge
           DEC  EAX                     ; x1 : 0, x2 : 1, etc. (skipped lines)
           XOR  EDX,EDX                 ; clear EDX for multiply
           MOV  EBX,1280                ; number of bytes/VCA line
           MUL  EBX                     ; number of bytes in skipped lines
           MOV  EBX,640                 ; total pels per line
           MOV  EDX,[rwidth]            ; get the image width
           SUB  EBX,EDX                 ; number of pels to skip
           SHL  EBX,1                   ; convert to bytes
           ADD  EAX,EBX                 ; total bytes to skip at end of line
           CMP  double,0                ; Double the scanline?
           JE   save_eol                ; Double Not requested
           ADD  EAX,640*2               ; Add in skipped/doubled scanline
save_eol:
           MOV  eolskipbytes,EAX        ; save

; determine the number of bytes to skip between pels
           MOV  EBX,[scale]             ; get the scaling factor
           SHL  EBX,1                   ; convert to bytes to skip
           MOV  EBP,EBX                 ; bytes to skip per pel
; determine the number of bytes to advance source every 2 pels
           SHL  EBX,1                   ; bytes to skip per two pels

           MOV  DX,CX                   ; get number of lines to copy in DX
           XOR  ECX,ECX                 ; clear ECX 31-16

copyline:
           MOV  CX,pelsperlineover4     ; get number of 4-pels to move
copy4pels:
           MOV  AX,fs:[ESI+EBP]         ; get the second pixel value
           SHL  EAX,16                  ; shift it to 31-16
           MOV  AX,fs:[ESI]             ; get the first pixel value
           STOS dword ptr es:[edi]      ; do a DWORD-aligned doubleword store
           ADD  ESI,EBX                 ; advance pointer to next two pels
           MOV  AX,fs:[ESI+EBP]         ; get the second pixel value
           SHL  EAX,16                  ; shift it to 31-16
           MOV  AX,fs:[ESI]             ; get the first pixel value
           STOS dword ptr es:[edi]      ; do a DWORD-aligned doubleword store
           ADD  ESI,EBX                 ; advance pointer to next two pels
           LOOP copy4pels

           CMP  Double,0                ; Double Scanline?
           JE   copy_done               ; Don't scanline Double
           ; Double the Scanline Just Copied
           push ESI
           mov  ESI,EDI
           MOV  CX,pelsperlineover4     ; get number of 4-pels to move
           shl  ecx,3                   ; PEL/4 * 8 = Bytes
           sub  ESI,ECX                 ; Start of Line just copied
           shr  ecx,2                   ; Number of PELs/2
           REP  MOVS dword ptr es:[edi],dword ptr es:[esi]; Copy a PIXEL at a time
           POP  ESI
           DEC  DX
copy_done:

           ADD  ESI,eolskipbytes
           DEC  DX
           JA   copyline

           POP  EBP

           LEnd
           RET

EndProc _VCACopyBuf

;**************************************************************************
; Procedure Name  :     _VCACopyBuf2
;
; Description     :     Copies RGB16 data from the VCA buffer to the copy
;                       buffer.  Speed is of the essence.
;                       This Routine works with VCA multiple page Memory configurations.
;
; Input Parameters:     SrcBuf       : pointer to source buffer (VCA)
;                       DestBuf      : pointer to destination buffer
;                       left         : Xrect to copy in video coordinates
;                       top          : (Ymax - Yrect) to copy in video coords
;                       width        : rect width in video coordinates
;                       height       : rect height in video coodinates
;                       scale        : scaling factor (1=640, 2=320, 4=160)
;
; Register status :     All registers trashed
;
; Notes:
;                       The Y/Top start address is truncated to an even number
;                        this simpilifies field 1 or 2 address calculations
;                       Height must be a multiple of 2
;                       Weight must be a multiple of 4
;
;**************************************************************************
ALIGN 4
Procedure _VCACopyBuf2, FAR
         ASSUME cs:_TEXT,ds:DATA,es:NOTHING,ss:NOTHING
   ;*********************************************
   ; Parameters on stack
        SrcBuf                  equ ebp+8
        DestBuf                 equ ebp+12
        rleft                   equ ebp+16
        rtop                    equ ebp+20
        rwidth                  equ ebp+24
        rheight                 equ ebp+28
        scale                   equ ebp+32
        X2                      equ ebp+36
   ;*********************************************
   ; Local Variables on stack

           LBegin 20h

           CLD
           PUSH EBP                     ; save EBP
           MOV  eax,[X2]                ; Is Scanline Double requested
           MOV  Double,eax              ; Save Double Scanline Info
           MOV  ESI,[SrcBuf]            ; HW buffer to copy from
           MOV  SourceBuffStart,ESI     ; Save Start of Source Buffer
           MOV  EDI,[DestBuf]           ; get pointer to copy buffer
           MOV  AX,FS                   ; Load ES with FS the Flat Selector
           MOV  ES,AX                   ; Load ES with FS the Flat Selector
; determine number of lines to copy
           MOV  EAX,[rheight]           ; get the image height
           XOR  EDX,EDX                 ; clear EDX for divide
           MOV  EBX,[scale]             ; get the scaling factor
           MOV  Iscale,EBX              ; Save Image scale factor
           ADD  Iscale,EBX              ; Convert to Byte scale factor
           DIV  EBX                     ; AX = number of lines to copy
           MOV  LinesToCopy,EAX         ; Save number of lines to copy
; determine number of pels per line to copy
           MOV  EAX,[rwidth]            ; get the image width
           SHL  EAX,1                   ; PELs * 2 = Bytes
           MOV  Iwidth,EAX              ; Save the image width in bytes
           SHR  EAX,1                   ; Restore to PELs (Bytes / 2 = PELs)
           XOR  EDX,EDX                 ; clear EDX for divide
           MOV  EBX,[scale]             ; get the scaling factor
           DIV  BX                      ; AX = lines pels/lines to skip
           MOV  pelsperline,AX          ; save pels per row to copy
; determine the initial starting address
           MOV  EAX,[rtop]              ; get the rectangle top edge
           MOV  DL,reg12                ; Which Fields are valid
           AND  DL,11100000B            ; Only the Field Info Need
           JZ   got_fields              ; Both Fields were captured
           AND  DL,00100000B            ; Was Field 2 captured
           JNZ  field2_only             ; Only Field 2 was captured
           AND  EAX,0FFFFFFFEh          ; Make it even (only Field 1 captured)
           jmp  got_fields              ;
field2_only:                            ; Only Field 2 was captured
           OR   EAX,000000001h          ; Make it odd (only Field 2 captured)
got_fields:                           ;
           XOR  EDX,EDX                 ; clear EDX for multiply
           MOV  EBX,1280                ; number of bytes/VCA line
           MUL  EBX                     ; get address of first scan line
           ADD  ESI,EAX                 ; advance source pointer to first line
           MOV  EAX,[rleft]             ; get the rectangle left edge
           SHL  EAX,1                   ; convert to number of bytes
           ADD  ESI,EAX                 ; advance source pointer to first pel

; determine which bank the image starts in
           mov  EAX,ESI                 ; Address of first PEL to copy
           sub  EAX,SourceBuffStart     ; Offset to first PEL to be copy in the image
           mov  SourceBuffCur,EAX       ; Absolute offset in Source Buffer
           mov  ECX,TotalBytesinBank    ; Bytes in a Bank
           XOR  EDX,EDX                 ; zero for divid
           DIV  ECX                     ; EAX=Starting Bank Number, EDX = bytes into Bank
           MOV  ESI,SourceBuffStart     ; Offset to first PEL to be copy in the image
           ADD  ESI,EDX                 ; Offset to image start in this bank
           MOV  ECX,EAX                 ; Bank Number image starts in
           MOV  CurBankNum,EAX          ; Save current Bank Number
           CALL SETBANKNUM              ; Program for starting bank Number

; determine the number of bytes to skip at end-of-line
           MOV  EAX,[scale]             ; get the rectangle top edge
           XOR  EDX,EDX                 ; clear EDX for multiply
           MOV  EBX,1280                ; number of bytes/VCA line
           MUL  EBX                     ; number of bytes in skipped lines
           CMP  double,0                ; Double the scanline?
           JE   save_eol2               ; Double Not requested
           ADD  EAX,640*2               ; Add in skipped/doubled scanline
save_eol2:
           MOV  eolskipbytes,EAX        ; save
; determine the number of bytes to skip between pels
           MOV  EBX,[scale]             ; get the scaling factor
           SHL  EBX,1                   ; convert to bytes to skip
           MOV  EBP,EBX                 ; bytes to skip per pel
           SUB  EBP,2                   ; bytes to skip after MOVSW auto increment
; determine the absolute offset in Source Buffer
           MOV  EBX,SourceBuffCur       ; bytes to from start of source buffer

copyline2:
           mov  EAX,EBX                 ; Absolute offset in Source Buffer
           mov  ECX,TotalBytesinBank    ; Bytes in a Bank
           XOR  EDX,EDX                 ; zero for divid
           DIV  ECX                     ; EAX=Starting Bank Number, EDX = bytes into Bank
           MOV  ESI,SourceBuffStart     ; Offset to first PEL to be copy in the image
           ADD  ESI,EDX                 ; Offset to image start in this bank
           cmp  EAX,curBankNum          ; has the bank number changed?
           je   OldBankNum              ; Same old Bank Number (no need to reprogram)
           MOV  ECX,EAX                 ; Bank Number image starts in
           MOV  CurBankNum,EAX          ; Save current Bank Number
           CALL SETBANKNUM              ; Program for starting bank Number

OldBankNum:
           MOV  ECX,TotalBytesinBank  ; Bytes in a Bank
           SUB  ECX,EDX               ; Bytes to end of Bank
           MOV  EAX,Iwidth            ; Width of the Image
           SUB  EAX,ECX               ; Bytes past end of bank
           MOV  CX,PELsperline        ; Assume all PELs in this Bank (PELs to move)
           jbe  copylastpage          ; this part of image dosen't span a bank

           XOR  EDX,EDX               ; zero for divide
           MOV  ECX,[Iscale]          ; divide by scale factor
           DIV  ECX                   ; EAX = PELsToCopy in bank 2,  EDX = offset into bank 2
           mov  PELsToCopyB2,EAX      ; Save number of PELs to copy from the 2nd BANK
           mov  PELsRemianB2,EDX      ; Offset into 2nd Bank
           MOV  CX,PELsperline        ; Assume all PELs in this Bank (PELs to move)
           SUB  CX,AX                 ; PELs to copy from bank 1

copyfirstpage:
           MOVS word ptr es:[edi],word ptr fs:[esi]; Copy a PIXEL at a time
           ADD  ESI,EBP                 ; advance pointer to next two pels
           LOOP copyfirstpage

;           cmp  PELsToCopyB2,0          ; Are any PELs in the next bank for this scanline
;           je   copyLineDone            ; No PELs in next bank for this scanline

           ;change to next bank
           INC  CurBankNum              ; Next Bank Number
           MOV  ECX,CurBankNum          ; Last Bank Number
           CALL SETBANKNUM              ; Program the new Bank Number

           mov  ESI,SourceBuffStart
           ADD  ESI,PELsRemianB2       ; Add offset into 2nd Bank
           mov  ECX,PELsToCopyB2       ; Save number of PELs to copy from the 2nd BANK

copylastpage:
           MOVS word ptr es:[edi],word ptr fs:[esi]; Copy a PIXEL at a time
           ADD  ESI,EBP                ; advance pointer to next two pels
           LOOP copylastpage

copyLineDone:
           CMP  Double,0                ; Double Scanline?
           JE   skip_double             ; Don't scanline Double
           ; Double the Scanline Just Copied
           push ESI
           mov  ESI,EDI
           MOV  CX,PELsperline          ; PELs per Line
           shl  cx,1                    ; PELs * 2 = Bytes
           sub  ESI,ECX                 ; Start of Line just copied
           shr  ecx,2                   ; Number of PELs/2
           REP  MOVS dword ptr es:[edi],dword ptr es:[esi]; Copy 2 PIXELs at a time
           POP  ESI
           DEC  LinesToCopy
skip_double:

           ADD  EBX,eolskipbytes       ; Absolute offset in source buffer
           DEC  LinesToCopy
           JNZ  copyline2

copydone2:
           POP  EBP

           LEnd
           RET

EndProc _VCACopyBuf2
;***********************************
; END OF CODE SEGMENT (MUST BE LAST)
;***********************************
        PUBLIC  END_OF_CODE
END_OF_CODE     EQU     $
_TEXT   ENDS
END
