; =============================================================================
;
; 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
|