Category : C Source Code
Archive   : XLIB06.ZIP
Filename : XPBMCLIP.ASM

 
Output of file : XPBMCLIP.ASM contained in archive : XLIB06.ZIP
;-----------------------------------------------------------------------
; MODULE XPBMCLIP
;
; Clipped Planar Bitmap functions - System Ram <-> Video Ram
;
; Compile with Tasm.
; C callable.
;
;
; ****** XLIB - Mode X graphics library ****************
; ****** ****************
; ****** Written By Themie Gouthas ****************
;
; [email protected]
; [email protected]
;-----------------------------------------------------------------------


COMMENT $

This module implements a set of functions to operate on planar bitmaps.
Planar bitmaps as used by these functions have the following structure:

BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255
BYTE 1 The bitmap height in rows range 1..255
BYTE 2..n1 The plane 0 pixels width*height bytes
BYTE n1..n2 The plane 1 pixels width*height bytes
BYTE n2..n3 The plane 2 pixels width*height bytes
BYTE n3..n4 The plane 3 pixels width*height bytes

These functions provide the fastest possible bitmap blts from system ram to
to video and further, the single bitmap is applicable to all pixel
allignments. The masked functions do not need separate masks since all non
zero pixels are considered to be masking pixels, hence if a pixel is 0 the
corresponding screen destination pixel is left unchanged.


$
LOCALS
include xlib.inc
include xpbmclip.inc

.code

;----------------------------------------------------------------------
; x_put_masked_pbm_clipx - mask write a planar bitmap from system ram to video
; ram all zero source bitmap bytes indicate destination
; byte to be left unchanged.
; Performs clipping in x directions. similar to
; "x_put_masked_pbm".
;
; See Also: x_put_masked_pbm, x_put_masked_pbm_clipxy
;
; Clipping region variables: LeftClip,RightClip
;
; Written by Themie Gouthas
;
; This code is a SLOW hack, any better ideas are welcome
;----------------------------------------------------------------------
_x_put_masked_pbm_clipx proc
ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword
LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:word=LocalStk
push bp
mov bp,sp
sub sp,LocalStk ; Create space for local variables
push si
push di
push ds
cld

les si,[Bitmap] ; Point ES:SI to start of bitmap

xor ax,ax ; Clear AX
mov [CType],ax ; Clear Clip type descision var
mov al,byte ptr es:[si] ; AX=width (byte coverted to word)


mov di,[X] ; DI = X coordinate of dest
mov cx,di ; copy to CX
sar di,2 ; convert to offset in row


;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;

mov dx,[_LeftClip] ; Is X Coord to the right of
sub dx,di ; LeftClip ?
jle @@NotLeftClip ; Yes! => no left clipping
cmp dx,ax ; Is dist of X Coord from
jnl @@NotVisible ; ClipLeft > Width ? yes => the
; bitmap is not visible
add di,dx
mov [LeftSkip],dx
mov [DataInc],dx
sub ax,dx
mov [CType],1
jmp short @@HorizClipDone

;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;

@@NotVisible:
mov ax,1
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret

;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;

@@NotLeftClip:
mov dx,[_RightClip]
sub dx,di
js @@NotVisible
mov [LeftSkip],0
mov [DataInc],0
cmp dx,ax
jge @@HorizClipDone ; was jg
inc dx
sub ax,dx
mov [DataInc],ax
mov ax,dx
mov [CType],-1

@@HorizClipDone:

xor bh,bh
mov bl,byte ptr es:[si+1] ; BX = height

mov [Width],ax ; Save width and height of clipped
mov [Height],bx ; image


add si,2 ; Skip dimension bytes in source
add si,[LeftSkip] ; Skip pixels in front of row that
; are clipped


mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width
mov dx,bx ; BX - Width of image = No. bytes
sub dx,ax ; to first byte of next screen
mov [LineInc],dx ; row.

mov ax,[Y] ; Calculate screen start row
mul bx ; then adding screen offset
add di,ax
add di,[ScrnOffs]
mov ax,es ; copy ES to DS
mov ds,ax
mov ax,SCREEN_SEG ; Point ES to VGA segment
mov es,ax

and cx,3
mov ah,11h ; Set up initial plane mask
shl ah,cl

mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
mov al,MAP_MASK
out dx,al
inc dx
mov [Plane],4 ; Set plane counter to 4
mov bh,byte ptr [Width] ; set bh to width for fast looping
@@PlaneLoop:
push di ; Save bitmap's start dest. offset
mov bl,byte ptr [Height] ; Reset row counter (BL)
mov al,ah
out dx,al ; set vga write plane
@@RowLoop:
mov cl,bh ; Reset Column counter cl
jcxz @@NoWidth
@@ColLoop:
lodsb ; Get next source bitmap byte
or al,al ; If not zero then write to dest.
jz @@NoPixel ; otherwise skip to next byte
mov es:[di],al
@@NoPixel:
inc di
loop @@ColLoop
@@NoWidth:
add si,[DataInc] ; Move to next source row
add di,[LineInc] ; Move to next screen row
dec bl ; decrement row counter
jnz @@RowLoop ; Jump if more rows left
pop di ; Restore bitmaps start dest byte
rol ah,1 ; Shift mask for next plane

; Plane Transition (A HACK but it works!)

jnb @@Nocarry ; Jump if not plane transition
mov bl,ah ; Save Plane Mask
mov ax,[CType] ; set AX to clip type inc variable
add bh,al ; Update advancing variables
sub [DataInc],ax ;
sub [LineInc],ax ;
cmp al,0 ; What type of clip do we have
mov ah,bl ; restore Plane mask
jg @@RightAdvance ; jump on a right clip!
inc di ; otherwise increment DI
jmp @@Nocarry
@@RightAdvance:
dec si
@@Nocarry:
dec [Plane] ; Decrement plane counter
jnz @@PlaneLoop ; Jump if more planes left

xor ax,ax
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret
_x_put_masked_pbm_clipx endp


;----------------------------------------------------------------------
; x_put_masked_pbm_clipy - mask write a planar bitmap from system ram to video
; ram all zero source bitmap bytes indicate destination
; byte to be left unchanged.
; Performs clipping in y direction. similar to
; "x_put_masked_pbm".
;
; See Also: x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipy
;
; Clipping region variables: TopClip,BottomClip
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_put_masked_pbm_clipy proc
ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword
LOCAL Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk
push bp
mov bp,sp
sub sp,LocalStk ; Create space for local variables
push si
push di
push ds
cld

les si,[Bitmap]

xor bh,bh
mov bl,byte ptr es:[si+1] ; BX = height

xor ah,ah
mov al,byte ptr es:[si] ; AX = width

mov cx,ax ; Save AX
mul bx ; AX = AX*BX = bytes/plane
mov [PlaneInc],ax ; save as PlaneInc
mov ax,cx ; Restore AX

mov di,[X]
mov cx,di
shr di,2

;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;

mov dx,[_TopClip] ; Compare u.l. Y coord with Top
sub dx,[Y] ; clipping border
jle @@NotTopClip ; jump if VBM not clipped from above
cmp dx,bx
jnl @@NotVisible ; jump if VBM is completely obscured
mov [TopRow],dx
sub bx,dx
add [Y],dx
jmp short @@VertClipDone

;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;

@@NotVisible:
mov ax,1
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret

;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;

@@NotTopClip:
mov dx,[_BottomClip]
sub dx,[Y]
js @@NotVisible
mov [TopRow],0
cmp dx,bx
jg @@VertClipDone
inc dx
mov bx,dx

@@VertClipDone:

mov [Width],ax
mov [Height],bx ; Calculate relative offset in data
mul [TopRow] ; of first visible scanline
add ax,2 ; Skip dimension bytes in source
add si,ax ; Skip top rows that arent visible


mov ax,[Y] ; Calculate screen row
mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen
mul bx ; width then adding screen offset
add di,ax
add di,[ScrnOffs]
sub bx,[Width] ; calculate difference from end of
mov [LineInc],bx ; b.m. in curr line to beginning of
; b.m. on next scan line
mov ax,es ; copy ES to DS
mov ds,ax
mov ax,SCREEN_SEG ; Point ES to VGA segment
mov es,ax

mov ah,11h ; Set up initial plane mask
and cx,3
shl ah,cl

mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
mov al,MAP_MASK
out dx,al
inc dx
mov bh,4 ; Set plane counter to 4
@@PlaneLoop:
push di ; Save bitmap's start dest. offset
push si ; Save Bitmaps data offset
mov bl,byte ptr [Height] ; Reset row counter (BL)
mov al,ah
out dx,al ; set vga write plane
@@RowLoop:
mov cl,byte ptr [Width] ; Reset Column counter cl
@@ColLoop:
lodsb ; Get next source bitmap byte
or al,al ; If not zero then write to dest.
jz @@NoPixel ; otherwise skip to next byte
mov es:[di],al
@@NoPixel:
inc di
loop @@ColLoop ; loop if more columns left
add di,[LineInc] ; Move to next row
dec bl ; decrement row counter
jnz @@RowLoop ; Jump if more rows left
pop si ; Restore SI and set to offset of
add si,[PlaneInc] ; first vis pixel in next plane data
pop di ; Restore bitmaps start dest byte
rol ah,1 ; Shift mask for next plane
adc di,0 ; if carry increment screen offset
dec bh ; Decrement plane counter
jnz @@PlaneLoop ; Jump if more planes left

xor ax,ax
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret
_x_put_masked_pbm_clipy endp

;----------------------------------------------------------------------
; x_put_masked_pbm_clipxy - Write a planar bitmap from system ram to video
; RAM with clipping in x and y directions. similar to
; "x_put_masked_pbm".
;
; See Also: x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipxy
;
; Clipping region variables: LeftClip,RightClip,TopClip,BottomClip
;
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_put_masked_pbm_clipxy proc
ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword
LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk
push bp
mov bp,sp
sub sp,LocalStk ; Create space for local variables
push si
push di
push ds
cld

les si,[Bitmap]

xor ax,ax
mov [CType],ax
mov al,byte ptr es:[si] ; AX = width
xor bh,bh
mov bl,byte ptr es:[si+1] ; BX = height

mov cx,ax ; Save AX
mul bx ; AX = AX*BX = bytes/plane
mov [PlaneInc],ax ; save as PlaneInc
mov ax,cx ; Restore AX


mov di,[X] ; DI = X coordinate of dest.
mov cx,di ; save in CX
sar di,2 ; convert to address byte


;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;

mov dx,[_TopClip] ; Compare u.l. Y coord with Top
sub dx,[Y] ; clipping border
jle @@NotTopClip ; jump if VBM not clipped from above
cmp dx,bx
jnl @@NotVisible ; jump if VBM is completely obscured
mov [TopRow],dx
sub bx,dx
add [Y],dx
jmp short @@VertClipDone

;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;

@@NotVisible:
mov ax,1
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret

;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;

@@NotTopClip:
mov dx,[_BottomClip]
sub dx,[Y]
js @@NotVisible
mov [TopRow],0
cmp dx,bx
jg @@VertClipDone
inc dx
mov bx,dx

@@VertClipDone:

;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;

mov dx,[_LeftClip]
sub dx,di
jle @@NotLeftClip
cmp dx,ax
jnl @@NotVisible

add di,dx
mov [LeftSkip],dx
mov [DataInc],dx
sub ax,dx
mov [CType],1
jmp short @@HorizClipDone

;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;

@@NotLeftClip:
mov dx,[_RightClip]
sub dx,di
js @@NotVisible
mov [LeftSkip],0
mov [DataInc],0
cmp dx,ax
jge @@HorizClipDone ; was jg
inc dx
sub ax,dx
mov [DataInc],ax
mov ax,dx


mov [CType],-1

@@HorizClipDone:



mov [Width],ax ; Save width and height of clipped

mov [Height],bx ; image

add ax,[DataInc] ; AX = original width of image
mul [TopRow] ; Calculate bytes in clipped top
add si,ax ; rows
add si,2 ; Skip dimension bytes in source
add si,[LeftSkip] ; Skip pixels in front of row that
; are clipped

mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width
mov dx,bx ; BX - Width of image = No. bytes
sub dx,[Width] ; to first byte of next screen
mov [LineInc],dx ; row.

mov ax,[Y] ; Calculate screen start row
mul bx ; then adding screen offset
add di,ax
add di,[ScrnOffs]
mov ax,es ; copy ES to DS
mov ds,ax
mov ax,SCREEN_SEG ; Point ES to VGA segment
mov es,ax



and cx,3
mov ah,11h ; Set up initial plane mask
shl ah,cl

mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
mov al,MAP_MASK
out dx,al
inc dx
mov [Plane],4 ; Set plane counter to 4
mov bh,byte ptr [Width] ; set bh to width for fast looping
@@PlaneLoop:
push di ; Save bitmap's start dest. offset
push si
mov bl,byte ptr [Height] ; Reset row counter (BL)
mov al,ah
out dx,al ; set vga write plane
@@RowLoop:
mov cl,bh ; Reset Column counter cl
jcxz @@NoWidth
@@ColLoop:
lodsb ; Get next source bitmap byte
or al,al ; If not zero then write to dest.
jz @@NoPixel ; otherwise skip to next byte
mov es:[di],al
@@NoPixel:
inc di
loop @@ColLoop
@@NoWidth:
add si,[DataInc] ; Move to next source row
add di,[LineInc] ; Move to next screen row
dec bl ; decrement row counter
jnz @@RowLoop ; Jump if more rows left
pop si ; Restore SI and set to offset of
add si,[PlaneInc] ; first vis pixel in next plane data
pop di ; Restore bitmaps start dest byte
rol ah,1 ; Shift mask for next plane

; Plane Transition (A HACK but it works!)

jnb @@Nocarry ; Jump if not plane transition
mov bl,ah ; Save Plane Mask
mov ax,[CType] ; set AX to clip type inc variable
add bh,al ; Update advancing variables
sub [DataInc],ax ;
sub [LineInc],ax ;
cmp al,0 ; What type of clip do we have
mov ah,bl ; restore Plane mask
jg @@RightAdvance ; jump on a right clip!
inc di ; otherwise increment DI
jmp @@Nocarry
@@RightAdvance:
dec si
@@Nocarry:
dec [Plane] ; Decrement plane counter
jnz @@PlaneLoop ; Jump if more planes left

xor ax,ax
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret
_x_put_masked_pbm_clipxy endp




;----------------------------------------------------------------------
; x_put_pbm_clipx - Write a planar bitmap from system ram to video ram
; with clipping in x and y directions. similar to
; "x_put_pbm".
;
; See Also: x_put_pbm_clip
;
;
; See Also: x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipxy
;
; Clipping region variables: LeftClip,RightClip
;
; Written by Themie Gouthas
;
; This code is a SLOW hack, any better ideas are welcome
;----------------------------------------------------------------------
_x_put_pbm_clipx proc
ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword
LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:word=LocalStk
push bp
mov bp,sp
sub sp,LocalStk ; Create space for local variables
push si
push di
push ds
cld

les si,[Bitmap]

xor ax,ax
mov [CType],ax
mov al,byte ptr es:[si] ; AX = width


mov di,[X] ; DI = X coordinate of dest.
mov cx,di ; save in CX
sar di,2 ; convert to address byte



;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;

mov dx,[_LeftClip]
sub dx,di
jle @@NotLeftClip
cmp dx,ax
jnl @@NotVisible

add di,dx
mov [LeftSkip],dx
mov [DataInc],dx
sub ax,dx
mov [CType],1
jmp short @@HorizClipDone

;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;

@@NotVisible:
mov ax,1
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret

;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;

@@NotLeftClip:
mov dx,[_RightClip]
sub dx,di
js @@NotVisible
mov [LeftSkip],0
mov [DataInc],0
cmp dx,ax
jge @@HorizClipDone ; was jg
inc dx
sub ax,dx
mov [DataInc],ax
mov ax,dx
mov [CType],-1

@@HorizClipDone:

xor bh,bh
mov bl,byte ptr es:[si+1] ; BX = height

mov [Width],ax ; Save width and height of clipped
mov [Height],bx ; image


add si,2 ; Skip dimension bytes in source
add si,[LeftSkip] ; Skip pixels in front of row that
; are clipped


mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width
mov dx,bx ; BX - Width of image = No. bytes
sub dx,ax ; to first byte of next screen
mov [LineInc],dx ; row.

mov ax,[Y] ; Calculate screen start row
mul bx ; then adding screen offset
add di,ax
add di,[ScrnOffs]
mov ax,es ; copy ES to DS
mov ds,ax
mov ax,SCREEN_SEG ; Point ES to VGA segment
mov es,ax

and cx,3
mov ah,11h ; Set up initial plane mask
shl ah,cl

mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
mov al,MAP_MASK
out dx,al
inc dx
mov [Plane],4 ; Set plane counter to 4
mov bh,byte ptr [Width] ; set bh to width for fast looping
@@PlaneLoop:
push di ; Save bitmap's start dest. offset
mov bl,byte ptr [Height] ; Reset row counter (BL)
mov al,ah
out dx,al ; set vga write plane
@@RowLoop:
mov cl,bh ; Reset Column counter cl
shr cl,1
rep movsw ; Copy a complete row
adc cl,0
rep movsb
add si,[DataInc] ; Move to next source row
add di,[LineInc] ; Move to next screen row
dec bl ; decrement row counter
jnz @@RowLoop ; Jump if more rows left
pop di ; Restore bitmaps start dest byte
rol ah,1 ; Shift mask for next plane

; Plane Transition (A HACK but it works!)

jnb @@Nocarry ; Jump if not plane transition
mov bl,ah ; Save Plane Mask
mov ax,[CType] ; set AX to clip type inc variable
add bh,al ; Update advancing variables
sub [DataInc],ax ;
sub [LineInc],ax ;
cmp al,0 ; What type of clip do we have
mov ah,bl ; restore Plane mask
jg @@RightAdvance ; jump on a right clip!
inc di ; otherwise increment DI
jmp @@Nocarry
@@RightAdvance:
dec si
@@Nocarry:
dec [Plane] ; Decrement plane counter
jnz @@PlaneLoop ; Jump if more planes left

xor ax,ax
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret
_x_put_pbm_clipx endp



;----------------------------------------------------------------------
; x_put_pbm_clipy - Write a planar bitmap from system ram to video ram
; with clipping in y direction only. similar to
; "x_put_pbm".
;
; See Also: x_put_pbm,x_put_pbm_clipx,x_put_pbm_clipxy
;
; Clipping region variables: TopClip,BottomClip
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_put_pbm_clipy proc
ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword
LOCAL Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk
push bp
mov bp,sp
sub sp,LocalStk ; Create space for local variables
push si
push di
push ds
cld

les si,[Bitmap]

xor bh,bh
mov bl,byte ptr es:[si+1] ; BX = height
;mov [Height],bx

xor ah,ah
mov al,byte ptr es:[si] ; AX = width
mov [Width],ax

mov cx,ax ; Save AX
mul bx ; AX = AX*BX = bytes/plane
mov [PlaneInc],ax ; save as PlaneInc
mov ax,cx ; Restore AX

mov di,[X]
mov cx,di
and cx,3
shr di,2

;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;

mov dx,[_TopClip] ; Compare u.l. Y coord with Top
sub dx,[Y] ; clipping border
jle @@NotTopClip ; jump if VBM not clipped from above
cmp dx,bx
jnl @@NotVisible ; jump if VBM is completely obscured
mov [TopRow],dx
sub bx,dx
add [Y],dx
jmp short @@VertClipDone

;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;

@@NotVisible:
mov ax,1
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret

;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;

@@NotTopClip:
mov dx,[_BottomClip]
sub dx,[Y]
js @@NotVisible
mov [TopRow],0
cmp dx,bx
jg @@VertClipDone
inc dx
mov bx,dx

@@VertClipDone:

mov [Height],bx ; Calculate relative offset in data
mul [TopRow] ; of first visible scanline
add ax,2 ; Skip dimension bytes in source
add si,ax ; Skip top rows that arent visible


mov ax,[Y] ; Calculate screen row
mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen
mul bx ; width then adding screen offset
add di,ax
add di,[ScrnOffs]
sub bx,[Width] ; calculate difference from end of
mov [LineInc],bx ; b.m. in curr line to beginning of
; b.m. on next scan line
mov ax,es ; copy ES to DS
mov ds,ax
mov ax,SCREEN_SEG ; Point ES to VGA segment
mov es,ax

mov ah,11h ; Set up initial plane mask
shl ah,cl

mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
mov al,MAP_MASK
out dx,al
inc dx
mov bh,4 ; Set plane counter to 4
@@PlaneLoop:
push di ; Save bitmap's start dest. offset
push si ; Save Bitmaps data offset
mov bl,byte ptr [Height] ; Reset row counter (BL)
mov al,ah
out dx,al ; set vga write plane
@@RowLoop:
mov cl,byte ptr [Width] ; Reset Column counter cl
shr cl,1
rep movsw ; Copy a complete row
adc cl,0
rep movsb

add di,[LineInc] ; Move to next row
dec bl ; decrement row counter
jnz @@RowLoop ; Jump if more rows left
pop si ; Restore SI and set to offset of
add si,[PlaneInc] ; first vis pixel in next plane data
pop di ; Restore bitmaps start dest byte
rol ah,1 ; Shift mask for next plane
adc di,0 ; if carry increment screen offset
dec bh ; Decrement plane counter
jnz @@PlaneLoop ; Jump if more planes left

xor ax,ax
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret
_x_put_pbm_clipy endp


;----------------------------------------------------------------------
; x_put_pbm_clipxy - Write a planar bitmap from system ram to video ram
; with clipping in x and y directions. similar to
; "x_put_pbm".
;
; See Also: x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipx
;
; Clipping region variables: LeftClip,RightClip,TopClip,BottomClip
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_put_pbm_clipxy proc
ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword
LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk
push bp
mov bp,sp
sub sp,LocalStk ; Create space for local variables
push si
push di
push ds
cld

les si,[Bitmap]

xor ax,ax
mov [CType],ax
mov al,byte ptr es:[si] ; AX = width
xor bh,bh
mov bl,byte ptr es:[si+1] ; BX = height

mov cx,ax ; Save AX
mul bx ; AX = AX*BX = bytes/plane
mov [PlaneInc],ax ; save as PlaneInc
mov ax,cx ; Restore AX


mov di,[X] ; DI = X coordinate of dest.
mov cx,di ; save in CX
sar di,2 ; convert to address byte


;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;

mov dx,[_TopClip] ; Compare u.l. Y coord with Top
sub dx,[Y] ; clipping border
jle @@NotTopClip ; jump if VBM not clipped from above
cmp dx,bx
jnl @@NotVisible ; jump if VBM is completely obscured
mov [TopRow],dx
sub bx,dx
add [Y],dx
jmp short @@VertClipDone

;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;

@@NotVisible:
mov ax,1
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret

;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;

@@NotTopClip:
mov dx,[_BottomClip]
sub dx,[Y]
js @@NotVisible
mov [TopRow],0
cmp dx,bx
jg @@VertClipDone
inc dx
mov bx,dx

@@VertClipDone:

;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;

mov dx,[_LeftClip]
sub dx,di
jle @@NotLeftClip
cmp dx,ax
jnl @@NotVisible

add di,dx
mov [LeftSkip],dx
mov [DataInc],dx
sub ax,dx
mov [CType],1
jmp short @@HorizClipDone

;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;

@@NotLeftClip:
mov dx,[_RightClip]
sub dx,di
js @@NotVisible
mov [LeftSkip],0
mov [DataInc],0
cmp dx,ax
jge @@HorizClipDone ; was jg
inc dx
sub ax,dx
mov [DataInc],ax
mov ax,dx
mov [CType],-1

@@HorizClipDone:



mov [Width],ax ; Save width and height of clipped
mov [Height],bx ; image

add ax,[DataInc] ; AX = original width of image
mul [TopRow] ; Calculate bytes in clipped top
add si,ax ; rows
add si,2 ; Skip dimension bytes in source
add si,[LeftSkip] ; Skip pixels in front of row that
; are clipped

mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width
mov dx,bx ; BX - Width of image = No. bytes
sub dx,[Width] ; to first byte of next screen
mov [LineInc],dx ; row.

mov ax,[Y] ; Calculate screen start row
mul bx ; then adding screen offset
add di,ax
add di,[ScrnOffs]
mov ax,es ; copy ES to DS
mov ds,ax
mov ax,SCREEN_SEG ; Point ES to VGA segment
mov es,ax



and cx,3
mov ah,11h ; Set up initial plane mask
shl ah,cl

mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
mov al,MAP_MASK
out dx,al
inc dx
mov [Plane],4 ; Set plane counter to 4
mov bh,byte ptr [Width] ; set bh to width for fast looping
@@PlaneLoop:
push di ; Save bitmap's start dest. offset
push si
mov bl,byte ptr [Height] ; Reset row counter (BL)
mov al,ah
out dx,al ; set vga write plane
@@RowLoop:
mov cl,bh ; Reset Column counter cl
shr cl,1
rep movsw ; Copy a complete row
adc cl,0
rep movsb
add si,[DataInc] ; Move to next source row
add di,[LineInc] ; Move to next screen row
dec bl ; decrement row counter
jnz @@RowLoop ; Jump if more rows left
pop si ; Restore SI and set to offset of
add si,[PlaneInc] ; first vis pixel in next plane data
pop di ; Restore bitmaps start dest byte
rol ah,1 ; Shift mask for next plane

; Plane Transition (A HACK but it works!)

jnb @@Nocarry ; Jump if not plane transition
mov bl,ah ; Save Plane Mask
mov ax,[CType] ; set AX to clip type inc variable
add bh,al ; Update advancing variables
sub [DataInc],ax ;
sub [LineInc],ax ;
cmp al,0 ; What type of clip do we have
mov ah,bl ; restore Plane mask
jg @@RightAdvance ; jump on a right clip!
inc di ; otherwise increment DI
jmp @@Nocarry
@@RightAdvance:
dec si
@@Nocarry:
dec [Plane] ; Decrement plane counter
jnz @@PlaneLoop ; Jump if more planes left

xor ax,ax
pop ds ; restore data segment
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret
_x_put_pbm_clipxy endp

end





  3 Responses to “Category : C Source Code
Archive   : XLIB06.ZIP
Filename : XPBMCLIP.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/