home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QBasic & Borland Pascal & C
/
Delphi5.iso
/
C
/
Samples
/
C-ASM_VI.ARJ
/
PROGASM.ZIP
/
PROG087P.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-05-25
|
10KB
|
329 lines
;************************************************************************
; Transfer Bit Aligned Block of dimensions Width x Height, from *
; source, with upper left corner at (X_Src,Y_Src), to destination with *
; upper left corner at (X_Dst,Y_Dst), using function fn. *
; Entry: X_Srs, Y_Src - Source upper left *
; X_Dst, Y_Dst - Destination upper left *
; BWidth,BHeight- Dimensions of the block *
; Fn - Logical function (Copy, AND, OR, XOR) *
;************************************************************************
;xxxx add later traversing x in reverse for overlapped src and dst
X_Src EQU [BP+18] ;Formal parameters on the stack
Y_Src EQU [BP+16]
X_Dst EQU [BP+14]
Y_Dst EQU [BP+12]
BWidth EQU [BP+10]
BHeight EQU [BP+8]
Fn EQU [BP+6]
HBYTES EQU 80 ;Number of bytes per scanline
GRF_SEG EQU 0A000H ;Segment for display buffer
Y_Incr EQU WORD PTR [BP-2] ;Local variables
First_Mask EQU BYTE PTR [BP-4]
InFirst EQU WORD PTR [BP-6]
Last_Mask EQU BYTE PTR [BP-8]
Read_Plane EQU BYTE PTR [BP-10]
Lower_Mask EQU BYTE PTR [BP-12]
Upper_Mask EQU BYTE PTR [BP-14]
Src_Address EQU WORD PTR [BP-16]
Dst_Address EQU WORD PTR [BP-18]
Block_Dx EQU WORD PTR [BP-20]
Block_Dy EQU WORD PTR [BP-22]
PUBLIC BitBlt
BitBlt PROC FAR
PUSH BP
MOV BP,SP
SUB SP,24 ;Setup local variables
PUSH DS ;Presrve segment registers
PUSH ES
PUSH DI
PUSH SI
;-------------------------------------------------------------
;--- COMPUTE MASKS FOR FIRST AND LAST BYTE WITHIN A RASTER
; ROTATION FACTOR, AND MASKS FOR HI AND LOW BITS AFTER ROTATION
; ENABLE ROTATION AND LOGICAL FUNCTIONS IN GRAPHICS CONTROLLER
;-------------------------------------------------------------
MOV CX,X_Dst ; NUMBER OF CLEAR BITS IN FIRST BYTE
AND CX,7
MOV First_Mask,0FFH ; COMPUTE MASK TO CLEAR LEADING BITS
SHR First_Mask,CL
MOV AX,8
SUB AX,CX
MOV InFirst,AX
;MASK TO KEEP BITS IN LAST BYTE (PARTIAL BYTE)
MOV CX,X_Dst ; GET ADDRESS OF LAST BIT
ADD CX,BWidth
AND CX,7 ; POSITION JUST AFTER LAST BIT
MOV Last_Mask,0FFH ; COMPUTE MASK TO KEEP BITS AFTER
SHR Last_Mask,CL
NOT Last_Mask ; COMPLEMENT TO KEEP LEADING BITS
;BITS FROM SOURCE BYTE MUST BE ALLIGNED WITH BITS IN THE
;DESTINATION BYTE. HERE IS COMPUTED THE ROTATION AND THE
;TWO MASKS NEEDED TO ISOLOTATE TWO HALVES OF THE BYTE
; COMPUTE ROTATION
MOV CX,X_Dst ; COMPUTE BIT DISTANCE BETWEEN
SUB CX,X_Src ;... BIT POSITIONS IN FIRST BYTES
AND CX,7 ; ... OF SOURCE AND DESTINATION BYTES
; ... AS (SRC-DST)&7
MOV AX,00FFH ;Compute masks for non-zero rotation
ROR AX,CL
MOV Lower_Mask,AL ;Save the masks
MOV Upper_Mask,AH
MOV DX,3CEH ;Address of GRAPHICS controller
MOV AL,3 ;Index for DATA ROTATE & FN SELECT
OUT DX,AL ;Select DATA ROTATE & FN SELECT REG
INC DX
MOV AL,CL ;Fetch rotate count
MOV AH,Fn ;Fetch logical function
AND AH,3 ;Move logical function into
SHL AH,1 ;bits 3 and 4
SHL AH,1
SHL AH,1
OR AL,AH
OUT DX,AL ;Write value into DATA ROTATE... reg
;-------------------------------------------------------------
;--- COMPUTE ABSOLUTE ADDRESS OF SOURCE AND DESTINATION
;-------------------------------------------------------------
MOV WORD PTR Y_Incr,HBYTES ;Initialize y traversal as normal
;Because of possible overlap we must adjust direction of traversal
;If source block is above the destination then reverse Y traversal
;If source block is to the left, then reverse X traversal
MOV AX,Y_Src ;Compare source and destination Y
MOV BX,Y_Dst
CMP AX,BX
JLE Compute_Address ;...Leave alone if src <= dst
ADD AX,BHeight ;Begin with last raster in block
DEC AX
ADD BX,BHeight
DEC BX
MOV Y_Src,AX
MOV Y_Dst,BX
NEG WORD PTR Y_Incr ;And traverse backwards
Compute_Address:
MOV AX,Y_Src ;Compute offset for source
MOV BX,HBYTES ;as offset = y * 80 + x/8
MUL BX
MOV SI,X_Src
SHR SI,1
SHR SI,1
SHR SI,1
ADD SI,AX
MOV Src_Address,SI
MOV AX,Y_Dst ;Compute offset for destination
MOV BX,HBYTES ;as offset = y * 80 + x/8
MUL BX
MOV DI,X_Dst
SHR DI,1
SHR DI,1
SHR DI,1
ADD DI,AX
MOV Dst_Address,DI
MOV AX,GRF_SEG ;Setup segment
MOV ES,AX
MOV DS,AX
;-------------------------------------------------------------
;--- ENABLE NEXT PLANE FOR READ AND WRITE
;-------------------------------------------------------------
MOV AL,3 ;Initialize counter of planes
MOV Read_Plane,AL
Plane_Loop:
MOV AX,BWidth ;Copy dimensions of the block
MOV Block_Dx,AX
MOV AX,BHeight
MOV Block_Dy,AX
MOV SI,Src_Address ;Fetch source address
MOV DI,Dst_Address ;Fetch destination address
MOV CL,Read_Plane ;Fetch next plane to do
MOV AH,1 ;Use plane number to setup value
SHL AH,CL ;for WRITE PLANE SELECT register
MOV DX,3C4H ;Fetch address of SEQUENCER
MOV AL,2 ;Index for WRITE PLANE SELECT register
OUT DX,AL ;Select register
INC DX
MOV AL,AH ;Fetch value
OUT DX,AL ;Write value into register
MOV DX,3CEH ;Fetch address of GRAPHICS controller
MOV AL,4 ;Index for READ PLANE SELECT register
OUT DX,AL ;Select register
INC DX
MOV AL,CL ;Fetch plane number
OUT DX,AL ;Write plane number into register
DEC DX
MOV AL,8 ;Index for BIT MASK register
OUT DX,AL ;Select BIT MASK register
INC DX
;-------------------------------------------------------------
; RASTER LOOP IS DONE IN FOUR STEPS
; (1) MASKS AND ROTATION FACTOR IS COMPUTED TO ALIGN SRC AND DEST
; (2) LEADIING PARTIAL BYTE OF DESTINATION IS MODIFIED
; (3) FULL BYTES OF DESTINATION ARE MODIFIED
; (4) TRAILLING PARTIAL BYTE OF DESTINATION IS MODIFIED
;-------------------------------------------------------------
;-------------------------------------------------------------
;--- GET ENOUGH BITS FROM SOUCE TO CONSTRUCT FIRST PARTIAL BYTE OF DST
;-------------------------------------------------------------
Raster_Loop:
MOV CX,Block_Dx ;Number of bits to copy
PUSH SI ;Preserve addresses for next raster loo
PUSH DI
MOV AX,X_Src ;Check if need one or two bytes
AND AX,7 ;for first byte of destination
MOV BX,X_Dst
AND BX,7
CMP AX,BX
JG Get_2_Bytes
Get_1_Byte:
MOV AL,First_Mask ;Fetch mask for first partial byte
AND AL,Lower_Mask ;Combine with 'lower mask'
OUT DX,AL ;Write mask into BIT MASK register
LODSB ;Fetch first source byte
MOV AH,[DI] ;Latch destination
STOSB ;Write first byte of destination
MOV AH,AL ;Save AL since it will be trashed by OU
JMP Leading_Done
Get_2_Bytes:
MOV AL,First_Mask ;Fetch mask for first partial byte
AND AL,Upper_Mask ;Combine with 'upper mask'
OUT DX,AL ;Write mask into BIT MASK register
LODSB
MOV AH,[DI] ;Latch destination bits
MOV ES:[DI],AL ;Write first byte
MOV AL,First_Mask ;Fetch mask for first partial byte
AND AL,Lower_Mask ;Combine with 'lower mask'
OUT DX,AL ;Write mask into BIT MASK register
LODSB
MOV AH,[DI] ;Latch destination bits
STOSB ;Write first byte
MOV AH,AL ;Save AL since it will be trashed by OU
Leading_Done:
SUB CX,InFirst ;Update number of bits to transfer
JLE Raster_Done
;-------------------------------------------------------------
;--- LOOP OVER COMPLETE BYTES WITHIN A SINGLE SOURCE RASTER
;-------------------------------------------------------------
Full_Loop:
CMP CX,8 ;If less then 8 bits to do
JL Full_Done ;quit this loop
MOV AL,Upper_Mask ;Fetch the 'upper mask'
OUT DX,AL ;Write mask into BIT MASK register
MOV AL,[DI] ;Latch destination bits
MOV [DI],AH ;Write half 2 for src to half 1 of dst
MOV AL,Lower_Mask ;Fetch the lower mask
OUT DX,AL ;Write mask into BIT MASK register
LODSB ;Fetch next source byte
MOV AH,[DI] ;Latch destination bits
STOSB ;Write half 1 of src to half 2 of dst
MOV AH,AL ;Save AL since it will be trashed by OU
SUB CX,8 ; DECREMENT WIDTH BY BITS TO BE DONE
JMP Full_Loop
Full_Done:
;-------------------------------------------------------------
;--- TRANSFER THE LAST PARTIAL BYTE
;-------------------------------------------------------------
Last_Partial:
CMP CX,0 ;Any more bits to transfer?
JLE Raster_Done ;...No, quit this raster
MOV AL,Last_Mask ;Fetch mask for last partial byte
AND AL,Upper_Mask ;Combine with 'upper mask'
OUT DX,AL ;Write mask into BIT MASK register
MOV AL,[DI] ;Latch destination bits
MOV [DI],AH ;Write half 2 for src to half 1 of dst
MOV AL,Last_Mask ;Fetch mask for last partial byte
AND AL,Lower_Mask ;Combine with 'upper mask'
OUT DX,AL ;Write mask into BIT MASK register
LODSB ;Fetch next source byte
MOV AH,[DI] ;Latch destination bits
STOSB ;Write half 1 of src to half 2 of dst
;--- ADVANCE TO THE NEXT RASTER
Raster_Done:
POP DI ;Pointers to current raster
POP SI
ADD SI,Y_Incr ;Update pointer to point to the next
ADD DI,Y_Incr ;raster
DEC WORD PTR Block_Dy ;Update number of rasters to do
JLE Test_Plane
JMP Raster_Loop ;And repeat if not all done
Test_Plane:
DEC Read_Plane ;Update number of planes to do
JL Blit_Done
JMP Plane_Loop ;And do next plane if any left to do
;-------------------------------------------------------------
;--- Clean up and exit
;-------------------------------------------------------------
Blit_Done:
;restore rotate value
MOV DX,3CEH ;Address of GRAPHICS controller
MOV AL,3 ;Index for ROTATE & FN SELECT
OUT DX,AL ;Select ROTATE & FN SELECT register
INC DX
XOR AL,AL ;Disable rotate and set fn=copy
OUT DX,AL ;Write value into register
;restore bit mask
DEC DX
MOV AL,8 ;Index for BIT MASK register
OUT DX,AL ;Select BIT MASK register
INC DX
MOV AL,0FFH ;Enable all 8 bits for write
OUT DX,AL ;Write value into register
;enable all four planes for write
MOV DX,3C4H ;Address of SEQUENCER
MOV AL,2 ;Index for PLANE ENABLE register
OUT DX,AL ;Select register
INC DX
MOV AL,0FH ;Value to enable all four planes
OUT DX,AL ;Write value into register
POP SI ;Restore segment registers
POP DI
POP ES
POP DS
MOV SP,BP
POP BP
RET 14
BitBlt ENDP