Tvùrce webu je i pro tebe! Postav tøeba web. Bez grafika. Bez kodéra. Hned.
wz

TXT.ASM

TXT Display


; =============================================================================
;
;                             Litos - TXT display
;
; =============================================================================

		CODE_SECTION	32

; -----------------------------------------------------------------------------
;                        Enumerate standard videomodes
; -----------------------------------------------------------------------------
; INPUT:	EAX = index (0..., -1 = get max. index)
;		EBX = display driver
;		EDX = videomode structure VMODE (NULL=not used)
; OUTPUT:	CY = invalid index (EAX = maximum index)
;		NC = videomode is valid (EDX structure is filled-up)
;		EAX = index or maximum index (in case of error)
; NOTES: Structure VMODE (EDX) will be filled-up (if EDX is not NULL).
;	 This function enumerates only recommended standard videomodes.
; -----------------------------------------------------------------------------

TXTEnumMode:	ret

; -----------------------------------------------------------------------------
;                             Test videomode
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver
;		EDX = videomode structure VMODE (full dimension, display
;			dimension, font dimension, frequency and memory mode
;			entries can be set or 0 = auto)
; OUTPUT:	CY = invalid videomode
;		NC = videomode is valid (EDX structure is filled-up)
; -----------------------------------------------------------------------------

TXTTestMode:	ret

; -----------------------------------------------------------------------------
;                                Set videomode
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver
;		EDX = videomode structure VMODE (full dimension, display
;			dimension, font dimension, frequency and memory mode
;			entries can be set or 0 = auto)
; OUTPUT:	CY = invalid videomode
;		NC = videomode is valid and set (EDX structure is filled-up)
; -----------------------------------------------------------------------------

TXTSetMode:	ret

; -----------------------------------------------------------------------------
;                         Clear screen and reset cursor
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver
; NOTES:	It clears entire screen, sets offset to 0 and resets cursor.
; -----------------------------------------------------------------------------

; ------------- Push registers

TXTClear:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edi		; push EDI

; ------------- Clear videomemory

		mov	edi,[ebx+DDPB_BaseAddr] ; EDI <- base address
		mov	ecx,[ebx+DDPB_MemSize] ; ECX <- size of videomemory
		shr	ecx,1		; ECX <- size in characters
		shr	ecx,1		; ECX <- size in double characters
		mov	eax,7200720h	; EAX <- clearing pattern
		rep	stosd		; clear videomemory

; ------------- Set display offset

		xor	ecx,ecx		; ECX <- 0
		xor	edx,edx		; EDX <- 0
		call	TXTSetOffset	; set display offset

; ------------- Set cursor position

		call	TXTSetCursor	; set cursor position

; ------------- Set cursor size

		mov	edx,[ebx+DDPB_FontH] ; EDX <- font height
		dec	edx		; EDX <- last scan line
		mov	ecx,edx		; ECX <- last scan line
		dec	ecx		; ECX <- previous scan line
		call	TXTSetCurSize	; set cursor size

; ------------- Set cursor on

		mov	al,1		; AL <- 1, cursor on
		call	TXTSetVisible	; set cursor on

; ------------- Pop registers

		pop	edi		; pop EDI
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                            Set display offset
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver
;		ECX = X coordinate of visible region of display
;		EDX = Y coordinate of visible region of display
; -----------------------------------------------------------------------------

; ------------- Check if offset changed

TXTSetOffset:	cmp	ecx,[ebx+DDPB_OffX] ; check offset X
		jne	TXTSetOffset2	; offset changed
		cmp	edx,[ebx+DDPB_OffY] ; check offset Y
		je	TXTSetOffset8	; offset not changed

; ------------- Push registers

TXTSetOffset2:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Correct cursor position X

		mov	eax,ecx		; EAX <- offset X
		sub	eax,[ebx+DDPB_OffX] ; EAX <- shift X
		sub	[ebx+DDPB_CurPosX],eax ; correct cursor X

; ------------- Correct cursor position Y

		mov	eax,edx		; EAX <- offset Y
		sub	eax,[ebx+DDPB_OffY] ; EAX <- shift Y
		sub	[ebx+DDPB_CurPosY],eax ; correct cursor Y

; ------------- Store new offset

		mov	[ebx+DDPB_OffX],ecx ; new offset X
		mov	[ebx+DDPB_OffY],edx ; new offset Y

; ------------- Calculate new offset (-> EAX)

		mov	eax,[ebx+DDPB_VirtW] ; EAX <- characters per row
		mul	edx		; recalc Y offset to characters
		add	eax,ecx		; EAX <- add X coordinate

; ------------- Set new display offset

		mov	cl,12		; CL <- register number
		call	DispOutWord	; set memory offset

; ------------- Calculate new memory address

		shl	eax,1		; EAX <- offset in videomemory
		add	eax,[ebx+DDPB_BaseAddr] ; EAX <- address in memory
		mov	[ebx+DDPB_Addr],eax ; store new memory address

; ------------- Pop registers

		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
TXTSetOffset8:	ret

; -----------------------------------------------------------------------------
;                            Set cursor position
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver
;		ECX = cursor column
;		EDX = cursor row
; -----------------------------------------------------------------------------

; ------------- Check if cursor position changed

TXTSetCursor:	cmp	ecx,[ebx+DDPB_CurPosX] ; check cursor column
		jne	TXTSetCursor2	; cursor changed
		cmp	edx,[ebx+DDPB_CurPosY] ; check cursor row
		je	TXTSetCursor8	; cors not changed

; ------------- Push registers

TXTSetCursor2:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Store new cursor position

		mov	[ebx+DDPB_CurPosX],ecx ; new cursor position X
		mov	[ebx+DDPB_CurPosY],edx ; new cursor position Y

; ------------- Calculate cursor offset

		mov	eax,[ebx+DDPB_VirtW] ; EAX <- characters per row
		mul	edx		; recalc Y offset to characters
		add	eax,ecx		; EAX <- add X coordinate

; ------------- Set new cursor offset

		mov	cl,14		; CL <- register number
		call	DispOutWord	; set memory offset

; ------------- Pop registers

		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
TXTSetCursor8:	ret

; -----------------------------------------------------------------------------
;                             Set cursor size
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver
;		ECX = top scan line
;		EDX = bottom scan line
; -----------------------------------------------------------------------------

; ------------- Check if cursor size changed

TXTSetCurSize:	cmp	ecx,[ebx+DDPB_CurSizeT] ; check top scan line
		jne	TXTSetCurSize2	; cursor size changed
		cmp	edx,[ebx+DDPB_CurSizeB] ; check bottom scan line
		je	TXTSetCurSize8	; cursor size not changed

; ------------- Store new cursor size

TXTSetCurSize2:	mov	[ebx+DDPB_CurSizeT],ecx ; store top scan line
		mov	[ebx+DDPB_CurSizeB],edx ; store bottom scan line

; ------------- Check if cursor is off

		test	byte [ebx+DDPB_Flags],DDPB_CURON ; is cursor on?
		jz	TXTSetCurSize8	; cursor is off

; ------------- Push registers

		push	eax		; push EAX
		push	ecx		; push ECX

; ------------- Set new cursor size

		mov	al,dl		; AL <- bottom scan line
		mov	ah,cl		; AH <- top scan line
		mov	cl,10		; CL <- register of cursor size
		call	DispOutWord	; set cursor size

; ------------- Pop registers

		pop	ecx		; pop ECX
		pop	eax		; pop EAX
TXTSetCurSize8:	ret

; -----------------------------------------------------------------------------
;                            Set cursor visible
; -----------------------------------------------------------------------------
; INPUT:	AL = 0 cursor off, 1 cursor on, 2 flip state
;		EBX = display driver
; -----------------------------------------------------------------------------

; ------------- Push registers

TXTSetVisible:	push	eax		; push EAX
		push	ecx		; push ECX

; ------------- Check if cursor state changed

		test	byte [ebx+DDPB_Flags],DDPB_CURON ; is cursor ON?
		setnz	ah		; AH <- 1 cursor on, AL <- cursor off
		cmp	al,ah		; cursor state changed?
		je	TXTSetVisible8	; cursor state not changed

; ------------- Change flag of cursor visibility

		xor	byte [ebx+DDPB_Flags],DDPB_CURON ; change flag

; ------------- Set new cursor state

		or	ah,ah		; was cursor on?
		mov	ax,2020h	; AX <- size of cursor off
		jnz	TXTSetVisible4	; cursor was on		
		mov	al,[ebx+DDPB_CurSizeB] ; AL <- bottom scan line
		mov	ah,[ebx+DDPB_CurSizeT] ; AH <- top scan line
TXTSetVisible4:	mov	cl,10		; CL <- register of cursor size
		call	DispOutWord	; set cursor size

; ------------- Pop registers

TXTSetVisible8:	pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                             Load text font
; -----------------------------------------------------------------------------
; INPUT:	AL = font bank (0..3 for EGA, 0..7 for VGA)
;		AH = font height (1..32, 0=default)
;		EBX = display driver
;		CL = first index (0..255)
;		DL = last index (0..255, must not be lesser than first index)
;		ESI = pointer to font (character with start index)
; -----------------------------------------------------------------------------

TXTLoadFont:	ret

; -----------------------------------------------------------------------------
;                            Set font bank
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver
;		CL = font bank for color attribute bit 3 = 0 (0..3 or 0..7)
;		DL = font bank for color attribute bit 3 = 1 (0..3 or 0..7)
; -----------------------------------------------------------------------------

TXTSetFont:	ret

; -----------------------------------------------------------------------------
;                             Set border color
; -----------------------------------------------------------------------------
; INPUT:	AL = border color (0..15 for 16-color or 0..255 for 256-color)
;		EBX = display driver
; -----------------------------------------------------------------------------

TXTSetBorder:	ret

; -----------------------------------------------------------------------------
;                      Set CGA palette (only CGA videomode)
; -----------------------------------------------------------------------------
; INPUT:	AL = palette set (0=red/green/yellow, 1=cyan/magenta/white)
;		EBX = display driver
; -----------------------------------------------------------------------------

TXTSetPalCGA:	ret

; -----------------------------------------------------------------------------
;                              Set EGA palette
; -----------------------------------------------------------------------------
; INPUT:	AL = start index (0..16, last entry is border color)
;		EBX = display driver
;		CL = stop index (0..16)
;		EDX = pointer to EGA palette (palette entry with start index)
; NOTES: EGA palettes are array of 17 bytes: B0 blue 2/3, B1 green 2/3,
;	 B2 red 2/3, B3 blue 1/3, B4 green 1/3, B5 red 1/3. Last palette entry
;	 (index 16) is border color. On VGA card EGA palette is index into
;	 VGA palette table indexed 64 to 127.
; -----------------------------------------------------------------------------

TXTSetPalEGA:	ret

; -----------------------------------------------------------------------------
;                              Set VGA palette
; -----------------------------------------------------------------------------
; INPUT:	AL = start index (0..255)
;		EBX = display driver
;		CL = stop index (0..255)
;		EDX = pointer to VGA palette (palette entry with start index)
; NOTES: VGA palettes are array of byte triples: red, green and blue color
;	 components with range 0 to 63.
; -----------------------------------------------------------------------------

TXTSetPalVGA:	ret

; -----------------------------------------------------------------------------
;                              Set indexed palette
; -----------------------------------------------------------------------------
; INPUT:	EAX = index table (array of bytes with value 0 to 255)
;		EBX = display driver
;		ECX = number of color entries (1 to 255)
;		EDX = pointer to VGA palette
; NOTES: VGA palettes are array of byte triples: red, green and blue color
;	 components with range 0 to 63.
; -----------------------------------------------------------------------------

TXTSetPalInx:	ret

; -----------------------------------------------------------------------------
;                              Fill-up region
; -----------------------------------------------------------------------------
; INPUT:	AL = color (in graphics mode) or character (in text mode)
;		AH = color attribute (only in text mode)
;		EBX = display driver
;		ECX = region width
;		EDX = region height
;		ESI = region left margin (in display area)
;		EDI = region top margin (in display area)
; NOTES: Parameters are not checked and can be used to fill-up hide regions.
; -----------------------------------------------------------------------------

TXTFillUp:	ret

; -----------------------------------------------------------------------------
;                               Move region
; -----------------------------------------------------------------------------
; INPUT:	EAX = destination offset in videomemory
;		EBX = display driver
;		ECX = region width
;		EDX = region height
;		ESI = region left margin (in display area)
;		EDI = region top margin (in display area)
; NOTES: Parameters are not checked and can be used to move in invisible area.
; -----------------------------------------------------------------------------

TXTMove:	ret

; -----------------------------------------------------------------------------
;                               Get buffer size
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver
;		ECX = region width
;		EDX = region height
; OUTPUT:	EAX = buffer size
; -----------------------------------------------------------------------------

TXTBufferSize:	ret

; -----------------------------------------------------------------------------
;                                 Get region
; -----------------------------------------------------------------------------
; INPUT:	EAX = destination buffer
;		EBX = display driver
;		ECX = region width
;		EDX = region height
;		ESI = region left margin (in display area)
;		EDI = region top margin (in display area)
; NOTES: Parameters are not checked and can be used to get hide regions.
; -----------------------------------------------------------------------------

TXTGetRegion:	ret

; -----------------------------------------------------------------------------
;                                 Set region
; -----------------------------------------------------------------------------
; INPUT:	EAX = source buffer
;		EBX = display driver
;		ECX = region width
;		EDX = region height
;		ESI = region left margin (in display area)
;		EDI = region top margin (in display area)
; NOTES: Parameters are not checked and can be used to set hide regions.
; -----------------------------------------------------------------------------

TXTSetRegion:	ret

; -----------------------------------------------------------------------------
;                        Set text region with color
; -----------------------------------------------------------------------------
; INPUT:	EAX = source buffer (only characters without attributes)
;		EBX = display driver
;		ECX = region width
;		EDX = region height
;		ESI = region left margin (in display area)
;		EDI = region top margin (in display area)
;		EBP = color attribute
; NOTES: Parameters are not checked and can be used to set hide regions.
; -----------------------------------------------------------------------------

TXTSetRegCol:	ret

; -----------------------------------------------------------------------------
;                         Set region with color mask
; -----------------------------------------------------------------------------
; INPUT:	EAX = source buffer
;		EBX = display driver
;		ECX = region width
;		EDX = region height
;		ESI = region left margin (in display area)
;		EDI = region top margin (in display area)
;		EBP = transparent color
; NOTES: Parameters are not checked and can be used to set hide regions.
; -----------------------------------------------------------------------------

TXTSetColMask:	ret

; -----------------------------------------------------------------------------
;                            Set region with mask
; -----------------------------------------------------------------------------
; INPUT:	EAX = source buffer with data and bit mask
;		EBX = display driver
;		ECX = region width
;		EDX = region height
;		ESI = region left margin (in display area)
;		EDI = region top margin (in display area)
; NOTES: Parameters are not checked and can be used to set hide regions.
;	 Bit mask follow after region data, one bit = 1 if point is visible.
; -----------------------------------------------------------------------------

TXTSetMasked:	ret

; -----------------------------------------------------------------------------
;                            Set region with alpha
; -----------------------------------------------------------------------------
; INPUT:	EAX = source buffer with data and alpha
;		EBX = display driver
;		ECX = region width
;		EDX = region height
;		ESI = region left margin (in display area)
;		EDI = region top margin (in display area)
; NOTES: Parameters are not checked and can be used to set hide regions.
;	 Alpha is array of bytes in range 0 (transparent) to 255 (opaque).
; -----------------------------------------------------------------------------

TXTSetAlpha:	ret







%ifdef AAAA

; -----------------------------------------------------------------------------
;                      Initialize driver parameter block
; -----------------------------------------------------------------------------

; ------------- Driver pointer

TXTInit:	mov	ebx,TXTDrvDDPB	; EBX <- driver parameter block

; ------------- Addresses

		movzx	eax,word [VideoSegm] ; video segment
		shl	eax,4		; transfer segment to address
		add	eax,SYSTEM_ADDR	; + system address
		mov	[ebx+DDPB_Addr],eax ; virtual address
		mov	[TXTDrvDDPB2+RES_Start],eax ; start address

; ------------- Control port

		mov	eax,3b4h	; EAX <- video port for MDA
		cmp	byte [VideoSegm+1],0b0h ; MDA videomode?
		je	TXTInit2	; MDA videomode
		mov	al,0d4h		; EAX <- video port for CGA
TXTInit2:	mov	[ebx+DDPB_Port],eax ; control port

; ------------- Display dimension

		movzx	eax,byte [VideoCols] ; EAX <- number of columns
		mov	[ebx+DDPB_Dim+DIM_W],eax ; number of columns
		shl	eax,1		; EAX <- number of columns * 2
		mov	[ebx+DDPB_RowBytes],eax ; lenght of row in bytes
		movzx	eax,byte [VideoRows] ; EDX <- number of rows
		mov	[ebx+DDPB_Dim+DIM_H],eax ; number of rows

; ------------- Cursor position

		movzx	eax,byte [VideoPos] ; EAX <- current position
		mov	[ebx+DDPB_CurPos+POS_X],eax ; cursor position
		movzx	eax,byte [VideoRow] ; EAX <- current row
		mov	[ebx+DDPB_CurPos+POS_Y],eax ; cursor row

; ------------- Current color

		mov	al,[VideoCol]	; AL <- current color
		mov	[ebx+DDPB_Color],al ; current color

; ------------- Install driver

		call	DrvLstInsert	; insert driver into list
		ret

; -----------------------------------------------------------------------------
;                             Get information
; -----------------------------------------------------------------------------
; INPUT:	AL = info code
;		EBX = display driver parameter block
; OUTPUT:	EAX = info value
; -----------------------------------------------------------------------------

; ------------- Jump to service

TXTInfo:	cmp	al,DCHOUT_GETMAX ; check maximal information code
		jae	TXTInfoErr	; error
		movzx	eax,al		; EAX <- info code
		shl	eax,2		; EAX <- offset in jump table
		add	eax,[ebx+DDPB_InfoTab] ; EAX <- jump address
		jmp	dword [eax]	; jump to service

; ------------- Get interface version

TXTGetVer:	mov	al,0
TXTInfoErr:	ret

; ------------- Get window width

TXTGetW:	mov	eax,[ebx+DDPB_Dim+DIM_W] ; EAX <- display width
		ret

; ------------- Get window height

TXTGetH:	mov	eax,[ebx+DDPB_Dim+DIM_H] ; EAX <- display height
		ret

; ------------- Get cursor position X

TXTGetCurX:	mov	eax,[ebx+DDPB_CurPos+POS_X] ; EAX <- cursor position X
		ret

; ------------- Get cursor position Y

TXTGetCurY:	mov	eax,[ebx+DDPB_CurPos+POS_Y] ; EAX <- cursor position Y
		ret

; ------------- Get cursor "on" flag (1=on, 0=off)

TXTGetCurON:	test	byte [ebx+DDPB_Flags],DDPB_CURSON ; test cursor on flag
		setnz	al		; EAX <- 1 if flag is on
		ret

; ------------- Get cursor "update" flag (1=on,0=off)

TXTGetUpd:	test	byte [ebx+DDPB_Flags],DDPB_CURSUPD ; test update flag
		setnz	al		; EAX <- 1 if flag is on
		ret

; ------------- Get line height

TXTGetSizH:	movzx	eax,byte [ebx+DDPB_LineH] ; EAX <- line height
		ret

; ------------- Get cursor top scan line

TXTGetSizT:	movzx	eax,byte [ebx+DDPB_CurSizeT] ; EAX <- cursor top line
		ret

; ------------- Get cursor bottom scan line

TXTGetSizB:	movzx	eax,byte [ebx+DDPB_CurSizeB] ; EAX<-cursor bottom line
		ret

; ------------- Get color

TXTGetColor:	movzx	eax,byte [ebx+DDPB_Color] ; EAX <- color
		ret

; -----------------------------------------------------------------------------
;                              Setup display
; -----------------------------------------------------------------------------
; INPUT:	AL = setup code
;		EBX = display driver parameter block
;		ECX = parameter 1
;		EDX = parameter 2
; OUTPUT:	CY = error, only for test/set window dimension
; -----------------------------------------------------------------------------

; ------------- Jump to service

TXTSetup:	push	eax		; push EAX
		cmp	al,DCHOUT_SETMAX ; check maximal setup code
		jae	short TXTSetupErr ; error
		movzx	eax,al		; EAX <- setup code
		shl	eax,2		; EAX <- offset in jump table
		add	eax,[ebx+DDPB_SetupTab] ; EAX <- jump address
		mov	eax,[eax]	; EAX <- jump address
		xchg	eax,[esp]	; [ESP] <- jump, EAX <- pop EAX
		ret			; jump to service

TXTSetupErr:	pop	eax		; pop EAX
TXTSetupRet:	ret

; ------------- Test window dimension (ECX, EDX)

TXTSetTest: 
; !!! TODO
	  	stc			; set error flag
		ret

; ------------- Set new window dimension (ECX, EDX)

TXTSetResize:
; !!! TODO
	  	stc			; set error flag
		ret

; ------------- Set cursor on

TXTCurOn:	bts	dword [ebx+DDPB_Flags],DDPB_CURSON_BIT ; cursor is on?
		jnc	short TXTCurSizeUpd ; update cursor size
		ret

; ------------- Set cursor off

TXTCurOff:	btr	dword [ebx+DDPB_Flags],DDPB_CURSON_BIT ; cursor is off?
		jc	short TXTCurSizeUpd ; update cursor size
		ret

; ------------- Set cursor update on

TXTUpdOn:	bts	dword [ebx+DDPB_Flags],DDPB_CURSUP_BIT ; update is on?
		jnc	short TXTSetCur4 ; update cursor position
		ret

; ------------- Set cursor update off

TXTUpdOff:	and	byte [ebx+DDPB_Flags],~DDPB_CURSUPD ; set update off
		ret

; ------------- Set cursor size (CL top, DL bottom)

TXTSetSize	mov	[ebx+DDPB_CurSizeT],cl ; set top scan line
		mov	[ebx+DDPB_CurSizeB],dl ; set bottom scan line

; TXTCurSizeUpd must follow

; -----------------------------------------------------------------------------
;                            Update cursor size
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver parameter block
; NOTES: If start is greater than end, cursor will be disabled.
; -----------------------------------------------------------------------------
; It must follow after TXTSetSize

; ------------- Push registers

TXTCurSizeUpd: 	push	eax		; push EAX
		push	ecx		; push ECX

; ------------- Check if cursor is off

		test	byte [ebx+DDPB_Flags],DDPB_CURSON ; cursor is on?
		jz	TXTCurSizeUpd2	; cursor is on		

; ------------- Get cursor size

		mov	ax,[ebx+DDPB_CurSize] ; AL <- bottom, AH <- top line

; ------------- Cursor off

		cmp	al,ah		; start is greater than end?
		jae	TXTCurSizeUpd4	; cursor is OK
TXTCurSizeUpd2:	mov	ax,2020h	; MDA flag - cursor is off

; ------------- Set cursor address

TXTCurSizeUpd4:	mov	cl,10		; CL <- register of cursor size
		call	DispOutWordLock	; set cursor address

; ------------- Pop registers

		pop	ecx		; pop ECX
		pop	eax		; pop EAX
TXTSetCur6:	ret

; -----------------------------------------------------------------------------
;                         Set cursor position
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver parameter block
;		ECX = cursor column
;		EDX = cursor row
; -----------------------------------------------------------------------------

; ------------- Check if cursor position changed

TXTSetCur:	cmp	ecx,[ebx+DDPB_CurPos+POS_X] ; check cursor column
		jne	short TXTSetCur2 ; cursor changed
		cmp	edx,[ebx+DDPB_CurPos+POS_Y] ; check cursor row
		je	short TXTSetCur6 ; cursor not changed

; ------------- Set new cursor position

TXTSetCur2:	mov	[ebx+DDPB_CurPos+POS_X],ecx ; set cursor column
		mov	[ebx+DDPB_CurPos+POS_Y],edx ; set cursor row
TXTSetCur4:	jmp	TXTCurUpdate	; update cursor position

; -----------------------------------------------------------------------------
;                                 Set color
; -----------------------------------------------------------------------------
; INPUT:	AL = color
;		EBX = display driver parameter block
; -----------------------------------------------------------------------------

TXTSetColor:	mov	[ebx+DDPB_Color],al ; set color
		ret

; -----------------------------------------------------------------------------
;                            Write one character
; -----------------------------------------------------------------------------
; INPUT:	AL = character
;		EBX = display driver parameter block
; -----------------------------------------------------------------------------

; ------------- Push registers

TXTWriteChr:	push	eax		; push EAX
		push	edx		; push EDX
		push	edi		; push EDI
		xchg	eax,edi		; EDI <- push EAX

; ------------- Get current row (-> EAX)

		mov	eax,[ebx+DDPB_CurPos+POS_Y] ; EAX <- current row
		cmp	eax,[ebx+DDPB_Dim+DIM_H] ; check row
		jae	TXTWriteChr4	; invalid row
		mul	dword [ebx+DDPB_RowBytes] ; EAX <- recalc row to bytes

; ------------- Get current column (-> EDX)

		mov	edx,[ebx+DDPB_CurPos+POS_X] ; EDX <- current column
		cmp	edx,[ebx+DDPB_Dim+DIM_W] ; check column
		jae	TXTWriteChr4	; invalid column

; ------------- Calculate address in videomemory (-> EDI)

		shl	edx,1		; EDX <- recalc column to bytes
		add	eax,edx		; EAX <- offset in videomemory
		add	eax,[ebx+DDPB_Addr] ; EAX <- address
		xchg	eax,edi		; EDI <- address, AL <- character

; ------------- Store character into videomemory
	
		mov	ah,[ebx+DDPB_Color] ; AH <- color of text
		stosw			; store character into videomemory

; ------------- Pop registers

TXTWriteChr4:	pop	edi		; pop EDI
		pop	edx		; pop EDX
		pop	eax		; pop EAX

; ------------- Shift cursor position

		inc	dword [ebx+DDPB_CurPos+POS_X] ; increase column

; TXTCurUpdate must follow.

; -----------------------------------------------------------------------------
;                              Update cursor
; -----------------------------------------------------------------------------
; NOTES: Cursor can be moved into invalid position (it is not checked).
; -----------------------------------------------------------------------------
; It must follow after TXTWriteChr.

; ------------- Check if auto update cursor position

TXTCurUpdate:	test	byte [ebx+DDPB_Flags],DDPB_CURSUPD ; update cursor?
		jz	TXTCurUpdate8	; don't update cursor

; ------------- Push registers

		push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Set cursor position

		mov	eax,[ebx+DDPB_CurPos+POS_Y] ; EAX <- current row
		mul	dword [ebx+DDPB_RowBytes] ; EAX <- recalc row to bytes
		shr	eax,1		; EAX <- offset of row
		add	eax,[ebx+DDPB_CurPos+POS_X] ; add current column
		mov	cl,14		; CL <- register of cursor address
		call	DispOutWordLock	; set cursor address

; ------------- Pop registers

		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
TXTCurUpdate8:	ret

; -----------------------------------------------------------------------------
;                               Write text string
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver parameter block
;		ECX = length of the text
;		EDX = text to display
; -----------------------------------------------------------------------------

; ------------- Push registers

TXTWriteStr:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX
		push	esi		; push ESI
		push	edi		; push EDI
		mov	esi,edx		; ESI <- text to display

; ------------- Get current row (-> EAX)

		mov	eax,[ebx+DDPB_CurPos+POS_Y] ; EAX <- current row
		cmp	eax,[ebx+DDPB_Dim+DIM_H] ; check row
		jae	TXTWriteStr8	; invalid row
		mul	dword [ebx+DDPB_RowBytes] ; EAX <- recalc row to bytes

; ------------- Get current column (-> EDX) and limit text length (-> ECX)

		mov	edi,[ebx+DDPB_Dim+DIM_W] ; EDI <- display width
		mov	edx,[ebx+DDPB_CurPos+POS_X] ; EDX <- current column
		or	edx,edx		; is position positive?
		js	short TXTWriteStr8 ; negative position is invalid
		sub	edi,edx		; EDI <- remaining columns
		cmp	edi,ecx		; check length of text
		jg	TXTWriteStr2	; text length is OK
		mov	ecx,edi		; ECX <- limit text length
TXTWriteStr2:	or	ecx,ecx		; check length of text
		jle	TXTWriteStr8	; invalid length of text

; ------------- Calculate address in videomemory (-> EDI)

		shl	edx,1		; EDX <- recalc column to bytes
		add	eax,edx		; EAX <- offset in videomemory
		add	eax,[ebx+DDPB_Addr] ; EAX <- address
		xchg	eax,edi		; EDI <- address

; ------------- Move text into videomemory
	
		mov	ah,[ebx+DDPB_Color] ; AH <- color of text
TXTWriteStr4:	lodsb			; load character
		stosw			; store character into videomemory
		loop	TXTWriteStr4	; next character

; ------------- Pop registers

TXTWriteStr8:	pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX

; ------------- Shift cursor position

		add	dword [ebx+DDPB_CurPos+POS_X],ecx ; increase column
		jmp	short TXTCurUpdate ; update cursor

; -----------------------------------------------------------------------------
;                     Fill-up region (from cursor position)
; -----------------------------------------------------------------------------
; INPUT:	AL = character
;		EBX = display driver parameter block
;		ECX = width of region
;		EDX = height of region
; -----------------------------------------------------------------------------

; ------------- Push registers

TXTFillUp:	pusha			; push all registers
		mov	esi,edx		; ESI <- height of region
		xchg	eax,edi		; EDI <- character

; ------------- Get current row (-> EAX) and limit height (-> ESI)

		mov	ebp,[ebx+DDPB_Dim+DIM_H] ; EBP <- display height
		mov	eax,[ebx+DDPB_CurPos+POS_Y] ; EAX <- current row
		or	eax,eax		; is row positive?
		js	short TXTFillUp6 ; negative row is invalid
		sub	ebp,eax		; EBP <- remaining rows
		cmp	ebp,esi		; check height of region
		jg	short TXTFillUp2 ; height is OK
		mov	esi,ebp		; ESI <- limit height of region
TXTFillUp2:	or	esi,esi		; check height of region
		jle	short TXTFillUp9 ; invalid height of region
		mul	dword [ebx+DDPB_RowBytes] ; EAX <- recalc row to bytes

; ------------- Get current column (-> EDX) and limit width (-> ECX)

		mov	ebp,[ebx+DDPB_Dim+DIM_W] ; EBP <- display width
		mov	edx,[ebx+DDPB_CurPos+POS_X] ; EDX <- current column
		or	edx,edx		; is position positive?
		js	short TXTFillUp9 ; negative position is invalid
		sub	ebp,edx		; EBP <- remaining columns
		cmp	ebp,ecx		; check width of region
		jg	short TXTFillUp3 ; width of region is OK
		mov	ecx,ebp		; ECX <- limit width of region
TXTFillUp3:	or	ecx,ecx		; check width of region
		jle	short TXTFillUp9 ; invalid width of region

; ------------- Calculate address in videomemory (-> EDI)

		shl	edx,1		; EDX <- recalc column to bytes
		add	eax,edx		; EAX <- offset in videomemory
		add	eax,[ebx+DDPB_Addr] ; EAX <- address
		xchg	eax,edi		; EDI <- address, AL <- character

; ------------- Prepare registers
	
		movzx	eax,al		; EAX <- character
		mov	ah,[ebx+DDPB_Color] ; AH <- color of text
		mov	edx,[ebx+DDPB_RowBytes] ; EDX <- bytes per row
		sub	edx,ecx		; subtract number of characters
		sub	edx,ecx		; EDX <- address increment

; ------------- Check if it is vertical line (width = 1)

		cmp	ecx,byte 1	; width of region = 1?
		je	short TXTFillUp8 ; fill-up vertical line

; ------------- Prepare double-character (-> EAX)

		mov	ebp,eax		; EBP <- character
		shl	eax,16		; EAX <- character * 16
		or	eax,ebp		; EAX <- 2 characters

; ------------- Check width of region

		mov	ebp,ecx		; EBP <- number of characters
		shr	ebp,1		; EBP <- characters / 2
		jnc	short TXTFillUp7 ; even characters

; ------------- Check odd/even address

		bt	edi,1		; odd address?
		jnc	short TXTFillUp5 ; even address

; ------------- Fill-up region with odd characters and odd address

TXTFillUp4:	mov	ecx,ebp		; ECX <- number of characters/2
		stosw			; fill-up odd character
		rep	stosd		; fill-up one row
		add	edi,edx		; EDI <- next row
		dec	esi		; count height of region
		jnz	short TXTFillUp4 ; next row
		popa			; pop all registesr
		ret

; ------------- Fill-up region with odd characters and even address

TXTFillUp5:	mov	ecx,ebp		; ECX <- number of characters/2
		rep	stosd		; fill-up one row
		stosw			; fill-up odd character
		add	edi,edx		; EDI <- next row
		dec	esi		; count height of region
		jnz	short TXTFillUp5 ; next row
TXTFillUp6:	popa			; pop all registesr
		ret

; ------------- Fill-up region with even characters

TXTFillUp7:	mov	ecx,ebp		; ECX <- number of characters/2
		rep	stosd		; fill-up one row
		add	edi,edx		; EDI <- next row
		dec	esi		; count height of region
		jnz	short TXTFillUp7 ; next row
		popa			; pop all registesr
		ret

; ------------- Fill-up vertical line

TXTFillUp8:	stosw			; store one character
		add	edi,edx		; EDI <- next row
		dec	esi		; count height of region
		jnz	short TXTFillUp8 ; next row

; ------------- Pop registers

TXTFillUp9:	popa			; pop all registesr
		ret

; -----------------------------------------------------------------------------
;                     Copy region (into cursor position)
; -----------------------------------------------------------------------------
; INPUT:	EAX = source column
;		EBX = display driver parameter block
;		ECX = width of region
;		EDX = height of region
;		ESI = source row
; -----------------------------------------------------------------------------

; ------------- Push registers

TXTCopy:	pusha			; push all registers

; ------------- Limit width of region from source column (-> ECX)

		or	eax,eax		; check source column
		js	short TXTCopy6	; source column is not valid
		mov	ebp,[ebx+DDPB_Dim+DIM_W] ; EBP <- display width
		sub	ebp,eax		; EBP <- remaining columns
		cmp	ebp,ecx		; check width of region
		jg	short TXTCopy1	; width of region is OK
		mov	ecx,ebp		; ECX <- limit width of region

; ------------- Limit height of region from source row (-> EBP)

TXTCopy1:	or	esi,esi		; check source row
		js	short TXTCopy6	; source row is not valid
		mov	ebp,[ebx+DDPB_Dim+DIM_H] ; EBP <- display height
		sub	ebp,esi		; EBP <- remaining rows
		cmp	ebp,edx		; check height of region
		jl	short TXTCopy2	; limit height of region
		mov	ebp,edx		; EBP <- height of region is OK

; ------------- Calculate source address (-> ESI)

TXTCopy2:	shl	eax,1		; EAX <- recalc column to bytes
		xchg	eax,esi		; EAX <- source row, ESI <- column*2
		mul	dword [ebx+DDPB_RowBytes] ; EAX <- recalc row to bytes
		add	esi,eax		; ESI <- offset in videomemory
		add	esi,[ebx+DDPB_Addr] ; ESI <- source address

; ------------- Get destination row (-> EAX) and limit height (-> EBP)

		mov	edx,[ebx+DDPB_Dim+DIM_H] ; EDX <- display height
		mov	eax,[ebx+DDPB_CurPos+POS_Y] ; EAX <- current row
		or	eax,eax		; check destination row
		js	short TXTCopy6	; destination row is not valid
		sub	edx,eax		; EDX <- remaining rows
		cmp	edx,ebp		; check height of region
		jg	short TXTCopy3	; height is OK
		mov	ebp,edx		; EBP <- limit height of region
TXTCopy3:	or	ebp,ebp		; check height of region
		jle	short TXTCopy6	; invalid height of region
		mul	dword [ebx+DDPB_RowBytes] ; EAX <- recalc row to bytes

; ------------- Get destination column (-> EDX) and limit width (-> ECX)

		mov	edi,[ebx+DDPB_Dim+DIM_W] ; EDI <- display width
		mov	edx,[ebx+DDPB_CurPos+POS_X] ; EDX <- current column
		or	edx,edx		; check destination column
		js	short TXTCopy6	; destination column is not valid
		sub	edi,edx		; EDI <- remaining columns
		cmp	edi,ecx		; check width of region
		jg	short TXTCopy4	; width of region is OK
		mov	ecx,edi		; ECX <- limit width of region
TXTCopy4:	or	ecx,ecx		; check width of region
		jle	short TXTCopy6	; invalid width of region

; ------------- Calculate destination address (-> EDI)

		shl	edx,1		; EDX <- recalc column to bytes
		add	eax,edx		; EAX <- offset in videomemory
		add	eax,[ebx+DDPB_Addr] ; EAX <- address
		xchg	eax,edi		; EDI <- destination address

; ------------- Prepare registers

		mov	edx,[ebx+DDPB_RowBytes] ; EDX <- bytes per row
		sub	edx,ecx		; subtract number of characters
		sub	edx,ecx		; EDX <- address increment

; ------------- Compare source and destination address

		cmp	edi,esi		; source and destination is identical?
		je	TXTCopy6	; no operation
		ja	TXTCopy8	; direction DOWN

; ------------- Direction UP (destination is before source)

		xchg	eax,ecx		; EAX <- width of region
		shr	eax,1		; EAX <- width / 2
		jc	TXTCopy7	; odd width

; ------------- Direction UP with even width

TXTCopy5:	mov	ecx,eax		; ECX <- width of region/2
		rep	movsd		; move one row
		add	esi,edx		; ESI <- shift source address
		add	edi,edx		; EDI <- shift destination address
		dec	ebp		; counter of rows
		jnz	TXTCopy5	; next row
TXTCopy6:	popa			; pop all registers
		ret

; ------------- Direction UP width odd width

TXTCopy7:	mov	ecx,eax		; ECX <- width of region/2
		rep	movsd		; move one row
		movsw			; move odd character
		add	esi,edx		; ESI <- shift source address
		add	edi,edx		; EDI <- shift destination address
		dec	ebp		; counter of rows
		jnz	TXTCopy7	; next row
		popa			; pop all registers
		ret

; ------------- Direction DOWN (destination is after source)

TXTCopy8:	mov	eax,[ebx+DDPB_RowBytes] ; EAX <- bytes per row
		push	edx		; push EDX
		mul	ebp		; EAX <- height in bytes	
		pop	edx		; pop EDX
		sub	eax,edx		; EAX <- behind last row
		dec	eax		; EAX - 1
		dec	eax		; EAX <- offset of last character
		add	esi,eax		; ESI <- source of last character
		add	edi,eax		; EDI <- destination of last character
		std			; direction down
		xchg	eax,ecx		; EAX <- width of region

; ------------- Transfer with direction DOWN

TXTCopy9:	mov	ecx,eax		; ECX <- width of region
		rep	movsw		; move one row
		sub	esi,edx		; ESI <- shift source address
		sub	edi,edx		; EDI <- shift destination address
		dec	ebp		; counter of rows
		jnz	TXTCopy9	; next row
		cld			; direction up
		popa			; pop all registers
		ret

; -----------------------------------------------------------------------------
;                                 Set font
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver parameter block
;		EDX = font address
; -----------------------------------------------------------------------------

TXTSetFont:	ret

; -----------------------------------------------------------------------------
;                                 Set EGA palettes
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver parameter block
;		EDX = palettes (16 registers)
; -----------------------------------------------------------------------------

TXTSetPal:	ret

%endif

; -----------------------------------------------------------------------------
;                                   Data
; -----------------------------------------------------------------------------

		DATA_SECTION

TXTDispTxt:	db	'Text display'
TXTDispTxt2:

; ------------- Text display driver DDPB

		align	8, db 0
TXTDrvDDPB:	RBTREENODE		; red-black tree node
		SPINLOCK		; driver lock
		db	0,DRV_OUT_TXT	; index, class and subclass
		db	DPB_STATIC,0	; flags and class flags
		db	0,0,0,1		; driver version
		dd	DrvVendorName	; pointer to vendor name
		dd	TXTDrvName	; pointer to driver name
		dd	EmptySText	; pointer to model name
		dd	EmptySText	; modul path
		dd	TXTDrvDDFB	; pointer to function table
TXTDrvDDPB1:	LINKEDLIST TXTDrvDDPB2,TXTDrvDDPB2 ; resource list

		dd	DDPB_CURON+DDPB_CANTEXT ; flags
		dd	8000h		; memory size
		dd	0,0		; cursor position
		dd	14,15		; cursor size
		dd	0,0		; current display offset
		dd	SYSTEM_ADDR+0b8000h ; memory address
		dd	TXTDrvUniMap	; mapping from Unicode
		dd	EGAFontBuff	; font buffer (128*32 = 4 KB)
		dd	0		; ...padding

		dd	80,25*4		; virtual dimension
		dd	80,25		; display dimension
		dd	8,16		; font dimension
		dd	60		; vertical frequency
		db	VMODE_TEXTCOLOR	; memory mode
		db	16		; total bits per point
		db	16		; bits in one plane
		db	1		; color planes
		dd	SYSTEM_ADDR+0b8000h ; memory base address
		dd	80*25*2		; size of display page
		dd	80*25*2*3	; maximal offset
		dd	80*2		; bytes per scan line
		dd	0		; size of one plane
		dd	3d4h		; control port
		times	DISPMAXREG db -1 ; cache of display registers

		align	4, db 0
TXTDrvDDPB2:	LINKEDLIST TXTDrvDDPB1,TXTDrvDDPB1 ; resource list
		dd	SYSTEM_ADDR+0b8000h ; start of resource
		dw	8000h-1		; size of resource-1
		db	RES_MEM		; resource type
		db	RES_STATIC+RES_AUTO ; flags

TXTDrvName:	STEXT	'Text display'

; ------------- Test display interface DDFB

		align	4, db 0
TXTDrvDDFB:	dd	DrvStdFuncOK	; device detection
		dd	DrvStdFuncOK	; device initialization
		dd	DrvStdFuncERR	; device deinitialization
		dd	DrvStdFuncERR	; enable device
		dd	DrvStdFuncERR	; disable device

		dd	TXTEnumMode	; enumerate videomodes
		dd	TXTTestMode	; test videomode
		dd	TXTSetMode	; set videomode
		dd	TXTClear	; clear screen
		dd	TXTSetOffset	; set memory offset
		dd	TXTSetCursor	; set cursor position
		dd	TXTSetCurSize	; set cursor size
		dd	TXTSetVisible	; set cursor visible
		dd	TXTLoadFont	; load text font
		dd	TXTSetFont	; set font bank                       
		dd	TXTSetBorder	; set border color
		dd	TXTSetPalCGA	; set CGA palette
		dd	TXTSetPalEGA	; set EGA palette
		dd	TXTSetPalVGA	; set VGA palette
		dd	TXTSetPalInx	; set indexed palette
		dd	TXTFillUp	; fill-up region
		dd	TXTMove		; move region
		dd	TXTBufferSize	; get buffer size
		dd	TXTGetRegion	; get region
		dd	TXTSetRegion	; set region
		dd	TXTSetRegCol	; set text region with color
		dd	TXTSetColMask	; set region with color mask
		dd	TXTSetMasked	; set region with mask
		dd	TXTSetAlpha	; set region with alpha

; ------------- Display videomode 1: 40x25 text color, 8 lines per row

DispMode1Reg:	db	12		; number of registers
		db	56		; 0: horizontal total
		db	40		; 1: horizontal displayed
		db	45		; 2: horizontal sync position
		db	10 + 0*B4	; 3: B0..B3=hsync/B4..B7=vsync width
		db	31		; 4: start horizontal retrace
		db	6		; 5: end horizontal retrace
		db	25		; 6: vertical displayed
		db	28		; 7: vertical pulse width - 1
		db	2		; 8: interlace mode
		db	7		; 9: maximum scan lines
		db	6		; 10: first cursor scanline
		db	7		; 11: last cursor scanline

; ------------- Display videomode 3: 80x25 text color, 8 lines per row

DispMode3Reg:	db	12		; number of registers
		db	113		; 0: horizontal total
		db	80		; 1: horizontal displayed
		db	90		; 2: horizontal sync position
		db	10 + 0*B4	; 3: B0..B3=hsync/B4..B7=vsync width
		db	31		; 4: start horizontal retrace
		db	6		; 5: end horizontal retrace
		db	25		; 6: vertical displayed
		db	28		; 7: vertical pulse width - 1
		db	2		; 8: interlace mode
		db	7		; 9: maximum scan lines
		db	6		; 10: first cursor scanline
		db	7		; 11: last cursor scanline

; ------------- Display videomode 4: 320x240 graphic 4-color CGA

DispMode4Reg:	db	12		; number of registers
		db	56		; 0: horizontal total
		db	40		; 1: horizontal displayed
		db	32		; 2: horizontal sync position
		db	10 + 0*B4	; 3: B0..B3=hsync/B4..B7=vsync width
		db	127		; 4: start horizontal retrace
		db	6		; 5: end horizontal retrace
		db	100		; 6: vertical displayed
		db	112		; 7: vertical pulse width - 1
		db	2		; 8: interlace mode
		db	1		; 9: maximum scan lines
		db	6		; 10: first cursor scanline
		db	7		; 11: last cursor scanline

; ------------- Display videomode 7: 80x25 text mono, 8 lines per row

DispMode7Reg:	db	12		; number of registers
		db	97		; 0: horizontal total
		db	80		; 1: horizontal displayed
		db	82		; 2: horizontal sync position
		db	15 + 0*B4	; 3: B0..B3=hsync/B4..B7=vsync width
		db	25		; 4: start horizontal retrace
		db	2		; 5: end horizontal retrace
		db	25		; 6: vertical displayed
		db	25		; 7: vertical pulse width - 1
		db	2		; 8: interlace mode
		db	13		; 9: maximum scan lines
		db	11		; 10: first cursor scanline
		db	12		; 11: last cursor scanline

; ------------- Display videomode on VGA: 640x350 graphic 16 colors

DispMode14Reg:	db	12		; number of registers
		db	91		; 0: horizontal total
		db	79		; 1: last displayed character
		db	83		; 2: start of horizontal sync
		db	55		; 3: end of horizontal sync
		db	82		; 4: start horizontal retrace
		db	0		; 5: end horizontal retrace
		db	108		; 6: vertical displayed LOW
		db	31		; 7: vertical pulse width - 1
		db	0		; 8: interlace mode
		db	0		; 9: maximum scan lines
		db	0		; 10: first cursor scanline
		db	0		; 11: last cursor scanline
		; ... TODO

DispTestText:	db	'Display 512-character test:'
DispTestText2:

; -----------------------------------------------------------------------------
;                            Uninitialized data
; -----------------------------------------------------------------------------

		BSS_SECTION

; ------------- Mapping from Unicode

TXTDrvUniMap:	resd	FONTMAP		; mapping from Unicode

Back to source browser