📄 gwio.asm
字号:
PUSH SI
PUSH AX
SUB AL,32D ;make into index into soft key table
MOV SI,OFFSET DGROUP:B$SOFT_KEYS
XOR AH,AH
SHL AL,1 ;Soft Key Table entry size is 4
SHL AL,1 ;[AX] = Key no. * 4
ADD SI,AX ;Index into Soft Key Descriptor Table
MOV AX,[SI] ;[AX] = Soft Key string Length
MOV B$SOFT_KEY_LEN,AX ;Store Length of Soft Key
OR AX,AX ;Null?
POP AX ;clean up stack
JZ SKEY_RET ;If null then return Scan Code
MOV SI,[SI+2] ;[SI] = Addr of Soft Key String
MOV B$SOFT_KEY_INDEX,SI ;Store index for SKEY_RD
JMP SHORT SKEY_RD_2 ; and return 1st character...
;SKEY_RD - If Soft Key in Progress, return next character
; from Soft Key String.
SKEY_RD:
PUSH SI
SKEY_RD_2:
MOV SI,[B$SOFT_KEY_INDEX]
MOV AL,[SI] ;Get char from Soft Key string
xor ah,ah
cmp al,0feh ; soft key assigned to chr$(254) ?
jne not_254 ; brif not
mov dx,0feh ; else set [dx] to 00feh bcos $inkmap
; assumes a three byte code if [al]=254
mov [dchar_save],dx ; store the same in [dchar_save] also
not_254:
INC [B$SOFT_KEY_INDEX]
DEC [B$SOFT_KEY_LEN]
SKEY_RET:
POP SI
JMP TTYINX
;***
;B$CNTRL - check for control characters during printing
;
;****
cProc B$CNTRL,<NEAR,PUBLIC>
cBegin
JMP [B$IPOLKEY] ; wait on pause_key
cEnd <nogen>
PAGE
;***
;B$DOS3CHECK - Check DOS version, return carry set if < DOS 3.00
;OEM-callback routine
;
;Purpose:
; Common routine to check for DOS 3. This check is made
; several places in the runtime. A near call and a relative
; jump is smaller than a cmp imm,mem and relative jump.
;
;Entry:
; __osmajor - byte containing DOS major version number - must be set.
; This is done before any OEM routines can be called.
;
;Exit:
; PSW.C - Set if __osmajor < DOS 3.00
; PSW.Z - Set if = DOS 3.00
;
;Uses:
; Per Convention
;
;Preserves:
; AX, BX, CX, DX
;
;Exceptions:
; None.
;*****************************************************************************
cProc B$DOS3CHECK,<PUBLIC,NEAR>
cBegin
CMP __osmajor,3 ; check for dos 3
cEnd
PAGE
SUBTTL DEVR_INT - fatal device error interrupt handler
;***
;DEVR_INT - fatal device error interrupt handler
;
;Purpose:
;
;Entry:
; [BP:SI] = points to the device header
; [AL] = has drive number if block device (a=0,b=1,...)
; [DI] = Error code as follows:
; 00 - Write Protected.
; 01 - Unknown Unit
; 02 - Not Ready
; 03 - Unknown command
; 04 - Data Error
; 05 - Bad Drive structure length
; 06 - Seek Error
; 07 - Unknown Media
; 08 - Sector not found
; 09 - Printer out of paper
; 10 - Write Fault (hard disks only)
; 11 - Read Fault
; 12 - Other error.
;
; Special handling must be done for "Disk Write Protect" error due to some
; MS-DOS booboo. Control must pass to the standard INT 24h handler in order
; to clean up some (state?) variables. But then BASIC cannot trap the error.
; The solution is to modify BASIC's parent pointer to point to itself, then
; if a write protect error occurs, DEVR_INT can abort to MS-DOS which will
; return via the parent pointer to BASIC's error handling routine DSKERC.
;
; Note: On entry DS, ES are not pointing to BASIC.
;
;Exit:
;
;Uses:
;
;Preserves: (optional)
; SS, SP, DS, ES, BX, CX, and DX must be preserved if an IRET is executed
;
;Exceptions:
;
;******************************************************************************
DbPub DEVR_INT
cProc DEVR_INT,FAR
cBegin
ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING
STI
PUSH DS
PUSH BX
CALL B$GETDS
MOV DS,BX
ASSUME DS:DGROUP
MOV fInt24Error,-1 ; set flag for QB5/COW
CMP b$fInt24Err,0 ;Should we IGNORE this error?
JZ TestWriteProtect ;brif not, test for a write protect sequence
MOV b$fInt24Err,DI ; save error in b$fInt24Err
OR b$fInt24Err,0FF00h; insure b$fInt24Err does not go to 0.
JMP SHORT IgnoreInt24 ;ignore this error
TestWriteProtect:
CMP BYTE PTR [WPRFLG],0 ;Are we in a write protect INT 24 Seqenc
JZ DSKER1 ;Brif not
IgnoreInt24:
XOR AX,AX ;Tell DOS to ignore the error
pop bx
pop ds
IRET ;Back to DOS - ignore dirty buffers
DSKER1: ;Here if Write protect flag not set
CLI ; Critical section below. A second
; interrupt would blow away the first one
PUSH BX ; save basic DGROUP
MOV BX,SP ; get psuedo frame pointer
MOV CX,[BX+24] ; [CX] = [BP] at INT 21H time (documented)
POP BX ; restore basic DGROUP
mov es,bx ; ES = DGROUP
mov ss,bx ; restore BASIC's stack
mov sp,cx ; new stack pointer = previous BP
; Stack now back to where it was just after the:
; PUSH BP
; MOV BP,SP
; of the runtime entry point that caused the error.
assume ds:dgroup, es:dgroup, ss:dgroup
STI ;Turn interrupts back on
.erre ID_SSEQDS ; assumes ss equals ds.
push cx ; save old BP for later
mov cx,di ;get device error into cl
mov DEVICE,AL ; device
AND AH,80H ;test for char dev or bad FAT
JZ CHRDEV ;not either, so not char dev
PUSH DS
MOV DS,BP ; get device header segment
TEST BYTE PTR DS:[SI+4],80H ; test for character device
POP DS
JZ CHRDEV ;jump if char dev, not block dev
XOR AH,AH ;clear flag for no char device
CHRDEV:
mov al,cl ;error code into al
mov DERRCD,AX ; Save error code and device type bit
assume es:nothing
test al,255 ; Is this a write protect error?
jnz noprtct ; Yes: return to MS-DOS with abort request
; --------------------------- ;Mark begining of Wr-Pro Sequence
mov byte ptr [wprflg],1 ;"Zibo" method of handling INT 24
callos REST ;from write protects. Forces DOS
mov byte ptr [wprflg],0 ;to REALLY ignore error and discard
; --------------------------- ;pending dirty buffers.
noprtct:
MOV EXTFLG,0 ;no violation yet
CALL B$GETEXTERR ; psw.c set if <dos 3
; JB NO_VIOLATION ;if DOS2, then branch
JNZ NO_VIOLATION ; ZF=1 if violation
INC EXTFLG ;set violation flag
NO_VIOLATION:
callos VERSN ;Do this for good luck. clears unstable dos
;state
;Control is passed here after a hard disk error (INT 24H).
; Now we decide what the error is and JMP to its error handler.
; Entry DS, ES undefined
mov ax,DERRCD ; Restore error code
MOV BX,OFFSET DGROUP:b$ERDEVP ;[BX]= ptr to ERDEV$ sd
TEST AH,80H ;Character device ?
jnz devr_2 ;Yes: go copy name
;No: block oriented device (disk)
mov WORD PTR[BX],2 ;device name length to 2
MOV BX,[BX+2] ;get ptr to erdev$ string
mov word ptr [BX],":A" ;damn hi/low
mov ch,DEVICE
add byte ptr [BX],ch ;set name
jmp short devr_3
devr_2:
PUSH DS ;save basic data segment
MOV DS,BP ;point to device header segment
add si,10 ;get to character device name
mov cx,8
mov es:[BX],cx ;store name length
mov di,ES:[BX+2] ;target
cld
rep movsb
pop ds ;get back ds
devr_3:
POP BP ; get frame at error time
mov b$ERDEV,ax ;save in error variable
CALL [b$pTEST_CLOSE] ; If closing, close it w/o error checks
CMP EXTFLG,0 ;violation?
JNZ FWP ;if so, then PERMISSION DENIED
cmp al,0 ;Write protected ?
jz dwp
cmp al,1 ;Device available ?
je dna ; no
cmp al,9 ;no paper ?
je nopaper
cmp al,10 ;device fault ?
je dvf
TEST AH,80H ;Character device ?
jnz devr_4 ; yes
cmp al,2 ;disk not ready
je dnr
cmp al,7 ;disk media error
je dme
jmp short ioe ;device i/o error
devr_4:
cmp al,2 ;timeout ?
je dto
IOE:
JMP B$ERR_IOE ; device i/o error
cEnd <nogen>
;***
;B$GETEXTERR -- get extended error info.
;
;Purpose:
; Return extended error info, if available.
; Redone, edit [24]
;
;Entry:
; None
;
;Exit:
; CF (and NZ): No extended info available (running under < DOS 3.x)
; NC: [AX] = extended error code
; ZF if error was either sharing violation or locking violation
; NZ Some other error
;
;Uses:
; If C1: nothing, else only AX.
;
;Preserves: (optional)
; BX, CX, DX
;
;******************************************************************************
cProc B$GETEXTERR,<NEAR,PUBLIC>,<BX,CX,DX,SI,DI,BP,DS,ES> ; extended
; error call destroys all these
cBegin
cCall B$DOS3CHECK ;See if we're DOS 3 or not
JC GETEXTERR_90 ;just exit if not
XOR BX,BX ;clear for call...
MOV AH,59H ;extended error code
INT 21H ;do the call
CMP AX,20H ;test if sharing violation
JE GACERR_10 ;if so, then return it
CMP AX,21H ;test if lock violation
GACERR_10:
CLC ;C0 means okay
GETEXTERR_90:
cEnd
DTO:
JMP B$ERR_DTO
DVF:
JMP B$ERR_DVF
NOPAPER:
JMP B$ERR_OTP
DNA:
JMP B$ERR_DNA
DME:
JMP B$ERR_DME ; give disk media error
DWP: ;permission denied due to write protection
FWP: ;permission denied due to open violation
JMP B$ERR_FWP ; give permission denied error
DNR:
JMP B$ERR_DNR ; give disk not ready error
PAGE
;***
; B$IOCLOS - Run-time initialization
;
;Purpose: To deinstall handlers for Divide by zero, Oveflow and I/O interrupts.
;
;Entry:
; None
;Exit:
; None
;Modifies:
; Per convention
;Exceptions:
; None
;
;****
cProc B$IOCLOS,<PUBLIC,NEAR>
cBegin
ASSUME ES:DGROUP
ASSUME DS:NOTHING
XOR AX,AX ;Clear segment
PUSH DS ;Save DS
PUSH DS ; Restore ES
POP ES
MOV DS,AX ;Set DS to 0:xxxx
PUSHF ;Save interrupt status
CLI ;Turn off interrupts
RSTVEC 0,ES:DIV0_SAVE
RSTVEC 4,ES:OVRF_SAVE
RSTVEC 24h,ES:DEVR_SAVE
POPF ;Restore interrupts
POP DS ;Restore DS
ASSUME DS:DGROUP
cEnd ; End of B$IOCLOS
sEnd DV_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -