;// FAKEMODE.ASM Assembler Routines Library for FakeMode
;// (c) 1993,94 by Yaka/Xography
;// V1.1; arranged 12.5.94
.model large
PUBLIC _F_settimer ;//Timer routines.
PUBLIC _F_gettimer
PUBLIC _F_isvga ;//FakeMode routines.
PUBLIC _F_initgraph
PUBLIC _F_closegraph
PUBLIC _F_videooff ;//Display routines.
PUBLIC _F_videoon
PUBLIC _F_fadein
PUBLIC _F_fadeout
PUBLIC _F_fadeinfast
PUBLIC _F_fadeoutfast
PUBLIC _F_setlumi
PUBLIC _F_putbigpixel ;//Pixel routines.
PUBLIC _F_putsmallpixel
.code
;//---------------============ INTERNAL ROUTINES =============--------------
palette db 768 dup (?)
initpalette PROC
push di
push cs
pop es
mov di, offset palette
cld
mov dx,3c8h
xor ax,ax
xor bx,bx
out dx,al
inc dx ;//ah=red, bh=green, bl=blue
mov cx,15
initpal_outer:
push cx
mov cx,16
initpal_inner:
mov al,ah
out dx,al
stosb
mov al,bh
out dx,al
stosb
mov al,bl
out dx,al
stosb
add ah,4
loop initpal_inner
mov ah,0
add bl,4
cmp bl,4
jne goon
add bl,4
goon:
pop cx
loop initpal_outer
mov cx,16
xor ax,ax
xor bx,bx
initpal_second:
mov al,ah
out dx,al
stosb
mov al,bh
out dx,al
stosb
mov al,bl
out dx,al
stosb
add bh,4
loop initpal_second
pop di
ret
initpalette ENDP
setluminance PROC
;//Internal Routine to set one luminance value when fading in/out.
;//requires luminance value (0..255) in AL
;//Sets original VGA palette (256 colors)
;//Attention! Changes values of all general purpose registers (ax,bx,cx,dx)!
;//This routine is used in routines H_setlumi, H_fadein, H_fadeout.
mov bl,al ;//luminance in bl
push ds
push cs
pop ds
push si
mov si, offset palette
push di
cld
mov dx,3c8h
mov di,3dah
mov al,0
out dx,al
inc dx
mov cx,256
lumiloop:
lodsb
mul bl
mov al,ah
out dx,al
lodsb
mul bl
mov al,ah
out dx,al
lodsb
mul bl
mov al,ah
push ax
xchg dx,di
lumjmp1: ;//wait for end of retrace
in al,dx
and al,00000001b
jnz lumjmp1
lumjmp2: ;//wait for retrace
in al,dx
and al,00000001b
jz lumjmp2
xchg dx,di
pop ax
out dx,al
loop lumiloop
pop di
pop si
pop ds
ret
setluminance ENDP
;//------ TIMER
systimer dw 0
currentfloptime dw ?
currentpage dw 0
currentsystimer dw 0
alterint08 dw ?,?
switchpageint PROC
push ax
push bx
push dx
inc word ptr systimer ;//set system timer
mov bx,currentpage
add bx,32768
mov currentpage,bx
mov dx,3d4h
mov al,0ch ;//set Start Adresse High (0Ch)
mov ah,bh
out dx,ax
mov dx,3dah ;//Wait for Retrace
swretjmp:
in al,dx
and al,00001000b
jz swretjmp
mov al,34h ;//start Monoflop new
out 43h,al
mov ax,currentfloptime
out 40h,al
mov al,ah
out 40h,al
mov bx,currentsystimer ;//Test for Systemtimer call at 18.2 Hz
add ax,bx
mov currentsystimer,ax
cmp ax,bx
ja nosysroutine ;//No --> continue
pop dx
pop bx
pop ax
jmp dword ptr alterint08 ;//call Systemtimer routine
nosysroutine:
mov al,20h ;//acknowledge interrupt controller
out 20h,al
pop dx
pop bx
pop ax
iret
switchpageint ENDP
counter dw 0
synchroint PROC
push ax
mov ax,counter
inc ax
mov counter,ax
mov al,20h
out 20h,al
pop ax
iret
synchroint ENDP
inittimer PROC
push di
mov ax,1234h
mov currentfloptime,ax
mov ax,3508h ;//save old Interrupt 08
int 21h
mov alterint08,bx
mov alterint08+2,es
xor ax,ax ;//redirect Interrupt 08 to synchronisation routine
mov es,ax
mov di,08h*4
cli
cld
mov ax,offset synchroint
stosw
mov ax,cs
stosw
sti
;//------ measure Synchronisation
mov dx,3dah ;//Wait for End of Retrace
s1endretjmp:
in al,dx
and al,00001000b
jnz s1endretjmp
s1retjmp: ;//Wait for Retrace
in al,dx
and al,00001000b
jz s1retjmp
synchroback:
mov al,36h
out 43h,al
mov ax,currentfloptime
out 40h,al
mov al,ah
out 40h,al
mov ax,0
mov counter, ax
mov dx,3dah ;//Wait for End of Retrace
s2endretjmp:
in al,dx
and al,00001000b
jnz s2endretjmp
s2retjmp: ;//Wait for Retrace
in al,dx
and al,00001000b
jz s2retjmp
mov ax,counter
cmp ax,0
je fertig
mov ax,currentfloptime
add ax,250
mov currentfloptime,ax
jmp synchroback
fertig:
mov al,34h ;//set Systemtimer correctly (Monoflop)
out 43h,al
mov ax, currentfloptime
sub ax,800
mov currentfloptime,ax
out 40h,al
mov al,ah
out 40h,al
xor ax,ax ;//redirect Interrupt 08 to Screenswitch routine
mov es,ax
mov di,08h*4
cli
cld
mov ax,offset switchpageint
stosw
mov ax,cs
stosw
sti
pop di
ret
inittimer ENDP
closetimer PROC
push ds
push di
push si
cli
mov al,36h ;//Systemtimer back to normal speed
out 43h,al
xor al,al
out 40h,al
out 40h,al
push cs ;//restore interrupt vector back to normal
pop ds
mov si,offset alterint08
xor ax,ax
mov es,ax
mov di,08h*4
cld
movsw
movsw
sti
pop si
pop di
pop ds
ret
closetimer ENDP
;//---------------============ USER ROUTINES =============--------------
_F_settimer PROC
;//Sets timer variable to defined value. (timer variable is incremented
;// every vertical retrace)
arg value:word
push bp
mov bp,sp
mov ax,value
mov systimer,ax
pop bp
ret
_F_settimer ENDP
_F_gettimer PROC
;//Reads current value of timer variable.
mov ax,systimer
ret
_F_gettimer ENDP
_F_isvga PROC ;//AX=0 = No VGA, AX=255 = is VGA, AX = 254 = unknown
;//Checks if VGA card is installed.
mov ax,1a00h
int 10h
cmp al,1ah
jne isnovga
cmp bl,07h
jb isnovga
xor ax,ax
cmp bl,08
ja isunknown
mov al,0ffh
ret
isunknown:
mov al,254d
ret
isnovga:
xor ax,ax
ret
_F_isvga ENDP
oldvideomode db 3
_F_initgraph PROC
;//Initializes Fakemode, including palette and timer setup.
push di
mov ax,0f00h
int 10h
mov oldvideomode,al
mov ax,0013h
int 10h
mov dx,3ceh
mov al,5
out dx,al
inc dx
in al,dx
and al,11101111b
out dx,al
dec dx
mov al,6
out dx,al
inc dx
in al,dx
and al,11111101b
out dx,al
mov dx,3c4h
mov al,4
out dx,al
inc dx
in al,dx
and al,11110111b
or al,4
out dx,al
mov ax,0a000h
mov es,ax
xor di,di
mov ax,di
mov cx,8000h
rep stosw
mov dx,3d4h
mov al,9
out dx,al
inc dx
in al,dx
and al,01110000b
out dx,al
dec dx
mov al,14h
out dx,al
inc dx
in al,dx
and al,10111111b
out dx,al
dec dx
mov al,17h ;//select Word-Mode (normally: Bytemode)
out dx,al
inc dx
in al,dx
and al,10111111b ;//normally: or al,01000000b
out dx,al
call initpalette
call inittimer
pop di
ret
_F_initgraph ENDP
_F_closegraph PROC
;//Closes FakeMode and returns to previous video mode.
call closetimer
xor ax,ax
mov al,oldvideomode
int 10h
ret
_F_closegraph ENDP
_F_videooff PROC
;//Switches Screen off.
mov dx,3c4h
mov al,1
out dx,al
inc dx
in al,dx
or al,00100000b
out dx,al
ret
_F_videooff ENDP
_F_videoon PROC
;//Switches screen on.
mov dx,3c4h
mov al,1
out dx,al
inc dx
in al,dx
and al,11011111b
out dx,al
ret
_F_videoon ENDP
_F_fadein PROC
;//Fades screen in slowly. (Attention! Works only when Screen is switched on.
;// Use H_setlumi(0) to darken screen before fadein (instead of H_videooff)!)
mov ax,0
fadeinloop:
push ax
call setluminance
pop ax
inc ax
cmp ax,256
jb fadeinloop
ret
_F_fadein ENDP
_F_fadeout PROC
;//Fades out screen slowly.
mov ax,256
fadeoutloop:
dec ax
push ax
call setluminance
pop ax
cmp ax,0
ja fadeoutloop
ret
_F_fadeout ENDP
_F_fadeinfast PROC
;//Fades in screen with double speed
mov ax,0
fadeinfastloop:
push ax
call setluminance
pop ax
add ax,2
cmp ax,256
jb fadeinfastloop
mov al,255
call setluminance
ret
_F_fadeinfast ENDP
_F_fadeoutfast PROC
;//Fades out screen with double speed
mov ax,256
fadeoutfastloop:
sub ax,2
push ax
call setluminance
pop ax
cmp ax,0
ja fadeoutfastloop
ret
_F_fadeoutfast ENDP
_F_setlumi PROC
;//Sets screen luminance directly.
arg lumi:byte
push bp
mov bp,sp
mov al,lumi
call setluminance
pop bp
ret
_F_setlumi ENDP
_F_putbigpixel PROC
;//Puts one pixel with 320x200 resolution (Actually there are 2 pixels at
;// 320x400 resolution)
ARG x:word, y:byte, red:byte, green:byte, blue:byte
push bp
mov bp,sp
push di
mov bx,x
mov cx,bx
and cl,00000011b ;//calculate Bitplane...
mov dx,3c4h
mov ax,0102h
shl ah,cl
out dx,ax ;//...and set it
mov ax,0a000h ;//set dest segment
mov es,ax
mov ax,320 ;//set dest offset
mov dl,y
mov dh,0
mul dx
shr bx,1
and bl,11111110b
add bx,ax ;//bx contains basic offset
mov di,bx
mov al,blue ;//calculate red-blue
mov ah,16
mul ah
cmp ax,0
je bpixgoon
sub ax,16
bpixgoon:
add al,red
mov ah,green
add ah,240
and cl,00000001b
jz typetwo
mov es:[di+160],ax
xchg ah,al
mov es:[di],ax
jmp tend
typetwo:
mov es:[di],ax
xchg ah,al
mov es:[di+160],ax
jmp tend
tend:
pop di
pop bp
ret
_F_putbigpixel ENDP
_F_putsmallpixel PROC
;//Puts one pixel with 320x400 resolution.
ARG x:word, y:word, red:byte, green:byte, blue:byte
push bp
mov bp,sp
push di
mov bx,x
mov cx,bx
and cl,00000011b ;//calculate Bitplane...
mov dx,3c4h
mov ax,0102h
shl ah,cl
out dx,ax ;//...and set it
mov ax,0a000h ;//set destination segment
mov es,ax
mov ax,160 ;//set destination offset
mov dx,y
mul dx
shr bx,1
and bl,11111110b
add bx,ax ;//bx contains basic offset
mov di,bx
mov al,blue ;//calculate red-blue
mov ah,16
mul ah
cmp ax,0
je spixgoon
sub ax,16 ;//This is where i adapt blue values.
spixgoon:
add al,red
add cx,y
and cl,00000001b
jz stypetwo ;//Here i decide whether to put red/blue on page 1
mov ah,al ;//and green on page 2 OR to put green on page 1
mov al,green ;//and red/blue on page 2.
add al,240
mov es:[di],ax
jmp send
stypetwo:
mov ah,green
add ah,240
mov es:[di],ax
send:
pop di
pop bp
ret
_F_putsmallpixel ENDP
END