📄 saveega.asm
字号:
;*
;* CW : Character Windows
;*
;* ega.asm : DOS3 TWIN compatible screen driver
;*
;*****************************************************************************
;* * Special screen save
NonStandard CbSizeVidsCsd
NonStandard FSaveVidsCsd
NonStandard FRestoreVidsCsd
NonStandard SetVideoMode
NonStandard SaveVidDataCsd
NonStandard RestoreVidDataCsd
NonStandard EnableVidsMonitorCsd
;********** CbSizeVidsCsd **********
;* * CSD entry point (see documentation for interface)
cProc CbSizeVidsCsd, <FAR, PUBLIC, ATOMIC>
cBegin CbSizeVidsCsd
mov ax,SIZE EGA_VIDS
mov bx,OFF_lpwDataCsd ;* Data in data segment
test [bx].fvmCurAdap, fvmEGA or fvmVGA or fvm64KEGA or fvmEGAM or fvmMCGA
jnz notCGAVids
sub ax,24 ;for EGA palette settings
jmp short CbSizeExit
notCGAVids:
test [bx].fvmCurAdap, fvmMCGA or fvmVGA
jz CbSizeExit
add ax,255*3 ;for PS2 palette settings
CbSizeExit:
inc ax ;get even cb
and ax,0FFFEh
cEnd CbSizeVidsCsd
;********** FSaveVidsCsd ********
;* entry: pvidsSave = near pointer to VIDS structure
;* pinst = near pointer to INST for new mode
;* * fill *pvidsSave with state of current screen mode (not screen data)
;* exit: AX != 0 if ok, == 0 if error
cProc FSaveVidsCsd, <FAR, PUBLIC, ATOMIC>, <si, di>
parmDP pvidsSave
parmDP pinst
cBegin FSaveVidsCsd
mov di,pvidsSave
mov ah,0Fh
int 10h ;* GetMode and page
and al,07Fh ; clear msb
mov [di].modeVids,al
mov [di].pageVids,bh
mov [di].fClearRegenVids,00H
mov ax,SIZE EGA_VIDS - cbVidsMin ;default EGA
mov bx,OFF_lpwDataCsd ;* Data in data segment
test [bx].fvmCurAdap, fvmEGA or fvmVGA or fvm64KEGA or fvmEGAM or fvmMCGA
jnz notFSCGA
sub ax,24 ;EGA palette regs
jmp short notFSPS2
notFSCGA:
test [bx].fvmCurAdap, fvmMCGA or fvmVGA
jz notFSPS2
add ax,255*3 ;DAC color regs
notFSPS2:
inc ax ;get even cb
and ax,0FFFEh
shr ax,1
mov [di].cwExtraVids,ax
mov ah,3
int 10h ;* GetCursorPos
mov [di].vparmCursorVids,cx
mov ax,ds
mov es,ax
mov dx,di
lea di,[di].rgwCursorPosVids ;* save cursor positions here
push ds
xor ax,ax
mov ds,ax
mov si,BIOS_cursor_posn ;* 8 Cursor positions in BIOS
mov cx,8
rep movsw
pop ds
mov di,dx ; restore di
public saveCGAPal ;UNDONE - remove these two lines
saveCGAPal: ;UNDONE
;
; Assumes bCGABg is immediately before bCGAPal
; and bCGABgVids is immediately before bCGAPalVids
;
.errnz (bCGABgVids+1) - bCGAPalVids
.errnz (bCGABg+1) - bCGAPal
mov ax, word ptr cs:[bCGABg]
mov word ptr [di].bCGABgVids, ax
mov dl, [di].modeVids
cmp dl,40H ;Olivetti
jz @F
test [bx].fvmCurAdap, fvmCGA
jz skipCGA
@@:
;* for CGA only
xor ax,ax
mov es,ax
mov al, byte ptr es:[466H]
mov [di].ayOverScanVids, al
mov ax, 80*25 ; Maybe we can get by just saving what we use (4k b).
cmp dl, 2
je save_not_graphics
cmp dl, 3
je save_not_graphics
mov ax, 8*1024 ; Must mode switch (4,5,6) so must save all of regen(16k b)
cmp dl, 40H ; Is this an Olivetti graphics screen mode?
jne @F
add ax, ax ; Yes, there is twice as much memory to save
@@:
save_graphics:
and [di].fvidsVids,not fvidsChAttr ;graphics modes
save_not_graphics: ;* ax = # of words to swap
mov [di].cwSwapVids,ax
jmp EgaSS_Exit
skipCGA:
test [bx].fvmCurAdap, fvmEGA or fvmVGA or fvm64KEGA or fvmEGAM or fvmMCGA
jz @F
cCall EgaSavePalette ;save palette regs
@@:
push bp
mov ax,1130h ; get info
xor bx,bx
xor cx,cx
int 10h
pop bp
inc dl ; dl = scan lines
mov [di].ayMacVids,dl ; rows
mov [di].ayPointsVids,cl ; cl = number of lines in char
cmp [di].modeVids,4 ;check simple graphics
jb notmode4to6
cmp [di].modeVids,6
ja notmode4to6
mov ax,8*1024 ; Must mode switch (4,5,6) so must save all of regen(16k b)
mov [di].cwSwapVids,ax
and [di].fvidsVids,not fvidsChAttr ;graphics modes
jmp EgaSS_Exit
notmode4to6:
mov ax,80 ;default 80 columns
mov si,pinst
cmp dl,[si].ayMacInst ;rows
ja AboveNewAy
mov dl,[si].ayMacInst ;assume going into text mode
AboveNewAy:
mul dl ;columns * rows
mov cl,[di].modeVids
cmp cl, 08H
ja EgaSS_Hard
cmp cl, 07H
jb NotHerc
; We are in mode 7 or 8 so we might have a Hercules card.
push ax ;Save cwSwap
mov ah,0efH
mov dl, -1
int 10H
pop ax ;restore cwSwap
inc dl
jz NotHerc ;DL not changed by INT 10 unless herc.
mov ax,8*1024 ;Must save 8k words for herc
;We would only have to save 4K words
;If it weren't for Compaq's stupid
;BIOS which always clears 16K bytes
;when switching into mode 7.
mov [di].fClearRegenVids,80H
NotHerc:
mov [di].cwSwapVids,ax
mov [di].fvidsVids,fvidsChAttr ;Text modes
jmp EgaSS_Exit
; *** Graphics Text ***
; Ok, we are in one of the difficult graphics modes.
; We must save cLines*80 words from bit plane 0 and the same from bit plane 1
; and we must save 4k words from bit plane 2 (because the character
; generator gets loaded into this area when we switch to alpha mode).
EgaSS_Hard:
mov [di].cwSwapVids,ax
and [di].fvidsVids,not fvidsChAttr ;graphics modes
mov ax, 2*1024 ; MCGA uses 2k words
mov bx,OFF_lpwDataCsd ;* Data in data segment
test [bx].fvmCurAdap, fvmMCGA
jnz EgaSS_Alloc
mov ax,[di].cwSwapVids ; ax == cLines*cColumns words
shl ax,1 ; for bit plane 0 and 1
EgaSS_Alloc:
add ax, 4*1024 ; Save 4k words of bit plane 2
test [bx].fvmCurAdap, fvm64KEGA
jz EgaSS_Exit
; More memory gets trashed by the BIOS doing a mode reset on a 64k Ega.
; Note: On a 64k Ega, the 4k words starting at 16k of bit plane 2 also get
; trashed by the BIOS for some reason (so we gotta save that too).
add ax,4*1024
EgaSS_Exit:
mov [di].cwVidDataVids,ax
mov ax,sp ;* success
cEnd FSaveVidsCsd
;********** EgaSavePalette ********
;*
;* entry: ds:[di] => Vids
cProc EgaSavePalette,<NEAR,PUBLIC>,<SI,DI,ES>
cBegin EgaSavePalette
mov bx,OFF_lpwDataCsd ;* Data in data segment
mov ax,ds
mov es,ax
test [bx].fvmCurAdap, fvmMCGA or fvmVGA ;PS2 ?
jz @F
lea dx, [di].rgbPS2PaletteVids
mov ax, 1017H ; Read block of Palette regs
xor bx,bx ; start at reg 0
mov cx, 256 ; read 256 regs
int 10H
@@:
mov bx,OFF_lpwDataCsd ;* Data in data segment
test [bx].fvmCurAdap, fvmEGA or fvmVGA or fvm64KEGA or fvmEGAM
jz @F
push ds
pop es
lea di, [di].rgbEgaPaletteVids ;es:[di] -> buffer
push cs
pop ds
mov si, DrvOffset EGAPaletteMirror
mov cx,17 ;16 palette + overscan regs
rep movsb
push ss
pop ds ;restore ds
@@:
cEnd EgaSavePalette
;********** FRestoreVidsCsd ********
;* entry: pvidsRestore = near pointer to VIDS structure
;* * restore video state with data in *pvidsRestore (not screen data)
;* exit: AX != 0 if ok, == 0 if error
cProc FRestoreVidsCsd, <FAR, PUBLIC, ATOMIC>, <si, di>
parmDP pvidsRestore
cBegin FRestoreVidsCsd
mov di,pvidsRestore
mov al, [di].modeVids
cmp al, 2
je EgaFRS_Text
cmp al, 3
je EgaFRS_Text
cmp al, 40H ;[==] Olivetti
je EgaFRS_SimpleGraphics ;[==]
cmp al, 8
ja EgaFRs_HardGraphics
cmp al, 7
jae EgaFRS_Text
EgaFRS_SimpleGraphics: ;mode 4,5 & 6
cCall SetVideoMode
jmp EgaFRS_Common
EgaFRS_Text: ; mode 2,3 and 7
ifndef KANJI
mov bx,OFF_lpwDataCsd ;* Data in data segment
cmp [bx].fBlinkEnable,0
je @F ;trash ax,dx
mov [bx].fBlinkEnable,0 ;disable Blink
cCall DiddleBlinkbit
jmp short RestoreBlink
@@:
mov [bx].fBlinkEnable,1 ;enable Blink
cCall EnableBlinkbit
RestoreBlink:
endif ; !KANJI
mov bx,OFF_lpwDataCsd ;* Data in data segment
test [bx].fvmCurAdap, fvmVGA ;VGA ?
jz EgaFRs_SetScanLines_done
mov al,2 ;default 400 lines
cmp [di].ayMacVids,43 ; 43 line mode
jne useDefaultLine
dec al ;set 350 scan line
useDefaultLine:
mov ah,12h ;set vertical scan line
mov bl,30h
int 10h ;takes effect on next mode set
EgaFRs_SetScanLines_done:
cCall SetVideoMode
or ax,ax ;mode set ?
jz EgaFRS_Common
cmp [di].ayPointsVids,8 ;8x8 font ?
jne EgaFRS_Common
mov ax,1112h
mov bh,8
xor bl,bl
int 10h
jmp EgaFRS_Common
EgaFRS_HardGraphics:
cCall ClearRegen
cCall SetVideoMode
cmp [di].ayPointsVids, 8
jne EgaFRs_NoLoad8
mov ax,1123h
xor bh,bh
mov bl,[di].modeVids
sub bl,0dh
mov dl,cs:[GraphicsModeRows+bx]
xor bl,bl
int 10h
EgaFRs_NoLoad8:
EgaFRs_Common:
mov al,[di].pageVids
mov ah,5
int 10h ;* SetPage
mov dx,di
xor ax,ax
mov es,ax
lea si,[di].rgwCursorPosVids
mov di,BIOS_cursor_posn
mov cx,8
rep movsw
mov di,dx
mov bl,[di].pageVids
xor bh,bh
shl bx,1
mov dx,[di+bx].rgwCursorPosVids ;* get cursor pos for this page
shr bx,1
mov bh,bl
mov ah,2
int 10h ;* SetCursorPos
mov cx,[di].vparmCursorVids
mov ah,1
int 10h ;* SetCursor
cmp [di].modeVids,40H ;Don't EgaRestore palette for
je @F ; Olivetti
mov bx,OFF_lpwDataCsd ;* Data in data segment
test [bx].fvmCurAdap, fvmEGA or fvmVGA or fvm64KEGA or fvmEGAM or fvmMCGA
jz @F
cCall EgaRestorePalette
@@:
public restoreCGAPal ;UNDONE - remove
restoreCGAPal: ;UNDONE - remove
push bx
mov bl, [di].bCGAPalVids
or bl,bl
js @F ;* skip if negative
mov bh,1
mov ah,0BH
int 10H ;* set color palette
@@:
mov bl, [di].bCGABgVids
or bl,bl
js @F ;* skip if negative
xor bh,bh
mov ah,0BH
int 10H ;* set background color
@@:
pop bx
test [bx].fvmCurAdap, fvmCGA ;CGA ?
jz @F
xor ax,ax
mov es,ax
mov al, [di].ayOverScanVids
mov byte ptr es:[466H],al
mov dx, 3d9H
out dx, al
@@:
mov ax,sp ;* success
cEnd FRestoreVidsCsd
;********** EgaRestorePalette ********
;*
;*
cProc EgaRestorePalette,<NEAR,PUBLIC>,<SI,DI,ES>
cBegin EgaRestorePalette
mov bx,OFF_lpwDataCsd ;* Data in data segment
mov ax,ds
mov es,ax
test [bx].fvmCurAdap, fvmMCGA or fvmVGA ;PS2 ?
jz @F
lea dx, [di].rgbPS2PaletteVids
mov ax, 1012H ; write block of Palette regs
xor bx,bx ; start at reg 0
mov cx, 256 ; read 256 regs
int 10H
@@:
mov bx,OFF_lpwDataCsd ;* Data in data segment
test [bx].fvmCurAdap, fvmEGA or fvmVGA or fvm64KEGA or fvmEGAM
jz @F
cmp cs:[lpbBIOSINT10_Offset],0 ;save check
je @F
mov ax,1002h
lea dx, [di].rgbEGAPaletteVids ;es:[dx] -> buffer
int 10h
@@:
cEnd EgaRestorePalette
;***********************
cProc EnableBlinkBit, <NEAR, ATOMIC, PUBLIC>, <DS>
cBegin EnableBlinkBit
;* * Diddle blink bit via BIOS call (or diddle CGA bit)
mov bx,OFF_lpwDataCsd ;* Data in data segment
test [bx].fvmCurAdap, fvmCGA or fvmMDA
jz EBB_NotCGA
xor ax,ax
mov ds,ax
mov dx,ds:[BIOS_addr_6845]
add dx,PORT_mode
;* * set the mode set flag
or byte ptr ds:[BIOS_crt_mode_set],20H
mov al,ds:[BIOS_crt_mode_set]
out dx,al ;* send to port
;* * EGA etc has a BIOS call for this
EBB_NotCGA:
mov ax,1003H ;* set intensify/blink
mov bl,1 ;* enable blink
int 10h
cEnd EnableBlinkBit
;********** SetVideoMode **********
;* entry: al = video mode
;* * Set specified video mode
;* exit: trash ax,cx,es
;* ax = 0 same mode,-1 mode set
cProc SetVideoMode,<NEAR>,<es>
cBegin SetVideoMode
mov ah,0Fh
int 10h ;* GetMode
and al,7fh
cmp al,[di].modeVids
jne SVM_SetMode ;reset
;same mode, check rows
mov bx,OFF_lpwDataCsd ;* Data in data segment
test ss:[bx].fvmCurAdap, fvmCGA ;CGA only support 25 rows
jnz mode_already_set
push bp
mov ax,1130h ; get info
xor bx,bx
xor cx,cx
int 10h
pop bp
inc dl ; dl = scan lines
cmp dl,[di].ayMacVids ; rows
jne SVM_SetMode
jmp mode_already_set
SVM_SetMode:
mov al,[di].modeVids
or al,[di].fClearRegenVids
mov bx,OFF_lpwDataCsd ;* Data in data segment
test ss:[bx].fvmCurAdap, fvmEGA or fvmVGA or fvm64KEGA or fvmMCGA or fvmEGAM
jz TrashRegen ;CGA doesn't support the function below
cmp al, 40H ;Olivetti doesn't support it either.
je TrashRegen
or al,80h ;* don't clear RGEN
TrashRegen:
xor ah,ah
push ax ;save mode
int 10h ;* set mode
pop ax ;restore
;* * Delay so that we won't start writting to the display before it has
;* * settled down.
mov cx,500
delay_me:
loop delay_me
;
; When the olivetti is in mode 40H the value at BIOS_info is a pointer to
; the character set (NOT flags as it is in EGA modes)
; So let's not trash the pointer by clearing the "don't clear regen" bit.
;
cmp al, 40H
je @F
test ss:[bx].fvmCurAdap, fvmEGA or fvmVGA or fvm64KEGA or fvmMCGA or fvmEGAM
jz @F
;* Clear the "don't clear regen" bit in the BIOS image
xor ax,ax
mov es,ax
and byte ptr es:[BIOS_info],7fH ;487H
mov ax,40h
mov es,ax
mov al,[di].ayMacVids ;
dec al ; rows - 1
mov byte ptr es:[0084H],al ;* update BIOS rows
@@:
;
; The following is provided only to overcome a bug in the EGA BIOS
; routines which support the graphics "compatibility mode" (BIOS 4)
; so that the two calls related to PALETTE (INT10 AH = 0BH and
; INT10H AH = 10H) work correctly. If we use the first call once
; when user invokes SCREEN 1 to set the background color, then the
; BIOS will subsequently reference the correct (low-intensity)
; color values for the 4 palette attributes whenever the call using
; INT10H, AH = 0BH is used to toggle the palette, and whenever the
; call INT10H, AH = 10H is used to set an individual palette regis-
; ter. In the absence of this initialization, the high-intensity
; color values for both palettes are referenced.
;
test ss:[bx].fvmCurAdap, fvmEGA or fvmVGA or fvm64KEGA or fvmEGAM
jz SkipKludge
mov al, [di].modeVids
cmp al,4
je @F
cmp al,5
jne SkipKludge
@@:
push bx
xor bx,bx
mov ah, 0BH
int 10H ;set background color
pop bx
SkipKludge:
mov ax,-1 ;mode set
jmp short @F
mode_already_set:
xor ax,ax ;same mode
@@:
cEnd SetVideoMode
;********** SaveVidDataCsd ********
;* entry: pvidsSaveData = near pointer to VIDS structure
;* lpwBuffer = buffer to save data
;* * save screen data into buffer
;* exit: n/a
cProc SaveVidDataCsd, <FAR, PUBLIC, ATOMIC>, <DS, SI, DI>
parmDP pvidsSaveData
parmD lpwBuffer
cBegin SaveVidDataCsd
mov di,pvidsSaveData
mov si,di
mov dl,[di].modeVids
mov cx,0B800h
cmp dl,7
jb @F
cmp dl,8
ja @F
mov cx,0B000h ;video segment for mono mode
@@:
mov ax,[di].cwSwapVids
les di,lpwBuffer ;es:[di] -> buffer
cmp dl,40h ;Olivetti ?
je @F
cmp dl,8
ja save_graphics_text
@@: ;Text modes or mode 6
cCall SaveRegen
mov di,si
cCall ClearRegen
jmp SaveVidsDataExit
save_graphics_text:
mov bx,OFF_lpwDataCsd ;* Data in data segment
mov ax, 0a000H ; Address of bit planes
mov ds, ax ;ds:[si] -> video buffer
test ss:[bx].fvmCurAdap, fvmMCGA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -