MS-DOS/v2.0/source/GETSET.ASM
2018-09-21 17:53:34 -07:00

627 lines
18 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

TITLE GETSET - GETting and SETting MS-DOS system calls
NAME GETSET
;
; System Calls which get and set various things
;
; $GET_VERSION
; $GET_VERIFY_ON_WRITE
; $SET_VERIFY_ON_WRITE
; $SET_CTRL_C_TRAPPING
; $INTERNATIONAL
; $GET_DRIVE_FREESPACE
; $GET_DMA
; $SET_DMA
; $GET_DEFAULT_DRIVE
; $SET_DEFAULT_DRIVE
; $GET_INTERRUPT_VECTOR
; $SET_INTERRUPT_VECTOR
; RECSET
; $CHAR_OPER
;
.xlist
;
; get the appropriate segment definitions
;
INCLUDE DOSSEG.ASM
IFNDEF ALTVECT
ALTVECT EQU 0 ; FALSE
ENDIF
IFNDEF IBM
IBM EQU 0
ENDIF
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
i_need VERFLG,BYTE
i_need CNTCFLAG,BYTE
i_need DMAADD,DWORD
i_need CURDRV,BYTE
i_need Current_Country,WORD
i_need international_table,BYTE
i_need INDOS,BYTE
i_need SYSINITVAR,WORD
i_need NUMIO,BYTE
i_need SWITCH_CHARACTER,BYTE
i_need DEVICE_AVAILABILITY,BYTE
USERNUM DW ? ; 24 bit user number
DB ?
IF IBM
OEMNUM DB 0 ; 8 bit OEM number
ELSE
OEMNUM DB 0FFH ; 8 bit OEM number
ENDIF
MSVERS EQU THIS WORD ; MS-DOS version in hex for $GET_VERSION
MSMAJOR DB DOS_MAJOR_VERSION
MSMINOR DB DOS_MINOR_VERSION
BREAK <$Get_Version -- Return MSDOS version number>
procedure $GET_VERSION,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Return MS-DOS version number
; Outputs:
; OEM number in BH
; User number in BL:CX (24 bits)
; Version number as AL.AH in binary
; NOTE: On pre 1.28 DOSs AL will be zero
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV BX,[USERNUM + 2]
MOV CX,[USERNUM]
MOV AX,[MSVERS]
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI.user_BX],BX
MOV [SI.user_CX],CX
MOV [SI.user_AX],AX ; Really only sets AH
return
$GET_VERSION ENDP
BREAK <$International - return country-dependent information>
;
; Inputs:
; DS:DX point to a block
; Function:
; give users an idea of what country the application is running
; Outputs:
; AX = number of bytes transferred
; DS:DX ->+---------------------------------+
; | WORD Date/time format |
; +---------------------------------+
; | BYTE ASCIZ currency symbol |
; +---------------------------------+
; | BYTE ASCIZ thousands separator |
; +---------------------------------+
; | BYTE ASCIZ decimal separator |
; +---------------------------------+
procedure $INTERNATIONAL,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV BL,AL
PUSH DS
POP ES
PUSH DX
POP DI
PUSH SS
POP DS
ASSUME DS:DOSGROUP
CMP DI,-1
JZ international_set
OR BL,BL
JNZ international_find
MOV SI,[Current_Country]
MOV AX,WORD PTR [SI-2] ; Get size in AL, country code in AH
MOV BL,AH ; Set country code
JMP SHORT international_copy
international_find:
CALL international_get
JNC international_copy
error country_not_found
international_get:
MOV SI,OFFSET DOSGROUP:international_table
international_next:
LODSW ; Get size in AL, country code in AH
CMP AL,-1
JNZ check_code
STC
RET35:
RET
check_code:
CMP BL,AH
JZ RET35 ; Carry clear
XOR AH,AH
ADD SI,AX
JMP international_next
international_copy:
MOV CL,AL
XOR CH,CH
PUSH DI
REP MOVSB
POP DI
MOV WORD PTR ES:[DI.MAP_CALL + 2],CS ; Set segment for case map call
international_ok:
XOR AX,AX
MOV AL,BL ; Return country code in AX
transfer SYS_RET_OK
international_set:
CALL international_get
JNC international_store
error country_not_found
international_store:
MOV [Current_Country],SI
JMP international_ok
$INTERNATIONAL ENDP
BREAK <$Get_Verify_on_Write - return verify-after-write flag>
procedure $GET_VERIFY_ON_WRITE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; none.
; Function:
; returns flag
; Returns:
; AL = value of VERIFY flag
MOV AL,[VERFLG]
return
$GET_VERIFY_ON_WRITE ENDP
BREAK <$Set_Verify_on_Write - Toggle verify-after-write flag>
procedure $SET_VERIFY_ON_WRITE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = desired value of VERIFY flag
; Function:
; Sets flag
; Returns:
; None
AND AL,1
MOV [VERFLG],AL
return
$SET_VERIFY_ON_WRITE ENDP
BREAK <$Set_CTRL_C_Trapping -- En/Disable ^C check in dispatcher>
procedure $SET_CTRL_C_TRAPPING,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = 0 read ^C status
; AL = 1 Set ^C status, DL = 0/1 for ^C off/on
; Function:
; Enable disable ^C checking in dispatcher
; Outputs:
; If AL = 0 then DL = 0/1 for ^C off/on
OR AL,AL
JNZ CTRL_C_set
invoke get_user_stack
MOV AL,[CNTCFLAG]
MOV BYTE PTR [SI.user_DX],AL
return
CTRL_C_set:
DEC AL
JNZ bad_val
AND DL,01h
MOV [CNTCFLAG],DL
return
bad_val:
MOV AL,0FFH
return
$SET_CTRL_C_TRAPPING ENDP
BREAK <$Get_INDOS_Flag -- Return location of DOS critical-section flag>
procedure $GET_INDOS_FLAG,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Returns location of DOS status for interrupt routines
; Returns:
; Flag location in ES:BX
invoke get_user_stack
MOV [SI.user_BX],OFFSET DOSGROUP:INDOS
MOV [SI.user_ES],SS
return
$GET_INDOS_FLAG ENDP
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
procedure $GET_IN_VARS,NEAR
; Return a pointer to interesting DOS variables This call is version
; dependent and is subject to change without notice in future versions.
; Use at risk.
invoke get_user_stack
MOV [SI.user_BX],OFFSET DOSGROUP:SYSINITVAR
MOV [SI.user_ES],SS
return
$GET_IN_VARS ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <$Get_Drive_Freespace -- Return bytes of free disk space on a drive>
procedure $GET_DRIVE_FREESPACE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = Drive number
; Function:
; Return number of free allocation units on drive
; Outputs:
; BX = Number of free allocation units
; DX = Total Number of allocation units on disk
; CX = Sector size
; AX = Sectors per allocation unit
; = -1 if bad drive specified
; This call returns the same info in the same registers (except for FAT pointer)
; as the old FAT pointer calls
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,DL
invoke GETTHISDRV
MOV AX,-1
JC BADFRDRIVE
invoke FATREAD
XOR DX,DX
MOV BX,2
MOV CX,ES:[BP.dpb_max_cluster]
DEC CX
PUSH CX ; Save Total
SCANFREE:
invoke UNPACK
JNZ NOTFREECLUS
INC DX
NOTFREECLUS:
INC BX
LOOP SCANFREE
POP BX ; Remember Total
MOV AL,ES:[BP.dpb_cluster_mask]
INC AL
XOR AH,AH
MOV CX,ES:[BP.dpb_sector_size]
BADFRDRIVE:
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI. user_CX],CX
MOV [SI.user_DX],BX
MOV [SI.user_BX],DX
MOV [SI.user_AX],AX
return
$GET_DRIVE_FREESPACE ENDP
BREAK <$Get_DMA, $Set_DMA -- Get/Set current DMA address>
procedure $GET_DMA,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Get DISK TRANSFER ADDRESS
; Returns:
; ES:BX is current transfer address
MOV BX,WORD PTR [DMAADD]
MOV CX,WORD PTR [DMAADD+2]
invoke get_user_stack
MOV [SI.user_BX],BX
MOV [SI.user_ES],CX
return
$GET_DMA ENDP
procedure $SET_DMA,NEAR ; System call 26
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX is desired new disk transfer address
; Function:
; Set DISK TRANSFER ADDRESS
; Returns:
; None
MOV WORD PTR [DMAADD],DX
MOV WORD PTR [DMAADD+2],DS
return
$SET_DMA ENDP
BREAK <$Get_Default_DPB,$Get_DPB -- Return pointer to DPB>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
procedure $GET_DEFAULT_DPB,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = Drive number (always default drive for call 31)
; Function:
; Return pointer to drive parameter table for default drive
; Returns:
; DS:BX points to the DPB
; AL = 0 If OK, = -1 if bad drive (call 50 only)
MOV DL,0
entry $GET_DPB
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,DL
invoke GETTHISDRV
JC ISNODRV
invoke FATREAD
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI.user_BX],BP
MOV [SI.user_DS],ES
XOR AL,AL
return
ISNODRV:
MOV AL,-1
return
$GET_Default_dpb ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <$Get_Default_Drive, $Set_Default_Drive -- Set/Get default drive>
procedure $GET_DEFAULT_DRIVE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Return current drive number
; Returns:
; AL = drive number
MOV AL,[CURDRV]
return
$GET_DEFAULT_DRIVE ENDP
procedure $SET_DEFAULT_DRIVE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = Drive number for new default drive
; Function:
; Set the default drive
; Returns:
; AL = Number of drives, NO ERROR RETURN IF DRIVE NUMBER BAD
MOV AL,[NUMIO]
CMP DL,AL
JNB RET17
MOV [CURDRV],DL
RET17: return
$SET_DEFAULT_DRIVE ENDP
BREAK <$Get_Interrupt_Vector - Get/Set interrupt vectors>
procedure $GET_INTERRUPT_VECTOR,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = interrupt number
; Function:
; Get the interrupt vector
; Returns:
; ES:BX is current interrupt vector
CALL RECSET
LES BX,DWORD PTR ES:[BX]
invoke get_user_stack
MOV [SI.user_BX],BX
MOV [SI.user_ES],ES
return
$GET_INTERRUPT_VECTOR ENDP
procedure $SET_INTERRUPT_VECTOR,NEAR ; System call 37
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = interrupt number
; DS:DX is desired new interrupt vector
; Function:
; Set the interrupt vector
; Returns:
; None
CALL RECSET
MOV ES:[BX],DX
MOV ES:[BX+2],DS
return
$SET_INTERRUPT_VECTOR ENDP
IF ALTVECT
VECIN: ; INPUT VECTORS
DB 22H ; Terminate
DB 23H ; ^C
DB 24H ; Hard error
DB 28H ; Spooler
LSTVEC DB ? ; ALL OTHER
VECOUT: ; GET MAPPED VECTOR
DB int_terminate
DB int_ctrl_c
DB int_fatal_abort
DB int_spooler
LSTVEC2 DB ? ; Map to itself
NUMVEC = VECOUT-VECIN
ENDIF
procedure RECSET,NEAR
IF ALTVECT
PUSH SS
POP ES
MOV [LSTVEC],AL ; Terminate list with real vector
MOV [LSTVEC2],AL ; Terminate list with real vector
MOV CX,NUMVEC ; Number of possible translations
MOV DI,OFFSET DOSGROUP:VECIN ; Point to vectors
REPNE SCASB
MOV AL,ES:[DI+NUMVEC-1] ; Get translation
ENDIF
XOR BX,BX
MOV ES,BX
MOV BL,AL
SHL BX,1
SHL BX,1
return
recset ENDP
BREAK <$Char_Oper - hack on paths, switches so that xenix can look like PCDOS>
;
; input: AL = function:
; 0 - read switch char
; 1 - set switch char (char in DL)
; 2 - read device availability
; 3 - set device availability (0/FF in DL)
; DL = 0 means /DEV/ must preceed device names
; DL = Non0 means /DEV/ need not preeceed
; output: (get) DL - character/flag
;
procedure $CHAR_OPER,NEAR
ASSUME DS:NOTHING,ES:NOTHING
PUSH SS
POP DS
ASSUME DS:DOSGROUP
OR AL,AL
JNZ char_oper_set_switch
MOV DL,[switch_character]
JMP SHORT char_oper_ret
char_oper_set_switch:
DEC AL
JNZ char_oper_read_avail
MOV [switch_character],DL
return
char_oper_read_avail:
DEC AL
JNZ char_oper_set_avail
MOV DL,[device_availability]
JMP SHORT char_oper_ret
char_oper_set_avail:
DEC AL
JNZ char_oper_bad_ret
MOV [device_availability],DL
return
char_oper_bad_ret:
MOV AL,0FFh
return
char_oper_ret:
invoke get_user_stack
MOV [SI.user_DX],DX
return
$CHAR_OPER ENDP
BREAK <$SetDPB - Create a valid DPB from a user-specified BPB>
procedure $SETDPB,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; ES:BP Points to DPB
; DS:SI Points to BPB
; Function:
; Build a correct DPB from the BPB
; Outputs:
; ES:BP and DS preserved all others destroyed
MOV DI,BP
ADD DI,2 ; Skip over dpb_drive and dpb_UNIT
LODSW
STOSW ; dpb_sector_size
MOV DX,AX
LODSB
DEC AL
STOSB ; dpb_cluster_mask
INC AL
XOR AH,AH
LOG2LOOP:
TEST AL,1
JNZ SAVLOG
INC AH
SHR AL,1
JMP SHORT LOG2LOOP
SAVLOG:
MOV AL,AH
STOSB ; dpb_cluster_shift
MOV BL,AL
MOVSW ; dpb_first_FAT Start of FAT (# of reserved sectors)
LODSB
STOSB ; dpb_FAT_count Number of FATs
MOV BH,AL
LODSW
STOSW ; dpb_root_entries Number of directory entries
MOV CL,5
SHR DX,CL ; Directory entries per sector
DEC AX
ADD AX,DX ; Cause Round Up
MOV CX,DX
XOR DX,DX
DIV CX
MOV CX,AX ; Number of directory sectors
INC DI
INC DI ; Skip dpb_first_sector
MOVSW ; Total number of sectors in DSKSIZ (temp as dpb_max_cluster)
LODSB
MOV ES:[BP.dpb_media],AL ; Media byte
LODSW ; Number of sectors in a FAT
STOSB ; dpb_FAT_size
MUL BH ; Space occupied by all FATs
ADD AX,ES:[BP.dpb_first_FAT]
STOSW ; dpb_dir_sector
ADD AX,CX ; Add number of directory sectors
MOV ES:[BP.dpb_first_sector],AX
SUB AX,ES:[BP.DSKSIZ]
NEG AX ; Sectors in data area
MOV CL,BL ; dpb_cluster_shift
SHR AX,CL ; Div by sectors/cluster
INC AX
MOV ES:[BP.dpb_max_cluster],AX
MOV ES:[BP.dpb_current_dir],0 ; Current directory is root
return
$SETDPB ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
do_ext
CODE ENDS
END