LISTING 44.2 L44-2.ASM
; Low-level animation routines.
; Tested with TASM
SCREEN-WIDTH equ 80 ;screen width in bytes
INPUT-STATUS-1 equ 03dah ;Input Status 1 register
CRTC-INDEX equ 03d4h ;CRT Controller Index reg
START-ADDRESS-HIGH equ 0ch ;bitmap start address high byte
START-ADDRESS-LOW equ 0dh ;bitmap start address low byte
GC-INDEX equ 03ceh ;Graphics Controller Index reg
SET-RESET equ 0 ;GC index of Set/Reset reg
G-MODE equ 5 ;GC index of Mode register
.model small
.data
BIOS8x8Ptr dd ? ;points to BIOS 8x8 font
; Tables used to look up left and right clip masks.
LeftMask d 0ffh, 07fh, 03fh, 01fh, 00fh, 007h, 003h, 001h
RightMask d 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0fch, 0feh, 0ffh
.code
; Draws the specified filled rectangle in the specified color.
; Assumes the display is in mode 12h. Does not clip and assumes
; rectangle coordinates are valid.
;
; C near-callable as: void DrawRect(int LeftX, int TopY, int RightX,
; int BottomY, int Color, unsigned int ScrnOffset,
; unsigned int ScrnSegment);
DrawRectParms struc
dw 2 dup (?) ;pushed BP and return address
LeftX dw ? ;X coordinate of left side of rectangle
TopY dw ? ;Y coordinate of top side of rectangle
RightX dw ? ;X coordinate of right side of rectangle
BottomY dw ? ;Y coordinate of bottom side of rectangle
Color dw ? ;color in which to draw rectangle (only the
; lower 4 bits matter)
ScrnOffset dw ? ;offset of base of bitmap in which to draw
ScrnSegment dw ? ;segment of base of bitmap in which to draw
DrawRectParms ends
public -DrawRect
-DrawRect proc near
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
push si ;preserve caller's register variables
push di
cld
mov dx,GC-INDEX
mov al,SET-RESET
mov ah,byte ptr Color[bp]
out dx,ax ;set the color in which to draw
mov ax,G-MODE + (0300h)
out dx,ax ;set to write mode 3
les di,dword ptr ScrnOffset[bp] ;point to bitmap start
mov ax,SCREEN-WIDTH
mul TopY[bp] ;point to the start of the top scan
add di,ax ; line to fill
mov ax,LeftX[bp]
mov bx,ax
shr ax,1 ;/8 = byte offset from left of screen
shr ax,1
shr ax,1
add di,ax ;point to the upper-left corner of fill area
and bx,7 ;isolate intrapixel address
mov dl,LeftMask[bx] ;set the left-edge clip mask
mov bx,RightX[bp]
mov si,bx
and bx,7 ;isolate intrapixel address of right edge
mov dh,RightMask[bx] ;set the right-edge clip mask
mov bx,LeftX[bp]
and bx,NOT 7 ;intrapixel address of left edge
su si,bx
shr si,1
shr si,1
shr si,1 ;# of bytes across spanned by rectangle - 1
jnz MasksSet ;if there's only one byte across,
and dl,dh ; combine the masks
MasksSet:
mov bx,BottomY[bp]
su bx,TopY[bp] ;# of scan lines to fill - 1
FillLoop:
push di ;remember line start offset
mov al,dl ;left edge clip mask
xchg es:[di],al ;draw the left edge
inc di ;point to the next byte
mov cx,si ;# of bytes left to do
dec cx ;# of bytes left to do - 1
js LineDone ;that's it if there's only 1 byte across
jz DrawRightEdge ;no middle bytes if only 2 bytes across
mov al,0ffh ;non-edge bytes are solid
rep stos ;draw the solid bytes across the middle
DrawRightEdge:
mov al,dh ;right-edge clip mask
xchg es:[di],al ;draw the right edge
LineDone:
pop di ;retrieve line start offset
add di,SCREEN-WIDTH ;point to the next line
dec bx ;count off scan lines
jns FillLoop
pop di ;restore caller's register variables
pop si
pop bp ;restore caller's stack frame
ret
-DrawRect endp
; Shows the page at the specified offset in the bitmap. Page is
; displayed when this routine returns.
;
; C near-callable as: void ShowPage(unsigned int StartOffset);
ShowPageParms struc
dw 2 dup (?) ;pushed BP and return address
StartOffset dw ? ;offset in bitmap of page to display
ShowPageParms ends
public -ShowPage
-ShowPage proc near
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
; Wait for display enable to be active (status is active low), to be
; sure both halves of the start address will take in the same frame.
mov bl,START-ADDRESS-LOW ;preload for fastest
mov bh,byte ptr StartOffset[bp] ; flipping once display
mov cl,START-ADDRESS-HIGH ; enable is detected
mov ch,byte ptr StartOffset+1[bp]
mov dx,INPUT-STATUS-1
WaitDE:
in al,dx
test al,01h
jnz WaitDE ;display enable is active low (0 = active)
; Set the start offset in display memory of the page to display.
mov dx,CRTC-INDEX
mov ax,bx
out dx,ax ;start address low
mov ax,cx
out dx,ax ;start address high
; Now wait for vertical sync, so the other page will be invisible when
; we start drawing to it.
mov dx,INPUT-STATUS-1
WaitVS:
in al,dx
test al,08h
jz WaitVS ;vertical sync is active high (1 = active)
pop bp ;restore caller's stack frame
ret
-ShowPage endp
; Displays the specified image at the specified location in the
; specified bitmap, in the desired color.
;
; C near-callable as: void DrawImage(int LeftX, int TopY,
; image **RotationTable, int Color, unsigned int ScrnOffset,
; unsigned int ScrnSegment);
DrawImageParms struc
dw 2 dup (?) ;pushed BP and return address
DILeftX dw ? ;X coordinate of left side of image
DITopY dw ? ;Y coordinate of top side of image
RotationTable dw ? ;pointer to table of pointers to image
; rotations
DIColor dw ? ;color in which to draw image (only the
; lower 4 bits matter)
DIScrnOffset dw ? ;offset of base of bitmap in which to draw
DIScrnSegment dw ? ;segment of base of bitmap in which to draw
DrawImageParms ends
image struc
WidthInBytes dw ?
Height dw ?
BitPattern dw ?
image ends
public -DrawImage
-DrawImage proc near
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
push si ;preserve caller's register variables
push di
cld
mov dx,GC-INDEX
mov al,SET-RESET
mov ah,byte ptr DIColor[bp]
out dx,ax ;set the color in which to draw
mov ax,G-MODE + (0300h)
out dx,ax ;set to write mode 3
les di,dword ptr DIScrnOffset[bp] ;point to bitmap start
mov ax,SCREEN-WIDTH
mul DITopY[bp] ;point to the start of the top scan
add di,ax ; line on which to draw
mov ax,DILeftX[bp]
mov bx,ax
shr ax,1 ;/8 = byte offset from left of screen
shr ax,1
shr ax,1
add di,ax ;point to the upper-left corner of draw area
and bx,7 ;isolate intrapixel address
shl bx,1 ;*2 for word look-up
add bx,RotationTable[bp] ;point to the image structure for
mov bx,[bx] ; the intrabyte rotation
mov dx,[bx].WidthInBytes ;image width
mov si,[bx].BitPattern ;pointer to image pattern bytes
mov bx,[bx].Height ;image height
DrawImageLoop:
push di ;remember line start offset
mov cx,dx ;# of bytes across
DrawImageLineLoop:
lods ;get the next image byte
xchg es:[di],al ;draw the next image byte
inc di ;point to the following screen byte
loop DrawImageLineLoop
pop di ;retrieve line start offset
add di,SCREEN-WIDTH ;point to the next line
dec bx ;count off scan lines
jnz DrawImageLoop
pop di ;restore caller's register variables
pop si
pop bp ;restore caller's stack frame
ret
-DrawImage endp
; Draws a 0-terminated text string at the specified location in the
; specified bitmap in white, using the 8x8 BIOS font. Must be at an X
; coordinate that's a multiple of 8.
;
; C near-callable as: void TextUp(char *Text, int LeftX, int TopY,
; unsigned int ScrnOffset, unsigned int ScrnSegment);
TextUpParms struc
dw 2 dup (?) ;pushed BP and return address
Text dw ? ;pointer to text to draw
TULeftX dw ? ;X coordinate of left side of rectangle
; (must be a multiple of 8)
TUTopY dw ? ;Y coordinate of top side of rectangle
TUScrnOffset dw ? ;offset of base of bitmap in which to draw
TUScrnSegment dw ? ;segment of base of bitmap in which to draw
TextUpParms ends
public -TextUp
-TextUp proc near
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
push si ;preserve caller's register variables
push di
cld
mov dx,GC-INDEX
mov ax,G-MODE + (0000h)
out dx,ax ;set to write mode 0
les di,dword ptr TUScrnOffset[bp] ;point to bitmap start
mov ax,SCREEN-WIDTH
mul TUTopY[bp] ;point to the start of the top scan
add di,ax ; line the text starts on
mov ax,TULeftX[bp]
mov bx,ax
shr ax,1 ;/8 = byte offset from left of screen
shr ax,1
shr ax,1
add di,ax ;point to the upper-left corner of first char
mov si,Text[bp] ;point to text to draw
TextUpLoop:
lods ;get the next character to draw
and al,al
jz TextUpDone ;done if null byte
push si ;preserve text string pointer
push di ;preserve character's screen offset
push ds ;preserve default data segment
call CharUp ;draw this character
pop ds ;restore default data segment
pop di ;retrieve character's screen offset
pop si ;retrieve text string pointer
inc di ;point to next character's start location
jmp TextUpLoop
TextUpDone:
pop di ;restore caller's register variables
pop si
pop bp ;restore caller's stack frame
ret
CharUp: ;draws the character in AL at ES:DI
lds si,[BIOS8x8Ptr] ;point to the 8x8 font start
mov bl,al
su bh,bh
shl bx,1
shl bx,1
shl bx,1 ;*8 to look up character offset in font
add si,bx ;point DS:Sito character data in font
mov cx,8 ;characters are 8 high
CharUpLoop:
movs ;copy the next character pattern byte
add di,SCREEN-WIDTH-1 ;point to the next dest byte
loop CharUpLoop
ret
-TextUp endp
; Sets the pointer to the BIOS 8x8 font.
;
; C near-callable as: extern void SetBIOS8x8Font(void);
public -SetBIOS8x8Font
-SetBIOS8x8Font proc near
push bp ;preserve caller's stack frame
push si ;preserve caller's register variables
push di ; and data segment (don't assume BIOS
push ds ; preserves anything)
mov ah,11h ;BIOS character generator function
mov al,30h ;BIOS information subfunction
mov bh,3 ;request 8x8 font pointer
int 10h ;invoke BIOS video services
mov word ptr [BIOS8x8Ptr],bp ;store the pointer
mov word ptr [BIOS8x8Ptr+2],es
pop ds
pop di ;restore caller's register variables
pop si
pop bp ;restore caller's stack frame
ret
-SetBIOS8x8Font endp
end
Graphics Programming Black Book © 2001 Michael Abrash