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

 
Output of file : XCLIPPBM.ASM contained in archive : XLIB06.ZIP
;-----------------------------------------------------------------------
; MODULE XCLIPPBM
;
; This module was written by Matthew MacKenzie
; [email protected]
;
; Clipped transfer of planar bitmaps from system memory to video memory.
;
; Compile with TASM.
; C near-callable.
;
; ****** XLIB - Mode X graphics library ****************
; ****** ****************
; ****** Written By Themie Gouthas ****************
;
; [email protected]
; [email protected]
;-----------------------------------------------------------------------

include xlib.inc
include xclippbm.inc


.data

align 2

; global clipping variables
_TopBound dw (?)
_BottomBound dw (?)
_LeftBound dw (?)
_RightBound dw (?)

; VGA plane masks
ColumnMask db 011h,022h,044h,088h

; bit delay timers
LeftDelay db 0, 1, 2, 4
RightDelay db 0, 4, 2, 1


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; _x_clip_pbm
;
; C near-callable as:
;
; void x_clip_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);
;
; Bitmap is a planar bitmap, in the regular Xlib format.
;
; ax, bx, cx, and dx go south.

.code

public _x_clip_pbm
align 2
_x_clip_pbm proc
ARG X:word, Y:word, ScreenOffs:word, Bitmap:dword
LOCAL left_counter, right_counter,column,clipped_height,clipped_width,screen_pos,bitmap_pos,bitmap_size,VGA_mask,width_copy,height_temp,screen_width:word=LocalStk
; Tasm 1.0 does not allow the \ line continuation
;LOCAL left_counter:word, right_counter:word, \
; column:word, clipped_height:word, clipped_width:word, \
; screen_pos:word, bitmap_pos:word, bitmap_size:word, \
; VGA_mask:word, width_copy, height_temp:word, \
; screen_width:word=LocalStk

push bp
mov bp, sp
sub sp, LocalStk
push si
push di
push ds

; sociopathic cases: are the clipping bounds out of order?
mov ax, _TopBound
cmp ax, _BottomBound
jg @@GetOut
mov ax, _LeftBound
cmp ax, _RightBound
jle @@ReasonableAndProper
@@GetOut: ; return a 1 -- no image drawn
pop ds
pop di
pop si
mov ax, 1
mov sp, bp
pop bp
ret

@@ReasonableAndProper:

; we need to use both the tables in ds and the height and width of the bitmap
les si, Bitmap

; vertical position
xor cx, cx
mov cl, byte ptr es:[si + 1] ; height of bitmap
xor ax, ax
mov al, byte ptr es:[si] ; width of bitmap
mul cx
mov bitmap_size, ax
mov ax, Y
cmp ax, _BottomBound ; top edge below clipping box?
jg @@GetOut

mov bx, cx
add bx, ax
dec bx ; bottom edge = Y + height - 1
cmp bx, _TopBound
jl @@GetOut
sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound
jle @@NoBottomBound
sub cx, bx ; clip bottom margin from height
@@NoBottomBound:
mov bx, _TopBound
sub bx, ax ; top margin = TopBound - Y
jle @@NoTopBound
add ax, bx ; top edge = Y + top margin
sub cx, bx ; clip top margin from height
jmp @@KeepMargin
@@NoTopBound:
xor bx, bx
@@KeepMargin:
mov clipped_height, cx

mul _ScrnLogicalByteWidth
mov di, ax
add di, ScreenOffs ; row of upper-left corner of blit

mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height)
mov ax, cx
mul bx
add si, ax
add si, 2 ; starting position in bitmap

; horizontal position
mov width_copy, cx
mov dx, X
cmp dx, _RightBound
jg @@GetOut
mov dx, 0 ; unclipped value for right delay

mov ax, cx
shl ax, 2 ; width in pixels
add ax, X
dec ax ; right edge = X + width in pixels - 1
cmp ax, _LeftBound
jl @@GetOut
sub ax, _RightBound ; right margin = right edge - RightBound
jle @@NoRightBound
mov bx, ax
and bx, 3
mov dl, RightDelay[bx]
shr ax, 2
sub cx, ax ; subtract clipped bytes from width
@@NoRightBound:
mov right_counter, dx
mov dx, 0 ; unclipped value for left delay
mov ax, _LeftBound
sub ax, X ; left margin = LeftBound - X
jle @@NoLeftBound
mov bx, ax
and bx, 3
mov dl, LeftDelay[bx]
add ax, 3
shr ax, 2 ; left margin/4, rounded up
sub cx, ax ; subtract clipped bytes from width
add si, ax ; move starting position in bitmap past margin
add di, ax ; move starting position on screen past margin
@@NoLeftBound:
mov left_counter, dx
mov clipped_width, cx

mov ax, X ; add x coordinate to screen position
mov bx, ax
sar ax, 2
add di, ax

mov dx, SC_INDEX
mov al, MAP_MASK
out dx, al
inc dx

and bx, 3 ; initial mask
xor ax, ax
mov al, ColumnMask[bx]
mov VGA_mask, ax
out dx, al ; initial mask

mov column, 4
mov bitmap_pos, si
mov screen_pos, di
mov ax, _ScrnLogicalByteWidth
mov screen_width, ax ; since we move ds

; we've used all our tables, so we can change ds to point to the bitmap,
; and es to point to the screen
mov ds, word ptr [Bitmap + 2]
mov ax, SCREEN_SEG
mov es, ax

cld ; strings go forward
mov bx, width_copy
sub bx, clipped_width ; bytes to advance one line in bitmap

; let's actually draw something for a change
@@WritePlane:
mov ax, clipped_height
mov height_temp, ax
mov dx, screen_width
sub dx, clipped_width ; bytes to advance one line across screen

@@WriteLine:
mov cx, clipped_width
shr cx, 1
rep movsw ; in they went, two by two...
adc cx, 0
rep movsb ; catch stray last byte, if it's there
add si, bx ; advance one bitmap line
add di, dx ; advance one screen line

dec height_temp
jnz @@WriteLine

dec column
jz @@OuttaHere ; only four columns per customer, please
mov dx, SC_INDEX + 1
rol byte ptr VGA_mask, 1
adc screen_pos, 0 ; add to location if we've wrapped to plane 0
mov al, byte ptr VGA_mask
out dx, al ; set VGA for next column

shr right_counter, 1
jnc @@NoRightCounter
dec clipped_width ; cut off right edge for later planes
inc bx
@@NoRightCounter:
shr left_counter, 1
jnc @@NoLeftCounter
inc clipped_width ; add to left edge for later planes
dec bx
dec bitmap_pos
dec screen_pos
@@NoLeftCounter:
mov si, bitmap_pos
add si, bitmap_size
mov bitmap_pos, si
mov di, screen_pos
jmp @@WritePlane

@@OuttaHere: ; return a 0 -- something was inside the boundary
pop ds
pop di
pop si
mov ax, 0
mov sp, bp
pop bp
ret
_x_clip_pbm endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; _x_clip_masked_pbm
;
; C near-callable as:
;
; void x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);
;
; Bitmap is a planar bitmap, in the regular Xlib format.
; The width of the bitmap cannot be greater than 90 bytes, however.
; Ain't that just criminal?
;
; ax, bx, cx, and dx go south.


; one branch per pixel is more than enough -- we'll unroll the line-writing
; loop all the way to try to get a little speed (at the expense, as usual,
; of a chunk of memory)

MaskedPoint macro offset
mov al, [si + offset]
or al, al
jz $+6
mov es:[di + offset], al
endm

MaskedPointSize equ 11

public _x_clip_masked_pbm
align 2
_x_clip_masked_pbm proc
ARG X:word, Y:word, ScreenOffs:word, Bitmap:dword
; Tasm 1.0 does not allow the \ line continuation
LOCAL left_counter,right_counter,column:word,clipped_height,screen_pos,bitmap_pos,bitmap_size,VGA_mask,width_copy,height_temp,screen_width:word=LocalStk
;LOCAL left_counter:word, right_counter:word, \
; column:word, clipped_height:word, \
; screen_pos:word, bitmap_pos:word, bitmap_size:word, \
; VGA_mask:word, width_copy, height_temp:word, \
; screen_width:word=LocalStk
push bp
mov bp, sp
sub sp, LocalStk
push si
push di
push ds

; sociopathic cases: are the clipping bounds out of order?
mov ax, _TopBound
cmp ax, _BottomBound
jg @@GetOut
mov ax, _LeftBound
cmp ax, _RightBound
jle @@ReasonableAndProper
@@GetOut: ; return a 1 -- no image drawn
pop ds
pop di
pop si
mov ax, 1
mov sp, bp
pop bp
ret

@@ReasonableAndProper:

; we need to use both the tables in ds and the height and width of the bitmap
les si, Bitmap

; vertical position
xor cx, cx
mov cl, byte ptr es:[si + 1] ; height of bitmap
xor ax, ax
mov al, byte ptr es:[si] ; width of bitmap
mul cx
mov bitmap_size, ax
mov ax, Y
cmp ax, _BottomBound ; top edge below clipping box?
jg @@GetOut

mov bx, cx
add bx, ax
dec bx ; bottom edge = Y + height - 1
cmp bx, _TopBound
jl @@GetOut
sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound
jle @@NoBottomBound
sub cx, bx ; clip bottom margin from height
@@NoBottomBound:
mov bx, _TopBound
sub bx, ax ; top margin = TopBound - Y
jle @@NoTopBound
add ax, bx ; top edge = Y + top margin
sub cx, bx ; clip top margin from height
jmp @@KeepMargin
@@NoTopBound:
xor bx, bx
@@KeepMargin:
mov clipped_height, cx

mul _ScrnLogicalByteWidth
mov di, ax
add di, ScreenOffs ; row of upper-left corner of blit

mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height)
mov ax, cx
mul bx
add si, ax
add si, 2 ; starting position in bitmap

; horizontal position
mov width_copy, cx
mov dx, X
cmp dx, _RightBound
jg @@GetOut
mov dx, 0 ; unclipped value for right delay

mov ax, cx
shl ax, 2 ; width in pixels
add ax, X
dec ax ; right edge = X + width in pixels - 1
cmp ax, _LeftBound
jl @@GetOut
sub ax, _RightBound ; right margin = right edge - RightBound
jle @@NoRightBound
mov bx, ax
and bx, 3
mov dl, RightDelay[bx]
shr ax, 2
sub cx, ax ; subtract clipped bytes from width
@@NoRightBound:
mov right_counter, dx
mov dx, 0 ; unclipped value for left delay
mov ax, _LeftBound
sub ax, X ; left margin = LeftBound - X
jle @@NoLeftBound
mov bx, ax
and bx, 3
mov dl, LeftDelay[bx]
add ax, 3
shr ax, 2 ; left margin/4, rounded up
sub cx, ax ; subtract clipped bytes from width
add si, ax ; move starting position in bitmap past margin
add di, ax ; move starting position on screen past margin
@@NoLeftBound:
mov left_counter, dx
mov ax, cx
imul ax, (-1 * MaskedPointSize)
add ax, offset @@LineDone + 2
mov cx, ax ; jump offset for plotting

mov ax, X ; add x coordinate to screen position
mov bx, ax
shr ax, 2
add di, ax

mov dx, SC_INDEX
mov al, MAP_MASK
out dx, al
inc dx

and bx, 3 ; initial mask
xor ax, ax
mov al, ColumnMask[bx]
mov VGA_mask, ax
out dx, al

mov column, 4
mov bitmap_pos, si
mov screen_pos, di
mov ax, _ScrnLogicalByteWidth
mov screen_width, ax ; since we move ds

; we've used all our tables, so we can change ds to point to the bitmap,
; and es to point to the screen
mov ds, word ptr [Bitmap + 2]
mov ax, SCREEN_SEG
mov es, ax

mov bx, width_copy

; let's actually draw something for a change
mov ax, clipped_height
mov height_temp, ax
mov dx, screen_width
jmp cx

; 90 bottles of beer on the wall...
PointLoop = 89
rept 89
MaskedPoint PointLoop
PointLoop = PointLoop - 1
endm
; one bottle of beer...

; final point needs a different branch offset, so we don't use MaskedPoint
mov al, [si]
or al, al
jz @@LineDone
mov es:[di], al

@@LineDone:
add si, bx ; advance one bitmap line
add di, dx ; advance one screen line
dec height_temp
jz @@PlaneDone
jmp cx

@@PlaneDone:
dec column
jz @@OuttaHere ; only four columns per customer, please
mov dx, SC_INDEX + 1
rol byte ptr VGA_mask, 1
adc screen_pos, 0 ; move to new column if we've wrapped to plane 0
mov al, byte ptr VGA_mask
out dx, al ; set VGA for next column

shr right_counter, 1
jnc @@NoRightCounter
add cx, MaskedPointSize ; cut off right edge for later planes
@@NoRightCounter:
shr left_counter, 1
jnc @@NoLeftCounter
sub cx, MaskedPointSize ; add to left edge for later planes
dec bitmap_pos
dec screen_pos
@@NoLeftCounter:
mov si, bitmap_pos
add si, bitmap_size
mov bitmap_pos, si
mov di, screen_pos

mov ax, clipped_height
mov height_temp, ax
mov dx, screen_width
jmp cx

@@OuttaHere: ; return a 0 -- something was inside the boundary
pop ds
pop di
pop si
mov ax, 0
mov sp, bp
pop bp
ret
_x_clip_masked_pbm endp

end



  3 Responses to “Category : C Source Code
Archive   : XLIB06.ZIP
Filename : XCLIPPBM.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/