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

EGA.ASM

EGA Display


; =============================================================================
;
;                             Litos - EGA display
;
; =============================================================================

		CODE_SECTION	32

; -----------------------------------------------------------------------------
;                         Initialize EGA driver
; -----------------------------------------------------------------------------

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

EGAInit:	mov	ebx,EGADrvDDPB	; EBX <- driver parameter block

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

EGAInitDrv:	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

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

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

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

		movzx	eax,byte [VideoCols] ; EAX <- number of columns
		mov	[ebx+DDPB_W],eax ; number of columns
		mov	[ebx+DDPB_VirtW],eax ; number of columns
		shl	eax,1		; EAX <- number of columns * 2
		mov	[ebx+DDPB_ScanLine],eax ; lenght of row in bytes
		movzx	eax,byte [VideoRows] ; EDX <- number of rows
		mov	[ebx+DDPB_H],eax ; number of rows
		mov	[ebx+DDPB_VirtH],eax ; number of rows

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

		movzx	eax,byte [VideoPos] ; EAX <- current position
		mov	[ebx+DDPB_CurPosX],eax ; cursor position
		movzx	eax,byte [VideoRow] ; EAX <- current row
		mov	[ebx+DDPB_CurPosY],eax ; cursor row

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

		call	DrvLstInsert	; insert driver into list
		ret

; -----------------------------------------------------------------------------
;                              Set EGA palettes
; -----------------------------------------------------------------------------
; 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.
; -----------------------------------------------------------------------------

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

EGASetPal:	push	eax		; push EAX
		push	edx		; push EDX
		push	esi		; push ESI
		mov	esi,edx		; ESI <- palettes
		mov	ah,al		; AH <- start index

; ------------- Synchronise palette register

		mov	edx,[ebx+DDPB_Port] ; DX <- control port
		add	edx,byte 6	; DX <- status port
		in	al,dx		; synchronise palet registers

; ------------- Set palettes

		mov	dx,3c0h		; DX <- palette port
EGASetPal2:	cmp	ah,10h		; border color should be set?
		jne	EGASetPal3	; no border color
		mov	ah,11h		; AH <- register with border color
EGASetPal3:	mov	al,ah		; AL <- register number
		out	dx,al		; select register
		lodsb			; AL <- palette value
		out	dx,al		; set palette value
		inc	ah		; increase register number
		cmp	ah,cl		; check register number
		jle	EGASetPal2	; set next register

; ------------- Enable video access to registers

		mov	al,B5		; AL <- video access enabled
		out	dx,al		; enable video access to registers

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

		pop	esi		; pop ESI
		pop	edx		; pop EDX
		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)
; -----------------------------------------------------------------------------

; ------------- Start font mode

EGALoadFont:	call	EGAFontStart	; start font mode

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

		pusha			; push all registers
		movzx	edi,al		; EDI <- font bank

; ------------- Prepare font height (-> EBX)

		mov	ebx,[ebx+DDPB_FontH] ; EBX <- font height
		or	ah,ah		; use default font height?
		jz	EGALoadFont1	; use default font height
		movzx	ebx,ah		; EBX <- font height

; ------------- Prepare number of characters (-> EDX)

EGALoadFont1:	movzx	eax,cl		; EAX <- first index
		movzx	edx,dl		; EDX <- last index
		inc	edx		; EDX <- last index + 1
		sub	edx,eax		; EDX <- number of characters

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

		shl	di,14		; EDI <- 16 KB bank (max. 64 KB)
		jnc	EGALoadFont2	; it is EGA font (0 to 3)
		add	edi,2000h	; add 8 KB (for odd VGA bank)
EGALoadFont2:	add	edi,SYSTEM_ADDR+0a0000h ; EDI <- font address
		shl	eax,5		; EAX <- *32, character offset
		add	edi,eax		; EDI <- character address

; ------------- Prepare destination increment (-> EBP)

		mov	ebp,32		; EBP <- 32 bytes per one character
		sub	ebp,ebx		; EBP <- address increment
		shr	ebp,2		; EBP <- address increment / 4
		xor	eax,eax		; EAX <- 0, clear pattern

; ------------- Check odd/even height

		shr	ebx,1		; EBX <- font height / 2
		jc	EGALoadFont5	; odd height

; ------------- Define fonts - heigh modulo 0

		shr	ebx,1		; EBX <- font height / 4
		jc	EGALoadFont4	; height modulo 2
EGALoadFont3:	mov	ecx,ebx		; ECX <- font height
		rep	movsd		; move one font
		mov	ecx,ebp		; ECX <- height of rest of font
		rep	stosd		; clear rest of font
		dec	edx		; character counter
		jnz	EGALoadFont3	; next character
		jmp	short EGALoadFont8

; ------------- Define fonts - heigh modulo 2

EGALoadFont4:	mov	ecx,ebx		; ECX <- font height
		rep	movsd		; move one font
		movsw			; move odd word
		mov	ecx,ebp		; ECX <- height of rest of font
		stosw			; clear rest word of font
		rep	stosd		; clear rest of font
		dec	edx		; character counter
		jnz	EGALoadFont4	; next character
		jmp	short EGALoadFont8

; ------------- Define fonts - height modulo 1

EGALoadFont5:	shr	ebx,1		; EBX <- font height / 4
		jc	EGALoadFont7	; height modulo 3
EGALoadFont6:	mov	ecx,ebx		; ECX <- font height
		rep	movsd		; move one font
		movsb			; move odd byte
		stosb			; clear rest byte of font
		mov	ecx,ebp		; ECX <- height of rest of font
		stosw			; clear rest word of font
		rep	stosd		; clear rest of font
		dec	edx		; character counter
		jnz	EGALoadFont6	; next character
		jmp	short EGALoadFont8

; ------------- Define fonts - height modulo 3

EGALoadFont7:	mov	ecx,ebx		; ECX <- font height
		rep	movsd		; move one font
		movsw			; move odd word
		movsb			; move odd byte
		mov	ecx,ebp		; ECX <- height of rest of font
		stosb			; clear rest byte of font
		rep	stosd		; clear rest of font
		dec	edx		; character counter
		jnz	EGALoadFont7	; next character

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

EGALoadFont8:	popa			; pop all registers

; ------------- Stop font mode

		call	EGAFontStop	; stop font mode
		ret

; -----------------------------------------------------------------------------
;                             Start font mode
; -----------------------------------------------------------------------------

; ------------- Push reguisters

EGAFontStart:	push	eax		; push EAX
		push	ebx		; push EBX
		push	ecx		; push ECX
		push	edx		; push EDX

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

		mov	ah,2		; AH <- reading plane
		mov	bl,B0+B1+B2	; BL <- non interlaced text mode
		mov	bh,B2		; BH <- write plane mask
		mov	ch,0		; CH <- mode register
		mov	cl,1<<2		; CL <- memory mapping A000 (64 KB)
		jmp	short EGAFontStop4 ; initialize registers

; -----------------------------------------------------------------------------
;                             Stop font mode
; -----------------------------------------------------------------------------
; INPUT:	EBX = display driver
; -----------------------------------------------------------------------------

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

EGAFontStop:	push	eax		; push EAX
		push	ebx		; push EBX
		push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Prepare memory mapping

		mov	cl,(2<<2)+B1	; CL <- memory mapping B000
		cmp	byte [ebx+DDPB_BaseAddr+1],40h ; xxxB8000 or more?
		jb	EGAFontStop2	; xxxB0000 base address
		mov	cl,(3<<2)+B1	; CL <- memory mapping B800

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

EGAFontStop2:	mov	ah,0		; AH <- reading plane
		mov	bl,B0+B1	; BL <- interlaced text mode
		mov	bh,B0+B1	; BH <- write mask, BL <- interl. mode
		mov	ch,B4		; CH <- mode register (odd/even)

; ------------- Set synchronous reset

EGAFontStop4:	mov	dx,3c4h		; DX <- register selector
		mov	al,0		; AL <- 0, reset register
		out	dx,al		; select register 0
		inc	edx		; DX <- data
		mov	al,B0		; AL <- synchronous reset mode
		out	dx,al		; set synchronous reset

; ------------- Select write plane mask

		dec	edx		; DX <- register selector
		mov	al,2		; AL <- 2, write mask register
		out	dx,al		; select register 2
		inc	edx		; DX <- data
		mov	al,bh		; AL <- write plane mask
		out	dx,al		; set write plane mask

; ------------- Set interlaced mode

		dec	edx		; DX <- register selector
		mov	al,4		; AL <- 4, memory mode register
		out	dx,al		; select register 4
		inc	edx		; DX <- data
		mov	al,bl		; AL <- interlaced mode
		out	dx,al		; set interlaced mode

; ------------- Clear synchronous reset

		dec	edx		; DX <- register selector
		mov	al,0		; AL <- 0, reset register
		out	dx,al		; select register 0
		inc	edx		; DX <- data
		mov	al,B0+B1	; AL <- clear reset mode
		out	dx,al		; clear synchronous reset

; ------------- Set reading planes

		mov	dl,0ceh		; DX <- 3ceh/3cfh port
		mov	al,4		; AL <- 4, reading register
		out	dx,al		; select register 4
		inc	edx		; DX <- data
		mov	al,ah		; AL <- reading planes
		out	dx,al		; set reading planes

; ------------- Set mode register (enable odd/even address mode)

		dec	edx		; DX <- register selector
		mov	al,5		; AL <- 5, mode register
		out	dx,al		; select register 5
		inc	edx		; DX <- data
		mov	al,ch		; AL <- mode register
		out	dx,al		; set mode register

; ------------- Set memory mapping

		dec	edx		; DX <- register selector
		mov	al,6		; AL <- 6, mapping register
		out	dx,al		; select register 6
		inc	edx		; DX <- data
		mov	al,cl		; AL <- memory mapping mode
		out	dx,al		; set mapping mode

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

		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		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)
; -----------------------------------------------------------------------------

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

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

; ------------- Prepare font bank (-> CL)

		test	cl,B2		; bank 4 to 7?
		jz	EGASetFont2	; bank 0 to 3
		xor	cl,B2 + B4	; correct bits
EGASetFont2:	shl	dl,2		; rotate bank 2
		test	dl,B4		; bank 4 to 7?
		jz	EGASetFont3	; bank 0 to 3
		xor	dl,B4 + B5	; correct bits
EGASetFont3:	or	cl,dl		; add bank 2

; ------------- Set synchronous reset

		mov	dx,3c4h		; DX <- register selector
		mov	al,0		; AL <- 0, reset register
		out	dx,al		; select register 0
		inc	edx		; DX <- data
		mov	al,B0		; AL <- asyn. reset mode
		out	dx,al		; set synchronous reset

; ------------- Select character map

		dec	edx		; DX <- register selector
		mov	al,3		; AL <- register
		out	dx,al		; select register 3
		inc	edx		; DX <- data
		mov	al,cl		; AL <- character generator
		out	dx,al		; set write planes

; ------------- Clear synchronous reset

		dec	edx		; DX <- register selector
		mov	al,0		; AL <- 0, reset register
		out	dx,al		; select register 0
		inc	edx		; DX <- data
		mov	al,B0+B1	; AL <- clear reset mode
		out	dx,al		; clear synchronous reset

; ------------- Set 256/512-character mode (select color planes 0 to 2)

;		mov	edx,[ebx+DDPB_Port] ; DX <- control port
;		add	edx,byte 6	; DX <- status port
;		in	al,dx		; synchronise palet registers
;		mov	dx,3c0h		; DX <- palet registers
;		mov	al,12h		; AL <- register 12h
;		out	dx,al		; select register 12h
;		mov	al,B0+B1+B2	; AL <- color planes
;		out	dx,al		; set color planes

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

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

%ifdef AAAA

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

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

EGASetFont:	pusha			; push all registers
		push	ebx		; push EBX

; ------------- Start font mode

		call	EGAFontStart	; start font mode
		push	ecx		; push old memory mapping

; ------------- Get font height (-> EBX)

		mov	esi,edx		; ESI <- font address
		inc	esi		; skip font width
		lodsb			; AL <- font height
		movzx	ebx,al		; EBX <- font height

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

		xor	edx,edx		; EDX <- 0
		inc	dh		; EDX <- 256, number of characters
		mov	edi,0a0000h+SYSTEM_ADDR ; EDI <- font memory
		mov	ebp,32		; EBP <- max. font height
		sub	ebp,ebx		; EBP <- address increment

; ------------- Check odd/even height

		shr	ebx,1		; EBX <- font height / 2
		jc	EGASetFont4	; odd height

; ------------- Define fonts - even height

EGASetFont2:	mov	ecx,ebx		; ECX <- font height
		rep	movsw		; move one font
		add	edi,ebp		; EDI <- address of next character
		dec	edx		; character counter
		jnz	EGASetFont2	; next character

		mov	edi,0a4000h+SYSTEM_ADDR ; EDI <- font memory
		inc	dh		; EDX <- 256, number of characters
EGASetFont3:	mov	ecx,ebx		; ECX <- font height
		rep	movsw		; move one font
		add	edi,ebp		; EDI <- address of next character
		dec	edx		; character counter
		jnz	EGASetFont3	; next character
		jmp	short EGASetFont6

; ------------- Define fonts - odd height

EGASetFont4:	mov	ecx,ebx		; ECX <- font height
		rep	movsw		; move one font
		movsb			; move odd byte
		add	edi,ebp		; EDI <- address of next character
		dec	edx		; character counter
		jnz	EGASetFont4	; next character

		mov	edi,0a4000h+SYSTEM_ADDR ; EDI <- font memory
		inc	dh		; EDX <- 256, number of characters
EGASetFont5:	mov	ecx,ebx		; ECX <- font height
		rep	movsw		; move one font
		movsb			; move odd byte
		add	edi,ebp		; EDI <- address of next character
		dec	edx		; character counter
		jnz	EGASetFont5	; next character

; ------------- Stop font mode

EGASetFont6:	pop	ecx		; pop old memory mapping
		call	EGAFontStop	; stop font mode
		pop	ebx		; pop EBX

; ------------- Set 512-character mode (select color planes 0 to 2)

;		mov	edx,[ebx+DDPB_Port] ; DX <- control port
;		add	edx,byte 6	; DX <- status port
;		in	al,dx		; synchronise palet registers
;		mov	dx,3c0h		; DX <- palet registers
;		mov	al,12h		; AL <- register 12h
;		out	dx,al		; select register 12h
;		mov	al,B0+B1+B2	; AL <- color planes
;		out	dx,al		; set color planes

; ------------- Set intensity mode

		mov	edx,[ebx+DDPB_Port] ; DX <- control port
		add	edx,byte 6	; DX <- status port
		in	al,dx		; synchronise palet registers

		mov	dx,3c0h		; DX <- palet registers
		mov	al,10h
		out	dx,al
;		inc	dx
;		in	al,dx
;		dec	dx
;		and	al,~B3
		mov	al,B2
		out	dx,al

		mov	al,B5		; AL <- video access enabled
		out	dx,al		; enable video access to registers

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

		popa			; pop all registers
		ret

%endif

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

		DATA_SECTION

; ------------- EGA display driver

		align	8, db 0
EGADrvDDPB:	RBTREENODE		; red-black tree node
		SPINLOCK		; driver lock
		db	0,DRV_OUT_GRAPH	; 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	EGADrvName	; pointer to driver name
		dd	EmptySText	; pointer to model name
		dd	EmptySText	; modul path
		dd	EGADrvDDFBText	; pointer to function table
EGADrvDDPB1:	LINKEDLIST EGADrvDDPB2,EGADrvDDPB2 ; 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	EGADrvUniMap	; 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
EGADrvDDPB2:	LINKEDLIST EGADrvDDPB1,EGADrvDDPB1 ; resource list
		dd	SYSTEM_ADDR+0a0000h ; start of resource
		dw	20000h/PAGE_SIZE-1 ; size of resource-1
		db	RES_MEM		; resource type
		db	RES_STATIC+RES_AUTO+RES_PAGES ; flags

EGADrvName:	STEXT	'EGA display'

; ------------- EGA display interface DDFB - text mode

		align	4, db 0
EGADrvDDFBText:	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	EGALoadFont	; load text font
		dd	EGASetFont	; set font bank
		dd	TXTSetBorder	; set border color
		dd	TXTSetPalCGA	; set CGA palette
		dd	EGASetPal	; 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

; ------------- EGA Standard palettes
;	B0	blue	2/3
;	B1	green	2/3
;	B2	red	2/3
;	B3	blue	1/3
;	B4	green	1/3
;	B5	red	1/3

		align	4, db 0
EGAStdPal:	db	0			; black		(00h)
		db	B0			; blue		(01h)
		db	B1			; green		(02h)
		db	B0+B1			; cyan		(03h)
		db	B2			; red		(04h)
		db	B0+B2			; magenta	(05h)
		db	B4+B2			; brown		(14h)
		db	B0+B1+B2		; white		(07h)
		db	B3+B4+B5		; gray		(38h)
		db	B0+B3+B4+B5		; light blue	(39h)
		db	B1+B3+B4+B5		; light green	(3Ah)
		db	B0+B1+B3+B4+B5		; light cyan	(3Bh)
		db	B2+B3+B4+B5		; light red	(3Ch)
		db	B0+B2+B3+B4+B5		; light magenta	(3Dh)
		db	B1+B2+B3+B4+B5		; yellow	(3Eh)
		db	B0+B1+B2+B3+B4+B5	; light white	(3Fh)
		db	0			; black (border)

; ------------- 8-color palettes
;	B0	blue	2/3
;	B1	green	2/3
;	B2	red	2/3
;	B3	blue	1/3
;	B4	green	1/3
;	B5	red	1/3

		align	4, db 0
EGA8Pal:
%rep 2
		db	0			; black		(00h)
		db	B0			; blue		(01h)
		db	B1			; green		(02h)
		db	B0+B1+B3+B4		; cyan		(1Bh)
		db	B2+B5			; red		(24h)
		db	B0+B2+B3+B5		; magenta	(2Dh)
		db	B1+B2+B3+B4+B5		; yellow	(3Eh)
		db	B0+B1+B2+B3+B4+B5	; white		(3Fh)
%endrep
		db	0			; black (border)

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

		BSS_SECTION

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

		align	4, resb 1
EGADrvUniMap:	resd	FONTMAP		; mapping from Unicode

; ------------- Buffer to load fonts

		align	4, resb 1
EGAFontBuff:	resb	128*32        

Back to source browser