#include "global.h" #include "filesystem.h" #include "msgdata.h" #include "heap.h" #include "MI_memory.h" #include "string16.h" #pragma thumb on static void * LoadSingleElementFromNarc(NarcId narc_id, s32 file_id, u32 heap_id); static void FreeMsgDataRawData(void * data); static void ReadMsgData_ExistingTable_ExistingArray(struct MsgDataTable * table, u32 num, u16 * dest); static void ReadMsgData_NewNarc_ExistingArray(NarcId narc_id, u32 group, u32 num, u32 heap_id, u16 * dest); static void CopyEncryptedMessage16(u16 * dest, const u16 * src, struct MsgDataAlloc * param); static void ReadMsgData_ExistingTable_ExistingString(struct MsgDataTable * table, u32 num, struct String * dest); static struct String * ReadMsgData_ExistingTable_NewString(struct MsgDataTable * table, u32 num, u32 heap_id); static void ReadMsgData_ExistingNarc_ExistingString(NARC * narc, u32 group, u32 num, u32 heap_id, struct String * dest); static struct String * ReadMsgData_ExistingNarc_NewString(NARC * narc, u32 group, u32 num, u32 heap_id); static u16 GetMsgCount_ExistingTable(struct MsgDataTable * tbl); static u16 GetMsgCount_TableFromNarc(NarcId narc_id, s32 file_id); static void * LoadSingleElementFromNarc(NarcId narc_id, s32 file_id, u32 heap_id) { return AllocAndReadWholeNarcMemberByIdPair(narc_id, file_id, heap_id); } static void FreeMsgDataRawData(void * data) { FreeToHeap(data); } inline static void Decrypt1(struct MsgDataAlloc * arg0, u32 arg1, u32 seed) { seed = seed * 765 * (arg1 + 1) & 0xffff; seed |= seed << 16; arg0->offset ^= seed; arg0->length ^= seed; } inline static void Decrypt2(u16 * arg0, u32 count, u32 arg2) { u16 seed = (u16)((arg2 + 1) * 596947); while (count-- > 0) { *arg0 ^= seed; arg0++; seed += 18749; } } static void ReadMsgData_ExistingTable_ExistingArray(struct MsgDataTable * table, u32 num, u16 * dest) { struct MsgDataAlloc sp0; if (num < table->count) { sp0 = table->alloc[num]; Decrypt1(&sp0, num, table->key); CopyEncryptedMessage16(dest, (const u16 *)((u8 *)table + sp0.offset), &sp0); Decrypt2(dest, sp0.length, num); } else { GF_ASSERT(0); } } static void ReadMsgData_NewNarc_ExistingArray(NarcId narc_id, u32 group, u32 num, u32 heap_id, u16 * dest) { NARC * narc = NARC_ctor(narc_id, heap_id); u16 header[2]; struct MsgDataAlloc alloc; if (narc != NULL) { NARC_ReadFromMember(narc, group, 0, 4, header); NARC_ReadFromMember(narc, group, 8 * num + 4, 8, &alloc); Decrypt1(&alloc, num, header[1]); NARC_ReadFromMember(narc, group, alloc.offset, 2 * alloc.length, dest); Decrypt2(dest, alloc.length, num); NARC_dtor(narc); } } static void CopyEncryptedMessage16(u16 * dest, const u16 * src, struct MsgDataAlloc * param) { MI_CpuCopy16(src, dest, 2 * param->length); } static void ReadMsgData_ExistingTable_ExistingString(struct MsgDataTable * table, u32 num, struct String * dest) { struct MsgDataAlloc alloc; u16 * buf; if (num < table->count) { alloc = table->alloc[num]; Decrypt1(&alloc, num, table->key); buf = AllocFromHeapAtEnd(0, 2 * alloc.length); if (buf != NULL) { MI_CpuCopy16((char *)table + alloc.offset, buf, 2 * alloc.length); Decrypt2(buf, alloc.length, num); CopyU16ArrayToStringN(dest, buf, alloc.length); FreeToHeap(buf); } } else { GF_ASSERT(0); StringSetEmpty(dest); } } static struct String * ReadMsgData_ExistingTable_NewString(struct MsgDataTable * table, u32 num, u32 heap_id) { struct MsgDataAlloc alloc; u16 * buf; struct String * dest; if (num < table->count) { alloc = table->alloc[num]; Decrypt1(&alloc, num, table->key); buf = AllocFromHeapAtEnd(heap_id, 2 * alloc.length); if (buf != NULL) { MI_CpuCopy16((char *)table + alloc.offset, buf, 2 * alloc.length); Decrypt2(buf, alloc.length, num); dest = String_ctor(alloc.length, heap_id); if (dest != NULL) CopyU16ArrayToStringN(dest, buf, alloc.length); FreeToHeap(buf); return dest; } else { return NULL; } } else { GF_ASSERT(0); return String_ctor(4, heap_id); } } void ReadMsgData_NewNarc_ExistingString(NarcId narc_id, u32 group, u32 num, u32 heap_id, struct String * dest) { NARC * narc = NARC_ctor(narc_id, heap_id); if (narc != NULL) { ReadMsgData_ExistingNarc_ExistingString(narc, group, num, heap_id, dest); NARC_dtor(narc); } } static void ReadMsgData_ExistingNarc_ExistingString(NARC * narc, u32 group, u32 num, u32 heap_id, struct String * dest) { u16 * buf; u32 size; u16 sp10[2]; struct MsgDataAlloc alloc; NARC_ReadFromMember(narc, group, 0, 4, sp10); if (num < sp10[0]) { NARC_ReadFromMember(narc, group, 8 * num + 4, 8, &alloc); Decrypt1(&alloc, num, sp10[1]); size = alloc.length * 2; buf = AllocFromHeapAtEnd(heap_id, size); if (buf != NULL) { NARC_ReadFromMember(narc, group, alloc.offset, size, buf); Decrypt2(buf, alloc.length, num); CopyU16ArrayToStringN(dest, buf, alloc.length); FreeToHeap(buf); return; } } else { GF_ASSERT(0); StringSetEmpty(dest); } } struct String * ReadMsgData_NewNarc_NewString(NarcId narc_id, u32 group, u32 num, u32 heap_id) { NARC * narc = NARC_ctor(narc_id, heap_id); struct String * string; if (narc != NULL) { string = ReadMsgData_ExistingNarc_NewString(narc, group, num, heap_id); NARC_dtor(narc); } else { string = String_ctor(4, heap_id); } return string; } static struct String * ReadMsgData_ExistingNarc_NewString(NARC * narc, u32 group, u32 num, u32 heap_id) { struct String * dest; u16 * buf; u32 size; u16 sp10[2]; struct MsgDataAlloc alloc; NARC_ReadFromMember(narc, group, 0, 4, sp10); if (num < sp10[0]) { NARC_ReadFromMember(narc, group, 8 * num + 4, 8, &alloc); Decrypt1(&alloc, num, sp10[1]); dest = String_ctor(alloc.length, heap_id); if (dest != NULL) { size = alloc.length * 2; buf = AllocFromHeapAtEnd(heap_id, size); if (buf != NULL) { NARC_ReadFromMember(narc, group, alloc.offset, size, buf); Decrypt2(buf, alloc.length, num); CopyU16ArrayToStringN(dest, buf, alloc.length); FreeToHeap(buf); } } return dest; } else { GF_ASSERT(0); return String_ctor(4, heap_id); } } static u16 GetMsgCount_ExistingTable(struct MsgDataTable * tbl) { return tbl->count; } static u16 GetMsgCount_TableFromNarc(NarcId narc_id, s32 file_id) { u16 n[2]; ReadFromNarcMemberByIdPair(&n, narc_id, file_id, 0, 4); return n[0]; } struct MsgData * NewMsgDataFromNarc(u32 type, NarcId narc_id, s32 file_id, u32 heap_id) { struct MsgData * msgData = AllocFromHeapAtEnd(heap_id, sizeof(struct MsgData)); if (msgData != NULL) { if (type == 0) { msgData->data.raw = LoadSingleElementFromNarc(narc_id, file_id, heap_id); if (msgData->data.raw == NULL) { FreeToHeap(msgData); return NULL; } } else { msgData->data.narc = NARC_ctor(narc_id, heap_id); } msgData->type = (u16)type; msgData->narc_id = (u16)narc_id; msgData->file_id = (u16)file_id; msgData->heap_id = (u16)heap_id; } return msgData; } void DestroyMsgData(struct MsgData * msgData) { if (msgData != NULL) { switch (msgData->type) { case 0: FreeMsgDataRawData(msgData->data.raw); break; case 1: NARC_dtor(msgData->data.narc); break; } FreeToHeap(msgData); } } void ReadMsgDataIntoString(struct MsgData * msgData, u32 msg_no, struct String * dest) { switch (msgData->type) { case 0: ReadMsgData_ExistingTable_ExistingString(msgData->data.raw, msg_no, dest); break; case 1: ReadMsgData_ExistingNarc_ExistingString(msgData->data.narc, msgData->file_id, msg_no, msgData->heap_id, dest); break; } } struct String * NewString_ReadMsgData(struct MsgData * msgData, u32 msg_no) { switch (msgData->type) { case 0: return ReadMsgData_ExistingTable_NewString(msgData->data.raw, msg_no, msgData->heap_id); case 1: return ReadMsgData_ExistingNarc_NewString(msgData->data.narc, msgData->file_id, msg_no, msgData->heap_id); default: return NULL; } } u16 MsgDataGetCount(struct MsgData * msgData) { switch (msgData->type) { case 0: return GetMsgCount_ExistingTable(msgData->data.raw); case 1: return GetMsgCount_TableFromNarc((NarcId)msgData->narc_id, msgData->file_id); default: return 0; } } void ReadMsgDataIntoU16Array(struct MsgData * msgData, u32 msg_no, u16 * dest) { switch (msgData->type) { case 0: ReadMsgData_ExistingTable_ExistingArray(msgData->data.raw, msg_no, dest); break; case 1: ReadMsgData_NewNarc_ExistingArray((NarcId)msgData->narc_id, msgData->file_id, msg_no, msgData->heap_id, dest); break; } } void GetSpeciesNameIntoArray(u16 species, u32 heap_id, u16 * dest) { struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 362, heap_id); ReadMsgDataIntoU16Array(msgData, species, dest); DestroyMsgData(msgData); } struct String * ReadMsgData_ExpandPlaceholders(struct ScrStrBufs * a0, struct MsgData * msgData, u32 msgno, u32 a3) { struct String * ret = NULL; struct String * r4 = String_ctor(1024, 0); struct String * r5; if (r4 != NULL) { r5 = NewString_ReadMsgData(msgData, msgno); if (r5 != NULL) { StringExpandPlaceholders(a0, r4, r5); ret = StringDup(r4, a3); String_dtor(r5); } String_dtor(r4); } return ret; } struct String * GetMoveName(u32 move, u32 heapno) { struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 588, heapno); struct String * ret; if (msgData != NULL) { ret = String_ctor(16, heapno); if (ret != NULL) { ReadMsgDataIntoString(msgData, move, ret); } DestroyMsgData(msgData); return ret; } return NULL; } struct String * GetSpeciesName(u16 species, u32 heap_id) { struct String * ret; struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 362, heap_id); if (msgData != NULL) { ret = NewString_ReadMsgData(msgData, species); DestroyMsgData(msgData); return ret; } return NULL; }