]> git.sur5r.net Git - cc65/blobdiff - libsrc/atari/settime.s
Atari: clock_gettime() and clock_settime() implementations
[cc65] / libsrc / atari / settime.s
index 698aa2a29bc14fa638ac322dea9b05b629a9f0aa..7d6fff2c01ab3e3535d69e06a3b614e95e117e34 100644 (file)
@@ -1,8 +1,99 @@
 ;
-; int clock_settime (clockid_t clk_id, const struct timespec *tp);
+; Oliver Schmidt, 15.08.2018
+; Christian Groessler, 25.09.2018
 ;
-        .include "errno.inc"
-        .export _clock_settime
+; int __fastcall__ clock_settime (clockid_t clk_id, const struct timespec *tp);
+;
+
+        .import         __dos_type
+        .import         incsp1, return0
+        .import         sdxtry
+
+        .include        "time.inc"
+        .include        "zeropage.inc"
+        .include        "errno.inc"
+        .include        "atari.inc"
+
 _clock_settime:
-        lda     #ENOSYS
-        jmp     __directerrno
+
+; cleanup stack
+
+        jsr     incsp1          ; preserves AX
+
+; only supported on SpartaDOS-X >= 4.40
+
+        ldy     #SPARTADOS
+        cpy     __dos_type
+        bne     enosys
+        ldy     SDX_VERSION
+        cpy     #$44
+        bcc     enosys
+
+; create tm from tp (tv_sec) input parameter
+
+        .assert timespec::tv_sec = 0, error
+        jsr     _localtime
+        sta     ptr1
+        stx     ptr1+1
+
+; set date
+
+        ldy     #tm::tm_mday
+        lda     (ptr1),y        ; get day of month
+        sta     SDX_DATE        ; set day of month
+
+        ldy     #tm::tm_mon
+        lda     (ptr1),y        ; get month (0-based)
+        tax
+        inx                     ; move [0..11] to [1..12]
+        stx     SDX_DATE+1
+
+        ldy     #tm::tm_year
+        lda     (ptr1),y        ; get year (0 = year 1900)
+        cmp     #100
+        bcc     :+
+        sbc     #100
+:       sta     SDX_DATE+2
+
+        ldy     #tm::tm_hour
+        lda     (ptr1),y        ; get hour
+        sta     SDX_TIME
+
+        ldy     #tm::tm_min
+        lda     (ptr1),y        ; get minutes
+        sta     SDX_TIME+1
+
+        ldy     #tm::tm_sec
+        lda     (ptr1),y        ; get seconds
+        sta     SDX_TIME+2
+
+; set new time/date (SD-X call)
+; SpartaDOS-X User's Guide (4.48) states at page 145:
+; "In the I_GETTD and I_SETTD procedures a set Carry-Flag means that the clock driver is
+; busy at the moment. You should call the routine again."
+; It goes on to mention that one should provide an upper limit on the number of calls,
+; in order not to "hang". We are doing this here...
+
+        lda     #0              ; init loop count (256)
+        sta     sdxtry
+
+try_set:lda     #SDX_CLK_DEV    ; CLK device
+        sta     SDX_DEVICE
+        ldy     #SDX_KD_SETTD   ; SETTD function
+        jsr     SDX_KERNEL      ; do the call
+        bcc     done
+
+        dec     sdxtry
+        bne     try_set
+
+        lda     #EBUSY
+        bne     drcter          ; jump always
+
+; return success
+
+done:   jmp     return0
+
+; load errno code
+
+enosys: lda     #ENOSYS
+drcter: jmp     __directerrno