From 782b00b34c72ba783f89438dcae6e1d809e930f0 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Sun, 2 Apr 2023 06:32:00 -0400 Subject: [PATCH] Implement & link in lb_reki.c --- config/rel_slices.yml | 4 + include/lb_reki.h | 12 +- rel/lb_reki.c | 409 ++++++++++++++++++++++++++++++++++++++++++ rel/lb_rtc.c | 43 ++++- 4 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 rel/lb_reki.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 079a97e4..9f8f3737 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -22,6 +22,10 @@ lb_rtc.c: .rodata: [0x806436F8, 0x806437A0] .data: [0x8065ECD0, 0x8065ECD8] .bss: [0x812F4CB0, 0x812F4CC0] +lb_reki.c: + .text: [0x8040752C, 0x80407AE8] + .rodata: [0x806437A0, 0x806437C0] + .data: [0x8065ECD8, 0x8065F110] zurumode.c: .text: [0x8040eb38, 0x8040f008] .bss: [0x812f9670, 0x812f9680] diff --git a/include/lb_reki.h b/include/lb_reki.h index f090e00c..3090d91c 100644 --- a/include/lb_reki.h +++ b/include/lb_reki.h @@ -10,7 +10,17 @@ extern "C" { #define lbRk_YEAR_MIN GAME_YEAR_MIN #define lbRk_YEAR_MAX GAME_YEAR_MAX -#define lbRk_YEAR_COUNT ((lbRk_YEAR_MAX - lbRk_YEAR_MIN) + 1) +#define lbRk_YEAR_NUM ((lbRk_YEAR_MAX - lbRk_YEAR_MIN) + 1) + +#define lbRk_KYUU_MONTH_START 1 +#define lbRk_KYUU_MONTH_END 12 +#define lbRk_KYUU_LEAP_MONTH 13 + +#define lbRk_HARVEST_MOON_YEAR_MIN 2002 +#define lbRk_HARVEST_MOON_YEAR_MAX 2030 +#define lbRk_HARVEST_MOON_YEAR_NUM ((lbRk_HARVEST_MOON_YEAR_MAX - lbRk_HARVEST_MOON_YEAR_MIN) + 1) + +#define lbRk_KYUU_DAY_START 1 #ifdef __cplusplus } diff --git a/rel/lb_reki.c b/rel/lb_reki.c new file mode 100644 index 00000000..c99f2e57 --- /dev/null +++ b/rel/lb_reki.c @@ -0,0 +1,409 @@ +/* + * lb_reki.c + * + * This source file contains a set of functions used to convert dates + * between the Gregorian calendar (seiyo reki, 西洋暦) and the old Japanese + * lunisolar calendar (kyuu reki, 旧暦). The functions also handle special + * date calculations related to the Japanese calendar, such as Vernal Equinox Day, + * Autumnal Equinox Day, and Harvest Moon Day. + * + * Functions in this file include: + * + * - lbRk_SeirekiDays: Calculate the number of days in a given month of a given year in the Gregorian calendar. + * - lbRk_ToSeiyoMonthAndDay: Convert a kyuureki year and month to the corresponding Gregorian month and day. + * - lbRk_KyuurekiLeapDays: Calculate the number of leap days in a given kyuureki year. + * - lbRk_IsKyuurekiLeapYear: Check if a kyuureki year is a leap year. + * - lbRk_IsLeapMonth: Check if a kyuureki month is a leap month. + * - lbRk_IsLeapOnNextMonth: Check if a leap month occurs after the given kyuureki month. + * - lbRk_KyuurekiDays: Calculate the number of days in a given kyuureki month of a given year. + * - lbRk_ToSeiyouReki: Convert a kyuureki date to the corresponding Gregorian date. + * - lbRk_ToKyuuReki: Convert a Gregorian date to the corresponding kyuureki date. + * - lbRk_VernalEquinoxDay: Calculate the Vernal Equinox Day for a given year. + * - lbRk_AutumnalEquinoxDay: Calculate the Autumnal Equinox Day for a given year. + * - lbRk_HarvestMoonDay: Calculate the Harvest Moon Day for a given year. + */ + +#include "lb_reki.h" + +#include "types.h" + +typedef struct lbRk_date_s { + lbRTC_month_t month; + lbRTC_day_t day; +} lbRk_date_t; + +/** + * @brief Gets the number of days in a given month of the Seiyo Reki (Gregorian calendar). + * + * @param year Year value. + * @param month Month value. + * @return The number of days in the specified month of the given year. + */ +static int lbRk_SeirekiDays(int year, int month) { + // Table containing the number of days for each month in standard and leap years in the Seiyo Reki (Gregorian calendar) + static lbRTC_day_t t_seiyo_days_tbl[][lbRTC_MONTHS_MAX + 1] = { + {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Standard days for each month */ + {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} /* Days for each month during leap year */ + }; + + int idx = 0; + if ((year % 4) == 0) { + idx = 1; + } + + return t_seiyo_days_tbl[idx][month]; +} + +/* Convesion table which gets the beginning of a Kyuu Reki (Japanese lunisolar) + date in Seiyo Reki (Gregoran calendar) date. */ +static lbRk_date_t l_lbRk_ConvertTable[lbRk_YEAR_NUM][lbRk_KYUU_LEAP_MONTH] = { + /* 2000 */ {{2, 5}, {3, 6}, {4, 5}, {5, 4}, {6, 2}, {7, 2}, {7, 31}, {8, 29}, { 9, 28}, {10, 27}, {11, 26}, {12, 26}, { 0, 0}}, + /* 2001 */ {{1, 24}, {2, 23}, {3, 25}, {4, 24}, {6, 21}, {7, 21}, {8, 19}, {9, 17}, {10, 17}, {11, 15}, {12, 15}, { 1, 13}, { 5, 23}}, + /* 2002 */ {{2, 12}, {3, 14}, {4, 13}, {5, 12}, {6, 11}, {7, 10}, {8, 9}, {9, 7}, {10, 6}, {11, 5}, {12, 4}, { 1, 3}, { 0, 0}}, + /* 2003 */ {{2, 1}, {3, 3}, {4, 2}, {5, 1}, {5, 31}, {6, 30}, {7, 29}, {8, 28}, { 9, 26}, {10, 25}, {11, 24}, {12, 23}, { 0, 0}}, + /* 2004 */ {{1, 22}, {2, 20}, {4, 19}, {5, 19}, {6, 18}, {7, 17}, {8, 16}, {9, 14}, {10, 14}, {11, 12}, {12, 12}, { 1, 10}, { 3, 21}}, + /* 2005 */ {{2, 9}, {3, 10}, {4, 9}, {5, 8}, {6, 7}, {7, 6}, {8, 5}, {9, 4}, {10, 3}, {11, 2}, {12, 2}, {12, 31}, { 0, 0}}, + /* 2006 */ {{1, 29}, {2, 28}, {3, 29}, {4, 28}, {5, 27}, {6, 26}, {7, 25}, {9, 22}, {10, 22}, {11, 21}, {12, 20}, { 1, 19}, { 8, 24}}, + /* 2007 */ {{2, 18}, {3, 19}, {4, 17}, {5, 17}, {6, 15}, {7, 14}, {8, 13}, {9, 11}, {10, 11}, {11, 10}, {12, 10}, { 1, 8}, { 0, 0}}, + /* 2008 */ {{2, 7}, {3, 8}, {4, 6}, {5, 5}, {6, 4}, {7, 3}, {8, 1}, {8, 31}, { 9, 29}, {10, 29}, {11, 28}, {12, 27}, { 0, 0}}, + /* 2009 */ {{1, 26}, {2, 25}, {3, 27}, {4, 25}, {5, 24}, {7, 22}, {8, 20}, {9, 19}, {10, 18}, {11, 17}, {12, 16}, { 1, 15}, { 6, 23}}, + /* 2010 */ {{2, 14}, {3, 16}, {4, 14}, {5, 14}, {6, 12}, {7, 12}, {8, 10}, {9, 8}, {10, 8}, {11, 6}, {12, 6}, { 1, 4}, { 0, 0}}, + /* 2011 */ {{2, 3}, {3, 5}, {4, 3}, {5, 3}, {6, 2}, {7, 1}, {7, 31}, {8, 29}, { 9, 27}, {10, 27}, {11, 25}, {12, 25}, { 0, 0}}, + /* 2012 */ {{1, 23}, {2, 22}, {3, 22}, {5, 21}, {6, 20}, {7, 19}, {8, 18}, {9, 16}, {10, 15}, {11, 14}, {12, 13}, { 1, 12}, { 4, 21}}, + /* 2013 */ {{2, 10}, {3, 12}, {4, 10}, {5, 10}, {6, 9}, {7, 8}, {8, 7}, {9, 5}, {10, 5}, {11, 3}, {12, 3}, { 1, 1}, { 0, 0}}, + /* 2014 */ {{1, 31}, {3, 1}, {3, 31}, {4, 29}, {5, 29}, {6, 27}, {7, 27}, {8, 25}, { 9, 24}, {11, 22}, {12, 22}, { 1, 20}, {10, 24}}, + /* 2015 */ {{2, 19}, {3, 20}, {4, 19}, {5, 18}, {6, 16}, {7, 16}, {8, 14}, {9, 13}, {10, 13}, {11, 12}, {12, 11}, { 1, 10}, { 0, 0}}, + /* 2016 */ {{2, 8}, {3, 9}, {4, 7}, {5, 7}, {6, 5}, {7, 4}, {8, 3}, {9, 1}, {10, 1}, {10, 31}, {11, 29}, {12, 29}, { 0, 0}}, + /* 2017 */ {{1, 28}, {2, 26}, {3, 28}, {4, 26}, {5, 26}, {7, 23}, {8, 22}, {9, 20}, {10, 20}, {11, 18}, {12, 18}, { 1, 17}, { 6, 24}}, + /* 2018 */ {{2, 16}, {3, 17}, {4, 16}, {5, 15}, {6, 14}, {7, 13}, {8, 11}, {9, 10}, {10, 9}, {11, 8}, {12, 27}, { 1, 6}, { 0, 0}}, + /* 2019 */ {{2, 5}, {3, 7}, {4, 5}, {5, 5}, {6, 3}, {7, 3}, {8, 1}, {8, 30}, { 9, 29}, {10, 28}, {11, 27}, {12, 26}, { 0, 0}}, + /* 2020 */ {{1, 25}, {2, 24}, {3, 24}, {4, 23}, {6, 21}, {7, 21}, {8, 19}, {9, 17}, {10, 17}, {11, 15}, {12, 15}, { 1, 13}, { 5, 23}}, + /* 2021 */ {{2, 12}, {3, 13}, {4, 12}, {5, 12}, {6, 10}, {7, 10}, {8, 8}, {9, 7}, {10, 6}, {11, 5}, {12, 4}, { 1, 3}, { 0, 0}}, + /* 2022 */ {{2, 1}, {3, 3}, {4, 1}, {5, 1}, {5, 30}, {6, 29}, {7, 29}, {8, 27}, { 9, 26}, {10, 25}, {11, 24}, {12, 23}, { 0, 0}}, + /* 2023 */ {{1, 22}, {2, 20}, {3, 22}, {5, 20}, {6, 18}, {7, 18}, {8, 16}, {9, 15}, {10, 15}, {11, 13}, {12, 13}, { 1, 11}, { 4, 20}}, + /* 2024 */ {{2, 10}, {3, 10}, {4, 9}, {5, 8}, {6, 6}, {7, 6}, {8, 4}, {9, 3}, {10, 3}, {11, 1}, {12, 1}, {12, 31}, { 0, 0}}, + /* 2025 */ {{1, 29}, {2, 28}, {3, 29}, {4, 28}, {5, 27}, {6, 25}, {8, 23}, {9, 22}, {10, 21}, {11, 20}, {12, 20}, { 1, 19}, { 7, 25}}, + /* 2026 */ {{2, 17}, {3, 19}, {4, 17}, {5, 17}, {6, 15}, {7, 14}, {8, 13}, {9, 11}, {10, 11}, {11, 9}, {12, 9}, { 1, 8}, { 0, 0}}, + /* 2027 */ {{2, 7}, {3, 8}, {4, 7}, {5, 6}, {6, 5}, {7, 4}, {8, 2}, {9, 1}, { 9, 30}, {10, 29}, {11, 28}, {12, 28}, { 0, 0}}, + /* 2028 */ {{1, 27}, {2, 25}, {3, 26}, {4, 25}, {5, 24}, {7, 22}, {8, 20}, {9, 19}, {10, 18}, {11, 16}, {12, 16}, { 1, 15}, { 6, 23}}, + /* 2029 */ {{2, 13}, {3, 15}, {4, 14}, {5, 13}, {6, 12}, {7, 12}, {8, 10}, {9, 8}, {10, 8}, {11, 6}, {12, 5}, { 1, 4}, { 0, 0}}, + /* 2030 */ {{2, 3}, {3, 4}, {4, 3}, {5, 2}, {6, 1}, {7, 1}, {7, 30}, {8, 29}, { 9, 27}, {10, 27}, {11, 25}, {12, 25}, { 0, 0}}, + /* 2031 */ {{1, 23}, {2, 22}, {3, 23}, {4, 22}, {6, 20}, {7, 19}, {8, 18}, {9, 17}, {10, 16}, {11, 15}, {12, 14}, { 1, 13}, { 5, 21}}, + /* 2032 */ {{2, 11}, {3, 12}, {4, 10}, {5, 9}, {6, 8}, {7, 7}, {8, 6}, {9, 5}, {10, 4}, {11, 3}, {12, 3}, { 1, 1}, { 0, 0}}, +}; + +// The number of Japanese lunisolar leap days for a given lunisolar year. +static int l_lbRk_leapdays[lbRk_YEAR_NUM] = { + 0, 29, 0, 0, + 29, 0, 29, 0, + 0, 29, 0, 0, + 30, 0, 29, 0, + 0, 29, 0, 0, + 29, 0, 0, 30, + 0, 29, 0, 0, + 29, 0, 0, 30, + 0 +}; + +/** + * @brief Get a pointer to the lbRk_date_t structure for the Seiyo Reki (Gregorian calendar) month and day. + * + * @param year Year value. + * @param month Month value. + * @return Pointer to the lbRk_date_t structure representing the Seiyo Reki (Gregorian calendar) month and day. + */ +static lbRk_date_t* lbRk_ToSeiyoMonthAndDay(int year, int month) { + return &l_lbRk_ConvertTable[year - lbRk_YEAR_MIN][month - 1]; +} + +/** + * @brief Get the number of leap days for a given Kyuu Reki (Japanese lunisolar) year. + * + * @param year Year value. + * @return The number of leap days for the specified Kyuu Reki (Japanese lunisolar) year. + */ +static int lbRk_KyuurekiLeapDays(int year) { + return l_lbRk_leapdays[year - lbRk_YEAR_MIN]; +} + +/** + * @brief Check if a given Kyuu Reki (Japanese lunisolar) year is a leap year. + * + * @param year Year value. + * @return Non-zero (TRUE) if the given Kyuu Reki (Japanese lunisolar) year is a leap year, zero (FALSE) otherwise. + */ +static int lbRk_IsKyuurekiLeapYear(int year) { + return l_lbRk_leapdays[year - lbRk_YEAR_MIN] != 0; +} + +/** + * @brief Check if a given month is a leap month in the Kyuu Reki (Japanese lunisolar) calendar. + * + * @param month Month value. + * @return Non-zero (TRUE) if the given month is a leap month, zero (FALSE) otherwise. + */ +static int lbRk_IsLeapMonth(int month) { + return month == lbRk_KYUU_LEAP_MONTH; +} + +/** + * @brief Check if the leap month occurs next month in the Kyuu Reki (Japanese lunisolar) calendar. + * + * @param year Year value. + * @param month Month value. + * @return Non-zero (TRUE) if the leap month occurs next month, zero (FALSE) otherwise. + */ +static int lbRk_IsLeapOnNextMonth(int year, int month) { + lbRk_date_t* seiyo_monthday = lbRk_ToSeiyoMonthAndDay(year, month); + lbRk_date_t* convert_monthday = &l_lbRk_ConvertTable[year - lbRk_YEAR_MIN][lbRTC_MONTHS_MAX]; + + // Check if the leap month occurs next month by comparing the month values + // in the Seiyo Reki (Gregorian calendar) + return !(convert_monthday->month != seiyo_monthday->month + 1); +} + +/** + * Calculates the number of days in a given month of the Japanese lunisolar calendar (kyuureki) + * for a given year and month. + * + * @param year The year in the kyuureki calendar. + * @param month The month in the kyuureki calendar. + * @return The number of days in the specified month of the Japanese lunisolar calendar. + */ +static int lbRk_KyuurekiDays(int year, int month) { + int days; + lbRk_date_t* next_seiyo_month_day; + + // Get the corresponding Seiyo (Gregorian) month and day for the given kyuureki year and month + lbRk_date_t* seiyo_monthday = lbRk_ToSeiyoMonthAndDay(year, month); + + // If the month is a leap month, return the number of leap days for the year + if (lbRk_IsLeapMonth(month) == TRUE) { + return lbRk_KyuurekiLeapDays(year); + } + + // Determine the Seiyo (Gregorian) month and day for the next month in the kyuureki calendar + if (month != lbRTC_MONTHS_MAX) { + if (lbRk_IsLeapOnNextMonth(year, month) == TRUE) { + next_seiyo_month_day = lbRk_ToSeiyoMonthAndDay(year, lbRk_KYUU_LEAP_MONTH); + } else { + next_seiyo_month_day = lbRk_ToSeiyoMonthAndDay(year, month + 1); + } + } else { + next_seiyo_month_day = lbRk_ToSeiyoMonthAndDay(year + 1, 1); + } + + // Calculate the number of days in the Kyuu (Japanese lunisolar) month + if (seiyo_monthday->month == next_seiyo_month_day->month) { + days = next_seiyo_month_day->day - seiyo_monthday->day; + } else { + if (seiyo_monthday->month < month) { + year += 1; + } + + days = lbRk_SeirekiDays(year, seiyo_monthday->month) - seiyo_monthday->day; + if ((next_seiyo_month_day->month - seiyo_monthday->month) >= 2) { + days += lbRk_SeirekiDays(year, seiyo_monthday->month + 1); + } + days += next_seiyo_month_day->day; + } + return days; +} + + +/** + * Converts a date from the Japanese lunisolar calendar (kyuureki) to the Gregorian calendar (seiyo reki). + * + * @param seiyo_ymd The output date in the Gregorian calendar. + * @param kyuu_ymd The input date in the kyuureki calendar. + * @return TRUE if the conversion is successful, FALSE if the input date is invalid. + */ +extern int lbRk_ToSeiyouReki(lbRTC_ymd_t* seiyo_ymd, const lbRTC_ymd_t* kyuu_ymd) { + int seireki_days; + int year; + int month; + int day; + lbRk_date_t* seiyo_monthday; + + // Validate the input kyuureki date + if ((kyuu_ymd->year < 1) || (kyuu_ymd->year > lbRk_YEAR_MAX)) { + return FALSE; + } + if (kyuu_ymd->month > lbRk_KYUU_LEAP_MONTH) { + return FALSE; + } + if (lbRk_IsKyuurekiLeapYear(kyuu_ymd->year) == FALSE && kyuu_ymd->month >= lbRk_KYUU_LEAP_MONTH) { + return FALSE; + } + if (lbRk_KyuurekiDays(kyuu_ymd->year, kyuu_ymd->month) < kyuu_ymd->day) { + return FALSE; + } + + // Get the corresponding Seiyo (Gregorian) month and day for the given kyuureki year and month + seiyo_monthday = lbRk_ToSeiyoMonthAndDay(kyuu_ymd->year, kyuu_ymd->month); + month = seiyo_monthday->month; + year = kyuu_ymd->year; + day = seiyo_monthday->day + kyuu_ymd->day - 1; + + // Adjust the Gregorian date based on the number of days in the Seiyo (Gregorian) month + seireki_days = lbRk_SeirekiDays(year, month); + if (day > seireki_days) { + month++; + day -= seireki_days; + if (month > lbRTC_MONTHS_MAX) { + month = 1; + } + } + + // Adjust the Gregorian year if necessary + if (month < kyuu_ymd->month && kyuu_ymd->month != lbRk_KYUU_LEAP_MONTH) { + year++; + } + + // Set the output Gregorian date + seiyo_ymd->year = year; + seiyo_ymd->month = month; + seiyo_ymd->day = day; + + return TRUE; +} + +/** + * Converts a date from the Gregorian calendar (seiyo reki) to the Japanese lunisolar calendar (kyuureki). + * + * @param kyuu_ymd The output date in the kyuureki calendar. + * @param seiyo_ymd The input date in the Gregorian calendar. + * @return TRUE if the conversion is successful, FALSE if the input date is invalid. + */ +extern int lbRk_ToKyuuReki(lbRTC_ymd_t* kyuu_ymd, const lbRTC_ymd_t* seiyo_ymd) { + lbRTC_ymd_t kyuu_date = (lbRTC_ymd_t){lbRk_YEAR_MIN, lbRk_KYUU_MONTH_START, lbRk_KYUU_DAY_START}; + lbRTC_ymd_t seyio_date; + + while (TRUE) { + // Attempt to convert the current kyuureki date to Gregorian date + if (lbRk_ToSeiyouReki(&seyio_date, &kyuu_date) == FALSE) { + return FALSE; + } + + // Check if the converted Gregorian date matches the input seiyo_ymd + if (seyio_date.day == seiyo_ymd->day && seyio_date.month == seiyo_ymd->month && seyio_date.year == seiyo_ymd->year) { + kyuu_ymd->day = kyuu_date.day; + kyuu_ymd->month = kyuu_date.month; + kyuu_ymd->year = kyuu_date.year; + return TRUE; + } + + // Increment the kyuureki day + kyuu_date.day++; + + // If the kyuureki day exceeds the number of days in the current kyuureki month, reset the day and increment the month + if (lbRk_KyuurekiDays(kyuu_date.year, kyuu_date.month) < kyuu_date.day) { + kyuu_date.day = 1; + kyuu_date.month++; + + // Handle leap years and month transitions + if (lbRk_IsKyuurekiLeapYear(kyuu_date.year) == FALSE) { + if (kyuu_date.month > lbRk_KYUU_MONTH_END) { + kyuu_date.month = 1; + kyuu_date.year++; + if (kyuu_date.year > lbRk_YEAR_MAX) { + return FALSE; + } + } + } else if (kyuu_date.month > lbRk_KYUU_LEAP_MONTH) { + kyuu_date.month = 1; + kyuu_date.year++; + if (kyuu_date.year > lbRk_YEAR_MAX) { + return FALSE; + } + } + } + } +} + +/** + * Calculates the Vernal Equinox Day for the given year. + * + * @param year The input year. + * @return The Vernal Equinox Day for the given year. + * @remarks This function calculates the Vernal Equinox Day from 1980 thru 2099. + * It was sourced from '新こよみ便利帳 天文現象・暦計算のすべて' + * by Kouseisha Kouseikaku (ISBN4-7699-0700-1). + */ +extern int lbRk_VernalEquinoxDay(int year) { + year -= 1980; + return (int)(20.8431f + (0.242194f * (f32)year)) - (year / 4); +} + +/** + * Calculates the Autumnal Equinox Day for the given year. + * + * @param year The input year. + * @return The Autumnal Equinox Day for the given year. + * @remarks This function calculates the Autmnal Equinox Day from 1980 thru 2099. + * It was sourced from '新こよみ便利帳 天文現象・暦計算のすべて' + * by Kouseisha Kouseikaku (ISBN4-7699-0700-1). + */ +extern int lbRk_AutumnalEquinoxDay(int year) { + year -= 1980; + return (int)(23.2488f + (0.242194f * (f32)year)) - (year / 4); +} + +/** + * Calculates the Harvest Moon Day for the given year. + * + * @param harvest_moon_day The output Harvest Moon Day in the Gregorian calendar. + * @param year The input year. + */ +extern void lbRk_HarvestMoonDay(lbRTC_ymd_t* harvest_moon_day, int year) { + /* Array of precomputed Seiyo Reki (Gregorian calendar) + Havest Moon Day dates. */ + static lbRk_date_t ev_day[lbRk_HARVEST_MOON_YEAR_NUM] = { + /* 2002 */ {9, 21}, + /* 2003 */ {9, 10}, + /* 2004 */ {9, 28}, + /* 2005 */ {9, 18}, + /* 2006 */ {10, 7}, + /* 2007 */ {9, 26}, + /* 2008 */ {9, 15}, + /* 2009 */ {10, 4}, + /* 2010 */ {9, 23}, + /* 2011 */ {9, 12}, + /* 2012 */ {9, 30}, + /* 2013 */ {9, 19}, + /* 2014 */ {9, 9}, + /* 2015 */ {9, 28}, + /* 2016 */ {9, 16}, + /* 2017 */ {10, 5}, + /* 2018 */ {9, 25}, + /* 2019 */ {9, 14}, + /* 2020 */ {10, 1}, + /* 2021 */ {9, 20}, + /* 2022 */ {9, 10}, + /* 2023 */ {9, 29}, + /* 2024 */ {9, 18}, + /* 2025 */ {10, 7}, + /* 2026 */ {9, 26}, + /* 2027 */ {9, 15}, + /* 2028 */ {10, 3}, + /* 2029 */ {9, 22}, + /* 2030 */ {9, 11} + }; + + lbRTC_ymd_t kyuu_ymd; + + // If the year is within the pre-calculated range, use the stored values + if ((year >= lbRk_HARVEST_MOON_YEAR_MIN) && (year < lbRk_HARVEST_MOON_YEAR_MAX + 1)) { + year -= lbRk_HARVEST_MOON_YEAR_MIN; + harvest_moon_day->month = ev_day[year].month; + harvest_moon_day->day = ev_day[year].day; + return; + } + + // If the year is outside the pre-calculated range, calculate the Harvest Moon Day + // using the Japanese lunisolar date of 8th month 15th day. + kyuu_ymd.year = year; + kyuu_ymd.month = 8; + kyuu_ymd.day = 15; + lbRk_ToSeiyouReki(harvest_moon_day, &kyuu_ymd); +} diff --git a/rel/lb_rtc.c b/rel/lb_rtc.c index ff54ec49..6631ac0e 100644 --- a/rel/lb_rtc.c +++ b/rel/lb_rtc.c @@ -1,6 +1,47 @@ +/* + * lb_rtc.c + * + * This source file contains a set of functions for handling + * date and time calculations and conversions in the context of the lbRTC system. + * The lbRTC system is designed to manage timekeeping and manipulation of date-times. + * + * Functions in this file include (but are not limited to): + * + * - lbRTC_HardTime: Retrieve the hardware time. + * - lbRTC_IsAbnormal: Check if the lbRTC system is in an abnormal state. + * - lbRTC_Sampling: Perform a sampling operation on the lbRTC system. + * - lbRTC_SetTime: Set the current time in the lbRTC system. + * - lbRTC_GetTime: Get the current time from the lbRTC system. + * - lbRTC_GetDaysByMonth: Get the number of days in a given month and year. + * - lbRTC_IsEqualDate: Check if two dates are equal. + * - lbRTC_IsEqualTime: Check if two times are equal. + * - lbRTC_IsOverTime: Check if one time is greater than another time. + * - lbRTC_IsOverRTC: Check if the given time is greater than the current time. + * - lbRTC_IntervalTime: Calculate the interval between two times. + * - lbRTC_GetIntervalDays: Calculate the interval between two times in days. + * - lbRTC_GetIntervalDays2: Calculate the interval between two times (date only) in days. + * - lbRTC_Add_YY: Add years to a time. + * - lbRTC_Add_MM: Add months to a time. + * - lbRTC_Add_DD: Add days to a time. + * - lbRTC_Add_hh: Add hours to a time. + * - lbRTC_Add_mm: Add minutes to a time. + * - lbRTC_Add_ss: Add seconds to a time. + * - lbRTC_Add_Date: Add a time duration to a time. + * - lbRTC_Sub_YY: Subtract years from a time. + * - lbRTC_Sub_MM: Subtract months from a time. + * - lbRTC_Sub_DD: Subtract days from a time. + * - lbRTC_Sub_hh: Subtract hours from a time. + * - lbRTC_Sub_mm: Subtract minutes from a time. + * - lbRTC_Sub_ss: Subtract seconds from a time. + * - lbRTC_Week: Calculate the day of the week for a given date. + * - lbRTC_TimeCopy: Copy one time structure to another. + * - lbRTC_IsValidTime: Check if the given time is valid. + * - lbRTC_time_c_save_data_check: Check if the given time from save data is valid. + * - lbRTC_Weekly_day: Calculate the day of the week for a given date, considering weeks and the desired day of the week. + */ + #include "lb_rtc.h" -#include "lb_reki.h" #include "m_common_data.h" #include "m_lib.h" #include "types.h"