Merge branch 'master' into gno-version

This commit is contained in:
Stephen Heumann 2023-04-06 15:54:40 -05:00
commit 14121f55b6
11 changed files with 1945 additions and 327 deletions

107
cc.asm
View File

@ -186,6 +186,9 @@ TAB equ 9 TAB key code
stz ~ExitList+2
stz ~QuickExitList
stz ~QuickExitList+2
case on
stz __useTimeTool do not use Time Tool
case off
lda cLine if cLine == 0 then
ora cLine+2
@ -240,8 +243,6 @@ lb6 long M
phy
sec
adc 1,S
ply
pha
pha
pea 0
pha
@ -261,20 +262,19 @@ lb7 pl4 argv get the pointer to the area
lda [argv]
sta targv
stx targv+2
clc get a pointer to the command line string
adc start
; clc (already clear)
adc start get a pointer to the command line string
bcc lb8
inx
lb8 sta argv
stx argv+2
short M move the command line string
ldy #0
lb9 lda [cLine],Y
ldy #-1
lb9 iny
lda [cLine],Y
sta [argv],Y
beq lb10
iny
bra lb9
lb10 long M
bne lb9
long M
move4 argv,cLine save the pointer
move4 targv,argv set up the pointer to argv
@ -360,6 +360,9 @@ start ds 2 start of the command line string
stz ~ExitList+2
stz ~QuickExitList
stz ~QuickExitList+2
case on
stz __useTimeTool do not use Time Tool
case off
lda #~RTL set up so exit(), etc. call ~RTL
sta ~C_Quit+1
@ -372,6 +375,78 @@ start ds 2 start of the command line string
targv ds 4
end
****************************************************************
*
* ~CDevCleanup - cleanup code run after a CDev call
*
* Inputs:
* A+X - CDev result value
* 1,S - Original data bank to restore
* 2,S - Return address
* 5,S - Message code passed to CDev
* 7,S - Old user ID from before the call (0 if none)
*
* Notes:
* This routine handles cases where the CDev is going
* away and so the user ID allocated for it needs to be
* disposed of to avoid being leaked.
*
****************************************************************
*
~CDevCleanup start
MachineCDEV equ 1
BootCDEV equ 2
CloseCDEV equ 5
AboutCDEV equ 8
tay stash low word of result
lda 5,s if message == CloseCDEV
cmp #CloseCDEV
beq cleanup
cmp #BootCDEV or message == BootCDEV
beq cleanup
cmp #AboutCDEV or message == AboutCDEV
bne lb1
lda 7,s and original user ID was 0
beq cleanup (i.e. CDev window was not open)
bra ret
lb1 cmp #MachineCDEV or message == MachineCDEV
bne ret
tya and return value is 0
bne ret
txa
bne ret
cleanup pea 0 ...then dispose of user ID
jsl >~DAID
ret tya store return value in result space
sta 5,s
txa
sta 7,s
plb restore data bank
rtl return to original caller
end
****************************************************************
*
* ~CheckPtrC - check a pointer to insure it is not null
*
* Inputs:
* 1,S - return address
* 4,S - pointer
*
****************************************************************
*
~CheckPtrC start
lda 4,S
ora 5,S
bne lb1
error #1 subrange exceeded
lb1 rtl
end
****************************************************************
*
* ~CUMul2 - unsigned multiply
@ -443,10 +518,7 @@ ptr equ 3 pointer to exit routines
;
; Set up our stack frame
;
phb
phk
plb
ph4 ~ExitList set up our stack frame
ph4 >~ExitList set up our stack frame
phd
tsc
tcd
@ -501,7 +573,6 @@ lb3 lda >__cleanup+2
lb4 pld return
pla
pla
plb
rts
end
@ -519,10 +590,7 @@ ptr equ 3 pointer to exit routines
;
; Set up our stack frame
;
phb
phk
plb
ph4 ~QuickExitList set up our stack frame
ph4 >~QuickExitList set up our stack frame
phd
tsc
tcd
@ -559,7 +627,6 @@ lb2 ldy #2 dereference the pointer
lb3 pld return
pla
pla
plb
rts
end

View File

@ -47,8 +47,7 @@ feclearexcept start
sta 1,S
FSETENV clear them
stz excepts
creturn 2:excepts
creturn 2:#0
end
****************************************************************
@ -76,8 +75,7 @@ fegetexceptflag start
and #FE_ALL_EXCEPT
sta [flagp] store them in *flagp
stz excepts
creturn 2:excepts
creturn 2:#0
end
****************************************************************
@ -104,8 +102,7 @@ feraiseexcept start
pha
FSETXCP raise exceptions
done stz excepts
creturn 2:excepts
done creturn 2:#0
end
****************************************************************
@ -144,8 +141,7 @@ fesetexceptflag start
sta 1,S
FSETENV
stz excepts
creturn 2:excepts
creturn 2:#0
end
****************************************************************
@ -250,8 +246,7 @@ fegetenv start
txa
sta [envp] store it in *envp
stz envp
creturn 2:envp
creturn 2:#0
end
****************************************************************
@ -280,8 +275,7 @@ feholdexcept start
pha
FSETENV set the new environment
stz envp
creturn 2:envp
creturn 2:#0
end
****************************************************************
@ -306,8 +300,7 @@ fesetenv start
pha
FSETENV
stz envp
creturn 2:envp
creturn 2:#0
end
****************************************************************
@ -332,8 +325,7 @@ feupdateenv start
pha
FPROCEXIT
stz envp
creturn 2:envp
creturn 2:#0
end
****************************************************************

View File

@ -691,16 +691,17 @@ convert lda 4+8,s
pla if original value was negative
bpl done
sec
lda #0 negate result
ldx #0 negate result
txa
sbc 6,s
sta 6,s
lda #0
txa
sbc 6+2,s
sta 6+2,s
lda #0
txa
sbc 6+4,s
sta 6+4,s
lda #0
txa
sbc 6+6,s
sta 6+6,s

1093
math2.asm

File diff suppressed because it is too large Load Diff

View File

@ -377,6 +377,21 @@
~a&SYSCNT anop
~restm
mend
macro
&l jmi &bp
&l bpl *+5
brl &bp
mend
macro
&l jpl &bp
&l bmi *+5
brl &bp
mend
macro
&l jeq &bp
&l bne *+5
brl &bp
mend
MACRO
&LAB FCLASSS
&LAB PEA $021C
@ -652,3 +667,84 @@
LDX #$0B0A
JSL $E10000
MEND
MACRO
&LAB FCMPS
&LAB PEA $0208
LDX #$090A
JSL $E10000
MEND
MACRO
&LAB FEXPX
&LAB PEA $0008
LDX #$0B0A
JSL $E10000
MEND
MACRO
&LAB FCMPI
&LAB PEA $0408
LDX #$090A
JSL $E10000
MEND
MACRO
&LAB FSUBS
&LAB PEA $0202
LDX #$090A
JSL $E10000
MEND
MACRO
&LAB FSINX
&LAB PEA $001A
LDX #$0B0A
JSL $E10000
MEND
MACRO
&LAB FREMI
&LAB PEA $040C
LDX #$090A
JSL $E10000
MEND
macro
&l dec4 &a
&l ~setm
lda &a
bne ~&SYSCNT
dec 2+&a
~&SYSCNT dec &a
~restm
mend
macro
&l add4 &m1,&m2,&m3
lclb &yistwo
lclc &c
&l ~setm
aif c:&m3,.a
&c amid "&m2",1,1
aif "&c"<>"#",.a
&c amid "&m1",1,1
aif "&c"="{",.a
aif "&c"="[",.a
&c amid "&m2",2,l:&m2-1
aif &c>=65536,.a
clc
~lda &m1
~op adc,&m2
~sta &m1
bcc ~&SYSCNT
~op.h inc,&m1
~&SYSCNT anop
ago .c
.a
aif c:&m3,.b
lclc &m3
&m3 setc &m1
.b
clc
~lda &m1
~op adc,&m2
~sta &m3
~lda.h &m1
~op.h adc,&m2
~sta.h &m3
.c
~restm
mend

151
stdio.asm
View File

@ -688,24 +688,26 @@ disp equ 1 disp in s
ph4 <stream verify that stream exists
jsl ~VerifyStream
bcs err1
ph4 <stream quit with NULL if at EOF
jsl feof
tax
beq lb0
err1 stz s
stz s+2
bra rts
lb0 stz disp no characters processed so far
lda #0
sta [s]
bcs err
stz disp no characters processed so far
dec n leave room for the null terminator
bmi err
beq err
bne lb1
short M n = 1: store null terminator only
lda #0
sta [s]
long M
bra rts
lb1 ph4 <stream get a character
jsl fgetc
tax quit with error if it is an EOF
tax if error or EOF encountered
bpl lb2
lda disp if no characters read, return NULL
beq err
ldy #FILE_flag if error encountered, return NULL
lda [stream],Y
and #_IOERR
beq rts else return s
err stz s
stz s+2
bra rts
@ -2249,9 +2251,15 @@ disp equ 1 disp in s
stz disp no characters processed so far
lb1 jsl getchar get a character
tax quit with error if it is an EOF
tax if error or EOF encountered
bpl lb2
stz s
lda disp if no characters read, return NULL
beq err
ph4 >stdin if error encountered, return NULL
jsl ferror
tax
beq rts else return s
err stz s
stz s+2
bra rts
lb2 cmp #LF quit if it was a \n
@ -3202,9 +3210,8 @@ pr dc i'2' parameter block for OSGet_Prefix
dc i'3'
dc a4'name'
name dc i'16,0' GS/OS name buffer
name dc i'17+4,0' GS/OS name buffer
cname ds 26 part of name; also C buffer
GS_OSname dc i'8' used for OSGet_File_Info
syscxxxx dc c'SYSC0000',i1'0' for creating unique names
GIParm dc i'2' used to see if the file exists
@ -4909,20 +4916,20 @@ fm4 cmp #'L' else if *format in ['L','h'] then
inc ~isByte
fm5 inc4 format ++format
lda [format] find the proper format character
and #$00FF
fm6 inc4 format
ldx #fListEnd-fList-4
short M,I
ldx #fListEnd-fList-3
fm7 cmp fList,X
beq fm8
dex
dex
dex
dex
bpl fm7
long M,I
brl ps1 none found - continue
fm8 pea ps1-1 push the return address
fm8 long M,I
pea ps1-1 push the return address
inx call the subroutine
inx
jmp (fList,X)
;
; Flag - Read and process a flag character
@ -5013,27 +5020,27 @@ val ds 2 value
;
; List of format specifiers and the equivalent subroutines
;
fList dc c'%',i1'0',a'~Format_Percent' %
dc c'a',i1'0',a'~Format_e' a (not formatted correctly)
dc c'A',i1'0',a'~Format_E' A (not formatted correctly)
dc c'f',i1'0',a'~Format_f' f
dc c'F',i1'0',a'~Format_f' F
dc c'e',i1'0',a'~Format_e' e
dc c'E',i1'0',a'~Format_E' E
dc c'g',i1'0',a'~Format_g' g
dc c'G',i1'0',a'~Format_G' G
dc c'n',i1'0',a'~Format_n' n
dc c's',i1'0',a'~Format_s' s
dc c'b',i1'0',a'~Format_b' b
dc c'P',i1'0',a'~Format_P' P
dc c'p',i1'0',a'~Format_p' p
dc c'c',i1'0',a'~Format_c' c
dc c'X',i1'0',a'~Format_X' X
dc c'x',i1'0',a'~Format_x' x
dc c'o',i1'0',a'~Format_o' o
dc c'u',i1'0',a'~Format_u' u
dc c'd',i1'0',a'~Format_d' d
dc c'i',i1'0',a'~Format_d' i
fList dc c'%',a'~Format_Percent' %
dc c'a',a'~Format_e' a (not formatted correctly)
dc c'A',a'~Format_E' A (not formatted correctly)
dc c'f',a'~Format_f' f
dc c'F',a'~Format_f' F
dc c'e',a'~Format_e' e
dc c'E',a'~Format_E' E
dc c'g',a'~Format_g' g
dc c'G',a'~Format_G' G
dc c'n',a'~Format_n' n
dc c's',a'~Format_s' s
dc c'b',a'~Format_b' b
dc c'P',a'~Format_P' P
dc c'p',a'~Format_p' p
dc c'c',a'~Format_c' c
dc c'X',a'~Format_X' X
dc c'x',a'~Format_x' x
dc c'o',a'~Format_o' o
dc c'u',a'~Format_u' u
dc c'd',a'~Format_d' d
dc c'i',a'~Format_d' i
fListEnd anop
end
@ -6117,7 +6124,7 @@ fm2b inc ~size
fm2c inc ~size
bra fm4
fm3 cmp #'h' 'h' specifies short int
bne fm5
bne fm6
inc4 format unless it is 'hh' for char types
lda [format]
and #$00FF
@ -6126,21 +6133,21 @@ fm3 cmp #'h' 'h' specifies short int
dec ~size
fm4 inc4 format ignore the character
fm5 lda [format] find the proper format character
and #$00FF
lda [format] find the proper format character
fm6 inc4 format
ldx #fListEnd-fList-4
short M,I
ldx #fListEnd-fList-3
fm7 cmp fList,X
beq fm8
dex
dex
dex
dex
bpl fm7
long M,I
brl ps1 none found - continue
fm8 pea ps1-1 push the return address
fm8 long M,I
pea ps1-1 push the return address
inx call the subroutine
inx
jmp (fList,X)
;
; GetSize - get a numeric value
@ -6182,28 +6189,28 @@ val ds 2 value
;
; List of format specifiers and the equivalent subroutines
;
fList dc c'd',i1'0',a'~Scan_d' d
dc c'i',i1'0',a'~Scan_i' i
dc c'u',i1'0',a'~Scan_u' u
dc c'o',i1'0',a'~Scan_o' o
dc c'x',i1'0',a'~Scan_x' x
dc c'X',i1'0',a'~Scan_x' X
dc c'p',i1'0',a'~Scan_p' p
dc c'c',i1'0',a'~Scan_c' c
dc c's',i1'0',a'~Scan_s' s
dc c'b',i1'0',a'~Scan_b' b
dc c'P',i1'0',a'~Scan_P' P
dc c'n',i1'0',a'~Scan_n' n
dc c'a',i1'0',a'~Scan_f' a
dc c'A',i1'0',a'~Scan_f' A
dc c'f',i1'0',a'~Scan_f' f
dc c'F',i1'0',a'~Scan_f' F
dc c'e',i1'0',a'~Scan_f' e
dc c'E',i1'0',a'~Scan_f' E
dc c'g',i1'0',a'~Scan_f' g
dc c'G',i1'0',a'~Scan_f' G
dc c'%',i1'0',a'~Scan_percent' %
dc c'[',i1'0',a'~Scan_lbrack' [
fList dc c'd',a'~Scan_d' d
dc c'i',a'~Scan_i' i
dc c'u',a'~Scan_u' u
dc c'o',a'~Scan_o' o
dc c'x',a'~Scan_x' x
dc c'X',a'~Scan_x' X
dc c'p',a'~Scan_p' p
dc c'c',a'~Scan_c' c
dc c's',a'~Scan_s' s
dc c'b',a'~Scan_b' b
dc c'P',a'~Scan_P' P
dc c'n',a'~Scan_n' n
dc c'a',a'~Scan_f' a
dc c'A',a'~Scan_f' A
dc c'f',a'~Scan_f' f
dc c'F',a'~Scan_f' F
dc c'e',a'~Scan_f' e
dc c'E',a'~Scan_f' E
dc c'g',a'~Scan_f' g
dc c'G',a'~Scan_f' G
dc c'%',a'~Scan_percent' %
dc c'[',a'~Scan_lbrack' [
fListEnd anop
;
; Other local data

View File

@ -333,6 +333,10 @@ addr equ 13 address of array element of index test
csubroutine (4:key,4:base,4:count,4:size,4:compar),16
lda count if count is 0 then
ora count+2
jeq lb5 just return a null pointer
lda compar patch the call address
sta >jsl+1
lda compar+1
@ -700,13 +704,14 @@ ret stx n
qsort start
csubroutine (4:base,4:count,4:size,4:compar),0
phb
phk
plb
lda count nothing to do if count is 0
ora count+2
beq done
phb
phk
plb
dec4 count set count to the addr of the last entry
mul4 count,size
add4 count,base
@ -717,12 +722,13 @@ qsort start
lda compar+1
sta jsl1+2
sta jsl2+2
plb
ph4 <count do the sort
ph4 <base
jsl rsort
done plb
creturn
done creturn
end
****************************************************************
@ -765,26 +771,31 @@ right equ 5 right address
csubroutine (4:first,4:last),8
phb
sr0 phb
phk
plb
sr0 lda last+2 if last <= first then quit
lda last+2 if last <= first then quit
bmi sr1a
cmp first+2
bne sr1
lda last
cmp first
sr1 bgt sr1a
plb
sr1 bgt sr1b
sr1a plb
creturn
sr1a move4 last,right right = last
sr1b move4 last,right right = last
move4 first,left left = first
bra sr3
sr2 add4 left,lsize inc left until *left >= *last
sr3 ph4 <last
sr3 plb
ph4 <last
ph4 <left
jsl1 entry
jsl jsl1
phb
phk
plb
tax
bmi sr2
sr4 lda right quit if right = first
@ -794,10 +805,14 @@ sr4 lda right quit if right = first
cmp first+2
beq sr4b
sr4a sub4 right,lsize dec right until *right <= *last
plb
ph4 <last
ph4 <right
jsl2 entry
jsl jsl2
phb
phk
plb
dec A
bpl sr4
sr4b ph4 <left swap left/right entries
@ -815,11 +830,24 @@ sr5 blt sr2
ph4 <left swap left/last entries
ph4 <last
jsr swap
sub4 left,lsize,right sort left part of array
ph4 <right
sub4 left,lsize,right calculate bounds of subarrays
add4 left,lsize (first..right and left..last)
add4 first,last,mid calculate midpoint of range being sorted
lsr mid+2
ror mid
cmpl right,mid if right < mid then
bge sr6
plb
ph4 <right sort left subarray recursively
ph4 <first
jsl rsort
add4 left,lsize,first sort right part of array
move4 left,first sort right subarray via tail call
brl sr0
sr6 plb else
ph4 <last sort right subarray recursively
ph4 <left
jsl rsort
move4 right,last sort left subarray via tail call
brl sr0
;
; swap - swap two entries
@ -830,8 +858,9 @@ r equ 7 right entry
swap tsc set up addressing
phd
tcd
ldx lsize+2 move 64K chunks
lda lsize+2 move 64K chunks
beq sw2
sta banks
ldy #0
sw1 lda [l],Y
tax
@ -844,7 +873,7 @@ sw1 lda [l],Y
bne sw1
inc l+2
inc r+2
dex
dec banks
bne sw1
sw2 lda lsize if there are an odd number of bytes then
lsr A
@ -893,6 +922,8 @@ sw6 pld
;
lsize entry
ds 4 local copy of size
banks ds 2 number of whole banks to swap
mid ds 4 midpoint of the elements being sorted
end
****************************************************************
@ -968,9 +999,10 @@ rtl equ 7 return address
val equ 3 value
negative equ 1 is the number negative?
pea 0 make room for & initialize val
pea 0
pea 0 make room for & initialize negative
lda #0
pha make room for & initialize val
pha
pha make room for & initialize negative
tsc set up direct page addressing
phd
tcd
@ -1095,10 +1127,11 @@ foundOne equ 1 have we found a number?
ldx #1
init pea 1 make room for & initialize rangeOK
pea 0 make room for & initialize negative
pea 0 make room for & initialize val
pea 0
pea 0 make room for & initialize foundOne
lda #0
pha make room for & initialize negative
pha make room for & initialize val
pha
pha make room for & initialize foundOne
tsc set up direct page addressing
phd
tcd
@ -1286,13 +1319,14 @@ retptr equ 11 pointer to location for return value
val equ 3 value
negative equ 1 is the number negative?
pea 0 make room for & initialize retptr
lda #0
pha make room for & initialize retptr
phx
pea 0 make room for & initialize val
pea 0
pea 0
pea 0
pea 0 make room for & initialize negative
pha make room for & initialize val
pha
pha
pha
pha make room for & initialize negative
tsc set up direct page addressing
phd
tcd
@ -1435,15 +1469,16 @@ foundOne equ 1 have we found a number?
~strtoull entry alt entry point called from strtoll
ldy #1
init pea 0 make room for & initialize retptr
init lda #0
pha make room for & initialize retptr
phx
pea 1 make room for & initialize rangeOK
pea 0 make room for & initialize negative
pea 0 make room for & initialize val
pea 0
pea 0
pea 0
pea 0 make room for & initialize foundOne
pha make room for & initialize negative
pha make room for & initialize val
pha
pha
pha
pha make room for & initialize foundOne
tsc set up direct page addressing
phd
tcd

View File

@ -734,3 +734,15 @@
&l bne *+5
brl &bp
mend
macro
&l cmpl &n1,&n2
lclb &yistwo
&l ~setm
~lda.h &n1
~op.h cmp,&n2
bne ~a&SYSCNT
~lda &n1
~op cmp,&n2
~a&SYSCNT anop
~restm
mend

613
time.asm
View File

@ -19,7 +19,18 @@
*
****************************************************************
*
Time start dummy segment
Time private dummy segment
; struct tm fields
tm_sec gequ 0 seconds 0..59
tm_min gequ tm_sec+2 minutes 0..59
tm_hour gequ tm_min+2 hours 0..23
tm_mday gequ tm_hour+2 day 1..31
tm_mon gequ tm_mday+2 month 0..11
tm_year gequ tm_mon+2 year 69..205 (1900=0)
tm_wday gequ tm_year+2 day of week 0..6 (Sun = 0)
tm_yday gequ tm_wday+2 day of year 0..365
tm_isdst gequ tm_yday+2 daylight savings? 1 = yes, 0 = no
end
****************************************************************
@ -30,15 +41,15 @@ Time start dummy segment
*
TimeCommon privdata
;
; For conversion to/from seconds since 1970
; For conversion to/from seconds since 13 Nov 1969
;
year ds 4 year 0..99
month ds 4 month 1..12
year ds 4 year (years since 1900)
month ds 4 month 0..11
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
count ds 8 seconds since 13 Nov 1969
t1 ds 4 work variable
t2 ds 4 work variable
@ -225,63 +236,260 @@ mk1 inx
****************************************************************
*
* factor - compute the seconds since 1 Jan 1970 from date
* factor - compute the seconds since 13 Nov 1969 from date
*
* factor_second32 - alt entry point taking second as a
* signed 32-bit input value
*
* Inputs:
* year,month,day,hour,minute,second - time to convert
* (each treated as a signed 16-bit value, with the
* exception of second when using factor_second32)
*
* Outputs:
* count - seconds since 1 Jan 1970
* count - seconds since 13 Nov 1969 (signed 64-bit value)
*
* Note: Input values outside their normal ranges are allowed.
*
****************************************************************
*
factor private
using TimeCommon
;
; compute the # of days since 1 Jan 1970
; sign-extend time components to 4 bytes
;
mul4 year,#365,count count := 365*year + day + 31*(month-1)
stz second+2
lda second
bpl lb0
dec second+2
factor_second32 entry
lb0 stz year+2
lda year
bpl lb0a
dec year+2
lb0a stz month+2
stz day+2
lda day
bpl lb0b
dec day+2
lb0b stz hour+2
lda hour
bpl lb0c
dec hour+2
lb0c stz minute+2
lda minute
bpl lb0e
dec minute+2
;
; adjust for out-of-range month values
;
lb0e lda month
bpl lb0f
clc
adc #12
sta month
dec4 year
bra lb0e
lb0f sec
sbc #12
bmi lb0x
sta month
inc4 year
bra lb0e
;
; compute the # of days since 13 Nov 1969
;
lb0x mul4 year,#365,count count := 365*year + day + 31*month
add4 count,day
mul4 month,#31,t1
add4 count,t1
sub4 count,#31
move4 year,t2 t2 := year
add4 year,#32800,t2 t2 := year + 32800 (so it is positive)
lda month if January or February then
cmp #3
cmp #2
bge lb1
dec t2 year := year-1
dec4 t2 year := year-1
bra lb2 else
lb1 mul4 month,#4,t1 count := count - (month*4+23) div 10
add4 t1,#23
lb1 mul4 month,#4,t1 count := count - (month*4+27) div 10
add4 t1,#27
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
lb2 div4 t2,#4,t1 count := count + (year+32800) div 4
add4 count,t1
add4 t2,#300 count := count -
div4 t2,#100 ((300+year+32800) 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
sub4 count,#25518-2+7954 subtract off days between 1 Jan 1900
! and 13 Nov 1969, minus 2 to adjust for
! skipped leap days in 1700 and 1800,
! plus 7954 to adjust for leap days in
! an additional 32800 years
;
; 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
lda count+2 convert to 64-bit count of seconds
pha
bpl lb3 if count is negative, negate it
sub4 #0,count,count
lb3 tsc compute count*24*60*60
sec
sbc #8
tcs
ph4 count
ph4 #24*60*60
_LongMul
pla
sta count
pla
sta count+2
pla
sta count+4
pla
sta count+6
pla
bpl lb4 if count was negative, negate result
negate8 count
lb4 mul4 hour,#3600,t1 add in hours*3600
jsr add_t1_to_count
mul4 minute,#60,t1 add in minutes*60
add4 count,t1
add4 count,second add in seconds
jsr add_t1_to_count
move4 second,t1 add in seconds
;
; Add t1 (4 bytes) to count (8 bytes).
; (This is called as a subroutine and also run at the end of factor.)
;
add_t1_to_count anop
clc
lda t1
adc count
sta count
lda t1+2
tax
adc count+2
sta count+2
lda #0
txy
bpl ad1
dec a
ad1 tay
adc count+4
sta count+4
tya
adc count+6
sta count+6
rts
end
****************************************************************
*
* ~get_tz_offset - get current time zone offset from UTC
*
* Outputs:
* A-X - time zone offset from UTC
*
****************************************************************
*
~get_tz_offset private
lda >__useTimeTool if not using time tool
beq no_tz assume we have no TZ offset
pha make space for TZ prefs
pha
pea 1 get one record element only (TZ offset)
tsc get time zone preference
inc a
pea 0
pha
_tiGetTimePrefs
pla
bcc have_tz
pla
pla
lda #0 assume 0 offset if TZ info not available
no_tz tax
rts
have_tz pha determine if it's daylight savings
ph2 #$5E
_ReadBParam
pla
lsr a
lsr a
bcs ret
; clc
lda #60*60 adjust for DST (+1 hour) if needed
adc 1,s
sta 1,s
lda #0
adc 3,s
sta 3,s
ret pla return offset value
plx
rts
end
****************************************************************
*
* gmlocaltime_tm - struct tm used by gmtime and localtime
*
****************************************************************
*
gmlocaltime_tm private
ds 9*2
end
****************************************************************
*
* struct tm *gmtime(t)
* time_t *t;
*
* Inputs:
* t - pointer to # of seconds since 13 Nov 1969
*
* Outputs:
* returns a pointer to a time record for UTC time
*
****************************************************************
*
gmtime start
t equ 6
phd
tsc
tcd
ldy #2 dereference the pointer to time_t
lda [t],Y
tax
lda [t]
tay
pld
phb
pla move return address
sta 3,s
pla
sta 3,s
plb
ph4 #gmlocaltime_tm push address of struct tm to use
pea 0 push tm_isdst value (no DST for UTC)
phx push time_t value to convert
phy
jsr ~get_tz_offset push time zone offset
phx
pha
doit jsl ~gmlocaltime use common gmtime/localtime code
rtl
end
****************************************************************
*
@ -289,106 +497,172 @@ lb3 add4 t2,#300 count := count -
* time_t *t;
*
* Inputs:
* t - # seconds since 1 Jan 1970
* t - pointer to # of seconds since 13 Nov 1969
*
* Outputs:
* returns a pointer to a time record for local time
*
****************************************************************
*
localtime start
using TimeCommon
t equ 6
phd
tsc
tcd
ldy #2 dereference the pointer to time_t
lda [t],Y
tax
lda [t]
tay
pld
phb
pla move return address
sta 3,s
pla
sta 3,s
lda #-1 default DST setting = -1 (unknown)
cpy lasttime determine DST setting, if we can
bne lb1
cpx lasttime+2
bne lb1
lda lastDST
lb1 plb
ph4 #gmlocaltime_tm push address of struct tm to use
pha push tm_isdst value
phx push time_t value to convert
phy
pea 0 no time zone offset
pea 0
jsl ~gmlocaltime use common gmtime/localtime code
rtl
end
****************************************************************
*
* ~gmlocaltime - common code for gmtime and localtime
*
* Inputs:
* tz_offset - offset of local time from desired time zone
* t - time_t value (# of seconds since 13 Nov 1969)
* isdst - value for tm_isdst flag
* tm - pointer to struct tm for result
*
* Outputs:
* returns a pointer to a time record
*
****************************************************************
*
localtime start
gmtime entry
~gmlocaltime private
using TimeCommon
csubroutine (4:t),0
csubroutine (4:tz_offset,4:t,2:isdst,4:tm),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 month
stz hour
stz minute
stz second
lda tz_offset
sta second
lda tz_offset+2
sta second+2
lb1 inc year
jsr factor
jsr factor_second32
lda count+4
bne lb1b
lda count+2
cmp t+2
bne lb1a
lda count
cmp t
lb1a ble lb1
dec year
lb1b dec year
lb2 inc month find the month
jsr factor
jsr factor_second32
lda count+4
bmi lb2
bne lb2b
lda count+2
cmp t+2
bne lb2a
lda count
cmp t
lb2a ble lb2
dec month
jsr factor recompute the factor
lb2b dec month
jsr factor_second32 recompute the factor
lda year set the year
sta tm_year
ldy #tm_year
sta [tm],y
lda month set the month
dec A
sta tm_mon
ldy #tm_mon
sta [tm],y
ph4 <t save original t value
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
ldy #tm_sec
sta [tm],y
move4 t,t1 find the number of minutes
div4 t,#60
mul4 t,#60,t2
sub4 t1,t2
lda t1
sta tm_min
ldy #tm_min
sta [tm],y
move4 t,t1 find the number of hours
div4 t,#24
mul4 t,#24,t2
sub4 t1,t2
lda t1
sta tm_hour
ldy #tm_hour
sta [tm],y
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
ldy #tm_mday
sta [tm],y
pl4 t restore original t value
stz month compute the days since the start of the
jsr factor_second32 year (in desired time zone)
sub4 t,count,count
div4 count,#60*60*24
ldy #tm_yday set the day of year
lda count
sta [tm],y
lb3 cmpl t,#7*3000*60*60*24 compute the day of week
blt lb3a
sub4 t,#7*3000*60*60*24
bra lb3
lb3a add4 t,#4*60*60*24
sec (adjust for time zone)
lda t
sbc tz_offset
sta t
lda t+2
sbc tz_offset+2
sta t+2
div4 t,#60*60*24
mod4 t,#7
lda t set the day of week
ldy #tm_wday
sta [tm],y
lda isdst set the DST flag
ldy #tm_isdst
sta [tm],y
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
creturn 4:tm
end
****************************************************************
@ -402,7 +676,7 @@ tm_isdst ds 2 daylight savings? 1 = yes, 0 = no
* Outputs:
* tmptr->wday - day of week
* tmptr->yday - day of year
* returns the ime in seconds since 1 Jan 1970
* returns the ime in seconds since 13 Nov 1969
*
****************************************************************
*
@ -416,16 +690,12 @@ temp2 equ 5 temp variable
phk
plb
lla temp,-1 assume we can't do it
ldy #10 error if year < 70
ldy #tm_year set time parameters
lda [tmptr],Y
sta year
cmp #70
jlt lb1
dey set the other time parameters
dey
dey
lda [tmptr],Y
inc A
sta month
dey
dey
@ -441,24 +711,22 @@ temp2 equ 5 temp variable
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
jsr factor compute seconds since 13 Nov 1969
lda count+4 if time is unrepresentable
ora count+6
beq lb0
lda #-1 return -1
sta temp
sta temp+2
brl lb1
lb0 move4 count,temp save the value for later return
ph4 <tmptr recompute struct tm values
ldy #tm_isdst
lda [tmptr],y
pha
ph4 <temp
ph4 #0
jsl ~gmlocaltime
lb1 plb
creturn 4:temp
end
@ -494,20 +762,16 @@ time start
and #$00FF
inc A
sta day
lda 5,S set the month
and #$FF00
xba
inc A
lda 6,S set the month
and #$00FF
sta month
lda 3,S set the year
and #$FF00
xba
lda 4,S set the year
and #$00FF
sta year
lda 3,S set the hour
and #$00FF
sta hour
lda 1,S set the minute
xba
lda 2,S set the minute
and #$00FF
sta minute
pla set the second
@ -517,7 +781,13 @@ time start
pla
pla
jsr factor convert the seconds
lda tptr if tptr <> nil then
lda count+4 if time is unrepresentable
ora count+6
beq lb0
lda #-1 set return value to -1
sta count
sta count+2
lb0 lda tptr if tptr <> nil then
ora tptr+2
beq lb1
ldy #2 place the result there
@ -544,6 +814,70 @@ lb1 lda count
creturn 4:tptr
end
****************************************************************
*
* int timespec_get(struct timespec *ts, int base);
*
* Inputs:
* ts - pointer to structure for result
* base - requested time base
*
* Outputs:
* *tptr - the requested time (if successful)
* returns base if successful, or 0 otherwise
*
****************************************************************
*
timespec_get start
using TimeCommon
tz_offset equ 1 time zone offset from UTC
current_time equ 5 current time
TIME_UTC equ 1 UTC time base
tv_sec equ 0 struct timespec members
tv_nsec equ 4
csubroutine (4:ts,2:base),8
lda base
cmp #TIME_UTC
bne err
ph4 #0 get current time (in count)
jsl time
sta current_time
stx current_time+2
and current_time+2 if time is not available
inc a
beq err report error
jsr ~get_tz_offset get time zone offset
sta tz_offset
stx tz_offset+2
sec adjust for time zone & store result
lda current_time
sbc tz_offset
sta [ts]
lda current_time+2
sbc tz_offset+2
ldy #tv_sec+2
sta [ts],y
ldy #tv_nsec ts->tv_nsec = 0
lda #0
sta [ts],y
iny
iny
sta [ts],y
bra ret
err stz base unsupported base: return 0
ret creturn 2:base
end
****************************************************************
*
* size_t strftime(
@ -978,12 +1312,53 @@ Y_skip inx
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
;we print the numeric offset for both, or nothing if time zone is not available
fmt_z anop
fmt_Z lda >__useTimeTool if not using Time Tool
beq z_ret write nothing
pea 0 push pointer to string buffer
tdc
clc
adc #numstr
pha
pha make space for TZ preferences record
pha
pea 1 get one record element only (TZ offset)
tsc get time zone preference
inc a
pea 0
pha
_tiGetTimePrefs
pla
bcc z_dst
z_bail pla bail out in case of error
pla
pla
pla
z_ret rts
z_dst ldy #tm_isdst adjust for DST (+1 hour) if needed
lda [timeptr],y
bmi z_bail bail out if DST is unknown
beq z_fmtstr
; clc
pla
adc #60*60
tay
pla
adc #0
pha
phy
z_fmtstr pea 0 no DST mangling
_tiOffset2TimeZoneString get TZ offset string
bcs z_ret
ldx #1
z_loop lda numstr,x print the digits
jsr writech
inx
cpx #5+1
blt z_loop
rts
fmt_invalid rts

View File

@ -477,11 +477,6 @@
~&SYSCNT ~RESTM
MEND
MACRO
&LAB JLT &BP
&LAB BGE *+5
BRL &BP
MEND
MACRO
&LAB LLA &AD1,&AD2
&LAB ANOP
LCLA &L
@ -621,3 +616,54 @@
&LAB LDX #$260B
JSL $E10000
MEND
MACRO
&lab _tiStatus
&lab ldx #$0638
jsl $E10000
MEND
MACRO
&lab _tiGetTimePrefs
&lab ldx #$0938
jsl $E10000
MEND
MACRO
&lab _tiOffset2TimeZoneString
&lab ldx #$1138
jsl $E10000
MEND
MACRO
&lab _LongMul
&lab ldx #$0C0B
jsl $E10000
MEND
macro
&l negate8 &n1
&l ~setm
sec
ldy #0
tya
sbc &n1
sta &n1
tya
sbc &n1+2
sta &n1+2
tya
sbc &n1+4
sta &n1+4
tya
sbc &n1+6
sta &n1+6
~restm
mend
macro
&l cmpl &n1,&n2
lclb &yistwo
&l ~setm
~lda.h &n1
~op.h cmp,&n2
bne ~a&SYSCNT
~lda &n1
~op cmp,&n2
~a&SYSCNT anop
~restm
mend

View File

@ -23,7 +23,7 @@ Dummy start (dummy root segment)
*
****************************************************************
*
CVars start
~CVars start
errno entry library error number
ds 2
@ -35,4 +35,6 @@ __cleanup entry function to clean up files at exit
_toolErr entry last error in a tool call (C)
~TOOLERROR entry last error in a tool call (Pascal)
ds 2
__useTimeTool entry use Time Tool in <time.h> functions?
ds 2
end