ORCALib/time.asm

1197 lines
33 KiB
NASM

keep obj/time
mcopy time.macros
case on
****************************************************************
*
* Time - Time and date libraries for C
*
* This code implements the tables and subroutines needed to
* support the standard C library TIME.
*
* January 1989
* Mike Westerfield
*
* Copyright 1989
* Byte Works, Inc.
*
* Note: Portions of this library appear in SysFloat
*
****************************************************************
*
Time start dummy segment
end
****************************************************************
*
* TimeCommon - common variables for the time library
*
****************************************************************
*
TimeCommon privdata
;
; For conversion to/from seconds since 1970
;
year ds 4 year 0..99
month ds 4 month 1..12
day ds 4 day 1..31
hour ds 4 hour 0..23
minute ds 4 minute 0..59
second ds 4 second 0..59
count ds 4 seconds since 1 Jan 1970
t1 ds 4 work variable
t2 ds 4 work variable
lasttime ds 4 last time_t value returned by time()
lastDST dc i2'-1' tm_isdst value for lasttime
end
****************************************************************
*
* clock_t __clocks_per_sec()
*
* Outputs:
* X-A - the number of clock ticks per second (50 or 60)
*
****************************************************************
*
__clocks_per_sec start
LANGSEL equ $E1C02B LANGSEL soft switch
short I,M
ldy #60
ldx #0
lda >LANGSEL
and #$10 test NTSC/PAL bit of LANGSEL
beq lb1
ldy #50
lb1 long I,M
tya
rtl
end
****************************************************************
*
* char *asctime(struct tm *ts)
*
* Inputs:
* ts - time record to create string for
*
* Outputs:
* returns a pointer to the time string
*
****************************************************************
*
asctime start
csubroutine (4:ts),0
phb
phk
plb
brl ~ctime2
end
****************************************************************
*
* clock_t clock()
*
* Outputs:
* X-A - tick count
*
****************************************************************
*
clock start
pha
pha
_GetTick
pla
plx
rtl
end
****************************************************************
*
* char *ctime(timeptr)
* time_t *timptr;
*
* Inputs:
* timeptr - time to create string for
*
* Outputs:
* returns a pointer to the time string
*
****************************************************************
*
ctime start
tm_sec equ 0 displacements into the time record
tm_min equ 2
tm_hour equ 4
tm_mday equ 6
tm_mon equ 8
tm_year equ 10
tm_wday equ 12
csubroutine (4:timeptr),0
phb
phk
plb
ph4 <timeptr convert to a time record
jsl localtime
sta timeptr
stx timeptr+2
~ctime2 entry
ldy #tm_wday convert the week day to a string
lda [timeptr],Y
asl a
asl a
tax
lda weekDay,X
sta str
lda weekDay+1,X
sta str+1
ldy #tm_mon convert the month to a string
lda [timeptr],Y
asl a
asl a
tax
lda monthStr,X
sta str+4
lda monthStr+1,X
sta str+5
ldy #tm_mday convert the day to a string
lda [timeptr],Y
jsr mkstr
bit #$00CF check for leading '0'
bne lb1
and #$FFEF convert leading '0' to ' '
lb1 sta str+8
ldy #tm_hour convert the hour to a string
lda [timeptr],Y
jsr mkstr
sta str+11
ldy #tm_min convert minutes to a string
lda [timeptr],Y
jsr mkstr
sta str+14
ldy #tm_sec convert seconds to a string
lda [timeptr],Y
jsr mkstr
sta str+17
ldy #tm_year convert the year to a string
lda [timeptr],Y
ldy #19
sec
yr1 iny
sbc #100
bpl yr1
clc
yr2 dey
adc #100
bmi yr2
jsr mkstr
sta str+22
tya
jsr mkstr
sta str+20
lla timeptr,str
plb
creturn 4:timeptr
weekDay dc c'Sun Mon Tue Wed Thu Fri Sat'
monthStr dc c'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'
str dc c'Sun Jan 00 00:00:00 1900',i1'10,0'
;
; mkstr - convert a number to a string
;
mkstr ldx #-1
mk1 inx
sec
sbc #10
bcs mk1
clc
adc #10
xba
pha
txa
ora 1,S
ora #$3030
plx
rts
end
****************************************************************
*
* factor - compute the seconds since 1 Jan 1970 from date
*
* Inputs:
* year,month,day,hour,minute,second - time to convert
*
* Outputs:
* count - seconds since 1 Jan 1970
*
****************************************************************
*
factor private
using TimeCommon
;
; compute the # of days since 1 Jan 1970
;
mul4 year,#365,count count := 365*year + day + 31*(month-1)
add4 count,day
mul4 month,#31,t1
add4 count,t1
sub4 count,#31
move4 year,t2 t2 := year
lda month if January or February then
cmp #3
bge lb1
dec t2 year := year-1
bra lb2 else
lb1 mul4 month,#4,t1 count := count - (month*4+23) div 10
add4 t1,#23
div4 t1,#10
sub4 count,t1
lb2 lda t2 count := count + year div 4
lsr A
lsr A
clc
adc count
sta count
bcc lb3
inc count+2
lb3 add4 t2,#300 count := count -
div4 t2,#100 ((300+year) div 100+1)*3 div 4
inc4 t2
mul4 t2,#3
div4 t2,#4
sub4 count,t2
sub4 count,#25516 subtract off days between 1 Jan 00 and
! 1 Jan 70
;
; Convert to seconds and add in time of day in seconds
;
mul4 count,#24*60*60 convert to seconds
mul4 hour,#3600,t1 add in hours*3600
add4 count,t1
mul4 minute,#60,t1 add in minutes*60
add4 count,t1
add4 count,second add in seconds
rts
end
****************************************************************
*
* struct tm *localtime(t)
* time_t *t;
*
* Inputs:
* t - # seconds since 1 Jan 1970
*
* Outputs:
* returns a pointer to a time record
*
****************************************************************
*
localtime start
gmtime entry
using TimeCommon
csubroutine (4:t),0
phb
phk
plb
ldy #2 dereference the pointer
lda [t],Y
tax
lda [t]
sta t
stx t+2
ldy #-1 default DST setting = -1 (unknown)
cmp lasttime determine DST setting, if we can
bne lb0
cpx lasttime+2
bne lb0
ldy lastDST
lb0 sty tm_isdst
lda #69 find the year
sta year
lda #1
sta month
sta day
stz hour
stz minute
stz second
lb1 inc year
jsr factor
lda count+2
cmp t+2
bne lb1a
lda count
cmp t
lb1a ble lb1
dec year
lb2 inc month find the month
jsr factor
lda count+2
cmp t+2
bne lb2a
lda count
cmp t
lb2a ble lb2
dec month
jsr factor recompute the factor
lda year set the year
sta tm_year
lda month set the month
dec A
sta tm_mon
sub4 t,count find the number of seconds
move4 t,t1
div4 t,#60
mul4 t,#60,t2
sub4 t1,t2
lda t1
sta tm_sec
move4 t,t1 find the number of minutes
div4 t,#60
mul4 t,#60,t2
sub4 t1,t2
lda t1
sta tm_min
move4 t,t1 find the number of hours
div4 t,#24
mul4 t,#24,t2
sub4 t1,t2
lda t1
sta tm_hour
lda t set the day
inc A
sta tm_mday
ph4 #tm_sec set the day of week/year
jsl mktime
lla t,tm_sec
plb
creturn 4:t
tm_sec ds 2 seconds 0..59
tm_min ds 2 minutes 0..59
tm_hour ds 2 hours 0..23
tm_mday ds 2 day 1..31
tm_mon ds 2 month 0..11
tm_year ds 2 year 70..200 (1900=0)
tm_wday ds 2 day of week 0..6 (Sun = 0)
tm_yday ds 2 day of year 0..365
tm_isdst ds 2 daylight savings? 1 = yes, 0 = no
end
****************************************************************
*
* time_t mktime(tmptr)
* struct tm *tmptr
*
* Inputs:
* tmptr - pointer to a time record
*
* Outputs:
* tmptr->wday - day of week
* tmptr->yday - day of year
* returns the ime in seconds since 1 Jan 1970
*
****************************************************************
*
mktime start
using TimeCommon
temp equ 1 temp variable
temp2 equ 5 temp variable
csubroutine (4:tmptr),8
phb
phk
plb
lla temp,-1 assume we can't do it
ldy #10 error if year < 70
lda [tmptr],Y
sta year
cmp #70
jlt lb1
dey set the other time parameters
dey
lda [tmptr],Y
inc A
sta month
dey
dey
lda [tmptr],Y
sta day
dey
dey
lda [tmptr],Y
sta hour
dey
dey
lda [tmptr],Y
sta minute
lda [tmptr]
sta second
jsr factor compute seconds since 1970
move4 count,temp save the value for later return
lda #1 compute the days since the start of the
sta month year
sta day
jsr factor
sub4 temp,count,count
div4 count,#60*60*24
ldy #14 set the days
lda count
sta [tmptr],Y
div4 temp,#60*60*24,temp2 compute the day of week
add4 temp2,#4
mod4 temp2,#7
lda temp2 set the day of week
ldy #12
sta [tmptr],Y
lb1 plb
creturn 4:temp
end
****************************************************************
*
* time_t time(tptr)
* time_t *tptr;
*
* Outputs:
* tptr - if non-null, the value it points to is set
* time - returns the value
*
****************************************************************
*
time start
using TimeCommon
csubroutine (4:tptr),0
phb
phk
plb
;
; get the current time
;
pha get the current time
pha
pha
pha
_ReadTimeHex
lda 5,S set the day
and #$00FF
inc A
sta day
lda 5,S set the month
and #$FF00
xba
inc A
sta month
lda 3,S set the year
and #$FF00
xba
sta year
lda 3,S set the hour
and #$00FF
sta hour
lda 1,S set the minute
xba
and #$00FF
sta minute
pla set the second
and #$00FF
sta second
pla clean up the stack
pla
pla
jsr factor convert the seconds
lda tptr if tptr <> nil then
ora tptr+2
beq lb1
ldy #2 place the result there
lda count
sta [tptr]
lda count+2
sta [tptr],Y
lb1 lda count
sta tptr
sta lasttime
lda count+2
sta tptr+2
sta lasttime+2
pha determine if it's daylight savings
ph2 #$5E
_ReadBParam
pla
lsr A
and #$0001
eor #$0001
sta lastDST
plb
creturn 4:tptr
end
****************************************************************
*
* size_t strftime(
* char * restrict s,
* size_t maxsize,
* const char * restrict format,
* const struct tm * restrict timeptr);
*
* Inputs:
* s - pointer to output buffer
* maxsize - max number of bytes to write
* format - format string
* timeptr - the time/date
*
* Outputs:
* s - formatted string representation of the time/date
* returns length of s (not including terminating null),
* or 0 if maxsize is too small
*
****************************************************************
*
strftime start
csubroutine (4:s,4:maxsize,4:format,4:timeptr),14
substfmt equ 1 substitute format str (used if non-null)
s_orig equ substfmt+2 original s pointer (start of output str)
overflow equ s_orig+4 overflow flag
numstr equ overflow+2 string representation of a number
numstr_len equ 6 length of numstr
tm_sec equ 0 displacements into the time record
tm_min equ 2
tm_hour equ 4
tm_mday equ 6
tm_mon equ 8
tm_year equ 10
tm_wday equ 12
tm_yday equ 14
tm_isdst equ 16
phb set data bank = program bank
phk
plb
;initialization of local variables
stz substfmt substfmt = 0
lda s s_orig = s
sta s_orig
lda s+2
sta s_orig+2
stz overflow overflow = false
;main loop to process the format string
fmtloop jsr nextch get next character in format
cmp #'%' if it is not '%'
beq dosubst
nonfmt jsr writech write it to the output
bra fmtloop continue format loop
dosubst jsr nextch get next character in format
cmp #'E' if it is 'E' or 'O'
beq skipalt
cmp #'O'
bne dofmt
skipalt jsr nextch skip it
dofmt cmp #'%' if format character is '%'
beq nonfmt write it like an ordinary character
cmp #'@' if fmt chr is outside valid range
blt fmtloop skip it
cmp #'z'+1
bge fmtloop
and #$003f if we are here, fmt chr is in ['@'..'z']
asl a convert to jump table position
asl a
tax
lda fmttbl+2,x if there is a substitution
beq fmtcall
sta substfmt do the substitution
bra fmtloop
fmtcall jsr (fmttbl,x) otherwise, call the format routine
bra fmtloop continue format loop
;subroutine to get next character in format string (call only from main loop)
;returns with character in a, or exits via strftime_return if character is 0
nextch lda substfmt if there is a substitute format string
beq nosubst
lda (substfmt) get next character from it
inc substfmt advance subst string pointer
and #$00FF
bne retchar if at end of substitute format string
stz substfmt go back to using main format string
nosubst lda [format] get next character from main fmt string
and #$00FF
beq strftime_return if char is '\0', return from strftime
inc4 format advance fmt string pointer
retchar rts return from nextch
;code to return from strftime
strftime_return anop
jsr writech write '\0' to output
pla discard nextch return address
lda overflow if there was an overflow
beq ret_good
stz maxsize maxsize = 0
stz maxsize+2
bra ret
ret_good clc else
lda s maxsize = s - s_orig - 1
sbc s_orig
sta maxsize
lda s+2
sbc s_orig+2
sta maxsize+2
ret plb restore program bank
creturn 4:maxsize return maxsize
;subroutine to write a character to the output
;input: character in low-order byte of a (high-order byte is ignored)
;leaves x unchanged
writech ldy maxsize if remaining size is 0
bne writeok
ldy maxsize+2
bne writeok
lda #1 set overflow flag
sta overflow
rts return
writeok short M write the character to s
sta [s]
long M
inc4 s s++
dec4 maxsize maxsize--
rts return
;table of formatting routines or substitutions for the conversion specifiers
;first ptr is a routine, second is a subst string - only one should be non-zero
fmttbl anop
dc a2'fmt_invalid,0' @
dc a2'fmt_A,0' A
dc a2'fmt_B,0' B
dc a2'fmt_C,0' C
dc a2'0,subst_D' D
dc a2'fmt_invalid,0' E
dc a2'0,subst_F' F
dc a2'fmt_G,0' G
dc a2'fmt_H,0' H
dc a2'fmt_I,0' I
dc a2'fmt_invalid,0' J
dc a2'fmt_invalid,0' K
dc a2'fmt_invalid,0' L
dc a2'fmt_M,0' M
dc a2'fmt_invalid,0' N
dc a2'fmt_invalid,0' O
dc a2'fmt_invalid,0' P
dc a2'fmt_invalid,0' Q
dc a2'0,subst_R' R
dc a2'fmt_S,0' S
dc a2'0,subst_T' T
dc a2'fmt_U,0' U
dc a2'fmt_V,0' V
dc a2'fmt_W,0' W
dc a2'0,subst_X' X
dc a2'fmt_Y,0' Y
dc a2'fmt_Z,0' Z
dc a2'fmt_invalid,0' [
dc a2'fmt_invalid,0' \
dc a2'fmt_invalid,0' ]
dc a2'fmt_invalid,0' ^
dc a2'fmt_invalid,0' _
dc a2'fmt_invalid,0' `
dc a2'fmt_a,0' a
dc a2'fmt_b,0' b
dc a2'0,subst_c' c
dc a2'fmt_d,0' d
dc a2'fmt_e,0' e
dc a2'fmt_invalid,0' f
dc a2'fmt_g,0' g
dc a2'fmt_h,0' h
dc a2'fmt_invalid,0' i
dc a2'fmt_j,0' j
dc a2'fmt_invalid,0' k
dc a2'fmt_invalid,0' l
dc a2'fmt_m,0' m
dc a2'fmt_n,0' n
dc a2'fmt_invalid,0' o
dc a2'fmt_p,0' p
dc a2'fmt_invalid,0' q
dc a2'0,subst_r' r
dc a2'fmt_invalid,0' s
dc a2'fmt_t,0' t
dc a2'fmt_u,0' u
dc a2'fmt_invalid,0' v
dc a2'fmt_w,0' w
dc a2'0,subst_x' x
dc a2'fmt_y,0' y
dc a2'fmt_z,0' z
;%a - abbreviated weekday name
fmt_a ldy #tm_wday
lda [timeptr],y
asl a
tay
ldx weekdays,y
lda |0,x
jsr writech
lda |1,x
jsr writech
lda |2,x
brl writech
;%A - full weekday name
fmt_A ldy #tm_wday
lda [timeptr],y
asl a
tay
ldx weekdays,y
A_loop lda |0,x
and #$00FF
beq A_ret
jsr writech
inx
bra A_loop
A_ret rts
;%b - abbreviated month name
fmt_b ldy #tm_mon
lda [timeptr],y
asl a
tay
ldx months,y
lda |0,x
jsr writech
lda |1,x
jsr writech
lda |2,x
brl writech
;%B - full month name
fmt_B ldy #tm_mon
lda [timeptr],y
asl a
tay
ldx months,y
B_loop lda |0,x
and #$00FF
beq A_ret
jsr writech
inx
bra A_loop
B_ret rts
;%c - date and time
subst_c dc c'%a %b %e %H:%M:%S %Y',i1'0'
;%C - century
fmt_C jsr format_year
ldx #0
C_loop lda numstr,x
and #$00FF
cmp #' '
beq C_skip
jsr writech
C_skip inx
cpx #numstr_len-2
blt C_loop
rts
;%d - day of the month (01-31)
fmt_d ldy #tm_mday
brl print2digits_of_field
;%D - equivalent to %m/%d/%y
subst_D dc c'%m/%d/%y',i1'0'
;%e - day of the month (1-31, padded with space if a single digit)
fmt_e ldy #tm_mday
lda [timeptr],y
ldy #2
cmp #10
bge e_print
tax
lda #' '
jsr writech
txa
ldy #1
e_print brl printdigits
;%F - equivalent to %Y-%m-%d
subst_F dc c'%Y-%m-%d',i1'0'
;%g - last two digits of week-based year
fmt_g jsr week_number_V
jsr format_year_altbase
brl write_year_2digit
;%G - week-based year
fmt_G jsr week_number_V
jsr format_year_altbase
brl write_year
;%h - equivalent to %b
fmt_h brl fmt_b
;%H - hour (24-hour clock, 00-23)
fmt_H ldy #tm_hour
brl print2digits_of_field
;%I - hour (12-hour clock, 01-12)
fmt_I ldy #tm_hour
lda [timeptr],y
bne I_adjust
lda #12
I_adjust cmp #12+1
blt I_print
sbc #12
I_print brl print2digits
;%j - day of the year (001-366)
fmt_j ldy #tm_yday
lda [timeptr],y
inc a
ldy #3
brl printdigits
;%m - month number
fmt_m ldy #tm_mon
lda [timeptr],y
inc a
brl print2digits
;%M - minute
fmt_M ldy #tm_min
brl print2digits_of_field
;%n - new-line character
fmt_n lda #$0A
brl writech
;%p - AM/PM
fmt_p ldy #tm_hour
lda [timeptr],y
cmp #12
bge p_pm
lda #'A'
bra p_write
p_pm lda #'P'
p_write jsr writech
lda #'M'
brl writech
;%r - time (using 12-hour clock)
subst_r dc c'%I:%M:%S %p',i1'0'
;%R - equivalent to %H:%M
subst_R dc c'%H:%M',i1'0'
;%S - seconds
fmt_S ldy #tm_sec
brl print2digits_of_field
;%t - horizontal tab character
fmt_t lda #$09
brl writech
;%T - equivalent to %H:%M:%S
subst_T dc c'%H:%M:%S',i1'0'
;%u - weekday number (1-7, Monday=1)
fmt_u ldy #tm_wday
lda [timeptr],y
bne u_print
lda #7
u_print ldy #1
brl printdigits
;%U - week number of the year (first Sunday starts week 01)
fmt_U ldy #tm_yday
lda [timeptr],y
clc
adc #7
sec
ldy #tm_wday
sbc [timeptr],y
jsr div7
tya
brl print2digits
;%V - ISO 8601 week number
fmt_V jsr week_number_V
txa
brl print2digits
;%w - weekday number (0-6, 0=Sunday)
fmt_w ldy #tm_wday
lda [timeptr],y
ldy #1
brl printdigits
;%W - week number of the year (first Monday starts week 01)
fmt_W jsr week_number_W
tya
brl print2digits
;%x - date
subst_x dc c'%m/%d/%y',i1'0'
;%X - time
subst_X dc c'%T',i1'0'
;%y - last two digits of year
fmt_y jsr format_year
write_year_2digit anop
lda numstr+4
jsr writech
lda numstr+5
brl writech
;%Y - year
fmt_Y jsr format_year
write_year anop
ldx #0
Y_loop lda numstr,x
and #$00FF
cmp #' '
beq Y_skip
jsr writech
Y_skip inx
cpx #numstr_len
blt Y_loop
rts
;%z - offset from UTC, if available
;we print nothing, because time zone info is not available
fmt_z rts
;%Z - time zone name or abbreviation, if available
;we print nothing, because time zone info is not available
fmt_Z rts
fmt_invalid rts
;get decimal representation of the year in numstr
;the string is adjusted to have at least four digits
format_year anop
lda #1900
format_year_altbase anop alt entry point using year base in a
ldx #1 default to signed
clc
ldy #tm_year
adc [timeptr],y
bvc year_ok
ldx #0 use unsigned if signed value overflows
year_ok jsr int2dec
short M,I
ldx #4
yr_adjlp lda numstr,x adjust year to have >= 4 digits
cmp #'-'
bne yr_adj1
sta numstr-1,x
bra yr_adj2
yr_adj1 cmp #' '
bne yr_adj3
yr_adj2 lda #'0'
sta numstr,x
yr_adj3 dex
cpx #2
bge yr_adjlp
long M,I
rts
;get the week number as for %W (first Monday starts week 1)
;output: week number in y
week_number_W anop
ldy #tm_wday
lda [timeptr],y
beq W_yday
sec
lda #7
sbc [timeptr],y
W_yday sec
ldy #tm_yday
adc [timeptr],y
brl div7
;get the ISO 8601 week number (as for %V) and corresponding year adjustment
;output: week number in x, adjusted year base in a (1900-1, 1900, or 1900+1)
week_number_V anop
jsr week_number_W get %W-style week number (kept in x)
tyx
ldy #tm_wday calculate wday for Jan 1 (kept in a)
lda [timeptr],y
sec
ldy #tm_yday
sbc [timeptr],y
clc
adc #53*7
jsr div7
cmp #2 if Jan 1 was Tue/Wed/Thu
blt V_adjust
cmp #4+1
bge V_adjust
inx inc week (week 1 started in last year)
V_adjust txy
bne V_not0 week 0 is really 52 or 53 of last year:
ldx #52 assume 52
cmp #5 if Jan 1 is Fri
bne V_0notfr
inx last year had week 53
bra V_0done
V_0notfr cmp #6 else if Jan 1 is Sat
bne V_0done
ldy #tm_year
lda [timeptr],y
dec a
jsr leapyear if last year was a leap year
bne V_0done
inx last year had week 53
V_0done lda #-1+1900 year adjustment is -1
bra V_done
V_not0 cpx #53 week 53 might be week 1 of next year:
bne V_noadj
cmp #4 if Jan 1 was Thu
beq V_noadj it is week 53
cmp #3 else if Jan 1 was Wed
bne V_53is1
ldy #tm_year
lda [timeptr],y
jsr leapyear and this is a leap year
beq V_noadj it is week 53
V_53is1 ldx #1 otherwise, it is really week 1
lda #1+1900 and year adjustment is +1
rts
V_noadj lda #0+1900 if we get here, year adjustment is 0
V_done rts
;check if a year is a leap year
;input: tm_year value in a
;output: z flag set if a leap year, clear if not; x,y unmodified
leapyear and #$0003 not multiple of 4 => not leap year
bne ly_done
clc calculate year mod 400
adc #1900-1600
bpl ly_lp400
clc
adc #32800
sec
ly_lp400 sbc #400
bcs ly_lp400
adc #400
beq ly_done multiple of 400 => leap year
sec
ly_lp100 sbc #100
bcs ly_lp100
cmp #-100
bne ly_leap
dec a other multiple of 100 => not leap year
rts
ly_leap lda #0 other multiple of 4 => leap year
ly_done rts
;divide a number (treated as unsigned) by 7
;input: dividend in a
;output: quotient in y, remainder in a, x unmodified
div7 ldy #-1
sec
sublp iny
sbc #7
bcs sublp
adc #7
rts
;print the low-order two digits of a field of struct tm
;(with leading zeros, if any)
;input: offset of field in y
print2digits_of_field anop
lda [timeptr],y load the field
;print the low-order two digits of a number (with leading zeros, if any)
;input: number in a
print2digits anop
ldy #2 print two digits
;print the low-order digits of a number (with leading zeros, if any)
;input: number in a, how many digits to print in y
printdigits anop
pd1 phy save number of digits to print
ldx #0 treat as signed
jsr int2dec convert to decimal string
sec calculate where to print from
lda #numstr_len
sbc 1,s
ply
tax
pd_loop lda numstr,x print the digits
and #$00FF
cmp #' ' change padding spaces to zeros
bne pd_write
lda #'0'
pd_write jsr writech
inx
cpx #numstr_len
blt pd_loop
rts
;get decimal representation of a number, placed in numstr
;input: number in a, signed flag in y
int2dec pha number to convert
pea 0000 pointer to string buffer
tdc
clc
adc #numstr
pha
pea numstr_len length of string buffer
phx signed flag
_Int2Dec
rts
weekdays dc a2'sun,mon,tue,wed,thu,fri,sat'
sun dc c'Sunday',i1'0'
mon dc c'Monday',i1'0'
tue dc c'Tuesday',i1'0'
wed dc c'Wednesday',i1'0'
thu dc c'Thursday',i1'0'
fri dc c'Friday',i1'0'
sat dc c'Saturday',i1'0'
months dc a2'jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec'
jan dc c'January',i1'0'
feb dc c'February',i1'0'
mar dc c'March',i1'0'
apr dc c'April',i1'0'
may dc c'May',i1'0'
jun dc c'June',i1'0'
jul dc c'July',i1'0'
aug dc c'August',i1'0'
sep dc c'September',i1'0'
oct dc c'October',i1'0'
nov dc c'November',i1'0'
dec dc c'December',i1'0'
end