; =============================================================================
;
;                               Litos8 display driver
;
; =============================================================================

; -----------------------------------------------------------------------------
; Exported user functions (22):
;	DispGetCard - get video card type
;	DispSetMode - set videomode
;	DispGetMode - get current videomode
;	DispGetModeDesc - get videomode descriptor
;	DispGetFontSize - get current font height
;	DispClear - clear display
;	SetCursor - set cursor position
;	GetCursor - get cursor position
;	SetCursorSize - set cursor size
;	GetCursorSize - get cursor size
;	DispGetDefCol - get default color
;	DispSetDefCol - set default color
;	DispFill - fill text area
;	DispChar - display character
;	DispText - display text
;	DispMove - move text area
;	DispScroll - scroll screen by one row
;	DispSetShift - set shift of view window
;	DispGetShift - get shift of view window
;	GetCharFont - get character font (8x8 character)
;	SetBorder - set screen border color
;	DispCharTable - display character table
; -----------------------------------------------------------------------------

		CONST_SECTION

%include	"SOURCE/FONT8x8.ASM"	; 8x8 font
%include	"SOURCE/FONT8x8K.ASM"	; 8x8 font Kamenickych

		CODEINIT_SECTION

; -----------------------------------------------------------------------------
;                      INIT: Initialize display driver
; -----------------------------------------------------------------------------

; ------------- set default settings

InitDisp:	mov	byte [DefColor],7 ; default text color

; ------------- check EGA videocard

		mov	byte [VideoCard],VCARD_MDA
		mov	byte [VideoCardMask],VCARD_MDA_MASK
		mov	ah,12h		; AH <- command
		mov	bx,0ff10h	; BL <- function subcode
		call	Int10		; check videocard type
		cmp	bh,1		; check color mode flag
		ja	short InitDisp3	; invalid EGA videocard
		cmp	bl,10h		; check memory size
		je	short InitDisp3	; invalid EGA videocard
		mov	byte [VideoCard],VCARD_EGA ; set EGA type card
		mov	byte [VideoCardMask],VCARD_EGA_MASK ; set EGA type card

; ------------- check VGA videocard

		mov	ax,1a00h	; AX <- function code
		call	Int10		; check VGA card
		cmp	al,1ah		; check magic number
		jne	short InitDisp4	; invalid VGA videocard
		inc	bx		; BL += 1
		shr	bl,1		; BL /= 2
		cmp	bl,(7+1)/2	; display combination 7 or 8?
		je	short InitDisp2	; ok, VGA with bw/col display
		cmp	bl,(11+1)/2	; display combination 11 or 12?
		jne	short InitDisp4	; no VGA card
InitDisp2:	mov	byte [VideoCard],VCARD_VGA ; set VGA type card
		mov	byte [VideoCardMask],VCARD_VGA_MASK ; set VGA type card
		jmp	short InitDisp4

; ------------- check CGA videocard (checking control port address 3d4h/3b4h)

InitDisp3:	cmp	byte [463h],0d4h ; is it MDA videocard?
		jb	short InitDisp4	; it is MDA videocard (addr. 3b4h)
		mov	byte [VideoCard],VCARD_CGA ; set CGA videocard
		mov	byte [VideoCardMask],VCARD_CGA_MASK ; set CGA videocard

; ------------- initialize videomode

InitDisp4:	mov   byte [VModeTabs+VMODE_INVALID*VMODE_size+VMODE_DEFMODE],3
		call	DetectMode	; detect current videomode
		mov	al,[VideoDefMode] ; AL <- default videomode
		call	DispSetMode	; initizalize videomode
DispEmptyFunc:	ret


		CODE_SECTION

; -----------------------------------------------------------------------------
;                           Set screen border color
; -----------------------------------------------------------------------------
; INPUT:	AL = border color 0..31 (bit 4: high intensity)
; NOTES:	With CGA graphics card it works only in text modes.
; -----------------------------------------------------------------------------

; ------------- push registers

SetBorder:	push	ax		; push AX
		push	bx		; push BX

; ------------- prepare to set EGA border color

		mov	bh,al		; BH <- required color
		mov	ax,1001h	; AX <- function and subfunction

; ------------- check video vard

		cmp	byte [VideoCard],VCARD_EGA ; check EGA/VGA video card
		jae	short SetBorder6 ; set border with EGA/VGA

; ------------- CGA: check text mode

		cmp	byte [VideoModel],VMODE_MODEL_TXT ; text model?
		jne	short SetBorder8 ; no text mode
		
; ------------- set CGA border color

		mov	bl,bh		; BL <- required color
		mov	bh,0		; BH <- 0, subcommand
		mov	ah,0bh		; AH <- command
SetBorder6:	call	Int10All	; set border color

; ------------- pop registers

SetBorder8:	pop	bx		; pop BX
		pop	ax		; pop AX
		ret

; -----------------------------------------------------------------------------
;                     Display character table (characters 0..255)
; -----------------------------------------------------------------------------
; INPUT:	AH = color attributes
;		DH = column
;		DL = row
; NOTES:	Table has size 35 x 18.
; -----------------------------------------------------------------------------

; ------------- push registers

DispCharTable:	push	ax		; push AX
		push	cx		; push CX
		push	dx		; push DX

; ------------- display frame

		mov	al,FRAME_H + FRAME_V + FRAME_FILL ; AL <- flags
		mov	cx,18*256 + 35	; CL <- width, CH <- height
		call	DispFrame	; display frame

; ------------- display characters

		mov	ch,16		; CH <- row counter
		mov	al,0		; AL <- character
DispCharTable2:	inc	dh		; DH <- increase row
		mov	cl,16		; CL <- column counter
DispCharTable4:	inc	dx		; DL <- increase column
		inc	dx		; DL <- start column
		call	DispChar	; display character
		inc	ax		; AL <- next character
		dec	cl		; CL = position counter
		jnz	short DispCharTable4 ; next character
		sub	dl,16*2		; DL <- reset column
		dec	ch		; CH = row counter
		jnz	short DispCharTable2 ; next row

; ------------- pop registers

		pop	dx		; pop DX
		pop	cx		; pop CX
		pop	ax		; pop AX
		ret

; -----------------------------------------------------------------------------
;                      Get video card type
; -----------------------------------------------------------------------------
; OUTPUT:	AL = video card type (VCARD_MDA..)
; -----------------------------------------------------------------------------

DispGetCard:	mov	al,[VideoCard]
		ret

; -----------------------------------------------------------------------------
;                         Get current videomode
; -----------------------------------------------------------------------------
; OUTPUT:	AL = videomode (VMODE_40x25G..)
; -----------------------------------------------------------------------------

DispGetMode:	mov	al,[VideoMode]
		ret

; -----------------------------------------------------------------------------
;                         Get default color
; -----------------------------------------------------------------------------
; OUTPUT:	AL = default color
; -----------------------------------------------------------------------------

DispGetDefCol:	mov	al,[DefColor]
		ret

; -----------------------------------------------------------------------------
;                         Set default color
; -----------------------------------------------------------------------------
; INPUT:	AL = default color
; -----------------------------------------------------------------------------

DispSetDefCol:	mov	[DefColor],al
		ret

; -----------------------------------------------------------------------------
;                     Get current videomode descriptor
; -----------------------------------------------------------------------------
; OUTPUT:	SI = pointer to VMODE descriptor
; -----------------------------------------------------------------------------

DispGetModeDesc:mov	si,VideoDesc
		ret

; -----------------------------------------------------------------------------
;                       Get current font size
; -----------------------------------------------------------------------------
; OUTPUT:	AL = number of lines per character
; NOTES:	Can be used when setting cursor size.
;		All graphics modes use 8-line characters.
; -----------------------------------------------------------------------------

DispGetFontSize:cmp	byte [VideoModel],VMODE_MODEL_TXT ; text model?
		jne	short DispGetFntSize2 ; no hw cursor, use 8-line font
		mov	al,[485h]	; AL <- font height
		cmp	al,32		; maximal font height
		ja	short DispGetFntSize2 ; invalid font height
		cmp	al,8		; minimal font height
		ja	short DispGetFntSize4 ; font height is OK
DispGetFntSize2:mov	al,8		; AL <- 8-line characters
DispGetFntSize4:ret

; -----------------------------------------------------------------------------
;               Call INT 10h service, saving some registers
; -----------------------------------------------------------------------------
; DESTROY:	AX, BX, CX, DX
; -----------------------------------------------------------------------------

; ------------- push registers

Int10:		pushf			; push flags
		push	si		; push SI
		push	di		; push DI
		push	bp		; push BP
		push	ds		; push DS
		push	es		; push ES

; ------------- call INT 10h

		int	10h

; ------------- pop registers

		pop	es		; pop ES
		pop	ds		; pop DS
		pop	bp		; pop BP
		pop	di		; pop DI
		pop	si		; pop SI
		popf			; pop flags
		ret

; -----------------------------------------------------------------------------
;               Call INT 10h service, saving all registers
; -----------------------------------------------------------------------------

; ------------- push registers

Int10All:	push	ax		; push AX
		push	bx		; push BX
		push	cx		; push CX
		push	dx		; push DX

; ------------- call INT 10h

		call	Int10		; call INT 10h service

; ------------- pop registers

		pop	dx		; pop DX
		pop	cx		; pop CX
		pop	bx		; pop BX
		pop	ax		; pop AX
		ret

; -----------------------------------------------------------------------------
;                          Detect videomode
; -----------------------------------------------------------------------------

; ------------- push registers

DetectMode:	push	ax		; push AX
		push	bx		; push BX
		push	cx		; push CX
		push	dx		; push DX
		push	si		; push SI
		push	di		; push DI

; ------------- get current videomode -> AL

		mov	ah,0fh		; AH <- command
		call	Int10		; get current videomode
		and	al,7fh		; reset bit 7
		mov	[VideoMode],al	; save current videomode
		cmp	al,VMODE_NUM	; chech videomode range
		jb	short DetectMode2 ; videomode is OK
		mov	al,VMODE_INVALID ; invalid vidomode

; ------------- get videomode descriptor

DetectMode2:	mov	cx,VMODE_size	; CX <- descriptor size
		mul	cl		; AX <- offset of videomode
		add	ax,VModeTabs	; AX <- videomode descriptor
		xchg	ax,si		; SI <- videomode descriptor
		mov	di,VideoDesc	; DI <- current descriptor
		rep	movsb		; save descriptor

; ------------- pop registers

		pop	di		; pop DI
		pop	si		; pop SI
		pop	dx		; pop DX
		pop	cx		; pop CX
		pop	bx		; pop BX
		pop	ax		; pop AX
		ret

; -----------------------------------------------------------------------------
;                         Initialize videomode
; -----------------------------------------------------------------------------
; INPUT:	AL = required videomode
; OUTPUT:	AL = new current videomode
; -----------------------------------------------------------------------------

; ------------- push registers

DispSetMode:	push	ax		; push AX
		push	dx		; push DX

; ------------- initialize videomode

		mov	ah,0		; AH <- command
		call	Int10All	; initialize videomode

; ------------- detect current videomode

		call	DetectMode	; detect videomode

; ------------- set cursor position to 0:0

		mov	word [VideoOff],0 ; reset memory offset
		mov	word [PageRow],0 ; reset current row of displayed page
		xor	dx,dx		; DX <- position 0:0	
		call	SetCursorNow	; set cursor position

; ------------- set cursor size

		call	DispGetFontSize	; get font size -> AL
		dec	ax
		dec	ax		; AL <- bottom line
		mov	ah,al		; AH <- font size
		dec	ah		; AH <- top line
		mov	byte [CursorSizeT],-1 ; invalidate cursor size
		call	SetCursorSize	; set cursor size

; ------------- reset page offset

		xor	ax,ax		; AX <- 0
		dec	word [PageRow]	; invalidate row of displayed page
		call	DispSetShift	; set current offset

; ------------- switch off text blinking

		mov	al,0		; AL <- 0, intensive background
		call	SetTXTBlink	; set text blinking

; ------------- update text fonts

		call	UpdateTextFont	; update fonts

; ------------- set default VGA palettes

		cmp	byte [VideoModel],VMODE_MODEL_VGA ; 256 colors?
		jne	short DispSetMode4 ; no
		call	VGASetPalDef	; set default VGA palettes

; ------------- clear display, using default color

DispSetMode4:	call	DispClear	; clear display

; ------------- pop registers

		pop	dx		; pop DX
		pop	ax		; pop AX
		mov	al,[VideoMode]	; AL <- new current videomode
		ret

; -----------------------------------------------------------------------------
;                      Output byte to display register
; -----------------------------------------------------------------------------
; INPUT:	AL = data byte
;		CL = register number
; -----------------------------------------------------------------------------

; ------------- push registers

DispOutByte:	push	dx		; push DX

; ------------- select register and output data byte

		mov	dx,[VideoPort]	; DX <- control port (3D4h or 3B4h)
		xchg	ax,cx		; AL <- register, CL <- data byte
		out	dx,al		; select register
		xchg	ax,cx		; AL <- data byte, CL <- register
		inc	dx		; DX <- data port
		out	dx,al		; set data byte 

; ------------- pop registers

		pop	dx		; pop DX
		ret

; -----------------------------------------------------------------------------
;                      Output word to display registers
; -----------------------------------------------------------------------------
; INPUT:	AX = data word
;		CL = first register number (for HIGH, CL+1=register for LOW)
; NOTES:	It temporaly disables interrupts.
; -----------------------------------------------------------------------------

DispOutWord:	pushf			; push flags
		cli			; disable interrupts

		xchg	al,ah		; AL <- data HIGH, AH <- data LOW
		call	DispOutByte	; set register HIGH
		xchg	al,ah		; AL <- data LOW, AH <- data HIGH
		inc	cx		; CL <- register + 1
		call	DispOutByte	; set register LOW
		dec	cx		; CL <- register

		popf			; pop flags and maybe enable interrupts
		ret

; -----------------------------------------------------------------------------
;                            Set cursor position
; -----------------------------------------------------------------------------
; INPUT:	DL = column
;		DH = row
; NOTES:	Cursor is visible only in text modes.
;		To disable cursor, move it out of display area.
;		It temporaly disables interrupts.
; -----------------------------------------------------------------------------

; ------------- check if cursor position has been changed

SetCursor:	cmp	dx,[CursorPos]	; check cursor position
		je	short SetCursor8 ; cursor not changed

; ------------- push registers

SetCursorNow:	push	ax		; push AX
		push	cx		; push CX

; ------------- save new cursor position

		mov	[CursorPos],dx	; save cursor position

; ------------- available only in text mode

		cmp	byte [VideoModel],VMODE_MODEL_TXT ; text model?
		jne	short SetCursor6 ; no hardware cursor

; ------------- calculate cursor offset

		mov	cx,dx		; CX <- push DX
		mov	dl,dh		; DL <- cursor row
		mov	dh,0		; DH <- 0
		add	dx,[PageRow]	; DX <- add page shift
		mov	al,[VideoCols]	; AL <- characters per row
		cbw			; AX <- characters per row
		mul	dx		; AX <- recalc row to characters
		mov	dx,cx		; DX <- pop DX
		add	al,dl		; AL <- add column
		adc	ah,0		; AH <- carry

; ------------- set new cursor offset

		mov	cl,14		; CL <- register number
		call	DispOutWord	; set memory offset

; ------------- pop registers

SetCursor6:	pop	cx		; pop CX
		pop	ax		; pop AX
SetCursor8:	ret

; -----------------------------------------------------------------------------
;                            Get cursor position
; -----------------------------------------------------------------------------
; INPUT:	AL = column
;		AH = row
; -----------------------------------------------------------------------------

GetCursor:	mov	ax,[CursorPos]
		ret

; -----------------------------------------------------------------------------
;                            Set cursor size
; -----------------------------------------------------------------------------
; INPUT:	AL = bottom line of cursor, from top (0..31, AL >= AH)
;		AH = top line of cursor, from top (0..31, AH <= AL)
; NOTES:	Cursor is visible only in text modes.
;		To disable cursor, move it out of display area.
;		It temporaly disables interrupts.
; -----------------------------------------------------------------------------

; ------------- push registers

SetCursorSize:	push	ax		; push AX
		push	cx		; push CX

; ------------- byte order correction

		cmp	ah,al		; check line order
		jb	short SetCursorSize2 ; line order is OK
		xchg	al,ah		; correct line order

; ------------- check, if cursor size changed

SetCursorSize2:	cmp	ax,[CursorSize]	; cursor size changed?
		je	short SetCursorSize4 ; cursor size not changed
		mov	[CursorSize],ax	; save current cursor size

; ------------- available only in text mode

		cmp	byte [VideoModel],VMODE_MODEL_TXT ; text model?
		jne	short SetCursorSize4 ; no hardware cursor

; ------------- set new cursor size
		
		mov	cl,10		; CL <- register number
		call	DispOutWord	; set cursor size

; ------------- pop registers

SetCursorSize4:	pop	cx		; pop CX
		pop	ax		; pop AX
		ret

; -----------------------------------------------------------------------------
;                            Get cursor size
; -----------------------------------------------------------------------------
; OUTPUT:	AL = bottom line of cursor,from top (0..31, AL >= AH)
;		AH = top line of cursor, from top (0..31, AH <= AL)
; NOTES:	Cursor is visible only in text modes.
;		To disable cursor, move it out of display area.
; -----------------------------------------------------------------------------

GetCursorSize:	mov	ax,[CursorSize]	; AX <- cursor size
		ret

; -----------------------------------------------------------------------------
;                            Clear display
; -----------------------------------------------------------------------------

DispClear:	call	[VideoClearFnc]	; clear display

		push	dx		; push DX
		xor	dx,dx		; DX <- 0
		call	SetCursor	; set cursor
		pop	dx		; pop DX
		ret

; -----------------------------------------------------------------------------
;                            Fill text area
; -----------------------------------------------------------------------------
; INPUT:	AL = character
;		AH = color attributes
;		CL = width
;		CH = height
;		DL = column
;		DH = row
; -----------------------------------------------------------------------------

; ------------- check start position

DispFill:	cmp	dl,[VideoCols]	; check column
		jae	short DispFill9	; invalid column
		cmp	dh,[VideoRows]	; check row
		jae	short DispFill9	; invalid row

; ------------- push registers

		push	cx		; push CX

; ------------- limit dimension -> CX

		push	ax		; push AX
		mov	ax,[VideoColsRows] ; AL <- columns, AH <- rows
		sub	al,dl		; AL <- remaining columns
		cmp	al,cl		; check width
		ja	short DispFill2	; width is OK
		mov	cl,al		; CL <- limit width
DispFill2:	sub	ah,dh		; AH <- remaining rows
		cmp	ah,ch		; check height
		ja	short DispFill4	; height is OK
		mov	ch,ah		; CH <- limit height
DispFill4:	pop	ax

; ------------- check dimension

		or	cl,cl		; check width
		jz	short DispFill8	; invalid width
		or	ch,ch		; check height
		jz	short DispFill8	; invalid height

; ------------- fill text area

		call	[VideoFillFnc]

; ------------- pop registers

DispFill8:	pop	cx
DispFill9:	ret

; -----------------------------------------------------------------------------
;                            Display character
; -----------------------------------------------------------------------------
; INPUT:	AL = character
;		AH = color attributes
;		DL = column
;		DH = row
; -----------------------------------------------------------------------------

DispChar:	cmp	dl,[VideoCols]	; check column
		jae	short DispText9	; invalid column
		cmp	dh,[VideoRows]	; check row
		jae	short DispText9	; invalid row
		jmp	[VideoCharFnc]

; -----------------------------------------------------------------------------
;                            Display text
; -----------------------------------------------------------------------------
; INPUT:	AH = color attributes
;		SI = pointer to text
;		CX = text length
;		DL = column
;		DH = row
; -----------------------------------------------------------------------------

; ------------- push registers

DispText:	push	ax		; push AX
		push	cx		; push CX
		push	dx		; push DX
		push	si		; push SI

; ------------- display text

		jcxz	DispText8	; no text
DispText2:	lodsb			; AL <- character
		call	DispChar	; display character
		inc	dx		; increase position
		loop	DispText2	; next character

; ------------- pop registers

DispText8:	pop	si		; pop SI
		pop	dx		; pop DX
		pop	cx		; pop CX
		pop	ax		; pop AX
DispText9:	ret

; -----------------------------------------------------------------------------
;                            Move text area
; -----------------------------------------------------------------------------
; INPUT:	BL = source column
;		BH = source row
;		CL = width
;		CH = height
;		DL = destination column
;		DH = destination row
; -----------------------------------------------------------------------------

DispMove:	jmp	[VideoMoveFnc]

; -----------------------------------------------------------------------------
;                            Scroll screen by on row
; -----------------------------------------------------------------------------

; ------------- push registers

DispScroll:	push	ax		; push AX
		push	bx		; push BX
		push	cx		; push CX
		push	dx		; push DX

; ------------- move screen content

		mov	bl,0		; BL <- source column
		mov	bh,1		; BH <- source row
		xor	dx,dx		; DH,DL <- 0, destination row,column
		mov	cx,[VideoColsRows] ; CX <- screen size
		dec	ch		; CH <- number of rows - 1
		call	DispMove	; move screen content

; ------------- clear bottom row

		mov	al,32		; AL <- space character
		mov	ah,[DefColor]	; AH <- default color
		mov	dh,ch		; DH <- last row
		mov	ch,1		; CH <- height of last row
		call	DispFill	; clear last row

; ------------- pop registers

		pop	dx		; pop DX
		pop	cx		; pop CX
		pop	bx		; pop BX
		pop	ax		; pop AX
		ret

; -----------------------------------------------------------------------------
;                           Set shift of view window
; -----------------------------------------------------------------------------
; INPUT:	AX = row (text) or Y coordinate (graphics)
; -----------------------------------------------------------------------------

; ------------- push registers

DispSetShift:	push	ax		; push AX
		push	dx		; push DX

; ------------- limit minimal row

		or	ax,ax		; check underflow
		jns	short DispSetShift2 ; row is OK
		xor	ax,ax		; AX <- 0, limit minimal row

; ------------- limit maximal row

DispSetShift2:	cmp	ax,[VideoMaxShift] ; check overflow
		jbe	short DispSetShift4 ; shift is OK
		mov	ax,[VideoMaxShift] ; AX <- limit shift

; ------------- check, if shift is changed

DispSetShift4:	cmp	ax,[PageRow]	; row changed?
		je	short DispSetShift8 ; no change
		mov	[PageRow],ax	; save new page row

; ------------- shift view window

		call	[VideoShiftFnc]	; shift view window

; ------------- set new cursor

		mov	dx,[CursorPos]	; DX <- current cursor position
		call	SetCursorNow	; update cursor position

; ------------- pop registers

DispSetShift8:	pop	dx		; pop DX
		pop	ax		; pop AX
		ret

; -----------------------------------------------------------------------------
;                          Get shift of view window
; -----------------------------------------------------------------------------
; OUTPUT:	AX = row (text) or Y coordinate (graphics)
; -----------------------------------------------------------------------------

DispGetShift:	mov	ax,[PageRow]	; AX <- current shift
		ret

; -----------------------------------------------------------------------------
;                            Get character font
; -----------------------------------------------------------------------------
; INPUT:	AL = character
; OUTPUT:	SI = address of 8x8 character font
; -----------------------------------------------------------------------------

; ------------- prepare offset in font table -> SI

GetCharFont:	mov	si,ax		; SI <- character
		and	si,0ffh		; SI <- character
		shl	si,1
		shl	si,1
		shl	si,1		; SI <- offset in font table

; ------------- get font address -> SI

		add	si,Font8x8	; SI <- standard font
		cmp	byte [Language],LANG_EN ; national font?
		je	short GetCharFont2 ; not using national
		cmp	al,NATCHAR_MIN	; check min. national character
		jb	short GetCharFont2 ; no national character
		cmp	al,NATCHAR_MAX	; check max. national character
		ja	short GetCharFont2 ; no national character
		add	si,Font8x8Kam - Font8x8 - NATCHAR_MIN*8 ; SI <- address
GetCharFont2:	ret

; -----------------------------------------------------------------------------
;                            Constant data
; -----------------------------------------------------------------------------

		CONST_SECTION

; ------------- videomode tables

		align	2, db 0
VModeTabs:
	; --- 0: text 40 x 25 gray (204 rows: 8 pages + 4 rows)
		db	VMODE_FLAGS_CGA + VMODE_FLAGS_EGA + VMODE_FLAGS_VGA
		db	VMODE_MODEL_TXT	; 1: color model
		db	4		; 2: number of color bits
		db	0		; 3: default text videomode
		db	40		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	2*40		; 6: bytes per row (text or graphics)
		dw	40		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b800h		; 12: videomemory segment
		dw	4000h/80-25 	; 14: view window max. shift
		dw	3d4h		; 16: control port
		dw	TXTDispClear	; 18: function - clear display
		dw	TXTDispFill	; 20: function - fill text area
		dw	TXTDispChar	; 22: function - display character
		dw	TXTDispMove	; 24: function - move text area
		dw	TXTDispShift	; 26: function - shift view vindow

	; --- 1: text 40 x 25 color (204 rows: 8 pages + 4 rows)
		db	VMODE_FLAGS_CGA + VMODE_FLAGS_EGA + VMODE_FLAGS_VGA
		db	VMODE_MODEL_TXT	; 1: color model
		db	4		; 2: number of color bits
		db	1		; 3: default text videomode
		db	40		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	2*40		; 6: bytes per row (text or graphics)
		dw	40		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b800h		; 12: videomemory segment
		dw	4000h/80-25	; 14: view window max. shift
		dw	3d4h		; 16: control port
		dw	TXTDispClear	; 18: function - clear display
		dw	TXTDispFill	; 20: function - fill text area
		dw	TXTDispChar	; 22: function - display character
		dw	TXTDispMove	; 24: function - move text area
		dw	TXTDispShift	; 26: function - shift view vindow

	; --- 2: text 80 x 25 gray (102 rows: 4 pages + 2 rows)
		db	VMODE_FLAGS_CGA + VMODE_FLAGS_EGA + VMODE_FLAGS_VGA
		db	VMODE_MODEL_TXT	; 1: color model
		db	4		; 2: number of color bits
		db	2		; 3: default text videomode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	2*80		; 6: bytes per row (text or graphics)
		dw	80		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b800h		; 12: videomemory segment
		dw	4000h/160-25	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	TXTDispClear	; 18: function - clear display
		dw	TXTDispFill	; 20: function - fill text area
		dw	TXTDispChar	; 22: function - display character
		dw	TXTDispMove	; 24: function - move text area
		dw	TXTDispShift	; 26: function - shift view vindow

	; --- 3: text 80 x 25 color (102 rows: 4 pages + 2 rows)
		db	VMODE_FLAGS_CGA + VMODE_FLAGS_EGA + VMODE_FLAGS_VGA
		db	VMODE_MODEL_TXT	; 1: color model
		db	4		; 2: number of color bits
		db	3		; 3: default text videomode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	2*80		; 6: bytes per row (text or graphics)
		dw	80		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b800h		; 12: videomemory segment
		dw	4000h/160-25	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	TXTDispClear	; 18: function - clear display
		dw	TXTDispFill	; 20: function - fill text area
		dw	TXTDispChar	; 22: function - display character
		dw	TXTDispMove	; 24: function - move text area
		dw	TXTDispShift	; 26: function - shift view vindow

	; --- 4: CGA graphics 320x200/4 color (204 lines: 1 page + 4 lines)
		db	VMODE_FLAGS_CGA + VMODE_FLAGS_EGA + VMODE_FLAGS_VGA
		db	VMODE_MODEL_CG2	; 1: color model
		db	2		; 2: number of color bits
		db	1		; 3: default text mode
		db	40		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	80		; 6: bytes per row (text or graphics)
		dw	320		; 8: graphics width
		dw	200		; 10: graphics height
		dw	0b800h		; 12: videomemory segment
		dw	4000h/80-200	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	CGA4DispClear	; 18: function - clear display
		dw	CGA4DispFill	; 20: function - fill text area
		dw	CGA4DispChar	; 22: function - display character
		dw	CGA4DispMove	; 24: function - move text area
		dw	CGA4DispShift	; 26: function - shift view vindow

	; --- 5: CGA graphics 320x200/4 gray (204 lines: 1 page + 4 lines)
		db	VMODE_FLAGS_CGA + VMODE_FLAGS_EGA + VMODE_FLAGS_VGA
		db	VMODE_MODEL_CG2	; 1: color model
		db	2		; 2: number of color bits
		db	0		; 3: default text mode
		db	40		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	80		; 6: bytes per row (text or graphics)
		dw	320		; 8: graphics width
		dw	200		; 10: graphics height
		dw	0b800h		; 12: videomemory segment
		dw	4000h/80-200	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	CGA4DispClear	; 18: function - clear display
		dw	CGA4DispFill	; 20: function - fill text area
		dw	CGA4DispChar	; 22: function - display character
		dw	CGA4DispMove	; 24: function - move text area
		dw	CGA4DispShift	; 26: function - shift view vindow

	; --- 6: CGA graphics 640x200/2 (204 lines: 1 page + 4 lines)
		db	VMODE_FLAGS_CGA + VMODE_FLAGS_EGA + VMODE_FLAGS_VGA
		db	VMODE_MODEL_CG1	; 1: color model
		db	1		; 2: number of color bits
		db	2		; 3: default text mode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	80		; 6: bytes per row (text or graphics)
		dw	640		; 8: graphics width
		dw	200		; 10: graphics height
		dw	0b800h		; 12: videomemory segment
		dw	4000h/80-200	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	CGA2DispClear	; 18: function - clear display
		dw	CGA2DispFill	; 20: function - fill text area
		dw	CGA2DispChar	; 22: function - display character
		dw	CGA2DispMove	; 24: function - move text area
		dw	CGA2DispShift	; 26: function - shift view vindow

	; --- 7: text 80 x 25 b&w (204 rows: 8 pages + 4 rows)
		db	VMODE_FLAGS_MDA + VMODE_FLAGS_EGA + VMODE_FLAGS_VGA
		db	VMODE_MODEL_TXT	; 1: color model
		db	1		; 2: number of color bits
		db	7		; 3: default text videomode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	2*80		; 6: bytes per row (text or graphics)
		dw	80		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b000h		; 12: videomemory segment
		dw	0		; 14: view window maximal shift
		dw	3b4h		; 16: control port
		dw	TXTDispClear	; 18: function - clear display
		dw	TXTDispFill	; 20: function - fill text area
		dw	TXTDispChar	; 22: function - display character
		dw	TXTDispMove	; 24: function - move text area
		dw	TXTDispShift	; 26: function - shift view vindow

	; --- 8: unsupported videomode
		db	0		; 0: flags
		db	VMODE_MODEL_NO	; 1: color model
		db	1		; 2: number of color bits
		db	3		; 3: default text videomode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	160		; 6: bytes per row (text or graphics)
		dw	80		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b000h		; 12: videomemory segment
		dw	0		; 14: view window maximal shift
		dw	3b4h		; 16: control port
		dw	DispEmptyFunc	; 18: function - clear display
		dw	DispEmptyFunc	; 20: function - fill text area
		dw	DispEmptyFunc	; 22: function - display character
		dw	DispEmptyFunc	; 24: function - move text area
		dw	DispEmptyFunc	; 26: function - shift view vindow

	; --- 9: unsupported videomode
		db	0		; 0: flags
		db	VMODE_MODEL_NO	; 1: color model
		db	1		; 2: number of color bits
		db	3		; 3: default text videomode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	160		; 6: bytes per row (text or graphics)
		dw	80		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b000h		; 12: videomemory segment
		dw	0		; 14: view window maximal shift
		dw	3b4h		; 16: control port
		dw	DispEmptyFunc	; 18: function - clear display
		dw	DispEmptyFunc	; 20: function - fill text area
		dw	DispEmptyFunc	; 22: function - display character
		dw	DispEmptyFunc	; 24: function - move text area
		dw	DispEmptyFunc	; 26: function - shift view vindow

	; --- 10: unsupported videomode
		db	0		; 0: flags
		db	VMODE_MODEL_NO	; 1: color model
		db	1		; 2: number of color bits
		db	3		; 3: default text videomode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	160		; 6: bytes per row (text or graphics)
		dw	80		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b000h		; 12: videomemory segment
		dw	0		; 14: view window maximal shift
		dw	3b4h		; 16: control port
		dw	DispEmptyFunc	; 18: function - clear display
		dw	DispEmptyFunc	; 20: function - fill text area
		dw	DispEmptyFunc	; 22: function - display character
		dw	DispEmptyFunc	; 24: function - move text area
		dw	DispEmptyFunc	; 26: function - shift view vindow

	; --- 11: unsupported videomode
		db	0		; 0: flags
		db	VMODE_MODEL_NO	; 1: color model
		db	1		; 2: number of color bits
		db	3		; 3: default text videomode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	160		; 6: bytes per row (text or graphics)
		dw	80		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b000h		; 12: videomemory segment
		dw	0		; 14: view window maximal shift
		dw	3b4h		; 16: control port
		dw	DispEmptyFunc	; 18: function - clear display
		dw	DispEmptyFunc	; 20: function - fill text area
		dw	DispEmptyFunc	; 22: function - display character
		dw	DispEmptyFunc	; 24: function - move text area
		dw	DispEmptyFunc	; 26: function - shift view vindow

	; --- 12: unsupported videomode
		db	0		; 0: flags
		db	VMODE_MODEL_NO	; 1: color model
		db	1		; 2: number of color bits
		db	3		; 3: default text videomode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	160		; 6: bytes per row (text or graphics)
		dw	80		; 8: graphics width
		dw	25		; 10: graphics height
		dw	0b000h		; 12: videomemory segment
		dw	0		; 14: view window maximal shift
		dw	3b4h		; 16: control port
		dw	DispEmptyFunc	; 18: function - clear display
		dw	DispEmptyFunc	; 20: function - fill text area
		dw	DispEmptyFunc	; 22: function - display character
		dw	DispEmptyFunc	; 24: function - move text area
		dw	DispEmptyFunc	; 26: function - shift view vindow

	; --- 13: EGA graphics 320x200/16 color (1638 lines:8 pages + 38 lines)
		db	VMODE_FLAGS_EGA + VMODE_FLAGS_VGA ; 0: flags
		db	VMODE_MODEL_EG4	; 1: color model
		db	4		; 2: number of color bits
		db	1		; 3: default text mode
		db	40		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	40		; 6: bytes per row (text or graphics)
		dw	320		; 8: graphics width
		dw	200		; 10: graphics height
		dw	0a000h		; 12: videomemory segment
		dw	0ffffh/40-200	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	EGADispClear	; 18: function - clear display
		dw	EGADispFill	; 20: function - fill text area
		dw	EGADispChar	; 22: function - display character
		dw	EGADispMove	; 24: function - move text area
		dw	EGADispShift	; 26: function - shift view vindow

	; --- 14: EGA graphics 640x200/16 color (819 lines:4 pages + 19 lines)
		db	VMODE_FLAGS_EGA + VMODE_FLAGS_VGA ; 0: flags
		db	VMODE_MODEL_EG4	; 1: color model
		db	4		; 2: number of color bits
		db	3		; 3: default text mode
		db	80		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	80		; 6: bytes per row (text or graphics)
		dw	640		; 8: graphics width
		dw	200		; 10: graphics height
		dw	0a000h		; 12: videomemory segment
		dw	0ffffh/80-200	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	EGADispClear	; 18: function - clear display
		dw	EGADispFill	; 20: function - fill text area
		dw	EGADispChar	; 22: function - display character
		dw	EGADispMove	; 24: function - move text area
		dw	EGADispShift	; 26: function - shift view vindow

	; --- 15: EGA graphics 640x350/b&w (819 lines:2 pages + 119 lines)
		db	VMODE_FLAGS_EGA + VMODE_FLAGS_VGA ; 0: flags
		db	VMODE_MODEL_EG1	; 1: color model
		db	3		; 2: number of color bits (3=B&W)
		db	7		; 3: default text mode
		db	80		; 4: number of text columns
		db	43		; 5: number of text rows
		dw	80		; 6: bytes per row (text or graphics)
		dw	640		; 8: graphics width
		dw	350		; 10: graphics height
		dw	0a000h		; 12: videomemory segment
		dw	0ffffh/80-350	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	EGADispClear	; 18: function - clear display
		dw	EGADispFill	; 20: function - fill text area
		dw	EGADispChar	; 22: function - display character
		dw	EGADispMove	; 24: function - move text area
		dw	EGADispShift	; 26: function - shift view vindow

	; --- 16: EGA graphics 640x350/16 color (819 lines:2 pages + 119 lines)
		db	VMODE_FLAGS_EGA + VMODE_FLAGS_VGA ; 0: flags
		db	VMODE_MODEL_EG4	; 1: color model
		db	4		; 2: number of color bits
		db	3		; 3: default text mode
		db	80		; 4: number of text columns
		db	43		; 5: number of text rows
		dw	80		; 6: bytes per row (text or graphics)
		dw	640		; 8: graphics width
		dw	350		; 10: graphics height
		dw	0a000h		; 12: videomemory segment
		dw	0ffffh/80-350	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	EGADispClear	; 18: function - clear display
		dw	EGADispFill	; 20: function - fill text area
		dw	EGADispChar	; 22: function - display character
		dw	EGADispMove	; 24: function - move text area
		dw	EGADispShift	; 26: function - shift view vindow

	; --- 17: EGA graphics 640x480/2 color (819 lines:1 page + 339 lines)
		db	VMODE_FLAGS_VGA	; 0: flags
		db	VMODE_MODEL_EG1	; 1: color model
		db	1		; 2: number of color bits
		db	2		; 3: default text mode
		db	80		; 4: number of text columns
		db	60		; 5: number of text rows
		dw	80		; 6: bytes per row (text or graphics)
		dw	640		; 8: graphics width
		dw	480		; 10: graphics height
		dw	0a000h		; 12: videomemory segment
		dw	0ffffh/80-480	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	EGADispClear	; 18: function - clear display
		dw	EGADispFill	; 20: function - fill text area
		dw	EGADispChar	; 22: function - display character
		dw	EGADispMove	; 24: function - move text area
		dw	EGADispShift	; 26: function - shift view vindow

	; --- 18: EGA graphics 640x480/16 color (819 lines:1 page + 339 lines)
		db	VMODE_FLAGS_VGA	; 0: flags
		db	VMODE_MODEL_EG4	; 1: color model
		db	4		; 2: number of color bits
		db	3		; 3: default text mode
		db	80		; 4: number of text columns
		db	60		; 5: number of text rows
		dw	80		; 6: bytes per row (text or graphics)
		dw	640		; 8: graphics width
		dw	480		; 10: graphics height
		dw	0a000h		; 12: videomemory segment
		dw	0ffffh/80-480	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	EGADispClear	; 18: function - clear display
		dw	EGADispFill	; 20: function - fill text area
		dw	EGADispChar	; 22: function - display character
		dw	EGADispMove	; 24: function - move text area
		dw	EGADispShift	; 26: function - shift view vindow

	; --- 19: VGA graphics 320x200/256 color (204 lines: 1 page + 4 line)
		db	VMODE_FLAGS_VGA	; 0: flags
		db	VMODE_MODEL_VGA	; 1: color model
		db	8		; 2: number of color bits
		db	1		; 3: default text mode
		db	40		; 4: number of text columns
		db	25		; 5: number of text rows
		dw	320		; 6: bytes per row (text or graphics)
		dw	320		; 8: graphics width
		dw	200		; 10: graphics height
		dw	0a000h		; 12: videomemory segment
		dw	0ffffh/320-200	; 14: view window maximal shift
		dw	3d4h		; 16: control port
		dw	VGADispClear	; 18: function - clear display
		dw	VGADispFill	; 20: function - fill text area
		dw	VGADispChar	; 22: function - display character
		dw	VGADispMove	; 24: function - move text area
		dw	VGADispShift	; 26: function - shift view vindow

; -----------------------------------------------------------------------------
;                            Uninitialised data
; -----------------------------------------------------------------------------

		DATA_SECTION

VideoCard:	resb	1		; type of videocard - number
VideoCardMask:	resb	1		; type of videocard - bit mask
VideoMode:	resb	1		; current videomode
DefColor:	resb	1		; default text color

; ------------- current videomode descriptor

		align	2, resb 1
VideoDesc:				; current descriptor
VideoFlags:	resb	1		; 0: videomode flags
VideoModel:	resb	1		; 1: color model
VideoColBits:	resb	1		; 2: number of color bits
VideoDefMode:	resb	1		; 3: default text videomode
VideoColsRows:
VideoCols:	resb	1		; 4: number of text columns
VideoRows:	resb	1		; 5: number of text rows
VideoScanLine:	resw	1		; 6: bytes per row (text or graphics)
VideoWidth:	resw	1		; 8: graphics width
VideoHeight:	resw	1		; 10: graphics height
VideoSegm:	resw	1		; 12: videomemory segment
VideoMaxShift:	resw	1		; 14: view window maximal shift
VideoPort:	resw	1		; 16: control port (3D4h or 3B4h)
VideoClearFnc:	resw	1		; 18: function - clear display
VideoFillFnc:	resw	1		; 20: function - fill text area
VideoCharFnc:	resw	1		; 22: function - display character
VideoMoveFnc:	resw	1		; 24: function - move text area
VideoShiftFnc:	resw	1		; 26: function - shift view vindow

VideoOff:	resw	1		; memory offset of displayed page
PageRow:	resw	1		; current row of displayed page

; ------------- cursor position

		align	2, resb 1
CursorPos:
CursorCol:	resb	1		; column with cursor
CursorRow:	resb	1		; row with cursor

CursorSize:
CursorSizeB:	resb	1		; cursor size - bottom line
CursorSizeT:	resb	1		; cursor size - top line
