📄 llinit.asm
字号:
;
; GWPAL.ASM:
; B$PAL0, B$PAL2, Handles PALETTE.
; B$PALU
;
; GWSCR.ASM:
; B$CSRL: Handles CSRLIN. No changes.
;
; IOTTY.ASM:
; B$FPOS: Handles POS. No changes.
;
; LLASCN:
; B$PCOPYS: Handles PCOPY.
;
; LLCSCN:
; B$SCREEN: Handles SCREEN().
; B$SCRSTT: Handles SCREEN.
; B$SWIDTH: Handles WIDTH.
; B$SETCLR: Handles COLOR.
;
; LLSCNIO:
; B$CSRDSP: Handles INPUT, LINE INPUT, PRINT,
; WRITE, LOCATE, KEY, SHELL,
; VIEW PRINT, TAB, SPC, WINDOW.
; B$CLRSCN: Handles CLS.
; B$SCROUT, B$STRSOUT: Handles PRINT, WRITE.
;
; PAINT.ASM:
; B$PAIN, B$PNTC: Handles PAINT.
;
;
cProc B$SCINIT,<PUBLIC,NEAR>
cBegin
TEST b$IOFLAG,SCN_INIT ; init done already?
JZ DO_INIT ; brif not -- do it now
INIT_DONE: ; took initialization code out of here
; so that most calls will fall through
cEnd
cProc DO_INIT,<NEAR>,<AX,BX,CX,DX>
cBegin
OR b$IOFLAG,SCN_INIT ; signal screen init done
test b$SCNFLAG,SCN_RESET ;startup screen mode change?
jz NoReset ;go if not
call B$ChkMonitor ; Set VGA monitor type before setting mode
call [b$SetMode] ;set the new screen mode
call B$FixTextPage ; fix b$CurrPSize, b$PageTable
NoReset:
mov ax,b$CurPages
call [b$SetPages] ; Set current page data
; move up one line if on the last one
TEST b$IOFLAG,SCN_SCROLL ; are we to scroll the screen?
JZ NOT_LAST ; brif not
CALL B$SCROLL ; scroll up 1 line
NOT_LAST:
CALL [b$PalReset] ;initialize the palette
cEnd ; restore registers & return
;***
; B$SetAdapter
;
;Purpose:
; Determine configuration of video adapter, monitor and memory.
; Major rewrite (from $SETCL4) with [21].
;Entry:
;Exit:
; b$Adapter, b$Monitor, and b$VideoMem updated
; b$EgaPalSup set as appropriate
;Uses:
;Exceptions:
;****
cProc B$SetAdapter,<PUBLIC,NEAR>,<AX,BX,CX>
cBegin
PUSH ES
PUSH DI
mov ax,StdColor ;AH gets 0, AL gets CGA mask
mov b$Adapter,al ;Assume CGA, no EGA or VGA card present
mov b$VideoMem,16 ; w/16K video memory
mov b$Monitor,al ;Assume std color monitor
mov b$EgaPalSup,ah ; no EGA palette support
PUSH DS ;set ES=DS
POP ES ; for vGetVgaInfo call
MOV DI,OFFSET DGROUP:b$Buf1 ; dest. buffer for VGA info
XOR BX,BX ;Bios sub-function to return VGA info
SCNIOS vGetVgaInfo ;Returns: [AL] = 1B (vGetVgaInfo) if VGA
; if VGA, 64 bytes of info at ES:DI
CMP AL,vGetVgaInfo ;is VGA present?
JNE NOTVGA ;no, go check for EGA
MOV BL,[DI+31H] ; available video memory
MOV AL,[DI+2Dh] ; VGA-MCGA-PS/2 Miscellaneous state info
MOV [VgaMiscInfo],AL ; save state info for B$ChkMonitor
LES DI,[DI] ;long pointer to static functionality table
MOV AX,ES:[DI] ; find out which VGA modes hardware supports
MOV [b$VGAmodesL],AX ; save for Screen mode validation
MOV AL,ES:[DI+2] ; same for modes 10h-13h
MOV [b$VGAmodesH],AL ; save for Screen mode validation
; The first three bytes of the static functionality table define (by bit
; flags) which bios modes are supported by the current graphics adapter.
; Bios mode 12H is supported by the VGA but not by the MCGA. We can tell
; which of these two we are working with by testing the bit which
; corresponds to that bios mode.
MOV b$Adapter,MCGA ;assume MCGA
MOV b$Monitor,AnalogColor ; analog color monitor (in case MCGA)
TEST AL,VGAmode12h ; is bios mode 12H supported?
JZ MonOK ;no, we must have an MCGA
; At this point we know we have a VGA, but we must check if there is
; a second adapter (MDPA, HGC, CGA) installed and, if so, which one is
; currently active. ADJUST_VGA returns with PSW.C set if VGA not active.
; Also, b$Monitor, b$VGAmodeL, and b$VGAmodeH are adjusted accordingly.
MOV b$Monitor,AnalogColor + AnalogMono ; analog monitor
CALL ADJUST_VGA ; check/adjust for 2nd adapter
JC TRANS ; brif VGA not active adapter
MOV b$Adapter,VGA ;using VGA
MOV b$EgaPalSup,1 ;have EGA palette support
JMP SHORT MonOK ;translate video memory size and then exit
NOTVGA:
MOV BL,10h ;% Bios sub-function to return EGA information
SCNIOS vAltSelect ;% Returns: [BH] = 0=color/1=mono mode
;% [BL] = memory on ega card
; [CH] = feature bits
; [CL] = switch settings (monitor)
TEST BL,11111100B ;if EGA support, only bit 0,1 have values
JNZ TRANS ;exit if no EGA
; At this point we know we have an EGA card, and whether it has
; monochrome monitor attached.
; Use the 30H bits in b$CurEquip to determine
; the active display. 10H for COLOR40, 20H for COLOR80 or 30h for
; Monochrome.
mov al,b$CurEquip ; Read the current equipment setting
AND AX,30H ; Knock off unwanted bits : AH = 0
CMP AL,30H ; Is it monochrome?
JNE COLOR_ACTIVE ; Brif not - color monitor
INC AH ; AH = 1 for Monochrome
COLOR_ACTIVE:
CMP AH,BH ; init mode same as EGA mode?
JNE TRANS ; Brif not
mov b$Adapter,EGA ;using EGA
mov b$EgaPalSup,1 ;have EGA palette support
and cl,0FH ;monitor 7=color,8=enh as color,9=enh,B=mono
sub cl,9 ;<0=color,0=enh,2=mono
jc MonOk ;go if color (the above assumption)
MOV CH,EnhColor ; assume enh (cl=0)
JZ IsEnh ; it is enh, CH has bit mask we want
MOV CH,Monochrome ; must be mono, set up bit mask accordingly
IsEnh:
MOV b$Monitor,CH ; save it
MonOk:
;BL=amount of EGA memory: 0 -- 64K, 1 -- 128K, 2 -- 192K,3 -- 256K
inc bl ;now increments of 64K
xor bh,bh
mov cl,6
shl bx,cl ;times 64 to put in increments of 1K
mov b$VideoMem,bx ;save it
JMP SHORT SETEXT ;exit
; this label reached only if EGA card is not installed or is not the
; current active card.
TRANS:
mov al,b$CurEquip ;check if equipment set for MDPA
AND AL,00110000B ;by isolating bits 4 and 5
CMP AL,00110000B ;and checking for both set
JNZ SETEXT ;BRIF color correct (not MDPA)
dec b$Monitor ;else MDPA
dec b$Adapter ; and mono monitor
mov b$VideoMem,4 ;w/4K video memory
SETEXT:
; check for OGA here if CGA, EGA, or VGA
test [b$Adapter],CGA+EGA+VGA ; only these could be Olivetti
jz ChkHerc ; brif cannot be Olivetti
xor ax,ax ; ensure AX = 0 if lloga.ob3 not linked in
call [b$pChkOlivetti] ; check if Olivetti 640x400 mode supported
jz ChkHerc ; returns AL=0, PSW.Z = 1 if not supported
or [b$Adapter],al ; Assumes b$Adapter never CMPed in runtime!
cmp [b$VideoMem],32 ; will have at least 32K
ja ChkHerc ; brif already set
mov [b$VideoMem],32 ; set 32K video memory
ChkHerc:
mov dx,-1 ; DX will not change if no driver
SCNIOS 0EFH ;test for Hercules INT10 driver
cmp dl,-1 ;DL returns -1 if no driver or no HGC
; code to handle CGA plus HGC
je setext2 ; brif so, already set to CGA or MDPA above
test [b$Adapter],MDPA ; do we have a monochrome display?
jz half_mode ; brif not, make CGA work with HGC
mov b$Adapter,HGC ;set adapter to HGC
mov b$VideoMem,64 ;w/64K video memory
or dh,dh ; see if driver indicated HALF mode
jnz setext2 ; brif not, assume only card
shr [b$VideoMem],1 ; only 32K with second card
half_mode: ; make HGC work with CGA
mov dx,03BFh ; Hercules configuration port
mov al,HALF ; make sure only in HALF mode
out dx,al ; write to HGC config. port
setext2:
POP DI
POP ES
cEnd
;***
;ADJUST_VGA - Check if VGA is active and which modes it supports
;
;Purpose:
; Checks for multiple adapters when one is a VGA.
;
;Entry:
; b$Monitor = AnalogColor + AnalogMono
;
;Exit:
; b$CurEquip possibly updated.
; PSW.C set if VGA not active adapter.
; b$VGAmodeL and b$VGAModeH adjusted as necessary.
; b$Monitor adjusted for active display (if PSW.C, = StdColor)
;
;Uses:
; AX.
;
;Preserves:
; ES.
;
;Exceptions:
; None.
;
;******************************************************************************
cProc ADJUST_VGA,<NEAR>,<ES>
cBegin ; entire routine
XOR AX,AX
mov ES,AX
MOV AX,ES:[488h]
TEST AH,1 ; see if VGA handles all modes
JNZ vga_exit ; brif so
TEST AL,8 ; see if display attached
JNZ got_display
XOR AL,2 ; reverse BIT 1
got_display:
MOV AH,ES:[BiosEquip] ; read current BiosEquip
mov b$CurEquip,ah ; update the current equipment setting
AND AH,30H ; Knock off unwanted bits
CMP AH,30H ; Is it monochrome?
JE flag_Set ; Brif so
XOR AL,2 ; invert for color monitor
flag_set:
TEST AL,2
JZ no_vga ; VGA not active
CMP AH,30h ; MONO?
je setvgamono ; brif so
and b$VGAmodesL, NOT (VGAMode7h+VGAModeFh)
MOV b$Monitor,AnalogColor
jmp short vga_exit
setvgamono:
mov b$VGAmodesH,0
and b$VGAmodesL, VGAMode7h+VGAModeFh
MOV b$Monitor,AnalogMono
jmp short vga_exit
no_vga:
XOR AX,AX
MOV b$VGAmodesH,AL
MOV b$VGAmodesL,AX
MOV AL,StdColor ; reset back to defaults:
MOV b$Adapter,AL ; CGA
MOV b$Monitor,AL ; StdColor monitor
STC ; PSW.C indicates VGA not active
vga_exit:
cEnd
;***
;B$ChkMonitor - Make sure VGA set for mono or color appropriately
;
;Purpose:
; This routine ensures that a VGA card is properly set up for whatever
; Bios mode we are about to go into, monochrome or color.
; Added with revision [49].
; Rewritten with revision [64].
; Note: this is unnecessary for PS/2 VGA and Olivetti VGA
;
;Entry:
; [b$BiosMode] set to desired BIOS mode
; B$Adapter & VgaMiscInfo initialized.
;
;Exit:
; [b$CurEquip] updated.
; VGA card set up for desired mode.
;
;Uses:
; Per convention.
;
;Preserves:
; ES.
;
;Exceptions:
; None.
;
;******************************************************************************
cProc B$ChkMonitor,<PUBLIC,NEAR>
cBegin
CMP [b$Adapter],VGA ; VGA? (not MCGA or Olivetti VGA)
JNE EndOfChk ; no - nothing to do
PUSH ES ; preserve ES
XOR AX,AX ; ES = 0
MOV ES,AX
MOV AH,ES:[BiosEquip] ; read current BiosEquip
DbAssertTst AX,NZ,2000h,RT_TEXT,<Unexpected BiosEquip flag in B$ChkMonitor>
OR AH,30h ; set equipment flag for MONO (default)
MOV AL,[b$BiosMode] ; check desired BIOS mode for 7 of F.
DbAssertRelB AL,B,17h,RT_TEXT,<Advanced BIOS mode in B$ChkMonitor>
AND AL,7
SUB AL,7 ; Is it a monochrome mode?
JZ NeedMono ; brif & set Adapter to monochrome
AND AH,0EFh ; set equipment flag for Color80
MOV AL,1 ; turn off summing if color monitor
NeedMono:
MOV [B$CurEquip],AH ; update [b$CurEquip]
MOV ES:[BiosEquip],AH ; update current BiosEquip
POP ES
TEST [VgaMiscInfo],4 ; monochrome analog monitor?
JNZ EndOfChk ; brif so -- okay as is
MOV BL,33h ; turn gray-scale summing on/off
SCNIOS vAltSelect
EndOfChk:
cEnd
;***
;B$GWTERM - OEM termination
;OEM-interface routine
;
;Purpose:
; This routine is called once immediately before BASIC terminates.
; It contains machine specific code to put the system into
; a deterministic final state. The final state should be as close
; to the initial startup state as possible.
;
; NOTE: All of the screen termination is done by a call to
; B$RESETSCN from a different part of the runtime. This
; routine should not try to reset the screen in any way.
;
;Entry:
; None
;
;Exit:
; None
;
;Uses:
; Per convention
;
;Exceptions:
; None
;****
cProc B$GWTERM,<PUBLIC,NEAR>
cBegin
; All of the screen restoration code has been moved from here
; into B$CNTERM.
IN AL,MSKREG ; get IMR into [AL]
OR AL,01H ; mask out timer interrupt
PAUSE ; make sure instruction fetch has occurred
OUT MSKREG,AL ; write mask to IMR
CLI
PUSH DS
XOR AX,AX
MOV DS,AX
ASSUME DS:NOTHING
RSTVEC TMRCTL,DS:TICSAV ;restore clock interrupt
POP DS
ASSUME DS:DGROUP
XFRINT KYBINT,KBDVEC/4 ;move INT EFH to INT 09H
PUSH DS ;save seg register...
RSTVEC KBDVEC/4,b$KBDVEC_SAVE ;restore INT EF vector
POP DS ;restore seg register
PUSH DS ;save seg register...
RSTVEC CLKVEC/4,b$CLKVEC_SAVE ;restore INT F0 vector
POP DS ;restore seg register
IN AL,MSKREG ; get IMR into [AL]
AND AL,0FEH ; unmask timer interrupt
PAUSE ; make sure instruction fetch has occurred
OUT MSKREG,AL ; write mask to IMR
STI
cEnd
;***
;B$SEGINI - Initialize Variable for B$GETDS
;OEM-interface routine
;
;Purpose:
; This routine stores the address of the runtime data segment.
; The value is stored in the code segment so that it can be
; retrieved later by a call to B$GETDS. These two routines
; are used to save the data segment across a run, chain, or
; shell command. The runtime will call B$SEGINI before it
; needs to call B$GETDS.
;
; Note that it is possible that B$SEGINI is called multiple
; times throughout the execution of a program.
;
; This is a DOS 3 only routine.
;
;Entry:
; DS = Final runtime data segment address
;
;Exit:
; DS stored.
;
;Uses:
; Per Convention
;
;Preserves:
; AX, BX, CX, DX, FLAGS
;
;Exceptions:
; none
;****
cProc B$SEGINI,<PUBLIC,NEAR>
cBegin
MOV [b$BASDSG],DS ;store addr of BASIC data segment
cEnd
;***
;B$GETDS - Get Data Segment for Runtime
;OEM-interface routine
;
;Purpose:
; This routine is used to obtain the location of
; the BASIC data segment. The value is kept in the
; basic code segment, where it is put by B$SEGINI.
;
; See also B$SEGINI.
;
;Entry:
; None.
;
;Exit:
; [BX] = BASIC data segment
;
;Uses:
; Per Convention
;
;Preserves:
; AX, CX, DX, FLAGS
;
;Exceptions:
; None
;****
cProc B$GETDS,<PUBLIC,NEAR>
cBegin
MOV BX,[b$BASDSG]
cEnd
sEnd RT_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -