;********************************************************************** ; ; TIMEZD 1.2 ; ; Full featured utility for setting/viewing current system time ; using Z80DOS. ; ; Eugene Nolan ; 7/9/88 ; ; With translations of: ; ; DATEHL 1.0 by Carson Wilson ; BCD2JUL by Bridger Mitchell and Howard Goldstein ; ;******************************************************************** ; ASEG ; Needed for M80 and RMAC, ignore error ; ORG 0100H ; JMP START ; NO EQU 0 YES EQU NOT NO ; (Some assemblers don't like 0FFh) ; ; Define version number ; MAIN EQU 1 ; Main block number VER EQU 2 ; Current version MONTH EQU 07 ; Month DAY EQU 09 ; Day YEAR EQU 88 ; Year ; TBUF EQU 80h ; Command line location WHEEL EQU NO ; *Yes if using ZCPR wheel byte WHLOC EQU 3EH ; *Set to wheel location if WHEEL=Yes PRBRDR EQU NO ; Yes = print quasi-borders for libraries DB 'Z3ENV' ; For ZCPR3 Environment ID DB 1 ; Class 1, External DW 0 ; Environment Address. If using ZCPR33 ; This can be left as is. ZCPR3 EQU NO ; Allow named directory in command line VERNAME:DB 13,10,'TIMEZD ',MAIN+'0','.' DB VER+'0',' -- ' DB MONTH/10+'0',MONTH MOD 10+'0','/' DB DAY/10+'0',DAY MOD 10+'0','/' DB YEAR/10+'0',YEAR MOD 10+'0' DB 13,10,13,10 DB 'Syntax:',13,10 DB ' TIMEZD MM/DD/YY HH:MM:SS for set 24 hour time',13,10 DB ' TIMEZD MM/DD/YY HH:MM:SS [A][P] for set AM/PM time',13,10 DB ' TIMEZD MM/DD/YY Default to 00:00:00',13,10 DB ' TIMEZD Show current time',13,10 DB ' TIMEZD [?][/] This message',13,10,13,10 DB ' MM optional if HH, SS optional if HH:MM (=0 if not present)' DB 13,10,13,10,'$' ; ;----------------------------------------------------------------------- ; Program starts here ;----------------------------------------------------------------------- ; START: LXI H,0 DAD SP ; HL=old stack SHLD STACK ; Save it LXI SP,STACK ; Get new stack ; ; See if help is wanted ; LXI H,TBUF MOV A,M ; 1st Character ORA A ; Was anything entered JZ DISDAT ; Z=no,display current date CPI 1 JZ DISDAT INX H INX H MOV A,M CPI '?' ; Is it "?" JZ HELPME CPI '/' JZ HELPME LXI D,TBUF+1 LOKDAT: IF WHEEL LDA WHLOC ; If wheel option, only allow setting ORA A ; time if wheel on JNZ LOKDT1 PUSH D LXI D,WHLMES ; No wheel, say can't do CALL PUTS POP D JMP EXIT2 WHLMES: DB 13,10,'NO wheel',13,10,'$' LOKDT1: ENDIF ;WHEEL INX D call eval10 ; convert month to binary ORA A ; month can't be 0 JZ BADDATE CPI 13 ; can't be >12 JNC BADDATE STA MONTHS ; store month LDAX D ; End of input line? ORA A JZ BADDATE ; Z=yes, a no-no INX D ; Skip / call eval10 ; convert ORA A ; day can't be 0 JZ BADDATE CPI 32 ; or >31 JNC BADDATE STA DAYS1 ; store day LDAX D ; End of input line? ORA A JZ BADDATE ; Z=yes, a no-no INX D ; Skip / call eval10 STA YEARS1 ; store year LXI H,YEARS1 ; pt at date PUSH D call bin2jul ; get jul date in hl POP D SHLD JDAY ; Save Julian day away LDAX D ORA A JZ DTIME ; Z= End of input INX D CALL EVALBCD ; Get hours CPI 24H JNC CLERR STA HOURS LDAX D ORA A JZ DTIME ; Z= end of input CPI ' ' JZ LOKAMPM INX D CALL EVALBCD ; Get minutes CPI 60H JNC CLERR STA MINUTES LDAX D ORA A JZ DTIME ; Z= End of input CPI ' ' JZ LOKAMPM INX D CALL EVALBCD CPI 60H JNC CLERR STA SECONDS LDAX D ORA A JZ DTIME ; Z= end of input CPI ' ' JZ LOKAMPM ; Space entered, if so go look for Am/Pm DTIME: LXI D,JDAY MVI C,104 ; Set Z80DOS system time CALL 5 EXIT2: LHLD STACK SPHL RET LOKAMPM: INX D LDAX D CPI 'A' ; A(m)? JZ DTIME CPI 'a' JZ DTIME CPI 'P' ; P(m)? JZ PM CPI 'p' JNZ CLERR PM: LDA HOURS ; P(m) entered, up hours by 12 CPI 12H JZ DTIME ADI 12H DAA STA HOURS CPI 24H JNC CLERR ; Time >24:00 JMP DTIME HELPME: LXI D,VERNAME ; Put up Verison/help message MVI C,9 CALL 5 JMP EXIT2 ;..... ; ; Playback the command line up to the character that stopped the scan ; and exit ; CLERR: XRA A ; Clear "A" register INX D ; Tag end of CLB STAX D ; With terminator CALL CRLF ; New line LXI D,ERRMS2 ; 'Error' CALL PUTS LXI D,ERRTAG ; '->' CALL PUTS LXI H,TBUF+1 ; Playback CLB to error point CLELP: MOV A,M ; Character ORA A ; Zero? JZ CLEX ; Yes, exit CALL PUTCHR ; No, output to console INX H ; CLB pointer+1 JMP CLELP ; Continue CLEX: MVI A,'?' ; Tag line with a '?' field CALL PUTCHR CALL CRLF ; New Line JMP EXIT2 CRLF: MVI A,13 CALL PUTCHR MVI A,10 CALL PUTCHR RET PUTS: PUSH B ; Output string pointed to by DE till $ MVI C,9 PUSH D PUSH H CALL 5 POP H POP D POP B RET SPACE: MVI A,' ' PUTCHR: PUSH B PUSH D PUSH H MOV E,A MVI C,2 ; CONOUT BDOS call CALL 5 POP H POP D POP B RET EVAL10: XRA A MOV B,A ; B holds current number input EVAL1: LDAX D ; Get input CPI '/' ; / is seperator JZ DEVAL10 ; Z= done ORA A JZ DEVAL10 ; Z= at end of line CPI ' ' JZ DEVAL10 SUI '0' ; Verify ascii 0-9 JC BADDATE CPI 10 JNC BADDATE INX D MOV C,A ; Old*10+new MOV A,B ADD A ADD A ADD B ADD A ADD C MOV B,A ; B has current JMP EVAL1 DEVAL10: MOV A,B RET EVALBCD: XRA A MOV B,A ; B holds current number input EVLBC1: LDAX D ; Get input CPI '/' ; / is seperator JZ DEVBC10 ; Z= done CPI ':' JZ DEVBC10 ORA A JZ DEVBC10 ; Z= at end of line CPI ' ' JZ DEVBC10 SUI '0' ; Verify ascii 0-9 JC BADDATE CPI 10 JNC BADDATE INX D MOV C,A ; Old*10+new MOV A,B ADD A ADD A ADD A ADD A ADD C MOV B,A ; B has current JMP EVLBC1 DEVBC10: MOV A,B RET BADDATE: ; Bad input, put up Ver/help and command line PUSH D LXI D,VERNAME CALL PUTS POP D JMP CLERR ; ; Binary to Julian Date routine. ; ; >> hl -> yr,mo,da in bin ; << hl = Julian date ; ; bin2jul: PUSH PSW PUSH B PUSH D MOV A,M ; A=yr INX H MOV C,M ;c = mo INX H PUSH H ;save ptr to day PUSH PSW ;save year ; ; set hl= initial julian value of 77/12/31 ; LXI H,0 SUI 78 JZ B2JUL3 JNC B2JUL0 ADI 100 ;<78, assume next century b2jul0: MOV B,A ;b = # yrs > 78 MVI A,1 ;init modulo 4 counter LXI D,365 ;days/yr b2jul1: DAD D ;calc julian val. of (yr/01/01 - 1) INR A ANI 3 ;every 4 yrs, JNZ B2JUL2 INX H ;..add 1 for leap year b2jul2: DCR B JNZ B2JUL1 ; ; hl now = # days in years before current year ; b2jul3: POP PSW ANI 3 ;if current yr == leap year JNZ B2JUL5 MOV A,C CPI 3 ;..and mo >= march JC B2JUL5 INX H ;..add the extra day (Feb 29) ; b2jul5: MOV B,C ; b = month = # months +1 to sum LXI D,DPERMO ;point at table JMP B2JUL7 ; b2jul6: call addhl ;add # days in this month INX D ;bump tbl ptr b2jul7: DCR B JNZ B2JUL6 ; POP D ;ptr to day call addhl pop d pop b pop a ret addhl: LDAX D ;add day of current month ; adda2hl:ADD L MOV L,A RNC INR H ret ; ; table of days per month (non-leap year) ; dpermo: db 31 ;jan db 28 ;feb db 31 ;mar db 30 ;apr db 31 ;may db 30 ;jun db 31 ;jul db 31 ;aug db 30 ;sep db 31 ;oct db 30 ;nov db 31 ;dec DISDAT: CALL CRLF LXI D,JDAY MVI C,105 CALL 5 LXI H,JDAY MOV E,M ; Get JD in DE INX H ; MOV D,M ; XCHG ; to HL CALL DATEHL ; PUSH H ; Month and Year in L,H PUSH PSW ; Day in A CALL SPACE CALL SPACE POP PSW JNZ DAYOK ; NZ = was a day there POP H CALL NODATE JMP DNOTOK DAYOK: PUSH PSW LHLD JDAY LXI D,7 DAYCLC: ORA A ; Clear the carry PUSH H ; Put remainder in BC POP B DW 52EDH ; SBC HL,DE JNC DAYCLC ; NC=not less than MOV A,C ; C has remainder which is index to day array LXI H,DAYARY ; Put out ascii of current day CALL LOOKUP POP PSW POP H PUSH H PUSH PSW MOV A,L ; Month out ANI 0FH ; BCD coded, convert to binary MOV E,A MOV A,L CPI 10H JC MOOK MOV A,E ADI 10 MOV E,A MOOK: MOV A,E LXI H,MONARY ; Dsiplay ascii of month CALL LOOKUP XRA A STA SUPR ; Suppress leading 0's POP PSW CALL BCDOUT ; Put out Day LXI D,MESS0 ; ', 19' CALL PUTS POP H MVI A,1 STA SUPR ; Keep leading 0's MOV A,H ; Year out CALL BCDOUT CALL SPACE CALL SPACE XRA A STA SUPR ; No leading 0's LDA HOURS CPI 12H ; 12 o'clock? JZ HR12 ; Z=yes, say PM CPI 13H ; >1 PM? JC HROK ; C=NO SUI 12H DAA HR12: PUSH PSW MVI A,'P' ; Pm STA AMPM+1 POP PSW HROK: CALL BCDOUT ; Put it out MVI A,':' CALL PUTCHR MVI A,1 STA SUPR ; Keep leading 0's LDA MINUTES CALL BCDOUT MVI A,':' CALL PUTCHR LDA SECONDS CALL BCDOUT LXI D,AMPM ; Display AM or PM CALL PUTS DNOTOK: CALL CRLF JMP EXIT2 NODATE: ; System time not set LXI D,NODATM CALL PUTS RET NODATM: DB 'No Date Set',13,10,'$' LOOKUP: ; Display element A of array pointed by HL ORA A RAL MOV E,A MVI D,0 DAD D MOV E,M INX H MOV D,M CALL PUTS RET BCDOUT: PUSH B ; Save MOV B,A ; A holds BCD digits RAR RAR RAR RAR ANI 0FH MOV C,A ORA A JNZ BCDOT0 ; Digit 0? LDA SUPR ; Suppress leading 0's? ORA A JZ BCDOT1 ; Z=yes BCDOT0: MOV A,C CALL BCDOT2 ; Output high order BCDOT1: MOV A,B CALL BCDOT2 ; And low order POP B RET BCDOT2: ANI 0FH ADI '0' CALL PUTCHR RET ; ; DATEHL converts the value in HL to BCD year, month, day ; for use with Z80DOS time stamps. ; ; Inputs: HL contains hex days since December 31, 1977 ; ; Outputs: H contains BCD 20th century year ; L contains BCD month ; A contains BCD day ; ; Zero flag set (Z) and A=0 if invalid date (zero) detected, ; Zero flag reset (NZ) and A=0ffh otherwise. ; Converted to 8080 from DATEHL by Carson Wilson who Adapted from B5C-CPM3.INS DateHL: MOV A,H ORA L ; Test blank date (zero) RZ ; Return Z and A=0 if so SHLD DAYS ; Save initial value MVI B,78 ; Set years counter loop: call ckleap LXI D,-365 ; Set up for subtract JNZ NOLPY ; Skip if no leap year DCX D ; Set for leap year nolpy: DAD D ; Subtract JNC YDONE ; Continue if years done MOV A,H ORA L JZ YDONE SHLD DAYS ; Else save days count INR B ; Increment years count JMP LOOP ; And do again ; ; The years are now finished, the years count is in 'B' (HL is invalid) ; ydone: MOV A,B call binbcd STA YEARS ; save BCD year ; call ckleap ; Check if leap year MVI A,-28 JNZ FEBNO ; February not 29 days MVI A,-29 ; Leap year febno: STA FEB ; Set february LHLD DAYS ; Get days count LXI D,MTABLE ; Point to months table MVI B,0FFH ; Set up 'B' for subtract MVI A,0 ; Set a for # of months mloop: PUSH PSW LDAX D ; Get month MOV C,A ; Put in 'C' for subtract POP PSW SHLD DAYS ; save days count DAD B ; Subtract INX D ; Increment months counter INR A JC MLOOP ; Loop for next month ; ; The months are finished, days count is on stack. First, calculate ; month. ; mdone: MOV B,A ; Save months LHLD DAYS MOV A,H ORA L JNZ NZD DCX D DCX D LDAX D CMA INR A MOV L,A DCR B nzd: MOV A,L ; Retrieve binary day of month call binbcd ; Convert to BCD PUSH PSW ; Save day in A ; MOV A,B ; Retrieve the binary month call binbcd ; Convert binary month to BCD MOV L,A ; Return month in L ; LDA YEARS MOV H,A ; Return year in H ; POP PSW ; Restore day ORA A ; Set NZ flag ret ; ; Support Routines: ; ; ; Check for leap years. ; ckleap: MOV A,B ANI 0FCH CMP B ret ; ; Convert A to BCD & store back in A ; BinBCD: ORA A RZ PUSH B MOV B,A XRA A BinBCD1: ADI 1 daa DCR B JNZ BINBCD1 POP B ret ; ; Buffers: ; ; ; Months table ; mtable: db -31 ;January feb: db -28 ;February db -31,-30,-31,-30 ;Mar-Jun db -31,-31,-30 ;Jul-Sep db -31,-30,-31 ;Oct-Dec DAYARY: DW SAT,SUN,MON,TUE,WED,THU,FRI SAT: DB 'Saturday $' SUN: DB 'Sunday $' MON: DB 'Monday $' TUE: DB 'Tuesday $' WED: DB 'Wednesday $' THU: DB 'Thursday $' FRI: DB 'Friday $' MONARY: DW 0,JAN,FEBU,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCTO,NOV,DECE JAN: DB 'January $' FEBU: DB 'Febuary $' MAR: DB 'March $' APR: DB 'April $' MAY: DB 'MAY $' JUN: DB 'June $' JUL: DB 'July $' AUG: DB 'August $' SEP: DB 'September $' OCTO: DB 'October $' NOV: DB 'November $' DECE: DB 'December $' AMPM: DB ' AM','$' SUPR: DB 0 ; ; Messages and Error statements ; ERRMS1: DB ' $' ERRMS2: DB 'Error$' ERRTAG: DB ' ->$' MESS0: DB ', 19$' JDAY: DS 2 HOURS: DB 0 MINUTES: DB 0 SECONDS: DB 0 DAYS: ds 2 YEARS: ds 1 YEARS1: DS 1 MONTHS: DS 1 DAYS1: DS 1 DS 40 STACK EQU $ END