**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