; ============================================================================
;
; LT-DOS - DOS clock
;
; ============================================================================
; ----------------------------------------------------------------------------
; Calculate day of week
; ----------------------------------------------------------------------------
; INPUT: DS = data segment
; DESTROYS: AX, CX, DX
; ----------------------------------------------------------------------------
CalcDayWeek: mov ax,[CurrDate] ; AX <- current date
inc ax
inc ax ; AX +2 (1/1/1980 is Tuesday, e.g. 2)
xor dx,dx ; DX <- 0
mov cx,7 ; CX <- days in week
div cx ; calculate day of week
mov [CurrDayWeek],dl ; current day of week
ret
; ----------------------------------------------------------------------------
; Get system date and time
; ----------------------------------------------------------------------------
; OUTPUT: DS = data segment
; DESTROYS: SI, ES
; ----------------------------------------------------------------------------
; ------------- Push registers
GetDateTime: push ax ; push AX
push bx ; push BX
push cx ; push CX
push dx ; push DX
; ------------- Prepare DDR table for read operation
xor ax,ax ; AL <- 0 unit, AH <- 0 media
mov bx,DOSClock ; BX <- DOS clock buffer
mov cx,CLOCKData_size ; size of data
xor dx,dx ; DX <- starting offset
push cs ; push CS
pop ds ; DS <- data segment
call InitR16DDR ; prepare DDR table
; ------------- Read system date and time
push cs ; push CS
pop es ; ES <- data segment
lds si,[ClockDev] ; DS:SI <- clock device header
call DevExec ; execute device service
push cs ; push CS
pop ds ; DS <- data segment
; ------------- Check if current date changed
mov ax,[DOSClockDate] ; AX <- date in days from 1/1/1980
cmp ax,[CurrDate] ; current date changed?
je GetDateTime9 ; current date did not change
; ------------- Calculate new current date
call DOS2Date ; recalc DOS date do date
mov [CurrDayMonth],dx ; current day and month
mov al,100 ; years in century
mul ch ; recalc century to years
mov ch,0 ; CX = year in century
add ax,cx ; AX <- year
mov [CurrYear],ax ; current year
; ------------- Calculate day of week
call CalcDayWeek ; calculate day of week
; ------------- Pop registers
GetDateTime9: pop dx ; pop DX
pop cx ; pop CX
pop bx ; pop BX
pop ax ; pop AX
ret
; ----------------------------------------------------------------------------
; Set system date or time
; ----------------------------------------------------------------------------
; INPUT: AL = 0 for date
; CX = year (1980-2099)
; DH = month (1-12)
; DL = day (1-31)
; AL <> 0 for time
; CH = hour (0 to 23)
; CL = minute (0 to 59)
; DH = second (0 to 59)
; DL = 1/100 seconds (0 to 99)
; OUTPUT: DS = data segment
; DESTROYS: SI, ES
; NOTES: Date and time must be valid!
; ----------------------------------------------------------------------------
; ------------- Push registers
SetDateTime: push ax ; push AX
push bx ; push BX
push cx ; push CX
push dx ; push DX
; ------------- Get system date and time (data segment -> DS)
call GetDateTime ; get system date and time
; ------------- Check if a date will be set
or al,al ; set date?
jz SetDateTime4 ; set date
; ------------- Store current time
mov [DOSClockMinHour],cx ; store minute and hour
mov [DOSClockHundSec],dx ; store hundredth and second
jmp short SetDateTime6
; ------------- Store current date
SetDateTime4: mov [CurrDayMonth],dx ; store current day and month
mov [CurrYear],cx ; store current year
; ------------- Split year into year and century (-> CX)
mov al,100 ; AL <- 100 years in century
xchg ax,cx ; AX <- year, CL <- 100
div cl ; split year
xchg al,ah ; AL <- year, AH <- century
xchg ax,cx ; CL <- year, CH <- century
; ------------- Recalc date to DOS date (-> AX)
call Date2DOS ; recalc date to DOS date
mov [CurrDate],ax ; store current date
mov [DOSClockDate],ax ; set new current date
; ------------- Calculate day of week
call CalcDayWeek ; calculate day of week
; ------------- Prepare DDR table for write operation
SetDateTime6: xor ax,ax ; AL <- 0 unit, AH <- 0 media
mov bx,DOSClock ; BX <- DOS clock buffer
mov cx,CLOCKData_size ; size of data
xor dx,dx ; DX <- starting offset
call InitW16DDR ; prepare DDR table
; ------------- Write system date and time
push cs ; push CS
pop es ; ES <- data segment
lds si,[ClockDev] ; DS:SI <- clock device header
call DevExec ; execute device service
push cs ; push CS
pop ds ; DS <- data segment
; ------------- Pop registers
pop dx ; pop DX
pop cx ; pop CX
pop bx ; pop BX
pop ax ; pop AX
ret
; ----------------------------------------------------------------------------
; Int 21h, function 2Ah - Get system date
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 2Ah (function code)
; INT21 OUTPUT: AL = day of week (0-6, 0=Sunday, 1=Monday, ...)
; CX = year (1980-2099)
; DH = month (1-12)
; DL = day (1-31)
; ----------------------------------------------------------------------------
; ------------- Get system date and time
Int212A: call GetDateTime ; get system date and time
; ------------- Return current date
mov cx,[CurrYear] ; CX <- year
call SetRegCX ; set year
mov dx,[CurrDayMonth] ; DL <- day, DH <- month
call SetRegDX ; set day and month
mov al,[CurrDayWeek] ; AL <- day of week
ret
; ----------------------------------------------------------------------------
; Int 21h, function 2Bh - Set system date
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 2Bh (function code)
; CX = year (1980-2099)
; DH = month (1-12)
; DL = day (1-31)
; INT21 OUTPUT: AL = result
; 0: successful
; 0ffh: invalid date, system date unchanged
; ----------------------------------------------------------------------------
; ------------- Check year
Int212B: mov al,0ffh ; AL <- 0ffh, invalid date flag
cmp cx,1980 ; minimal year
jb Int212B8 ; invalid year
cmp cx,2099 ; maximal year
ja Int212B8 ; invalid year
; ------------- Check month
or dh,dh ; minimal month
jz Int212B8 ; invalid month
cmp dh,12 ; maximal month
ja Int212B8 ; invalid month
; ------------- Prepare days in February
push cx ; push CX
sub cx,1980 ; CX <- offset from 1980
call PrepareFeb ; prepare February
pop cx ; pop CX
; ------------- Check day
or dl,dl ; minimal day
jz Int212B8 ; invalid day
push bx ; push BX
xor bx,bx ; BX <- 0
mov bl,dh ; BL <- month
cmp dl,[cs:bx+DayMonthTab-1] ; check days in month
pop bx ; pop BX
ja Int212B8 ; invalid day
; ------------- Set system date
mov al,0 ; AL <- 0, flag to set date, result OK
call SetDateTime ; set system date
Int212B8: ret
; ----------------------------------------------------------------------------
; Int 21h, function 2Ch - Get system time
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 2Ch (function code)
; INT21 OUTPUT: CH = hour (0 to 23)
; CL = minute (0 to 59)
; DH = second (0 to 59)
; DL = 1/100 seconds (0 to 99)
; NOTES: Time resolution is 55 ms. On some systems DL may return 0.
; ----------------------------------------------------------------------------
; ------------- Get system date and time
Int212C: call GetDateTime ; get system date and time
; ------------- Return current time
mov cx,[DOSClockMinHour] ; CL <- minute, CH <- hour
call SetRegCX ; set minute and hour
mov dx,[DOSClockHundSec] ; DL <- hundredth, DH <- second
call SetRegDX ; set hundredth and second
mov al,0 ; return code OK
ret
; ----------------------------------------------------------------------------
; Int 21h, function 2Dh - Set system time
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 2Dh (function code)
; CH = hour (0 to 23)
; CL = minute (0 to 59)
; DH = second (0 to 59)
; DL = 1/100 seconds (0 to 99)
; INT21 OUTPUT: AL = result
; 0: successful
; 0ffh: invalid time, system time unchanged
; ----------------------------------------------------------------------------
; ------------- Check time
Int212D: mov al,0ffh ; AL <- 0ffh, invalid time flag
cmp ch,23 ; maximal hour
ja Int212D8 ; invalid hour
cmp cl,59 ; maximal minute
ja Int212D8 ; invalid minute
cmp dh,59 ; maximal second
ja Int212D8 ; invalid second
cmp dl,99 ; maximal hundredth
ja Int212D8 ; invalid hundredth
; ------------- Set system time (here is AL = 0ffh)
call SetDateTime ; set system time
mov al,0 ; return code OK
Int212D8: ret
; ----------------------------------------------------------------------------
; Data
; ----------------------------------------------------------------------------
; ------------- DOS clock data
DOSClock: ; structure CLOCKData
DOSClockDate: dw 0 ; date in days from 1/1/1980
DOSClockMinHour:
DOSClockMin: db 0 ; minute (0 to 59)
DOSClockHour: db 0 ; hour (0 to 23)
DOSClockHundSec:
DOSClockHund: db 0 ; hundredth second (0 to 99)
DOSClockSec: db 0 ; second (0 to 59)
CurrDate: dw 0 ; current date from 1/1/1980
CurrDayMonth:
CurrDay: db 1 ; currant day (1 to 31)
CurrMonth: db 1 ; current month (1 to 12)
CurrYear: dw 1980 ; current year (1980 to 2099)
CurrDayWeek: db 2 ; current day of week (0=Sunday to 6)
|