NEW PREFIX AUTO 4,1 *-------------------------------------- * https://www.cise.ufl.edu/~cop4600/cgi-bin/lxr/http/source.cgi/lib/ansi/gmtime.c *-------------------------------------- SECSDAY .EQ 86400 60*60*24 CENTURY0 .EQ 19 YEAR0 .EQ 70 DAY0 .EQ 4 day 0 was a thursday *-------------------------------------- .DUMMY .OR ZPTMP TIME.DWORD .BS 4 TIME.DivDay .BS 2 TIME.ModDay .BS 3 TIME.Div60 .BS 2 TIME.Mod .BS 1 TIME.Div3600 .BS 1 TIME.Century .BS 1 TIME.Year .BS 1 .ED */-------------------------------------- * # Time * Get System Time in Buffer * ## C * `time_t time (S.TIME* timer);` * ## ASM * `>LDYA timer` * `>SYSCALL time` * ## RETURN VALUE * S.TIME filled with System date/time *\-------------------------------------- K.Time >STYA ZPPtr2 >MLICALL MLIGETTIME >LDYAI DATELO >STYA ZPPtr1 bra TIME.PTime2TimeP1P2 */-------------------------------------- * # PTime2Time * Convert ProDOS Time To S.TIME * ## C * `int PTime2Time (long* ptime, S.TIME* timer);` * ## ASM * `>PUSHW timer` * `>LDYA ptime` * `>SYSCALL PTime2Time` * ## RETURN VALUE *\-------------------------------------- K.PTime2Time jsr MEM.SPtr1PPtr2 TIME.PTime2TimeP1P2 ldy #1 lda (ZPPtr1),y Get Year lsr C is high bit of month ldy #S.Time.YEAR sta (ZPPtr2),y set year sta TIME.Year for conputing Century/WDAY later lda (ZPPtr1) Get Month/day pha save Day ror lsr lsr lsr lsr ldy #S.Time.MONTH sta (ZPPtr2),y set month pla get back day and #$1F iny sta (ZPPtr2),y set day lda TIME.Year get back year cmp #69 if before 70 CC,if > 70, CS lda #0 rol get back C in bit 0 eor #1 toggle C adc #19 set date before 1970 -> 20xx sta (ZPPtr2) set Century sta TIME.Century for conputing WDAY later ldy #2 lda (ZPPtr1),y Get Min tax iny lda (ZPPtr1),y Get Hour ldy #S.Time.HOUR sta (ZPPtr2),y set hour iny txa sta (ZPPtr2),y set min iny lda #0 sta (ZPPtr2),y set seconds (ProDOS does not provide it) * 1/1/1970 was Thursday...if not leap, add one, if leap add 2 K.ComputeWDAY lda #3 Thursday : 4 (-1 for mod 7) pha lda #19 sta TIME.DWORD lda #70 sta TIME.DWORD+1 .1 ldy TIME.DWORD lda TIME.DWORD+1 cpy TIME.Century bne .2 cmp TIME.Year beq .4 .2 jsr TIME.IsLeapYearYA CS = Leap pla adc #1 cmp #7 bcc .3 sbc #7 MOD 7 .3 pha inc TIME.DWORD+1 lda TIME.DWORD+1 cmp #100 bne .1 lda #0 sta TIME.DWORD+1 inc TIME.DWORD bra .1 .4 ldy #S.Time.MONTH lda (ZPPtr2),y get month tax .5 lda K.StrFTime.MDAY-1,x get day count in this month bne .6 february ? ldy TIME.Century lda TIME.Year jsr TIME.IsLeapYearYA CS = Leap .6 pla adc K.StrFTime.MDAY-1,x cmp #7 bcc .7 sbc #7 .7 pha dex bne .5 pla ldy #S.Time.DAY adc (ZPPtr2),y get day in month (1..31) dec adjust range 0.30 for MOD 7 .8 cmp #7 MOD 7 bcc .80 sbc #7 bra .8 .80 inc adjust range 1..7 ldy #S.Time.WDAY sta (ZPPtr2),y clc rts */-------------------------------------- * # CTime2Time * Convert CTime Time To S.TIME * ## C * `int CTime2Time (long* ctime, S.TIME* timer);` * ## ASM * `>PUSHW timer` * `>LDYA ctime` * `>SYSCALL CTime2Time` * ## RETURN VALUE *\-------------------------------------- K.CTime2Time jsr MEM.SPtr1PPtr2 ldy #3 .1 lda (ZPPtr1),y sta TIME.DWORD,y dey bpl .1 stz TIME.DivDay stz TIME.DivDay+1 .2 lda TIME.DWORD sta TIME.ModDay sec sbc #SECSDAY pha lda TIME.DWORD+1 sta TIME.ModDay+1 sbc /SECSDAY pha lda TIME.DWORD+2 sta TIME.ModDay+2 sbc ^SECSDAY pha lda TIME.DWORD+3 sbc #0 bcc .3 end of DIV/MOD ? sta TIME.DWORD+3 ldx #2 .21 pla sta TIME.DWORD,x dex bpl .21 inc TIME.DivDay bne .2 inc TIME.DivDay+1 bne .2 .3 pla pla pla stz TIME.Div60 stz TIME.Div60+1 .4 lda TIME.ModDay sta TIME.Mod sec sbc #60 pha lda TIME.ModDay+1 sbc #0 pha lda TIME.ModDay+2 sbc #0 bcc .5 sta TIME.ModDay+2 pla sta TIME.ModDay+1 pla sta TIME.ModDay inc TIME.Div60 bne .4 inc TIME.Div60+1 bne .4 .5 pla pla lda TIME.Mod ldy #S.Time.SECOND sta (ZPPtr2),y stz TIME.Div3600 .6 lda TIME.Div60 sta TIME.Mod sec sbc #60 pha lda TIME.Div60+1 sbc #0 pha bcc .7 sta TIME.Div60+1 pla sta TIME.Div60 inc TIME.Div3600 bne .6 .7 pla lda TIME.Mod dey ldy #S.Time.MINUTE sta (ZPPtr2),y lda TIME.Div3600 dey ldy #S.Time.HOUR sta (ZPPtr2),y lda TIME.DivDay WDAY computation : (DivDay + DAY0) mod 7 clc adc #DAY0 pha lda TIME.DivDay+1 adc /DAY0 eor #$ff tax pla .8 sta TIME.Mod sec sbc #7 bcs .8 inx bne .8 lda TIME.Mod ldy #S.Time.WDAY sta (ZPPtr2),y lda #CENTURY0 sta TIME.Century lda #YEAR0 sta TIME.Year K.CTime2Time.Year .1 ldy TIME.Century lda TIME.Year jsr TIME.IsLeapYearYA if Leap year CS lda #0 Toggle Carry rol eor #1 lsr lda TIME.DivDay sbc #365 pha lda TIME.DivDay+1 sbc /365 bcc .2 sta TIME.DivDay+1 pla sta TIME.DivDay inc TIME.Year lda TIME.Year cmp #100 bne .1 stz TIME.Year inc TIME.Century bne .1 .2 pla lda TIME.Century * ldy #S.Time.CENTURY sta (ZPPtr2) ldy #S.Time.YEAR lda TIME.Year sta (ZPPtr2),y clc rts *-------------------------------------- * In : * Y = Century * A = Year (0..99) * if (year mod 400 = 0) * or * if not (year mod 100 = 0) and (year mod 4 = 0) * Out : * CS = Leap * CC = Not Leap *-------------------------------------- TIME.IsLeapYearYA cmp #0 Year = 00 ? bne .1 no tya year = 00, get century in a and #$3 mod 4 = 0 ? beq .9 leap year .8 clc not leap rts .1 and #$3 mod 4 = 0 ? bne .8 .9 sec Leap rts *-------------------------------------- K.StrFTime.MDAY .DA #3,#0,#3,#2,#3,#2,#3,#3,#2,#3,#2,#3 */-------------------------------------- * # StrFTime * ## C * Convert S.TIME struct to CSTR * `void strftime (char* ptr, const char* format, const struct S.TIME* timeptr );` * ## ASM * `PUSHW timeptr` * `PUSHW format` * + %a : Abbreviated weekday name : Thu * + %A : Full weekday name : Thursday * + %b : Abbreviated month name : Aug * + %B : Full month name : August * + %d : Day of the month, zero-padded (01-31) * + %H : Hour in 24h format (00-23) 14 * + %I : Hour in 12h format (01-12) 02 * + %m : Month as a decimal number (01-12) 08 * + %M : Minute (00-59) 55 * + %p : AM or PM designation PM * + %S : Second (00-61) 02 * + %w : Weekday as a decimal number with Sunday as 0 (0-6) * + %y : Year, last two digits (00-99) * + %Y : Year four digits 2001 * `>LDYA ptr` * `>SYSCALL strftime` * ## RETURN VALUE * none. always succeed. *\-------------------------------------- K.StrFTime jsr MEM.SPtr1PPtr2 >PULLW ZPPtr3 timeptr .1 lda (ZPPtr2) beq .8 jsr MEM.NextCharPtr2 cmp #'%' beq .2 jsr K.StrFTime.addChar bra .1 .2 ldx #K.StrFTime.JMP-K.StrFTime.Tbl-1 lda (ZPPtr2) beq .8 jsr MEM.NextCharPtr2 .3 cmp K.StrFTime.Tbl,x beq .4 dex bpl .3 bra .1 .4 txa asl tax jsr .5 bra .1 .5 jmp (K.StrFTime.JMP,x) .8 lda #0 Terminate C string sta (ZPPtr1) rts *-------------------------------------- K.StrFTime.TBL .AS "aAbBdHImMpSwyY" K.StrFTime.JMP .DA K.StrFTime.A .DA K.StrFTime.AA .DA K.StrFTime.B .DA K.StrFTime.BB .DA K.StrFTime.D .DA K.StrFTime.HH .DA K.StrFTime.II .DA K.StrFTime.M .DA K.StrFTime.MM .DA K.StrFTime.P .DA K.StrFTime.SS .DA K.StrFTime.W .DA K.StrFTime.Y .DA K.StrFTime.YY *-------------------------------------- K.StrFTime.A ldx #3 Short day of week, 3 chars... .HS 2C Bit abs K.StrFTime.AA ldx #15 full DoW >LDYAI K.StrFTime.DAY >STYA ZPPtr4 ldy #S.Time.WDAY bra K.StrFTime.STR K.StrFTime.B ldx #3 Short Month, 3 chars.... .HS 2C Bit abs K.StrFTime.BB ldx #15 full Month.... >LDYAI K.StrFTime.MON >STYA ZPPtr4 ldy #S.Time.MONTH K.StrFTime.STR lda (ZPPtr3),y get required S.Time field value tay beq .9 Illegal value .1 dey range 0..x beq .2 lda (ZPPtr4) sec adc ZPPtr4 sta ZPPtr4 bcc .1 inc ZPPtr4+1 bra .1 .2 * ldy #0 Y is already 0 .3 iny lda (ZPPtr4),y jsr K.StrFTime.addChar tya cmp (ZPPtr4) beq .8 dex bne .3 .8 rts .9 ldx #3 lda #'?' .99 jsr K.StrFTime.addChar dex bne .99 rts *-------------------------------------- K.StrFTime.II ldy #S.Time.HOUR lda (ZPPtr3),y cmp #12 bcc .1 sbc #12 .1 bra K.StrFTime.addDecA K.StrFTime.P ldy #S.Time.HOUR lda (ZPPtr3),y cmp #12 bcc .1 lda #'p' .HS 2C bit abs .1 lda #'a' jsr K.StrFTime.addChar lda #'m' bra K.StrFTime.addChar K.StrFTime.YY ldy #S.Time.CENTURY jsr K.StrFTime.addDecPtr1Y K.StrFTime.Y ldy #S.Time.YEAR .HS 2C bit abs K.StrFTime.D ldy #S.Time.DAY .HS 2C bit abs K.StrFTime.HH ldy #S.Time.HOUR .HS 2C bit abs K.StrFTime.SS ldy #S.Time.SECOND .HS 2C bit abs K.StrFTime.W ldy #S.Time.WDAY .HS 2C bit abs K.StrFTime.M ldy #S.Time.MONTH .HS 2C bit abs K.StrFTime.MM ldy #S.Time.MINUTE *-------------------------------------- K.StrFTime.addDecPtr1Y lda (ZPPtr3),y K.StrFTime.addDecA stz .2+1 ldx #8 sed .1 asl pha .2 lda #$ff Self Modified adc .2+1 sta .2+1 pla dex bne .1 cld lda .2+1 pha lsr lsr lsr lsr ora #$30 jsr K.StrFTime.addChar pla and #$0f ora #$30 *-------------------------------------- K.StrFTime.addChar sta (ZPPtr1) jmp MEM.NextCharPtr1 *-------------------------------------- K.StrFTime.DAY >PSTR "Monday" >PSTR "Tuesday" >PSTR "Wednesday" >PSTR "Thursday" >PSTR "Friday" >PSTR "Saturday" >PSTR "Sunday" *-------------------------------------- K.StrFTime.MON >PSTR "January" >PSTR "February" >PSTR "March" >PSTR "April" >PSTR "May" >PSTR "June" >PSTR "July" >PSTR "August" >PSTR "September" >PSTR "October" >PSTR "November" >PSTR "December" *-------------------------------------- MAN SAVE USR/SRC/SYS/KERNEL.S.TIME LOAD USR/SRC/SYS/KERNEL.S ASM