diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 1dc5a17e..84f81a81 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -9,6 +9,9 @@ m_debug_hayakawa.c: .text: [0x803965E4, 0x803973E8] .rodata: [0x80641D50, 0x80641D90] .data: [0x80651328, 0x80651358] +m_eappli.c: + .text: [0x8039A5E0, 0x8039A960] + .bss: [0x81295150, 0x81295550] m_fbdemo.c: .text: [0x803A0350, 0x803A0ABC] .rodata: [0x80641F40, 0x80641F60] diff --git a/include/libjsys/jsyswrapper.h b/include/libjsys/jsyswrapper.h index 692a487e..b29d2a01 100644 --- a/include/libjsys/jsyswrapper.h +++ b/include/libjsys/jsyswrapper.h @@ -9,12 +9,18 @@ extern "C" { #endif +enum resource_index { + /* TODO: finish */ + RESOURCE_MY_ORIGINAL = 27, +}; + extern void JW_Init(); extern void JW_Init2(); extern void* JW_Alloc(size_t size, int align); extern void JW_Free(void* ptr); extern s32 JW_Resize(void* ptr, size_t new_size); extern size_t JW_GetMemBlockSize(void* ptr); +extern size_t JW_GetResSizeFileNo(int file_no); extern void JW_BeginFrame(); extern void JW_EndFrame(); extern void JW_JUTReport(int x, int y, int show_count, const char* fmt, ...); diff --git a/include/m_eappli.h b/include/m_eappli.h new file mode 100644 index 00000000..740a44e2 --- /dev/null +++ b/include/m_eappli.h @@ -0,0 +1,16 @@ +#ifndef M_EAPPLI_H +#define M_EAPPLI_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_malloc.h b/include/m_malloc.h index 5ee359d0..5c7acfb9 100644 --- a/include/m_malloc.h +++ b/include/m_malloc.h @@ -10,15 +10,15 @@ extern "C" { extern Arena zelda_arena; -extern void zelda_malloc_align(u32,u32); -extern void zelda_malloc(u32); -extern void zelda_malloc_r(u32); +extern void* zelda_malloc_align(size_t,u32); +extern void* zelda_malloc(size_t); +extern void* zelda_malloc_r(size_t); extern void zelda_free(void*); extern void zelda_GetFreeArena(size_t* max, size_t* free, size_t* alloc); -extern u32 zelda_GetTotalFreeSize(void); -extern u32 zelda_GetMemBlockSize(void*); -extern void zelda_InitArena(void*, u32); -extern void zelda_AddBlockArena(void*, u32); +extern size_t zelda_GetTotalFreeSize(void); +extern size_t zelda_GetMemBlockSize(void*); +extern void zelda_InitArena(void*, size_t); +extern void zelda_AddBlockArena(void*, size_t); extern void zelda_CleanupArena(void); extern int zelda_MallocIsInitalized(); diff --git a/include/m_private.h b/include/m_private.h index 90ce0670..39e64418 100644 --- a/include/m_private.h +++ b/include/m_private.h @@ -28,6 +28,9 @@ enum { mPr_PLAYER_NUM }; +#define mPr_ECARD_NUM 367 +#define mPr_ECARD_LETTER_NUM ((mPr_ECARD_NUM + 7) / 8) // 46 + #define mPr_POCKETS_SLOT_COUNT 15 #define mPr_INVENTORY_MAIL_COUNT 10 #define mPr_DELIVERY_QUEST_NUM mPr_POCKETS_SLOT_COUNT @@ -95,7 +98,7 @@ typedef struct player_sunburn_s { /* sizeof(mPr_carde_data_c) == 0x32 */ typedef struct player_ecard_data_s { /* 0x00 */ lbRTC_ymd_t letter_send_date; /* date the latest eCard letter was sent */ - /* 0x04 */ u8 card_letters_sent[46]; /* bitfield keeping track of which eCard letters have been sent to the player [0, 366] */ + /* 0x04 */ u8 card_letters_sent[mPr_ECARD_LETTER_NUM]; /* bitfield keeping track of which eCard letters have been sent to the player [0, 366] */ } mPr_carde_data_c; typedef struct private_s { diff --git a/rel/m_eappli.c b/rel/m_eappli.c new file mode 100644 index 00000000..700af571 --- /dev/null +++ b/rel/m_eappli.c @@ -0,0 +1,136 @@ +#include "m_eappli.h" + +#include "m_common_data.h" +#include "m_private.h" +#include "lb_rtc.h" +#include "m_scene.h" +#include "m_malloc.h" +#include "libjsys/jsyswrapper.h" + +#define CRC32_POLYNOMIAL 0xEDB88320 +#define CRC32_START_VALUE 0xAA478422 + +static u32 crcTable[256]; + +static u32 getcrc(u8* data, size_t len) { + u32 crc = CRC32_START_VALUE; + size_t i = 0; + + do { + crc = (crc >> 8) ^ crcTable[(crc ^ data[i]) & 0xFF]; + i++; + } while (i != len); + + return crc; +} + +static void crcgen() { + int bit; + u32 c; + int i; + + for (i = 0; i < 256; i++) { + int j; + c = i; + + for (j = 0; j < 8; j++) { + bit = c & 1; + c >>= 1; + if (bit) { + c ^= CRC32_POLYNOMIAL; + } + } + + crcTable[i] = c; + } +} + +static u32 mEA_GetCRC(u8* data, size_t len) { + crcgen(); + return getcrc(data, len); +} + +static void putLEWord(u8* dst, u32 word) { + dst[0] = word >> 0; + dst[1] = word >> 8; + dst[2] = word >> 16; + dst[3] = word >> 24; +} + +extern void mEA_InitLetterCardE() { + mPr_carde_data_c* carde_data = &Common_Get(now_private)->ecard_letter_data; + lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time); + + /* only reset if current date isn't same as last scan date */ + u16 year = carde_data->letter_send_date.year; + u8 month = carde_data->letter_send_date.month; + u8 day = carde_data->letter_send_date.day; + if (rtc_time->year != year || rtc_time->month != month || rtc_time->day != day) { + int i; + for (i = 0; i < mPr_ECARD_LETTER_NUM; i++) { + carde_data->card_letters_sent[i] = 0; + } + } +} + +extern int mEA_CheckLetterCardE(int card_no) { + mPr_carde_data_c* card_data = &Common_Get(now_private)->ecard_letter_data; + int index = card_no < mPr_ECARD_NUM ? card_no : mPr_ECARD_NUM - 1; + + if (index == mPr_ECARD_NUM - 1) { + return ((card_data->card_letters_sent[index >> 3] >> (index & 7)) & 1) ? 2 : 0; + } + + return (card_data->card_letters_sent[index >> 3] >> (index & 7)) & 1; +} + +extern void mEA_SetLetterCardE(int card_no) { + mPr_carde_data_c* card_data = &Common_Get(now_private)->ecard_letter_data; + int index = card_no < mPr_ECARD_NUM ? card_no : mPr_ECARD_NUM - 1; + lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time); + + card_data->card_letters_sent[index >> 3] |= 1 << (index & 7); + card_data->letter_send_date.year = rtc_time->year; + card_data->letter_send_date.month = rtc_time->month; + card_data->letter_send_date.day = rtc_time->day; +} + +#define MY_ORIGINAL_DESIGN_DATA_SIZE (4*(32/2)*32) +extern void mEA_GetCardDLProgram() { + if (Save_Get(scene_no) != SCENE_TITLE_DEMO && Common_Get(carde_program_p) == NULL) { + u32 crc; + + Common_Set(carde_program_size, JW_GetResSizeFileNo(RESOURCE_MY_ORIGINAL) - MY_ORIGINAL_DESIGN_DATA_SIZE); // my_original.bin also contains texture data + Common_Set(carde_program_p, (u8*)zelda_malloc_align(Common_Get(carde_program_size), 32)); + _JW_GetResourceAram(JW_GetAramAddress(RESOURCE_MY_ORIGINAL) + MY_ORIGINAL_DESIGN_DATA_SIZE, Common_Get(carde_program_p), Common_Get(carde_program_size)); + + /* write compressed program size to vpk payload */ + putLEWord( + Common_Get(carde_program_p) + 0x2C, + Common_Get(carde_program_size) - 0x34 + ); + + /* write vpk CRC32 */ + crc = mEA_GetCRC(Common_Get(carde_program_p) + sizeof(u32), Common_Get(carde_program_size) - sizeof(u32)); + putLEWord( + Common_Get(carde_program_p), + crc + ); + } +} + +extern void mEA_CleanCardDLProgram() { + if (Common_Get(carde_program_p) != NULL) { + zelda_free(Common_Get(carde_program_p)); + Common_Set(carde_program_p, NULL); + Common_Set(carde_program_size, 0); + } +} + +extern u8* mEA_dl_carde_program_p() { + return Common_Get(carde_program_p); +} + +extern size_t mEA_dl_carde_program_size() { + return Common_Get(carde_program_size); +} diff --git a/rel/m_malloc.c b/rel/m_malloc.c index 7cd3d4f3..4899d6ab 100644 --- a/rel/m_malloc.c +++ b/rel/m_malloc.c @@ -2,45 +2,45 @@ Arena zelda_arena; -void zelda_malloc_align(u32 size, u32 align){ - __osMallocAlign(&zelda_arena, size, align); +extern void* zelda_malloc_align(size_t size, u32 align) { + return __osMallocAlign(&zelda_arena, size, align); } -void zelda_malloc(u32 size){ - __osMalloc(&zelda_arena,size); +extern void* zelda_malloc(size_t size) { + return __osMalloc(&zelda_arena,size); } -void zelda_malloc_r(u32 size){ - __osMallocR(&zelda_arena, size); +extern void* zelda_malloc_r(size_t size) { + return __osMallocR(&zelda_arena, size); } -void zelda_free(void* ptr){ - __osFree(&zelda_arena, ptr); +extern void zelda_free(void* ptr) { + __osFree(&zelda_arena, ptr); } -void zelda_GetFreeArena(size_t* max, size_t* free, size_t* alloc){ - __osGetFreeArena(&zelda_arena,max,free,alloc); +extern void zelda_GetFreeArena(size_t* max, size_t* free, size_t* alloc) { + __osGetFreeArena(&zelda_arena,max,free,alloc); } -size_t zelda_GetTotalFreeSize(void){ - return __osGetTotalFreeSize(&zelda_arena); +extern size_t zelda_GetTotalFreeSize(void) { + return __osGetTotalFreeSize(&zelda_arena); } -size_t zelda_GetMemBlockSize(void* ptr){ - return __osGetMemBlockSize(&zelda_arena, ptr); +extern size_t zelda_GetMemBlockSize(void* ptr) { + return __osGetMemBlockSize(&zelda_arena, ptr); } -void zelda_InitArena(void* start, u32 size){ - __osMallocInit(&zelda_arena, start, size); +extern void zelda_InitArena(void* start, size_t size) { + __osMallocInit(&zelda_arena, start, size); } -void zelda_AddBlockArena(void* start, u32 size){ - __osMallocAddBlock(&zelda_arena,start, size); +extern void zelda_AddBlockArena(void* start, size_t size) { + __osMallocAddBlock(&zelda_arena,start, size); } -void zelda_CleanupArena() { - __osMallocCleanup(&zelda_arena); +extern void zelda_CleanupArena() { + __osMallocCleanup(&zelda_arena); } extern int zelda_MallocIsInitalized() { - return __osMallocIsInitalized(&zelda_arena); + return __osMallocIsInitalized(&zelda_arena); }