From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/DOS/TIME.ASM | 380 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 v4.0/src/DOS/TIME.ASM (limited to 'v4.0/src/DOS/TIME.ASM') diff --git a/v4.0/src/DOS/TIME.ASM b/v4.0/src/DOS/TIME.ASM new file mode 100644 index 0000000..0d3895c --- /dev/null +++ b/v4.0/src/DOS/TIME.ASM @@ -0,0 +1,380 @@ +; SCCSID = @(#)time.asm 1.1 85/04/10 +TITLE TIME - time and date functions +NAME TIME +; +; System Calls and low level routines for DATE and TIME +; +; $GET_DATE +; $SET_DATE +; $GET_TIME +; $SET_TIME +; DATE16 +; READTIME +; DSLIDE +; SETYEAR +; DODATE +; DSUM +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + + + i_need DAY,BYTE + i_need MONTH,BYTE + i_need YEAR,WORD + i_need WEEKDAY,BYTE + i_need TIMEBUF,6 + i_need BCLOCK,DWORD + i_need DAYCNT,WORD + i_need YRTAB,8 + i_need MONTAB,12 + i_need DATE_FLAG,WORD + + FOURYEARS = 3*365 + 366 + +SUBTTL DATE AND TIME - SYSTEM CALLS 42,43,44,45 +PAGE + procedure $GET_DATE,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; None +; Function: +; Return current date +; Returns: +; Date in CX:DX + + Context DS + CALL READTIME ;Check for rollover to next day + MOV AX,[YEAR] +; +; WARNING!!!! DAY and MONTH must be adjacently allocated! +; + MOV BX,WORD PTR [DAY] ; fetch both day and month + invoke get_user_stack ;Get pointer to user registers +ASSUME DS:NOTHING + MOV [SI.user_DX],BX ;DH=month, DL=day + ADD AX,1980 ;Put bias back + MOV [SI.user_CX],AX ;CX=year + MOV AL,BYTE PTR [WEEKDAY] + return +EndProc $GET_DATE + + procedure $SET_DATE,NEAR ;System call 43 +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; CX:DX valid date +; Function: +; Set current date +; Returns: +; AL = -1 date bad, = 0 OK + + MOV AL,-1 ;Be ready to flag error + SUB CX,1980 ;Fix bias in year + retc ;Error if not big enough + CMP CX,119 ;Year must be less than 2100 + JA RET24 + OR DH,DH + retz + OR DL,DL + retz ;Error if either month or day is 0 + CMP DH,12 ;Check against max. month + JA RET24 + Context DS + invoke DODATE +RET24: return +EndProc $SET_DATE + + procedure $GET_TIME,NEAR ;System call 44 +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; None +; Function: +; Get current time +; Returns: +; Time in CX:DX + + Context DS + CALL READTIME + invoke get_user_stack ;Get pointer to user registers + MOV [SI.user_DX],DX + MOV [SI.user_CX],CX + XOR AL,AL +RET26: return +EndProc $GET_TIME + + procedure $SET_TIME,NEAR ;System call 45 +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; CX:DX = Time +; Function: +; Set time +; Returns: +; AL = -1 time bad, = 0 OK + + MOV AL,-1 ;Flag in case of error + CMP CH,24 ;Check hours + JAE RET26 + CMP CL,60 ;Check minutes + JAE RET26 + CMP DH,60 ;Check seconds + JAE RET26 + CMP DL,100 ;Check 1/100's + JAE RET26 + PUSH CX + PUSH DX + Context DS + MOV BX,OFFSET DOSGROUP:TIMEBUF + MOV CX,6 + XOR DX,DX + MOV AX,DX + PUSH BX + invoke SETREAD + DOSAssume CS,,"TIME/SetRead" + PUSH DS + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Get correct day count + POP DS + DOSAssume CS,,"TIME/DevIOCall2" + POP BX + invoke SETWRITE + POP WORD PTR [TIMEBUF+4] + POP WORD PTR [TIMEBUF+2] + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Set the time + XOR AL,AL + return +EndProc $SET_TIME + +SUBTTL DATE16, READTIME, DODATE -- GUTS OF TIME AND DATE +PAGE + +; +; Date16 returns the current date in AX, current time in DX +; AX - YYYYYYYMMMMDDDDD years months days +; DX - HHHHHMMMMMMSSSSS hours minutes seconds/2 +; +; DS = DOSGROUP on output + +procedure DATE16,NEAR + Context DS + ASSUME ES:NOTHING + PUSH CX + PUSH ES + CALL READTIME + POP ES + SHL CL,1 ;Minutes to left part of byte + SHL CL,1 + SHL CX,1 ;Push hours and minutes to left end + SHL CX,1 + SHL CX,1 + SHR DH,1 ;Count every two seconds + OR CL,DH ;Combine seconds with hours and minutes + MOV DX,CX +; +; WARNING! MONTH and YEAR must be adjacently allocated +; + MOV AX,WORD PTR [MONTH] ;Fetch month and year + MOV CL,4 + SHL AL,CL ;Push month to left to make room for day + SHL AX,1 + POP CX + OR AL,[DAY] + return +EndProc DATE16 + +;Gets time in CX:DX. Figures new date if it has changed. +;Uses AX, CX, DX. + + procedure READTIME,NEAR + DOSAssume CS,,"ReadTime" + ASSUME ES:NOTHING + + MOV [DATE_FLAG],0 ; reset date flag for CPMIO + PUSH SI + PUSH BX + MOV BX,OFFSET DOSGROUP:TIMEBUF + MOV CX,6 + XOR DX,DX + MOV AX,DX + invoke SETREAD + PUSH DS + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Get correct date and time + POP DS + DOSAssume CS,,"ReadTime/DevIOCall2" + POP BX + POP SI + MOV AX,WORD PTR [TIMEBUF] + MOV CX,WORD PTR [TIMEBUF+2] + MOV DX,WORD PTR [TIMEBUF+4] + CMP AX,[DAYCNT] ;See if day count is the same + retz + CMP AX,FOURYEARS*30 ;Number of days in 120 years + JAE RET22 ;Ignore if too large + MOV [DAYCNT],AX + PUSH SI + PUSH CX + PUSH DX ;Save time + XOR DX,DX + MOV CX,FOURYEARS ;Number of days in 4 years + DIV CX ;Compute number of 4-year units + SHL AX,1 + SHL AX,1 + SHL AX,1 ;Multiply by 8 (no. of half-years) + MOV CX,AX ;<240 implies AH=0 + MOV SI,OFFSET DOSGROUP:YRTAB;Table of days in each year + CALL DSLIDE ;Find out which of four years we're in + SHR CX,1 ;Convert half-years to whole years + JNC SK ;Extra half-year? + ADD DX,200 +SK: + CALL SETYEAR + MOV CL,1 ;At least at first month in year + MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month + CALL DSLIDE ;Find out which month we're in + MOV [MONTH],CL + INC DX ;Remainder is day of month (start with one) + MOV [DAY],DL + CALL WKDAY ;Set day of week + POP DX + POP CX + POP SI +RET22: return +EndProc READTIME + + procedure DSLIDE,NEAR + MOV AH,0 +DSLIDE1: + LODSB ;Get count of days + CMP DX,AX ;See if it will fit + retc ;If not, done + SUB DX,AX + INC CX ;Count one more month/year + JMP SHORT DSLIDE1 +EndProc DSLIDE + + procedure SETYEAR,NEAR +;Set year with value in CX. Adjust length of February for this year. + MOV BYTE PTR [YEAR],CL + +CHKYR: + TEST CL,3 ;Check for leap year + MOV AL,28 + JNZ SAVFEB ;28 days if no leap year + INC AL ;Add leap day +SAVFEB: + MOV [MONTAB+1],AL ;Store for February +RET23: return +EndProc SETYEAR + + procedure DODATE,NEAR + DOSAssume CS,,"DoDate" + ASSUME ES:NOTHING + CALL CHKYR ;Set Feb. up for new year + MOV AL,DH + MOV BX,OFFSET DOSGROUP:MONTAB-1 + XLAT ;Look up days in month + CMP AL,DL + MOV AL,-1 ;Restore error flag, just in case + retc ;Error if too many days + CALL SETYEAR +; +; WARNING! DAY and MONTH must be adjacently allocated +; + MOV WORD PTR [DAY],DX ;Set both day and month + SHR CX,1 + SHR CX,1 + MOV AX,FOURYEARS + MOV BX,DX + MUL CX + MOV CL,BYTE PTR [YEAR] + AND CL,3 + MOV SI,OFFSET DOSGROUP:YRTAB + MOV DX,AX + SHL CX,1 ;Two entries per year, so double count + CALL DSUM ;Add up the days in each year + MOV CL,BH ;Month of year + MOV SI,OFFSET DOSGROUP:MONTAB + DEC CX ;Account for months starting with one + CALL DSUM ;Add up days in each month + MOV CL,BL ;Day of month + DEC CX ;Account for days starting with one + ADD DX,CX ;Add in to day total + XCHG AX,DX ;Get day count in AX + MOV [DAYCNT],AX + PUSH SI + PUSH BX + PUSH AX + MOV BX,OFFSET DOSGROUP:TIMEBUF + MOV CX,6 + XOR DX,DX + MOV AX,DX + PUSH BX + invoke SETREAD + DOSAssume CS,,"DoDate/SetRead" + PUSH DS + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Get correct date and time + POP DS + POP BX + DOSAssume CS,,"DoDate/DevIOCall2" + invoke SETWRITE + POP WORD PTR [TIMEBUF] + PUSH DS + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Set the date + POP DS + DOSAssume CS,,"DoDate/DevIOCall2(second)" + POP BX + POP SI +WKDAY: + MOV AX,[DAYCNT] + XOR DX,DX + MOV CX,7 + INC AX + INC AX ;First day was Tuesday + DIV CX ;Compute day of week + MOV [WEEKDAY],DL + XOR AL,AL ;Flag OK +Ret25: return +EndProc DODATE + + procedure DSUM,NEAR + MOV AH,0 + JCXZ RET25 +DSUM1: + LODSB + ADD DX,AX + LOOP DSUM1 + return +EndProc DSUM + +CODE ENDS + END + \ No newline at end of file -- cgit v1.2.3