519 lines
12 KiB
NASM
519 lines
12 KiB
NASM
SC_INDEX equ 3c4h ;Sequence Controller Index register
|
|
GC_INDEX equ 3ceh ;Graphics Controller Index register
|
|
CRTC_INDEX equ 3d4h ;CRT Controller Index register
|
|
MEMORY_MODE equ 4 ;Memory Mode register index in SC
|
|
UNDERLINE equ 14h ;Underline Location reg index in CRTC
|
|
MODE_CONTROL equ 17h ;Mode Control register index in CRTC
|
|
GRAPHICS_MODE equ 5 ;Graphics Mode register index in GC
|
|
MISCELLANEOUS equ 6 ;Miscellaneous register index in GC
|
|
|
|
hseq1 LABEL WORD ;0=start
|
|
dw 479 ;display enable end
|
|
dw 485 ;start vertical blank
|
|
dw 490 ;start vertical retrace
|
|
dw 500 ;end vertical retrace
|
|
dw 505 ;end vertical blank
|
|
dw 510 ;vertical total
|
|
dw 480+1 ;200/350/400/480=lines/monitor, +1=double scanning
|
|
|
|
hseq2 LABEL WORD ;0=start
|
|
dw 349 ;display enable end
|
|
dw 354 ;start vertical blank
|
|
dw 360+50 ;start vertical retrace
|
|
dw 375+100 ;end vertical retrace
|
|
dw 395+100 ;end vertical blank
|
|
dw 399+100 ;vertical total
|
|
|
|
tweak320x200 PROC NEAR
|
|
;
|
|
; First, go to normal 320x200 256-color mode, which is really a
|
|
; 320x400 256-color mode with each line scanned twice.
|
|
;
|
|
mov ax,0013h ;AH = 0 means mode set, AL = 13h selects
|
|
; 256-color graphics mode
|
|
int 10h ;BIOS video interrupt
|
|
mov dx,3c8h
|
|
mov al,0
|
|
out dx,al
|
|
inc dx
|
|
mov cx,768
|
|
reclr: out dx,al
|
|
loop reclr
|
|
;
|
|
; Change CPU addressing of video memory to linear (not odd/even,
|
|
; chain, or chain 4), to allow us to access all 256K of display
|
|
; memory. When this is done, VGA memory will look just like memory
|
|
; in modes 10h and 12h, except that each byte of display memory will
|
|
; control one 256-color pixel, with 4 adjacent pixels at any given
|
|
; address, one pixel per plane.
|
|
;
|
|
mov dx,SC_INDEX
|
|
mov al,MEMORY_MODE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 08h ;turn off chain 4
|
|
or al,04h ;turn off odd/even
|
|
out dx,al
|
|
mov dx,GC_INDEX
|
|
mov al,GRAPHICS_MODE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 10h ;turn off odd/even
|
|
out dx,al
|
|
dec dx
|
|
mov al,MISCELLANEOUS
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 02h ;turn off chain
|
|
out dx,al
|
|
|
|
;
|
|
; Tweak the mode to 320x200 256-color mode by scanning each
|
|
; line twice.
|
|
;
|
|
mov dx,CRTC_INDEX
|
|
mov al,9
|
|
; out dx,al
|
|
inc dx
|
|
; in al,dx
|
|
and al,not 5fh ;set maximum scan line = 0
|
|
OR AL,1
|
|
; out dx,al
|
|
dec dx
|
|
;
|
|
; Change CRTC scanning from doubleword mode to byte mode, allowing
|
|
; the CRTC to scan more than 64K of video data.
|
|
;
|
|
mov al,UNDERLINE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 40h ;turn off doubleword
|
|
out dx,al
|
|
dec dx
|
|
mov al,MODE_CONTROL
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
or al,40h ;turn on the byte mode bit, so memory is
|
|
; scanned for video data in a purely
|
|
; linear way, just as in modes 10h and 12h
|
|
out dx,al
|
|
|
|
ret
|
|
|
|
;
|
|
; First, go to normal 320x200 256-color mode, which is really a
|
|
; 320x400 256-color mode with each line scanned twice.
|
|
;
|
|
mov ax,0013h ;AH = 0 means mode set, AL = 13h selects
|
|
; 256-color graphics mode
|
|
int 10h ;BIOS video interrupt
|
|
;
|
|
; Change CPU addressing of video memory to linear (not odd/even,
|
|
; chain, or chain 4), to allow us to access all 256K of display
|
|
; memory. When this is done, VGA memory will look just like memory
|
|
; in modes 10h and 12h, except that each byte of display memory will
|
|
; control one 256-color pixel, with 4 adjacent pixels at any given
|
|
; address, one pixel per plane.
|
|
;
|
|
mov dx,SC_INDEX
|
|
mov al,MEMORY_MODE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 08h ;turn off chain 4
|
|
or al,04h ;turn off odd/even
|
|
out dx,al
|
|
mov dx,GC_INDEX
|
|
mov al,GRAPHICS_MODE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 10h ;turn off odd/even
|
|
out dx,al
|
|
dec dx
|
|
mov al,MISCELLANEOUS
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 02h ;turn off chain
|
|
out dx,al
|
|
|
|
mov dx,SC_INDEX
|
|
mov ax,00f02h ;CLEAR ALL PLANES
|
|
out dx,ax
|
|
;mov ax,cs:vram
|
|
;mov es,ax
|
|
;mov cx,32768
|
|
;xor ax,ax
|
|
;rep stosw
|
|
;
|
|
; Tweak the mode to 320x200 256-color mode by scanning each
|
|
; line twice.
|
|
;
|
|
mov dx,CRTC_INDEX
|
|
mov al,9
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 5fh ;set maximum scan line = 0
|
|
OR AL,1
|
|
out dx,al
|
|
dec dx
|
|
;
|
|
; Change CRTC scanning from doubleword mode to byte mode, allowing
|
|
; the CRTC to scan more than 64K of video data.
|
|
;
|
|
mov al,UNDERLINE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 40h ;turn off doubleword
|
|
out dx,al
|
|
dec dx
|
|
mov al,MODE_CONTROL
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
or al,40h ;turn on the byte mode bit, so memory is
|
|
; scanned for video data in a purely
|
|
; linear way, just as in modes 10h and 12h
|
|
out dx,al
|
|
|
|
mov dx,CRTC_INDEX
|
|
mov ax,2813h
|
|
out dx,ax ;width>=320
|
|
|
|
ret
|
|
tweak320x200 ENDP
|
|
|
|
sethseq PROC NEAR ;ds:si=hseq
|
|
mov bl,1fh ;overflow
|
|
mov bh,40h ;maximum scan line
|
|
test word ptr ds:[si+12],1
|
|
jz sss9
|
|
or bh,80h
|
|
sss9:
|
|
mov ax,ds:[si+0]
|
|
test ax,256
|
|
jz sss3
|
|
or bl,2
|
|
sss3: test ax,512
|
|
jz sss4
|
|
or bl,64
|
|
sss4: mov ah,al
|
|
mov dx,3d4h
|
|
mov al,12h
|
|
out dx,ax
|
|
|
|
mov ax,ds:[si+2]
|
|
test ax,256
|
|
jz sss1
|
|
or bl,8
|
|
sss1: test ax,512
|
|
jz sss2
|
|
or bh,32
|
|
sss2: mov ah,al
|
|
mov dx,3d4h
|
|
mov al,15h
|
|
out dx,ax
|
|
|
|
mov ax,ds:[si+4]
|
|
test ax,256
|
|
jz sss7
|
|
or bl,4
|
|
sss7: test ax,512
|
|
jz sss8
|
|
or bl,128
|
|
sss8: mov ah,al
|
|
mov dx,3d4h
|
|
mov al,10h
|
|
out dx,ax
|
|
|
|
mov ax,ds:[si+6]
|
|
mov ah,al
|
|
and ah,15
|
|
or ah,20h ;disable vertical int
|
|
mov dx,3d4h
|
|
mov al,11h
|
|
out dx,ax
|
|
|
|
mov ax,ds:[si+8]
|
|
mov ah,al
|
|
mov dx,3d4h
|
|
mov al,16h
|
|
out dx,ax
|
|
|
|
mov ax,ds:[si+10]
|
|
test ax,256
|
|
jz sss5
|
|
or bl,1
|
|
sss5: test ax,512
|
|
jz sss6
|
|
or bl,32
|
|
sss6: mov ah,al
|
|
mov dx,3d4h
|
|
mov al,6h
|
|
out dx,ax
|
|
|
|
mov dx,3d4h
|
|
mov al,7h
|
|
mov ah,bl
|
|
out dx,ax
|
|
|
|
mov dx,3d4h
|
|
mov al,9h
|
|
mov ah,bh
|
|
out dx,ax
|
|
|
|
mov ax,ds:[si+12]
|
|
and ax,not 1
|
|
mov bh,0
|
|
cmp ax,350
|
|
jne sss10
|
|
mov bh,1*64
|
|
sss10: cmp ax,400
|
|
jne sss11
|
|
mov bh,2*64
|
|
sss11: cmp ax,480
|
|
jne sss12
|
|
mov bh,3*64
|
|
sss12: mov dx,3cch
|
|
in al,dx
|
|
and al,3fh
|
|
or al,bh
|
|
mov dx,3c2h
|
|
out dx,al
|
|
ret
|
|
sethseq ENDP
|
|
|
|
vptbl dw 06a00h ; horz total
|
|
dw 05901h ; horz displayed
|
|
dw 05a02h ; start horz blanking
|
|
dw 08d03h ; end horz blanking
|
|
dw 05e04h ; start h sync
|
|
dw 08a05h ; end h sync
|
|
dw 08b06h ;0d06h ; vertical total
|
|
dw 01f07h ;03e07h ; overflow
|
|
dw 04009h ; cell height
|
|
dw 06810h ; v sync start
|
|
dw 02a11h ; v sync end and protect cr0-cr7
|
|
dw 05d12h ; vertical displayed
|
|
dw 02e13h ; offset 92
|
|
dw 00014h ; turn off dword mode
|
|
dw 05d15h ; v blank start
|
|
dw 00016h ; v blank end
|
|
dw 0e317h ; turn on byte mode
|
|
vpend label word
|
|
|
|
mode13x proc
|
|
push ds
|
|
mov ax,cs
|
|
mov ds,ax
|
|
|
|
mov ax,13h ; start with standard mode 13h
|
|
int 10h ; let the bios set the mode
|
|
|
|
mov dx,3c4h ; alter sequencer registers
|
|
mov ax,0604h ; disable chain 4
|
|
out dx,ax
|
|
|
|
mov ax,0f02h ; set write plane mask to all bit planes
|
|
out dx,ax
|
|
push di
|
|
xor di,di
|
|
mov ax,0a000h ; screen starts at segment A000
|
|
mov es,ax
|
|
mov cx,21600 ; ((XSIZE*YSIZE)/(4 planes))/(2 bytes per word)
|
|
xor ax,ax
|
|
cld
|
|
rep stosw ; clear the whole of the screen
|
|
pop di
|
|
|
|
mov ax,0100h ; synchronous reset
|
|
out dx,ax ; asserted
|
|
mov dx,3c2h ; misc output
|
|
mov al,0a7h ; use 28 mHz dot clock ;a7
|
|
out dx,al ; select it
|
|
mov dx,3c4h ; sequencer again
|
|
mov ax,0300h ; restart sequencer
|
|
out dx,ax ; running again
|
|
|
|
mov dx,3d4h ; alter crtc registers
|
|
|
|
mov al,11h ; cr11
|
|
out dx,al ; current value
|
|
inc dx ; point to data
|
|
in al,dx ; get cr11 value
|
|
and al,7fh ; remove cr0 -> cr7
|
|
out dx,al ; write protect
|
|
dec dx ; point to index
|
|
cld
|
|
mov si,offset vptbl
|
|
mov cx,((offset vpend)-(offset vptbl)) shr 1
|
|
outlp: lodsw
|
|
out dx,ax
|
|
loop outlp
|
|
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov si,OFFSET hseq2
|
|
call sethseq
|
|
|
|
; mov dx,3dah
|
|
; in al,dx
|
|
; mov dx,3c0h
|
|
; mov al,11h+32
|
|
; out dx,al
|
|
; mov al,8
|
|
; out dx,al
|
|
|
|
pop ds
|
|
ret
|
|
mode13x endp
|
|
|
|
tweak640x400 PROC NEAR
|
|
;
|
|
; First, go to normal 320x200 256-color mode, which is really a
|
|
; 320x400 256-color mode with each line scanned twice.
|
|
;
|
|
mov ax,002fh
|
|
int 10h ;BIOS video interrupt
|
|
;
|
|
; Change CPU addressing of video memory to linear (not odd/even,
|
|
; chain, or chain 4), to allow us to access all 256K of display
|
|
; memory. When this is done, VGA memory will look just like memory
|
|
; in modes 10h and 12h, except that each byte of display memory will
|
|
; control one 256-color pixel, with 4 adjacent pixels at any given
|
|
; address, one pixel per plane.
|
|
;
|
|
mov dx,SC_INDEX
|
|
mov al,MEMORY_MODE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 08h ;turn off chain 4
|
|
or al,04h ;turn off odd/even
|
|
out dx,al
|
|
mov dx,GC_INDEX
|
|
mov al,GRAPHICS_MODE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 10h ;turn off odd/even
|
|
out dx,al
|
|
dec dx
|
|
mov al,MISCELLANEOUS
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 02h ;turn off chain
|
|
out dx,al
|
|
ret
|
|
;
|
|
; Change CRTC scanning from doubleword mode to byte mode, allowing
|
|
; the CRTC to scan more than 64K of video data.
|
|
;
|
|
mov al,UNDERLINE
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
and al,not 40h ;turn off doubleword
|
|
out dx,al
|
|
dec dx
|
|
mov al,MODE_CONTROL
|
|
out dx,al
|
|
inc dx
|
|
in al,dx
|
|
or al,40h ;turn on the byte mode bit, so memory is
|
|
; scanned for video data in a purely
|
|
; linear way, just as in modes 10h and 12h
|
|
out dx,al
|
|
|
|
ret
|
|
tweak640x400 ENDP
|
|
|
|
hseq3 LABEL WORD ;0=start
|
|
dw 349 ;display enable end
|
|
dw 355 ;start vertical blank
|
|
dw 395 ;start vertical retrace
|
|
dw 405 ;end vertical retrace
|
|
dw 445 ;end vertical blank
|
|
dw 455 ;vertical total
|
|
dw 350 ;200/350/400/480=lines/monitor, +1=double scanning
|
|
|
|
tweak360x350 proc
|
|
push ds
|
|
mov ax,cs
|
|
mov ds,ax
|
|
|
|
mov ax,13h ; start with standard mode 13h
|
|
int 10h ; let the bios set the mode
|
|
|
|
mov dx,3c4h ; alter sequencer registers
|
|
mov ax,0604h ; disable chain 4
|
|
out dx,ax
|
|
|
|
mov ax,0f02h ; set write plane mask to all bit planes
|
|
out dx,ax
|
|
push di
|
|
xor di,di
|
|
mov ax,0a000h ; screen starts at segment A000
|
|
mov es,ax
|
|
mov cx,21600 ; ((XSIZE*YSIZE)/(4 planes))/(2 bytes per word)
|
|
xor ax,ax
|
|
cld
|
|
rep stosw ; clear the whole of the screen
|
|
pop di
|
|
|
|
mov ax,0100h ; synchronous reset
|
|
out dx,ax ; asserted
|
|
mov dx,3c2h ; misc output
|
|
mov al,0a7h ; use 28 mHz dot clock
|
|
out dx,al ; select it
|
|
mov dx,3c4h ; sequencer again
|
|
mov ax,0300h ; restart sequencer
|
|
out dx,ax ; running again
|
|
|
|
mov dx,3d4h ; alter crtc registers
|
|
|
|
mov al,11h ; cr11
|
|
out dx,al ; current value
|
|
inc dx ; point to data
|
|
in al,dx ; get cr11 value
|
|
and al,7fh ; remove cr0 -> cr7
|
|
out dx,al ; write protect
|
|
dec dx ; point to index
|
|
cld
|
|
mov si,offset vptbl
|
|
mov cx,((offset vpend)-(offset vptbl)) shr 1
|
|
outlpn: lodsw
|
|
out dx,ax
|
|
loop outlpn
|
|
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov si,OFFSET hseq3
|
|
call sethseq
|
|
|
|
pop ds
|
|
ret
|
|
tweak360x350 endp
|
|
|
|
hseq4 LABEL WORD ;0=start
|
|
dw 349 ;display enable end
|
|
dw 355 ;start vertical blank
|
|
dw 395 ;start vertical retrace
|
|
dw 405 ;end vertical retrace
|
|
dw 450 ;end vertical blank
|
|
dw 455 ;vertical total
|
|
dw 350 ;200/350/400/480=lines/monitor, +1=double scanning
|
|
|
|
tweak320x350 proc
|
|
call tweak360x350
|
|
ret
|
|
tweak320x350 endp
|