diff --git a/config/rel_slices.yml b/config/rel_slices.yml index ef4b798d..eab88d2d 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -121,6 +121,9 @@ m_rcp.c: .bss: [0x8129F2E8, 0x8129F2F0] m_room_type/mRmTp_FtrItemNo2FtrIdx.c: .text: [0x803E7878, 0x803E78BC] +m_string.c: + .text: [0x803EED30, 0x803EF290] + .bss: [0x8129F320, 0x8129F400] #m_time.c: # unlinked until function callers that reorder local static variables are implemented. # .text: [0x803F33DC, 0x803F3E58] # .rodata: [0x806433B0, 0x806433D8] diff --git a/include/m_choice.h b/include/m_choice.h index daea5eea..a70f0ab0 100644 --- a/include/m_choice.h +++ b/include/m_choice.h @@ -2,6 +2,7 @@ #define M_CHOICE_H #include "types.h" +#include "m_lib.h" #ifdef __cplusplus extern "C" { diff --git a/include/m_string.h b/include/m_string.h index 3011cd9c..2bf48e25 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -8,11 +8,27 @@ extern "C" { #endif +#define mString_MAX_STR 0x7FF + +#define mString_AM 0x001 +#define mString_PM 0x002 +#define mString_WEEKDAY_START 0x009 +#define mString_DAY_START 0x64E +#define mString_MONTH_START 0x66D #define mString_ARTICLE_START 0x737 -extern void mString_Load_StringFromRom(u8* buf, size_t buf_size, u32 str_no); -extern int mString_Load_MonthStringFromRom(u8* buf, lbRTC_month_t month); -extern int mString_Load_DayStringFromRom(u8* buf, lbRTC_day_t day); + +extern void mString_aram_init(); +extern void mString_Load_StringFromRom(u8* dst, int dst_len, int str_no); +extern int mString_Load_YearStringFromRom(u8* dst, lbRTC_year_t year); +extern int mString_Load_MonthStringFromRom(u8* dst, lbRTC_month_t month); +extern int mString_Load_WeekStringFromRom(u8* dst, lbRTC_weekday_t weekday); +extern int mString_Load_DayStringFromRom(u8* dst, lbRTC_day_t day); +extern int mString_Load_HourStringFromRom(u8* dst, lbRTC_hour_t hour); +extern int mString_Load_HourStringFromRom2(u8* dst, lbRTC_hour_t hour); +extern int mString_Load_MinStringFromRom(u8* dst, lbRTC_min_t min); +extern int mString_Load_SecStringFromRom(u8* dst, lbRTC_sec_t sec); +extern int mString_Load_NumberStringAddUnitFromRom(u8* dst, u16 num, int str_no); #define mString_Load_ArticleFromRom(buf, buf_size, art) mString_Load_StringFromRom(buf, buf_size, mString_ARTICLE_START + art) diff --git a/rel/m_string.c b/rel/m_string.c new file mode 100644 index 00000000..1cc512fa --- /dev/null +++ b/rel/m_string.c @@ -0,0 +1,177 @@ +#include "m_string.h" + +#include "m_msg.h" +#include "libjsys/jsyswrapper.h" +#include "m_lib.h" +#include "m_font.h" +#include "m_mail.h" + +static u8 buff[MAIL_BODY_LEN - 1] ATTRIBUTE_ALIGN(32); // TODO: proper bss ordering +static u32 String_rom_start; +static u32 String_table_rom_start; + +extern void mString_aram_init() { + String_table_rom_start = JW_GetAramAddress(RESOURCE_STRING_TABLE); + String_rom_start = JW_GetAramAddress(RESOURCE_STRING); +} + +static void mString_Get_StringDataAddressAndSize(int string_no, u32* string_addr, u32* string_size) { + mMsg_Get_BodyParam(String_table_rom_start, String_rom_start, string_no, string_addr, string_size); +} + +extern void mString_Load_StringFromRom(u8* dst, int dst_len, int str_no) { + //static u8 buff[MAIL_BODY_LEN - 1] ATTRIBUTE_ALIGN(32); // TODO: proper bss ordering + + u32 string_data_addr; + u32 string_size; + + if (str_no >= 0 && str_no < mString_MAX_STR) { + mString_Get_StringDataAddressAndSize(str_no, &string_data_addr, &string_size); + + if (string_size == 0) { + mem_clear(dst, dst_len, CHAR_SPACE); + } + else if (string_data_addr != 0) { + u32 base_addr = ALIGN_PREV(string_data_addr, 32); + u32 ofs = string_data_addr - base_addr; + u32 dma_size = ALIGN_NEXT(ofs + string_size, 32); + int i; + u8* s_src; + int copy_size; + u8* s_dst; + + _JW_GetResourceAram(base_addr, buff, dma_size); + if (dst_len < (int)string_size) { + string_size = dst_len; + } + + s_src = buff + ofs; + s_dst = dst; + copy_size = string_size; + for (i = 0; i < copy_size; i++) { + *s_dst++ = *s_src++; + } + + for (i; i < dst_len; i++) { + *s_dst++ = CHAR_SPACE; + } + } + } +} + +extern int mString_Load_YearStringFromRom(u8* dst, lbRTC_year_t year) { + if (year < lbRTC_YEAR_MIN || year > lbRTC_YEAR_MAX) { + year = GAME_YEAR_MIN; + } + + return mFont_UnintToString(dst, 6, year, 6, TRUE, FALSE, FALSE); +} + +extern int mString_Load_MonthStringFromRom(u8* dst, lbRTC_month_t month) { + if (month < lbRTC_JANUARY || month > lbRTC_DECEMBER) { + month = lbRTC_JANUARY; + } + + mString_Load_StringFromRom(dst, 9, mString_MONTH_START + month - 1); + return mMsg_Get_Length_String(dst, 9); +} + +extern int mString_Load_WeekStringFromRom(u8* dst, lbRTC_weekday_t weekday) { + if (weekday > lbRTC_SATURDAY) { + weekday = lbRTC_SUNDAY; + } + + mString_Load_StringFromRom(dst, 9, mString_WEEKDAY_START + weekday); + return mMsg_Get_Length_String(dst, 9); +} + +extern int mString_Load_DayStringFromRom(u8* dst, lbRTC_day_t day) { + if (day < 1 || day > 31) { + day = 1; + } + + mString_Load_StringFromRom(dst, 4, mString_DAY_START + day - 1); + return mMsg_Get_Length_String(dst, 4); +} + +extern int mString_Load_HourStringFromRom(u8* dst, lbRTC_hour_t hour) { + int hour_num_len; + int clamped_hour; + int specifier; + + if (hour > 23) { + hour = 0; + } + + clamped_hour = hour; + switch (clamped_hour) { + case 0: + clamped_hour = 12; + break; + case 12: + clamped_hour = 12; + break; + + default: + clamped_hour %= 12; + break; + } + + specifier = hour < 12 ? mString_AM : mString_PM; + hour_num_len = mFont_UnintToString(dst, 15, clamped_hour, 15, TRUE, FALSE, FALSE); + dst[hour_num_len] = CHAR_SPACE; + hour_num_len++; + + /* Load AM/PM string */ + mString_Load_StringFromRom(dst + hour_num_len, 15 - hour_num_len, specifier); + return mMsg_Get_Length_String(dst, 15); +} + +extern int mString_Load_HourStringFromRom2(u8* dst, lbRTC_hour_t hour) { + int clamped_hour; + + if (hour > 23) { + hour = 0; + } + + clamped_hour = hour; + switch (clamped_hour) { + case 0: + case 12: + clamped_hour = 12; + break; + + default: + clamped_hour %= 12; + break; + } + + return mFont_UnintToString(dst, 15, clamped_hour, 2, TRUE, FALSE, FALSE); +} + +extern int mString_Load_MinStringFromRom(u8* dst, lbRTC_min_t min) { + if (min > 59) { + min = 0; + } + + return mFont_UnintToString(dst, 4, min, 2, TRUE, TRUE, TRUE); +} + +extern int mString_Load_SecStringFromRom(u8* dst, lbRTC_sec_t sec) { + if (sec > 59) { + sec = 0; + } + + return mFont_UnintToString(dst, 5, sec, 2, TRUE, TRUE, TRUE); +} + +extern int mString_Load_NumberStringAddUnitFromRom(u8* dst, u16 num, int str_no) { + int num_len = mFont_UnintToString(dst, mMsg_FREE_STRING_LEN, num, mMsg_FREE_STRING_LEN, TRUE, FALSE, TRUE); + u8* n_dst = dst + num_len; + dst[num_len] = CHAR_SPACE; + num_len++; + + /* Add the unit */ + mString_Load_StringFromRom(dst + num_len, mMsg_FREE_STRING_LEN - num_len, str_no); + return mMsg_Get_Length_String(dst, mMsg_FREE_STRING_LEN); +}