summaryrefslogtreecommitdiff
path: root/arm9/src
diff options
context:
space:
mode:
authorred031000 <rubenru09@aol.com>2020-08-22 21:06:37 +0100
committerGitHub <noreply@github.com>2020-08-22 21:06:37 +0100
commit7a6abfe3982d516b39a13a8fd934dbfe8211cfe6 (patch)
tree0c7a403f7b9680519acb5a0b086ce84e165e503b /arm9/src
parent4ed13afd18de6f0b94d35e83023094efcfec73f5 (diff)
parentdd904623a1ff019bfa6d88b1e178d87676d31320 (diff)
Merge pull request #266 from PikalaxALT/pikalax_work
Decompile code related to input handling, initialization/runtime, and script string placeholders
Diffstat (limited to 'arm9/src')
-rw-r--r--arm9/src/game_init.c532
-rw-r--r--arm9/src/main.c20
-rw-r--r--arm9/src/poke_overlay.c2
-rw-r--r--arm9/src/script_buffers.c826
-rw-r--r--arm9/src/unk_0200CA44.c2
-rw-r--r--arm9/src/unk_020286F8.c150
6 files changed, 1519 insertions, 13 deletions
diff --git a/arm9/src/game_init.c b/arm9/src/game_init.c
new file mode 100644
index 00000000..327c66c6
--- /dev/null
+++ b/arm9/src/game_init.c
@@ -0,0 +1,532 @@
+#include "global.h"
+#include "gx.h"
+#include "math.h"
+#include "main.h"
+#include "FS_rom.h"
+#include "PAD_pad.h"
+#include "heap.h"
+#include "MWC_string.h"
+#include "tp.h"
+#include "unk_0201B4E8.h"
+#include "game_init.h"
+#include "registers.h"
+
+#pragma thumb on
+
+extern void FUN_020166C8(const u32 (*)[2], int, int, int);
+extern void FUN_02022450(void);
+
+typedef volatile struct
+{
+ u8 sys_and_irq_stack[0x3F80];
+ u8 svc_stack[0x40];
+ u8 reserved[0x38];
+ u32 intr_check;
+ void * intr_vector;
+}
+OS_DTCM;
+
+#define DTCM (*(OS_DTCM *)HW_DTCM)
+
+static struct {
+ void * contents;
+ u32 name_hash;
+} UNK_021C4928[128];
+
+struct Main gMain;
+
+void Main_HBlankIntr(BOOL);
+void FUN_0201B5CC(void *);
+
+void FUN_02015EA0(void)
+{
+ DTCM.intr_check |= 1;
+ MI_WaitDma(3);
+ FUN_0201B5CC(gMain.unk1C);
+ gMain.unk30++;
+}
+
+void FUN_02015ED4(void)
+{
+ DTCM.intr_check |= 1;
+ MI_WaitDma(3);
+}
+
+void FUN_02015EF4(void)
+{
+ OS_DisableIrqMask(1);
+ OS_SetIrqFunction(1, FUN_02015ED4);
+ OS_EnableIrqMask(1);
+}
+
+void Main_SetVBlankIntrCB(void (*a0)(void *), void * a1)
+{
+ gMain.vBlankIntr = a0;
+ gMain.vBlankIntrArg = a1;
+}
+
+void FUN_02015F1C(void)
+{
+ Main_HBlankIntr(FALSE);
+ gMain.hBlankIntr = NULL;
+ gMain.hBlankIntrArg = NULL;
+}
+
+BOOL FUN_02015F34(void (*a0)(void *), void * a1)
+{
+ if (a0 == 0)
+ {
+ Main_HBlankIntr(FALSE);
+ gMain.hBlankIntr = NULL;
+ gMain.hBlankIntrArg = NULL;
+ return TRUE;
+ }
+ else if (gMain.hBlankIntr == NULL)
+ {
+ gMain.hBlankIntrArg = a1;
+ gMain.hBlankIntr = a0;
+ Main_HBlankIntr(TRUE);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void FUN_02015F6C(void)
+{
+ if (gMain.hBlankIntr != NULL)
+ gMain.hBlankIntr(gMain.hBlankIntrArg);
+}
+
+void Main_HBlankIntr(BOOL a0)
+{
+ (void)OS_DisableIrq();
+ if (!a0)
+ {
+ (void)OS_GetIrqMask();
+ OS_DisableIrqMask(2);
+ GX_HBlankIntr(FALSE);
+ }
+ else
+ {
+ (void)OS_GetIrqMask();
+ OS_SetIrqFunction(2, FUN_02015F6C);
+ OS_EnableIrqMask(2);
+ GX_HBlankIntr(TRUE);
+ }
+ (void)OS_EnableIrq();
+}
+
+const u32 UNK_020EDB10[][2] = {
+ { 0x0000D000, 0x00000000 },
+ { 0x00021000, 0x00000000 },
+ { 0x00001000, 0x00000000 },
+ { 0x0010D800, 0x00000000 }
+};
+
+void FUN_02015FC8(void)
+{
+ u32 data[8];
+ u8 digest[16];
+ OS_GetLowEntropyData(data);
+ MATH_CalcMD5(digest, data, 32);
+ u32 csum = 0, i;
+ for (i = 0; i < sizeof(digest); i++)
+ {
+ csum += digest[i];
+ }
+ csum = (csum << 24) >> 24;
+ while (csum & 3)
+ {
+ csum++;
+ }
+ FUN_020166C8(UNK_020EDB10, 4, 92, (int)csum);
+}
+
+void InitSystemForTheGame(void)
+{
+ OS_Init();
+ FX_Init();
+ reg_GX_POWCNT = (REGType16v)((reg_GX_POWCNT & ~(REG_GX_POWCNT_GE_MASK | REG_GX_POWCNT_RE_MASK | REG_GX_POWCNT_E2DG_MASK | REG_GX_POWCNT_E2DGB_MASK)) | (REG_GX_POWCNT_GE_MASK | REG_GX_POWCNT_RE_MASK | REG_GX_POWCNT_E2DG_MASK | REG_GX_POWCNT_E2DGB_MASK));
+ GX_Init();
+ OS_InitTick();
+ FUN_02015FC8();
+ gMain.unk18 = FUN_0201B580(0xa0, OS_AllocFromArenaLo(OS_ARENA_MAIN, FUN_0201B578(0xa0), 4));
+ gMain.unk1C = FUN_0201B580(0x10, OS_AllocFromArenaLo(OS_ARENA_MAIN, FUN_0201B578(0x10), 4));
+ gMain.unk20 = FUN_0201B580(0x20, OS_AllocFromArenaLo(OS_ARENA_MAIN, FUN_0201B578(0x20), 4));
+ gMain.unk24 = FUN_0201B580(0x04, OS_AllocFromArenaLo(OS_ARENA_MAIN, FUN_0201B578(0x04), 4));
+ GX_DispOff();
+ reg_GXS_DB_DISPCNT &= ~0x10000;
+ reg_GX_POWCNT |= REG_GX_POWCNT_DSEL_MASK;
+ OS_SetIrqFunction(1, FUN_02015EA0);
+ OS_EnableIrqMask(1);
+ OS_EnableIrqMask(0x40000);
+ (void)OS_EnableIrq();
+ GX_VBlankIntr(TRUE);
+ FS_Init(1);
+ FUN_02022450();
+ u32 size = FS_TryLoadTable(NULL, 0);
+ void * table = OS_AllocFromArenaLo(OS_ARENA_MAIN, size, 4);
+ GF_ASSERT(table != NULL);
+ FS_TryLoadTable(table, size);
+ gMain.vBlankIntr = NULL;
+ gMain.hBlankIntr = NULL;
+ gMain.unk10 = 0;
+ gMain.unk14 = 0;
+ gMain.unk2C = 0;
+ gMain.unk65 = 0;
+}
+
+void InitGraphicMemory(void)
+{
+ GX_SetBankForLCDC(0x1FF);
+ MIi_CpuClearFast(0, (void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
+ GX_DisableBankForLCDC();
+ MIi_CpuClearFast(0xC0, (void *)HW_OAM, HW_OAM_SIZE);
+ MIi_CpuClearFast(0xC0, (void *)HW_DB_OAM, HW_DB_OAM_SIZE);
+ MIi_CpuClearFast(0, (void *)HW_PLTT, HW_PLTT_SIZE);
+ MIi_CpuClearFast(0, (void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
+}
+
+void * FUN_020161A4(u32 heap_id, const char * path)
+{
+ void * ret;
+
+ FSFile file;
+ FS_InitFile(&file);
+ if (FS_OpenFile(&file, path))
+ {
+ u32 size = file.prop.file.bottom - file.prop.file.top;
+ ret = AllocFromHeap(heap_id, size);
+ if (ret != NULL)
+ {
+ if (size != FS_ReadFile(&file, ret, (s32)size))
+ {
+ FUN_02016A8C(heap_id, ret);
+ ret = NULL;
+ }
+ }
+ FS_CloseFile(&file);
+ }
+ else
+ ret = NULL;
+ return ret;
+}
+
+void FUN_020161F8(const char * path, void ** ptr)
+{
+ FSFile file;
+ FS_InitFile(&file);
+ if (FS_OpenFile(&file, path))
+ {
+ u32 size = file.prop.file.bottom - file.prop.file.top;
+ if (*ptr != NULL)
+ FS_ReadFile(&file, *ptr, (s32)size);
+ FS_CloseFile(&file);
+ }
+}
+
+u32 FUN_02016230(const s8 * str)
+{
+ u16 len = (u16)strlen(str);
+ u16 sp4;
+ if ((len % 4) != 0)
+ sp4 = (u16)((len / 4) + 1);
+ else
+ sp4 = (u16)(len / 4);
+ u32 r7 = 0;
+ s32 i, j;
+ for (i = 0; i < sp4; i++)
+ {
+ u32 r1 = 0;
+ for (j = 0; j < 4; j++)
+ {
+ int r5 = str[4 * i + j];
+ if (r5 == 0)
+ break;
+ r1 |= r5 << (8 * j);
+ }
+ r7 ^= r1;
+ }
+ return r7;
+}
+
+int FUN_020162A0(u32 a0)
+{
+ for (int i = 0; i < 128; i++)
+ {
+ if (UNK_021C4928[i].name_hash == a0 && UNK_021C4928[i].contents != NULL)
+ return i;
+ }
+ return -1;
+}
+
+int FUN_020162C8(void * a0, u32 a1)
+{
+ for (int i = 0; i < 128; i++)
+ {
+ if (UNK_021C4928[i].contents == NULL)
+ {
+ UNK_021C4928[i].contents = a0;
+ UNK_021C4928[i].name_hash = a1;
+ return i;
+ }
+ }
+ return -1;
+}
+
+void FUN_020162FC(void)
+{
+ for (int i = 127; i > -1; i--)
+ {
+ if (UNK_021C4928[i].contents != NULL)
+ {
+ FreeToHeap(UNK_021C4928[i].contents);
+ UNK_021C4928[i].contents = NULL;
+ UNK_021C4928[i].name_hash = 0;
+ }
+ }
+}
+
+void * FUN_02016324(const s8 * str, u32 heap_id)
+{
+ s8 sp0[32];
+ FSFile file;
+ void * ret;
+ int r5 = 0;
+
+ if (str[0] == '!')
+ {
+ strcpy(sp0, str + 1);
+ r5 = 1;
+ }
+ else
+ {
+ strcpy(sp0, str);
+ }
+ u32 r7 = FUN_02016230(sp0);
+ s32 r0 = FUN_020162A0(r7);
+ if (r0 >= 0 && r5 == 0)
+ {
+ ret = UNK_021C4928[r0].contents;
+ }
+ else
+ {
+ FS_InitFile(&file);
+ if (FS_OpenFile(&file, (const char *)sp0))
+ {
+ u32 size = file.prop.file.bottom - file.prop.file.top;
+ ret = AllocFromHeap(heap_id, size);
+ if (ret != NULL)
+ {
+ if (size != FS_ReadFile(&file, ret, (s32)size))
+ {
+ FreeToHeap(ret);
+ ret = NULL;
+ }
+ }
+ FS_CloseFile(&file);
+ if (r5 == 0)
+ FUN_020162C8(ret, r7);
+ }
+ else
+ ret = NULL;
+ }
+ return ret;
+}
+
+void FUN_020163BC(void)
+{
+ TPCalibrateParam tp;
+ gMain.unk34 = 0;
+ gMain.unk38 = 0;
+ gMain.unk3C = 0;
+ gMain.unk40 = 0;
+ gMain.unk44 = 0;
+ gMain.unk48 = 0;
+ gMain.unk4C = 0;
+ gMain.unk50 = 0;
+ gMain.unk54 = 8;
+ gMain.unk58 = 15;
+ gMain.unk5C = 0;
+ gMain.unk5E = 0;
+ gMain.unk60 = 0;
+ gMain.unk62 = 0;
+ gMain.unk64 = 0;
+ TP_Init();
+ if (TP_GetUserInfo(&tp) == TRUE)
+ TP_SetCalibrateParam(&tp);
+ else
+ {
+ tp.x0 = 686;
+ tp.y0 = 1420;
+ tp.xDotSize = 3621;
+ tp.yDotSize = 4616;
+ TP_SetCalibrateParam(&tp);
+ }
+}
+
+void FUN_02016438(u8 a0)
+{
+ gMain.unk66 = a0;
+}
+
+void FUN_02016444(u8 a0)
+{
+ gMain.unk67 |= a0;
+}
+
+void FUN_02016454(u8 a0)
+{
+ gMain.unk67 &= ~a0;
+}
+
+void FUN_02016464(void)
+{
+ TPData raw, calib;
+ if (PAD_DetectFold())
+ {
+ gMain.unk48 = 0;
+ gMain.unk44 = 0;
+ gMain.unk4C = 0;
+ gMain.unk60 = 0;
+ gMain.unk62 = 0;
+ return;
+ }
+ u32 r0 = PAD_Read();
+ gMain.unk40 = gMain.unk3C = (r0 ^ gMain.unk38) & r0;
+ if (r0 != 0 && gMain.unk38 == r0)
+ {
+ if (--gMain.unk50 == 0)
+ {
+ gMain.unk40 = r0;
+ gMain.unk50 = gMain.unk54;
+ }
+ }
+ else
+ {
+ gMain.unk50 = gMain.unk58;
+ }
+ gMain.unk38 = r0;
+ gMain.unk48 = gMain.unk3C;
+ gMain.unk44 = r0;
+ gMain.unk4C = gMain.unk40;
+ FUN_02016568();
+ if (gMain.unk64 == 0)
+ {
+ while (TP_RequestRawSampling(&raw))
+ ;
+ }
+ else
+ TP_GetLatestRawPointInAuto(&raw);
+ TP_GetCalibratedPoint(&calib, &raw);
+ if (calib.validity == 0)
+ {
+ gMain.unk5C = calib.x;
+ gMain.unk5E = calib.y;
+ }
+ else if (gMain.unk62)
+ {
+ switch (calib.validity)
+ {
+ case 1:
+ gMain.unk5E = calib.y;
+ break;
+ case 2:
+ gMain.unk5C = calib.x;
+ break;
+ case 3:
+ break;
+ }
+ }
+ else
+ calib.touch = 0;
+ gMain.unk60 = (u16)((gMain.unk62 ^ calib.touch) & calib.touch);
+ gMain.unk62 = calib.touch;
+}
+
+void FUN_02016568(void)
+{
+ switch (gMain.unk34)
+ {
+ case 0: // Normal
+ break;
+ case 1: // Start = X
+ if (gMain.unk48 & PAD_BUTTON_START)
+ gMain.unk48 |= PAD_BUTTON_X;
+ if (gMain.unk44 & PAD_BUTTON_START)
+ gMain.unk44 |= PAD_BUTTON_X;
+ if (gMain.unk4C & PAD_BUTTON_START)
+ gMain.unk4C |= PAD_BUTTON_X;
+ break;
+ case 2: // Swap X and Y; unused in the retail game
+ {
+ u32 r1 = 0;
+ if (gMain.unk48 & PAD_BUTTON_X)
+ {
+ r1 |= PAD_BUTTON_Y;
+ }
+ if (gMain.unk48 & PAD_BUTTON_Y)
+ {
+ r1 |= PAD_BUTTON_X;
+ }
+ gMain.unk48 &= 0xF3FF;
+ gMain.unk48 |= r1;
+ }
+ {
+ u32 r1 = 0;
+ if (gMain.unk44 & PAD_BUTTON_X)
+ {
+ r1 |= PAD_BUTTON_Y;
+ }
+ if (gMain.unk44 & PAD_BUTTON_Y)
+ {
+ r1 |= PAD_BUTTON_X;
+ }
+ gMain.unk44 &= 0xF3FF;
+ gMain.unk44 |= r1;
+ }
+ {
+ u32 r1 = 0;
+ if (gMain.unk4C & PAD_BUTTON_X)
+ {
+ r1 |= PAD_BUTTON_Y;
+ }
+ if (gMain.unk4C & PAD_BUTTON_Y)
+ {
+ r1 |= PAD_BUTTON_X;
+ }
+ gMain.unk4C &= 0xF3FF;
+ gMain.unk4C |= r1;
+ }
+ break;
+ case 3: // L = A
+ if (gMain.unk48 & PAD_BUTTON_L)
+ gMain.unk48 |= PAD_BUTTON_A;
+ if (gMain.unk44 & PAD_BUTTON_L)
+ gMain.unk44 |= PAD_BUTTON_A;
+ if (gMain.unk4C & PAD_BUTTON_L)
+ gMain.unk4C |= PAD_BUTTON_A;
+ gMain.unk48 &= 0xFCFF;
+ gMain.unk44 &= 0xFCFF;
+ gMain.unk4C &= 0xFCFF;
+ }
+}
+
+void FUN_0201669C(int x, int y)
+{
+ gMain.unk54 = x;
+ gMain.unk58 = y;
+}
+
+void FUN_020166A8(u8 a0)
+{
+ gMain.unk68 |= a0;
+}
+
+void FUN_020166B8(u8 a0)
+{
+ gMain.unk68 &= ~a0;
+}
diff --git a/arm9/src/main.c b/arm9/src/main.c
index 06673b65..e1c8fb38 100644
--- a/arm9/src/main.c
+++ b/arm9/src/main.c
@@ -5,6 +5,7 @@
#include "CTRDG_common.h"
#include "PAD_pad.h"
#include "main.h"
+#include "game_init.h"
#include "poke_overlay.h"
#include "player_data.h"
#include "sound.h"
@@ -22,12 +23,9 @@ extern void OverlayManager_delete(int);
extern BOOL FUN_02033678(void);
extern u32 FUN_020335B8(void);
extern BOOL FUN_0202FB80(void);
-extern void FUN_02016464(void);
-extern void FUN_02016438(s32);
extern void InitSystemForTheGame(void);
extern void InitGraphicMemory(void);
-extern void FUN_020163BC(void);
extern void FUN_02022294(void);
extern void FUN_0201259C(void);
extern void FUN_02002C14(void);
@@ -41,7 +39,7 @@ extern int FUN_020227FC(struct SaveBlock2 *);
extern void FUN_02089D90(int);
extern void FUN_0200A2AC(void);
extern void FUN_02015E30(void);
-extern void FUN_0201B5CC(int);
+extern void FUN_0201B5CC(void *);
extern void FUN_020125D4(void);
extern void FUN_02015E60(void);
extern void FUN_020222C4(void);
@@ -112,7 +110,7 @@ THUMB_FUNC void NitroMain(void)
FUN_02000EE8();
HandleDSLidAction();
FUN_02016464();
- if ((gMain.unk38 & SOFT_RESET_KEY) == SOFT_RESET_KEY && !gUnk021C4918.unk8) // soft reset?
+ if ((gMain.unk38 & SOFT_RESET_KEY) == SOFT_RESET_KEY && !gMain.unk68) // soft reset?
{
DoSoftReset(0); // soft reset?
}
@@ -136,8 +134,8 @@ THUMB_FUNC void NitroMain(void)
gMain.unk30 = 0;
FUN_0200A318();
FUN_0200E2D8();
- if (gMain.unk0)
- gMain.unk0(gMain.unk4);
+ if (gMain.vBlankIntr)
+ gMain.vBlankIntr(gMain.vBlankIntrArg);
DoSoundUpdateFrame();
FUN_0201B5CC(gMain.unk20);
}
@@ -187,8 +185,8 @@ THUMB_FUNC void FUN_02000E9C(void)
OS_WaitIrq(TRUE, OS_IE_V_BLANK);
gMain.unk2C++;
gMain.unk30 = 0;
- if (gMain.unk0 != NULL)
- gMain.unk0(gMain.unk4);
+ if (gMain.vBlankIntr != NULL)
+ gMain.vBlankIntr(gMain.vBlankIntrArg);
}
THUMB_FUNC void FUN_02000EC8(u32 parameter)
@@ -289,7 +287,7 @@ THUMB_FUNC void HandleDSLidAction(void)
PMBackLightSwitch top, bottom;
if (PAD_DetectFold())
{
- if (!gUnk021C4918.unk7)
+ if (!gMain.unk67)
{
FUN_0201CE04();
if (CTRDG_IsPulledOut() == TRUE)
@@ -301,7 +299,7 @@ THUMB_FUNC void HandleDSLidAction(void)
while (1)
{
PMWakeUpTrigger trigger = PM_TRIGGER_COVER_OPEN | PM_TRIGGER_CARD;
- if (gUnk021C4918.unk6 && !r1)
+ if (gMain.unk66 && !r1)
trigger |= PM_TRIGGER_CARTRIDGE;
PM_GoSleepMode(trigger, PM_PAD_LOGIC_OR, 0);
if (CARD_IsPulledOut())
diff --git a/arm9/src/poke_overlay.c b/arm9/src/poke_overlay.c
index 237cdc26..4dd98670 100644
--- a/arm9/src/poke_overlay.c
+++ b/arm9/src/poke_overlay.c
@@ -40,7 +40,7 @@ THUMB_FUNC s32 GetOverlayLoadDestination(FSOverlayID id)
end = (u8 *)HW_ITCM_END;
if (info.header.ram_address <= end && info.header.ram_address >= start)
return OVERLAY_LOAD_ITCM;
- start = (u8 *)SDK_AUTOLOAD_DTCM_START;
+ start = (u8 *)HW_DTCM;
end = start + HW_DTCM_SIZE;
if (info.header.ram_address <= end && info.header.ram_address >= start)
return OVERLAY_LOAD_DTCM;
diff --git a/arm9/src/script_buffers.c b/arm9/src/script_buffers.c
new file mode 100644
index 00000000..c29feed3
--- /dev/null
+++ b/arm9/src/script_buffers.c
@@ -0,0 +1,826 @@
+#include "global.h"
+#include "heap.h"
+#include "string16.h"
+#include "player_data.h"
+#include "msgdata.h"
+#include "pokemon.h"
+#include "pokemon_storage_system.h"
+#include "unk_02015CC0.h"
+#include "unk_020286F8.h"
+#include "filesystem.h"
+#include "unk_0201B8B8.h"
+#include "script_buffers.h"
+
+#pragma thumb on
+
+extern void * FUN_02024EC0(struct SaveBlock2 * sav2);
+extern u16 * FUN_02024EE8(void *);
+extern u32 GetCityNamesMsgdataIdByCountry(u32);
+extern void FUN_02013A58(u32 a0, struct String * a1);
+extern void FUN_02022048(struct String * dest, const struct String * src);
+extern void StrAddChar(struct String * str, u16 val);
+extern void * FUN_02006BB0(NarcId, s32, s32, struct UnkStruct_0200B870_sub **, u32);
+extern BOOL UncompressFromNarc(NarcId narcId, s32 memberNo, BOOL a2, u32 heap_id, BOOL a4);
+extern void FUN_02019658(int, u8 *, u16, u16, u16, u16, u16, u16, u16, u16);
+extern void FUN_020196F4(int, u8, u16, u16, u16, u16);
+
+const u16 UNK_020ECE6C[][2] = {
+ { 0x0140, 0x0008 },
+ { 0x0160, 0x0010 },
+ { 0x01A0, 0x0010 },
+ { 0x01E0, 0x0010 },
+ { 0x0220, 0x0010 },
+ { 0x0260, 0x0010 },
+ { 0x02A0, 0x0010 },
+};
+
+const u16 UNK_020ECE64[] = {
+ 382,
+ 384,
+ 383,
+ 0
+};
+
+struct ScrStrBufs * ScrStrBufs_new(u32 heap_id)
+{
+ return ScrStrBufs_new_custom(8, 32, heap_id);
+}
+
+struct ScrStrBufs * ScrStrBufs_new_custom(u32 nstr, u32 strlen, u32 heap_id)
+{
+ GF_ASSERT(nstr != 0);
+ GF_ASSERT(strlen != 0);
+ struct ScrStrBufs * r4 = AllocFromHeapAtEnd(heap_id, sizeof(struct ScrStrBufs));
+ if (r4 != NULL)
+ {
+ r4->count = nstr;
+ r4->heap_id = heap_id;
+ r4->tmpbuf = String_ctor(strlen, heap_id);
+ if (r4->tmpbuf != NULL)
+ {
+ r4->array = AllocFromHeapAtEnd(heap_id, nstr * sizeof(struct UnkStruct_0200AA80_sub));
+ if (r4->array != NULL)
+ {
+ int i;
+ for (i = 0; i < nstr; i++)
+ {
+ ScrStrBufs_InitSub(&r4->array[i]);
+ r4->array[i].msg = String_ctor(strlen, heap_id);
+ if (r4->array[i].msg == NULL)
+ break;
+ }
+ if (i == nstr)
+ return r4;
+ }
+ }
+ }
+ return NULL;
+}
+
+void ScrStrBufs_delete(struct ScrStrBufs * ptr)
+{
+ GF_ASSERT(ptr->count != 0);
+ if (ptr->array != NULL)
+ {
+ int i;
+ for (i = 0; i < ptr->count; i++)
+ {
+ if (ptr->array[i].msg == NULL)
+ break;
+ String_dtor(ptr->array[i].msg);
+ }
+ FreeToHeap(ptr->array);
+ }
+ if (ptr->tmpbuf != NULL)
+ String_dtor(ptr->tmpbuf);
+ ptr->count = 0;
+ FreeToHeap(ptr);
+}
+
+void ScrStrBufs_InitSub(struct UnkStruct_0200AA80_sub * sub)
+{
+#pragma unused(sub)
+}
+
+void SetStringAsPlaceholder(struct ScrStrBufs * mgr, u32 idx, struct String * str, struct UnkStruct_0200AA80_sub_sub * a3)
+{
+ GF_ASSERT(idx < mgr->count);
+ if (idx < mgr->count)
+ {
+ if (a3 != NULL)
+ {
+ mgr->array[idx].attrs = *a3;
+ }
+ StringCopy(mgr->array[idx].msg, str);
+ }
+}
+
+void BufferString(struct ScrStrBufs * mgr, u32 idx, struct String * str, u32 a3, u32 a4, u32 a5)
+{
+#pragma unused(a3,a4,a5)
+ SetStringAsPlaceholder(mgr, idx, str, NULL);
+}
+
+void BufferPlayersName(struct ScrStrBufs * mgr, u32 idx, struct PlayerData * data)
+{
+ u16 * name = PlayerProfile_GetNamePtr(data);
+ CopyU16ArrayToString(mgr->tmpbuf, name);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+}
+
+void BufferRivalsName(struct ScrStrBufs * mgr, u32 idx, struct SaveBlock2 * sav2)
+{
+ u16 * name = FUN_02024EE8(FUN_02024EC0(sav2));
+ CopyU16ArrayToString(mgr->tmpbuf, name);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+}
+
+void BufferFriendsName(struct ScrStrBufs * mgr, u32 idx, struct SaveBlock2 * sav2)
+{
+ struct PlayerData * data = Sav2_PlayerData_GetProfileAddr(sav2);
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 497, mgr->heap_id);
+ if (PlayerProfile_GetTrainerGender(data) == 0)
+ {
+ ReadMsgDataIntoString(msgData, 1, mgr->tmpbuf);
+ }
+ else
+ {
+ ReadMsgDataIntoString(msgData, 0, mgr->tmpbuf);
+ }
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+}
+
+void BufferBoxMonSpeciesName(struct ScrStrBufs * mgr, u32 idx, struct BoxPokemon * mon)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 362, mgr->heap_id);
+ ReadMsgDataIntoString(msgData, GetBoxMonData(mon, MON_DATA_SPECIES, NULL), mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+}
+
+void BufferBoxMonSpeciesNameWithArticle(struct ScrStrBufs * mgr, u32 idx, struct BoxPokemon * mon)
+{
+ BufferSpeciesNameWithArticle(mgr, idx, GetBoxMonData(mon, MON_DATA_SPECIES, NULL));
+}
+
+void BufferSpeciesNameWithArticle(struct ScrStrBufs * mgr, u32 idx, u32 species)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 363, mgr->heap_id);
+ ReadMsgDataIntoString(msgData, species, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+}
+
+void BufferBoxMonNickname(struct ScrStrBufs * mgr, u32 idx, struct BoxPokemon * mon)
+{
+ GetBoxMonData(mon, MON_DATA_NICKNAME_3, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+}
+
+void BufferBoxMonOTName(struct ScrStrBufs * mgr, u32 idx, struct BoxPokemon * mon)
+{
+ GetBoxMonData(mon, MON_DATA_OT_NAME_2, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+}
+
+void BufferIntegerAsString(struct ScrStrBufs * mgr, u32 idx, int num, u32 ndigits, int strConvMode, BOOL whichCharset)
+{
+ String16_FormatInteger(mgr->tmpbuf, num, ndigits, strConvMode, whichCharset);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+}
+
+void BufferMoveName(struct ScrStrBufs * mgr, u32 idx, u32 move)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 588, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, move, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferRibbonNameOrDesc(struct ScrStrBufs * mgr, u32 idx, u32 ribbon)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 484, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, ribbon, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferAbilityName(struct ScrStrBufs * mgr, u32 idx, u32 ability)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 552, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, ability, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferNatureName(struct ScrStrBufs * mgr, u32 idx, u32 nature)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 190, mgr->heap_id);
+ ReadMsgDataIntoString(msgData, nature, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+}
+
+void BufferItemName(struct ScrStrBufs * mgr, u32 idx, u32 item)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 344, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, item, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferItemNameWithIndefArticle(struct ScrStrBufs * mgr, u32 idx, u32 item)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 346, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, item, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferItemNamePlural(struct ScrStrBufs * mgr, u32 idx, u32 item)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 347, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, item, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferPocketName(struct ScrStrBufs * mgr, u32 idx, u32 pocket)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 349, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, pocket, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferTypeName(struct ScrStrBufs * mgr, u32 idx, u32 type)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 565, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, type, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferStatName(struct ScrStrBufs * mgr, u32 idx, u32 stat)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 495, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, stat, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferStatusName(struct ScrStrBufs * mgr, u32 idx, u32 status)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 205, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, status, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferFlavorDislikeText(struct ScrStrBufs * mgr, u32 idx, u32 flavor)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 548, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, flavor, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferLandmarkName(struct ScrStrBufs * mgr, u32 idx, u32 landmark)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 382, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, landmark, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferPoketchAppName(struct ScrStrBufs * mgr, u32 idx, u32 app)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 406, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, app, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferTrainerClassName(struct ScrStrBufs * mgr, u32 idx, u32 trclass)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 560, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, trclass, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferTrainerClassNameWithArticle(struct ScrStrBufs * mgr, u32 idx, u32 trclass)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 561, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, trclass, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferTrainerClassName2(struct ScrStrBufs * mgr, u32 idx, struct Trainer * tr)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 560, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, tr->unk1, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void FUN_0200B10C(struct ScrStrBufs * mgr, u32 idx, u32 msgno)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 559, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, msgno, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void FUN_0200B144(struct ScrStrBufs * mgr, u32 idx, void * unk_struct)
+{
+ CopyU16ArrayToString(mgr->tmpbuf, (u16 *)((char *)unk_struct + 20));
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+}
+
+void BufferUndergroundItemName(struct ScrStrBufs * mgr, u32 idx, u32 item)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 569, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, item, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferUndergroundItemNameWithArticle(struct ScrStrBufs * mgr, u32 idx, u32 item)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 570, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, item, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferUndergroundTrapName(struct ScrStrBufs * mgr, u32 idx, u32 trap)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 571, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, trap, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferUndergroundTrapNameWithArticle(struct ScrStrBufs * mgr, u32 idx, u32 trap)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 572, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, trap, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferContestJudgeName(struct ScrStrBufs * mgr, u32 idx, u32 judge)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 194, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, judge, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferContestMessage(struct ScrStrBufs * mgr, u32 idx, u32 msg)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 191, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, msg, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferContestMessage2(struct ScrStrBufs * mgr, u32 idx, u32 msg)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 191, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, msg, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferInterviewQuestion(struct ScrStrBufs * mgr, u32 idx, u32 question)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 574, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, question, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferInterviewAnswer(struct ScrStrBufs * mgr, u32 idx, u32 answer)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 573, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, answer, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferDecorationName(struct ScrStrBufs * mgr, u32 idx, u32 decor)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 567, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, decor, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferDecorationNameWithArticle(struct ScrStrBufs * mgr, u32 idx, u32 decor)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 568, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, decor, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferGenderSymbol(struct ScrStrBufs * mgr, u32 idx, u32 gender)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 199, mgr->heap_id);
+ switch (gender)
+ {
+ case 0:
+ ReadMsgDataIntoString(msgData, 68, mgr->tmpbuf);
+ break;
+ case 1:
+ ReadMsgDataIntoString(msgData, 69, mgr->tmpbuf);
+ break;
+ default:
+ StringSetEmpty(mgr->tmpbuf);
+ break;
+ }
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+}
+
+void BufferBoxName(struct ScrStrBufs * mgr, u32 idx, struct PCStorage * pc, int boxno)
+{
+ PCStorage_GetBoxName(pc, boxno, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+}
+
+void BufferGymName(struct ScrStrBufs * mgr, u32 idx, u32 gym)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 331, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, gym, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferTimeOfDayName(struct ScrStrBufs * mgr, u32 idx, u32 time)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 550, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, time, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferCountryName(struct ScrStrBufs * mgr, u32 idx, u32 country)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 612, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, country, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferCityName(struct ScrStrBufs * mgr, u32 idx, u32 a2, u32 a3)
+{
+ u32 r2 = GetCityNamesMsgdataIdByCountry(a2);
+ if (r2 != 0 && a3 != 0)
+ {
+ struct MsgData *msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, (int)r2, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, a3, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+ }
+}
+
+void FUN_0200B518(struct ScrStrBufs * mgr, u32 idx, u32 a2)
+{
+ FUN_02013A58(a2, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+}
+
+void BufferSealName(struct ScrStrBufs * mgr, u32 idx, u32 seal)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 10, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, seal, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferSealNamePlural(struct ScrStrBufs * mgr, u32 idx, u32 seal)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 11, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, seal, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferLocationName(struct ScrStrBufs * mgr, u32 idx, u16 a2)
+{
+ u32 r6 = (u32)FUN_02015CC0(a2);
+ u32 r4 = (u32)FUN_02015CE0(a2);
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, UNK_020ECE64[r6], mgr->heap_id);
+ if (msgData != NULL)
+ {
+ if (r4 < MsgDataGetCount(msgData))
+ {
+ ReadMsgDataIntoString(msgData, r4, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ return;
+ }
+ // Location is invalid.
+ // Fallback: Mystery Zone
+ DestroyMsgData(msgData);
+ msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 382, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, 0, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+ }
+}
+
+void BufferPoffinName(struct ScrStrBufs * mgr, u32 idx, u32 poffin)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 414, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, poffin, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferFashionName(struct ScrStrBufs * mgr, u32 idx, u32 fashion)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 338, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, fashion, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferFashionNameWithArticle(struct ScrStrBufs * mgr, u32 idx, u32 fashion)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 339, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, fashion, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void BufferContestBackgroundName(struct ScrStrBufs * mgr, u32 idx, u32 bg)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 340, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ ReadMsgDataIntoString(msgData, bg, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void FUN_0200B708(struct ScrStrBufs * mgr, struct SaveBlock2 * sav2, u32 r5, u32 idx, u32 sp28)
+{
+ void * r6 = FUN_0202881C(sav2);
+ u8 sp10 = FUN_020287F8(r6, r5);
+ u8 r7 = FUN_02028804(r6, r5);
+ struct String * r4 = String_ctor(64, 4);
+ CopyU16ArrayToString(r4, FUN_020287A8(r6, r5, sp28));
+ BufferString(mgr, idx, r4, sp10, 1, r7);
+ String_dtor(r4);
+}
+
+void BufferMonthNameAbbr(struct ScrStrBufs * mgr, u32 idx, u32 month)
+{
+ struct MsgData * msgData = NewMsgDataFromNarc(1, NARC_MSGDATA_MSG, 364, mgr->heap_id);
+ if (msgData != NULL)
+ {
+ if (month < 1 || month > 12)
+ month = 1;
+ ReadMsgDataIntoString(msgData, month - 1, mgr->tmpbuf);
+ SetStringAsPlaceholder(mgr, idx, mgr->tmpbuf, NULL);
+ DestroyMsgData(msgData);
+ }
+}
+
+void FUN_0200B7A8(struct ScrStrBufs * mgr, u32 idx)
+{
+ StrUpperFirstChar(mgr->array[idx].msg);
+}
+
+void StringExpandPlaceholders(struct ScrStrBufs * mgr, struct String * dest, struct String * src)
+{
+ const u16 * cstr = String_c_str(src);
+ StringSetEmpty(dest);
+ while (*cstr != EOS)
+ {
+ if (*cstr == 0xFFFE)
+ {
+ if (MsgArray_ControlCodeIsStrVar(cstr))
+ {
+ u32 idx = MsgArray_ControlCodeGetField(cstr, 0);
+ GF_ASSERT(idx < mgr->count);
+ FUN_02022048(dest, mgr->array[idx].msg);
+ cstr = MsgArray_SkipControlCode(cstr);
+ }
+ else
+ {
+ const u16 * before = cstr;
+ cstr = MsgArray_SkipControlCode(cstr);
+ while (before < cstr)
+ StrAddChar(dest, *before++);
+ }
+ }
+ else
+ StrAddChar(dest, *cstr++);
+ }
+}
+
+void FUN_0200B84C(struct ScrStrBufs * mgr)
+{
+ for (int i = 0; i < mgr->count; i++)
+ StringSetEmpty(mgr->array[i].msg);
+}
+
+struct UnkStruct_0200B870 * FUN_0200B870(u32 r5, u32 r6, u32 sp4, u32 r4)
+{
+ struct UnkStruct_0200B870 * sp8 = AllocFromHeap(r4, sizeof(struct UnkStruct_0200B870));
+ if (sp8 != NULL)
+ {
+ sp8->unk_0 = FUN_02006BB0(NARC_GRAPHIC_FONT, 4, 1, &sp8->unk_4, r4);
+ int i;
+ u8 * ptr = sp8->unk_4->unk_14;
+ for (i = 0; i < sp8->unk_4->unk_10; i++)
+ {
+ switch (ptr[i])
+ {
+ case 0x00:
+ ptr[i] = (u8)((sp4 << 4) | sp4);
+ break;
+ case 0x01:
+ ptr[i] = (u8)((sp4 << 4) | r5);
+ break;
+ case 0x02:
+ ptr[i] = (u8)((sp4 << 4) | r6);
+ break;
+ case 0x10:
+ ptr[i] = (u8)((r5 << 4) | sp4);
+ break;
+ case 0x11:
+ ptr[i] = (u8)((r5 << 4) | r5);
+ break;
+ case 0x12:
+ ptr[i] = (u8)((r5 << 4) | r6);
+ break;
+ case 0x20:
+ ptr[i] = (u8)((r6 << 4) | sp4);
+ break;
+ case 0x21:
+ ptr[i] = (u8)((r6 << 4) | r5);
+ break;
+ case 0x22:
+ ptr[i] = (u8)((r6 << 4) | r6);
+ break;
+ }
+ }
+ sp8->unk_28 = sp4;
+ }
+ return sp8;
+}
+
+void FUN_0200B990(struct UnkStruct_0200B870 * a0)
+{
+ if (a0 != NULL)
+ {
+ if (a0->unk_0 != NULL)
+ FreeToHeap(a0->unk_0);
+ FreeToHeap(a0);
+ }
+}
+
+void FUN_0200B9A8(struct UnkStruct_0200B870 * a0, int a1, int a2, int a3, int a4)
+{
+ FUN_02019658(a2, a0->unk_4->unk_14 + UNK_020ECE6C[a1][0], 0, 0, UNK_020ECE6C[a1][1], 8, (u16)a3, (u16)a4, UNK_020ECE6C[a1][1], 8);
+}
+
+void FUN_0200B9EC(struct UnkStruct_0200B870 * string, u32 value, u32 n, enum PrintingMode mode, int sp30, int r5, int r7)
+{
+ ConvertUIntToDecimalString(string->data, value, mode, n);
+ for (int i = 0; string->data[i] != EOS; i++)
+ {
+ if (string->data[i] >= 0x00A2 && string->data[i] <= 0x00AB)
+ {
+ FUN_02019658(sp30, string->unk_4->unk_14 + (string->data[i] - 0x00A2) * 32, 0, 0, 8, 8, (u16)r5, (u16)r7, 8, 8);
+ }
+ else
+ {
+ FUN_020196F4(sp30, (u8)string->unk_28, (u16)r5, (u16)r7, 8, 8);
+ }
+ r5 += 8;
+ }
+}
diff --git a/arm9/src/unk_0200CA44.c b/arm9/src/unk_0200CA44.c
index 86dac59d..fc4656b2 100644
--- a/arm9/src/unk_0200CA44.c
+++ b/arm9/src/unk_0200CA44.c
@@ -2,7 +2,7 @@
#include "main.h"
#include "unk_0200CA44.h"
-extern void FUN_0201B60C(s32, void (*)(void *, void *), void *, void *);
+extern void FUN_0201B60C(void *, void (*)(void *, void *), void *, void *);
extern void FUN_0201B6A0(s32);
THUMB_FUNC void FUN_0200CA44(void (*r0)(void *, void *), void * r1, void * r2)
diff --git a/arm9/src/unk_020286F8.c b/arm9/src/unk_020286F8.c
new file mode 100644
index 00000000..f54d1e2e
--- /dev/null
+++ b/arm9/src/unk_020286F8.c
@@ -0,0 +1,150 @@
+#include "global.h"
+#include "save_block_2.h"
+#include "MI_memory.h"
+#include "string_util.h"
+#include "math_util.h"
+#include "string16.h"
+#include "unk_020286F8.h"
+
+#pragma thumb on
+
+struct UnkSaveStruct_020286F8 * UNK_021C59D0;
+
+u32 FUN_020286F8(void)
+{
+ return 6 * sizeof(struct UnkSaveStruct_020286F8);
+}
+
+void FUN_02028700(struct UnkSaveStruct_020286F8 * ptr, int a, int b)
+{
+ ptr[b] = ptr[a];
+}
+
+void FUN_02028724(struct UnkSaveStruct_020286F8 * ptr)
+{
+ MI_CpuClearFast(ptr, 6 * sizeof(struct UnkSaveStruct_020286F8));
+ for (int i = 0; i < 6; i++)
+ {
+ ptr[i].unk_0[0] = EOS;
+ ptr[i].unk_10[0] = EOS;
+ }
+ UNK_021C59D0 = ptr;
+}
+
+void FUN_02028754(struct UnkSaveStruct_020286F8 * ptr, u32 n)
+{
+ u32 i, j;
+ for (i = 0; i < 6; i++)
+ {
+ for (j = 0; j < n; j++)
+ {
+ ptr[i].unk_28 = PRandom(ptr[i].unk_28);
+ }
+ }
+}
+
+u32 FUN_0202877C(struct UnkSaveStruct_020286F8 * ptr, u32 i)
+{
+ return ptr[i].unk_24;
+}
+
+void FUN_02028788(struct UnkSaveStruct_020286F8 * ptr, u32 i, u32 j)
+{
+ ptr[i].unk_24 = j;
+ ptr[i].unk_28 = PRandom(j);
+}
+
+u32 FUN_020287A4(struct UnkSaveStruct_020286F8 * ptr)
+{
+ return ptr[1].unk_28;
+}
+
+u16 * FUN_020287A8(struct UnkSaveStruct_020286F8 * ptr, u32 i, u32 j)
+{
+ if (j == 0)
+ return ptr[i].unk_0;
+ else
+ return ptr[i].unk_10;
+}
+
+void FUN_020287C0(struct UnkSaveStruct_020286F8 * ptr, u32 i, u32 j, struct String * k)
+{
+ if (j == 0)
+ CopyStringToU16Array(k, ptr[i].unk_0, 8);
+ else
+ CopyStringToU16Array(k, ptr[i].unk_10, 8);
+}
+
+void FUN_020287EC(struct UnkSaveStruct_020286F8 * ptr, u32 i, u8 j)
+{
+ ptr[i].unk_20 = j;
+}
+
+u8 FUN_020287F8(struct UnkSaveStruct_020286F8 * ptr, u32 i)
+{
+ return ptr[i].unk_20;
+}
+
+u8 FUN_02028804(struct UnkSaveStruct_020286F8 * ptr, u32 i)
+{
+ return ptr[i].unk_21;
+}
+
+
+void FUN_02028810(struct UnkSaveStruct_020286F8 * ptr, u32 i, u8 j)
+{
+ ptr[i].unk_21 = j;
+}
+
+struct UnkSaveStruct_020286F8 * FUN_0202881C(struct SaveBlock2 * sav2)
+{
+ return (struct UnkSaveStruct_020286F8 *)SavArray_get(sav2, 17);
+}
+
+BOOL FUN_0202888C(struct UnkSaveStruct_020286F8 * ptr);
+
+BOOL FUN_02028828(struct UnkSaveStruct_020286F8 * ptr, u32 i)
+{
+ return !FUN_0202888C(&ptr[i]);
+}
+
+BOOL FUN_020288AC(struct UnkSaveStruct_020286F8 * ptr, struct UnkSaveStruct_020286F8 * ptr2);
+
+BOOL FUN_02028840(struct UnkSaveStruct_020286F8 * ptr, int i)
+{
+ return FUN_020288AC(&ptr[1], &ptr[i]);
+}
+
+BOOL FUN_02028854(struct UnkSaveStruct_020286F8 * ptr, const u16 * str)
+{
+ if (str[0] == EOS)
+ return FALSE;
+ for (int i = 0; i < 6; i++)
+ {
+ if (!StringNotEqualN(str, ptr[i].unk_0, 8))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL FUN_0202888C(struct UnkSaveStruct_020286F8 * ptr)
+{
+ if (ptr->unk_0[0] == EOS)
+ return TRUE;
+ if (ptr->unk_10[0] == EOS)
+ return TRUE;
+ return FALSE;
+}
+
+BOOL FUN_020288AC(struct UnkSaveStruct_020286F8 * ptr, struct UnkSaveStruct_020286F8 * ptr2)
+{
+ if (StringNotEqualN(ptr->unk_10, ptr2->unk_10, 8))
+ return FALSE;
+ if (StringNotEqualN(ptr->unk_0, ptr2->unk_0, 8))
+ return FALSE;
+ if (ptr->unk_20 != ptr2->unk_20)
+ return FALSE;
+ if (ptr->unk_21 != ptr2->unk_21)
+ return FALSE;
+ return ptr->unk_24 == ptr2->unk_24;
+}