summaryrefslogtreecommitdiff
path: root/arm9/src
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/src')
-rw-r--r--arm9/src/msgdata.c400
-rw-r--r--arm9/src/nutdata.c14
-rw-r--r--arm9/src/pokemon.c27
-rw-r--r--arm9/src/string_util.c4
-rw-r--r--arm9/src/unk_0201B8B8.c33
5 files changed, 456 insertions, 22 deletions
diff --git a/arm9/src/msgdata.c b/arm9/src/msgdata.c
new file mode 100644
index 00000000..ae33e0f5
--- /dev/null
+++ b/arm9/src/msgdata.c
@@ -0,0 +1,400 @@
+#include "global.h"
+#include "filesystem.h"
+#include "msgdata.h"
+#include "heap.h"
+#include "MI_memory.h"
+#include "string16.h"
+#include "proto.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);
+ FUN_02021E8C(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)
+ FUN_02021E8C(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);
+ FUN_02021E8C(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);
+ FUN_02021E8C(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(u32 * 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;
+}
diff --git a/arm9/src/nutdata.c b/arm9/src/nutdata.c
index 09542052..a8f916e2 100644
--- a/arm9/src/nutdata.c
+++ b/arm9/src/nutdata.c
@@ -1,7 +1,7 @@
#include "global.h"
#include "filesystem.h"
#include "itemtool.h"
-#include "msg_data.h"
+#include "msgdata.h"
#pragma thumb on
@@ -20,12 +20,12 @@ void CloseNutsDataNarc(NARC * narc)
NARC_dtor(narc);
}
-struct NutData * LoadNutDataSingle(u32 berry_idx, u32 heap_id)
+struct NutData * LoadNutDataSingle(s32 berry_idx, u32 heap_id)
{
return AllocAndReadWholeNarcMemberByIdPair(NARC_ITEMTOOL_ITEMDATA_NUTS_DATA, berry_idx, heap_id);
}
-struct NutData * LoadNutDataSingleByItemId(u32 item_id, u32 heap_id)
+struct NutData * LoadNutDataSingleByItemId(s32 item_id, u32 heap_id)
{
return LoadNutDataSingle(item_id - FIRST_BERRY_IDX, heap_id);
}
@@ -61,18 +61,18 @@ u32 GetNutAttr(struct NutData * nut, u32 attr)
}
}
-u16 * GetNutName(u32 berry_idx, u32 heap_id)
+struct String * GetNutName(u32 berry_idx, u32 heap_id)
{
struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 373, heap_id);
- u16 * ret = FUN_0200A914(msgData, berry_idx);
+ struct String * ret = NewString_ReadMsgData(msgData, berry_idx);
DestroyMsgData(msgData);
return ret;
}
-u16 * GetNutDesc(u32 berry_idx, u32 heap_id)
+struct String * GetNutDesc(u32 berry_idx, u32 heap_id)
{
struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 372, heap_id);
- u16 * ret = FUN_0200A914(msgData, berry_idx);
+ struct String * ret = NewString_ReadMsgData(msgData, berry_idx);
DestroyMsgData(msgData);
return ret;
}
diff --git a/arm9/src/pokemon.c b/arm9/src/pokemon.c
index 8df597a6..a15d20c1 100644
--- a/arm9/src/pokemon.c
+++ b/arm9/src/pokemon.c
@@ -10,6 +10,7 @@
#include "move_data.h"
#include "string_util.h"
#include "text.h"
+#include "msgdata.h"
#include "constants/abilities.h"
#include "constants/items.h"
#include "constants/moves.h"
@@ -843,7 +844,7 @@ u32 GetBoxMonDataInternal(struct BoxPokemon * boxmon, int attr, void * dest)
break;
case MON_DATA_NICKNAME:
if (boxmon->checksum_fail)
- GetSpeciesName(SPECIES_MANAPHY_EGG, 0, dest);
+ GetSpeciesNameIntoArray(SPECIES_MANAPHY_EGG, 0, dest);
else
{
u16 * dest16 = (u16 *)dest;
@@ -860,9 +861,9 @@ u32 GetBoxMonDataInternal(struct BoxPokemon * boxmon, int attr, void * dest)
case MON_DATA_NICKNAME_3:
if (boxmon->checksum_fail)
{
- u16 * buffer = FUN_0200AA50(SPECIES_MANAPHY_EGG, 0);
- FUN_02021A74(dest, buffer);
- FUN_02021A20(buffer);
+ struct String * buffer = GetSpeciesName(SPECIES_MANAPHY_EGG, 0);
+ StringCopy(dest, buffer);
+ String_dtor(buffer);
}
else
{
@@ -978,7 +979,7 @@ u32 GetBoxMonDataInternal(struct BoxPokemon * boxmon, int attr, void * dest)
}
break;
case MON_DATA_SPECIES_NAME:
- GetSpeciesName(blockA->species, 0, dest);
+ GetSpeciesNameIntoArray(blockA->species, 0, dest);
break;
}
return ret;
@@ -1090,7 +1091,7 @@ void SetBoxMonDataInternal(struct BoxPokemon * boxmon, int attr, void * value)
u16 namebuf[POKEMON_NAME_LENGTH + 1];
u16 namebuf2[POKEMON_NAME_LENGTH + 1];
u16 namebuf3[POKEMON_NAME_LENGTH + 1];
- u16 * speciesName;
+ struct String * speciesName;
PokemonDataBlockA *blockA = &GetSubstruct(boxmon, boxmon->pid, 0)->blockA;
PokemonDataBlockB *blockB = &GetSubstruct(boxmon, boxmon->pid, 1)->blockB;
@@ -1309,7 +1310,7 @@ void SetBoxMonDataInternal(struct BoxPokemon * boxmon, int attr, void * value)
blockB->Unused = VALUE(u16);
break;
case MON_DATA_NICKNAME_2:
- GetSpeciesName(blockA->species, 0, namebuf);
+ GetSpeciesNameIntoArray(blockA->species, 0, namebuf);
blockB->isNicknamed = StringNotEqual(namebuf, value);
// fallthrough
case MON_DATA_NICKNAME:
@@ -1319,7 +1320,7 @@ void SetBoxMonDataInternal(struct BoxPokemon * boxmon, int attr, void * value)
}
break;
case MON_DATA_NICKNAME_4:
- GetSpeciesName(blockA->species, 0, namebuf2);
+ GetSpeciesNameIntoArray(blockA->species, 0, namebuf2);
FUN_02021EF0(value, namebuf3, POKEMON_NAME_LENGTH + 1);
blockB->isNicknamed = StringNotEqual(namebuf2, namebuf3);
// fallthrough
@@ -1420,9 +1421,9 @@ void SetBoxMonDataInternal(struct BoxPokemon * boxmon, int attr, void * value)
blockB->spdefIV = (VALUE(u32) >> 25) & 0x1F;
break;
case MON_DATA_SPECIES_NAME:
- speciesName = FUN_0200AA50(blockA->species, 0);
+ speciesName = GetSpeciesName(blockA->species, 0);
FUN_02021EF0(speciesName, blockC->nickname, POKEMON_NAME_LENGTH + 1);
- FUN_02021A20(speciesName);
+ String_dtor(speciesName);
break;
}
#undef VALUE
@@ -3682,13 +3683,13 @@ BOOL FUN_0206A9AC(struct BoxPokemon * boxmon, struct SaveBlock2 * sb2, u32 heap_
u32 myGender = FUN_020239CC(sb2);
u32 otGender = GetBoxMonData(boxmon, MON_DATA_MET_GENDER, NULL);
struct String * r7 = FUN_020239A0(sb2, heap_id);
- struct String * r6 = FUN_020219F4(OT_NAME_LENGTH + 1, heap_id);
+ struct String * r6 = String_ctor(OT_NAME_LENGTH + 1, heap_id);
BOOL ret = FALSE;
GetBoxMonData(boxmon, MON_DATA_OT_NAME_2, r6);
if (myId == otId && myGender == otGender && FUN_02021CE0(r7, r6) == 0)
ret = TRUE;
- FUN_02021A20(r6);
- FUN_02021A20(r7);
+ String_dtor(r6);
+ String_dtor(r7);
return ret;
}
diff --git a/arm9/src/string_util.c b/arm9/src/string_util.c
index 54ad61fc..19ed5fa3 100644
--- a/arm9/src/string_util.c
+++ b/arm9/src/string_util.c
@@ -32,7 +32,7 @@ const s32 gPowersOfTen[] = {
1000000000,
};
-THUMB_FUNC void StringCopy(u16 *dest, const u16 *src)
+THUMB_FUNC void CopyU16StringArray(u16 *dest, const u16 *src)
{
u16 c = *src;
while (c != EOS) {
@@ -44,7 +44,7 @@ THUMB_FUNC void StringCopy(u16 *dest, const u16 *src)
*dest = EOS;
}
-THUMB_FUNC u16 *StringCopyN(u16 *dest, const u16 *src, u32 num)
+THUMB_FUNC u16 *CopyU16StringArrayN(u16 *dest, const u16 *src, u32 num)
{
u32 copied = 0;
if (num > copied) {
diff --git a/arm9/src/unk_0201B8B8.c b/arm9/src/unk_0201B8B8.c
new file mode 100644
index 00000000..abb92067
--- /dev/null
+++ b/arm9/src/unk_0201B8B8.c
@@ -0,0 +1,33 @@
+#include "global.h"
+#include "unk_0201B8B88.h"
+
+#pragma thumb on
+
+const u16 * FUN_0201B8B8(const u16 * r4)
+{
+ GF_ASSERT(*r4 == 0xFFFE);
+ if (*r4 == 0xFFFE) {
+ u16 r0 = r4[2];
+ r4 += 3;
+ r4 += r0;
+ }
+ return r4;
+}
+
+u16 FUN_0201B8E0(const u16 * r4)
+{
+ GF_ASSERT(*r4 == 0xFFFE);
+ return r4[1];
+}
+
+BOOL FUN_0201B8F8(const u16 * r4)
+{
+ return (FUN_0201B8E0(r4) & 0xFF00) == 0x100;
+}
+
+u16 FUN_0201B914(const u16 * r5, u32 r4)
+{
+ GF_ASSERT(*r5 == 0xFFFE);
+ GF_ASSERT(r4 < r5[2]);
+ return r5[3 + r4];
+}