     1                                  ;	SCCSID = @(#)time.asm	1.1 85/04/10
     2                                  ;TITLE	TIME - time and date functions
     3                                  ;NAME	TIME
     4                                  ;
     5                                  ; System Calls and low level routines for DATE and TIME
     6                                  ;
     7                                  ;   $GET_DATE
     8                                  ;   $SET_DATE
     9                                  ;   $GET_TIME
    10                                  ;   $SET_TIME
    11                                  ;   DATE16
    12                                  ;   READTIME
    13                                  ;   DSLIDE
    14                                  ;   SETYEAR
    15                                  ;   DODATE
    16                                  ;   DSUM
    17                                  ;
    18                                  ;   Modification history:
    19                                  ;
    20                                  ;	Created: ARR 30 March 1983
    21                                  ;
    22                                  
    23                                  [list -]
    23          ******************       warning: redefining multi-line macro `struc' [-w+pp-macro-redef-multi]
    14                              <4> [list -]
    14                              <3> [list -]
     3                              <2> 
     4                              <2> addsection DOSSTART, align=16 PUBLIC class=DOSSTART
     5                              <2> ; (no prior section) ; DOSSTART		ENDS
     6                              <2> 
     7                              <2> addsection DOSSTARTJUMP, align=1 PUBLIC class=START
     8                              <2> ; (no prior section) ; DOSSTARTJUMP		ENDS
     9                              <2> 
    10                              <2> addsection CONSTANTS, align=2 PUBLIC class=CONST
    11                              <2> ; (no prior section) ; CONSTANTS	ENDS
    12                              <2> 
    13                              <2> addsection DATA, align=2 PUBLIC class=DATA
    14                              <2> ; (no prior section) ; DATA		ENDS
    15                              <2> 
    16                              <2> addsection TABLE, align=2 PUBLIC class=TABLE
    17                              <2> ; (no prior section) ; TABLE		ENDS
    18                              <2> 
    19                              <2> addsection DOSDATATABLE, align=2 PUBLIC class=DOSDATACODE
    20                              <2> ; (no prior section) ; DOSDATATABLE		ENDS
    21                              <2> 
    22                              <2> addsection DOSDATACODE, align=1 PUBLIC class=DOSDATACODE
    23                              <2> ; (no prior section) ; DOSDATACODE		ENDS
    24                              <2> 
    25                              <2> addsection DOSBIODATA, align=2 PUBLIC class=DOSBIODATA
    26                              <2> 
    27                              <2> addsection LAST, align=16 PUBLIC class=LAST
    28                              <2> ; (no prior section) ; LAST		ENDS
    29                              <2> 
    30                              <2> group DOSGROUP DOSSTART DOSSTARTJUMP CONSTANTS DATA TABLE DOSDATATABLE DOSDATACODE DOSBIODATA LAST
     8                              <1> 
     9                              <1> %include "dcodeseg.nas"
     1                              <2> 
     2                              <2> %ifndef DCODESEGNAS
     3                              <2> %assign DCODESEGNAS 1
     4                              <2> 
     5                              <2> section DOSCODETABLE align=2 PUBLIC class=DOSCODE
     6                              <2> ; (no prior section) ; DOSCODETABLE		ENDS
     7                              <2> section DOSCODECODE align=1 PUBLIC class=DOSCODE
     8                              <2> ; (no prior section) ; DOSCODECODE		ENDS
     9                              <2> section DOSBIOCODE align=2 PUBLIC class=DOSCODE
    10                              <2> section BIOCODE	align=2 PUBLIC class=DOSCODE
    11                              <2> 
    12                              <2> %ifnidni DOSENTRYGROUP, DOSCODEGROUP
    13                              <2>  group DOSCODEGROUP DOSCODETABLE DOSCODECODE DOSBIOCODE BIOCODE
    14                              <2> %endif
    15                              <2> 
    16                              <2> %endif
    10                              <1> 
    11                              <1> section LAST
    12                              <1> ; (no prior section) ; LAST		ENDS
    28                                  
    29                                  [list +]
    30                                  section DOSCODECODE
    31                                  [list -]
    31          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    31          ******************       warning: out: BPB.INC... [-w+user]
    31          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    31          ******************       warning: out: DEVSYM.INC... [-w+user]
    38                                  
    39                                  
    40                                      i_need  DAY,BYTE
    41                                      i_need  MONTH,BYTE
    42                                      i_need  YEAR,WORD
    43                                      i_need  WEEKDAY,BYTE
    44                                      i_need  TIMEBUF,6
    45                                      i_need  BCLOCK,DWORD
    46                                      i_need  DAYCNT_DOS,WORD
    47                                      i_need  YRTAB,8
    48                                      i_need  MONTAB,12
    49                                      i_need  DATE_FLAG,WORD
    50                                  
    51                                      FOURYEARS equ 3*365 + 366
    52                                  
    53                                   assume nocheck, ss:DOSGROUP
    54                                  
    55                                  ;SUBTTL DATE AND TIME - SYSTEM CALLS 42,43,44,45
    56                                  ;PAGE
    57                                  	procedure   D_GET_DATE,NEAR
    57          ******************       warning: proc D_GET_DATE... [-w+user]
    58                                  ASSUME	DS:NOTHING,ES:NOTHING
    59                                  
    60                                  ; Inputs:
    61                                  ;	None
    62                                  ; Function:
    63                                  ;	Return current date
    64                                  ; Returns:
    65                                  ;	Date in CX:DX
    66                                  
    67 00000000 161F                    	Context DS
    68 00000002 E8B700                  	CALL	READTIME		;Check for rollover to next day
    69 00000005 A1[0000]                	MOV	AX,[YEAR]
    70                                  ;
    71                                  ; WARNING!!!! DAY and MONTH must be adjacently allocated!
    72                                  ;
    73 00000008 8B1E[0000]              	MOV	BX,WORD PTR [DAY]	; fetch both day and month
    74 0000000C E8(0000)                	invoke	get_user_stack		;Get pointer to user registers
    75                                  ASSUME	DS:NOTHING
    76 0000000F 895C06                  	MOV	[SI + user_DX],BX 	;DH=month, DL=day
    77 00000012 05BC07                  	ADD	AX,1980 		;Put bias back
    78 00000015 894404                  	MOV	[SI + user_CX],AX 	;CX=year
    79 00000018 36A0[0000]              	MOV	AL,BYTE PTR [ss:WEEKDAY]
    80 0000001C C3                      	return
    81                                  EndProc D_GET_DATE
    82                                  
    83                                  	procedure   D_SET_DATE,NEAR	;System call 43
    83          ******************       warning: proc D_SET_DATE... [-w+user]
    84                                  ASSUME	DS:NOTHING,ES:NOTHING
    85                                  
    86                                  ; Inputs:
    87                                  ;	CX:DX valid date
    88                                  ; Function:
    89                                  ;	Set current date
    90                                  ; Returns:
    91                                  ;	AL = -1 date bad, = 0 OK
    92                                  
    93 0000001D B0FF                    	MOV	AL,-1			;Be ready to flag error
    94 0000001F 81E9BC07                	SUB	CX,1980 		;Fix bias in year
    95 00000023 72F7                    	retc				;Error if not big enough
    96 00000025 83F977                  	CMP	CX,119			;Year must be less than 2100
    97 00000028 7712                    	JA	RET24
    98 0000002A 08F6                    	OR	DH,DH
    99 0000002C 74EE                    	retz
   100 0000002E 08D2                    	OR	DL,DL
   101 00000030 74EA                    	retz				;Error if either month or day is 0
   102 00000032 80FE0C                  	CMP	DH,12			;Check against max. month
   103 00000035 7705                    	JA	RET24
   104 00000037 161F                    	Context DS
   105 00000039 E81001                  	invoke	DODATE
   106 0000003C C3                      RET24:	return
   107                                  EndProc D_SET_DATE
   108                                  
   109                                  	procedure   D_GET_TIME,NEAR	;System call 44
   109          ******************       warning: proc D_GET_TIME... [-w+user]
   110                                  ASSUME	DS:NOTHING,ES:NOTHING
   111                                  
   112                                  ; Inputs:
   113                                  ;	None
   114                                  ; Function:
   115                                  ;	Get current time
   116                                  ; Returns:
   117                                  ;	Time in CX:DX
   118                                  
   119 0000003D 161F                    	Context DS
   120 0000003F E87A00                  	CALL	READTIME
   121 00000042 E8(0000)                	invoke	get_user_stack		;Get pointer to user registers
   122 00000045 895406                  	MOV	[SI + user_DX],DX
   123 00000048 894C04                  	MOV	[SI + user_CX],CX
   124 0000004B 30C0                    	XOR	AL,AL
   125 0000004D C3                      RET26:	return
   126                                  EndProc D_GET_TIME
   127                                  
   128                                  	procedure   D_SET_TIME,NEAR	;System call 45
   128          ******************       warning: proc D_SET_TIME... [-w+user]
   129                                  ASSUME	DS:NOTHING,ES:NOTHING
   130                                  
   131                                  ; Inputs:
   132                                  ;	CX:DX = Time
   133                                  ; Function:
   134                                  ;	Set time
   135                                  ; Returns:
   136                                  ;	AL = -1 time bad, = 0 OK
   137                                  
   138 0000004E B0FF                    	MOV	AL,-1			;Flag in case of error
   139 00000050 80FD18                  	CMP	CH,24			;Check hours
   140 00000053 73F8                    	JAE	RET26
   141 00000055 80F93C                  	CMP	CL,60			;Check minutes
   142 00000058 73F3                    	JAE	RET26
   143 0000005A 80FE3C                  	CMP	DH,60			;Check seconds
   144 0000005D 73EE                    	JAE	RET26
   145 0000005F 80FA64                  	CMP	DL,100			;Check 1/100's
   146 00000062 73E9                    	JAE	RET26
   147 00000064 51                      	PUSH	CX
   148 00000065 52                      	PUSH	DX
   149 00000066 161F                    	Context DS
   150 00000068 BB[0000]                	MOV	BX,OFFSET TIMEBUF wrt DOSGROUP
   151 0000006B B90600                  	MOV	CX,6
   152 0000006E 31D2                    	XOR	DX,DX
   153 00000070 89D0                    	MOV	AX,DX
   154 00000072 53                      	PUSH	BX
   155 00000073 E8(0000)                	invoke	SETREAD
   156                                  	DOSAssume   CS,<ES>,"TIME/SetRead"
   157 00000076 1E                      	PUSH	DS
   158 00000077 C536[0000]              	LDS	SI,[BCLOCK]
   159                                  ASSUME	DS:NOTHING
   160 0000007B E8(0000)                	invoke	DEVIOCALL2		;Get correct day count
   161 0000007E 1F                      	POP	DS
   162                                  	DOSAssume   CS,<DS>,"TIME/DevIOCall2"
   163 0000007F 5B                      	POP	BX
   164 00000080 E8(0000)                	invoke	SETWRITE
   165 00000083 8F06[0400]              	POP	WORD PTR [TIMEBUF+4]
   166 00000087 8F06[0200]              	POP	WORD PTR [TIMEBUF+2]
   167 0000008B C536[0000]              	LDS	SI,[BCLOCK]
   168                                  ASSUME	DS:NOTHING
   169 0000008F E8(0000)                	invoke	DEVIOCALL2		;Set the time
   170 00000092 30C0                    	XOR	AL,AL
   171 00000094 C3                      	return
   172                                  EndProc D_SET_TIME
   173                                  
   174                                  ;SUBTTL DATE16, READTIME, DODATE -- GUTS OF TIME AND DATE
   175                                  ;PAGE
   176                                  
   177                                  ;
   178                                  ; Date16 returns the current date in AX, current time in DX
   179                                  ;   AX - YYYYYYYMMMMDDDDD  years months days
   180                                  ;   DX - HHHHHMMMMMMSSSSS  hours minutes seconds/2
   181                                  ;
   182                                  ; DS = DOSGROUP on output
   183                                  
   184                                  procedure   DATE16,NEAR
   184          ******************       warning: proc DATE16... [-w+user]
   185 00000095 161F                    	Context DS
   186                                  	ASSUME	ES:NOTHING
   187 00000097 51                      	PUSH	CX
   188 00000098 06                      	PUSH	ES
   189 00000099 E82000                  	CALL	READTIME
   190 0000009C 07                      	POP	ES
   191                                   assume es:nothing
   192 0000009D D0E1                    	SHL	CL,1			;Minutes to left part of byte
   193 0000009F D0E1                    	SHL	CL,1
   194 000000A1 D1E1                    	SHL	CX,1			;Push hours and minutes to left end
   195 000000A3 D1E1                    	SHL	CX,1
   196 000000A5 D1E1                    	SHL	CX,1
   197 000000A7 D0EE                    	SHR	DH,1			;Count every two seconds
   198 000000A9 08F1                    	OR	CL,DH			;Combine seconds with hours and minutes
   199 000000AB 89CA                    	MOV	DX,CX
   200                                  ;
   201                                  ; WARNING!  MONTH and YEAR must be adjacently allocated
   202                                  ;
   203 000000AD A1[0000]                	MOV	AX,WORD PTR [MONTH]	;Fetch month and year
   204 000000B0 B104                    	MOV	CL,4
   205 000000B2 D2E0                    	SHL	AL,CL			;Push month to left to make room for day
   206 000000B4 D1E0                    	SHL	AX,1
   207 000000B6 59                      	POP	CX
   208 000000B7 0A06[0000]              	OR	AL,[DAY]
   209 000000BB C3                      	return
   210                                  EndProc DATE16
   211                                  
   212                                  ;Gets time in CX:DX. Figures new date if it has changed.
   213                                  ;Uses AX, CX, DX.
   214                                  
   215                                  	procedure   READTIME,NEAR
   215          ******************       warning: proc READTIME... [-w+user]
   216                                  	DOSAssume   CS,<DS>,"ReadTime"
   217                                  	ASSUME	ES:NOTHING
   218                                  
   219 000000BC C706[0000]0000          	MOV	word [DATE_FLAG],0		; reset date flag for CPMIO
   220 000000C2 56                      	PUSH	SI
   221 000000C3 53                      	PUSH	BX
   222 000000C4 BB[0000]                	MOV	BX,OFFSET TIMEBUF wrt DOSGROUP
   223 000000C7 B90600                  	MOV	CX,6
   224 000000CA 31D2                    	XOR	DX,DX
   225 000000CC 89D0                    	MOV	AX,DX
   226 000000CE E8(0000)                	invoke	SETREAD
   227 000000D1 1E                      	PUSH	DS
   228 000000D2 C536[0000]              	LDS	SI,[BCLOCK]
   229                                  ASSUME	DS:NOTHING
   230 000000D6 E8(0000)                	invoke	DEVIOCALL2		;Get correct date and time
   231 000000D9 1F                      	POP	DS
   232                                  	DOSAssume   CS,<DS>,"ReadTime/DevIOCall2"
   233 000000DA 5B                      	POP	BX
   234 000000DB 5E                      	POP	SI
   235 000000DC A1[0000]                	MOV	AX,WORD PTR [TIMEBUF]
   236 000000DF 8B0E[0200]              	MOV	CX,WORD PTR [TIMEBUF+2]
   237 000000E3 8B16[0400]              	MOV	DX,WORD PTR [TIMEBUF+4]
   238 000000E7 3B06[0000]              	CMP	AX,[DAYCNT_DOS]		;See if day count is the same
   239 000000EB 74CE                    	retz
   240 000000ED 3D36AB                  	CMP	AX,FOURYEARS*30 	;Number of days in 120 years
   241 000000F0 733D                    	JAE	RET22			;Ignore if too large
   242 000000F2 A3[0000]                	MOV	[DAYCNT_DOS],AX
   243 000000F5 56                      	PUSH	SI
   244 000000F6 51                      	PUSH	CX
   245 000000F7 52                      	PUSH	DX			;Save time
   246 000000F8 31D2                    	XOR	DX,DX
   247 000000FA B9B505                  	MOV	CX,FOURYEARS		;Number of days in 4 years
   248 000000FD F7F1                    	DIV	CX			;Compute number of 4-year units
   249 000000FF D1E0                    	SHL	AX,1
   250 00000101 D1E0                    	SHL	AX,1
   251 00000103 D1E0                    	SHL	AX,1			;Multiply by 8 (no. of half-years)
   252 00000105 89C1                    	MOV	CX,AX			;<240 implies AH=0
   253 00000107 BE[0000]                	MOV	SI,OFFSET YRTAB wrt DOSGROUP;Table of days in each year
   254 0000010A E82300                  	CALL	DSLIDE			;Find out which of four years we're in
   255 0000010D D1E9                    	SHR	CX,1			;Convert half-years to whole years
   256 0000010F 7304                    	JNC	SK			;Extra half-year?
   257 00000111 81C2C800                	ADD	DX,200
   258                                  SK:
   259 00000115 E82400                  	CALL	SETYEAR
   260 00000118 B101                    	MOV	CL,1			;At least at first month in year
   261 0000011A BE[0000]                	MOV	SI,OFFSET MONTAB wrt DOSGROUP   ;Table of days in each month
   262 0000011D E81000                  	CALL	DSLIDE			;Find out which month we're in
   263 00000120 880E[0000]              	MOV	[MONTH],CL
   264 00000124 42                      	INC	DX			;Remainder is day of month (start with one)
   265 00000125 8816[0000]              	MOV	[DAY],DL
   266 00000129 E89100                  	CALL	WKDAY			;Set day of week
   267 0000012C 5A                      	POP	DX
   268 0000012D 59                      	POP	CX
   269 0000012E 5E                      	POP	SI
   270 0000012F C3                      RET22:	return
   271                                  EndProc READTIME
   272                                  
   273                                  	procedure   DSLIDE,NEAR
   273          ******************       warning: proc DSLIDE... [-w+user]
   274 00000130 B400                    	MOV	AH,0
   275                                  DSLIDE1:
   276 00000132 AC                      	LODSB				;Get count of days
   277 00000133 39C2                    	CMP	DX,AX			;See if it will fit
   278 00000135 72F8                    	retc				;If not, done
   279 00000137 29C2                    	SUB	DX,AX
   280 00000139 41                      	INC	CX			;Count one more month/year
   281 0000013A EBF6                    	JMP	SHORT DSLIDE1
   282                                  EndProc DSLIDE
   283                                  
   284                                  	procedure   SETYEAR,NEAR
   284          ******************       warning: proc SETYEAR... [-w+user]
   285                                  ;Set year with value in CX. Adjust length of February for this year.
   286 0000013C 880E[0000]              	MOV	BYTE PTR [YEAR],CL
   287                                  
   288                                  CHKYR:
   289 00000140 F6C103                  	TEST	CL,3			;Check for leap year
   290 00000143 B01C                    	MOV	AL,28
   291 00000145 7501                    	JNZ	SAVFEB			;28 days if no leap year
   292 00000147 40                      	inc ax				;Add leap day
   293                                  SAVFEB:
   294 00000148 A2[0100]                	MOV	[MONTAB+1],AL		;Store for February
   295 0000014B C3                      RET23:	return
   296                                  EndProc SETYEAR
   297                                  
   298                                  	procedure   DODATE,NEAR
   298          ******************       warning: proc DODATE... [-w+user]
   299                                  	DOSAssume   CS,<DS>,"DoDate"
   300                                  	ASSUME	ES:NOTHING
   301 0000014C E8F1FF                  	CALL	CHKYR			;Set Feb. up for new year
   302 0000014F 88F0                    	MOV	AL,DH
   303 00000151 BB[FFFF]                	MOV	BX,OFFSET MONTAB-1 wrt DOSGROUP	; access with ds
   304 00000154 D7                      	xlatb;Look up days in month
   305 00000155 38D0                    	CMP	AL,DL
   306 00000157 B0FF                    	MOV	AL,-1			;Restore error flag, just in case
   307 00000159 72F0                    	retc				;Error if too many days
   308 0000015B E8DEFF                  	CALL	SETYEAR
   309                                  ;
   310                                  ; WARNING!  DAY and MONTH must be adjacently allocated
   311                                  ;
   312 0000015E 8916[0000]              	MOV	WORD PTR [DAY],DX	;Set both day and month
   313 00000162 D1E9                    	SHR	CX,1
   314 00000164 D1E9                    	SHR	CX,1
   315 00000166 B8B505                  	MOV	AX,FOURYEARS
   316 00000169 89D3                    	MOV	BX,DX
   317 0000016B F7E1                    	MUL	CX
   318 0000016D 8A0E[0000]              	MOV	CL,BYTE PTR [YEAR]
   319 00000171 80E103                  	AND	CL,3
   320 00000174 BE[0000]                	MOV	SI,OFFSET YRTAB wrt DOSGROUP
   321 00000177 89C2                    	MOV	DX,AX
   322 00000179 D1E1                    	SHL	CX,1			;Two entries per year, so double count
   323 0000017B E85200                  	CALL	DSUM			;Add up the days in each year
   324 0000017E 88F9                    	MOV	CL,BH			;Month of year
   325 00000180 BE[0000]                	MOV	SI,OFFSET MONTAB wrt DOSGROUP
   326 00000183 49                      	DEC	CX			;Account for months starting with one
   327 00000184 E84900                  	CALL	DSUM			;Add up days in each month
   328 00000187 88D9                    	MOV	CL,BL			;Day of month
   329 00000189 49                      	DEC	CX			;Account for days starting with one
   330 0000018A 01CA                    	ADD	DX,CX			;Add in to day total
   331 0000018C 92                      	XCHG	AX,DX			;Get day count in AX
   332 0000018D A3[0000]                	MOV	[DAYCNT_DOS],AX
   333 00000190 56                      	PUSH	SI
   334 00000191 53                      	PUSH	BX
   335 00000192 50                      	PUSH	AX
   336 00000193 BB[0000]                	MOV	BX,OFFSET TIMEBUF wrt DOSGROUP
   337 00000196 B90600                  	MOV	CX,6
   338 00000199 31D2                    	XOR	DX,DX
   339 0000019B 89D0                    	MOV	AX,DX
   340 0000019D 53                      	PUSH	BX
   341 0000019E E8(0000)                	invoke	SETREAD
   342                                  	DOSAssume   CS,<ES>,"DoDate/SetRead"
   343 000001A1 1E                      	PUSH	DS
   344 000001A2 C536[0000]              	LDS	SI,[BCLOCK]
   345                                  ASSUME	DS:NOTHING
   346 000001A6 E8(0000)                	invoke	DEVIOCALL2		;Get correct date and time
   347 000001A9 1F                      	POP	DS
   348                                  	DOSAssume   CS,<DS>,"DoDate/DevIOCall2"
   349 000001AA 5B                      	POP	BX
   350 000001AB E8(0000)                	invoke	SETWRITE
   351 000001AE 8F06[0000]              	POP	WORD PTR [TIMEBUF]
   352 000001B2 1E                      	PUSH	DS
   353 000001B3 C536[0000]              	LDS	SI,[BCLOCK]
   354                                  ASSUME	DS:NOTHING
   355 000001B7 E8(0000)                	invoke	DEVIOCALL2		;Set the date
   356 000001BA 1F                      	POP	DS
   357                                  	DOSAssume   CS,<DS>,"DoDate/DevIOCall2(second)"
   358 000001BB 5B                      	POP	BX
   359 000001BC 5E                      	POP	SI
   360                                  WKDAY:
   361 000001BD A1[0000]                	MOV	AX,[DAYCNT_DOS]
   362 000001C0 31D2                    	XOR	DX,DX
   363 000001C2 B90700                  	MOV	CX,7
   364 000001C5 40                      	INC	AX
   365 000001C6 40                      	INC	AX			;First day was Tuesday
   366 000001C7 F7F1                    	DIV	CX			;Compute day of week
   367 000001C9 8816[0000]              	MOV	[WEEKDAY],DL
   368 000001CD 30C0                    	XOR	AL,AL			;Flag OK
   369 000001CF C3                      Ret25:	return
   370                                  EndProc DODATE
   371                                  
   372                                  	procedure   DSUM,NEAR
   372          ******************       warning: proc DSUM... [-w+user]
   373 000001D0 B400                    	MOV	AH,0
   374                                  RET25 equ Ret25	; NASM port label
   375 000001D2 E3FB                    	JCXZ	RET25
   376                                  DSUM1:
   377 000001D4 AC                      	LODSB
   378 000001D5 01C2                    	ADD	DX,AX
   379 000001D7 E2FB                    	LOOP	DSUM1
   380 000001D9 C3                      	return
   381                                  EndProc DSUM
   382                                  
   383                                      END
   384                                  
   385                                  
