Category : Printer + Display Graphics
Archive   : VGAMOIRE.ZIP
Filename : VGAMOIRE.ASM

 
Output of file : VGAMOIRE.ASM contained in archive : VGAMOIRE.ZIP
; VGAMOIRE.COM

; Structured pattern generator to show off the undocumented
; 320x400 256 color mode of the IBM VGA as revealed by
; Michael Abrash in his "On Graphics" column in the
; January/February 1989 issue of Programmer's Journal, Volume 7.1


VGA_SEGMENT equ 0A000h
SC_INDEX equ 3C4h
GC_INDEX equ 3CEh
CRTC_INDEX equ 3D4h
MAP_MASK equ 2
MEMORY_MODE equ 4
MAX_SCAN_LINE equ 9
START_ADDRESS_HIGH equ 0Ch
UNDERLINE equ 14h
MODE_CONTROL equ 17h
READ_MAP equ 4
GRAPHICS_MODE equ 5
MISCELLANEOUS equ 6
SCREEN_WIDTH equ 320
SCREEN_HEIGHT equ 400

tab equ 9
lf equ 10
cr equ 13


CONSTANT_TO_INDEXED_REGISTER macro ADDRESS, INDEX, VALUE
mov dx, ADDRESS
mov ax, (VALUE shl 8) + INDEX
out dx, ax
endm

code segment
org 100h
assume cs:code, ds:code


Begin:

push cs
pop ds

mov ax, VGA_SEGMENT
mov es, ax

call Set320x400Mode

mov ah, 2Ch
int 21h
mov Random, dx

mov si, 256 ; ColorCount

call Randy
mov bp, ax
call DoCircles


MainLoop:
call MakeRandomPalette

cmp PageNo, 0
je SetPage1
mov ax, 0A800h
mov es, ax
CONSTANT_TO_INDEXED_REGISTER CRTC_INDEX,START_ADDRESS_HIGH,0
mov PageNo, 0
jmp Start
SetPage1:
mov ax, 0A000h
mov es, ax
CONSTANT_TO_INDEXED_REGISTER CRTC_INDEX,START_ADDRESS_HIGH,80h
mov PageNo, 1

Start:
call Randy
and ax, 0003h
cmp al, 0
je Circ
cmp al, 1
je Sqar
cmp al, 2
je TiltCirc
jmp TiltSqar

Circ:
call Randy
inc ax
mov bp, ax
call DoCircles
jmp CheckKey

Sqar:
call Randy
inc ax
mov bp, ax
call DoSquares
jmp CheckKey

TiltCirc:
call Randy
inc ax
mov bp, ax
call DoTiltCircles
jmp CheckKey

TiltSqar:
call Randy
inc ax
mov bp, ax
call DoTiltSquares

CheckKey:
mov ah, 0Bh
int 21h
cmp al, 0
jne GetOut
jmp MainLoop

GetOut:
mov ax, 0003h ; Back to Text Mode
int 10h

mov ax, 4C00h
int 21h

PageNo dw 1


DoCircles proc near

mov bl, 00010001b ; Plane Mask bit
mov di, 0 ; Video memory pointer


mov cx, 0 ; For Y := 0 to 399 do
ForYCirc:
push cx
mov cx, 0 ; For X := 0 to 319 do
ForXCirc:
mov ax, bp ; Get IterateCnt
mul cx ; DX:AX := IterateCnt * X
add si, ax ; ColorCount := ColorCount + (IterateCnt * X)

mov dx, SC_INDEX ; Select the correct plane
mov ah, bl
mov al, MAP_MASK
out dx, ax

mov ax, si ; Poke Color
mov byte ptr es:[di], al

rol bl, 1 ; Rotate for next plane
cmp bl, 00010001b ; Did we rotate four times?
jne DoNextXCirc ; If not then do the next pixel
inc di ; Otherwise bump the Video MemPtr

DoNextXCirc:
inc cx ; Next X
cmp cx, 320
jl ForXCirc

pop cx

mov ax, bp ; Get IterateCnt
mul cx ; DX:AX := IterateCnt * Y
add si, ax ; ColorCount := ColorCount + (IterateCnt * Y)

inc cx ; Next Y
cmp cx, 400
jl ForYCirc

ret

DoCircles endp


DoTiltCircles proc near

mov bl, 00010001b ; Plane Mask bit
mov di, 0 ; Video memory pointer

mov cx, 0 ; For Y := 0 to 399 do
ForYTiltCirc:
push cx
mov cx, 0 ; For X := 0 to 319 do
ForXTiltCirc:
mov ax, bp ; Get IterateCnt
mul cx ; DX:AX := IterateCnt * X
add si, ax ; ColorCount := ColorCount + (IterateCnt * X)

mov dx, SC_INDEX ; Select the correct plane
mov ah, bl
mov al, MAP_MASK
out dx, ax

mov ax, si ; Poke Color
mov byte ptr es:[di], al

rol bl, 1 ; Rotate for next plane
cmp bl, 00010001b ; Did we rotate four times?
jne DoNextXTiltCirc ; If not then do the next pixel
inc di ; Otherwise bump the Video MemPtr

DoNextXTiltCirc:
inc cx ; Next X
cmp cx, 320
jl ForXTiltCirc

pop cx

mov ax, bp ; Get IterateCnt
mul cx ; DX:AX := IterateCnt * Y
sub si, ax ; ColorCount := ColorCount - (IterateCnt * Y)

inc cx ; Next Y
cmp cx, 400
jl ForYTiltCirc

ret

DoTiltCircles endp


DoSquares proc near

mov bl, 00010001b ; Plane Mask bit
mov di, 0 ; Video memory pointer

mov cx, 0 ; For Y := 0 to 399 do
ForYSqr:
mov CurrY, cx
push cx
mov cx, 0 ; For X := 0 to 319 do
ForXSqr:
mov CurrX, cx
mov ax, bp ; Get IterateCnt
mov dx, CurrY ; Get current Y
mul dx ; DX:AX := IterateCnt * Y
add si, ax ; ColorCount := ColorCount + (IterateCnt * Y)

mov dx, SC_INDEX ; Select the correct plane
mov ah, bl
mov al, MAP_MASK
out dx, ax

mov ax, si ; Poke Color
mov byte ptr es:[di], al

rol bl, 1 ; Rotate for next plane
cmp bl, 00010001b ; Did we rotate four times?
jne DoNextXSqr ; If not then do the next pixel
inc di ; Otherwise bump the Video MemPtr

DoNextXSqr:
inc cx ; Next X
cmp cx, 320
jl ForXSqr

pop cx

mov ax, bp ; Get IterateCnt
mov dx, CurrX ; Get current X
mul dx ; DX:AX := IterateCnt * X
add si, ax ; ColorCount := ColorCount + (IterateCnt * X)

inc cx ; Next Y
cmp cx, 400
jl ForYSqr

ret

CurrX dw (?)
CurrY dw (?)

DoSquares endp


DoTiltSquares proc near

mov bl, 00010001b ; Plane Mask bit
mov di, 0 ; Video memory pointer

mov cx, 0 ; For Y := 0 to 399 do
ForYTiltSqr:
mov CurrTiltY, cx
push cx
mov cx, 0 ; For X := 0 to 319 do
ForXTiltSqr:
mov CurrTiltX, cx
mov ax, bp ; Get IterateCnt
mov dx, CurrTiltY ; Get current Y
mul dx ; DX:AX := IterateCnt * Y
add si, ax ; ColorCount := ColorCount + (IterateCnt * Y)

mov dx, SC_INDEX ; Select the correct plane
mov ah, bl
mov al, MAP_MASK
out dx, ax

mov ax, si ; Poke Color
mov byte ptr es:[di], al

rol bl, 1 ; Rotate for next plane
cmp bl, 00010001b ; Did we rotate four times?
jne DoNextXTiltSqr ; If not then do the next pixel
inc di ; Otherwise bump the Video MemPtr

DoNextXTiltSqr:
inc cx ; Next X
cmp cx, 320
jl ForXTiltSqr

pop cx

mov ax, bp ; Get IterateCnt
mov dx, CurrTiltX ; Get current X
mul dx ; DX:AX := IterateCnt * X
add si, ax ; ColorCount := ColorCount + (IterateCnt * X)

inc cx ; Next Y
cmp cx, 400
jl ForYTiltSqr

ret

CurrTiltX dw (?)
CurrTiltY dw (?)

DoTiltSquares endp


Randy proc near

; Returns a pseudo random integer in AX

GetTime:
mov ah, 2Ch
int 21h

mov ax, Random
add ax, 13
mul dx
add dx, 23
mul dx
shr dx, 1
shr dx, 1
shr dx, 1
add ax, dx
and ax, 7FFFh
mov Random, ax

ret

Random dw (?)

Randy endp


MakeRandomPalette proc near

call Randy
mov byte ptr RED, al
call Randy
mov byte ptr GREEN, al
call Randy
mov byte ptr BLUE, al

mov cx, 0
NextPal:
mov al, cl
mov dx, 03C8h ; Set Write PEL Address
out dx, al
inc dx

mov al, byte ptr RED ; Get RED
and al, 3Fh
out dx, al

mov al, byte ptr GREEN ; Get GREEN
and al, 3Fh
out dx, al

mov al, byte ptr BLUE ; Get BLUE
and al, 3Fh
out dx, al

inc byte ptr RED
inc byte ptr GREEN
inc byte ptr BLUE
inc cx
cmp cx, 256
jl NextPal

ret

RED db (?)
GREEN db (?)
BLUE db (?)

MakeRandomPalette endp


Set320x400Mode proc near

mov ax, 0013h
int 10h

mov dx, SC_INDEX
mov al, MEMORY_MODE
out dx, al
inc dx
in al, dx
and al, NOT 08h
or al, 04h
out dx, al
mov dx, GC_INDEX
mov al, GRAPHICS_MODE
out dx, al
inc dx
in al, dx
and al, NOT 10h
out dx, al
dec dx
mov al, MISCELLANEOUS
out dx, al
inc dx
in al, dx
and al, NOT 02h
out dx, al

CONSTANT_TO_INDEXED_REGISTER SC_INDEX, MAP_MASK, 0Fh

mov ax, VGA_SEGMENT
mov es, ax
sub di, di
mov ax, di
mov cx, 8000h
rep stosw

mov dx, CRTC_INDEX
mov al, MAX_SCAN_LINE
out dx, al
inc dx
in al, dx
and al, NOT 1Fh
out dx, al
dec dx

mov al, UNDERLINE
out dx, al
inc dx
in al, dx
and al, NOT 40h
out dx, al
dec dx
mov al, MODE_CONTROL
out dx, al
inc dx
in al, dx
or al, 40h
out dx, al

ret

Set320x400Mode endp


code ends

End Begin


  3 Responses to “Category : Printer + Display Graphics
Archive   : VGAMOIRE.ZIP
Filename : VGAMOIRE.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/