📄 misc.a86
字号:
ja f2B_20
cmp dl,99 ; Range check hundredths
ja f2B_20
push cx ; save hours/mins
push dx ; save secs/hundredths
call ReadTimeAndDate ; Get the current Time and Date
pop biosDate+4 ; leave the date alone
pop biosDate+2 ; but update the time
jmps f2B_10 ; Update the Date and Time
Public ReadTimeAndDate
ReadTimeAndDate: ; Get the current Time and Date
call rw_clock_common ; make sure clock is there/setup regs
call device_read ; read the Date and Time
mov ax,biosDate ; get the BIOS date and convert
cmp ax,daysSince1980 ; (but only if necessary)
jne NewDate
ret
NewDate:
mov daysSince1980,ax ; so we won't have to convert next time
inc ax ; Day number starting 1 Jan 1980
mov cx,ax ; save day count
inc ax ; convert to a sunday as 1/1/80 is tues
xor dx,dx
mov bx,7
div bx
mov dayOfWeek,dl ; save day of week
xor dx,dx
mov ax,cx ; recover day count
xor di,di ; assume zero leap days
sub ax,60 ; less than 60 days
jc no_leap_days ; means no leap days to subtract
mov bx,1461 ; 1461 = days in four years
div bx ; get number of leap years since 1980
inc ax ; include 1980
sub cx,ax ; normalize years to 365 days
mov di,ax ; save proper leap day count
no_leap_days:
xor dx,dx
xchg ax,cx ; DX:AX = years since 1980 * 365
mov bx,365
div bx ; get number of years since 1980
or dx,dx ; check for zero days left
jnz days_left
dec ax ; dec year count
mov dx,365 ; set day count to last day of last year
days_left:
mov yearsSince1980,ax ; save the year
xchg ax,si ; save in SI
xor bx,bx
mov cx,12
get_month: ; find the appropriate month
cmp dx,totaldays[bx]
jbe got_month
inc bx ! inc bx
loop get_month
got_month:
shr bx,1 ; BX = month
mov month,bl
dec bx
shl bx,1 ; BX = index to previous months
sub dx,totaldays[bx] ; get days into this month
cmp bx,2 ; if it's FEB 29th we've lost a day
jne not_leap_yr ; check it's FEB
test si,3
jnz not_leap_yr ; but is it a leap year ?
shr si,1 ! shr si,1 ; divide years by 4
inc si ; include this year
cmp si,di ; compare against leap day adjustment
jne not_leap_yr
inc dx ; put 29th feb back again
not_leap_yr:
mov dayOfMonth,dl ; save the day of the month
ret
ConvertDate:
sub cx,1980 ; Base year is 1980
jc xset_date_error
cmp cx,2100-1980 ; Year in valid range ?
jnc xset_date_error
mov bl,dh ; Month to BL
xor bh,bh
dec bx ; Adjust month to 0-11
cmp bl,12 ; Month in valid range ?
jnc xset_date_error
mov al,dl ; Day of month
cbw
test cl,3 ; Leap year ?
jnz not_leap_year ; Jump if not
cmp dh,3 ; After February ?
cmc
adc al,ah ; Increment days in current year if so
cmp dl,29 ; Day of month 29 ?
jz day_valid ; Valid if so
not_leap_year:
dec dx
cmp dl,monthdays[bx] ; Day of month within range for non-leap
; year ?
jnc xset_date_error
day_valid:
shl bx,1
add ax,totaldays[bx] ; Get total days in current year
push ax
mov ax,365
mul cx ; Convert year to days since 1-1-1980
mov cx,ax
; if total (ax) >= 60 (Feb 29 1980) then
; leap$days = (total - 60) / (365 * 4) + 1
sub ax,60 ; Before first leap year date
jc noleap ; Jump if so
mov bx,365*4 ; 4 years worth of days (365 * 4)
sub dx,dx
div bx ; Get number of leap years - 1
inc ax
add cx,ax ; CX now has total days including leap
; days
noleap:
dec cx
pop ax
add cx,ax ; Get total days since 1-1-1980
clc
ret
xset_date_error:
stc
ret
rw_clock_common:
mov cx,6 ; read/write 6 characters
mov dx,offset biosDate ; DX -> 6 byte buffer
les si,clk_device ; Get the address of the Clock Device
cmp si,-1 ; Has a valid device been selected
jne rw_clock_common10
add sp,WORD ; discard near return address
rw_clock_common10:
ret
; *****************************
; *** DOS Function 38 ***
; *** Get/Set Country Data ***
; *****************************
Public func38
func38:
xor ah,ah ; Generate 16 Bit country
cmp al,0FFh ; FF means country code in BX
jne f38_10
xchg ax,bx ; AX = real country code
f38_10:
xchg ax,dx ; DX = country
test dx,dx ; dos_AL = 0 get the current country
jz f38_get
inc ax ; now check for dos_DX = FFFF
jz f38_set ; which means set country code
dec ax ; no, return buffer to normal
f38_get:
test dx,dx ; Get current?
jnz f38_g10 ; Yes
mov dx,cur_country ; use current country
f38_g10:
; look for (and if neccessary load) type 1 info into buffer
xchg ax,di ; ES:DI -> buffer
mov bx,cur_cp ; bx=codepage
call f38_get_info ; get info in current codepage
jnc f38_g20
push ss ! pop ds
xor bx,bx ; now try any codepage
call f38_get_info ; if none for current codepage
jc f38_error ; No Match Found
f38_g20:
lea si,EXCI_CI_DATAOFF[si] ; point at CI_, not EXCI_ data
mov bx,CI_CODE[si] ; Return the selected country code
mov cx,CI_STATICLEN/2
rep movsw
if NLSFUNC
push ss
pop ds
; call get_dseg ; DS back to PCMODE
endif
call return_BX ; return country code in BX
xchg ax,bx
jmp return_AX_CLC ; and in AX
f38_get_info:
push es ! push di ! push dx ; save pointer to buffer
mov al,1 ; Get data list seperators etc...
call f65_get_info ; DS:SI -> extended country info buffer
pop dx ! pop di ! pop es ; ES:DI -> users buffer
ret
f38_set:
mov bx,cur_cp ; bx=codepage
and bx,f38_flag ; force CP to zero if 1st time here
call f38_set_country ; Update the Internal Data Structures
jc f38_error
f38_s20:
mov f38_flag,0FFFFh ; Country Code Set Successfully
mov ax,cur_country ; and return the current country
jmp return_AX_CLC ; to the user
f38_error:
if NLSFUNC
push ss
pop ds
; call get_dseg ; DS back to PCMODE
endif
mov ax,ED_FILE ; This is the Error to return
jmp error_exit
f38_set_country:
; On Entry:
; BX = codepage
; DX = country
; On Exit:
; AX = error code
; preserve codepage/country info if there is an error (ie do type 1 last!)
;
mov al,2 ; Get uppercase & filename table
mov di,offset Ucasetbl
mov cx,info2_len
call f38_update
jc f38_seterr
mov al,4 ; Get uppercase & filename table
mov di,offset FileUcasetbl
mov cx,info4_len
call f38_update
jc f38_seterr
mov al,5 ; Get Legal file characters
mov di,offset FileCharstbl
mov cx,info5_len
call f38_update
jc f38_seterr
mov al,6 ; Get Collating table
mov di,offset Collatingtbl
mov cx,info6_len
call f38_update
jc f38_seterr
mov al,7 ; Get double byte character set table
mov di,offset DBCS_tbl
mov cx,info7_len
call f38_update
jc f38_seterr
mov al,1 ; Get data list seperators etc...
mov di,offset country_data ; do last since this updates
mov cx,info1_len ; cur_country/cur_cp
call f38_update
; jc f38_seterr
; clc
ret
f38_seterr:
mov ax,ED_FILE ; return file not found error
ret
f38_update:
push ds ; save important registers
push bx ; codepage
push cx ; count for move
push dx ; country
push di ; destination offset for move
push ds ; destination segment
call f65_get_info ; DS:SI -> buffer with country info
pop es ; destination seg in ES
pop di ; ES:DI -> destination of move
pop dx ; country
pop cx ; bytes to move
pop bx ; codepage back again
jc f38_update10 ; any problems ?
rep movsb ; no, copy the data
f38_update10:
pop ds ; DS back to PCMDSEG
ret
; *****************************
; *** DOS Function 65 ***
; *** Extended Country Data ***
; *****************************
;
;CODEPAGE equ 437 ; Return Standard Code Page
;
; Get Extended Country Code Sub-Functions
;
func65_dt dw 0FFFFh ; 00 Illegal Sub-Function
dw offset country_data ; 01 Extended Country Info
dw offset Ucasetbl ; 02 UpperCase Table
dw 0FFFFh ; 03 Invalid Subfunction
dw offset FileUcasetbl ; 04 FileName Upper Case Table
dw offset FileCharstbl ; 05 Valid Filename Characters
dw offset Collatingtbl ; 06 Collating Sequence
dw offset DBCS_tbl ; 07 DBCS Environment Vector
func65_dtl equ (offset $ - offset func65_dt)/2
Public func65
func65:
cmp al,func65_dtl ; is sub-function 0-7 ?
jb func65_read_table
sub al,20h ; now check for 20-22
jb f65_invalid
je func6520 ; it's upper case character
sub al,2
je func6522
jb func6521
sub al,1 ; how about 6523 ?
jnz f65_invalid
; jmp func6523
func6523:
;--------
; On Entry:
; DX = character to check
; On Exit:
; AX = 0, No
; AX = 1, Yes
; AX = 2, neither
;
push ds
pop es
mov di,offset NoYesChars ; 'NnYy'
cbw ; assume No (AX=0)
xchg ax,dx ; AX = char, DX = answer
call dbcs_lead ; is it 1st of a DBCS pair
jne func6523_10
scasw ; check 'N'
je func6523_30
inc dx ; assume Yes (DX=1)
scasw ; check 'Y'
jmps func6523_20
func6523_10:
scasb ; check 'N'
je func6523_30
scasb ; check 'n'
je func6523_30
inc dx ; assume Yes (DX=1)
scasb ; check 'Y'
je func6523_30
scasb ; check 'y'
func6523_20:
je func6523_30
inc dx ; it's neither (DX=2)
func6523_30:
xchg ax,dx ; return result in AX
jmp return_AX_CLC ; Return the Code Page
func6522:
;--------
; Upper case ASCIIZ string at ES:DX
mov cx,0FFFFh ; calculate the length
mov di,dx ; of the string
; mov al,0
repne scasb
not cx ; CX = length, including 0
; jmp func6521 ; now use upper case CX bytes
func6521:
;--------
; Upper case string of CX bytes at ES:DX
mov si,dx
mov di,dx ; point SI & DI at string
f6521_10:
lods es:al ; read a character
call dbcs_lead ; is it 1st of a DBCS pair
jne f6521_20
stosb ; store 1st byte of this pair
movs es:byte ptr [di],es:byte ptr [si]
; copy 2nd byte
dec cx ; 1st byte of pair
loopnz f6521_10 ; go around for another one
ret ; time to go...
f6521_20:
call toupper ; upper case the character
stosb ;
loop f6521_10 ; go and do another one
ret
func6520:
;--------
; Upper case character DL
xchg ax,dx ; character in AX
call toupper ; upper case it
mov dl,al ; return in AL and DL
jmp return_DX ; set return code
f65_invalid:
;-----------
; short jump to invalid function
jmp invalid_function
func65_read_table:
;-----------------
cmp cx,5 ; Check for valid buffer size
jb f65_invalid
cbw ; Get the request sub-function
mov si,ax ; into SI
shl si,1
mov si,func65_dt[si]
inc si ; is SI = 0FFFFh
jz f65_invalid ; if so it's an invalid function
dec si
cmp dx,0ffffh
jne f65_21 ; FFFF means
mov dx,cur_country ; use default country
f65_21:
cmp bx,0ffffh
jne f65_22 ; FFFF means
mov bx,cur_cp ; use default codepage
f65_22:
call f65_get_info ; DS:SI -> extended info for this pair
mov ax,ED_FILE ; On Error return File Not Found
jnc f65_23 ; for any error
push ss ! pop ds
jmp error_exit ; so Quit
f65_23:
les bx,ss:int21regs_ptr ; point to callers registers
mov ax,es:reg_AX[bx] ; get the subfunction number
mov cx,es:reg_CX[bx] ; this much data is requested
mov di,es:reg_DI[bx] ; Get the Parameter Block Offset
mov es,es:reg_ES[bx] ; and Segment
stosb ; fill in Info ID
cmp al,1 ; 1 is special - the rest
jne f65_30 ; want a DWORD ptr
cmp cx,EXCI_MAXLEN ; Check CX against the sub-function 1
jbe f65_25 ; maximum and force CX to this value
mov cx,EXCI_MAXLEN ; if it is greater
f65_25:
call return_CX ; Return the number of bytes transfered
sub cx,EXI_DATA_LEN ; Adjust count for 3 byte header
mov ax,cx ! stosw ; fill in EXCI_LENGTH
push cx ; Save the count and copy as much
cmp cx,EXCI_STATLEN ; valid data a possible. IE at most
jbe f65_27 ; EXCI_STATLEN bytes
mov cx,EXCI_STATLEN
f65_27:
rep movsb ; just copy the data
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -