
; This program is in public domain
; Jussi Puttonen 22.7.1990

.286

EMUL_MODE	equ	88	; Paradise VGA 800x600

STACK   SEGMENT STACK  'STACK'
        DB      128 DUP (?)
STACK   ENDS


code	segment	para public 'code'
	assume	cs:code


rows_on_screen	equ	600/16
cols_on_screen	equ	800/8

comment #

; tweaked register values
						; 800 x 600 mode

crtc_regs	db	074h ; horisontal total time (0)
		db	063h ; horisontal display end (1)
		db	064h ; start horisontal blank (2)
		db	097h ; end horisontal blank (3)
		db	068h ; start horisontal retrace (4)
		db	095h ; end horisontal retrace (5)

		db	086h ; vertical total (6)
		db	0F0h ; overflow register (7)

		db	000h, 060h, 000h, 000h ; misc
		db	000h, 000h, 002h, 085h
		db	05Bh ; vertical retrace start (10)
		db	08Dh ; vertical retrace end
		db	057h	; vertical display end
		db 	032h ; offset register
		db	000h
		db	060h ; start vertical blank
		db	080h ; end vertical blank
		db	0E3h ; mode control
		db	0FFh

#

; tweaked register values
						; 800 x 564 mode

crtc_regs	db	074h ; horisontal total time (0)
		db	063h ; horisontal display end (1)
		db	064h ; start horisontal blank (2)
		db	097h ; end horisontal blank (3)
		db	068h ; start horisontal retrace (4)
		db	095h ; end horisontal retrace (5)

		db	062h ; vertical total (6)
		db	0F0h ; overflow register (7)

		db	000h, 060h, 000h, 000h ; misc
		db	000h, 000h, 002h, 061h
		db	037h ; vertical retrace start (10)
		db	089h ; vertical retrace end
		db	033h	; vertical display end
		db 	032h ; offset register
		db	000h
		db	03Ch ; start vertical blank
		db	05Ch ; end vertical blank
		db	0E3h ; mode control
		db	0FFh

VGA_SEGMENT       EQU   0A000h

OldVector	dd	0

Handler:	cmp	ax, EMUL_MODE
		je	set_mode
		cmp	ax, EMUL_MODE + 80h
		je	set_mode
	assume ds:nothing
		jmp	[OldVector]

set_mode:
	push	ds
	push es
	pusha
	and	ax, 80h
	or	ax, 12h
	int	10h		; set video mode to 12h

	push	cs
	pop	ds

	assume ds:code

	mov	ax,1124h		; load ROM 8*16 characters
	mov	bx,0
	mov	dh,0
	mov	dl, rows_on_screen
	int	10h


; this code is from FRACTINT, a public domain
; fractal program
	mov	ax,40h			; Video BIOS DATA area
	mov	es,ax			;  ...

	mov	ax, cols_on_screen
	mov	word ptr es:[4ah],ax
	mov	ax, cols_on_screen*rows_on_screen*2
	mov	word ptr es:[4ch],ax

	mov	dx,word ptr es:[63h]	; say, where's the 6845?
	add	dx,6			; locate the status register
vrdly1:	in	al,dx			; loop until vertical retrace is off
	test	al,8			;   ...
	jnz	vrdly1			;   ...
vrdly2:	in	al,dx			; now loop until it's on!
	test	al,8			;   ...
	jz	vrdly2			;   ...

	cli				; turn off all interrupts
	mov	dx,03c4h		; Sequencer Synchronous reset
	mov	ax,0100h		; set sequencer reset
	out	dx,ax
	mov	dx,03c2h		; Update Misc Output Reg
	mov	al,0E7h
	out	dx,al
	mov	dx,03c4h		; Sequencer Synchronous reset
	mov	ax,0300h		; clear sequencer reset
	out	dx,ax

	mov	si, offset crtc_regs

	mov	dx,word ptr es:[63h]	; say, where's the 6845?
	mov	al,11h			; deprotect registers 0-7
	mov	ah,byte ptr [si+11h]
	and	ah,7fh
	out	dx,ax

	mov	cx,18h			; update this many registers
	mov	bx,00			; starting with this one.
crtcloop:
	mov	al,bl			; update this register
	mov	ah,byte ptr [bx+si]	; to this
	out	dx,ax
	inc	bx			; ready for the next register
	loop	crtcloop		; (if there is a next register)

; code quoted from FRACTINT ends here

	popa
	pop	es
	pop	ds
	iret

pspseg	dw	0

start:
	assume	ds:nothing
	mov	pspseg, ds
;; Get Interrupt
	mov	ax,3510h
	int	21h
	mov	word ptr OldVector.2,es
	mov	word ptr OldVector,bx

;; Set Interrupt

	mov	ax,2510h
	mov	dx,seg Handler
	mov	ds,dx
	mov	dx,offset Handler
	int	21h

;; Now  T S R
	mov	dx,offset start
	mov	cl,4
	shr	dx,cl
	add	dx, 1
	mov	ax, cs
	add	dx, ax
	sub	dx, pspseg
	mov	ax,3100h
	int	21h

code	ends

		end start
