ega.asm
资源名称:DOS系统的源代码.rar [点击查看]
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:61k
源码类别:
操作系统开发
开发平台:
Visual C++
- page 56,132
- name EGASYS
- title EGA Screen Device Driver
- subttl Header
- IFDEF OS2
- .286 ; Oh goody, can use 80286 instructions
- ELSE ; NOT OS2
- .8086 ; Have to support everything
- ENDIF ; NOT OS2
- ;
- ; I N C L U D E S
- ;
- include ega.inc
- ;
- ; C O D E
- ;
- IFDEF OS2 ; Start of OS/2 functions
- ;
- ; DoSave - Save state of EGA
- ;
- ; ENTRY
- ; ds = cs
- ;
- ; EXIT
- ; ax = 0, operation complete
- ;
- ; DESTROYS
- ; bx, si
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- DoSave proc near
- mov ax,cs
- mov es,ax
- assume es:CODE
- mov ax,0F901h ; Select new context subfunction
- jmp short DoCommon
- DoSave endp
- ;
- ; DoRestore - Restore state of EGA
- ;
- ; ENTRY
- ; ds = cs
- ;
- ; EXIT
- ; ax = 0, operation complete
- ;
- ; DESTROYS
- ; bx, si, ds
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- DoRestore proc near
- mov ax,cs
- mov es,ax
- assume es:CODE
- mov ax,0F902h ; Select new context subfunction
- DoCommon:
- mov bx,offset ContextCopy
- int 10h ; Restore from ContextCopy
- if2 ; Pass 2 of the assembler
- .errnz ($ - StatusComplete) ; Drop into StatusComplete
- endif ; Pass 2 of the assembler
- DoRestore endp
- ENDIF ; OS2
- ;
- ; StatusComplete - Set completion status
- ;
- ; ENTRY
- ; none
- ;
- ; EXIT
- ; ax = 0, request completed
- ;
- ; DESTROYS
- ; None
- ;
- assume cs:CODE, ds:nothing, es:nothing, ss:nothing
- StatusComplete proc near
- sub ax,ax ; AX = 0, complete
- ret
- StatusComplete endp
- ENDIF ; SYS
- subttl Miscellaneous Code
- page
- ;
- ; UpdateCRTCMap - get the latest values for certain readable CRTC regs
- ;
- ; Called by all routines that return register values to the user,
- ; this function updates the current CRTC shadow map with the latest
- ; values of the readable CRTC StartAddress (00Ch, 00Dh) and
- ; CursorPosition (00Eh, 00Fh).
- ;
- ; Of the numerous EGA regs that are write only, the CRTC contains a
- ; handful of readable regs. Normally, for readable regs like Input
- ; Status 1, EGA.SYS requires the user keep track of its value. But if
- ; the goal is for the user of EGA.SYS to be able to rely 100% on the
- ; shadow maps, we must properly update readables that we do return.
- ; Note that the CRTC lightpen regs do not fall into this category,
- ; since we shadow writes to that index, which is really the vertical
- ; sync start/stop regs.
- ;
- ; ENTRY
- ; none
- ; EXIT
- ; none
- ; DESTROYS
- ; AX, SI (if VGA)
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- UpdateCRTCMap proc near
- push dx ; Save environment
- mov dx,[PortTable][0].prPortAddr
- mov ax,0C0Dh
- pushf ; Save interrupt flag state
- CLI ; Disable interrupts
- out dx,al ; Address CRTCStart high
- IOdelay
- inc dx
- in al,dx ; Get CRTCStart high
- IOdelay
- dec dx
- xchg al,ah
- out dx,al ; Address CRTCStart low
- IOdelay
- inc dx
- in al,dx ; Get CRTCStart low
- IOdelay
- mov word ptr [CRTCRegs][00Ch],ax ; Stash low:high
- dec dx
- mov ax,00E0Fh
- out dx,al ; Address CRTCCursor pos high
- IOdelay
- inc dx
- in al,dx ; Get CRTCCursor pos high
- IOdelay
- dec dx
- xchg al,ah
- out dx,al ; Address CRTCCursor pos low
- IOdelay
- inc dx
- in al,dx ; Get CRTCCursor pos low
- popf ; Restore interrupt flag state
- mov word ptr [CRTCRegs][00Eh],ax ; Stash low:high
- cmp [fVga],false ; On VGA card?
- je UpdateCRTCMapDone ; No - skip
- xor si,si ; Don't change default save maps
- push bx ; Save environment
- push cx ; Save environment
- call ReadVGARegs
- mov [fPalette],cl ; fPalette = FALSE
- pop cx ; Restore environment
- pop bx ; Restore environment
- UpdateCRTCMapDone:
- pop dx ; Restore environment
- ret
- UpdateCRTCMap endp
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- ReadVGARegs proc near
- ;
- ; Save Miscellaneous Output Register
- ;
- MOV DX,MiscOutputRegR ; Get Miscellaneous Output Register
- IN AL,DX ; Get current state of the register
- IOdelay
- MOV [MiscOutReg],AL ; value
- or si,si ; Change default save map?
- jz @F ; No - skip
- MOV [DefMiscOutReg],AL ; Save initial
- ;
- ; Save Feature Control Register
- ;
- @@:
- MOV DL,FeatureCtrlReg AND 0FFH ; Get Feature Control Register
- IN AL,DX ; Get current state of the register
- MOV [FeatureReg],AL ; value
- or si,si ; Change default save map?
- jz @F ; No - skip
- MOV [DefFeatureReg],AL ; Save initial
- ;
- ; Save Sequencer Registers
- ;
- @@:
- MOV CX,NumSeqRegs ; Initialize 5H registers
- MOV DL,(EGA_BASE + SEQ_ADDR) AND 0FFH ; Get Sequencer Register
- XOR BX,BX ; Code to select reset reg
- pushf ; Save interrupt flag state
- SaveSequencerRegs:
- MOV AL,BL ; Get index
- CLI ; Disable interrupts
- OUT DX,AL ; Send index to the Address Register
- IOdelay
- INC DX ; Choose read only register
- IN AL,DX ; Get current state of the register
- STI ; Enable interrupts
- DEC DX ; Choose index register
- MOV [SeqRegs][BX],AL ; value
- or si,si ; Change default save map?
- jz @F ; No - skip
- MOV [DefSeqRegs][BX],AL ; Save initial
- @@:
- INC BX ; Move to the next index register
- LOOP SaveSequencerRegs ; Loop back and initialize another reg
- ;
- ; Save Graphics Controller Registers
- ;
- MOV BX,CX ; Code to select enable set/reset reg
- MOV CL,NumGraphicsRegs ; Initialize 9H registers
- MOV DL,(EGA_BASE + GRAF_CONT) AND 0FFH
- ; Get Graphics Control Addr Reg
- SaveGraphicsContRegs:
- MOV AL,BL ; Get index
- CLI ; Disable interrupts
- OUT DX,AL ; Send index to the Address Register
- IOdelay
- INC DX ; Choose read only register
- IN AL,DX ; Get current state of the register
- STI ; Enable interrupts
- DEC DX ; Choose index register
- MOV [GraphicsRegs][BX],AL ; value
- or si,si ; Change default save map?
- jz @F ; No - skip
- MOV [DefGraphicsRegs][BX],AL ; Save initial
- @@:
- INC BX ; Move to the next index register
- LOOP SaveGraphicsContRegs ; Loop back and initialize another reg
- ;
- ; Save Attribute Controller Registers
- ;
- MOV BX,CX ; Code to select Palette
- ; Register and keep video disabled
- MOV CL,NumAttrRegs ; Initialize 15H registers
- SaveAttributeContRegs:
- MOV DL,BYTE PTR [PortTable][5 * SIZE PortRec].PRPortAddr
- CLI ; Disable interrupts
- IN AL,DX ; Initialize flip-flop to select address
- MOV AL,BL ; Get index
- CMP AL,10H ; Past palette registers?
- JB PaletteCheckDone ; No - skip
- OR AL,PaletteAddressSource ; Code to enable video
- jmp short GetAttrReg
- ;
- ; We are stuck. In order to correctly read the Palette registers
- ; on a VGA, the Palette address source bit (bit 5 of the Attribute
- ; Address Register) needs to be 0, but making this 0 will disable
- ; video. Then after reading the Palette registers, we need to
- ; re-enable video. But this happens so often that the screen
- ; flashes. So, we can only read these registers at init time.
- ; Only loss of functionality is if the palette registers get
- ; out of sync with the shadow maps after init time.
- ;
- PaletteCheckDone:
- cmp [fPalette],ch ; Did user request the palette regs?
- jne GetAttrReg ; Yes - skip
- or si,si ; Init?
- jz NextAttrReg ; No - skip
- GetAttrReg:
- MOV DL,AttCtrlAddrReg AND 0FFH ; Get Attribute Control Address Reg
- OUT DX,AL ; Send index to the Address Register
- IOdelay
- INC DX ; Choose read only register
- IN AL,DX ; Get current state of the register
- MOV [AttrRegs][BX],AL ; value
- or si,si ; Change default save map?
- jz NextAttrReg ; No - skip
- MOV [DefAttrRegs][BX],AL ; Save initial
- NextAttrReg:
- STI ; Enable interrupts
- INC BX ; Move to the next index register
- LOOP SaveAttributeContRegs ; Loop back and initialize another reg
- ;
- ; Save CRT Controller Registers
- ;
- MOV BX,CX ; Code to select horizontal total reg
- MOV CL,NumCRTCRegs ; Initialize 19H registers
- MOV DL,BYTE PTR [PortTable][5 * SIZE PortRec].PRPortAddr
- CLI ; Disable interrupts
- IN AL,DX ; So that we get back to index again
- IOdelay
- SUB DL,6 ; Get CRT Controller Address Reg
- SaveCRTContRegs:
- CLI ; Disable interrupts
- MOV AL,BL ; Get index
- OUT DX,AL ; Send index to the Address Register
- IOdelay
- INC DX ; Choose read only register
- IN AL,DX ; Get current state of the register
- STI ; Enable interrupts
- DEC DX ; Choose index register
- MOV [CRTCRegs][BX],AL ; value
- or si,si ; Change default save map?
- jz @F ; No - skip
- MOV [DefCRTCRegs][BX],AL ; Save initial
- @@:
- INC BX ; Move to the next index register
- LOOP SaveCRTContRegs ; Loop back and initialize another reg
- popf ; Restore interrupt flag state
- ret
- ReadVGARegs endp
- page
- ;
- ; BrstDet - determine number of scan lines for raster
- ;
- ; BrstDet, similar to the IBM function by the same name, determines
- ; whether the current raster should be 200 or 350 scanlines based on
- ; the switch settings on the rear of the EGA card. In a nutshell,
- ; switch settings 0011 or 1001 indicate 350 lines, otherwise 200 lines.
- ;
- ; EXIT
- ; cy = 200 scanlines
- ; nc = 350 scanlines
- ; DESTROYS
- ; None
- ;
- assume cs:CODE, ds:nothing, es:nothing, ss:nothing
- BrstDet proc near
- push ax
- mov al,[biosinfo3] ; Get feature and switch info
- and al,00001111b ; Mask for switches
- cmp al,00001001b ; Most common config
- je @F
- cmp al,00000011b ; Less common
- je @F
- stc ; Else set carry
- @@:
- pop ax
- ret
- BrstDet endp
- page
- ;
- ; MakeBase - find proper video params for given mode
- ;
- ; MakeBase, similar to the IBM function by the same name, will return
- ; a pointer to the correct table of video parameters to use when
- ; initializing the EGA for a given mode. The root of the list of tables
- ; is derived from the ParmPtr in the SavePtr table.
- ;
- ; ENTRY
- ; ah = video mode
- ; ds = 0
- ; EXIT
- ; es:si -> base of correct parameter table
- ; DESTROYS
- ; ax, flags
- ;
- assume cs:CODE, ds:INTVEC, es:nothing, ss:nothing
- MakeBase proc near
- les si,[lpSavePtr] ; Load up SavePtr
- assume es:nothing
- les si,es:[si] ; Load up ParmPtr
- assume es:nothing
- test [Info],01100000b ; If 64K video memory,
- jz mb64K ; skip special graphics tests
- add si,440h ; Bump to alt 640x350x1
- cmp ah,0Fh ; If this is what we want,
- je mbX ; we are done
- add si,40h ; Bump to alt 640x350x4
- cmp ah,10h ; If this is what we want,
- je mbX ; we are done
- ;
- ; I assume that the special VGA modes 11h, 12h, and 13h are
- ; contiguous and lie after the last EGA table in memory, but
- ; I don't know this for sure.
- ;
- add si,140h ; Bump for VGA modes 11h, 12h, 13h
- cmp ah,11h ; Is it a VGA mode 11h?
- je mbx ; Yes - skip
- add si,40h ; Bump for VGA mode 12h
- cmp ah,12h ; Is it a VGA mode 12h?
- je mbx ; Yes - skip
- add si,40h ; Bump for VGA mode 13h
- cmp ah,13h ; Is it a VGA mode 13h?
- je mbx ; Yes - skip
- sub si,640h ; Nope, not special graphics
- mb64K:
- cmp ah,3h ; If not alpha,
- ja @F ; skip special alpha tests
- call BrstDet ; If not enhanced config,
- jc @F ; no adjustment needed
- add si,4C0h ; Bump to enhanced alpha parms
- @@:
- xor al,al ; Now use mode as final index
- ifdef OS2
- shr ax,2
- else ; NOT OS2
- shr ax,1 ; Funky math does the job
- shr ax,1
- endif ; NOT OS2
- add si,ax
- mbX:
- ret ; ES:SI -> correct table
- MakeBase endp
- ;-----------------------------------------------------------------------
- ; HandleIODelay -- Delay for doing close together I/O for hardware
- ; to catch it's breath
- ;
- ; Entry: None
- ;
- ; Exit: None
- ;
- ; Alters: None
- ;
- ; Note: This was implemented because processors (e.g. 80486) keep
- ; getting faster and smarter (prefetch and caching)
- ; and ruin our old jmp $+2 scheme, so this is a better
- ; (i.e. more processor independent) method.
- ;
- ;-----------------------------------------------------------------------
- assume cs:CODE, ds:nothing, es:nothing, ss:nothing
- HandleIODelay proc near
- push ax ; Save environment
- in al,43h ; Delay by reading status register
- in al,43h ; Delay by reading status register
- pop ax ; Restore environment
- ret
- HandleIODelay endp
- page
- ;
- ; ChangeRegs - reinitialize all shadow maps and EGA state info
- ;
- ; ENTRY
- ; ah = video mode
- ; al = low byte of CRTC io address
- ; Used in EGAChooseMonoColorDisplay macro
- ; EXIT
- ; ds = cs
- ; DESTROYS
- ; ax, si
- ;
- assume cs:CODE, ds:INTVEC, es:nothing, ss:nothing
- ChangeRegs proc near
- push cx ; Save environment
- push di ; Save environment
- PUSH BX ; Save environment
- ifdef OS2
- mov cx,cs ; DS = Code segment
- mov ds,cx ; Two instructions needed
- assume ds:CODE
- EGAChooseMonoColorDisplay ; Validate CRTC address
- endif ; OS2
- CMP [fVga],FALSE ; Do we have a VGA Card?
- JE HandleEGA ; No - skip
- PUSH DX ; Save environment
- ifndef OS2
- mov cx,cs ; DS = Code segment
- mov ds,cx ; Two instructions needed
- assume ds:CODE
- VGAChooseMonoColorDisplay ; Validate CRTC address
- endif ; NOT OS2
- mov si,1 ; Change default save maps
- call ReadVGARegs
- POP DX ; Restore environment
- JMP SHORT FinishChangeRegs
- HandleEGA:
- ifdef OS2
- PUSH ES ; Save environment
- xor si,si ; DS = Segment 0
- mov ds,si ; Two instructions needed
- assume ds:INTVEC
- else ; NOT OS2
- assume ds:INTVEC
- PUSH ES ; Save environment
- EGAChooseMonoColorDisplay ; Validate CRTC address
- endif ; NOT OS2
- call MakeBase ; ES:SI -> correct table on exit
- assume es:nothing
- mov ax,es
- mov ds,ax ; DS = ES
- assume ds:nothing
- mov ax,cs
- mov es,ax ; ES = CS
- assume es:CODE
- add si,5 ; Bump past BIOS misc junk
- mov di,offset StartShadowMaps
- mov al,3 ; Always stash 3 in seq reset reg
- stosb
- mov cx,(VGAPatch - 2) / 2 ; Move data up to extra VGA reg
- if (VGAPatch - 2) AND 1
- movsb ; Odd count adjust
- endif ; (VGAPatch - 2) AND 1
- rep movsw
- inc di ; Bump past VGA reg
- mov cl,NumGraphicsRegs / 2 ; Finish up grph ctrlr regs
- if NumGraphicsRegs AND 1
- movsb ; Odd count adjust
- endif ; NumGraphicsRegs AND 1
- rep movsw
- sub si,(SizeShadowMaps - 2) ; Drop back to beginning
- stosb ; Always stash 3 in seq reset reg
- mov cl,(VGAPatch - 2) / 2 ; Move data up extra VGA reg
- if (VGAPatch - 2) AND 1
- movsb ; Odd count adjust
- endif ; (VGAPatch - 2) AND 1
- rep movsw
- inc di ; Bump past VGA reg
- mov cl,NumGraphicsRegs / 2 ; Finish up grph ctrlr regs
- if NumGraphicsRegs AND 1
- movsb ; Odd count adjust
- endif ; NumGraphicsRegs AND 1
- rep movsw
- mov ax,cs
- mov ds,ax
- assume ds:CODE ; DS = CS
- mov [PortTable][3 * SIZE PortRec].prNumRegs,NumAttrRegs - 1
- ; Adjust size for EGA
- xor ax,ax ; Get a zero value
- mov [Gr1PosReg],al ; AX = 0, init Gr1PosRegs
- mov [DefGr1PosReg],al
- inc ax
- mov [Gr2PosReg],al ; AX = 1, init Gr2PosRegs
- mov [DefGr2PosReg],al
- POP ES ; Restore environment
- assume es:nothing
- FinishChangeRegs:
- assume ds:CODE
- xor ax,ax
- mov di,ax ; Now clear all dirty flags
- mov cl,NumPtrData
- mov bx,offset PortTable ; Start at beginning
- @@:
- mov code:[bx][di].prModFlag,al
- add di,SIZE PortRec
- loop @B
- mov [SingleRegMod],al
- POP BX ; Restore environment
- pop di ; Restore environment
- pop cx ; Restore environment
- ret
- ChangeRegs endp
- subttl SetMode
- page
- ;
- ; SetMode - shadow int 10h SetMode functionality (subfunction 00h)
- ;
- ; This code is executed when a BIOS setmode call is made. It must
- ; predict which mode table the BIOS will use, so the BIOS decision
- ; logic is duplicated here.
- ;
- ; ENTRY
- ; SaveAX = original ax on entry with mode in al
- ; ds = cs
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, si, ds, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- SetMode proc near
- xor ax,ax
- mov ds,ax
- assume ds:INTVEC
- mov al,byte ptr [EquipFlag] ; Get planar switch setting
- mov ah,byte ptr [SaveAX] ; AH = mode
- and ah,01111111b ; Reset noclear bit
- test [Info],00000010b ; If EGA has color monitor
- jz smNoMonochrome ; skip mono tests
- test al,030h ; If default video is color,
- jnz smNoChange ; get out now
- mov al,0B4h ; IO addr = 3Bx
- cmp ah,00Fh ; If mono hi-res graphics,
- je @F ; do it
- mov ah,007h ; Else force mono alpha
- jmp short @F ; do it
- smNoMonochrome:
- test al,030h ; If default video mono,
- jz smNoChange ; get out now
- mov al,0D4h ; IO addr = 3Dx
- @@:
- push ax ; Save video mode
- call ChangeRegs ; Initialize shadow maps
- assume ds:CODE
- pop ax ; Recover mode
- push bx ; We need it
- mov bx,0FF01h ; Assume mono 8x14 font
- cmp [fVga],FALSE ; Do we have a VGA Card?
- je @F ; No - skip
- mov bl,4 ; Assume mono 8x16 font
- @@:
- cmp ah,7 ; If mode is mono alpha,
- je smDoFonts ; do it
- mov bl,0FFh ; Assume no fonts (graphics)
- cmp ah,3 ; If mode is graphics,
- ja smDoFonts ; do it
- mov bl,001h ; Assume 8x14 font
- cmp [fVga],FALSE ; Do we have a VGA Card?
- je @F ; No - skip
- mov bl,004h ; Assume 8x16 font
- @@:
- call BrstDet ; If 350 scanlines,
- jnc smDoFonts ; do it
- mov bl,2 ; Else show 8x8 font
- smDoFonts:
- mov word ptr [FontBank][0],bx ; Stash bl:bh
- mov word ptr [FontBank][2],0FFFFh ; Stash 0FFh:0FFh
- pop bx
- smNoChange:
- assume ds:nothing
- ret
- SetMode endp
- if CallTableNeeded
- subttl SetCursorType
- page
- ;
- ; SetCursorType - shadow int 10h SetCursorType functionality (subfunction 01h)
- ;
- ; ENTRY
- ; ch = bits 0-4: start scanline for cursor
- ; bits 5-6: visibility attributes
- ; cl = bits 0-4: stop scanline for cursor
- ; ds = cs
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- SetCursorType proc near
- push bx ; Save environment
- push ds ; Save environment
- xor ax,ax
- mov ds,ax
- assume ds:INTVEC
- mov bx,cx ; BX = cursor type
- test [Info],00001000b ; If EGA not active,
- jnz sctStash ; just stash the raw values
- mov al,bh ; AL = raw start
- and al,01100000b ; Extract visibility attributes
- cmp al,00100000b ; If cursor-off flag not set,
- jne @F ; continue
- mov bx,01E00h ; Else emulate cursor off
- jmp short sctStash
- @@:
- test [Info],00000001b ; If not emulating cursor,
- jnz sctStash ; just stash the raw values
- cmp [CrtMode],3 ; If not alpha mode,
- ja sctNoBump2 ; avoid special alpha tests
- call BrstDet ; If 200 lines,
- jc sctNoBump2 ; avoid 350 line heuristics
- mov al,005h ; Magic number
- cmp bh,al ; If start < 5,
- jb @F ; leave it alone
- add bh,al ; Else bump it up
- @@:
- cmp bl,al ; If stop < 5,
- jb sctNoBump2 ; leave it alone
- add bl,al ; Else bump it up
- sctNoBump2:
- inc bl ; Bump stop
- or bh,bh ; If start = 0,
- jz @F ; check for wraparound
- cmp bl,byte ptr [Points] ; If stop < char cell height,
- jb @F ; proceed to final test
- xor bl,bl ; Else stop = 0
- @@:
- mov ax,bx ; Get copy into ax
- sub al,ah
- cmp al,16 ; If stop - start != magic
- jne sctStash ; continue
- inc bl ; Else bump stop
- sctStash:
- pop ds ; Restore environment
- assume ds:CODE
- xchg bh,bl ; Flip start/stop
- mov word ptr [CRTCRegs][10],bx ; Stash computed value
- pop bx ; Restore environment
- if2 ; Pass 2 of the assembler
- .ERRNZ ($ - Ignore) ; Drop into Ignore
- endif ; Pass 2 of the assembler
- SetCursorType endp
- ;
- ; Ignore - Unsupported device driver calls enter here
- ;
- ; ENTRY
- ; none
- ; EXIT
- ; none
- ; DESTROYS
- ; none
- ; NOTE:
- ; We are using the RET instruction from SetMode above
- ;
- assume cs:CODE, ds:nothing, es:nothing, ss:nothing
- Ignore proc near ; Enter here just to use the ret
- ret
- Ignore endp
- subttl ScrollUpDown
- page
- ;
- ; ScrollUpDown - shadow int 10h Scroll functionality (subfunctions 06h, 07h)
- ;
- ; ENTRY
- ; al = current video mode
- ; ah = static copy of ega info byte
- ;
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- ScrollUpDown proc near
- push bp
- mov bp,sp ; Watch out for stack!
- push bx
- mov bh,byte ptr [bp].userAX ; BH = num lines to scroll
- or bh,bh ; If bh = 0,
- jz sudSetSeq ; only change sequencer
- mov bl,dh ; BL = lower row of window
- sub bl,ch ; BL = lower row - upper row
- inc bx ; Make 1-based
- cmp bl,bh ; If size window = num lines,
- je sudSetSeq ; treat as blank whole window
- mov bl,010h ; Assume odd/even addressing
- cmp al,00Fh ; If mode < 0Fh,
- jb @F ; assumption is correct
- test ah,01100000b ; If EGA memory is 64K,
- jz @F ; assumption is correct
- xor bl,bl ; Else use enhanced default
- @@:
- mov [GraphicsRegs][005h],bl ; Stash the default
- sudSetSeq:
- mov [SeqRegs][002h],00Fh ; Stash another default
- pop bx
- pop bp
- ret
- ScrollUpDown endp
- subttl ReadChar
- page
- ;
- ; ReadChar - shadow int 10h ReadChar functionality (subfunction 08h)
- ;
- ; ENTRY
- ; al = current video mode
- ; ah = static copy of ega info byte
- ;
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- ReadChar proc near
- cmp al,00Fh ; If mode < 0Fh,
- mov al,0 ; (reuse al and assume default)
- jb @F ; no more processing needed
- test ah,0110000b ; If EGA memory >64K
- jnz @F ; no more processing needed
- mov al,010h ; Else use crippled default
- @@:
- mov [GraphicsRegs][005h],al ; Put al in r/w mode reg
- ret
- ReadChar endp
- subttl WriteChar
- page
- ;
- ; WriteChar - shadow int 10h WriteChar functionality (subfunctions 09h, 0Ah)
- ;
- ; ENTRY
- ; al = current video mode
- ; ah = static copy of ega info byte
- ;
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- WriteChar proc near
- mov [GraphicsRegs][003h],0 ; Put 000h in data rotate reg
- mov [SeqRegs][002h],00Fh ; Put 00Fh in map mask reg
- scpGetOut: ; Mind if we use your ret? Thanks.
- assume ds:nothing
- ret
- WriteChar endp
- subttl SetCGAPalette
- page
- ;
- ; SetCGAPalette - shadow int 10h SetCGAPalette functionality (subfunction 0Bh)
- ;
- ; SetCGAPalette is a quirky function, even on a CGA system. Note the
- ; following points carefully:
- ;
- ; 1. When using bh = 0 to set background/overscan, the call will fall
- ; through to the bh = 1 code because bit 4 is the palette intensity
- ; which must be combined with the current palette selection. Thus
- ; when making a set background call, you are also implicitly making
- ; a set palette intensity call (subject to constraints that follow).
- ;
- ; 2. In alpha modes, you may only set the overscan color if you are in
- ; a CGA compatible (200 lines, 15KHz) sweep mode. Attempting to do
- ; this in 350 line alpha will cause display problems and therefore is
- ; a nop in this function. It is also meaningless to set the palette
- ; and the background color in either alpha sweep mode, and thus is a
- ; nop.
- ;
- ; ENTRY
- ; bh = 0: set background/overscan color
- ; bl = bits 0-3: irgb color for background/overscan
- ; bit 4: palette intensity
- ; bits 5-7: unused
- ; bh = 1: set foreground palette
- ; bl = 0: set palette 0 (green/red/brown)
- ; 1: set palette 1 (cyan/magenta/white)
- ; ds = cs
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, si, ds, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- SetCgaPalette proc near
- xor ax,ax
- mov ds,ax
- assume ds:INTVEC
- cmp byte ptr [Addr6845],0B4h; If mono active,
- je scpGetOut ; get out
- test [Info],00000010b ; If EGA has no color monitor,
- jnz scpGetOut ; get out
- mov ah,[CrtMode] ; AH = video mode
- mov al,[CrtPalette] ; AL = CGA palette byte
- mov si,cs ; DS = Code segment
- mov ds,si ; Two instructions needed
- assume ds:CODE
- push bx
- or bh,bh ; If bh != 0,
- jnz scpPal ; go set CGA palette colors
- and al,11100000b ; Clear old backgnd, pal intense
- and bl,00011111b ; Isolate new backgnd, pal int
- or al,bl ; AL = new palette byte
- mov bh,bl ; Get a copy into bh
- shl bl,1 ; Shift intensity into position
- and bx,0000011100010000b ; And isolate it
- ; Isolate rgb in bh
- or bh,bl ; BH = EGA compatible background
- cmp ah,3 ; If in graphics mode,
- ja @F ; do background and overscan
- call BrstDet ; If 200 lines,
- jc scpOverScan ; do overscan only
- jmp short scpX ; Else nothing left to do
- @@:
- mov [AttrRegs][000h],bh ; Stash background
- scpOverScan:
- mov [AttrRegs][011h],bh ; Stash overscan
- mov bl,al ; Recover new palette byte
- and bl,00100000b ; Isolate palette bit
- ifdef OS2
- rol bl,3 ; And get into bit 0
- else ; NOT OS2
- rol bl,1 ; And get into bit 0
- rol bl,1
- rol bl,1
- endif ; NOT OS2
- scpPal:
- cmp ah,3 ; If in alpha mode,
- jbe scpX ; don't bother with palettes
- and bl,00000001b ; Only allow palettes 0 and 1
- and al,00010000b ; Isolate palette intensity bit
- or al,bl ; Or intensity into palette
- or al,2 ; Green (2) or cyan (3)
- mov [AttrRegs][001h],al ; Stash color 1
- inc ax ; Red (4) or magenta (5)
- inc ax ; "
- mov [AttrRegs][002h],al ; Stash color 2
- inc ax ; Brown/yellow (6) or white (7)
- inc ax ; "
- mov [AttrRegs][003h],al ; Stash color 3
- scpX:
- pop bx
- ret
- SetCgaPalette endp
- subttl WriteDot
- page
- ;
- ; WriteDot - shadow int 10h WriteDot functionality (subfunction 0Ch)
- ;
- ; ENTRY
- ; al = current video mode
- ; ah = static copy of ega info byte
- ;
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- WriteDot proc near
- mov al,0FFh
- mov [GraphicsRegs][003h],ah ; Put 000h in data rotate reg
- mov [GraphicsRegs][008h],al ; Put 0FFh in bit mask reg
- mov [SeqRegs][002h],al ; Put 0FFh in map mask reg
- ret
- WriteDot endp
- subttl ReadDot
- page
- ;
- ; ReadDot - shadow int 10h ReadDot functionality (subfunction 0Dh)
- ;
- ; ENTRY
- ; al = current video mode
- ; ah = static copy of ega info byte
- ;
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- ReadDot proc near
- push bx
- mov bl,003h ; Assume >64K or modes 0Dh/0Eh
- cmp al,00Fh ; If mode < 0Fh,
- jb @F ; assumption is correct
- test ah,01100000b ; If EGA memory > 64K,
- jnz @F ; assumption is correct
- dec bx ; Else use crippled default
- @@:
- mov [GraphicsRegs][004h],bl ; Put in read map reg
- pop bx
- ret
- ReadDot endp
- subttl SetEGAPalette
- page
- ;
- ; SetEGAPalette - shadow int 10h SetEGAPalette functionality (subfunction 10h)
- ;
- ; ENTRY
- ; (Source - Direct quote from IBM Enhanced Graphics Adapter manual)
- ; SubFunctions:
- ; (AL) = 0 Set individual palette register
- ; BL = Palette register to be set
- ; BH = Value to set
- ;
- ; AL = 1 Set overscan register
- ; BH = Value to set
- ;
- ; AL = 2 Set all palette register and overscan
- ; ES:BX points to a 17 byte table
- ; Bytes 0 - 15 are the palette values, respectively
- ; Byte 16 is the overscan value
- ;
- ; AL = 3 Toggle intensity/blinking bit
- ; BL - 0 Enable intensity
- ; BL - 1 Enable blinking
- ;
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, si, ds, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- SetEgaPalette proc near
- push bp
- mov bp,sp
- xor ax,ax
- mov ds,ax
- assume ds:INTVEC
- mov al,0D4h ; Assume color
- test [Info],00000010b ; If EGA has color monitor,
- jz @F ; go check Addr6845
- mov al,0B4h ; Else try mono
- @@:
- cmp byte ptr [Addr6845],al ; If no agreement with Addr6845,
- jne sepX0 ; get out
- push bx
- mov al,byte ptr [bp].userAX ; AL = original subfunction
- xor ah,ah ; Allows dec ax instruction
- or al,al ; If al != 0 (set one reg),
- jnz @F ; try next subfunction
- cmp bl,NumAttrRegs - 1 ; If user gave us bogus index,
- ja sepX1 ; get out or we'll lunch
- mov al,bh ; Copy data
- xor bh,bh ; Zero bh for the index
- mov [AttrRegs][bx],al ; Stash it
- jmp short sepX1
- @@:
- dec ax ; If al != 1 (set overscan reg),
- jnz @F ; try next subfunction
- mov [AttrRegs][011h],bh ; Stash overscan reg
- jmp short sepX1
- @@:
- push es
- dec ax ; If al != 2 (set all regs),
- jnz @F ; try next subfunction
- push cx
- push di
- mov ax,es
- mov ds,ax ; DS = ES
- assume ds:nothing
- mov ax,cs
- mov es,ax ; ES = CS
- assume es:CODE
- mov si,dx ; DS:SI -> src table
- mov di,offset AttrRegs ; ES:DI -> AttrReg array
- mov cx,8 ; Do first 16 bytes
- rep movsw
- inc di ; Bump past mode control
- movsb ; Stash overscan
- pop di
- pop cx
- jmp short sepX
- @@:
- assume ds:INTVEC, es:nothing
- dec ax ; If al != 3 (toggle blink),
- jnz sepX ; get out
- ;
- ; Legal values of bl (0 or 1) should be used to act NOT on the current
- ; setting of the mode reg, but on the default value pointed to by the parm
- ; ptr in the save ptr table. Illegal values for bl cause this reg to be
- ; restored to the default value given by the parm ptr. See IBM EGA BIOS
- ; pg. 148
- ;
- mov ah,[CrtMode] ; AH = video mode
- call MakeBase
- assume es:nothing
- mov al,es:[si][51] ; Get default attr mode value
- or bl,bl ; If bl != 0 (reset bit)
- jnz @F ; try next subfunction
- and al,11110111b ; Reset blink bit
- jmp short sepStoreBit
- @@:
- dec bl ; If bl still not 0,
- jnz sepStoreBit ; give'em a default
- or al,00001000b ; Set blink bit
- sepStoreBit:
- mov [AttrRegs][010h],al
- sepX:
- assume ds:nothing, es:nothing
- pop es
- assume es:nothing
- sepX1:
- pop bx
- sepX0:
- assume ds:INTVEC, es:nothing
- pop bp
- ret
- SetEgaPalette endp
- subttl DownloadFont
- page
- ;
- ; DownloadFont - shadow int 10h DownloadFont functionality (subfunction 11h)
- ;
- ; ENTRY
- ; (Source - Direct quote from IBM Enhanced Graphics Adapter manual)
- ; SubFunctions:
- ; Note: This call will initiate a mode set, completely
- ; resetting the video environment but maintaining
- ; the regen buffer.
- ;
- ; AL = 00 User alpha load
- ; ES:BP - Pointer to user table
- ; CX - Count to store
- ; DX - Character offset into table
- ; BL - Block to load
- ; BH - Number of bytes per character
- ; AL = 01 ROM monochrome set
- ; BL - Block to load
- ; AL = 02 ROM 8x8 double dot
- ; BL - Block to load
- ; AL = 03 Set block specifier
- ; BL - Char gen block specifier
- ; D3-D2 Attr bit 3 one, char gen 0-3
- ; D1-D0 Attr bit 3 zero, char gen 0-3
- ; Note: When using AL = 03 a function call
- ; AX = 1000H
- ; BX = 0712H
- ; is recommended to set the color planes
- ; resulting in 512 characters and eight
- ; consistant colors
- ;
- ; Note : The following interface (AL=1X) is similar in function
- ; to (AL=0X) except that :
- ; - Page zero must be active
- ; - Points (bytes/char) will be recalculated
- ; - Rows will be calculated from the following:
- ; INT((200 or 350) / points) - 1
- ; - CRT_LEN will be calculated from :
- ; (rows + 1) * CRT_COLS * 2
- ; - The CRTC will be reprogrammed as follows :
- ; R09H = points - 1 Max scan line
- ; R09H done only in mode 7
- ; R0AH = points 2 Cursor start
- ; R0BH = 0 Cursor end
- ; R12H = Vert disp end
- ; ((rows + 1) * points) - 1
- ; R14H = points Underline loc
- ;
- ; The above register calculations must be close to the
- ; original table values or undetermined results will
- ; occur.
- ;
- ; Note : The following interface is designed to be
- ; called only immediately after a mode set has
- ; been issued. Failure to adhere to this practice
- ; may cause undetermined results.
- ;
- ; AL = 10 User alpha load
- ; ES:BP - Pointer to user table
- ; CX - Count to store
- ; DX - Character offset into table
- ; BL - Block to load
- ; BH - Number of bytes per character
- ; AL = 11 ROM monochrome set
- ; BL - Block to load
- ; AL = 12 ROM 8x8 double dot
- ; BL - Block to load
- ;
- ; Note : The following interface is designed to be
- ; called only immediately after a mode set has
- ; been issued. Failure to adhere to this practice
- ; may cause undetermined results.
- ;
- ; AL = 20 User graphics chars INT 01FH (8x8)
- ; ES:BP - Pointer to user table
- ; AL = 21 User graphics chars
- ; ES:BP - Pointer to user table
- ; CX - Points (bytes per character)
- ; BL - Row specifier
- ;
- ; BL = 0 User
- ; DL - Rows
- ; BL = 1 14 (0EH)
- ; BL = 2 25 (19H)
- ; BL = 3 43 (28H)
- ;
- ; AL = 22 ROM 8 x 14 set
- ; BL - Row specifier
- ; AL = 23 ROM 8 x 8 double dot
- ; BL - Row specifier
- ;
- ; AL = 30 Information
- ; CX - Points
- ; DL - Rows
- ; BH - 0 Return current INT 1FH Ptr
- ; ES:BP - Ptr to table
- ; BH - 1 Return current INT 44H Ptr
- ; ES:BP - Ptr to table
- ; BH - 2 Return ROM 8 x 14 Ptr
- ; ES:BP - Ptr to table
- ; BH - 3 Return ROM double dot Ptr
- ; ES:BP - Ptr to table
- ; BH - 4 Return ROM double dot Ptr (TOP)
- ; ES:BP - Ptr to table
- ; BH - 5 Return ROM alpha alternate 9 x 14
- ; ES:BP - Ptr to table
- ;
- ; EXIT
- ; None
- ;
- ; DESTROYS
- ; AX, SI
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- DownloadFont proc near
- push bp ; Save environment
- mov bp,sp
- mov al,byte ptr [bp].userAX ; Recover original subfunction
- cmp al,20h ; If not one of the alpha loads,
- jae dfX0 ; get out
- cmp al,3 ; If only changing banks,
- je dfSetBlock ; go do it
- and al,00001111b ; Else extract sub-subfunction
- cmp al,3 ; If not 0, 1, or 2,
- jae dfX0 ; get out
- mov si,bx ; Get row specifier
- and si,000000000000011b ; Extract font bank
- mov byte ptr [FontBank][si],al ; Stash font id in table
- xor ax,ax
- mov ds,ax ; DS = 0
- assume ds:INTVEC
- mov ah,[CrtMode] ; Get current video mode
- push bx ; Save environment
- mov bl,ah ; Save a copy for later
- mov al,byte ptr [Addr6845] ; Get low byte CRTC io address
- call ChangeRegs ; Re-initialize all regs
- assume ds:CODE
- mov al,byte ptr [bp].userAX ; Get original subfunction
- sub al,010h ; Check 1x series
- js dfX ; If not 1x series, we're done
- jz dfSetUnderLine ; If al was 10h, bh set by user
- mov bh,14 ; Assume 8x14 font
- cmp [fVga],FALSE ; Do we have a VGA Card?
- je @F ; No - skip
- mov bh,16 ; Assume 8x16 font
- @@:
- dec al ; If al was 11h,
- jz dfSetUnderLine ; go check underline
- mov bh,008h ; Assume 8x8 font
- dec al ; If al was not 12h,
- jnz dfX ; then invalid code
- dfSetUnderLine:
- cmp bl,007h ; If not mono alpha,
- jne @F ; don't set underline
- mov [CRTCRegs][014h],bh ; Set underline position
- @@:
- dec bh ; Make 0-based
- mov [CRTCRegs][009h],bh ; Set last char line
- mov ax,350 ; Assume 350 total scan lines
- cmp bl,003h ; If not color alpha,
- ja @F ; skip special alpha tests
- call BrstDet ; If 350 lines,
- jnc @F ; our assumption was good
- mov ax,200 ; Else show 200 lines
- @@:
- inc bh ; Make char lines 1-based
- div bh
- mul bh
- dec ax ; Make total lines 0-based
- mov [CRTCRegs][012h],al ; Stash new vertical total
- dfX:
- pop bx ; Restore environment
- dfX0:
- pop bp ; Restore environment
- ret
- dfSetBlock:
- mov [SeqRegs][003h],bl ; Stash new font bank selection
- pop bp ; Restore environment
- ret
- DownloadFont endp
- endif ; CallTableNeeded
- subttl Read Register
- page
- ;
- ; ReadReg - Read a single EGA register from shadow maps
- ;
- ; ENTRY
- ; urAH = 0F0h
- ; bx = register index if register id is indexed chip
- ; ignored if register id is single reg
- ; dx = register id
- ; EXIT
- ; bl = current register data
- ; DESTROYS
- ; ax, si, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- ReadReg proc near
- cmp dl,18h ; Is it Attr reg?
- jne @F ; No - skip
- cmp bl,10h ; Is it palette reg?
- jae @F ; No - skip
- mov [fPalette],dl ; fPalette = TRUE
- @@:
- call UpdateCRTCMap ; Get latest readable regs
- mov si,dx ; Reg id indexes PortTable
- mov si,[PortTable][si].prCurrTable
- cmp dl,NumPtrData * SIZE PortRec ; If not a chip,
- jae @F ; no need for bx
- mov bl,CODE:[si][bx] ; Read indexed chip data
- ret
- @@:
- mov bl,CODE:[si] ; Read a single reg
- ret
- ReadReg endp
- subttl Write Register
- page
- ;
- ; WriteReg - write to a single EGA register and update shadow maps
- ;
- ; ENTRY
- ; urAH = 0F1h
- ; bl = register index if register id is indexed chip
- ; data to be written if register id is single reg
- ; bh = data to be written if register id is indexed chip
- ; = ignored if register id is single reg
- ; dx = register id
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, bh, dx, si, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- WriteReg proc near
- mov ax,bx
- mov si,dx ; Reg id indexes PortTable
- cli ; Disable interrupts
- or [PortTable][si].prModFlag,3
- cmp dl,NumPtrData * SIZE PortRec ; If not a chip,
- mov dx,[PortTable][si].prPortAddr
- mov si,[PortTable][si].prCurrTable
- jae WRegNotPtr ; Just write it directly
- xor bh,bh ; Zero bh for indexing
- mov CODE:[si][bx],ah ; Update shadow map
- cmp dl,AttCtrlAddrReg AND 0FFh ; If not attribute chip,
- jne @F ; Skip special processing
- OutWordAttr ax,NoInts ; Write index/data to AttrAddr
- sti ; Restore interrupt state
- ret
- @@:
- OutWord NoInts,DestroyAX,DestroyDX
- sti ; Restore interrupt state
- ret
- WRegNotPtr:
- mov CODE:[si],al ; Update shadow map
- or [SingleRegMod],3 ; Show a single reg is dirty
- out dx,al ; And finally send out data
- sti ; Restore interrupt state
- ret
- WriteReg endp
- subttl Read Register Range
- page
- ;
- ; ReadRange - read a range of EGA registers from shadow maps
- ;
- ; ENTRY
- ; urAH = 0F2h
- ; dx = register id (must be an indexed chip!)
- ; cl = # of registers to read (must be > 1 !)
- ; ch = starting register index
- ; es:bx -> buffer to put reg data
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, cx, si, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- ReadRange proc near
- cmp dl,18h ; Is it Attr reg?
- jne @F ; No - skip
- cmp ch,10h ; Is it palette reg?
- jae @F ; No - skip
- mov [fPalette],dl ; fPalette = TRUE
- @@:
- call UpdateCRTCMap ; Get latest readable regs
- push di
- mov di,bx ; DI = ptr to user table
- mov si,dx ; Reg id indexes PortTable
- mov si,[PortTable][si].prCurrTable
- xor ax,ax ; AX = 0
- xchg al,ch ; AX = reg offset, ch = 0
- add si,ax ; Adjust si for offset
- shr cx,1 ; CX now has reg count
- rep movsw ; Blast shadow map to user table
- rcl cx,1
- rep movsb
- pop di
- ret
- ReadRange endp
- subttl Write Register Range
- page
- ;
- ; WriteRange - write to a range of EGA registers and update shadow maps
- ;
- ; ENTRY
- ; urAH = 0F3h
- ; dx = register id (must be an indexed chip!)
- ; cl = # of registers to write (must be > 1 !)
- ; ch = starting register index
- ; es:bx -> buffer to get reg data
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, bx, dx, si, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- WriteRange proc near
- push di
- push es
- mov si,bx ; SI = ptr to user table
- mov di,dx ; Reg id indexes PortTable
- mov bx,offset PortTable ; Start at beginning
- cli ; Disable interrupts
- or code:[bx][di].prModFlag,3
- mov dx,code:[bx][di].prPortAddr
- mov di,code:[bx][di].prCurrTable ; DI = ptr to shadow map
- mov ax,es ; XCHG ES,DS
- mov bx,ds
- mov es,bx
- assume es:CODE
- mov ds,ax
- assume ds:nothing
- xor ax,ax ; AX = 0
- xchg al,ch ; AX = reg offset, ch = 0
- add di,ax ; Adjust di for offset
- push cx ; CX now has reg count
- shr cx,1
- rep movsw ; Blast table to shadow map
- rcl cx,1
- rep movsb
- mov ds,bx ; DS = CS
- assume ds:CODE
- pop cx ; Restore reg count
- sub di,cx ; Rewind di
- cmp dl,AttCtrlAddrReg AND 0FFh ; If not attribute chip,
- jne WRangeNotAttr ; Skip special processing
- @@:
- mov ah,CODE:[di] ; AH = reg data, al = reg index
- IODelay
- OutWordAttr ,NoInts ; Write index/data to AttrAddr
- inc di
- inc ax ; INC reg index (al)
- loop @B
- jmp short @F ; All done for this chip
- WRangeNotAttr:
- mov ah,CODE:[di] ; AH = reg data, al = reg index
- IODelay
- OutWord NoInts
- inc di
- inc ax ; INC reg index (al)
- loop WRangeNotAttr
- @@:
- pop es
- assume es:nothing
- pop di
- sti ; Restore interrupt state
- ret
- WriteRange endp
- subttl Read Register Set
- page
- ;
- ; ReadSet - read a set of EGA registers from shadow maps
- ;
- ; ENTRY
- ; urAH = 0F4h
- ; cx = # of registers to read (must be > 1 !)
- ; es:bx -> buffer of contiguous SetRec
- ; structures, one for each register
- ; to be read
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, cx, si, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- ReadSet proc near
- push cx ; Save count
- push bx ; Save buffer address
- LookForPalette:
- cmp byte ptr es:[bx][0],18h ; Is it Attr reg?
- jne @F ; No - skip
- cmp byte ptr es:[bx][2],10h ; Is it palette reg?
- jae @F ; No - skip
- mov [fPalette],cl ; fPalette = TRUE
- jmp short LookForPaletteDone
- @@:
- add bx,4 ; Next entry
- loop LookForPalette ; Continue through the list
- LookForPaletteDone:
- pop bx ; Restore buffer address
- pop cx ; Restore count
- call UpdateCRTCMap ; Get latest readable regs
- push di
- mov di,bx
- @@:
- mov si,es:[di].srPortNum ; SI = reg id
- mov si,[PortTable][si].prCurrTable ; SI -> our shadow map
- mov al,es:[di].srPtr ; AL = reg index
- cbw
- add si,ax ; Adjust si for index
- add di,srData ; DI -> stash location
- movsb
- loop @B
- pop di
- ret
- ReadSet endp
- subttl Write Register Set
- page
- ;
- ; WriteSet - write to a set of EGA registers and update shadow maps
- ;
- ; ENTRY
- ; urAH = 0F5h
- ; cx = # of registers to write (must be > 1 !)
- ; es:bx -> buffer of contiguous SetRec
- ; structures, one for each register
- ; to be written
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, cx, si, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- WriteSet proc near
- push di
- push dx
- mov di,bx
- cli ; Disable interrupts
- WSetNextEntry:
- mov si,es:[di].srPortNum ; SI = reg id
- or [PortTable][si].prModFlag,3
- mov dx,[PortTable][si].prPortAddr
- mov si,[PortTable][si].prCurrTable ; SI -> our shadow map
- mov al,es:[di].srPtr ; AL = reg index
- cbw
- add si,ax ; Adjust si for index
- mov ah,es:[di].srData ; AH = reg data
- mov CODE:[si],ah ; Update shadow map
- cmp dl,AttCtrlAddrReg AND 0FFh ; If not attribute chip,
- jne WSetNotAttr ; Skip special processing
- OutWordAttr ax,NoInts ; Write index/data to AttrAddr
- jmp short @F ; All done for this register
- WSetNotAttr:
- OutWord NoInts,DestroyAX,DestroyDX
- @@:
- add di,SIZE SetRec ; Bump to next record
- loop WSetNextEntry
- pop dx
- pop di
- sti ; Restore interrupt state
- DDefExit: ; Mind if we use your ret? Thanks.
- ret
- WriteSet endp
- subttl Define Default Shadow Maps
- page
- ;
- ; DefineDefault - load up default shadow maps from user buffer
- ;
- ; ENTRY
- ; urAH = 0F7h
- ; cx = 'TH' if user wants to program VGA specific color select
- ; register. This was added version 2.07.12.
- ; dx = register id
- ; If high bit of dx set, an internal RevertDefault will
- ; occur after the default shadow maps have been updated.
- ;
- ; es:bx -> buffer of default values for specified register id.
- ; If register id is a chip, all values must be present.
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, bx, si, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- DefineDefault proc near
- push di
- push cx
- mov di,dx ; Reg id indexes PortTable
- and di,7FFFh ; Strip "revert" flag
- mov si,cx ; SI = Possible special VGA code
- xor ch,ch ; No high byte
- mov cl,[PortTable][di].prNumRegs
- cmp [fVGA],ch ; Are we on a VGA?
- je @F ; No - skip
- cmp di,18h ; Is it the attribute controller regs?
- jne @F ; No - skip
- cmp si,'TH' ; Is it code for VGA color select?
- je @F ; Yes - skip
- dec cx ; Don't deal with color select register
- @@:
- mov si,bx ; SI -> user buffer
- mov al,1
- mov bx,offset PortTable ; Start at beginning
- or code:[bx][di].prModFlag,al
- or [SingleRegMod],al
- mov di,code:[bx][di].prDefTable ; DI -> default shadow map
- mov ax,es ; XCHG ES,DS
- mov bx,ds
- mov es,bx
- assume es:CODE
- mov ds,ax
- assume ds:nothing
- shr cx,1
- rep movsw ; Blast to default shadow map
- rcl cx,1
- rep movsb
- mov es,ax ; Recover old es
- assume es:NOTHING
- mov ds,bx ; DS = CS
- assume ds:CODE
- pop cx
- pop di
- or dh,dh ; If not "revert" flag,
- jns DDefExit ; just leave
- ; Else make defaults active
- if2 ; Pass 2 of the assembler
- .errnz ($ - RevertDefault) ; Drop into RevertDefault
- endif ; Pass 2 of the assembler
- DefineDefault endp
- subttl Revert to Default Shadow Maps
- page
- ;
- ; RevertDefault - blast default shadow maps to EGA and update shadow maps
- ;
- ; ENTRY
- ; urAH = 0F6h
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, si, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- RevertDefault proc near
- push di ; Save environment
- push es ; Save environment
- push dx ; Save environment
- push cx ; Save environment
- push bx ; Save environment
- mov ax,ds
- mov es,ax ; ES = DS = CS
- assume es:CODE
- mov bx,offset PortTable ; Start at beginning
- xor cx,cx
- RDefNextPtrData:
- test CODE:[bx].prModFlag,1 ; If dirty flag = 0,
- jz ToRDefNotModified ; done with this map
- mov CODE:[bx].prModFlag,2 ; Else clear dirty flag
- mov cl,CODE:[bx].prNumRegs
- mov di,CODE:[bx].prCurrTable
- mov si,CODE:[bx].prDefTable
- mov dl,cl ; Save count
- shr cx,1
- rep movsw ; Blast default map to current map
- rcl cx,1
- rep movsb
- mov al,ch ; CH still 0 from above
- mov cl,dl ; Restore count
- sub si,cx ; Rewind si
- mov dx,CODE:[bx].prPortAddr
- cmp dl,AttCtrlAddrReg AND 0FFh ; If not attribute chip,
- jne RDefNotAttr ; Skip special processing
- pushf ; Save interrupt flag state
- WaitRetrace ; Also disables interrupts
- mov al,ch ; Restore index (0)
- mov dl,AttCtrlAddrReg AND 0FFh ; Restore dx to AttrAddr
- @@:
- mov ah,CODE:[si] ; Get data
- OutWordAttr ,NoInts ; Write index/data to AttrAddr
- IODelay
- inc si
- inc ax
- loop @B
- mov al,PaletteAddressSource ; Since dx still has AttrAddr,
- out dx,al ; Enable video now
- IOdelay
- InitFlipFlop NoSaveAX ; Be sure to reset the flip-flop
- popf ; Restore interrupt flag state
- ToRDefNotModified:
- jmp short RDefNotModified ; All done for Attr chip
- RDefNotAttr:
- mov ah,CODE:[si]
- cmp dl,(EGA_BASE + SEQ_ADDR) AND 0FFh ; SAS 06/09/86
- jne RDefNotAttr1 ; SAS 06/09/86
- cmp al,SeqClMReg ; SAS 06/09/86
- je @F ; SAS 06/09/86
- RDefNotAttr1:
- cmp dl,(EGA_BASE + GRAF_CONT) AND 0FFh
- jne RDefOut
- cmp al,GRAF_MISC_REG
- je @F
- RDefOut:
- OutWord
- @@:
- inc si
- inc ax
- loop RDefNotAttr
- RDefNotModified:
- add bx,SIZE PortRec
- cmp bx,offset PortTable + (NumPtrData * SIZE PortRec)
- jnb @F
- jmp RDefNextPtrData
- @@:
- InitFlipFlop NoSaveAX ; Reset FF and get FeatAddr!
- IOdelay
- test [SingleRegMod],1 ; If singles dirty flag = 0,
- jz @F ; we're done
- mov [SingleRegMod],2 ; Clear singles dirty flag
- mov al,[DefFeatureReg]
- mov [FeatureReg],al ; Since dx still has FeatAddr,
- out dx,al ; program it now
- IOdelay
- mov dl,MiscAddr AND 0FFh ; Deal with MiscOut reg
- mov al,[DefMiscOutReg]
- mov [MiscOutReg],al
- out dx,al
- IOdelay
- cmp [fVga],CL ; If VGA is present,
- jne @F ; skip GR1&2 processing
- mov dl,Gr1PosAddr AND 0FFh
- mov al,[DefGR1PosReg]
- mov [GR1PosReg],al
- out dx,al
- IOdelay
- mov dl,Gr2PosAddr AND 0FFh
- mov al,[DefGR2PosReg]
- mov [GR2PosReg],al
- out dx,al
- @@:
- pop bx ; Restore environment
- pop cx ; Restore environment
- pop dx ; Restore environment
- pop es ; Restore environment
- assume es:nothing
- pop di ; Restore environment
- ret
- RevertDefault endp
- subttl Get Default Shadow Maps
- page
- ;
- ; GetDefault - dump default shadow maps to user buffer
- ;
- ; ENTRY
- ; urAH = 0F8h
- ; dx = register id
- ; es:bx -> buffer to receive default values
- ; If register id is a chip, table must have room for all
- ; regs in chip.
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, si, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- GetDefault proc near
- push di
- push cx
- mov di,bx ; DI -> user buffer
- mov si,dx ; Reg id indexes PortTable
- xor ch,ch
- mov cl,[PortTable][si].prNumRegs
- mov si,[PortTable][si].prDefTable ; SI -> default shadow map
- shr cx,1
- rep movsw ; Blast default map to user buffer
- rcl cx,1
- rep movsb
- pop cx
- pop di
- ret
- GetDefault endp
- subttl EGA Context Functions
- page
- ;
- ; ContextInfo - Save/Restore full EGA.SYS context information
- ;
- ; This entrypoint was added for TSR's and environment managers like
- ; Windows and Presentation Manager that must be able to save/restore the
- ; EGA.SYS context information as well as the state of the EGA hardware.
- ; Without this functionality, Windows is unable to properly preserve the
- ; state of variables internal to EGA.SYS such as the dirty flags and/or
- ; the state of the EGA data latches. It also provides software
- ; developers a more rapid mechanism for context switching the EGA, as it
- ; dispenses with the need to make numerous Read/WriteRange and
- ; Read/WriteSet calls.
- ;
- ; Secondly, there are two types of context information that developers
- ; must implicitly handle: 1) the screen data, and 2) the font data (for
- ; alpha modes). Since shadowing the EGA registers alone does not
- ; provide sufficient information for efficiently handling downloaded
- ; font data, a call has been added to retrieve the current status of
- ; each alpha font bank programmed through int 010h, subfunction 011h.
- ;
- ; ENTRY
- ; urAH = 0F9h
- ; urAL = 000h GetContextSize
- ; = 001h SaveContext
- ; = 002h RestoreContext
- ; = 003h GetFontInfo
- ; = 004h GetInBiosFlag
- ;
- ; other regs per function being called
- ; EXIT
- ; per function being called
- ; DESTROYS
- ; ax, si for this particular procedure,
- ; otherwise, per function being called
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- ContextInfo proc near
- push bp ; Save environment
- mov bp,sp ; Set up stack addressing
- mov al,byte ptr [bp].userAX ; Get old ax from stack
- pop bp ; Restore environment
- cmp al,MaxContextCall ; If not one of our subfunctions,
- ja ciX ; get out now
- xor ah,ah ; Reset ah for dispatch
- shl ax,1 ; *2 for word addresses
- mov si,ax
- jmp [ContextTable][si] ; MUST jmp for stack integrity
- ContextInfo endp
- ;
- ; GetContextSize - return size in bytes needed to save EGA.SYS context
- ;
- ; ENTRY
- ; none
- ; EXIT
- ; userAX = size in bytes needed to save EGA.SYS context
- ; DESTROYS
- ; AX
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- GetContextSize proc near
- push bp ; Save environment
- mov bp,sp ; Set up stack addressing
- mov [bp].userAX,SizeEGAContext ; Stash size on stack for ax
- pop bp ; Restore environment
- ciX: ; Mind if we use your ret? Thanks.
- ret
- GetContextSize endp
- page
- ;
- ; SaveContext - dump current EGA.SYS context data to user buffer
- ;
- ; If an app or TSR must change the EGA regs, but wants to restore
- ; EGA.SYS and the hardware to the original state on entry, it should
- ; first call GetContextSize. Based on the value returned, it should
- ; allocate the necessary buffer (possibly on the stack), set es:bx to
- ; point to it, and issue this call. The app is then free to issue other
- ; EGA.SYS or int 10h calls at will. When finished, it should call
- ; RestoreContext data with a pointer to the saved context data. Since
- ; the current state of the dirty flags is included in the context data,
- ; these too will be properly restored.
- ;
- ; Note that apps must not assume a given size for the context data.
- ; An app should call GetContextSize at least once, beforehand, to
- ; determine how much memory to provide. Also, apps must not assume a
- ; given structure for the context data or modify it in any way.
- ;
- ; If an app or TSR plans to make semi-permanent changes to the EGA regs,
- ; it may avoid the Save/Restore context calls. EGA.SYS will shadow any
- ; int 10h calls that modify the EGA regs, updating both the default and
- ; current shadow maps, but not touching any of the dirty flags. This
- ; allows the interrupted app to continue making RevertDefault calls, yet
- ; keeps the new changes in effect until the app explicitly changes a reg
- ; which the TSR modified.
- ;
- ; ENTRY
- ; es:bx -> user save area buffer for EGA context
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, si, ds, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- SaveContext proc near
- push cx ; Save environment
- push dx ; Save environment
- push di ; Save environment
- push bx ; Save environment
- call GetLatchLocation ; Get EGA/VGA latch save location
- or di,di ; Are we in text mode?
- jz @F ; Yes - skip
- ;
- ; Save the EGA/VGA latches
- ;
- mov ah,ReadRegNum ; Read 1 register
- mov dx,10h ; Graphics port register
- mov bx,5 ; Index 5
- int 10h ; Get it
- mov si,ds ; Find a place for our byte
- ; in vram, past visible memory
- mov dx,egamem
- mov ds,dx
- assume ds:egamem
- mov ax,(MR_SET shl 8) or GRAF_MODE_REG ; Set mode reg
- ; to writethrough (mode 1)
- mov dx,EGA_BASE + GRAF_CONT ; Set the port
- OutWord ,DestroyAX,DestroyDX
- mov egamem:[di],al ; Actually write to vram and store
- ; latches at offset [bx]
- mov bh,bl ; Position it properly
- mov bl,5 ; Index 5
- mov ah,WriteRegNum ; Write 1 register
- mov dx,10h ; Graphics port register
- int 10h ; Restore original port value
- mov ds,si
- assume ds:CODE
- ;
- ; Save the EGA/VGA registers
- ;
- @@:
- call UpdateCRTCMap ; Get latest readable regs
- pop bx ; Restore environment
- mov di,bx
- mov si,offset StartEGAContext
- mov cx,SizeEGAContext / 2
- if SizeEgaContext AND 1
- movsb
- endif ; SizeEgaContext AND 1
- rep movsw
- pop di ; Restore environment
- pop dx ; Restore environment
- pop cx ; Restore environment
- ret
- SaveContext endp
- page
- ;
- ; RestoreContext - restore EGA.SYS context data from user buffer
- ;
- ; RestoreContext copies a previously saved EGA context pointed to by
- ; es:bx to the internal data areas of EGA.SYS and updates the hardware
- ; to reflect the restored state. The only caveat is that the state of
- ; the Attribute index/data flip-flop is reset to the "index" state since
- ; SaveContext is unable to save this information. Note that this should
- ; not be a problem if the caller checks the fInBIOS flag before
- ; attempting to reprogram the EGA and if the interrupted application
- ; only uses EGA.SYS or int 010h to modify the hardware. This is because
- ; EGA.SYS and int 010h always reset this flip-flop to the "index" state
- ; on return.
- ;
- ; ENTRY
- ; es:bx -> previously saved EGA context
- ; EXIT
- ; none
- ; DESTROYS
- ; ax, si, ds, flags
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- RestoreContext proc near
- push cx ; Save environment
- push dx ; Save environment
- push di ; Save environment
- push es ; Save environment
- ;
- ; Restore the EGA/VGA latches
- ;
- call GetLatchLocation ; Get EGA/VGA latch save location
- or di,di ; Are we in text mode?
- jz @F ; Yes - skip
- mov dx,egamem
- mov ds,dx
- assume ds:egamem
- mov dx,EGA_BASE + GRAF_ADDR ; Setup for writethrough mode
- mov ax,(DR_SET shl 8) or GRAF_DATA_ROT
- pushf ; Save interrupt flag state
- cli ; No interrupts while changing regs
- OutWord NoInts,DestroyAX
- IOdelay
- mov ax,(0ffh shl 8) or GRAF_BIT_MASK ; Don't mask any bits
- OutWord NoInts,DestroyAX,DestroyDX
- IOdelay
- ; DH already set correctly
- mov dl,SEQ_ADDR ; Enable all planes, set seq
- mov ax,(MM_ALL shl 8) or SEQ_MAP_MASK ; Addr reg to point
- OutWord NoInts,DestroyAX,DestroyDX ; to map mask reg
- popf ; Restore interrupt flag state
- mov al,egamem:[di] ; Actually write to vram to
- ; restore the latches
- @@:
- mov si,bx
- mov di,offset StartEGAContext
- mov ax,es ; ES = CS
- mov dx,cs ; DS = Old ES
- mov es,dx ; "
- assume es:CODE
- mov ds,ax ; Get new clocking mode 1st
- assume ds:nothing
- mov al,ds:[si + offset SeqRegs - offset StartEgaContext + 01h]
- cmp al,CODE:[di + offset SeqRegs - offset StartEgaContext + 01h]
- jne @F ; If same, compare mem mode
- mov al,ds:[si + offset SeqRegs - offset StartEgaContext + 04h]
- cmp al,CODE:[di + offset SeqRegs - offset StartEgaContext + 04h]
- jne @F ; If same, compare misc regs
- mov al,ds:[si + offset GraphicsRegs - offset StartEgaContext + 06h]
- cmp al,CODE:[di + offset GraphicsRegs - offset StartEgaContext + 06h]
- @@:
- mov cx,SizeEGAContext / 2
- if SizeEgaContext AND 1
- movsb
- endif ; SizeEgaContext AND 1
- rep movsw
- pop es ; ES = old ES
- assume es:nothing
- mov ds,dx ; DS = CS
- assume ds:CODE
- mov cl,NumSeqRegs - 2 ; Don't do clocking/memory modes
- mov dh,3 ; "prefix" for port addresses
- mov si,offset SeqRegs
- je @F ; Jump if no changes here
- mov ax,0100h
- mov dl,(EGA_BASE + SEQ_ADDR) AND 0FFh
- pushf ; Save interrupt flag state
- cli ; RAM refresh will be off now!
- OutWord NoInts ; Synchronous reset to sequencer
- IOdelay
- inc ax ; Now select clocking mode reg
- mov ah,CODE:[si + 01h]
- OutWord NoInts,DestroyAX ; Write its new value (in ah)
- IOdelay
- mov al,04h ; Now select memory mode reg
- mov ah,CODE:[si + 04h]
- OutWord NoInts,DestroyAX,DestroyDX ; Write its new value (in ah)
- IOdelay
- mov dl,(EGA_BASE + GRAF_CONT) AND 0FFh
- mov al,06h ; Now select grphx misc reg
- mov ah,[GraphicsRegs + 06h]
- OutWord NoInts,DestroyAX,DestroyDX ; Write its new value, too (ah)
- popf ; Restore interrupt flag state
- @@:
- mov dl,(EGA_BASE + SEQ_ADDR) AND 0FFh ; Setup for seq loop
- mov al,ch ; AL = 0
- recSeqLoop:
- mov ah,CODE:[si]
- IOdelay
- OutWord ; No ints can occur until after
- @@:
- inc si
- inc ax
- cmp al,01h ; Clocking mode reg next?
- je @B ; If so, skip it
- loop recSeqLoop ; Otherwise continue if more
- mov al,cl ; AL = 0
- mov cl,NumGraphicsRegs - 1
- mov si,offset GraphicsRegs
- mov dl,(EGA_BASE + GRAF_CONT) AND 0FFh
- recGrphLoop:
- mov ah,CODE:[si]
- IOdelay
- OutWord
- @@:
- inc si
- inc ax
- cmp al,06h ; Grphx misc reg next?
- je @B ; If so, skip it
- loop recGrphLoop ; Otherwise continue if more
- mov al,cl ; AL = 0
- mov cl,NumCRTCRegs
- mov dl,byte ptr [PortTable][0].prPortAddr
- mov si,offset CRTCRegs
- @@:
- mov ah,CODE:[si]
- IOdelay
- OutWord
- inc si
- inc ax
- loop @B
- mov cl,[PortTable][3 * SIZE PortRec].prNumRegs
- mov si,offset AttrRegs
- pushf ; Save interrupt flag state
- WaitRetrace ; Also disables interrupts
- mov al,ch ; Restore index (0)
- mov dl,AttCtrlAddrReg AND 0FFh ; Restore dx to AttrAddr
- @@:
- mov ah,CODE:[si] ; Get data
- IOdelay
- OutWordAttr ,NoInts ; Write index/data to AttrAddr
- inc si
- inc ax
- loop @B
- mov al,PaletteAddressSource ; Since dx still has AttrAddr,
- IOdelay
- out dx,al ; enable video now
- IOdelay
- InitFlipFlop NoSaveAX ; Reset FF and get FeatAddr!
- popf ; Restore interrupt flag state
- IOdelay
- mov al,[FeatureReg] ; Since dx still has FeatAddr,
- out dx,al ; program it now
- IOdelay
- mov dl,MiscAddr AND 0FFh
- mov al,[MiscOutReg]
- out dx,al
- cmp [fVga],CL ; If VGA is present,
- jne @F ; skip GR1&2 processing
- mov dl,Gr1PosAddr AND 0FFh
- mov al,[GR1PosReg]
- IOdelay
- out dx,al
- IOdelay
- mov dl,Gr2PosAddr AND 0FFh
- mov al,[GR2PosReg]
- out dx,al
- @@:
- pop di ; Restore environment
- pop dx ; Restore environment
- pop cx ; Restore environment
- ret
- RestoreContext endp
- page
- ;
- ; GetLatchLocation - dump current EGA.SYS context data to user buffer
- ;
- ; ENTRY
- ; None
- ; EXIT
- ; If currently in graphics mode
- ; DI -> Latch location
- ; Else (Text mode)
- ; DI = 0
- ; DESTROYS
- ; AX
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- GetLatchLocation proc near
- xor di,di ; Assume text mode
- mov al,[biosmode] ; Get current video mode
- and al,01111111b ; Reset noclear bit
- cmp al,13h ; Is it a mode we can handle?
- ja @F ; No - skip (fake text mode)
- sub al,0dh ; Adjust to zero base
- js @F ; Skip if text mode
- xor ah,ah ; No high byte
- add di,ax ; Position to video mode in table
- mov di,CODE:[di] + offset EGALatchTable ; Get desired latch location
- @@:
- ret
- GetLatchLocation endp
- page
- ;
- ; GetFontInfo - dump current font data in FontInfo format to user buffer
- ;
- ; GetInfo is provided for environments like Windows that need to know
- ; which alpha fonts have been downloaded and which banks they are in.
- ;
- ; This call copies the current EGA.SYS FontInfo structure to a user
- ; buffer pointed to by es:bx. Based on this information, the caller can
- ; determine the need to save alpha font data in plane 2, as well as
- ; determine the most efficient way to do it. For example, font ID's
- ; 001h and 002h need not be saved since a copy exists in the EGA ROM.
- ;
- ; Graphics font data is maintained by the EGA BIOS via int 01Fh and int
- ; 043h and does not exist in the EGA hardware. Since these interrupts
- ; can be directly manipulated for Save/Restore operations, EGA.SYS does
- ; not attempt to record any graphics font information.
- ;
- ; FontInfo format:
- ;
- ; FontInfo struc
- ; fibank0 db ?
- ; fibank1 db ?
- ; fibank2 db ?
- ; fibank3 db ?
- ; FontInfo ends
- ;
- ; where each fiBankx contains a byte defined as follows:
- ;
- ; 000h - user font in specified bank
- ; 001h - 08x14 ROM font in specified bank (Default for EGA)
- ; 002h - 08x08 ROM font in specified bank
- ; 004h - 08x16 ROM font in specified bank (Default for VGA)
- ; 0FFh - empty bank
- ;
- ; ENTRY
- ; es:bx -> user buffer for FontInfo
- ; EXIT
- ; none
- ; DESTROYS
- ; ax
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- GetFontInfo proc near
- mov ax,word ptr [FontBank][0]
- mov es:[bx],ax
- mov ax,word ptr [FontBank][2]
- mov es:[bx][2],ax
- ret
- GetFontInfo endp
- ;
- ; GetInBiosFlag - return segment:offset of the InBiosFlag
- ;
- ; ENTRY
- ; none
- ; EXIT
- ; es:bx -> InBiosFlag
- ; DESTROYS
- ; none
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- GetInBiosFlag proc near
- mov bx,cs
- mov es,bx
- assume es:CODE
- mov bx,offset fInBIOS
- ret
- GetInBiosFlag endp
- subttl InquireDriver
- page
- ;
- ; InquireDriver - return ptr to driver version number
- ;
- ; ENTRY
- ; none
- ; EXIT
- ; es:bx -> DriverInfo data area
- ; DESTROYS
- ; None
- ;
- assume cs:CODE, ds:CODE, es:nothing, ss:nothing
- InquireDriver proc near
- mov bx,ds
- mov es,bx
- assume es:CODE
- mov bx,offset DriverInfo
- ret
- InquireDriver endp
- ifdef Sys
- include int10rtn.inc ; Contains Int10Routine and Int2FRoutine
- ; Also in load.inc for .COM version
- endif ; Sys
- EndOfResidentCode label near
- ;
- ; I N C L U D E S
- ;
- include load.inc
- CODE ends
- end main