summaryrefslogtreecommitdiff
path: root/src/code/lbrtc/722AB0.c
blob: 919927103b94c2631587e64bc3de8d4ee1077fd0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "lbrtc.h"
#include "lb_rtc.h"
#include "PRinternal/siint.h"
#include "PRinternal/controller.h"

u16 total_days_internal[2][lbRTC_MONTHS_MAX + 1] = {
    // Standard year
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
    // Leap year (flawed leap year calculation)
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};

s32 func_800FEE10_jp(OSMesgQueue* mq, u8 blockType, u8* buf) {
    s32 ret;
    __OSContRTCRWFormat* ptr;
    __OSContRTCRWFormat format;

    __osSiGetAccess();
    func_800FEF9C_jp(blockType);
    __osContLastCmd = CONT_CMD_READ_RTC;

    ret = __osSiRawStartDma(OS_WRITE, &__osEepPifRam);
    osRecvMesg(mq, NULL, OS_MESG_BLOCK);

    ret = __osSiRawStartDma(OS_READ, &__osEepPifRam);
    osRecvMesg(mq, NULL, OS_MESG_BLOCK);

    ptr = (__OSContRTCRWFormat*)&__osEepPifRam.ramarray[1];

    format = *ptr;
    ret = format.rxsize & CHNL_ERR_MASK;

    if (ret == 0) {
        bcopy(&format.data, buf, 8);
        if (format.status & RTC_STATUS_BATTERY_FAILURE) {
            ret = RTC_ERR_BATTERY;
            //! @bug should have checked for RTC_STATUS_CRYSTAL_FAILURE
        } else if (format.status & RTC_STATUS_BATTERY_FAILURE) {
            ret = RTC_ERR_CRYSTAL;
        } else if (format.status & RTC_STATUS_STOPPED) {
            ret = RTC_STOPPED;
        }
    } else if (ret & CHNL_ERR_NORESP) {
        ret = 1;
    } else {
        ret = 4;
    }

    __osSiRelAccess();
    return ret;
}

void func_800FEF9C_jp(u8 blockType) {
    u8* ptr = (u8*)&__osEepPifRam.ramarray;
    s32 i;
    __OSContRTCRWFormat format;

    __osEepPifRam.pifstatus = CONT_CMD_EXE;

    format.txsize = CONT_CMD_READ_RTC_TX;
    format.rxsize = CONT_CMD_READ_RTC_RX;
    format.cmd = CONT_CMD_READ_RTC;
    format.blockType = blockType;

    for (i = 0; i < 4; i++) {
        *ptr++ = 0;
    }

    *(__OSContRTCRWFormat*)ptr = format;

    ptr += sizeof(__OSContRTCRWFormat);
    *ptr = CONT_CMD_END;
}

s32 lbrtc_GetIntervalMinutes(OSRTCTime* t0, OSRTCTime* t1) {
    u8 yearLeapPeriod = (t1->year - t0->year) / 4;
    /* Total 'leap years' (missing extra not divisible by 100, except when divisible by 400 rule) */

    u8 extraYears = (t1->year - t0->year) % 4;            /* Non-leap year remainder */
    u8 lessLeap = (t0->year % 4) == 0;                    /* Is the lesser year a leap year? */
    u8 overLeap = (t1->year % 4) == 0;                    /* Is the greater year a leap year? */
    u8 leapAdd = ((4 - (t0->year % 4)) % 4) < extraYears; /* Add leap day when leap day occurs during 'extra years' */

    s32 days;
    s32 hour;
    s32 min;
    if (t0->year > t1->year) {
        return 0;
    } else if (t0->year == t1->year) {
        if (t0->month > t1->month) {
            return 0;
        } else if (t0->month == t1->month) {
            if (t0->day > t1->day) {
                return 0;
            } else if (t0->day == t1->day) {
                if (t0->hour > t1->hour) {
                    return 0;
                } else if (t0->hour == t1->hour) {
                    if (t0->min > t1->min) {
                        return 0;
                    }
                }
            }
        }
    }

    days = yearLeapPeriod * 1461 + extraYears * 365 + leapAdd;
    days += t1->day - 1;
    days += total_days_internal[overLeap][t1->month - 1];
    days -= t0->day - 1;
    days -= total_days_internal[lessLeap][t0->month - 1];

    hour = days * 24;
    hour = (t1->hour + hour) - t0->hour;

    min = hour * 60;
    min = (t1->min + min) - t0->min;

    return min;
}