NEW
  AUTO 3,1
*--------------------------------------
* https://www.cise.ufl.edu/~cop4600/cgi-bin/lxr/http/source.cgi/lib/ansi/gmtime.c
*--------------------------------------
SECSDAY			.EQ 86400				60*60*24
CENT0			.EQ 19
YEAR0			.EQ 70
DAY0			.EQ 4					day 0 was a thursday
*--------------------------------------
* ZPPtr3 *S.TIME
* FORPNT str
* TXTPTR format
*--------------------------------------
TIMEX.StrFTime
.1				jsr SHARED.TXTPTR.GetNext
				beq .8

				cmp #'%'
				beq .2

				jsr SHARED.FORPNT.PutNext
				bra .1
				
.2				ldx #K.StrFTime.Cnt-1
				jsr SHARED.TXTPTR.GetNext
				beq .8

.3				cmp K.StrFTime.Tbl,x
				beq .4
				dex
				bpl .3

				bra .1
				
.4				cpx #7
				bcc .5
				jsr K.StrFTime.AtX
				bra .1

.5				txa
				asl
				tax
				jsr .7
				bra .1

.7				jmp (K.StrFTime.JMP,x)			

.8				lda #0					Terminate C string
				jsr SHARED.FORPNT.PutNext
				clc
				rts
*--------------------------------------
K.StrFTime.Tbl	.AS "aAbBIpYydHSwmM"
K.StrFTime.Cnt	.EQ *-K.StrFTime.TBL
K.StrFTime.OfsX	.DA #S.Time.YEAR,#S.Time.DAY,#S.Time.HOUR,#S.Time.SECOND,#S.Time.WDAY,#S.Time.MONTH,#S.Time.MINUTE
K.StrFTime.JMP	.DA K.StrFTime.A
				.DA K.StrFTime.AA
				.DA K.StrFTime.B
				.DA K.StrFTime.BB
				.DA K.StrFTime.II
				.DA K.StrFTime.P
				.DA K.StrFTime.YY
*--------------------------------------
K.StrFTime.A	sec						Short day of week, 3 chars...
				.HS	90					BCC
				 
K.StrFTime.AA	clc						full DoW
				lda #TIMEX.DAY
				ldx /TIMEX.DAY	
				ldy #S.Time.WDAY
				bra K.StrFTime.STR
K.StrFTime.B	sec						Short Month, 3 chars....
				.HS	90					BCC
K.StrFTime.BB	clc						full Month....
				lda #TIMEX.MON
				ldx /TIMEX.MON
				ldy #S.Time.MONTH
K.StrFTime.STR	sta ZPPtr4
				stx ZPPtr4+1

				ldx #15
				bcc .10
				ldx #3
				
.10				jsr SHARED.ZPPtr3.GetY	get required S.Time field value

				tay
				beq .2					Illegal value, print ???
.1				lda (ZPPtr4)
				sec
				adc ZPPtr4
				sta ZPPtr4
				bcc .11
				inc ZPPtr4+1
.11				dey
				bne .1
.2
*				ldy #0					Y is already 0

.3				iny
				lda (ZPPtr4),y
				jsr SHARED.FORPNT.PutNext
				tya
				cmp (ZPPtr4)
				beq .8
				dex
				bne .3

.8				rts
*--------------------------------------
K.StrFTime.II	ldy #S.Time.HOUR
				jsr SHARED.ZPPtr3.GetY
				cmp #12
				bcc K.StrFTime.addDecA
				sbc #12
				bra K.StrFTime.addDecA
				
K.StrFTime.P	ldy #S.Time.HOUR
				jsr SHARED.ZPPtr3.GetY
				cmp #12
				bcc .1
				lda #'p'
				.HS 2C					bit abs
.1				lda #'a'
				jsr SHARED.FORPNT.PutNext
				lda #'m'
				jmp SHARED.FORPNT.PutNext
t
K.StrFTime.YY	ldy #S.Time.CENTURY
				jsr K.StrFTime.addDecPtr3Y
				ldx #7					"y"
K.StrFTime.AtX	ldy K.StrFTime.OfsX-7,x
*--------------------------------------
K.StrFTime.addDecPtr3Y
				jsr SHARED.ZPPtr3.GetY
K.StrFTime.addDecA
				ldx #2
				ldy #'0'
				clc
				jsr MATH.A2STR10
				lda A2osX.NumStrBuf
				jsr SHARED.FORPNT.PutNext
				lda A2osX.NumStrBuf+1
				jmp SHARED.FORPNT.PutNext
*--------------------------------------
TIMEX.DAY		>PSTR "???"
				>PSTR "Monday"
				>PSTR "Tuesday"
				>PSTR "Wednesday"
				>PSTR "Thursday"
				>PSTR "Friday"
				>PSTR "Saturday"
				>PSTR "Sunday"
*--------------------------------------
TIMEX.MON		>PSTR "???"
				>PSTR "January"
				>PSTR "February"
				>PSTR "March"
				>PSTR "April"
				>PSTR "May"
				>PSTR "June"
				>PSTR "July"
				>PSTR "August"
				>PSTR "September"
				>PSTR "October"
				>PSTR "November"
				>PSTR "December"
*--------------------------------------
TIMEX.PTime2Time
				ldy #1
				jsr SHARED.TXTPTR.GetY	Get Year
				lsr						C is high bit of month
				ldy #S.Time.YEAR
				jsr SHARED.FORPNT.PutY	set year
				sta ARG32+3				for computing Century/WDAY later

				ldy #0
				jsr SHARED.TXTPTR.GetY	Get Month/day

				pha						save Day
				ror
				lsr
				lsr
				lsr
				lsr
				ldy #S.Time.MONTH
				jsr SHARED.FORPNT.PutY	set month
				sta K.ComputeWDAY.1+1
				
				pla						get back day
				and #$1F
				iny
				jsr SHARED.FORPNT.PutY	set day

				dec						adjust range 0.30 for MOD 7
				sta ARG32.Sign			For later...

				lda ARG32+3				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
				ldy #0
				jsr SHARED.FORPNT.PutY	set Century
				sta ARG32+2				for computing WDAY later

				ldy #2
				jsr SHARED.TXTPTR.GetY	Get Min
				tax
				iny
				jsr SHARED.TXTPTR.GetY	Get Hour
				ldy #S.Time.HOUR
				jsr SHARED.FORPNT.PutY	set hour
				iny
				txa
				jsr SHARED.FORPNT.PutY	set min
				iny
				lda #0
				jsr SHARED.FORPNT.PutY	set seconds (ProDOS does not provide it)
*--------------------------------------
* 1/1/1970 was Thursday...if not leap, add one, if leap add 2
*--------------------------------------		
K.ComputeWDAY	lda #DAY0-1				Thursday : 4 (-1 for mod 7)
				pha

				lda #CENT0
				sta ARG32
				lda #YEAR0
				sta ARG32+1

.1				ldy ARG32
				lda ARG32+1

				cpy ARG32+2
				bne .2
				cmp ARG32+3	
				beq K.ComputeWDAY.1

.2				jsr TIMEX.IsLeap		CS = Leap			

				pla
				adc #1					365 mod 7
				cmp #7
				bcc .3
				sbc #7					MOD 7

.3				pha
				inc ARG32+1
				lda ARG32+1
				cmp #100
				bne .1

				stz ARG32+1
				inc ARG32
				bra .1
*--------------------------------------
K.ComputeWDAY.1	ldx #$ff				SELF MODIFIED : month

				dex						don't include actual month
				beq .71

.5				clc						assume NO leap

				lda TIMEX.MDAY-1,x		get day count in this month
				bne	.6					february ?

				ldy ARG32+2
				lda ARG32+3	
				jsr TIMEX.IsLeap		CS = Leap			

.6				pla
				adc TIMEX.MDAY-1,x

				cmp #7
				bcc .7
				sbc #7
				
.7				pha
				dex
				bne .5
				
.71				pla
				clc

				adc ARG32.Sign			get day in month (0..30)

.8				cmp #7					MOD 7
				bcc .80
				sbc #7
				bra .8

.80				inc						adjust range 1..7
				ldy #S.Time.WDAY
				jsr SHARED.FORPNT.PutY
				clc
				rts
*--------------------------------------
TIMEX.MDAY		.DA #3,#0,#3,#2,#3,#2,#3,#3,#2,#3,#2,#3
*--------------------------------------
TIMEX.CTime2Time
				ldy #3

.1				lda (ZPPtr1),y
				sta ARG32,y				ARG = ctime
				dey
				bpl .1

				lda #SECSDAY			ACC = SECSDAY
				sta ACC32
				lda /SECSDAY
				sta ACC32+1
				lda ^SECSDAY
				sta ACC32+2
				stz ACC32+3
				jsr MATH.DIVMOD32		ARG32 = Days, TMP32 = remaining secs

				lda ARG32				WDAY computation : (ARG32 + DAY0) mod 7
				clc
				adc #DAY0
				pha
				lda ARG32+1				65535 days = 179 years
				adc /DAY0
				eor #$ff
				tax
				pla
.2				tay
				sec
				sbc #7
				bcs .2
				inx
				bne .2
				tya
				ldy #S.Time.WDAY
				sta (ZPPtr2),y
				ldy #CENT0
				sty ZPPtr3
				lda #YEAR0
				sta ZPPtr3+1
K.CTime2Time.Year
.1				ldy ZPPtr3
				lda ZPPtr3+1
				jsr TIMEX.IsLeap 		if Leap year CS
				rol						Toggle Carry
				eor #1
				lsr
				lda ARG32
				sbc #365
				pha
				lda ARG32+1
				sbc /365
				bcc .2
				sta ARG32+1
				pla
				sta ARG32
				inc ZPPtr3
				lda ZPPtr3
				cmp #100
				bne .1

				stz ZPPtr3
				inc ZPPtr3+1
				bne .1
.2				pla

				lda ZPPtr3+1
*				ldy #S.Time.CENTURY
				sta (ZPPtr2)

				ldy #S.Time.YEAR
				lda ZPPtr3
				sta (ZPPtr2),y
K.CTime2Time.HMS
				ldx #3
.1				lda TMP32,x
				sta ARG32,x
				dex
				bpl .1
				ldy #S.TIME.SECOND
				jsr .2
				dey						#S.TIME.MINUTE
				jsr .2
				dey						#S.TIME.HOUR
				lda ARG32
				sta (ZPPtr2),y

				clc
				rts
.2				phy

				lda #60
				jsr MATH.A2ACC32
				jsr MATH.DIVMOD32
				ply
				lda TMP32
				sta (ZPPtr2),y
				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
*--------------------------------------
TIMEX.IsLeap	cmp #0					Year = 00 ?
				bne .1					no

				tya						year = 00, get century in A
				
				and #$3					Century mod 4 = 0 ?
				beq .9					leap year (2000)
.8				clc						not leap (1900)
				rts

.1				and #$3					mod 4 = 0 ?
				bne .8

.9				sec						Leap
				rts
*--------------------------------------
MAN
SAVE USR/SRC/SYS/KERNEL.S.TIMEX
LOAD USR/SRC/SYS/KERNEL.S
ASM
