abrash-black-book/25-02.html
2013-12-30 12:21:49 +11:00

301 lines
9.2 KiB
HTML

<HTML>
<HEAD>
<META name=vsisbn content="1576101746">
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
<META name=vsauthor content="Michael Abrash">
<META name=vspublisher content="The Coriolis Group">
<META name=vspubdate content="07/01/97">
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: VGA Data Machinery</TITLE>
<!-- HEADER -->
<!-- Empty Reference Subhead -->
<!--ISBN=1576101746//-->
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
<!--AUTHOR=Michael Abrash//-->
<!--PUBLISHER=The Coriolis Group, Inc.//-->
<!--CHAPTER=25//-->
<!--PAGES=466-470//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="25-01.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="25-03.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<P><B>LISTING 25.1 L25-1.ASM</B></P>
<!-- CODE //-->
<PRE>
; Program to illustrate operation of data rotate and bit mask
; features of Graphics Controller. Draws 8&#215;8 character at
; specified location, using VGA&#146;s 8&#215;8 ROM font. Designed
; for use with modes 0Dh, 0Eh, 0Fh, 10h, and 12h.
; By Michael Abrash.
;
stack segment para stack &#145;STACK&#146;
db 512 dup(?)
stack ends
;
VGA_VIDEO_SEGMENT equ 0a000h ;VGA display memory segment
SCREEN_WIDTH_IN_BYTES equ 044ah ;offset of BIOS variable
FONT_CHARACTER_SIZE equ 8 ;# bytes in each font char
;
; VGA register equates.
;
GC_INDEX equ 3ceh ;GC index register
GC_ROTATE equ 3 ;GC data rotate/logical function
; register index
GC_BIT_MASK equ 8 ;GC bit mask register index
;
dseg segment para common &#145;DATA&#146;
TEST_TEXT_ROW equ 69 ;row to display test text at
TEST_TEXT_COL equ 17 ;column to display test text at
TEST_TEXT_WIDTH equ 8 ;width of a character in pixels
TestString label byte
db &#145;Hello, world!&#146;,0 ;test string to print.
FontPointer dd ? ;font offset
dseg ends
;
; Macro to set indexed register INDEX of GC chip to SETTING.
;
SETGC macro INDEX, SETTING
mov dx,GC_INDEX
mov ax,(SETTING SHL 8) OR INDEX
out dx,ax
endm
;
cseg segment para public &#145;CODE&#146;
assume cs:cseg, ds:dseg
start proc near
mov ax,dseg
mov ds,ax
;
; Select 640&#215;480 graphics mode.
;
mov ax,012h
int 10h
;
; Set driver to use the 8&#215;8 font.
;
mov ah,11h ;VGA BIOS character generator function,
mov al,30h ; return info subfunction
mov bh,3;get 8&#215;8 font pointer
int 10h
call SelectFont
;
; Print the test string.
;
mov si,offset TestString
mov bx,TEST_TEXT_ROW
mov cx,TEST_TEXT_COL
StringOutLoop:
lodsb
and al,al
jz StringOutDone
call DrawChar
add cx,TEST_TEXT_WIDTH
jmp StringOutLoop
StringOutDone:
;
; Reset the data rotate and bit mask registers.
;
SETGC GC_ROTATE, 0
SETGC GC_BIT_MASK, 0ffh
;
; Wait for a keystroke.
;
mov ah,1
int 21h
;
; Return to text mode.
;
mov ax,03h
int 10h
;
; Exit to DOS.
;
mov ah,4ch
int 21h
Start endp
;
; Subroutine to draw a text character in a linear graphics mode
; (0Dh, 0Eh, 0Fh, 010h, 012h).
; Font used should be pointed to by FontPointer.
;
; Input:
; AL = character to draw
; BX = row to draw text character at
; CX = column to draw text character at
;
; Forces ALU function to &#147;move&#148;.
;
DrawChar proc near
push ax
push bx
push cx
push dx
push si
push di
push bp
push ds
;
; Set DS:SI to point to font and ES to point to display memory.
;
lds si,[FontPointer] ;point to font
mov dx,VGA_VIDEO_SEGMENT
mov es,dx ;point to display memory
;
; Calculate screen address of byte character starts in.
;
push ds ;point to BIOS data segment
sub dx,dx
mov ds,dx
xchg ax,bx
mov di,ds:[SCREEN_WIDTH_IN_BYTES] ;retrieve BIOS
; screen width
pop ds
mul di ;calculate offset of start of row
push di ;set aside screen width
mov di,cx ;set aside the column
and cl,0111b ;keep only the column in-byte address
shr di,1
shr di,1
shr di,1 ;divide column by 8 to make a byte address
add di,ax ;and point to byte
;
; Calculate font address of character.
;
sub bh,bh
shl bx,1 ;assumes 8 bytes per character; use
shl bx,1 ; a multiply otherwise
shl bx,1 ;offset in font of character
add si,bx ;offset in font segment of character
;
; Set up the GC rotation.
;
mov dx,GC_INDEX
mov al,GC_ROTATE
mov ah,cl
out dx,ax
;
; Set up BH as bit mask for left half,
; BL as rotation for right half.
;
mov bx,0ffffh
shr bh,cl
neg cl
add cl,8
shl bl,cl
;
; Draw the character, left half first, then right half in the
; succeeding byte, using the data rotation to position the character
; across the byte boundary and then using the bit mask to get the
; proper portion of the character into each byte.
; Does not check for case where character is byte-aligned and
; no rotation and only one write is required.
;
mov bp,FONT_CHARACTER_SIZE
mov dx,GC_INDEX
pop cx ;get back screen width
dec cx
dec cx ; -2 because do two bytes for each char
CharacterLoop:
;
; Set the bit mask for the left half of the character.
;
mov al,GC_BIT_MASK
mov ah,bh
out dx,ax
;
; Get the next character byte & write it to display memory.
; (Left half of character.)
;
mov al,[si] ;get character byte
mov ah,es:[di] ;load latches
stosb ;write character byte
;
; Set the bit mask for the right half of the character.
;
mov al,GC_BIT_MASK
mov ah,bl
out dx,ax
;
; Get the character byte again & write it to display memory.
; (Right half of character.)
;
lodsb ;get character byte
mov ah,es:[di] ;load latches
stosb ;write character byte
;
; Point to next line of character in display memory.
;
add di,cx
;
dec bp
jnz CharacterLoop
;
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
DrawChar endp
;
; Set the pointer to the font to draw from to ES:BP.
;
SelectFont proc near
mov word ptr [FontPointer],bp ;save pointer
mov word ptr [FontPointer&#43;2],es
ret
SelectFont endp
;
cseg ends
end start
</PRE>
<!-- END CODE //-->
<P>The bit mask can be used for much more than bit-aligned fonts. For example, the bit mask is useful for fast pixel drawing, such as that performed when drawing lines, as we&#146;ll see in Chapter 35. It&#146;s also useful for drawing the edges of primitives, such as filled polygons, that potentially involve modifying some but not all of the pixels controlled by a single byte of display memory.
</P>
<P>Basically, the bit mask is handy whenever only <I>some</I> of the eight pixels in a byte of display memory need to be changed, because it allows full use of the VGA&#146;s four-way parallel processing capabilities for the pixels that are to be drawn, without interfering with the pixels that are to be left unchanged. The alternative would be plane-by-plane processing, which from a performance perspective would be undesirable indeed.</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="25-01.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="25-03.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<hr width="90%" size="1" noshade>
<div align="center">
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book &copy; 2001 Michael Abrash</font>
</div>
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
<!-- reference_subfoot = footer -->
<!-- reference_footer = subfoot -->
<!-- BEGIN SUB FOOTER -->
</BODY>
</HTML>
<!-- END FOOTER -->