📄 ega.asm
字号:
; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -