mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-27 10:29:32 +00:00
225 lines
6.5 KiB
Plaintext
225 lines
6.5 KiB
Plaintext
|
;EASE$$$ READ ONLY COPY of file <20>sexydate.a<>
|
|||
|
; 1.1 CCH 11/10/1988 Fixed Header.
|
|||
|
; 1.0 CCH 11/ 9/1988 Adding to EASE.
|
|||
|
; OLD REVISIONS BELOW
|
|||
|
; 1.0 BBM 2/11/88 Adding file for the first time into EASE<53>
|
|||
|
; END EASE MODIFICATION HISTORY
|
|||
|
; File SexyDate.TEXT
|
|||
|
;
|
|||
|
; Routines to convert between number of seconds elapsed since 1904 Jan 1 00:00:00 am
|
|||
|
; and date: year / month / day / hour / min / sec / (day of week).
|
|||
|
; Written by Jerome T. Coonen 2 July 1983
|
|||
|
;
|
|||
|
; Seconds: unsigned 32-bit integer passed in D0.
|
|||
|
;
|
|||
|
; Date: array of 7 16-bit integers pointed to by A0.
|
|||
|
; 0: year -- 1904, 1905, ...
|
|||
|
; 1: month -- 1, 2, ..., 12
|
|||
|
; 2: day -- 1, 2, ..., 31
|
|||
|
; 3: hour -- 0, 1, ..., 24
|
|||
|
; 4: minute -- 0, 1, ..., 59
|
|||
|
; 5: second -- 0, 1, ..., 59
|
|||
|
; 6: weekday -- 1, 2, ..., 7 corresponding to Sun, Mon, ..., Sat
|
|||
|
;
|
|||
|
|
|||
|
BLANKS ON
|
|||
|
STRING ASIS
|
|||
|
|
|||
|
SEXYDATE PROC EXPORT
|
|||
|
EXPORT SECS2DATE, DATE2SECS
|
|||
|
|
|||
|
SECS2DATE
|
|||
|
MOVEM.L D0-D4/A0,-(SP) ; SAVE WORKING REGISTERS
|
|||
|
|
|||
|
;
|
|||
|
; Have number of seconds N 1904 in D0. Compute
|
|||
|
; DN = number of days elapsed = N div 86400 where 86400 = 24 * 60 * 60
|
|||
|
; HMS = number of seconds in last day = N mod 86400.
|
|||
|
; Since 86400 > 2^31-1 cannot use 68000 DIVU directly. Instead, divide halved number
|
|||
|
; of seconds by 43200. To get HMS, must double computed mod (with 43200) and add in the
|
|||
|
; low order bit of the input N.
|
|||
|
;
|
|||
|
MOVEQ #0,D1 ; INIT HMS
|
|||
|
LSR.L #1,D0 ; N DIV 2, WITH ODD BIT TO X
|
|||
|
ROXR.L #1,D1 ; GET X BIT IN HI SLOT, FOR LATER ROTATE
|
|||
|
DIVU #43200,D0
|
|||
|
SWAP D0 ; GET MOD 43200 IN D0.W
|
|||
|
MOVE.W D0,D1 ; HALF THE MOD IN D1.W
|
|||
|
ROL.L #1,D1
|
|||
|
CLR.W D0 ; WANT LONG DN
|
|||
|
SWAP D0 ; DN
|
|||
|
|
|||
|
;
|
|||
|
; YearsGone = (DN * 4) div 1461 where 1461 is 4*365+1
|
|||
|
; Formula depends on leap year being the first of the four.
|
|||
|
;
|
|||
|
MOVE.L D0,D2 ; COPY DN
|
|||
|
ASL.L #2,D2 ; DN * 4
|
|||
|
DIVU #1461,D2 ; YEARSGONE = (DN * 4) DIV 1461
|
|||
|
ADDI.W #1904,D2 ; YEAR
|
|||
|
MOVE.W D2,(A0)+
|
|||
|
|
|||
|
;
|
|||
|
; Need number of days in Jan+Feb just below. So take YEAR mod 3 before clearing year.
|
|||
|
;
|
|||
|
MOVEQ #59,D3 ; ASSUME NOT LEAP YEAR
|
|||
|
ANDI.W #3,D2 ; YEAR MOD 3
|
|||
|
BNE.S SDNOTLEAP
|
|||
|
ADDQ.W #1,D3
|
|||
|
SDNOTLEAP
|
|||
|
CLR.W D2 ; LEAVE 4 * DOY = DAY OF YEAR IN HI WORD
|
|||
|
SWAP D2
|
|||
|
LSR.W #2,D2 ; D0Y
|
|||
|
|
|||
|
;
|
|||
|
; Computing Month/Day from DOY is an exercise in interpolation. As a function of DOY,
|
|||
|
; MONTH is a step function. Because of the leap year glitch, convenient to restart
|
|||
|
; function at March.
|
|||
|
;
|
|||
|
; DOY MONTH
|
|||
|
;-------------------------------------------------------------------
|
|||
|
; 0-30 1 -- January
|
|||
|
; 31-58/59 2 -- February (depends on whether leap year)
|
|||
|
;
|
|||
|
; 0-30 3 -- March
|
|||
|
; 31-60 4 -- April
|
|||
|
; 61-91 5 -- May
|
|||
|
; 92-121 6 -- June
|
|||
|
; 122-152 7 -- July
|
|||
|
; 153-183 8 -- August
|
|||
|
; 184-213 9 -- September
|
|||
|
; 214-244 10 -- October
|
|||
|
; 244-274 11 -- November
|
|||
|
; 275-305 12 -- December
|
|||
|
;
|
|||
|
; The linear interpolator is ((DOY * 128) + 71) div 3919.
|
|||
|
;
|
|||
|
MOVEQ #1,D4 ; MONTH OFFSET, 1 OR 3
|
|||
|
CMP.W D3,D2 ; 59/60 VERSUS DOY
|
|||
|
BLT.S SDJANORFEB ; LESS THAN MEANS JAN OR FEB
|
|||
|
ADDQ.W #2,D4 ; ADJUST MONTH OFFSET
|
|||
|
SUB.W D3,D2 ; START DOY AT MARCH
|
|||
|
SDJANORFEB
|
|||
|
LSL.L #7,D2 ; DOY * 128
|
|||
|
MOVEQ #71,D3
|
|||
|
ADD.L D3,D2 ; (DOY * 128) + 71
|
|||
|
DIVU #3919,D2 ; ((DOY * 128) + 71) DIV 3919
|
|||
|
ADD.W D4,D2 ; ADJUST MONTH 1..12
|
|||
|
SWAP D2 ; HAVE MONTH | DAY-1
|
|||
|
LSR.W #7,D2 ; DIVIDE BY 128 TO GET DAY OF MONTH
|
|||
|
ADDQ.W #1,D2 ; DAY 1..31
|
|||
|
MOVE.L D2,(A0)+
|
|||
|
|
|||
|
;
|
|||
|
; HOURS = HMS div 3600
|
|||
|
; MS = HMS mod 3600 = minutes/seconds
|
|||
|
; MINUTES = MS div 60
|
|||
|
; SECONDS = MS mod 60
|
|||
|
;
|
|||
|
DIVU #3600,D1 ; HMS DIV 3600
|
|||
|
MOVE.W D1,(A0)+ ; HOURS
|
|||
|
CLR.W D1
|
|||
|
SWAP D1 ; MS
|
|||
|
DIVU #60,D1 ; SECONDS | MINUTES
|
|||
|
SWAP D1
|
|||
|
MOVE.L D1,(A0)+ ; MINUTES | SECONDS
|
|||
|
|
|||
|
;
|
|||
|
; Finally get the day of week = ((DN + 5) mod 7) + 1
|
|||
|
; The 5 is added since 1 Jan 1904 was a Friday.
|
|||
|
;
|
|||
|
ADDQ.W #5,D0
|
|||
|
DIVU #7,D0
|
|||
|
SWAP D0
|
|||
|
ADDQ.W #1,D0
|
|||
|
MOVE.W D0,(A0)
|
|||
|
|
|||
|
;
|
|||
|
; Clean up stack and return.
|
|||
|
;
|
|||
|
MOVEM.L (SP)+,D0-D4/A0
|
|||
|
RTS
|
|||
|
|
|||
|
|
|||
|
;
|
|||
|
; Have year / month / day / hours / min / sec in a sequence of words pointed to by A0.
|
|||
|
; Deduce number of seconds since 1904, and return in D0.
|
|||
|
;
|
|||
|
; Since a date is no more than a representation of time in a bizarre mixed radix,
|
|||
|
; the computation reduces to:
|
|||
|
; DAYSGONE * 86400 + HOURS * 3600 + MINUTES * 60 + SECONDS
|
|||
|
; The hard part is deducing the DAYSGONE from the YEAR / MONTH / DAY.
|
|||
|
;
|
|||
|
DATE2SECS
|
|||
|
MOVEM.L D1-D4,-(SP) ; WORKING REGISTERS
|
|||
|
|
|||
|
;
|
|||
|
; Do the easy part with HOURS, MINUTES, and SECONDS.
|
|||
|
;
|
|||
|
MOVEQ #0,D0 ; INIT SECOND COUNT
|
|||
|
ADDQ.L #8,A0 ; POINT TO MINUTES/SECONDS
|
|||
|
MOVE.L (A0),D1 ; MINUTES | SECONDS
|
|||
|
MOVE.W D1,D0 ; SECONDS
|
|||
|
SWAP D1 ; MINUTES
|
|||
|
MOVE.W -(A0),D2 ; HOURS
|
|||
|
MOVEQ #60,D3
|
|||
|
MULU D3,D2 ; HOURS * 60
|
|||
|
ADD.W D1,D2 ; (HOURS * 60) + MINUTES
|
|||
|
MULU D3,D2 ; ((HOURS * 60) + MINUTES) * 60
|
|||
|
ADD.L D2,D0
|
|||
|
|
|||
|
;
|
|||
|
; Compute DAYSGONE in D1.
|
|||
|
;
|
|||
|
MOVE.W -(A0),D1 ; DAYS
|
|||
|
SUBQ.W #1,D1
|
|||
|
MOVE.W -(A0),D2 ; MONTH
|
|||
|
MOVE.W -(A0),D3 ; YEAR, AND A0 IS BACK TO INPUT VALUE
|
|||
|
|
|||
|
MOVE.W D3,D4 ; COPY YEAR FOR LEAP TEST
|
|||
|
|
|||
|
;
|
|||
|
; To find number of days in elapsed years use ((YEARSGONE * 1461) + 3) div 4.
|
|||
|
; Formula depends on leap year being the first of a quartet.
|
|||
|
;
|
|||
|
SUBI.W #1904,D3 ; YEARSGONE
|
|||
|
MULU #1461,D3 ; YEARSGONE * 1461
|
|||
|
ADDQ.L #3,D3 ; (YEARSGONE * 1461) + 3
|
|||
|
LSR.L #2,D3 ; ((YEARSGONE * 1461) + 3) DIV 4
|
|||
|
ADD.W D3,D1 ; ACCUMULATE DAYSGONE
|
|||
|
|
|||
|
;
|
|||
|
; As above, the tough part is finding the number of days in the elapsed months.
|
|||
|
; The function to be interpolated is in a sense the inverse of the step function above.
|
|||
|
; The interpolating function is ((MONTHSGONE * 3917) + 52) div 128.
|
|||
|
;
|
|||
|
SUBQ.W #1,D2 ; MONTH-1 RANGES 0..11
|
|||
|
CMPI.W #1,D2 ; 2 OR MORE IS MARCH...
|
|||
|
BLE.S DSJANORFEB
|
|||
|
|
|||
|
SUBQ.W #2,D2 ; MONTH-3, RESTART INTERP AT MARCH
|
|||
|
MOVEQ #59,D3 ; DAYS IN JAN AND FEB
|
|||
|
ANDI.W #3,D4 ; CHECK FOR LEAP YEAR, MOD 3
|
|||
|
BNE.S DSNOTLEAP
|
|||
|
ADDQ.W #1,D3
|
|||
|
DSNOTLEAP
|
|||
|
ADD.W D3,D1 ; SOME MORE ELAPSED DAYS
|
|||
|
DSJANORFEB
|
|||
|
MULU #3917,D2 ; (MONTHSGONE * 3917)
|
|||
|
ADDI.W #52,D2 ; (MONTHSGONE * 3917) + 52
|
|||
|
LSR.W #7,D2 ; ((MONTHSGONE * 3917) + 52) DIV 128
|
|||
|
ADD.W D2,D1 ; MORE ELAPSED DAYS
|
|||
|
|
|||
|
;
|
|||
|
; Finally multiply the number of days elapsed by 24*60*60 = 86400 = 43200*2
|
|||
|
;
|
|||
|
MULU #43200,D1
|
|||
|
ADD.L D1,D1
|
|||
|
ADD.L D1,D0
|
|||
|
|
|||
|
MOVEM.L (SP)+,D1-D4
|
|||
|
RTS
|
|||
|
|
|||
|
END
|
|||
|
|