More VGA tests

This commit is contained in:
Jeff Parsons 2015-06-27 18:34:55 -07:00
commit fed558c8d4
3 changed files with 737 additions and 0 deletions

218
tests/pc/vga/L27-1.ASM Normal file
View file

@ -0,0 +1,218 @@
; Program to illustrate one use of write mode 2 of the VGA and EGA by
; animating the image of an "A" drawn by copying it from a chunky
; bit-map in system memory to a planar bit-map in VGA or EGA memory.
;
; Assemble with MASM or TASM
;
; By Michael Abrash
;
Stack segment para stack 'STACK'
db 512 dup(0)
Stack ends
SCREEN_WIDTH_IN_BYTES equ 80
DISPLAY_MEMORY_SEGMENT equ 0a000h
SC_INDEX equ 3c4h ;Sequence Controller Index register
MAP_MASK equ 2 ;index of Map Mask register
GC_INDEX equ 03ceh ;Graphics Controller Index reg
GRAPHICS_MODE equ 5 ;index of Graphics Mode reg
BIT_MASK equ 8 ;index of Bit Mask reg
Data segment para common 'DATA'
;
; Current location of "A" as it is animated across the screen.
;
CurrentX dw ?
CurrentY dw ?
RemainingLength dw ?
;
; Chunky bit-map image of a yellow "A" on a bright blue background
;
AImage label byte
dw 13, 13 ;width, height in pixels
db 000h, 000h, 000h, 000h, 000h, 000h, 000h
db 009h, 099h, 099h, 099h, 099h, 099h, 000h
db 009h, 099h, 099h, 099h, 099h, 099h, 000h
db 009h, 099h, 099h, 0e9h, 099h, 099h, 000h
db 009h, 099h, 09eh, 0eeh, 099h, 099h, 000h
db 009h, 099h, 0eeh, 09eh, 0e9h, 099h, 000h
db 009h, 09eh, 0e9h, 099h, 0eeh, 099h, 000h
db 009h, 09eh, 0eeh, 0eeh, 0eeh, 099h, 000h
db 009h, 09eh, 0e9h, 099h, 0eeh, 099h, 000h
db 009h, 09eh, 0e9h, 099h, 0eeh, 099h, 000h
db 009h, 099h, 099h, 099h, 099h, 099h, 000h
db 009h, 099h, 099h, 099h, 099h, 099h, 000h
db 000h, 000h, 000h, 000h, 000h, 000h, 000h
Data ends
Code segment para public 'CODE'
assume cs:Code, ds:Data
Start proc near
mov ax,Data
mov ds,ax
mov ax,10h
int 10h ;select video mode 10h (640x350)
;
; Prepare for animation.
;
mov [CurrentX],0
mov [CurrentY],200
mov [RemainingLength],600 ;move 600 times
;
; Animate, repeating RemainingLength times. It's unnecessary to erase
; the old image, since the one pixel of blank fringe around the image
; erases the part of the old image not overlapped by the new image.
;
AnimationLoop:
mov bx,[CurrentX]
mov cx,[CurrentY]
mov si,offset AImage
call DrawFromChunkyBitmap ;draw the "A" image
inc [CurrentX] ;move one pixel to the right
mov cx,0 ;delay so we don't move the
DelayLoop: ; image too fast; adjust as
; needed
loop DelayLoop
dec [RemainingLength]
jnz AnimationLoop
;
; Wait for a key before returning to text mode and ending.
;
mov ah,01h
int 21h
mov ax,03h
int 10h
mov ah,4ch
int 21h
Start endp
;
; Draw an image stored in a chunky-bit map into planar VGA/EGA memory
; at the specified location.
;
; Input:
; BX = X screen location at which to draw the upper-left corner
; of the image
; CX = Y screen location at which to draw the upper-left corner
; of the image
; DS:SI = pointer to chunky image to draw, as follows:
; word at 0: width of image, in pixels
; word at 2: height of image, in pixels
; byte at 4: msb/lsb = first & second chunky pixels,
; repeating for the remainder of the scan line
; of the image, then for all scan lines. Images
; with odd widths have an unused null nibble
; padding each scan line out to a byte width
;
; AX, BX, CX, DX, SI, DI, ES destroyed.
;
DrawFromChunkyBitmap proc near
cld
;
; Select write mode 2.
;
mov dx,GC_INDEX
mov al,GRAPHICS_MODE
out dx,al
inc dx
mov al,02h
out dx,al
;
; Enable writes to all 4 planes.
;
mov dx,SC_INDEX
mov al,MAP_MASK
out dx,al
inc dx
mov al,0fh
out dx,al
;
; Point ES:DI to the display memory byte in which the first pixel
; of the image goes, with AH set up as the bit mask to access that
; pixel within the addressed byte.
;
mov ax,SCREEN_WIDTH_IN_BYTES
mul cx ;offset of start of top scan line
mov di,ax
mov cl,bl
and cl,111b
mov ah,80h ;set AH to the bit mask for the
shr ah,cl ; initial pixel
shr bx,1
shr bx,1
shr bx,1 ;X in bytes
add di,bx ;offset of upper-left byte of image
mov bx,DISPLAY_MEMORY_SEGMENT
mov es,bx ;ES:DI points to the byte at which the
; upper left of the image goes
;
; Get the width and height of the image.
;
mov cx,[si] ;get the width
inc si
inc si
mov bx,[si] ;get the height
inc si
inc si
mov dx,GC_INDEX
mov al,BIT_MASK
out dx,al ;leave the GC Index register pointing
inc dx ; to the Bit Mask register
RowLoop:
push ax ;preserve the left column's bit mask
push cx ;preserve the width
push di ;preserve the destination offset
ColumnLoop:
mov al,ah
out dx,al ;set the bit mask to draw this pixel
mov al,es:[di] ;load the latches
mov al,[si] ;get the next two chunky pixels
shr al,1
shr al,1
shr al,1
shr al,1 ;move the first pixel into the lsb
stosb ;draw the first pixel
ror ah,1 ;move mask to next pixel position
jc CheckMorePixels ;is next pixel in the adjacent byte?
dec di ;no
CheckMorePixels:
dec cx ;see if there are any more pixels
jz AdvanceToNextScanLine ; across in image
mov al,ah
out dx,al ;set the bit mask to draw this pixel
mov al,es:[di] ;load the latches
lodsb ;get the same two chunky pixels again
; and advance pointer to the next
; two pixels
stosb ;draw the second of the two pixels
ror ah,1 ;move mask to next pixel position
jc CheckMorePixels2;is next pixel in the adjacent byte?
dec di ;no
CheckMorePixels2:
loop ColumnLoop ;see if there are any more pixels
; across in the image
jmp short CheckMoreScanLines
AdvanceToNextScanLine:
inc si ;advance to the start of the next
; scan line in the image
CheckMoreScanLines:
pop di ;get back the destination offset
pop cx ;get back the width
pop ax ;get back the left column's bit mask
add di,SCREEN_WIDTH_IN_BYTES
;point to the start of the next scan
; line of the image
dec bx ;see if there are any more scan lines
jnz RowLoop ; in the image
ret
DrawFromChunkyBitmap endp
Code ends
end Start

327
tests/pc/vga/L27-2.ASM Normal file
View file

@ -0,0 +1,327 @@
; Program to illustrate one use of write mode 2 of the VGA and EGA by
; drawing lines in color patterns.
;
; Assemble with MASM or TASM
;
; By Michael Abrash
;
Stack segment para stack 'STACK'
db 512 dup(0)
Stack ends
SCREEN_WIDTH_IN_BYTES equ 80
GRAPHICS_SEGMENT equ 0a000h ;mode 10 bit-map segment
SC_INDEX equ 3c4h ;Sequence Controller Index register
MAP_MASK equ 2 ;index of Map Mask register
GC_INDEX equ 03ceh ;Graphics Controller Index reg
GRAPHICS_MODE equ 5 ;index of Graphics Mode reg
BIT_MASK equ 8 ;index of Bit Mask reg
Data segment para common 'DATA'
Pattern0 db 16
db 0, 1, 2, 3, 4, 5, 6, 7, 8
db 9, 10, 11, 12, 13, 14, 15
Pattern1 db 6
db 2, 2, 2, 10, 10, 10
Pattern2 db 8
db 15, 15, 15, 0, 0, 15, 0, 0
Pattern3 db 9
db 1, 1, 1, 2, 2, 2, 4, 4, 4
Data ends
Code segment para public 'CODE'
assume cs:Code, ds:Data
Start proc near
mov ax,Data
mov ds,ax
mov ax,10h
int 10h ;select video mode 10h (640x350)
;
; Draw 8 radial lines in upper-left quadrant in pattern 0.
;
mov bx,0
mov cx,0
mov si,offset Pattern0
call QuadrantUp
;
; Draw 8 radial lines in upper-right quadrant in pattern 1.
;
mov bx,320
mov cx,0
mov si,offset Pattern1
call QuadrantUp
;
; Draw 8 radial lines in lower-left quadrant in pattern 2.
;
mov bx,0
mov cx,175
mov si,offset Pattern2
call QuadrantUp
;
; Draw 8 radial lines in lower-right quadrant in pattern 3.
;
mov bx,320
mov cx,175
mov si,offset Pattern3
call QuadrantUp
;
; Wait for a key before returning to text mode and ending.
;
mov ah,01h
int 21h
mov ax,03h
int 10h
mov ah,4ch
int 21h
;
; Draws 8 radial lines with specified pattern in specified mode 10h
; quadrant.
;
; Input:
; BX = X coordinate of upper left corner of quadrant
; CX = Y coordinate of upper left corner of quadrant
; SI = pointer to pattern, in following form:
; Byte 0: Length of pattern
; Byte 1: Start of pattern, one color per byte
;
; AX, BX, CX, DX destroyed
;
QuadrantUp proc near
add bx,160
add cx,87 ;point to the center of the quadrant
mov ax,0
mov dx,160
call LineUp ;draw horizontal line to right edge
mov ax,1
mov dx,88
call LineUp ;draw diagonal line to upper right
mov ax,2
mov dx,88
call LineUp ;draw vertical line to top edge
mov ax,3
mov dx,88
call LineUp ;draw diagonal line to upper left
mov ax,4
mov dx,161
call LineUp ;draw horizontal line to left edge
mov ax,5
mov dx,88
call LineUp ;draw diagonal line to lower left
mov ax,6
mov dx,88
call LineUp ;draw vertical line to bottom edge
mov ax,7
mov dx,88
call LineUp ;draw diagonal line to bottom right
ret
QuadrantUp endp
;
; Draws a horizontal, vertical, or diagonal line (one of the eight
; possible radial lines) of the specified length from the specified
; starting point.
;
; Input:
; AX = line direction, as follows:
; 3 2 1
; 4 * 0
; 5 6 7
; BX = X coordinate of starting point
; CX = Y coordinate of starting point
; DX = length of line (number of pixels drawn)
;
; All registers preserved.
;
; Table of vectors to routines for each of the 8 possible lines.
;
LineUpVectors label word
dw LineUp0, LineUp1, LineUp2, LineUp3
dw LineUp4, LineUp5, LineUp6, LineUp7
;
; Macro to draw horizontal, vertical, or diagonal line.
;
; Input:
; XParm = 1 to draw right, -1 to draw left, 0 to not move horz.
; YParm = 1 to draw up, -1 to draw down, 0 to not move vert.
; BX = X start location
; CX = Y start location
; DX = number of pixels to draw
; DS:SI = line pattern
;
MLineUp macro XParm, YParm
local LineUpLoop, CheckMoreLine
mov di,si ;set aside start offset of pattern
lodsb ;get length of pattern
mov ah,al
LineUpLoop:
lodsb ;get color of this pixel...
call DotUpInColor ;...and draw it
if XParm EQ 1
inc bx
endif
if XParm EQ -1
dec bx
endif
if YParm EQ 1
inc cx
endif
if YParm EQ -1
dec cx
endif
dec ah ;at end of pattern?
jnz CheckMoreLine
mov si,di ;get back start of pattern
lodsb
mov ah,al ;reset pattern count
CheckMoreLine:
dec dx
jnz LineUpLoop
jmp LineUpEnd
endm
LineUp proc near
push ax
push bx
push cx
push dx
push si
push di
push es
mov di,ax
mov ax,GRAPHICS_SEGMENT
mov es,ax
push dx ;save line length
;
; Enable writes to all planes.
;
mov dx,SC_INDEX
mov al,MAP_MASK
out dx,al
inc dx
mov al,0fh
out dx,al
;
; Select write mode 2.
;
mov dx,GC_INDEX
mov al,GRAPHICS_MODE
out dx,al
inc dx
mov al,02h
out dx,al
;
; Vector to proper routine.
;
pop dx ;get back line length
shl di,1
jmp cs:[LineUpVectors+di]
;
; Horizontal line to right.
;
LineUp0:
MLineUp 1, 0
;
; Diagonal line to upper right.
;
LineUp1:
MLineUp 1, -1
;
; Vertical line to top.
;
LineUp2:
MLineUp 0, -1
;
; Diagonal line to upper left.
;
LineUp3:
MLineUp -1, -1
;
; Horizontal line to left.
;
LineUp4:
MLineUp -1, 0
;
; Diagonal line to bottom left.
;
LineUp5:
MLineUp -1, 1
;
; Vertical line to bottom.
;
LineUp6:
MLineUp 0, 1
;
; Diagonal line to bottom right.
;
LineUp7:
MLineUp 1, 1
LineUpEnd:
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
LineUp endp
;
; Draws a dot in the specified color at the specified location.
; Assumes that the VGA is in write mode 2 with writes to all planes
; enabled and that ES points to display memory.
;
; Input:
; AL = dot color
; BX = X coordinate of dot
; CX = Y coordinate of dot
; ES = display memory segment
;
; All registers preserved.
;
DotUpInColor proc near
push bx
push cx
push dx
push di
;
; Point ES:DI to the display memory byte in which the pixel goes, with
; the bit mask set up to access that pixel within the addressed byte.
;
push ax ;preserve dot color
mov ax,SCREEN_WIDTH_IN_BYTES
mul cx ;offset of start of top scan line
mov di,ax
mov cl,bl
and cl,111b
mov dx,GC_INDEX
mov al,BIT_MASK
out dx,al
inc dx
mov al,80h
shr al,cl
out dx,al ;set the bit mask for the pixel
shr bx,1
shr bx,1
shr bx,1 ;X in bytes
add di,bx ;offset of byte pixel is in
mov al,es:[di] ;load latches
pop ax ;get back dot color
stosb ;write dot in desired color
pop di
pop dx
pop cx
pop bx
ret
DotUpInColor endp
Start endp
Code ends
end Start

192
tests/pc/vga/L27-3.ASM Normal file
View file

@ -0,0 +1,192 @@
; Program to illustrate flipping from bit-mapped graphics mode to
; text mode and back without losing any of the graphics bit-map.
;
; Assemble with MASM or TASM
;
; By Michael Abrash
;
Stack segment para stack 'STACK'
db 512 dup(0)
Stack ends
GRAPHICS_SEGMENT equ 0a000h ;mode 10 bit-map segment
TEXT_SEGMENT equ 0b800h ;mode 3 bit-map segment
SC_INDEX equ 3c4h ;Sequence Controller Index register
MAP_MASK equ 2 ;index of Map Mask register
GC_INDEX equ 3ceh ;Graphics Controller Index register
READ_MAP equ 4 ;index of Read Map register
Data segment para common 'DATA'
GStrikeAnyKeyMsg0 label byte
db 0dh, 0ah, 'Graphics mode', 0dh, 0ah
db 'Strike any key to continue...', 0dh, 0ah, '$'
GStrikeAnyKeyMsg1 label byte
db 0dh, 0ah, 'Graphics mode again', 0dh, 0ah
db 'Strike any key to continue...', 0dh, 0ah, '$'
TStrikeAnyKeyMsg label byte
db 0dh, 0ah, 'Text mode', 0dh, 0ah
db 'Strike any key to continue...', 0dh, 0ah, '$'
Plane2Save db 2000h dup (?) ;save area for plane 2 data
; where font gets loaded
CharAttSave db 4000 dup (?) ;save area for memory wiped
; out by character/attribute
; data in text mode
Data ends
Code segment para public 'CODE'
assume cs:Code, ds:Data
Start proc near
mov ax,10h
int 10h ;select video mode 10h (640x350)
;
; Fill the graphics bit-map with a colored pattern.
;
cld
mov ax,GRAPHICS_SEGMENT
mov es,ax
mov ah,3 ;initial fill pattern
mov cx,4 ;four planes to fill
mov dx,SC_INDEX
mov al,MAP_MASK
out dx,al ;leave the SC Index pointing to the
inc dx ; Map Mask register
FillBitMap:
mov al,10h
shr al,cl ;generate map mask for this plane
out dx,al ;set map mask for this plane
sub di,di ;start at offset 0
mov al,ah ;get the fill pattern
push cx ;preserve plane count
mov cx,8000h ;fill 32K words
rep stosw ;do fill for this plane
pop cx ;get back plane count
shl ah,1
shl ah,1
loop FillBitMap
;
; Put up "strike any key" message.
;
mov ax,Data
mov ds,ax
mov dx,offset GStrikeAnyKeyMsg0
mov ah,9
int 21h
;
; Wait for a key.
;
mov ah,01h
int 21h
;
; Save the 8K of plane 2 that will be used by the font.
;
mov dx,GC_INDEX
mov al,READ_MAP
out dx,al
inc dx
mov al,2
out dx,al ;set up to read from plane 2
mov ax,Data
mov es,ax
mov ax,GRAPHICS_SEGMENT
mov ds,ax
sub si,si
mov di,offset Plane2Save
mov cx,2000h/2 ;save 8K (length of default font)
rep movsw
;
; Go to text mode without clearing display memory.
;
mov ax,083h
int 10h
;
; Save the text mode bit-map.
;
mov ax,Data
mov es,ax
mov ax,TEXT_SEGMENT
mov ds,ax
sub si,si
mov di,offset CharAttSave
mov cx,4000/2 ;length of one text screen in words
rep movsw
;
; Fill the text mode screen with dots and put up "strike any key"
; message.
;
mov ax,TEXT_SEGMENT
mov es,ax
sub di,di
mov al,'.' ;fill character
mov ah,7 ;fill attribute
mov cx,4000/2 ;length of one text screen in words
rep stosw
mov ax,Data
mov ds,ax
mov dx,offset TStrikeAnyKeyMsg
mov ah,9
int 21h
;
; Wait for a key.
;
mov ah,01h
int 21h
;
; Restore the text mode screen to the state it was in on entering
; text mode.
;
mov ax,Data
mov ds,ax
mov ax,TEXT_SEGMENT
mov es,ax
mov si,offset CharAttSave
sub di,di
mov cx,4000/2 ;length of one text screen in words
rep movsw
;
; Return to mode 10h without clearing display memory.
;
mov ax,90h
int 10h
;
; Restore the portion of plane 2 that was wiped out by the font.
;
mov dx,SC_INDEX
mov al,MAP_MASK
out dx,al
inc dx
mov al,4
out dx,al ;set up to write to plane 2
mov ax,Data
mov ds,ax
mov ax,GRAPHICS_SEGMENT
mov es,ax
mov si,offset Plane2Save
sub di,di
mov cx,2000h/2 ;restore 8K (length of default font)
rep movsw
;
; Put up "strike any key" message.
;
mov ax,Data
mov ds,ax
mov dx,offset GStrikeAnyKeyMsg1
mov ah,9
int 21h
;
; Wait for a key before returning to text mode and ending.
;
mov ah,01h
int 21h
mov ax,03h
int 10h
mov ah,4ch
int 21h
Start endp
Code ends
end Start