Move everything into one directory, update links
This commit is contained in:
parent
b946ff9e70
commit
4eef8b2919
680 changed files with 1638 additions and 1638 deletions
443
30-02.html
Normal file
443
30-02.html
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
<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: Video Est Omnis Divisa</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=30//-->
|
||||
<!--PAGES=566-572//-->
|
||||
<!--UNASSIGNED1//-->
|
||||
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
|
||||
|
||||
<CENTER>
|
||||
<TABLE BORDER>
|
||||
<TR>
|
||||
<TD><A HREF="30-01.html">Previous</A></TD>
|
||||
<TD><A HREF="index.html">Table of Contents</A></TD>
|
||||
<TD><A HREF="30-03.html">Next</A></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</CENTER>
|
||||
<P><BR></P>
|
||||
<P>Finally, after another keypress, Listing 30.1 halts.
|
||||
</P>
|
||||
<P><B>LISTING 30.1 L30-1.ASM</B></P>
|
||||
<!-- CODE //-->
|
||||
<PRE>
|
||||
; Demonstrates the VGA/EGA split screen in action.
|
||||
;
|
||||
;*********************************************************************
|
||||
IS_VGA equ 1 ;set to 0 to assemble for EGA
|
||||
;
|
||||
VGA_SEGMENT equ 0a000h
|
||||
SCREEN_WIDTH equ 640
|
||||
SCREEN_HEIGHT equ 350
|
||||
CRTC_INDEX equ 3d4h ;CRT Controller Index register
|
||||
OVERFLOW equ 7 ;index of Overflow reg in CRTC
|
||||
MAXIMUM_SCAN_LINEequ 9 ;index of Maximum Scan Line register
|
||||
; in CRTC
|
||||
START_ADDRESS_HIGH equ 0ch ;index of Start Address High register
|
||||
; in CRTC
|
||||
START_ADDRESS_LOW equ 0dh ;index of Start Address Low register
|
||||
; in CRTC
|
||||
LINE_COMPARE equ 18h ;index of Line Compare reg (bits 7-0
|
||||
; of split screen start scan line)
|
||||
; in CRTC
|
||||
INPUT_STATUS_0 equ 3dah ;Input Status 0 register
|
||||
WORD_OUTS_OK equ 1 ;set to 0 to assemble for
|
||||
; computers that can't handle
|
||||
; word outs to indexed VGA registers
|
||||
;*********************************************************************
|
||||
; Macro to output a word value to a port.
|
||||
;
|
||||
OUT_WORD macro
|
||||
if WORD_OUTS_OK
|
||||
out dx,ax
|
||||
else
|
||||
out dx,al
|
||||
inc dx
|
||||
xchg ah,al
|
||||
out dx,al
|
||||
dec dx
|
||||
xchg ah,al
|
||||
endif
|
||||
endm
|
||||
;*********************************************************************
|
||||
MyStack segment para stack 'STACK'
|
||||
db 512 dup (0)
|
||||
MyStack ends
|
||||
;*********************************************************************
|
||||
Data segment
|
||||
SplitScreenLine dw ? ;line the split screen currently
|
||||
; starts after
|
||||
StartAddress dw ? ;display memory offset at which
|
||||
; scanning for video data starts
|
||||
; Message displayed in split screen.
|
||||
SplitScreenMsg db 'Split screen text row #'
|
||||
DigitInsert dw ?
|
||||
db '...$'
|
||||
Data ends
|
||||
;*********************************************************************
|
||||
Code segment
|
||||
assume cs:Code, ds:Data
|
||||
;*********************************************************************
|
||||
Start proc near
|
||||
mov ax,Data
|
||||
mov ds,ax
|
||||
;
|
||||
; Select mode 10h, 640x350 16-color graphics mode.
|
||||
;
|
||||
mov ax,0010h ;AH=0 is select mode function
|
||||
;AL=10h is mode to select,
|
||||
; 640x350 16-color graphics mode
|
||||
int 10h
|
||||
;
|
||||
; Put text into display memory starting at offset 0, with each row
|
||||
; labelled as to number. This is the part of memory that will be
|
||||
; displayed in the split screen portion of the display.
|
||||
;
|
||||
mov cx,25 ;# of lines of text we'll draw into
|
||||
; the split screen part of memory
|
||||
FillSplitScreenLoop:
|
||||
mov ah,2 ;set cursor location function #
|
||||
sub bh,bh ;set cursor in page 0
|
||||
mov dh,25
|
||||
sub dh,cl ;calculate row to draw in
|
||||
sub dl,dl ;start in column 0
|
||||
int 10h ;set the cursor location
|
||||
mov al,25
|
||||
sub al,cl ;calculate row to draw in again
|
||||
sub ah,ah ;make the value a word for division
|
||||
mov dh,10
|
||||
div dh ;split the row # into two digits
|
||||
add ax,'00' ;convert the digits to ASCII
|
||||
mov [DigitInsert],ax ;put the digits into the text
|
||||
; to be displayed
|
||||
mov ah,9
|
||||
mov dx,offset SplitScreenMsg
|
||||
int 21h ;print the text
|
||||
loop FillSplitScreenLoop
|
||||
;
|
||||
; Fill display memory starting at 8000h with a diagonally striped
|
||||
; pattern.
|
||||
;
|
||||
mov ax,VGA_SEGMENT
|
||||
mov es,ax
|
||||
mov di,8000h
|
||||
mov dx,SCREEN_HEIGHT ;fill all lines
|
||||
mov ax,8888h ;starting fill pattern
|
||||
cld
|
||||
RowLoop:
|
||||
mov cx,SCREEN_WIDTH/8/2 ;fill 1 scan line a word at a time
|
||||
rep stosw ;fill the scan line
|
||||
ror ax,1 ;shift pattern word
|
||||
dec dx
|
||||
jnz RowLoop
|
||||
;
|
||||
; Set the start address to 8000h and display that part of memory.
|
||||
;
|
||||
mov [StartAddress],8000h
|
||||
call SetStartAddress
|
||||
;
|
||||
; Slide the split screen half way up the screen and then back down
|
||||
; a quarter of the screen.
|
||||
;
|
||||
mov [SplitScreenLine],SCREEN_HEIGHT-1
|
||||
;set the initial line just off
|
||||
; the bottom of the screen
|
||||
mov cx,SCREEN_HEIGHT/2
|
||||
call SplitScreenUp
|
||||
mov cx,SCREEN_HEIGHT/4
|
||||
call SplitScreenDown
|
||||
;
|
||||
; Now move up another half a screen and then back down a quarter.
|
||||
;
|
||||
mov cx,SCREEN_HEIGHT/2
|
||||
call SplitScreenUp
|
||||
mov cx,SCREEN_HEIGHT/4
|
||||
call SplitScreenDown
|
||||
;
|
||||
; Finally move up to the top of the screen.
|
||||
;
|
||||
mov cx,SCREEN_HEIGHT/2-2
|
||||
call SplitScreenUp
|
||||
;
|
||||
; Wait for a key press (don't echo character).
|
||||
;
|
||||
mov ah,8 ;DOS console input without echo function
|
||||
int 21h
|
||||
;
|
||||
; Turn the split screen off.
|
||||
;
|
||||
mov [SplitScreenLine],0ffffh
|
||||
call SetSplitScreenScanLine
|
||||
;
|
||||
; Wait for a key press (don't echo character).
|
||||
;
|
||||
mov ah,8 ;DOS console input without echo function
|
||||
int 21h
|
||||
;
|
||||
; Display the memory at 0 (the same memory the split screen displays).
|
||||
;
|
||||
mov [StartAddress],0
|
||||
call SetStartAddress
|
||||
;
|
||||
; Flip between the split screen and the normal screen every 10th
|
||||
; frame until a key is pressed.
|
||||
;
|
||||
FlipLoop:
|
||||
xor [SplitScreenLine],0ffffh
|
||||
call SetSplitScreenScanLine
|
||||
mov cx,10
|
||||
CountVerticalSyncsLoop:
|
||||
call WaitForVerticalSyncEnd
|
||||
loop CountVerticalSyncsLoop
|
||||
mov ah,0bh ;DOS character available status
|
||||
int 21h
|
||||
and al,al ;character available?
|
||||
jz FlipLoop ;no, toggle split screen on/off status
|
||||
mov ah,1
|
||||
int 21h ;clear the character
|
||||
;
|
||||
; Return to text mode and DOS.
|
||||
;
|
||||
mov ax,0003h ;AH=0 is select mode function
|
||||
;AL=3 is mode to select, text mode
|
||||
int 10h ;return to text mode
|
||||
mov ah,4ch
|
||||
int 21h ;return to DOS
|
||||
Startendp
|
||||
;*********************************************************************
|
||||
; Waits for the leading edge of the vertical sync pulse.
|
||||
;
|
||||
; Input: none
|
||||
;
|
||||
; Output: none
|
||||
;
|
||||
; Registers altered: AL, DX
|
||||
;
|
||||
WaitForVerticalSyncStartprocnear
|
||||
mov dx,INPUT_STATUS_0
|
||||
WaitNotVerticalSync:
|
||||
in al,dx
|
||||
test al,08h
|
||||
jnz WaitNotVerticalSync
|
||||
WaitVerticalSync:
|
||||
in al,dx
|
||||
test al,08h
|
||||
jz WaitVerticalSync
|
||||
ret
|
||||
WaitForVerticalSyncStart endp
|
||||
;*********************************************************************
|
||||
; Waits for the trailing edge of the vertical sync pulse.
|
||||
;
|
||||
; Input: none
|
||||
;
|
||||
; Output: none
|
||||
;
|
||||
; Registers altered: AL, DX
|
||||
;
|
||||
WaitForVerticalSyncEndprocnear
|
||||
mov dx,INPUT_STATUS_0
|
||||
WaitVerticalSync2:
|
||||
in al,dx
|
||||
test al,08h
|
||||
jz WaitVerticalSync2
|
||||
WaitNotVerticalSync2:
|
||||
in al,dx
|
||||
test al,08h
|
||||
jnz WaitNotVerticalSync2
|
||||
ret
|
||||
WaitForVerticalSyncEndendp
|
||||
;*********************************************************************
|
||||
; Sets the start address to the value specifed by StartAddress.
|
||||
; Wait for the trailing edge of vertical sync before setting so that
|
||||
; one half of the address isn't loaded before the start of the frame
|
||||
; and the other half after, resulting in flicker as one frame is
|
||||
; displayed with mismatched halves. The new start address won't be
|
||||
; loaded until the start of the next frame; that is, one full frame
|
||||
; will be displayed before the new start address takes effect.
|
||||
;
|
||||
; Input: none
|
||||
;
|
||||
; Output: none
|
||||
;
|
||||
; Registers altered: AX, DX
|
||||
;
|
||||
SetStartAddress proc near
|
||||
call WaitForVerticalSyncEnd
|
||||
mov dx,CRTC_INDEX
|
||||
mov al,START_ADDRESS_HIGH
|
||||
mov ah,byte ptr [StartAddress+1]
|
||||
cli ;make sure both registers get set at once
|
||||
OUT_WORD
|
||||
mov al,START_ADDRESS_LOW
|
||||
mov ah,byte ptr [StartAddress]
|
||||
OUT_WORD
|
||||
sti
|
||||
ret
|
||||
SetStartAddress endp
|
||||
;*********************************************************************
|
||||
; Sets the scan line the split screen starts after to the scan line
|
||||
; specified by SplitScreenLine.
|
||||
;
|
||||
; Input: none
|
||||
;
|
||||
; Output: none
|
||||
;
|
||||
; All registers preserved
|
||||
;
|
||||
SetSplitScreenScanLine proc near
|
||||
push ax
|
||||
push cx
|
||||
push dx
|
||||
;
|
||||
; Wait for the leading edge of the vertical sync pulse. This ensures
|
||||
; that we don't get mismatched portions of the split screen setting
|
||||
; while setting the two or three split screen registers (register 18h
|
||||
; set but register 7 not yet set when a match occurs, for example),
|
||||
; which could produce brief flickering.
|
||||
;
|
||||
call WaitForVerticalSyncStart
|
||||
;
|
||||
; Set the split screen scan line.
|
||||
;
|
||||
mov dx,CRTC_INDEX
|
||||
mov ah,byte ptr [SplitScreenLine]
|
||||
mov al,LINE_COMPARE
|
||||
cli ;make sure all the registers get set at once
|
||||
OUT_WORD ;set bits 7-0 of the split screen scan line
|
||||
mov ah,byte ptr [SplitScreenLine+1]
|
||||
and ah,1
|
||||
mov cl,4
|
||||
shl ah,cl ;move bit 8 of the split split screen scan
|
||||
; line into position for the Overflow reg
|
||||
mov al,OVERFLOW
|
||||
if IS_VGA
|
||||
;
|
||||
; The Split Screen, Overflow, and Line Compare registers all contain
|
||||
; part of the split screen start scan line on the VGA. We'll take
|
||||
; advantage of the readable registers of the VGA to leave other bits
|
||||
; in the registers we access undisturbed.
|
||||
;
|
||||
out dx,al ;set CRTC Index reg to point to Overflow
|
||||
inc dx ;point to CRTC Data reg
|
||||
in al,dx ;get the current Overflow reg setting
|
||||
and al,not 10h ;turn off split screen bit 8
|
||||
or al,ah ;insert the new split screen bit 8
|
||||
; (works in any mode)
|
||||
out dx,al ;set the new split screen bit 8
|
||||
dec dx ;point to CRTC Index reg
|
||||
mov ah,byte ptr [SplitScreenLine+1]
|
||||
and ah,2
|
||||
mov cl,3
|
||||
ror ah,cl ;move bit 9 of the split split screen scan
|
||||
; line into position for the Maximum Scan
|
||||
; Line register
|
||||
mov al,MAXIMUM_SCAN_LINE
|
||||
out dx,al ;set CRTC Index reg to point to Maximum
|
||||
; Scan Line
|
||||
inc dx ;point to CRTC Data reg
|
||||
in al,dx ;get the current Maximum Scan Line setting
|
||||
and al,not 40h ;turn off split screen bit 9
|
||||
or al,ah ;insert the new split screen bit 9
|
||||
; (works in any mode)
|
||||
out dx,al ;set the new split screen bit 9
|
||||
else
|
||||
;
|
||||
; Only the Split Screen and Overflow registers contain part of the
|
||||
; Split Screen start scan line and need to be set on the EGA.
|
||||
; EGA registers are not readable, so we have to set the non-split
|
||||
; screen bits of the Overflow register to a preset value, in this
|
||||
; case the value for 350-scan-line modes.
|
||||
;
|
||||
or ah,0fh ;insert the new split screen bit 8
|
||||
; (only works in 350-scan-line EGA modes)
|
||||
OUT_WORD ;set the new split screen bit 8
|
||||
endif
|
||||
sti
|
||||
pop dx
|
||||
pop cx
|
||||
pop ax
|
||||
ret
|
||||
SetSplitScreenScanLine endp
|
||||
;*********************************************************************
|
||||
; Moves the split screen up the specified number of scan lines.
|
||||
;
|
||||
; Input: CX = # of scan lines to move the split screen up by
|
||||
;
|
||||
; Output: none
|
||||
;
|
||||
; Registers altered: CX
|
||||
;
|
||||
SplitScreenUp proc near
|
||||
SplitScreenUpLoop:
|
||||
dec [SplitScreenLine]
|
||||
call SetSplitScreenScanLine
|
||||
loop SplitScreenUpLoop
|
||||
ret
|
||||
SplitScreenUp endp
|
||||
;*********************************************************************
|
||||
; Moves the split screen down the specified number of scan lines.
|
||||
;
|
||||
; Input: CX = # of scan lines to move the split screen down by
|
||||
;
|
||||
; Output: none
|
||||
;
|
||||
; Registers altered: CX
|
||||
;
|
||||
SplitScreenDown proc near
|
||||
SplitScreenDownLoop:
|
||||
inc [SplitScreenLine]
|
||||
call SetSplitScreenScanLine
|
||||
loop SplitScreenDownLoop
|
||||
ret
|
||||
SplitScreenDown endp
|
||||
;*********************************************************************
|
||||
Code ends
|
||||
end Start
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
<P><BR></P>
|
||||
<CENTER>
|
||||
<TABLE BORDER>
|
||||
<TR>
|
||||
<TD><A HREF="30-01.html">Previous</A></TD>
|
||||
<TD><A HREF="index.html">Table of Contents</A></TD>
|
||||
<TD><A HREF="30-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 © 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 -->
|
||||
|
||||
|
||||
Loading…
Reference in a new issue