summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSwastik Baranwal <swstkbaranwal@gmail.com>2019-06-23 18:47:35 +0530
committerGitHub <noreply@github.com>2019-06-23 18:47:35 +0530
commit99703c6ab831d34e6859d8a8f53ba8e73dc4d3d9 (patch)
tree3a712d3039d152616af58a45a13d82c40a87e58f /src
parent6d190f861e3559eec922cd760778c0cba6e08397 (diff)
parent9ee0c34758a63f8c00724b6fc984b4e96be2f7af (diff)
Merge pull request #5 from pret/master
Take files
Diffstat (limited to 'src')
-rw-r--r--src/bag.c321
-rw-r--r--src/battle_ai_script_commands.c6
-rw-r--r--src/battle_anim_mon_movement.c809
-rw-r--r--src/berry.c169
-rw-r--r--src/berry_fix_program.c191
-rw-r--r--src/berry_powder.c132
-rw-r--r--src/blend_palette.c46
-rw-r--r--src/blit.c212
-rw-r--r--src/braille_text.c222
-rw-r--r--src/cereader_tool.c88
-rw-r--r--src/coins.c6
-rw-r--r--src/coord_event_weather.c47
-rw-r--r--src/data/items.json6062
-rw-r--r--src/data/items.json.txt31
-rw-r--r--src/data/pokemon/egg_moves.h1310
-rw-r--r--src/daycare.c2209
-rw-r--r--src/dodrio_berry_picking_2.c23
-rw-r--r--src/egg_hatch.c878
-rw-r--r--src/ereader_helpers.c397
-rw-r--r--src/fame_checker.c69
-rw-r--r--src/fieldmap.c1025
-rw-r--r--src/fldeff_berrytree.c4
-rw-r--r--src/fldeff_softboiled.c109
-rw-r--r--src/fldeff_teleport.c42
-rw-r--r--src/heal_location.c176
-rw-r--r--src/help_system.c1202
-rw-r--r--src/help_system_812B1E0.c1580
-rw-r--r--src/item.c684
-rw-r--r--src/item_menu_icons.c783
-rw-r--r--src/item_pc.c1150
-rw-r--r--src/item_use.c880
-rw-r--r--src/load_save.c6
-rw-r--r--src/m4a.c1779
-rw-r--r--src/m4a_2.c912
-rw-r--r--src/m4a_4.c545
-rw-r--r--src/main.c16
-rw-r--r--src/map_obj_lock.c116
-rw-r--r--src/menews_jisan.c140
-rw-r--r--src/menu2.c851
-rw-r--r--src/mevent.c246
-rw-r--r--src/mevent_8145654.c60
-rw-r--r--src/mevent_server.c92
-rw-r--r--src/money.c4
-rw-r--r--src/mystery_event_msg.c2
-rw-r--r--src/mystery_gift_menu.c1756
-rw-r--r--src/oak_speech.c1891
-rw-r--r--src/pokemon.c42
-rw-r--r--src/prof_pc.c108
-rw-r--r--src/quest_log.c76
-rw-r--r--src/quest_log_battle.c10
-rw-r--r--src/roamer.c240
-rw-r--r--src/roulette_util.c463
-rw-r--r--src/save.c6
-rw-r--r--src/scanline_effect.c262
-rw-r--r--src/scrcmd.c2267
-rw-r--r--src/script.c10
-rw-r--r--src/seagallop.c499
-rw-r--r--src/sound.c18
-rw-r--r--src/ss_anne.c200
-rw-r--r--src/teachy_tv.c1416
-rw-r--r--src/text.c24
-rw-r--r--src/text_printer.c14
-rw-r--r--src/text_window.c169
-rw-r--r--src/text_window_graphics.c60
-rw-r--r--src/tm_case.c1537
-rw-r--r--src/trainer_pokemon_sprites.c324
-rw-r--r--src/trainer_tower.c961
-rw-r--r--src/trig.c543
-rw-r--r--src/unk_8159F40.c622
-rw-r--r--src/unk_815C980.c437
-rw-r--r--src/unk_815F138.c322
-rw-r--r--src/util.c513
-rw-r--r--src/vs_seeker.c240
-rw-r--r--src/window.c50
-rw-r--r--src/window_8bpp.c18
-rw-r--r--src/wireless_communication_status_screen.c436
76 files changed, 39130 insertions, 2036 deletions
diff --git a/src/bag.c b/src/bag.c
new file mode 100644
index 000000000..f2fc40d93
--- /dev/null
+++ b/src/bag.c
@@ -0,0 +1,321 @@
+#include "global.h"
+#include "task.h"
+#include "palette.h"
+#include "item_menu.h"
+#include "text.h"
+#include "window.h"
+#include "text_window.h"
+#include "menu_helpers.h"
+#include "menu.h"
+#include "money.h"
+#include "bag.h"
+
+extern const u8 gText_DepositItem[];
+
+const u16 gUnknown_8453098[] = INCBIN_U16("data/bag/bag_window_pal.gbapal");
+const struct TextColor gUnknown_84530B8[] = {
+ {0, 1, 2},
+ {0, 2, 3},
+ {0, 3, 2},
+ {0, 8, 9}
+};
+const struct WindowTemplate gUnknown_84530C4[] = {
+ {
+ .bg = 0,
+ .tilemapLeft = 0x0b,
+ .tilemapTop = 0x01,
+ .width = 0x12,
+ .height = 0x0c,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x008a
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x05,
+ .tilemapTop = 0x0e,
+ .width = 0x19,
+ .height = 0x06,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0162
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x01,
+ .width = 0x09,
+ .height = 0x02,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x01f8
+ }, DUMMY_WIN_TEMPLATE
+};
+const struct WindowTemplate gUnknown_84530E4[] = {
+ {
+ .bg = 0,
+ .tilemapLeft = 0x0b,
+ .tilemapTop = 0x01,
+ .width = 0x12,
+ .height = 0x0c,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x008a
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x05,
+ .tilemapTop = 0x0e,
+ .width = 0x19,
+ .height = 0x06,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0162
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x01,
+ .width = 0x08,
+ .height = 0x02,
+ .paletteNum = 0x0C,
+ .baseBlock = 0x01f8
+ }, DUMMY_WIN_TEMPLATE
+};
+const struct WindowTemplate gUnknown_8453104[] = {
+ {
+ .bg = 0,
+ .tilemapLeft = 24,
+ .tilemapTop = 15,
+ .width = 5,
+ .height = 4,
+ .paletteNum = 0xF,
+ .baseBlock = 0x242
+ }, {
+ .bg = 0,
+ .tilemapLeft = 17,
+ .tilemapTop = 9,
+ .width = 12,
+ .height = 4,
+ .paletteNum = 0xF,
+ .baseBlock = 0x242
+ }, {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 1,
+ .width = 8,
+ .height = 3,
+ .paletteNum = 0xC,
+ .baseBlock = 0x272
+ }
+};
+
+const struct WindowTemplate gUnknown_845311C = {
+ .bg = 0,
+ .tilemapLeft = 23,
+ .tilemapTop = 15,
+ .width = 6,
+ .height = 4,
+ .paletteNum = 0xF,
+ .baseBlock = 0x28a
+};
+
+const struct WindowTemplate gUnknown_8453124 = {
+ .bg = 0,
+ .tilemapLeft = 21,
+ .tilemapTop = 9,
+ .width = 6,
+ .height = 4,
+ .paletteNum = 0xF,
+ .baseBlock = 0x28a
+};
+
+const struct WindowTemplate gUnknown_845312C[] = {
+ {
+ .bg = 0x00,
+ .tilemapLeft = 0x02,
+ .tilemapTop = 0x0f,
+ .width = 0x1a,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x02a2
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0f,
+ .width = 0x0e,
+ .height = 0x04,
+ .paletteNum = 0x0c,
+ .baseBlock = 0x02a2
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0f,
+ .width = 0x0f,
+ .height = 0x04,
+ .paletteNum = 0x0c,
+ .baseBlock = 0x02da
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0f,
+ .width = 0x10,
+ .height = 0x04,
+ .paletteNum = 0x0c,
+ .baseBlock = 0x0316
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0f,
+ .width = 0x17,
+ .height = 0x04,
+ .paletteNum = 0x0c,
+ .baseBlock = 0x0356
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x11,
+ .width = 0x07,
+ .height = 0x02,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x020a
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0f,
+ .width = 0x07,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x020a
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0d,
+ .width = 0x07,
+ .height = 0x06,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x020a
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0b,
+ .width = 0x07,
+ .height = 0x08,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x020a
+ }
+};
+
+const u8 gUnknown_8453174[] = {16, 8, 4};
+
+EWRAM_DATA u8 gUnknown_203AD34[11] = {};
+
+void sub_810B858(void)
+{
+ u8 i;
+
+ if (gUnknown_203ACFC.location != 3)
+ InitWindows(gUnknown_84530C4);
+ else
+ InitWindows(gUnknown_84530E4);
+ DeactivateAllTextPrinters();
+ TextWindow_SetUserSelectedFrame(0, 0x64, 0xE0);
+ TextWindow_SetBubbleFrame_841F1C8(0, 0x6D, 0xD0);
+ TextWindow_SetStdFrame0_WithPal(0, 0x81, 0xC0);
+ LoadPalette(gUnknown_8453098, 0xF0, 0x20);
+ for (i = 0; i < 3; i++)
+ {
+ FillWindowPixelBuffer(i, 0x00);
+ PutWindowTilemap(i);
+ }
+ schedule_bg_copy_tilemap_to_vram(0);
+ for (i = 0; i < 11; i++)
+ {
+ gUnknown_203AD34[i] = 0xFF;
+ }
+}
+
+void sub_810B8F0(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, s8 speed, u8 colorIdx)
+{
+ AddTextPrinterParameterized4(windowId, fontId, x, y, letterSpacing, lineSpacing, &gUnknown_84530B8[colorIdx], speed, str);
+}
+
+void sub_810B958(const u8 * str)
+{
+ u32 x = 0x48 - GetStringWidth(1, str, 0);
+ AddTextPrinterParameterized3(2, 1, x / 2, 1, &gUnknown_84530B8[0], 0, str);
+}
+
+void sub_810B994(void)
+{
+ u32 x;
+ SetWindowBorderStyle(2, FALSE, 0x081, 0x0C);
+ x = 0x40 - GetStringWidth(0, gText_DepositItem, 0);
+ AddTextPrinterParameterized(2, 0, gText_DepositItem, x / 2, 1, 0, NULL);
+}
+
+u8 sub_810B9DC(u8 a0, u8 a1)
+{
+ if (gUnknown_203AD34[a0] == 0xFF)
+ {
+ gUnknown_203AD34[a0] = AddWindow(&gUnknown_8453104[a0 + a1]);
+ if (a0 != 6)
+ {
+ SetWindowBorderStyle(gUnknown_203AD34[a0], FALSE, 0x064, 0x0E);
+ }
+ else
+ {
+ SetWindowBorderStyle(gUnknown_203AD34[a0], FALSE, 0x081, 0x0C);
+ }
+ schedule_bg_copy_tilemap_to_vram(0);
+ }
+ return gUnknown_203AD34[a0];
+}
+
+void sub_810BA3C(u8 a0)
+{
+ ClearMenuWindow(gUnknown_203AD34[a0], FALSE);
+ ClearWindowTilemap(gUnknown_203AD34[a0]);
+ RemoveWindow(gUnknown_203AD34[a0]);
+ schedule_bg_copy_tilemap_to_vram(0);
+ gUnknown_203AD34[a0] = 0xFF;
+}
+
+u8 sub_810BA70(u8 a0)
+{
+ if (gUnknown_203AD34[a0] == 0xFF)
+ {
+ gUnknown_203AD34[a0] = AddWindow(&gUnknown_8453104[a0]);
+ }
+ return gUnknown_203AD34[a0];
+}
+
+void sub_810BA9C(u8 a0)
+{
+ if (gUnknown_203AD34[a0] != 0xFF)
+ {
+ ClearMenuWindow_BorderThickness2(gUnknown_203AD34[a0], FALSE);
+ ClearWindowTilemap(gUnknown_203AD34[a0]);
+ RemoveWindow(gUnknown_203AD34[a0]);
+ PutWindowTilemap(1);
+ schedule_bg_copy_tilemap_to_vram(0);
+ gUnknown_203AD34[a0] = 0xFF;
+
+ }
+}
+
+u8 sub_810BAD8(u8 a0)
+{
+ return gUnknown_203AD34[a0];
+}
+
+void sub_810BAE8(u8 taskId, const struct YesNoFuncTable * ptrs)
+{
+ CreateYesNoMenuWithCallbacks(taskId, &gUnknown_845311C, 2, 0, 2, 0x64, 0x0E, ptrs);
+}
+
+void sub_810BB14(u8 taskId, const struct YesNoFuncTable * ptrs)
+{
+ CreateYesNoMenuWithCallbacks(taskId, &gUnknown_8453124, 2, 0, 2, 0x064, 0x0E, ptrs);
+}
+
+void sub_810BB40(void)
+{
+ PrintMoneyAmountInMoneyBoxWithBorder(sub_810B9DC(2, 0), 0x081, 0x0C, GetMoney(&gSaveBlock1Ptr->money));
+}
+
+void sub_810BB74(u8 windowId)
+{
+ DrawTextBorderOuter(windowId, 0x064, 0x0E);
+}
diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c
index 6f5577f70..6343b55cd 100644
--- a/src/battle_ai_script_commands.c
+++ b/src/battle_ai_script_commands.c
@@ -1623,7 +1623,7 @@ static void BattleAICmd_if_status_not_in_party(void)
enum
{
- WEATHER_TYPE_SUN,
+ WEATHER_TYPE_SUNNY,
WEATHER_TYPE_RAIN,
WEATHER_TYPE_SANDSTORM,
WEATHER_TYPE_HAIL,
@@ -1637,8 +1637,8 @@ static void BattleAICmd_get_weather(void)
AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_RAIN;
if (gBattleWeather & WEATHER_SANDSTORM_ANY)
AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_SANDSTORM;
- if (gBattleWeather & WEATHER_SUN_ANY)
- AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_SUN;
+ if (gBattleWeather & WEATHER_SUNNY_ANY)
+ AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_SUNNY;
if (gBattleWeather & WEATHER_HAIL)
AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_HAIL;
diff --git a/src/battle_anim_mon_movement.c b/src/battle_anim_mon_movement.c
new file mode 100644
index 000000000..27e6ef28c
--- /dev/null
+++ b/src/battle_anim_mon_movement.c
@@ -0,0 +1,809 @@
+#include "global.h"
+#include "battle.h"
+#include "battle_anim.h"
+#include "task.h"
+#include "trig.h"
+
+#define abs(x) ((x) < 0 ? -(x) : (x))
+
+void sub_8098A6C(u8 taskId);
+void sub_8098C08(u8 taskId);
+void sub_8098D54(u8 taskId);
+void sub_8098EF0(u8 taskId);
+void sub_8099004(u8 taskId);
+void sub_80990AC(struct Sprite * sprite);
+void sub_8099120(struct Sprite * sprite);
+void sub_8099144(struct Sprite * sprite);
+void sub_8099190(struct Sprite * sprite);
+void sub_80991B4(struct Sprite * sprite);
+void sub_8099270(struct Sprite * sprite);
+void sub_80992E0(struct Sprite * sprite);
+void sub_8099394(struct Sprite * sprite);
+void sub_809946C(struct Sprite * sprite);
+void sub_8099530(u8 taskId);
+void sub_8099594(u8 taskId);
+void sub_80996B8(u8 taskId);
+void sub_8099788(u8 taskId);
+void sub_8099908(u8 taskId);
+void sub_8099B54(u8 taskId);
+void sub_8099CB8(u8 taskId);
+
+const struct SpriteTemplate gUnknown_83D4E4C[] = {
+ {
+ 0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_80990AC
+ }, {
+ 0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_8099144
+ }, {
+ 0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_80991B4
+ }, {
+ 0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_80992E0
+ }, {
+ 0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_8099394
+ }
+};
+
+void sub_80989F8(u8 taskId)
+{
+ u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
+
+ if (spriteId == 0xFF)
+ DestroyAnimVisualTask(taskId);
+ else
+ {
+ gSprites[spriteId].pos2.x = gBattleAnimArgs[1];
+ gSprites[spriteId].pos2.y = gBattleAnimArgs[2];
+ gTasks[taskId].data[0] = spriteId;
+ gTasks[taskId].data[1] = gBattleAnimArgs[3];
+ gTasks[taskId].data[2] = gBattleAnimArgs[4];
+ gTasks[taskId].data[3] = gBattleAnimArgs[4];
+ gTasks[taskId].data[4] = gBattleAnimArgs[1];
+ gTasks[taskId].data[5] = gBattleAnimArgs[2];
+ gTasks[taskId].func = sub_8098A6C;
+ gTasks[taskId].func(taskId);
+ }
+}
+
+void sub_8098A6C(u8 taskId)
+{
+ if (gTasks[taskId].data[3] == 0)
+ {
+ if (gSprites[gTasks[taskId].data[0]].pos2.x == 0)
+ gSprites[gTasks[taskId].data[0]].pos2.x = gTasks[taskId].data[4];
+ else
+ gSprites[gTasks[taskId].data[0]].pos2.x = 0;
+ if (gSprites[gTasks[taskId].data[0]].pos2.y == 0)
+ gSprites[gTasks[taskId].data[0]].pos2.y = gTasks[taskId].data[5];
+ else
+ gSprites[gTasks[taskId].data[0]].pos2.y = 0;
+ gTasks[taskId].data[3] = gTasks[taskId].data[2];
+ if (--gTasks[taskId].data[1] == 0)
+ {
+ gSprites[gTasks[taskId].data[0]].pos2.x = 0;
+ gSprites[gTasks[taskId].data[0]].pos2.y = 0;
+ DestroyAnimVisualTask(taskId);
+ }
+ }
+ else
+ gTasks[taskId].data[3]--;
+}
+
+void sub_8098B1C(u8 taskId)
+{
+ bool8 abort = FALSE;
+ u8 spriteId;
+ u8 battlerId;
+
+ if (gBattleAnimArgs[0] < MAX_BATTLERS_COUNT)
+ {
+ spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
+ if (spriteId == 0xFF)
+ abort = TRUE;
+ }
+ else if (gBattleAnimArgs[0] != 8)
+ {
+ switch (gBattleAnimArgs[0])
+ {
+ case 4:
+ battlerId = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
+ break;
+ case 5:
+ battlerId = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
+ break;
+ case 6:
+ battlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
+ break;
+ default:
+ battlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
+ break;
+ }
+ if (!sub_8072DF0(battlerId))
+ abort = TRUE;
+ spriteId = gBattlerSpriteIds[battlerId];
+ }
+ else
+ spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
+ if (abort)
+ DestroyAnimVisualTask(taskId);
+ else
+ {
+ gSprites[spriteId].pos2.x = gBattleAnimArgs[1];
+ gSprites[spriteId].pos2.y = gBattleAnimArgs[2];
+ gTasks[taskId].data[0] = spriteId;
+ gTasks[taskId].data[1] = gBattleAnimArgs[3];
+ gTasks[taskId].data[2] = gBattleAnimArgs[4];
+ gTasks[taskId].data[3] = gBattleAnimArgs[4];
+ gTasks[taskId].data[4] = gBattleAnimArgs[1];
+ gTasks[taskId].data[5] = gBattleAnimArgs[2];
+ gTasks[taskId].func = sub_8098C08;
+ gTasks[taskId].func(taskId);
+ }
+}
+
+void sub_8098C08(u8 taskId)
+{
+ if (gTasks[taskId].data[3] == 0)
+ {
+ if (gSprites[gTasks[taskId].data[0]].pos2.x == gTasks[taskId].data[4])
+ gSprites[gTasks[taskId].data[0]].pos2.x = -gTasks[taskId].data[4];
+ else
+ gSprites[gTasks[taskId].data[0]].pos2.x = gTasks[taskId].data[4];
+ if (gSprites[gTasks[taskId].data[0]].pos2.y == gTasks[taskId].data[5])
+ gSprites[gTasks[taskId].data[0]].pos2.y = -gTasks[taskId].data[5];
+ else
+ gSprites[gTasks[taskId].data[0]].pos2.y = gTasks[taskId].data[5];
+ gTasks[taskId].data[3] = gTasks[taskId].data[2];
+ if (--gTasks[taskId].data[1] == 0)
+ {
+ gSprites[gTasks[taskId].data[0]].pos2.x = 0;
+ gSprites[gTasks[taskId].data[0]].pos2.y = 0;
+ DestroyAnimVisualTask(taskId);
+ }
+ }
+ else
+ gTasks[taskId].data[3]--;
+}
+
+void sub_8098CD0(u8 taskId)
+{
+ u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
+
+ if (spriteId == 0xFF)
+ DestroyAnimVisualTask(taskId);
+ else
+ {
+ gSprites[spriteId].pos2.x += gBattleAnimArgs[1];
+ gSprites[spriteId].pos2.y += gBattleAnimArgs[2];
+ gTasks[taskId].data[0] = spriteId;
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].data[2] = gBattleAnimArgs[3];
+ gTasks[taskId].data[3] = 0;
+ gTasks[taskId].data[4] = gBattleAnimArgs[4];
+ gTasks[taskId].data[5] = gBattleAnimArgs[1] * 2;
+ gTasks[taskId].data[6] = gBattleAnimArgs[2] * 2;
+ gTasks[taskId].func = sub_8098D54;
+ gTasks[taskId].func(taskId);
+ }
+}
+
+void sub_8098D54(u8 taskId)
+{
+ if (gTasks[taskId].data[3] == 0)
+ {
+ if (gTasks[taskId].data[1] & 1)
+ {
+ gSprites[gTasks[taskId].data[0]].pos2.x += gTasks[taskId].data[5];
+ gSprites[gTasks[taskId].data[0]].pos2.y += gTasks[taskId].data[6];
+ }
+ else
+ {
+ gSprites[gTasks[taskId].data[0]].pos2.x -= gTasks[taskId].data[5];
+ gSprites[gTasks[taskId].data[0]].pos2.y -= gTasks[taskId].data[6];
+ }
+ gTasks[taskId].data[3] = gTasks[taskId].data[4];
+ if (++gTasks[taskId].data[1] >= gTasks[taskId].data[2])
+ {
+ if (gTasks[taskId].data[1] & 1)
+ {
+ gSprites[gTasks[taskId].data[0]].pos2.x += gTasks[taskId].data[5] / 2;
+ gSprites[gTasks[taskId].data[0]].pos2.y += gTasks[taskId].data[6] / 2;
+ }
+ else
+ {
+ gSprites[gTasks[taskId].data[0]].pos2.x -= gTasks[taskId].data[5] / 2;
+ gSprites[gTasks[taskId].data[0]].pos2.y -= gTasks[taskId].data[6] / 2;
+ }
+ DestroyAnimVisualTask(taskId);
+ }
+ }
+ else
+ gTasks[taskId].data[3]--;
+}
+
+void sub_8098E90(u8 taskId)
+{
+ u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
+
+ gSprites[spriteId].pos2.x = gBattleAnimArgs[1];
+ gTasks[taskId].data[0] = spriteId;
+ gTasks[taskId].data[1] = gBattleAnimArgs[1];
+ gTasks[taskId].data[2] = gBattleAnimArgs[2];
+ gTasks[taskId].data[3] = gBattleAnimArgs[3];
+ gTasks[taskId].data[4] = gBattleAnimArgs[4];
+ gTasks[taskId].func = sub_8098EF0;
+ gTasks[taskId].func(taskId);
+}
+
+void sub_8098EF0(u8 taskId)
+{
+ u8 spriteId = gTasks[taskId].data[0];
+ s16 data1 = gTasks[taskId].data[1];
+ if (gTasks[taskId].data[2] == gTasks[taskId].data[8]++)
+ {
+ gTasks[taskId].data[8] = 0;
+ if (gSprites[spriteId].pos2.x == data1)
+ data1 = -data1;
+ gSprites[spriteId].pos2.x += data1;
+ }
+ gTasks[taskId].data[1] = data1;
+ gTasks[taskId].data[9] += gTasks[taskId].data[3];
+ gSprites[spriteId].pos2.y = gTasks[taskId].data[9] >> 8;
+ if (--gTasks[taskId].data[4] == 0)
+ DestroyAnimVisualTask(taskId);
+}
+
+void sub_8098F84(u8 taskId)
+{
+ u8 r6 = 1;
+ u8 i;
+ u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
+ if (gBattleAnimArgs[4] > 5)
+ gBattleAnimArgs[4] = 5;
+ for (i = 0; i < gBattleAnimArgs[4]; i++)
+ r6 *= 2;
+ gTasks[taskId].data[0] = spriteId;
+ gTasks[taskId].data[1] = gBattleAnimArgs[1];
+ gTasks[taskId].data[2] = gBattleAnimArgs[2];
+ gTasks[taskId].data[3] = gBattleAnimArgs[3];
+ gTasks[taskId].data[4] = r6;
+ gTasks[taskId].func = sub_8099004;
+ gTasks[taskId].func(taskId);
+}
+
+void sub_8099004(u8 taskId)
+{
+ u8 spriteId = gTasks[taskId].data[0];
+ gSprites[spriteId].pos2.x = Sin(gTasks[taskId].data[5], gTasks[taskId].data[1]);
+ gSprites[spriteId].pos2.y = -Cos(gTasks[taskId].data[5], gTasks[taskId].data[2]);
+ gSprites[spriteId].pos2.y += gTasks[taskId].data[2];
+ gTasks[taskId].data[5] += gTasks[taskId].data[4];
+ gTasks[taskId].data[5] &= 0xFF;
+ if (gTasks[taskId].data[5] == 0)
+ gTasks[taskId].data[3]--;
+ if (gTasks[taskId].data[3] == 0)
+ {
+ gSprites[spriteId].pos2.x = 0;
+ gSprites[spriteId].pos2.y = 0;
+ DestroyAnimVisualTask(taskId);
+ }
+}
+
+void sub_809907C(u8 taskId)
+{
+ if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ sub_8098F84(taskId);
+}
+
+void sub_80990AC(struct Sprite * sprite)
+{
+ sprite->invisible = TRUE;
+ if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ sprite->data[1] = -gBattleAnimArgs[1];
+ else
+ sprite->data[1] = gBattleAnimArgs[1];
+ sprite->data[0] = gBattleAnimArgs[0];
+ sprite->data[2] = 0;
+ sprite->data[3] = gBattlerSpriteIds[gBattleAnimAttacker];
+ sprite->data[4] = gBattleAnimArgs[0];
+ StoreSpriteCallbackInData6(sprite, sub_8099120);
+ sprite->callback = sub_8074DC4;
+}
+
+void sub_8099120(struct Sprite * sprite)
+{
+ sprite->data[0] = sprite->data[4];
+ sprite->data[1] = -sprite->data[1];
+ sprite->callback = sub_8074DC4;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+void sub_8099144(struct Sprite * sprite)
+{
+ u8 spriteId;
+ sprite->invisible = TRUE;
+ spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]);
+ sprite->data[0] = gBattleAnimArgs[0];
+ sprite->data[1] = 0;
+ sprite->data[2] = gBattleAnimArgs[1];
+ sprite->data[3] = spriteId;
+ sprite->data[4] = gBattleAnimArgs[0];
+ StoreSpriteCallbackInData6(sprite, sub_8099190);
+ sprite->callback = sub_8074DC4;
+}
+
+void sub_8099190(struct Sprite * sprite)
+{
+ sprite->data[0] = sprite->data[4];
+ sprite->data[2] = -sprite->data[2];
+ sprite->callback = sub_8074DC4;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+}
+
+void sub_80991B4(struct Sprite * sprite)
+{
+ u8 spriteId;
+ if (gBattleAnimArgs[0] == 0)
+ spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
+ else
+ spriteId = gBattlerSpriteIds[gBattleAnimTarget];
+ sprite->data[0] = gBattleAnimArgs[2];
+ sprite->data[1] = gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x;
+ sprite->data[2] = gSprites[spriteId].pos1.x;
+ sprite->data[3] = gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y;
+ sprite->data[4] = gSprites[spriteId].pos1.y;
+ sub_80754B8(sprite);
+ sprite->data[3] = 0;
+ sprite->data[4] = 0;
+ sprite->data[5] = gSprites[spriteId].pos2.x;
+ sprite->data[6] = gSprites[spriteId].pos2.y;
+ sprite->invisible = TRUE;
+ if (gBattleAnimArgs[1] == 1)
+ sprite->data[2] = 0;
+ else if (gBattleAnimArgs[1] == 2)
+ sprite->data[1] = 0;
+ sprite->data[7] = gBattleAnimArgs[1];
+ sprite->data[7] |= spriteId << 8;
+ sprite->callback = sub_8099270;
+}
+
+void sub_8099270(struct Sprite * sprite)
+{
+ u8 data7 = sprite->data[7];
+ struct Sprite *otherSprite = &gSprites[sprite->data[7] >> 8];
+ if (sprite->data[0] == 0)
+ {
+ if (data7 == 1 || data7 == 0)
+ otherSprite->pos2.x = 0;
+ if (data7 == 2 || data7 == 0)
+ otherSprite->pos2.y = 0;
+ DestroyAnimSprite(sprite);
+ }
+ else
+ {
+ sprite->data[0]--;
+ sprite->data[3] += sprite->data[1];
+ sprite->data[4] += sprite->data[2];
+ otherSprite->pos2.x = (sprite->data[3] >> 8) + sprite->data[5];
+ otherSprite->pos2.y = (sprite->data[4] >> 8) + sprite->data[6];
+ }
+}
+
+void sub_80992E0(struct Sprite * sprite)
+{
+ u8 battlerId;
+ u8 spriteId;
+ if (gBattleAnimArgs[0] == 0)
+ battlerId = gBattleAnimAttacker;
+ else
+ battlerId = gBattleAnimTarget;
+ spriteId = gBattlerSpriteIds[battlerId];
+ if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
+ {
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ if (gBattleAnimArgs[3] == 1)
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ }
+ sprite->data[0] = gBattleAnimArgs[4];
+ sprite->data[1] = gSprites[spriteId].pos1.x;
+ sprite->data[2] = gSprites[spriteId].pos1.x + gBattleAnimArgs[1];
+ sprite->data[3] = gSprites[spriteId].pos1.y;
+ sprite->data[4] = gSprites[spriteId].pos1.y + gBattleAnimArgs[2];
+ sub_80754B8(sprite);
+ sprite->data[3] = 0;
+ sprite->data[4] = 0;
+ sprite->data[5] = spriteId;
+ sprite->invisible = TRUE;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+ sprite->callback = sub_8074E14;
+}
+
+void sub_8099394(struct Sprite * sprite)
+{
+ u8 battlerId;
+ u8 spriteId;
+ sprite->invisible = TRUE;
+ if (gBattleAnimArgs[0] == 0)
+ battlerId = gBattleAnimAttacker;
+ else
+ battlerId = gBattleAnimTarget;
+ spriteId = gBattlerSpriteIds[battlerId];
+ if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
+ {
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ if (gBattleAnimArgs[3] == 1)
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ }
+ sprite->data[0] = gBattleAnimArgs[4];
+ sprite->data[1] = gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x;
+ sprite->data[2] = sprite->data[1] + gBattleAnimArgs[1];
+ sprite->data[3] = gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y;
+ sprite->data[4] = sprite->data[3] + gBattleAnimArgs[2];
+ sub_80754B8(sprite);
+ sprite->data[3] = gSprites[spriteId].pos2.x << 8;
+ sprite->data[4] = gSprites[spriteId].pos2.y << 8;
+ sprite->data[5] = spriteId;
+ sprite->data[6] = gBattleAnimArgs[5];
+ if (gBattleAnimArgs[5] == 0)
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+ else
+ StoreSpriteCallbackInData6(sprite, sub_809946C);
+ sprite->callback = sub_8074E14;
+}
+
+void sub_809946C(struct Sprite * sprite)
+{
+ gSprites[sprite->data[5]].pos2.x = 0;
+ gSprites[sprite->data[5]].pos2.y = 0;
+ DestroyAnimSprite(sprite);
+}
+
+void sub_809949C(u8 taskId)
+{
+ u16 r7 = 0x8000 / gBattleAnimArgs[3];
+ if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ {
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ gBattleAnimArgs[5] = -gBattleAnimArgs[5];
+ }
+ gTasks[taskId].data[0] = GetAnimBankSpriteId(gBattleAnimArgs[0]);
+ gTasks[taskId].data[1] = gBattleAnimArgs[1] * 256 / gBattleAnimArgs[3];
+ gTasks[taskId].data[2] = gBattleAnimArgs[2];
+ gTasks[taskId].data[3] = gBattleAnimArgs[3];
+ gTasks[taskId].data[4] = gBattleAnimArgs[4];
+ gTasks[taskId].data[5] = gBattleAnimArgs[5] * 256 / gBattleAnimArgs[6];
+ gTasks[taskId].data[6] = gBattleAnimArgs[6];
+ gTasks[taskId].data[7] = r7;
+ gTasks[taskId].func = sub_8099530;
+}
+
+void sub_8099530(u8 taskId)
+{
+ u8 spriteId = gTasks[taskId].data[0];
+ gTasks[taskId].data[11] += gTasks[taskId].data[1];
+ gSprites[spriteId].pos2.x = gTasks[taskId].data[11] >> 8;
+ gSprites[spriteId].pos2.y = Sin((u8)(gTasks[taskId].data[10] >> 8), gTasks[taskId].data[2]);
+ gTasks[taskId].data[10] += gTasks[taskId].data[7];
+ if (--gTasks[taskId].data[3] == 0)
+ gTasks[taskId].func = sub_8099594;
+}
+
+void sub_8099594(u8 taskId)
+{
+ u8 spriteId;
+
+ if (gTasks[taskId].data[4] > 0)
+ gTasks[taskId].data[4]--;
+ else
+ {
+ spriteId = gTasks[taskId].data[0];
+ gTasks[taskId].data[12] += gTasks[taskId].data[5];
+ gSprites[spriteId].pos2.x = (gTasks[taskId].data[12] >> 8) + (gTasks[taskId].data[11] >> 8);
+ if (--gTasks[taskId].data[6] == 0)
+ DestroyAnimVisualTask(taskId);
+ }
+}
+
+void sub_80995FC(u8 taskId)
+{
+ u8 spriteId;
+
+ switch (gBattleAnimArgs[0])
+ {
+ case 0:
+ case 1:
+ spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
+ break;
+ case 2:
+ if (!sub_8072DF0(gBattleAnimAttacker ^ BIT_FLANK))
+ {
+ DestroyAnimVisualTask(taskId);
+ return;
+ }
+ spriteId = gBattlerSpriteIds[gBattleAnimAttacker ^ BIT_FLANK];
+ break;
+ case 3:
+ if (!sub_8072DF0(gBattleAnimTarget ^ BIT_FLANK))
+ {
+ DestroyAnimVisualTask(taskId);
+ return;
+ }
+ spriteId = gBattlerSpriteIds[gBattleAnimTarget ^ BIT_FLANK];
+ break;
+ default:
+ DestroyAnimVisualTask(taskId);
+ return;
+ }
+ gTasks[taskId].data[0] = spriteId;
+ if (GetBattlerSide(gBattleAnimTarget) != B_SIDE_PLAYER)
+ gTasks[taskId].data[1] = gBattleAnimArgs[1];
+ else
+ gTasks[taskId].data[1] = -gBattleAnimArgs[1];
+ gTasks[taskId].func = sub_80996B8;
+}
+
+void sub_80996B8(u8 taskId)
+{
+ u8 spriteId = gTasks[taskId].data[0];
+ gSprites[spriteId].pos2.x += gTasks[taskId].data[1];
+ if (gSprites[spriteId].pos2.x + gSprites[spriteId].pos1.x < -0x20 || gSprites[spriteId].pos2.x + gSprites[spriteId].pos1.x > 0x110)
+ DestroyAnimVisualTask(taskId);
+}
+
+void sub_8099704(u8 taskId)
+{
+ u8 spriteId;
+ if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ spriteId = GetAnimBankSpriteId(gBattleAnimArgs[4]);
+ gTasks[taskId].data[0] = gBattleAnimArgs[0];
+ gTasks[taskId].data[1] = gBattleAnimArgs[1];
+ gTasks[taskId].data[2] = gBattleAnimArgs[2];
+ gTasks[taskId].data[3] = gBattleAnimArgs[3];
+ gTasks[taskId].data[4] = spriteId;
+ if (gBattleAnimArgs[4] == 0)
+ gTasks[taskId].data[5] = gBattleAnimAttacker;
+ else
+ gTasks[taskId].data[5] = gBattleAnimTarget;
+ gTasks[taskId].data[12] = 1;
+ gTasks[taskId].func = sub_8099788;
+}
+
+void sub_8099788(u8 taskId)
+{
+ u8 spriteId;
+ u32 r8;
+ s16 r5;
+ u16 tmp;
+
+ spriteId = gTasks[taskId].data[4];
+ tmp = gTasks[taskId].data[10] + gTasks[taskId].data[2];
+ gTasks[taskId].data[10] = tmp;
+ r8 = tmp >> 8;
+ r5 = Sin(r8, gTasks[taskId].data[1]);
+ if (gTasks[taskId].data[0] == 0)
+ {
+ gSprites[spriteId].pos2.x = r5;
+ }
+ else if (GetBattlerSide(gTasks[taskId].data[5]) == B_SIDE_PLAYER)
+ {
+ gSprites[spriteId].pos2.y = abs(r5);
+ }
+ else
+ gSprites[spriteId].pos2.y = -abs(r5);
+ if ((r8 > 0x7F && gTasks[taskId].data[11] == 0 && gTasks[taskId].data[12] == 1) || (r8 < 0x7F && gTasks[taskId].data[11] == 1 && gTasks[taskId].data[12] == 0))
+ {
+ gTasks[taskId].data[11] ^= 1;
+ gTasks[taskId].data[12] ^= 1;
+ if (--gTasks[taskId].data[3] == 0)
+ {
+ gSprites[spriteId].pos2.x = 0;
+ gSprites[spriteId].pos2.y = 0;
+ DestroyAnimVisualTask(taskId);
+ }
+ }
+}
+
+void sub_80998B0(u8 taskId)
+{
+ u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[3]);
+ sub_80758E0(spriteId, gBattleAnimArgs[4]);
+ gTasks[taskId].data[0] = gBattleAnimArgs[0];
+ gTasks[taskId].data[1] = gBattleAnimArgs[1];
+ gTasks[taskId].data[2] = gBattleAnimArgs[2];
+ gTasks[taskId].data[3] = gBattleAnimArgs[2];
+ gTasks[taskId].data[4] = spriteId;
+ gTasks[taskId].data[10] = 0x100;
+ gTasks[taskId].data[11] = 0x100;
+ gTasks[taskId].func = sub_8099908;
+}
+
+void sub_8099908(u8 taskId)
+{
+ u8 spriteId;
+ gTasks[taskId].data[10] += gTasks[taskId].data[0];
+ gTasks[taskId].data[11] += gTasks[taskId].data[1];
+ spriteId = gTasks[taskId].data[4];
+ obj_id_set_rotscale(spriteId, gTasks[taskId].data[10], gTasks[taskId].data[11], 0);
+ if (--gTasks[taskId].data[2] == 0)
+ {
+ if (gTasks[taskId].data[3] > 0)
+ {
+ gTasks[taskId].data[0] = -gTasks[taskId].data[0];
+ gTasks[taskId].data[1] = -gTasks[taskId].data[1];
+ gTasks[taskId].data[2] = gTasks[taskId].data[3];
+ gTasks[taskId].data[3] = 0;
+ }
+ else
+ {
+ sub_8075980(spriteId);
+ DestroyAnimVisualTask(taskId);
+ }
+ }
+}
+
+void sub_8099980(u8 taskId)
+{
+ u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]);
+ sub_80758E0(spriteId, 0);
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].data[2] = gBattleAnimArgs[0];
+ if (gBattleAnimArgs[3] != 1)
+ gTasks[taskId].data[3] = 0;
+ else
+ gTasks[taskId].data[3] = gBattleAnimArgs[0] * gBattleAnimArgs[1];
+ gTasks[taskId].data[4] = gBattleAnimArgs[1];
+ gTasks[taskId].data[5] = spriteId;
+ gTasks[taskId].data[6] = gBattleAnimArgs[3];
+ if (sub_8073788())
+ gTasks[taskId].data[7] = 1;
+ else
+ {
+ if (gBattleAnimArgs[2] == 0)
+ gTasks[taskId].data[7] = GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER ? 1 : 0;
+ else
+ gTasks[taskId].data[7] = GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER ? 1 : 0;
+ }
+ if (gTasks[taskId].data[7] && !sub_8073788())
+ {
+ s16 tmp;
+ tmp = gTasks[taskId].data[3];
+ gTasks[taskId].data[3] = -tmp;
+ tmp = gTasks[taskId].data[4];
+ gTasks[taskId].data[4] = -tmp;
+ }
+ gTasks[taskId].func = sub_8099B54;
+}
+
+void sub_8099A78(u8 taskId)
+{
+ u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]);
+ sub_80758E0(spriteId, 0);
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].data[2] = gBattleAnimArgs[0];
+ if (gBattleAnimArgs[2] == 0)
+ {
+ if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ }
+ else
+ {
+ if (GetBattlerSide(gBattleAnimTarget) != B_SIDE_PLAYER)
+ gBattleAnimArgs[1] = -gBattleAnimArgs[1];
+ }
+ if (gBattleAnimArgs[3] != 1)
+ gTasks[taskId].data[3] = 0;
+ else
+ gTasks[taskId].data[3] = gBattleAnimArgs[0] * gBattleAnimArgs[1];
+ gTasks[taskId].data[4] = gBattleAnimArgs[1];
+ gTasks[taskId].data[5] = spriteId;
+ gTasks[taskId].data[6] = gBattleAnimArgs[3];
+ gTasks[taskId].data[7] = 1;
+ if (gTasks[taskId].data[7] )
+ {
+ s16 tmp;
+ tmp = gTasks[taskId].data[3];
+ gTasks[taskId].data[3] = -tmp;
+ tmp = gTasks[taskId].data[4];
+ gTasks[taskId].data[4] = -tmp;
+ }
+ gTasks[taskId].func = sub_8099B54;
+}
+
+void sub_8099B54(u8 taskId)
+{
+ s16 tmp;
+ gTasks[taskId].data[3] += gTasks[taskId].data[4];
+ obj_id_set_rotscale(gTasks[taskId].data[5], 0x100, 0x100, gTasks[taskId].data[3]);
+ if (gTasks[taskId].data[7])
+ sub_80759DC(gTasks[taskId].data[5]);
+ if (++gTasks[taskId].data[1] >= gTasks[taskId].data[2])
+ {
+ switch (gTasks[taskId].data[6])
+ {
+ case 1:
+ sub_8075980(gTasks[taskId].data[5]);
+ // fallthrough
+ case 0:
+ default:
+ DestroyAnimVisualTask(taskId);
+ break;
+ case 2:
+ gTasks[taskId].data[1] = 0;
+ tmp = gTasks[taskId].data[4];
+ gTasks[taskId].data[4] = -tmp;
+ gTasks[taskId].data[6] = 1;
+ break;
+ }
+ }
+}
+
+void sub_8099BD4(u8 taskId)
+{
+ if (gBattleAnimArgs[0] == 0)
+ {
+ gTasks[taskId].data[15] = gUnknown_2037EEC / 12;
+ if (gTasks[taskId].data[15] < 1)
+ gTasks[taskId].data[15] = 1;
+ if (gTasks[taskId].data[15] > 16)
+ gTasks[taskId].data[15] = 16;
+ }
+ else
+ {
+ gTasks[taskId].data[15] = gUnknown_2037EE8 / 12;
+ if (gTasks[taskId].data[15] < 1)
+ gTasks[taskId].data[15] = 1;
+ if (gTasks[taskId].data[15] > 16)
+ gTasks[taskId].data[15] = 16;
+ }
+ gTasks[taskId].data[14] = gTasks[taskId].data[15] / 2;
+ gTasks[taskId].data[13] = gTasks[taskId].data[14] + (gTasks[taskId].data[15] & 1);
+ gTasks[taskId].data[12] = 0;
+ gTasks[taskId].data[10] = gBattleAnimArgs[3];
+ gTasks[taskId].data[11] = gBattleAnimArgs[4];
+ gTasks[taskId].data[7] = GetAnimBankSpriteId(1);
+ gTasks[taskId].data[8] = gSprites[gTasks[taskId].data[7]].pos2.x;
+ gTasks[taskId].data[9] = gSprites[gTasks[taskId].data[7]].pos2.y;
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = gBattleAnimArgs[1];
+ gTasks[taskId].data[2] = gBattleAnimArgs[2];
+ gTasks[taskId].func = sub_8099CB8;
+}
+
+void sub_8099CB8(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ if (++task->data[0] > task->data[1])
+ {
+ task->data[0] = 0;
+ task->data[12] = (task->data[12] + 1) & 1;
+ if (task->data[10])
+ {
+ if (task->data[12])
+ {
+ gSprites[task->data[7]].pos2.x = task->data[8] + task->data[13];
+ }
+ else
+ {
+ gSprites[task->data[7]].pos2.x = task->data[8] - task->data[14];
+ }
+ }
+ if (task->data[11])
+ {
+ if (task->data[12])
+ {
+ gSprites[task->data[7]].pos2.y = task->data[15];
+ }
+ else
+ {
+ gSprites[task->data[7]].pos2.y = 0;
+ }
+ }
+ if (!--task->data[2])
+ {
+ gSprites[task->data[7]].pos2.x = 0;
+ gSprites[task->data[7]].pos2.y = 0;
+ DestroyAnimVisualTask(taskId);
+ return;
+ }
+ }
+}
diff --git a/src/berry.c b/src/berry.c
new file mode 100644
index 000000000..91d83f40c
--- /dev/null
+++ b/src/berry.c
@@ -0,0 +1,169 @@
+#include "global.h"
+#include "berry.h"
+#include "text.h"
+#include "constants/items.h"
+
+extern const struct Berry sBerries[];
+
+#define ENIGMA_BERRY_STRUCT ({const struct Berry2 *berries = (const struct Berry2 *)sBerries;berries[ITEM_ENIGMA_BERRY - FIRST_BERRY_INDEX];})
+
+void sub_809C718(void)
+{
+ s32 i;
+
+ gSaveBlock1Ptr->enigmaBerry.berry = ENIGMA_BERRY_STRUCT;
+ for (i = 0; i < 18; i++)
+ gSaveBlock1Ptr->enigmaBerry.itemEffect[i] = 0;
+ gSaveBlock1Ptr->enigmaBerry.holdEffect = 0;
+ gSaveBlock1Ptr->enigmaBerry.holdEffectParam = 0;
+ gSaveBlock1Ptr->enigmaBerry.checksum = GetEnigmaBerryChecksum(&gSaveBlock1Ptr->enigmaBerry);
+}
+
+void sub_809C794(void)
+{
+ CpuFill16(0, &gSaveBlock1Ptr->enigmaBerry, sizeof(gSaveBlock1Ptr->enigmaBerry));
+ sub_809C718();
+}
+
+#ifdef NONMATCHING
+void SetEnigmaBerry(u8 * berry)
+{
+ struct EnigmaBerry * enigmaBerry;
+
+ sub_809C794();
+
+ {
+ const struct Berry2 * src = (const struct Berry2 *)berry;
+ struct Berry2 * dest = &gSaveBlock1Ptr->enigmaBerry.berry;
+ *dest = *src;
+ }
+
+ enigmaBerry = &gSaveBlock1Ptr->enigmaBerry;
+ {
+ s32 i = 0;
+ u8 * dest = gSaveBlock1Ptr->enigmaBerry.itemEffect;
+ const u8 * src = berry + 0x516;
+
+ for (i = 0; i < 18; i++) dest[i] = src[i];
+ }
+ enigmaBerry->holdEffect = berry[0x528];
+ enigmaBerry->holdEffectParam = berry[0x529];
+ enigmaBerry->checksum = GetEnigmaBerryChecksum(enigmaBerry);
+}
+#else
+NAKED
+void SetEnigmaBerry(u8 * berry)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tadds r4, r0, 0\n"
+ "\tbl sub_809C794\n"
+ "\tadds r5, r4, 0\n"
+ "\tldr r0, _0809C824 @ =gSaveBlock1Ptr\n"
+ "\tldr r2, [r0]\n"
+ "\tldr r0, _0809C828 @ =0x000030ec\n"
+ "\tadds r4, r2, r0\n"
+ "\tadds r1, r4, 0\n"
+ "\tadds r0, r5, 0\n"
+ "\tldm r0!, {r3,r6,r7}\n"
+ "\tstm r1!, {r3,r6,r7}\n"
+ "\tldm r0!, {r3,r6,r7}\n"
+ "\tstm r1!, {r3,r6,r7}\n"
+ "\tldr r0, [r0]\n"
+ "\tstr r0, [r1]\n"
+ "\tmovs r3, 0\n"
+ "\tldr r0, _0809C82C @ =0x00003108\n"
+ "\tadds r6, r2, r0\n"
+ "\tldr r1, _0809C830 @ =0x00000516\n"
+ "\tadds r2, r5, r1\n"
+ "_0809C7F0:\n"
+ "\tadds r0, r6, r3\n"
+ "\tadds r1, r2, r3\n"
+ "\tldrb r1, [r1]\n"
+ "\tstrb r1, [r0]\n"
+ "\tadds r3, 0x1\n"
+ "\tcmp r3, 0x11\n"
+ "\tble _0809C7F0\n"
+ "\tmovs r3, 0xA5\n"
+ "\tlsls r3, 3\n"
+ "\tadds r0, r5, r3\n"
+ "\tldrb r0, [r0]\n"
+ "\tadds r1, r4, 0\n"
+ "\tadds r1, 0x2E\n"
+ "\tstrb r0, [r1]\n"
+ "\tldr r6, _0809C834 @ =0x00000529\n"
+ "\tadds r0, r5, r6\n"
+ "\tldrb r0, [r0]\n"
+ "\tadds r1, 0x1\n"
+ "\tstrb r0, [r1]\n"
+ "\tadds r0, r4, 0\n"
+ "\tbl GetEnigmaBerryChecksum\n"
+ "\tstr r0, [r4, 0x30]\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r0}\n"
+ "\tbx r0\n"
+ "\t.align 2, 0\n"
+ "_0809C824: .4byte gSaveBlock1Ptr\n"
+ "_0809C828: .4byte 0x000030ec\n"
+ "_0809C82C: .4byte 0x00003108\n"
+ "_0809C830: .4byte 0x00000516\n"
+ "_0809C834: .4byte 0x00000529");
+}
+#endif
+
+u32 GetEnigmaBerryChecksum(struct EnigmaBerry * enigmaBerry)
+{
+ const u8 * src = (const u8 *)enigmaBerry;
+ u32 result = 0;
+ u32 i;
+
+ for (i = 0; i < offsetof(struct EnigmaBerry, checksum); i++)
+ result += src[i];
+
+ return result;
+}
+
+bool32 IsEnigmaBerryValid(void)
+{
+ if (gSaveBlock1Ptr->enigmaBerry.berry.stageDuration == 0)
+ return FALSE;
+ if (gSaveBlock1Ptr->enigmaBerry.berry.maxYield == 0)
+ return FALSE;
+ if (GetEnigmaBerryChecksum(&gSaveBlock1Ptr->enigmaBerry) != gSaveBlock1Ptr->enigmaBerry.checksum)
+ return FALSE;
+
+ return TRUE;
+}
+
+const struct Berry * sub_809C8A0(u8 berryIdx)
+{
+ if (berryIdx == ITEM_TO_BERRY(ITEM_ENIGMA_BERRY) && IsEnigmaBerryValid())
+ return (struct Berry *)&gSaveBlock1Ptr->enigmaBerry.berry;
+
+ if (berryIdx == 0 || berryIdx > ITEM_TO_BERRY(ITEM_ENIGMA_BERRY))
+ berryIdx = 1;
+
+ return &sBerries[berryIdx - 1];
+}
+
+u8 ItemIdToBerryType(u16 itemId)
+{
+ if (itemId - FIRST_BERRY_INDEX < 0 || itemId - FIRST_BERRY_INDEX > ITEM_ENIGMA_BERRY - FIRST_BERRY_INDEX)
+ return 1;
+
+ return ITEM_TO_BERRY(itemId);
+}
+
+u16 BerryTypeToItemId(u16 berryType)
+{
+ if (berryType - 1 < 0 || berryType - 1 > ITEM_ENIGMA_BERRY - FIRST_BERRY_INDEX)
+ return FIRST_BERRY_INDEX;
+
+ return berryType + FIRST_BERRY_INDEX - 1;
+}
+
+void GetBerryNameByBerryType(u8 berryType, u8 * dest)
+{
+ const struct Berry * berry = sub_809C8A0(berryType);
+ memcpy(dest, berry->name, 6);
+ dest[6] = EOS;
+}
diff --git a/src/berry_fix_program.c b/src/berry_fix_program.c
new file mode 100644
index 000000000..f224bbc47
--- /dev/null
+++ b/src/berry_fix_program.c
@@ -0,0 +1,191 @@
+#include "global.h"
+#include "gpu_regs.h"
+#include "multiboot.h"
+#include "malloc.h"
+#include "bg.h"
+#include "graphics.h"
+#include "main.h"
+#include "sprite.h"
+#include "task.h"
+#include "scanline_effect.h"
+#include "window.h"
+#include "text.h"
+#include "help_system.h"
+#include "menu.h"
+#include "m4a.h"
+
+// Static type declarations
+
+typedef struct {
+ u8 state;
+ u8 unk1;
+ u16 unk2;
+ struct MultiBootParam mb;
+} berryfix_t;
+
+// Static RAM declarations
+
+const void * gUnknown_3005EF0;
+int gUnknown_3005EF4;
+size_t gUnknown_3005EF8;
+struct MultiBootParam gUnknown_3005F00;
+
+// Static ROM declarations
+
+static void mb_berry_fix_maincb(void);
+static void mb_berry_fix_task(u8 taskId);
+
+// .rodata
+
+static const void *const gUnknown_847A890[][3] = {
+ {
+ gBerryFixGameboy_Gfx,
+ gBerryFixGameboy_Tilemap,
+ gBerryFixGameboy_Pal
+ }, {
+ gBerryFixGameboyLogo_Gfx,
+ gBerryFixGameboyLogo_Tilemap,
+ gBerryFixGameboyLogo_Pal
+ }, {
+ gBerryFixGbaTransfer_Gfx,
+ gBerryFixGbaTransfer_Tilemap,
+ gBerryFixGbaTransfer_Pal
+ }, {
+ gBerryFixGbaTransferHighlight_Gfx,
+ gBerryFixGbaTransferHighlight_Tilemap,
+ gBerryFixGbaTransferHighlight_Pal
+ }, {
+ gBerryFixGbaTransferError_Gfx,
+ gBerryFixGbaTransferError_Tilemap,
+ gBerryFixGbaTransferError_Pal
+ }, {
+ gBerryFixWindow_Gfx,
+ gBerryFixWindow_Tilemap,
+ gBerryFixWindow_Pal
+ },
+};
+
+extern const u8 gMultiBootProgram_BerryGlitchFix_Start[0x3BF4];
+extern const u8 gMultiBootProgram_BerryGlitchFix_End[];
+
+// .text
+
+static void mb_berry_fix_print(int scene)
+{
+ REG_DISPCNT = 0;
+ REG_BG0HOFS = 0;
+ REG_BG0VOFS = 0;
+ REG_BLDCNT = 0;
+ LZ77UnCompVram(gUnknown_847A890[scene][0], (void *)BG_CHAR_ADDR(0));
+ LZ77UnCompVram(gUnknown_847A890[scene][1], (void *)BG_SCREEN_ADDR(31));
+ CpuCopy16(gUnknown_847A890[scene][2], (void *)BG_PLTT, 0x200);
+ REG_BG0CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(31) | BGCNT_TXT256x256;
+ REG_DISPCNT = DISPCNT_BG0_ON;
+}
+
+void mb_berry_fix_serve(void) // noreturn
+{
+ u8 taskId;
+ DisableInterrupts(0xFFFF);
+ EnableInterrupts(INTR_FLAG_VBLANK);
+ m4aSoundVSyncOff();
+ SetVBlankCallback(NULL);
+ DmaFill32(3, 0, (void *)VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, (void *)PLTT, PLTT_SIZE);
+ ResetSpriteData();
+ ResetTasks();
+ ScanlineEffect_Stop();
+ gUnknown_3005ECC = 0;
+ taskId = CreateTask(mb_berry_fix_task, 0);
+ gTasks[taskId].data[0] = 0;
+ SetMainCallback2(mb_berry_fix_maincb);
+}
+
+static void mb_berry_fix_maincb(void)
+{
+ RunTasks();
+}
+
+static void mb_berry_fix_task(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ mb_berry_fix_print(5);
+ data[0] = 1;
+ break;
+ case 1:
+ if (JOY_NEW(A_BUTTON))
+ {
+ mb_berry_fix_print(0);
+ data[0] = 2;
+ }
+ break;
+ case 2:
+ if (JOY_NEW(A_BUTTON))
+ {
+ mb_berry_fix_print(1);
+ data[0] = 4;
+ }
+ break;
+ case 4:
+ gUnknown_3005EF0 = gMultiBootProgram_BerryGlitchFix_Start;
+ gUnknown_3005EF8 = gMultiBootProgram_BerryGlitchFix_End - gMultiBootProgram_BerryGlitchFix_Start;
+ gUnknown_3005F00.masterp = (void *)gMultiBootProgram_BerryGlitchFix_Start;
+ gUnknown_3005F00.server_type = MULTIBOOT_SERVER_TYPE_NORMAL;
+ MultiBootInit(&gUnknown_3005F00);
+ data[1] = 0;
+ data[0] = 5;
+ break;
+ case 5:
+ if (gUnknown_3005F00.probe_count == 0 && gUnknown_3005F00.response_bit & 0x2 && gUnknown_3005F00.client_bit & 0x2)
+ {
+ data[1]++;
+ if (data[1] > 180)
+ {
+ mb_berry_fix_print(2);
+ MultiBootStartMaster(&gUnknown_3005F00, gUnknown_3005EF0 + MULTIBOOT_HEADER_SIZE, gUnknown_3005EF8 - MULTIBOOT_HEADER_SIZE, 4, 1);
+ data[1] = 0;
+ data[0] = 6;
+ }
+ else
+ gUnknown_3005EF4 = MultiBootMain(&gUnknown_3005F00);
+ }
+ else
+ {
+ data[1] = 0;
+ gUnknown_3005EF4 = MultiBootMain(&gUnknown_3005F00);
+ }
+ break;
+ case 6:
+ gUnknown_3005EF4 = MultiBootMain(&gUnknown_3005F00);
+ if (MultiBootCheckComplete(&gUnknown_3005F00))
+ {
+ mb_berry_fix_print(3);
+ data[0] = 7;
+ }
+ else if (!(gUnknown_3005F00.client_bit & 2))
+ data[0] = 9;
+ break;
+ case 7:
+ data[0] = 8;
+ break;
+ case 8:
+ if (JOY_NEW(A_BUTTON))
+ {
+ DestroyTask(taskId);
+ DoSoftReset();
+ }
+ break;
+ case 9:
+ mb_berry_fix_print(4);
+ data[0] = 10;
+ break;
+ case 10:
+ if (JOY_NEW(A_BUTTON))
+ data[0] = 0;
+ break;
+ }
+}
diff --git a/src/berry_powder.c b/src/berry_powder.c
new file mode 100644
index 000000000..b3069d697
--- /dev/null
+++ b/src/berry_powder.c
@@ -0,0 +1,132 @@
+#include "global.h"
+#include "event_data.h"
+#include "load_save.h"
+#include "menu.h"
+#include "quest_log.h"
+#include "script_menu.h"
+#include "string_util.h"
+#include "strings.h"
+#include "text.h"
+#include "text_window.h"
+
+EWRAM_DATA u8 gUnknown_203F464 = 0;
+
+u32 sub_815EE3C(u32 * a0)
+{
+ return *a0 ^ gSaveBlock2Ptr->encryptionKey;
+}
+
+void sub_815EE54(u32 * a0, u32 a1)
+{
+ *a0 = gSaveBlock2Ptr->encryptionKey ^ a1;
+}
+
+void sub_815EE6C(u32 a0)
+{
+ ApplyNewEncryptionKeyToWord(&gSaveBlock2Ptr->berryCrush.berryPowderAmount, a0);
+}
+
+bool8 sub_815EE88(u32 a0)
+{
+ if (sub_815EE3C(&gSaveBlock2Ptr->berryCrush.berryPowderAmount) < a0)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+bool8 sub_815EEB0(void)
+{
+ if (sub_815EE3C(&gSaveBlock2Ptr->berryCrush.berryPowderAmount) < gSpecialVar_0x8004)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+bool8 sub_815EEE0(u32 a0)
+{
+ u32 * ptr = &gSaveBlock2Ptr->berryCrush.berryPowderAmount;
+ u32 amount = sub_815EE3C(ptr) + a0;
+ if (amount > 99999)
+ {
+ sub_815EE54(ptr, 99999);
+ return FALSE;
+ }
+ else
+ {
+ sub_815EE54(ptr, amount);
+ return TRUE;
+ }
+}
+
+bool8 sub_815EF20(u32 a0)
+{
+ u32 * ptr = &gSaveBlock2Ptr->berryCrush.berryPowderAmount;
+ if (!sub_815EE88(a0))
+ return FALSE;
+ else
+ {
+ u32 amount = sub_815EE3C(ptr);
+ sub_815EE54(ptr, amount - a0);
+ return TRUE;
+ }
+}
+
+bool8 sub_815EF5C(void)
+{
+ u32 * ptr = &gSaveBlock2Ptr->berryCrush.berryPowderAmount;
+ if (!sub_815EE88(gSpecialVar_0x8004))
+ return FALSE;
+ else
+ {
+ u32 amount = sub_815EE3C(ptr);
+ sub_815EE54(ptr, amount - gSpecialVar_0x8004);
+ return TRUE;
+ }
+}
+
+u32 GetBerryPowder(void)
+{
+ return sub_815EE3C(&gSaveBlock2Ptr->berryCrush.berryPowderAmount);
+}
+
+void sub_815EFBC(u8 windowId, u32 powder, u8 x, u8 y, u8 speed)
+{
+ ConvertIntToDecimalStringN(gStringVar1, powder, STR_CONV_MODE_RIGHT_ALIGN, 5);
+ AddTextPrinterParameterized(windowId, 0, gStringVar1, x, y, speed, NULL);
+}
+
+void sub_815F014(u8 windowId, u16 baseBlock, u8 palette, u32 powder)
+{
+ SetWindowBorderStyle(windowId, FALSE, baseBlock, palette);
+ AddTextPrinterParameterized(windowId, 0, gOtherText_Powder, 0, 0, -1, NULL);
+ sub_815EFBC(windowId, powder, 39, 12, 0);
+}
+
+void sub_815F070(void)
+{
+ sub_815EFBC(gUnknown_203F464, GetBerryPowder(), 39, 12, 0);
+}
+
+void sub_815F094(void)
+{
+ struct WindowTemplate template;
+ struct WindowTemplate template2;
+
+ if (sub_81119D4(sub_809D6D4) != TRUE)
+ {
+ SetWindowTemplateFields(&template, 0, 1, 1, 8, 3, 15, 32);
+ template2 = template;
+ gUnknown_203F464 = AddWindow(&template2);
+ FillWindowPixelBuffer(gUnknown_203F464, 0);
+ PutWindowTilemap(gUnknown_203F464);
+ TextWindow_SetStdFrame0_WithPal(gUnknown_203F464, 0x21D, 0xD0);
+ sub_815F014(gUnknown_203F464, 0x21D, 0xD, GetBerryPowder());
+ }
+}
+
+void sub_815F114(void)
+{
+ ClearWindowTilemap(gUnknown_203F464);
+ ClearMenuWindow(gUnknown_203F464, 1);
+ RemoveWindow(gUnknown_203F464);
+}
diff --git a/src/blend_palette.c b/src/blend_palette.c
new file mode 100644
index 000000000..8cd65ae4b
--- /dev/null
+++ b/src/blend_palette.c
@@ -0,0 +1,46 @@
+#include "global.h"
+#include "blend_palette.h"
+#include "palette.h"
+
+void BlendPalette(u16 palOffset, u16 numEntries, u8 coeff, u16 blendColor)
+{
+ u16 i;
+ for (i = 0; i < numEntries; i++)
+ {
+ u16 index = i + palOffset;
+ struct PlttData *data1 = (struct PlttData *)&gPlttBufferUnfaded[index];
+ s8 r = data1->r;
+ s8 g = data1->g;
+ s8 b = data1->b;
+ struct PlttData *data2 = (struct PlttData *)&blendColor;
+ gPlttBufferFaded[index] = ((r + (((data2->r - r) * coeff) >> 4)) << 0)
+ | ((g + (((data2->g - g) * coeff) >> 4)) << 5)
+ | ((b + (((data2->b - b) * coeff) >> 4)) << 10);
+ }
+}
+
+void sub_8045314(u16 * palbuff, u16 blend_pal, u32 coefficient, s32 size)
+{
+ if (coefficient == 16)
+ {
+ while (--size != -1)
+ {
+ *palbuff++ = blend_pal;
+ }
+ }
+ else
+ {
+ u16 r = (blend_pal >> 0) & 0x1F;
+ u16 g = (blend_pal >> 5) & 0x1F;
+ u16 b = (blend_pal >> 10) & 0x1F;
+ while (--size != -1)
+ {
+ u16 r2 = (*palbuff >> 0) & 0x1F;
+ u16 g2 = (*palbuff >> 5) & 0x1F;
+ u16 b2 = (*palbuff >> 10) & 0x1F;
+ *palbuff++ = ((r2 + (((r - r2) * coefficient) >> 4)) << 0)
+ | ((g2 + (((g - g2) * coefficient) >> 4)) << 5)
+ | ((b2 + (((b - b2) * coefficient) >> 4)) << 10);
+ }
+ }
+}
diff --git a/src/blit.c b/src/blit.c
new file mode 100644
index 000000000..969f89900
--- /dev/null
+++ b/src/blit.c
@@ -0,0 +1,212 @@
+#include "global.h"
+#include "blit.h"
+
+void BlitBitmapRect4BitWithoutColorKey(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height)
+{
+ BlitBitmapRect4Bit(src, dst, srcX, srcY, dstX, dstY, width, height, 0xFF);
+}
+
+void BlitBitmapRect4Bit(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey)
+{
+ s32 xEnd;
+ s32 yEnd;
+ s32 multiplierSrcY;
+ s32 multiplierDstY;
+ s32 loopSrcY, loopDstY;
+ s32 loopSrcX, loopDstX;
+ const u8 *pixelsSrc;
+ u8 *pixelsDst;
+ s32 toOrr;
+ s32 toAnd;
+ s32 toShift;
+
+ if (dst->width - dstX < width)
+ xEnd = (dst->width - dstX) + srcX;
+ else
+ xEnd = srcX + width;
+
+ if (dst->height - dstY < height)
+ yEnd = (dst->height - dstY) + srcY;
+ else
+ yEnd = height + srcY;
+
+ multiplierSrcY = (src->width + (src->width & 7)) >> 3;
+ multiplierDstY = (dst->width + (dst->width & 7)) >> 3;
+
+ if (colorKey == 0xFF)
+ {
+ for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
+ {
+ for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
+ {
+ pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1B);
+ pixelsDst = dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX >> 3) << 5) + (((loopDstY >> 3) * multiplierDstY) << 5) + ((u32)(loopDstY << 0x1d) >> 0x1B);
+ toOrr = ((*pixelsSrc >> ((loopSrcX & 1) << 2)) & 0xF);
+ toShift = ((loopDstX & 1) << 2);
+ toOrr <<= toShift;
+ toAnd = 0xF0 >> (toShift);
+ *pixelsDst = toOrr | (*pixelsDst & toAnd);
+ }
+ }
+ }
+ else
+ {
+ for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
+ {
+ for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
+ {
+ pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1B);
+ pixelsDst = dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX >> 3) << 5) + (((loopDstY >> 3) * multiplierDstY) << 5) + ((u32)(loopDstY << 0x1d) >> 0x1B);
+ toOrr = ((*pixelsSrc >> ((loopSrcX & 1) << 2)) & 0xF);
+ if (toOrr != colorKey)
+ {
+ toShift = ((loopDstX & 1) << 2);
+ toOrr <<= toShift;
+ toAnd = 0xF0 >> (toShift);
+ *pixelsDst = toOrr | (*pixelsDst & toAnd);
+ }
+ }
+ }
+ }
+}
+
+void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue)
+{
+ s32 xEnd;
+ s32 yEnd;
+ s32 multiplierY;
+ s32 loopX, loopY;
+
+ xEnd = x + width;
+ if (xEnd > surface->width)
+ xEnd = surface->width;
+
+ yEnd = y + height;
+ if (yEnd > surface->height)
+ yEnd = surface->height;
+
+ multiplierY = (surface->width + (surface->width & 7)) >> 3;
+
+ for (loopY = y; loopY < yEnd; loopY++)
+ {
+ for (loopX = x; loopX < xEnd; loopX++)
+ {
+ u8 *pixels = surface->pixels + ((loopX >> 1) & 3) + ((loopX >> 3) << 5) + (((loopY >> 3) * multiplierY) << 5) + ((u32)(loopY << 0x1d) >> 0x1B);
+ if ((loopX & 1) != 0)
+ {
+ *pixels &= 0xF;
+ *pixels |= fillValue << 4;
+ }
+ else
+ {
+ *pixels &= 0xF0;
+ *pixels |= fillValue;
+ }
+ }
+ }
+}
+
+void BlitBitmapRect4BitTo8Bit(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey, u8 paletteOffset)
+{
+ s32 palOffsetBits;
+ s32 xEnd;
+ s32 yEnd;
+ s32 multiplierSrcY;
+ s32 multiplierDstY;
+ s32 loopSrcY, loopDstY;
+ s32 loopSrcX, loopDstX;
+ const u8 *pixelsSrc;
+ u8 *pixelsDst;
+ s32 colorKeyBits;
+
+ palOffsetBits = (u32)(paletteOffset << 0x1C) >> 0x18;
+ colorKeyBits = (u32)(colorKey << 0x1C) >> 0x18;
+
+ if (dst->width - dstX < width)
+ xEnd = (dst->width - dstX) + srcX;
+ else
+ xEnd = width + srcX;
+
+ if (dst->height - dstY < height)
+ yEnd = (srcY + dst->height) - dstY;
+ else
+ yEnd = srcY + height;
+
+ multiplierSrcY = (src->width + (src->width & 7)) >> 3;
+ multiplierDstY = (dst->width + (dst->width & 7)) >> 3;
+
+ if (colorKey == 0xFF)
+ {
+ for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
+ {
+ pixelsSrc = src->pixels + ((srcX >> 1) & 3) + ((srcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
+ for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
+ {
+ pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a);
+ if (loopSrcX & 1)
+ {
+ *pixelsDst = palOffsetBits + (*pixelsSrc >> 4);
+ }
+ else
+ {
+ pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
+ *pixelsDst = palOffsetBits + (*pixelsSrc & 0xF);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
+ {
+ pixelsSrc = src->pixels + ((srcX >> 1) & 3) + ((srcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
+ for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
+ {
+ if (loopSrcX & 1)
+ {
+ if ((*pixelsSrc & 0xF0) != colorKeyBits)
+ {
+ pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a);
+ *pixelsDst = palOffsetBits + (*pixelsSrc >> 4);
+ }
+ }
+ else
+ {
+ pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
+ if ((*pixelsSrc & 0xF) != colorKey)
+ {
+ pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a);
+ *pixelsDst = palOffsetBits + (*pixelsSrc & 0xF);
+ }
+ }
+ }
+ }
+ }
+}
+
+void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue)
+{
+ s32 xEnd;
+ s32 yEnd;
+ s32 multiplierY;
+ s32 loopX, loopY;
+
+ xEnd = x + width;
+ if (xEnd > surface->width)
+ xEnd = surface->width;
+
+ yEnd = y + height;
+ if (yEnd > surface->height)
+ yEnd = surface->height;
+
+ multiplierY = (surface->width + (surface->width & 7)) >> 3;
+
+ for (loopY = y; loopY < yEnd; loopY++)
+ {
+ for (loopX = x; loopX < xEnd; loopX++)
+ {
+ u8 *pixels = surface->pixels + (loopX & 7) + ((loopX >> 3) << 6) + (((loopY >> 3) * multiplierY) << 6) + ((u32)(loopY << 0x1d) >> 0x1a);
+ *pixels = fillValue;
+ }
+ }
+}
diff --git a/src/braille_text.c b/src/braille_text.c
new file mode 100644
index 000000000..047fcab08
--- /dev/null
+++ b/src/braille_text.c
@@ -0,0 +1,222 @@
+#include "global.h"
+#include "main.h"
+#include "window.h"
+#include "text.h"
+#include "sound.h"
+
+extern u8 gGlyphInfo[];
+
+ALIGNED(4)
+static const u8 gUnknown_846FB08[] = {1, 2, 4};
+static const u16 sFont6BrailleGlyphs[] = INCBIN_U16("data/graphics/fonts/font6.fwjpnfont");
+
+static void DecompressGlyphFont6(u16);
+
+u16 Font6Func(struct TextPrinter *textPrinter)
+{
+ u16 char_;
+ struct TextPrinterSubStruct *sub;
+
+ sub = &textPrinter->sub_union.sub;
+ switch (textPrinter->state)
+ {
+ case 0:
+ if (gMain.heldKeys & (A_BUTTON | B_BUTTON) && sub->font_type_upper)
+ {
+ textPrinter->delayCounter = 0;
+ }
+ if (textPrinter->delayCounter && textPrinter->text_speed)
+ {
+ textPrinter->delayCounter --;
+ if (gTextFlags.canABSpeedUpPrint && gMain.newKeys & (A_BUTTON | B_BUTTON))
+ {
+ sub->font_type_upper = TRUE;
+ textPrinter->delayCounter = 0;
+ }
+ return 3;
+ }
+ if (gTextFlags.autoScroll)
+ {
+ textPrinter->delayCounter = 1;
+ }
+ else
+ {
+ textPrinter->delayCounter = textPrinter->text_speed;
+ }
+ char_ = *textPrinter->subPrinter.currentChar++;
+ switch (char_)
+ {
+ case EOS:
+ return 1;
+ case CHAR_NEWLINE:
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
+ textPrinter->subPrinter.currentY += gFonts[textPrinter->subPrinter.fontId].maxLetterHeight + textPrinter->subPrinter.lineSpacing;
+ return 2;
+ case PLACEHOLDER_BEGIN:
+ textPrinter->subPrinter.currentChar++;
+ return 2;
+ case EXT_CTRL_CODE_BEGIN:
+ char_ = *textPrinter->subPrinter.currentChar++;
+ switch (char_)
+ {
+ case 1:
+ textPrinter->subPrinter.fgColor = *textPrinter->subPrinter.currentChar++;
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fgColor, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 2:
+ textPrinter->subPrinter.bgColor = *textPrinter->subPrinter.currentChar++;
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fgColor, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 3:
+ textPrinter->subPrinter.shadowColor = *textPrinter->subPrinter.currentChar++;
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fgColor, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 4:
+ textPrinter->subPrinter.fgColor = *textPrinter->subPrinter.currentChar;
+ textPrinter->subPrinter.bgColor = *++textPrinter->subPrinter.currentChar;
+ textPrinter->subPrinter.shadowColor = *++textPrinter->subPrinter.currentChar;
+ textPrinter->subPrinter.currentChar++;
+
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fgColor, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 5:
+ textPrinter->subPrinter.currentChar++;
+ return 2;
+ case 6:
+ sub->font_type = *textPrinter->subPrinter.currentChar;
+ textPrinter->subPrinter.currentChar++;
+ return 2;
+ case 7:
+ return 2;
+ case 8:
+ textPrinter->delayCounter = *textPrinter->subPrinter.currentChar++;
+ textPrinter->state = 6;
+ return 2;
+ case 9:
+ textPrinter->state = 1;
+ if (gTextFlags.autoScroll)
+ {
+ sub->frames_visible_counter = 0;
+ }
+ return 3;
+ case 10:
+ textPrinter->state = 5;
+ return 3;
+ case 11:
+ case 16:
+ textPrinter->subPrinter.currentChar += 2;
+ return 2;
+ case 12:
+ char_ = *++textPrinter->subPrinter.currentChar;
+ break;
+ case 13:
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x + *textPrinter->subPrinter.currentChar++;
+ return 2;
+ case 14:
+ textPrinter->subPrinter.currentY = textPrinter->subPrinter.y + *textPrinter->subPrinter.currentChar++;
+ return 2;
+ case 15:
+ FillWindowPixelBuffer(textPrinter->subPrinter.windowId, PIXEL_FILL(textPrinter->subPrinter.bgColor));
+ return 2;
+ }
+ break;
+ case CHAR_PROMPT_CLEAR:
+ textPrinter->state = 2;
+ TextPrinterInitDownArrowCounters(textPrinter);
+ return 3;
+ case CHAR_PROMPT_SCROLL:
+ textPrinter->state = 3;
+ TextPrinterInitDownArrowCounters(textPrinter);
+ return 3;
+ case 0xF9:
+ char_ = *textPrinter->subPrinter.currentChar++| 0x100;
+ break;
+ case 0xF8:
+ textPrinter->subPrinter.currentChar++;
+ return 0;
+ }
+ DecompressGlyphFont6(char_);
+ CopyGlyphToWindow(textPrinter);
+ textPrinter->subPrinter.currentX += gGlyphInfo[0x80] + textPrinter->subPrinter.letterSpacing;
+ return 0;
+ case 1:
+ if (TextPrinterWait(textPrinter))
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 2:
+ if (TextPrinterWaitWithDownArrow(textPrinter))
+ {
+ FillWindowPixelBuffer(textPrinter->subPrinter.windowId, PIXEL_FILL(textPrinter->subPrinter.bgColor));
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
+ textPrinter->subPrinter.currentY = textPrinter->subPrinter.y;
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 3:
+ if (TextPrinterWaitWithDownArrow(textPrinter))
+ {
+ TextPrinterClearDownArrow(textPrinter);
+ textPrinter->scrollDistance = gFonts[textPrinter->subPrinter.fontId].maxLetterHeight + textPrinter->subPrinter.lineSpacing;
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
+ textPrinter->state = 4;
+ }
+ return 3;
+ case 4:
+ if (textPrinter->scrollDistance)
+ {
+ if (textPrinter->scrollDistance < gUnknown_846FB08[gSaveBlock2Ptr->optionsTextSpeed])
+ {
+ ScrollWindow(textPrinter->subPrinter.windowId, 0, textPrinter->scrollDistance, PIXEL_FILL(textPrinter->subPrinter.bgColor));
+ textPrinter->scrollDistance = 0;
+ }
+ else
+ {
+ ScrollWindow(textPrinter->subPrinter.windowId, 0, gUnknown_846FB08[gSaveBlock2Ptr->optionsTextSpeed], PIXEL_FILL(textPrinter->subPrinter.bgColor));
+ textPrinter->scrollDistance -= gUnknown_846FB08[gSaveBlock2Ptr->optionsTextSpeed];
+ }
+ CopyWindowToVram(textPrinter->subPrinter.windowId, 2);
+ }
+ else
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 5:
+ if (!IsSEPlaying())
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 6:
+ if (textPrinter->delayCounter)
+ {
+ textPrinter->delayCounter --;
+ }
+ else
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ }
+ return 1;
+}
+
+static void DecompressGlyphFont6(u16 glyph)
+{
+ const u16 *glyphs;
+
+ glyphs = sFont6BrailleGlyphs + 0x100 * (glyph / 8) + 0x10 * (glyph % 8);
+ DecompressGlyphTile(glyphs, (u16 *)gGlyphInfo);
+ DecompressGlyphTile(glyphs + 0x8, (u16 *)(gGlyphInfo + 0x20));
+ DecompressGlyphTile(glyphs + 0x80, (u16 *)(gGlyphInfo + 0x40));
+ DecompressGlyphTile(glyphs + 0x88, (u16 *)(gGlyphInfo + 0x60));
+ gGlyphInfo[0x80] = 0x10;
+ gGlyphInfo[0x81] = 0x10;
+}
+
+u32 GetGlyphWidthFont6(u16 font_type, bool32 isJapanese)
+{
+ return 0x10;
+}
diff --git a/src/cereader_tool.c b/src/cereader_tool.c
new file mode 100644
index 000000000..1b25f4828
--- /dev/null
+++ b/src/cereader_tool.c
@@ -0,0 +1,88 @@
+#include "global.h"
+#include "util.h"
+#include "save.h"
+#include "malloc.h"
+#include "cereader_tool.h"
+
+u8 sub_815D654(void)
+{
+ return (gSaveBlock1Ptr->unkArray[0].unk9 + 1) % 256;
+}
+
+static bool32 ValidateTrainerTowerTrainer(struct TrainerTowerTrainer * trainer)
+{
+ if (trainer->unk_001 < 1 || trainer->unk_001 > 8)
+ return FALSE;
+ if (trainer->unk_002 > 2)
+ return FALSE;
+ if (CalcByteArraySum((const u8 *)trainer, offsetof(typeof(*trainer), checksum)) != trainer->checksum)
+ return FALSE;
+ return TRUE;
+}
+
+bool32 ValidateTrainerTowerData(struct TrainerTowerData * ttdata)
+{
+ u32 count = ttdata->count;
+ s32 i;
+ if (count < 1 || count > 8)
+ return FALSE;
+ for (i = 0; i < count; i++)
+ {
+ if (!ValidateTrainerTowerTrainer(&ttdata->trainers[i]))
+ return FALSE;
+ }
+ if (CalcByteArraySum((const u8 *)ttdata->trainers, count * sizeof(ttdata->trainers[0])) != ttdata->checksum)
+ return FALSE;
+ return TRUE;
+}
+
+#define SEC30_SIZE (offsetof(struct TrainerTowerData, trainers[4]))
+#define SEC31_SIZE (sizeof(struct TrainerTowerData) - SEC30_SIZE)
+
+static bool32 CEReaderTool_SaveTrainerTower_r(struct TrainerTowerData * ttdata, u8 * buffer)
+{
+ AGB_ASSERT_EX(ttdata->dummy == 0, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/cereader_tool.c", 198);
+ AGB_ASSERT_EX(ttdata->id == 0, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/cereader_tool.c", 199)
+
+ memset(buffer, 0, 0x1000);
+ memcpy(buffer, ttdata, SEC30_SIZE);
+ buffer[1] = sub_815D654();
+ if (TryWriteSpecialSaveSection(30, buffer) != TRUE)
+ return FALSE;
+ memset(buffer, 0, 0x1000);
+ memcpy(buffer, (u8 *)ttdata + SEC30_SIZE, SEC31_SIZE);
+ if (TryWriteSpecialSaveSection(31, buffer) != TRUE)
+ return FALSE;
+ return TRUE;
+}
+
+bool32 CEReaderTool_SaveTrainerTower(struct TrainerTowerData * ttdata)
+{
+ u8 * buffer = AllocZeroed(0x1000);
+ bool32 result = CEReaderTool_SaveTrainerTower_r(ttdata, buffer);
+ Free(buffer);
+ return result;
+}
+
+static bool32 CEReaderTool_LoadTrainerTower_r(struct TrainerTowerData * ttdata, void * buffer)
+{
+ if (TryCopySpecialSaveSection(30, buffer) != 1)
+ return FALSE;
+ memcpy(ttdata + 0x000, buffer, SEC30_SIZE);
+
+ if (TryCopySpecialSaveSection(31, buffer) != 1)
+ return FALSE;
+ memcpy((u8 *)ttdata + SEC30_SIZE, buffer, SEC31_SIZE);
+
+ if (!ValidateTrainerTowerData(ttdata))
+ return FALSE;
+ return TRUE;
+}
+
+bool32 CEReaderTool_LoadTrainerTower(struct TrainerTowerData * ttdata)
+{
+ void * buffer = AllocZeroed(0x1000);
+ bool32 success = CEReaderTool_LoadTrainerTower_r(ttdata, buffer);
+ Free(buffer);
+ return success;
+}
diff --git a/src/coins.c b/src/coins.c
index 08646e2f9..3a51f6813 100644
--- a/src/coins.c
+++ b/src/coins.c
@@ -3,8 +3,8 @@
#include "text.h"
#include "menu.h"
#include "text_window.h"
+#include "strings.h"
-extern const u8 gText_Coins[];
extern const u8 gUnknown_8417C2D[];
EWRAM_DATA static u8 sCoinsWindowId = 0;
@@ -87,7 +87,7 @@ void ShowCoinsWindow(u32 coinAmount, u8 x, u8 y)
sCoinsWindowId = AddWindow(&template2);
FillWindowPixelBuffer(sCoinsWindowId, 0);
PutWindowTilemap(sCoinsWindowId);
- sub_814FF2C(sCoinsWindowId, 0x21D, 0xD0);
+ TextWindow_SetStdFrame0_WithPal(sCoinsWindowId, 0x21D, 0xD0);
SetWindowBorderStyle(sCoinsWindowId, FALSE, 0x21D, 0xD);
AddTextPrinterParameterized(sCoinsWindowId, 2, gUnknown_8417C2D, 0, 0, 0xFF, 0);
PrintCoinsString(coinAmount);
@@ -96,6 +96,6 @@ void ShowCoinsWindow(u32 coinAmount, u8 x, u8 y)
void HideCoinsWindow(void)
{
ClearWindowTilemap(sCoinsWindowId);
- sub_810F4D8(sCoinsWindowId, TRUE);
+ ClearMenuWindow(sCoinsWindowId, TRUE);
RemoveWindow(sCoinsWindowId);
}
diff --git a/src/coord_event_weather.c b/src/coord_event_weather.c
new file mode 100644
index 000000000..4dbdd574b
--- /dev/null
+++ b/src/coord_event_weather.c
@@ -0,0 +1,47 @@
+#include "global.h"
+
+void nullsub_27(void) {}
+void nullsub_28(void) {}
+void nullsub_29(void) {}
+void nullsub_30(void) {}
+void nullsub_31(void) {}
+void nullsub_32(void) {}
+void nullsub_33(void) {}
+void nullsub_34(void) {}
+void nullsub_35(void) {}
+void nullsub_36(void) {}
+void nullsub_37(void) {}
+void nullsub_38(void) {}
+void nullsub_39(void) {}
+
+struct {
+ u8 weatherId;
+ void (*callback)(void);
+} const gUnknown_83A72A8[] = {
+ {0x01, nullsub_27},
+ {0x02, nullsub_28},
+ {0x03, nullsub_29},
+ {0x04, nullsub_30},
+ {0x05, nullsub_31},
+ {0x06, nullsub_32},
+ {0x07, nullsub_33},
+ {0x08, nullsub_34},
+ {0x09, nullsub_35},
+ {0x0a, nullsub_36},
+ {0x0b, nullsub_37},
+ {0x14, nullsub_38},
+ {0x15, nullsub_39}
+};
+
+void trigger_activate_weather(u8 weatherId)
+{
+ u8 i;
+ for (i = 0; i < NELEMS(gUnknown_83A72A8); i++)
+ {
+ if (gUnknown_83A72A8[i].weatherId == weatherId)
+ {
+ gUnknown_83A72A8[i].callback();
+ return;
+ }
+ }
+}
diff --git a/src/data/items.json b/src/data/items.json
new file mode 100644
index 000000000..b976e4c3e
--- /dev/null
+++ b/src/data/items.json
@@ -0,0 +1,6062 @@
+{
+ "items": [
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MASTER BALL",
+ "itemId": "ITEM_MASTER_BALL",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The best BALL with the ultimate\\nperformance. It will catch any wild\\nPOKéMON without fail.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 0,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 0
+ },
+ {
+ "english": "ULTRA BALL",
+ "itemId": "ITEM_ULTRA_BALL",
+ "price": 1200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A very high-grade BALL that offers\\na higher POKéMON catch rate than\\na GREAT BALL.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 1
+ },
+ {
+ "english": "GREAT BALL",
+ "itemId": "ITEM_GREAT_BALL",
+ "price": 600,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A good, quality BALL that offers\\na higher POKéMON catch rate than\\na standard POKé BALL.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 2,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 2
+ },
+ {
+ "english": "POK\u00e9 BALL",
+ "itemId": "ITEM_POKE_BALL",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A BALL thrown to catch a wild\\nPOKéMON. It is designed in a\\ncapsule style.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 3,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 3
+ },
+ {
+ "english": "SAFARI BALL",
+ "itemId": "ITEM_SAFARI_BALL",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A special BALL that is used only in\\nthe SAFARI ZONE. It is finished in\\na camouflage pattern.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 4,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 4
+ },
+ {
+ "english": "NET BALL",
+ "itemId": "ITEM_NET_BALL",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A somewhat different BALL that\\nworks especially well on WATER- and\\nBUG-type POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 5,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 5
+ },
+ {
+ "english": "DIVE BALL",
+ "itemId": "ITEM_DIVE_BALL",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A somewhat different BALL that\\nworks especially well on POKéMON\\ndeep in the sea.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 6,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 6
+ },
+ {
+ "english": "NEST BALL",
+ "itemId": "ITEM_NEST_BALL",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A somewhat different BALL that\\nworks especially well on weaker\\nPOKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 7,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 7
+ },
+ {
+ "english": "REPEAT BALL",
+ "itemId": "ITEM_REPEAT_BALL",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A somewhat different BALL that\\nworks especially well on POKéMON\\ncaught before.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 8,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 8
+ },
+ {
+ "english": "TIMER BALL",
+ "itemId": "ITEM_TIMER_BALL",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A somewhat different BALL that\\nbecomes progressively better the\\nmore turns there are in a battle.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 9,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 9
+ },
+ {
+ "english": "LUXURY BALL",
+ "itemId": "ITEM_LUXURY_BALL",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A comfortable BALL that makes a\\ncaptured wild POKéMON quickly grow\\nfriendly.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 10,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 10
+ },
+ {
+ "english": "PREMIER BALL",
+ "itemId": "ITEM_PREMIER_BALL",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A rare BALL that has been\\nspecially made to commemorate an\\nevent of some sort.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_POKE_BALLS",
+ "type": 11,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeBallEtc",
+ "secondaryId": 11
+ },
+ {
+ "english": "POTION",
+ "itemId": "ITEM_POTION",
+ "price": 300,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 20,
+ "description_english": "A spray-type wound medicine.\\nIt restores the HP of one POKéMON\\nby 20 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "ANTIDOTE",
+ "itemId": "ITEM_ANTIDOTE",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A spray-type medicine.\\nIt heals one POKéMON from a\\npoisoning.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "BURN HEAL",
+ "itemId": "ITEM_BURN_HEAL",
+ "price": 250,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A spray-type medicine.\\nIt heals one POKéMON of a burn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "ICE HEAL",
+ "itemId": "ITEM_ICE_HEAL",
+ "price": 250,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A spray-type medicine.\\nIt defrosts a frozen POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "AWAKENING",
+ "itemId": "ITEM_AWAKENING",
+ "price": 250,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A spray-type medicine.\\nIt awakens a sleeping POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "PARLYZ HEAL",
+ "itemId": "ITEM_PARALYZE_HEAL",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A spray-type medicine.\\nIt heals one POKéMON from\\nparalysis.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "FULL RESTORE",
+ "itemId": "ITEM_FULL_RESTORE",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 255,
+ "description_english": "A medicine that fully restores the\\nHP and heals any status problems\\nof one POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "MAX POTION",
+ "itemId": "ITEM_MAX_POTION",
+ "price": 2500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 255,
+ "description_english": "A spray-type wound medicine.\\nIt fully restores the HP of one\\nPOKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "HYPER POTION",
+ "itemId": "ITEM_HYPER_POTION",
+ "price": 1200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 200,
+ "description_english": "A spray-type wound medicine.\\nIt restores the HP of one POKéMON\\nby 200 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "SUPER POTION",
+ "itemId": "ITEM_SUPER_POTION",
+ "price": 700,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 50,
+ "description_english": "A spray-type wound medicine.\\nIt restores the HP of one POKéMON\\nby 50 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "FULL HEAL",
+ "itemId": "ITEM_FULL_HEAL",
+ "price": 600,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A spray-type medicine.\\nIt heals all the status problems of\\none POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "REVIVE",
+ "itemId": "ITEM_REVIVE",
+ "price": 1500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A medicine that revives a fainted\\nPOKéMON, restoring HP by half the\\nmaximum amount.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "MAX REVIVE",
+ "itemId": "ITEM_MAX_REVIVE",
+ "price": 4000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A medicine that revives a fainted\\nPOKéMON, restoring HP fully.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "FRESH WATER",
+ "itemId": "ITEM_FRESH_WATER",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 50,
+ "description_english": "Water with a high mineral content.\\nIt restores the HP of one POKéMON\\nby 50 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "SODA POP",
+ "itemId": "ITEM_SODA_POP",
+ "price": 300,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 60,
+ "description_english": "A fizzy soda drink.\\nIt restores the HP of one POKéMON\\nby 60 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "LEMONADE",
+ "itemId": "ITEM_LEMONADE",
+ "price": 350,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 80,
+ "description_english": "A very sweet drink.\\nIt restores the HP of one POKéMON\\nby 80 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "MOOMOO MILK",
+ "itemId": "ITEM_MOOMOO_MILK",
+ "price": 500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 100,
+ "description_english": "Highly nutritious milk.\\nIt restores the HP of one POKéMON\\nby 100 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "ENERGYPOWDER",
+ "itemId": "ITEM_ENERGY_POWDER",
+ "price": 500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A very bitter medicine powder.\\nIt restores the HP of one POKéMON\\nby 50 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "ENERGY ROOT",
+ "itemId": "ITEM_ENERGY_ROOT",
+ "price": 800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A very bitter root.\\nIt restores the HP of one POKéMON\\nby 200 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "HEAL POWDER",
+ "itemId": "ITEM_HEAL_POWDER",
+ "price": 450,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A very bitter medicine powder.\\nIt heals all the status problems of\\none POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "REVIVAL HERB",
+ "itemId": "ITEM_REVIVAL_HERB",
+ "price": 2800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A very bitter medicinal herb.\\nIt revives a fainted POKéMON,\\nrestoring HP fully.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "ETHER",
+ "itemId": "ITEM_ETHER",
+ "price": 1200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 10,
+ "description_english": "Restores a selected move's PP by\\n10 points for one POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Ether",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Ether",
+ "secondaryId": 0
+ },
+ {
+ "english": "MAX ETHER",
+ "itemId": "ITEM_MAX_ETHER",
+ "price": 2000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 255,
+ "description_english": "Fully restores a selected move's PP\\nfor one POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Ether",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Ether",
+ "secondaryId": 0
+ },
+ {
+ "english": "ELIXIR",
+ "itemId": "ITEM_ELIXIR",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 10,
+ "description_english": "Restores the PP of all moves for\\none POKéMON by 10 points each.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Ether",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Ether",
+ "secondaryId": 0
+ },
+ {
+ "english": "MAX ELIXIR",
+ "itemId": "ITEM_MAX_ELIXIR",
+ "price": 4500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 255,
+ "description_english": "Fully restores the PP of all moves\\nfor one POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Ether",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Ether",
+ "secondaryId": 0
+ },
+ {
+ "english": "LAVA COOKIE",
+ "itemId": "ITEM_LAVA_COOKIE",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "LAVARIDGE TOWN's local specialty.\\nIt heals all the status problems of\\none POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "BLUE FLUTE",
+ "itemId": "ITEM_BLUE_FLUTE",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A blue glass flute that awakens\\na sleeping POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "YELLOW FLUTE",
+ "itemId": "ITEM_YELLOW_FLUTE",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A yellow glass flute that snaps one\\nPOKéMON out of confusion.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "RED FLUTE",
+ "itemId": "ITEM_RED_FLUTE",
+ "price": 300,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A red glass flute that snaps one\\nPOKéMON out of infatuation.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "BLACK FLUTE",
+ "itemId": "ITEM_BLACK_FLUTE",
+ "price": 400,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 50,
+ "description_english": "A black glass flute.\\nWhen blown, it makes wild POKéMON\\nless likely to appear.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_BlackFlute",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "WHITE FLUTE",
+ "itemId": "ITEM_WHITE_FLUTE",
+ "price": 500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 150,
+ "description_english": "A white glass flute.\\nWhen blown, it makes wild POKéMON\\nmore likely to appear.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_BlackFlute",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BERRY JUICE",
+ "itemId": "ITEM_BERRY_JUICE",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_RESTORE_HP",
+ "holdEffectParam": 20,
+ "description_english": "A 100% pure juice.\\nIt restores the HP of one POKéMON\\nby 20 points.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "SACRED ASH",
+ "itemId": "ITEM_SACRED_ASH",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Revives all fainted POKéMON,\\nrestoring HP fully.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_SacredAsh",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SHOAL SALT",
+ "itemId": "ITEM_SHOAL_SALT",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Pure salt obtained from deep inside\\nthe SHOAL CAVE. It is extremely\\nsalty.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SHOAL SHELL",
+ "itemId": "ITEM_SHOAL_SHELL",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A pretty seashell found deep inside\\nthe SHOAL CAVE. It is striped in\\nblue and white.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RED SHARD",
+ "itemId": "ITEM_RED_SHARD",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A small red shard.\\nIt appears to be from some sort of\\na tool made long ago.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BLUE SHARD",
+ "itemId": "ITEM_BLUE_SHARD",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A small blue shard.\\nIt appears to be from some sort of\\na tool made long ago.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "YELLOW SHARD",
+ "itemId": "ITEM_YELLOW_SHARD",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A small yellow shard.\\nIt appears to be from some sort of\\na tool made long ago.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "GREEN SHARD",
+ "itemId": "ITEM_GREEN_SHARD",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A small green shard.\\nIt appears to be from some sort of\\na tool made long ago.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "HP UP",
+ "itemId": "ITEM_HP_UP",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A nutritious drink for POKéMON.\\nIt raises the base HP of one\\nPOKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "PROTEIN",
+ "itemId": "ITEM_PROTEIN",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A nutritious drink for POKéMON.\\nIt raises the base ATTACK stat of\\none POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "IRON",
+ "itemId": "ITEM_IRON",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A nutritious drink for POKéMON.\\nIt raises the base DEFENSE stat of\\none POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "CARBOS",
+ "itemId": "ITEM_CARBOS",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A nutritious drink for POKéMON.\\nIt raises the base SPEED stat of\\none POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "CALCIUM",
+ "itemId": "ITEM_CALCIUM",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A nutritious drink for POKéMON.\\nIt raises the base SP. ATK stat\\nof one POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RARE CANDY",
+ "itemId": "ITEM_RARE_CANDY",
+ "price": 4800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A candy that is packed with energy.\\nIt raises the level of a POKéMON\\nby one.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_RareCandy",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "PP UP",
+ "itemId": "ITEM_PP_UP",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Slightly raises the maximum PP of\\na selected move for one POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_PpUp",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "ZINC",
+ "itemId": "ITEM_ZINC",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A nutritious drink for POKéMON.\\nIt raises the base SP. DEF stat\\nof one POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "PP MAX",
+ "itemId": "ITEM_PP_MAX",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Raises the PP of a selected move\\nto its maximum level for one\\nPOKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_PpUp",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "GUARD SPEC.",
+ "itemId": "ITEM_GUARD_SPEC",
+ "price": 700,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An item that prevents stat reduction\\namong party POKéMON for five turns\\nafter use.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_GuardSpec",
+ "secondaryId": 0
+ },
+ {
+ "english": "DIRE HIT",
+ "itemId": "ITEM_DIRE_HIT",
+ "price": 650,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Raises the critical-hit ratio of\\nPOKéMON in battle. Wears off if the\\nPOKéMON is withdrawn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_GuardSpec",
+ "secondaryId": 0
+ },
+ {
+ "english": "X ATTACK",
+ "itemId": "ITEM_X_ATTACK",
+ "price": 500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Raises the ATTACK stat of POKéMON\\nin battle. Wears off if the POKéMON\\nis withdrawn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_GuardSpec",
+ "secondaryId": 0
+ },
+ {
+ "english": "X DEFEND",
+ "itemId": "ITEM_X_DEFEND",
+ "price": 550,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Raises the DEFENSE stat of POKéMON\\nin battle. Wears off if the POKéMON\\nis withdrawn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_GuardSpec",
+ "secondaryId": 0
+ },
+ {
+ "english": "X SPEED",
+ "itemId": "ITEM_X_SPEED",
+ "price": 350,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Raises the SPEED stat of POKéMON\\nin battle. Wears off if the POKéMON\\nis withdrawn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_GuardSpec",
+ "secondaryId": 0
+ },
+ {
+ "english": "X ACCURACY",
+ "itemId": "ITEM_X_ACCURACY",
+ "price": 950,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Raises the accuracy stat of\\nPOKéMON in battle. Wears off if the\\nPOKéMON is withdrawn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_GuardSpec",
+ "secondaryId": 0
+ },
+ {
+ "english": "X SPECIAL",
+ "itemId": "ITEM_X_SPECIAL",
+ "price": 350,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Raises the SP. ATK stat of\\nPOKéMON in battle. Wears off if the\\nPOKéMON is withdrawn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_GuardSpec",
+ "secondaryId": 0
+ },
+ {
+ "english": "POK\u00e9 DOLL",
+ "itemId": "ITEM_POKE_DOLL",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An attractive doll.\\nUse it to flee from any battle with\\na wild POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeDoll",
+ "secondaryId": 0
+ },
+ {
+ "english": "FLUFFY TAIL",
+ "itemId": "ITEM_FLUFFY_TAIL",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An attractive item.\\nUse it to flee from any battle with\\na wild POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeDoll",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SUPER REPEL",
+ "itemId": "ITEM_SUPER_REPEL",
+ "price": 500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 200,
+ "description_english": "Prevents weak wild POKéMON from\\nappearing for 200 steps.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_SuperRepel",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MAX REPEL",
+ "itemId": "ITEM_MAX_REPEL",
+ "price": 700,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 250,
+ "description_english": "Prevents weak wild POKéMON from\\nappearing for 250 steps.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_SuperRepel",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "ESCAPE ROPE",
+ "itemId": "ITEM_ESCAPE_ROPE",
+ "price": 550,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A long, durable rope.\\nUse it to escape instantly from a\\ncave or a dungeon.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "ItemUseOutOfBattle_EscapeRope",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "REPEL",
+ "itemId": "ITEM_REPEL",
+ "price": 350,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 100,
+ "description_english": "Prevents weak wild POKéMON from\\nappearing for 100 steps.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_SuperRepel",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SUN STONE",
+ "itemId": "ITEM_SUN_STONE",
+ "price": 2100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A peculiar stone that makes certain\\nspecies of POKéMON evolve.\\nIt is as red as the sun.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_EvoItem",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MOON STONE",
+ "itemId": "ITEM_MOON_STONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A peculiar stone that makes certain\\nspecies of POKéMON evolve.\\nIt is as black as the night sky.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_EvoItem",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "FIRE STONE",
+ "itemId": "ITEM_FIRE_STONE",
+ "price": 2100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A peculiar stone that makes certain\\nspecies of POKéMON evolve.\\nIt is colored orange.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_EvoItem",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "THUNDERSTONE",
+ "itemId": "ITEM_THUNDER_STONE",
+ "price": 2100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A peculiar stone that makes certain\\nspecies of POKéMON evolve.\\nIt has a thunderbolt pattern.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_EvoItem",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "WATER STONE",
+ "itemId": "ITEM_WATER_STONE",
+ "price": 2100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A peculiar stone that makes certain\\nspecies of POKéMON evolve.\\nIt is a clear light blue.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_EvoItem",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LEAF STONE",
+ "itemId": "ITEM_LEAF_STONE",
+ "price": 2100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A peculiar stone that makes certain\\nspecies of POKéMON evolve.\\nIt has a leaf pattern.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_EvoItem",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "TINYMUSHROOM",
+ "itemId": "ITEM_TINY_MUSHROOM",
+ "price": 500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A small and rare mushroom.\\nIt is quite popular among certain\\npeople.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BIG MUSHROOM",
+ "itemId": "ITEM_BIG_MUSHROOM",
+ "price": 5000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A large and rare mushroom.\\nIt is very popular among certain\\npeople.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "PEARL",
+ "itemId": "ITEM_PEARL",
+ "price": 1400,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A relatively small pearl that\\nsparkles in a pretty silver color.\\nIt can be sold cheaply.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BIG PEARL",
+ "itemId": "ITEM_BIG_PEARL",
+ "price": 7500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A quite-large pearl that sparkles\\nin a pretty silver color.\\nIt can be sold at a high price.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "STARDUST",
+ "itemId": "ITEM_STARDUST",
+ "price": 2000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A pretty red sand with a loose,\\nsilky feel.\\nIt can be sold at a high price.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "STAR PIECE",
+ "itemId": "ITEM_STAR_PIECE",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A shard of a pretty gem that\\nsparkles in a red color.\\nIt can be sold at a high price.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "NUGGET",
+ "itemId": "ITEM_NUGGET",
+ "price": 10000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A nugget of pure gold that gives\\noff a lustrous gleam.\\nIt can be sold at a high price.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "HEART SCALE",
+ "itemId": "ITEM_HEART_SCALE",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A pretty, heart-shaped scale that\\nis extremely rare. It glows faintly\\nin the colors of a rainbow.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "ORANGE MAIL",
+ "itemId": "ITEM_ORANGE_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a cute\\nZIGZAGOON print.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "HARBOR MAIL",
+ "itemId": "ITEM_HARBOR_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a cute\\nWINGULL print.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 1
+ },
+ {
+ "english": "GLITTER MAIL",
+ "itemId": "ITEM_GLITTER_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a cute\\nPIKACHU print.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 2
+ },
+ {
+ "english": "MECH MAIL",
+ "itemId": "ITEM_MECH_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a cute\\nMAGNEMITE print.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 3
+ },
+ {
+ "english": "WOOD MAIL",
+ "itemId": "ITEM_WOOD_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a cute\\nSLAKOTH print.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 4
+ },
+ {
+ "english": "WAVE MAIL",
+ "itemId": "ITEM_WAVE_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a cute\\nWAILMER print.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 5
+ },
+ {
+ "english": "BEAD MAIL",
+ "itemId": "ITEM_BEAD_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL to be held by a\\nPOKéMON. It will bear the print of\\nthe POKéMON holding it.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 6
+ },
+ {
+ "english": "SHADOW MAIL",
+ "itemId": "ITEM_SHADOW_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a cute\\nDUSKULL print.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 7
+ },
+ {
+ "english": "TROPIC MAIL",
+ "itemId": "ITEM_TROPIC_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a cute\\nBELLOSSOM print.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 8
+ },
+ {
+ "english": "DREAM MAIL",
+ "itemId": "ITEM_DREAM_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL to be held by a\\nPOKéMON. It will bear the print of\\nthe POKéMON holding it.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 9
+ },
+ {
+ "english": "FAB MAIL",
+ "itemId": "ITEM_FAB_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a\\ngorgeous, extravagant print.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 10
+ },
+ {
+ "english": "RETRO MAIL",
+ "itemId": "ITEM_RETRO_MAIL",
+ "price": 50,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of MAIL featuring a print\\nof three cute POKéMON.\\nIt is to be held by a POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 0,
+ "fieldUseFunc": "FieldUseFunc_OrangeMail",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 11
+ },
+ {
+ "english": "CHERI BERRY",
+ "itemId": "ITEM_CHERI_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CURE_PAR",
+ "holdEffectParam": 0,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle to heal paralysis.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "CHESTO BERRY",
+ "itemId": "ITEM_CHESTO_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CURE_SLP",
+ "holdEffectParam": 0,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle to wake up.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "PECHA BERRY",
+ "itemId": "ITEM_PECHA_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CURE_PSN",
+ "holdEffectParam": 0,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle to cure poison.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "RAWST BERRY",
+ "itemId": "ITEM_RAWST_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CURE_BRN",
+ "holdEffectParam": 0,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle to heal a burn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "ASPEAR BERRY",
+ "itemId": "ITEM_ASPEAR_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CURE_FRZ",
+ "holdEffectParam": 0,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle for defrosting.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "LEPPA BERRY",
+ "itemId": "ITEM_LEPPA_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_RESTORE_PP",
+ "holdEffectParam": 10,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle to restore 10 PP.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Ether",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Ether",
+ "secondaryId": 0
+ },
+ {
+ "english": "ORAN BERRY",
+ "itemId": "ITEM_ORAN_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_RESTORE_HP",
+ "holdEffectParam": 10,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle to restore 10 HP.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "PERSIM BERRY",
+ "itemId": "ITEM_PERSIM_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CURE_CONFUSION",
+ "holdEffectParam": 0,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle to lift confusion.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "LUM BERRY",
+ "itemId": "ITEM_LUM_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CURE_STATUS",
+ "holdEffectParam": 0,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle to heal any problem.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "SITRUS BERRY",
+ "itemId": "ITEM_SITRUS_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_RESTORE_HP",
+ "holdEffectParam": 30,
+ "description_english": "When held by a POKéMON, it will be\\nused in battle to restore 30 HP.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 1,
+ "fieldUseFunc": "FieldUseFunc_Medicine",
+ "battleUsage": 1,
+ "battleUseFunc": "BattleUseFunc_Medicine",
+ "secondaryId": 0
+ },
+ {
+ "english": "FIGY BERRY",
+ "itemId": "ITEM_FIGY_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CONFUSE_SPICY",
+ "holdEffectParam": 8,
+ "description_english": "A hold item that restores HP but\\nmay cause confusion when used.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "WIKI BERRY",
+ "itemId": "ITEM_WIKI_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CONFUSE_DRY",
+ "holdEffectParam": 8,
+ "description_english": "A hold item that restores HP but\\nmay cause confusion when used.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MAGO BERRY",
+ "itemId": "ITEM_MAGO_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CONFUSE_SWEET",
+ "holdEffectParam": 8,
+ "description_english": "A hold item that restores HP but\\nmay cause confusion when used.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "AGUAV BERRY",
+ "itemId": "ITEM_AGUAV_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CONFUSE_BITTER",
+ "holdEffectParam": 8,
+ "description_english": "A hold item that restores HP but\\nmay cause confusion when used.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "IAPAPA BERRY",
+ "itemId": "ITEM_IAPAPA_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CONFUSE_SOUR",
+ "holdEffectParam": 8,
+ "description_english": "A hold item that restores HP but\\nmay cause confusion when used.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RAZZ BERRY",
+ "itemId": "ITEM_RAZZ_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BLUK BERRY",
+ "itemId": "ITEM_BLUK_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "NANAB BERRY",
+ "itemId": "ITEM_NANAB_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "WEPEAR BERRY",
+ "itemId": "ITEM_WEPEAR_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "PINAP BERRY",
+ "itemId": "ITEM_PINAP_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "POMEG BERRY",
+ "itemId": "ITEM_POMEG_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "KELPSY BERRY",
+ "itemId": "ITEM_KELPSY_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "QUALOT BERRY",
+ "itemId": "ITEM_QUALOT_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "HONDEW BERRY",
+ "itemId": "ITEM_HONDEW_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "GREPA BERRY",
+ "itemId": "ITEM_GREPA_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "TAMATO BERRY",
+ "itemId": "ITEM_TAMATO_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "CORNN BERRY",
+ "itemId": "ITEM_CORNN_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MAGOST BERRY",
+ "itemId": "ITEM_MAGOST_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RABUTA BERRY",
+ "itemId": "ITEM_RABUTA_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "NOMEL BERRY",
+ "itemId": "ITEM_NOMEL_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SPELON BERRY",
+ "itemId": "ITEM_SPELON_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "PAMTRE BERRY",
+ "itemId": "ITEM_PAMTRE_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "WATMEL BERRY",
+ "itemId": "ITEM_WATMEL_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "DURIN BERRY",
+ "itemId": "ITEM_DURIN_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BELUE BERRY",
+ "itemId": "ITEM_BELUE_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LIECHI BERRY",
+ "itemId": "ITEM_LIECHI_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_ATTACK_UP",
+ "holdEffectParam": 4,
+ "description_english": "When held by a POKéMON, it raises\\nthe ATTACK stat in a pinch.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "GANLON BERRY",
+ "itemId": "ITEM_GANLON_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_DEFENSE_UP",
+ "holdEffectParam": 4,
+ "description_english": "When held by a POKéMON, it raises\\nthe DEFENSE stat in a pinch.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SALAC BERRY",
+ "itemId": "ITEM_SALAC_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_SPEED_UP",
+ "holdEffectParam": 4,
+ "description_english": "When held by a POKéMON, it raises\\nthe SPEED stat in a pinch.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "PETAYA BERRY",
+ "itemId": "ITEM_PETAYA_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_SP_ATTACK_UP",
+ "holdEffectParam": 4,
+ "description_english": "When held by a POKéMON, it raises\\nthe SP. ATK stat in a pinch.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "APICOT BERRY",
+ "itemId": "ITEM_APICOT_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_SP_DEFENSE_UP",
+ "holdEffectParam": 4,
+ "description_english": "When held by a POKéMON, it raises\\nthe SP. DEF stat in a pinch.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LANSAT BERRY",
+ "itemId": "ITEM_LANSAT_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_CRITICAL_UP",
+ "holdEffectParam": 4,
+ "description_english": "When held by a POKéMON, it raises\\nthe critical-hit ratio in a pinch.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "STARF BERRY",
+ "itemId": "ITEM_STARF_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_RANDOM_STAT_UP",
+ "holdEffectParam": 4,
+ "description_english": "When held by a POKéMON, it sharply\\nraises one stat in a pinch.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "ENIGMA BERRY",
+ "itemId": "ITEM_ENIGMA_BERRY",
+ "price": 20,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Can be ground up into a powder as\\nan ingredient for medicine.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_BERRY_POUCH",
+ "type": 4,
+ "fieldUseFunc": "ItemUseOutOfBattle_EnigmaBerry",
+ "battleUsage": 1,
+ "battleUseFunc": "ItemUseInBattle_EnigmaBerry",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BRIGHTPOWDER",
+ "itemId": "ITEM_BRIGHT_POWDER",
+ "price": 10,
+ "holdEffect": "HOLD_EFFECT_EVASION_UP",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nIt casts a tricky glare that lowers\\nthe opponent's accuracy.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "WHITE HERB",
+ "itemId": "ITEM_WHITE_HERB",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_RESTORE_STATS",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt restores any lowered stat in\\nbattle. It can be used only once.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MACHO BRACE",
+ "itemId": "ITEM_MACHO_BRACE",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_MACHO_BRACE",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt promotes strong growth but\\nlowers SPEED while it is held.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "EXP. SHARE",
+ "itemId": "ITEM_EXP_SHARE",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_EXP_SHARE",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nThe holder gets a share of EXP.\\npoints without having to battle.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "QUICK CLAW",
+ "itemId": "ITEM_QUICK_CLAW",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_QUICK_CLAW",
+ "holdEffectParam": 20,
+ "description_english": "An item to be held by a POKéMON.\\nA light and sharp claw. The holder\\nmay be able to strike first.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SOOTHE BELL",
+ "itemId": "ITEM_SOOTHE_BELL",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_HAPPINESS_UP",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nA bell with a comforting chime that\\nmakes the holder calm and friendly.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MENTAL HERB",
+ "itemId": "ITEM_MENTAL_HERB",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_CURE_ATTRACT",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt snaps the holder out of\\ninfatuation. It can be used once.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "CHOICE BAND",
+ "itemId": "ITEM_CHOICE_BAND",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_CHOICE_BAND",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt powers up one move, which\\nbecomes the only usable one.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "KING'S ROCK",
+ "itemId": "ITEM_KINGS_ROCK",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_FLINCH",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nIt may cause the foe to flinch\\nupon taking damage.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SILVERPOWDER",
+ "itemId": "ITEM_SILVER_POWDER",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_BUG_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA shiny silver powder that boosts\\nthe power of BUG-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "AMULET COIN",
+ "itemId": "ITEM_AMULET_COIN",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_DOUBLE_PRIZE",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nIt doubles the battle money if the\\nholding POKéMON takes part.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "CLEANSE TAG",
+ "itemId": "ITEM_CLEANSE_TAG",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_REPEL",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt repels wild POKéMON if the\\nholder is first in the party.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SOUL DEW",
+ "itemId": "ITEM_SOUL_DEW",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_SOUL_DEW",
+ "holdEffectParam": 0,
+ "description_english": "An orb to be held by a LATIOS or\\nLATIAS. It raises the SP. ATK\\nand SP. DEF stats.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "DEEPSEATOOTH",
+ "itemId": "ITEM_DEEP_SEA_TOOTH",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_DEEP_SEA_TOOTH",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nA fang that gleams a sharp silver.\\nIt raises the SP. ATK stat.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "DEEPSEASCALE",
+ "itemId": "ITEM_DEEP_SEA_SCALE",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_DEEP_SEA_SCALE",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nA scale that shines a faint pink.\\nIt raises the SP. DEF stat.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SMOKE BALL",
+ "itemId": "ITEM_SMOKE_BALL",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_CAN_ALWAYS_RUN",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nThe holding POKéMON can flee from\\nany wild POKéMON for sure.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "EVERSTONE",
+ "itemId": "ITEM_EVERSTONE",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_PREVENT_EVOLVE",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nThe holding POKéMON is prevented\\nfrom evolving.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "FOCUS BAND",
+ "itemId": "ITEM_FOCUS_BAND",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_FOCUS_BAND",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nThe holding POKéMON may endure an\\nattack, leaving just 1 HP.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LUCKY EGG",
+ "itemId": "ITEM_LUCKY_EGG",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_LUCKY_EGG",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nAn egg filled with happiness that\\nearns extra EXP. points in battle.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SCOPE LENS",
+ "itemId": "ITEM_SCOPE_LENS",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_SCOPE_LENS",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nA lens that boosts the critical-hit\\nratio of the holding POKéMON.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "METAL COAT",
+ "itemId": "ITEM_METAL_COAT",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_STEEL_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA special metallic film that boosts\\nthe power of STEEL-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LEFTOVERS",
+ "itemId": "ITEM_LEFTOVERS",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_LEFTOVERS",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nThe holding POKéMON gradually\\nregains HP during battle.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "DRAGON SCALE",
+ "itemId": "ITEM_DRAGON_SCALE",
+ "price": 2100,
+ "holdEffect": "HOLD_EFFECT_DRAGON_SCALE",
+ "holdEffectParam": 10,
+ "description_english": "A thick and tough scale.\\nA DRAGON-type POKéMON may be\\nholding it.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LIGHT BALL",
+ "itemId": "ITEM_LIGHT_BALL",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_LIGHT_BALL",
+ "holdEffectParam": 0,
+ "description_english": "An orb to be held by a PIKACHU\\nthat raises the SP. ATK stat.\\nTouching it may cause a shock.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SOFT SAND",
+ "itemId": "ITEM_SOFT_SAND",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_GROUND_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA loose, silky sand that boosts the\\npower of GROUND-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "HARD STONE",
+ "itemId": "ITEM_HARD_STONE",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_ROCK_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nAn unbreakable stone that boosts\\nthe power of ROCK-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MIRACLE SEED",
+ "itemId": "ITEM_MIRACLE_SEED",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_GRASS_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA seed imbued with life that boosts\\nthe power of GRASS-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BLACKGLASSES",
+ "itemId": "ITEM_BLACK_GLASSES",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_DARK_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA shady-looking pair of glasses\\nthat boosts DARK-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BLACK BELT",
+ "itemId": "ITEM_BLACK_BELT",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_FIGHTING_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA belt that boosts determination\\nand FIGHTING-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MAGNET",
+ "itemId": "ITEM_MAGNET",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_ELECTRIC_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA powerful magnet that boosts the\\npower of ELECTRIC-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MYSTIC WATER",
+ "itemId": "ITEM_MYSTIC_WATER",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_WATER_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA teardrop-shaped gem that boosts\\nthe power of WATER-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SHARP BEAK",
+ "itemId": "ITEM_SHARP_BEAK",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_FLYING_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA long, sharp beak that boosts the\\npower of FLYING-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "POISON BARB",
+ "itemId": "ITEM_POISON_BARB",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_POISON_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA small, poisonous barb that boosts\\nthe power of POISON-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "NEVERMELTICE",
+ "itemId": "ITEM_NEVER_MELT_ICE",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_ICE_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA piece of ice that repels heat\\nand boosts ICE-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SPELL TAG",
+ "itemId": "ITEM_SPELL_TAG",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_GHOST_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA sinister, eerie tag that boosts\\nGHOST-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "TWISTEDSPOON",
+ "itemId": "ITEM_TWISTED_SPOON",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_PSYCHIC_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA spoon imbued with telekinetic\\npower boosts PSYCHIC-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "CHARCOAL",
+ "itemId": "ITEM_CHARCOAL",
+ "price": 9800,
+ "holdEffect": "HOLD_EFFECT_FIRE_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA combustible fuel that boosts the\\npower of FIRE-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "DRAGON FANG",
+ "itemId": "ITEM_DRAGON_FANG",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_DRAGON_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA hard and sharp fang that boosts\\nthe power of DRAGON-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SILK SCARF",
+ "itemId": "ITEM_SILK_SCARF",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_NORMAL_POWER",
+ "holdEffectParam": 10,
+ "description_english": "An item to be held by a POKéMON.\\nA sumptuous scarf that boosts the\\npower of NORMAL-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "UP-GRADE",
+ "itemId": "ITEM_UP_GRADE",
+ "price": 2100,
+ "holdEffect": "HOLD_EFFECT_UP_GRADE",
+ "holdEffectParam": 0,
+ "description_english": "A transparent device filled with all\\nsorts of data.\\nIt is made by SILPH CO.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SHELL BELL",
+ "itemId": "ITEM_SHELL_BELL",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_SHELL_BELL",
+ "holdEffectParam": 8,
+ "description_english": "An item to be held by a POKéMON.\\nThe holding POKéMON regains some\\nHP upon striking the foe.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SEA INCENSE",
+ "itemId": "ITEM_SEA_INCENSE",
+ "price": 9600,
+ "holdEffect": "HOLD_EFFECT_WATER_POWER",
+ "holdEffectParam": 5,
+ "description_english": "An item to be held by a POKéMON.\\nIt slightly boosts the power of\\nWATER-type moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LAX INCENSE",
+ "itemId": "ITEM_LAX_INCENSE",
+ "price": 9600,
+ "holdEffect": "HOLD_EFFECT_EVASION_UP",
+ "holdEffectParam": 5,
+ "description_english": "An item to be held by a POKéMON.\\nIts tricky aroma slightly reduces\\nthe foe's accuracy.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LUCKY PUNCH",
+ "itemId": "ITEM_LUCKY_PUNCH",
+ "price": 10,
+ "holdEffect": "HOLD_EFFECT_LUCKY_PUNCH",
+ "holdEffectParam": 0,
+ "description_english": "A glove to be held by a CHANSEY.\\nIt raises CHANSEY's critical-hit\\nratio.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "METAL POWDER",
+ "itemId": "ITEM_METAL_POWDER",
+ "price": 10,
+ "holdEffect": "HOLD_EFFECT_METAL_POWDER",
+ "holdEffectParam": 0,
+ "description_english": "A fine, hard powder to be held by\\na DITTO.\\nIt raises DITTO's DEFENSE stat.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "THICK CLUB",
+ "itemId": "ITEM_THICK_CLUB",
+ "price": 500,
+ "holdEffect": "HOLD_EFFECT_THICK_CLUB",
+ "holdEffectParam": 0,
+ "description_english": "A hard bone of some sort to be\\nheld by a CUBONE or MAROWAK.\\nIt raises the ATTACK stat.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "STICK",
+ "itemId": "ITEM_STICK",
+ "price": 200,
+ "holdEffect": "HOLD_EFFECT_STICK",
+ "holdEffectParam": 0,
+ "description_english": "A stick of leek to be held by a\\nFARFETCH'D. It raises FARFETCH'D's\\ncritical-hit ratio.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RED SCARF",
+ "itemId": "ITEM_RED_SCARF",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt boosts the holding POKéMON's\\nCOOL condition in CONTESTS.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BLUE SCARF",
+ "itemId": "ITEM_BLUE_SCARF",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt boosts the holding POKéMON's\\nBEAUTY condition in CONTESTS.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "PINK SCARF",
+ "itemId": "ITEM_PINK_SCARF",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt boosts the holding POKéMON's\\nCUTE condition in CONTESTS.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "GREEN SCARF",
+ "itemId": "ITEM_GREEN_SCARF",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt boosts the holding POKéMON's\\nSMART condition in CONTESTS.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "YELLOW SCARF",
+ "itemId": "ITEM_YELLOW_SCARF",
+ "price": 100,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An item to be held by a POKéMON.\\nIt boosts the holding POKéMON's\\nTOUGH condition in CONTESTS.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MACH BIKE",
+ "itemId": "ITEM_MACH_BIKE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A folding bicycle that is at least\\ntwice as fast as walking.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "FieldUseFunc_MachBike",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "COIN CASE",
+ "itemId": "ITEM_COIN_CASE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A case for holding COINS obtained\\nat the GAME CORNER.\\nIt holds up to 9,999 COINS.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_CoinCase",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "ITEMFINDER",
+ "itemId": "ITEM_ITEMFINDER",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A device used for finding items.\\nIf there is a hidden item nearby\\nwhen it is used, it emits a signal.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "ItemUseOutOfBattle_Itemfinder",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "OLD ROD",
+ "itemId": "ITEM_OLD_ROD",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An old and beat-up fishing rod.\\nUse it by any body of water to \\nfish for wild POKéMON.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "FieldUseFunc_OldRod",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "GOOD ROD",
+ "itemId": "ITEM_GOOD_ROD",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A new, good-quality fishing rod.\\nUse it by any body of water to \\nfish for wild POKéMON.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "FieldUseFunc_OldRod",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 1
+ },
+ {
+ "english": "SUPER ROD",
+ "itemId": "ITEM_SUPER_ROD",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An awesome, high-tech fishing rod.\\nUse it by any body of water to fish\\nfor wild POKéMON.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "FieldUseFunc_OldRod",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 2
+ },
+ {
+ "english": "S.S. TICKET",
+ "itemId": "ITEM_SS_TICKET",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The ticket required for sailing on\\nthe ferry S.S. ANNE.\\nIt has a drawing of a ship on it.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "CONTEST PASS",
+ "itemId": "ITEM_CONTEST_PASS",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The pass required for entering\\nPOKéMON CONTESTS. It has a\\ndrawing of an award ribbon on it.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "WAILMER PAIL",
+ "itemId": "ITEM_WAILMER_PAIL",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A nifty watering pail.\\nUse it to promote strong growth in\\nBERRIES planted in soft soil.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "DEVON GOODS",
+ "itemId": "ITEM_DEVON_GOODS",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A package that contains mechanical\\nparts of some sort made by the\\nDEVON CORPORATION.",
+ "importance": 2,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SOOT SACK",
+ "itemId": "ITEM_SOOT_SACK",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A sack used to collect volcanic\\nash automatically during walks\\nover deep ash.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BASEMENT KEY",
+ "itemId": "ITEM_BASEMENT_KEY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The key to NEW MAUVILLE, which\\nwas constructed beneath MAUVILLE\\nCITY.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "ACRO BIKE",
+ "itemId": "ITEM_ACRO_BIKE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A folding bicycle that is capable\\nof stunts like jumps and wheelies.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "FieldUseFunc_MachBike",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 1
+ },
+ {
+ "english": "{POKEBLOCK} CASE",
+ "itemId": "ITEM_POKEBLOCK_CASE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A case for holding {POKEBLOCK}S made\\nwith a BERRY BLENDER. It releases\\none {POKEBLOCK} when shaken.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LETTER",
+ "itemId": "ITEM_LETTER",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An extremely important letter to\\nSTEVEN from the PRESIDENT of the\\nDEVON CORPORATION.",
+ "importance": 2,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "EON TICKET",
+ "itemId": "ITEM_EON_TICKET",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The ticket required for sailing on a\\nferry to a distant southern island.\\nIt features a drawing of an island.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 1
+ },
+ {
+ "english": "RED ORB",
+ "itemId": "ITEM_RED_ORB",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An orb that glows red.\\nIt is said to contain an incredible\\npower from ancient times.",
+ "importance": 2,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BLUE ORB",
+ "itemId": "ITEM_BLUE_ORB",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An orb that glows blue.\\nIt is said to contain an incredible\\npower from ancient times.",
+ "importance": 2,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SCANNER",
+ "itemId": "ITEM_SCANNER",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A device used to search for\\nlife-forms in water.\\nIt looks too difficult to use.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "GO-GOGGLES",
+ "itemId": "ITEM_GO_GOGGLES",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A pair of protective goggles.\\nThey enable a TRAINER to travel\\nthrough even desert sandstorms.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "METEORITE",
+ "itemId": "ITEM_METEORITE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A meteorite that fell from space\\nonto MT. MOON long ago.\\nIt is very lumpy and hard.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RM. 1 KEY",
+ "itemId": "ITEM_ROOM_1_KEY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A key that opens the door to Room\\n1 inside the ABANDONED SHIP.\\nIt is old and looks easily broken.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RM. 2 KEY",
+ "itemId": "ITEM_ROOM_2_KEY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A key that opens the door to Room\\n2 inside the ABANDONED SHIP.\\nIt is old and looks easily broken.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RM. 4 KEY",
+ "itemId": "ITEM_ROOM_4_KEY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A key that opens the door to Room\\n4 inside the ABANDONED SHIP.\\nIt is old and looks easily broken.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RM. 6 KEY",
+ "itemId": "ITEM_ROOM_6_KEY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A key that opens the door to Room\\n6 inside the ABANDONED SHIP.\\nIt is old and looks easily broken.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "STORAGE KEY",
+ "itemId": "ITEM_STORAGE_KEY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A key that opens the storage hold\\ninside the ABANDONED SHIP.\\nIt is old and looks easily broken.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "ROOT FOSSIL",
+ "itemId": "ITEM_ROOT_FOSSIL",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A fossil of an ancient, seafloor-\\ndwelling POKéMON. It appears to be\\npart of a plant root.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "CLAW FOSSIL",
+ "itemId": "ITEM_CLAW_FOSSIL",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A fossil of an ancient, seafloor-\\ndwelling POKéMON. It appears to be\\npart of a claw.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "DEVON SCOPE",
+ "itemId": "ITEM_DEVON_SCOPE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A scope that signals the presence\\nof any unseeable POKéMON.\\nIt is made by the DEVON CORP.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "TM01",
+ "itemId": "ITEM_TM01",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An extremely powerful attack.\\nHowever, if the user is hit before\\nusing the move, they will flinch.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "FocusPunch"
+ },
+ {
+ "english": "TM02",
+ "itemId": "ITEM_TM02",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Sharp, huge claws hook and slash\\nthe foe quickly and with great\\npower.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "DragonClaw"
+ },
+ {
+ "english": "TM03",
+ "itemId": "ITEM_TM03",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The foe is hit with a pulsing blast\\nof water. It may also confuse the\\ntarget.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "WaterPulse"
+ },
+ {
+ "english": "TM04",
+ "itemId": "ITEM_TM04",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The user calms its spirit and\\nfocuses its mind to raise its\\nSP. ATK and SP. DEF stats.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "CalmMind"
+ },
+ {
+ "english": "TM05",
+ "itemId": "ITEM_TM05",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A savage roar that causes the foe\\nto switch out of battle. In the\\nwild, ROAR ends the battle.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Roar"
+ },
+ {
+ "english": "TM06",
+ "itemId": "ITEM_TM06",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A move that leaves the foe badly\\npoisoned. Its poison damage worsens\\nevery turn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Toxic"
+ },
+ {
+ "english": "TM07",
+ "itemId": "ITEM_TM07",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Summons a hailstorm that lasts for\\nfive turns. The hailstorm damages\\nall types except the ICE type.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Hail"
+ },
+ {
+ "english": "TM08",
+ "itemId": "ITEM_TM08",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The user tightens all its muscles\\nand bulks up, boosting both its\\nATTACK and DEFENSE stats.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "BulkUp"
+ },
+ {
+ "english": "TM09",
+ "itemId": "ITEM_TM09",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The user shoots seeds at the foe\\nin rapid succession. Two to five\\nseeds are shot at once.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "BulletSeed"
+ },
+ {
+ "english": "TM10",
+ "itemId": "ITEM_TM10",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A variable move that changes type\\nand power depending on the POKéMON\\nusing it.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "HiddenPower"
+ },
+ {
+ "english": "TM11",
+ "itemId": "ITEM_TM11",
+ "price": 2000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The weather is turned sunny for\\nfive turns. Over that time, FIRE-\\ntype moves are powered up.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "SunnyDay"
+ },
+ {
+ "english": "TM12",
+ "itemId": "ITEM_TM12",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A taunted foe may become enraged.\\nIt will then only be able to use\\nattack moves.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Taunt"
+ },
+ {
+ "english": "TM13",
+ "itemId": "ITEM_TM13",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An icy-cold beam is shot at the\\nfoe. It may leave the target\\nfrozen.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "IceBeam"
+ },
+ {
+ "english": "TM14",
+ "itemId": "ITEM_TM14",
+ "price": 5500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A vicious snow-and-wind attack that\\nstrikes all foes in battle. It may\\ncause freezing.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Blizzard"
+ },
+ {
+ "english": "TM15",
+ "itemId": "ITEM_TM15",
+ "price": 7500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A harsh attack that inflicts severe\\ndamage on the foe. However, the\\nuser must rest the next turn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "HyperBeam"
+ },
+ {
+ "english": "TM16",
+ "itemId": "ITEM_TM16",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A wall of light is created over\\nfive turns. It reduces damage from\\nSP. ATK attacks.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "LightScreen"
+ },
+ {
+ "english": "TM17",
+ "itemId": "ITEM_TM17",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The user is completely protected\\nfrom attack in the turn it is used.\\nIt may fail if used in succession.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Protect"
+ },
+ {
+ "english": "TM18",
+ "itemId": "ITEM_TM18",
+ "price": 2000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A heavy rain is summoned for five\\nturns. Over that time, WATER-type\\nmoves are powered up.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "RainDance"
+ },
+ {
+ "english": "TM19",
+ "itemId": "ITEM_TM19",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The user strikes the foe with\\ntentacles or roots, stealing the\\ntarget's HP and healing itself.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "GigaDrain"
+ },
+ {
+ "english": "TM20",
+ "itemId": "ITEM_TM20",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Protects the party with a shield\\nagainst all status problems over\\nfive turns.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Safeguard"
+ },
+ {
+ "english": "TM21",
+ "itemId": "ITEM_TM21",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "This attack move grows more\\npowerful the more the POKéMON\\ndislikes its TRAINER.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Frustration"
+ },
+ {
+ "english": "TM22",
+ "itemId": "ITEM_TM22",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A 2-turn attack that uses the first\\nturn for absorbing sunlight, then\\nblasting the foe in the next turn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "SolarBeam"
+ },
+ {
+ "english": "TM23",
+ "itemId": "ITEM_TM23",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The foe is slammed with a sturdy\\ntail of steel. It may lower the\\ntarget's DEFENSE stat.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "IronTail"
+ },
+ {
+ "english": "TM24",
+ "itemId": "ITEM_TM24",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A massive jolt of electricity is\\nlaunched at the foe. It may cause\\nparalysis.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Thunderbolt"
+ },
+ {
+ "english": "TM25",
+ "itemId": "ITEM_TM25",
+ "price": 5500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Strikes the foe with a huge\\nthunderbolt. It may cause\\nparalysis.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Thunder"
+ },
+ {
+ "english": "TM26",
+ "itemId": "ITEM_TM26",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Causes an earthquake that strikes\\nall POKéMON in battle, excluding\\nthe user.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Earthquake"
+ },
+ {
+ "english": "TM27",
+ "itemId": "ITEM_TM27",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "This attack move grows more\\npowerful the more the POKéMON\\nlikes its TRAINER.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Return"
+ },
+ {
+ "english": "TM28",
+ "itemId": "ITEM_TM28",
+ "price": 2000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A 2-turn attack in which the user\\ndigs underground, then strikes.\\nIt can be used to exit dungeons.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Dig"
+ },
+ {
+ "english": "TM29",
+ "itemId": "ITEM_TM29",
+ "price": 2000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A powerful blast of telekinetic\\nenergy strikes the foe. It may\\nlower the target's SP. DEF stat.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Psychic"
+ },
+ {
+ "english": "TM30",
+ "itemId": "ITEM_TM30",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The foe is attacked with a shadowy\\nlump. It may lower the target's\\nSP. DEF stat.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "ShadowBall"
+ },
+ {
+ "english": "TM31",
+ "itemId": "ITEM_TM31",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Strikes the foe with a rock-hard\\nfist, etc. It shatters barriers such\\nas REFLECT and LIGHT SCREEN.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "BrickBreak"
+ },
+ {
+ "english": "TM32",
+ "itemId": "ITEM_TM32",
+ "price": 2000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The user begins moving so quickly\\nthat it creates illusory copies to\\nraise its evasiveness.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "DoubleTeam"
+ },
+ {
+ "english": "TM33",
+ "itemId": "ITEM_TM33",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A tough barrier is put up over five\\nturns. It reduces damage from\\nphysical attacks over that time.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Reflect"
+ },
+ {
+ "english": "TM34",
+ "itemId": "ITEM_TM34",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A rapid jolt of electricity strikes\\nthe foe. This attack is impossible\\nto evade.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "ShockWave"
+ },
+ {
+ "english": "TM35",
+ "itemId": "ITEM_TM35",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The foe is roasted with a heavy\\nblast of fire. It may leave the\\ntarget with a burn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Flamethrower"
+ },
+ {
+ "english": "TM36",
+ "itemId": "ITEM_TM36",
+ "price": 1000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Toxic sludge is hurled at the foe\\nwith great force. It may also\\npoison the target.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "SludgeBomb"
+ },
+ {
+ "english": "TM37",
+ "itemId": "ITEM_TM37",
+ "price": 2000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Summons a sandstorm that lasts for\\nfive turns. It damages all types\\nexcept ROCK, GROUND, and STEEL.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Sandstorm"
+ },
+ {
+ "english": "TM38",
+ "itemId": "ITEM_TM38",
+ "price": 5500,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The foe is incinerated with an\\nintense flame. It may leave the\\ntarget with a burn.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "FireBlast"
+ },
+ {
+ "english": "TM39",
+ "itemId": "ITEM_TM39",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Boulders are hurled at the foe.\\nIt also lowers the target's SPEED\\nstat if it hits.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "RockTomb"
+ },
+ {
+ "english": "TM40",
+ "itemId": "ITEM_TM40",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An extremely fast attack against\\none target. It is impossible to\\nevade.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "AerialAce"
+ },
+ {
+ "english": "TM41",
+ "itemId": "ITEM_TM41",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "If enraged by this move, the target\\nbecomes incapable of using the same\\nmove twice in a row.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Torment"
+ },
+ {
+ "english": "TM42",
+ "itemId": "ITEM_TM42",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An attack move that becomes very\\npowerful if the user is poisoned,\\nburned, or paralyzed.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Facade"
+ },
+ {
+ "english": "TM43",
+ "itemId": "ITEM_TM43",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An attack move that may have an\\nadditional effect depending on the\\nbattle terrain.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "SecretPower"
+ },
+ {
+ "english": "TM44",
+ "itemId": "ITEM_TM44",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A move that makes the user fall\\nasleep over two turns to restore HP\\nand heal any status problems.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Rest"
+ },
+ {
+ "english": "TM45",
+ "itemId": "ITEM_TM45",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The foe, if it is the opposite\\ngender as the user, becomes\\ninfatuated and may not attack.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Attract"
+ },
+ {
+ "english": "TM46",
+ "itemId": "ITEM_TM46",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An attack that gives the user an\\nopportunity to steal the foe's hold\\nitem.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Thief"
+ },
+ {
+ "english": "TM47",
+ "itemId": "ITEM_TM47",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The foe is struck with steel-hard\\nwings. It may also raise the user's\\nDEFENSE stat.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "SteelWing"
+ },
+ {
+ "english": "TM48",
+ "itemId": "ITEM_TM48",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A special power is transmitted to\\nthe foe, causing it to switch\\nabilities with the user.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "SkillSwap"
+ },
+ {
+ "english": "TM49",
+ "itemId": "ITEM_TM49",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A move that steals the effects of\\nany status-changing or healing move\\nthat the foe tries to use.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Snatch"
+ },
+ {
+ "english": "TM50",
+ "itemId": "ITEM_TM50",
+ "price": 3000,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A maximum-power attack of great\\nferocity, but one that also sharply\\nreduces the user's SP. ATK stat.",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Overheat"
+ },
+ {
+ "english": "HM01",
+ "itemId": "ITEM_HM01",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Attacks the foe with sharp blades\\nor claws. It can also cut down thin\\ntrees and grass outside of battle.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Cut"
+ },
+ {
+ "english": "HM02",
+ "itemId": "ITEM_HM02",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The user flies up on the first turn,\\nthen attacks next turn. It can be\\nused to fly to any known town.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Fly"
+ },
+ {
+ "english": "HM03",
+ "itemId": "ITEM_HM03",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Creates a huge wave, then crashes\\nit down on the foe. It can be used\\nfor traveling on water.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Surf"
+ },
+ {
+ "english": "HM04",
+ "itemId": "ITEM_HM04",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The user builds enormous power,\\nthen slams the foe. It can be used\\nfor moving large, round boulders.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Strength"
+ },
+ {
+ "english": "HM05",
+ "itemId": "ITEM_HM05",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Looses a powerful blast of light\\nthat reduces the foe's accuracy.\\nIt also lights up dark caves.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Flash"
+ },
+ {
+ "english": "HM06",
+ "itemId": "ITEM_HM06",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Hits the foe with a rock-crushingly\\ntough attack. It can smash cracked\\nboulders.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "RockSmash"
+ },
+ {
+ "english": "HM07",
+ "itemId": "ITEM_HM07",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A powerful charge attack. It can\\nbe used for climbing a torrential\\nwaterfall.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Waterfall"
+ },
+ {
+ "english": "HM08",
+ "itemId": "ITEM_HM08",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A 2-turn attack in which the user\\ndives underwater on the first turn,\\nthen strikes in the next turn.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_TM_CASE",
+ "type": 1,
+ "fieldUseFunc": "NULL",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0,
+ "moveId": "Dive"
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "????????",
+ "itemId": "ITEM_NONE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "?????",
+ "importance": 0,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "OAK'S PARCEL",
+ "itemId": "ITEM_OAKS_PARCEL",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A parcel to be delivered to PROF.\\nOAK from VIRIDIAN CITY's POKéMON\\nMART.",
+ "importance": 2,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "POK\u00e9 FLUTE",
+ "itemId": "ITEM_POKE_FLUTE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A flute that is said to instantly\\nawaken any POKéMON. It has a\\nlovely tone.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_PokeFlute",
+ "battleUsage": 2,
+ "battleUseFunc": "BattleUseFunc_PokeFlute",
+ "secondaryId": 0
+ },
+ {
+ "english": "SECRET KEY",
+ "itemId": "ITEM_SECRET_KEY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "The key to CINNABAR ISLAND GYM's\\nfront door. It is colored red and\\ndecorated.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BIKE VOUCHER",
+ "itemId": "ITEM_BIKE_VOUCHER",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "Take this voucher to the BIKE SHOP\\nin CERULEAN CITY and exchange it\\nfor a bicycle.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "GOLD TEETH",
+ "itemId": "ITEM_GOLD_TEETH",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A set of false teeth lost by the\\nSAFARI ZONE'S WARDEN. It makes his\\nsmile sparkle.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "OLD AMBER",
+ "itemId": "ITEM_OLD_AMBER",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A piece of amber that contains\\nthe genes of an ancient POKéMON.\\nIt is clear with a reddish tint.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "CARD KEY",
+ "itemId": "ITEM_CARD_KEY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A card-type key that unlocks doors\\nin SILPH CO.'s HEAD OFFICE in\\nSAFFRON CITY.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "LIFT KEY",
+ "itemId": "ITEM_LIFT_KEY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A key that operates the elevator\\nin TEAM ROCKET's HIDEOUT.\\nIt bears the TEAM ROCKET logo.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "HELIX FOSSIL",
+ "itemId": "ITEM_HELIX_FOSSIL",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A fossil of an ancient, seafloor-\\ndwelling POKéMON. It appears to be\\npart of a seashell.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "DOME FOSSIL",
+ "itemId": "ITEM_DOME_FOSSIL",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A fossil of an ancient, seafloor-\\ndwelling POKéMON. It appears to be\\npart of a shell.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SILPH SCOPE",
+ "itemId": "ITEM_SILPH_SCOPE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A scope that makes unseeable\\nPOKéMON visible.\\nIt is made by SILPH CO.",
+ "importance": 1,
+ "exitsBagOnUse": 0,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BICYCLE",
+ "itemId": "ITEM_BICYCLE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A folding bicycle that allows\\nfaster movement than the RUNNING\\nSHOES.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "FieldUseFunc_MachBike",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "TOWN MAP",
+ "itemId": "ITEM_TOWN_MAP",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A very convenient map that can be\\nviewed anytime. It even shows your \\npresent location.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_TownMap",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "VS SEEKER",
+ "itemId": "ITEM_VS_SEEKER",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A device that indicates TRAINERS\\nwho want to battle. The battery\\ncharges while traveling.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "FieldUseFunc_VsSeeker",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "FAME CHECKER",
+ "itemId": "ITEM_FAME_CHECKER",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A device that enables you to\\nrecall what you've heard and seen\\nabout famous people.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_FameChecker",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "TM CASE",
+ "itemId": "ITEM_TM_CASE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A case that holds TMs and HMs.\\nIt is attached to the BAG's\\ncompartment for important items.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_TmCase",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "BERRY POUCH",
+ "itemId": "ITEM_BERRY_POUCH",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A pouch for carrying BERRIES.\\nIt is attached to the BAG's\\ncompartment for important items.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_BerryPouch",
+ "battleUsage": 3,
+ "battleUseFunc": "BattleUseFunc_BerryPouch",
+ "secondaryId": 0
+ },
+ {
+ "english": "TEACHY TV",
+ "itemId": "ITEM_TEACHY_TV",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A television set that is tuned to\\na program with useful tips for\\nnovice TRAINERS.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 2,
+ "fieldUseFunc": "FieldUseFunc_TeachyTv",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "TRI-PASS",
+ "itemId": "ITEM_TRI_PASS",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A pass for ferries between ONE,\\nTWO, and THREE ISLAND.\\nIt has a drawing of three islands.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RAINBOW PASS",
+ "itemId": "ITEM_RAINBOW_PASS",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A pass for ferries between\\nVERMILION and the SEVII ISLANDS.\\nIt features a drawing of a rainbow.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "TEA",
+ "itemId": "ITEM_TEA",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An aromatic tea prepared by an old\\nlady. It will slake even the worst\\nthirst.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "MYSTICTICKET",
+ "itemId": "ITEM_MYSTIC_TICKET",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A ticket required to board the ship\\nto NAVEL ROCK.\\nIt glows with a mystic light.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "AURORATICKET",
+ "itemId": "ITEM_AURORA_TICKET",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A ticket required to board the ship\\nto BIRTH ISLAND.\\nIt glows beautifully.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "POWDER JAR",
+ "itemId": "ITEM_POWDER_JAR",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "A jar for storing BERRY POWDER\\nmade using a BERRY CRUSHER.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_PowderJar",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "RUBY",
+ "itemId": "ITEM_RUBY",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An exquisitely beautiful gem that\\nhas a red glow.\\nIt symbolizes passion.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ },
+ {
+ "english": "SAPPHIRE",
+ "itemId": "ITEM_SAPPHIRE",
+ "price": 0,
+ "holdEffect": "HOLD_EFFECT_NONE",
+ "holdEffectParam": 0,
+ "description_english": "An exquisitely beautiful gem that\\nhas a blue glow.\\nIt symbolizes honesty.",
+ "importance": 1,
+ "exitsBagOnUse": 1,
+ "pocket": "POCKET_KEY_ITEMS",
+ "type": 4,
+ "fieldUseFunc": "FieldUseFunc_OakStopsYou",
+ "battleUsage": 0,
+ "battleUseFunc": "NULL",
+ "secondaryId": 0
+ }
+ ]
+} \ No newline at end of file
diff --git a/src/data/items.json.txt b/src/data/items.json.txt
new file mode 100644
index 000000000..0daa783aa
--- /dev/null
+++ b/src/data/items.json.txt
@@ -0,0 +1,31 @@
+{{ doNotModifyHeader }}
+## for item in items
+## if item.pocket == "POCKET_TM_CASE"
+extern const u8 gMoveDescription_{{ item.moveId }}[];
+## endif
+{% if item.itemId != "ITEM_NONE" %}const u8 gItemDescription_{{ item.itemId }}[] = _("{{ item.description_english }}");{% endif %}
+## endfor
+const u8 gItemDescription_ITEM_NONE[] = _("?????");
+
+const struct Item gItems[] = {
+ {% for item in items %}{
+ .name = _("{{ item.english }}"),
+ .itemId = {{ item.itemId }},
+ .price = {{ item.price }},
+ .holdEffect = {{ item.holdEffect }},
+ .holdEffectParam = {{ item.holdEffectParam }},
+## if item.pocket == "POCKET_TM_CASE"
+ .description = gMoveDescription_{{ item.moveId }},
+## else
+ .description = gItemDescription_{{ item.itemId }},
+## endif
+ .importance = {{ item.importance }},
+ .exitsBagOnUse = {{ item.exitsBagOnUse }},
+ .pocket = {{ item.pocket }},
+ .type = {{ item.type }},
+ .fieldUseFunc = {{ item.fieldUseFunc }},
+ .battleUsage = {{ item.battleUsage }},
+ .battleUseFunc = {{ item.battleUseFunc }},
+ .secondaryId = {{ item.secondaryId }}
+ }, {% endfor %}
+};
diff --git a/src/data/pokemon/egg_moves.h b/src/data/pokemon/egg_moves.h
new file mode 100644
index 000000000..f8c250c6d
--- /dev/null
+++ b/src/data/pokemon/egg_moves.h
@@ -0,0 +1,1310 @@
+#define EGG_MOVES_SPECIES_OFFSET 20000
+#define EGG_MOVES_TERMINATOR 0xFFFF
+#define egg_moves(species, moves...) (SPECIES_##species + EGG_MOVES_SPECIES_OFFSET), moves
+
+const u16 gEggMoves[] = {
+ egg_moves(BULBASAUR,
+ MOVE_LIGHT_SCREEN,
+ MOVE_SKULL_BASH,
+ MOVE_SAFEGUARD,
+ MOVE_CHARM,
+ MOVE_PETAL_DANCE,
+ MOVE_MAGICAL_LEAF,
+ MOVE_GRASS_WHISTLE,
+ MOVE_CURSE),
+
+ egg_moves(CHARMANDER,
+ MOVE_BELLY_DRUM,
+ MOVE_ANCIENT_POWER,
+ MOVE_ROCK_SLIDE,
+ MOVE_BITE,
+ MOVE_OUTRAGE,
+ MOVE_BEAT_UP,
+ MOVE_SWORDS_DANCE,
+ MOVE_DRAGON_DANCE),
+
+ egg_moves(SQUIRTLE,
+ MOVE_MIRROR_COAT,
+ MOVE_HAZE,
+ MOVE_MIST,
+ MOVE_FORESIGHT,
+ MOVE_FLAIL,
+ MOVE_REFRESH,
+ MOVE_MUD_SPORT,
+ MOVE_YAWN),
+
+ egg_moves(PIDGEY,
+ MOVE_PURSUIT,
+ MOVE_FAINT_ATTACK,
+ MOVE_FORESIGHT,
+ MOVE_STEEL_WING,
+ MOVE_AIR_CUTTER),
+
+ egg_moves(RATTATA,
+ MOVE_SCREECH,
+ MOVE_FLAME_WHEEL,
+ MOVE_FURY_SWIPES,
+ MOVE_BITE,
+ MOVE_COUNTER,
+ MOVE_REVERSAL,
+ MOVE_UPROAR,
+ MOVE_SWAGGER),
+
+ egg_moves(SPEAROW,
+ MOVE_FAINT_ATTACK,
+ MOVE_FALSE_SWIPE,
+ MOVE_SCARY_FACE,
+ MOVE_QUICK_ATTACK,
+ MOVE_TRI_ATTACK,
+ MOVE_ASTONISH,
+ MOVE_SKY_ATTACK),
+
+ egg_moves(EKANS,
+ MOVE_PURSUIT,
+ MOVE_SLAM,
+ MOVE_SPITE,
+ MOVE_BEAT_UP,
+ MOVE_POISON_FANG),
+
+ egg_moves(SANDSHREW,
+ MOVE_FLAIL,
+ MOVE_SAFEGUARD,
+ MOVE_COUNTER,
+ MOVE_RAPID_SPIN,
+ MOVE_ROCK_SLIDE,
+ MOVE_METAL_CLAW,
+ MOVE_SWORDS_DANCE,
+ MOVE_CRUSH_CLAW),
+
+ egg_moves(NIDORAN_F,
+ MOVE_SUPERSONIC,
+ MOVE_DISABLE,
+ MOVE_TAKE_DOWN,
+ MOVE_FOCUS_ENERGY,
+ MOVE_CHARM,
+ MOVE_COUNTER,
+ MOVE_BEAT_UP),
+
+ egg_moves(NIDORAN_M,
+ MOVE_COUNTER,
+ MOVE_DISABLE,
+ MOVE_SUPERSONIC,
+ MOVE_TAKE_DOWN,
+ MOVE_AMNESIA,
+ MOVE_CONFUSION,
+ MOVE_BEAT_UP),
+
+ egg_moves(VULPIX,
+ MOVE_FAINT_ATTACK,
+ MOVE_HYPNOSIS,
+ MOVE_FLAIL,
+ MOVE_SPITE,
+ MOVE_DISABLE,
+ MOVE_HOWL,
+ MOVE_PSYCH_UP,
+ MOVE_HEAT_WAVE),
+
+ egg_moves(ZUBAT,
+ MOVE_QUICK_ATTACK,
+ MOVE_PURSUIT,
+ MOVE_FAINT_ATTACK,
+ MOVE_GUST,
+ MOVE_WHIRLWIND,
+ MOVE_CURSE),
+
+ egg_moves(ODDISH,
+ MOVE_SWORDS_DANCE,
+ MOVE_RAZOR_LEAF,
+ MOVE_FLAIL,
+ MOVE_SYNTHESIS,
+ MOVE_CHARM,
+ MOVE_INGRAIN),
+
+ egg_moves(PARAS,
+ MOVE_FALSE_SWIPE,
+ MOVE_SCREECH,
+ MOVE_COUNTER,
+ MOVE_PSYBEAM,
+ MOVE_FLAIL,
+ MOVE_SWEET_SCENT,
+ MOVE_LIGHT_SCREEN,
+ MOVE_PURSUIT),
+
+ egg_moves(VENONAT,
+ MOVE_BATON_PASS,
+ MOVE_SCREECH,
+ MOVE_GIGA_DRAIN,
+ MOVE_SIGNAL_BEAM),
+
+ egg_moves(DIGLETT,
+ MOVE_FAINT_ATTACK,
+ MOVE_SCREECH,
+ MOVE_ANCIENT_POWER,
+ MOVE_PURSUIT,
+ MOVE_BEAT_UP,
+ MOVE_UPROAR,
+ MOVE_ROCK_SLIDE),
+
+ egg_moves(MEOWTH,
+ MOVE_SPITE,
+ MOVE_CHARM,
+ MOVE_HYPNOSIS,
+ MOVE_AMNESIA,
+ MOVE_PSYCH_UP,
+ MOVE_ASSIST),
+
+ egg_moves(PSYDUCK,
+ MOVE_HYPNOSIS,
+ MOVE_PSYBEAM,
+ MOVE_FORESIGHT,
+ MOVE_LIGHT_SCREEN,
+ MOVE_FUTURE_SIGHT,
+ MOVE_PSYCHIC,
+ MOVE_CROSS_CHOP,
+ MOVE_REFRESH),
+
+ egg_moves(MANKEY,
+ MOVE_ROCK_SLIDE,
+ MOVE_FORESIGHT,
+ MOVE_MEDITATE,
+ MOVE_COUNTER,
+ MOVE_REVERSAL,
+ MOVE_BEAT_UP,
+ MOVE_REVENGE,
+ MOVE_SMELLING_SALT),
+
+ egg_moves(GROWLITHE,
+ MOVE_BODY_SLAM,
+ MOVE_SAFEGUARD,
+ MOVE_CRUNCH,
+ MOVE_THRASH,
+ MOVE_FIRE_SPIN,
+ MOVE_HOWL,
+ MOVE_HEAT_WAVE),
+
+ egg_moves(POLIWAG,
+ MOVE_MIST,
+ MOVE_SPLASH,
+ MOVE_BUBBLE_BEAM,
+ MOVE_HAZE,
+ MOVE_MIND_READER,
+ MOVE_WATER_SPORT,
+ MOVE_ICE_BALL),
+
+ egg_moves(ABRA,
+ MOVE_ENCORE,
+ MOVE_BARRIER,
+ MOVE_KNOCK_OFF,
+ MOVE_FIRE_PUNCH,
+ MOVE_THUNDER_PUNCH,
+ MOVE_ICE_PUNCH),
+
+ egg_moves(MACHOP,
+ MOVE_LIGHT_SCREEN,
+ MOVE_MEDITATE,
+ MOVE_ROLLING_KICK,
+ MOVE_ENCORE,
+ MOVE_SMELLING_SALT,
+ MOVE_COUNTER,
+ MOVE_ROCK_SLIDE),
+
+ egg_moves(BELLSPROUT,
+ MOVE_SWORDS_DANCE,
+ MOVE_ENCORE,
+ MOVE_REFLECT,
+ MOVE_SYNTHESIS,
+ MOVE_LEECH_LIFE,
+ MOVE_INGRAIN,
+ MOVE_MAGICAL_LEAF),
+
+ egg_moves(TENTACOOL,
+ MOVE_AURORA_BEAM,
+ MOVE_MIRROR_COAT,
+ MOVE_RAPID_SPIN,
+ MOVE_HAZE,
+ MOVE_SAFEGUARD,
+ MOVE_CONFUSE_RAY),
+
+ egg_moves(GEODUDE,
+ MOVE_MEGA_PUNCH,
+ MOVE_ROCK_SLIDE,
+ MOVE_BLOCK),
+
+ egg_moves(PONYTA,
+ MOVE_FLAME_WHEEL,
+ MOVE_THRASH,
+ MOVE_DOUBLE_KICK,
+ MOVE_HYPNOSIS,
+ MOVE_CHARM,
+ MOVE_DOUBLE_EDGE),
+
+ egg_moves(SLOWPOKE,
+ MOVE_SAFEGUARD,
+ MOVE_BELLY_DRUM,
+ MOVE_FUTURE_SIGHT,
+ MOVE_STOMP,
+ MOVE_MUD_SPORT,
+ MOVE_SLEEP_TALK,
+ MOVE_SNORE),
+
+ egg_moves(FARFETCHD,
+ MOVE_STEEL_WING,
+ MOVE_FORESIGHT,
+ MOVE_MIRROR_MOVE,
+ MOVE_GUST,
+ MOVE_QUICK_ATTACK,
+ MOVE_FLAIL,
+ MOVE_FEATHER_DANCE,
+ MOVE_CURSE),
+
+ egg_moves(DODUO,
+ MOVE_QUICK_ATTACK,
+ MOVE_SUPERSONIC,
+ MOVE_HAZE,
+ MOVE_FAINT_ATTACK,
+ MOVE_FLAIL,
+ MOVE_ENDEAVOR),
+
+ egg_moves(SEEL,
+ MOVE_LICK,
+ MOVE_PERISH_SONG,
+ MOVE_DISABLE,
+ MOVE_HORN_DRILL,
+ MOVE_SLAM,
+ MOVE_ENCORE,
+ MOVE_FAKE_OUT,
+ MOVE_ICICLE_SPEAR),
+
+ egg_moves(GRIMER,
+ MOVE_HAZE,
+ MOVE_MEAN_LOOK,
+ MOVE_LICK,
+ MOVE_IMPRISON,
+ MOVE_CURSE,
+ MOVE_SHADOW_PUNCH,
+ MOVE_EXPLOSION),
+
+ egg_moves(SHELLDER,
+ MOVE_BUBBLE_BEAM,
+ MOVE_TAKE_DOWN,
+ MOVE_BARRIER,
+ MOVE_RAPID_SPIN,
+ MOVE_SCREECH,
+ MOVE_ICICLE_SPEAR),
+
+ egg_moves(GASTLY,
+ MOVE_PSYWAVE,
+ MOVE_PERISH_SONG,
+ MOVE_HAZE,
+ MOVE_ASTONISH,
+ MOVE_WILL_O_WISP,
+ MOVE_GRUDGE,
+ MOVE_EXPLOSION),
+
+ egg_moves(ONIX,
+ MOVE_ROCK_SLIDE,
+ MOVE_FLAIL,
+ MOVE_EXPLOSION,
+ MOVE_BLOCK),
+
+ egg_moves(DROWZEE,
+ MOVE_BARRIER,
+ MOVE_ASSIST,
+ MOVE_ROLE_PLAY,
+ MOVE_FIRE_PUNCH,
+ MOVE_THUNDER_PUNCH,
+ MOVE_ICE_PUNCH),
+
+ egg_moves(KRABBY,
+ MOVE_DIG,
+ MOVE_HAZE,
+ MOVE_AMNESIA,
+ MOVE_FLAIL,
+ MOVE_SLAM,
+ MOVE_KNOCK_OFF,
+ MOVE_SWORDS_DANCE),
+
+ egg_moves(EXEGGCUTE,
+ MOVE_SYNTHESIS,
+ MOVE_MOONLIGHT,
+ MOVE_REFLECT,
+ MOVE_ANCIENT_POWER,
+ MOVE_PSYCH_UP,
+ MOVE_INGRAIN,
+ MOVE_CURSE),
+
+ egg_moves(CUBONE,
+ MOVE_ROCK_SLIDE,
+ MOVE_ANCIENT_POWER,
+ MOVE_BELLY_DRUM,
+ MOVE_SCREECH,
+ MOVE_SKULL_BASH,
+ MOVE_PERISH_SONG,
+ MOVE_SWORDS_DANCE),
+
+ egg_moves(LICKITUNG,
+ MOVE_BELLY_DRUM,
+ MOVE_MAGNITUDE,
+ MOVE_BODY_SLAM,
+ MOVE_CURSE,
+ MOVE_SMELLING_SALT,
+ MOVE_SLEEP_TALK,
+ MOVE_SNORE,
+ MOVE_SUBSTITUTE),
+
+ egg_moves(KOFFING,
+ MOVE_SCREECH,
+ MOVE_PSYWAVE,
+ MOVE_PSYBEAM,
+ MOVE_DESTINY_BOND,
+ MOVE_PAIN_SPLIT,
+ MOVE_WILL_O_WISP),
+
+ egg_moves(RHYHORN,
+ MOVE_CRUNCH,
+ MOVE_REVERSAL,
+ MOVE_ROCK_SLIDE,
+ MOVE_COUNTER,
+ MOVE_MAGNITUDE,
+ MOVE_SWORDS_DANCE,
+ MOVE_CURSE,
+ MOVE_CRUSH_CLAW),
+
+ egg_moves(CHANSEY,
+ MOVE_PRESENT,
+ MOVE_METRONOME,
+ MOVE_HEAL_BELL,
+ MOVE_AROMATHERAPY,
+ MOVE_SUBSTITUTE),
+
+ egg_moves(TANGELA,
+ MOVE_FLAIL,
+ MOVE_CONFUSION,
+ MOVE_MEGA_DRAIN,
+ MOVE_REFLECT,
+ MOVE_AMNESIA,
+ MOVE_LEECH_SEED,
+ MOVE_NATURE_POWER),
+
+ egg_moves(KANGASKHAN,
+ MOVE_STOMP,
+ MOVE_FORESIGHT,
+ MOVE_FOCUS_ENERGY,
+ MOVE_SAFEGUARD,
+ MOVE_DISABLE,
+ MOVE_COUNTER,
+ MOVE_CRUSH_CLAW,
+ MOVE_SUBSTITUTE),
+
+ egg_moves(HORSEA,
+ MOVE_FLAIL,
+ MOVE_AURORA_BEAM,
+ MOVE_OCTAZOOKA,
+ MOVE_DISABLE,
+ MOVE_SPLASH,
+ MOVE_DRAGON_RAGE,
+ MOVE_DRAGON_BREATH),
+
+ egg_moves(GOLDEEN,
+ MOVE_PSYBEAM,
+ MOVE_HAZE,
+ MOVE_HYDRO_PUMP,
+ MOVE_SLEEP_TALK,
+ MOVE_MUD_SPORT),
+
+ egg_moves(MR_MIME,
+ MOVE_FUTURE_SIGHT,
+ MOVE_HYPNOSIS,
+ MOVE_MIMIC,
+ MOVE_PSYCH_UP,
+ MOVE_FAKE_OUT,
+ MOVE_TRICK),
+
+ egg_moves(SCYTHER,
+ MOVE_COUNTER,
+ MOVE_SAFEGUARD,
+ MOVE_BATON_PASS,
+ MOVE_RAZOR_WIND,
+ MOVE_REVERSAL,
+ MOVE_LIGHT_SCREEN,
+ MOVE_ENDURE,
+ MOVE_SILVER_WIND),
+
+ egg_moves(PINSIR,
+ MOVE_FURY_ATTACK,
+ MOVE_FLAIL,
+ MOVE_FALSE_SWIPE,
+ MOVE_FAINT_ATTACK),
+
+ egg_moves(LAPRAS,
+ MOVE_FORESIGHT,
+ MOVE_SUBSTITUTE,
+ MOVE_TICKLE,
+ MOVE_REFRESH,
+ MOVE_DRAGON_DANCE,
+ MOVE_CURSE,
+ MOVE_SLEEP_TALK,
+ MOVE_HORN_DRILL),
+
+ egg_moves(EEVEE,
+ MOVE_CHARM,
+ MOVE_FLAIL,
+ MOVE_ENDURE,
+ MOVE_CURSE,
+ MOVE_TICKLE,
+ MOVE_WISH),
+
+ egg_moves(OMANYTE,
+ MOVE_BUBBLE_BEAM,
+ MOVE_AURORA_BEAM,
+ MOVE_SLAM,
+ MOVE_SUPERSONIC,
+ MOVE_HAZE,
+ MOVE_ROCK_SLIDE,
+ MOVE_SPIKES),
+
+ egg_moves(KABUTO,
+ MOVE_BUBBLE_BEAM,
+ MOVE_AURORA_BEAM,
+ MOVE_RAPID_SPIN,
+ MOVE_DIG,
+ MOVE_FLAIL,
+ MOVE_KNOCK_OFF,
+ MOVE_CONFUSE_RAY),
+
+ egg_moves(AERODACTYL,
+ MOVE_WHIRLWIND,
+ MOVE_PURSUIT,
+ MOVE_FORESIGHT,
+ MOVE_STEEL_WING,
+ MOVE_DRAGON_BREATH,
+ MOVE_CURSE),
+
+ egg_moves(SNORLAX,
+ MOVE_LICK,
+ MOVE_CHARM,
+ MOVE_DOUBLE_EDGE,
+ MOVE_CURSE,
+ MOVE_FISSURE,
+ MOVE_SUBSTITUTE),
+
+ egg_moves(DRATINI,
+ MOVE_LIGHT_SCREEN,
+ MOVE_MIST,
+ MOVE_HAZE,
+ MOVE_SUPERSONIC,
+ MOVE_DRAGON_BREATH,
+ MOVE_DRAGON_DANCE),
+
+ egg_moves(CHIKORITA,
+ MOVE_VINE_WHIP,
+ MOVE_LEECH_SEED,
+ MOVE_COUNTER,
+ MOVE_ANCIENT_POWER,
+ MOVE_FLAIL,
+ MOVE_NATURE_POWER,
+ MOVE_INGRAIN,
+ MOVE_GRASS_WHISTLE),
+
+ egg_moves(CYNDAQUIL,
+ MOVE_FURY_SWIPES,
+ MOVE_QUICK_ATTACK,
+ MOVE_REVERSAL,
+ MOVE_THRASH,
+ MOVE_FORESIGHT,
+ MOVE_COVET,
+ MOVE_HOWL,
+ MOVE_CRUSH_CLAW),
+
+ egg_moves(TOTODILE,
+ MOVE_CRUNCH,
+ MOVE_THRASH,
+ MOVE_HYDRO_PUMP,
+ MOVE_ANCIENT_POWER,
+ MOVE_ROCK_SLIDE,
+ MOVE_MUD_SPORT,
+ MOVE_WATER_SPORT,
+ MOVE_DRAGON_CLAW),
+
+ egg_moves(SENTRET,
+ MOVE_DOUBLE_EDGE,
+ MOVE_PURSUIT,
+ MOVE_SLASH,
+ MOVE_FOCUS_ENERGY,
+ MOVE_REVERSAL,
+ MOVE_SUBSTITUTE,
+ MOVE_TRICK,
+ MOVE_ASSIST),
+
+ egg_moves(HOOTHOOT,
+ MOVE_MIRROR_MOVE,
+ MOVE_SUPERSONIC,
+ MOVE_FAINT_ATTACK,
+ MOVE_WING_ATTACK,
+ MOVE_WHIRLWIND,
+ MOVE_SKY_ATTACK,
+ MOVE_FEATHER_DANCE),
+
+ egg_moves(LEDYBA,
+ MOVE_PSYBEAM,
+ MOVE_BIDE,
+ MOVE_SILVER_WIND),
+
+ egg_moves(SPINARAK,
+ MOVE_PSYBEAM,
+ MOVE_DISABLE,
+ MOVE_SONIC_BOOM,
+ MOVE_BATON_PASS,
+ MOVE_PURSUIT,
+ MOVE_SIGNAL_BEAM),
+
+ egg_moves(CHINCHOU,
+ MOVE_FLAIL,
+ MOVE_SCREECH,
+ MOVE_AMNESIA),
+
+ egg_moves(PICHU,
+ MOVE_REVERSAL,
+ MOVE_BIDE,
+ MOVE_PRESENT,
+ MOVE_ENCORE,
+ MOVE_DOUBLE_SLAP,
+ MOVE_WISH,
+ MOVE_CHARGE),
+
+ egg_moves(CLEFFA,
+ MOVE_PRESENT,
+ MOVE_METRONOME,
+ MOVE_AMNESIA,
+ MOVE_BELLY_DRUM,
+ MOVE_SPLASH,
+ MOVE_MIMIC,
+ MOVE_WISH,
+ MOVE_SUBSTITUTE),
+
+ egg_moves(IGGLYBUFF,
+ MOVE_PERISH_SONG,
+ MOVE_PRESENT,
+ MOVE_FAINT_ATTACK,
+ MOVE_WISH,
+ MOVE_FAKE_TEARS),
+
+ egg_moves(TOGEPI,
+ MOVE_PRESENT,
+ MOVE_MIRROR_MOVE,
+ MOVE_PECK,
+ MOVE_FORESIGHT,
+ MOVE_FUTURE_SIGHT,
+ MOVE_SUBSTITUTE,
+ MOVE_PSYCH_UP),
+
+ egg_moves(NATU,
+ MOVE_HAZE,
+ MOVE_DRILL_PECK,
+ MOVE_QUICK_ATTACK,
+ MOVE_FAINT_ATTACK,
+ MOVE_STEEL_WING,
+ MOVE_PSYCH_UP,
+ MOVE_FEATHER_DANCE,
+ MOVE_REFRESH),
+
+ egg_moves(MAREEP,
+ MOVE_TAKE_DOWN,
+ MOVE_BODY_SLAM,
+ MOVE_SAFEGUARD,
+ MOVE_SCREECH,
+ MOVE_REFLECT,
+ MOVE_ODOR_SLEUTH,
+ MOVE_CHARGE),
+
+ egg_moves(MARILL,
+ MOVE_LIGHT_SCREEN,
+ MOVE_PRESENT,
+ MOVE_AMNESIA,
+ MOVE_FUTURE_SIGHT,
+ MOVE_BELLY_DRUM,
+ MOVE_PERISH_SONG,
+ MOVE_SUPERSONIC,
+ MOVE_SUBSTITUTE),
+
+ egg_moves(SUDOWOODO,
+ MOVE_SELF_DESTRUCT),
+
+ egg_moves(HOPPIP,
+ MOVE_CONFUSION,
+ MOVE_ENCORE,
+ MOVE_DOUBLE_EDGE,
+ MOVE_REFLECT,
+ MOVE_AMNESIA,
+ MOVE_HELPING_HAND,
+ MOVE_PSYCH_UP),
+
+ egg_moves(AIPOM,
+ MOVE_COUNTER,
+ MOVE_SCREECH,
+ MOVE_PURSUIT,
+ MOVE_AGILITY,
+ MOVE_SPITE,
+ MOVE_SLAM,
+ MOVE_DOUBLE_SLAP,
+ MOVE_BEAT_UP),
+
+ egg_moves(SUNKERN,
+ MOVE_GRASS_WHISTLE,
+ MOVE_ENCORE,
+ MOVE_LEECH_SEED,
+ MOVE_NATURE_POWER,
+ MOVE_CURSE,
+ MOVE_HELPING_HAND),
+
+ egg_moves(YANMA,
+ MOVE_WHIRLWIND,
+ MOVE_REVERSAL,
+ MOVE_LEECH_LIFE,
+ MOVE_SIGNAL_BEAM,
+ MOVE_SILVER_WIND),
+
+ egg_moves(WOOPER,
+ MOVE_BODY_SLAM,
+ MOVE_ANCIENT_POWER,
+ MOVE_SAFEGUARD,
+ MOVE_CURSE,
+ MOVE_MUD_SPORT,
+ MOVE_STOCKPILE,
+ MOVE_SWALLOW,
+ MOVE_SPIT_UP),
+
+ egg_moves(MURKROW,
+ MOVE_WHIRLWIND,
+ MOVE_DRILL_PECK,
+ MOVE_MIRROR_MOVE,
+ MOVE_WING_ATTACK,
+ MOVE_SKY_ATTACK,
+ MOVE_CONFUSE_RAY,
+ MOVE_FEATHER_DANCE,
+ MOVE_PERISH_SONG),
+
+ egg_moves(MISDREAVUS,
+ MOVE_SCREECH,
+ MOVE_DESTINY_BOND,
+ MOVE_PSYCH_UP,
+ MOVE_IMPRISON),
+
+ egg_moves(GIRAFARIG,
+ MOVE_TAKE_DOWN,
+ MOVE_AMNESIA,
+ MOVE_FORESIGHT,
+ MOVE_FUTURE_SIGHT,
+ MOVE_BEAT_UP,
+ MOVE_PSYCH_UP,
+ MOVE_WISH,
+ MOVE_MAGIC_COAT),
+
+ egg_moves(PINECO,
+ MOVE_REFLECT,
+ MOVE_PIN_MISSILE,
+ MOVE_FLAIL,
+ MOVE_SWIFT,
+ MOVE_COUNTER,
+ MOVE_SAND_TOMB),
+
+ egg_moves(DUNSPARCE,
+ MOVE_BIDE,
+ MOVE_ANCIENT_POWER,
+ MOVE_ROCK_SLIDE,
+ MOVE_BITE,
+ MOVE_HEADBUTT,
+ MOVE_ASTONISH,
+ MOVE_CURSE),
+
+ egg_moves(GLIGAR,
+ MOVE_METAL_CLAW,
+ MOVE_WING_ATTACK,
+ MOVE_RAZOR_WIND,
+ MOVE_COUNTER,
+ MOVE_SAND_TOMB),
+
+ egg_moves(SNUBBULL,
+ MOVE_METRONOME,
+ MOVE_FAINT_ATTACK,
+ MOVE_REFLECT,
+ MOVE_PRESENT,
+ MOVE_CRUNCH,
+ MOVE_HEAL_BELL,
+ MOVE_SNORE,
+ MOVE_SMELLING_SALT),
+
+ egg_moves(QWILFISH,
+ MOVE_FLAIL,
+ MOVE_HAZE,
+ MOVE_BUBBLE_BEAM,
+ MOVE_SUPERSONIC,
+ MOVE_ASTONISH),
+
+ egg_moves(SHUCKLE,
+ MOVE_SWEET_SCENT),
+
+ egg_moves(HERACROSS,
+ MOVE_HARDEN,
+ MOVE_BIDE,
+ MOVE_FLAIL,
+ MOVE_FALSE_SWIPE),
+
+ egg_moves(SNEASEL,
+ MOVE_COUNTER,
+ MOVE_SPITE,
+ MOVE_FORESIGHT,
+ MOVE_REFLECT,
+ MOVE_BITE,
+ MOVE_CRUSH_CLAW,
+ MOVE_FAKE_OUT),
+
+ egg_moves(TEDDIURSA,
+ MOVE_CRUNCH,
+ MOVE_TAKE_DOWN,
+ MOVE_SEISMIC_TOSS,
+ MOVE_COUNTER,
+ MOVE_METAL_CLAW,
+ MOVE_FAKE_TEARS,
+ MOVE_YAWN,
+ MOVE_SLEEP_TALK),
+
+ egg_moves(SLUGMA,
+ MOVE_ACID_ARMOR,
+ MOVE_HEAT_WAVE),
+
+ egg_moves(SWINUB,
+ MOVE_TAKE_DOWN,
+ MOVE_BITE,
+ MOVE_BODY_SLAM,
+ MOVE_ROCK_SLIDE,
+ MOVE_ANCIENT_POWER,
+ MOVE_MUD_SHOT,
+ MOVE_ICICLE_SPEAR,
+ MOVE_DOUBLE_EDGE),
+
+ egg_moves(CORSOLA,
+ MOVE_ROCK_SLIDE,
+ MOVE_SCREECH,
+ MOVE_MIST,
+ MOVE_AMNESIA,
+ MOVE_BARRIER,
+ MOVE_INGRAIN,
+ MOVE_CONFUSE_RAY,
+ MOVE_ICICLE_SPEAR),
+
+ egg_moves(REMORAID,
+ MOVE_AURORA_BEAM,
+ MOVE_OCTAZOOKA,
+ MOVE_SUPERSONIC,
+ MOVE_HAZE,
+ MOVE_SCREECH,
+ MOVE_THUNDER_WAVE,
+ MOVE_ROCK_BLAST),
+
+ egg_moves(DELIBIRD,
+ MOVE_AURORA_BEAM,
+ MOVE_QUICK_ATTACK,
+ MOVE_FUTURE_SIGHT,
+ MOVE_SPLASH,
+ MOVE_RAPID_SPIN,
+ MOVE_ICE_BALL),
+
+ egg_moves(MANTINE,
+ MOVE_TWISTER,
+ MOVE_HYDRO_PUMP,
+ MOVE_HAZE,
+ MOVE_SLAM,
+ MOVE_MUD_SPORT,
+ MOVE_ROCK_SLIDE),
+
+ egg_moves(SKARMORY,
+ MOVE_DRILL_PECK,
+ MOVE_PURSUIT,
+ MOVE_WHIRLWIND,
+ MOVE_SKY_ATTACK,
+ MOVE_CURSE),
+
+ egg_moves(HOUNDOUR,
+ MOVE_FIRE_SPIN,
+ MOVE_RAGE,
+ MOVE_PURSUIT,
+ MOVE_COUNTER,
+ MOVE_SPITE,
+ MOVE_REVERSAL,
+ MOVE_BEAT_UP,
+ MOVE_WILL_O_WISP),
+
+ egg_moves(PHANPY,
+ MOVE_FOCUS_ENERGY,
+ MOVE_BODY_SLAM,
+ MOVE_ANCIENT_POWER,
+ MOVE_SNORE,
+ MOVE_COUNTER,
+ MOVE_FISSURE),
+
+ egg_moves(STANTLER,
+ MOVE_SPITE,
+ MOVE_DISABLE,
+ MOVE_BITE,
+ MOVE_SWAGGER,
+ MOVE_PSYCH_UP,
+ MOVE_EXTRASENSORY),
+
+ egg_moves(TYROGUE,
+ MOVE_RAPID_SPIN,
+ MOVE_HI_JUMP_KICK,
+ MOVE_MACH_PUNCH,
+ MOVE_MIND_READER,
+ MOVE_HELPING_HAND),
+
+ egg_moves(SMOOCHUM,
+ MOVE_MEDITATE,
+ MOVE_PSYCH_UP,
+ MOVE_FAKE_OUT,
+ MOVE_WISH,
+ MOVE_ICE_PUNCH),
+
+ egg_moves(ELEKID,
+ MOVE_KARATE_CHOP,
+ MOVE_BARRIER,
+ MOVE_ROLLING_KICK,
+ MOVE_MEDITATE,
+ MOVE_CROSS_CHOP,
+ MOVE_FIRE_PUNCH,
+ MOVE_ICE_PUNCH),
+
+ egg_moves(MAGBY,
+ MOVE_KARATE_CHOP,
+ MOVE_MEGA_PUNCH,
+ MOVE_BARRIER,
+ MOVE_SCREECH,
+ MOVE_CROSS_CHOP,
+ MOVE_THUNDER_PUNCH),
+
+ egg_moves(MILTANK,
+ MOVE_PRESENT,
+ MOVE_REVERSAL,
+ MOVE_SEISMIC_TOSS,
+ MOVE_ENDURE,
+ MOVE_PSYCH_UP,
+ MOVE_CURSE,
+ MOVE_HELPING_HAND,
+ MOVE_SLEEP_TALK),
+
+ egg_moves(LARVITAR,
+ MOVE_PURSUIT,
+ MOVE_STOMP,
+ MOVE_OUTRAGE,
+ MOVE_FOCUS_ENERGY,
+ MOVE_ANCIENT_POWER,
+ MOVE_DRAGON_DANCE,
+ MOVE_CURSE),
+
+ egg_moves(TREECKO,
+ MOVE_CRUNCH,
+ MOVE_MUD_SPORT,
+ MOVE_ENDEAVOR,
+ MOVE_LEECH_SEED,
+ MOVE_DRAGON_BREATH,
+ MOVE_CRUSH_CLAW),
+
+ egg_moves(TORCHIC,
+ MOVE_COUNTER,
+ MOVE_REVERSAL,
+ MOVE_ENDURE,
+ MOVE_SWAGGER,
+ MOVE_ROCK_SLIDE,
+ MOVE_SMELLING_SALT),
+
+ egg_moves(MUDKIP,
+ MOVE_REFRESH,
+ MOVE_UPROAR,
+ MOVE_CURSE,
+ MOVE_STOMP,
+ MOVE_ICE_BALL,
+ MOVE_MIRROR_COAT),
+
+ egg_moves(POOCHYENA,
+ MOVE_ASTONISH,
+ MOVE_POISON_FANG,
+ MOVE_COVET,
+ MOVE_LEER,
+ MOVE_YAWN),
+
+ egg_moves(ZIGZAGOON,
+ MOVE_CHARM,
+ MOVE_PURSUIT,
+ MOVE_SUBSTITUTE,
+ MOVE_TICKLE,
+ MOVE_TRICK),
+
+ egg_moves(LOTAD,
+ MOVE_SYNTHESIS,
+ MOVE_RAZOR_LEAF,
+ MOVE_SWEET_SCENT,
+ MOVE_LEECH_SEED,
+ MOVE_FLAIL,
+ MOVE_WATER_GUN),
+
+ egg_moves(SEEDOT,
+ MOVE_LEECH_SEED,
+ MOVE_AMNESIA,
+ MOVE_QUICK_ATTACK,
+ MOVE_RAZOR_WIND,
+ MOVE_TAKE_DOWN,
+ MOVE_FALSE_SWIPE),
+
+ egg_moves(NINCADA,
+ MOVE_ENDURE,
+ MOVE_FAINT_ATTACK,
+ MOVE_GUST,
+ MOVE_SILVER_WIND),
+
+ egg_moves(TAILLOW,
+ MOVE_PURSUIT,
+ MOVE_SUPERSONIC,
+ MOVE_REFRESH,
+ MOVE_MIRROR_MOVE,
+ MOVE_RAGE,
+ MOVE_SKY_ATTACK),
+
+ egg_moves(SHROOMISH,
+ MOVE_FAKE_TEARS,
+ MOVE_SWAGGER,
+ MOVE_CHARM,
+ MOVE_FALSE_SWIPE,
+ MOVE_HELPING_HAND),
+
+ egg_moves(SPINDA,
+ MOVE_ENCORE,
+ MOVE_ROCK_SLIDE,
+ MOVE_ASSIST,
+ MOVE_DISABLE,
+ MOVE_BATON_PASS,
+ MOVE_WISH,
+ MOVE_TRICK,
+ MOVE_SMELLING_SALT),
+
+ egg_moves(WINGULL,
+ MOVE_MIST,
+ MOVE_TWISTER,
+ MOVE_AGILITY,
+ MOVE_GUST,
+ MOVE_WATER_SPORT),
+
+ egg_moves(SURSKIT,
+ MOVE_FORESIGHT,
+ MOVE_MUD_SHOT,
+ MOVE_PSYBEAM,
+ MOVE_HYDRO_PUMP,
+ MOVE_MIND_READER),
+
+ egg_moves(WAILMER,
+ MOVE_DOUBLE_EDGE,
+ MOVE_THRASH,
+ MOVE_SWAGGER,
+ MOVE_SNORE,
+ MOVE_SLEEP_TALK,
+ MOVE_CURSE,
+ MOVE_FISSURE,
+ MOVE_TICKLE),
+
+ egg_moves(SKITTY,
+ MOVE_HELPING_HAND,
+ MOVE_PSYCH_UP,
+ MOVE_UPROAR,
+ MOVE_FAKE_TEARS,
+ MOVE_WISH,
+ MOVE_BATON_PASS,
+ MOVE_SUBSTITUTE,
+ MOVE_TICKLE),
+
+ egg_moves(KECLEON,
+ MOVE_DISABLE,
+ MOVE_MAGIC_COAT,
+ MOVE_TRICK),
+
+ egg_moves(NOSEPASS,
+ MOVE_MAGNITUDE,
+ MOVE_ROLLOUT,
+ MOVE_EXPLOSION),
+
+ egg_moves(TORKOAL,
+ MOVE_ERUPTION,
+ MOVE_ENDURE,
+ MOVE_SLEEP_TALK,
+ MOVE_YAWN),
+
+ egg_moves(SABLEYE,
+ MOVE_PSYCH_UP,
+ MOVE_RECOVER,
+ MOVE_MOONLIGHT),
+
+ egg_moves(BARBOACH,
+ MOVE_THRASH,
+ MOVE_WHIRLPOOL,
+ MOVE_SPARK),
+
+ egg_moves(LUVDISC,
+ MOVE_SPLASH,
+ MOVE_SUPERSONIC,
+ MOVE_WATER_SPORT,
+ MOVE_MUD_SPORT),
+
+ egg_moves(CORPHISH,
+ MOVE_MUD_SPORT,
+ MOVE_ENDEAVOR,
+ MOVE_BODY_SLAM,
+ MOVE_ANCIENT_POWER),
+
+ egg_moves(FEEBAS,
+ MOVE_MIRROR_COAT,
+ MOVE_DRAGON_BREATH,
+ MOVE_MUD_SPORT,
+ MOVE_HYPNOSIS,
+ MOVE_LIGHT_SCREEN,
+ MOVE_CONFUSE_RAY),
+
+ egg_moves(CARVANHA,
+ MOVE_HYDRO_PUMP,
+ MOVE_DOUBLE_EDGE,
+ MOVE_THRASH),
+
+ egg_moves(TRAPINCH,
+ MOVE_FOCUS_ENERGY,
+ MOVE_QUICK_ATTACK,
+ MOVE_GUST),
+
+ egg_moves(MAKUHITA,
+ MOVE_FAINT_ATTACK,
+ MOVE_DETECT,
+ MOVE_FORESIGHT,
+ MOVE_HELPING_HAND,
+ MOVE_CROSS_CHOP,
+ MOVE_REVENGE,
+ MOVE_DYNAMIC_PUNCH,
+ MOVE_COUNTER),
+
+ egg_moves(ELECTRIKE,
+ MOVE_CRUNCH,
+ MOVE_HEADBUTT,
+ MOVE_UPROAR,
+ MOVE_CURSE,
+ MOVE_SWIFT),
+
+ egg_moves(NUMEL,
+ MOVE_HOWL,
+ MOVE_SCARY_FACE,
+ MOVE_BODY_SLAM,
+ MOVE_ROLLOUT,
+ MOVE_DEFENSE_CURL,
+ MOVE_STOMP),
+
+ egg_moves(SPHEAL,
+ MOVE_WATER_SPORT,
+ MOVE_STOCKPILE,
+ MOVE_SWALLOW,
+ MOVE_SPIT_UP,
+ MOVE_YAWN,
+ MOVE_ROCK_SLIDE,
+ MOVE_CURSE,
+ MOVE_FISSURE),
+
+ egg_moves(CACNEA,
+ MOVE_GRASS_WHISTLE,
+ MOVE_ACID,
+ MOVE_TEETER_DANCE,
+ MOVE_DYNAMIC_PUNCH,
+ MOVE_COUNTER),
+
+ egg_moves(SNORUNT,
+ MOVE_BLOCK,
+ MOVE_SPIKES),
+
+ egg_moves(AZURILL,
+ MOVE_ENCORE,
+ MOVE_SING,
+ MOVE_REFRESH,
+ MOVE_SLAM,
+ MOVE_TICKLE),
+
+ egg_moves(SPOINK,
+ MOVE_FUTURE_SIGHT,
+ MOVE_EXTRASENSORY,
+ MOVE_SUBSTITUTE,
+ MOVE_TRICK),
+
+ egg_moves(PLUSLE,
+ MOVE_SUBSTITUTE,
+ MOVE_WISH),
+
+ egg_moves(MINUN,
+ MOVE_SUBSTITUTE,
+ MOVE_WISH),
+
+ egg_moves(MAWILE,
+ MOVE_SWORDS_DANCE,
+ MOVE_FALSE_SWIPE,
+ MOVE_POISON_FANG,
+ MOVE_PSYCH_UP,
+ MOVE_ANCIENT_POWER,
+ MOVE_TICKLE),
+
+ egg_moves(MEDITITE,
+ MOVE_FIRE_PUNCH,
+ MOVE_THUNDER_PUNCH,
+ MOVE_ICE_PUNCH,
+ MOVE_FORESIGHT,
+ MOVE_FAKE_OUT,
+ MOVE_BATON_PASS,
+ MOVE_DYNAMIC_PUNCH),
+
+ egg_moves(SWABLU,
+ MOVE_AGILITY,
+ MOVE_HAZE,
+ MOVE_PURSUIT,
+ MOVE_RAGE),
+
+ egg_moves(DUSKULL,
+ MOVE_IMPRISON,
+ MOVE_DESTINY_BOND,
+ MOVE_PAIN_SPLIT,
+ MOVE_GRUDGE,
+ MOVE_MEMENTO,
+ MOVE_FAINT_ATTACK),
+
+ egg_moves(ROSELIA,
+ MOVE_SPIKES,
+ MOVE_SYNTHESIS,
+ MOVE_PIN_MISSILE,
+ MOVE_COTTON_SPORE),
+
+ egg_moves(SLAKOTH,
+ MOVE_PURSUIT,
+ MOVE_SLASH,
+ MOVE_BODY_SLAM,
+ MOVE_SNORE,
+ MOVE_CRUSH_CLAW,
+ MOVE_CURSE,
+ MOVE_SLEEP_TALK),
+
+ egg_moves(GULPIN,
+ MOVE_DREAM_EATER,
+ MOVE_ACID_ARMOR,
+ MOVE_SMOG,
+ MOVE_PAIN_SPLIT),
+
+ egg_moves(TROPIUS,
+ MOVE_HEADBUTT,
+ MOVE_SLAM,
+ MOVE_RAZOR_WIND,
+ MOVE_LEECH_SEED,
+ MOVE_NATURE_POWER),
+
+ egg_moves(WHISMUR,
+ MOVE_TAKE_DOWN,
+ MOVE_SNORE,
+ MOVE_SWAGGER,
+ MOVE_EXTRASENSORY,
+ MOVE_SMELLING_SALT),
+
+ egg_moves(CLAMPERL,
+ MOVE_REFRESH,
+ MOVE_MUD_SPORT,
+ MOVE_BODY_SLAM,
+ MOVE_SUPERSONIC,
+ MOVE_BARRIER,
+ MOVE_CONFUSE_RAY),
+
+ egg_moves(ABSOL,
+ MOVE_BATON_PASS,
+ MOVE_FAINT_ATTACK,
+ MOVE_DOUBLE_EDGE,
+ MOVE_MAGIC_COAT,
+ MOVE_CURSE,
+ MOVE_SUBSTITUTE),
+
+ egg_moves(SHUPPET,
+ MOVE_DISABLE,
+ MOVE_DESTINY_BOND,
+ MOVE_FORESIGHT,
+ MOVE_ASTONISH,
+ MOVE_IMPRISON),
+
+ egg_moves(SEVIPER,
+ MOVE_STOCKPILE,
+ MOVE_SWALLOW,
+ MOVE_SPIT_UP,
+ MOVE_BODY_SLAM),
+
+ egg_moves(ZANGOOSE,
+ MOVE_FLAIL,
+ MOVE_DOUBLE_KICK,
+ MOVE_RAZOR_WIND,
+ MOVE_COUNTER,
+ MOVE_ROAR,
+ MOVE_CURSE),
+
+ egg_moves(RELICANTH,
+ MOVE_MAGNITUDE,
+ MOVE_SKULL_BASH,
+ MOVE_WATER_SPORT,
+ MOVE_AMNESIA,
+ MOVE_SLEEP_TALK,
+ MOVE_ROCK_SLIDE),
+
+ egg_moves(ARON,
+ MOVE_ENDEAVOR,
+ MOVE_BODY_SLAM,
+ MOVE_STOMP,
+ MOVE_SMELLING_SALT),
+
+ egg_moves(CASTFORM,
+ MOVE_FUTURE_SIGHT,
+ MOVE_PSYCH_UP),
+
+ egg_moves(VOLBEAT,
+ MOVE_BATON_PASS,
+ MOVE_SILVER_WIND,
+ MOVE_TRICK),
+
+ egg_moves(ILLUMISE,
+ MOVE_BATON_PASS,
+ MOVE_SILVER_WIND,
+ MOVE_GROWTH),
+
+ egg_moves(LILEEP,
+ MOVE_BARRIER,
+ MOVE_RECOVER,
+ MOVE_MIRROR_COAT,
+ MOVE_ROCK_SLIDE),
+
+ egg_moves(ANORITH,
+ MOVE_RAPID_SPIN,
+ MOVE_KNOCK_OFF,
+ MOVE_SWORDS_DANCE,
+ MOVE_ROCK_SLIDE),
+
+ egg_moves(RALTS,
+ MOVE_DISABLE,
+ MOVE_WILL_O_WISP,
+ MOVE_MEAN_LOOK,
+ MOVE_MEMENTO,
+ MOVE_DESTINY_BOND),
+
+ egg_moves(BAGON,
+ MOVE_HYDRO_PUMP,
+ MOVE_THRASH,
+ MOVE_DRAGON_RAGE,
+ MOVE_TWISTER,
+ MOVE_DRAGON_DANCE),
+
+ egg_moves(CHIMECHO,
+ MOVE_DISABLE,
+ MOVE_CURSE,
+ MOVE_HYPNOSIS,
+ MOVE_DREAM_EATER),
+
+ EGG_MOVES_TERMINATOR
+};
diff --git a/src/daycare.c b/src/daycare.c
new file mode 100644
index 000000000..206e0b383
--- /dev/null
+++ b/src/daycare.c
@@ -0,0 +1,2209 @@
+#include "global.h"
+#include "pokemon.h"
+#include "battle.h"
+#include "daycare.h"
+#include "string_util.h"
+#include "constants/species.h"
+#include "constants/items.h"
+#include "mail.h"
+#include "pokemon_storage_system.h"
+#include "event_data.h"
+#include "random.h"
+#include "main.h"
+#include "constants/moves.h"
+#include "text.h"
+#include "menu.h"
+#include "new_menu_helpers.h"
+#include "international_string_util.h"
+#include "script.h"
+#include "strings.h"
+#include "task.h"
+#include "window.h"
+#include "party_menu.h"
+#include "list_menu.h"
+#include "overworld.h"
+#include "pokedex.h"
+#include "decompress.h"
+#include "task.h"
+#include "palette.h"
+#include "main.h"
+#include "sound.h"
+#include "constants/songs.h"
+#include "text_window.h"
+#include "trig.h"
+#include "malloc.h"
+#include "dma3.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "m4a.h"
+#include "graphics.h"
+#include "constants/abilities.h"
+#include "constants/species.h"
+#include "scanline_effect.h"
+#include "field_weather.h"
+#include "naming_screen.h"
+#include "field_screen_effect.h"
+#include "help_system.h"
+#include "field_fadetransition.h"
+
+#define EGG_MOVES_ARRAY_COUNT 10
+#define EGG_LVL_UP_MOVES_ARRAY_COUNT 50
+
+struct EggHatchData
+{
+ u8 eggSpriteID;
+ u8 pokeSpriteID;
+ u8 CB2_state;
+ u8 CB2_PalCounter;
+ u8 eggPartyID;
+ u8 unused_5;
+ u8 unused_6;
+ u8 eggShardVelocityID;
+ u8 windowId;
+ u8 unused_9;
+ u8 unused_A;
+ u16 species;
+ struct TextColor textColor;
+};
+
+extern const u8 gText_MaleSymbol4[];
+extern const u8 gText_FemaleSymbol4[];
+extern const u8 gText_GenderlessSymbol[];
+extern const u8 gText_Lv[];
+extern const u8 gDaycareText_GetAlongVeryWell[];
+extern const u8 gDaycareText_GetAlong[];
+extern const u8 gDaycareText_DontLikeOther[];
+extern const u8 gDaycareText_PlayOther[];
+extern const u8 gExpandedPlaceholder_Empty[];
+
+extern const u32 gUnknown_08331F60[]; // tilemap gameboy circle
+extern const u8 gText_HatchedFromEgg[];
+extern const u8 gText_NickHatchPrompt[];
+
+// this file's functions
+static void ClearDaycareMonMail(struct DayCareMail *mail);
+static void SetInitialEggData(struct Pokemon *mon, u16 species, struct DayCare *daycare);
+static u8 GetDaycareCompatibilityScore(struct DayCare *daycare);
+static void DaycarePrintMonInfo(u8 windowId, s32 daycareSlotId, u8 y);
+
+static void Task_EggHatch(u8 taskID);
+static void CB2_EggHatch_0(void);
+static void CB2_EggHatch_1(void);
+static void SpriteCB_Egg_0(struct Sprite* sprite);
+static void SpriteCB_Egg_1(struct Sprite* sprite);
+static void SpriteCB_Egg_2(struct Sprite* sprite);
+static void SpriteCB_Egg_3(struct Sprite* sprite);
+static void SpriteCB_Egg_4(struct Sprite* sprite);
+static void SpriteCB_Egg_5(struct Sprite* sprite);
+static void SpriteCB_EggShard(struct Sprite* sprite);
+static void EggHatchPrintMessage(u8 windowId, u8* string, u8 x, u8 y, u8 speed);
+static void CreateRandomEggShardSprite(void);
+static void CreateEggShardSprite(u8 x, u8 y, s16 data1, s16 data2, s16 data3, u8 spriteAnimIndex);
+
+// IWRAM bss
+static IWRAM_DATA struct EggHatchData *sEggHatchData;
+
+// RAM buffers used to assist with BuildEggMoveset()
+EWRAM_DATA static u16 sHatchedEggLevelUpMoves[EGG_LVL_UP_MOVES_ARRAY_COUNT] = {0};
+EWRAM_DATA static u16 sHatchedEggFatherMoves[4] = {0};
+EWRAM_DATA static u16 sHatchedEggFinalMoves[4] = {0};
+EWRAM_DATA static u16 sHatchedEggEggMoves[EGG_MOVES_ARRAY_COUNT] = {0};
+EWRAM_DATA static u16 sHatchedEggMotherMoves[4] = {0};
+
+#include "data/pokemon/egg_moves.h"
+
+static const struct WindowTemplate sDaycareLevelMenuWindowTemplate =
+{
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 1,
+ .width = 17,
+ .height = 5,
+ .paletteNum = 15,
+ .baseBlock = 8
+};
+
+static const struct ListMenuItem sLevelMenuItems[] =
+{
+ {gExpandedPlaceholder_Empty, 0},
+ {gExpandedPlaceholder_Empty, 1},
+ {gOtherText_Exit, 5}
+};
+
+static const struct ListMenuTemplate sDaycareListMenuLevelTemplate =
+{
+ .items = sLevelMenuItems,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = DaycarePrintMonInfo,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 2,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 1,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 3,
+ .cursorKind = 0
+};
+
+static const u8 *const sCompatibilityMessages[] =
+{
+ gDaycareText_GetAlongVeryWell,
+ gDaycareText_GetAlong,
+ gDaycareText_DontLikeOther,
+ gDaycareText_PlayOther
+};
+
+static const u8 sNewLineText[] = _("\n");
+static const u8 sJapaneseEggNickname[] = _("タマゴ"); // "tamago" ("egg" in Japanese)
+
+static const u16 sEggPalette[] = INCBIN_U16("graphics/pokemon/egg/normal.gbapal");
+static const u8 sEggHatchTiles[] = INCBIN_U8("graphics/misc/egg_hatch.4bpp");
+static const u8 sEggShardTiles[] = INCBIN_U8("graphics/misc/egg_shard.4bpp");
+
+static const struct OamData sOamData_EggHatch =
+ {
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = SPRITE_SHAPE(32x32),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(32x32),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+ };
+
+static const union AnimCmd sSpriteAnim_EggHatch0[] =
+ {
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggHatch1[] =
+ {
+ ANIMCMD_FRAME(16, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggHatch2[] =
+ {
+ ANIMCMD_FRAME(32, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggHatch3[] =
+ {
+ ANIMCMD_FRAME(48, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd *const sSpriteAnimTable_EggHatch[] =
+ {
+ sSpriteAnim_EggHatch0,
+ sSpriteAnim_EggHatch1,
+ sSpriteAnim_EggHatch2,
+ sSpriteAnim_EggHatch3,
+ };
+
+static const struct SpriteSheet sEggHatch_Sheet =
+ {
+ .data = sEggHatchTiles,
+ .size = 2048,
+ .tag = 12345,
+ };
+
+static const struct SpriteSheet sEggShards_Sheet =
+ {
+ .data = sEggShardTiles,
+ .size = 128,
+ .tag = 23456,
+ };
+
+static const struct SpritePalette sEgg_SpritePalette =
+ {
+ .data = sEggPalette,
+ .tag = 54321
+ };
+
+static const struct SpriteTemplate sSpriteTemplate_EggHatch =
+ {
+ .tileTag = 12345,
+ .paletteTag = 54321,
+ .oam = &sOamData_EggHatch,
+ .anims = sSpriteAnimTable_EggHatch,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+ };
+
+static const struct OamData sOamData_EggShard =
+ {
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = SPRITE_SHAPE(8x8),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(8x8),
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 0,
+ .affineParam = 0,
+ };
+
+static const union AnimCmd sSpriteAnim_EggShard0[] =
+ {
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggShard1[] =
+ {
+ ANIMCMD_FRAME(1, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggShard2[] =
+ {
+ ANIMCMD_FRAME(2, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggShard3[] =
+ {
+ ANIMCMD_FRAME(3, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd *const sSpriteAnimTable_EggShard[] =
+ {
+ sSpriteAnim_EggShard0,
+ sSpriteAnim_EggShard1,
+ sSpriteAnim_EggShard2,
+ sSpriteAnim_EggShard3,
+ };
+
+static const struct SpriteTemplate sSpriteTemplate_EggShard =
+ {
+ .tileTag = 23456,
+ .paletteTag = 54321,
+ .oam = &sOamData_EggShard,
+ .anims = sSpriteAnimTable_EggShard,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_EggShard
+ };
+
+static const struct BgTemplate sBgTemplates_EggHatch[2] =
+ {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 24,
+ .screenSize = 3,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0
+ },
+
+ {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 8,
+ .screenSize = 1,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0
+ },
+ };
+
+static const struct WindowTemplate sWinTemplates_EggHatch[2] =
+ {
+ {
+ .bg = 0,
+ .tilemapLeft = 2,
+ .tilemapTop = 15,
+ .width = 26,
+ .height = 4,
+ .paletteNum = 0,
+ .baseBlock = 64
+ },
+ DUMMY_WIN_TEMPLATE
+ };
+
+static const struct WindowTemplate sYesNoWinTemplate =
+ {
+ .bg = 0,
+ .tilemapLeft = 21,
+ .tilemapTop = 9,
+ .width = 6,
+ .height = 4,
+ .paletteNum = 15,
+ .baseBlock = 424
+ };
+
+static const s16 sEggShardVelocities[][2] =
+ {
+ {Q_8_8(-1.5), Q_8_8(-3.75)},
+ {Q_8_8(-5), Q_8_8(-3)},
+ {Q_8_8(3.5), Q_8_8(-3)},
+ {Q_8_8(-4), Q_8_8(-3.75)},
+ {Q_8_8(2), Q_8_8(-1.5)},
+ {Q_8_8(-0.5), Q_8_8(-6.75)},
+ {Q_8_8(5), Q_8_8(-2.25)},
+ {Q_8_8(-1.5), Q_8_8(-3.75)},
+ {Q_8_8(4.5), Q_8_8(-1.5)},
+ {Q_8_8(-1), Q_8_8(-6.75)},
+ {Q_8_8(4), Q_8_8(-2.25)},
+ {Q_8_8(-3.5), Q_8_8(-3.75)},
+ {Q_8_8(1), Q_8_8(-1.5)},
+ {Q_8_8(-3.515625), Q_8_8(-6.75)},
+ {Q_8_8(4.5), Q_8_8(-2.25)},
+ {Q_8_8(-0.5), Q_8_8(-7.5)},
+ {Q_8_8(1), Q_8_8(-4.5)},
+ {Q_8_8(-2.5), Q_8_8(-2.25)},
+ {Q_8_8(2.5), Q_8_8(-7.5)},
+ };
+
+// code
+
+u8 *GetMonNick(struct Pokemon *mon, u8 *dest)
+{
+ u8 nickname[POKEMON_NAME_LENGTH * 2];
+
+ GetMonData(mon, MON_DATA_NICKNAME, nickname);
+ return StringCopy10(dest, nickname);
+}
+
+u8 *GetBoxMonNick(struct BoxPokemon *mon, u8 *dest)
+{
+ u8 nickname[POKEMON_NAME_LENGTH * 2];
+
+ GetBoxMonData(mon, MON_DATA_NICKNAME, nickname);
+ return StringCopy10(dest, nickname);
+}
+
+u8 CountPokemonInDaycare(struct DayCare *daycare)
+{
+ u8 i, count;
+ count = 0;
+
+ for (i = 0; i < DAYCARE_MON_COUNT; i++)
+ {
+ if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES) != 0)
+ count++;
+ }
+
+ return count;
+}
+
+void InitDaycareMailRecordMixing(struct DayCare *daycare, struct RecordMixingDayCareMail *daycareMail)
+{
+ u8 i;
+ u8 numDaycareMons = 0;
+
+ for (i = 0; i < DAYCARE_MON_COUNT; i++)
+ {
+ if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ numDaycareMons++;
+ if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_HELD_ITEM) == ITEM_NONE)
+ {
+ daycareMail->holdsItem[i] = FALSE;
+ }
+ else
+ {
+ daycareMail->holdsItem[i] = TRUE;
+ }
+ }
+ else
+ {
+ daycareMail->holdsItem[i] = TRUE;
+ }
+ }
+
+ daycareMail->numDaycareMons = numDaycareMons;
+}
+
+static s8 Daycare_FindEmptySpot(struct DayCare *daycare)
+{
+ u8 i;
+
+ for (i = 0; i < DAYCARE_MON_COUNT; i++)
+ {
+ if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+static void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon)
+{
+ if (MonHasMail(mon))
+ {
+ u8 mailId;
+
+ StringCopy(daycareMon->mail.OT_name, gSaveBlock2Ptr->playerName);
+ GetMonNick(mon, daycareMon->mail.monName);
+// StripExtCtrlCodes(daycareMon->mail.monName);
+// daycareMon->mail.gameLanguage = LANGUAGE_ENGLISH;
+// daycareMon->mail.monLanguage = GetMonData(mon, MON_DATA_LANGUAGE);
+ mailId = GetMonData(mon, MON_DATA_MAIL);
+ daycareMon->mail.message = gSaveBlock1Ptr->mail[mailId];
+ TakeMailFromMon(mon);
+ }
+
+ daycareMon->mon = mon->box;
+ BoxMonRestorePP(&daycareMon->mon);
+ daycareMon->steps = 0;
+ ZeroMonData(mon);
+ CompactPartySlots();
+ CalculatePlayerPartyCount();
+}
+
+static void StorePokemonInEmptyDaycareSlot(struct Pokemon *mon, struct DayCare *daycare)
+{
+ s8 slotId = Daycare_FindEmptySpot(daycare);
+ StorePokemonInDaycare(mon, &daycare->mons[slotId]);
+}
+
+void StoreSelectedPokemonInDaycare(void)
+{
+ u8 monId = GetCursorSelectionMonId();
+ StorePokemonInEmptyDaycareSlot(&gPlayerParty[monId], &gSaveBlock1Ptr->daycare);
+}
+
+// Shifts the second daycare pokemon slot into the first slot.
+static void ShiftDaycareSlots(struct DayCare *daycare)
+{
+ // This condition is only satisfied when the player takes out the first pokemon from the daycare.
+ if (GetBoxMonData(&daycare->mons[1].mon, MON_DATA_SPECIES) != 0
+ && GetBoxMonData(&daycare->mons[0].mon, MON_DATA_SPECIES) == 0)
+ {
+ daycare->mons[0].mon = daycare->mons[1].mon;
+ ZeroBoxMonData(&daycare->mons[1].mon);
+
+ daycare->mons[0].mail = daycare->mons[1].mail;
+ daycare->mons[0].steps = daycare->mons[1].steps;
+ daycare->mons[1].steps = 0;
+ ClearDaycareMonMail(&daycare->mons[1].mail);
+ }
+}
+
+static void ApplyDaycareExperience(struct Pokemon *mon)
+{
+ s32 i;
+ bool8 firstMove;
+ u16 learnedMove;
+
+ for (i = 0; i < MAX_MON_LEVEL; i++)
+ {
+ // Add the mon's gained daycare experience level by level until it can't level up anymore.
+ if (TryIncrementMonLevel(mon))
+ {
+ // Teach the mon new moves it learned while in the daycare.
+ firstMove = TRUE;
+ while ((learnedMove = MonTryLearningNewMove(mon, firstMove)) != 0)
+ {
+ firstMove = FALSE;
+ if (learnedMove == 0xFFFF)
+ {
+ // Mon already knows 4 moves.
+ DeleteFirstMoveAndGiveMoveToMon(mon, gMoveToLearn);
+ }
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // Re-calculate the mons stats at its new level.
+ CalculateMonStats(mon);
+}
+
+static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon)
+{
+ u16 species;
+ u32 experience;
+ struct Pokemon pokemon;
+
+ GetBoxMonNick(&daycareMon->mon, gStringVar1);
+ species = GetBoxMonData(&daycareMon->mon, MON_DATA_SPECIES);
+ BoxMonToMon(&daycareMon->mon, &pokemon);
+
+ if (GetMonData(&pokemon, MON_DATA_LEVEL) != MAX_MON_LEVEL)
+ {
+ experience = GetMonData(&pokemon, MON_DATA_EXP) + daycareMon->steps;
+ SetMonData(&pokemon, MON_DATA_EXP, &experience);
+ ApplyDaycareExperience(&pokemon);
+ }
+
+ gPlayerParty[PARTY_SIZE - 1] = pokemon;
+ if (daycareMon->mail.message.itemId)
+ {
+ GiveMailToMon2(&gPlayerParty[PARTY_SIZE - 1], &daycareMon->mail.message);
+ ClearDaycareMonMail(&daycareMon->mail);
+ }
+
+ ZeroBoxMonData(&daycareMon->mon);
+ daycareMon->steps = 0;
+ CompactPartySlots();
+ CalculatePlayerPartyCount();
+ return species;
+}
+
+static u16 TakeSelectedPokemonMonFromDaycareShiftSlots(struct DayCare *daycare, u8 slotId)
+{
+ u16 species = TakeSelectedPokemonFromDaycare(&daycare->mons[slotId]);
+ ShiftDaycareSlots(daycare);
+ return species;
+}
+
+u16 TakePokemonFromDaycare(void)
+{
+ return TakeSelectedPokemonMonFromDaycareShiftSlots(&gSaveBlock1Ptr->daycare, gSpecialVar_0x8004);
+}
+
+static u8 GetLevelAfterDaycareSteps(struct BoxPokemon *mon, u32 steps)
+{
+ struct BoxPokemon tempMon = *mon;
+
+ u32 experience = GetBoxMonData(mon, MON_DATA_EXP) + steps;
+ SetBoxMonData(&tempMon, MON_DATA_EXP, &experience);
+ return GetLevelFromBoxMonExp(&tempMon);
+}
+
+static u8 GetNumLevelsGainedFromSteps(struct DaycareMon *daycareMon)
+{
+ u8 levelBefore;
+ u8 levelAfter;
+
+ levelBefore = GetLevelFromBoxMonExp(&daycareMon->mon);
+ levelAfter = GetLevelAfterDaycareSteps(&daycareMon->mon, daycareMon->steps);
+ return levelAfter - levelBefore;
+}
+
+static u8 GetNumLevelsGainedForDaycareMon(struct DaycareMon *daycareMon)
+{
+ u8 numLevelsGained = GetNumLevelsGainedFromSteps(daycareMon);
+ ConvertIntToDecimalStringN(gStringVar2, numLevelsGained, STR_CONV_MODE_LEFT_ALIGN, 2);
+ GetBoxMonNick(&daycareMon->mon, gStringVar1);
+ return numLevelsGained;
+}
+
+static u32 GetDaycareCostForSelectedMon(struct DaycareMon *daycareMon)
+{
+ u32 cost;
+
+ u8 numLevelsGained = GetNumLevelsGainedFromSteps(daycareMon);
+ GetBoxMonNick(&daycareMon->mon, gStringVar1);
+ cost = 100 + 100 * numLevelsGained;
+ ConvertIntToDecimalStringN(gStringVar2, cost, STR_CONV_MODE_LEFT_ALIGN, 5);
+ return cost;
+}
+
+static u16 GetDaycareCostForMon(struct DayCare *daycare, u8 slotId)
+{
+ return GetDaycareCostForSelectedMon(&daycare->mons[slotId]);
+}
+
+void GetDaycareCost(void)
+{
+ gSpecialVar_0x8005 = GetDaycareCostForMon(&gSaveBlock1Ptr->daycare, gSpecialVar_0x8004);
+}
+
+static void Debug_AddDaycareSteps(u16 numSteps)
+{
+ gSaveBlock1Ptr->daycare.mons[0].steps += numSteps;
+ gSaveBlock1Ptr->daycare.mons[1].steps += numSteps;
+ gSaveBlock1Ptr->route5DayCareMon.steps += numSteps;
+}
+
+u8 GetNumLevelsGainedFromDaycare(void)
+{
+ if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004], MON_DATA_SPECIES) != 0)
+ return GetNumLevelsGainedForDaycareMon(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004]);
+
+ return 0;
+}
+
+static void ClearDaycareMonMail(struct DayCareMail *mail)
+{
+ s32 i;
+
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ mail->OT_name[i] = 0;
+ for (i = 0; i < POKEMON_NAME_LENGTH + 1; i++)
+ mail->monName[i] = 0;
+
+ ClearMailStruct(&mail->message);
+}
+
+static void ClearDaycareMon(struct DaycareMon *daycareMon)
+{
+ ZeroBoxMonData(&daycareMon->mon);
+ daycareMon->steps = 0;
+ ClearDaycareMonMail(&daycareMon->mail);
+}
+
+static void ClearAllDaycareData(struct DayCare *daycare)
+{
+ u8 i;
+
+ for (i = 0; i < DAYCARE_MON_COUNT; i++)
+ ClearDaycareMon(&daycare->mons[i]);
+
+ daycare->offspringPersonality = 0;
+ daycare->stepCounter = 0;
+}
+
+// Determines what the species of an Egg would be based on the given species.
+// It determines this by working backwards through the evolution chain of the
+// given species.
+static u16 GetEggSpecies(u16 species)
+{
+ int i, j, k;
+ bool8 found;
+
+ // Working backwards up to 5 times seems arbitrary, since the maximum number
+ // of times would only be 3 for 3-stage evolutions.
+ for (i = 0; i < EVOS_PER_MON; i++)
+ {
+ found = FALSE;
+ for (j = 1; j < NUM_SPECIES; j++)
+ {
+ for (k = 0; k < EVOS_PER_MON; k++)
+ {
+ if (gEvolutionTable[j][k].targetSpecies == species)
+ {
+ species = j;
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found)
+ break;
+ }
+
+ if (j == NUM_SPECIES)
+ break;
+ }
+
+ return species;
+}
+//
+//static s32 GetSlotToInheritNature(struct DayCare *daycare)
+//{
+// u32 species[DAYCARE_MON_COUNT];
+// s32 i;
+// s32 dittoCount;
+// s32 slot = -1;
+//
+// // search for female gender
+// for (i = 0; i < DAYCARE_MON_COUNT; i++)
+// {
+// if (GetBoxMonGender(&daycare->mons[i].mon) == MON_FEMALE)
+// slot = i;
+// }
+//
+// // search for ditto
+// for (dittoCount = 0, i = 0; i < DAYCARE_MON_COUNT; i++)
+// {
+// species[i] = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES);
+// if (species[i] == SPECIES_DITTO)
+// dittoCount++, slot = i;
+// }
+//
+// // coin flip on ...two Dittos
+// if (dittoCount == 2)
+// {
+// if (Random() >= USHRT_MAX / 2)
+// slot = 0;
+// else
+// slot = 1;
+// }
+//
+// // nature inheritance only if holds everstone
+// if (GetBoxMonData(&daycare->mons[slot].mon, MON_DATA_HELD_ITEM) != ITEM_EVERSTONE
+// || Random() >= USHRT_MAX / 2)
+// {
+// return -1;
+// }
+//
+// return slot;
+//}
+
+static void _TriggerPendingDaycareEgg(struct DayCare *daycare)
+{
+// s32 natureSlot;
+// s32 natureTries = 0;
+//
+// SeedRng2(gMain.vblankCounter2);
+// natureSlot = GetSlotToInheritNature(daycare);
+//
+// if (natureSlot < 0)
+// {
+// daycare->offspringPersonality = (Random2() << 0x10) | ((Random() % 0xfffe) + 1);
+// }
+// else
+// {
+// u8 wantedNature = GetNatureFromPersonality(GetBoxMonData(&daycare->mons[natureSlot].mon, MON_DATA_PERSONALITY, NULL));
+// u32 personality;
+//
+// do
+// {
+// personality = (Random2() << 0x10) | (Random());
+// if (wantedNature == GetNatureFromPersonality(personality) && personality != 0)
+// break; // we found a personality with the same nature
+//
+// natureTries++;
+// } while (natureTries <= 2400);
+//
+// daycare->offspringPersonality = personality;
+// }
+
+ daycare->offspringPersonality = ((Random()) % 0xFFFE) + 1;
+ FlagSet(FLAG_PENDING_DAYCARE_EGG);
+}
+
+static void _TriggerPendingDaycareMaleEgg(struct DayCare *daycare)
+{
+ daycare->offspringPersonality = (Random()) | (0x8000);
+ FlagSet(FLAG_PENDING_DAYCARE_EGG);
+}
+
+void TriggerPendingDaycareEgg(void)
+{
+ _TriggerPendingDaycareEgg(&gSaveBlock1Ptr->daycare);
+}
+
+static void TriggerPendingDaycareMaleEgg(void)
+{
+ _TriggerPendingDaycareMaleEgg(&gSaveBlock1Ptr->daycare);
+}
+
+// Removes the selected index from the given IV list and shifts the remaining
+// elements to the left.
+static void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv)
+{
+ s32 i, j;
+ u8 temp[NUM_STATS];
+
+ ivs[selectedIv] = 0xFF;
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ temp[i] = ivs[i];
+ }
+
+ j = 0;
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ if (temp[i] != 0xFF)
+ ivs[j++] = temp[i];
+ }
+}
+
+static void InheritIVs(struct Pokemon *egg, struct DayCare *daycare)
+{
+ u8 i;
+ u8 selectedIvs[3];
+ u8 availableIVs[NUM_STATS];
+ u8 whichParent[ARRAY_COUNT(selectedIvs)];
+ u8 iv;
+
+ // Initialize a list of IV indices.
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ availableIVs[i] = i;
+ }
+
+ // Select the 3 IVs that will be inherited.
+ for (i = 0; i < ARRAY_COUNT(selectedIvs); i++)
+ {
+ // Randomly pick an IV from the available list.
+ selectedIvs[i] = availableIVs[Random() % (NUM_STATS - i)];
+
+ // Remove the selected IV index from the available IV indices.
+ RemoveIVIndexFromList(availableIVs, selectedIvs[i]);
+ }
+
+ // Determine which parent each of the selected IVs should inherit from.
+ for (i = 0; i < ARRAY_COUNT(selectedIvs); i++)
+ {
+ whichParent[i] = Random() % 2;
+ }
+
+ // Set each of inherited IVs on the egg mon.
+ for (i = 0; i < ARRAY_COUNT(selectedIvs); i++)
+ {
+ switch (selectedIvs[i])
+ {
+ case 0:
+ iv = GetBoxMonData(&daycare->mons[whichParent[i]].mon, MON_DATA_HP_IV);
+ SetMonData(egg, MON_DATA_HP_IV, &iv);
+ break;
+ case 1:
+ iv = GetBoxMonData(&daycare->mons[whichParent[i]].mon, MON_DATA_ATK_IV);
+ SetMonData(egg, MON_DATA_ATK_IV, &iv);
+ break;
+ case 2:
+ iv = GetBoxMonData(&daycare->mons[whichParent[i]].mon, MON_DATA_DEF_IV);
+ SetMonData(egg, MON_DATA_DEF_IV, &iv);
+ break;
+ case 3:
+ iv = GetBoxMonData(&daycare->mons[whichParent[i]].mon, MON_DATA_SPEED_IV);
+ SetMonData(egg, MON_DATA_SPEED_IV, &iv);
+ break;
+ case 4:
+ iv = GetBoxMonData(&daycare->mons[whichParent[i]].mon, MON_DATA_SPATK_IV);
+ SetMonData(egg, MON_DATA_SPATK_IV, &iv);
+ break;
+ case 5:
+ iv = GetBoxMonData(&daycare->mons[whichParent[i]].mon, MON_DATA_SPDEF_IV);
+ SetMonData(egg, MON_DATA_SPDEF_IV, &iv);
+ break;
+ }
+ }
+}
+
+// Counts the number of egg moves a pokemon learns and stores the moves in
+// the given array.
+static u8 GetEggMoves(struct Pokemon *pokemon, u16 *eggMoves)
+{
+ u16 eggMoveIdx;
+ u16 numEggMoves;
+ u16 species;
+ u16 i;
+
+ numEggMoves = 0;
+ eggMoveIdx = 0;
+ species = GetMonData(pokemon, MON_DATA_SPECIES);
+ for (i = 0; i < ARRAY_COUNT(gEggMoves) - 1; i++)
+ {
+ if (gEggMoves[i] == species + EGG_MOVES_SPECIES_OFFSET)
+ {
+ eggMoveIdx = i + 1;
+ break;
+ }
+ }
+
+ for (i = 0; i < EGG_MOVES_ARRAY_COUNT; i++)
+ {
+ if (gEggMoves[eggMoveIdx + i] > EGG_MOVES_SPECIES_OFFSET)
+ {
+ // TODO: the curly braces around this if statement are required for a matching build.
+ break;
+ }
+
+ eggMoves[i] = gEggMoves[eggMoveIdx + i];
+ numEggMoves++;
+ }
+
+ return numEggMoves;
+}
+
+static void BuildEggMoveset(struct Pokemon *egg, struct BoxPokemon *father, struct BoxPokemon *mother)
+{
+ u16 numSharedParentMoves;
+ u32 numLevelUpMoves;
+ u16 numEggMoves;
+ u16 i, j;
+
+ numSharedParentMoves = 0;
+ for (i = 0; i < MAX_MON_MOVES; i++)
+ {
+ sHatchedEggMotherMoves[i] = 0;
+ sHatchedEggFatherMoves[i] = 0;
+ sHatchedEggFinalMoves[i] = 0;
+ }
+ for (i = 0; i < EGG_MOVES_ARRAY_COUNT; i++)
+ sHatchedEggEggMoves[i] = 0;
+ for (i = 0; i < EGG_LVL_UP_MOVES_ARRAY_COUNT; i++)
+ sHatchedEggLevelUpMoves[i] = 0;
+
+ numLevelUpMoves = GetLevelUpMovesBySpecies(GetMonData(egg, MON_DATA_SPECIES), sHatchedEggLevelUpMoves);
+ for (i = 0; i < MAX_MON_MOVES; i++)
+ {
+ sHatchedEggFatherMoves[i] = GetBoxMonData(father, MON_DATA_MOVE1 + i);
+ sHatchedEggMotherMoves[i] = GetBoxMonData(mother, MON_DATA_MOVE1 + i);
+ }
+
+ numEggMoves = GetEggMoves(egg, sHatchedEggEggMoves);
+
+ for (i = 0; i < MAX_MON_MOVES; i++)
+ {
+ if (sHatchedEggFatherMoves[i] != MOVE_NONE)
+ {
+ for (j = 0; j < numEggMoves; j++)
+ {
+ if (sHatchedEggFatherMoves[i] == sHatchedEggEggMoves[j])
+ {
+ if (GiveMoveToMon(egg, sHatchedEggFatherMoves[i]) == 0xFFFF)
+ DeleteFirstMoveAndGiveMoveToMon(egg, sHatchedEggFatherMoves[i]);
+ break;
+ }
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ for (i = 0; i < MAX_MON_MOVES; i++)
+ {
+ if (sHatchedEggFatherMoves[i] != MOVE_NONE)
+ {
+ for (j = 0; j < NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES; j++)
+ {
+ if (sHatchedEggFatherMoves[i] == ItemIdToBattleMoveId(ITEM_TM01/*_FOCUS_PUNCH*/ + j) && CanMonLearnTMHM(egg, j))
+ {
+ if (GiveMoveToMon(egg, sHatchedEggFatherMoves[i]) == 0xFFFF)
+ DeleteFirstMoveAndGiveMoveToMon(egg, sHatchedEggFatherMoves[i]);
+ }
+ }
+ }
+ }
+ for (i = 0; i < MAX_MON_MOVES; i++)
+ {
+ if (sHatchedEggFatherMoves[i] == MOVE_NONE)
+ break;
+ for (j = 0; j < MAX_MON_MOVES; j++)
+ {
+ if (sHatchedEggFatherMoves[i] == sHatchedEggMotherMoves[j] && sHatchedEggFatherMoves[i] != MOVE_NONE)
+ sHatchedEggFinalMoves[numSharedParentMoves++] = sHatchedEggFatherMoves[i];
+ }
+ }
+
+ for (i = 0; i < MAX_MON_MOVES; i++)
+ {
+ if (sHatchedEggFinalMoves[i] == MOVE_NONE)
+ break;
+ for (j = 0; j < numLevelUpMoves; j++)
+ {
+ if (sHatchedEggLevelUpMoves[j] != MOVE_NONE && sHatchedEggFinalMoves[i] == sHatchedEggLevelUpMoves[j])
+ {
+ if (GiveMoveToMon(egg, sHatchedEggFinalMoves[i]) == 0xFFFF)
+ DeleteFirstMoveAndGiveMoveToMon(egg, sHatchedEggFinalMoves[i]);
+ break;
+ }
+ }
+ }
+}
+
+static void RemoveEggFromDayCare(struct DayCare *daycare)
+{
+ daycare->offspringPersonality = 0;
+ daycare->stepCounter = 0;
+}
+
+void RejectEggFromDayCare(void)
+{
+ RemoveEggFromDayCare(&gSaveBlock1Ptr->daycare);
+}
+
+static void AlterEggSpeciesWithIncenseItem(u16 *species, struct DayCare *daycare)
+{
+ u16 motherItem, fatherItem;
+ if (*species == SPECIES_WYNAUT || *species == SPECIES_AZURILL)
+ {
+ motherItem = GetBoxMonData(&daycare->mons[0].mon, MON_DATA_HELD_ITEM);
+ fatherItem = GetBoxMonData(&daycare->mons[1].mon, MON_DATA_HELD_ITEM);
+ if (*species == SPECIES_WYNAUT && motherItem != ITEM_LAX_INCENSE && fatherItem != ITEM_LAX_INCENSE)
+ {
+ *species = SPECIES_WOBBUFFET;
+ }
+
+ if (*species == SPECIES_AZURILL && motherItem != ITEM_SEA_INCENSE && fatherItem != ITEM_SEA_INCENSE)
+ {
+ *species = SPECIES_MARILL;
+ }
+ }
+}
+
+/*static void GiveVoltTackleIfLightBall(struct Pokemon *mon, struct DayCare *daycare)
+{
+ u32 motherItem = GetBoxMonData(&daycare->mons[0].mon, MON_DATA_HELD_ITEM);
+ u32 fatherItem = GetBoxMonData(&daycare->mons[1].mon, MON_DATA_HELD_ITEM);
+
+ if (motherItem == ITEM_LIGHT_BALL || fatherItem == ITEM_LIGHT_BALL)
+ {
+ if (GiveMoveToMon(mon, MOVE_VOLT_TACKLE) == 0xFFFF)
+ DeleteFirstMoveAndGiveMoveToMon(mon, MOVE_VOLT_TACKLE);
+ }
+}*/
+
+static u16 DetermineEggSpeciesAndParentSlots(struct DayCare *daycare, u8 *parentSlots)
+{
+ u16 i;
+ u16 species[2];
+ u16 eggSpecies;
+
+ // Determine which of the daycare mons is the mother and father of the egg.
+ // The 0th index of the parentSlots array is considered the mother slot, and the
+ // 1st index is the father slot.
+ for (i = 0; i < 2; i++)
+ {
+ species[i] = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES);
+ if (species[i] == SPECIES_DITTO)
+ {
+ parentSlots[0] = i ^ 1;
+ parentSlots[1] = i;
+ }
+ else if (GetBoxMonGender(&daycare->mons[i].mon) == MON_FEMALE)
+ {
+ parentSlots[0] = i;
+ parentSlots[1] = i ^ 1;
+ }
+ }
+
+ eggSpecies = GetEggSpecies(species[parentSlots[0]]);
+ if (eggSpecies == SPECIES_NIDORAN_F && daycare->offspringPersonality & 0x8000)
+ {
+ eggSpecies = SPECIES_NIDORAN_M;
+ }
+ if (eggSpecies == SPECIES_ILLUMISE && daycare->offspringPersonality & 0x8000)
+ {
+ eggSpecies = SPECIES_VOLBEAT;
+ }
+
+ // Make Ditto the "mother" slot if the other daycare mon is male.
+ if (species[parentSlots[1]] == SPECIES_DITTO && GetBoxMonGender(&daycare->mons[parentSlots[0]].mon) != MON_FEMALE)
+ {
+ u8 temp = parentSlots[1];
+ parentSlots[1] = parentSlots[0];
+ parentSlots[0] = temp;
+ }
+
+ return eggSpecies;
+}
+
+static void _GiveEggFromDaycare(struct DayCare *daycare) // give_egg
+{
+ struct Pokemon egg;
+ u16 species;
+ u8 parentSlots[2]; // 0th index is "mother" daycare slot, 1st is "father"
+ bool8 isEgg;
+
+ species = DetermineEggSpeciesAndParentSlots(daycare, parentSlots);
+ AlterEggSpeciesWithIncenseItem(&species, daycare);
+ SetInitialEggData(&egg, species, daycare);
+ InheritIVs(&egg, daycare);
+ BuildEggMoveset(&egg, &daycare->mons[parentSlots[1]].mon, &daycare->mons[parentSlots[0]].mon);
+
+ /*if (species == SPECIES_PICHU)
+ GiveVoltTackleIfLightBall(&egg, daycare);*/
+
+ isEgg = TRUE;
+ SetMonData(&egg, MON_DATA_IS_EGG, &isEgg);
+ gPlayerParty[PARTY_SIZE - 1] = egg;
+ CompactPartySlots();
+ CalculatePlayerPartyCount();
+ RemoveEggFromDayCare(daycare);
+}
+
+void CreateEgg(struct Pokemon *mon, u16 species, bool8 setHotSpringsLocation)
+{
+ u8 metLevel;
+ u16 ball;
+ u8 language;
+ u8 metLocation;
+ u8 isEgg;
+
+ CreateMon(mon, species, EGG_HATCH_LEVEL, 0x20, FALSE, 0, FALSE, 0);
+ metLevel = 0;
+ ball = ITEM_POKE_BALL;
+ language = LANGUAGE_JAPANESE;
+ SetMonData(mon, MON_DATA_POKEBALL, &ball);
+ SetMonData(mon, MON_DATA_NICKNAME, sJapaneseEggNickname);
+ SetMonData(mon, MON_DATA_FRIENDSHIP, &gBaseStats[species].eggCycles);
+ SetMonData(mon, MON_DATA_MET_LEVEL, &metLevel);
+ SetMonData(mon, MON_DATA_LANGUAGE, &language);
+ if (setHotSpringsLocation)
+ {
+ metLocation = 253; // hot springs; see PokemonSummaryScreen_PrintEggTrainerMemo
+ SetMonData(mon, MON_DATA_MET_LOCATION, &metLocation);
+ }
+
+ isEgg = TRUE;
+ SetMonData(mon, MON_DATA_IS_EGG, &isEgg);
+}
+
+static void SetInitialEggData(struct Pokemon *mon, u16 species, struct DayCare *daycare)
+{
+ u32 personality;
+ u16 ball;
+ u8 metLevel;
+ u8 language;
+
+ personality = daycare->offspringPersonality | (Random() << 16);
+ CreateMon(mon, species, EGG_HATCH_LEVEL, 0x20, TRUE, personality, FALSE, 0);
+ metLevel = 0;
+ ball = ITEM_POKE_BALL;
+ language = LANGUAGE_JAPANESE;
+ SetMonData(mon, MON_DATA_POKEBALL, &ball);
+ SetMonData(mon, MON_DATA_NICKNAME, sJapaneseEggNickname);
+ SetMonData(mon, MON_DATA_FRIENDSHIP, &gBaseStats[species].eggCycles);
+ SetMonData(mon, MON_DATA_MET_LEVEL, &metLevel);
+ SetMonData(mon, MON_DATA_LANGUAGE, &language);
+}
+
+void GiveEggFromDaycare(void)
+{
+ _GiveEggFromDaycare(&gSaveBlock1Ptr->daycare);
+}
+
+static bool8 _DoEggActions_CheckHatch(struct DayCare *daycare)
+{
+ u32 i, validEggs = 0;
+
+ for (i = 0; i < DAYCARE_MON_COUNT; i++)
+ {
+ if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SANITY_HAS_SPECIES))
+ daycare->mons[i].steps++, validEggs++;
+ }
+
+ // try to trigger poke sex
+ if (daycare->offspringPersonality == 0 && validEggs == 2 && (daycare->mons[1].steps & 0xFF) == 0xFF)
+ {
+ u8 loveScore = GetDaycareCompatibilityScore(daycare);
+ if (loveScore > (Random() * 100u) / USHRT_MAX)
+ TriggerPendingDaycareEgg();
+ }
+
+ if (++daycare->stepCounter == 255) // hatch an egg
+ {
+ u32 steps;
+
+ for (i = 0; i < gPlayerPartyCount; i++)
+ {
+ if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
+ continue;
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SANITY_IS_BAD_EGG))
+ continue;
+
+ steps = GetMonData(&gPlayerParty[i], MON_DATA_FRIENDSHIP);
+ if (steps != 0) // subtract needed steps
+ {
+ steps -= 1;
+
+ SetMonData(&gPlayerParty[i], MON_DATA_FRIENDSHIP, &steps);
+ }
+ else // hatch the egg
+ {
+ gSpecialVar_0x8004 = i;
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE; // no hatching
+}
+
+bool8 ShouldEggHatch(void)
+{
+ if (GetBoxMonData(&gSaveBlock1Ptr->route5DayCareMon.mon, MON_DATA_SANITY_HAS_SPECIES))
+ gSaveBlock1Ptr->route5DayCareMon.steps++;
+ return _DoEggActions_CheckHatch(&gSaveBlock1Ptr->daycare);
+}
+
+static bool8 IsEggPending(struct DayCare *daycare)
+{
+ return (daycare->offspringPersonality != 0);
+}
+
+// gStringVar1 = first mon's nickname
+// gStringVar2 = second mon's nickname
+// gStringVar3 = first mon trainer's name
+static void _GetDaycareMonNicknames(struct DayCare *daycare)
+{
+ u8 text[12];
+ if (GetBoxMonData(&daycare->mons[0].mon, MON_DATA_SPECIES) != 0)
+ {
+ GetBoxMonNick(&daycare->mons[0].mon, gStringVar1);
+ GetBoxMonData(&daycare->mons[0].mon, MON_DATA_OT_NAME, text);
+ StringCopy(gStringVar3, text);
+ }
+
+ if (GetBoxMonData(&daycare->mons[1].mon, MON_DATA_SPECIES) != 0)
+ {
+ GetBoxMonNick(&daycare->mons[1].mon, gStringVar2);
+ }
+}
+
+u16 GetSelectedMonNickAndSpecies(void)
+{
+ GetBoxMonNick(&gPlayerParty[GetCursorSelectionMonId()].box, gStringVar1);
+ return GetBoxMonData(&gPlayerParty[GetCursorSelectionMonId()].box, MON_DATA_SPECIES);
+}
+
+void GetDaycareMonNicknames(void)
+{
+ _GetDaycareMonNicknames(&gSaveBlock1Ptr->daycare);
+}
+
+u8 GetDaycareState(void)
+{
+ // The daycare can be in 4 possible states:
+ // 0: default state--no deposited mons, no egg
+ // 1: there is an egg waiting for the player to pick it up
+ // 2: there is a single pokemon in the daycare
+ // 3: there are two pokemon in the daycare, no egg
+
+ u8 numMons;
+ if (IsEggPending(&gSaveBlock1Ptr->daycare))
+ {
+ // There is an Egg waiting for the player.
+ return 1;
+ }
+
+ numMons = CountPokemonInDaycare(&gSaveBlock1Ptr->daycare);
+ if (numMons != 0)
+ {
+ return numMons + 1;
+ }
+
+ return 0;
+}
+
+u8 GetDaycarePokemonCount(void)
+{
+ u8 ret = CountPokemonInDaycare(&gSaveBlock1Ptr->daycare);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static bool8 EggGroupsOverlap(u16 *eggGroups1, u16 *eggGroups2)
+{
+ // Determine if the two given egg group lists contain any of the
+ // same egg groups.
+ s32 i, j;
+
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ if (eggGroups1[i] == eggGroups2[j])
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static u8 GetDaycareCompatibilityScore(struct DayCare *daycare)
+{
+ u32 i;
+ u16 eggGroups[2][2];
+ u16 species[2];
+ u32 trainerIds[2];
+ u32 genders[2];
+
+ for (i = 0; i < 2; i++)
+ {
+ u32 personality;
+
+ species[i] = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES);
+ trainerIds[i] = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_OT_ID);
+ personality = GetBoxMonData(&daycare->mons[i].mon, MON_DATA_PERSONALITY);
+ genders[i] = GetGenderFromSpeciesAndPersonality(species[i], personality);
+ eggGroups[i][0] = gBaseStats[species[i]].eggGroup1;
+ eggGroups[i][1] = gBaseStats[species[i]].eggGroup2;
+ }
+
+ // check unbreedable egg group
+ if (eggGroups[0][0] == EGG_GROUP_UNDISCOVERED || eggGroups[1][0] == EGG_GROUP_UNDISCOVERED)
+ return 0;
+ // two Ditto can't breed
+ if (eggGroups[0][0] == EGG_GROUP_DITTO && eggGroups[1][0] == EGG_GROUP_DITTO)
+ return 0;
+
+ // now that we checked, one ditto can breed with any other mon
+ if (eggGroups[0][0] == EGG_GROUP_DITTO || eggGroups[1][0] == EGG_GROUP_DITTO)
+ {
+ if (trainerIds[0] == trainerIds[1]) // same trainer
+ return 20;
+
+ return 50; // different trainers, more chance of poke sex
+ }
+ else
+ {
+ if (genders[0] == genders[1]) // no homo
+ return 0;
+ if (genders[0] == MON_GENDERLESS || genders[1] == MON_GENDERLESS)
+ return 0;
+ if (!EggGroupsOverlap(eggGroups[0], eggGroups[1])) // not compatible with each other
+ return 0;
+
+ if (species[0] == species[1]) // same species
+ {
+ if (trainerIds[0] == trainerIds[1]) // same species and trainer
+ return 50;
+
+ return 70; // different trainers, same species
+ }
+ else
+ {
+ if (trainerIds[0] != trainerIds[1]) // different trainers, different species
+ return 50;
+
+ return 20; // different species, same trainer
+ }
+ }
+}
+
+static u8 GetDaycareCompatibilityScoreFromSave(void)
+{
+ return GetDaycareCompatibilityScore(&gSaveBlock1Ptr->daycare);
+}
+
+void SetDaycareCompatibilityString(void)
+{
+ u8 whichString;
+ u8 relationshipScore;
+
+ relationshipScore = GetDaycareCompatibilityScoreFromSave();
+ whichString = 0;
+ if (relationshipScore == 0)
+ whichString = 3;
+ if (relationshipScore == 20)
+ whichString = 2;
+ if (relationshipScore == 50)
+ whichString = 1;
+ if (relationshipScore == 70)
+ whichString = 0;
+
+ StringCopy(gStringVar4, sCompatibilityMessages[whichString]);
+}
+
+bool8 NameHasGenderSymbol(const u8 *name, u8 genderRatio)
+{
+ u8 i;
+ u8 symbolsCount[2]; // male, female
+ symbolsCount[0] = symbolsCount[1] = 0;
+
+ for (i = 0; name[i] != EOS; i++)
+ {
+ if (name[i] == CHAR_MALE)
+ symbolsCount[0]++;
+ if (name[i] == CHAR_FEMALE)
+ symbolsCount[1]++;
+ }
+
+ if (genderRatio == MON_MALE && symbolsCount[0] != 0 && symbolsCount[1] == 0)
+ return TRUE;
+ if (genderRatio == MON_FEMALE && symbolsCount[1] != 0 && symbolsCount[0] == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static u8 *AppendGenderSymbol(u8 *name, u8 gender)
+{
+ if (gender == MON_MALE)
+ {
+ if (!NameHasGenderSymbol(name, MON_MALE))
+ return StringAppend(name, gText_MaleSymbol4);
+ }
+ else if (gender == MON_FEMALE)
+ {
+ if (!NameHasGenderSymbol(name, MON_FEMALE))
+ return StringAppend(name, gText_FemaleSymbol4);
+ }
+
+ return StringAppend(name, gText_GenderlessSymbol);
+}
+
+static u8 *AppendMonGenderSymbol(u8 *name, struct BoxPokemon *boxMon)
+{
+ return AppendGenderSymbol(name, GetBoxMonGender(boxMon));
+}
+
+static void GetDaycareLevelMenuText(struct DayCare *daycare, u8 *dest)
+{
+ u8 monNames[2][20];
+ u8 i;
+
+ *dest = EOS;
+ for (i = 0; i < 2; i++)
+ {
+ GetBoxMonNick(&daycare->mons[i].mon, monNames[i]);
+ AppendMonGenderSymbol(monNames[i], &daycare->mons[i].mon);
+ }
+
+ StringCopy(dest, monNames[0]);
+ StringAppend(dest, sNewLineText);
+ StringAppend(dest, monNames[1]);
+ StringAppend(dest, sNewLineText);
+ StringAppend(dest, gOtherText_Exit);
+}
+
+static void GetDaycareLevelMenuLevelText(struct DayCare *daycare, u8 *dest)
+{
+ u8 i;
+ u8 level;
+ u8 text[20];
+
+ *dest = EOS;
+ for (i = 0; i < 2; i++)
+ {
+ StringAppend(dest, gText_Lv);
+ level = GetLevelAfterDaycareSteps(&daycare->mons[i].mon, daycare->mons[i].steps);
+ ConvertIntToDecimalStringN(text, level, STR_CONV_MODE_LEFT_ALIGN, 3);
+ StringAppend(dest, text);
+ StringAppend(dest, sNewLineText);
+ }
+}
+
+static void DaycareAddTextPrinter(u8 windowId, const u8 *text, u32 x, u32 y)
+{
+ struct TextPrinterTemplate printer;
+
+ printer.currentChar = text;
+ printer.windowId = windowId;
+ printer.fontId = 3;
+ printer.x = x;
+ printer.y = y;
+ printer.currentX = x;
+ printer.currentY = y;
+ printer.unk = 0;
+ gTextFlags.useAlternateDownArrow = 0;
+ printer.letterSpacing = 1;
+ printer.lineSpacing = 1;
+ printer.fgColor = 2;
+ printer.bgColor = 1;
+ printer.shadowColor = 3;
+
+ AddTextPrinter(&printer, 0xFF, NULL);
+}
+
+static void DaycarePrintMonNick(struct DayCare *daycare, u8 windowId, u32 daycareSlotId, u32 y)
+{
+ u8 nick[POKEMON_NAME_LENGTH * 2];
+
+ GetBoxMonNick(&daycare->mons[daycareSlotId].mon, nick);
+ AppendMonGenderSymbol(nick, &daycare->mons[daycareSlotId].mon);
+ DaycareAddTextPrinter(windowId, nick, 8, y);
+}
+
+static void DaycarePrintMonLvl(struct DayCare *daycare, u8 windowId, u32 daycareSlotId, u32 y)
+{
+ u8 level;
+ u32 x;
+ u8 lvlText[12];
+ u8 intText[8];
+
+ strcpy((char *)lvlText, (const char *)gText_Lv);
+ level = GetLevelAfterDaycareSteps(&daycare->mons[daycareSlotId].mon, daycare->mons[daycareSlotId].steps);
+ ConvertIntToDecimalStringN(intText, level, STR_CONV_MODE_LEFT_ALIGN, 3);
+ StringAppend(lvlText, intText);
+ x = 132 - GetStringWidth(3, lvlText, 0);
+ DaycareAddTextPrinter(windowId, lvlText, x, y);
+}
+
+static void DaycarePrintMonInfo(u8 windowId, s32 daycareSlotId, u8 y)
+{
+ if (daycareSlotId < (unsigned) DAYCARE_MON_COUNT)
+ {
+ DaycarePrintMonNick(&gSaveBlock1Ptr->daycare, windowId, daycareSlotId, y);
+ DaycarePrintMonLvl(&gSaveBlock1Ptr->daycare, windowId, daycareSlotId, y);
+ }
+}
+
+#define tMenuListTaskId data[0]
+#define tWindowId data[1]
+
+static void Task_HandleDaycareLevelMenuInput(u8 taskId)
+{
+ u32 input = ListMenuHandleInput(gTasks[taskId].tMenuListTaskId);
+
+ if (gMain.newKeys & A_BUTTON)
+ {
+ switch (input)
+ {
+ case 0:
+ case 1:
+ gSpecialVar_Result = input;
+ break;
+ case 5:
+ gSpecialVar_Result = 2;
+ break;
+ }
+ DestroyListMenu(gTasks[taskId].tMenuListTaskId, NULL, NULL);
+ ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE);
+ RemoveWindow(gTasks[taskId].tWindowId);
+ DestroyTask(taskId);
+ EnableBothScriptContexts();
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ gSpecialVar_Result = 2;
+ DestroyListMenu(gTasks[taskId].tMenuListTaskId, NULL, NULL);
+ ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE);
+ RemoveWindow(gTasks[taskId].tWindowId);
+ DestroyTask(taskId);
+ EnableBothScriptContexts();
+ }
+}
+
+void ShowDaycareLevelMenu(void)
+{
+ struct ListMenuTemplate menuTemplate;
+ u8 windowId;
+ u8 listMenuTaskId;
+ u8 daycareMenuTaskId;
+
+ windowId = AddWindow(&sDaycareLevelMenuWindowTemplate);
+ DrawStdWindowFrame(windowId, FALSE);
+
+ menuTemplate = sDaycareListMenuLevelTemplate;
+ menuTemplate.windowId = windowId;
+ listMenuTaskId = ListMenuInit(&menuTemplate, 0, 0);
+
+ CopyWindowToVram(windowId, 3);
+
+ daycareMenuTaskId = CreateTask(Task_HandleDaycareLevelMenuInput, 3);
+ gTasks[daycareMenuTaskId].tMenuListTaskId = listMenuTaskId;
+ gTasks[daycareMenuTaskId].tWindowId = windowId;
+}
+
+#undef tMenuListTaskId
+#undef tWindowId
+
+void ChooseSendDaycareMon(void)
+{
+ sub_8128370();
+ gMain.savedCallback = CB2_ReturnToField;
+}
+
+// Route 5 Daycare
+
+void PutMonInRoute5Daycare(void)
+{
+ u8 monIdx = GetCursorSelectionMonId();
+ StorePokemonInDaycare(&gPlayerParty[monIdx], &gSaveBlock1Ptr->route5DayCareMon);
+}
+
+void GetCostToWithdrawRoute5DaycareMon(void)
+{
+ u16 cost = GetDaycareCostForSelectedMon(&gSaveBlock1Ptr->route5DayCareMon);
+ gSpecialVar_0x8005 = cost;
+}
+
+bool8 IsThereMonInRoute5Daycare(void)
+{
+ if (GetBoxMonData(&gSaveBlock1Ptr->route5DayCareMon.mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ return TRUE;
+
+ return FALSE;
+}
+
+u8 GetNumLevelsGainedForRoute5DaycareMon(void)
+{
+ return GetNumLevelsGainedForDaycareMon(&gSaveBlock1Ptr->route5DayCareMon);
+}
+
+u16 TakePokemonFromRoute5Daycare(void)
+{
+ return TakeSelectedPokemonFromDaycare(&gSaveBlock1Ptr->route5DayCareMon);
+}
+
+static void CreatedHatchedMon(struct Pokemon *egg, struct Pokemon *temp)
+{
+ u16 species;
+ u32 personality, pokerus;
+ u8 i, friendship, language, gameMet, markings, obedience;
+ u16 moves[4];
+ u32 ivs[NUM_STATS];
+
+
+ species = GetMonData(egg, MON_DATA_SPECIES);
+
+ for (i = 0; i < 4; i++)
+ {
+ moves[i] = GetMonData(egg, MON_DATA_MOVE1 + i);
+ }
+
+ personality = GetMonData(egg, MON_DATA_PERSONALITY);
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ ivs[i] = GetMonData(egg, MON_DATA_HP_IV + i);
+ }
+
+// language = GetMonData(egg, MON_DATA_LANGUAGE);
+ gameMet = GetMonData(egg, MON_DATA_MET_GAME);
+ markings = GetMonData(egg, MON_DATA_MARKINGS);
+ pokerus = GetMonData(egg, MON_DATA_POKERUS);
+ obedience = GetMonData(egg, MON_DATA_OBEDIENCE);
+
+ CreateMon(temp, species, EGG_HATCH_LEVEL, 32, TRUE, personality, 0, 0);
+
+ for (i = 0; i < 4; i++)
+ {
+ SetMonData(temp, MON_DATA_MOVE1 + i, &moves[i]);
+ }
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ SetMonData(temp, MON_DATA_HP_IV + i, &ivs[i]);
+ }
+
+ language = GAME_LANGUAGE;
+ SetMonData(temp, MON_DATA_LANGUAGE, &language);
+ SetMonData(temp, MON_DATA_MET_GAME, &gameMet);
+ SetMonData(temp, MON_DATA_MARKINGS, &markings);
+
+ friendship = 120;
+ SetMonData(temp, MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(temp, MON_DATA_POKERUS, &pokerus);
+ SetMonData(temp, MON_DATA_OBEDIENCE, &obedience);
+
+ *egg = *temp;
+}
+
+static void AddHatchedMonToParty(u8 id)
+{
+ u8 isEgg = 0x46; // ?
+ u16 pokeNum;
+ u8 name[12];
+ u16 ball;
+ u16 caughtLvl;
+ u8 mapNameID;
+ struct Pokemon* mon = &gPlayerParty[id];
+
+ CreatedHatchedMon(mon, &gEnemyParty[0]);
+ SetMonData(mon, MON_DATA_IS_EGG, &isEgg);
+
+ pokeNum = GetMonData(mon, MON_DATA_SPECIES);
+ GetSpeciesName(name, pokeNum);
+ SetMonData(mon, MON_DATA_NICKNAME, name);
+
+ pokeNum = SpeciesToNationalPokedexNum(pokeNum);
+ GetSetPokedexFlag(pokeNum, FLAG_SET_SEEN);
+ GetSetPokedexFlag(pokeNum, FLAG_SET_CAUGHT);
+
+ GetMonNick(mon, gStringVar1);
+
+ ball = ITEM_POKE_BALL;
+ SetMonData(mon, MON_DATA_POKEBALL, &ball);
+
+ caughtLvl = 0;
+ SetMonData(mon, MON_DATA_MET_LEVEL, &caughtLvl);
+
+ mapNameID = GetCurrentRegionMapSectionId();
+ SetMonData(mon, MON_DATA_MET_LOCATION, &mapNameID);
+
+ MonRestorePP(mon);
+ CalculateMonStats(mon);
+}
+
+void ScriptHatchMon(void)
+{
+ AddHatchedMonToParty(gSpecialVar_0x8004);
+}
+
+static bool8 sub_8046E34(struct DayCare *daycare, u8 daycareId)
+{
+ u8 nick[0x20];
+ struct DaycareMon *daycareMon = &daycare->mons[daycareId];
+
+ GetBoxMonNick(&daycareMon->mon, nick);
+ if (daycareMon->mail.message.itemId != 0
+ && (StringCompare(nick, daycareMon->mail.monName) != 0
+ || StringCompare(gSaveBlock2Ptr->playerName, daycareMon->mail.OT_name) != 0))
+ {
+ StringCopy(gStringVar1, nick);
+ StringCopy(gStringVar2, daycareMon->mail.OT_name);
+ StringCopy(gStringVar3, daycareMon->mail.monName);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8046EAC(void)
+{
+ return sub_8046E34(&gSaveBlock1Ptr->daycare, gSpecialVar_0x8004);
+}
+
+extern const struct CompressedSpriteSheet gMonFrontPicTable[];
+
+static u8 EggHatchCreateMonSprite(u8 a0, u8 switchID, u8 pokeID, u16* speciesLoc)
+{
+ u8 r4 = 0;
+ u8 spriteID = 0; // r7
+ struct Pokemon* mon = NULL; // r5
+
+ if (a0 == 0)
+ {
+ mon = &gPlayerParty[pokeID];
+ r4 = 1;
+ }
+ if (a0 == 1)
+ {
+ mon = &gPlayerParty[pokeID];
+ r4 = 3;
+ }
+ switch (switchID)
+ {
+ case 0:
+ {
+ u16 species = GetMonData(mon, MON_DATA_SPECIES);
+ u32 pid = GetMonData(mon, MON_DATA_PERSONALITY);
+ sub_800ECC4(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites[(a0 * 2) + 1], species, pid);
+ LoadCompressedObjectPalette(GetMonSpritePalStruct(mon));
+ *speciesLoc = species;
+ }
+ break;
+ case 1:
+ SetMultiuseSpriteTemplateToPokemon(GetMonSpritePalStruct(mon)->tag, r4);
+ spriteID = CreateSprite(&gMultiuseSpriteTemplate, 120, 70, 6);
+ gSprites[spriteID].invisible = TRUE;
+ gSprites[spriteID].callback = SpriteCallbackDummy;
+ break;
+ }
+ return spriteID;
+}
+
+static void VBlankCB_EggHatch(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+void EggHatch(void)
+{
+ ScriptContext2_Enable();
+ CreateTask(Task_EggHatch, 10);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+ sub_812B478();
+}
+
+static void Task_EggHatch(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ CleanupOverworldWindowsAndTilemaps();
+ SetMainCallback2(CB2_EggHatch_0);
+ gFieldCallback = FieldCallback_ReturnToEventScript2;
+ DestroyTask(taskID);
+ }
+}
+
+static void CB2_EggHatch_0(void)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+
+ sEggHatchData = Alloc(sizeof(struct EggHatchData));
+ AllocateMonSpritesGfx();
+ sEggHatchData->eggPartyID = gSpecialVar_0x8004;
+ sEggHatchData->eggShardVelocityID = 0;
+
+ SetVBlankCallback(VBlankCB_EggHatch);
+ gSpecialVar_0x8005 = GetCurrentMapMusic();
+
+ reset_temp_tile_data_buffers();
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, sBgTemplates_EggHatch, ARRAY_COUNT(sBgTemplates_EggHatch));
+
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+
+ SetBgAttribute(1, 7, 2);
+ SetBgTilemapBuffer(1, Alloc(0x1000));
+ SetBgTilemapBuffer(0, Alloc(0x2000));
+
+ DeactivateAllTextPrinters();
+ ResetPaletteFade();
+ FreeAllSpritePalettes();
+ ResetSpriteData();
+ ResetTasks();
+ ScanlineEffect_Stop();
+ m4aSoundVSyncOn();
+ gMain.state++;
+ break;
+ case 1:
+ InitWindows(sWinTemplates_EggHatch);
+ sEggHatchData->windowId = 0;
+ gMain.state++;
+ break;
+ case 2:
+ DecompressAndLoadBgGfxUsingHeap(0, gBattleTextboxTiles, 0, 0, 0);
+ CopyToBgTilemapBuffer(0, gFile_graphics_interface_menu_map_tilemap, 0, 0);
+ LoadCompressedPalette(gBattleTextboxPalette, 0, 0x20);
+ gMain.state++;
+ break;
+ case 3:
+ LoadSpriteSheet(&sEggHatch_Sheet);
+ LoadSpriteSheet(&sEggShards_Sheet);
+ LoadSpritePalette(&sEgg_SpritePalette);
+ gMain.state++;
+ break;
+ case 4:
+ CopyBgTilemapBufferToVram(0);
+ AddHatchedMonToParty(sEggHatchData->eggPartyID);
+ gMain.state++;
+ break;
+ case 5:
+ EggHatchCreateMonSprite(0, 0, sEggHatchData->eggPartyID, &sEggHatchData->species);
+ gMain.state++;
+ break;
+ case 6:
+ sEggHatchData->pokeSpriteID = EggHatchCreateMonSprite(0, 1, sEggHatchData->eggPartyID, &sEggHatchData->species);
+ gMain.state++;
+ break;
+ case 7:
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
+ LoadPalette(gTradeGba2_Pal, 0x10, 0xA0);
+ LoadBgTiles(1, gTradeGba_Gfx, 0x1420, 0);
+ CopyToBgTilemapBuffer(1, gUnknown_08331F60, 0x1000, 0);
+ CopyBgTilemapBufferToVram(1);
+ gMain.state++;
+ break;
+ case 8:
+ SetMainCallback2(CB2_EggHatch_1);
+ sEggHatchData->CB2_state = 0;
+ break;
+ }
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void EggHatchSetMonNickname(void)
+{
+ SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar3);
+ FreeMonSpritesGfx();
+ Free(sEggHatchData);
+ sub_812B484();
+ SetMainCallback2(CB2_ReturnToField);
+}
+
+static void Task_EggHatchPlayBGM(u8 taskID)
+{
+ if (gTasks[taskID].data[0] == 0)
+ {
+ StopMapMusic();
+ }
+ if (gTasks[taskID].data[0] == 1)
+ PlayBGM(MUS_ME_SHINKA);
+ if (gTasks[taskID].data[0] > 60)
+ {
+ PlayBGM(MUS_SHINKA);
+ DestroyTask(taskID);
+ // UB: task is destroyed, yet the value is incremented
+ }
+ gTasks[taskID].data[0]++;
+}
+
+static void CB2_EggHatch_1(void)
+{
+ u16 species;
+ u8 gender;
+ u32 personality;
+
+ switch (sEggHatchData->CB2_state)
+ {
+ case 0:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, RGB_BLACK);
+ sEggHatchData->eggSpriteID = CreateSprite(&sSpriteTemplate_EggHatch, 120, 75, 5);
+ ShowBg(0);
+ ShowBg(1);
+ sEggHatchData->CB2_state++;
+ CreateTask(Task_EggHatchPlayBGM, 5);
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ {
+ FillWindowPixelBuffer(sEggHatchData->windowId, 0x00);
+ sEggHatchData->CB2_PalCounter = 0;
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 2:
+ if (++sEggHatchData->CB2_PalCounter > 30)
+ {
+ sEggHatchData->CB2_state++;
+ gSprites[sEggHatchData->eggSpriteID].callback = SpriteCB_Egg_0;
+ }
+ break;
+ case 3:
+ if (gSprites[sEggHatchData->eggSpriteID].callback == SpriteCallbackDummy)
+ {
+ PlayCry1(sEggHatchData->species, 0);
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 4:
+ if (IsCryFinished())
+ {
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 5:
+ GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_HatchedFromEgg);
+ EggHatchPrintMessage(sEggHatchData->windowId, gStringVar4, 0, 3, 0xFF);
+ PlayFanfare(MUS_FANFA5);
+ sEggHatchData->CB2_state++;
+ PutWindowTilemap(sEggHatchData->windowId);
+ CopyWindowToVram(sEggHatchData->windowId, 3);
+ break;
+ case 6:
+ if (IsFanfareTaskInactive())
+ sEggHatchData->CB2_state++;
+ break;
+ case 7:
+ if (IsFanfareTaskInactive())
+ sEggHatchData->CB2_state++;
+ break;
+ case 8:
+ GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_NickHatchPrompt);
+ EggHatchPrintMessage(sEggHatchData->windowId, gStringVar4, 0, 2, 1);
+ sEggHatchData->CB2_state++;
+ break;
+ case 9:
+ if (!IsTextPrinterActive(sEggHatchData->windowId))
+ {
+ LoadUserWindowBorderGfx(sEggHatchData->windowId, 0x140, 0xE0);
+ CreateYesNoMenu(&sYesNoWinTemplate, 3, 0, 2, 0x140, 0xE, 0);
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 10:
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0:
+ GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar3);
+ species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
+ gender = GetMonGender(&gPlayerParty[sEggHatchData->eggPartyID]);
+ personality = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_PERSONALITY, 0);
+ DoNamingScreen(3, gStringVar3, species, gender, personality, EggHatchSetMonNickname);
+ break;
+ case 1:
+ case -1:
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 11:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
+ sEggHatchData->CB2_state++;
+ break;
+ case 12:
+ if (!gPaletteFade.active)
+ {
+ RemoveWindow(sEggHatchData->windowId);
+ UnsetBgTilemapBuffer(0);
+ UnsetBgTilemapBuffer(1);
+ Free(sEggHatchData);
+ SetMainCallback2(CB2_ReturnToField);
+ sub_812B484();
+ }
+ break;
+ }
+
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void SpriteCB_Egg_0(struct Sprite* sprite)
+{
+ if (++sprite->data[0] > 20)
+ {
+ sprite->callback = SpriteCB_Egg_1;
+ sprite->data[0] = 0;
+ }
+ else
+ {
+ sprite->data[1] = (sprite->data[1] + 20) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data[1], 1);
+ if (sprite->data[0] == 15)
+ {
+ PlaySE(SE_BOWA);
+ StartSpriteAnim(sprite, 1);
+ CreateRandomEggShardSprite();
+ }
+ }
+}
+
+static void SpriteCB_Egg_1(struct Sprite* sprite)
+{
+ if (++sprite->data[2] > 30)
+ {
+ if (++sprite->data[0] > 20)
+ {
+ sprite->callback = SpriteCB_Egg_2;
+ sprite->data[0] = 0;
+ sprite->data[2] = 0;
+ }
+ else
+ {
+ sprite->data[1] = (sprite->data[1] + 20) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data[1], 2);
+ if (sprite->data[0] == 15)
+ {
+ PlaySE(SE_BOWA);
+ StartSpriteAnim(sprite, 2);
+ }
+ }
+ }
+}
+
+struct UnkStruct_82349CC
+{
+ u8 field_0;
+ u8 field_1;
+ u8 field_2;
+ u8 field_3;
+};
+
+extern const struct UnkStruct_82349CC gUnknown_82349CC[NUM_SPECIES];
+
+static void SpriteCB_Egg_2(struct Sprite* sprite)
+{
+ if (++sprite->data[2] > 30)
+ {
+ if (++sprite->data[0] > 38)
+ {
+ u16 species;
+
+ sprite->callback = SpriteCB_Egg_3;
+ sprite->data[0] = 0;
+ species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
+ gSprites[sEggHatchData->pokeSpriteID].pos2.x = 0;
+ gSprites[sEggHatchData->pokeSpriteID].pos2.y = gUnknown_82349CC[species].field_1;
+ }
+ else
+ {
+ sprite->data[1] = (sprite->data[1] + 20) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data[1], 2);
+ if (sprite->data[0] == 15)
+ {
+ PlaySE(SE_BOWA);
+ StartSpriteAnim(sprite, 2);
+ CreateRandomEggShardSprite();
+ CreateRandomEggShardSprite();
+ }
+ if (sprite->data[0] == 30)
+ PlaySE(SE_BOWA);
+ }
+ }
+}
+
+static void SpriteCB_Egg_3(struct Sprite* sprite)
+{
+ if (++sprite->data[0] > 50)
+ {
+ sprite->callback = SpriteCB_Egg_4;
+ sprite->data[0] = 0;
+ }
+}
+
+static void SpriteCB_Egg_4(struct Sprite* sprite)
+{
+ s16 i;
+ if (sprite->data[0] == 0)
+ BeginNormalPaletteFade(0xFFFFFFFF, -1, 0, 0x10, 0xFFFF);
+ if (sprite->data[0] < 4u)
+ {
+ for (i = 0; i <= 3; i++)
+ CreateRandomEggShardSprite();
+ }
+ sprite->data[0]++;
+ if (!gPaletteFade.active)
+ {
+ PlaySE(SE_JIHANKI);
+ sprite->invisible = TRUE;
+ sprite->callback = SpriteCB_Egg_5;
+ sprite->data[0] = 0;
+ }
+}
+
+static void SpriteCB_Egg_5(struct Sprite* sprite)
+{
+ if (sprite->data[0] == 0)
+ {
+ gSprites[sEggHatchData->pokeSpriteID].invisible = FALSE;
+ StartSpriteAffineAnim(&gSprites[sEggHatchData->pokeSpriteID], 1);
+ }
+ if (sprite->data[0] == 8)
+ BeginNormalPaletteFade(0xFFFFFFFF, -1, 0x10, 0, 0xFFFF);
+ if (sprite->data[0] <= 9)
+ gSprites[sEggHatchData->pokeSpriteID].pos1.y -= 1;
+ if (sprite->data[0] > 40)
+ sprite->callback = SpriteCallbackDummy;
+ sprite->data[0]++;
+}
+
+static void SpriteCB_EggShard(struct Sprite* sprite)
+{
+ sprite->data[4] += sprite->data[1];
+ sprite->data[5] += sprite->data[2];
+
+ sprite->pos2.x = sprite->data[4] / 256;
+ sprite->pos2.y = sprite->data[5] / 256;
+
+ sprite->data[2] += sprite->data[3];
+
+ if (sprite->pos1.y + sprite->pos2.y > sprite->pos1.y + 20 && sprite->data[2] > 0)
+ DestroySprite(sprite);
+}
+
+static void CreateRandomEggShardSprite(void)
+{
+ u16 spriteAnimIndex;
+
+ s16 velocity1 = sEggShardVelocities[sEggHatchData->eggShardVelocityID][0];
+ s16 velocity2 = sEggShardVelocities[sEggHatchData->eggShardVelocityID][1];
+ sEggHatchData->eggShardVelocityID++;
+ spriteAnimIndex = Random() % 4;
+ CreateEggShardSprite(120, 60, velocity1, velocity2, 100, spriteAnimIndex);
+}
+
+static void CreateEggShardSprite(u8 x, u8 y, s16 data1, s16 data2, s16 data3, u8 spriteAnimIndex)
+{
+ u8 spriteID = CreateSprite(&sSpriteTemplate_EggShard, x, y, 4);
+ gSprites[spriteID].data[1] = data1;
+ gSprites[spriteID].data[2] = data2;
+ gSprites[spriteID].data[3] = data3;
+ StartSpriteAnim(&gSprites[spriteID], spriteAnimIndex);
+}
+
+static void EggHatchPrintMessage(u8 windowId, u8* string, u8 x, u8 y, u8 speed)
+{
+ FillWindowPixelBuffer(windowId, 0xFF);
+ sEggHatchData->textColor.fgColor = 0;
+ sEggHatchData->textColor.bgColor = 5;
+ sEggHatchData->textColor.shadowColor = 6;
+ AddTextPrinterParameterized4(windowId, 3, x, y, 1, 1, &sEggHatchData->textColor, speed, string);
+}
diff --git a/src/dodrio_berry_picking_2.c b/src/dodrio_berry_picking_2.c
new file mode 100644
index 000000000..fc6aa14c6
--- /dev/null
+++ b/src/dodrio_berry_picking_2.c
@@ -0,0 +1,23 @@
+#include "global.h"
+#include "link.h"
+#include "link_rfu.h"
+
+void sub_815A5BC(s32 a0)
+{
+ struct Padded_U8 data[2];
+ data[0].value = 1;
+ data[1].value = a0;
+ sub_80F9E2C(data);
+}
+
+u8 sub_815A5E8(s32 a0)
+{
+ u8 * r1;
+ if ((gRecvCmds[0][0] & 0xFF00) != 0x2F00)
+ return 0;
+ r1 = (u8 *)&gRecvCmds[a0][1];
+ if (r1[0] == 1)
+ return r1[4];
+ return 0;
+}
+
diff --git a/src/egg_hatch.c b/src/egg_hatch.c
new file mode 100644
index 000000000..5e27a6482
--- /dev/null
+++ b/src/egg_hatch.c
@@ -0,0 +1,878 @@
+#include "global.h"
+#include "pokemon.h"
+#include "egg_hatch.h"
+#include "pokedex.h"
+#include "constants/items.h"
+#include "script.h"
+#include "decompress.h"
+#include "task.h"
+#include "palette.h"
+#include "main.h"
+#include "event_data.h"
+#include "sound.h"
+#include "constants/songs.h"
+#include "text.h"
+#include "text_window.h"
+#include "string_util.h"
+#include "menu.h"
+#include "trig.h"
+#include "random.h"
+#include "malloc.h"
+#include "dma3.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "m4a.h"
+#include "window.h"
+#include "graphics.h"
+#include "constants/abilities.h"
+#include "constants/species.h"
+#include "daycare.h"
+#include "overworld.h"
+#include "scanline_effect.h"
+#include "field_weather.h"
+#include "international_string_util.h"
+#include "naming_screen.h"
+#include "pokemon_storage_system.h"
+#include "field_screen_effect.h"
+#include "battle.h" // to get rid of later
+#include "help_system.h"
+#include "field_fadetransition.h"
+#include "new_menu_helpers.h"
+
+struct EggHatchData
+{
+ u8 eggSpriteID;
+ u8 pokeSpriteID;
+ u8 CB2_state;
+ u8 CB2_PalCounter;
+ u8 eggPartyID;
+ u8 unused_5;
+ u8 unused_6;
+ u8 eggShardVelocityID;
+ u8 windowId;
+ u8 unused_9;
+ u8 unused_A;
+ u16 species;
+ struct TextColor textColor;
+};
+
+extern const u32 gUnknown_08331F60[]; // tilemap gameboy circle
+extern const u8 gText_HatchedFromEgg[];
+extern const u8 gText_NickHatchPrompt[];
+
+static void Task_EggHatch(u8 taskID);
+static void CB2_EggHatch_0(void);
+static void CB2_EggHatch_1(void);
+static void SpriteCB_Egg_0(struct Sprite* sprite);
+static void SpriteCB_Egg_1(struct Sprite* sprite);
+static void SpriteCB_Egg_2(struct Sprite* sprite);
+static void SpriteCB_Egg_3(struct Sprite* sprite);
+static void SpriteCB_Egg_4(struct Sprite* sprite);
+static void SpriteCB_Egg_5(struct Sprite* sprite);
+static void SpriteCB_EggShard(struct Sprite* sprite);
+static void EggHatchPrintMessage(u8 windowId, u8* string, u8 x, u8 y, u8 speed);
+static void CreateRandomEggShardSprite(void);
+static void CreateEggShardSprite(u8 x, u8 y, s16 data1, s16 data2, s16 data3, u8 spriteAnimIndex);
+
+// IWRAM bss
+static IWRAM_DATA struct EggHatchData *sEggHatchData;
+
+// rom data
+static const u16 sEggPalette[] = INCBIN_U16("graphics/pokemon/egg/normal.gbapal");
+static const u8 sEggHatchTiles[] = INCBIN_U8("graphics/misc/egg_hatch.4bpp");
+static const u8 sEggShardTiles[] = INCBIN_U8("graphics/misc/egg_shard.4bpp");
+
+static const struct OamData sOamData_EggHatch =
+ {
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = SPRITE_SHAPE(32x32),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(32x32),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+ };
+
+static const union AnimCmd sSpriteAnim_EggHatch0[] =
+ {
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggHatch1[] =
+ {
+ ANIMCMD_FRAME(16, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggHatch2[] =
+ {
+ ANIMCMD_FRAME(32, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggHatch3[] =
+ {
+ ANIMCMD_FRAME(48, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd *const sSpriteAnimTable_EggHatch[] =
+ {
+ sSpriteAnim_EggHatch0,
+ sSpriteAnim_EggHatch1,
+ sSpriteAnim_EggHatch2,
+ sSpriteAnim_EggHatch3,
+ };
+
+static const struct SpriteSheet sEggHatch_Sheet =
+ {
+ .data = sEggHatchTiles,
+ .size = 2048,
+ .tag = 12345,
+ };
+
+static const struct SpriteSheet sEggShards_Sheet =
+ {
+ .data = sEggShardTiles,
+ .size = 128,
+ .tag = 23456,
+ };
+
+static const struct SpritePalette sEgg_SpritePalette =
+ {
+ .data = sEggPalette,
+ .tag = 54321
+ };
+
+static const struct SpriteTemplate sSpriteTemplate_EggHatch =
+ {
+ .tileTag = 12345,
+ .paletteTag = 54321,
+ .oam = &sOamData_EggHatch,
+ .anims = sSpriteAnimTable_EggHatch,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+ };
+
+static const struct OamData sOamData_EggShard =
+ {
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = SPRITE_SHAPE(8x8),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(8x8),
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 0,
+ .affineParam = 0,
+ };
+
+static const union AnimCmd sSpriteAnim_EggShard0[] =
+ {
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggShard1[] =
+ {
+ ANIMCMD_FRAME(1, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggShard2[] =
+ {
+ ANIMCMD_FRAME(2, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd sSpriteAnim_EggShard3[] =
+ {
+ ANIMCMD_FRAME(3, 5),
+ ANIMCMD_END
+ };
+
+static const union AnimCmd *const sSpriteAnimTable_EggShard[] =
+ {
+ sSpriteAnim_EggShard0,
+ sSpriteAnim_EggShard1,
+ sSpriteAnim_EggShard2,
+ sSpriteAnim_EggShard3,
+ };
+
+static const struct SpriteTemplate sSpriteTemplate_EggShard =
+ {
+ .tileTag = 23456,
+ .paletteTag = 54321,
+ .oam = &sOamData_EggShard,
+ .anims = sSpriteAnimTable_EggShard,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_EggShard
+ };
+
+static const struct BgTemplate sBgTemplates_EggHatch[2] =
+ {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 24,
+ .screenSize = 3,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0
+ },
+
+ {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 8,
+ .screenSize = 1,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0
+ },
+ };
+
+static const struct WindowTemplate sWinTemplates_EggHatch[2] =
+ {
+ {
+ .bg = 0,
+ .tilemapLeft = 2,
+ .tilemapTop = 15,
+ .width = 26,
+ .height = 4,
+ .paletteNum = 0,
+ .baseBlock = 64
+ },
+ DUMMY_WIN_TEMPLATE
+ };
+
+static const struct WindowTemplate sYesNoWinTemplate =
+ {
+ .bg = 0,
+ .tilemapLeft = 21,
+ .tilemapTop = 9,
+ .width = 5,
+ .height = 4,
+ .paletteNum = 15,
+ .baseBlock = 424
+ };
+
+static const s16 sEggShardVelocities[][2] =
+ {
+ {Q_8_8(-1.5), Q_8_8(-3.75)},
+ {Q_8_8(-5), Q_8_8(-3)},
+ {Q_8_8(3.5), Q_8_8(-3)},
+ {Q_8_8(-4), Q_8_8(-3.75)},
+ {Q_8_8(2), Q_8_8(-1.5)},
+ {Q_8_8(-0.5), Q_8_8(-6.75)},
+ {Q_8_8(5), Q_8_8(-2.25)},
+ {Q_8_8(-1.5), Q_8_8(-3.75)},
+ {Q_8_8(4.5), Q_8_8(-1.5)},
+ {Q_8_8(-1), Q_8_8(-6.75)},
+ {Q_8_8(4), Q_8_8(-2.25)},
+ {Q_8_8(-3.5), Q_8_8(-3.75)},
+ {Q_8_8(1), Q_8_8(-1.5)},
+ {Q_8_8(-3.515625), Q_8_8(-6.75)},
+ {Q_8_8(4.5), Q_8_8(-2.25)},
+ {Q_8_8(-0.5), Q_8_8(-7.5)},
+ {Q_8_8(1), Q_8_8(-4.5)},
+ {Q_8_8(-2.5), Q_8_8(-2.25)},
+ {Q_8_8(2.5), Q_8_8(-7.5)},
+ };
+
+// code
+
+static void CreatedHatchedMon(struct Pokemon *egg, struct Pokemon *temp)
+{
+ u16 species;
+ u32 personality, pokerus;
+ u8 i, friendship, language, gameMet, markings, obedience;
+ u16 moves[4];
+ u32 ivs[NUM_STATS];
+
+
+ species = GetMonData(egg, MON_DATA_SPECIES);
+
+ for (i = 0; i < 4; i++)
+ {
+ moves[i] = GetMonData(egg, MON_DATA_MOVE1 + i);
+ }
+
+ personality = GetMonData(egg, MON_DATA_PERSONALITY);
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ ivs[i] = GetMonData(egg, MON_DATA_HP_IV + i);
+ }
+
+// language = GetMonData(egg, MON_DATA_LANGUAGE);
+ gameMet = GetMonData(egg, MON_DATA_MET_GAME);
+ markings = GetMonData(egg, MON_DATA_MARKINGS);
+ pokerus = GetMonData(egg, MON_DATA_POKERUS);
+ obedience = GetMonData(egg, MON_DATA_OBEDIENCE);
+
+ CreateMon(temp, species, EGG_HATCH_LEVEL, 32, TRUE, personality, 0, 0);
+
+ for (i = 0; i < 4; i++)
+ {
+ SetMonData(temp, MON_DATA_MOVE1 + i, &moves[i]);
+ }
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ SetMonData(temp, MON_DATA_HP_IV + i, &ivs[i]);
+ }
+
+ language = GAME_LANGUAGE;
+ SetMonData(temp, MON_DATA_LANGUAGE, &language);
+ SetMonData(temp, MON_DATA_MET_GAME, &gameMet);
+ SetMonData(temp, MON_DATA_MARKINGS, &markings);
+
+ friendship = 120;
+ SetMonData(temp, MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(temp, MON_DATA_POKERUS, &pokerus);
+ SetMonData(temp, MON_DATA_OBEDIENCE, &obedience);
+
+ *egg = *temp;
+}
+
+static void AddHatchedMonToParty(u8 id)
+{
+ u8 isEgg = 0x46; // ?
+ u16 pokeNum;
+ u8 name[12];
+ u16 ball;
+ u16 caughtLvl;
+ u8 mapNameID;
+ struct Pokemon* mon = &gPlayerParty[id];
+
+ CreatedHatchedMon(mon, &gEnemyParty[0]);
+ SetMonData(mon, MON_DATA_IS_EGG, &isEgg);
+
+ pokeNum = GetMonData(mon, MON_DATA_SPECIES);
+ GetSpeciesName(name, pokeNum);
+ SetMonData(mon, MON_DATA_NICKNAME, name);
+
+ pokeNum = SpeciesToNationalPokedexNum(pokeNum);
+ GetSetPokedexFlag(pokeNum, FLAG_SET_SEEN);
+ GetSetPokedexFlag(pokeNum, FLAG_SET_CAUGHT);
+
+ GetMonNick(mon, gStringVar1);
+
+ ball = ITEM_POKE_BALL;
+ SetMonData(mon, MON_DATA_POKEBALL, &ball);
+
+ caughtLvl = 0;
+ SetMonData(mon, MON_DATA_MET_LEVEL, &caughtLvl);
+
+ mapNameID = GetCurrentRegionMapSectionId();
+ SetMonData(mon, MON_DATA_MET_LOCATION, &mapNameID);
+
+ MonRestorePP(mon);
+ CalculateMonStats(mon);
+}
+
+void ScriptHatchMon(void)
+{
+ AddHatchedMonToParty(gSpecialVar_0x8004);
+}
+
+static bool8 sub_8046E34(struct DayCare *daycare, u8 daycareId)
+{
+ u8 nick[0x20];
+ struct DaycareMon *daycareMon = &daycare->mons[daycareId];
+
+ GetBoxMonNick(&daycareMon->mon, nick);
+ if (daycareMon->mail.message.itemId != 0
+ && (StringCompare(nick, daycareMon->mail.monName) != 0
+ || StringCompare(gSaveBlock2Ptr->playerName, daycareMon->mail.OT_name) != 0))
+ {
+ StringCopy(gStringVar1, nick);
+ StringCopy(gStringVar2, daycareMon->mail.OT_name);
+ StringCopy(gStringVar3, daycareMon->mail.monName);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8046EAC(void)
+{
+ return sub_8046E34(&gSaveBlock1Ptr->daycare, gSpecialVar_0x8004);
+}
+
+extern const struct CompressedSpriteSheet gMonFrontPicTable[];
+
+static u8 EggHatchCreateMonSprite(u8 a0, u8 switchID, u8 pokeID, u16* speciesLoc)
+{
+ u8 r4 = 0;
+ u8 spriteID = 0; // r7
+ struct Pokemon* mon = NULL; // r5
+
+ if (a0 == 0)
+ {
+ mon = &gPlayerParty[pokeID];
+ r4 = 1;
+ }
+ if (a0 == 1)
+ {
+ mon = &gPlayerParty[pokeID];
+ r4 = 3;
+ }
+ switch (switchID)
+ {
+ case 0:
+ {
+ u16 species = GetMonData(mon, MON_DATA_SPECIES);
+ u32 pid = GetMonData(mon, MON_DATA_PERSONALITY);
+ sub_800ECC4(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites[(a0 * 2) + 1], species, pid);
+ LoadCompressedObjectPalette(GetMonSpritePalStruct(mon));
+ *speciesLoc = species;
+ }
+ break;
+ case 1:
+ SetMultiuseSpriteTemplateToPokemon(GetMonSpritePalStruct(mon)->tag, r4);
+ spriteID = CreateSprite(&gMultiuseSpriteTemplate, 120, 70, 6);
+ gSprites[spriteID].invisible = TRUE;
+ gSprites[spriteID].callback = SpriteCallbackDummy;
+ break;
+ }
+ return spriteID;
+}
+
+static void VBlankCB_EggHatch(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+void EggHatch(void)
+{
+ ScriptContext2_Enable();
+ CreateTask(Task_EggHatch, 10);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+ sub_812B478();
+}
+
+static void Task_EggHatch(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ CleanupOverworldWindowsAndTilemaps();
+ SetMainCallback2(CB2_EggHatch_0);
+ gFieldCallback = FieldCallback_ReturnToEventScript2;
+ DestroyTask(taskID);
+ }
+}
+
+static void CB2_EggHatch_0(void)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+
+ sEggHatchData = Alloc(sizeof(struct EggHatchData));
+ AllocateMonSpritesGfx();
+ sEggHatchData->eggPartyID = gSpecialVar_0x8004;
+ sEggHatchData->eggShardVelocityID = 0;
+
+ SetVBlankCallback(VBlankCB_EggHatch);
+ gSpecialVar_0x8005 = GetCurrentMapMusic();
+
+ reset_temp_tile_data_buffers();
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, sBgTemplates_EggHatch, ARRAY_COUNT(sBgTemplates_EggHatch));
+
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+
+ SetBgAttribute(1, 7, 2);
+ SetBgTilemapBuffer(1, Alloc(0x1000));
+ SetBgTilemapBuffer(0, Alloc(0x2000));
+
+ DeactivateAllTextPrinters();
+ ResetPaletteFade();
+ FreeAllSpritePalettes();
+ ResetSpriteData();
+ ResetTasks();
+ ScanlineEffect_Stop();
+ m4aSoundVSyncOn();
+ gMain.state++;
+ break;
+ case 1:
+ InitWindows(sWinTemplates_EggHatch);
+ sEggHatchData->windowId = 0;
+ gMain.state++;
+ break;
+ case 2:
+ DecompressAndLoadBgGfxUsingHeap(0, gBattleTextboxTiles, 0, 0, 0);
+ CopyToBgTilemapBuffer(0, gFile_graphics_interface_menu_map_tilemap, 0, 0);
+ LoadCompressedPalette(gBattleTextboxPalette, 0, 0x20);
+ gMain.state++;
+ break;
+ case 3:
+ LoadSpriteSheet(&sEggHatch_Sheet);
+ LoadSpriteSheet(&sEggShards_Sheet);
+ LoadSpritePalette(&sEgg_SpritePalette);
+ gMain.state++;
+ break;
+ case 4:
+ CopyBgTilemapBufferToVram(0);
+ AddHatchedMonToParty(sEggHatchData->eggPartyID);
+ gMain.state++;
+ break;
+ case 5:
+ EggHatchCreateMonSprite(0, 0, sEggHatchData->eggPartyID, &sEggHatchData->species);
+ gMain.state++;
+ break;
+ case 6:
+ sEggHatchData->pokeSpriteID = EggHatchCreateMonSprite(0, 1, sEggHatchData->eggPartyID, &sEggHatchData->species);
+ gMain.state++;
+ break;
+ case 7:
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
+ LoadPalette(gTradeGba2_Pal, 0x10, 0xA0);
+ LoadBgTiles(1, gTradeGba_Gfx, 0x1420, 0);
+ CopyToBgTilemapBuffer(1, gUnknown_08331F60, 0x1000, 0);
+ CopyBgTilemapBufferToVram(1);
+ gMain.state++;
+ break;
+ case 8:
+ SetMainCallback2(CB2_EggHatch_1);
+ sEggHatchData->CB2_state = 0;
+ break;
+ }
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void EggHatchSetMonNickname(void)
+{
+ SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar3);
+ FreeMonSpritesGfx();
+ Free(sEggHatchData);
+ sub_812B484();
+ SetMainCallback2(CB2_ReturnToField);
+}
+
+static void Task_EggHatchPlayBGM(u8 taskID)
+{
+ if (gTasks[taskID].data[0] == 0)
+ {
+ StopMapMusic();
+ }
+ if (gTasks[taskID].data[0] == 1)
+ PlayBGM(MUS_ME_SHINKA);
+ if (gTasks[taskID].data[0] > 60)
+ {
+ PlayBGM(MUS_SHINKA);
+ DestroyTask(taskID);
+ // UB: task is destroyed, yet the value is incremented
+ }
+ gTasks[taskID].data[0]++;
+}
+
+static void CB2_EggHatch_1(void)
+{
+ u16 species;
+ u8 gender;
+ u32 personality;
+
+ switch (sEggHatchData->CB2_state)
+ {
+ case 0:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, RGB_BLACK);
+ sEggHatchData->eggSpriteID = CreateSprite(&sSpriteTemplate_EggHatch, 120, 75, 5);
+ ShowBg(0);
+ ShowBg(1);
+ sEggHatchData->CB2_state++;
+ CreateTask(Task_EggHatchPlayBGM, 5);
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ {
+ FillWindowPixelBuffer(sEggHatchData->windowId, 0x00);
+ sEggHatchData->CB2_PalCounter = 0;
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 2:
+ if (++sEggHatchData->CB2_PalCounter > 30)
+ {
+ sEggHatchData->CB2_state++;
+ gSprites[sEggHatchData->eggSpriteID].callback = SpriteCB_Egg_0;
+ }
+ break;
+ case 3:
+ if (gSprites[sEggHatchData->eggSpriteID].callback == SpriteCallbackDummy)
+ {
+ PlayCry1(sEggHatchData->species, 0);
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 4:
+ if (IsCryFinished())
+ {
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 5:
+ GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_HatchedFromEgg);
+ EggHatchPrintMessage(sEggHatchData->windowId, gStringVar4, 0, 3, 0xFF);
+ PlayFanfare(MUS_FANFA5);
+ sEggHatchData->CB2_state++;
+ PutWindowTilemap(sEggHatchData->windowId);
+ CopyWindowToVram(sEggHatchData->windowId, 3);
+ break;
+ case 6:
+ if (IsFanfareTaskInactive())
+ sEggHatchData->CB2_state++;
+ break;
+ case 7:
+ if (IsFanfareTaskInactive())
+ sEggHatchData->CB2_state++;
+ break;
+ case 8:
+ GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_NickHatchPrompt);
+ EggHatchPrintMessage(sEggHatchData->windowId, gStringVar4, 0, 2, 1);
+ sEggHatchData->CB2_state++;
+ break;
+ case 9:
+ if (!IsTextPrinterActive(sEggHatchData->windowId))
+ {
+ LoadUserWindowBorderGfx(sEggHatchData->windowId, 0x140, 0xE0);
+ CreateYesNoMenu(&sYesNoWinTemplate, 3, 0, 2, 0x140, 0xE, 0);
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 10:
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0:
+ GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar3);
+ species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
+ gender = GetMonGender(&gPlayerParty[sEggHatchData->eggPartyID]);
+ personality = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_PERSONALITY, 0);
+ DoNamingScreen(3, gStringVar3, species, gender, personality, EggHatchSetMonNickname);
+ break;
+ case 1:
+ case -1:
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 11:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
+ sEggHatchData->CB2_state++;
+ break;
+ case 12:
+ if (!gPaletteFade.active)
+ {
+ RemoveWindow(sEggHatchData->windowId);
+ UnsetBgTilemapBuffer(0);
+ UnsetBgTilemapBuffer(1);
+ Free(sEggHatchData);
+ SetMainCallback2(CB2_ReturnToField);
+ sub_812B484();
+ }
+ break;
+ }
+
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void SpriteCB_Egg_0(struct Sprite* sprite)
+{
+ if (++sprite->data[0] > 20)
+ {
+ sprite->callback = SpriteCB_Egg_1;
+ sprite->data[0] = 0;
+ }
+ else
+ {
+ sprite->data[1] = (sprite->data[1] + 20) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data[1], 1);
+ if (sprite->data[0] == 15)
+ {
+ PlaySE(SE_BOWA);
+ StartSpriteAnim(sprite, 1);
+ CreateRandomEggShardSprite();
+ }
+ }
+}
+
+static void SpriteCB_Egg_1(struct Sprite* sprite)
+{
+ if (++sprite->data[2] > 30)
+ {
+ if (++sprite->data[0] > 20)
+ {
+ sprite->callback = SpriteCB_Egg_2;
+ sprite->data[0] = 0;
+ sprite->data[2] = 0;
+ }
+ else
+ {
+ sprite->data[1] = (sprite->data[1] + 20) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data[1], 2);
+ if (sprite->data[0] == 15)
+ {
+ PlaySE(SE_BOWA);
+ StartSpriteAnim(sprite, 2);
+ }
+ }
+ }
+}
+
+struct UnkStruct_82349CC
+{
+ u8 field_0;
+ u8 field_1;
+ u8 field_2;
+ u8 field_3;
+};
+
+extern const struct UnkStruct_82349CC gUnknown_82349CC[NUM_SPECIES];
+
+static void SpriteCB_Egg_2(struct Sprite* sprite)
+{
+ if (++sprite->data[2] > 30)
+ {
+ if (++sprite->data[0] > 38)
+ {
+ u16 species;
+
+ sprite->callback = SpriteCB_Egg_3;
+ sprite->data[0] = 0;
+ species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
+ gSprites[sEggHatchData->pokeSpriteID].pos2.x = 0;
+ gSprites[sEggHatchData->pokeSpriteID].pos2.y = gUnknown_82349CC[species].field_1;
+ }
+ else
+ {
+ sprite->data[1] = (sprite->data[1] + 20) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data[1], 2);
+ if (sprite->data[0] == 15)
+ {
+ PlaySE(SE_BOWA);
+ StartSpriteAnim(sprite, 2);
+ CreateRandomEggShardSprite();
+ CreateRandomEggShardSprite();
+ }
+ if (sprite->data[0] == 30)
+ PlaySE(SE_BOWA);
+ }
+ }
+}
+
+static void SpriteCB_Egg_3(struct Sprite* sprite)
+{
+ if (++sprite->data[0] > 50)
+ {
+ sprite->callback = SpriteCB_Egg_4;
+ sprite->data[0] = 0;
+ }
+}
+
+static void SpriteCB_Egg_4(struct Sprite* sprite)
+{
+ s16 i;
+ if (sprite->data[0] == 0)
+ BeginNormalPaletteFade(0xFFFFFFFF, -1, 0, 0x10, 0xFFFF);
+ if (sprite->data[0] < 4u)
+ {
+ for (i = 0; i <= 3; i++)
+ CreateRandomEggShardSprite();
+ }
+ sprite->data[0]++;
+ if (!gPaletteFade.active)
+ {
+ PlaySE(SE_JIHANKI);
+ sprite->invisible = TRUE;
+ sprite->callback = SpriteCB_Egg_5;
+ sprite->data[0] = 0;
+ }
+}
+
+static void SpriteCB_Egg_5(struct Sprite* sprite)
+{
+ if (sprite->data[0] == 0)
+ {
+ gSprites[sEggHatchData->pokeSpriteID].invisible = FALSE;
+ StartSpriteAffineAnim(&gSprites[sEggHatchData->pokeSpriteID], 1);
+ }
+ if (sprite->data[0] == 8)
+ BeginNormalPaletteFade(0xFFFFFFFF, -1, 0x10, 0, 0xFFFF);
+ if (sprite->data[0] <= 9)
+ gSprites[sEggHatchData->pokeSpriteID].pos1.y -= 1;
+ if (sprite->data[0] > 40)
+ sprite->callback = SpriteCallbackDummy;
+ sprite->data[0]++;
+}
+
+static void SpriteCB_EggShard(struct Sprite* sprite)
+{
+ sprite->data[4] += sprite->data[1];
+ sprite->data[5] += sprite->data[2];
+
+ sprite->pos2.x = sprite->data[4] / 256;
+ sprite->pos2.y = sprite->data[5] / 256;
+
+ sprite->data[2] += sprite->data[3];
+
+ if (sprite->pos1.y + sprite->pos2.y > sprite->pos1.y + 20 && sprite->data[2] > 0)
+ DestroySprite(sprite);
+}
+
+static void CreateRandomEggShardSprite(void)
+{
+ u16 spriteAnimIndex;
+
+ s16 velocity1 = sEggShardVelocities[sEggHatchData->eggShardVelocityID][0];
+ s16 velocity2 = sEggShardVelocities[sEggHatchData->eggShardVelocityID][1];
+ sEggHatchData->eggShardVelocityID++;
+ spriteAnimIndex = Random() % 4;
+ CreateEggShardSprite(120, 60, velocity1, velocity2, 100, spriteAnimIndex);
+}
+
+static void CreateEggShardSprite(u8 x, u8 y, s16 data1, s16 data2, s16 data3, u8 spriteAnimIndex)
+{
+ u8 spriteID = CreateSprite(&sSpriteTemplate_EggShard, x, y, 4);
+ gSprites[spriteID].data[1] = data1;
+ gSprites[spriteID].data[2] = data2;
+ gSprites[spriteID].data[3] = data3;
+ StartSpriteAnim(&gSprites[spriteID], spriteAnimIndex);
+}
+
+static void EggHatchPrintMessage(u8 windowId, u8* string, u8 x, u8 y, u8 speed)
+{
+ FillWindowPixelBuffer(windowId, 0xFF);
+ sEggHatchData->textColor.fgColor = 0;
+ sEggHatchData->textColor.bgColor = 5;
+ sEggHatchData->textColor.shadowColor = 6;
+ AddTextPrinterParameterized4(windowId, 3, x, y, 1, 1, &sEggHatchData->textColor, speed, string);
+}
diff --git a/src/ereader_helpers.c b/src/ereader_helpers.c
new file mode 100644
index 000000000..2a9b9ea71
--- /dev/null
+++ b/src/ereader_helpers.c
@@ -0,0 +1,397 @@
+#include "global.h"
+#include "link.h"
+#include "unk_815c27c.h"
+
+enum {
+ EREADER_XFR_STATE_INIT,
+ EREADER_XFR_STATE_HANDSHAKE,
+ EREADER_XFR_STATE_START,
+ EREADER_XFR_STATE_TRANSFER,
+};
+
+struct SendRecvMgr
+{
+ u8 sendOrRecv;
+ u8 state;
+ u8 field_02;
+ u8 field_03;
+ u8 field_04;
+ u32 * dataptr;
+ int cursor;
+ int size;
+ u32 checksum;
+};
+
+static bool16 DetermineSendRecvState(u8);
+static void SetUpTransferManager(size_t, const void *, void *);
+static void StartTm3(void);
+static void EnableSio(void);
+static void DisableTm3(void);
+static void GetKeyInput(void);
+
+static struct SendRecvMgr sSendRecvMgr;
+static u16 sJoyNewOrRepeated;
+static u16 sJoyNew;
+static u16 sSendRecvStatus;
+static u16 sCounter1;
+static u32 sCounter2;
+static u16 sSavedIme;
+static u16 sSavedIe;
+static u16 sSavedTm3Cnt;
+static u16 sSavedSioCnt;
+static u16 sSavedSioCnt;
+static u16 sSavedRCnt;
+
+int EReader_Send(size_t r6, const void * r5)
+{
+ int result;
+ EReaderHelper_SaveRegsState();
+
+ while (1)
+ {
+ GetKeyInput();
+ if (TEST_BUTTON(sJoyNew, B_BUTTON))
+ gUnknown_3003F84 = 2;
+
+ sSendRecvStatus = EReaderHandleTransfer(1, r6, r5, NULL);
+ if ((sSendRecvStatus & 0x13) == 0x10)
+ {
+ result = 0;
+ break;
+ }
+ else if (sSendRecvStatus & 8)
+ {
+ result = 1;
+ break;
+ }
+ else if (sSendRecvStatus & 4)
+ {
+ result = 2;
+ break;
+ }
+ else
+ {
+ gUnknown_3003F84 = 0;
+ VBlankIntrWait();
+ }
+ }
+
+ CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
+ EReaderHelper_RestoreRegsState();
+ return result;
+}
+
+int EReader_Recv(void * r5)
+{
+ int result;
+ EReaderHelper_SaveRegsState();
+
+ while (1)
+ {
+ GetKeyInput();
+ if (TEST_BUTTON(sJoyNew, B_BUTTON))
+ gUnknown_3003F84 = 2;
+
+ sSendRecvStatus = EReaderHandleTransfer(0, 0, NULL, r5);
+ if ((sSendRecvStatus & 0x13) == 0x10)
+ {
+ result = 0;
+ break;
+ }
+ else if (sSendRecvStatus & 8)
+ {
+ result = 1;
+ break;
+ }
+ else if (sSendRecvStatus & 4)
+ {
+ result = 2;
+ break;
+ }
+ else
+ {
+ gUnknown_3003F84 = 0;
+ VBlankIntrWait();
+ }
+ }
+
+ CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
+ EReaderHelper_RestoreRegsState();
+ return result;
+}
+
+static void CloseSerial(void)
+{
+ REG_IME = 0;
+ REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
+ REG_IME = 1;
+ REG_SIOCNT = 0;
+ REG_TM3CNT_H = 0;
+ REG_IF = INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL;
+}
+
+static void OpenSerialMulti(void)
+{
+ REG_IME = 0;
+ REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
+ REG_IME = 1;
+ REG_RCNT = 0;
+ REG_SIOCNT = SIO_MULTI_MODE;
+ REG_SIOCNT |= SIO_INTR_ENABLE | SIO_115200_BPS;
+ REG_IME = 0;
+ REG_IE |= INTR_FLAG_SERIAL;
+ REG_IME = 1;
+ if (sSendRecvMgr.state == 0)
+ CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
+}
+
+static void OpenSerial32(void)
+{
+ REG_RCNT = 0;
+ REG_SIOCNT = SIO_INTR_ENABLE | SIO_32BIT_MODE;
+ REG_SIOCNT |= SIO_MULTI_SD;
+ gUnknown_3003F84 = 0;
+ sCounter1 = 0;
+ sCounter2 = 0;
+}
+
+u16 EReaderHandleTransfer(u8 mode, size_t size, const void * data, void * recvBuffer)
+{
+ switch (sSendRecvMgr.state)
+ {
+ case 0:
+ OpenSerialMulti();
+ sSendRecvMgr.field_02 = 1;
+ sSendRecvMgr.state = 1;
+ break;
+ case 1:
+ if (DetermineSendRecvState(mode))
+ EnableSio();
+ if (gUnknown_3003F84 == 2)
+ {
+ sSendRecvMgr.field_04 = 2;
+ sSendRecvMgr.state = 6;
+ }
+ break;
+ case 2:
+ OpenSerial32();
+ SetUpTransferManager(size, data, recvBuffer);
+ sSendRecvMgr.state = 3;
+ // fallthrough
+ case 3:
+ if (gUnknown_3003F84 == 2)
+ {
+ sSendRecvMgr.field_04 = 2;
+ sSendRecvMgr.state = 6;
+ }
+ else
+ {
+ sCounter1++;
+ sCounter2++;
+ if (sSendRecvMgr.sendOrRecv == 0 && sCounter2 > 60)
+ {
+ sSendRecvMgr.field_04 = 1;
+ sSendRecvMgr.state = 6;
+ }
+ if (sSendRecvMgr.field_02 != 2)
+ {
+ if (sSendRecvMgr.sendOrRecv != 0 && sCounter1 > 2)
+ {
+ EnableSio();
+ sSendRecvMgr.field_02 = 2;
+ }
+ else
+ {
+ EnableSio();
+ sSendRecvMgr.field_02 = 2;
+ }
+ }
+ }
+ break;
+ case 4:
+ OpenSerialMulti();
+ sSendRecvMgr.state = 5;
+ break;
+ case 5:
+ if (sSendRecvMgr.sendOrRecv == 1 && sCounter1 > 2)
+ EnableSio();
+ if (++sCounter1 > 60)
+ {
+ sSendRecvMgr.field_04 = 1;
+ sSendRecvMgr.state = 6;
+ }
+ break;
+ case 6:
+ if (sSendRecvMgr.field_02 != 0)
+ {
+ CloseSerial();
+ sSendRecvMgr.field_02 = 0;
+ }
+ break;
+ }
+ return sSendRecvMgr.field_02 | (sSendRecvMgr.field_04 << 2) | (sSendRecvMgr.field_03 << 4);
+}
+
+static bool16 DetermineSendRecvState(u8 mode)
+{
+ bool16 resp;
+ if ((*(vu32 *)REG_ADDR_SIOCNT & (SIO_MULTI_SI | SIO_MULTI_SD)) == SIO_MULTI_SD && mode)
+ resp = sSendRecvMgr.sendOrRecv = TRUE;
+ else
+ resp = sSendRecvMgr.sendOrRecv = FALSE;
+ return resp;
+}
+
+static void SetUpTransferManager(size_t size, const void * data, void * recvBuffer)
+{
+ if (sSendRecvMgr.sendOrRecv)
+ {
+ REG_SIOCNT |= SIO_38400_BPS;
+ sSendRecvMgr.dataptr = (void *)data;
+ REG_SIODATA32 = size;
+ sSendRecvMgr.size = size / 4 + 1;
+ StartTm3();
+ }
+ else
+ {
+ REG_SIOCNT |= SIO_9600_BPS;
+ sSendRecvMgr.dataptr = recvBuffer;
+ }
+}
+
+static void StartTm3(void)
+{
+ REG_TM3CNT_L = -601;
+ REG_TM3CNT_H = TIMER_INTR_ENABLE;
+ REG_IME = 0;
+ REG_IE |= INTR_FLAG_TIMER3;
+ REG_IME = 1;
+}
+
+void EReaderHelper_Timer3Callback(void)
+{
+ DisableTm3();
+ EnableSio();
+}
+
+void EReaderHelper_SerialCallback(void)
+{
+ u16 recv[4];
+ u16 i;
+ u16 cnt1;
+ u16 cnt2;
+ u32 recv32;
+
+ switch (sSendRecvMgr.state)
+ {
+ case 1:
+ REG_SIOMLT_SEND = 0xCCD0;
+ *(u64 *)recv = REG_SIOMLT_RECV;
+ for (i = 0, cnt1 = 0, cnt2 = 0; i < 4; i++)
+ {
+ if (recv[i] == 0xCCD0)
+ cnt1++;
+ else if (recv[i] != 0xFFFF)
+ cnt2++;
+ }
+ if (cnt1 == 2 && cnt2 == 0)
+ sSendRecvMgr.state = 2;
+ break;
+ case 3:
+ recv32 = REG_SIODATA32;
+ if (sSendRecvMgr.cursor == 0 && sSendRecvMgr.sendOrRecv == 0)
+ sSendRecvMgr.size = recv32 / 4 + 1;
+ if (sSendRecvMgr.sendOrRecv == 1)
+ {
+ if (sSendRecvMgr.cursor < sSendRecvMgr.size)
+ {
+ REG_SIODATA32 = sSendRecvMgr.dataptr[sSendRecvMgr.cursor];
+ sSendRecvMgr.checksum += sSendRecvMgr.dataptr[sSendRecvMgr.cursor];
+ }
+ else
+ REG_SIODATA32 = sSendRecvMgr.checksum;
+ }
+ else
+ {
+ if (sSendRecvMgr.cursor > 0 && sSendRecvMgr.cursor < sSendRecvMgr.size + 1)
+ {
+ sSendRecvMgr.dataptr[sSendRecvMgr.cursor - 1] = recv32;
+ sSendRecvMgr.checksum += recv32;
+ }
+ else if (sSendRecvMgr.cursor != 0)
+ {
+ if (sSendRecvMgr.checksum == recv32)
+ sSendRecvMgr.field_03 = 1;
+ else
+ sSendRecvMgr.field_03 = 2;
+ }
+ sCounter2 = 0;
+ }
+ sSendRecvMgr.cursor++;
+ if (sSendRecvMgr.cursor < sSendRecvMgr.size + 2)
+ {
+ if (sSendRecvMgr.sendOrRecv != 0)
+ REG_TM3CNT_H |= TIMER_ENABLE;
+ else
+ EnableSio();
+ }
+ else
+ {
+ sSendRecvMgr.state = 4;
+ sCounter1 = 0;
+ }
+ break;
+ case 5:
+ if (sSendRecvMgr.sendOrRecv == 0)
+ REG_SIODATA8 = sSendRecvMgr.field_03;
+ *(vu64 *)recv = REG_SIOMLT_RECV;
+ if (recv[1] == 1 || recv[1] == 2)
+ {
+ if (sSendRecvMgr.sendOrRecv == 1)
+ sSendRecvMgr.field_03 = recv[1];
+ sSendRecvMgr.state = 6;
+ }
+ break;
+ }
+}
+
+static void EnableSio(void)
+{
+ REG_SIOCNT |= SIO_ENABLE;
+}
+
+static void DisableTm3(void)
+{
+ REG_TM3CNT_H &= ~TIMER_ENABLE;
+ REG_TM3CNT_L = -601;
+}
+
+static void GetKeyInput(void)
+{
+ u16 rawKeys = REG_KEYINPUT ^ 0x3FF;
+ sJoyNew = rawKeys & ~sJoyNewOrRepeated;
+ sJoyNewOrRepeated = rawKeys;
+}
+
+void EReaderHelper_SaveRegsState(void)
+{
+ sSavedIme = REG_IME;
+ sSavedIe = REG_IE;
+ sSavedTm3Cnt = REG_TM3CNT_H;
+ sSavedSioCnt = REG_SIOCNT;
+ sSavedRCnt = REG_RCNT;
+}
+
+void EReaderHelper_RestoreRegsState(void)
+{
+ REG_IME = sSavedIme;
+ REG_IE = sSavedIe;
+ REG_TM3CNT_H = sSavedTm3Cnt;
+ REG_SIOCNT = sSavedSioCnt;
+ REG_RCNT = sSavedRCnt;
+}
+
+void EReaderHelper_ClearsSendRecvMgr(void)
+{
+ CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
+}
diff --git a/src/fame_checker.c b/src/fame_checker.c
index bbbe02c58..bf99bdf56 100644
--- a/src/fame_checker.c
+++ b/src/fame_checker.c
@@ -8,7 +8,7 @@
#include "battle.h"
#include "battle_setup.h"
#include "menu.h"
-#include "battle_dome_cards.h"
+#include "trainer_pokemon_sprites.h"
#include "scanline_effect.h"
#include "new_menu_helpers.h"
#include "item_menu.h"
@@ -127,9 +127,9 @@ extern const u8 gFameCheckerText_Cancel[];
extern const u8 gFameCheckerText_ListMenuCursor[];
extern const u8 gFameCheckerText_FameCheckerWillBeClosed[];
extern const u8 gFameCheckerText_ClearTextbox[];
-extern const u8 gFameCheckerText_MainScreenUI[]; // "{KEYGFX_START_BUTTON}PICK {KEYGFX_DPAD_UP_DOWN}SELECT {KEYGFX_A_BUTTON}OK$"
-extern const u8 gFameCheckerText_PickScreenUI[]; // "{KEYGFX_START_BUTTON}PICK {KEYGFX_DPAD_UP_DOWN}SELECT {KEYGFX_B_BUTTON}CANCEL$"
-extern const u8 gFameCheckerText_FlavorTextUI[]; // "{KEYGFX_DPAD_ANY}PICK {KEYGFX_A_BUTTON}READ {KEYGFX_B_BUTTON}CANCEL$"
+extern const u8 gFameCheckerText_MainScreenUI[]; // "{KEYGFX_DPAD_ANY}PICK {KEYGFX_DPAD_UP_DOWN}SELECT {KEYGFX_A_BUTTON}OK$"
+extern const u8 gFameCheckerText_PickScreenUI[]; // "{KEYGFX_DPAD_ANY}PICK {KEYGFX_DPAD_UP_DOWN}SELECT {KEYGFX_B_BUTTON}CANCEL$"
+extern const u8 gFameCheckerText_FlavorTextUI[]; // "{KEYGFX_START_BUTTON}PICK {KEYGFX_A_BUTTON}READ {KEYGFX_B_BUTTON}CANCEL$"
extern const u8 gFameCheckerOakName[]; // "OAK$"
extern const u8 gFameCheckerDaisyName[]; // "DAISY$"
extern const u8 gFameCheckerBillName[]; // "BILL$"
@@ -552,7 +552,7 @@ static void Task_TopMenuHandleInput(u8 taskId)
if (FindTaskIdByFunc(Task_FCOpenOrCloseInfoBox) == 0xFF)
{
RunTextPrinters();
- if ((JOY_NEW(SELECT_BUTTON)) && !sFameCheckerData->inPickMode && sFameCheckerData->savedCallback != UseFameCheckerFromMenu)
+ if ((JOY_NEW(SELECT_BUTTON)) && !sFameCheckerData->inPickMode && sFameCheckerData->savedCallback != ReturnToBagFromKeyItem)
task->func = Task_StartToCloseFameChecker;
else if (JOY_NEW(START_BUTTON))
{
@@ -639,7 +639,7 @@ static bool8 TryExitPickMode(u8 taskId)
static void MessageBoxPrintEmptyText(void)
{
- AddTextPrinterParametrized(2, 2, gFameCheckerText_ClearTextbox, 0, NULL, 2, 1, 3);
+ AddTextPrinterParameterized2(2, 2, gFameCheckerText_ClearTextbox, 0, NULL, 2, 1, 3);
}
static void Task_EnterPickMode(u8 taskId)
@@ -779,7 +779,7 @@ static void GetPickModeText(void)
if (HasUnlockedAllFlavorTextsForCurrentPerson() == TRUE)
offset = NUM_FAMECHECKER_PERSONS;
StringExpandPlaceholders(gStringVar4, sFameCheckerNameAndQuotesPointers[sFameCheckerData->unlockedPersons[who] + offset]);
- AddTextPrinterParametrized(FCWINDOWID_MSGBOX, 2, gStringVar4, sub_80F78A8(), NULL, 2, 1, 3);
+ AddTextPrinterParameterized2(FCWINDOWID_MSGBOX, 2, gStringVar4, GetTextSpeedSetting(), NULL, 2, 1, 3);
FC_PutWindowTilemapAndCopyWindowToVramMode3(FCWINDOWID_MSGBOX);
}
}
@@ -790,7 +790,7 @@ static void PrintSelectedNameInBrightGreen(u8 taskId)
u16 cursorPos = FameCheckerGetCursorY();
FillWindowPixelRect(FCWINDOWID_MSGBOX, 0x11, 0, 0, 0xd0, 0x20);
StringExpandPlaceholders(gStringVar4, sFameCheckerFlavorTextPointers[sFameCheckerData->unlockedPersons[cursorPos] * 6 + data[1]]);
- AddTextPrinterParametrized(FCWINDOWID_MSGBOX, 2, gStringVar4, sub_80F78A8(), NULL, 2, 1, 3);
+ AddTextPrinterParameterized2(FCWINDOWID_MSGBOX, 2, gStringVar4, GetTextSpeedSetting(), NULL, 2, 1, 3);
FC_PutWindowTilemapAndCopyWindowToVramMode3(FCWINDOWID_MSGBOX);
}
@@ -803,7 +803,7 @@ static void WipeMsgBoxAndTransfer(void)
static void Setup_DrawMsgAndListBoxes(void)
{
sub_80F6E9C();
- sub_80F6EE4(FCWINDOWID_MSGBOX, TRUE);
+ DrawDialogueFrame(FCWINDOWID_MSGBOX, TRUE);
FC_PutWindowTilemapAndCopyWindowToVramMode3(FCWINDOWID_MSGBOX);
FC_PutWindowTilemapAndCopyWindowToVramMode3(FCWINDOWID_LIST);
}
@@ -853,7 +853,7 @@ static void Task_DestroyAssetsAndCloseFameChecker(u8 taskId)
FreeQuestionMarkSpriteResources();
FreeListMenuSelectorArrowPairResources();
SetMainCallback2(sFameCheckerData->savedCallback);
- sub_810713C(sFameCheckerData->listMenuTaskId, 0, 0);
+ DestroyListMenu(sFameCheckerData->listMenuTaskId, NULL, NULL);
Free(sBg3TilemapBuffer);
Free(sBg1TilemapBuffer);
Free(sBg2TilemapBuffer);
@@ -900,7 +900,7 @@ static void PrintUIHelp(u8 state)
}
width = GetStringWidth(0, src, 0);
FillWindowPixelRect(FCWINDOWID_UIHELP, 0x00, 0, 0, 0xc0, 0x10);
- AddTextPrinterParametrized2(FCWINDOWID_UIHELP, 0, 188 - width, 0, 0, 2, &sTextColor_White, -1, src);
+ AddTextPrinterParameterized4(FCWINDOWID_UIHELP, 0, 188 - width, 0, 0, 2, &sTextColor_White, -1, src);
FC_PutWindowTilemapAndCopyWindowToVramMode3(FCWINDOWID_UIHELP);
}
@@ -1009,10 +1009,10 @@ static void FCSetup_ClearVideoRegisters(void)
static void FCSetup_ResetTasksAndSpriteResources(void)
{
- remove_some_task();
+ ScanlineEffect_Stop();
ResetTasks();
ResetSpriteData();
- dp13_810BB8C();
+ ResetAllPicSprites();
ResetPaletteFade();
npc_paltag_set_load(0);
gReservedSpritePaletteCount = 7;
@@ -1181,7 +1181,7 @@ static u8 CreatePersonPicSprite(u8 fcPersonIdx)
}
else
{
- spriteId = sub_810C2A4(sFameCheckerTrainerPicIdxs[fcPersonIdx], 1, 0x94, 0x42, 6, 0xFFFF);
+ spriteId = CreateTrainerPicSprite(sFameCheckerTrainerPicIdxs[fcPersonIdx], 1, 0x94, 0x42, 6, 0xFFFF);
}
gSprites[spriteId].callback = SpriteCB_FCSpinningPokeball;
if (gSaveBlock1Ptr->fameChecker[fcPersonIdx].pickState == FCPICKSTATE_SILHOUETTE)
@@ -1202,7 +1202,7 @@ static void DestroyPersonPicSprite(u8 taskId, u16 who)
)
DestroySprite(&gSprites[data[2]]);
else
- sub_810C2E8(data[2]);
+ FreeAndDestroyTrainerPicSprite(data[2]);
}
static void UpdateIconDescriptionBox(u8 whichText)
@@ -1213,10 +1213,10 @@ static void UpdateIconDescriptionBox(u8 whichText)
gIconDescriptionBoxIsOpen = 1;
FillWindowPixelRect(FCWINDOWID_ICONDESC, 0x00, 0, 0, 0x58, 0x20);
width = (0x54 - GetStringWidth(0, sFlavorTextOriginLocationTexts[idx], 0)) / 2;
- AddTextPrinterParametrized2(FCWINDOWID_ICONDESC, 0, width, 0, 0, 2, &sTextColor_DkGrey, -1, sFlavorTextOriginLocationTexts[idx]);
+ AddTextPrinterParameterized4(FCWINDOWID_ICONDESC, 0, width, 0, 0, 2, &sTextColor_DkGrey, -1, sFlavorTextOriginLocationTexts[idx]);
StringExpandPlaceholders(gStringVar1, sFlavorTextOriginObjectNameTexts[idx]);
width = (0x54 - GetStringWidth(0, gStringVar1, 0)) / 2;
- AddTextPrinterParametrized2(FCWINDOWID_ICONDESC, 0, width, 10, 0, 2, &sTextColor_DkGrey, -1, gStringVar1);
+ AddTextPrinterParameterized4(FCWINDOWID_ICONDESC, 0, width, 10, 0, 2, &sTextColor_DkGrey, -1, gStringVar1);
FC_PutWindowTilemapAndCopyWindowToVramMode3(FCWINDOWID_ICONDESC);
}
@@ -1270,7 +1270,7 @@ static void FC_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list
struct Task *task = &gTasks[taskId];
PlaySE(SE_SELECT);
task->data[1] = 0;
- get_coro_args_x18_x1A(sFameCheckerData->listMenuTaskId, &listMenuTopIdx, NULL);
+ ListMenuGetScrollAndRow(sFameCheckerData->listMenuTaskId, &listMenuTopIdx, NULL);
sFameCheckerData->listMenuTopIdx = listMenuTopIdx;
if (itemIndex != sFameCheckerData->numUnlockedPersons - 1)
{
@@ -1330,7 +1330,7 @@ static void Task_SwitchToPickMode(u8 taskId)
static void PrintCancelDescription(void)
{
FillWindowPixelRect(FCWINDOWID_MSGBOX, 0x11, 0, 0, 0xd0, 0x20);
- AddTextPrinterParametrized(FCWINDOWID_MSGBOX, 2, gFameCheckerText_FameCheckerWillBeClosed, 0, NULL, 2, 1, 3);
+ AddTextPrinterParameterized2(FCWINDOWID_MSGBOX, 2, gFameCheckerText_FameCheckerWillBeClosed, 0, NULL, 2, 1, 3);
FC_PutWindowTilemapAndCopyWindowToVramMode3(FCWINDOWID_MSGBOX);
}
@@ -1339,16 +1339,16 @@ static void FC_DoMoveCursor(s32 itemIndex, bool8 onInit)
u16 listY;
u16 cursorY;
u16 who;
- get_coro_args_x18_x1A(sFameCheckerData->listMenuTaskId, &listY, &cursorY);
+ ListMenuGetScrollAndRow(sFameCheckerData->listMenuTaskId, &listY, &cursorY);
who = listY + cursorY;
- AddTextPrinterParametrized2(FCWINDOWID_LIST, 2, 8, 14 * cursorY + 4, 0, 0, &sTextColor_Green, 0, sListMenuItems[itemIndex].unk_00);
+ AddTextPrinterParameterized4(FCWINDOWID_LIST, 2, 8, 14 * cursorY + 4, 0, 0, &sTextColor_Green, 0, sListMenuItems[itemIndex].label);
if (!onInit)
{
if (listY < sFameCheckerData->listMenuTopIdx2)
sFameCheckerData->listMenuDrawnSelIdx++;
else if (listY > sFameCheckerData->listMenuTopIdx2 && who != sFameCheckerData->numUnlockedPersons - 1)
sFameCheckerData->listMenuDrawnSelIdx--;
- AddTextPrinterParametrized2(FCWINDOWID_LIST, 2, 8, 14 * sFameCheckerData->listMenuDrawnSelIdx + 4, 0, 0, &sTextColor_DkGrey, 0, sListMenuItems[sFameCheckerData->listMenuCurIdx].unk_00);
+ AddTextPrinterParameterized4(FCWINDOWID_LIST, 2, 8, 14 * sFameCheckerData->listMenuDrawnSelIdx + 4, 0, 0, &sTextColor_DkGrey, 0, sListMenuItems[sFameCheckerData->listMenuCurIdx].label);
}
sFameCheckerData->listMenuCurIdx = itemIndex;
@@ -1368,20 +1368,20 @@ static u8 FC_PopulateListMenu(void)
{
if (sTrainerIdxs[fameCheckerIdx] < FC_NONTRAINER_START)
{
- sListMenuItems[nitems].unk_00 = gTrainers[sTrainerIdxs[fameCheckerIdx]].trainerName;
- sListMenuItems[nitems].unk_04 = nitems;
+ sListMenuItems[nitems].label = gTrainers[sTrainerIdxs[fameCheckerIdx]].trainerName;
+ sListMenuItems[nitems].index = nitems;
}
else
{
- sListMenuItems[nitems].unk_00 = sNonTrainerNamePointers[sTrainerIdxs[fameCheckerIdx] - FC_NONTRAINER_START];
- sListMenuItems[nitems].unk_04 = nitems;
+ sListMenuItems[nitems].label = sNonTrainerNamePointers[sTrainerIdxs[fameCheckerIdx] - FC_NONTRAINER_START];
+ sListMenuItems[nitems].index = nitems;
}
sFameCheckerData->unlockedPersons[nitems] = fameCheckerIdx;
nitems++;
}
}
- sListMenuItems[nitems].unk_00 = gFameCheckerText_Cancel;
- sListMenuItems[nitems].unk_04 = nitems;
+ sListMenuItems[nitems].label = gFameCheckerText_Cancel;
+ sListMenuItems[nitems].index = nitems;
sFameCheckerData->unlockedPersons[nitems] = 0xFF;
nitems++;
gFameChecker_ListMenuTemplate.totalItems = nitems;
@@ -1400,7 +1400,7 @@ static void FC_PutWindowTilemapAndCopyWindowToVramMode3_2(u8 windowId)
static void FC_CreateScrollIndicatorArrowPair(void)
{
- struct ScrollIndicatorArrowPairTemplate template = {
+ struct ScrollArrowsTemplate template = {
2,
40,
26,
@@ -1412,13 +1412,12 @@ static void FC_CreateScrollIndicatorArrowPair(void)
SPRITETAG_SCROLL_INDICATORS,
0xFFFF,
1,
- 0
};
if (sFameCheckerData->numUnlockedPersons > 5)
{
- template.unk_06 = 0;
- template.unk_08 = sFameCheckerData->numUnlockedPersons - 5;
+ template.fullyUpThreshold = 0;
+ template.fullyDownThreshold = sFameCheckerData->numUnlockedPersons - 5;
sFameCheckerData->scrollIndicatorPairTaskId = AddScrollIndicatorArrowPair(&template, &sFameCheckerData->listMenuTopIdx);
}
}
@@ -1432,7 +1431,7 @@ static void FreeListMenuSelectorArrowPairResources(void)
static u16 FameCheckerGetCursorY(void)
{
u16 listY, cursorY;
- get_coro_args_x18_x1A(sFameCheckerData->listMenuTaskId, &listY, &cursorY);
+ ListMenuGetScrollAndRow(sFameCheckerData->listMenuTaskId, &listY, &cursorY);
return listY + cursorY;
}
@@ -1547,7 +1546,7 @@ static void PlaceListMenuCursor(bool8 isActive)
{
u16 cursorY = ListMenuGetYCoordForPrintingArrowCursor(sFameCheckerData->listMenuTaskId);
if (isActive == TRUE)
- AddTextPrinterParametrized2(FCWINDOWID_LIST, 2, 0, cursorY, 0, 0, &sTextColor_DkGrey, 0, gFameCheckerText_ListMenuCursor);
+ AddTextPrinterParameterized4(FCWINDOWID_LIST, 2, 0, cursorY, 0, 0, &sTextColor_DkGrey, 0, gFameCheckerText_ListMenuCursor);
else
- AddTextPrinterParametrized2(FCWINDOWID_LIST, 2, 0, cursorY, 0, 0, &sTextColor_White, 0, gFameCheckerText_ListMenuCursor);
+ AddTextPrinterParameterized4(FCWINDOWID_LIST, 2, 0, cursorY, 0, 0, &sTextColor_White, 0, gFameCheckerText_ListMenuCursor);
}
diff --git a/src/fieldmap.c b/src/fieldmap.c
new file mode 100644
index 000000000..5d11c7d99
--- /dev/null
+++ b/src/fieldmap.c
@@ -0,0 +1,1025 @@
+#include "global.h"
+#include "bg.h"
+#include "palette.h"
+#include "overworld.h"
+#include "script.h"
+#include "menu.h"
+#include "new_menu_helpers.h"
+#include "quest_log.h"
+#include "fieldmap.h"
+
+struct ConnectionFlags
+{
+ u8 south:1;
+ u8 north:1;
+ u8 west:1;
+ u8 east:1;
+};
+
+void sub_8058A00(struct MapHeader *mapHeader);
+void map_copy_with_padding(u16 *map, u16 width, u16 height);
+void mapheader_copy_mapdata_of_adjacent_maps(struct MapHeader *mapHeader);
+void fillSouthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset);
+void fillNorthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset);
+void fillWestConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset);
+void fillEastConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset);
+void LoadSavedMapView(void);
+struct MapConnection *sub_8059600(u8 direction, s32 x, s32 y);
+bool8 sub_8059658(u8 direction, s32 x, s32 y, struct MapConnection *connection);
+bool8 sub_80596BC(s32 x, s32 src_width, s32 dest_width, s32 offset);
+
+struct BackupMapData VMap;
+EWRAM_DATA u16 gBackupMapData[VIRTUAL_MAP_SIZE] = {};
+EWRAM_DATA struct MapHeader gMapHeader = {};
+EWRAM_DATA struct Camera gCamera = {};
+EWRAM_DATA struct ConnectionFlags gMapConnectionFlags = {};
+
+const struct ConnectionFlags sDummyConnectionFlags = {};
+
+const u32 gUnknown_8352EF0[] = {
+ 0x1ff,
+ 0x3e00,
+ 0x3c000,
+ 0xfc0000,
+ 0x7000000,
+ 0x18000000,
+ 0x60000000,
+ 0x80000000
+};
+
+const u8 gUnknown_8352F10[] = {
+ 0,
+ 9,
+ 14,
+ 18,
+ 24,
+ 27,
+ 29,
+ 31
+};
+
+const struct MapHeader * mapconnection_get_mapheader(struct MapConnection * connection)
+{
+ return get_mapheader_by_bank_and_number(connection->mapGroup, connection->mapNum);
+}
+
+void not_trainer_hill_battle_pyramid(void)
+{
+ sub_8058A00(&gMapHeader);
+ mapheader_run_script_with_tag_x1();
+}
+
+void sub_80589E8(void)
+{
+ sub_8058A00(&gMapHeader);
+ LoadSavedMapView();
+ mapheader_run_script_with_tag_x1();
+}
+
+void sub_8058A00(struct MapHeader * mapHeader)
+{
+ const struct MapData * mapData = mapHeader->mapData;
+ CpuFastFill(0x03FF03FF, gBackupMapData, sizeof(gBackupMapData));
+ VMap.map = gBackupMapData;
+ VMap.Xsize = mapData->width + 15;
+ VMap.Ysize = mapData->height + 14;
+ AGB_ASSERT_EX(VMap.Xsize * VMap.Ysize <= VIRTUAL_MAP_SIZE, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/fieldmap.c", 158);
+ map_copy_with_padding(mapData->map, mapData->width, mapData->height);
+ mapheader_copy_mapdata_of_adjacent_maps(mapHeader);
+}
+
+void map_copy_with_padding(u16 *map, u16 width, u16 height)
+{
+ s32 y;
+ u16 *dest = VMap.map;
+ dest += VMap.Xsize * 7 + 7;
+
+ for (y = 0; y < height; y++)
+ {
+ CpuCopy16(map, dest, width * sizeof(u16));
+ dest += width + 15;
+ map += width;
+ }
+}
+
+void mapheader_copy_mapdata_of_adjacent_maps(struct MapHeader *mapHeader)
+{
+ s32 count;
+ struct MapConnection *connection;
+ s32 i;
+
+ gMapConnectionFlags = sDummyConnectionFlags;
+
+ /*
+ * This null pointer check is new to FireRed. It was kept in
+ * Emerald, with the above struct assignment moved to after
+ * this check.
+ */
+ if (mapHeader->connections)
+ {
+ count = mapHeader->connections->count;
+ connection = mapHeader->connections->connections;
+ // Emerald puts this line here instead:
+ // gMapConnectionFlags = sDummyConnectionFlags;
+ for (i = 0; i < count; i++, connection++)
+ {
+ struct MapHeader const *cMap = mapconnection_get_mapheader(connection);
+ u32 offset = connection->offset;
+ switch (connection->direction)
+ {
+ case CONNECTION_SOUTH:
+ fillSouthConnection(mapHeader, cMap, offset);
+ gMapConnectionFlags.south = 1;
+ break;
+ case CONNECTION_NORTH:
+ fillNorthConnection(mapHeader, cMap, offset);
+ gMapConnectionFlags.north = 1;
+ break;
+ case CONNECTION_WEST:
+ fillWestConnection(mapHeader, cMap, offset);
+ gMapConnectionFlags.west = 1;
+ break;
+ case CONNECTION_EAST:
+ fillEastConnection(mapHeader, cMap, offset);
+ gMapConnectionFlags.east = 1;
+ break;
+ }
+ }
+ }
+}
+
+void sub_8058B54(s32 x, s32 y, const struct MapHeader *connectedMapHeader, s32 x2, s32 y2, s32 width, s32 height)
+{
+ s32 i;
+ u16 *src;
+ u16 *dest;
+ s32 mapWidth;
+
+ mapWidth = connectedMapHeader->mapData->width;
+ src = &connectedMapHeader->mapData->map[mapWidth * y2 + x2];
+ dest = &VMap.map[VMap.Xsize * y + x];
+
+ for (i = 0; i < height; i++)
+ {
+ CpuCopy16(src, dest, width * 2);
+ dest += VMap.Xsize;
+ src += mapWidth;
+ }
+}
+
+void fillSouthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset)
+{
+ s32 x, y;
+ s32 x2;
+ s32 width;
+ s32 cWidth;
+
+ if (connectedMapHeader)
+ {
+ cWidth = connectedMapHeader->mapData->width;
+ x = offset + 7;
+ y = mapHeader->mapData->height + 7;
+ if (x < 0)
+ {
+ x2 = -x;
+ x += cWidth;
+ if (x < VMap.Xsize)
+ {
+ width = x;
+ }
+ else
+ {
+ width = VMap.Xsize;
+ }
+ x = 0;
+ }
+ else
+ {
+ x2 = 0;
+ if (x + cWidth < VMap.Xsize)
+ {
+ width = cWidth;
+ }
+ else
+ {
+ width = VMap.Xsize - x;
+ }
+ }
+
+ sub_8058B54(
+ x, y,
+ connectedMapHeader,
+ x2, /*y2*/ 0,
+ width, /*height*/ 7);
+ }
+}
+
+void fillNorthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset)
+{
+ s32 x;
+ s32 x2, y2;
+ s32 width;
+ s32 cWidth, cHeight;
+
+ if (connectedMapHeader)
+ {
+ cWidth = connectedMapHeader->mapData->width;
+ cHeight = connectedMapHeader->mapData->height;
+ x = offset + 7;
+ y2 = cHeight - 7;
+ if (x < 0)
+ {
+ x2 = -x;
+ x += cWidth;
+ if (x < VMap.Xsize)
+ {
+ width = x;
+ }
+ else
+ {
+ width = VMap.Xsize;
+ }
+ x = 0;
+ }
+ else
+ {
+ x2 = 0;
+ if (x + cWidth < VMap.Xsize)
+ {
+ width = cWidth;
+ }
+ else
+ {
+ width = VMap.Xsize - x;
+ }
+ }
+
+ sub_8058B54(
+ x, /*y*/ 0,
+ connectedMapHeader,
+ x2, y2,
+ width, /*height*/ 7);
+
+ }
+}
+
+void fillWestConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset)
+{
+ s32 y;
+ s32 x2, y2;
+ s32 height;
+ s32 cWidth, cHeight;
+ if (connectedMapHeader)
+ {
+ cWidth = connectedMapHeader->mapData->width;
+ cHeight = connectedMapHeader->mapData->height;
+ y = offset + 7;
+ x2 = cWidth - 7;
+ if (y < 0)
+ {
+ y2 = -y;
+ if (y + cHeight < VMap.Ysize)
+ {
+ height = y + cHeight;
+ }
+ else
+ {
+ height = VMap.Ysize;
+ }
+ y = 0;
+ }
+ else
+ {
+ y2 = 0;
+ if (y + cHeight < VMap.Ysize)
+ {
+ height = cHeight;
+ }
+ else
+ {
+ height = VMap.Ysize - y;
+ }
+ }
+
+ sub_8058B54(
+ /*x*/ 0, y,
+ connectedMapHeader,
+ x2, y2,
+ /*width*/ 7, height);
+ }
+}
+
+void fillEastConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset)
+{
+ s32 x, y;
+ s32 y2;
+ s32 height;
+ s32 cHeight;
+ if (connectedMapHeader)
+ {
+ cHeight = connectedMapHeader->mapData->height;
+ x = mapHeader->mapData->width + 7;
+ y = offset + 7;
+ if (y < 0)
+ {
+ y2 = -y;
+ if (y + cHeight < VMap.Ysize)
+ {
+ height = y + cHeight;
+ }
+ else
+ {
+ height = VMap.Ysize;
+ }
+ y = 0;
+ }
+ else
+ {
+ y2 = 0;
+ if (y + cHeight < VMap.Ysize)
+ {
+ height = cHeight;
+ }
+ else
+ {
+ height = VMap.Ysize - y;
+ }
+ }
+
+ sub_8058B54(
+ x, y,
+ connectedMapHeader,
+ /*x2*/ 0, y2,
+ /*width*/ 8, height);
+ }
+}
+
+union Block
+{
+ struct
+ {
+ u16 block:10;
+ u16 collision:2;
+ u16 elevation:4;
+ } block;
+ u16 value;
+};
+
+#define MapGridGetBorderTileAt(x, y) ({ \
+ u16 block; \
+ s32 xprime; \
+ s32 yprime; \
+ \
+ struct MapData *mapData = gMapHeader.mapData; \
+ \
+ xprime = x - 7; \
+ xprime += 8 * mapData->unk18; \
+ xprime %= mapData->unk18; \
+ \
+ yprime = y - 7; \
+ yprime += 8 * mapData->unk19; \
+ yprime %= mapData->unk19; \
+ \
+ block = mapData->border[xprime + yprime * mapData->unk18]; \
+ block |= 0xC00; \
+ block; \
+})
+
+#define MapGridGetBorderTileAt2(x, y) ({ \
+ u16 block; \
+ s32 xprime; \
+ s32 yprime; \
+ \
+ struct MapData *mapData = gMapHeader.mapData; \
+ \
+ xprime = x - 7; \
+ xprime += 8 * mapData->unk18; \
+ xprime %= mapData->unk18; \
+ \
+ yprime = y - 7; \
+ yprime += 8 * mapData->unk19; \
+ yprime %= mapData->unk19; \
+ \
+ block = mapData->border[xprime + yprime * mapData->unk18] | 0xC00; \
+ block; \
+})
+
+#define AreCoordsWithinMapGridBounds(x, y) (x >= 0 && x < VMap.Xsize && y >= 0 && y < VMap.Ysize)
+
+#define MapGridGetTileAt(x, y) (AreCoordsWithinMapGridBounds(x, y) ? VMap.map[x + VMap.Xsize * y] : MapGridGetBorderTileAt2(x, y))
+
+u8 MapGridGetZCoordAt(s32 x, s32 y)
+{
+ u16 block = MapGridGetTileAt(x, y);
+
+ if (block == 0x3ff)
+ {
+ return 0;
+ }
+
+ return block >> 12;
+}
+
+u8 MapGridIsImpassableAt(s32 x, s32 y)
+{
+
+ u16 block = MapGridGetTileAt(x, y);
+
+ if (block == 0x3ff)
+ {
+ return 1;
+ }
+
+ return (block & 0xc00) >> 10;
+}
+
+u32 MapGridGetMetatileIdAt(s32 x, s32 y)
+{
+ u16 block = MapGridGetTileAt(x, y);
+
+ if (block == 0x3FF)
+ {
+ return MapGridGetBorderTileAt(x, y) & 0x3FF;
+ }
+ return block & 0x3FF;
+}
+
+u32 sub_8058F1C(u32 original, u8 bit)
+{
+ if (bit >= 8)
+ return original;
+
+ return (original & gUnknown_8352EF0[bit]) >> gUnknown_8352F10[bit];
+}
+
+u32 sub_8058F48(s16 x, s16 y, u8 z)
+{
+ u16 metatileId = MapGridGetMetatileIdAt(x, y);
+ return GetBehaviorByMetatileIdAndMapData(gMapHeader.mapData, metatileId, z);
+}
+
+u32 MapGridGetMetatileBehaviorAt(s32 x, s32 y)
+{
+ return sub_8058F48(x, y, 0);
+}
+
+u8 MapGridGetMetatileLayerTypeAt(s32 x, s32 y)
+{
+ return sub_8058F48(x, y, 6);
+}
+
+void MapGridSetMetatileIdAt(s32 x, s32 y, u16 metatile)
+{
+ s32 i;
+ if (x >= 0 && x < VMap.Xsize
+ && y >= 0 && y < VMap.Ysize)
+ {
+ i = x + y * VMap.Xsize;
+ VMap.map[i] = (VMap.map[i] & 0xf000) | (metatile & 0xfff);
+ }
+}
+
+void MapGridSetMetatileEntryAt(s32 x, s32 y, u16 metatile)
+{
+ s32 i;
+ if (x >= 0 && x < VMap.Xsize
+ && y >= 0 && y < VMap.Ysize)
+ {
+ i = x + VMap.Xsize * y;
+ VMap.map[i] = metatile;
+ }
+}
+
+void sub_8059024(s32 x, s32 y, bool32 arg2)
+{
+ if (x >= 0 && x < VMap.Xsize
+ && y >= 0 && y < VMap.Ysize)
+ {
+ if (arg2)
+ {
+ VMap.map[x + VMap.Xsize * y] |= 0x0C00;
+ }
+ else
+ {
+ VMap.map[x + VMap.Xsize * y] &= ~0x0C00;
+ }
+ }
+}
+
+u32 GetBehaviorByMetatileIdAndMapData(struct MapData *mapData, u16 metatile, u8 attr)
+{
+ u32 * attributes;
+
+ if (metatile < NUM_METATILES_IN_PRIMARY)
+ {
+ attributes = mapData->primaryTileset->metatileAttributes;
+ return sub_8058F1C(attributes[metatile], attr);
+ }
+ else if (metatile < 0x400)
+ {
+ attributes = mapData->secondaryTileset->metatileAttributes;
+ return sub_8058F1C(attributes[metatile - NUM_METATILES_IN_PRIMARY], attr);
+ }
+ else
+ {
+ return 0xFF;
+ }
+}
+
+void save_serialize_map(void)
+{
+ s32 i, j;
+ s32 x, y;
+ u16 *mapView;
+ s32 width;
+ mapView = gSaveBlock2Ptr->mapView;
+ width = VMap.Xsize;
+ x = gSaveBlock1Ptr->pos.x;
+ y = gSaveBlock1Ptr->pos.y;
+ for (i = y; i < y + 14; i++)
+ {
+ for (j = x; j < x + 15; j++)
+ {
+ *mapView++ = gBackupMapData[width * i + j];
+ }
+ }
+}
+
+bool32 SavedMapViewIsEmpty(void)
+{
+ u16 i;
+ u32 marker = 0;
+
+ // BUG: This loop extends past the bounds of the mapView array. Its size is only 0x100.
+ for (i = 0; i < 0x200; i++)
+ marker |= gSaveBlock2Ptr->mapView[i];
+
+ if (marker == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void ClearSavedMapView(void)
+{
+ CpuFill16(0, gSaveBlock2Ptr->mapView, sizeof(gSaveBlock2Ptr->mapView));
+}
+
+void LoadSavedMapView(void)
+{
+ s32 i, j;
+ s32 x, y;
+ u16 *mapView;
+ s32 width;
+ mapView = gSaveBlock2Ptr->mapView;
+ if (!SavedMapViewIsEmpty())
+ {
+ width = VMap.Xsize;
+ x = gSaveBlock1Ptr->pos.x;
+ y = gSaveBlock1Ptr->pos.y;
+ for (i = y; i < y + 14; i++)
+ {
+ for (j = x; j < x + 15; j++)
+ {
+ gBackupMapData[j + width * i] = *mapView;
+ mapView++;
+ }
+ }
+ ClearSavedMapView();
+ }
+}
+
+void sub_8059250(u8 a1)
+{
+ s32 width;
+ u16 *mapView;
+ s32 x0, y0;
+ s32 x2, y2;
+ u16 *src, *dest;
+ s32 srci, desti;
+ s32 r9, r8;
+ s32 x, y;
+ s32 i, j;
+ mapView = gSaveBlock2Ptr->mapView;
+ width = VMap.Xsize;
+ r9 = 0;
+ r8 = 0;
+ x0 = gSaveBlock1Ptr->pos.x;
+ y0 = gSaveBlock1Ptr->pos.y;
+ x2 = 15;
+ y2 = 14;
+ switch (a1)
+ {
+ case CONNECTION_NORTH:
+ y0 += 1;
+ y2 = 13;
+ break;
+ case CONNECTION_SOUTH:
+ r8 = 1;
+ y2 = 13;
+ break;
+ case CONNECTION_WEST:
+ x0 += 1;
+ x2 = 14;
+ break;
+ case CONNECTION_EAST:
+ r9 = 1;
+ x2 = 14;
+ break;
+ }
+ for (y = 0; y < y2; y++)
+ {
+ i = 0;
+ j = 0;
+ for (x = 0; x < x2; x++)
+ {
+ desti = width * (y + y0);
+ srci = (y + r8) * 15 + r9;
+ src = &mapView[srci + i];
+ dest = &gBackupMapData[x0 + desti + j];
+ *dest = *src;
+ i++;
+ j++;
+ }
+ }
+ ClearSavedMapView();
+}
+
+s32 GetMapBorderIdAt(s32 x, s32 y)
+{
+ if (MapGridGetTileAt(x, y) == 0x3FF)
+ {
+ return -1;
+ }
+
+ if (x >= VMap.Xsize - 8)
+ {
+ if (!gMapConnectionFlags.east)
+ {
+ return -1;
+ }
+ return CONNECTION_EAST;
+ }
+
+ if (x < 7)
+ {
+ if (!gMapConnectionFlags.west)
+ {
+ return -1;
+ }
+ return CONNECTION_WEST;
+ }
+
+ if (y >= VMap.Ysize - 7)
+ {
+ if (!gMapConnectionFlags.south)
+ {
+ return -1;
+ }
+ return CONNECTION_SOUTH;
+ }
+
+ if (y < 7)
+ {
+ if (!gMapConnectionFlags.north)
+ {
+ return -1;
+ }
+ return CONNECTION_NORTH;
+ }
+
+ return 0;
+}
+
+s32 GetPostCameraMoveMapBorderId(s32 x, s32 y)
+{
+ return GetMapBorderIdAt(7 + gSaveBlock1Ptr->pos.x + x, 7 + gSaveBlock1Ptr->pos.y + y);
+}
+
+bool32 CanCameraMoveInDirection(s32 direction)
+{
+ s32 x, y;
+
+ x = gSaveBlock1Ptr->pos.x + 7 + gDirectionToVectors[direction].x;
+ y = gSaveBlock1Ptr->pos.y + 7 + gDirectionToVectors[direction].y;
+ if (GetMapBorderIdAt(x, y) == -1)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void sub_80594AC(struct MapConnection *connection, int direction, s32 x, s32 y)
+{
+ struct MapHeader const *mapHeader;
+ mapHeader = mapconnection_get_mapheader(connection);
+ switch (direction)
+ {
+ case CONNECTION_EAST:
+ gSaveBlock1Ptr->pos.x = -x;
+ gSaveBlock1Ptr->pos.y -= connection->offset;
+ break;
+ case CONNECTION_WEST:
+ gSaveBlock1Ptr->pos.x = mapHeader->mapData->width;
+ gSaveBlock1Ptr->pos.y -= connection->offset;
+ break;
+ case CONNECTION_SOUTH:
+ gSaveBlock1Ptr->pos.x -= connection->offset;
+ gSaveBlock1Ptr->pos.y = -y;
+ break;
+ case CONNECTION_NORTH:
+ gSaveBlock1Ptr->pos.x -= connection->offset;
+ gSaveBlock1Ptr->pos.y = mapHeader->mapData->height;
+ break;
+ }
+}
+
+bool8 CameraMove(s32 x, s32 y)
+{
+ u32 direction;
+ struct MapConnection *connection;
+ s32 old_x, old_y;
+ gCamera.active = FALSE;
+ direction = GetPostCameraMoveMapBorderId(x, y);
+ if (direction + 1 <= 1)
+ {
+ gSaveBlock1Ptr->pos.x += x;
+ gSaveBlock1Ptr->pos.y += y;
+ }
+ else
+ {
+ save_serialize_map();
+ old_x = gSaveBlock1Ptr->pos.x;
+ old_y = gSaveBlock1Ptr->pos.y;
+ connection = sub_8059600(direction, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y);
+ sub_80594AC(connection, direction, x, y);
+ sub_8055864(connection->mapGroup, connection->mapNum);
+ gCamera.active = TRUE;
+ gCamera.x = old_x - gSaveBlock1Ptr->pos.x;
+ gCamera.y = old_y - gSaveBlock1Ptr->pos.y;
+ gSaveBlock1Ptr->pos.x += x;
+ gSaveBlock1Ptr->pos.y += y;
+ sub_8059250(direction);
+ }
+ return gCamera.active;
+}
+
+struct MapConnection *sub_8059600(u8 direction, s32 x, s32 y)
+{
+ s32 count;
+ struct MapConnection *connection;
+ s32 i;
+ count = gMapHeader.connections->count;
+ connection = gMapHeader.connections->connections;
+ for (i = 0; i < count; i++, connection++)
+ {
+ if (connection->direction == direction && sub_8059658(direction, x, y, connection) == TRUE)
+ return connection;
+ }
+ return NULL;
+
+}
+
+bool8 sub_8059658(u8 direction, s32 x, s32 y, struct MapConnection *connection)
+{
+ struct MapHeader const *mapHeader;
+ mapHeader = mapconnection_get_mapheader(connection);
+ switch (direction)
+ {
+ case CONNECTION_SOUTH:
+ case CONNECTION_NORTH:
+ return sub_80596BC(x, gMapHeader.mapData->width, mapHeader->mapData->width, connection->offset);
+ case CONNECTION_WEST:
+ case CONNECTION_EAST:
+ return sub_80596BC(y, gMapHeader.mapData->height, mapHeader->mapData->height, connection->offset);
+ }
+ return FALSE;
+}
+
+bool8 sub_80596BC(s32 x, s32 src_width, s32 dest_width, s32 offset)
+{
+ s32 offset2 = max(offset, 0);
+
+ if (dest_width + offset < src_width)
+ src_width = dest_width + offset;
+
+ if (offset2 <= x && x <= src_width)
+ return TRUE;
+
+ return FALSE;
+}
+
+bool32 sub_80596E8(s32 x, s32 width)
+{
+ if (x >= 0 && x < width)
+ return TRUE;
+
+ return FALSE;
+}
+
+s32 sub_80596FC(struct MapConnection *connection, s32 x, s32 y)
+{
+ struct MapHeader const *mapHeader;
+ mapHeader = mapconnection_get_mapheader(connection);
+ switch (connection->direction)
+ {
+ case CONNECTION_SOUTH:
+ case CONNECTION_NORTH:
+ return sub_80596E8(x - connection->offset, mapHeader->mapData->width);
+ case CONNECTION_WEST:
+ case CONNECTION_EAST:
+ return sub_80596E8(y - connection->offset, mapHeader->mapData->height);
+ }
+ return FALSE;
+}
+
+struct MapConnection *sub_805973C(s16 x, s16 y)
+{
+ s32 count;
+ struct MapConnection *connection;
+ s32 i;
+ u8 direction;
+ if (!gMapHeader.connections)
+ {
+ return NULL;
+ }
+ else
+ {
+ count = gMapHeader.connections->count;
+ connection = gMapHeader.connections->connections;
+ for (i = 0; i < count; i++, connection++)
+ {
+ direction = connection->direction;
+ if ((direction == CONNECTION_DIVE || direction == CONNECTION_EMERGE)
+ || (direction == CONNECTION_NORTH && y > 6)
+ || (direction == CONNECTION_SOUTH && y < gMapHeader.mapData->height + 7)
+ || (direction == CONNECTION_WEST && x > 6)
+ || (direction == CONNECTION_EAST && x < gMapHeader.mapData->width + 7))
+ {
+ continue;
+ }
+ if (sub_80596FC(connection, x - 7, y - 7) == TRUE)
+ {
+ return connection;
+ }
+ }
+ }
+ return NULL;
+}
+
+void SetCameraFocusCoords(u16 x, u16 y)
+{
+ gSaveBlock1Ptr->pos.x = x - 7;
+ gSaveBlock1Ptr->pos.y = y - 7;
+}
+
+void GetCameraFocusCoords(u16 *x, u16 *y)
+{
+ *x = gSaveBlock1Ptr->pos.x + 7;
+ *y = gSaveBlock1Ptr->pos.y + 7;
+}
+
+void SetCameraCoords(u16 x, u16 y)
+{
+ gSaveBlock1Ptr->pos.x = x;
+ gSaveBlock1Ptr->pos.y = y;
+}
+
+void GetCameraCoords(u16 *x, u16 *y)
+{
+ *x = gSaveBlock1Ptr->pos.x;
+ *y = gSaveBlock1Ptr->pos.y;
+}
+void copy_tileset_patterns_to_vram(struct Tileset const *tileset, u16 numTiles, u16 offset)
+{
+ if (tileset)
+ {
+ if (!tileset->isCompressed)
+ LoadBgTiles(2, tileset->tiles, numTiles * 32, offset);
+ else
+ sub_80F68F0(2, tileset->tiles, numTiles * 32, offset, 0);
+ }
+}
+
+void copy_tileset_patterns_to_vram2(struct Tileset const *tileset, u16 numTiles, u16 offset)
+{
+ if (tileset)
+ {
+ if (!tileset->isCompressed)
+ LoadBgTiles(2, tileset->tiles, numTiles * 32, offset);
+ else
+ sub_80F69E8(2, tileset->tiles, numTiles * 32, offset, 0);
+ }
+}
+
+void sub_80598CC(u16 a0, u16 a1)
+{
+ switch (gUnknown_2036E28)
+ {
+ case 0:
+ return;
+ case 1:
+ TintPalette_GrayScale(gPlttBufferUnfaded + a0, a1);
+ break;
+ case 2:
+ TintPalette_SepiaTone(gPlttBufferUnfaded + a0, a1);
+ break;
+ case 3:
+ sub_8111F38(a0, a1);
+ TintPalette_GrayScale(gPlttBufferUnfaded + a0, a1);
+ break;
+ default:
+ return;
+ }
+ CpuCopy16(gPlttBufferUnfaded + a0, gPlttBufferFaded + a0, a1 * sizeof(u16));
+}
+
+void sub_8059948(u8 a0, u8 a1)
+{
+ switch (gUnknown_2036E28)
+ {
+ case 0:
+ return;
+ case 1:
+ TintPalette_GrayScale(gPlttBufferUnfaded + a0 * 16, a1 * 16);
+ break;
+ case 2:
+ TintPalette_SepiaTone(gPlttBufferUnfaded + a0 * 16, a1 * 16);
+ break;
+ case 3:
+ sub_8111F38(a0 * 16, a1 * 16);
+ TintPalette_GrayScale(gPlttBufferUnfaded + a0 * 16, a1 * 16);
+ break;
+ default:
+ return;
+ }
+ CpuFastCopy(gPlttBufferUnfaded + a0 * 16, gPlttBufferFaded + a0 * 16, a1 * 16 * sizeof(u16));
+}
+
+void apply_map_tileset_palette(struct Tileset const *tileset, u16 destOffset, u16 size)
+{
+ u16 black = RGB_BLACK;
+
+ if (tileset)
+ {
+ if (tileset->isSecondary == FALSE)
+ {
+ LoadPalette(&black, destOffset, 2);
+ LoadPalette(((u16*)tileset->palettes) + 1, destOffset + 1, size - 2);
+ sub_80598CC(destOffset + 1, (size - 2) >> 1);
+ }
+ else if (tileset->isSecondary == TRUE)
+ {
+ LoadPalette(((u16*)tileset->palettes) + (NUM_PALS_IN_PRIMARY * 16), destOffset, size);
+ sub_80598CC(destOffset, size >> 1);
+ }
+ else
+ {
+ LoadCompressedPalette((u32*)tileset->palettes, destOffset, size);
+ sub_80598CC(destOffset, size >> 1);
+ }
+ }
+}
+
+void copy_map_tileset1_to_vram(const struct MapData *mapData)
+{
+ copy_tileset_patterns_to_vram(mapData->primaryTileset, NUM_TILES_IN_PRIMARY, 0);
+}
+
+void copy_map_tileset2_to_vram(const struct MapData *mapData)
+{
+ copy_tileset_patterns_to_vram(mapData->secondaryTileset, NUM_TILES_TOTAL - NUM_TILES_IN_PRIMARY, NUM_TILES_IN_PRIMARY);
+}
+
+void copy_map_tileset2_to_vram_2(const struct MapData *mapData)
+{
+ copy_tileset_patterns_to_vram2(mapData->secondaryTileset, NUM_TILES_TOTAL - NUM_TILES_IN_PRIMARY, NUM_TILES_IN_PRIMARY);
+}
+
+void apply_map_tileset1_palette(const struct MapData *mapData)
+{
+ apply_map_tileset_palette(mapData->primaryTileset, 0, NUM_PALS_IN_PRIMARY * 16 * 2);
+}
+
+void apply_map_tileset2_palette(const struct MapData *mapData)
+{
+ apply_map_tileset_palette(mapData->secondaryTileset, NUM_PALS_IN_PRIMARY * 16, (NUM_PALS_TOTAL - NUM_PALS_IN_PRIMARY) * 16 * 2);
+}
+
+void copy_map_tileset1_tileset2_to_vram(struct MapData const *mapData)
+{
+ if (mapData)
+ {
+ copy_tileset_patterns_to_vram2(mapData->primaryTileset, NUM_TILES_IN_PRIMARY, 0);
+ copy_tileset_patterns_to_vram2(mapData->secondaryTileset, NUM_TILES_TOTAL - NUM_TILES_IN_PRIMARY, NUM_TILES_IN_PRIMARY);
+ }
+}
+
+void apply_map_tileset1_tileset2_palette(struct MapData const *mapData)
+{
+ if (mapData)
+ {
+ apply_map_tileset1_palette(mapData);
+ apply_map_tileset2_palette(mapData);
+ }
+}
diff --git a/src/fldeff_berrytree.c b/src/fldeff_berrytree.c
new file mode 100644
index 000000000..90ca36508
--- /dev/null
+++ b/src/fldeff_berrytree.c
@@ -0,0 +1,4 @@
+void nullsub_56(void)
+{
+
+}
diff --git a/src/fldeff_softboiled.c b/src/fldeff_softboiled.c
new file mode 100644
index 000000000..50c715388
--- /dev/null
+++ b/src/fldeff_softboiled.c
@@ -0,0 +1,109 @@
+#include "global.h"
+#include "party_menu.h"
+#include "sound.h"
+#include "string_util.h"
+#include "menu.h"
+#include "constants/songs.h"
+
+void sub_80E57E8(u8 taskId);
+void sub_80E583C(u8 taskId);
+void sub_80E58A0(u8 taskId);
+void sub_80E5934(u8 taskId);
+
+extern const u8 gUnknown_84169F8[];
+extern const u8 gUnknown_8416F27[];
+
+bool8 hm_prepare_dive_probably(void)
+{
+ u16 maxHp = GetMonData(&gPlayerParty[GetCursorSelectionMonId()], MON_DATA_MAX_HP);
+ u16 curHp = GetMonData(&gPlayerParty[GetCursorSelectionMonId()], MON_DATA_HP);
+
+ if (curHp > maxHp / 5)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void sub_80E56DC(u8 taskId)
+{
+ gUnknown_203B0A0.unkB = 10;
+ gUnknown_203B0A0.unkA = gUnknown_203B0A0.unk9;
+ sub_811F818(GetCursorSelectionMonId(), 1);
+ sub_8121D0C(5);
+ gTasks[taskId].func = sub_811FB28;
+}
+
+void sub_80E5724(u8 taskId)
+{
+ u8 r8 = gUnknown_203B0A0.unk9;
+ u8 r5 = gUnknown_203B0A0.unkA;
+ u16 curHp;
+ s16 delta;
+
+ if (r5 > 6)
+ {
+ gUnknown_203B0A0.unkB = 0;
+ sub_8121D0C(0);
+ gTasks[taskId].func = sub_811FB28;
+ }
+ else
+ {
+ curHp = GetMonData(&gPlayerParty[r5], MON_DATA_HP);
+ if (curHp == 0 || r8 == r5 || GetMonData(&gPlayerParty[r5], MON_DATA_MAX_HP) == curHp)
+ {
+ sub_80E5934(taskId);
+ }
+ else
+ {
+ PlaySE(SE_KAIFUKU);
+ sub_8120760(taskId, r8, -1, GetMonData(&gPlayerParty[r8], MON_DATA_MAX_HP) / 5, sub_80E57E8);
+ }
+ }
+}
+
+void sub_80E57E8(u8 taskId)
+{
+ PlaySE(SE_KAIFUKU);
+ sub_8120760(taskId, gUnknown_203B0A0.unkA, 1, GetMonData(&gPlayerParty[gUnknown_203B0A0.unk9], MON_DATA_MAX_HP) / 5, sub_80E583C);
+}
+
+void sub_80E583C(u8 taskId)
+{
+ GetMonNickname(&gPlayerParty[gUnknown_203B0A0.unkA], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gUnknown_8416F27);
+ sub_81202F8(gStringVar4, 0);
+ schedule_bg_copy_tilemap_to_vram(2);
+ gTasks[taskId].func = sub_80E58A0;
+}
+
+void sub_80E58A0(u8 taskId)
+{
+ if (sub_8120370() != TRUE)
+ {
+ gUnknown_203B0A0.unkB = 0;
+ sub_811F818(gUnknown_203B0A0.unk9, 0);
+ gUnknown_203B0A0.unk9 = gUnknown_203B0A0.unkA;
+ sub_811F818(gUnknown_203B0A0.unkA, 1);
+ ClearMenuWindow(6, 0);
+ ClearWindowTilemap(6);
+ sub_8121D0C(0);
+ gTasks[taskId].func = sub_811FB28;
+ }
+}
+
+void sub_80E5900(u8 taskId)
+{
+ if (sub_8120370() != TRUE)
+ {
+ sub_8121D0C(5);
+ gTasks[taskId].func = sub_811FB28;
+ }
+}
+
+void sub_80E5934(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ sub_81202F8(gUnknown_84169F8, 0);
+ schedule_bg_copy_tilemap_to_vram(2);
+ gTasks[taskId].func = sub_80E5900;
+}
diff --git a/src/fldeff_teleport.c b/src/fldeff_teleport.c
new file mode 100644
index 000000000..74fad1110
--- /dev/null
+++ b/src/fldeff_teleport.c
@@ -0,0 +1,42 @@
+#include "global.h"
+#include "field_effect.h"
+#include "field_player_avatar.h"
+#include "fldeff.h"
+#include "party_menu.h"
+#include "overworld.h"
+
+static void FieldCallback_Teleport(void);
+static void StartTeleportFieldEffect(void);
+
+bool8 SetUpFieldMove_Teleport(void)
+{
+ if (Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE)
+ {
+ gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
+ gPostMenuFieldCallback = FieldCallback_Teleport;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void FieldCallback_Teleport(void)
+{
+ Overworld_ResetStateAfterTeleport();
+ FieldEffectStart(FLDEFF_USE_TELEPORT);
+ gFieldEffectArguments[0] = (u32)GetCursorSelectionMonId();
+}
+
+bool8 FldEff_UseTeleport(void)
+{
+ u8 taskId = oei_task_add();
+ gTasks[taskId].data[8] = (u32)StartTeleportFieldEffect >> 16;
+ gTasks[taskId].data[9] = (u32)StartTeleportFieldEffect;
+ SetPlayerAvatarTransitionFlags(PLAYER_AVATAR_FLAG_ON_FOOT);
+ return FALSE;
+}
+
+static void StartTeleportFieldEffect(void)
+{
+ FieldEffectActiveListRemove(FLDEFF_USE_TELEPORT);
+ CreateTeleportFieldEffectTask();
+}
diff --git a/src/heal_location.c b/src/heal_location.c
new file mode 100644
index 000000000..9756f0951
--- /dev/null
+++ b/src/heal_location.c
@@ -0,0 +1,176 @@
+#include "global.h"
+#include "heal_location.h"
+#include "event_data.h"
+#include "constants/vars.h"
+#include "constants/maps.h"
+#include "constants/spawn_points.h"
+
+void SetBlackoutRespawnHealerNpcAsLastTalked(u32 healLocationIdx);
+
+// This array defines the fly points for unlocked spawns.
+static const struct HealLocation sSpawnPoints[] = {
+ [SPAWN_PALLET_TOWN - 1] = {MAP_GROUP(PALLET_TOWN), MAP_NUM(PALLET_TOWN), 0x06, 0x08},
+ [SPAWN_VIRIDIAN_CITY - 1] = {MAP_GROUP(VIRIDIAN_CITY), MAP_NUM(VIRIDIAN_CITY), 0x1a, 0x1b},
+ [SPAWN_PEWTER_CITY - 1] = {MAP_GROUP(PEWTER_CITY), MAP_NUM(PEWTER_CITY), 0x11, 0x1a},
+ [SPAWN_CERULEAN_CITY - 1] = {MAP_GROUP(CERULEAN_CITY), MAP_NUM(CERULEAN_CITY), 0x16, 0x14},
+ [SPAWN_LAVENDER_TOWN - 1] = {MAP_GROUP(LAVENDER_TOWN), MAP_NUM(LAVENDER_TOWN), 0x06, 0x06},
+ [SPAWN_VERMILION_CITY - 1] = {MAP_GROUP(VERMILION_CITY), MAP_NUM(VERMILION_CITY), 0x0f, 0x07},
+ [SPAWN_CELADON_CITY - 1] = {MAP_GROUP(CELADON_CITY), MAP_NUM(CELADON_CITY), 0x30, 0x0c},
+ [SPAWN_FUCHSIA_CITY - 1] = {MAP_GROUP(FUCHSIA_CITY), MAP_NUM(FUCHSIA_CITY), 0x19, 0x20},
+ [SPAWN_CINNABAR_ISLAND - 1] = {MAP_GROUP(CINNABAR_ISLAND), MAP_NUM(CINNABAR_ISLAND), 0x0e, 0x0c},
+ [SPAWN_INDIGO_PLATEAU - 1] = {MAP_GROUP(INDIGO_PLATEAU_EXTERIOR), MAP_NUM(INDIGO_PLATEAU_EXTERIOR), 0x0b, 0x07},
+ [SPAWN_SAFFRON_CITY - 1] = {MAP_GROUP(SAFFRON_CITY_DUPLICATE), MAP_NUM(SAFFRON_CITY_DUPLICATE), 0x18, 0x27},
+ [SPAWN_ROUTE4 - 1] = {MAP_GROUP(ROUTE4), MAP_NUM(ROUTE4), 0x0c, 0x06},
+ [SPAWN_ROUTE10 - 1] = {MAP_GROUP(ROUTE10), MAP_NUM(ROUTE10), 0x0d, 0x15},
+ [SPAWN_ONE_ISLAND - 1] = {MAP_GROUP(ONE_ISLAND), MAP_NUM(ONE_ISLAND), 0x0e, 0x06},
+ [SPAWN_TWO_ISLAND - 1] = {MAP_GROUP(TWO_ISLAND), MAP_NUM(TWO_ISLAND), 0x15, 0x08},
+ [SPAWN_THREE_ISLAND - 1] = {MAP_GROUP(THREE_ISLAND), MAP_NUM(THREE_ISLAND), 0x0e, 0x1c},
+ [SPAWN_FOUR_ISLAND - 1] = {MAP_GROUP(FOUR_ISLAND), MAP_NUM(FOUR_ISLAND), 0x12, 0x15},
+ [SPAWN_FIVE_ISLAND - 1] = {MAP_GROUP(FIVE_ISLAND), MAP_NUM(FIVE_ISLAND), 0x12, 0x07},
+ [SPAWN_SEVEN_ISLAND - 1] = {MAP_GROUP(SEVEN_ISLAND), MAP_NUM(SEVEN_ISLAND), 0x0c, 0x04},
+ [SPAWN_SIX_ISLAND - 1] = {MAP_GROUP(SIX_ISLAND), MAP_NUM(SIX_ISLAND), 0x0b, 0x0c},
+};
+
+// This array defines the map where you actually respawn when you black out,
+// based on where you last checkpointed.
+// This is either the player's house or a Pokémon Center.
+// The data are u16 instead of u8 for reasons unknown.
+const u16 sBlackoutRespawnHealCenterMapIdxs[][2] = {
+ [SPAWN_PALLET_TOWN - 1] = {MAP_GROUP(PALLET_TOWN_PLAYERS_HOUSE_1F), MAP_NUM(PALLET_TOWN_PLAYERS_HOUSE_1F)},
+ [SPAWN_VIRIDIAN_CITY - 1] = {MAP_GROUP(VIRIDIAN_CITY_POKEMON_CENTER_1F), MAP_NUM(VIRIDIAN_CITY_POKEMON_CENTER_1F)},
+ [SPAWN_PEWTER_CITY - 1] = {MAP_GROUP(PEWTER_CITY_POKEMON_CENTER_1F), MAP_NUM(PEWTER_CITY_POKEMON_CENTER_1F)},
+ [SPAWN_CERULEAN_CITY - 1] = {MAP_GROUP(CERULEAN_CITY_POKEMON_CENTER_1F), MAP_NUM(CERULEAN_CITY_POKEMON_CENTER_1F)},
+ [SPAWN_LAVENDER_TOWN - 1] = {MAP_GROUP(LAVENDER_TOWN_POKEMON_CENTER_1F), MAP_NUM(LAVENDER_TOWN_POKEMON_CENTER_1F)},
+ [SPAWN_VERMILION_CITY - 1] = {MAP_GROUP(VERMILION_CITY_POKEMON_CENTER_1F), MAP_NUM(VERMILION_CITY_POKEMON_CENTER_1F)},
+ [SPAWN_CELADON_CITY - 1] = {MAP_GROUP(CELADON_CITY_POKEMON_CENTER_1F), MAP_NUM(CELADON_CITY_POKEMON_CENTER_1F)},
+ [SPAWN_FUCHSIA_CITY - 1] = {MAP_GROUP(FUCHSIA_CITY_POKEMON_CENTER_1F), MAP_NUM(FUCHSIA_CITY_POKEMON_CENTER_1F)},
+ [SPAWN_CINNABAR_ISLAND - 1] = {MAP_GROUP(CINNABAR_ISLAND_POKEMON_CENTER_1F), MAP_NUM(CINNABAR_ISLAND_POKEMON_CENTER_1F)},
+ [SPAWN_INDIGO_PLATEAU - 1] = {MAP_GROUP(INDIGO_PLATEAU_POKEMON_CENTER_1F), MAP_NUM(INDIGO_PLATEAU_POKEMON_CENTER_1F)},
+ [SPAWN_SAFFRON_CITY - 1] = {MAP_GROUP(SAFFRON_CITY_POKEMON_CENTER_1F), MAP_NUM(SAFFRON_CITY_POKEMON_CENTER_1F)},
+ [SPAWN_ROUTE4 - 1] = {MAP_GROUP(ROUTE4_POKEMON_CENTER_1F), MAP_NUM(ROUTE4_POKEMON_CENTER_1F)},
+ [SPAWN_ROUTE10 - 1] = {MAP_GROUP(ROUTE10_POKEMON_CENTER_1F), MAP_NUM(ROUTE10_POKEMON_CENTER_1F)},
+ [SPAWN_ONE_ISLAND - 1] = {MAP_GROUP(ONE_ISLAND_POKEMON_CENTER_1F), MAP_NUM(ONE_ISLAND_POKEMON_CENTER_1F)},
+ [SPAWN_TWO_ISLAND - 1] = {MAP_GROUP(TWO_ISLAND_POKEMON_CENTER_1F), MAP_NUM(TWO_ISLAND_POKEMON_CENTER_1F)},
+ [SPAWN_THREE_ISLAND - 1] = {MAP_GROUP(THREE_ISLAND_POKEMON_CENTER_1F), MAP_NUM(THREE_ISLAND_POKEMON_CENTER_1F)},
+ [SPAWN_FOUR_ISLAND - 1] = {MAP_GROUP(FOUR_ISLAND_POKEMON_CENTER_1F), MAP_NUM(FOUR_ISLAND_POKEMON_CENTER_1F)},
+ [SPAWN_FIVE_ISLAND - 1] = {MAP_GROUP(FIVE_ISLAND_POKEMON_CENTER_1F), MAP_NUM(FIVE_ISLAND_POKEMON_CENTER_1F)},
+ [SPAWN_SEVEN_ISLAND - 1] = {MAP_GROUP(SEVEN_ISLAND_POKEMON_CENTER_1F), MAP_NUM(SEVEN_ISLAND_POKEMON_CENTER_1F)},
+ [SPAWN_SIX_ISLAND - 1] = {MAP_GROUP(SIX_ISLAND_POKEMON_CENTER_1F), MAP_NUM(SIX_ISLAND_POKEMON_CENTER_1F)}
+};
+
+// When you respawn, your character scurries back to either their house
+// or a Pokémon Center, and hands their fainted Pokémon to their mother
+// or the Nurse for healing.
+// This array defines the index of the NPC on the map defined above
+// with whom your character interacts in this cutscene.
+static const u8 sBlackoutRespawnHealerNpcIds[] = {
+ [SPAWN_PALLET_TOWN - 1] = 1,
+ [SPAWN_VIRIDIAN_CITY - 1] = 1,
+ [SPAWN_PEWTER_CITY - 1] = 3,
+ [SPAWN_CERULEAN_CITY - 1] = 1,
+ [SPAWN_LAVENDER_TOWN - 1] = 1,
+ [SPAWN_VERMILION_CITY - 1] = 1,
+ [SPAWN_CELADON_CITY - 1] = 1,
+ [SPAWN_FUCHSIA_CITY - 1] = 1,
+ [SPAWN_CINNABAR_ISLAND - 1] = 1,
+ [SPAWN_INDIGO_PLATEAU - 1] = 2,
+ [SPAWN_SAFFRON_CITY - 1] = 1,
+ [SPAWN_ROUTE4 - 1] = 1,
+ [SPAWN_ROUTE10 - 1] = 1,
+ [SPAWN_ONE_ISLAND - 1] = 1,
+ [SPAWN_TWO_ISLAND - 1] = 1,
+ [SPAWN_THREE_ISLAND - 1] = 1,
+ [SPAWN_FOUR_ISLAND - 1] = 1,
+ [SPAWN_FIVE_ISLAND - 1] = 1,
+ [SPAWN_SEVEN_ISLAND - 1] = 1,
+ [SPAWN_SIX_ISLAND - 1] = 1
+};
+
+u32 GetHealLocationIndexFromMapGroupAndNum(u16 mapGroup, u16 mapNum)
+{
+ u32 i;
+
+ for (i = 0; i < NELEMS(sSpawnPoints); i++) {
+ if (sSpawnPoints[i].group == mapGroup && sSpawnPoints[i].map == mapNum)
+ {
+ return i + 1;
+ }
+ }
+
+ return 0;
+}
+
+const struct HealLocation * GetHealLocationPointerFromMapGroupAndNum(u16 mapGroup, u16 mapNum)
+{
+ u32 i = GetHealLocationIndexFromMapGroupAndNum(mapGroup, mapNum);
+ if (i == 0)
+ return NULL;
+
+ return &sSpawnPoints[i - 1];
+}
+
+const struct HealLocation * GetHealLocationPointer(u32 idx)
+{
+ if (idx == 0)
+ return NULL;
+ if (idx > NELEMS(sSpawnPoints))
+ return NULL;
+ return &sSpawnPoints[idx - 1];
+}
+
+void SetBlackoutRespawnWarpAndHealerNpc(struct WarpData * warp)
+{
+ u32 healLocationIdx;
+
+ if (VarGet(VAR_0x4082) == 1)
+ {
+ if (!gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_2)
+ VarSet(VAR_0x4082, 0);
+ gSpecialVar_LastTalked = 1;
+ warp->x = 4;
+ warp->y = 11;
+ warp->mapGroup = MAP_GROUP(SEVEN_ISLAND_TRAINER_TOWER_LOBBY);
+ warp->mapNum = MAP_NUM(SEVEN_ISLAND_TRAINER_TOWER_LOBBY);
+ warp->warpId = 0xFF;
+ }
+ else
+ {
+ healLocationIdx = GetHealLocationIndexFromMapGroupAndNum(gSaveBlock1Ptr->lastHealLocation.mapGroup, gSaveBlock1Ptr->lastHealLocation.mapNum);
+ warp->mapGroup = sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][0];
+ warp->mapNum = sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][1];
+ warp->warpId = 0xFF;
+
+ if (sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][0] == MAP_GROUP(PALLET_TOWN_PLAYERS_HOUSE_1F) && sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][1] == MAP_NUM(PALLET_TOWN_PLAYERS_HOUSE_1F))
+ {
+ warp->x = 8;
+ warp->y = 5;
+ }
+ else if (sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][0] == MAP_GROUP(INDIGO_PLATEAU_POKEMON_CENTER_1F) && sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][1] == MAP_NUM(INDIGO_PLATEAU_POKEMON_CENTER_1F))
+ {
+ warp->x = 13;
+ warp->y = 12;
+ }
+ else if (sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][0] == MAP_GROUP(ONE_ISLAND_POKEMON_CENTER_1F) && sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][1] == MAP_NUM(ONE_ISLAND_POKEMON_CENTER_1F))
+ {
+ warp->x = 5;
+ warp->y = 4;
+ }
+ else if (sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][0] == MAP_GROUP(SEVEN_ISLAND_TRAINER_TOWER_LOBBY) && sBlackoutRespawnHealCenterMapIdxs[healLocationIdx - 1][1] == MAP_NUM(SEVEN_ISLAND_TRAINER_TOWER_LOBBY))
+ {
+ warp->x = 4;
+ warp->y = 11;
+ VarSet(VAR_0x4082, 0);
+ }
+ else
+ {
+ warp->x = 7;
+ warp->y = 4;
+ }
+ SetBlackoutRespawnHealerNpcAsLastTalked(healLocationIdx);
+ }
+}
+
+void SetBlackoutRespawnHealerNpcAsLastTalked(u32 healLocationIdx)
+{
+ gSpecialVar_LastTalked = sBlackoutRespawnHealerNpcIds[healLocationIdx - 1];
+}
diff --git a/src/help_system.c b/src/help_system.c
new file mode 100644
index 000000000..1fd43fffa
--- /dev/null
+++ b/src/help_system.c
@@ -0,0 +1,1202 @@
+#include "global.h"
+#include "decompress.h"
+#include "gpu_regs.h"
+#include "main.h"
+#include "m4a.h"
+#include "dma3.h"
+#include "help_system.h"
+#include "list_menu.h"
+#include "sound.h"
+#include "strings.h"
+#include "text.h"
+#include "blit.h"
+#include "event_data.h"
+#include "constants/songs.h"
+#include "constants/flags.h"
+
+extern u8 gGlyphInfo[];
+
+struct HelpSystemVideoState
+{
+ /*0x00*/ MainCallback savedVblankCb;
+ /*0x04*/ MainCallback savedHblankCb;
+ /*0x08*/ u16 savedDispCnt;
+ /*0x0a*/ u16 savedBg0Cnt;
+ /*0x0c*/ u16 savedBg0Hofs;
+ /*0x0e*/ u16 savedBg0Vofs;
+ /*0x10*/ u16 savedBldCnt;
+ /*0x12*/ struct TextColor savedTextColor;
+ /*0x15*/ u8 state;
+};
+
+static EWRAM_DATA u8 sMapTilesBackup[BG_CHAR_SIZE] = {0};
+EWRAM_DATA u8 gUnknown_203F174 = 0;
+EWRAM_DATA u8 gUnknown_203F175 = 0;
+static EWRAM_DATA u8 sDelayTimer = 0;
+static EWRAM_DATA u8 sInHelpSystem = 0;
+static EWRAM_DATA struct HelpSystemVideoState sVideoState = {0};
+EWRAM_DATA struct HelpSystemListMenu gHelpSystemListMenu = {0};
+EWRAM_DATA struct ListMenuItem gHelpSystemListMenuItems[52] = {0};
+
+static const u16 sTiles[] = INCBIN_U16("graphics/help_system/unk_8464008.4bpp");
+static const u16 sPals[] = INCBIN_U16("graphics/help_system/unk_8464008.gbapal");
+
+u8 RunHelpSystemCallback(void)
+{
+ s32 i;
+
+ switch (sVideoState.state)
+ {
+ case 0:
+ sInHelpSystem = 0;
+ if (gSaveBlock2Ptr->optionsButtonMode != OPTIONS_BUTTON_MODE_NORMAL)
+ return 0;
+ if (JOY_NEW(R_BUTTON) && gUnknown_203F175 == 1)
+ return 0;
+ if (JOY_NEW(L_BUTTON | R_BUTTON))
+ {
+ if (!sub_812B45C() || !gUnknown_3005ECC)
+ {
+ PlaySE(SE_HELP_PAGE);
+ return 0;
+ }
+ m4aMPlayStop(&gMPlayInfo_SE1);
+ m4aMPlayStop(&gMPlayInfo_SE2);
+ PlaySE(SE_HELP_OPEN);
+ if (!gUnknown_203F174)
+ m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x80);
+ SaveCallbacks();
+ sInHelpSystem = 1;
+ sVideoState.state = 1;
+ }
+ break;
+ case 1:
+ SaveMapTiles();
+ SaveMapGPURegs();
+ SaveMapTextColors();
+ (*(vu16 *)PLTT) = sPals[15];
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ sVideoState.state = 2;
+ break;
+ case 2:
+ RequestDma3Fill(0, (void *)BG_CHAR_ADDR(3), BG_CHAR_SIZE, 0);
+ RequestDma3Copy(sPals, (void *)PLTT, sizeof(sPals), 0);
+ RequestDma3Copy(sTiles, gDecompressionBuffer + 0x3EE0, sizeof(sTiles), 0);
+ sVideoState.state = 3;
+ break;
+ case 3:
+ sub_813BCF4();
+ HelpSystem_FillPanel3();
+ HelpSystem_FillPanel2();
+ HelpSystem_PrintText_Row61(gString_Help);
+ sub_813BD14(1);
+ if (sub_812B40C() == TRUE)
+ sub_812BC54(&gHelpSystemListMenu, gHelpSystemListMenuItems);
+ else
+ sub_812BCA8(&gHelpSystemListMenu, gHelpSystemListMenuItems);
+ sub_813BE78(1);
+ sub_813BF50(1);
+ CommitTilemap();
+ sVideoState.state = 4;
+ break;
+ case 4:
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(3) | BGCNT_16COLOR | BGCNT_SCREENBASE(31));
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_BG0_ON);
+ sVideoState.state = 5;
+ break;
+ case 5:
+ if (!sub_812BB9C(&gHelpSystemListMenu, gHelpSystemListMenuItems))
+ {
+ PlaySE(SE_HELP_CLOSE);
+ sVideoState.state = 6;
+ }
+ break;
+ case 6:
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ RestoreMapTiles();
+ for (i = 0; i < 0x200; i += 2)
+ {
+ *((vu16 *)(PLTT + 0x000 + i)) = sPals[15];
+ *((vu16 *)(PLTT + 0x200 + i)) = sPals[15];
+ }
+ sVideoState.state = 7;
+ break;
+ case 7:
+ if (!gUnknown_203F174)
+ m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x100);
+ RestoreMapTextColors();
+ RestoreGPURegs();
+ sVideoState.state = 8;
+ break;
+ case 8:
+ RestoreCallbacks();
+ sInHelpSystem = 0;
+ sVideoState.state = 0;
+ break;
+ }
+ return sVideoState.state;
+}
+
+void SaveCallbacks(void)
+{
+ vu16 * dma;
+ sVideoState.savedVblankCb = gMain.vblankCallback;
+ sVideoState.savedHblankCb = gMain.hblankCallback;
+ gMain.vblankCallback = NULL;
+ gMain.hblankCallback = NULL;
+
+ dma = (void *)REG_ADDR_DMA0;
+ dma[5] &= ~(DMA_START_MASK | DMA_DREQ_ON | DMA_REPEAT);
+ dma[5] &= ~DMA_ENABLE;
+ dma[5];
+}
+
+void SaveMapGPURegs(void)
+{
+ sVideoState.savedDispCnt = GetGpuReg(REG_OFFSET_DISPCNT);
+ sVideoState.savedBg0Cnt = GetGpuReg(REG_OFFSET_BG0CNT);
+ sVideoState.savedBg0Hofs = GetGpuReg(REG_OFFSET_BG0HOFS);
+ sVideoState.savedBg0Vofs = GetGpuReg(REG_OFFSET_BG0VOFS);
+ sVideoState.savedBldCnt = GetGpuReg(REG_OFFSET_BLDCNT);
+}
+
+void SaveMapTiles(void)
+{
+ RequestDma3Copy((void *)BG_CHAR_ADDR(3), sMapTilesBackup, BG_CHAR_SIZE, 0);
+}
+
+void SaveMapTextColors(void)
+{
+ SaveTextColors(
+ &sVideoState.savedTextColor.fgColor,
+ &sVideoState.savedTextColor.bgColor,
+ &sVideoState.savedTextColor.shadowColor
+ );
+}
+
+void RestoreCallbacks(void)
+{
+ gMain.vblankCallback = sVideoState.savedVblankCb;
+ gMain.hblankCallback = sVideoState.savedHblankCb;
+}
+
+void RestoreGPURegs(void)
+{
+ SetGpuReg(REG_OFFSET_BLDCNT, sVideoState.savedBldCnt);
+ SetGpuReg(REG_OFFSET_BG0HOFS, sVideoState.savedBg0Hofs);
+ SetGpuReg(REG_OFFSET_BG0VOFS, sVideoState.savedBg0Vofs);
+ SetGpuReg(REG_OFFSET_BG0CNT, sVideoState.savedBg0Cnt);
+ SetGpuReg(REG_OFFSET_DISPCNT, sVideoState.savedDispCnt);
+}
+
+void RestoreMapTiles(void)
+{
+ RequestDma3Copy(sMapTilesBackup, (void *)BG_CHAR_ADDR(3), BG_CHAR_SIZE, 0);
+}
+
+void RestoreMapTextColors(void)
+{
+ RestoreTextColors(
+ &sVideoState.savedTextColor.fgColor,
+ &sVideoState.savedTextColor.bgColor,
+ &sVideoState.savedTextColor.shadowColor
+ );
+}
+
+void CommitTilemap(void)
+{
+ RequestDma3Copy(gDecompressionBuffer, (void *)BG_CHAR_ADDR(3), BG_CHAR_SIZE, 0);
+}
+
+void HS_DrawBgTilemapRect(u16 baseTile, u8 left, u8 top, u8 width, u8 height, u16 increment)
+{
+ u16 i, j;
+
+ for (i = top; i < top + height; i++)
+ {
+ for (j = left; j < left + width; j++)
+ {
+ *((u16 *)(gDecompressionBuffer + 0x3800 + 64 * i + 2 * j)) = baseTile;
+ baseTile += increment;
+ }
+ }
+
+ CommitTilemap();
+}
+
+void sub_813BCF4(void)
+{
+ HS_DrawBgTilemapRect(0x1FF, 0, 0, 30, 20, 0);
+}
+
+void sub_813BD14(u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 1, 0, 7, 2, 0);
+ break;
+ case 1:
+ HS_DrawBgTilemapRect(0x1E8, 1, 0, 7, 2, 1);
+ break;
+ }
+}
+
+void sub_813BD5C(u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 13, 0, 16, 2, 0);
+ break;
+ case 1:
+ HS_DrawBgTilemapRect(0x1A0, 13, 0, 16, 2, 1);
+ break;
+ }
+}
+
+void sub_813BDA4(u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 2, 3, 26, 16, 0);
+ break;
+ case 1:
+ HS_DrawBgTilemapRect(0x000, 2, 3, 26, 16, 1);
+ break;
+ }
+}
+
+void sub_813BDE8(u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 1, 3, 28, 16, 0);
+ break;
+ case 1:
+ HS_DrawBgTilemapRect(0x1FA, 1, 3, 28, 17, 0);
+ break;
+ }
+}
+
+void sub_813BE30(u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 2, 14, 26, 5, 0);
+ break;
+ case 1:
+ HS_DrawBgTilemapRect(0x11E, 2, 14, 26, 5, 1);
+ break;
+ }
+}
+
+void sub_813BE78(u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 1, 2, 28, 1, 0);
+ HS_DrawBgTilemapRect(0x1FF, 1, 19, 28, 1, 0);
+ break;
+ case 1:
+ HS_DrawBgTilemapRect(0x1F7, 1, 2, 28, 1, 0);
+ HS_DrawBgTilemapRect(0x1F8, 1, 19, 28, 1, 0);
+ break;
+ }
+}
+
+void sub_813BEE4(u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 1, 2, 28, 1, 0);
+ HS_DrawBgTilemapRect(0x1FF, 1, 19, 28, 1, 0);
+ break;
+ case 1:
+ HS_DrawBgTilemapRect(0x1FB, 1, 2, 28, 1, 0);
+ HS_DrawBgTilemapRect(0x1FC, 1, 19, 28, 1, 0);
+ break;
+ }
+}
+
+void sub_813BF50(u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 0, 0, 1, 20, 0);
+ HS_DrawBgTilemapRect(0x1FF, 29, 0, 1, 20, 0);
+ break;
+ case 1:
+ HS_DrawBgTilemapRect(0x1F9, 0, 0, 1, 20, 0);
+ HS_DrawBgTilemapRect(0x1F9, 29, 0, 1, 20, 0);
+ break;
+ }
+}
+
+void sub_813BFC0(u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 1, 5, 28, 1, 0);
+ break;
+ case 1:
+ HS_DrawBgTilemapRect(0x1FC, 1, 5, 28, 1, 0);
+ break;
+ }
+}
+
+void sub_813C004(u8 a0, u8 mode)
+{
+ switch (mode)
+ {
+ case 0:
+ HS_DrawBgTilemapRect(0x1FF, 28, 3, 1, 1, 0);
+ HS_DrawBgTilemapRect(0x1FF, 28, 18, 1, 1, 0);
+ break;
+ case 1:
+ if (a0 == 0)
+ HS_DrawBgTilemapRect(0x1FE, 28, 3, 1, 1, 0);
+ else
+ HS_DrawBgTilemapRect(0x1FD, 28, 18, 1, 1, 0);
+ break;
+ }
+}
+
+#define HelpSystemHandleRenderGlyph(character) ({\
+ do {DecompressAndRenderGlyph(font, character, &srcBlit, &destBlit, dest, x, y, width, height);} while (0); font;\
+})
+
+#ifdef NONMATCHING
+void HelpSystemRenderText(u8 font, u8 * dest, const u8 * src, u8 x, u8 y, u8 width, u8 height)
+{
+ // font -> sp+24
+ // dest -> sp+28
+ // src -> r9
+ // x -> sp+34
+ // y -> r10
+ // width -> sp+2C
+ // height -> sp+30
+ struct Bitmap srcBlit;
+ struct Bitmap destBlit;
+ u8 i;
+ u8 orig_x = x;
+ s32 clearPixels;
+
+ while (1)
+ {
+ u16 curChar = *src++;
+ switch (curChar)
+ {
+ case EOS:
+ return;
+ case PLACEHOLDER_BEGIN:
+ curChar = *src++;
+ if (curChar == 1) {
+ for (i = 0; i < 10; i++)
+ {
+ if (gSaveBlock2Ptr->playerName[i] == EOS)
+ break;
+ HelpSystemHandleRenderGlyph(gSaveBlock2Ptr->playerName[i]);
+ x += gGlyphInfo[0x80];
+ }
+ }
+ else if (curChar == 2)
+ {
+ for (i = 0; ; i++)
+ {
+ if (FlagGet(FLAG_SYS_NOT_SOMEONES_PC) == TRUE)
+ {
+ if (gString_Bill[i] == EOS)
+ break;
+ HelpSystemHandleRenderGlyph(gString_Bill[i]);
+ }
+ else
+ {
+ if (gString_Someone[i] == EOS)
+ break;
+ HelpSystemHandleRenderGlyph(gString_Someone[i]);
+ }
+ x += gGlyphInfo[0x80];
+ }
+ }
+ break;
+ case CHAR_PROMPT_SCROLL:
+ case CHAR_PROMPT_CLEAR:
+ case CHAR_NEWLINE:
+ x = orig_x;
+ y += gGlyphInfo[0x81] + 1;
+ break;
+ case EXT_CTRL_CODE_BEGIN:
+ curChar = *src++;
+ switch (curChar)
+ {
+ case 4:
+ src++;
+ //fallthrough
+ case 11:
+ case 16:
+ src++;
+ //fallthrough
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 6:
+ case 8:
+ case 12:
+ case 13:
+ case 14:
+ src++;
+ break;
+ case 19:
+ clearPixels = *src + orig_x - x;
+ if (clearPixels > 0)
+ {
+ destBlit.pixels = dest;
+ destBlit.width = width * 8;
+ destBlit.height = height * 8;
+ FillBitmapRect4Bit(&destBlit, x, y, clearPixels, GetFontAttribute(font, 1), 0);
+ x += clearPixels;
+ }
+ src++;
+ break;
+ case 17:
+ case 18:
+ case 20:
+ src++;
+ break;
+ case 7:
+ case 9:
+ case 10:
+ case 15:
+ case 21:
+ case 22:
+ break;
+ }
+ break;
+ case CHAR_KEYPAD_ICON:
+ curChar = *src++;
+ srcBlit.pixels = (u8 *)gKeypadIconTiles + 0x20 * GetKeypadIconTileOffset(curChar);
+ srcBlit.width = 0x80;
+ srcBlit.height = 0x80;
+ destBlit.pixels = dest;
+ destBlit.width = width * 8;
+ destBlit.height = height * 8;
+ BlitBitmapRect4Bit(&srcBlit, &destBlit, 0, 0, x, y, GetKeypadIconWidth(curChar), GetKeypadIconHeight(curChar), 0);
+ x += GetKeypadIconWidth(curChar);
+ break;
+ case CHAR_EXTRA_EMOJI:
+ curChar = 0x100 | *src++;
+ //fallthrough
+ default:
+ if (curChar == CHAR_SPACE)
+ {
+ if (font == 0)
+ x += 5;
+ else
+ x += 4;
+ }
+ else
+ {
+ HelpSystemHandleRenderGlyph(curChar);
+ x += gGlyphInfo[0x80];
+ }
+ break;
+ }
+ }
+}
+#else
+NAKED
+void HelpSystemRenderText(u8 font, u8 * dest, const u8 * src, u8 x, u8 y, u8 width, u8 height)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmov r7, r10\n"
+ "\tmov r6, r9\n"
+ "\tmov r5, r8\n"
+ "\tpush {r5-r7}\n"
+ "\tsub sp, 0x38\n"
+ "\tstr r1, [sp, 0x28]\n"
+ "\tmov r9, r2\n"
+ "\tldr r1, [sp, 0x58]\n"
+ "\tldr r2, [sp, 0x5C]\n"
+ "\tldr r4, [sp, 0x60]\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r0, 24\n"
+ "\tstr r0, [sp, 0x24]\n"
+ "\tlsls r3, 24\n"
+ "\tlsrs r7, r3, 24\n"
+ "\tlsls r1, 24\n"
+ "\tlsrs r1, 24\n"
+ "\tmov r10, r1\n"
+ "\tlsls r2, 24\n"
+ "\tlsrs r2, 24\n"
+ "\tstr r2, [sp, 0x2C]\n"
+ "\tlsls r4, 24\n"
+ "\tlsrs r4, 24\n"
+ "\tstr r4, [sp, 0x30]\n"
+ "\tstr r7, [sp, 0x34]\n"
+ "_0813C0AC_masterLoop:\n"
+ "\tmov r0, r9\n"
+ "\tldrb r1, [r0]\n"
+ "\tmovs r2, 0x1\n"
+ "\tadd r9, r2\n"
+ "\tadds r0, r1, 0\n"
+ "\tsubs r0, 0xF8\n"
+ "\tcmp r0, 0x7\n"
+ "\tbls _0813C0BE\n"
+ "\tb _0813C358\n"
+ "_0813C0BE:\n"
+ "\tlsls r0, 2\n"
+ "\tldr r1, _0813C0C8 @ =_0813C0CC\n"
+ "\tadds r0, r1\n"
+ "\tldr r0, [r0]\n"
+ "\tmov pc, r0\n"
+ "\t.align 2, 0\n"
+ "_0813C0C8: .4byte _0813C0CC\n"
+ "\t.align 2, 0\n"
+ "_0813C0CC:\n"
+ "\t.4byte _0813C2D4\n"
+ "\t.4byte _0813C348\n"
+ "\t.4byte _0813C1E4\n"
+ "\t.4byte _0813C1E4\n"
+ "\t.4byte _0813C200\n"
+ "\t.4byte _0813C0EC\n"
+ "\t.4byte _0813C1E4\n"
+ "\t.4byte _0813C39C\n"
+ "_0813C0EC:\n"
+ "\tmov r0, r9\n"
+ "\tldrb r1, [r0]\n"
+ "\tmovs r2, 0x1\n"
+ "\tadd r9, r2\n"
+ "\tcmp r1, 0x1\n"
+ "\tbne _0813C154\n"
+ "\tmovs r4, 0\n"
+ "\tldr r0, _0813C14C @ =gSaveBlock2Ptr\n"
+ "\tldr r1, [r0]\n"
+ "\tldrb r1, [r1]\n"
+ "\tcmp r1, 0xFF\n"
+ "\tbeq _0813C0AC_masterLoop\n"
+ "\tldr r5, _0813C150 @ =gGlyphInfo + 0x80\n"
+ "_0813C106:\n"
+ "\tldr r0, [r0]\n"
+ "\tadds r0, r4\n"
+ "\tldrb r1, [r0]\n"
+ "\tldr r0, [sp, 0x28]\n"
+ "\tstr r0, [sp]\n"
+ "\tstr r7, [sp, 0x4]\n"
+ "\tmov r2, r10\n"
+ "\tstr r2, [sp, 0x8]\n"
+ "\tldr r0, [sp, 0x2C]\n"
+ "\tstr r0, [sp, 0xC]\n"
+ "\tldr r2, [sp, 0x30]\n"
+ "\tstr r2, [sp, 0x10]\n"
+ "\tldr r0, [sp, 0x24]\n"
+ "\tadd r2, sp, 0x14\n"
+ "\tadd r3, sp, 0x1C\n"
+ "\tbl DecompressAndRenderGlyph\n"
+ "\tldr r0, [sp, 0x24]\n"
+ "\tldrb r0, [r5]\n"
+ "\tadds r0, r7, r0\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r7, r0, 24\n"
+ "\tadds r0, r4, 0x1\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r4, r0, 24\n"
+ "\tcmp r4, 0x9\n"
+ "\tbhi _0813C0AC_masterLoop\n"
+ "\tldr r0, _0813C14C @ =gSaveBlock2Ptr\n"
+ "\tldr r1, [r0]\n"
+ "\tadds r1, r4\n"
+ "\tldrb r1, [r1]\n"
+ "\tcmp r1, 0xFF\n"
+ "\tbne _0813C106\n"
+ "\tb _0813C0AC_masterLoop\n"
+ "\t.align 2, 0\n"
+ "_0813C14C: .4byte gSaveBlock2Ptr\n"
+ "_0813C150: .4byte gGlyphInfo + 0x80\n"
+ "_0813C154:\n"
+ "\tcmp r1, 0x2\n"
+ "\tbne _0813C0AC_masterLoop\n"
+ "\tmovs r4, 0\n"
+ "\tldr r5, _0813C160 @ =gGlyphInfo + 0x80\n"
+ "\tb _0813C1BC\n"
+ "\t.align 2, 0\n"
+ "_0813C160: .4byte gGlyphInfo + 0x80\n"
+ "_0813C164:\n"
+ "\tldrb r1, [r1]\n"
+ "\tldr r2, [sp, 0x28]\n"
+ "\tstr r2, [sp]\n"
+ "\tstr r7, [sp, 0x4]\n"
+ "\tmov r0, r10\n"
+ "\tstr r0, [sp, 0x8]\n"
+ "\tldr r2, [sp, 0x2C]\n"
+ "\tstr r2, [sp, 0xC]\n"
+ "\tldr r0, [sp, 0x30]\n"
+ "\tstr r0, [sp, 0x10]\n"
+ "\tldr r0, [sp, 0x24]\n"
+ "\tadd r2, sp, 0x14\n"
+ "\tadd r3, sp, 0x1C\n"
+ "\tbl DecompressAndRenderGlyph\n"
+ "\tb _0813C1AC\n"
+ "_0813C184:\n"
+ "\tldr r0, _0813C1D8 @ =gString_Someone\n"
+ "\tadds r1, r4, r0\n"
+ "\tldrb r0, [r1]\n"
+ "\tcmp r0, 0xFF\n"
+ "\tbeq _0813C0AC_masterLoop\n"
+ "\tadds r1, r0, 0\n"
+ "\tldr r2, [sp, 0x28]\n"
+ "\tstr r2, [sp]\n"
+ "\tstr r7, [sp, 0x4]\n"
+ "\tmov r0, r10\n"
+ "\tstr r0, [sp, 0x8]\n"
+ "\tldr r2, [sp, 0x2C]\n"
+ "\tstr r2, [sp, 0xC]\n"
+ "\tldr r0, [sp, 0x30]\n"
+ "\tstr r0, [sp, 0x10]\n"
+ "\tldr r0, [sp, 0x24]\n"
+ "\tadd r2, sp, 0x14\n"
+ "\tadd r3, sp, 0x1C\n"
+ "\tbl DecompressAndRenderGlyph\n"
+ "_0813C1AC:\n"
+ "\tldr r1, [sp, 0x24]\n"
+ "\tldrb r0, [r5]\n"
+ "\tadds r0, r7, r0\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r7, r0, 24\n"
+ "\tadds r0, r4, 0x1\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r4, r0, 24\n"
+ "_0813C1BC:\n"
+ "\tldr r0, _0813C1DC @ =0x00000834\n"
+ "\tbl FlagGet\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r0, 24\n"
+ "\tcmp r0, 0x1\n"
+ "\tbne _0813C184\n"
+ "\tldr r0, _0813C1E0 @ =gString_Bill\n"
+ "\tadds r1, r4, r0\n"
+ "\tldrb r0, [r1]\n"
+ "\tcmp r0, 0xFF\n"
+ "\tbne _0813C164\n"
+ "\tb _0813C0AC_masterLoop\n"
+ "\t.align 2, 0\n"
+ "_0813C1D8: .4byte gString_Someone\n"
+ "_0813C1DC: .4byte 0x00000834\n"
+ "_0813C1E0: .4byte gString_Bill\n"
+ "_0813C1E4:\n"
+ "\tldr r7, [sp, 0x34]\n"
+ "\tldr r1, _0813C1FC @ =gGlyphInfo\n"
+ "\tadds r1, 0x81\n"
+ "\tmov r0, r10\n"
+ "\tadds r0, 0x1\n"
+ "\tldrb r1, [r1]\n"
+ "\tadds r0, r1\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r0, 24\n"
+ "\tmov r10, r0\n"
+ "\tb _0813C0AC_masterLoop\n"
+ "\t.align 2, 0\n"
+ "_0813C1FC: .4byte gGlyphInfo\n"
+ "_0813C200:\n"
+ "\tmov r2, r9\n"
+ "\tldrb r1, [r2]\n"
+ "\tmovs r0, 0x1\n"
+ "\tadd r9, r0\n"
+ "\tsubs r0, r1, 0x1\n"
+ "\tcmp r0, 0x15\n"
+ "\tbls _0813C210\n"
+ "\tb _0813C0AC_masterLoop\n"
+ "_0813C210:\n"
+ "\tlsls r0, 2\n"
+ "\tldr r1, _0813C21C @ =_0813C220\n"
+ "\tadds r0, r1\n"
+ "\tldr r0, [r0]\n"
+ "\tmov pc, r0\n"
+ "\t.align 2, 0\n"
+ "_0813C21C: .4byte _0813C220\n"
+ "\t.align 2, 0\n"
+ "_0813C220:\n"
+ "\t.4byte _0813C2C8\n"
+ "\t.4byte _0813C2C8\n"
+ "\t.4byte _0813C2C8\n"
+ "\t.4byte _0813C278\n"
+ "\t.4byte _0813C2C8\n"
+ "\t.4byte _0813C2C8\n"
+ "\t.4byte _0813C0AC_masterLoop\n"
+ "\t.4byte _0813C2C8\n"
+ "\t.4byte _0813C0AC_masterLoop\n"
+ "\t.4byte _0813C0AC_masterLoop\n"
+ "\t.4byte _0813C27C\n"
+ "\t.4byte _0813C2C8\n"
+ "\t.4byte _0813C2C8\n"
+ "\t.4byte _0813C2C8\n"
+ "\t.4byte _0813C0AC_masterLoop\n"
+ "\t.4byte _0813C27C\n"
+ "\t.4byte _0813C2CE\n"
+ "\t.4byte _0813C2CE\n"
+ "\t.4byte _0813C282\n"
+ "\t.4byte _0813C2CE\n"
+ "\t.4byte _0813C0AC_masterLoop\n"
+ "\t.4byte _0813C0AC_masterLoop\n"
+ "_0813C278:\n"
+ "\tmovs r1, 0x1\n"
+ "\tadd r9, r1\n"
+ "_0813C27C:\n"
+ "\tmovs r2, 0x1\n"
+ "\tadd r9, r2\n"
+ "\tb _0813C2C8\n"
+ "_0813C282:\n"
+ "\tmov r2, r9\n"
+ "\tldrb r0, [r2]\n"
+ "\tldr r1, [sp, 0x34]\n"
+ "\tadds r0, r1\n"
+ "\tsubs r6, r0, r7\n"
+ "\tcmp r6, 0\n"
+ "\tble _0813C2C8\n"
+ "\tldr r2, [sp, 0x28]\n"
+ "\tstr r2, [sp, 0x1C]\n"
+ "\tldr r1, [sp, 0x2C]\n"
+ "\tlsls r0, r1, 3\n"
+ "\tadd r4, sp, 0x1C\n"
+ "\tmovs r5, 0\n"
+ "\tstrh r0, [r4, 0x4]\n"
+ "\tldr r2, [sp, 0x30]\n"
+ "\tlsls r0, r2, 3\n"
+ "\tstrh r0, [r4, 0x6]\n"
+ "\tldr r0, [sp, 0x24]\n"
+ "\tmovs r1, 0x1\n"
+ "\tbl GetFontAttribute\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r0, 24\n"
+ "\tlsls r3, r6, 16\n"
+ "\tlsrs r3, 16\n"
+ "\tstr r0, [sp]\n"
+ "\tstr r5, [sp, 0x4]\n"
+ "\tadds r0, r4, 0\n"
+ "\tadds r1, r7, 0\n"
+ "\tmov r2, r10\n"
+ "\tbl FillBitmapRect4Bit\n"
+ "\tadds r0, r7, r6\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r7, r0, 24\n"
+ "_0813C2C8:\n"
+ "\tmovs r0, 0x1\n"
+ "\tadd r9, r0\n"
+ "\tb _0813C0AC_masterLoop\n"
+ "_0813C2CE:\n"
+ "\tmovs r1, 0x1\n"
+ "\tadd r9, r1\n"
+ "\tb _0813C0AC_masterLoop\n"
+ "_0813C2D4:\n"
+ "\tmov r2, r9\n"
+ "\tldrb r1, [r2]\n"
+ "\tmovs r0, 0x1\n"
+ "\tadd r9, r0\n"
+ "\tadds r6, r1, 0\n"
+ "\tadds r0, r6, 0\n"
+ "\tbl GetKeypadIconTileOffset\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r0, 19\n"
+ "\tldr r1, _0813C344 @ =gKeypadIconTiles\n"
+ "\tadds r0, r1\n"
+ "\tstr r0, [sp, 0x14]\n"
+ "\tadd r1, sp, 0x14\n"
+ "\tmovs r2, 0\n"
+ "\tmov r8, r2\n"
+ "\tmovs r0, 0x80\n"
+ "\tstrh r0, [r1, 0x4]\n"
+ "\tstrh r0, [r1, 0x6]\n"
+ "\tldr r0, [sp, 0x28]\n"
+ "\tstr r0, [sp, 0x1C]\n"
+ "\tldr r1, [sp, 0x2C]\n"
+ "\tlsls r0, r1, 3\n"
+ "\tadd r5, sp, 0x1C\n"
+ "\tstrh r0, [r5, 0x4]\n"
+ "\tldr r2, [sp, 0x30]\n"
+ "\tlsls r0, r2, 3\n"
+ "\tstrh r0, [r5, 0x6]\n"
+ "\tadds r0, r6, 0\n"
+ "\tbl GetKeypadIconWidth\n"
+ "\tadds r4, r0, 0\n"
+ "\tlsls r4, 24\n"
+ "\tlsrs r4, 24\n"
+ "\tadds r0, r6, 0\n"
+ "\tbl GetKeypadIconHeight\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r0, 24\n"
+ "\tstr r7, [sp]\n"
+ "\tmov r1, r10\n"
+ "\tstr r1, [sp, 0x4]\n"
+ "\tstr r4, [sp, 0x8]\n"
+ "\tstr r0, [sp, 0xC]\n"
+ "\tmov r2, r8\n"
+ "\tstr r2, [sp, 0x10]\n"
+ "\tadd r0, sp, 0x14\n"
+ "\tadds r1, r5, 0\n"
+ "\tmovs r2, 0\n"
+ "\tmovs r3, 0\n"
+ "\tbl BlitBitmapRect4Bit\n"
+ "\tadds r0, r6, 0\n"
+ "\tbl GetKeypadIconWidth\n"
+ "\tb _0813C38E\n"
+ "\t.align 2, 0\n"
+ "_0813C344: .4byte gKeypadIconTiles\n"
+ "_0813C348:\n"
+ "\tmov r0, r9\n"
+ "\tldrb r1, [r0]\n"
+ "\tmovs r2, 0x80\n"
+ "\tlsls r2, 1\n"
+ "\tadds r0, r2, 0\n"
+ "\torrs r1, r0\n"
+ "\tmovs r0, 0x1\n"
+ "\tadd r9, r0\n"
+ "_0813C358:\n"
+ "\tcmp r1, 0\n"
+ "\tbne _0813C36A\n"
+ "\tldr r1, [sp, 0x24]\n"
+ "\tcmp r1, 0\n"
+ "\tbne _0813C366\n"
+ "\tadds r0, r7, 0x5\n"
+ "\tb _0813C390\n"
+ "_0813C366:\n"
+ "\tadds r0, r7, 0x4\n"
+ "\tb _0813C390\n"
+ "_0813C36A:\n"
+ "\tadd r3, sp, 0x1C\n"
+ "\tldr r2, [sp, 0x28]\n"
+ "\tstr r2, [sp]\n"
+ "\tstr r7, [sp, 0x4]\n"
+ "\tmov r0, r10\n"
+ "\tstr r0, [sp, 0x8]\n"
+ "\tldr r2, [sp, 0x2C]\n"
+ "\tstr r2, [sp, 0xC]\n"
+ "\tldr r0, [sp, 0x30]\n"
+ "\tstr r0, [sp, 0x10]\n"
+ "\tldr r0, [sp, 0x24]\n"
+ "\tadd r2, sp, 0x14\n"
+ "\tbl DecompressAndRenderGlyph\n"
+ "\tldr r1, [sp, 0x24]\n"
+ "\tldr r0, _0813C398 @ =gGlyphInfo\n"
+ "\tadds r0, 0x80\n"
+ "\tldrb r0, [r0]\n"
+ "_0813C38E:\n"
+ "\tadds r0, r7, r0\n"
+ "_0813C390:\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r7, r0, 24\n"
+ "\tb _0813C0AC_masterLoop\n"
+ "\t.align 2, 0\n"
+ "_0813C398: .4byte gGlyphInfo\n"
+ "_0813C39C:\n"
+ "\tadd sp, 0x38\n"
+ "\tpop {r3-r5}\n"
+ "\tmov r8, r3\n"
+ "\tmov r9, r4\n"
+ "\tmov r10, r5\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r0}\n"
+ "\tbx r0");
+}
+#endif //NONMATCHING
+
+void DecompressAndRenderGlyph(u8 font, u16 glyph, struct Bitmap *srcBlit, struct Bitmap *destBlit, u8 *destBuffer, u8 x, u8 y, u8 width, u8 height)
+{
+ if (font == 0)
+ DecompressGlyphFont0(glyph, FALSE);
+ else if (font == 5)
+ DecompressGlyphFont5(glyph, FALSE);
+ else
+ DecompressGlyphFont2(glyph, FALSE);
+ srcBlit->pixels = gGlyphInfo;
+ srcBlit->width = 16;
+ srcBlit->height = 16;
+ destBlit->pixels = destBuffer;
+ destBlit->width = width * 8;
+ destBlit->height = height * 8;
+ BlitBitmapRect4Bit(srcBlit, destBlit, 0, 0, x, y, gGlyphInfo[0x80], gGlyphInfo[0x81], 0);
+}
+
+void HelpSystem_PrintText_Row61(const u8 * str)
+{
+ GenerateFontHalfRowLookupTable(1, 15, 2);
+ HelpSystemRenderText(5, gDecompressionBuffer + 0x3D00, str, 6, 2, 7, 2);
+}
+
+void HelpSystem_PrintTextRightAlign_Row52(const u8 * str)
+{
+ s32 left = 0x7C - GetStringWidth(0, str, 0);
+ GenerateFontHalfRowLookupTable(1, 15, 2);
+ HelpSystemRenderText(0, gDecompressionBuffer + 0x3400, str, left, 2, 16, 2);
+}
+
+void HelpSystem_PrintTextAt(const u8 * str, u8 x, u8 y)
+{
+ GenerateFontHalfRowLookupTable(1, 15, 2);
+ HelpSystemRenderText(2, gDecompressionBuffer + 0x0000, str, x, y, 26, 16);
+}
+
+void HelpSystem_PrintTwoStrings(const u8 * str1, const u8 * str2)
+{
+ CpuFill16(0xEEEE, gDecompressionBuffer + 0x0000, 0x3400);
+ GenerateFontHalfRowLookupTable(1, 14, 2);
+ HelpSystemRenderText(2, gDecompressionBuffer + 0x0000, str1, 0, 0, 26, 16);
+ HelpSystemRenderText(2, gDecompressionBuffer + 0x09C0, str2, 0, 0, 26, 13);
+}
+
+void HelpSystem_PrintText_813C584(const u8 * str)
+{
+ CpuFill16(0x1111, gDecompressionBuffer + 0x23C0, 0x1040);
+ GenerateFontHalfRowLookupTable(2, 1, 3);
+ HelpSystemRenderText(2, gDecompressionBuffer + 0x23C0, str, 2, 6, 26, 5);
+}
+
+void HelpSystem_FillPanel3(void)
+{
+ CpuFill16(0xFFFF, gDecompressionBuffer + 0x3D00, 0x1C0);
+}
+
+void HelpSystem_FillPanel2(void)
+{
+ CpuFill16(0xFFFF, gDecompressionBuffer + 0x3400, 0x400);
+}
+
+void HelpSystem_FillPanel1(void)
+{
+ CpuFill16(0xFFFF, gDecompressionBuffer + 0x0000, 0x3400);
+}
+
+void HelpSystem_InitListMenuController(struct HelpSystemListMenu * a0, u8 a1, u8 a2)
+{
+ gHelpSystemListMenu.sub = a0->sub;
+ gHelpSystemListMenu.field_0C = a1;
+ gHelpSystemListMenu.field_0D = a2;
+ gHelpSystemListMenu.field_0E = 0;
+ if (gHelpSystemListMenu.sub.totalItems < gHelpSystemListMenu.sub.maxShowed)
+ gHelpSystemListMenu.sub.maxShowed = gHelpSystemListMenu.sub.totalItems;
+ sub_813BDA4(0);
+ HelpSystem_FillPanel1();
+ PrintListMenuItems();
+ PlaceListMenuCursor();
+}
+
+void HelpSystem_SetInputDelay(u8 a0)
+{
+ sDelayTimer = a0;
+}
+
+s32 HelpSystem_GetMenuInput(void)
+{
+ if (sDelayTimer != 0)
+ {
+ sDelayTimer--;
+ return -1;
+ }
+ else if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ return gHelpSystemListMenu.sub.items[gHelpSystemListMenu.field_0C + gHelpSystemListMenu.field_0D].index;
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ return -2;
+ }
+ else if (JOY_NEW(L_BUTTON | R_BUTTON))
+ {
+ return -6;
+ }
+ else if (JOY_REPT(DPAD_UP))
+ {
+ if (!MoveCursor(1, 0))
+ PlaySE(SE_SELECT);
+ return -4;
+ }
+ else if (JOY_REPT(DPAD_DOWN))
+ {
+ if (!MoveCursor(1, 1))
+ PlaySE(SE_SELECT);
+ return -5;
+ }
+ else if (JOY_REPT(DPAD_LEFT))
+ {
+ if (!MoveCursor(7, 0))
+ PlaySE(SE_SELECT);
+ return -4;
+ }
+ else if (JOY_REPT(DPAD_RIGHT))
+ {
+ if (!MoveCursor(7, 1))
+ PlaySE(SE_SELECT);
+ return -5;
+ }
+ else
+ return -1;
+}
+
+void sub_813C75C(void)
+{
+ u8 r6 = gHelpSystemListMenu.sub.totalItems - 7;
+ if (gHelpSystemListMenu.sub.totalItems > 7)
+ {
+ s32 r4 = gHelpSystemListMenu.field_0C + gHelpSystemListMenu.field_0D;
+ sub_813C004(0, 0);
+ if (r4 == 0)
+ sub_813C004(1, 1);
+ else if (gHelpSystemListMenu.field_0C == 0 && gHelpSystemListMenu.field_0D != 0)
+ sub_813C004(1, 1);
+ else if (gHelpSystemListMenu.field_0C == r6)
+ sub_813C004(0, 1);
+ else if (gHelpSystemListMenu.field_0C != 0)
+ {
+ sub_813C004(0, 1);
+ sub_813C004(1, 1);
+ }
+ }
+}
+
+void PrintListMenuItems(void)
+{
+ u8 glyphHeight = GetFontAttribute(2, 1) + 1;
+ s32 i;
+ s32 r5 = gHelpSystemListMenu.field_0C;
+
+ for (i = 0; i < gHelpSystemListMenu.sub.maxShowed; i++)
+ {
+ u8 x = gHelpSystemListMenu.sub.left + 8;
+ u8 y = gHelpSystemListMenu.sub.top + glyphHeight * i;
+ HelpSystem_PrintTextAt(gHelpSystemListMenu.sub.items[r5].label, x, y);
+ r5++;
+ }
+}
+
+void PlaceListMenuCursor(void)
+{
+ u8 glyphHeight = GetFontAttribute(2, 1) + 1;
+ u8 x = gHelpSystemListMenu.sub.left;
+ u8 y = gHelpSystemListMenu.sub.top + glyphHeight * gHelpSystemListMenu.field_0D;
+ HelpSystem_PrintTextAt(gFameCheckerText_ListMenuCursor, x, y);
+}
+
+void sub_813C860(u8 i)
+{
+ u8 glyphHeight = GetFontAttribute(2, 1) + 1;
+ u8 x = gHelpSystemListMenu.sub.left;
+ u8 y = gHelpSystemListMenu.sub.top + i * glyphHeight;
+ HelpSystem_PrintTextAt(gString_HelpSystem_ClearTo8, x, y);
+}
+
+u8 TryMoveCursor1(u8 dirn)
+{
+ u16 r4;
+ if (dirn == 0)
+ {
+ if (gHelpSystemListMenu.sub.maxShowed == 1)
+ r4 = 0;
+ else
+ r4 = gHelpSystemListMenu.sub.maxShowed - (gHelpSystemListMenu.sub.maxShowed / 2 + (gHelpSystemListMenu.sub.maxShowed & 1)) - 1;
+ if (gHelpSystemListMenu.field_0C == 0)
+ {
+ if (gHelpSystemListMenu.field_0D != 0)
+ {
+ gHelpSystemListMenu.field_0D--;
+ return 1;
+ }
+ else
+ return 0;
+ }
+ if (gHelpSystemListMenu.field_0D > r4)
+ {
+ gHelpSystemListMenu.field_0D--;
+ return 1;
+ }
+ else
+ {
+ gHelpSystemListMenu.field_0C--;
+ return 2;
+ }
+ }
+ else
+ {
+ if (gHelpSystemListMenu.sub.maxShowed == 1)
+ r4 = 0;
+ else
+ r4 = gHelpSystemListMenu.sub.maxShowed / 2 + (gHelpSystemListMenu.sub.maxShowed & 1);
+ if (gHelpSystemListMenu.field_0C == gHelpSystemListMenu.sub.totalItems - gHelpSystemListMenu.sub.maxShowed)
+ {
+ if (gHelpSystemListMenu.field_0D < gHelpSystemListMenu.sub.maxShowed - 1)
+ {
+ gHelpSystemListMenu.field_0D++;
+ return 1;
+ }
+ else
+ return 0;
+ }
+ else if (gHelpSystemListMenu.field_0D < r4)
+ {
+ gHelpSystemListMenu.field_0D++;
+ return 1;
+ }
+ else
+ {
+ gHelpSystemListMenu.field_0C++;
+ return 2;
+ }
+ }
+}
+
+bool8 MoveCursor(u8 by, u8 dirn)
+{
+ u8 r7 = gHelpSystemListMenu.field_0D;
+ u8 flags = 0;
+ s32 i;
+ for (i = 0; i < by; i++)
+ flags |= TryMoveCursor1(dirn);
+
+ switch (flags)
+ {
+ case 0:
+ default:
+ // neither changed
+ return TRUE;
+ case 1:
+ // changed field_0D only
+ sub_813C860(r7);
+ PlaceListMenuCursor();
+ CommitTilemap();
+ break;
+ case 2:
+ case 3:
+ // changed field_0C
+ if (sub_812BF88() == TRUE)
+ {
+ HelpSystem_SetInputDelay(2);
+ HelpSystem_FillPanel1();
+ PrintListMenuItems();
+ PlaceListMenuCursor();
+ sub_812BDEC();
+ sub_813C75C();
+ }
+ else
+ {
+ sub_813BDA4(0);
+ HelpSystem_FillPanel1();
+ PrintListMenuItems();
+ PlaceListMenuCursor();
+ sub_813BDA4(1);
+ }
+ CommitTilemap();
+ break;
+ }
+ return FALSE;
+}
diff --git a/src/help_system_812B1E0.c b/src/help_system_812B1E0.c
new file mode 100644
index 000000000..98d6ce8be
--- /dev/null
+++ b/src/help_system_812B1E0.c
@@ -0,0 +1,1580 @@
+#include "global.h"
+#include "event_data.h"
+#include "event_scripts.h"
+#include "field_player_avatar.h"
+#include "help_system.h"
+#include "item.h"
+#include "link.h"
+#include "overworld.h"
+#include "pokedex.h"
+#include "quest_log.h"
+#include "save.h"
+#include "save_location.h"
+#include "sound.h"
+#include "strings.h"
+#include "constants/items.h"
+#include "constants/maps.h"
+#include "constants/songs.h"
+
+static EWRAM_DATA u16 gUnknown_203B0EC = 0;
+static EWRAM_DATA u8 gUnknown_203B0EE = 0;
+
+u8 gUnknown_3005E9C[4];
+u16 gUnknown_3005EA0;
+
+static bool32 sub_812B27C(const u16 * mapIdxs);
+static void sub_812B520(struct HelpSystemListMenu * a0, struct ListMenuItem * a1);
+static void sub_812B614(struct HelpSystemListMenu * a0, struct ListMenuItem * a1);
+static bool8 sub_812B754(void);
+static bool8 sub_812B780(u8);
+static bool8 sub_812BB10(void);
+
+static void sub_812BF5C(void);
+static void sub_812BF74(const u8 *);
+static void sub_812BF94(struct HelpSystemListMenu * a0);
+static void sub_812BF9C(struct HelpSystemListMenu * a0, struct ListMenuItem * a1);
+
+static const u8 *const gUnknown_845B080[] = {
+ gUnknown_81B2DF8,
+ gUnknown_81B2E1C,
+ gUnknown_81B2E2E,
+ gUnknown_81B2E48,
+ gUnknown_81B2E58,
+ gUnknown_81B2E6A
+};
+
+static const u8 *const gUnknown_845B098[] = {
+ gUnknown_81B2E88,
+ gUnknown_81B2EC8,
+ gUnknown_81B2F00,
+ gUnknown_81B2F43,
+ gUnknown_81B2F74,
+ gUnknown_81B2FA9
+};
+
+static const u8 *const gUnknown_845B0B0[] = {
+ NULL,
+ gUnknown_81B3083,
+ gUnknown_81B30A9,
+ gUnknown_81B30C1,
+ gUnknown_81B30DC,
+ gUnknown_81B30FC,
+ gUnknown_81B311F,
+ gUnknown_81B3140,
+ gUnknown_81B314F,
+ gUnknown_81B3168,
+ gUnknown_81B3189,
+ gUnknown_81B31AE,
+ gUnknown_81B31D3,
+ gUnknown_81B31EC,
+ gUnknown_81B31FF,
+ gUnknown_81B3215,
+ gUnknown_81B3226,
+ gUnknown_81B3243,
+ gUnknown_81B3261,
+ gUnknown_81B3276,
+ gUnknown_81B3290,
+ gUnknown_81B32B6,
+ gUnknown_81B32CD,
+ gUnknown_81B32E3,
+ gUnknown_81B32F9,
+ gUnknown_81B330B,
+ gUnknown_81B332B,
+ gUnknown_81B3344,
+ gUnknown_81B335C,
+ gUnknown_81B3373,
+ gUnknown_81B338C,
+ gUnknown_81B33A6,
+ gUnknown_81B33CA,
+ gUnknown_81B33EA,
+ gUnknown_81B3402,
+ gUnknown_81B3427,
+ gUnknown_81B3440,
+ gUnknown_81B3457,
+ gUnknown_81B346F,
+ gUnknown_81B3481,
+ gUnknown_81B349B,
+ gUnknown_81B34B7,
+ gUnknown_81B34D6,
+ gUnknown_81B34F6,
+ gUnknown_81B3516
+};
+
+static const u8 *const gUnknown_845B164[] = {
+ NULL,
+ gUnknown_81B3525,
+ gUnknown_81B35E6,
+ gUnknown_81B36EB,
+ gUnknown_81B379A,
+ gUnknown_81B3849,
+ gUnknown_81B3876,
+ gUnknown_81B3972,
+ gUnknown_81B3A51,
+ gUnknown_81B3ACC,
+ gUnknown_81B3BB6,
+ gUnknown_81B3C99,
+ gUnknown_81B3D1B,
+ gUnknown_81B3DE3,
+ gUnknown_81B3EBC,
+ gUnknown_81B3F7F,
+ gUnknown_81B406C,
+ gUnknown_81B410B,
+ gUnknown_81B41D7,
+ gUnknown_81B42B3,
+ gUnknown_81B439D,
+ gUnknown_81B4483,
+ gUnknown_81B457C,
+ gUnknown_81B4645,
+ gUnknown_81B470A,
+ gUnknown_81B47F0,
+ gUnknown_81B48C6,
+ gUnknown_81B497A,
+ gUnknown_81B4A72,
+ gUnknown_81B4B65,
+ gUnknown_81B4C54,
+ gUnknown_81B4D26,
+ gUnknown_81B4E0B,
+ gUnknown_81B4ED8,
+ gUnknown_81B4FB2,
+ gUnknown_81B4FFD,
+ gUnknown_81B50FF,
+ gUnknown_81B51B1,
+ gUnknown_81B5272,
+ gUnknown_81B5325,
+ gUnknown_81B5382,
+ gUnknown_81B547C,
+ gUnknown_81B54E1,
+ gUnknown_81B5589,
+ gUnknown_81B55F4
+};
+
+static const u8 *const gUnknown_845B218[] = {
+ NULL,
+ gUnknown_81B56E3,
+ gUnknown_81B56F4,
+ gUnknown_81B5705,
+ gUnknown_81B5717,
+ gUnknown_81B5728,
+ gUnknown_81B5737,
+ gUnknown_81B5744,
+ gUnknown_81B5754,
+ gUnknown_81B5767,
+ gUnknown_81B577B,
+ gUnknown_81B5787,
+ gUnknown_81B5795,
+ gUnknown_81B57A5,
+ gUnknown_81B57B8,
+ gUnknown_81B57CF,
+ gUnknown_81B57DE,
+ gUnknown_81B57EE,
+ gUnknown_81B580D,
+ gUnknown_81B5824,
+ gUnknown_81B5834,
+ gUnknown_81B583F,
+ gUnknown_81B5850,
+ gUnknown_81B5863,
+ gUnknown_81B5875,
+ gUnknown_81B5884,
+ gUnknown_81B5893,
+ gUnknown_81B58A4,
+ gUnknown_81B58BC,
+ gUnknown_81B58D3,
+ gUnknown_81B58E5,
+ gUnknown_81B58FD,
+ gUnknown_81B590E,
+ gUnknown_81B591D,
+ gUnknown_81B592E,
+ gUnknown_81B593E,
+ gUnknown_81B5950,
+ gUnknown_81B595D,
+ gUnknown_81B5974,
+ gUnknown_81B5989,
+ gUnknown_81B59A7,
+ gUnknown_81B59BF,
+ gUnknown_81B59D6,
+ gUnknown_81B59E8,
+ gUnknown_81B59F5,
+ gUnknown_81B5A0D,
+ gUnknown_81B5A1B,
+ gUnknown_81B5A29,
+ gUnknown_81B5A37
+};
+
+static const u8 *const gUnknown_845B2DC[] = {
+ NULL,
+ gUnknown_81B5A4D,
+ gUnknown_81B5B0C,
+ gUnknown_81B5B7D,
+ gUnknown_81B5C13,
+ gUnknown_81B5CDF,
+ gUnknown_81B5D87,
+ gUnknown_81B5E41,
+ gUnknown_81B5F10,
+ gUnknown_81B5FA6,
+ gUnknown_81B606C,
+ gUnknown_81B6140,
+ gUnknown_81B6203,
+ gUnknown_81B62E4,
+ gUnknown_81B6397,
+ gUnknown_81B6478,
+ gUnknown_81B6525,
+ gUnknown_81B65E7,
+ gUnknown_81B66BA,
+ gUnknown_81B678E,
+ gUnknown_81B6883,
+ gUnknown_81B68CD,
+ gUnknown_81B69B9,
+ gUnknown_81B6A9A,
+ gUnknown_81B6B6E,
+ gUnknown_81B6C4F,
+ gUnknown_81B6D4A,
+ gUnknown_81B6E02,
+ gUnknown_81B6EC1,
+ gUnknown_81B6FA8,
+ gUnknown_81B7075,
+ gUnknown_81B7108,
+ gUnknown_81B71EA,
+ gUnknown_81B723B,
+ gUnknown_81B7319,
+ gUnknown_81B73E8,
+ gUnknown_81B747E,
+ gUnknown_81B752C,
+ gUnknown_81B7611,
+ gUnknown_81B7692,
+ gUnknown_81B771E,
+ gUnknown_81B77DD,
+ gUnknown_81B7884,
+ gUnknown_81B7931,
+ gUnknown_81B79CB,
+ gUnknown_81B7A60,
+ gUnknown_81B7AEE,
+ gUnknown_81B7BBE,
+ gUnknown_81B7C57
+};
+
+static const u8 *const gUnknown_845B3A0[] = {
+ NULL,
+ gUnknown_81B7CC1,
+ gUnknown_81B7CC4,
+ gUnknown_81B7CD9,
+ gUnknown_81B7CDF,
+ gUnknown_81B7CE6,
+ gUnknown_81B7CEE,
+ gUnknown_81B7CF6,
+ gUnknown_81B7CFE,
+ gUnknown_81B7D04,
+ gUnknown_81B7D12,
+ gUnknown_81B7D17,
+ gUnknown_81B7D1A,
+ gUnknown_81B7D1F,
+ gUnknown_81B7D27,
+ gUnknown_81B7D2D,
+ gUnknown_81B7D37,
+ gUnknown_81B7D3E,
+ gUnknown_81B7D45,
+ gUnknown_81B7D48,
+ gUnknown_81B7D4E,
+ gUnknown_81B7D57,
+ gUnknown_81B7D5B,
+ gUnknown_81B7D61,
+ gUnknown_81B7D6B,
+ gUnknown_81B7D76,
+ gUnknown_81B7D7E,
+ gUnknown_81B7D88,
+ gUnknown_81B7D8F,
+ gUnknown_81B7D9A,
+ gUnknown_81B7DA7,
+ gUnknown_81B7DB4,
+ gUnknown_81B7DBA,
+ gUnknown_81B7DC6,
+ gUnknown_81B7DCC,
+ gUnknown_81B7DD3,
+ gUnknown_81B7DD6,
+ gUnknown_81B7DD9,
+ gUnknown_81B7DE1,
+ gUnknown_81B7DEB,
+ gUnknown_81B7DFA,
+ gUnknown_81B7E02,
+ gUnknown_81B7E09,
+ gUnknown_81B7E0F
+};
+
+static const u8 *const gUnknown_845B450[] = {
+ NULL,
+ gUnknown_81B7E16,
+ gUnknown_81B7F0A,
+ gUnknown_81B800A,
+ gUnknown_81B80EC,
+ gUnknown_81B81C2,
+ gUnknown_81B8256,
+ gUnknown_81B8348,
+ gUnknown_81B83EF,
+ gUnknown_81B847B,
+ gUnknown_81B8550,
+ gUnknown_81B8647,
+ gUnknown_81B86E2,
+ gUnknown_81B87B8,
+ gUnknown_81B8897,
+ gUnknown_81B8924,
+ gUnknown_81B8A04,
+ gUnknown_81B8A84,
+ gUnknown_81B8B62,
+ gUnknown_81B8C18,
+ gUnknown_81B8C94,
+ gUnknown_81B8D1D,
+ gUnknown_81B8DD4,
+ gUnknown_81B8E67,
+ gUnknown_81B8F4D,
+ gUnknown_81B901B,
+ gUnknown_81B90A7,
+ gUnknown_81B90E8,
+ gUnknown_81B9170,
+ gUnknown_81B91C2,
+ gUnknown_81B91F9,
+ gUnknown_81B92B8,
+ gUnknown_81B92ED,
+ gUnknown_81B93D8,
+ gUnknown_81B9439,
+ gUnknown_81B9497,
+ gUnknown_81B9560,
+ gUnknown_81B9656,
+ gUnknown_81B9749,
+ gUnknown_81B984F,
+ gUnknown_81B991C,
+ gUnknown_81B99C4,
+ gUnknown_81B9AA2,
+ gUnknown_81B9B2F
+};
+
+static const u8 *const gUnknown_845B500[] = {
+ NULL,
+ gUnknown_81B9BB7,
+ gUnknown_81B9BC7,
+ gUnknown_81B9BD0,
+ gUnknown_81B9BE1,
+ gUnknown_81B9BF5,
+ gUnknown_81B9C09,
+ gUnknown_81B9C1D
+};
+
+static const u8 *const gUnknown_845B520[] = {
+ NULL,
+ gUnknown_81B9C2F,
+ gUnknown_81B9D04,
+ gUnknown_81B9DC5,
+ gUnknown_81B9E75,
+ gUnknown_81B9F09,
+ gUnknown_81B9FCE,
+ gUnknown_81BA027
+};
+
+static const u8 *const gUnknown_845B540[] = {
+ NULL,
+ gUnknown_81BA0F1,
+ gUnknown_81BA10D,
+ gUnknown_81BA121,
+ gUnknown_81BA138,
+ gUnknown_81BA14C,
+ gUnknown_81BA163,
+ gUnknown_81BA17A,
+ gUnknown_81BA194,
+ gUnknown_81BA1AC,
+ gUnknown_81BA1C7,
+ gUnknown_81BA1DC,
+ gUnknown_81BA1F4,
+ gUnknown_81BA209,
+ gUnknown_81BA221,
+ gUnknown_81BA234,
+ gUnknown_81BA24A,
+ gUnknown_81BA260,
+ gUnknown_81BA279,
+ gUnknown_81BA291,
+ gUnknown_81BA2AC,
+ gUnknown_81BA2C2,
+ gUnknown_81BA2DB,
+ gUnknown_81BA2F1,
+ gUnknown_81BA30A,
+ gUnknown_81BA320,
+ gUnknown_81BA339,
+ gUnknown_81BA34E,
+ gUnknown_81BA366,
+ gUnknown_81BA37C,
+ gUnknown_81BA395,
+ gUnknown_81BA3A9,
+ gUnknown_81BA3C0,
+ gUnknown_81BA3D5,
+ gUnknown_81BA3ED,
+ gUnknown_81BA400
+};
+
+static const u8 *const gUnknown_845B5D0[] = {
+ NULL,
+ gUnknown_81BA416,
+ gUnknown_81BA4E6,
+ gUnknown_81BA539,
+ gUnknown_81BA595,
+ gUnknown_81BA5F2,
+ gUnknown_81BA66F,
+ gUnknown_81BA6C9,
+ gUnknown_81BA71F,
+ gUnknown_81BA796,
+ gUnknown_81BA7E9,
+ gUnknown_81BA862,
+ gUnknown_81BA8D3,
+ gUnknown_81BA92A,
+ gUnknown_81BA98D,
+ gUnknown_81BA9F1,
+ gUnknown_81BAA44,
+ gUnknown_81BAAB6,
+ gUnknown_81BAB18,
+ gUnknown_81BAB7A,
+ gUnknown_81BABCC,
+ gUnknown_81BAC29,
+ gUnknown_81BAC89,
+ gUnknown_81BACC4,
+ gUnknown_81BAD20,
+ gUnknown_81BAD60,
+ gUnknown_81BADA2,
+ gUnknown_81BADF7,
+ gUnknown_81BAEA8,
+ gUnknown_81BAF01,
+ gUnknown_81BAF6B,
+ gUnknown_81BAFCA,
+ gUnknown_81BB02E,
+ gUnknown_81BB084,
+ gUnknown_81BB0DF,
+ gUnknown_81BB156
+};
+
+
+static const u8 gUnknown_845B660[] = {
+ 0x01, 0x02, 0x03, 0xff
+};
+
+static const u8 gUnknown_845B664[] = {
+ 0x01, 0x02, 0x03, 0xff
+};
+
+static const u8 gUnknown_845B668[] = {
+ 0x13, 0xff
+};
+
+static const u8 gUnknown_845B66A[] = {
+ 0x01, 0x02, 0x03, 0xff
+};
+
+static const u8 gUnknown_845B66E[] = {
+ 0x01, 0x25, 0xff
+};
+
+static const u8 gUnknown_845B671[] = {
+ 0x02, 0x03, 0x04, 0x05, 0x11, 0xff
+};
+
+static const u8 gUnknown_845B677[] = {
+ 0x09, 0x01, 0xff
+};
+
+static const u8 gUnknown_845B67A[] = {
+ 0x02, 0x03, 0xff
+};
+
+static const u8 gUnknown_845B67D[] = {
+ 0x09, 0x0a, 0x0b, 0x11, 0x0c, 0x10, 0xff
+};
+
+static const u8 gUnknown_845B684[] = {
+ 0x09, 0x01, 0x04, 0x05, 0x06, 0x07, 0x08, 0x02, 0x0d, 0xff
+};
+
+static const u8 gUnknown_845B68E[] = {
+ 0x09, 0x03, 0x0a, 0x0f, 0x12, 0x13, 0x14, 0xff
+};
+
+static const u8 gUnknown_845B696[] = {
+ 0x06, 0x07, 0x08, 0x2c, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x12, 0xff
+};
+
+static const u8 gUnknown_845B6A1[] = {
+ 0x16, 0x17, 0x18, 0xff
+};
+
+static const u8 gUnknown_845B6A5[] = {
+ 0x0a, 0xff
+};
+
+static const u8 gUnknown_845B6A7[] = {
+ 0x11, 0x0e, 0x19, 0x1a, 0x1b, 0xff
+};
+
+static const u8 gUnknown_845B6AD[] = {
+ 0x0a, 0xff
+};
+
+static const u8 gUnknown_845B6AF[] = {
+ 0x0b, 0xff
+};
+
+static const u8 gUnknown_845B6B1[] = {
+ 0x2b, 0x19, 0x1a, 0xff
+};
+
+static const u8 gUnknown_845B6B5[] = {
+ 0x0c, 0xff
+};
+
+static const u8 gUnknown_845B6B7[] = {
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0xff
+};
+
+static const u8 gUnknown_845B6BF[] = {
+ 0x02, 0x03, 0x04, 0xff
+};
+
+static const u8 gUnknown_845B6C3[] = {
+ 0x01, 0x02, 0x03, 0x07, 0xff
+};
+
+static const u8 gUnknown_845B6C8[] = {
+ 0x02, 0x04, 0x05, 0x09, 0x25, 0xff
+};
+
+static const u8 gUnknown_845B6CE[] = {
+ 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x2c, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x0a, 0x0b, 0x0c, 0x11, 0xff
+};
+
+static const u8 gUnknown_845B6E2[] = {
+ 0x09, 0x01, 0x02, 0x03, 0x0a, 0x28, 0xff
+};
+
+static const u8 gUnknown_845B6E9[] = {
+ 0x02, 0x05, 0x06, 0x0a, 0x23, 0x24, 0x09, 0x25, 0xff
+};
+
+static const u8 gUnknown_845B6F2[] = {
+ 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x2c, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x0a, 0x0b, 0x0c, 0x11, 0x14, 0xff
+};
+
+static const u8 gUnknown_845B707[] = {
+ 0x09, 0x01, 0x02, 0x03, 0x0a, 0x28, 0xff
+};
+
+static const u8 gUnknown_845B70E[] = {
+ 0x03, 0x07, 0x04, 0x05, 0x06, 0xff
+};
+
+static const u8 gUnknown_845B714[] = {
+ 0x02, 0x05, 0x06, 0x0a, 0x23, 0x24, 0x09, 0x25, 0xff
+};
+
+static const u8 gUnknown_845B71D[] = {
+ 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x2c, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x0a, 0x0b, 0x0c, 0x11, 0xff
+};
+
+static const u8 gUnknown_845B731[] = {
+ 0x09, 0x01, 0x02, 0x03, 0x0a, 0x0c, 0x0e, 0x16, 0x17, 0x18, 0x15, 0xff
+};
+
+static const u8 gUnknown_845B73D[] = {
+ 0x06, 0x0a, 0x23, 0x24, 0x09, 0x25, 0xff
+};
+
+static const u8 gUnknown_845B744[] = {
+ 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x2c, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x0a, 0x0b, 0x0c, 0x11, 0xff
+};
+
+static const u8 gUnknown_845B758[] = {
+ 0x09, 0x01, 0x02, 0x03, 0x0a, 0x15, 0xff
+};
+
+static const u8 gUnknown_845B75F[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0xff
+};
+
+static const u8 gUnknown_845B783[] = {
+ 0x02, 0x0a, 0x04, 0x05, 0x06, 0x07, 0x0d, 0x27, 0x08, 0x0b, 0x21, 0x23, 0x24, 0x2c, 0x09, 0x0e, 0x16, 0x17, 0x0f, 0x10, 0x11, 0x1a, 0x15, 0x1f, 0x20, 0x12, 0x13, 0x14, 0x18, 0x19, 0x1b, 0x1e, 0x1c, 0x28, 0x25, 0xff
+};
+
+static const u8 gUnknown_845B7A7[] = {
+ 0x1f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x2c, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x0a, 0x0b, 0x0c, 0x11, 0xff
+};
+
+static const u8 gUnknown_845B7BB[] = {
+ 0x09, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0x0d, 0x15, 0xff
+};
+
+static const u8 gUnknown_845B7C4[] = {
+ 0x02, 0x0a, 0x04, 0x05, 0x06, 0x07, 0x0d, 0x27, 0x08, 0x0b, 0x21, 0x23, 0x24, 0x2c, 0x09, 0x0e, 0x16, 0x17, 0x0f, 0x10, 0x11, 0x1a, 0x15, 0x1f, 0x20, 0x12, 0x13, 0x14, 0x18, 0x19, 0x1b, 0x1e, 0x1c, 0x28, 0x25, 0xff
+};
+
+static const u8 gUnknown_845B7E8[] = {
+ 0x1f, 0x01, 0x02, 0x06, 0x0a, 0x0b, 0x0c, 0x11, 0xff
+};
+
+static const u8 gUnknown_845B7F1[] = {
+ 0x09, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0x0d, 0x15, 0x28, 0xff
+};
+
+static const u8 gUnknown_845B7FB[] = {
+ 0x0a, 0x07, 0x0d, 0x27, 0x08, 0x0b, 0x21, 0x23, 0x24, 0x2c, 0x09, 0x0e, 0x16, 0x0f, 0x10, 0x11, 0x1a, 0x15, 0x1f, 0x20, 0x12, 0x13, 0x14, 0x18, 0x19, 0x1b, 0x1e, 0x1c, 0x28, 0x25, 0xff
+};
+
+static const u8 gUnknown_845B81A[] = {
+ 0x1f, 0x01, 0x02, 0x06, 0x0a, 0x0b, 0x0c, 0x11, 0xff
+};
+
+static const u8 gUnknown_845B823[] = {
+ 0x09, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0x0d, 0x15, 0xff
+};
+
+static const u8 gUnknown_845B82C[] = {
+ 0x07, 0x27, 0x08, 0x2c, 0x15, 0x1f, 0x20, 0x12, 0x13, 0x14, 0x18, 0x19, 0x1b, 0x1e, 0x1c, 0x28, 0x25, 0xff
+};
+
+static const u8 gUnknown_845B83E[] = {
+ 0x1f, 0x01, 0x02, 0x06, 0x0a, 0x0b, 0x0c, 0x11, 0xff
+};
+
+static const u8 gUnknown_845B847[] = {
+ 0x09, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0x0d, 0x15, 0xff
+};
+
+static const u8 gUnknown_845B850[] = {
+ 0x0f, 0x1b, 0x1d, 0x11, 0x12, 0x15, 0x17, 0x16, 0x1f, 0x20, 0x13, 0x14, 0xff
+};
+
+static const u8 gUnknown_845B85D[] = {
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x07, 0x09, 0x2b, 0xff
+};
+
+static const u8 gUnknown_845B866[] = {
+ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0d, 0x0f, 0x12, 0x13, 0x14, 0x27, 0x15, 0xff
+};
+
+static const u8 gUnknown_845B878[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0xff
+};
+
+static const u8 gUnknown_845B89C[] = {
+ 0x0f, 0x1b, 0x1d, 0x11, 0x12, 0x16, 0x1f, 0x20, 0x13, 0x14, 0xff
+};
+
+static const u8 gUnknown_845B8A7[] = {
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x07, 0x2b, 0xff
+};
+
+static const u8 gUnknown_845B8AF[] = {
+ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0d, 0x0f, 0x12, 0x13, 0x14, 0x27, 0x15, 0xff
+};
+
+static const u8 gUnknown_845B8C1[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0xff
+};
+
+static const u8 gUnknown_845B8E5[] = {
+ 0x0f, 0x1b, 0x1d, 0x11, 0x12, 0x16, 0x1f, 0x20, 0x13, 0x14, 0xff
+};
+
+static const u8 gUnknown_845B8F0[] = {
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x07, 0x2b, 0xff
+};
+
+static const u8 gUnknown_845B8F8[] = {
+ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0d, 0x0f, 0x12, 0x13, 0x14, 0x27, 0x15, 0xff
+};
+
+static const u8 gUnknown_845B90A[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0xff
+};
+
+static const u8 gUnknown_845B92E[] = {
+ 0x29, 0x2a, 0x2b, 0xff
+};
+
+static const u8 gUnknown_845B932[] = {
+ 0x2d, 0x2e, 0x2f, 0x2b, 0xff
+};
+
+static const u8 gUnknown_845B937[] = {
+ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0d, 0x0f, 0x12, 0x13, 0x14, 0xff
+};
+
+static const u8 gUnknown_845B947[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0xff
+};
+
+static const u8 gUnknown_845B96B[] = {
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x30, 0xff
+};
+
+static const u8 gUnknown_845B978[] = {
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x30, 0xff
+};
+
+static const u8 gUnknown_845B985[] = {
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x30, 0xff
+};
+
+static const u8 gUnknown_845B992[] = {
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x30, 0xff
+};
+
+static const u8 gUnknown_845B99F[] = {
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x30, 0xff
+};
+
+static const u8 gUnknown_845B9AC[] = {
+ 0x26, 0x27, 0x28, 0x29, 0x2a, 0xff
+};
+
+static const u8 gUnknown_845B9B2[] = {
+ 0x26, 0x27, 0x28, 0x29, 0x2a, 0xff
+};
+
+static const u8 gUnknown_845B9B8[] = {
+ 0x26, 0x27, 0x28, 0x29, 0x2a, 0xff
+};
+
+static const u8 gUnknown_845B9BE[] = {
+ 0x09, 0x01, 0x02, 0x03, 0x23, 0x25, 0x24, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0x0d, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x27, 0x15, 0x26, 0x16, 0x17, 0x18, 0x1a, 0x0e, 0x1b, 0xff
+};
+
+static const u8 *const gUnknown_845B9E0[] = {
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, gUnknown_845B660, NULL,
+ NULL, NULL, NULL, gUnknown_845B664, NULL,
+ NULL, gUnknown_845B668, NULL, gUnknown_845B66A, NULL,
+ NULL, gUnknown_845B66E, NULL, NULL, NULL,
+ NULL, gUnknown_845B671, gUnknown_845B677, NULL, NULL,
+ NULL, gUnknown_845B67A, gUnknown_845B67D, NULL, NULL,
+ NULL, NULL, gUnknown_845B684, NULL, NULL,
+ NULL, NULL, gUnknown_845B68E, NULL, NULL,
+ NULL, gUnknown_845B696, gUnknown_845B6A1, NULL, NULL,
+ NULL, gUnknown_845B6A5, gUnknown_845B6A7, NULL, NULL,
+ NULL, gUnknown_845B6AD, NULL, NULL, NULL,
+ NULL, gUnknown_845B6AF, gUnknown_845B6B1, NULL, NULL,
+ NULL, gUnknown_845B6B5, gUnknown_845B6B7, NULL, NULL,
+ gUnknown_845B6BF, NULL, NULL, gUnknown_845B6C3, NULL,
+ gUnknown_845B6C8, gUnknown_845B6CE, gUnknown_845B6E2, NULL, NULL,
+ gUnknown_845B6E9, gUnknown_845B6F2, gUnknown_845B707, gUnknown_845B70E, NULL,
+ gUnknown_845B714, gUnknown_845B71D, gUnknown_845B731, NULL, NULL,
+ gUnknown_845B73D, gUnknown_845B744, gUnknown_845B758, NULL, gUnknown_845B75F,
+ gUnknown_845B783, gUnknown_845B7A7, gUnknown_845B7BB, NULL, NULL,
+ gUnknown_845B7C4, gUnknown_845B7E8, gUnknown_845B7F1, NULL, NULL,
+ gUnknown_845B7FB, gUnknown_845B81A, gUnknown_845B823, NULL, NULL,
+ gUnknown_845B82C, gUnknown_845B83E, gUnknown_845B847, NULL, NULL,
+ gUnknown_845B850, gUnknown_845B85D, gUnknown_845B866, NULL, gUnknown_845B878,
+ gUnknown_845B89C, gUnknown_845B8A7, gUnknown_845B8AF, NULL, gUnknown_845B8C1,
+ gUnknown_845B8E5, gUnknown_845B8F0, gUnknown_845B8F8, NULL, gUnknown_845B90A,
+ gUnknown_845B92E, gUnknown_845B932, gUnknown_845B937, NULL, gUnknown_845B947,
+ NULL, gUnknown_845B96B, NULL, NULL, NULL,
+ NULL, gUnknown_845B978, NULL, NULL, NULL,
+ NULL, gUnknown_845B985, NULL, NULL, NULL,
+ NULL, gUnknown_845B992, NULL, NULL, NULL,
+ NULL, gUnknown_845B99F, NULL, NULL, NULL,
+ NULL, gUnknown_845B9AC, NULL, NULL, NULL,
+ NULL, gUnknown_845B9B2, NULL, NULL, NULL,
+ NULL, gUnknown_845B9B8, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL
+};
+
+static const u16 unref_845BCB0[] = INCBIN_U16("graphics/help_system/unk_845BCB0.bin");
+
+static const u8 gUnknown_845C4B0[] = {
+ 3, 0, 1, 2, 4, 5
+};
+
+static const u8 gUnknown_845C4B6[][6] = {
+ {0, 0, 0, 0, 0, 1},
+ {0, 0, 0, 1, 0, 1},
+ {0, 0, 0, 1, 0, 1},
+ {0, 1, 0, 1, 0, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 1, 1, 0, 0, 1},
+ {0, 1, 1, 0, 0, 1},
+ {0, 0, 1, 0, 0, 1},
+ {0, 0, 1, 0, 0, 1},
+ {0, 1, 1, 0, 0, 1},
+ {0, 1, 1, 0, 0, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 1, 1, 0, 0, 1},
+ {0, 1, 1, 0, 0, 1},
+ {1, 0, 0, 1, 0, 1},
+ {1, 1, 1, 0, 0, 1},
+ {1, 1, 1, 1, 0, 1},
+ {1, 1, 1, 0, 0, 1},
+ {1, 1, 1, 0, 1, 1},
+ {1, 1, 1, 0, 0, 1},
+ {1, 1, 1, 0, 0, 1},
+ {1, 1, 1, 0, 0, 1},
+ {1, 1, 1, 0, 0, 1},
+ {1, 1, 1, 0, 1, 1},
+ {1, 1, 1, 0, 1, 1},
+ {1, 1, 1, 0, 1, 1},
+ {1, 1, 1, 0, 1, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 1, 0, 0, 0, 1},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}
+};
+
+static const u16 gUnknown_845C594[] = {
+ MAP_VIRIDIAN_CITY_MART,
+ MAP_PEWTER_CITY_MART,
+ MAP_CERULEAN_CITY_MART,
+ MAP_LAVENDER_TOWN_MART,
+ MAP_VERMILION_CITY_MART,
+ MAP_CELADON_CITY_DEPARTMENT_STORE_1F,
+ MAP_CELADON_CITY_DEPARTMENT_STORE_2F,
+ MAP_CELADON_CITY_DEPARTMENT_STORE_3F,
+ MAP_CELADON_CITY_DEPARTMENT_STORE_4F,
+ MAP_CELADON_CITY_DEPARTMENT_STORE_5F,
+ MAP_CELADON_CITY_DEPARTMENT_STORE_ROOF,
+ MAP_CELADON_CITY_DEPARTMENT_STORE_ELEVATOR,
+ MAP_FUCHSIA_CITY_MART,
+ MAP_CINNABAR_ISLAND_MART,
+ MAP_SAFFRON_CITY_MART,
+ MAP_THREE_ISLAND_MART,
+ MAP_FOUR_ISLAND_MART,
+ MAP_SEVEN_ISLAND_MART,
+ MAP_SIX_ISLAND_MART,
+ MAP_UNDEFINED
+};
+
+static const u16 gUnknown_845C5BC[] = {
+ MAP_PEWTER_CITY_GYM,
+ MAP_CERULEAN_CITY_GYM,
+ MAP_VERMILION_CITY_GYM,
+ MAP_CELADON_CITY_GYM,
+ MAP_FUCHSIA_CITY_GYM,
+ MAP_SAFFRON_CITY_GYM,
+ MAP_CINNABAR_ISLAND_GYM,
+ MAP_VIRIDIAN_CITY_GYM,
+ MAP_UNDEFINED
+};
+
+static const u8 gUnknown_845C5CE[][3] = {
+ { MAP_GROUP(VIRIDIAN_FOREST), MAP_NUM(VIRIDIAN_FOREST), 1 },
+ { MAP_GROUP(MT_MOON_1F), MAP_NUM(MT_MOON_1F), 3 },
+ { MAP_GROUP(ROCK_TUNNEL_1F), MAP_NUM(ROCK_TUNNEL_1F), 2 },
+ { MAP_GROUP(DIGLETTS_CAVE_NORTH_ENTRANCE), MAP_NUM(DIGLETTS_CAVE_NORTH_ENTRANCE), 3 },
+ { MAP_GROUP(SEAFOAM_ISLANDS_1F), MAP_NUM(SEAFOAM_ISLANDS_1F), 5 },
+ { MAP_GROUP(VICTORY_ROAD_1F), MAP_NUM(VICTORY_ROAD_1F), 3 },
+ { MAP_GROUP(CERULEAN_CAVE_1F), MAP_NUM(CERULEAN_CAVE_1F), 3 },
+ { MAP_GROUP(MT_EMBER_RUBY_PATH_B4F), MAP_NUM(MT_EMBER_RUBY_PATH_B4F), 1 },
+ { MAP_GROUP(MT_EMBER_SUMMIT_PATH_1F), MAP_NUM(MT_EMBER_SUMMIT_PATH_1F), 3 },
+ { MAP_GROUP(MT_EMBER_RUBY_PATH_B5F), MAP_NUM(MT_EMBER_RUBY_PATH_B5F), 7 },
+ { MAP_GROUP(THREE_ISLAND_BERRY_FOREST), MAP_NUM(THREE_ISLAND_BERRY_FOREST), 1 },
+ { MAP_GROUP(SIX_ISLAND_PATTERN_BUSH), MAP_NUM(SIX_ISLAND_PATTERN_BUSH), 1 },
+ { MAP_GROUP(FIVE_ISLAND_LOST_CAVE_ENTRANCE), MAP_NUM(FIVE_ISLAND_LOST_CAVE_ENTRANCE), 15 },
+ { MAP_GROUP(FOUR_ISLAND_ICEFALL_CAVE_ENTRANCE), MAP_NUM(FOUR_ISLAND_ICEFALL_CAVE_ENTRANCE), 4 },
+ { MAP_GROUP(SIX_ISLAND_ALTERING_CAVE), MAP_NUM(SIX_ISLAND_ALTERING_CAVE), 1 },
+ { MAP_GROUP(SEVEN_ISLAND_TANOBY_RUINS_MONEAN_CHAMBER), MAP_NUM(SEVEN_ISLAND_TANOBY_RUINS_MONEAN_CHAMBER), 7 }
+};
+
+void sub_812B1E0(u8 a0)
+{
+ gUnknown_203B0EC = a0;
+}
+
+void HelpSystem_SetSomeVariable2(u8 a0)
+{
+ switch (gUnknown_203B0EC)
+ {
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ if (a0 == 9 || a0 == 5 || a0 == 6 || a0 == 7 || a0 == 8)
+ break;
+ // fallthrough
+ default:
+ gUnknown_203B0EC = a0;
+ break;
+ }
+}
+
+void sub_812B220(void)
+{
+ gUnknown_203B0EC = gSpecialVar_0x8004;
+}
+
+void sub_812B234(void)
+{
+ gUnknown_3005EA0 = gUnknown_203B0EC;
+}
+
+void sub_812B248(void)
+{
+ gUnknown_203B0EC = gUnknown_3005EA0;
+}
+
+static bool32 sub_812B25C(void)
+{
+ return sub_812B27C(gUnknown_845C594);
+}
+
+static bool32 sub_812B26C(void)
+{
+ return sub_812B27C(gUnknown_845C5BC);
+}
+
+static bool32 sub_812B27C(const u16 * mapIdxs)
+{
+ u16 mapIdx = (gSaveBlock1Ptr->location.mapGroup << 8) + gSaveBlock1Ptr->location.mapNum;
+ s32 i;
+
+ for (i = 0; mapIdxs[i] != MAP_UNDEFINED; i++)
+ {
+ if (mapIdxs[i] == mapIdx)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static bool8 sub_812B2C4(void)
+{
+ u8 i, j;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < gUnknown_845C5CE[i][2]; j++)
+ {
+ if (
+ gUnknown_845C5CE[i][0] == gSaveBlock1Ptr->location.mapGroup
+ && gUnknown_845C5CE[i][1] + j == gSaveBlock1Ptr->location.mapNum
+ && (i != 15 || FlagGet(FLAG_0x849) == TRUE)
+ )
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void sub_812B35C(void)
+{
+ sub_812B4B8();
+ if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING))
+ HelpSystem_SetSomeVariable2(0x16);
+ else if (sub_812B2C4())
+ HelpSystem_SetSomeVariable2(0x15);
+ else if (is_light_level_8_or_9(gMapHeader.mapType))
+ {
+ if ((gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(PALLET_TOWN_PLAYERS_HOUSE_1F) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(PALLET_TOWN_PLAYERS_HOUSE_1F)) || (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(PALLET_TOWN_PLAYERS_HOUSE_2F) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(PALLET_TOWN_PLAYERS_HOUSE_2F)))
+ HelpSystem_SetSomeVariable2(0x0E);
+ else if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(PALLET_TOWN_PROFESSOR_OAKS_LAB) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(PALLET_TOWN_PROFESSOR_OAKS_LAB))
+ HelpSystem_SetSomeVariable2(0x0F);
+ else if (IsCurMapPokeCenter() == TRUE)
+ HelpSystem_SetSomeVariable2(0x10);
+ else if (sub_812B25C() == TRUE)
+ HelpSystem_SetSomeVariable2(0x11);
+ else if (sub_812B26C() == TRUE)
+ HelpSystem_SetSomeVariable2(0x12);
+ else
+ HelpSystem_SetSomeVariable2(0x13);
+ }
+ else
+ HelpSystem_SetSomeVariable2(0x14);
+}
+
+bool8 sub_812B40C(void)
+{
+ if (gUnknown_203B0EE == 1)
+ return FALSE;
+
+ if (gSaveFileStatus != SAVE_STATUS_EMPTY && gSaveFileStatus != SAVE_STATUS_INVALID && FlagGet(FLAG_0x83C))
+ return FALSE;
+
+ FlagSet(FLAG_0x83C);
+ gUnknown_203B0EE = 1;
+ return TRUE;
+}
+
+bool8 sub_812B45C(void)
+{
+ if (gReceivedRemoteLinkPlayers == 1)
+ return FALSE;
+ return TRUE;
+}
+
+void sub_812B478(void)
+{
+ gUnknown_3005ECC = 0;
+}
+
+void sub_812B484(void)
+{
+ if (gUnknown_203ADFA != 2 && gUnknown_203ADFA != 3)
+ {
+ gUnknown_3005ECC = 1;
+ sub_812B4B8();
+ }
+}
+
+void sub_812B4AC(void)
+{
+ gUnknown_203F175 = 1;
+}
+
+void sub_812B4B8(void)
+{
+ gUnknown_203F175 = 0;
+}
+
+static void sub_812B4C4(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ a0->sub.items = a1;
+ a0->sub.totalItems = 1;
+ a0->sub.maxShowed = 1;
+ a0->sub.left = 1;
+ a0->sub.top = 4;
+}
+
+static void sub_812B4D8(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ sub_812B4C4(a0, a1);
+ sub_812B520(a0, a1);
+ sub_812BF74(gUnknown_841DFAC);
+ HelpSystem_InitListMenuController(a0, 0, gUnknown_3005E9C[2]);
+ sub_812BF9C(a0, a1);
+ sub_813BDA4(1);
+ sub_813BD5C(1);
+}
+
+static void sub_812B520(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ u8 i;
+ u8 r4 = 0;
+ for (i = 0; i < 6; i++)
+ {
+ if (gUnknown_845C4B6[gUnknown_203B0EC][gUnknown_845C4B0[i]] == 1)
+ {
+ a1[r4].label = gUnknown_845B080[gUnknown_845C4B0[i]];
+ a1[r4].index = gUnknown_845C4B0[i];
+ r4++;
+ }
+ }
+ a1[r4 - 1].index = -2;
+ a0->sub.totalItems = r4;
+ a0->sub.maxShowed = r4;
+ a0->sub.left = 0;
+}
+
+static void sub_812B5A8(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ sub_813BDE8(0);
+ sub_813BFC0(0);
+ sub_813BE78(1);
+ sub_812B4C4(a0, a1);
+ sub_812B614(a0, a1);
+ sub_812BF74(gUnknown_841DFC9);
+ HelpSystem_InitListMenuController(a0, a0->field_0C, a0->field_0D);
+ HelpSystem_PrintTextAt(gUnknown_845B080[gUnknown_3005E9C[1]], 0, 0);
+ sub_813BDA4(1);
+ sub_813BD5C(1);
+}
+
+static void sub_812B614(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ u8 r6 = 0;
+ const u8 * r3 = gUnknown_845B9E0[gUnknown_203B0EC * 5 + gUnknown_3005E9C[1]];
+ u8 i;
+ for (i = 0; r3[i] != 0xFF; i++)
+ {
+ if (sub_812B780(r3[i]) == TRUE)
+ {
+ if (gUnknown_3005E9C[1] == 0)
+ a1[r6].label = gUnknown_845B0B0[r3[i]];
+ else if (gUnknown_3005E9C[1] == 1)
+ a1[r6].label = gUnknown_845B218[r3[i]];
+ else if (gUnknown_3005E9C[1] == 2)
+ a1[r6].label = gUnknown_845B3A0[r3[i]];
+ else if (gUnknown_3005E9C[1] == 3)
+ a1[r6].label = gUnknown_845B500[r3[i]];
+ else
+ a1[r6].label = gUnknown_845B540[r3[i]];
+ a1[r6].index = r3[i];
+ r6++;
+ }
+ }
+ if (sub_812B754() == TRUE)
+ {
+ for (i = 0, r3 = gUnknown_845B9BE; r3[i] != 0xFF; i++)
+ {
+ a1[r6].label = gUnknown_845B3A0[r3[i]];
+ a1[r6].index = r3[i];
+ r6++;
+ }
+ }
+ a1[r6].label = gUnknown_81B2E6F;
+ a1[r6].index = -2;
+ r6++;
+ a0->sub.totalItems = r6;
+ a0->sub.maxShowed = 7;
+ a0->sub.left = 0;
+ a0->sub.top = 21;
+}
+
+static bool8 sub_812B754(void)
+{
+ if (FlagGet(FLAG_0x4B0) == TRUE && gUnknown_3005E9C[1] == 2)
+ return TRUE;
+ return FALSE;
+}
+
+static bool8 sub_812B780(u8 id)
+{
+ u8 i = 0;
+
+ if (gUnknown_3005E9C[1] == 0)
+ {
+ switch (id)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 8:
+ case 34:
+ case 38:
+ case 41:
+ case 42:
+ case 43:
+ return TRUE;
+ case 4:
+ return FlagGet(FLAG_0x2CF);
+ case 6:
+ case 10:
+ case 16:
+ case 19:
+ case 22:
+ case 35:
+ case 36:
+ return FlagGet(FLAG_WORLD_MAP_VIRIDIAN_CITY);
+ case 7:
+ return FlagGet(FLAG_WORLD_MAP_VERMILION_CITY);
+ case 11:
+ case 24:
+ return FlagGet(FLAG_0x8A4);
+ case 9:
+ case 13:
+ case 14:
+ case 15:
+ case 17:
+ case 18:
+ case 20:
+ case 26:
+ case 29:
+ case 31:
+ case 37:
+ return FlagGet(FLAG_0x828);
+ case 21:
+ case 23:
+ return FlagGet(FLAG_0x829);
+ case 12:
+ case 25:
+ case 27:
+ case 30:
+ case 32:
+ case 33:
+ return FlagGet(FLAG_UNK820);
+ case 28:
+ case 40:
+ return sub_812BB10();
+ case 39:
+ return FlagGet(FLAG_0x29B);
+ case 44:
+ return FlagGet(FLAG_WORLD_MAP_PEWTER_CITY);
+ }
+ return FALSE;
+ }
+ if (gUnknown_3005E9C[1] == 1)
+ {
+ switch (id)
+ {
+ case 06:
+ case 10:
+ case 11:
+ case 12:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 31:
+ case 36:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 45:
+ case 46:
+ case 47:
+ return TRUE;
+ case 1:
+ case 30:
+ case 37:
+ return FlagGet(FLAG_0x829);
+ case 14:
+ return CheckBagHasItem(ITEM_TOWN_MAP, 1);
+ case 2:
+ case 3:
+ case 5:
+ case 7:
+ case 8:
+ case 9:
+ case 13:
+ case 32:
+ case 33:
+ case 35:
+ case 43:
+ case 44:
+ return FlagGet(FLAG_0x828);
+ case 4:
+ case 34:
+ if (sub_8088EDC(1) > 1)
+ return TRUE;
+ return FALSE;
+ case 15:
+ return FlagGet(FLAG_UNK820);
+ case 16:
+ case 17:
+ return sub_812BB10();
+ case 18:
+ return FlagGet(FLAG_0x271);
+ case 48:
+ return FlagGet(FLAG_0x82C);
+ }
+ return FALSE;
+ }
+ if (gUnknown_3005E9C[1] == 2)
+ {
+ if (sub_812B754() == TRUE)
+ {
+ for (i = 0; gUnknown_845B9BE[i] != 0xFF; i++)
+ {
+ if (gUnknown_845B9BE[i] == id)
+ return FALSE;
+ }
+ }
+ switch (id)
+ {
+ case 14:
+ case 17:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 38:
+ return TRUE;
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 16:
+ case 19:
+ case 20:
+ case 21:
+ return FlagGet(FLAG_0x828);
+ case 36:
+ case 37:
+ return sub_812BB10();
+ case 3:
+ case 15:
+ case 18:
+ case 39:
+ return FlagGet(FLAG_0x8A4);
+ }
+ return TRUE;
+ }
+ if (gUnknown_3005E9C[1] == 3)
+ {
+ switch (id)
+ {
+ case 5:
+ return FlagGet(FLAG_UNK820);
+ case 6:
+ return FlagGet(FLAG_0x821);
+ }
+ return TRUE;
+ }
+ if (gUnknown_3005E9C[1] == 4)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static bool8 sub_812BB10(void)
+{
+ if (FlagGet(FLAG_0x237) == TRUE)
+ return TRUE;
+ if (FlagGet(FLAG_0x238) == TRUE)
+ return TRUE;
+ if (FlagGet(FLAG_0x239) == TRUE)
+ return TRUE;
+ if (FlagGet(FLAG_0x23A) == TRUE)
+ return TRUE;
+ if (FlagGet(FLAG_0x23B) == TRUE)
+ return TRUE;
+ if (FlagGet(FLAG_0x2EF) == TRUE)
+ return TRUE;
+ if (FlagGet(FLAG_0x1F1) == TRUE)
+ return TRUE;
+ return FALSE;
+}
+
+bool8 sub_812BB9C(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ switch (a0->field_0E)
+ {
+ case 8:
+ return sub_812BC54(a0, a1);
+ case 9:
+ return sub_812BC80(a0, a1);
+ case 10:
+ return sub_812BCA8(a0, a1);
+ case 0:
+ return sub_812BCD0(a0, a1);
+ case 1:
+ return sub_812BD2C(a0, a1);
+ case 2:
+ return sub_812BD64(a0, a1);
+ case 3:
+ return sub_812BD98(a0, a1);
+ case 4:
+ return sub_812BE10(a0, a1);
+ case 5:
+ return sub_812BEEC(a0, a1);
+ case 6:
+ return sub_812BF18(a0, a1);
+ }
+ return FALSE;
+}
+
+bool8 sub_812BC54(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ sub_812BF74(gUnknown_841DFA5);
+ sub_812BF5C();
+ sub_813BDA4(1);
+ sub_813BD5C(1);
+ a0->field_0E = 9;
+ return TRUE;
+}
+
+bool8 sub_812BC80(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ a0->field_0E = 10;
+ }
+ return TRUE;
+}
+
+bool8 sub_812BCA8(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ gUnknown_3005E9C[2] = 0;
+ sub_812BF94(a0);
+ sub_812B4D8(a0, a1);
+ a0->field_0E = 0;
+ return TRUE;
+}
+
+bool8 sub_812BCD0(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ s32 v0 = HelpSystem_GetMenuInput();
+ switch (v0)
+ {
+ case -6:
+ case -2:
+ return FALSE;
+ case -5:
+ case -4:
+ sub_812BF9C(a0, a1);
+ break;
+ case -3:
+ case -1:
+ break;
+ default:
+ gUnknown_3005E9C[1] = v0;
+ a0->field_0E = 1;
+ break;
+ }
+ return TRUE;
+}
+
+bool8 sub_812BD2C(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ gUnknown_3005E9C[0] = 1;
+ gUnknown_3005E9C[2] = a0->field_0D;
+ sub_812BF94(a0);
+ sub_812B5A8(a0, a1);
+ sub_813C75C();
+ HelpSystem_SetInputDelay(2);
+ a0->field_0E = 3;
+ return TRUE;
+}
+
+bool8 sub_812BD64(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ sub_813C004(0, 0);
+ sub_813C004(1, 0);
+ gUnknown_3005E9C[0] = 0;
+ sub_812B4D8(a0, a1);
+ a0->field_0E = 0;
+ return TRUE;
+}
+
+bool8 sub_812BD98(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ s32 v0 = HelpSystem_GetMenuInput();
+ switch (v0)
+ {
+ case -6:
+ return FALSE;
+ case -2:
+ a0->field_0E = 2;
+ break;
+ case -5:
+ case -4:
+ case -3:
+ case -1:
+ break;
+ default:
+ gUnknown_3005E9C[3] = v0;
+ a0->field_0E = 4;
+ break;
+ }
+ return TRUE;
+}
+
+void sub_812BDEC(void)
+{
+ HelpSystem_PrintTextAt(gUnknown_845B080[gUnknown_3005E9C[1]], 0, 0);
+}
+
+bool8 sub_812BE10(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ gUnknown_3005E9C[0] = 2;
+ sub_813BDA4(0);
+ HelpSystem_FillPanel1();
+ sub_812BF74(gUnknown_841DFBE);
+ sub_813BDE8(1);
+ sub_813BEE4(1);
+
+ if (gUnknown_3005E9C[1] == 0)
+ {
+ HelpSystem_PrintTwoStrings(gUnknown_845B0B0[gUnknown_3005E9C[3]], gUnknown_845B164[gUnknown_3005E9C[3]]);
+ }
+ else if (gUnknown_3005E9C[1] == 1)
+ {
+ HelpSystem_PrintTwoStrings(gUnknown_845B218[gUnknown_3005E9C[3]], gUnknown_845B2DC[gUnknown_3005E9C[3]]);
+ }
+ else if (gUnknown_3005E9C[1] == 2)
+ {
+ HelpSystem_PrintTwoStrings(gUnknown_845B3A0[gUnknown_3005E9C[3]], gUnknown_845B450[gUnknown_3005E9C[3]]);
+ }
+ else if (gUnknown_3005E9C[1] == 3)
+ {
+ HelpSystem_PrintTwoStrings(gUnknown_845B500[gUnknown_3005E9C[3]], gUnknown_845B520[gUnknown_3005E9C[3]]);
+ }
+ else
+ {
+ HelpSystem_PrintTwoStrings(gUnknown_845B540[gUnknown_3005E9C[3]], gUnknown_845B5D0[gUnknown_3005E9C[3]]);
+ }
+ sub_813BDA4(1);
+ sub_813BD5C(1);
+ a0->field_0E = 6;
+ return TRUE;
+}
+
+bool8 sub_812BEEC(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ gUnknown_3005E9C[0] = 1;
+ sub_812B5A8(a0, a1);
+ sub_813C75C();
+ HelpSystem_SetInputDelay(2);
+ a0->field_0E = 3;
+ return TRUE;
+}
+
+bool8 sub_812BF18(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ if (JOY_NEW(B_BUTTON) || JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ a0->field_0E = 5;
+ return TRUE;
+ }
+ if (JOY_NEW(L_BUTTON | R_BUTTON))
+ return FALSE;
+ return TRUE;
+}
+
+static void sub_812BF5C(void)
+{
+ HelpSystem_FillPanel1();
+ HelpSystem_PrintTextAt(gUnknown_81B2FC9, 0, 0);
+}
+
+static void sub_812BF74(const u8 * str)
+{
+ HelpSystem_FillPanel2();
+ HelpSystem_PrintTextRightAlign_Row52(str);
+}
+
+u8 sub_812BF88(void)
+{
+ return gUnknown_3005E9C[0];
+}
+
+static void sub_812BF94(struct HelpSystemListMenu * a0)
+{
+ a0->field_0C = 0;
+ a0->field_0D = 0;
+}
+
+static void sub_812BF9C(struct HelpSystemListMenu * a0, struct ListMenuItem * a1)
+{
+ s32 index = a1[a0->field_0C + a0->field_0D].index;
+ if (index == -2)
+ HelpSystem_PrintText_813C584(gUnknown_845B098[5]);
+ else
+ HelpSystem_PrintText_813C584(gUnknown_845B098[index]);
+ sub_813BE30(1);
+}
diff --git a/src/item.c b/src/item.c
new file mode 100644
index 000000000..3f33f464d
--- /dev/null
+++ b/src/item.c
@@ -0,0 +1,684 @@
+#include "global.h"
+#include "berry.h"
+#include "event_data.h"
+#include "item.h"
+#include "item_use.h"
+#include "load_save.h"
+#include "malloc.h"
+#include "quest_log.h"
+#include "string_util.h"
+#include "strings.h"
+#include "constants/hold_effects.h"
+#include "constants/items.h"
+#include "constants/maps.h"
+
+void SortAndCompactBagPocket(struct BagPocket * pocket);
+
+// Item descriptions and data
+#include "data/items.h"
+
+u16 GetBagItemQuantity(u16 * ptr)
+{
+ return gSaveBlock2Ptr->encryptionKey ^ *ptr;
+}
+
+void SetBagItemQuantity(u16 * ptr, u16 value)
+{
+ *ptr = value ^ gSaveBlock2Ptr->encryptionKey;
+}
+
+u16 GetPcItemQuantity(u16 * ptr)
+{
+ return 0 ^ *ptr;
+}
+
+void SetPcItemQuantity(u16 * ptr, u16 value)
+{
+ *ptr = value ^ 0;
+}
+
+void ApplyNewEncryptionKeyToBagItems(u32 key)
+{
+ u32 i, j;
+
+ for (i = 0; i < NUM_BAG_POCKETS; i++)
+ {
+ for (j = 0; j < gBagPockets[i].capacity; j++)
+ {
+ ApplyNewEncryptionKeyToHword(&gBagPockets[i].itemSlots[j].quantity, key);
+ }
+ }
+}
+
+void ApplyNewEncryptionKeyToBagItems_(u32 key)
+{
+ ApplyNewEncryptionKeyToBagItems(key);
+}
+
+void SetBagPocketsPointers(void)
+{
+ gBagPockets[POCKET_ITEMS - 1].itemSlots = gSaveBlock1Ptr->bagPocket_Items;
+ gBagPockets[POCKET_ITEMS - 1].capacity = BAG_ITEMS_COUNT;
+ gBagPockets[POCKET_KEY_ITEMS - 1].itemSlots = gSaveBlock1Ptr->bagPocket_KeyItems;
+ gBagPockets[POCKET_KEY_ITEMS - 1].capacity = BAG_KEYITEMS_COUNT;
+ gBagPockets[POCKET_POKE_BALLS - 1].itemSlots = gSaveBlock1Ptr->bagPocket_PokeBalls;
+ gBagPockets[POCKET_POKE_BALLS - 1].capacity = BAG_POKEBALLS_COUNT;
+ gBagPockets[POCKET_TM_CASE - 1].itemSlots = gSaveBlock1Ptr->bagPocket_TMHM;
+ gBagPockets[POCKET_TM_CASE - 1].capacity = BAG_TMHM_COUNT;
+ gBagPockets[POCKET_BERRY_POUCH - 1].itemSlots = gSaveBlock1Ptr->bagPocket_Berries;
+ gBagPockets[POCKET_BERRY_POUCH - 1].capacity = BAG_BERRIES_COUNT;
+}
+
+void CopyItemName(u16 itemId, u8 * dest)
+{
+ if (itemId == ITEM_ENIGMA_BERRY)
+ {
+ StringCopy(dest, sub_809C8A0(43)->name);
+ StringAppend(dest, gUnknown_84162BD);
+ }
+ else
+ {
+ StringCopy(dest, ItemId_GetName(itemId));
+ }
+}
+
+s8 BagPocketGetFirstEmptySlot(u8 pocketId)
+{
+ u16 i;
+
+ for (i = 0; i < gBagPockets[pocketId].capacity; i++)
+ {
+ if (gBagPockets[pocketId].itemSlots[i].itemId == ITEM_NONE)
+ return i;
+ }
+
+ return -1;
+}
+
+bool8 IsPocketNotEmpty(u8 pocketId)
+{
+ u8 i;
+
+ for (i = 0; i < gBagPockets[pocketId - 1].capacity; i++)
+ {
+ if (gBagPockets[pocketId - 1].itemSlots[i].itemId != ITEM_NONE)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+bool8 CheckBagHasItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u8 pocket;
+
+ if (ItemId_GetPocket(itemId) == 0)
+ return FALSE;
+
+ pocket = ItemId_GetPocket(itemId) - 1;
+ // Check for item slots that contain the item
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ {
+ u16 quantity;
+ // Does this item slot contain enough of the item?
+ quantity = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity);
+ if (quantity >= count)
+ return TRUE;
+ // RS and Emerald check whether there is enough of the
+ // item across all stacks.
+ // For whatever reason, FR/LG assume there's only one
+ // stack of the item.
+ else
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+bool8 CheckHasAtLeastOneBerry(void)
+{
+ u8 itemId;
+ bool8 exists;
+
+ exists = CheckBagHasItem(ITEM_BERRY_POUCH, 1);
+ if (!exists)
+ {
+ gSpecialVar_Result = FALSE;
+ return FALSE;
+ }
+ for (itemId = FIRST_BERRY_INDEX; itemId <= LAST_BERRY_INDEX; itemId++)
+ {
+ exists = CheckBagHasItem(itemId, 1);
+ if (exists)
+ {
+ gSpecialVar_Result = TRUE;
+ return TRUE;
+ }
+ }
+
+ gSpecialVar_Result = FALSE;
+ return FALSE;
+}
+
+bool8 CheckBagHasSpace(u16 itemId, u16 count)
+{
+ u8 i;
+ u8 pocket;
+
+ if (ItemId_GetPocket(itemId) == 0)
+ return FALSE;
+
+ pocket = ItemId_GetPocket(itemId) - 1;
+ // Check for item slots that contain the item
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ {
+ u16 quantity;
+ // Does this stack have room for more??
+ quantity = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity);
+ if (quantity + count <= 999)
+ return TRUE;
+ // RS and Emerald check whether there is enough of the
+ // item across all stacks.
+ // For whatever reason, FR/LG assume there's only one
+ // stack of the item.
+ else
+ return FALSE;
+ }
+ }
+
+ if (BagPocketGetFirstEmptySlot(pocket) != -1)
+ return TRUE;
+
+ return FALSE;
+}
+
+bool8 AddBagItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u8 pocket;
+ s8 idx;
+
+ if (ItemId_GetPocket(itemId) == 0)
+ return FALSE;
+
+ pocket = ItemId_GetPocket(itemId) - 1;
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ {
+ u16 quantity;
+ // Does this stack have room for more??
+ quantity = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity);
+ if (quantity + count <= 999)
+ {
+ quantity += count;
+ SetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity, quantity);
+ return TRUE;
+ }
+ // RS and Emerald check whether there is enough of the
+ // item across all stacks.
+ // For whatever reason, FR/LG assume there's only one
+ // stack of the item.
+ else
+ return FALSE;
+ }
+ }
+
+ if (pocket == POCKET_TM_CASE - 1 && !CheckBagHasItem(ITEM_TM_CASE, 1))
+ {
+ idx = BagPocketGetFirstEmptySlot(POCKET_KEY_ITEMS - 1);
+ if (idx == -1)
+ return FALSE;
+ gBagPockets[POCKET_KEY_ITEMS - 1].itemSlots[idx].itemId = ITEM_TM_CASE;
+ SetBagItemQuantity(&gBagPockets[POCKET_KEY_ITEMS - 1].itemSlots[idx].quantity, 1);
+ }
+
+ if (pocket == POCKET_BERRY_POUCH - 1 && !CheckBagHasItem(ITEM_BERRY_POUCH, 1))
+ {
+ idx = BagPocketGetFirstEmptySlot(POCKET_KEY_ITEMS - 1);
+ if (idx == -1)
+ return FALSE;
+ gBagPockets[POCKET_KEY_ITEMS - 1].itemSlots[idx].itemId = ITEM_BERRY_POUCH;
+ SetBagItemQuantity(&gBagPockets[POCKET_KEY_ITEMS - 1].itemSlots[idx].quantity, 1);
+ FlagSet(FLAG_0x847);
+ }
+
+ if (itemId == ITEM_BERRY_POUCH)
+ FlagSet(FLAG_0x847);
+
+ idx = BagPocketGetFirstEmptySlot(pocket);
+ if (idx == -1)
+ return FALSE;
+
+ gBagPockets[pocket].itemSlots[idx].itemId = itemId;
+ SetBagItemQuantity(&gBagPockets[pocket].itemSlots[idx].quantity, count);
+ return TRUE;
+}
+
+bool8 RemoveBagItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u8 pocket;
+
+ if (ItemId_GetPocket(itemId) == 0)
+ return FALSE;
+
+ if (itemId == ITEM_NONE)
+ return FALSE;
+
+ pocket = ItemId_GetPocket(itemId) - 1;
+ // Check for item slots that contain the item
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ {
+ u16 quantity;
+ // Does this item slot contain enough of the item?
+ quantity = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity);
+ if (quantity >= count)
+ {
+ quantity -= count;
+ SetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity, quantity);
+ if (quantity == 0)
+ gBagPockets[pocket].itemSlots[i].itemId = ITEM_NONE;
+ return TRUE;
+ }
+ // RS and Emerald check whether there is enough of the
+ // item across all stacks.
+ // For whatever reason, FR/LG assume there's only one
+ // stack of the item.
+ else
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+u8 GetPocketByItemId(u16 itemId)
+{
+ return ItemId_GetPocket(itemId); // wow such important
+}
+
+void ClearItemSlots(struct ItemSlot * slots, u8 capacity)
+{
+ u16 i;
+
+ for (i = 0; i < capacity; i++)
+ {
+ slots[i].itemId = ITEM_NONE;
+ SetBagItemQuantity(&slots[i].quantity, 0);
+ }
+}
+
+void ClearPCItemSlots(void)
+{
+ u16 i;
+
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ gSaveBlock1Ptr->pcItems[i].itemId = ITEM_NONE;
+ SetPcItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity, 0);
+ }
+}
+
+void ClearItemSlotsInAllBagPockets(void)
+{
+ u16 i;
+
+ for (i = 0; i < 5; i++)
+ {
+ ClearItemSlots(gBagPockets[i].itemSlots, gBagPockets[i].capacity);
+ }
+}
+
+s8 PCItemsGetFirstEmptySlot(void)
+{
+ s8 i;
+
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId == ITEM_NONE)
+ return i;
+ }
+
+ return -1;
+}
+
+u8 CountItemsInPC(void)
+{
+ u8 count = 0;
+ u8 i;
+
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId != ITEM_NONE)
+ count++;
+ }
+
+ return count;
+}
+
+bool8 CheckPCHasItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u16 quantity;
+
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId == itemId)
+ {
+ quantity = GetPcItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity);
+ if (quantity >= count)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+bool8 AddPCItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u16 quantity;
+ s8 idx;
+
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId == itemId)
+ {
+ quantity = GetPcItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity);
+ if (quantity + count <= 999)
+ {
+ quantity += count;
+ SetPcItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity, quantity);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ }
+
+ idx = PCItemsGetFirstEmptySlot();
+ if (idx == -1)
+ return FALSE;
+
+ gSaveBlock1Ptr->pcItems[idx].itemId = itemId;
+ SetPcItemQuantity(&gSaveBlock1Ptr->pcItems[idx].quantity, count);
+ return TRUE;
+}
+
+void RemoveItemFromPC(u16 itemId, u16 count)
+{
+ u32 i;
+ u16 quantity;
+
+ if (itemId == ITEM_NONE)
+ return;
+
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId == itemId)
+ break;
+ }
+
+ if (i != PC_ITEMS_COUNT)
+ {
+ quantity = GetPcItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity) - count;
+ SetPcItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity, quantity);
+ if (quantity == 0)
+ gSaveBlock1Ptr->pcItems[i].itemId = ITEM_NONE;
+ }
+}
+
+void ItemPcCompaction(void)
+{
+ u16 i, j;
+ struct ItemSlot tmp;
+
+ for (i = 0; i < PC_ITEMS_COUNT - 1; i++)
+ {
+ for (j = i + 1; j < PC_ITEMS_COUNT; j++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId == ITEM_NONE)
+ {
+ tmp = gSaveBlock1Ptr->pcItems[i];
+ gSaveBlock1Ptr->pcItems[i] = gSaveBlock1Ptr->pcItems[j];
+ gSaveBlock1Ptr->pcItems[j] = tmp;
+ }
+ }
+ }
+}
+
+void RegisteredItemHandleBikeSwap(void)
+{
+ switch (gSaveBlock1Ptr->registeredItem)
+ {
+ case ITEM_MACH_BIKE:
+ gSaveBlock1Ptr->registeredItem = ITEM_ACRO_BIKE;
+ break;
+ case ITEM_ACRO_BIKE:
+ gSaveBlock1Ptr->registeredItem = ITEM_MACH_BIKE;
+ break;
+ }
+}
+
+void SwapItemSlots(struct ItemSlot * a, struct ItemSlot * b)
+{
+ struct ItemSlot c;
+ c = *a;
+ *a = *b;
+ *b = c;
+}
+
+void BagPocketCompaction(struct ItemSlot * slots, u8 capacity)
+{
+ u16 i, j;
+
+ for (i = 0; i < capacity - 1; i++)
+ {
+ for (j = i + 1; j < capacity; j++)
+ {
+ if (GetBagItemQuantity(&slots[i].quantity) == 0)
+ {
+ SwapItemSlots(&slots[i], &slots[j]);
+ }
+ }
+ }
+}
+
+void SortPocketAndPlaceHMsFirst(struct BagPocket * pocket)
+{
+ u16 i;
+ u16 j = 0;
+ u16 k;
+ struct ItemSlot * buff;
+
+ SortAndCompactBagPocket(pocket);
+
+ for (i = 0; i < pocket->capacity; i++)
+ {
+ if (pocket->itemSlots[i].itemId == ITEM_NONE && GetBagItemQuantity(&pocket->itemSlots[i].quantity) == 0)
+ return;
+ if (pocket->itemSlots[i].itemId >= ITEM_HM01 && GetBagItemQuantity(&pocket->itemSlots[i].quantity) != 0)
+ {
+ for (j = i + 1; j < pocket->capacity; j++)
+ {
+ if (pocket->itemSlots[j].itemId == ITEM_NONE && GetBagItemQuantity(&pocket->itemSlots[j].quantity) == 0)
+ break;
+ }
+ break;
+ }
+ }
+
+ for (k = 0; k < pocket->capacity; k++)
+ pocket->itemSlots[k].quantity = GetBagItemQuantity(&pocket->itemSlots[k].quantity);
+ buff = AllocZeroed(pocket->capacity * sizeof(struct ItemSlot));
+ CpuCopy16(pocket->itemSlots + i, buff, (j - i) * sizeof(struct ItemSlot));
+ CpuCopy16(pocket->itemSlots, buff + (j - i), i * sizeof(struct ItemSlot));
+ CpuCopy16(buff, pocket->itemSlots, pocket->capacity * sizeof(struct ItemSlot));
+ for (k = 0; k < pocket->capacity; k++)
+ SetBagItemQuantity(&pocket->itemSlots[k].quantity, pocket->itemSlots[k].quantity);
+ Free(buff);
+}
+
+void SortAndCompactBagPocket(struct BagPocket * pocket)
+{
+ u16 i, j;
+
+ for (i = 0; i < pocket->capacity; i++)
+ {
+ for (j = i + 1; j < pocket->capacity; j++)
+ {
+ if (GetBagItemQuantity(&pocket->itemSlots[i].quantity) == 0 || (GetBagItemQuantity(&pocket->itemSlots[j].quantity) != 0 && pocket->itemSlots[i].itemId > pocket->itemSlots[j].itemId))
+ SwapItemSlots(&pocket->itemSlots[i], &pocket->itemSlots[j]);
+ }
+ }
+}
+
+u16 BagGetItemIdByPocketPosition(u8 pocketId, u16 slotId)
+{
+ return gBagPockets[pocketId - 1].itemSlots[slotId].itemId;
+}
+
+u16 BagGetQuantityByPocketPosition(u8 pocketId, u16 slotId)
+{
+ return GetBagItemQuantity(&gBagPockets[pocketId - 1].itemSlots[slotId].quantity);
+}
+
+u16 BagGetQuantityByItemId(u16 itemId)
+{
+ u16 i;
+ struct BagPocket * pocket = &gBagPockets[ItemId_GetPocket(itemId) - 1];
+
+ for (i = 0; i < pocket->capacity; i++)
+ {
+ if (pocket->itemSlots[i].itemId == itemId)
+ return GetBagItemQuantity(&pocket->itemSlots[i].quantity);
+ }
+
+ return 0;
+}
+
+void sub_809A824(u16 itemId)
+{
+ struct QuestLogStruct_809A824
+ {
+ u16 itemId;
+ u8 mapSectionId;
+ } * ptr;
+ if
+ (
+ itemId == ITEM_OAKS_PARCEL
+ || itemId == ITEM_POKE_FLUTE
+ || itemId == ITEM_SECRET_KEY
+ || itemId == ITEM_BIKE_VOUCHER
+ || itemId == ITEM_GOLD_TEETH
+ || itemId == ITEM_OLD_AMBER
+ || itemId == ITEM_CARD_KEY
+ || itemId == ITEM_LIFT_KEY
+ || itemId == ITEM_HELIX_FOSSIL
+ || itemId == ITEM_DOME_FOSSIL
+ || itemId == ITEM_SILPH_SCOPE
+ || itemId == ITEM_BICYCLE
+ || itemId == ITEM_TOWN_MAP
+ || itemId == ITEM_VS_SEEKER
+ || itemId == ITEM_TEACHY_TV
+ || itemId == ITEM_RAINBOW_PASS
+ || itemId == ITEM_TEA
+ || itemId == ITEM_POWDER_JAR
+ || itemId == ITEM_RUBY
+ || itemId == ITEM_SAPPHIRE
+ )
+ {
+ if (itemId != ITEM_TOWN_MAP || (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(PALLET_TOWN_GARYS_HOUSE) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(PALLET_TOWN_GARYS_HOUSE)))
+ {
+ ptr = malloc(sizeof(*ptr));
+ ptr->itemId = itemId;
+ ptr->mapSectionId = gMapHeader.regionMapSectionId;
+ sub_8113550(40, (void *)ptr);
+ free(ptr);
+ }
+ }
+}
+
+u16 SanitizeItemId(u16 itemId)
+{
+ if (itemId >= ITEM_N_A)
+ return ITEM_NONE;
+ return itemId;
+}
+
+const u8 * ItemId_GetName(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].name;
+}
+
+u16 itemid_get_number(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].itemId;
+}
+
+u16 itemid_get_market_price(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].price;
+}
+
+u8 ItemId_GetHoldEffect(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].holdEffect;
+}
+
+u8 ItemId_GetHoldEffectParam(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].holdEffectParam;
+}
+
+const u8 * ItemId_GetDescription(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].description;
+}
+
+bool8 itemid_is_unique(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].importance;
+}
+
+u8 itemid_get_x19(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].exitsBagOnUse;
+}
+
+u8 ItemId_GetPocket(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].pocket;
+}
+
+u8 ItemId_GetType(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].type;
+}
+
+ItemUseFunc ItemId_GetFieldFunc(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].fieldUseFunc;
+}
+
+bool8 ItemId_GetBattleUsage(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].battleUsage;
+}
+
+ItemUseFunc ItemId_GetBattleFunc(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].battleUseFunc;
+}
+
+u8 ItemId_GetSecondaryId(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].secondaryId;
+}
diff --git a/src/item_menu_icons.c b/src/item_menu_icons.c
new file mode 100644
index 000000000..a244a1075
--- /dev/null
+++ b/src/item_menu_icons.c
@@ -0,0 +1,783 @@
+#include "global.h"
+#include "decompress.h"
+#include "graphics.h"
+#include "item_menu_icons.h"
+#include "malloc.h"
+#include "constants/items.h"
+
+static EWRAM_DATA u8 gUnknown_2039878[12] = {0};
+EWRAM_DATA void * gUnknown_2039884 = NULL;
+static EWRAM_DATA void * gUnknown_2039888 = NULL;
+
+static void sub_8098560(struct Sprite * sprite);
+static void sub_80985BC(struct Sprite * sprite);
+
+static const struct OamData gUnknown_83D416C = {
+ .affineMode = ST_OAM_AFFINE_NORMAL,
+ .shape = ST_OAM_SQUARE,
+ .size = 3,
+ .priority = 1,
+ .paletteNum = 0
+};
+
+static const union AnimCmd gUnknown_83D4174[] = {
+ ANIMCMD_FRAME( 0, 5),
+ ANIMCMD_FRAME(0x40, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83D4180[] = {
+ ANIMCMD_FRAME( 0, 5),
+ ANIMCMD_FRAME(0x80, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83D418C[] = {
+ ANIMCMD_FRAME( 0, 5),
+ ANIMCMD_FRAME(0xc0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const gUnknown_83D4198[] = {
+ gUnknown_83D4180,
+ gUnknown_83D418C,
+ gUnknown_83D4174
+};
+
+static const union AffineAnimCmd gUnknown_83D41A4[] = {
+ AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd gUnknown_83D41B4[] = {
+ AFFINEANIMCMD_FRAME(0, 0, -2, 2),
+ AFFINEANIMCMD_FRAME(0, 0, 2, 4),
+ AFFINEANIMCMD_FRAME(0, 0, -2, 4),
+ AFFINEANIMCMD_FRAME(0, 0, 2, 2),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd *const gUnknown_83D41DC[] = {
+ gUnknown_83D41A4,
+ gUnknown_83D41B4
+};
+
+const struct CompressedSpriteSheet gUnknown_83D41E4 = {
+ gUnknown_8E8362C,
+ 0x2000,
+ 100
+};
+
+const struct CompressedSpriteSheet gUnknown_83D41EC = {
+ gUnknown_8E83DBC,
+ 0x2000,
+ 100
+};
+
+const struct CompressedSpritePalette gUnknown_83D41F4 = {
+ gUnknown_8E84560,
+ 100
+};
+
+static const struct SpriteTemplate gUnknown_83D41FC = {
+ 100,
+ 100,
+ &gUnknown_83D416C,
+ gUnknown_83D4198,
+ NULL,
+ gUnknown_83D41DC,
+ SpriteCallbackDummy
+};
+
+static const struct OamData gUnknown_83D4214 = {
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .shape = ST_OAM_SQUARE,
+ .size = 1,
+ .priority = 1,
+ .paletteNum = 1
+};
+
+static const union AnimCmd gUnknown_83D421C[] = {
+ ANIMCMD_FRAME(0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83D4224[] = {
+ ANIMCMD_FRAME(4, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_83D422C[] = {
+ ANIMCMD_FRAME(0, 0, .hFlip = TRUE),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const gUnknown_83D4234[] = {
+ gUnknown_83D421C,
+ gUnknown_83D4224,
+ gUnknown_83D422C
+};
+
+const struct CompressedSpriteSheet gBagSwapSpriteSheet = {
+ gFile_graphics_interface_bag_swap_sheet,
+ 0x100,
+ 101
+};
+
+const struct CompressedSpritePalette gBagSwapSpritePalette = {
+ gFile_graphics_interface_bag_swap_palette,
+ 101
+};
+
+static const struct SpriteTemplate gUnknown_83D4250 = {
+ 101,
+ 101,
+ &gUnknown_83D4214,
+ gUnknown_83D4234,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCallbackDummy
+};
+
+static const struct OamData gUnknown_83D4268 = {
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .shape = ST_OAM_SQUARE,
+ .size = 2,
+ .priority = 1,
+ .paletteNum = 2
+};
+
+static const union AnimCmd gUnknown_83D4270[] = {
+ ANIMCMD_FRAME(0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const gUnknown_83D4278[] = {
+ gUnknown_83D4270
+};
+
+static const struct SpriteTemplate gUnknown_83D427C = {
+ 102,
+ 102,
+ &gUnknown_83D4268,
+ gUnknown_83D4278,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCallbackDummy
+};
+
+static const void *const gUnknown_83D4294[][2] = {
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_master_ball_sheet, gFile_graphics_items_icon_palettes_master_ball_palette},
+ {gFile_graphics_items_icons_ultra_ball_sheet, gFile_graphics_items_icon_palettes_ultra_ball_palette},
+ {gFile_graphics_items_icons_great_ball_sheet, gFile_graphics_items_icon_palettes_great_ball_palette},
+ {gFile_graphics_items_icons_poke_ball_sheet, gFile_graphics_items_icon_palettes_poke_ball_palette},
+ {gFile_graphics_items_icons_safari_ball_sheet, gFile_graphics_items_icon_palettes_safari_ball_palette},
+ {gFile_graphics_items_icons_net_ball_sheet, gFile_graphics_items_icon_palettes_net_ball_palette},
+ {gFile_graphics_items_icons_dive_ball_sheet, gFile_graphics_items_icon_palettes_dive_ball_palette},
+ {gFile_graphics_items_icons_nest_ball_sheet, gFile_graphics_items_icon_palettes_nest_ball_palette},
+ {gFile_graphics_items_icons_repeat_ball_sheet, gFile_graphics_items_icon_palettes_repeat_ball_palette},
+ {gFile_graphics_items_icons_timer_ball_sheet, gFile_graphics_items_icon_palettes_repeat_ball_palette},
+ {gFile_graphics_items_icons_luxury_ball_sheet, gFile_graphics_items_icon_palettes_luxury_ball_palette},
+ {gFile_graphics_items_icons_premier_ball_sheet, gFile_graphics_items_icon_palettes_luxury_ball_palette},
+ {gFile_graphics_items_icons_potion_sheet, gFile_graphics_items_icon_palettes_potion_palette},
+ {gFile_graphics_items_icons_antidote_sheet, gFile_graphics_items_icon_palettes_antidote_palette},
+ {gFile_graphics_items_icons_status_heal_sheet, gFile_graphics_items_icon_palettes_burn_heal_palette},
+ {gFile_graphics_items_icons_status_heal_sheet, gFile_graphics_items_icon_palettes_ice_heal_palette},
+ {gFile_graphics_items_icons_status_heal_sheet, gFile_graphics_items_icon_palettes_awakening_palette},
+ {gFile_graphics_items_icons_status_heal_sheet, gFile_graphics_items_icon_palettes_paralyze_heal_palette},
+ {gFile_graphics_items_icons_large_potion_sheet, gFile_graphics_items_icon_palettes_full_restore_palette},
+ {gFile_graphics_items_icons_large_potion_sheet, gFile_graphics_items_icon_palettes_max_potion_palette},
+ {gFile_graphics_items_icons_potion_sheet, gFile_graphics_items_icon_palettes_hyper_potion_palette},
+ {gFile_graphics_items_icons_potion_sheet, gFile_graphics_items_icon_palettes_super_potion_palette},
+ {gFile_graphics_items_icons_full_heal_sheet, gFile_graphics_items_icon_palettes_full_heal_palette},
+ {gFile_graphics_items_icons_revive_sheet, gFile_graphics_items_icon_palettes_revive_palette},
+ {gFile_graphics_items_icons_max_revive_sheet, gFile_graphics_items_icon_palettes_revive_palette},
+ {gFile_graphics_items_icons_fresh_water_sheet, gFile_graphics_items_icon_palettes_fresh_water_palette},
+ {gFile_graphics_items_icons_soda_pop_sheet, gFile_graphics_items_icon_palettes_soda_pop_palette},
+ {gFile_graphics_items_icons_lemonade_sheet, gFile_graphics_items_icon_palettes_lemonade_palette},
+ {gFile_graphics_items_icons_moomoo_milk_sheet, gFile_graphics_items_icon_palettes_moomoo_milk_palette},
+ {gFile_graphics_items_icons_powder_sheet, gFile_graphics_items_icon_palettes_energy_powder_palette},
+ {gFile_graphics_items_icons_energy_root_sheet, gFile_graphics_items_icon_palettes_energy_root_palette},
+ {gFile_graphics_items_icons_powder_sheet, gFile_graphics_items_icon_palettes_heal_powder_palette},
+ {gFile_graphics_items_icons_revival_herb_sheet, gFile_graphics_items_icon_palettes_revival_herb_palette},
+ {gFile_graphics_items_icons_ether_sheet, gFile_graphics_items_icon_palettes_ether_palette},
+ {gFile_graphics_items_icons_ether_sheet, gFile_graphics_items_icon_palettes_max_ether_palette},
+ {gFile_graphics_items_icons_ether_sheet, gFile_graphics_items_icon_palettes_elixir_palette},
+ {gFile_graphics_items_icons_ether_sheet, gFile_graphics_items_icon_palettes_max_elixir_palette},
+ {gFile_graphics_items_icons_lava_cookie_sheet, gFile_graphics_items_icon_palettes_lava_cookie_and_letter_palette},
+ {gFile_graphics_items_icons_flute_sheet, gFile_graphics_items_icon_palettes_blue_flute_palette},
+ {gFile_graphics_items_icons_flute_sheet, gFile_graphics_items_icon_palettes_yellow_flute_palette},
+ {gFile_graphics_items_icons_flute_sheet, gFile_graphics_items_icon_palettes_red_flute_palette},
+ {gFile_graphics_items_icons_flute_sheet, gFile_graphics_items_icon_palettes_black_flute_palette},
+ {gFile_graphics_items_icons_flute_sheet, gFile_graphics_items_icon_palettes_white_flute_palette},
+ {gFile_graphics_items_icons_berry_juice_sheet, gFile_graphics_items_icon_palettes_berry_juice_palette},
+ {gFile_graphics_items_icons_sacred_ash_sheet, gFile_graphics_items_icon_palettes_sacred_ash_palette},
+ {gFile_graphics_items_icons_powder_sheet, gFile_graphics_items_icon_palettes_shoal_salt_palette},
+ {gFile_graphics_items_icons_shoal_shell_sheet, gFile_graphics_items_icon_palettes_shell_palette},
+ {gFile_graphics_items_icons_shard_sheet, gFile_graphics_items_icon_palettes_red_shard_palette},
+ {gFile_graphics_items_icons_shard_sheet, gFile_graphics_items_icon_palettes_blue_shard_palette},
+ {gFile_graphics_items_icons_shard_sheet, gFile_graphics_items_icon_palettes_yellow_shard_palette},
+ {gFile_graphics_items_icons_shard_sheet, gFile_graphics_items_icon_palettes_green_shard_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_hp_up_sheet, gFile_graphics_items_icon_palettes_hp_up_palette},
+ {gFile_graphics_items_icons_vitamin_sheet, gFile_graphics_items_icon_palettes_protein_palette},
+ {gFile_graphics_items_icons_vitamin_sheet, gFile_graphics_items_icon_palettes_iron_palette},
+ {gFile_graphics_items_icons_vitamin_sheet, gFile_graphics_items_icon_palettes_carbos_palette},
+ {gFile_graphics_items_icons_vitamin_sheet, gFile_graphics_items_icon_palettes_calcium_palette},
+ {gFile_graphics_items_icons_rare_candy_sheet, gFile_graphics_items_icon_palettes_rare_candy_palette},
+ {gFile_graphics_items_icons_pp_up_sheet, gFile_graphics_items_icon_palettes_pp_up_palette},
+ {gFile_graphics_items_icons_vitamin_sheet, gFile_graphics_items_icon_palettes_zinc_palette},
+ {gFile_graphics_items_icons_pp_max_sheet, gFile_graphics_items_icon_palettes_pp_max_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_battle_stat_item_sheet, gFile_graphics_items_icon_palettes_guard_spec_palette},
+ {gFile_graphics_items_icons_battle_stat_item_sheet, gFile_graphics_items_icon_palettes_dire_hit_palette},
+ {gFile_graphics_items_icons_battle_stat_item_sheet, gFile_graphics_items_icon_palettes_x_attack_palette},
+ {gFile_graphics_items_icons_battle_stat_item_sheet, gFile_graphics_items_icon_palettes_x_defend_palette},
+ {gFile_graphics_items_icons_battle_stat_item_sheet, gFile_graphics_items_icon_palettes_x_speed_palette},
+ {gFile_graphics_items_icons_battle_stat_item_sheet, gFile_graphics_items_icon_palettes_x_accuracy_palette},
+ {gFile_graphics_items_icons_battle_stat_item_sheet, gFile_graphics_items_icon_palettes_x_special_palette},
+ {gFile_graphics_items_icons_poke_doll_sheet, gFile_graphics_items_icon_palettes_poke_doll_palette},
+ {gFile_graphics_items_icons_fluffy_tail_sheet, gFile_graphics_items_icon_palettes_fluffy_tail_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_repel_sheet, gFile_graphics_items_icon_palettes_super_repel_palette},
+ {gFile_graphics_items_icons_repel_sheet, gFile_graphics_items_icon_palettes_max_repel_palette},
+ {gFile_graphics_items_icons_escape_rope_sheet, gFile_graphics_items_icon_palettes_escape_rope_palette},
+ {gFile_graphics_items_icons_repel_sheet, gFile_graphics_items_icon_palettes_repel_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_sun_stone_sheet, gFile_graphics_items_icon_palettes_sun_stone_palette},
+ {gFile_graphics_items_icons_moon_stone_sheet, gFile_graphics_items_icon_palettes_moon_stone_palette},
+ {gFile_graphics_items_icons_fire_stone_sheet, gFile_graphics_items_icon_palettes_fire_stone_palette},
+ {gFile_graphics_items_icons_thunder_stone_sheet, gFile_graphics_items_icon_palettes_thunder_stone_palette},
+ {gFile_graphics_items_icons_water_stone_sheet, gFile_graphics_items_icon_palettes_water_stone_palette},
+ {gFile_graphics_items_icons_leaf_stone_sheet, gFile_graphics_items_icon_palettes_leaf_stone_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_tiny_mushroom_sheet, gFile_graphics_items_icon_palettes_mushroom_palette},
+ {gFile_graphics_items_icons_big_mushroom_sheet, gFile_graphics_items_icon_palettes_mushroom_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_pearl_sheet, gFile_graphics_items_icon_palettes_pearl_palette},
+ {gFile_graphics_items_icons_big_pearl_sheet, gFile_graphics_items_icon_palettes_pearl_palette},
+ {gFile_graphics_items_icons_stardust_sheet, gFile_graphics_items_icon_palettes_star_palette},
+ {gFile_graphics_items_icons_star_piece_sheet, gFile_graphics_items_icon_palettes_star_palette},
+ {gFile_graphics_items_icons_nugget_sheet, gFile_graphics_items_icon_palettes_nugget_palette},
+ {gFile_graphics_items_icons_heart_scale_sheet, gFile_graphics_items_icon_palettes_heart_scale_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_orange_mail_sheet, gFile_graphics_items_icon_palettes_orange_mail_palette},
+ {gFile_graphics_items_icons_harbor_mail_sheet, gFile_graphics_items_icon_palettes_harbor_mail_palette},
+ {gFile_graphics_items_icons_glitter_mail_sheet, gFile_graphics_items_icon_palettes_glitter_mail_palette},
+ {gFile_graphics_items_icons_mech_mail_sheet, gFile_graphics_items_icon_palettes_mech_mail_palette},
+ {gFile_graphics_items_icons_wood_mail_sheet, gFile_graphics_items_icon_palettes_wood_mail_palette},
+ {gFile_graphics_items_icons_wave_mail_sheet, gFile_graphics_items_icon_palettes_wave_mail_palette},
+ {gFile_graphics_items_icons_bead_mail_sheet, gFile_graphics_items_icon_palettes_bead_mail_palette},
+ {gFile_graphics_items_icons_shadow_mail_sheet, gFile_graphics_items_icon_palettes_shadow_mail_palette},
+ {gFile_graphics_items_icons_tropic_mail_sheet, gFile_graphics_items_icon_palettes_tropic_mail_palette},
+ {gFile_graphics_items_icons_dream_mail_sheet, gFile_graphics_items_icon_palettes_dream_mail_palette},
+ {gFile_graphics_items_icons_fab_mail_sheet, gFile_graphics_items_icon_palettes_fab_mail_palette},
+ {gFile_graphics_items_icons_retro_mail_sheet, gFile_graphics_items_icon_palettes_retro_mail_palette},
+ {gFile_graphics_items_icons_cheri_berry_sheet, gFile_graphics_items_icon_palettes_cheri_berry_palette},
+ {gFile_graphics_items_icons_chesto_berry_sheet, gFile_graphics_items_icon_palettes_chesto_berry_palette},
+ {gFile_graphics_items_icons_pecha_berry_sheet, gFile_graphics_items_icon_palettes_pecha_berry_palette},
+ {gFile_graphics_items_icons_rawst_berry_sheet, gFile_graphics_items_icon_palettes_rawst_berry_palette},
+ {gFile_graphics_items_icons_aspear_berry_sheet, gFile_graphics_items_icon_palettes_aspear_berry_palette},
+ {gFile_graphics_items_icons_leppa_berry_sheet, gFile_graphics_items_icon_palettes_leppa_berry_palette},
+ {gFile_graphics_items_icons_oran_berry_sheet, gFile_graphics_items_icon_palettes_oran_berry_palette},
+ {gFile_graphics_items_icons_persim_berry_sheet, gFile_graphics_items_icon_palettes_persim_berry_palette},
+ {gFile_graphics_items_icons_lum_berry_sheet, gFile_graphics_items_icon_palettes_lum_berry_palette},
+ {gFile_graphics_items_icons_sitrus_berry_sheet, gFile_graphics_items_icon_palettes_sitrus_berry_palette},
+ {gFile_graphics_items_icons_figy_berry_sheet, gFile_graphics_items_icon_palettes_figy_berry_palette},
+ {gFile_graphics_items_icons_wiki_berry_sheet, gFile_graphics_items_icon_palettes_wiki_berry_palette},
+ {gFile_graphics_items_icons_mago_berry_sheet, gFile_graphics_items_icon_palettes_mago_berry_palette},
+ {gFile_graphics_items_icons_aguav_berry_sheet, gFile_graphics_items_icon_palettes_aguav_berry_palette},
+ {gFile_graphics_items_icons_iapapa_berry_sheet, gFile_graphics_items_icon_palettes_iapapa_berry_palette},
+ {gFile_graphics_items_icons_razz_berry_sheet, gFile_graphics_items_icon_palettes_razz_berry_palette},
+ {gFile_graphics_items_icons_bluk_berry_sheet, gFile_graphics_items_icon_palettes_bluk_berry_palette},
+ {gFile_graphics_items_icons_nanab_berry_sheet, gFile_graphics_items_icon_palettes_nanab_berry_palette},
+ {gFile_graphics_items_icons_wepear_berry_sheet, gFile_graphics_items_icon_palettes_wepear_berry_palette},
+ {gFile_graphics_items_icons_pinap_berry_sheet, gFile_graphics_items_icon_palettes_pinap_berry_palette},
+ {gFile_graphics_items_icons_pomeg_berry_sheet, gFile_graphics_items_icon_palettes_pomeg_berry_palette},
+ {gFile_graphics_items_icons_kelpsy_berry_sheet, gFile_graphics_items_icon_palettes_kelpsy_berry_palette},
+ {gFile_graphics_items_icons_qualot_berry_sheet, gFile_graphics_items_icon_palettes_qualot_berry_palette},
+ {gFile_graphics_items_icons_hondew_berry_sheet, gFile_graphics_items_icon_palettes_hondew_berry_palette},
+ {gFile_graphics_items_icons_grepa_berry_sheet, gFile_graphics_items_icon_palettes_grepa_berry_palette},
+ {gFile_graphics_items_icons_tamato_berry_sheet, gFile_graphics_items_icon_palettes_tamato_berry_palette},
+ {gFile_graphics_items_icons_cornn_berry_sheet, gFile_graphics_items_icon_palettes_cornn_berry_palette},
+ {gFile_graphics_items_icons_magost_berry_sheet, gFile_graphics_items_icon_palettes_magost_berry_palette},
+ {gFile_graphics_items_icons_rabuta_berry_sheet, gFile_graphics_items_icon_palettes_rabuta_berry_palette},
+ {gFile_graphics_items_icons_nomel_berry_sheet, gFile_graphics_items_icon_palettes_nomel_berry_palette},
+ {gFile_graphics_items_icons_spelon_berry_sheet, gFile_graphics_items_icon_palettes_spelon_berry_palette},
+ {gFile_graphics_items_icons_pamtre_berry_sheet, gFile_graphics_items_icon_palettes_pamtre_berry_palette},
+ {gFile_graphics_items_icons_watmel_berry_sheet, gFile_graphics_items_icon_palettes_watmel_berry_palette},
+ {gFile_graphics_items_icons_durin_berry_sheet, gFile_graphics_items_icon_palettes_durin_berry_palette},
+ {gFile_graphics_items_icons_belue_berry_sheet, gFile_graphics_items_icon_palettes_belue_berry_palette},
+ {gFile_graphics_items_icons_liechi_berry_sheet, gFile_graphics_items_icon_palettes_liechi_berry_palette},
+ {gFile_graphics_items_icons_ganlon_berry_sheet, gFile_graphics_items_icon_palettes_ganlon_berry_palette},
+ {gFile_graphics_items_icons_salac_berry_sheet, gFile_graphics_items_icon_palettes_salac_berry_palette},
+ {gFile_graphics_items_icons_petaya_berry_sheet, gFile_graphics_items_icon_palettes_petaya_berry_palette},
+ {gFile_graphics_items_icons_apicot_berry_sheet, gFile_graphics_items_icon_palettes_apicot_berry_palette},
+ {gFile_graphics_items_icons_lansat_berry_sheet, gFile_graphics_items_icon_palettes_lansat_berry_palette},
+ {gFile_graphics_items_icons_starf_berry_sheet, gFile_graphics_items_icon_palettes_starf_berry_palette},
+ {gFile_graphics_items_icons_enigma_berry_sheet, gFile_graphics_items_icon_palettes_enigma_berry_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_bright_powder_sheet, gFile_graphics_items_icon_palettes_bright_powder_palette},
+ {gFile_graphics_items_icons_in_battle_herb_sheet, gFile_graphics_items_icon_palettes_white_herb_palette},
+ {gFile_graphics_items_icons_macho_brace_sheet, gFile_graphics_items_icon_palettes_macho_brace_palette},
+ {gFile_graphics_items_icons_exp_share_sheet, gFile_graphics_items_icon_palettes_exp_share_palette},
+ {gFile_graphics_items_icons_quick_claw_sheet, gFile_graphics_items_icon_palettes_quick_claw_palette},
+ {gFile_graphics_items_icons_soothe_bell_sheet, gFile_graphics_items_icon_palettes_soothe_bell_palette},
+ {gFile_graphics_items_icons_in_battle_herb_sheet, gFile_graphics_items_icon_palettes_mental_herb_palette},
+ {gFile_graphics_items_icons_choice_band_sheet, gFile_graphics_items_icon_palettes_choice_band_palette},
+ {gFile_graphics_items_icons_kings_rock_sheet, gFile_graphics_items_icon_palettes_kings_rock_palette},
+ {gFile_graphics_items_icons_silver_powder_sheet, gFile_graphics_items_icon_palettes_silver_powder_palette},
+ {gFile_graphics_items_icons_amulet_coin_sheet, gFile_graphics_items_icon_palettes_amulet_coin_palette},
+ {gFile_graphics_items_icons_cleanse_tag_sheet, gFile_graphics_items_icon_palettes_cleanse_tag_palette},
+ {gFile_graphics_items_icons_soul_dew_sheet, gFile_graphics_items_icon_palettes_soul_dew_palette},
+ {gFile_graphics_items_icons_deep_sea_tooth_sheet, gFile_graphics_items_icon_palettes_deep_sea_tooth_palette},
+ {gFile_graphics_items_icons_deep_sea_scale_sheet, gFile_graphics_items_icon_palettes_deep_sea_scale_palette},
+ {gFile_graphics_items_icons_smoke_ball_sheet, gFile_graphics_items_icon_palettes_smoke_ball_palette},
+ {gFile_graphics_items_icons_everstone_sheet, gFile_graphics_items_icon_palettes_everstone_palette},
+ {gFile_graphics_items_icons_focus_band_sheet, gFile_graphics_items_icon_palettes_focus_band_palette},
+ {gFile_graphics_items_icons_lucky_egg_sheet, gFile_graphics_items_icon_palettes_lucky_egg_palette},
+ {gFile_graphics_items_icons_scope_lens_sheet, gFile_graphics_items_icon_palettes_scope_lens_palette},
+ {gFile_graphics_items_icons_metal_coat_sheet, gFile_graphics_items_icon_palettes_metal_coat_palette},
+ {gFile_graphics_items_icons_leftovers_sheet, gFile_graphics_items_icon_palettes_leftovers_palette},
+ {gFile_graphics_items_icons_dragon_scale_sheet, gFile_graphics_items_icon_palettes_dragon_scale_palette},
+ {gFile_graphics_items_icons_light_ball_sheet, gFile_graphics_items_icon_palettes_light_ball_palette},
+ {gFile_graphics_items_icons_soft_sand_sheet, gFile_graphics_items_icon_palettes_soft_sand_palette},
+ {gFile_graphics_items_icons_hard_stone_sheet, gFile_graphics_items_icon_palettes_hard_stone_palette},
+ {gFile_graphics_items_icons_miracle_seed_sheet, gFile_graphics_items_icon_palettes_miracle_seed_palette},
+ {gFile_graphics_items_icons_black_glasses_sheet, gFile_graphics_items_icon_palettes_black_type_enhancing_item_palette},
+ {gFile_graphics_items_icons_black_belt_sheet, gFile_graphics_items_icon_palettes_black_type_enhancing_item_palette},
+ {gFile_graphics_items_icons_magnet_sheet, gFile_graphics_items_icon_palettes_magnet_palette},
+ {gFile_graphics_items_icons_mystic_water_sheet, gFile_graphics_items_icon_palettes_mystic_water_palette},
+ {gFile_graphics_items_icons_sharp_beak_sheet, gFile_graphics_items_icon_palettes_sharp_beak_palette},
+ {gFile_graphics_items_icons_poison_barb_sheet, gFile_graphics_items_icon_palettes_poison_barb_palette},
+ {gFile_graphics_items_icons_never_melt_ice_sheet, gFile_graphics_items_icon_palettes_never_melt_ice_palette},
+ {gFile_graphics_items_icons_spell_tag_sheet, gFile_graphics_items_icon_palettes_spell_tag_palette},
+ {gFile_graphics_items_icons_twisted_spoon_sheet, gFile_graphics_items_icon_palettes_twisted_spoon_palette},
+ {gFile_graphics_items_icons_charcoal_sheet, gFile_graphics_items_icon_palettes_charcoal_palette},
+ {gFile_graphics_items_icons_dragon_fang_sheet, gFile_graphics_items_icon_palettes_dragon_fang_palette},
+ {gFile_graphics_items_icons_silk_scarf_sheet, gFile_graphics_items_icon_palettes_silk_scarf_palette},
+ {gFile_graphics_items_icons_up_grade_sheet, gFile_graphics_items_icon_palettes_up_grade_palette},
+ {gFile_graphics_items_icons_shell_bell_sheet, gFile_graphics_items_icon_palettes_shell_palette},
+ {gFile_graphics_items_icons_sea_incense_sheet, gFile_graphics_items_icon_palettes_sea_incense_palette},
+ {gFile_graphics_items_icons_lax_incense_sheet, gFile_graphics_items_icon_palettes_lax_incense_palette},
+ {gFile_graphics_items_icons_lucky_punch_sheet, gFile_graphics_items_icon_palettes_lucky_punch_palette},
+ {gFile_graphics_items_icons_metal_powder_sheet, gFile_graphics_items_icon_palettes_metal_powder_palette},
+ {gFile_graphics_items_icons_thick_club_sheet, gFile_graphics_items_icon_palettes_thick_club_palette},
+ {gFile_graphics_items_icons_stick_sheet, gFile_graphics_items_icon_palettes_stick_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_scarf_sheet, gFile_graphics_items_icon_palettes_red_scarf_palette},
+ {gFile_graphics_items_icons_scarf_sheet, gFile_graphics_items_icon_palettes_blue_scarf_palette},
+ {gFile_graphics_items_icons_scarf_sheet, gFile_graphics_items_icon_palettes_pink_scarf_palette},
+ {gFile_graphics_items_icons_scarf_sheet, gFile_graphics_items_icon_palettes_green_scarf_palette},
+ {gFile_graphics_items_icons_scarf_sheet, gFile_graphics_items_icon_palettes_yellow_scarf_palette},
+ {gFile_graphics_items_icons_mach_bike_sheet, gFile_graphics_items_icon_palettes_mach_bike_palette},
+ {gFile_graphics_items_icons_coin_case_sheet, gFile_graphics_items_icon_palettes_coin_case_palette},
+ {gFile_graphics_items_icons_itemfinder_sheet, gFile_graphics_items_icon_palettes_itemfinder_palette},
+ {gFile_graphics_items_icons_old_rod_sheet, gFile_graphics_items_icon_palettes_old_rod_palette},
+ {gFile_graphics_items_icons_good_rod_sheet, gFile_graphics_items_icon_palettes_good_rod_palette},
+ {gFile_graphics_items_icons_super_rod_sheet, gFile_graphics_items_icon_palettes_super_rod_palette},
+ {gFile_graphics_items_icons_ss_ticket_sheet, gFile_graphics_items_icon_palettes_ss_ticket_palette},
+ {gFile_graphics_items_icons_contest_pass_sheet, gFile_graphics_items_icon_palettes_contest_pass_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_wailmer_pail_sheet, gFile_graphics_items_icon_palettes_wailmer_pail_palette},
+ {gFile_graphics_items_icons_devon_goods_sheet, gFile_graphics_items_icon_palettes_devon_goods_palette},
+ {gFile_graphics_items_icons_soot_sack_sheet, gFile_graphics_items_icon_palettes_soot_sack_palette},
+ {gFile_graphics_items_icons_basement_key_sheet, gFile_graphics_items_icon_palettes_old_key_palette},
+ {gFile_graphics_items_icons_acro_bike_sheet, gFile_graphics_items_icon_palettes_acro_bike_palette},
+ {gFile_graphics_items_icons_pokeblock_case_sheet, gFile_graphics_items_icon_palettes_pokeblock_case_palette},
+ {gFile_graphics_items_icons_letter_sheet, gFile_graphics_items_icon_palettes_lava_cookie_and_letter_palette},
+ {gFile_graphics_items_icons_eon_ticket_sheet, gFile_graphics_items_icon_palettes_eon_ticket_palette},
+ {gFile_graphics_items_icons_orb_sheet, gFile_graphics_items_icon_palettes_red_orb_palette},
+ {gFile_graphics_items_icons_orb_sheet, gFile_graphics_items_icon_palettes_blue_orb_palette},
+ {gFile_graphics_items_icons_scanner_sheet, gFile_graphics_items_icon_palettes_scanner_palette},
+ {gFile_graphics_items_icons_go_goggles_sheet, gFile_graphics_items_icon_palettes_go_goggles_palette},
+ {gFile_graphics_items_icons_meteorite_sheet, gFile_graphics_items_icon_palettes_meteorite_palette},
+ {gFile_graphics_items_icons_room1_key_sheet, gFile_graphics_items_icon_palettes_key_palette},
+ {gFile_graphics_items_icons_room2_key_sheet, gFile_graphics_items_icon_palettes_key_palette},
+ {gFile_graphics_items_icons_room4_key_sheet, gFile_graphics_items_icon_palettes_key_palette},
+ {gFile_graphics_items_icons_room6_key_sheet, gFile_graphics_items_icon_palettes_key_palette},
+ {gFile_graphics_items_icons_storage_key_sheet, gFile_graphics_items_icon_palettes_old_key_palette},
+ {gFile_graphics_items_icons_root_fossil_sheet, gFile_graphics_items_icon_palettes_hoenn_fossil_palette},
+ {gFile_graphics_items_icons_claw_fossil_sheet, gFile_graphics_items_icon_palettes_hoenn_fossil_palette},
+ {gFile_graphics_items_icons_devon_scope_sheet, gFile_graphics_items_icon_palettes_devon_scope_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_fighting_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_dragon_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_water_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_psychic_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_poison_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_ice_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_fighting_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_grass_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_fire_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_dark_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_ice_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_ice_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_psychic_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_water_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_grass_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_grass_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_steel_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_electric_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_electric_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_ground_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_ground_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_psychic_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_ghost_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_fighting_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_psychic_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_electric_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_fire_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_poison_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_rock_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_fire_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_rock_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_flying_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_dark_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_psychic_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_dark_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_steel_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_psychic_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_dark_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_fire_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_flying_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_water_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_normal_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_fighting_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_water_tm_hm_palette},
+ {gFile_graphics_items_icons_tm_sheet, gFile_graphics_items_icon_palettes_water_tm_hm_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_question_mark_sheet, gFile_graphics_items_icon_palettes_question_mark_palette},
+ {gFile_graphics_items_icons_oaks_parcel_sheet, gFile_graphics_items_icon_palettes_oaks_parcel_palette},
+ {gFile_graphics_items_icons_poke_flute_sheet, gFile_graphics_items_icon_palettes_poke_flute_palette},
+ {gFile_graphics_items_icons_secret_key_sheet, gFile_graphics_items_icon_palettes_secret_key_palette},
+ {gFile_graphics_items_icons_bike_voucher_sheet, gFile_graphics_items_icon_palettes_bike_voucher_palette},
+ {gFile_graphics_items_icons_gold_teeth_sheet, gFile_graphics_items_icon_palettes_gold_teeth_palette},
+ {gFile_graphics_items_icons_old_amber_sheet, gFile_graphics_items_icon_palettes_old_amber_palette},
+ {gFile_graphics_items_icons_card_key_sheet, gFile_graphics_items_icon_palettes_card_key_palette},
+ {gFile_graphics_items_icons_lift_key_sheet, gFile_graphics_items_icon_palettes_key_palette},
+ {gFile_graphics_items_icons_helix_fossil_sheet, gFile_graphics_items_icon_palettes_kanto_fossil_palette},
+ {gFile_graphics_items_icons_dome_fossil_sheet, gFile_graphics_items_icon_palettes_kanto_fossil_palette},
+ {gFile_graphics_items_icons_silph_scope_sheet, gFile_graphics_items_icon_palettes_silph_scope_palette},
+ {gFile_graphics_items_icons_bicycle_sheet, gFile_graphics_items_icon_palettes_bicycle_palette},
+ {gFile_graphics_items_icons_town_map_sheet, gFile_graphics_items_icon_palettes_town_map_palette},
+ {gFile_graphics_items_icons_vs_seeker_sheet, gFile_graphics_items_icon_palettes_vs_seeker_palette},
+ {gFile_graphics_items_icons_fame_checker_sheet, gFile_graphics_items_icon_palettes_fame_checker_palette},
+ {gFile_graphics_items_icons_tm_case_sheet, gFile_graphics_items_icon_palettes_tm_case_palette},
+ {gFile_graphics_items_icons_berry_pouch_sheet, gFile_graphics_items_icon_palettes_berry_pouch_palette},
+ {gFile_graphics_items_icons_teachy_tv_sheet, gFile_graphics_items_icon_palettes_teachy_tv_palette},
+ {gFile_graphics_items_icons_tri_pass_sheet, gFile_graphics_items_icon_palettes_tri_pass_palette},
+ {gFile_graphics_items_icons_rainbow_pass_sheet, gFile_graphics_items_icon_palettes_rainbow_pass_palette},
+ {gFile_graphics_items_icons_tea_sheet, gFile_graphics_items_icon_palettes_tea_palette},
+ {gFile_graphics_items_icons_mystic_ticket_sheet, gFile_graphics_items_icon_palettes_mystic_ticket_palette},
+ {gFile_graphics_items_icons_aurora_ticket_sheet, gFile_graphics_items_icon_palettes_aurora_ticket_palette},
+ {gFile_graphics_items_icons_powder_jar_sheet, gFile_graphics_items_icon_palettes_powder_jar_palette},
+ {gFile_graphics_items_icons_gem_sheet, gFile_graphics_items_icon_palettes_ruby_palette},
+ {gFile_graphics_items_icons_gem_sheet, gFile_graphics_items_icon_palettes_sapphire_palette},
+ {gFile_graphics_items_icons_return_to_field_arrow_sheet, gFile_graphics_items_icon_palettes_return_to_field_arrow_palette}
+};
+
+void ResetItemMenuIconState(void)
+{
+ u16 i;
+
+ for (i = 0; i < NELEMS(gUnknown_2039878); i++)
+ gUnknown_2039878[i] = 0xFF;
+}
+
+void sub_80984FC(u8 animNum)
+{
+ gUnknown_2039878[0] = CreateSprite(&gUnknown_83D41FC, 40, 68, 0);
+ sub_8098528(animNum);
+}
+
+void sub_8098528(u8 animNum)
+{
+ struct Sprite * sprite = &gSprites[gUnknown_2039878[0]];
+ sprite->pos2.y = -5;
+ sprite->callback = sub_8098560;
+ StartSpriteAnim(sprite, animNum);
+}
+
+static void sub_8098560(struct Sprite * sprite)
+{
+ if (sprite->pos2.y != 0)
+ sprite->pos2.y++;
+ else
+ sprite->callback = SpriteCallbackDummy;
+}
+
+void sub_8098580(void)
+{
+ struct Sprite * sprite = &gSprites[gUnknown_2039878[0]];
+ if (sprite->affineAnimEnded)
+ {
+ StartSpriteAffineAnim(sprite, 1);
+ sprite->callback = sub_80985BC;
+ }
+}
+
+static void sub_80985BC(struct Sprite * sprite)
+{
+ if (sprite->affineAnimEnded)
+ {
+ StartSpriteAffineAnim(sprite, 0);
+ sprite->callback = SpriteCallbackDummy;
+ }
+}
+
+void sub_80985E4(void)
+{
+ u8 i;
+ u8 * ptr = &gUnknown_2039878[1];
+
+ for (i = 0; i < 9; i++)
+ {
+ ptr[i] = CreateSprite(&gUnknown_83D4250, i * 16 + 0x60, 7, 0);
+ if (i != 0)
+ {
+ if (i == 8)
+ StartSpriteAnim(&gSprites[ptr[i]], 2);
+ else
+ StartSpriteAnim(&gSprites[ptr[i]], 1);
+ }
+ gSprites[ptr[i]].invisible = TRUE;
+ }
+}
+
+void sub_8098660(u8 flag)
+{
+ u8 i;
+ u8 * ptr = &gUnknown_2039878[1];
+
+ for (i = 0; i < 9; i++)
+ {
+ gSprites[ptr[i]].invisible = flag;
+ }
+}
+
+void sub_80986A8(s16 x, u16 y)
+{
+ u8 i;
+ u8 * ptr = &gUnknown_2039878[1];
+
+ for (i = 0; i < 9; i++)
+ {
+ gSprites[ptr[i]].pos2.x = x;
+ gSprites[ptr[i]].pos1.y = y + 7;
+ }
+}
+
+static bool8 sub_80986EC(void)
+{
+ void ** ptr1, ** ptr2;
+
+ ptr1 = &gUnknown_2039884;
+ *ptr1 = Alloc(0x120);
+ if (*ptr1 == NULL)
+ return FALSE;
+ ptr2 = &gUnknown_2039888;
+ *ptr2 = AllocZeroed(0x200);
+ if (*ptr2 == NULL)
+ {
+ Free(*ptr1);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void CopyItemIconPicTo4x4Buffer(const void * src, void * dest)
+{
+ u8 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ CpuCopy16(src + 0x60 * i, dest + 0x80 * i, 0x60);
+ }
+}
+
+u8 AddItemIconObject(u16 tilesTag, u16 paletteTag, u16 itemId)
+{
+ struct SpriteTemplate template;
+ struct SpriteSheet spriteSheet;
+ struct CompressedSpritePalette spritePalette;
+ u8 spriteId;
+
+ if (!sub_80986EC())
+ return MAX_SPRITES;
+
+ LZDecompressWram(sub_8098974(itemId, 0), gUnknown_2039884);
+ CopyItemIconPicTo4x4Buffer(gUnknown_2039884, gUnknown_2039888);
+ spriteSheet.data = gUnknown_2039888;
+ spriteSheet.size = 0x200;
+ spriteSheet.tag = tilesTag;
+ LoadSpriteSheet(&spriteSheet);
+
+ spritePalette.data = sub_8098974(itemId, 1);
+ spritePalette.tag = paletteTag;
+ LoadCompressedObjectPalette(&spritePalette);
+
+ CpuCopy16(&gUnknown_83D427C, &template, sizeof(struct SpriteTemplate));
+ template.tileTag = tilesTag;
+ template.paletteTag = paletteTag;
+ spriteId = CreateSprite(&template, 0, 0, 0);
+
+ Free(gUnknown_2039884);
+ Free(gUnknown_2039888);
+ return spriteId;
+}
+
+u8 AddItemIconObjectWithCustomObjectTemplate(const struct SpriteTemplate * origTemplate, u16 tilesTag, u16 paletteTag, u16 itemId)
+{
+ struct SpriteTemplate template;
+ struct SpriteSheet spriteSheet;
+ struct CompressedSpritePalette spritePalette;
+ u8 spriteId;
+
+ if (!sub_80986EC())
+ return MAX_SPRITES;
+
+ LZDecompressWram(sub_8098974(itemId, 0), gUnknown_2039884);
+ CopyItemIconPicTo4x4Buffer(gUnknown_2039884, gUnknown_2039888);
+ spriteSheet.data = gUnknown_2039888;
+ spriteSheet.size = 0x200;
+ spriteSheet.tag = tilesTag;
+ LoadSpriteSheet(&spriteSheet);
+
+ spritePalette.data = sub_8098974(itemId, 1);
+ spritePalette.tag = paletteTag;
+ LoadCompressedObjectPalette(&spritePalette);
+
+ CpuCopy16(origTemplate, &template, sizeof(struct SpriteTemplate));
+ template.tileTag = tilesTag;
+ template.paletteTag = paletteTag;
+ spriteId = CreateSprite(&template, 0, 0, 0);
+
+ Free(gUnknown_2039884);
+ Free(gUnknown_2039888);
+ return spriteId;
+}
+
+void CreateItemMenuIcon(u16 itemId, u8 idx)
+{
+ u8 * ptr = &gUnknown_2039878[10];
+ u8 spriteId;
+
+ if (ptr[idx] == 0xFF)
+ {
+ FreeSpriteTilesByTag(102 + idx);
+ FreeSpritePaletteByTag(102 + idx);
+ spriteId = AddItemIconObject(102 + idx, 102 + idx, itemId);
+ if (spriteId != MAX_SPRITES)
+ {
+ ptr[idx] = spriteId;
+ gSprites[spriteId].pos2.x = 24;
+ gSprites[spriteId].pos2.y = 140;
+ }
+ }
+}
+
+void DestroyItemMenuIcon(u8 idx)
+{
+ u8 * ptr = &gUnknown_2039878[10];
+
+ if (ptr[idx] != 0xFF)
+ {
+ DestroySpriteAndFreeResources(&gSprites[ptr[idx]]);
+ ptr[idx] = 0xFF;
+ }
+}
+
+const void * sub_8098974(u16 itemId, u8 attrId)
+{
+ if (itemId > ITEM_N_A)
+ itemId = ITEM_NONE;
+ return gUnknown_83D4294[itemId][attrId];
+}
+
+void sub_80989A0(u16 itemId, u8 idx)
+{
+ u8 * ptr = &gUnknown_2039878[10];
+ u8 spriteId;
+
+ if (ptr[idx] == 0xFF)
+ {
+ FreeSpriteTilesByTag(102 + idx);
+ FreeSpritePaletteByTag(102 + idx);
+ spriteId = AddItemIconObject(102 + idx, 102 + idx, itemId);
+ if (spriteId != MAX_SPRITES)
+ {
+ ptr[idx] = spriteId;
+ gSprites[spriteId].pos2.x = 24;
+ gSprites[spriteId].pos2.y = 147;
+ }
+ }
+}
diff --git a/src/item_pc.c b/src/item_pc.c
new file mode 100644
index 000000000..e2fa33f0a
--- /dev/null
+++ b/src/item_pc.c
@@ -0,0 +1,1150 @@
+#include "global.h"
+#include "bg.h"
+#include "data2.h"
+#include "decompress.h"
+#include "gpu_regs.h"
+#include "graphics.h"
+#include "help_system.h"
+#include "item.h"
+#include "item_menu.h"
+#include "item_menu_icons.h"
+#include "list_menu.h"
+#include "item_pc.h"
+#include "item_use.h"
+#include "main.h"
+#include "malloc.h"
+#include "menu.h"
+#include "menu_helpers.h"
+#include "menu_indicators.h"
+#include "new_menu_helpers.h"
+#include "palette.h"
+#include "party_menu.h"
+#include "pc_screen_effect.h"
+#include "scanline_effect.h"
+#include "sound.h"
+#include "string_util.h"
+#include "strings.h"
+#include "task.h"
+#include "text_window.h"
+#include "constants/items.h"
+#include "constants/songs.h"
+
+struct ItemPcResources
+{
+ MainCallback savedCallback;
+ u8 moveModeOrigPos;
+ u8 itemMenuIconSlot;
+ u8 maxShowed;
+ u8 nItems;
+ u8 scrollIndicatorArrowPairId;
+ u16 withdrawQuantitySubmenuCursorPos;
+ s16 data[3];
+};
+
+struct ItemPcStaticResources
+{
+ MainCallback savedCallback;
+ u16 scroll;
+ u16 row;
+ u8 initialized;
+};
+
+static EWRAM_DATA struct ItemPcResources * sStateDataPtr = NULL;
+static EWRAM_DATA u8 * sBg1TilemapBuffer = NULL;
+static EWRAM_DATA struct ListMenuItem * sListMenuItems = NULL;
+static EWRAM_DATA u8 * sUnusedStringAllocation = NULL;
+static EWRAM_DATA struct ItemPcStaticResources sListMenuState = {};
+static EWRAM_DATA u8 sSubmenuWindowIds[3] = {};
+
+extern const struct CompressedSpriteSheet gBagSwapSpriteSheet;
+extern const struct CompressedSpritePalette gBagSwapSpritePalette;
+
+static void ItemPc_RunSetup(void);
+static bool8 ItemPc_DoGfxSetup(void);
+static void ItemPc_FadeAndBail(void);
+static void Task_ItemPcWaitFadeAndBail(u8 taskId);
+static bool8 ItemPc_InitBgs(void);
+static bool8 ItemPc_LoadGraphics(void);
+static bool8 ItemPc_AllocateResourcesForListMenu(void);
+static void ItemPc_BuildListMenuTemplate(void);
+static void ItemPc_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu * list);
+static void ItemPc_ItemPrintFunc(u8 windowId, s32 itemId, u8 y);
+static void ItemPc_PrintOrRemoveCursorAt(u8 y, u8 state);
+static void ItemPc_PrintWithdrawItem(void);
+static void ItemPc_PlaceTopMenuScrollIndicatorArrows(void);
+static void ItemPc_SetCursorPosition(void);
+static void ItemPc_FreeResources(void);
+static void Task_ItemPcTurnOff2(u8 taskId);
+static u16 ItemPc_GetItemIdBySlotId(u16 itemIndex);
+static u16 ItemPc_GetItemQuantityBySlotId(u16 itemIndex);
+static void ItemPc_CountPcItems(void);
+static void ItemPc_SetScrollPosition(void);
+static void Task_ItemPcMain(u8 taskId);
+static void ItemPc_MoveItemModeInit(u8 taskId, s16 pos);
+static void Task_ItemPcMoveItemModeRun(u8 taskId);
+static void ItemPc_InsertItemIntoNewSlot(u8 taskId, u32 pos);
+static void ItemPc_MoveItemModeCancel(u8 taskId, u32 pos);
+static void Task_ItemPcSubmenuInit(u8 taskId);
+static void Task_ItemPcSubmenuRun(u8 taskId);
+static void Task_ItemPcWithdraw(u8 taskId);
+static void ItemPc_DoWithdraw(u8 taskId);
+static void Task_ItemPcWaitButtonAndFinishWithdrawMultiple(u8 taskId);
+static void Task_ItemPcWaitButtonWithdrawMultipleFailed(u8 taskId);
+static void Task_ItemPcCleanUpWithdraw(u8 taskId);
+static void ItemPc_WithdrawMultipleInitWindow(u16 slotId);
+static void Task_ItemPcHandleWithdrawMultiple(u8 taskId);
+static void Task_ItemPcGive(u8 taskId);
+static void ItemPc_CB2_SwitchToPartyMenu(void);
+static void ItemPc_CB2_ReturnFromPartyMenu(void);
+static void gTask_ItemPcWaitButtonAndExitSubmenu(u8 taskId);
+static void Task_ItemPcCancel(u8 taskId);
+static void ItemPc_InitWindows(void);
+static void ItemPc_AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, u8 speed, u8 colorIdx);
+static void ItemPc_SetBorderStyleOnWindow(u8 windowId);
+static u8 ItemPc_GetOrCreateSubwindow(u8 idx);
+static void ItemPc_DestroySubwindow(u8 idx);
+static void ItemPc_PrintOnWindow5WithContinueTask(u8 taskId, const u8 * str, TaskFunc taskFunc);
+
+static const struct BgTemplate sBgTemplates[2] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 31,
+ .priority = 0
+ }, {
+ .bg = 1,
+ .charBaseIndex = 3,
+ .mapBaseIndex = 30,
+ .priority = 1
+ }
+};
+
+static const struct MenuAction sItemPcSubmenuOptions[] = {
+ {gText_Withdraw, {.void_u8 = Task_ItemPcWithdraw}},
+ {gOtherText_Give, {.void_u8 = Task_ItemPcGive}},
+ {gFameCheckerText_Cancel, {.void_u8 = Task_ItemPcCancel}}
+};
+
+static const struct TextColor gUnknown_8453F8C[] = {
+ {0, 1, 2},
+ {0, 2, 3},
+ {0, 3, 2},
+ {0, 10, 2}
+};
+
+static const struct WindowTemplate gUnknown_8453F98[] = {
+ {
+ .bg = 0,
+ .tilemapLeft = 0x07,
+ .tilemapTop = 0x01,
+ .width = 0x13,
+ .height = 0x0c,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x02bf
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x05,
+ .tilemapTop = 0x0e,
+ .width = 0x19,
+ .height = 0x06,
+ .paletteNum = 0x0d,
+ .baseBlock = 0x0229
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x01,
+ .width = 0x05,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0215
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x18,
+ .tilemapTop = 0x0f,
+ .width = 0x05,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0201
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0d,
+ .width = 0x07,
+ .height = 0x06,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x01d7
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x02,
+ .tilemapTop = 0x0f,
+ .width = 0x1a,
+ .height = 0x04,
+ .paletteNum = 0x0b,
+ .baseBlock = 0x016f
+ }, DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate gUnknown_8453FD0[] = {
+ {
+ .bg = 0,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0f,
+ .width = 0x0e,
+ .height = 0x04,
+ .paletteNum = 0x0c,
+ .baseBlock = 0x0137
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0f,
+ .width = 0x10,
+ .height = 0x04,
+ .paletteNum = 0x0c,
+ .baseBlock = 0x0137
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0f,
+ .width = 0x17,
+ .height = 0x04,
+ .paletteNum = 0x0c,
+ .baseBlock = 0x009b
+ }
+};
+
+void ItemPc_Init(u8 a0, MainCallback callback)
+{
+ u8 i;
+
+ if (a0 >= 2)
+ {
+ SetMainCallback2(callback);
+ return;
+ }
+ if ((sStateDataPtr = Alloc(sizeof(struct ItemPcResources))) == NULL)
+ {
+ SetMainCallback2(callback);
+ return;
+ }
+ if (a0 != 1)
+ {
+ sListMenuState.savedCallback = callback;
+ sListMenuState.scroll = sListMenuState.row = 0;
+ }
+ sStateDataPtr->moveModeOrigPos = 0xFF;
+ sStateDataPtr->itemMenuIconSlot = 0;
+ sStateDataPtr->scrollIndicatorArrowPairId = 0xFF;
+ sStateDataPtr->savedCallback = 0;
+ for (i = 0; i < 3; i++)
+ {
+ sStateDataPtr->data[i] = 0;
+ }
+ SetMainCallback2(ItemPc_RunSetup);
+}
+
+static void ItemPc_MainCB(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ do_scheduled_bg_tilemap_copies_to_vram();
+ UpdatePaletteFade();
+}
+
+static void ItemPc_VBlankCB(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void ItemPc_RunSetup(void)
+{
+ while (1)
+ {
+ if (ItemPc_DoGfxSetup() == TRUE)
+ break;
+ if (MenuHelpers_LinkSomething() == TRUE)
+ break;
+ }
+}
+
+static bool8 ItemPc_DoGfxSetup(void)
+{
+ u8 taskId;
+ switch (gMain.state)
+ {
+ case 0:
+ VblankHblankHandlerSetZero();
+ clear_scheduled_bg_copies_to_vram();
+ gMain.state++;
+ break;
+ case 1:
+ ScanlineEffect_Stop();
+ gMain.state++;
+ break;
+ case 2:
+ FreeAllSpritePalettes();
+ gMain.state++;
+ break;
+ case 3:
+ ResetPaletteFade();
+ gMain.state++;
+ break;
+ case 4:
+ ResetSpriteData();
+ gMain.state++;
+ break;
+ case 5:
+ ResetItemMenuIconState();
+ gMain.state++;
+ break;
+ case 6:
+ ResetTasks();
+ gMain.state++;
+ break;
+ case 7:
+ if (ItemPc_InitBgs())
+ {
+ sStateDataPtr->data[0] = 0;
+ gMain.state++;
+ }
+ else
+ {
+ ItemPc_FadeAndBail();
+ return TRUE;
+ }
+ break;
+ case 8:
+ if (ItemPc_LoadGraphics() == TRUE)
+ gMain.state++;
+ break;
+ case 9:
+ ItemPc_InitWindows();
+ gMain.state++;
+ break;
+ case 10:
+ ItemPc_CountPcItems();
+ ItemPc_SetCursorPosition();
+ ItemPc_SetScrollPosition();
+ gMain.state++;
+ break;
+ case 11:
+ if (ItemPc_AllocateResourcesForListMenu())
+ gMain.state++;
+ else
+ {
+ ItemPc_FadeAndBail();
+ return TRUE;
+ }
+ break;
+ case 12:
+ ItemPc_BuildListMenuTemplate();
+ gMain.state++;
+ break;
+ case 13:
+ ItemPc_PrintWithdrawItem();
+ gMain.state++;
+ break;
+ case 14:
+ sub_80985E4();
+ gMain.state++;
+ break;
+ case 15:
+ taskId = CreateTask(Task_ItemPcMain, 0);
+ gTasks[taskId].data[0] = ListMenuInit(&gMultiuseListMenuTemplate, sListMenuState.scroll, sListMenuState.row);
+ gMain.state++;
+ break;
+ case 16:
+ ItemPc_PlaceTopMenuScrollIndicatorArrows();
+ gMain.state++;
+ break;
+ case 17:
+ HelpSystem_SetSomeVariable2(29);
+ gMain.state++;
+ break;
+ case 18:
+ if (sListMenuState.initialized == 1)
+ {
+ BlendPalettes(0xFFFFFFFF, 16, RGB_BLACK);
+ }
+ gMain.state++;
+ break;
+ case 19:
+ if (sListMenuState.initialized == 1)
+ {
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ }
+ else
+ {
+ sub_80A0A48(0, 0, 0);
+ ItemPc_SetInitializedFlag(1);
+ PlaySE(SE_PC_LOGON);
+ }
+ gMain.state++;
+ break;
+ case 20:
+ if (sub_80BF72C() != TRUE)
+ gMain.state++;
+ break;
+ default:
+ SetVBlankCallback(ItemPc_VBlankCB);
+ SetMainCallback2(ItemPc_MainCB);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void ItemPc_FadeAndBail(void)
+{
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+ CreateTask(Task_ItemPcWaitFadeAndBail, 0);
+ SetVBlankCallback(ItemPc_VBlankCB);
+ SetMainCallback2(ItemPc_MainCB);
+}
+
+static void Task_ItemPcWaitFadeAndBail(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(sListMenuState.savedCallback);
+ ItemPc_FreeResources();
+ DestroyTask(taskId);
+ }
+}
+
+static bool8 ItemPc_InitBgs(void)
+{
+ InitBgReg();
+ sBg1TilemapBuffer = Alloc(0x800);
+ if (sBg1TilemapBuffer == NULL)
+ return FALSE;
+ memset(sBg1TilemapBuffer, 0, 0x800);
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, sBgTemplates, NELEMS(sBgTemplates));
+ SetBgTilemapBuffer(1, sBg1TilemapBuffer);
+ schedule_bg_copy_tilemap_to_vram(1);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
+ SetGpuReg(REG_OFFSET_BLDCNT , 0);
+ ShowBg(0);
+ ShowBg(1);
+ return TRUE;
+}
+
+static bool8 ItemPc_LoadGraphics(void)
+{
+ switch (sStateDataPtr->data[0])
+ {
+ case 0:
+ reset_temp_tile_data_buffers();
+ decompress_and_copy_tile_data_to_vram(1, gItemPcTiles, 0, 0, 0);
+ sStateDataPtr->data[0]++;
+ break;
+ case 1:
+ if (free_temp_tile_data_buffers_if_possible() != TRUE)
+ {
+ LZDecompressWram(gItemPcTilemap, sBg1TilemapBuffer);
+ sStateDataPtr->data[0]++;
+ }
+ break;
+ case 2:
+ LoadCompressedPalette(gItemPcBgPals, 0x00, 0x60);
+ sStateDataPtr->data[0]++;
+ break;
+ case 3:
+ LoadCompressedObjectPic(&gBagSwapSpriteSheet);
+ sStateDataPtr->data[0]++;
+ break;
+ default:
+ LoadCompressedObjectPalette(&gBagSwapSpritePalette);
+ sStateDataPtr->data[0] = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#define try_alloc(ptr__, size) ({ \
+ void ** ptr = (void **)&(ptr__); \
+ *ptr = Alloc(size); \
+ if (*ptr == NULL) \
+ { \
+ ItemPc_FreeResources(); \
+ ItemPc_FadeAndBail(); \
+ return FALSE; \
+ } \
+})
+
+static bool8 ItemPc_AllocateResourcesForListMenu(void)
+{
+ try_alloc(sListMenuItems, sizeof(struct ListMenuItem) * (PC_ITEMS_COUNT + 1));
+ try_alloc(sUnusedStringAllocation, 14 * (PC_ITEMS_COUNT + 1));
+ return TRUE;
+}
+
+static void ItemPc_BuildListMenuTemplate(void)
+{
+ u16 i;
+
+ for (i = 0; i < sStateDataPtr->nItems; i++)
+ {
+ sListMenuItems[i].label = ItemId_GetName(gSaveBlock1Ptr->pcItems[i].itemId);
+ sListMenuItems[i].index = i;
+ }
+ sListMenuItems[i].label = gFameCheckerText_Cancel;
+ sListMenuItems[i].index = -2;
+
+ gMultiuseListMenuTemplate.items = sListMenuItems;
+ gMultiuseListMenuTemplate.totalItems = sStateDataPtr->nItems + 1;
+ gMultiuseListMenuTemplate.windowId = 0;
+ gMultiuseListMenuTemplate.header_X = 0;
+ gMultiuseListMenuTemplate.item_X = 9;
+ gMultiuseListMenuTemplate.cursor_X = 1;
+ gMultiuseListMenuTemplate.lettersSpacing = 1;
+ gMultiuseListMenuTemplate.itemVerticalPadding = 2;
+ gMultiuseListMenuTemplate.upText_Y = 2;
+ gMultiuseListMenuTemplate.maxShowed = sStateDataPtr->maxShowed;
+ gMultiuseListMenuTemplate.fontId = 2;
+ gMultiuseListMenuTemplate.cursorPal = 2;
+ gMultiuseListMenuTemplate.fillValue = 0;
+ gMultiuseListMenuTemplate.cursorShadowPal = 3;
+ gMultiuseListMenuTemplate.moveCursorFunc = ItemPc_MoveCursorFunc;
+ gMultiuseListMenuTemplate.itemPrintFunc = ItemPc_ItemPrintFunc;
+ gMultiuseListMenuTemplate.scrollMultiple = 0;
+ gMultiuseListMenuTemplate.cursorKind = 0;
+}
+
+static void ItemPc_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu * list)
+{
+ u16 itemId;
+ const u8 * desc;
+ if (onInit != TRUE)
+ PlaySE(SE_SELECT);
+
+ if (sStateDataPtr->moveModeOrigPos == 0xFF)
+ {
+ DestroyItemMenuIcon(sStateDataPtr->itemMenuIconSlot ^ 1);
+ if (itemIndex != -2)
+ {
+ itemId = ItemPc_GetItemIdBySlotId(itemIndex);
+ CreateItemMenuIcon(itemId, sStateDataPtr->itemMenuIconSlot);
+ if (ItemId_GetPocket(itemId) == POCKET_TM_CASE)
+ desc = gMoveNames[ItemIdToBattleMoveId(itemId)];
+ else
+ desc = ItemId_GetDescription(itemId);
+ }
+ else
+ {
+ CreateItemMenuIcon(ITEM_N_A, sStateDataPtr->itemMenuIconSlot);
+ desc = gText_ReturnToPC;
+ }
+ sStateDataPtr->itemMenuIconSlot ^= 1;
+ FillWindowPixelBuffer(1, 0);
+ ItemPc_AddTextPrinterParameterized(1, 2, desc, 0, 3, 2, 0, 0, 3);
+ }
+}
+
+static void ItemPc_ItemPrintFunc(u8 windowId, s32 itemId, u8 y)
+{
+ if (sStateDataPtr->moveModeOrigPos != 0xFF)
+ {
+ if (sStateDataPtr->moveModeOrigPos == (u8)itemId)
+ ItemPc_PrintOrRemoveCursorAt(y, 2);
+ else
+ ItemPc_PrintOrRemoveCursorAt(y, 0xFF);
+ }
+ if (itemId != -2)
+ {
+ u16 quantity = ItemPc_GetItemQuantityBySlotId(itemId);
+ ConvertIntToDecimalStringN(gStringVar1, quantity, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
+ ItemPc_AddTextPrinterParameterized(windowId, 0, gStringVar4, 110, y, 0, 0, 0xFF, 1);
+ }
+}
+
+static void ItemPc_PrintOrRemoveCursor(u8 listMenuId, u8 colorIdx)
+{
+ ItemPc_PrintOrRemoveCursorAt(ListMenuGetYCoordForPrintingArrowCursor(listMenuId), colorIdx);
+}
+
+static void ItemPc_PrintOrRemoveCursorAt(u8 y, u8 colorIdx)
+{
+ if (colorIdx == 0xFF)
+ {
+ u8 maxWidth = GetFontAttribute(2, FONTATTR_MAX_LETTER_WIDTH);
+ u8 maxHeight = GetFontAttribute(2, FONTATTR_MAX_LETTER_HEIGHT);
+ FillWindowPixelRect(0, 0, 0, y, maxWidth, maxHeight);
+ }
+ else
+ {
+ ItemPc_AddTextPrinterParameterized(0, 2, gFameCheckerText_ListMenuCursor, 0, y, 0, 0, 0, colorIdx);
+ }
+}
+
+static void ItemPc_PrintWithdrawItem(void)
+{
+ ItemPc_AddTextPrinterParameterized(2, 0, gText_WithdrawItem, 0, 1, 0, 1, 0, 0);
+}
+
+static void ItemPc_PlaceTopMenuScrollIndicatorArrows(void)
+{
+ sStateDataPtr->scrollIndicatorArrowPairId = AddScrollIndicatorArrowPairParameterized(2, 128, 8, 104, sStateDataPtr->nItems - sStateDataPtr->maxShowed + 1, 110, 110, &sListMenuState.scroll);
+}
+
+static void ItemPc_PlaceWithdrawQuantityScrollIndicatorArrows(void)
+{
+ sStateDataPtr->withdrawQuantitySubmenuCursorPos = 1;
+ sStateDataPtr->scrollIndicatorArrowPairId = AddScrollIndicatorArrowPairParameterized(2, 212, 120, 152, 2, 110, 110, &sStateDataPtr->withdrawQuantitySubmenuCursorPos);
+}
+
+static void ItemPc_RemoveScrollIndicatorArrowPair(void)
+{
+ if (sStateDataPtr->scrollIndicatorArrowPairId != 0xFF)
+ {
+ RemoveScrollIndicatorArrowPair(sStateDataPtr->scrollIndicatorArrowPairId);
+ sStateDataPtr->scrollIndicatorArrowPairId = 0xFF;
+ }
+}
+
+static void ItemPc_SetCursorPosition(void)
+{
+ if (sListMenuState.scroll != 0 && sListMenuState.scroll + sStateDataPtr->maxShowed > sStateDataPtr->nItems + 1)
+ sListMenuState.scroll = (sStateDataPtr->nItems + 1) - sStateDataPtr->maxShowed;
+ if (sListMenuState.scroll + sListMenuState.row >= sStateDataPtr->nItems + 1)
+ {
+ if (sStateDataPtr->nItems + 1 < 2)
+ sListMenuState.row = 0;
+ else
+ sListMenuState.row = sStateDataPtr->nItems;
+ }
+}
+
+#define try_free(ptr) ({ \
+ void ** ptr__ = (void **)&(ptr); \
+ if (*ptr__ != NULL) \
+ Free(*ptr__); \
+})
+
+static void ItemPc_FreeResources(void)
+{
+ try_free(sStateDataPtr);
+ try_free(sBg1TilemapBuffer);
+ try_free(sListMenuItems);
+ try_free(sUnusedStringAllocation);
+ FreeAllWindowBuffers();
+}
+
+static void Task_ItemPcTurnOff1(u8 taskId)
+{
+ if (sListMenuState.initialized == 1)
+ {
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+ }
+ else
+ {
+ sub_80A0A70(0, 0, 0);
+ PlaySE(SE_PC_OFF);
+ }
+ gTasks[taskId].func = Task_ItemPcTurnOff2;
+}
+
+static void Task_ItemPcTurnOff2(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!gPaletteFade.active && !sub_80A0AAC())
+ {
+ DestroyListMenu(data[0], &sListMenuState.scroll, &sListMenuState.row);
+ if (sStateDataPtr->savedCallback != NULL)
+ SetMainCallback2(sStateDataPtr->savedCallback);
+ else
+ SetMainCallback2(sListMenuState.savedCallback);
+ ItemPc_RemoveScrollIndicatorArrowPair();
+ ItemPc_FreeResources();
+ DestroyTask(taskId);
+ }
+}
+
+static u8 ItemPc_GetCursorPosition(void)
+{
+ return sListMenuState.scroll + sListMenuState.row;
+}
+
+static u16 ItemPc_GetItemIdBySlotId(u16 idx)
+{
+ return gSaveBlock1Ptr->pcItems[idx].itemId;
+}
+
+static u16 ItemPc_GetItemQuantityBySlotId(u16 idx)
+{
+ return GetPcItemQuantity(&gSaveBlock1Ptr->pcItems[idx].quantity);
+}
+
+static void ItemPc_CountPcItems(void)
+{
+ u16 i;
+
+ ItemPcCompaction();
+ sStateDataPtr->nItems = 0;
+ for (i = 0; i < PC_ITEMS_COUNT; sStateDataPtr->nItems++, i++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId == ITEM_NONE)
+ break;
+ }
+ sStateDataPtr->maxShowed = sStateDataPtr->nItems + 1 <= 6 ? sStateDataPtr->nItems + 1 : 6;
+}
+
+static void ItemPc_SetScrollPosition(void)
+{
+ u8 i;
+
+ if (sListMenuState.row > 3)
+ {
+ for (i = 0; i <= sListMenuState.row - 3; sListMenuState.row--, sListMenuState.scroll++, i++)
+ {
+ if (sListMenuState.scroll + sStateDataPtr->maxShowed == sStateDataPtr->nItems + 1)
+ break;
+ }
+ }
+}
+
+static void ItemPc_SetMessageWindowPalette(int a0)
+{
+ SetBgRectPal(1, 0, 14, 30, 6, a0 + 1);
+ schedule_bg_copy_tilemap_to_vram(1);
+}
+
+void ItemPc_SetInitializedFlag(u8 a0)
+{
+ sListMenuState.initialized = a0;
+}
+
+static void Task_ItemPcMain(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u16 scroll;
+ u16 row;
+ s32 input;
+
+ if (!gPaletteFade.active && !sub_80A0A98())
+ {
+ if (JOY_NEW(SELECT_BUTTON))
+ {
+ ListMenuGetScrollAndRow(data[0], &scroll, &row);
+ if (scroll + row != sStateDataPtr->nItems)
+ {
+ PlaySE(SE_SELECT);
+ ItemPc_MoveItemModeInit(taskId, scroll + row);
+ return;
+ }
+ }
+ input = ListMenuHandleInput(data[0]);
+ ListMenuGetScrollAndRow(data[0], &sListMenuState.scroll, &sListMenuState.row);
+ switch (input)
+ {
+ case -1:
+ break;
+ case -2:
+ PlaySE(SE_SELECT);
+ ItemPc_SetInitializedFlag(0);
+ gTasks[taskId].func = Task_ItemPcTurnOff1;
+ break;
+ default:
+ PlaySE(SE_SELECT);
+ ItemPc_SetMessageWindowPalette(1);
+ ItemPc_RemoveScrollIndicatorArrowPair();
+ data[1] = input;
+ data[2] = ItemPc_GetItemQuantityBySlotId(input);
+ ItemPc_PrintOrRemoveCursor(data[0], 2);
+ gTasks[taskId].func = Task_ItemPcSubmenuInit;
+ break;
+ }
+ }
+}
+
+static void ItemPc_ReturnFromSubmenu(u8 taskId)
+{
+ ItemPc_SetMessageWindowPalette(0);
+ ItemPc_PlaceTopMenuScrollIndicatorArrows();
+ gTasks[taskId].func = Task_ItemPcMain;
+}
+
+static void ItemPc_MoveItemModeInit(u8 taskId, s16 pos)
+{
+ s16 * data = gTasks[taskId].data;
+
+ sub_8107BD0(data[0], 16, 1);
+ data[1] = pos;
+ sStateDataPtr->moveModeOrigPos = pos;
+ StringCopy(gStringVar1, ItemId_GetName(ItemPc_GetItemIdBySlotId(data[1])));
+ StringExpandPlaceholders(gStringVar4, gOtherText_WhereShouldTheStrVar1BePlaced);
+ FillWindowPixelBuffer(1, 0x00);
+ ItemPc_AddTextPrinterParameterized(1, 2, gStringVar4, 0, 3, 2, 3, 0, 0);
+ sub_80986A8(-32, ListMenuGetYCoordForPrintingArrowCursor(data[0]));
+ sub_8098660(0);
+ ItemPc_PrintOrRemoveCursor(data[0], 2);
+ gTasks[taskId].func = Task_ItemPcMoveItemModeRun;
+}
+
+static void Task_ItemPcMoveItemModeRun(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ ListMenuHandleInput(data[0]);
+ ListMenuGetScrollAndRow(data[0], &sListMenuState.scroll, &sListMenuState.row);
+ sub_80986A8(-32, ListMenuGetYCoordForPrintingArrowCursor(data[0]));
+ if (JOY_NEW(A_BUTTON | SELECT_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ sStateDataPtr->moveModeOrigPos = 0xFF;
+ ItemPc_InsertItemIntoNewSlot(taskId, sListMenuState.scroll + sListMenuState.row);
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ sStateDataPtr->moveModeOrigPos = 0xFF;
+ ItemPc_MoveItemModeCancel(taskId, sListMenuState.scroll + sListMenuState.row);
+ }
+}
+
+static void ItemPc_InsertItemIntoNewSlot(u8 taskId, u32 pos)
+{
+ s16 * data = gTasks[taskId].data;
+ if (data[1] == pos || data[1] == pos - 1)
+ ItemPc_MoveItemModeCancel(taskId, pos);
+ else
+ {
+ ItemMenu_MoveItemSlotToNewPositionInArray(gSaveBlock1Ptr->pcItems, data[1], pos);
+ DestroyListMenu(data[0], &sListMenuState.scroll, &sListMenuState.row);
+ if (data[1] < pos)
+ sListMenuState.row--;
+ ItemPc_BuildListMenuTemplate();
+ data[0] = ListMenuInit(&gMultiuseListMenuTemplate, sListMenuState.scroll, sListMenuState.row);
+ sub_8098660(1);
+ gTasks[taskId].func = Task_ItemPcMain;
+ }
+}
+
+static void ItemPc_MoveItemModeCancel(u8 taskId, u32 pos)
+{
+ s16 * data = gTasks[taskId].data;
+
+ DestroyListMenu(data[0], &sListMenuState.scroll, &sListMenuState.row);
+ if (data[1] < pos)
+ sListMenuState.row--;
+ ItemPc_BuildListMenuTemplate();
+ data[0] = ListMenuInit(&gMultiuseListMenuTemplate, sListMenuState.scroll, sListMenuState.row);
+ sub_8098660(1);
+ gTasks[taskId].func = Task_ItemPcMain;
+}
+
+static void Task_ItemPcSubmenuInit(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u8 windowId;
+
+ ItemPc_SetBorderStyleOnWindow(4);
+ windowId = ItemPc_GetOrCreateSubwindow(0);
+ PrintTextArray(4, 2, 8, 2, GetFontAttribute(2, FONTATTR_MAX_LETTER_HEIGHT) + 2, 3, sItemPcSubmenuOptions);
+ ProgramAndPlaceMenuCursorOnWindow(4, 2, 0, 2, GetFontAttribute(2, FONTATTR_MAX_LETTER_HEIGHT) + 2, 3, 0);
+ CopyItemName(ItemPc_GetItemIdBySlotId(data[1]), gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gOtherText_StrVar1);
+ ItemPc_AddTextPrinterParameterized(windowId, 2, gStringVar4, 0, 2, 1, 0, 0, 1);
+ schedule_bg_copy_tilemap_to_vram(0);
+ gTasks[taskId].func = Task_ItemPcSubmenuRun;
+}
+
+static void Task_ItemPcSubmenuRun(u8 taskId)
+{
+ s8 input = ProcessMenuInputNoWrapAround();
+ switch (input)
+ {
+ case -1:
+ PlaySE(SE_SELECT);
+ Task_ItemPcCancel(taskId);
+ break;
+ case -2:
+ break;
+ default:
+ PlaySE(SE_SELECT);
+ sItemPcSubmenuOptions[input].func.void_u8(taskId);
+ }
+}
+
+static void Task_ItemPcWithdraw(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ ClearMenuWindow(4, FALSE);
+ ItemPc_DestroySubwindow(0);
+ ClearWindowTilemap(4);
+ data[8] = 1;
+ if (ItemPc_GetItemQuantityBySlotId(data[1]) == 1)
+ {
+ PutWindowTilemap(0);
+ schedule_bg_copy_tilemap_to_vram(0);
+ ItemPc_DoWithdraw(taskId);
+ }
+ else
+ {
+ PutWindowTilemap(0);
+ ItemPc_WithdrawMultipleInitWindow(data[1]);
+ ItemPc_PlaceWithdrawQuantityScrollIndicatorArrows();
+ gTasks[taskId].func = Task_ItemPcHandleWithdrawMultiple;
+ }
+}
+
+static void ItemPc_DoWithdraw(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u16 itemId = ItemPc_GetItemIdBySlotId(data[1]);
+ u8 windowId;
+
+ if (AddBagItem(itemId, data[8]) == TRUE)
+ {
+ ItemUse_SetQuestLogEvent(29, NULL, itemId, 0xFFFF);
+ CopyItemName(itemId, gStringVar1);
+ ConvertIntToDecimalStringN(gStringVar2, data[8], STR_CONV_MODE_LEFT_ALIGN, 3);
+ StringExpandPlaceholders(gStringVar4, gText_WithdrewQuantItem);
+ windowId = ItemPc_GetOrCreateSubwindow(2);
+ AddTextPrinterParameterized(windowId, 2, gStringVar4, 0, 2, 0, NULL);
+ gTasks[taskId].func = Task_ItemPcWaitButtonAndFinishWithdrawMultiple;
+ }
+ else
+ {
+ windowId = ItemPc_GetOrCreateSubwindow(2);
+ AddTextPrinterParameterized(windowId, 2, gText_NoMoreRoomInBag, 0, 2, 0, NULL);
+ gTasks[taskId].func = Task_ItemPcWaitButtonWithdrawMultipleFailed;
+ }
+}
+
+static void Task_ItemPcWaitButtonAndFinishWithdrawMultiple(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u16 itemId;
+
+ if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ itemId = ItemPc_GetItemIdBySlotId(data[1]);
+ RemoveItemFromPC(itemId, data[8]);
+ ItemPcCompaction();
+ Task_ItemPcCleanUpWithdraw(taskId);
+ }
+}
+
+static void Task_ItemPcWaitButtonWithdrawMultipleFailed(u8 taskId)
+{
+ if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ Task_ItemPcCleanUpWithdraw(taskId);
+ }
+}
+
+static void Task_ItemPcCleanUpWithdraw(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ ItemPc_DestroySubwindow(2);
+ PutWindowTilemap(1);
+ DestroyListMenu(data[0], &sListMenuState.scroll, &sListMenuState.row);
+ ItemPc_CountPcItems();
+ ItemPc_SetCursorPosition();
+ ItemPc_BuildListMenuTemplate();
+ data[0] = ListMenuInit(&gMultiuseListMenuTemplate, sListMenuState.scroll, sListMenuState.row);
+ schedule_bg_copy_tilemap_to_vram(0);
+ ItemPc_ReturnFromSubmenu(taskId);
+}
+
+static void ItemPc_WithdrawMultipleInitWindow(u16 slotId)
+{
+ u16 itemId = ItemPc_GetItemIdBySlotId(slotId);
+
+ CopyItemName(itemId, gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_WithdrawHowMany);
+ AddTextPrinterParameterized(ItemPc_GetOrCreateSubwindow(1), 2, gStringVar4, 0, 2, 0, NULL);
+ ConvertIntToDecimalStringN(gStringVar1, 1, STR_CONV_MODE_LEADING_ZEROS, 3);
+ StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
+ ItemPc_SetBorderStyleOnWindow(3);
+ ItemPc_AddTextPrinterParameterized(3, 0, gStringVar4, 8, 10, 1, 0, 0, 1);
+ schedule_bg_copy_tilemap_to_vram(0);
+}
+
+static void sub_810E670(s16 quantity)
+{
+ FillWindowPixelRect(3, 0x11, 10, 10, 28, 12);
+ ConvertIntToDecimalStringN(gStringVar1, quantity, STR_CONV_MODE_LEADING_ZEROS, 3);
+ StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
+ ItemPc_AddTextPrinterParameterized(3, 0, gStringVar4, 8, 10, 1, 0, 0, 1);
+}
+
+static void Task_ItemPcHandleWithdrawMultiple(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (sub_80BF848(&data[8], data[2]) == TRUE)
+ sub_810E670(data[8]);
+ else if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ ItemPc_DestroySubwindow(1);
+ ClearWindowTilemap(3);
+ PutWindowTilemap(0);
+ ItemPc_PrintOrRemoveCursor(data[0], 1);
+ schedule_bg_copy_tilemap_to_vram(0);
+ ItemPc_RemoveScrollIndicatorArrowPair();
+ ItemPc_DoWithdraw(taskId);
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ ClearMenuWindow(3, FALSE);
+ ItemPc_DestroySubwindow(1);
+ ClearWindowTilemap(3);
+ PutWindowTilemap(0);
+ PutWindowTilemap(1);
+ ItemPc_PrintOrRemoveCursor(data[0], 1);
+ schedule_bg_copy_tilemap_to_vram(0);
+ ItemPc_RemoveScrollIndicatorArrowPair();
+ ItemPc_ReturnFromSubmenu(taskId);
+ }
+}
+
+static void Task_ItemPcGive(u8 taskId)
+{
+ if (CalculatePlayerPartyCount() == 0)
+ {
+ ClearMenuWindow(4, FALSE);
+ ItemPc_DestroySubwindow(0);
+ ClearWindowTilemap(4);
+ PutWindowTilemap(0);
+ ItemPc_PrintOnWindow5WithContinueTask(taskId, gText_ThereIsNoPokemon, gTask_ItemPcWaitButtonAndExitSubmenu);
+ }
+ else
+ {
+ sStateDataPtr->savedCallback = ItemPc_CB2_SwitchToPartyMenu;
+ Task_ItemPcTurnOff1(taskId);
+ }
+}
+
+static void ItemPc_CB2_SwitchToPartyMenu(void)
+{
+ PartyMenuInit(0, 0, 6, 0, 6, sub_811FB28, ItemPc_CB2_ReturnFromPartyMenu);
+ gUnknown_203B0A0.unkC = ItemPc_GetItemIdBySlotId(ItemPc_GetCursorPosition());
+}
+
+static void ItemPc_CB2_ReturnFromPartyMenu(void)
+{
+ ItemPc_Init(1, NULL);
+}
+
+static void gTask_ItemPcWaitButtonAndExitSubmenu(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ ClearMenuWindow_BorderThickness2(5, 0);
+ ClearWindowTilemap(5);
+ PutWindowTilemap(1);
+ ItemPc_PrintOrRemoveCursor(data[0], 1);
+ schedule_bg_copy_tilemap_to_vram(0);
+ ItemPc_ReturnFromSubmenu(taskId);
+ }
+}
+
+static void Task_ItemPcCancel(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ ClearMenuWindow(4, FALSE);
+ ItemPc_DestroySubwindow(0);
+ ClearWindowTilemap(4);
+ PutWindowTilemap(0);
+ PutWindowTilemap(1);
+ ItemPc_PrintOrRemoveCursor(data[0], 1);
+ schedule_bg_copy_tilemap_to_vram(0);
+ ItemPc_ReturnFromSubmenu(taskId);
+}
+
+static void ItemPc_InitWindows(void)
+{
+ u8 i;
+
+ InitWindows(gUnknown_8453F98);
+ DeactivateAllTextPrinters();
+ TextWindow_SetUserSelectedFrame(0, 0x3C0, 0xE0);
+ TextWindow_SetStdFrame0_WithPal(0, 0x3A3, 0xC0);
+ TextWindow_SetBubbleFrame_841F1C8(0, 0x3AC, 0xB0);
+ LoadPalette(stdpal_get(2), 0xD0, 0x20);
+ LoadPalette(gTMCaseMainWindowPalette, 0xF0, 0x20);
+ for (i = 0; i < 3; i++)
+ {
+ FillWindowPixelBuffer(i, 0x00);
+ PutWindowTilemap(i);
+ }
+ schedule_bg_copy_tilemap_to_vram(0);
+ for (i = 0; i < 3; i++)
+ sSubmenuWindowIds[i] = 0xFF;
+}
+
+static void unused_ItemPc_AddTextPrinterParameterized(u8 windowId, const u8 * string, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, u8 speed)
+{
+ struct TextPrinterTemplate template;
+
+ template.currentChar = string;
+ template.windowId = windowId;
+ template.fontId = 3;
+ template.x = x;
+ template.y = y;
+ template.currentX = x;
+ template.currentY = y;
+ template.fgColor = 2;
+ template.bgColor = 0;
+ template.shadowColor = 3;
+ template.unk = GetFontAttribute(3, FONTATTR_UNKNOWN);
+ template.letterSpacing = letterSpacing + GetFontAttribute(3, FONTATTR_LETTER_SPACING);
+ template.lineSpacing = lineSpacing + GetFontAttribute(3, FONTATTR_LINE_SPACING);
+ AddTextPrinter(&template, speed, NULL);
+}
+
+static void ItemPc_AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, u8 speed, u8 colorIdx)
+{
+ AddTextPrinterParameterized4(windowId, fontId, x, y, letterSpacing, lineSpacing, &gUnknown_8453F8C[colorIdx], speed, str);
+}
+
+static void ItemPc_SetBorderStyleOnWindow(u8 windowId)
+{
+ SetWindowBorderStyle(windowId, FALSE, 0x3C0, 0x0E);
+}
+
+static u8 ItemPc_GetOrCreateSubwindow(u8 idx)
+{
+ if (sSubmenuWindowIds[idx] == 0xFF)
+ {
+ sSubmenuWindowIds[idx] = AddWindow(&gUnknown_8453FD0[idx]);
+ SetWindowBorderStyle(sSubmenuWindowIds[idx], TRUE, 0x3A3, 0x0C);
+ }
+
+ return sSubmenuWindowIds[idx];
+}
+
+static void ItemPc_DestroySubwindow(u8 idx)
+{
+ ClearMenuWindow(sSubmenuWindowIds[idx], FALSE);
+ ClearWindowTilemap(sSubmenuWindowIds[idx]); // redundant
+ RemoveWindow(sSubmenuWindowIds[idx]);
+ sSubmenuWindowIds[idx] = 0xFF;
+}
+
+static u8 ItemPc_GetSubwindow(u8 idx)
+{
+ return sSubmenuWindowIds[idx];
+}
+
+static void ItemPc_PrintOnWindow5WithContinueTask(u8 taskId, const u8 * str, TaskFunc taskFunc)
+{
+ DisplayMessageAndContinueTask(taskId, 5, 0x3AC, 0x0B, 2, GetTextSpeedSetting(), str, taskFunc);
+ schedule_bg_copy_tilemap_to_vram(0);
+}
diff --git a/src/item_use.c b/src/item_use.c
new file mode 100644
index 000000000..a7146b65e
--- /dev/null
+++ b/src/item_use.c
@@ -0,0 +1,880 @@
+#include "global.h"
+#include "battle.h"
+#include "berry_pouch.h"
+#include "berry_powder.h"
+#include "bike.h"
+#include "coins.h"
+#include "event_data.h"
+#include "field_effect.h"
+#include "field_fadetransition.h"
+#include "field_map_obj_helpers.h"
+#include "field_player_avatar.h"
+#include "field_specials.h"
+#include "field_weather.h"
+#include "fieldmap.h"
+#include "item.h"
+#include "item_menu.h"
+#include "item_use.h"
+#include "itemfinder.h"
+#include "mail.h"
+#include "main.h"
+#include "malloc.h"
+#include "map_obj_80688E4.h"
+#include "map_obj_lock.h"
+#include "metatile_behavior.h"
+#include "new_menu_helpers.h"
+#include "overworld.h"
+#include "palette.h"
+#include "party_menu.h"
+#include "quest_log.h"
+#include "region_map.h"
+#include "script.h"
+#include "sound.h"
+#include "string_util.h"
+#include "strings.h"
+#include "task.h"
+#include "teachy_tv.h"
+#include "tm_case.h"
+#include "vs_seeker.h"
+#include "constants/fanfares.h"
+#include "constants/flags.h"
+#include "constants/items.h"
+#include "constants/maps.h"
+#include "constants/moves.h"
+#include "constants/songs.h"
+
+EWRAM_DATA void (*sItemUseOnFieldCB)(u8 taskId) = NULL;
+
+void sub_80A1084(void);
+void sub_80A109C(u8 taskId);
+void sub_80A112C(u8 taskId);
+void sub_80A11C0(u8 taskId);
+bool8 sub_80A1194(void);
+void sub_80A1208(void);
+void ItemUseOnFieldCB_Bicycle(u8 taskId);
+bool8 ItemUseCheckFunc_Rod(void);
+void ItemUseOnFieldCB_Rod(u8 taskId);
+void FieldUseFunc_EvoItem(u8 taskId);
+void sub_80A1648(u8 taskId);
+void sub_80A1674(u8 taskId);
+void InitTMCaseFromBag(void);
+void Task_InitTMCaseFromField(u8 taskId);
+void InitBerryPouchFromBag(void);
+void Task_InitBerryPouchFromField(u8 taskId);
+void InitBerryPouchFromBattle(void);
+void InitTeachyTvFromBag(void);
+void Task_InitTeachyTvFromField(u8 taskId);
+void sub_80A19E8(u8 taskId);
+void sub_80A1A44(void);
+void sub_80A1B48(u8 taskId);
+void sub_80A1C08(u8 taskId);
+void sub_80A1C44(u8 taskId);
+void sub_80A1CAC(void);
+void sub_80A1CC0(u8 taskId);
+void sub_80A1D58(void);
+void sub_80A1D68(u8 taskId);
+void Task_BattleUse_StatBooster_DelayAndPrint(u8 taskId);
+void Task_BattleUse_StatBooster_WaitButton_ReturnToBattle(u8 taskId);
+
+extern void (*const gUnknown_83E2954[])(void);
+
+void sub_80A0FBC(u8 taskId)
+{
+ u8 itemType;
+ if (gSpecialVar_ItemId == ITEM_ENIGMA_BERRY)
+ itemType = gTasks[taskId].data[4] - 1;
+ else
+ itemType = ItemId_GetType(gSpecialVar_ItemId) - 1;
+ if (GetPocketByItemId(gSpecialVar_ItemId) == POCKET_BERRY_POUCH)
+ {
+ BerryPouch_SetExitCallback(gUnknown_83E2954[itemType]);
+ BerryPouch_StartFadeToExitCallback(taskId);
+ }
+ else
+ {
+ ItemMenu_SetExitCallback(gUnknown_83E2954[itemType]);
+ if (itemType == 1)
+ sub_8108CB4();
+ ItemMenu_StartFadeToExitCallback(taskId);
+ }
+}
+
+void sub_80A103C(u8 taskId)
+{
+ if (gTasks[taskId].data[3] != 1)
+ {
+ gFieldCallback = sub_80A1084;
+ sub_80A0FBC(taskId);
+ }
+ else
+ sItemUseOnFieldCB(taskId);
+}
+
+void sub_80A1084(void)
+{
+ sub_807DC00();
+ CreateTask(sub_80A109C, 8);
+}
+
+void sub_80A109C(u8 taskId)
+{
+ if (sub_807AA70() == TRUE)
+ {
+ sItemUseOnFieldCB(taskId);
+ }
+}
+
+void sub_80A10C4(u8 taskId, bool8 a1, u8 a2, const u8 * str)
+{
+ StringExpandPlaceholders(gStringVar4, str);
+ if (a1 == FALSE)
+ DisplayItemMessageInBag(taskId, a2, gStringVar4, sub_810A1F8);
+ else
+ DisplayItemMessageOnField(taskId, a2, gStringVar4, sub_80A112C);
+}
+
+void sub_80A1110(u8 taskId, bool8 a1)
+{
+ sub_80A10C4(taskId, a1, 4, gUnknown_8416425);
+}
+
+void sub_80A112C(u8 taskId)
+{
+ ClearDialogWindowAndFrame(0, 1);
+ DestroyTask(taskId);
+ sub_80696C0();
+ ScriptContext2_Disable();
+}
+
+u8 GetItemCompatibilityRule(u16 itemId)
+{
+ if (ItemId_GetPocket(itemId) == POCKET_TM_CASE)
+ return 1;
+ else if (ItemId_GetFieldFunc(itemId) == FieldUseFunc_EvoItem)
+ return 2;
+ else
+ return 0;
+}
+
+void sub_80A1184(void)
+{
+ gFieldCallback2 = sub_80A1194;
+}
+
+bool8 sub_80A1194(void)
+{
+ player_bitmagic();
+ ScriptContext2_Enable();
+ sub_807DC00();
+ CreateTask(sub_80A11C0, 10);
+ gUnknown_2031DE0 = 0;
+ return TRUE;
+}
+
+void sub_80A11C0(u8 taskId)
+{
+ if (sub_807AA70() == TRUE)
+ {
+ UnfreezeMapObjects();
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+ }
+}
+
+void FieldUseFunc_OrangeMail(u8 taskId)
+{
+ ItemMenu_SetExitCallback(sub_80A1208);
+ ItemMenu_StartFadeToExitCallback(taskId);
+}
+
+void sub_80A1208(void)
+{
+ struct MailStruct mail;
+
+ mail.itemId = gSpecialVar_ItemId;
+ sub_80BEBEC(&mail, ReturnToBagFromKeyItem, 0);
+}
+
+void FieldUseFunc_MachBike(u8 taskId)
+{
+ s16 x, y;
+ u8 behavior;
+
+ PlayerGetDestCoords(&x, &y);
+ behavior = MapGridGetMetatileBehaviorAt(x, y);
+
+ if (FlagGet(FLAG_0x830) == TRUE
+ || MetatileBehavior_ReturnFalse_17(behavior) == TRUE
+ || MetatileBehavior_ReturnFalse_18(behavior) == TRUE
+ || MetatileBehavior_ReturnFalse_15(behavior) == TRUE
+ || MetatileBehavior_ReturnFalse_16(behavior) == TRUE)
+ sub_80A10C4(taskId, gTasks[taskId].data[3], 2, gUnknown_8416451);
+ else if (sub_8055C9C() == TRUE && !sub_80BD540())
+ {
+ sItemUseOnFieldCB = ItemUseOnFieldCB_Bicycle;
+ sub_80A103C(taskId);
+ }
+ else
+ sub_80A1110(taskId, gTasks[taskId].data[3]);
+}
+
+void ItemUseOnFieldCB_Bicycle(u8 taskId)
+{
+ if (!TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE))
+ PlaySE(SE_JITENSYA);
+ StartTransitionToFlipBikeState(PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE);
+ sub_80696C0();
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+}
+
+void FieldUseFunc_OldRod(u8 taskId)
+{
+ if (ItemUseCheckFunc_Rod() == TRUE)
+ {
+ sItemUseOnFieldCB = ItemUseOnFieldCB_Rod;
+ sub_80A103C(taskId);
+ }
+ else
+ sub_80A1110(taskId, gTasks[taskId].data[3]);
+}
+
+bool8 ItemUseCheckFunc_Rod(void)
+{
+ s16 x, y;
+ u16 behavior;
+
+ GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
+ behavior = MapGridGetMetatileBehaviorAt(x, y);
+
+ if (MetatileBehavior_IsWaterfall(behavior))
+ return FALSE;
+ if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_4))
+ return FALSE;
+ if (!TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING))
+ {
+ if (IsPlayerFacingSurfableFishableWater())
+ return TRUE;
+ }
+ else
+ {
+ if (MetatileBehavior_IsSurfable(behavior) && !MapGridIsImpassableAt(x, y))
+ return TRUE;
+ if (MetatileBehavior_ReturnFalse_6(behavior) == TRUE)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void ItemUseOnFieldCB_Rod(u8 taskId)
+{
+ sub_805D2C0(ItemId_GetSecondaryId(gSpecialVar_ItemId));
+ DestroyTask(taskId);
+}
+
+void ItemUseOutOfBattle_Itemfinder(u8 taskId)
+{
+ IncrementGameStat(GAME_STAT_USED_ITEMFINDER);
+ sItemUseOnFieldCB = sub_813EC8C;
+ sub_80A103C(taskId);
+}
+
+void FieldUseFunc_CoinCase(u8 taskId)
+{
+ ConvertIntToDecimalStringN(gStringVar1, GetCoins(), STR_CONV_MODE_LEFT_ALIGN, 4);
+ StringExpandPlaceholders(gStringVar4, gUnknown_8416537);
+ ItemUse_SetQuestLogEvent(4, NULL, gSpecialVar_ItemId, 0xFFFF);
+ if (gTasks[taskId].data[3] == 0)
+ DisplayItemMessageInBag(taskId, 2, gStringVar4, sub_810A1F8);
+ else
+ DisplayItemMessageOnField(taskId, 2, gStringVar4, sub_80A112C);
+}
+
+void FieldUseFunc_PowderJar(u8 taskId)
+{
+ ConvertIntToDecimalStringN(gStringVar1, GetBerryPowder(), STR_CONV_MODE_LEFT_ALIGN, 5);
+ StringExpandPlaceholders(gStringVar4, gUnknown_8416644);
+ ItemUse_SetQuestLogEvent(4, NULL, gSpecialVar_ItemId, 0xFFFF);
+ if (gTasks[taskId].data[3] == 0)
+ DisplayItemMessageInBag(taskId, 2, gStringVar4, sub_810A1F8);
+ else
+ DisplayItemMessageOnField(taskId, 2, gStringVar4, sub_80A112C);
+}
+
+void FieldUseFunc_PokeFlute(u8 taskId)
+{
+ bool8 wokeSomeoneUp = FALSE;
+ u8 i;
+
+ for (i = 0; i < CalculatePlayerPartyCount(); i++)
+ {
+ if (!ExecuteTableBasedItemEffect(&gPlayerParty[i], ITEM_AWAKENING, i, MOVE_NONE))
+ wokeSomeoneUp = TRUE;
+ }
+
+ if (wokeSomeoneUp)
+ {
+ ItemUse_SetQuestLogEvent(4, NULL, gSpecialVar_ItemId, 0xFFFF);
+ if (gTasks[taskId].data[3] == 0)
+ DisplayItemMessageInBag(taskId, 2, gUnknown_8416690, sub_80A1648);
+ else
+ DisplayItemMessageOnField(taskId, 2, gUnknown_8416690, sub_80A1648);
+ }
+ else
+ {
+ // Now that's a catchy tune!
+ if (gTasks[taskId].data[3] == 0)
+ DisplayItemMessageInBag(taskId, 2, gUnknown_841665C, sub_810A1F8);
+ else
+ DisplayItemMessageOnField(taskId, 2, gUnknown_841665C, sub_80A112C);
+ }
+}
+
+void sub_80A1648(u8 taskId)
+{
+ PlayFanfareByFanfareNum(FANFARE_POKEFLUTE);
+ gTasks[taskId].func = sub_80A1674;
+}
+
+void sub_80A1674(u8 taskId)
+{
+ if (WaitFanfare(FALSE))
+ {
+ if (gTasks[taskId].data[3] == 0)
+ DisplayItemMessageInBag(taskId, 2, gUnknown_84166A7, sub_810A1F8);
+ else
+ DisplayItemMessageOnField(taskId, 2, gUnknown_84166A7, sub_80A112C);
+ }
+}
+
+void sub_80A16D0(u8 taskId)
+{
+ sub_80A0FBC(taskId);
+}
+
+void FieldUseFunc_Medicine(u8 taskId)
+{
+ gUnknown_3005E98 = sub_81252D0;
+ sub_80A16D0(taskId);
+}
+
+void FieldUseFunc_Ether(u8 taskId)
+{
+ gUnknown_3005E98 = ItemUseCB_PpRestore;
+ sub_80A16D0(taskId);
+}
+
+void FieldUseFunc_PpUp(u8 taskId)
+{
+ gUnknown_3005E98 = dp05_pp_up;
+ sub_80A16D0(taskId);
+}
+
+void FieldUseFunc_RareCandy(u8 taskId)
+{
+ gUnknown_3005E98 = dp05_rare_candy;
+ sub_80A16D0(taskId);
+}
+
+void FieldUseFunc_EvoItem(u8 taskId)
+{
+ gUnknown_3005E98 = sub_8126B60;
+ sub_80A16D0(taskId);
+}
+
+void FieldUseFunc_SacredAsh(u8 taskId)
+{
+ gUnknown_3005E98 = sub_8126894;
+ sub_80A0FBC(taskId);
+}
+
+void FieldUseFunc_TmCase(u8 taskId)
+{
+ if (gTasks[taskId].data[3] == 0)
+ {
+ ItemMenu_SetExitCallback(InitTMCaseFromBag);
+ ItemMenu_StartFadeToExitCallback(taskId);
+ }
+ else
+ {
+ sub_80CCB68();
+ fade_screen(1, 0);
+ gTasks[taskId].func = Task_InitTMCaseFromField;
+ }
+}
+
+void InitTMCaseFromBag(void)
+{
+ InitTMCase(0, ReturnToBagFromKeyItem, 0);
+}
+
+void Task_InitTMCaseFromField(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ CleanupOverworldWindowsAndTilemaps();
+ sub_80A1184();
+ InitTMCase(0, CB2_ReturnToField, 1);
+ DestroyTask(taskId);
+ }
+}
+
+void FieldUseFunc_BerryPouch(u8 taskId)
+{
+ if (gTasks[taskId].data[3] == 0)
+ {
+ ItemMenu_SetExitCallback(InitBerryPouchFromBag);
+ ItemMenu_StartFadeToExitCallback(taskId);
+ }
+ else
+ {
+ sub_80CCB68();
+ fade_screen(1, 0);
+ gTasks[taskId].func = Task_InitBerryPouchFromField;
+ }
+}
+
+void InitBerryPouchFromBag(void)
+{
+ InitBerryPouch(0, ReturnToBagFromKeyItem, 0);
+}
+
+void Task_InitBerryPouchFromField(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ CleanupOverworldWindowsAndTilemaps();
+ sub_80A1184();
+ InitBerryPouch(0, CB2_ReturnToField, 1);
+ DestroyTask(taskId);
+ }
+}
+
+void BattleUseFunc_BerryPouch(u8 taskId)
+{
+ ItemMenu_SetExitCallback(InitBerryPouchFromBattle);
+ ItemMenu_StartFadeToExitCallback(taskId);
+}
+
+void InitBerryPouchFromBattle(void)
+{
+ InitBerryPouch(4, sub_8107ECC, 0);
+}
+
+void FieldUseFunc_TeachyTv(u8 taskId)
+{
+ ItemUse_SetQuestLogEvent(4, NULL, gSpecialVar_ItemId, 0xFFFF);
+ if (gTasks[taskId].data[3] == 0)
+ {
+ ItemMenu_SetExitCallback(InitTeachyTvFromBag);
+ ItemMenu_StartFadeToExitCallback(taskId);
+ }
+ else
+ {
+ sub_80CCB68();
+ fade_screen(1, 0);
+ gTasks[taskId].func = Task_InitTeachyTvFromField;
+ }
+}
+
+void InitTeachyTvFromBag(void)
+{
+ InitTeachyTvController(0, ReturnToBagFromKeyItem);
+}
+
+void Task_InitTeachyTvFromField(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ CleanupOverworldWindowsAndTilemaps();
+ sub_80A1184();
+ InitTeachyTvController(0, CB2_ReturnToField);
+ DestroyTask(taskId);
+ }
+}
+
+void FieldUseFunc_SuperRepel(u8 taskId)
+{
+ if (VarGet(VAR_REPEL_STEP_COUNT) == 0)
+ {
+ PlaySE(SE_RU_GASYAN);
+ gTasks[taskId].func = sub_80A19E8;
+ }
+ else
+ // An earlier repel is still in effect
+ DisplayItemMessageInBag(taskId, 2, gUnknown_841659E, sub_810A1F8);
+}
+
+void sub_80A19E8(u8 taskId)
+{
+ if (!IsSEPlaying())
+ {
+ ItemUse_SetQuestLogEvent(4, NULL, gSpecialVar_ItemId, 0xFFFF);
+ VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId));
+ sub_80A1A44();
+ DisplayItemMessageInBag(taskId, 2, gStringVar4, sub_810A1F8);
+ }
+}
+
+void sub_80A1A44(void)
+{
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+ sub_8108DC8(ItemId_GetPocket(gSpecialVar_ItemId));
+ sub_81089F4(ItemId_GetPocket(gSpecialVar_ItemId));
+ CopyItemName(gSpecialVar_ItemId, gStringVar2);
+ StringExpandPlaceholders(gStringVar4, gUnknown_841658C);
+}
+
+void FieldUseFunc_BlackFlute(u8 taskId)
+{
+ ItemUse_SetQuestLogEvent(4, NULL, gSpecialVar_ItemId, 0xFFFF);
+ if (gSpecialVar_ItemId == ITEM_WHITE_FLUTE)
+ {
+ FlagSet(FLAG_WHITE_FLUTE_ACTIVE);
+ FlagClear(FLAG_BLACK_FLUTE_ACTIVE);
+ CopyItemName(gSpecialVar_ItemId, gStringVar2);
+ StringExpandPlaceholders(gStringVar4, gUnknown_84165D2);
+ gTasks[taskId].func = sub_80A1B48;
+ gTasks[taskId].data[8] = 0;
+ }
+ else if (gSpecialVar_ItemId == ITEM_BLACK_FLUTE)
+ {
+ FlagSet(FLAG_BLACK_FLUTE_ACTIVE);
+ FlagClear(FLAG_WHITE_FLUTE_ACTIVE);
+ CopyItemName(gSpecialVar_ItemId, gStringVar2);
+ StringExpandPlaceholders(gStringVar4, gUnknown_8416600);
+ gTasks[taskId].func = sub_80A1B48;
+ gTasks[taskId].data[8] = 0;
+ }
+}
+
+void sub_80A1B48(u8 taskId)
+{
+ if (++gTasks[taskId].data[8] > 7)
+ {
+ PlaySE(SE_PN_ON);
+ DisplayItemMessageInBag(taskId, 2, gStringVar4, sub_810A1F8);
+ }
+}
+
+bool8 sub_80A1B8C(void)
+{
+ if (gMapHeader.escapeRope & 1)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void ItemUseOutOfBattle_EscapeRope(u8 taskId)
+{
+ if (sub_80A1B8C() == TRUE)
+ {
+ ItemUse_SetQuestLogEvent(4, NULL, gSpecialVar_ItemId, gMapHeader.regionMapSectionId);
+ sItemUseOnFieldCB = sub_80A1C08;
+ sub_80A103C(taskId);
+ }
+ else
+ sub_80A1110(taskId, gTasks[taskId].data[3]);
+}
+
+void sub_80A1C08(u8 taskId)
+{
+ sub_8054D70();
+ sub_80A1A44();
+ gTasks[taskId].data[0] = 0;
+ DisplayItemMessageOnField(taskId, 2, gStringVar4, sub_80A1C44);
+}
+
+void sub_80A1C44(u8 taskId)
+{
+ ResetInitialPlayerAvatarState();
+ sub_8085620();
+ DestroyTask(taskId);
+}
+
+void FieldUseFunc_TownMap(u8 taskId)
+{
+ if (gTasks[taskId].data[3] == 0)
+ {
+ ItemMenu_SetExitCallback(sub_80A1CAC);
+ ItemMenu_StartFadeToExitCallback(taskId);
+ }
+ else
+ {
+ sub_80CCB68();
+ fade_screen(1, 0);
+ gTasks[taskId].func = sub_80A1CC0;
+ }
+}
+
+void sub_80A1CAC(void)
+{
+ sub_80BFF50(0, ReturnToBagFromKeyItem);
+}
+
+void sub_80A1CC0(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ CleanupOverworldWindowsAndTilemaps();
+ sub_80A1184();
+ sub_80BFF50(0, CB2_ReturnToField);
+ DestroyTask(taskId);
+ }
+}
+
+void FieldUseFunc_FameChecker(u8 taskId)
+{
+ ItemUse_SetQuestLogEvent(4, NULL, gSpecialVar_ItemId, 0xFFFF);
+ if (gTasks[taskId].data[3] == 0)
+ {
+ ItemMenu_SetExitCallback(sub_80A1D58);
+ ItemMenu_StartFadeToExitCallback(taskId);
+ }
+ else
+ {
+ sub_80CCB68();
+ fade_screen(1, 0);
+ gTasks[taskId].func = sub_80A1D68;
+ }
+}
+
+void sub_80A1D58(void)
+{
+ UseFameChecker(ReturnToBagFromKeyItem);
+}
+
+void sub_80A1D68(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ CleanupOverworldWindowsAndTilemaps();
+ sub_80A1184();
+ UseFameChecker(CB2_ReturnToField);
+ DestroyTask(taskId);
+ }
+}
+
+void FieldUseFunc_VsSeeker(u8 taskId)
+{
+ if ((gMapHeader.mapType != MAP_TYPE_ROUTE
+ && gMapHeader.mapType != MAP_TYPE_TOWN
+ && gMapHeader.mapType != MAP_TYPE_CITY)
+ || (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(VIRIDIAN_FOREST)
+ && (gSaveBlock1Ptr->location.mapNum == MAP_NUM(VIRIDIAN_FOREST)
+ || gSaveBlock1Ptr->location.mapNum == MAP_NUM(MT_EMBER_EXTERIOR)
+ || gSaveBlock1Ptr->location.mapNum == MAP_NUM(THREE_ISLAND_BERRY_FOREST)
+ || gSaveBlock1Ptr->location.mapNum == MAP_NUM(SIX_ISLAND_PATTERN_BUSH))))
+ {
+ sub_80A1110(taskId, gTasks[taskId].data[3]);
+ }
+ else
+ {
+ sItemUseOnFieldCB = Task_VsSeeker_0;
+ sub_80A103C(taskId);
+ }
+}
+
+void sub_80A1E0C(u8 taskId)
+{
+ sub_80A112C(taskId);
+}
+
+void BattleUseFunc_PokeBallEtc(u8 taskId)
+{
+ if (!IsPlayerPartyAndPokemonStorageFull())
+ {
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+ sub_8108CB4();
+ ItemMenu_StartFadeToExitCallback(taskId);
+ }
+ else
+ {
+ DisplayItemMessageInBag(taskId, 2, gUnknown_8416631, sub_810A1F8);
+ }
+}
+
+void BattleUseFunc_PokeFlute(u8 taskId)
+{
+ sub_8108CB4();
+ ItemMenu_StartFadeToExitCallback(taskId);
+}
+
+void BattleUseFunc_GuardSpec(u8 taskId)
+{
+ if (ExecuteTableBasedItemEffect(&gPlayerParty[gBattlerPartyIndexes[gBattlerInMenuId]], gSpecialVar_ItemId, gBattlerPartyIndexes[gBattlerInMenuId], 0))
+ {
+ DisplayItemMessageInBag(taskId, 2, gUnknown_84169DC, sub_810A1F8);
+ }
+ else
+ {
+ gTasks[taskId].data[8] = 0;
+ gTasks[taskId].func = Task_BattleUse_StatBooster_DelayAndPrint;
+ }
+}
+
+void Task_BattleUse_StatBooster_DelayAndPrint(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (++data[8] > 7)
+ {
+ u16 itemId = gSpecialVar_ItemId;
+ PlaySE(SE_KAIFUKU);
+ RemoveBagItem(itemId, 1);
+ DisplayItemMessageInBag(taskId, 2, Battle_PrintStatBoosterEffectMessage(itemId), Task_BattleUse_StatBooster_WaitButton_ReturnToBattle);
+ }
+}
+
+void Task_BattleUse_StatBooster_WaitButton_ReturnToBattle(u8 taskId)
+{
+ if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
+ {
+ sub_8108CB4();
+ ItemMenu_StartFadeToExitCallback(taskId);
+ }
+}
+
+void ItemUse_SwitchToPartyMenuInBattle(u8 taskId)
+{
+ if (GetPocketByItemId(gSpecialVar_ItemId) == POCKET_BERRY_POUCH)
+ {
+ BerryPouch_SetExitCallback(sub_81279E0);
+ BerryPouch_StartFadeToExitCallback(taskId);
+ }
+ else
+ {
+ ItemMenu_SetExitCallback(sub_81279E0);
+ ItemMenu_StartFadeToExitCallback(taskId);
+ }
+}
+
+void BattleUseFunc_Medicine(u8 taskId)
+{
+ gUnknown_3005E98 = ItemUseCB_Medicine;
+ ItemUse_SwitchToPartyMenuInBattle(taskId);
+}
+
+void sub_80A1FD8(u8 taskId)
+{
+ gUnknown_3005E98 = sub_8126894;
+ ItemUse_SwitchToPartyMenuInBattle(taskId);
+}
+
+void BattleUseFunc_Ether(u8 taskId)
+{
+ gUnknown_3005E98 = ItemUseCB_PpRestore;
+ ItemUse_SwitchToPartyMenuInBattle(taskId);
+}
+
+void BattleUseFunc_PokeDoll(u8 taskId)
+{
+ if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
+ {
+ sub_80A1A44();
+ ItemUse_SetQuestLogEvent(4, 0, gSpecialVar_ItemId, 0xFFFF);
+ DisplayItemMessageInBag(taskId, 2, gStringVar4, ItemMenu_StartFadeToExitCallback);
+ }
+ else
+ sub_80A1110(taskId, 0);
+}
+
+void ItemUseOutOfBattle_EnigmaBerry(u8 taskId)
+{
+ switch (GetItemEffectType(gSpecialVar_ItemId) - 1)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ gTasks[taskId].data[4] = 1;
+ FieldUseFunc_Medicine(taskId);
+ break;
+ case 9:
+ gTasks[taskId].data[4] = 1;
+ FieldUseFunc_SacredAsh(taskId);
+ break;
+ case 0:
+ gTasks[taskId].data[4] = 1;
+ FieldUseFunc_RareCandy(taskId);
+ break;
+ case 18:
+ case 19:
+ gTasks[taskId].data[4] = 1;
+ FieldUseFunc_PpUp(taskId);
+ break;
+ case 20:
+ gTasks[taskId].data[4] = 1;
+ FieldUseFunc_Ether(taskId);
+ break;
+ default:
+ gTasks[taskId].data[4] = 4;
+ FieldUseFunc_OakStopsYou(taskId);
+ }
+}
+
+void ItemUseInBattle_EnigmaBerry(u8 taskId)
+{
+ switch (GetItemEffectType(gSpecialVar_ItemId))
+ {
+ case 0:
+ BattleUseFunc_GuardSpec(taskId);
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 11:
+ BattleUseFunc_Medicine(taskId);
+ break;
+ case 21:
+ BattleUseFunc_Ether(taskId);
+ break;
+ default:
+ FieldUseFunc_OakStopsYou(taskId);
+ }
+}
+
+void FieldUseFunc_OakStopsYou(u8 taskId)
+{
+ if (GetPocketByItemId(gSpecialVar_ItemId) == POCKET_BERRY_POUCH)
+ {
+ StringExpandPlaceholders(gStringVar4, gUnknown_8416425);
+ DisplayItemMessageInBerryPouch(taskId, 4, gStringVar4, sub_813E2B8);
+ }
+ else
+ sub_80A1110(taskId, gTasks[taskId].data[3]);
+}
+
+void ItemUse_SetQuestLogEvent(u8 eventId, struct Pokemon * pokemon, u16 itemId, u16 param)
+{
+ struct UnkStruct_ItemUseQuestLog
+ {
+ u16 itemId;
+ u16 unk2;
+ u16 species;
+ u16 param;
+ } * questLog = Alloc(sizeof(*questLog));
+
+ questLog->itemId = itemId;
+ questLog->param = param;
+ if (pokemon != NULL)
+ questLog->species = GetMonData(pokemon, MON_DATA_SPECIES2);
+ else
+ questLog->species = 0xFFFF;
+ sub_8113550(eventId, (void *)questLog);
+ Free(questLog);
+}
diff --git a/src/load_save.c b/src/load_save.c
index da55869aa..8d09a86a8 100644
--- a/src/load_save.c
+++ b/src/load_save.c
@@ -7,7 +7,7 @@
#include "malloc.h"
#include "item.h"
-extern void sub_8099E44(void);
+extern void SetBagPocketsPointers(void);
extern void sub_8110840(void *oldSave);
extern void sub_8055778(int);
extern void sub_8054F38(u32 newKey);
@@ -80,7 +80,7 @@ void SetSaveBlocksPointers(void)
*sav1_LocalVar = (void*)(&gSaveBlock1) + offset;
gPokemonStoragePtr = (void*)(&gPokemonStorage) + offset;
- sub_8099E44();
+ SetBagPocketsPointers();
sub_8110840(oldSave);
}
@@ -287,7 +287,7 @@ void ApplyNewEncryptionKeyToAllEncryptedData(u32 encryptionKey)
int i;
for(i = 0; i < 4; i++)
- ApplyNewEncryptionKeyToWord(&gSaveBlock1Ptr->unkArray[i][1], encryptionKey);
+ ApplyNewEncryptionKeyToWord(&gSaveBlock1Ptr->unkArray[i].unk4, encryptionKey);
sub_8054F38(encryptionKey);
ApplyNewEncryptionKeyToBagItems_(encryptionKey);
diff --git a/src/m4a.c b/src/m4a.c
new file mode 100644
index 000000000..7b4441ca4
--- /dev/null
+++ b/src/m4a.c
@@ -0,0 +1,1779 @@
+#include "gba/m4a_internal.h"
+
+extern const u8 gCgb3Vol[];
+
+#define BSS_CODE __attribute__((section(".bss.code")))
+
+BSS_CODE ALIGNED(4) char SoundMainRAM_Buffer[0x800] = {0};
+
+struct SoundInfo gSoundInfo;
+struct PokemonCrySong gPokemonCrySongs[MAX_POKEMON_CRIES];
+struct MusicPlayerInfo gPokemonCryMusicPlayers[MAX_POKEMON_CRIES];
+void *gMPlayJumpTable[36];
+struct CgbChannel gCgbChans[4];
+struct MusicPlayerTrack gPokemonCryTracks[MAX_POKEMON_CRIES * 2];
+struct PokemonCrySong gPokemonCrySong;
+struct MusicPlayerInfo gMPlayInfo_BGM;
+struct MusicPlayerInfo gMPlayInfo_SE1;
+struct MusicPlayerInfo gMPlayInfo_SE2;
+struct MusicPlayerInfo gMPlayInfo_SE3;
+u8 gMPlayMemAccArea[0x10];
+
+u32 MidiKeyToFreq(struct WaveData *wav, u8 key, u8 fineAdjust)
+{
+ u32 val1;
+ u32 val2;
+ u32 fineAdjustShifted = fineAdjust << 24;
+
+ if (key > 178)
+ {
+ key = 178;
+ fineAdjustShifted = 255 << 24;
+ }
+
+ val1 = gScaleTable[key];
+ val1 = gFreqTable[val1 & 0xF] >> (val1 >> 4);
+
+ val2 = gScaleTable[key + 1];
+ val2 = gFreqTable[val2 & 0xF] >> (val2 >> 4);
+
+ return umul3232H32(wav->freq, val1 + umul3232H32(val2 - val1, fineAdjustShifted));
+}
+
+void UnusedDummyFunc(void)
+{
+}
+
+void MPlayContinue(struct MusicPlayerInfo *mplayInfo)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void MPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->fadeOC = speed;
+ mplayInfo->fadeOI = speed;
+ mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aSoundInit(void)
+{
+ s32 i;
+
+ CpuCopy32((void *)((s32)SoundMainRAM & ~1), SoundMainRAM_Buffer, sizeof(SoundMainRAM_Buffer));
+
+ SoundInit(&gSoundInfo);
+ MPlayExtender(gCgbChans);
+ m4aSoundMode(SOUND_MODE_DA_BIT_8
+ | SOUND_MODE_FREQ_13379
+ | (12 << SOUND_MODE_MASVOL_SHIFT)
+ | (5 << SOUND_MODE_MAXCHN_SHIFT));
+
+ for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
+ {
+ struct MusicPlayerInfo *mplayInfo = gMPlayTable[i].info;
+ MPlayOpen(mplayInfo, gMPlayTable[i].track, gMPlayTable[i].unk_8);
+ mplayInfo->unk_B = gMPlayTable[i].unk_A;
+ mplayInfo->memAccArea = gMPlayMemAccArea;
+ }
+
+ memcpy(&gPokemonCrySong, &gPokemonCrySongTemplate, sizeof(struct PokemonCrySong));
+
+ for (i = 0; i < MAX_POKEMON_CRIES; i++)
+ {
+ struct MusicPlayerInfo *mplayInfo = &gPokemonCryMusicPlayers[i];
+ struct MusicPlayerTrack *track = &gPokemonCryTracks[i * 2];
+ MPlayOpen(mplayInfo, track, 2);
+ track->chan = 0;
+ }
+}
+
+void m4aSoundMain(void)
+{
+ SoundMain();
+}
+
+void m4aSongNumStart(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ MPlayStart(mplay->info, song->header);
+}
+
+void m4aSongNumStartOrChange(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader != song->header)
+ {
+ MPlayStart(mplay->info, song->header);
+ }
+ else
+ {
+ if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0
+ || (mplay->info->status & MUSICPLAYER_STATUS_PAUSE))
+ {
+ MPlayStart(mplay->info, song->header);
+ }
+ }
+}
+
+void m4aSongNumStartOrContinue(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader != song->header)
+ MPlayStart(mplay->info, song->header);
+ else if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0)
+ MPlayStart(mplay->info, song->header);
+ else if (mplay->info->status & MUSICPLAYER_STATUS_PAUSE)
+ MPlayContinue(mplay->info);
+}
+
+void m4aSongNumStop(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader == song->header)
+ m4aMPlayStop(mplay->info);
+}
+
+void m4aSongNumContinue(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader == song->header)
+ MPlayContinue(mplay->info);
+}
+
+void m4aMPlayAllStop(void)
+{
+ s32 i;
+
+ for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
+ m4aMPlayStop(gMPlayTable[i].info);
+
+ for (i = 0; i < MAX_POKEMON_CRIES; i++)
+ m4aMPlayStop(&gPokemonCryMusicPlayers[i]);
+}
+
+void m4aMPlayContinue(struct MusicPlayerInfo *mplayInfo)
+{
+ MPlayContinue(mplayInfo);
+}
+
+void m4aMPlayAllContinue(void)
+{
+ s32 i;
+
+ for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
+ MPlayContinue(gMPlayTable[i].info);
+
+ for (i = 0; i < MAX_POKEMON_CRIES; i++)
+ MPlayContinue(&gPokemonCryMusicPlayers[i]);
+}
+
+void m4aMPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ MPlayFadeOut(mplayInfo, speed);
+}
+
+void m4aMPlayFadeOutTemporarily(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->fadeOC = speed;
+ mplayInfo->fadeOI = speed;
+ mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT) | TEMPORARY_FADE;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayFadeIn(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->fadeOC = speed;
+ mplayInfo->fadeOI = speed;
+ mplayInfo->fadeOV = (0 << FADE_VOL_SHIFT) | FADE_IN;
+ mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayImmInit(struct MusicPlayerInfo *mplayInfo)
+{
+ s32 trackCount = mplayInfo->trackCount;
+ struct MusicPlayerTrack *track = mplayInfo->tracks;
+
+ while (trackCount > 0)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ if (track->flags & MPT_FLG_START)
+ {
+ Clear64byte(track);
+ track->flags = MPT_FLG_EXIST;
+ track->bendRange = 2;
+ track->volX = 64;
+ track->lfoSpeed = 22;
+ track->tone.type = 1;
+ }
+ }
+
+ trackCount--;
+ track++;
+ }
+}
+
+void MPlayExtender(struct CgbChannel *cgbChans)
+{
+ struct SoundInfo *soundInfo;
+ u32 ident;
+
+ REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
+ | SOUND_4_ON
+ | SOUND_3_ON
+ | SOUND_2_ON
+ | SOUND_1_ON;
+ REG_SOUNDCNT_L = 0; // set master volume to zero
+ REG_NR12 = 0x8;
+ REG_NR22 = 0x8;
+ REG_NR42 = 0x8;
+ REG_NR14 = 0x80;
+ REG_NR24 = 0x80;
+ REG_NR44 = 0x80;
+ REG_NR30 = 0;
+ REG_NR50 = 0x77;
+
+ soundInfo = SOUND_INFO_PTR;
+
+ ident = soundInfo->ident;
+
+ if (ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ gMPlayJumpTable[8] = ply_memacc;
+ gMPlayJumpTable[17] = ply_lfos;
+ gMPlayJumpTable[19] = ply_mod;
+ gMPlayJumpTable[28] = ply_xcmd;
+ gMPlayJumpTable[29] = ply_endtie;
+ gMPlayJumpTable[30] = SampleFreqSet;
+ gMPlayJumpTable[31] = TrackStop;
+ gMPlayJumpTable[32] = FadeOutBody;
+ gMPlayJumpTable[33] = TrkVolPitSet;
+
+ soundInfo->cgbChans = (struct CgbChannel *)cgbChans;
+ soundInfo->CgbSound = CgbSound;
+ soundInfo->CgbOscOff = CgbOscOff;
+ soundInfo->MidiKeyToCgbFreq = MidiKeyToCgbFreq;
+ soundInfo->maxLines = MAX_LINES;
+
+ CpuFill32(0, cgbChans, sizeof(struct CgbChannel) * 4);
+
+ cgbChans[0].ty = 1;
+ cgbChans[0].panMask = 0x11;
+ cgbChans[1].ty = 2;
+ cgbChans[1].panMask = 0x22;
+ cgbChans[2].ty = 3;
+ cgbChans[2].panMask = 0x44;
+ cgbChans[3].ty = 4;
+ cgbChans[3].panMask = 0x88;
+
+ soundInfo->ident = ident;
+}
+
+void MusicPlayerJumpTableCopy(void)
+{
+ asm("swi 0x2A");
+}
+
+void ClearChain(void *x)
+{
+ void (*func)(void *) = *(&gMPlayJumpTable[34]);
+ func(x);
+}
+
+void Clear64byte(void *x)
+{
+ void (*func)(void *) = *(&gMPlayJumpTable[35]);
+ func(x);
+}
+
+void SoundInit(struct SoundInfo *soundInfo)
+{
+ soundInfo->ident = 0;
+
+ if (REG_DMA1CNT & (DMA_REPEAT << 16))
+ REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ if (REG_DMA2CNT & (DMA_REPEAT << 16))
+ REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ REG_DMA1CNT_H = DMA_32BIT;
+ REG_DMA2CNT_H = DMA_32BIT;
+ REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
+ | SOUND_4_ON
+ | SOUND_3_ON
+ | SOUND_2_ON
+ | SOUND_1_ON;
+ REG_SOUNDCNT_H = SOUND_B_FIFO_RESET | SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
+ | SOUND_A_FIFO_RESET | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
+ | SOUND_ALL_MIX_FULL;
+ REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | 0x40;
+
+ REG_DMA1SAD = (s32)soundInfo->pcmBuffer;
+ REG_DMA1DAD = (s32)&REG_FIFO_A;
+ REG_DMA2SAD = (s32)soundInfo->pcmBuffer + PCM_DMA_BUF_SIZE;
+ REG_DMA2DAD = (s32)&REG_FIFO_B;
+
+ SOUND_INFO_PTR = soundInfo;
+ CpuFill32(0, soundInfo, sizeof(struct SoundInfo));
+
+ soundInfo->maxChans = 8;
+ soundInfo->masterVolume = 15;
+ soundInfo->plynote = (u32)ply_note;
+ soundInfo->CgbSound = DummyFunc;
+ soundInfo->CgbOscOff = (void (*)(u8))DummyFunc;
+ soundInfo->MidiKeyToCgbFreq = (u32 (*)(u8, u8, u8))DummyFunc;
+ soundInfo->ExtVolPit = (u32)DummyFunc;
+
+ MPlayJumpTableCopy(gMPlayJumpTable);
+
+ soundInfo->MPlayJumpTable = (u32)gMPlayJumpTable;
+
+ SampleFreqSet(SOUND_MODE_FREQ_13379);
+
+ soundInfo->ident = ID_NUMBER;
+}
+
+void SampleFreqSet(u32 freq)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ freq = (freq & 0xF0000) >> 16;
+ soundInfo->freq = freq;
+ soundInfo->pcmSamplesPerVBlank = gPcmSamplesPerVBlankTable[freq - 1];
+ soundInfo->pcmDmaPeriod = PCM_DMA_BUF_SIZE / soundInfo->pcmSamplesPerVBlank;
+
+ // LCD refresh rate 59.7275Hz
+ soundInfo->pcmFreq = (597275 * soundInfo->pcmSamplesPerVBlank + 5000) / 10000;
+
+ // CPU frequency 16.78Mhz
+ soundInfo->divFreq = (16777216 / soundInfo->pcmFreq + 1) >> 1;
+
+ // Turn off timer 0.
+ REG_TM0CNT_H = 0;
+
+ // cycles per LCD fresh 280896
+ REG_TM0CNT_L = -(280896 / soundInfo->pcmSamplesPerVBlank);
+
+ m4aSoundVSyncOn();
+
+ while (*(vu8 *)REG_ADDR_VCOUNT == 159)
+ ;
+
+ while (*(vu8 *)REG_ADDR_VCOUNT != 159)
+ ;
+
+ REG_TM0CNT_H = TIMER_ENABLE | TIMER_1CLK;
+}
+
+void m4aSoundMode(u32 mode)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ u32 temp;
+
+ if (soundInfo->ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ temp = mode & (SOUND_MODE_REVERB_SET | SOUND_MODE_REVERB_VAL);
+
+ if (temp)
+ soundInfo->reverb = temp & SOUND_MODE_REVERB_VAL;
+
+ temp = mode & SOUND_MODE_MAXCHN;
+
+ if (temp)
+ {
+ struct SoundChannel *chan;
+
+ soundInfo->maxChans = temp >> SOUND_MODE_MAXCHN_SHIFT;
+
+ temp = MAX_DIRECTSOUND_CHANNELS;
+ chan = &soundInfo->chans[0];
+
+ while (temp != 0)
+ {
+ chan->status = 0;
+ temp--;
+ chan++;
+ }
+ }
+
+ temp = mode & SOUND_MODE_MASVOL;
+
+ if (temp)
+ soundInfo->masterVolume = temp >> SOUND_MODE_MASVOL_SHIFT;
+
+ temp = mode & SOUND_MODE_DA_BIT;
+
+ if (temp)
+ {
+ temp = (temp & 0x300000) >> 14;
+ REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | temp;
+ }
+
+ temp = mode & SOUND_MODE_FREQ;
+
+ if (temp)
+ {
+ m4aSoundVSyncOff();
+ SampleFreqSet(temp);
+ }
+
+ soundInfo->ident = ID_NUMBER;
+}
+
+void SoundClear(void)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ s32 i;
+ void *chan;
+
+ if (soundInfo->ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ i = MAX_DIRECTSOUND_CHANNELS;
+ chan = &soundInfo->chans[0];
+
+ while (i > 0)
+ {
+ ((struct SoundChannel *)chan)->status = 0;
+ i--;
+ chan = (void *)((s32)chan + sizeof(struct SoundChannel));
+ }
+
+ chan = soundInfo->cgbChans;
+
+ if (chan)
+ {
+ i = 1;
+
+ while (i <= 4)
+ {
+ soundInfo->CgbOscOff(i);
+ ((struct CgbChannel *)chan)->sf = 0;
+ i++;
+ chan = (void *)((s32)chan + sizeof(struct CgbChannel));
+ }
+ }
+
+ soundInfo->ident = ID_NUMBER;
+}
+
+void m4aSoundVSyncOff(void)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ if (soundInfo->ident >= ID_NUMBER && soundInfo->ident <= ID_NUMBER + 1)
+ {
+ soundInfo->ident += 10;
+
+ if (REG_DMA1CNT & (DMA_REPEAT << 16))
+ REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ if (REG_DMA2CNT & (DMA_REPEAT << 16))
+ REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ REG_DMA1CNT_H = DMA_32BIT;
+ REG_DMA2CNT_H = DMA_32BIT;
+
+ CpuFill32(0, soundInfo->pcmBuffer, sizeof(soundInfo->pcmBuffer));
+ }
+}
+
+void m4aSoundVSyncOn(void)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ u32 ident = soundInfo->ident;
+
+ if (ident == ID_NUMBER)
+ return;
+
+ REG_DMA1CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
+ REG_DMA2CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
+
+ soundInfo->pcmDmaCounter = 0;
+ soundInfo->ident = ident - 10;
+}
+
+void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tracks, u8 trackCount)
+{
+ struct SoundInfo *soundInfo;
+
+ if (trackCount == 0)
+ return;
+
+ if (trackCount > MAX_MUSICPLAYER_TRACKS)
+ trackCount = MAX_MUSICPLAYER_TRACKS;
+
+ soundInfo = SOUND_INFO_PTR;
+
+ if (soundInfo->ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ Clear64byte(mplayInfo);
+
+ mplayInfo->tracks = tracks;
+ mplayInfo->trackCount = trackCount;
+ mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
+
+ while (trackCount != 0)
+ {
+ tracks->flags = 0;
+ trackCount--;
+ tracks++;
+ }
+
+ if (soundInfo->func != 0)
+ {
+ mplayInfo->func = soundInfo->func;
+ mplayInfo->intp = soundInfo->intp;
+ soundInfo->func = 0;
+ }
+
+ soundInfo->intp = (u32)mplayInfo;
+ soundInfo->func = (u32)MPlayMain;
+ soundInfo->ident = ID_NUMBER;
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader)
+{
+ s32 i;
+ u8 unk_B;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ unk_B = mplayInfo->unk_B;
+
+ if (!unk_B
+ || ((!mplayInfo->songHeader || !(mplayInfo->tracks[0].flags & MPT_FLG_START))
+ && ((mplayInfo->status & MUSICPLAYER_STATUS_TRACK) == 0
+ || (mplayInfo->status & MUSICPLAYER_STATUS_PAUSE)))
+ || (mplayInfo->priority <= songHeader->priority))
+ {
+ mplayInfo->ident++;
+ mplayInfo->status = 0;
+ mplayInfo->songHeader = songHeader;
+ mplayInfo->tone = songHeader->tone;
+ mplayInfo->priority = songHeader->priority;
+ mplayInfo->clock = 0;
+ mplayInfo->tempoD = 150;
+ mplayInfo->tempoI = 150;
+ mplayInfo->tempoU = 0x100;
+ mplayInfo->tempoC = 0;
+ mplayInfo->fadeOI = 0;
+
+ i = 0;
+ track = mplayInfo->tracks;
+
+ while (i < songHeader->trackCount && i < mplayInfo->trackCount)
+ {
+ TrackStop(mplayInfo, track);
+ track->flags = MPT_FLG_EXIST | MPT_FLG_START;
+ track->chan = 0;
+ track->cmdPtr = songHeader->part[i];
+ i++;
+ track++;
+ }
+
+ while (i < mplayInfo->trackCount)
+ {
+ TrackStop(mplayInfo, track);
+ track->flags = 0;
+ i++;
+ track++;
+ }
+
+ if (songHeader->reverb & 0x80)
+ m4aSoundMode(songHeader->reverb);
+
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayStop(struct MusicPlayerInfo *mplayInfo)
+{
+ s32 i;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+ mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+
+ while (i > 0)
+ {
+ TrackStop(mplayInfo, track);
+ i--;
+ track++;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void FadeOutBody(struct MusicPlayerInfo *mplayInfo)
+{
+ s32 i;
+ struct MusicPlayerTrack *track;
+ u16 fadeOV;
+#ifdef NONMATCHING
+ u16 mask;
+#else
+ register u16 mask asm("r2");
+#endif // NONMATCHING
+
+ if (mplayInfo->fadeOI == 0)
+ return;
+
+ mplayInfo->fadeOC--;
+ mask = 0xFFFF;
+
+ if (mplayInfo->fadeOC != 0)
+ return;
+
+ mplayInfo->fadeOC = mplayInfo->fadeOI;
+
+ if (mplayInfo->fadeOV & FADE_IN)
+ {
+ mplayInfo->fadeOV += (4 << FADE_VOL_SHIFT);
+
+ if ((u16)(mplayInfo->fadeOV & mask) >= (64 << FADE_VOL_SHIFT))
+ {
+ mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
+ mplayInfo->fadeOI = 0;
+ }
+ }
+ else
+ {
+ mplayInfo->fadeOV -= (4 << FADE_VOL_SHIFT);
+
+ if ((s16)(mplayInfo->fadeOV & mask) <= 0)
+ {
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+
+ while (i > 0)
+ {
+ u32 val;
+
+ TrackStop(mplayInfo, track);
+
+ val = TEMPORARY_FADE;
+ fadeOV = mplayInfo->fadeOV;
+ val &= fadeOV;
+
+ if (!val)
+ track->flags = 0;
+
+ i--;
+ track++;
+ }
+
+ if (mplayInfo->fadeOV & TEMPORARY_FADE)
+ mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
+ else
+ mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
+
+ mplayInfo->fadeOI = 0;
+ return;
+ }
+ }
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+
+ while (i > 0)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ fadeOV = mplayInfo->fadeOV;
+
+ track->volX = (fadeOV >> FADE_VOL_SHIFT);
+ track->flags |= MPT_FLG_VOLCHG;
+ }
+
+ i--;
+ track++;
+ }
+}
+
+void TrkVolPitSet(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ if (track->flags & MPT_FLG_VOLSET)
+ {
+ s32 x;
+ s32 y;
+
+ x = (u32)(track->vol * track->volX) >> 5;
+
+ if (track->modT == 1)
+ x = (u32)(x * (track->modM + 128)) >> 7;
+
+ y = 2 * track->pan + track->panX;
+
+ if (track->modT == 2)
+ y += track->modM;
+
+ if (y < -128)
+ y = -128;
+ else if (y > 127)
+ y = 127;
+
+ track->volMR = (u32)((y + 128) * x) >> 8;
+ track->volML = (u32)((127 - y) * x) >> 8;
+ }
+
+ if (track->flags & MPT_FLG_PITSET)
+ {
+ s32 bend = track->bend * track->bendRange;
+ s32 x = (track->tune + bend)
+ * 4
+ + (track->keyShift << 8)
+ + (track->keyShiftX << 8)
+ + track->pitX;
+
+ if (track->modT == 0)
+ x += 16 * track->modM;
+
+ track->keyM = x >> 8;
+ track->pitM = x;
+ }
+
+ track->flags &= ~(MPT_FLG_PITSET | MPT_FLG_VOLSET);
+}
+
+u32 MidiKeyToCgbFreq(u8 chanNum, u8 key, u8 fineAdjust)
+{
+ if (chanNum == 4)
+ {
+ if (key <= 20)
+ {
+ key = 0;
+ }
+ else
+ {
+ key -= 21;
+ if (key > 59)
+ key = 59;
+ }
+
+ return gNoiseTable[key];
+ }
+ else
+ {
+ s32 val1;
+ s32 val2;
+
+ if (key <= 35)
+ {
+ fineAdjust = 0;
+ key = 0;
+ }
+ else
+ {
+ key -= 36;
+ if (key > 130)
+ {
+ key = 130;
+ fineAdjust = 255;
+ }
+ }
+
+ val1 = gCgbScaleTable[key];
+ val1 = gCgbFreqTable[val1 & 0xF] >> (val1 >> 4);
+
+ val2 = gCgbScaleTable[key + 1];
+ val2 = gCgbFreqTable[val2 & 0xF] >> (val2 >> 4);
+
+ return val1 + ((fineAdjust * (val2 - val1)) >> 8) + 2048;
+ }
+}
+
+void CgbOscOff(u8 chanNum)
+{
+ switch (chanNum)
+ {
+ case 1:
+ REG_NR12 = 8;
+ REG_NR14 = 0x80;
+ break;
+ case 2:
+ REG_NR22 = 8;
+ REG_NR24 = 0x80;
+ break;
+ case 3:
+ REG_NR30 = 0;
+ break;
+ default:
+ REG_NR42 = 8;
+ REG_NR44 = 0x80;
+ }
+}
+
+static inline int CgbPan(struct CgbChannel *chan)
+{
+ u32 rightVolume = chan->rightVolume;
+ u32 leftVolume = chan->leftVolume;
+
+ if ((rightVolume = (u8)rightVolume) >= (leftVolume = (u8)leftVolume))
+ {
+ if (rightVolume / 2 >= leftVolume)
+ {
+ chan->pan = 0x0F;
+ return 1;
+ }
+ }
+ else
+ {
+ if (leftVolume / 2 >= rightVolume)
+ {
+ chan->pan = 0xF0;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void CgbModVol(struct CgbChannel *chan)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ if ((soundInfo->mode & 1) || !CgbPan(chan))
+ {
+ chan->pan = 0xFF;
+ chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4;
+ }
+ else
+ {
+ // Force chan->rightVolume and chan->leftVolume to be read from memory again,
+ // even though there is no reason to do so.
+ // The command line option "-fno-gcse" achieves the same result as this.
+ asm("" : : : "memory");
+
+ chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4;
+ if (chan->eg > 15)
+ chan->eg = 15;
+ }
+
+ chan->sg = (chan->eg * chan->su + 15) >> 4;
+ chan->pan &= chan->panMask;
+}
+
+void CgbSound(void)
+{
+ s32 ch;
+ struct CgbChannel *channels;
+ s32 evAdd;
+ s32 prevC15;
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ vu8 *nrx0ptr;
+ vu8 *nrx1ptr;
+ vu8 *nrx2ptr;
+ vu8 *nrx3ptr;
+ vu8 *nrx4ptr;
+
+ // Most comparision operations that cast to s8 perform 'and' by 0xFF.
+ int mask = 0xff;
+
+ if (soundInfo->c15)
+ soundInfo->c15--;
+ else
+ soundInfo->c15 = 14;
+
+ for (ch = 1, channels = soundInfo->cgbChans; ch <= 4; ch++, channels++)
+ {
+ if (!(channels->sf & 0xc7))
+ continue;
+
+ switch (ch)
+ {
+ case 1:
+ nrx0ptr = (vu8 *)(REG_ADDR_NR10);
+ nrx1ptr = (vu8 *)(REG_ADDR_NR11);
+ nrx2ptr = (vu8 *)(REG_ADDR_NR12);
+ nrx3ptr = (vu8 *)(REG_ADDR_NR13);
+ nrx4ptr = (vu8 *)(REG_ADDR_NR14);
+ break;
+ case 2:
+ nrx0ptr = (vu8 *)(REG_ADDR_NR10+1);
+ nrx1ptr = (vu8 *)(REG_ADDR_NR21);
+ nrx2ptr = (vu8 *)(REG_ADDR_NR22);
+ nrx3ptr = (vu8 *)(REG_ADDR_NR23);
+ nrx4ptr = (vu8 *)(REG_ADDR_NR24);
+ break;
+ case 3:
+ nrx0ptr = (vu8 *)(REG_ADDR_NR30);
+ nrx1ptr = (vu8 *)(REG_ADDR_NR31);
+ nrx2ptr = (vu8 *)(REG_ADDR_NR32);
+ nrx3ptr = (vu8 *)(REG_ADDR_NR33);
+ nrx4ptr = (vu8 *)(REG_ADDR_NR34);
+ break;
+ default:
+ nrx0ptr = (vu8 *)(REG_ADDR_NR30+1);
+ nrx1ptr = (vu8 *)(REG_ADDR_NR41);
+ nrx2ptr = (vu8 *)(REG_ADDR_NR42);
+ nrx3ptr = (vu8 *)(REG_ADDR_NR43);
+ nrx4ptr = (vu8 *)(REG_ADDR_NR44);
+ break;
+ }
+
+ prevC15 = soundInfo->c15;
+ evAdd = *nrx2ptr;
+
+ if (channels->sf & 0x80)
+ {
+ if (!(channels->sf & 0x40))
+ {
+ channels->sf = 3;
+ channels->mo = 3;
+ CgbModVol(channels);
+ switch (ch)
+ {
+ case 1:
+ *nrx0ptr = channels->sw;
+ // fallthrough
+ case 2:
+ *nrx1ptr = ((u32)channels->wp << 6) + channels->le;
+ goto loc_82E0E30;
+ case 3:
+ if ((u32)channels->wp != channels->cp)
+ {
+ *nrx0ptr = 0x40;
+ REG_WAVE_RAM0 = channels->wp[0];
+ REG_WAVE_RAM1 = channels->wp[1];
+ REG_WAVE_RAM2 = channels->wp[2];
+ REG_WAVE_RAM3 = channels->wp[3];
+ channels->cp = (u32)channels->wp;
+ }
+ *nrx0ptr = 0;
+ *nrx1ptr = channels->le;
+ if (channels->le)
+ channels->n4 = -64;
+ else
+ channels->n4 = -128;
+ break;
+ default:
+ *nrx1ptr = channels->le;
+ *nrx3ptr = (u32)channels->wp << 3;
+ loc_82E0E30:
+ evAdd = channels->at + 8;
+ if (channels->le)
+ channels->n4 = 64;
+ else
+ channels->n4 = 0;
+ break;
+ }
+ channels->ec = channels->at;
+ if ((s8)(channels->at & mask))
+ {
+ channels->ev = 0;
+ goto EC_MINUS;
+ }
+ else
+ {
+ goto loc_82E0F96;
+ }
+ }
+ else
+ {
+ goto loc_82E0E82;
+ }
+ }
+ else if (channels->sf & 0x04)
+ {
+ channels->echoLength--;
+ if ((s8)(channels->echoLength & mask) <= 0)
+ {
+ loc_82E0E82:
+ CgbOscOff(ch);
+ channels->sf = 0;
+ goto LAST_LABEL;
+ }
+ goto loc_82E0FD6;
+ }
+ else if ((channels->sf & 0x40) && (channels->sf & 0x03))
+ {
+ channels->sf &= 0xfc;
+ channels->ec = channels->re;
+ if ((s8)(channels->re & mask))
+ {
+ channels->mo |= 1;
+ if (ch != 3)
+ {
+ evAdd = channels->re;
+ }
+ goto EC_MINUS;
+ }
+ else
+ {
+ goto loc_82E0F02;
+ }
+ }
+ else
+ {
+ loc_82E0ED0:
+ if (channels->ec == 0)
+ {
+ if (ch == 3)
+ {
+ channels->mo |= 1;
+ }
+ CgbModVol(channels);
+ if ((channels->sf & 0x3) == 0)
+ {
+ channels->ev--;
+ if ((s8)(channels->ev & mask) <= 0)
+ {
+ loc_82E0F02:
+ channels->ev = ((channels->eg * channels->echoVolume) + 0xFF) >> 8;
+ if (channels->ev)
+ {
+ channels->sf |= 0x4;
+ channels->mo |= 1;
+ if (ch != 3)
+ {
+ evAdd = 8;
+ }
+ goto loc_82E0FD6;
+ }
+ else
+ {
+ goto loc_82E0E82;
+ }
+ }
+ else
+ {
+ channels->ec = channels->re;
+ }
+ }
+ else if ((channels->sf & 0x3) == 1)
+ {
+ loc_82E0F3A:
+ channels->ev = channels->sg;
+ channels->ec = 7;
+ }
+ else if ((channels->sf & 0x3) == 2)
+ {
+ int ev, sg;
+
+ channels->ev--;
+ ev = (s8)(channels->ev & mask);
+ sg = (s8)(channels->sg);
+ if (ev <= sg)
+ {
+ loc_82E0F5A:
+ if (channels->su == 0)
+ {
+ channels->sf &= 0xfc;
+ goto loc_82E0F02;
+ }
+ else
+ {
+ channels->sf--;
+ channels->mo |= 1;
+ if (ch != 3)
+ {
+ evAdd = 8;
+ }
+ goto loc_82E0F3A;
+ }
+ }
+ else
+ {
+ channels->ec = channels->de;
+ }
+ }
+ else
+ {
+ channels->ev++;
+ if ((u8)(channels->ev & mask) >= channels->eg)
+ {
+ loc_82E0F96:
+ channels->sf--;
+ channels->ec = channels->de;
+ if ((u8)(channels->ec & mask))
+ {
+ channels->mo |= 1;
+ channels->ev = channels->eg;
+ if (ch != 3)
+ {
+ evAdd = channels->de;
+ }
+ }
+ else
+ {
+ goto loc_82E0F5A;
+ }
+ }
+ else
+ {
+ channels->ec = channels->at;
+ }
+ }
+ }
+ }
+
+ EC_MINUS:
+ channels->ec--;
+ if (prevC15 == 0)
+ {
+ prevC15--;
+ goto loc_82E0ED0;
+ }
+
+ loc_82E0FD6:
+ if (channels->mo & 0x2)
+ {
+ if (ch < 4 && (channels->ty & 0x08))
+ {
+ int biasH = REG_SOUNDBIAS_H;
+
+ if (biasH < 64)
+ {
+ channels->fr = (channels->fr + 2) & 0x7fc;
+ }
+ else if (biasH < 128)
+ {
+ channels->fr = (channels->fr + 1) & 0x7fe;
+ }
+ }
+ if (ch != 4)
+ {
+ *nrx3ptr = channels->fr;
+ }
+ else
+ {
+ *nrx3ptr = (*nrx3ptr & 0x08) | channels->fr;
+ }
+ channels->n4 = (channels->n4 & 0xC0) + (*((u8*)(&channels->fr) + 1));
+ *nrx4ptr = (s8)(channels->n4 & mask);
+ }
+
+ if (channels->mo & 1)
+ {
+ REG_NR51 = (REG_NR51 & ~channels->panMask) | channels->pan;
+ if (ch == 3)
+ {
+ *nrx2ptr = gCgb3Vol[channels->ev];
+ if (channels->n4 & 0x80)
+ {
+ *nrx0ptr = 0x80;
+ *nrx4ptr = channels->n4;
+ channels->n4 &= 0x7f;
+ }
+ }
+ else
+ {
+ evAdd &= 0xf;
+ *nrx2ptr = (channels->ev << 4) + evAdd;
+ *nrx4ptr = channels->n4 | 0x80;
+ if (ch == 1 && !(*nrx0ptr & 0x08))
+ {
+ *nrx4ptr = channels->n4 | 0x80;
+ }
+ }
+ }
+
+ LAST_LABEL:
+ channels->mo = 0;
+ }
+}
+
+void m4aMPlayTempoControl(struct MusicPlayerInfo *mplayInfo, u16 tempo)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->tempoU = tempo;
+ mplayInfo->tempoI = (mplayInfo->tempoD * mplayInfo->tempoU) >> 8;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->volX = volume / 4;
+ track->flags |= MPT_FLG_VOLCHG;
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void m4aMPlayPitchControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s16 pitch)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->keyShiftX = pitch >> 8;
+ track->pitX = pitch;
+ track->flags |= MPT_FLG_PITCHG;
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void m4aMPlayPanpotControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s8 pan)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->panX = pan;
+ track->flags |= MPT_FLG_VOLCHG;
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void ClearModM(struct MusicPlayerTrack *track)
+{
+ track->lfoSpeedC = 0;
+ track->modM = 0;
+
+ if (track->modT == 0)
+ track->flags |= MPT_FLG_PITCHG;
+ else
+ track->flags |= MPT_FLG_VOLCHG;
+}
+
+void m4aMPlayModDepthSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 modDepth)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->mod = modDepth;
+
+ if (!track->mod)
+ ClearModM(track);
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void m4aMPlayLFOSpeedSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 lfoSpeed)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->lfoSpeed = lfoSpeed;
+
+ if (!track->lfoSpeed)
+ ClearModM(track);
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+#define MEMACC_COND_JUMP(cond) \
+if (cond) \
+ goto cond_true; \
+else \
+ goto cond_false; \
+
+void ply_memacc(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 op;
+ u8 *addr;
+ u8 data;
+
+ op = *track->cmdPtr;
+ track->cmdPtr++;
+
+ addr = mplayInfo->memAccArea + *track->cmdPtr;
+ track->cmdPtr++;
+
+ data = *track->cmdPtr;
+ track->cmdPtr++;
+
+ switch (op)
+ {
+ case 0:
+ *addr = data;
+ return;
+ case 1:
+ *addr += data;
+ return;
+ case 2:
+ *addr -= data;
+ return;
+ case 3:
+ *addr = mplayInfo->memAccArea[data];
+ return;
+ case 4:
+ *addr += mplayInfo->memAccArea[data];
+ return;
+ case 5:
+ *addr -= mplayInfo->memAccArea[data];
+ return;
+ case 6:
+ MEMACC_COND_JUMP(*addr == data)
+ return;
+ case 7:
+ MEMACC_COND_JUMP(*addr != data)
+ return;
+ case 8:
+ MEMACC_COND_JUMP(*addr > data)
+ return;
+ case 9:
+ MEMACC_COND_JUMP(*addr >= data)
+ return;
+ case 10:
+ MEMACC_COND_JUMP(*addr <= data)
+ return;
+ case 11:
+ MEMACC_COND_JUMP(*addr < data)
+ return;
+ case 12:
+ MEMACC_COND_JUMP(*addr == mplayInfo->memAccArea[data])
+ return;
+ case 13:
+ MEMACC_COND_JUMP(*addr != mplayInfo->memAccArea[data])
+ return;
+ case 14:
+ MEMACC_COND_JUMP(*addr > mplayInfo->memAccArea[data])
+ return;
+ case 15:
+ MEMACC_COND_JUMP(*addr >= mplayInfo->memAccArea[data])
+ return;
+ case 16:
+ MEMACC_COND_JUMP(*addr <= mplayInfo->memAccArea[data])
+ return;
+ case 17:
+ MEMACC_COND_JUMP(*addr < mplayInfo->memAccArea[data])
+ return;
+ default:
+ return;
+ }
+
+cond_true:
+ {
+ void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[1]);
+ func(mplayInfo, track);
+ return;
+ }
+
+cond_false:
+ track->cmdPtr += 4;
+}
+
+void ply_xcmd(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 n = *track->cmdPtr;
+ track->cmdPtr++;
+
+ gXcmdTable[n](mplayInfo, track);
+}
+
+void ply_xxx(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[0]);
+ func(mplayInfo, track);
+}
+
+#define READ_XCMD_BYTE(var, n) \
+{ \
+ u32 byte = track->cmdPtr[(n)]; \
+ byte <<= n * 8; \
+ (var) &= ~(0xFF << (n * 8)); \
+ (var) |= byte; \
+}
+
+void ply_xwave(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 wav;
+
+ READ_XCMD_BYTE(wav, 0) // UB: uninitialized variable
+ READ_XCMD_BYTE(wav, 1)
+ READ_XCMD_BYTE(wav, 2)
+ READ_XCMD_BYTE(wav, 3)
+
+ track->tone.wav = (struct WaveData *)wav;
+ track->cmdPtr += 4;
+}
+
+void ply_xtype(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.type = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xatta(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.attack = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xdeca(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.decay = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xsust(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.sustain = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xrele(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.release = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xiecv(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->echoVolume = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xiecl(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->echoLength = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xleng(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.length = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xswee(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.pan_sweep = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xcmd_0C(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 unk;
+
+ READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
+ READ_XCMD_BYTE(unk, 1)
+
+ if (track->unk_3A < (u16)unk)
+ {
+ track->unk_3A++;
+ track->cmdPtr -= 2;
+ track->wait = 1;
+ }
+ else
+ {
+ track->unk_3A = 0;
+ track->cmdPtr += 2;
+ }
+}
+
+void ply_xcmd_0D(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 unk;
+
+ READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
+ READ_XCMD_BYTE(unk, 1)
+ READ_XCMD_BYTE(unk, 2)
+ READ_XCMD_BYTE(unk, 3)
+
+ track->unk_3C = unk;
+ track->cmdPtr += 4;
+}
+
+void DummyFunc(void)
+{
+}
+
+struct MusicPlayerInfo *SetPokemonCryTone(struct ToneData *tone)
+{
+ u32 maxClock = 0;
+ s32 maxClockIndex = 0;
+ s32 i;
+ struct MusicPlayerInfo *mplayInfo;
+
+ for (i = 0; i < MAX_POKEMON_CRIES; i++)
+ {
+ struct MusicPlayerTrack *track = &gPokemonCryTracks[i * 2];
+
+ if (!track->flags && (!track->chan || track->chan->track != track))
+ goto start_song;
+
+ if (maxClock < gPokemonCryMusicPlayers[i].clock)
+ {
+ maxClock = gPokemonCryMusicPlayers[i].clock;
+ maxClockIndex = i;
+ }
+ }
+
+ i = maxClockIndex;
+
+start_song:
+ mplayInfo = &gPokemonCryMusicPlayers[i];
+ mplayInfo->ident++;
+
+#define CRY ((s32)&gPokemonCrySongs + i * sizeof(struct PokemonCrySong))
+#define CRY_OFS(field) offsetof(struct PokemonCrySong, field)
+
+ memcpy((void *)CRY, &gPokemonCrySong, sizeof(struct PokemonCrySong));
+
+ *(u32 *)(CRY + CRY_OFS(tone)) = (u32)tone;
+ *(u32 *)(CRY + CRY_OFS(part)) = CRY + CRY_OFS(part0);
+ *(u32 *)(CRY + CRY_OFS(part) + 4) = CRY + CRY_OFS(part1);
+ *(u32 *)(CRY + CRY_OFS(gotoTarget)) = CRY + CRY_OFS(cont);
+
+#undef CRY_OFS
+#undef CRY
+
+ mplayInfo->ident = ID_NUMBER;
+
+ MPlayStart(mplayInfo, (struct SongHeader *)(&gPokemonCrySongs[i]));
+
+ return mplayInfo;
+}
+
+void SetPokemonCryVolume(u8 val)
+{
+ gPokemonCrySong.volumeValue = val & 0x7F;
+}
+
+void SetPokemonCryPanpot(s8 val)
+{
+ gPokemonCrySong.panValue = (val + C_V) & 0x7F;
+}
+
+void SetPokemonCryPitch(s16 val)
+{
+ s16 b = val + 0x80;
+ u8 a = gPokemonCrySong.tuneValue2 - gPokemonCrySong.tuneValue;
+ gPokemonCrySong.tieKeyValue = (b >> 8) & 0x7F;
+ gPokemonCrySong.tuneValue = (b >> 1) & 0x7F;
+ gPokemonCrySong.tuneValue2 = (a + ((b >> 1) & 0x7F)) & 0x7F;
+}
+
+void SetPokemonCryLength(u16 val)
+{
+ gPokemonCrySong.unkCmd0CParam = val;
+}
+
+void SetPokemonCryRelease(u8 val)
+{
+ gPokemonCrySong.releaseValue = val;
+}
+
+void SetPokemonCryProgress(u32 val)
+{
+ gPokemonCrySong.unkCmd0DParam = val;
+}
+
+int IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo)
+{
+ struct MusicPlayerTrack *track = mplayInfo->tracks;
+
+ if (track->chan && track->chan->track == track)
+ return 1;
+ else
+ return 0;
+}
+
+void SetPokemonCryChorus(s8 val)
+{
+ if (val)
+ {
+ gPokemonCrySong.trackCount = 2;
+ gPokemonCrySong.tuneValue2 = (val + gPokemonCrySong.tuneValue) & 0x7F;
+ }
+ else
+ {
+ gPokemonCrySong.trackCount = 1;
+ }
+}
+
+void SetPokemonCryStereo(u32 val)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ if (val)
+ {
+ REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
+ | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
+ | SOUND_ALL_MIX_FULL;
+ soundInfo->mode &= ~1;
+ }
+ else
+ {
+ REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT | SOUND_B_RIGHT_OUTPUT
+ | SOUND_A_TIMER_0 | SOUND_A_LEFT_OUTPUT | SOUND_A_RIGHT_OUTPUT
+ | SOUND_B_MIX_HALF | SOUND_A_MIX_HALF | SOUND_CGB_MIX_FULL;
+ soundInfo->mode |= 1;
+ }
+}
+
+void SetPokemonCryPriority(u8 val)
+{
+ gPokemonCrySong.priority = val;
+}
diff --git a/src/m4a_2.c b/src/m4a_2.c
deleted file mode 100644
index 0625f05d1..000000000
--- a/src/m4a_2.c
+++ /dev/null
@@ -1,912 +0,0 @@
-#include "gba/m4a_internal.h"
-
-#define BSS_CODE __attribute__((section(".bss.code")))
-
-BSS_CODE ALIGNED(4) char SoundMainRAM_Buffer[0x800] = {0};
-
-struct SoundInfo gSoundInfo;
-struct PokemonCrySong gPokemonCrySongs[MAX_POKEMON_CRIES];
-struct MusicPlayerInfo gPokemonCryMusicPlayers[MAX_POKEMON_CRIES];
-void *gMPlayJumpTable[36];
-struct CgbChannel gCgbChans[4];
-struct MusicPlayerTrack gPokemonCryTracks[MAX_POKEMON_CRIES * 2];
-struct PokemonCrySong gPokemonCrySong;
-struct MusicPlayerInfo gMPlayInfo_BGM;
-struct MusicPlayerInfo gMPlayInfo_SE1;
-struct MusicPlayerInfo gMPlayInfo_SE2;
-struct MusicPlayerInfo gMPlayInfo_SE3;
-u8 gMPlayMemAccArea[0x10];
-
-u32 MidiKeyToFreq(struct WaveData *wav, u8 key, u8 fineAdjust)
-{
- u32 val1;
- u32 val2;
- u32 fineAdjustShifted = fineAdjust << 24;
-
- if (key > 178)
- {
- key = 178;
- fineAdjustShifted = 255 << 24;
- }
-
- val1 = gScaleTable[key];
- val1 = gFreqTable[val1 & 0xF] >> (val1 >> 4);
-
- val2 = gScaleTable[key + 1];
- val2 = gFreqTable[val2 & 0xF] >> (val2 >> 4);
-
- return umul3232H32(wav->freq, val1 + umul3232H32(val2 - val1, fineAdjustShifted));
-}
-
-void UnusedDummyFunc()
-{
-}
-
-void MPlayContinue(struct MusicPlayerInfo *mplayInfo)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void MPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->fadeOC = speed;
- mplayInfo->fadeOI = speed;
- mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aSoundInit(void)
-{
- s32 i;
-
- CpuCopy32((void *)((s32)SoundMainRAM & ~1), SoundMainRAM_Buffer, sizeof(SoundMainRAM_Buffer));
-
- SoundInit(&gSoundInfo);
- MPlayExtender(gCgbChans);
- m4aSoundMode(SOUND_MODE_DA_BIT_8
- | SOUND_MODE_FREQ_13379
- | (12 << SOUND_MODE_MASVOL_SHIFT)
- | (5 << SOUND_MODE_MAXCHN_SHIFT));
-
- for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
- {
- struct MusicPlayerInfo *mplayInfo = gMPlayTable[i].info;
- MPlayOpen(mplayInfo, gMPlayTable[i].track, gMPlayTable[i].unk_8);
- mplayInfo->unk_B = gMPlayTable[i].unk_A;
- mplayInfo->memAccArea = gMPlayMemAccArea;
- }
-
- memcpy(&gPokemonCrySong, &gPokemonCrySongTemplate, sizeof(struct PokemonCrySong));
-
- for (i = 0; i < MAX_POKEMON_CRIES; i++)
- {
- struct MusicPlayerInfo *mplayInfo = &gPokemonCryMusicPlayers[i];
- struct MusicPlayerTrack *track = &gPokemonCryTracks[i * 2];
- MPlayOpen(mplayInfo, track, 2);
- track->chan = 0;
- }
-}
-
-void m4aSoundMain(void)
-{
- SoundMain();
-}
-
-void m4aSongNumStart(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- MPlayStart(mplay->info, song->header);
-}
-
-void m4aSongNumStartOrChange(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- if (mplay->info->songHeader != song->header)
- {
- MPlayStart(mplay->info, song->header);
- }
- else
- {
- if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0
- || (mplay->info->status & MUSICPLAYER_STATUS_PAUSE))
- {
- MPlayStart(mplay->info, song->header);
- }
- }
-}
-
-void m4aSongNumStartOrContinue(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- if (mplay->info->songHeader != song->header)
- MPlayStart(mplay->info, song->header);
- else if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0)
- MPlayStart(mplay->info, song->header);
- else if (mplay->info->status & MUSICPLAYER_STATUS_PAUSE)
- MPlayContinue(mplay->info);
-}
-
-void m4aSongNumStop(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- if (mplay->info->songHeader == song->header)
- m4aMPlayStop(mplay->info);
-}
-
-void m4aSongNumContinue(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- if (mplay->info->songHeader == song->header)
- MPlayContinue(mplay->info);
-}
-
-void m4aMPlayAllStop(void)
-{
- s32 i;
-
- for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
- m4aMPlayStop(gMPlayTable[i].info);
-
- for (i = 0; i < MAX_POKEMON_CRIES; i++)
- m4aMPlayStop(&gPokemonCryMusicPlayers[i]);
-}
-
-void m4aMPlayContinue(struct MusicPlayerInfo *mplayInfo)
-{
- MPlayContinue(mplayInfo);
-}
-
-void m4aMPlayAllContinue(void)
-{
- s32 i;
-
- for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
- MPlayContinue(gMPlayTable[i].info);
-
- for (i = 0; i < MAX_POKEMON_CRIES; i++)
- MPlayContinue(&gPokemonCryMusicPlayers[i]);
-}
-
-void m4aMPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
-{
- MPlayFadeOut(mplayInfo, speed);
-}
-
-void m4aMPlayFadeOutTemporarily(struct MusicPlayerInfo *mplayInfo, u16 speed)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->fadeOC = speed;
- mplayInfo->fadeOI = speed;
- mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT) | TEMPORARY_FADE;
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aMPlayFadeIn(struct MusicPlayerInfo *mplayInfo, u16 speed)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->fadeOC = speed;
- mplayInfo->fadeOI = speed;
- mplayInfo->fadeOV = (0 << FADE_VOL_SHIFT) | FADE_IN;
- mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aMPlayImmInit(struct MusicPlayerInfo *mplayInfo)
-{
- s32 trackCount = mplayInfo->trackCount;
- struct MusicPlayerTrack *track = mplayInfo->tracks;
-
- while (trackCount > 0)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- if (track->flags & MPT_FLG_START)
- {
- Clear64byte(track);
- track->flags = MPT_FLG_EXIST;
- track->bendRange = 2;
- track->volX = 64;
- track->lfoSpeed = 22;
- track->tone.type = 1;
- }
- }
-
- trackCount--;
- track++;
- }
-}
-
-void MPlayExtender(struct CgbChannel *cgbChans)
-{
- struct SoundInfo *soundInfo;
- u32 ident;
-
- REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
- | SOUND_4_ON
- | SOUND_3_ON
- | SOUND_2_ON
- | SOUND_1_ON;
- REG_SOUNDCNT_L = 0; // set master volume to zero
- REG_NR12 = 0x8;
- REG_NR22 = 0x8;
- REG_NR42 = 0x8;
- REG_NR14 = 0x80;
- REG_NR24 = 0x80;
- REG_NR44 = 0x80;
- REG_NR30 = 0;
- REG_NR50 = 0x77;
-
- soundInfo = SOUND_INFO_PTR;
-
- ident = soundInfo->ident;
-
- if (ident != ID_NUMBER)
- return;
-
- soundInfo->ident++;
-
- gMPlayJumpTable[8] = ply_memacc;
- gMPlayJumpTable[17] = ply_lfos;
- gMPlayJumpTable[19] = ply_mod;
- gMPlayJumpTable[28] = ply_xcmd;
- gMPlayJumpTable[29] = ply_endtie;
- gMPlayJumpTable[30] = SampleFreqSet;
- gMPlayJumpTable[31] = TrackStop;
- gMPlayJumpTable[32] = FadeOutBody;
- gMPlayJumpTable[33] = TrkVolPitSet;
-
- soundInfo->cgbChans = (struct CgbChannel *)cgbChans;
- soundInfo->CgbSound = CgbSound;
- soundInfo->CgbOscOff = CgbOscOff;
- soundInfo->MidiKeyToCgbFreq = MidiKeyToCgbFreq;
- soundInfo->maxLines = MAX_LINES;
-
- CpuFill32(0, cgbChans, sizeof(struct CgbChannel) * 4);
-
- cgbChans[0].ty = 1;
- cgbChans[0].panMask = 0x11;
- cgbChans[1].ty = 2;
- cgbChans[1].panMask = 0x22;
- cgbChans[2].ty = 3;
- cgbChans[2].panMask = 0x44;
- cgbChans[3].ty = 4;
- cgbChans[3].panMask = 0x88;
-
- soundInfo->ident = ident;
-}
-
-void MusicPlayerJumpTableCopy(void)
-{
- asm("swi 0x2A");
-}
-
-void ClearChain(void *x)
-{
- void (*func)(void *) = *(&gMPlayJumpTable[34]);
- func(x);
-}
-
-void Clear64byte(void *x)
-{
- void (*func)(void *) = *(&gMPlayJumpTable[35]);
- func(x);
-}
-
-void SoundInit(struct SoundInfo *soundInfo)
-{
- soundInfo->ident = 0;
-
- if (REG_DMA1CNT & (DMA_REPEAT << 16))
- REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
-
- if (REG_DMA2CNT & (DMA_REPEAT << 16))
- REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
-
- REG_DMA1CNT_H = DMA_32BIT;
- REG_DMA2CNT_H = DMA_32BIT;
- REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
- | SOUND_4_ON
- | SOUND_3_ON
- | SOUND_2_ON
- | SOUND_1_ON;
- REG_SOUNDCNT_H = SOUND_B_FIFO_RESET | SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
- | SOUND_A_FIFO_RESET | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
- | SOUND_ALL_MIX_FULL;
- REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | 0x40;
-
- REG_DMA1SAD = (s32)soundInfo->pcmBuffer;
- REG_DMA1DAD = (s32)&REG_FIFO_A;
- REG_DMA2SAD = (s32)soundInfo->pcmBuffer + PCM_DMA_BUF_SIZE;
- REG_DMA2DAD = (s32)&REG_FIFO_B;
-
- SOUND_INFO_PTR = soundInfo;
- CpuFill32(0, soundInfo, sizeof(struct SoundInfo));
-
- soundInfo->maxChans = 8;
- soundInfo->masterVolume = 15;
- soundInfo->plynote = (u32)ply_note;
- soundInfo->CgbSound = DummyFunc;
- soundInfo->CgbOscOff = (void (*)(u8))DummyFunc;
- soundInfo->MidiKeyToCgbFreq = (u32 (*)(u8, u8, u8))DummyFunc;
- soundInfo->ExtVolPit = (u32)DummyFunc;
-
- MPlayJumpTableCopy(gMPlayJumpTable);
-
- soundInfo->MPlayJumpTable = (u32)gMPlayJumpTable;
-
- SampleFreqSet(SOUND_MODE_FREQ_13379);
-
- soundInfo->ident = ID_NUMBER;
-}
-
-void SampleFreqSet(u32 freq)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
-
- freq = (freq & 0xF0000) >> 16;
- soundInfo->freq = freq;
- soundInfo->pcmSamplesPerVBlank = gPcmSamplesPerVBlankTable[freq - 1];
- soundInfo->pcmDmaPeriod = PCM_DMA_BUF_SIZE / soundInfo->pcmSamplesPerVBlank;
-
- // LCD refresh rate 59.7275Hz
- soundInfo->pcmFreq = (597275 * soundInfo->pcmSamplesPerVBlank + 5000) / 10000;
-
- // CPU frequency 16.78Mhz
- soundInfo->divFreq = (16777216 / soundInfo->pcmFreq + 1) >> 1;
-
- // Turn off timer 0.
- REG_TM0CNT_H = 0;
-
- // cycles per LCD fresh 280896
- REG_TM0CNT_L = -(280896 / soundInfo->pcmSamplesPerVBlank);
-
- m4aSoundVSyncOn();
-
- while (*(vu8 *)REG_ADDR_VCOUNT == 159)
- ;
-
- while (*(vu8 *)REG_ADDR_VCOUNT != 159)
- ;
-
- REG_TM0CNT_H = TIMER_ENABLE | TIMER_1CLK;
-}
-
-void m4aSoundMode(u32 mode)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
- u32 temp;
-
- if (soundInfo->ident != ID_NUMBER)
- return;
-
- soundInfo->ident++;
-
- temp = mode & (SOUND_MODE_REVERB_SET | SOUND_MODE_REVERB_VAL);
-
- if (temp)
- soundInfo->reverb = temp & SOUND_MODE_REVERB_VAL;
-
- temp = mode & SOUND_MODE_MAXCHN;
-
- if (temp)
- {
- struct SoundChannel *chan;
-
- soundInfo->maxChans = temp >> SOUND_MODE_MAXCHN_SHIFT;
-
- temp = MAX_DIRECTSOUND_CHANNELS;
- chan = &soundInfo->chans[0];
-
- while (temp != 0)
- {
- chan->status = 0;
- temp--;
- chan++;
- }
- }
-
- temp = mode & SOUND_MODE_MASVOL;
-
- if (temp)
- soundInfo->masterVolume = temp >> SOUND_MODE_MASVOL_SHIFT;
-
- temp = mode & SOUND_MODE_DA_BIT;
-
- if (temp)
- {
- temp = (temp & 0x300000) >> 14;
- REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | temp;
- }
-
- temp = mode & SOUND_MODE_FREQ;
-
- if (temp)
- {
- m4aSoundVSyncOff();
- SampleFreqSet(temp);
- }
-
- soundInfo->ident = ID_NUMBER;
-}
-
-void SoundClear(void)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
- s32 i;
- void *chan;
-
- if (soundInfo->ident != ID_NUMBER)
- return;
-
- soundInfo->ident++;
-
- i = MAX_DIRECTSOUND_CHANNELS;
- chan = &soundInfo->chans[0];
-
- while (i > 0)
- {
- ((struct SoundChannel *)chan)->status = 0;
- i--;
- chan = (void *)((s32)chan + sizeof(struct SoundChannel));
- }
-
- chan = soundInfo->cgbChans;
-
- if (chan)
- {
- i = 1;
-
- while (i <= 4)
- {
- soundInfo->CgbOscOff(i);
- ((struct CgbChannel *)chan)->sf = 0;
- i++;
- chan = (void *)((s32)chan + sizeof(struct CgbChannel));
- }
- }
-
- soundInfo->ident = ID_NUMBER;
-}
-
-void m4aSoundVSyncOff(void)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
-
- if (soundInfo->ident >= ID_NUMBER && soundInfo->ident <= ID_NUMBER + 1)
- {
- soundInfo->ident += 10;
-
- if (REG_DMA1CNT & (DMA_REPEAT << 16))
- REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
-
- if (REG_DMA2CNT & (DMA_REPEAT << 16))
- REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
-
- REG_DMA1CNT_H = DMA_32BIT;
- REG_DMA2CNT_H = DMA_32BIT;
-
- CpuFill32(0, soundInfo->pcmBuffer, sizeof(soundInfo->pcmBuffer));
- }
-}
-
-void m4aSoundVSyncOn(void)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
- u32 ident = soundInfo->ident;
-
- if (ident == ID_NUMBER)
- return;
-
- REG_DMA1CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
- REG_DMA2CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
-
- soundInfo->pcmDmaCounter = 0;
- soundInfo->ident = ident - 10;
-}
-
-void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tracks, u8 trackCount)
-{
- struct SoundInfo *soundInfo;
-
- if (trackCount == 0)
- return;
-
- if (trackCount > MAX_MUSICPLAYER_TRACKS)
- trackCount = MAX_MUSICPLAYER_TRACKS;
-
- soundInfo = SOUND_INFO_PTR;
-
- if (soundInfo->ident != ID_NUMBER)
- return;
-
- soundInfo->ident++;
-
- Clear64byte(mplayInfo);
-
- mplayInfo->tracks = tracks;
- mplayInfo->trackCount = trackCount;
- mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
-
- while (trackCount != 0)
- {
- tracks->flags = 0;
- trackCount--;
- tracks++;
- }
-
- if (soundInfo->func != 0)
- {
- mplayInfo->func = soundInfo->func;
- mplayInfo->intp = soundInfo->intp;
- soundInfo->func = 0;
- }
-
- soundInfo->intp = (u32)mplayInfo;
- soundInfo->func = (u32)MPlayMain;
- soundInfo->ident = ID_NUMBER;
- mplayInfo->ident = ID_NUMBER;
-}
-
-void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader)
-{
- s32 i;
- u8 unk_B;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- unk_B = mplayInfo->unk_B;
-
- if (!unk_B
- || ((!mplayInfo->songHeader || !(mplayInfo->tracks[0].flags & MPT_FLG_START))
- && ((mplayInfo->status & MUSICPLAYER_STATUS_TRACK) == 0
- || (mplayInfo->status & MUSICPLAYER_STATUS_PAUSE)))
- || (mplayInfo->priority <= songHeader->priority))
- {
- mplayInfo->ident++;
- mplayInfo->status = 0;
- mplayInfo->songHeader = songHeader;
- mplayInfo->tone = songHeader->tone;
- mplayInfo->priority = songHeader->priority;
- mplayInfo->clock = 0;
- mplayInfo->tempoD = 150;
- mplayInfo->tempoI = 150;
- mplayInfo->tempoU = 0x100;
- mplayInfo->tempoC = 0;
- mplayInfo->fadeOI = 0;
-
- i = 0;
- track = mplayInfo->tracks;
-
- while (i < songHeader->trackCount && i < mplayInfo->trackCount)
- {
- TrackStop(mplayInfo, track);
- track->flags = MPT_FLG_EXIST | MPT_FLG_START;
- track->chan = 0;
- track->cmdPtr = songHeader->part[i];
- i++;
- track++;
- }
-
- while (i < mplayInfo->trackCount)
- {
- TrackStop(mplayInfo, track);
- track->flags = 0;
- i++;
- track++;
- }
-
- if (songHeader->reverb & 0x80)
- m4aSoundMode(songHeader->reverb);
-
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aMPlayStop(struct MusicPlayerInfo *mplayInfo)
-{
- s32 i;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
- mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
-
- while (i > 0)
- {
- TrackStop(mplayInfo, track);
- i--;
- track++;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void FadeOutBody(struct MusicPlayerInfo *mplayInfo)
-{
- s32 i;
- struct MusicPlayerTrack *track;
- u16 fadeOI = mplayInfo->fadeOI;
- register u32 temp asm("r3");
- register u16 mask asm("r2");
-
- if (fadeOI == 0)
- return;
-
- mplayInfo->fadeOC--;
-
- temp = 0xFFFF;
- mask = temp;
-
- if (mplayInfo->fadeOC != 0)
- return;
-
- mplayInfo->fadeOC = fadeOI;
-
- if (mplayInfo->fadeOV & FADE_IN)
- {
- mplayInfo->fadeOV += (4 << FADE_VOL_SHIFT);
-
- if ((u16)(mplayInfo->fadeOV & mask) >= (64 << FADE_VOL_SHIFT))
- {
- mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
- mplayInfo->fadeOI = 0;
- }
- }
- else
- {
- mplayInfo->fadeOV -= (4 << FADE_VOL_SHIFT);
-
- if ((s16)(mplayInfo->fadeOV & mask) <= 0)
- {
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
-
- while (i > 0)
- {
- register u32 fadeOV asm("r7");
- u32 val;
-
- TrackStop(mplayInfo, track);
-
- val = TEMPORARY_FADE;
- fadeOV = mplayInfo->fadeOV;
- val &= fadeOV;
-
- if (!val)
- track->flags = 0;
-
- i--;
- track++;
- }
-
- if (mplayInfo->fadeOV & TEMPORARY_FADE)
- mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
- else
- mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
-
- mplayInfo->fadeOI = 0;
- return;
- }
- }
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
-
- while (i > 0)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->volX = (mplayInfo->fadeOV >> FADE_VOL_SHIFT);
- track->flags |= MPT_FLG_VOLCHG;
- }
-
- i--;
- track++;
- }
-}
-
-void TrkVolPitSet(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- if (track->flags & MPT_FLG_VOLSET)
- {
- s32 x;
- s32 y;
-
- x = (u32)(track->vol * track->volX) >> 5;
-
- if (track->modT == 1)
- x = (u32)(x * (track->modM + 128)) >> 7;
-
- y = 2 * track->pan + track->panX;
-
- if (track->modT == 2)
- y += track->modM;
-
- if (y < -128)
- y = -128;
- else if (y > 127)
- y = 127;
-
- track->volMR = (u32)((y + 128) * x) >> 8;
- track->volML = (u32)((127 - y) * x) >> 8;
- }
-
- if (track->flags & MPT_FLG_PITSET)
- {
- s32 bend = track->bend * track->bendRange;
- register s32 x asm("r1") = track->tune;
- x += bend;
- x *= 4;
- x += (track->keyShift << 8);
- x += (track->keyShiftX << 8);
- x += track->pitX;
-
- if (track->modT == 0)
- x += 16 * track->modM;
-
- track->keyM = x >> 8;
- track->pitM = x;
- }
-
- track->flags &= ~(MPT_FLG_PITSET | MPT_FLG_VOLSET);
-}
-
-u32 MidiKeyToCgbFreq(u8 chanNum, u8 key, u8 fineAdjust)
-{
- if (chanNum == 4)
- {
- if (key <= 20)
- {
- key = 0;
- }
- else
- {
- key -= 21;
- if (key > 59)
- key = 59;
- }
-
- return gNoiseTable[key];
- }
- else
- {
- s32 val1;
- s32 val2;
-
- if (key <= 35)
- {
- fineAdjust = 0;
- key = 0;
- }
- else
- {
- key -= 36;
- if (key > 130)
- {
- key = 130;
- fineAdjust = 255;
- }
- }
-
- val1 = gCgbScaleTable[key];
- val1 = gCgbFreqTable[val1 & 0xF] >> (val1 >> 4);
-
- val2 = gCgbScaleTable[key + 1];
- val2 = gCgbFreqTable[val2 & 0xF] >> (val2 >> 4);
-
- return val1 + ((fineAdjust * (val2 - val1)) >> 8) + 2048;
- }
-}
-
-void CgbOscOff(u8 chanNum)
-{
- switch (chanNum)
- {
- case 1:
- REG_NR12 = 8;
- REG_NR14 = 0x80;
- break;
- case 2:
- REG_NR22 = 8;
- REG_NR24 = 0x80;
- break;
- case 3:
- REG_NR30 = 0;
- break;
- default:
- REG_NR42 = 8;
- REG_NR44 = 0x80;
- }
-}
-
-static inline int CgbPan(struct CgbChannel *chan)
-{
- u32 rightVolume = chan->rightVolume;
- u32 leftVolume = chan->leftVolume;
-
- if ((rightVolume = (u8)rightVolume) >= (leftVolume = (u8)leftVolume))
- {
- if (rightVolume / 2 >= leftVolume)
- {
- chan->pan = 0x0F;
- return 1;
- }
- }
- else
- {
- if (leftVolume / 2 >= rightVolume)
- {
- chan->pan = 0xF0;
- return 1;
- }
- }
-
- return 0;
-}
-
-void CgbModVol(struct CgbChannel *chan)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
-
- if ((soundInfo->mode & 1) || !CgbPan(chan))
- {
- chan->pan = 0xFF;
- chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4;
- }
- else
- {
- // Force chan->rightVolume and chan->leftVolume to be read from memory again,
- // even though there is no reason to do so.
- // The command line option "-fno-gcse" achieves the same result as this.
- asm("" : : : "memory");
-
- chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4;
- if (chan->eg > 15)
- chan->eg = 15;
- }
-
- chan->sg = (chan->eg * chan->su + 15) >> 4;
- chan->pan &= chan->panMask;
-}
diff --git a/src/m4a_4.c b/src/m4a_4.c
deleted file mode 100644
index 2e1d140b4..000000000
--- a/src/m4a_4.c
+++ /dev/null
@@ -1,545 +0,0 @@
-#include "gba/m4a_internal.h"
-
-void m4aMPlayTempoControl(struct MusicPlayerInfo *mplayInfo, u16 tempo)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->tempoU = tempo;
- mplayInfo->tempoI = (mplayInfo->tempoD * mplayInfo->tempoU) >> 8;
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->volX = volume / 4;
- track->flags |= MPT_FLG_VOLCHG;
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void m4aMPlayPitchControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s16 pitch)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->keyShiftX = (s16)pitch >> 8;
- track->pitX = pitch;
- track->flags |= MPT_FLG_PITCHG;
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void m4aMPlayPanpotControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s8 pan)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->panX = pan;
- track->flags |= MPT_FLG_VOLCHG;
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void ClearModM(struct MusicPlayerTrack *track)
-{
- track->lfoSpeedC = 0;
- track->modM = 0;
-
- if (track->modT == 0)
- track->flags |= MPT_FLG_PITCHG;
- else
- track->flags |= MPT_FLG_VOLCHG;
-}
-
-void m4aMPlayModDepthSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 modDepth)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->mod = modDepth;
-
- if (!track->mod)
- ClearModM(track);
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void m4aMPlayLFOSpeedSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 lfoSpeed)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->lfoSpeed = lfoSpeed;
-
- if (!track->lfoSpeed)
- ClearModM(track);
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-#define MEMACC_COND_JUMP(cond) \
-if (cond) \
- goto cond_true; \
-else \
- goto cond_false; \
-
-void ply_memacc(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 op;
- u8 *addr;
- u8 data;
-
- op = *track->cmdPtr;
- track->cmdPtr++;
-
- addr = mplayInfo->memAccArea + *track->cmdPtr;
- track->cmdPtr++;
-
- data = *track->cmdPtr;
- track->cmdPtr++;
-
- switch (op)
- {
- case 0:
- *addr = data;
- return;
- case 1:
- *addr += data;
- return;
- case 2:
- *addr -= data;
- return;
- case 3:
- *addr = mplayInfo->memAccArea[data];
- return;
- case 4:
- *addr += mplayInfo->memAccArea[data];
- return;
- case 5:
- *addr -= mplayInfo->memAccArea[data];
- return;
- case 6:
- MEMACC_COND_JUMP(*addr == data)
- return;
- case 7:
- MEMACC_COND_JUMP(*addr != data)
- return;
- case 8:
- MEMACC_COND_JUMP(*addr > data)
- return;
- case 9:
- MEMACC_COND_JUMP(*addr >= data)
- return;
- case 10:
- MEMACC_COND_JUMP(*addr <= data)
- return;
- case 11:
- MEMACC_COND_JUMP(*addr < data)
- return;
- case 12:
- MEMACC_COND_JUMP(*addr == mplayInfo->memAccArea[data])
- return;
- case 13:
- MEMACC_COND_JUMP(*addr != mplayInfo->memAccArea[data])
- return;
- case 14:
- MEMACC_COND_JUMP(*addr > mplayInfo->memAccArea[data])
- return;
- case 15:
- MEMACC_COND_JUMP(*addr >= mplayInfo->memAccArea[data])
- return;
- case 16:
- MEMACC_COND_JUMP(*addr <= mplayInfo->memAccArea[data])
- return;
- case 17:
- MEMACC_COND_JUMP(*addr < mplayInfo->memAccArea[data])
- return;
- default:
- return;
- }
-
-cond_true:
- {
- void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[1]);
- func(mplayInfo, track);
- return;
- }
-
-cond_false:
- track->cmdPtr += 4;
-}
-
-void ply_xcmd(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 n = *track->cmdPtr;
- track->cmdPtr++;
-
- gXcmdTable[n](mplayInfo, track);
-}
-
-void ply_xxx(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[0]);
- func(mplayInfo, track);
-}
-
-#define READ_XCMD_BYTE(var, n) \
-{ \
- u32 byte = track->cmdPtr[(n)]; \
- byte <<= n * 8; \
- (var) &= ~(0xFF << (n * 8)); \
- (var) |= byte; \
-}
-
-void ply_xwave(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 wav;
-
- READ_XCMD_BYTE(wav, 0) // UB: uninitialized variable
- READ_XCMD_BYTE(wav, 1)
- READ_XCMD_BYTE(wav, 2)
- READ_XCMD_BYTE(wav, 3)
-
- track->tone.wav = (struct WaveData *)wav;
- track->cmdPtr += 4;
-}
-
-void ply_xtype(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.type = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xatta(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.attack = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xdeca(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.decay = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xsust(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.sustain = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xrele(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.release = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xiecv(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->echoVolume = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xiecl(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->echoLength = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xleng(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.length = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xswee(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.pan_sweep = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xcmd_0C(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 unk;
-
- READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
- READ_XCMD_BYTE(unk, 1)
-
- if (track->unk_3A < (u16)unk)
- {
- track->unk_3A++;
- track->cmdPtr -= 2;
- track->wait = 1;
- }
- else
- {
- track->unk_3A = 0;
- track->cmdPtr += 2;
- }
-}
-
-void ply_xcmd_0D(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 unk;
-
- READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
- READ_XCMD_BYTE(unk, 1)
- READ_XCMD_BYTE(unk, 2)
- READ_XCMD_BYTE(unk, 3)
-
- track->unk_3C = unk;
- track->cmdPtr += 4;
-}
-
-void DummyFunc(void)
-{
-}
-
-struct MusicPlayerInfo *SetPokemonCryTone(struct ToneData *tone)
-{
- u32 maxClock = 0;
- s32 maxClockIndex = 0;
- s32 i;
- struct MusicPlayerInfo *mplayInfo;
-
- for (i = 0; i < MAX_POKEMON_CRIES; i++)
- {
- struct MusicPlayerTrack *track = &gPokemonCryTracks[i * 2];
-
- if (!track->flags && (!track->chan || track->chan->track != track))
- goto start_song;
-
- if (maxClock < gPokemonCryMusicPlayers[i].clock)
- {
- maxClock = gPokemonCryMusicPlayers[i].clock;
- maxClockIndex = i;
- }
- }
-
- i = maxClockIndex;
-
-start_song:
- mplayInfo = &gPokemonCryMusicPlayers[i];
- mplayInfo->ident++;
-
-#define CRY ((s32)&gPokemonCrySongs + i * sizeof(struct PokemonCrySong))
-#define CRY_OFS(field) offsetof(struct PokemonCrySong, field)
-
- memcpy((void *)CRY, &gPokemonCrySong, sizeof(struct PokemonCrySong));
-
- *(u32 *)(CRY + CRY_OFS(tone)) = (u32)tone;
- *(u32 *)(CRY + CRY_OFS(part)) = CRY + CRY_OFS(part0);
- *(u32 *)(CRY + CRY_OFS(part) + 4) = CRY + CRY_OFS(part1);
- *(u32 *)(CRY + CRY_OFS(gotoTarget)) = CRY + CRY_OFS(cont);
-
-#undef CRY_OFS
-#undef CRY
-
- mplayInfo->ident = ID_NUMBER;
-
- MPlayStart(mplayInfo, (struct SongHeader *)(&gPokemonCrySongs[i]));
-
- return mplayInfo;
-}
-
-void SetPokemonCryVolume(u8 val)
-{
- gPokemonCrySong.volumeValue = val & 0x7F;
-}
-
-void SetPokemonCryPanpot(s8 val)
-{
- gPokemonCrySong.panValue = (val + C_V) & 0x7F;
-}
-
-void SetPokemonCryPitch(s16 val)
-{
- s16 b = val + 0x80;
- u8 a = gPokemonCrySong.tuneValue2 - gPokemonCrySong.tuneValue;
- gPokemonCrySong.tieKeyValue = (b >> 8) & 0x7F;
- gPokemonCrySong.tuneValue = (b >> 1) & 0x7F;
- gPokemonCrySong.tuneValue2 = (a + ((b >> 1) & 0x7F)) & 0x7F;
-}
-
-void SetPokemonCryLength(u16 val)
-{
- gPokemonCrySong.unkCmd0CParam = val;
-}
-
-void SetPokemonCryRelease(u8 val)
-{
- gPokemonCrySong.releaseValue = val;
-}
-
-void SetPokemonCryProgress(u32 val)
-{
- gPokemonCrySong.unkCmd0DParam = val;
-}
-
-int IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo)
-{
- struct MusicPlayerTrack *track = mplayInfo->tracks;
-
- if (track->chan && track->chan->track == track)
- return 1;
- else
- return 0;
-}
-
-void SetPokemonCryChorus(s8 val)
-{
- if (val)
- {
- gPokemonCrySong.trackCount = 2;
- gPokemonCrySong.tuneValue2 = (val + gPokemonCrySong.tuneValue) & 0x7F;
- }
- else
- {
- gPokemonCrySong.trackCount = 1;
- }
-}
-
-void SetPokemonCryStereo(u32 val)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
-
- if (val)
- {
- REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
- | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
- | SOUND_ALL_MIX_FULL;
- soundInfo->mode &= ~1;
- }
- else
- {
- REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT | SOUND_B_RIGHT_OUTPUT
- | SOUND_A_TIMER_0 | SOUND_A_LEFT_OUTPUT | SOUND_A_RIGHT_OUTPUT
- | SOUND_B_MIX_HALF | SOUND_A_MIX_HALF | SOUND_CGB_MIX_FULL;
- soundInfo->mode |= 1;
- }
-}
-
-void SetPokemonCryPriority(u8 val)
-{
- gPokemonCrySong.priority = val;
-}
diff --git a/src/main.c b/src/main.c
index 068cc8578..ae9a33e81 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,6 +5,7 @@
#include "dma3.h"
#include "gba/flash_internal.h"
#include "battle.h"
+#include "help_system.h"
extern u16 GetGpuReg(u8);
extern void SetGpuReg(u8, u16);
@@ -29,10 +30,9 @@ extern void MapMusicMain(void);
extern void EnableInterrupts(u16);
extern void sub_800DD28(void);
extern u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void));
-extern void remove_some_task(void);
+extern void ScanlineEffect_Stop(void);
extern void sub_80F50F4(void);
extern bool32 sub_80F5118(void);
-extern bool8 sub_813B870(void);
extern struct SoundInfo gSoundInfo;
extern u32 gFlashMemoryPresent;
@@ -96,13 +96,13 @@ u8 gUnknown_3003D84;
static IntrFunc * const sTimerIntrFunc = gIntrTable + 0x7;
-extern u16 gTrainerId;
+EWRAM_DATA u8 gDecompressionBuffer[0x4000] = {0};
+EWRAM_DATA u16 gTrainerId = 0;
+
extern bool8 gUnknown_3005ECC;
extern bool8 gWirelessCommType;
extern bool8 gUnknown_3005E88;
-EWRAM_DATA void (**gFlashTimerIntrFunc)(void) = NULL;
-
static void UpdateLinkAndCallCallbacks(void);
static void InitMainCallbacks(void);
static void CallCallbacks(void);
@@ -116,7 +116,7 @@ void EnableVCountIntrAtLine150(void);
void AgbMain()
{
RegisterRamReset(RESET_ALL);
- *(vu16 *)BG_PLTT = 0x7FFF;
+ *(vu16 *)BG_PLTT = RGB_WHITE;
InitGpuRegManager();
REG_WAITCNT = WAITCNT_PREFETCH_ENABLE | WAITCNT_WS0_S_1 | WAITCNT_WS0_N_3;
InitKeys();
@@ -206,7 +206,7 @@ static void InitMainCallbacks(void)
static void CallCallbacks(void)
{
- if (!sub_80F5118() && !sub_813B870())
+ if (!sub_80F5118() && !RunHelpSystemCallback())
{
if (gMain.callback1)
gMain.callback1();
@@ -441,7 +441,7 @@ void DoSoftReset(void)
{
REG_IME = 0;
m4aSoundVSyncOff();
- remove_some_task();
+ ScanlineEffect_Stop();
DmaStop(1);
DmaStop(2);
DmaStop(3);
diff --git a/src/map_obj_lock.c b/src/map_obj_lock.c
new file mode 100644
index 000000000..cdd74a5b9
--- /dev/null
+++ b/src/map_obj_lock.c
@@ -0,0 +1,116 @@
+#include "global.h"
+#include "task.h"
+#include "field_player_avatar.h"
+#include "field_map_obj.h"
+#include "field_map_obj_helpers.h"
+#include "script_movement.h"
+#include "map_obj_80688E4.h"
+#include "event_data.h"
+#include "map_obj_lock.h"
+
+bool8 walkrun_is_standing_still(void)
+{
+ if (gPlayerAvatar.running1 == 1)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void sub_8069570(u8 taskId)
+{
+ if (walkrun_is_standing_still())
+ {
+ sub_805C270();
+ DestroyTask(taskId);
+ }
+}
+
+bool8 sub_8069590(void)
+{
+ if (FuncIsActiveTask(sub_8069570))
+ return FALSE;
+ else
+ {
+ sub_805C780();
+ return TRUE;
+ }
+}
+
+void ScriptFreezeMapObjects(void)
+{
+ player_bitmagic();
+ CreateTask(sub_8069570, 80);
+}
+
+void sub_80695CC(u8 taskId)
+{
+ struct Task * task = &gTasks[taskId];
+
+ if (task->data[0] == 0 && walkrun_is_standing_still() == TRUE)
+ {
+ sub_805C270();
+ task->data[0] = 1;
+ }
+
+ if (task->data[1] == 0 && !gMapObjects[gSelectedEventObject].mapobj_bit_1)
+ {
+ FreezeMapObject(&gMapObjects[gSelectedEventObject]);
+ task->data[1] = 1;
+ }
+
+ if (task->data[0] && task->data[1])
+ DestroyTask(taskId);
+}
+
+bool8 sub_8069648(void)
+{
+ if (FuncIsActiveTask(sub_80695CC))
+ return FALSE;
+ else
+ {
+ sub_805C780();
+ return TRUE;
+ }
+}
+
+void LockSelectedMapObject(void)
+{
+ u8 taskId;
+
+ FreezeMapObjectsExceptOne(gSelectedEventObject);
+ taskId = CreateTask(sub_80695CC, 80);
+ if (!gMapObjects[gSelectedEventObject].mapobj_bit_1)
+ {
+ FreezeMapObject(&gMapObjects[gSelectedEventObject]);
+ gTasks[taskId].data[1] = 1;
+ }
+}
+
+void sub_80696C0(void)
+{
+ u8 fieldObjectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[fieldObjectId]);
+ sub_80974D8();
+ UnfreezeMapObjects();
+}
+
+void sub_80696F0(void)
+{
+ u8 fieldObjectId;
+ if (gMapObjects[gSelectedEventObject].active)
+ FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gSelectedEventObject]);
+ fieldObjectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[fieldObjectId]);
+ sub_80974D8();
+ UnfreezeMapObjects();
+}
+
+void sub_8069740(void)
+{
+ FieldObjectFaceOppositeDirection(&gMapObjects[gSelectedEventObject], gSpecialVar_Facing);
+}
+
+void sub_8069768(void)
+{
+ FieldObjectClearAnimIfSpecialAnimActive(&gMapObjects[gSelectedEventObject]);
+}
diff --git a/src/menews_jisan.c b/src/menews_jisan.c
index b4fe080bf..0d406e66a 100644
--- a/src/menews_jisan.c
+++ b/src/menews_jisan.c
@@ -10,76 +10,24 @@ static u32 sub_8146E0C(struct MysteryEventStruct *);
static void sub_8146DA0(struct MysteryEventStruct *);
static void sub_8146D94(struct MysteryEventStruct *);
-#ifdef NONMATCHING
-void sub_8146C30(u32 a0)
+void GenerateRandomNews(u32 a0)
{
struct MysteryEventStruct *r5 = sub_8143D94();
r5->unk_0_0 = a0;
- asm_comment("The switch logic does not match. Specifically, the \"bhi\" is replaced with a \"bls\" and the comparisons with 1 and 3 are swapped chronologically.");
switch (a0)
{
- case 0:
- r5->unk_1 = (Random() % 15) + 16;
- break;
- case 1:
- break;
- case 2:
- break;
- case 3:
- r5->unk_1 = (Random() % 15) + 1;
- break;
+ case 0:
+ break;
+ case 1:
+ case 2:
+ r5->unk_1 = (Random() % 15) + 16;
+ break;
+ case 3:
+ r5->unk_1 = (Random() % 15) + 1;
+ break;
}
}
-#else
-NAKED
-void sub_8146C30(u32 a0)
-{
- asm_unified("\tpush {r4,r5,lr}\n"
- "\tadds r4, r0, 0\n"
- "\tbl sub_8143D94\n"
- "\tadds r5, r0, 0\n"
- "\tmovs r0, 0x3\n"
- "\tadds r1, r4, 0\n"
- "\tands r1, r0\n"
- "\tldrb r2, [r5]\n"
- "\tmovs r0, 0x4\n"
- "\tnegs r0, r0\n"
- "\tands r0, r2\n"
- "\torrs r0, r1\n"
- "\tstrb r0, [r5]\n"
- "\tcmp r4, 0x2\n"
- "\tbhi _08146C56\n"
- "\tcmp r4, 0x1\n"
- "\tbcs _08146C5C\n"
- "\tb _08146C80\n"
- "_08146C56:\n"
- "\tcmp r4, 0x3\n"
- "\tbeq _08146C6E\n"
- "\tb _08146C80\n"
- "_08146C5C:\n"
- "\tbl Random\n"
- "\tlsls r0, 16\n"
- "\tlsrs r0, 16\n"
- "\tmovs r1, 0xF\n"
- "\tbl __umodsi3\n"
- "\tadds r0, 0x10\n"
- "\tb _08146C7E\n"
- "_08146C6E:\n"
- "\tbl Random\n"
- "\tlsls r0, 16\n"
- "\tlsrs r0, 16\n"
- "\tmovs r1, 0xF\n"
- "\tbl __umodsi3\n"
- "\tadds r0, 0x1\n"
- "_08146C7E:\n"
- "\tstrb r0, [r5, 0x1]\n"
- "_08146C80:\n"
- "\tpop {r4,r5}\n"
- "\tpop {r0}\n"
- "\tbx r0");
-}
-#endif
void sub_8146C88(void)
{
@@ -111,33 +59,33 @@ u16 sub_8146CE8(void)
struct MysteryEventStruct *r4 = sub_8143D94();
u16 r5;
- if (!sub_806E2BC() || !sub_8143E1C())
+ if (!sub_806E2BC() || !ValidateReceivedWonderNews())
return 0;
r5 = sub_8146E0C(r4);
switch (r5)
{
- case 0:
- break;
- case 1:
- *r6 = sub_8146D74(r4);
- break;
- case 2:
- *r6 = sub_8146D74(r4);
- break;
- case 3:
- break;
- case 4:
- *r6 = sub_8146D74(r4);
- sub_8146DA0(r4);
- break;
- case 5:
- *r6 = sub_8146D74(r4);
- sub_8146D94(r4);
- break;
- case 6:
- break;
+ case 0:
+ break;
+ case 1:
+ *r6 = sub_8146D74(r4);
+ break;
+ case 2:
+ *r6 = sub_8146D74(r4);
+ break;
+ case 3:
+ break;
+ case 4:
+ *r6 = sub_8146D74(r4);
+ sub_8146DA0(r4);
+ break;
+ case 5:
+ *r6 = sub_8146D74(r4);
+ sub_8146D94(r4);
+ break;
+ case 6:
+ break;
}
return r5;
@@ -182,18 +130,18 @@ static u32 sub_8146E0C(struct MysteryEventStruct *a0)
r0 = *a0;
switch (r0.unk_0_0)
{
- case 0:
- return 3;
- case 1:
- return 1;
- case 2:
- return 2;
- case 3:
- if ((u8)r0.unk_0_2 < 3)
- return 4;
- return 5;
- default:
- AGB_ASSERT_EX(0, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/menews_jisan.c", 383);
- return 0;
+ case 0:
+ return 3;
+ case 1:
+ return 1;
+ case 2:
+ return 2;
+ case 3:
+ if ((u8)r0.unk_0_2 < 3)
+ return 4;
+ return 5;
+ default:
+ AGB_ASSERT_EX(0, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/menews_jisan.c", 383);
+ return 0;
}
}
diff --git a/src/menu2.c b/src/menu2.c
new file mode 100644
index 000000000..9a1846c7e
--- /dev/null
+++ b/src/menu2.c
@@ -0,0 +1,851 @@
+#include "global.h"
+#include "text.h"
+#include "gpu_regs.h"
+#include "task.h"
+#include "wild_encounter.h"
+#include "string_util.h"
+#include "constants/species.h"
+
+static void Task_SmoothBlendLayers(u8 taskId);
+
+static const u8 gUnknown_845FD54[][5] = {
+ [SPECIES_BULBASAUR - 1] = {0x16, 0x1b, 0x30, 0x16, 0x29},
+ [SPECIES_IVYSAUR - 1] = {0x14, 0x1b, 0x30, 0x15, 0x2a},
+ [SPECIES_VENUSAUR - 1] = {0x1b, 0x20, 0x20, 0x1b, 0x33},
+ [SPECIES_CHARMANDER - 1] = {0x14, 0x0f, 0x38, 0x13, 0x1e},
+ [SPECIES_CHARMELEON - 1] = {0x0d, 0x11, 0x30, 0x0f, 0x22},
+ [SPECIES_CHARIZARD - 1] = {0x1b, 0x07, 0x28, 0x1a, 0x19},
+ [SPECIES_SQUIRTLE - 1] = {0x19, 0x13, 0x30, 0x1a, 0x22},
+ [SPECIES_WARTORTLE - 1] = {0x16, 0x13, 0x30, 0x17, 0x21},
+ [SPECIES_BLASTOISE - 1] = {0x12, 0x08, 0x28, 0x15, 0x19},
+ [SPECIES_CATERPIE - 1] = {0x15, 0x14, 0x30, 0x13, 0x24},
+ [SPECIES_METAPOD - 1] = {0x13, 0x1d, 0x30, 0x18, 0x2a},
+ [SPECIES_BUTTERFREE - 1] = {0x12, 0x1b, 0x08, 0x12, 0x2a},
+ [SPECIES_WEEDLE - 1] = {0x16, 0x1c, 0x30, 0x15, 0x2b},
+ [SPECIES_KAKUNA - 1] = {0x19, 0x13, 0x30, 0x1a, 0x24},
+ [SPECIES_BEEDRILL - 1] = {0x19, 0x16, 0x08, 0x19, 0x25},
+ [SPECIES_PIDGEY - 1] = {0x15, 0x12, 0x30, 0x12, 0x1e},
+ [SPECIES_PIDGEOTTO - 1] = {0x24, 0x0e, 0x30, 0x1f, 0x1e},
+ [SPECIES_PIDGEOT - 1] = {0x0c, 0x13, 0x08, 0x0a, 0x23},
+ [SPECIES_RATTATA - 1] = {0x17, 0x1e, 0x30, 0x18, 0x2d},
+ [SPECIES_RATICATE - 1] = {0x12, 0x14, 0x30, 0x10, 0x26},
+ [SPECIES_SPEAROW - 1] = {0x15, 0x14, 0x30, 0x15, 0x1f},
+ [SPECIES_FEAROW - 1] = {0x0c, 0x27, 0x00, 0x0b, 0x3f},
+ [SPECIES_EKANS - 1] = {0x11, 0x0f, 0x30, 0x14, 0x1d},
+ [SPECIES_ARBOK - 1] = {0x1b, 0x01, 0x28, 0x1d, 0x10},
+ [SPECIES_PIKACHU - 1] = {0x19, 0x13, 0x30, 0x1a, 0x1f},
+ [SPECIES_RAICHU - 1] = {0x19, 0x14, 0x28, 0x1c, 0x22},
+ [SPECIES_SANDSHREW - 1] = {0x17, 0x16, 0x30, 0x18, 0x25},
+ [SPECIES_SANDSLASH - 1] = {0x11, 0x13, 0x28, 0x13, 0x22},
+ [SPECIES_NIDORAN_F - 1] = {0x16, 0x15, 0x30, 0x18, 0x21},
+ [SPECIES_NIDORINA - 1] = {0x1f, 0x17, 0x30, 0x1e, 0x28},
+ [SPECIES_NIDOQUEEN - 1] = {0x10, 0x0b, 0x28, 0x13, 0x1c},
+ [SPECIES_NIDORAN_M - 1] = {0x15, 0x22, 0x28, 0x15, 0x31},
+ [SPECIES_NIDORINO - 1] = {0x13, 0x1e, 0x28, 0x1b, 0x2d},
+ [SPECIES_NIDOKING - 1] = {0x12, 0x15, 0x28, 0x13, 0x27},
+ [SPECIES_CLEFAIRY - 1] = {0x19, 0x14, 0x30, 0x1b, 0x24},
+ [SPECIES_CLEFABLE - 1] = {0x1c, 0x12, 0x30, 0x1d, 0x21},
+ [SPECIES_VULPIX - 1] = {0x10, 0x16, 0x30, 0x0e, 0x25},
+ [SPECIES_NINETALES - 1] = {0x28, 0x10, 0x28, 0x27, 0x1e},
+ [SPECIES_JIGGLYPUFF - 1] = {0x1d, 0x15, 0x30, 0x1e, 0x25},
+ [SPECIES_WIGGLYTUFF - 1] = {0x1a, 0x12, 0x30, 0x1c, 0x22},
+ [SPECIES_ZUBAT - 1] = {0x14, 0x1d, 0x08, 0x14, 0x29},
+ [SPECIES_GOLBAT - 1] = {0x23, 0x1a, 0x00, 0x21, 0x2e},
+ [SPECIES_ODDISH - 1] = {0x1d, 0x20, 0x28, 0x1d, 0x2b},
+ [SPECIES_GLOOM - 1] = {0x1c, 0x18, 0x28, 0x1c, 0x27},
+ [SPECIES_VILEPLUME - 1] = {0x1c, 0x1e, 0x28, 0x1d, 0x2a},
+ [SPECIES_PARAS - 1] = {0x1d, 0x1a, 0x30, 0x1c, 0x27},
+ [SPECIES_PARASECT - 1] = {0x1e, 0x1c, 0x28, 0x20, 0x2e},
+ [SPECIES_VENONAT - 1] = {0x1b, 0x16, 0x10, 0x1a, 0x29},
+ [SPECIES_VENOMOTH - 1] = {0x12, 0x19, 0x08, 0x16, 0x27},
+ [SPECIES_DIGLETT - 1] = {0x1e, 0x16, 0x30, 0x1c, 0x23},
+ [SPECIES_DUGTRIO - 1] = {0x1a, 0x11, 0x30, 0x1a, 0x1f},
+ [SPECIES_MEOWTH - 1] = {0x1c, 0x16, 0x30, 0x1c, 0x23},
+ [SPECIES_PERSIAN - 1] = {0x13, 0x13, 0x30, 0x13, 0x21},
+ [SPECIES_PSYDUCK - 1] = {0x1c, 0x13, 0x30, 0x17, 0x29},
+ [SPECIES_GOLDUCK - 1] = {0x17, 0x12, 0x28, 0x17, 0x22},
+ [SPECIES_MANKEY - 1] = {0x1c, 0x15, 0x30, 0x1b, 0x23},
+ [SPECIES_PRIMEAPE - 1] = {0x1e, 0x16, 0x30, 0x1a, 0x27},
+ [SPECIES_GROWLITHE - 1] = {0x14, 0x17, 0x30, 0x14, 0x24},
+ [SPECIES_ARCANINE - 1] = {0x0f, 0x09, 0x28, 0x0c, 0x19},
+ [SPECIES_POLIWAG - 1] = {0x15, 0x14, 0x30, 0x13, 0x1f},
+ [SPECIES_POLIWHIRL - 1] = {0x1f, 0x10, 0x30, 0x1e, 0x17},
+ [SPECIES_POLIWRATH - 1] = {0x22, 0x0c, 0x30, 0x21, 0x18},
+ [SPECIES_ABRA - 1] = {0x1f, 0x13, 0x30, 0x1f, 0x21},
+ [SPECIES_KADABRA - 1] = {0x1b, 0x12, 0x30, 0x1c, 0x25},
+ [SPECIES_ALAKAZAM - 1] = {0x1c, 0x11, 0x28, 0x1d, 0x26},
+ [SPECIES_MACHOP - 1] = {0x1b, 0x11, 0x30, 0x1b, 0x1e},
+ [SPECIES_MACHOKE - 1] = {0x1d, 0x11, 0x30, 0x1d, 0x1f},
+ [SPECIES_MACHAMP - 1] = {0x1a, 0x0d, 0x28, 0x1c, 0x1b},
+ [SPECIES_BELLSPROUT - 1] = {0x15, 0x0e, 0x30, 0x0e, 0x1c},
+ [SPECIES_WEEPINBELL - 1] = {0x1a, 0x1c, 0x10, 0x15, 0x32},
+ [SPECIES_VICTREEBEL - 1] = {0x1e, 0x0f, 0x30, 0x1c, 0x1b},
+ [SPECIES_TENTACOOL - 1] = {0x1a, 0x15, 0x30, 0x1e, 0x26},
+ [SPECIES_TENTACRUEL - 1] = {0x1b, 0x10, 0x28, 0x1c, 0x26},
+ [SPECIES_GEODUDE - 1] = {0x1c, 0x20, 0x28, 0x1d, 0x2d},
+ [SPECIES_GRAVELER - 1] = {0x1d, 0x19, 0x28, 0x1e, 0x26},
+ [SPECIES_GOLEM - 1] = {0x19, 0x1b, 0x28, 0x1c, 0x27},
+ [SPECIES_PONYTA - 1] = {0x0f, 0x11, 0x30, 0x0e, 0x23},
+ [SPECIES_RAPIDASH - 1] = {0x2f, 0x0f, 0x28, 0x2b, 0x1e},
+ [SPECIES_SLOWPOKE - 1] = {0x14, 0x1f, 0x28, 0x15, 0x2f},
+ [SPECIES_SLOWBRO - 1] = {0x0e, 0x0d, 0x28, 0x0c, 0x1f},
+ [SPECIES_MAGNEMITE - 1] = {0x20, 0x1b, 0x10, 0x1f, 0x29},
+ [SPECIES_MAGNETON - 1] = {0x1f, 0x14, 0x08, 0x1f, 0x22},
+ [SPECIES_FARFETCHD - 1] = {0x16, 0x14, 0x30, 0x16, 0x29},
+ [SPECIES_DODUO - 1] = {0x11, 0x16, 0x30, 0x0d, 0x2c},
+ [SPECIES_DODRIO - 1] = {0x1d, 0x04, 0x28, 0x0e, 0x07},
+ [SPECIES_SEEL - 1] = {0x1b, 0x24, 0x20, 0x17, 0x35},
+ [SPECIES_DEWGONG - 1] = {0x12, 0x0a, 0x30, 0x0e, 0x1a},
+ [SPECIES_GRIMER - 1] = {0x1f, 0x10, 0x30, 0x1d, 0x25},
+ [SPECIES_MUK - 1] = {0x17, 0x0f, 0x30, 0x19, 0x22},
+ [SPECIES_SHELLDER - 1] = {0x1a, 0x18, 0x30, 0x17, 0x29},
+ [SPECIES_CLOYSTER - 1] = {0x19, 0x1e, 0x28, 0x1d, 0x2c},
+ [SPECIES_GASTLY - 1] = {0x1a, 0x1f, 0x08, 0x19, 0x30},
+ [SPECIES_HAUNTER - 1] = {0x20, 0x14, 0x08, 0x1d, 0x26},
+ [SPECIES_GENGAR - 1] = {0x1a, 0x16, 0x30, 0x19, 0x28},
+ [SPECIES_ONIX - 1] = {0x1f, 0x24, 0x20, 0x28, 0x36},
+ [SPECIES_DROWZEE - 1] = {0x1a, 0x0e, 0x30, 0x1a, 0x1e},
+ [SPECIES_HYPNO - 1] = {0x1c, 0x12, 0x30, 0x19, 0x24},
+ [SPECIES_KRABBY - 1] = {0x1d, 0x1d, 0x30, 0x1a, 0x2b},
+ [SPECIES_KINGLER - 1] = {0x1e, 0x1f, 0x28, 0x1c, 0x30},
+ [SPECIES_VOLTORB - 1] = {0x1c, 0x1b, 0x30, 0x1b, 0x2b},
+ [SPECIES_ELECTRODE - 1] = {0x1c, 0x18, 0x30, 0x1d, 0x2e},
+ [SPECIES_EXEGGCUTE - 1] = {0x21, 0x17, 0x30, 0x20, 0x24},
+ [SPECIES_EXEGGUTOR - 1] = {0x1c, 0x17, 0x28, 0x1b, 0x25},
+ [SPECIES_CUBONE - 1] = {0x1b, 0x12, 0x30, 0x1b, 0x22},
+ [SPECIES_MAROWAK - 1] = {0x14, 0x0f, 0x30, 0x11, 0x23},
+ [SPECIES_HITMONLEE - 1] = {0x2e, 0x11, 0x30, 0x28, 0x22},
+ [SPECIES_HITMONCHAN - 1] = {0x22, 0x0e, 0x30, 0x1e, 0x1d},
+ [SPECIES_LICKITUNG - 1] = {0x14, 0x11, 0x30, 0x14, 0x24},
+ [SPECIES_KOFFING - 1] = {0x1e, 0x14, 0x10, 0x1d, 0x20},
+ [SPECIES_WEEZING - 1] = {0x11, 0x0d, 0x10, 0x0f, 0x1c},
+ [SPECIES_RHYHORN - 1] = {0x0e, 0x23, 0x20, 0x14, 0x33},
+ [SPECIES_RHYDON - 1] = {0x0d, 0x12, 0x28, 0x17, 0x22},
+ [SPECIES_CHANSEY - 1] = {0x1a, 0x0d, 0x30, 0x1a, 0x1a},
+ [SPECIES_TANGELA - 1] = {0x1c, 0x18, 0x30, 0x1d, 0x29},
+ [SPECIES_KANGASKHAN - 1] = {0x1b, 0x06, 0x28, 0x1c, 0x14},
+ [SPECIES_HORSEA - 1] = {0x1c, 0x14, 0x30, 0x16, 0x23},
+ [SPECIES_SEADRA - 1] = {0x10, 0x17, 0x30, 0x09, 0x2a},
+ [SPECIES_GOLDEEN - 1] = {0x16, 0x23, 0x20, 0x15, 0x34},
+ [SPECIES_SEAKING - 1] = {0x16, 0x0f, 0x30, 0x10, 0x18},
+ [SPECIES_STARYU - 1] = {0x1c, 0x18, 0x30, 0x1a, 0x26},
+ [SPECIES_STARMIE - 1] = {0x1d, 0x13, 0x30, 0x1b, 0x20},
+ [SPECIES_MR_MIME - 1] = {0x24, 0x11, 0x30, 0x25, 0x1e},
+ [SPECIES_SCYTHER - 1] = {0x10, 0x19, 0x28, 0x12, 0x27},
+ [SPECIES_JYNX - 1] = {0x1b, 0x0f, 0x30, 0x19, 0x1c},
+ [SPECIES_ELECTABUZZ - 1] = {0x14, 0x11, 0x30, 0x17, 0x20},
+ [SPECIES_MAGMAR - 1] = {0x10, 0x0e, 0x30, 0x0b, 0x19},
+ [SPECIES_PINSIR - 1] = {0x1d, 0x1c, 0x28, 0x20, 0x2b},
+ [SPECIES_TAUROS - 1] = {0x11, 0x1d, 0x28, 0x13, 0x2e},
+ [SPECIES_MAGIKARP - 1] = {0x16, 0x15, 0x30, 0x13, 0x23},
+ [SPECIES_GYARADOS - 1] = {0x0b, 0x18, 0x28, 0x16, 0x29},
+ [SPECIES_LAPRAS - 1] = {0x16, 0x08, 0x28, 0x15, 0x16},
+ [SPECIES_DITTO - 1] = {0x24, 0x12, 0x30, 0x1f, 0x20},
+ [SPECIES_EEVEE - 1] = {0x16, 0x16, 0x30, 0x16, 0x23},
+ [SPECIES_VAPOREON - 1] = {0x18, 0x23, 0x28, 0x18, 0x30},
+ [SPECIES_JOLTEON - 1] = {0x14, 0x1b, 0x30, 0x16, 0x28},
+ [SPECIES_FLAREON - 1] = {0x16, 0x17, 0x30, 0x14, 0x25},
+ [SPECIES_PORYGON - 1] = {0x18, 0x12, 0x30, 0x10, 0x23},
+ [SPECIES_OMANYTE - 1] = {0x1d, 0x1d, 0x30, 0x1c, 0x2b},
+ [SPECIES_OMASTAR - 1] = {0x16, 0x1a, 0x30, 0x19, 0x2d},
+ [SPECIES_KABUTO - 1] = {0x1b, 0x16, 0x30, 0x1a, 0x27},
+ [SPECIES_KABUTOPS - 1] = {0x15, 0x11, 0x30, 0x15, 0x1f},
+ [SPECIES_AERODACTYL - 1] = {0x13, 0x1d, 0x00, 0x14, 0x30},
+ [SPECIES_SNORLAX - 1] = {0x35, 0x09, 0x30, 0x2e, 0x14},
+ [SPECIES_ARTICUNO - 1] = {0x18, 0x0b, 0x18, 0x17, 0x17},
+ [SPECIES_ZAPDOS - 1] = {0x0e, 0x0e, 0x10, 0x04, 0x28},
+ [SPECIES_MOLTRES - 1] = {0x0b, 0x2a, 0x08, 0x0b, 0x38},
+ [SPECIES_DRATINI - 1] = {0x0d, 0x12, 0x30, 0x0b, 0x21},
+ [SPECIES_DRAGONAIR - 1] = {0x18, 0x0e, 0x30, 0x13, 0x1c},
+ [SPECIES_DRAGONITE - 1] = {0x1b, 0x07, 0x18, 0x19, 0x17},
+ [SPECIES_MEWTWO - 1] = {0x2b, 0x09, 0x28, 0x2c, 0x18},
+ [SPECIES_MEW - 1] = {0x19, 0x14, 0x10, 0x1f, 0x21},
+ [SPECIES_CHIKORITA - 1] = {0x1b, 0x17, 0x30, 0x1b, 0x24},
+ [SPECIES_BAYLEEF - 1] = {0x1d, 0x10, 0x30, 0x20, 0x1d},
+ [SPECIES_MEGANIUM - 1] = {0x05, 0x0d, 0x28, 0x0d, 0x1b},
+ [SPECIES_CYNDAQUIL - 1] = {0x11, 0x1b, 0x30, 0x14, 0x27},
+ [SPECIES_QUILAVA - 1] = {0x25, 0x18, 0x30, 0x27, 0x26},
+ [SPECIES_TYPHLOSION - 1] = {0x09, 0x10, 0x28, 0x10, 0x1c},
+ [SPECIES_TOTODILE - 1] = {0x16, 0x10, 0x30, 0x19, 0x20},
+ [SPECIES_CROCONAW - 1] = {0x16, 0x10, 0x30, 0x18, 0x21},
+ [SPECIES_FERALIGATR - 1] = {0x0e, 0x0a, 0x28, 0x08, 0x1a},
+ [SPECIES_SENTRET - 1] = {0x1e, 0x0a, 0x30, 0x1d, 0x15},
+ [SPECIES_FURRET - 1] = {0x21, 0x0e, 0x30, 0x21, 0x19},
+ [SPECIES_HOOTHOOT - 1] = {0x1d, 0x15, 0x30, 0x1c, 0x24},
+ [SPECIES_NOCTOWL - 1] = {0x19, 0x0e, 0x30, 0x18, 0x1c},
+ [SPECIES_LEDYBA - 1] = {0x1b, 0x15, 0x30, 0x1c, 0x24},
+ [SPECIES_LEDIAN - 1] = {0x18, 0x12, 0x10, 0x1c, 0x21},
+ [SPECIES_SPINARAK - 1] = {0x20, 0x20, 0x28, 0x20, 0x2d},
+ [SPECIES_ARIADOS - 1] = {0x17, 0x23, 0x28, 0x15, 0x30},
+ [SPECIES_CROBAT - 1] = {0x22, 0x1e, 0x08, 0x23, 0x2b},
+ [SPECIES_CHINCHOU - 1] = {0x1f, 0x1d, 0x30, 0x1f, 0x29},
+ [SPECIES_LANTURN - 1] = {0x10, 0x23, 0x28, 0x19, 0x33},
+ [SPECIES_PICHU - 1] = {0x1e, 0x17, 0x30, 0x1e, 0x24},
+ [SPECIES_CLEFFA - 1] = {0x1c, 0x18, 0x30, 0x1e, 0x26},
+ [SPECIES_IGGLYBUFF - 1] = {0x1f, 0x19, 0x30, 0x1f, 0x24},
+ [SPECIES_TOGEPI - 1] = {0x21, 0x15, 0x30, 0x1f, 0x20},
+ [SPECIES_TOGETIC - 1] = {0x1b, 0x10, 0x30, 0x1c, 0x1c},
+ [SPECIES_NATU - 1] = {0x1c, 0x17, 0x30, 0x15, 0x21},
+ [SPECIES_XATU - 1] = {0x1b, 0x08, 0x30, 0x19, 0x14},
+ [SPECIES_MAREEP - 1] = {0x16, 0x15, 0x30, 0x15, 0x24},
+ [SPECIES_FLAAFFY - 1] = {0x19, 0x12, 0x30, 0x18, 0x21},
+ [SPECIES_AMPHAROS - 1] = {0x0f, 0x0a, 0x30, 0x10, 0x1b},
+ [SPECIES_BELLOSSOM - 1] = {0x1f, 0x13, 0x30, 0x1f, 0x20},
+ [SPECIES_MARILL - 1] = {0x1d, 0x15, 0x30, 0x1d, 0x22},
+ [SPECIES_AZUMARILL - 1] = {0x1a, 0x12, 0x30, 0x17, 0x1f},
+ [SPECIES_SUDOWOODO - 1] = {0x20, 0x10, 0x30, 0x20, 0x1f},
+ [SPECIES_POLITOED - 1] = {0x1d, 0x0f, 0x30, 0x1e, 0x20},
+ [SPECIES_HOPPIP - 1] = {0x23, 0x25, 0x08, 0x25, 0x33},
+ [SPECIES_SKIPLOOM - 1] = {0x1e, 0x18, 0x08, 0x1c, 0x27},
+ [SPECIES_JUMPLUFF - 1] = {0x1d, 0x21, 0x08, 0x20, 0x2f},
+ [SPECIES_AIPOM - 1] = {0x1e, 0x29, 0x18, 0x1e, 0x35},
+ [SPECIES_SUNKERN - 1] = {0x1f, 0x20, 0x08, 0x24, 0x2e},
+ [SPECIES_SUNFLORA - 1] = {0x1c, 0x0c, 0x30, 0x1b, 0x19},
+ [SPECIES_YANMA - 1] = {0x1b, 0x28, 0x08, 0x16, 0x35},
+ [SPECIES_WOOPER - 1] = {0x1d, 0x13, 0x30, 0x1f, 0x21},
+ [SPECIES_QUAGSIRE - 1] = {0x15, 0x09, 0x30, 0x12, 0x18},
+ [SPECIES_ESPEON - 1] = {0x11, 0x1b, 0x30, 0x11, 0x29},
+ [SPECIES_UMBREON - 1] = {0x23, 0x15, 0x30, 0x23, 0x22},
+ [SPECIES_MURKROW - 1] = {0x24, 0x13, 0x30, 0x20, 0x22},
+ [SPECIES_SLOWKING - 1] = {0x1e, 0x13, 0x28, 0x1d, 0x25},
+ [SPECIES_MISDREAVUS - 1] = {0x28, 0x21, 0x08, 0x26, 0x2e},
+ [SPECIES_UNOWN - 1] = {0x20, 0x17, 0x08, 0x1f, 0x21},
+ [SPECIES_WOBBUFFET - 1] = {0x1d, 0x09, 0x30, 0x1d, 0x1a},
+ [SPECIES_GIRAFARIG - 1] = {0x0b, 0x0d, 0x28, 0x11, 0x1d},
+ [SPECIES_PINECO - 1] = {0x1d, 0x12, 0x10, 0x19, 0x25},
+ [SPECIES_FORRETRESS - 1] = {0x19, 0x17, 0x08, 0x1e, 0x26},
+ [SPECIES_DUNSPARCE - 1] = {0x10, 0x1b, 0x30, 0x0c, 0x2d},
+ [SPECIES_GLIGAR - 1] = {0x1e, 0x13, 0x08, 0x1d, 0x23},
+ [SPECIES_STEELIX - 1] = {0x0c, 0x0d, 0x28, 0x0d, 0x1c},
+ [SPECIES_SNUBBULL - 1] = {0x1b, 0x15, 0x30, 0x1a, 0x23},
+ [SPECIES_GRANBULL - 1] = {0x1c, 0x09, 0x30, 0x19, 0x18},
+ [SPECIES_QWILFISH - 1] = {0x1f, 0x26, 0x20, 0x1d, 0x33},
+ [SPECIES_SCIZOR - 1] = {0x15, 0x0f, 0x10, 0x1a, 0x1a},
+ [SPECIES_SHUCKLE - 1] = {0x25, 0x0a, 0x30, 0x24, 0x18},
+ [SPECIES_HERACROSS - 1] = {0x18, 0x19, 0x28, 0x1a, 0x26},
+ [SPECIES_SNEASEL - 1] = {0x1c, 0x13, 0x30, 0x1d, 0x24},
+ [SPECIES_TEDDIURSA - 1] = {0x1e, 0x12, 0x30, 0x1b, 0x23},
+ [SPECIES_URSARING - 1] = {0x1e, 0x04, 0x28, 0x1d, 0x14},
+ [SPECIES_SLUGMA - 1] = {0x20, 0x18, 0x30, 0x20, 0x28},
+ [SPECIES_MAGCARGO - 1] = {0x16, 0x11, 0x30, 0x17, 0x23},
+ [SPECIES_SWINUB - 1] = {0x1c, 0x18, 0x30, 0x1b, 0x25},
+ [SPECIES_PILOSWINE - 1] = {0x18, 0x23, 0x20, 0x18, 0x36},
+ [SPECIES_CORSOLA - 1] = {0x19, 0x1d, 0x28, 0x19, 0x2b},
+ [SPECIES_REMORAID - 1] = {0x15, 0x1f, 0x28, 0x13, 0x2b},
+ [SPECIES_OCTILLERY - 1] = {0x1c, 0x11, 0x30, 0x1a, 0x20},
+ [SPECIES_DELIBIRD - 1] = {0x1d, 0x11, 0x30, 0x1b, 0x1f},
+ [SPECIES_MANTINE - 1] = {0x16, 0x1e, 0x28, 0x1f, 0x27},
+ [SPECIES_SKARMORY - 1] = {0x1e, 0x00, 0x28, 0x13, 0x07},
+ [SPECIES_HOUNDOUR - 1] = {0x25, 0x11, 0x30, 0x25, 0x1f},
+ [SPECIES_HOUNDOOM - 1] = {0x0d, 0x13, 0x30, 0x0d, 0x24},
+ [SPECIES_KINGDRA - 1] = {0x0e, 0x13, 0x28, 0x0a, 0x2c},
+ [SPECIES_PHANPY - 1] = {0x1b, 0x11, 0x30, 0x19, 0x24},
+ [SPECIES_DONPHAN - 1] = {0x11, 0x15, 0x30, 0x19, 0x2c},
+ [SPECIES_PORYGON2 - 1] = {0x18, 0x11, 0x30, 0x11, 0x20},
+ [SPECIES_STANTLER - 1] = {0x15, 0x15, 0x28, 0x17, 0x28},
+ [SPECIES_SMEARGLE - 1] = {0x18, 0x10, 0x30, 0x1b, 0x25},
+ [SPECIES_TYROGUE - 1] = {0x1e, 0x12, 0x30, 0x1f, 0x1f},
+ [SPECIES_HITMONTOP - 1] = {0x1a, 0x39, 0x10, 0x1a, 0x2b},
+ [SPECIES_SMOOCHUM - 1] = {0x20, 0x18, 0x30, 0x21, 0x26},
+ [SPECIES_ELEKID - 1] = {0x1d, 0x14, 0x30, 0x1d, 0x23},
+ [SPECIES_MAGBY - 1] = {0x1c, 0x15, 0x30, 0x1a, 0x24},
+ [SPECIES_MILTANK - 1] = {0x18, 0x0e, 0x30, 0x18, 0x1e},
+ [SPECIES_BLISSEY - 1] = {0x1d, 0x09, 0x30, 0x1d, 0x19},
+ [SPECIES_RAIKOU - 1] = {0x29, 0x0c, 0x28, 0x27, 0x1e},
+ [SPECIES_ENTEI - 1] = {0x08, 0x09, 0x28, 0x0b, 0x18},
+ [SPECIES_SUICUNE - 1] = {0x23, 0x1d, 0x28, 0x26, 0x2c},
+ [SPECIES_LARVITAR - 1] = {0x1c, 0x18, 0x30, 0x1a, 0x24},
+ [SPECIES_PUPITAR - 1] = {0x1b, 0x19, 0x30, 0x1b, 0x28},
+ [SPECIES_TYRANITAR - 1] = {0x06, 0x0b, 0x28, 0x0d, 0x19},
+ [SPECIES_LUGIA - 1] = {0x08, 0x2a, 0x08, 0x14, 0x34},
+ [SPECIES_HO_OH - 1] = {0x0d, 0x25, 0x08, 0x0e, 0x34},
+ [SPECIES_CELEBI - 1] = {0x15, 0x21, 0x08, 0x1a, 0x2b},
+ [SPECIES_OLD_UNOWN_B - 1] = {0x1f, 0x12, 0x08, 0x1e, 0x1c},
+ [SPECIES_OLD_UNOWN_C - 1] = {0x20, 0x17, 0x08, 0x1f, 0x21},
+ [SPECIES_OLD_UNOWN_D - 1] = {0x1c, 0x19, 0x08, 0x1b, 0x23},
+ [SPECIES_OLD_UNOWN_E - 1] = {0x21, 0x19, 0x08, 0x20, 0x23},
+ [SPECIES_OLD_UNOWN_F - 1] = {0x1b, 0x13, 0x08, 0x1a, 0x1d},
+ [SPECIES_OLD_UNOWN_G - 1] = {0x20, 0x16, 0x08, 0x1f, 0x21},
+ [SPECIES_OLD_UNOWN_H - 1] = {0x20, 0x19, 0x08, 0x1f, 0x23},
+ [SPECIES_OLD_UNOWN_I - 1] = {0x20, 0x19, 0x08, 0x1f, 0x23},
+ [SPECIES_OLD_UNOWN_J - 1] = {0x20, 0x16, 0x08, 0x1f, 0x20},
+ [SPECIES_OLD_UNOWN_K - 1] = {0x1d, 0x1a, 0x08, 0x1c, 0x24},
+ [SPECIES_OLD_UNOWN_L - 1] = {0x20, 0x16, 0x08, 0x1f, 0x1f},
+ [SPECIES_OLD_UNOWN_M - 1] = {0x20, 0x1c, 0x08, 0x1f, 0x26},
+ [SPECIES_OLD_UNOWN_N - 1] = {0x20, 0x1a, 0x08, 0x1f, 0x23},
+ [SPECIES_OLD_UNOWN_O - 1] = {0x20, 0x1a, 0x08, 0x1f, 0x23},
+ [SPECIES_OLD_UNOWN_P - 1] = {0x20, 0x16, 0x08, 0x1f, 0x20},
+ [SPECIES_OLD_UNOWN_Q - 1] = {0x1d, 0x16, 0x08, 0x1c, 0x20},
+ [SPECIES_OLD_UNOWN_R - 1] = {0x20, 0x15, 0x08, 0x1f, 0x1f},
+ [SPECIES_OLD_UNOWN_S - 1] = {0x20, 0x19, 0x08, 0x1f, 0x23},
+ [SPECIES_OLD_UNOWN_T - 1] = {0x20, 0x1e, 0x08, 0x1f, 0x28},
+ [SPECIES_OLD_UNOWN_U - 1] = {0x20, 0x17, 0x08, 0x1f, 0x21},
+ [SPECIES_OLD_UNOWN_V - 1] = {0x1e, 0x1e, 0x08, 0x1d, 0x28},
+ [SPECIES_OLD_UNOWN_W - 1] = {0x20, 0x1d, 0x08, 0x1f, 0x27},
+ [SPECIES_OLD_UNOWN_X - 1] = {0x20, 0x19, 0x08, 0x1f, 0x23},
+ [SPECIES_OLD_UNOWN_Y - 1] = {0x20, 0x15, 0x08, 0x1f, 0x1f},
+ [SPECIES_OLD_UNOWN_Z - 1] = {0x20, 0x19, 0x08, 0x1f, 0x23},
+ [SPECIES_TREECKO - 1] = {0x1a, 0x0f, 0x30, 0x19, 0x20},
+ [SPECIES_GROVYLE - 1] = {0x0d, 0x05, 0x10, 0x05, 0x13},
+ [SPECIES_SCEPTILE - 1] = {0x10, 0x04, 0x28, 0x0c, 0x12},
+ [SPECIES_TORCHIC - 1] = {0x17, 0x18, 0x30, 0x15, 0x25},
+ [SPECIES_COMBUSKEN - 1] = {0x20, 0x12, 0x28, 0x1e, 0x20},
+ [SPECIES_BLAZIKEN - 1] = {0x1a, 0x07, 0x28, 0x1d, 0x13},
+ [SPECIES_MUDKIP - 1] = {0x1b, 0x1d, 0x28, 0x19, 0x2c},
+ [SPECIES_MARSHTOMP - 1] = {0x1d, 0x11, 0x30, 0x1c, 0x20},
+ [SPECIES_SWAMPERT - 1] = {0x1b, 0x11, 0x28, 0x1b, 0x23},
+ [SPECIES_POOCHYENA - 1] = {0x14, 0x12, 0x30, 0x0f, 0x20},
+ [SPECIES_MIGHTYENA - 1] = {0x09, 0x0d, 0x28, 0x09, 0x1c},
+ [SPECIES_ZIGZAGOON - 1] = {0x0b, 0x1a, 0x30, 0x09, 0x2b},
+ [SPECIES_LINOONE - 1] = {0x0d, 0x28, 0x18, 0x0b, 0x37},
+ [SPECIES_WURMPLE - 1] = {0x21, 0x17, 0x30, 0x1f, 0x26},
+ [SPECIES_SILCOON - 1] = {0x13, 0x1c, 0x30, 0x11, 0x2a},
+ [SPECIES_BEAUTIFLY - 1] = {0x0f, 0x1b, 0x08, 0x0e, 0x28},
+ [SPECIES_CASCOON - 1] = {0x14, 0x1d, 0x30, 0x11, 0x2c},
+ [SPECIES_DUSTOX - 1] = {0x14, 0x19, 0x08, 0x16, 0x26},
+ [SPECIES_LOTAD - 1] = {0x19, 0x25, 0x28, 0x17, 0x32},
+ [SPECIES_LOMBRE - 1] = {0x22, 0x10, 0x30, 0x29, 0x1d},
+ [SPECIES_LUDICOLO - 1] = {0x1c, 0x0f, 0x28, 0x1b, 0x24},
+ [SPECIES_SEEDOT - 1] = {0x1b, 0x17, 0x30, 0x18, 0x28},
+ [SPECIES_NUZLEAF - 1] = {0x20, 0x0d, 0x30, 0x1a, 0x1d},
+ [SPECIES_SHIFTRY - 1] = {0x32, 0x11, 0x28, 0x2e, 0x23},
+ [SPECIES_NINCADA - 1] = {0x18, 0x1a, 0x30, 0x17, 0x28},
+ [SPECIES_NINJASK - 1] = {0x17, 0x21, 0x00, 0x17, 0x2f},
+ [SPECIES_SHEDINJA - 1] = {0x16, 0x19, 0x08, 0x18, 0x2a},
+ [SPECIES_TAILLOW - 1] = {0x17, 0x10, 0x30, 0x14, 0x1e},
+ [SPECIES_SWELLOW - 1] = {0x0c, 0x0a, 0x28, 0x05, 0x16},
+ [SPECIES_SHROOMISH - 1] = {0x1f, 0x16, 0x30, 0x1d, 0x23},
+ [SPECIES_BRELOOM - 1] = {0x25, 0x0c, 0x30, 0x23, 0x19},
+ [SPECIES_SPINDA - 1] = {0x21, 0x16, 0x30, 0x1f, 0x27},
+ [SPECIES_WINGULL - 1] = {0x1a, 0x16, 0x10, 0x15, 0x26},
+ [SPECIES_PELIPPER - 1] = {0x1d, 0x0a, 0x10, 0x09, 0x1b},
+ [SPECIES_SURSKIT - 1] = {0x1d, 0x16, 0x30, 0x1c, 0x25},
+ [SPECIES_MASQUERAIN - 1] = {0x1a, 0x21, 0x08, 0x14, 0x30},
+ [SPECIES_WAILMER - 1] = {0x17, 0x17, 0x30, 0x16, 0x28},
+ [SPECIES_WAILORD - 1] = {0x17, 0x03, 0x30, 0x09, 0x13},
+ [SPECIES_SKITTY - 1] = {0x24, 0x1a, 0x30, 0x22, 0x2a},
+ [SPECIES_DELCATTY - 1] = {0x1e, 0x12, 0x30, 0x1c, 0x21},
+ [SPECIES_KECLEON - 1] = {0x19, 0x10, 0x30, 0x13, 0x1e},
+ [SPECIES_BALTOY - 1] = {0x1d, 0x15, 0x30, 0x1b, 0x22},
+ [SPECIES_CLAYDOL - 1] = {0x1e, 0x0d, 0x28, 0x1d, 0x24},
+ [SPECIES_NOSEPASS - 1] = {0x1f, 0x10, 0x30, 0x15, 0x23},
+ [SPECIES_TORKOAL - 1] = {0x0e, 0x19, 0x28, 0x0a, 0x27},
+ [SPECIES_SABLEYE - 1] = {0x1e, 0x16, 0x30, 0x1d, 0x27},
+ [SPECIES_BARBOACH - 1] = {0x17, 0x12, 0x30, 0x15, 0x1e},
+ [SPECIES_WHISCASH - 1] = {0x18, 0x20, 0x28, 0x17, 0x31},
+ [SPECIES_LUVDISC - 1] = {0x19, 0x0f, 0x30, 0x13, 0x1c},
+ [SPECIES_CORPHISH - 1] = {0x1f, 0x14, 0x30, 0x1d, 0x23},
+ [SPECIES_CRAWDAUNT - 1] = {0x14, 0x0c, 0x28, 0x18, 0x23},
+ [SPECIES_FEEBAS - 1] = {0x18, 0x1e, 0x28, 0x16, 0x2f},
+ [SPECIES_MILOTIC - 1] = {0x20, 0x0c, 0x28, 0x1f, 0x1d},
+ [SPECIES_CARVANHA - 1] = {0x16, 0x19, 0x30, 0x13, 0x22},
+ [SPECIES_SHARPEDO - 1] = {0x19, 0x0c, 0x28, 0x17, 0x27},
+ [SPECIES_TRAPINCH - 1] = {0x29, 0x13, 0x30, 0x17, 0x18},
+ [SPECIES_VIBRAVA - 1] = {0x10, 0x27, 0x20, 0x0e, 0x34},
+ [SPECIES_FLYGON - 1] = {0x22, 0x07, 0x10, 0x21, 0x13},
+ [SPECIES_MAKUHITA - 1] = {0x22, 0x13, 0x30, 0x1c, 0x23},
+ [SPECIES_HARIYAMA - 1] = {0x24, 0x0f, 0x28, 0x26, 0x1c},
+ [SPECIES_ELECTRIKE - 1] = {0x11, 0x18, 0x30, 0x14, 0x27},
+ [SPECIES_MANECTRIC - 1] = {0x2f, 0x18, 0x28, 0x2e, 0x29},
+ [SPECIES_NUMEL - 1] = {0x10, 0x1a, 0x30, 0x0d, 0x2a},
+ [SPECIES_CAMERUPT - 1] = {0x0d, 0x22, 0x28, 0x0e, 0x36},
+ [SPECIES_SPHEAL - 1] = {0x1e, 0x0f, 0x30, 0x18, 0x1f},
+ [SPECIES_SEALEO - 1] = {0x1c, 0x09, 0x30, 0x1a, 0x18},
+ [SPECIES_WALREIN - 1] = {0x19, 0x01, 0x28, 0x10, 0x16},
+ [SPECIES_CACNEA - 1] = {0x1f, 0x17, 0x30, 0x1d, 0x29},
+ [SPECIES_CACTURNE - 1] = {0x1d, 0x0e, 0x28, 0x1d, 0x1b},
+ [SPECIES_SNORUNT - 1] = {0x1e, 0x16, 0x30, 0x1e, 0x26},
+ [SPECIES_GLALIE - 1] = {0x1a, 0x1c, 0x08, 0x1a, 0x31},
+ [SPECIES_LUNATONE - 1] = {0x1c, 0x16, 0x08, 0x19, 0x2c},
+ [SPECIES_SOLROCK - 1] = {0x18, 0x18, 0x10, 0x17, 0x31},
+ [SPECIES_AZURILL - 1] = {0x1b, 0x10, 0x30, 0x18, 0x1f},
+ [SPECIES_SPOINK - 1] = {0x21, 0x14, 0x30, 0x1b, 0x28},
+ [SPECIES_GRUMPIG - 1] = {0x14, 0x10, 0x30, 0x15, 0x20},
+ [SPECIES_PLUSLE - 1] = {0x1c, 0x16, 0x08, 0x1d, 0x25},
+ [SPECIES_MINUN - 1] = {0x21, 0x16, 0x08, 0x1f, 0x26},
+ [SPECIES_MAWILE - 1] = {0x2d, 0x14, 0x30, 0x2f, 0x24},
+ [SPECIES_MEDITITE - 1] = {0x1f, 0x17, 0x30, 0x1e, 0x25},
+ [SPECIES_MEDICHAM - 1] = {0x21, 0x0f, 0x28, 0x1e, 0x1d},
+ [SPECIES_SWABLU - 1] = {0x1b, 0x16, 0x10, 0x17, 0x23},
+ [SPECIES_ALTARIA - 1] = {0x1d, 0x0b, 0x10, 0x1a, 0x1a},
+ [SPECIES_WYNAUT - 1] = {0x1a, 0x15, 0x30, 0x1b, 0x26},
+ [SPECIES_DUSKULL - 1] = {0x10, 0x18, 0x08, 0x14, 0x2e},
+ [SPECIES_DUSCLOPS - 1] = {0x1c, 0x0f, 0x30, 0x1a, 0x28},
+ [SPECIES_ROSELIA - 1] = {0x1e, 0x11, 0x30, 0x1d, 0x20},
+ [SPECIES_SLAKOTH - 1] = {0x19, 0x1e, 0x30, 0x18, 0x2f},
+ [SPECIES_VIGOROTH - 1] = {0x10, 0x12, 0x28, 0x14, 0x24},
+ [SPECIES_SLAKING - 1] = {0x37, 0x0f, 0x30, 0x29, 0x21},
+ [SPECIES_GULPIN - 1] = {0x1b, 0x18, 0x30, 0x17, 0x26},
+ [SPECIES_SWALOT - 1] = {0x1f, 0x06, 0x30, 0x15, 0x13},
+ [SPECIES_TROPIUS - 1] = {0x18, 0x0a, 0x28, 0x20, 0x18},
+ [SPECIES_WHISMUR - 1] = {0x1f, 0x19, 0x30, 0x1d, 0x29},
+ [SPECIES_LOUDRED - 1] = {0x1c, 0x12, 0x28, 0x22, 0x27},
+ [SPECIES_EXPLOUD - 1] = {0x10, 0x10, 0x28, 0x1a, 0x2a},
+ [SPECIES_CLAMPERL - 1] = {0x20, 0x1a, 0x30, 0x1e, 0x26},
+ [SPECIES_HUNTAIL - 1] = {0x13, 0x1e, 0x28, 0x15, 0x33},
+ [SPECIES_GOREBYSS - 1] = {0x0d, 0x1f, 0x28, 0x03, 0x32},
+ [SPECIES_ABSOL - 1] = {0x2a, 0x11, 0x28, 0x2a, 0x22},
+ [SPECIES_SHUPPET - 1] = {0x16, 0x19, 0x08, 0x17, 0x27},
+ [SPECIES_BANETTE - 1] = {0x1c, 0x14, 0x08, 0x1b, 0x23},
+ [SPECIES_SEVIPER - 1] = {0x0e, 0x0d, 0x30, 0x0b, 0x1e},
+ [SPECIES_ZANGOOSE - 1] = {0x18, 0x0c, 0x28, 0x15, 0x1a},
+ [SPECIES_RELICANTH - 1] = {0x0c, 0x1f, 0x30, 0x09, 0x2d},
+ [SPECIES_ARON - 1] = {0x18, 0x1c, 0x30, 0x1a, 0x2c},
+ [SPECIES_LAIRON - 1] = {0x0b, 0x21, 0x30, 0x12, 0x2f},
+ [SPECIES_AGGRON - 1] = {0x10, 0x0b, 0x28, 0x16, 0x1b},
+ [SPECIES_CASTFORM - 1] = {0x1d, 0x18, 0x08, 0x1b, 0x26},
+ [SPECIES_VOLBEAT - 1] = {0x25, 0x15, 0x08, 0x21, 0x25},
+ [SPECIES_ILLUMISE - 1] = {0x20, 0x12, 0x08, 0x1f, 0x20},
+ [SPECIES_LILEEP - 1] = {0x1e, 0x11, 0x30, 0x1f, 0x1e},
+ [SPECIES_CRADILY - 1] = {0x12, 0x16, 0x28, 0x15, 0x28},
+ [SPECIES_ANORITH - 1] = {0x1c, 0x1e, 0x30, 0x1b, 0x2b},
+ [SPECIES_ARMALDO - 1] = {0x15, 0x05, 0x28, 0x14, 0x13},
+ [SPECIES_RALTS - 1] = {0x1f, 0x17, 0x30, 0x20, 0x23},
+ [SPECIES_KIRLIA - 1] = {0x1c, 0x12, 0x30, 0x1f, 0x1e},
+ [SPECIES_GARDEVOIR - 1] = {0x35, 0x07, 0x28, 0x32, 0x14},
+ [SPECIES_BAGON - 1] = {0x17, 0x13, 0x30, 0x16, 0x26},
+ [SPECIES_SHELGON - 1] = {0x19, 0x1b, 0x30, 0x19, 0x2c},
+ [SPECIES_SALAMENCE - 1] = {0x09, 0x11, 0x30, 0x0a, 0x21},
+ [SPECIES_BELDUM - 1] = {0x16, 0x19, 0x08, 0x18, 0x23},
+ [SPECIES_METANG - 1] = {0x22, 0x0f, 0x10, 0x1f, 0x21},
+ [SPECIES_METAGROSS - 1] = {0x24, 0x1b, 0x28, 0x22, 0x2b},
+ [SPECIES_REGIROCK - 1] = {0x16, 0x07, 0x28, 0x14, 0x12},
+ [SPECIES_REGICE - 1] = {0x19, 0x0c, 0x28, 0x17, 0x19},
+ [SPECIES_REGISTEEL - 1] = {0x19, 0x0d, 0x28, 0x19, 0x19},
+ [SPECIES_KYOGRE - 1] = {0x0e, 0x19, 0x28, 0x0b, 0x26},
+ [SPECIES_GROUDON - 1] = {0x04, 0x0b, 0x28, 0x0a, 0x19},
+ [SPECIES_RAYQUAZA - 1] = {0x0c, 0x0e, 0x10, 0x0e, 0x1f},
+ [SPECIES_LATIAS - 1] = {0x1e, 0x0c, 0x10, 0x23, 0x19},
+ [SPECIES_LATIOS - 1] = {0x05, 0x0e, 0x10, 0x05, 0x1d},
+ [SPECIES_JIRACHI - 1] = {0x1c, 0x15, 0x08, 0x1e, 0x22},
+ [SPECIES_DEOXYS - 1] = {0x1b, 0x08, 0x28, 0x1c, 0x16},
+ [SPECIES_CHIMECHO - 1] = {0x1d, 0x0c, 0x08, 0x1c, 0x1a},
+ [SPECIES_OLD_UNOWN_EMARK - 1] = {0x20, 0x21, 0x08, 0x20, 0x2b},
+ [SPECIES_OLD_UNOWN_QMARK - 1] = {0x20, 0x23, 0x08, 0x20, 0x2d}
+};
+
+void AddTextPrinterParameterized3(u8 windowId, u8 fontId, u8 x, u8 y, const struct TextColor * color, s8 speed, const u8 * str)
+{
+ struct TextPrinterTemplate printer;
+
+ printer.currentChar = str;
+ printer.windowId = windowId;
+ printer.fontId = fontId;
+ printer.x = x;
+ printer.y = y;
+ printer.currentX = printer.x;
+ printer.currentY = printer.y;
+ printer.letterSpacing = GetFontAttribute(fontId, 2);
+ printer.lineSpacing = GetFontAttribute(fontId, 3);
+ printer.unk = 0;
+ printer.fgColor = color->bgColor;
+ printer.bgColor = color->fgColor;
+ printer.shadowColor = color->shadowColor;
+ AddTextPrinter(&printer, speed, NULL);
+}
+
+void AddTextPrinterParameterized4(u8 windowId, u8 fontId, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, const struct TextColor *color, s8 speed, const u8 *str)
+{
+ struct TextPrinterTemplate printer;
+
+ printer.currentChar = str;
+ printer.windowId = windowId;
+ printer.fontId = fontId;
+ printer.x = x;
+ printer.y = y;
+ printer.currentX = printer.x;
+ printer.currentY = printer.y;
+ printer.letterSpacing = letterSpacing;
+ printer.lineSpacing = lineSpacing;
+ printer.unk = 0;
+ printer.fgColor = color->bgColor;
+ printer.bgColor = color->fgColor;
+ printer.shadowColor = color->shadowColor;
+ AddTextPrinter(&printer, speed, NULL);
+}
+
+void AddTextPrinterParameterized5(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16), u8 letterSpacing, u8 lineSpacing)
+{
+ struct TextPrinterTemplate printer;
+
+ printer.currentChar = str;
+ printer.windowId = windowId;
+ printer.fontId = fontId;
+ printer.x = x;
+ printer.y = y;
+ printer.currentX = x;
+ printer.currentY = y;
+ printer.letterSpacing = letterSpacing;
+ printer.lineSpacing = lineSpacing;
+ printer.unk = 0;
+ printer.fgColor = GetFontAttribute(fontId, 5);
+ printer.bgColor = GetFontAttribute(fontId, 6);
+ printer.shadowColor = GetFontAttribute(fontId, 7);
+ AddTextPrinter(&printer, speed, callback);
+}
+
+void sub_812E6DC(u8 windowId, const u8 * src, u16 x, u16 y)
+{
+ s32 i;
+
+ for (i = 0; gSaveBlock2Ptr->playerName[i] != EOS; i++)
+ ;
+
+ StringExpandPlaceholders(gStringVar4, src);
+ if (i != 5)
+ {
+ AddTextPrinterParameterized(windowId, 2, gStringVar4, x, y, 0xFF, NULL);
+ }
+ else
+ {
+ AddTextPrinterParameterized5(windowId, 2, gStringVar4, x, y, 0xFF, NULL, 0, 0);
+ }
+}
+
+// Yeah, no, I'm not bothering with this
+NAKED
+void sub_819A080(void * a0, void * a1, u16 a2, u16 a3, u16 a4, u16 a5, u16 a6, u16 a7)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmov r7, r10\n"
+ "\tmov r6, r9\n"
+ "\tmov r5, r8\n"
+ "\tpush {r5-r7}\n"
+ "\tsub sp, 0x28\n"
+ "\tstr r0, [sp]\n"
+ "\tstr r1, [sp, 0x4]\n"
+ "\tldr r0, [sp, 0x48]\n"
+ "\tldr r4, [sp, 0x4C]\n"
+ "\tldr r1, [sp, 0x50]\n"
+ "\tldr r5, [sp, 0x54]\n"
+ "\tlsls r2, 16\n"
+ "\tlsrs r2, 16\n"
+ "\tstr r2, [sp, 0x8]\n"
+ "\tlsls r3, 16\n"
+ "\tlsrs r3, 16\n"
+ "\tlsls r0, 16\n"
+ "\tlsrs r0, 16\n"
+ "\tstr r0, [sp, 0xC]\n"
+ "\tlsls r4, 16\n"
+ "\tlsrs r4, 16\n"
+ "\tlsls r1, 16\n"
+ "\tlsrs r1, 16\n"
+ "\tlsls r5, 16\n"
+ "\tlsrs r5, 16\n"
+ "\tldr r2, [sp, 0x4]\n"
+ "\tldrh r0, [r2, 0x4]\n"
+ "\tldr r2, [sp, 0xC]\n"
+ "\tsubs r0, r2\n"
+ "\tldr r2, [sp, 0x8]\n"
+ "\tadds r2, r1, r2\n"
+ "\tstr r2, [sp, 0x10]\n"
+ "\tcmp r0, r1\n"
+ "\tbge _0812E7B4\n"
+ "\tldr r1, [sp, 0x8]\n"
+ "\tadds r0, r1\n"
+ "\tstr r0, [sp, 0x10]\n"
+ "_0812E7B4:\n"
+ "\tldr r2, [sp, 0x4]\n"
+ "\tldrh r1, [r2, 0x6]\n"
+ "\tsubs r0, r1, r4\n"
+ "\tcmp r0, r5\n"
+ "\tbge _0812E7C6\n"
+ "\tadds r0, r3, r1\n"
+ "\tsubs r0, r4\n"
+ "\tstr r0, [sp, 0x14]\n"
+ "\tb _0812E7CA\n"
+ "_0812E7C6:\n"
+ "\tadds r5, r3, r5\n"
+ "\tstr r5, [sp, 0x14]\n"
+ "_0812E7CA:\n"
+ "\tldr r0, [sp]\n"
+ "\tldrh r1, [r0, 0x4]\n"
+ "\tmovs r2, 0x7\n"
+ "\tadds r0, r1, 0\n"
+ "\tands r0, r2\n"
+ "\tadds r1, r0\n"
+ "\tasrs r1, 3\n"
+ "\tstr r1, [sp, 0x18]\n"
+ "\tldr r0, [sp, 0x4]\n"
+ "\tldrh r1, [r0, 0x4]\n"
+ "\tadds r0, r1, 0\n"
+ "\tands r0, r2\n"
+ "\tadds r1, r0\n"
+ "\tasrs r1, 3\n"
+ "\tstr r1, [sp, 0x1C]\n"
+ "\tmov r12, r3\n"
+ "\tmov r8, r4\n"
+ "\tldr r1, [sp, 0x14]\n"
+ "\tcmp r12, r1\n"
+ "\tblt _0812E7F4\n"
+ "\tb _0812E932\n"
+ "_0812E7F4:\n"
+ "\tldr r5, [sp, 0x8]\n"
+ "\tldr r6, [sp, 0xC]\n"
+ "\tmov r2, r12\n"
+ "\tadds r2, 0x1\n"
+ "\tstr r2, [sp, 0x20]\n"
+ "\tmov r0, r8\n"
+ "\tadds r0, 0x1\n"
+ "\tstr r0, [sp, 0x24]\n"
+ "\tldr r1, [sp, 0x10]\n"
+ "\tcmp r5, r1\n"
+ "\tblt _0812E80C\n"
+ "\tb _0812E922\n"
+ "_0812E80C:\n"
+ "\tmovs r7, 0x1\n"
+ "\tmovs r2, 0xF0\n"
+ "\tmov r10, r2\n"
+ "\tmovs r0, 0xF\n"
+ "\tmov r9, r0\n"
+ "_0812E816:\n"
+ "\tasrs r0, r5, 1\n"
+ "\tmovs r1, 0x3\n"
+ "\tands r0, r1\n"
+ "\tldr r2, [sp]\n"
+ "\tldr r1, [r2]\n"
+ "\tadds r1, r0\n"
+ "\tasrs r0, r5, 3\n"
+ "\tlsls r0, 5\n"
+ "\tadds r1, r0\n"
+ "\tmov r2, r12\n"
+ "\tasrs r0, r2, 3\n"
+ "\tldr r2, [sp, 0x18]\n"
+ "\tmuls r0, r2\n"
+ "\tlsls r0, 5\n"
+ "\tadds r1, r0\n"
+ "\tmov r2, r12\n"
+ "\tlsls r0, r2, 29\n"
+ "\tlsrs r0, 27\n"
+ "\tadds r3, r1, r0\n"
+ "\tasrs r0, r6, 1\n"
+ "\tmovs r1, 0x3\n"
+ "\tands r0, r1\n"
+ "\tldr r2, [sp, 0x4]\n"
+ "\tldr r1, [r2]\n"
+ "\tadds r1, r0\n"
+ "\tasrs r0, r6, 3\n"
+ "\tlsls r0, 5\n"
+ "\tadds r1, r0\n"
+ "\tmov r2, r8\n"
+ "\tasrs r0, r2, 3\n"
+ "\tldr r2, [sp, 0x1C]\n"
+ "\tmuls r0, r2\n"
+ "\tlsls r0, 5\n"
+ "\tadds r1, r0\n"
+ "\tmov r2, r8\n"
+ "\tlsls r0, r2, 29\n"
+ "\tlsrs r0, 27\n"
+ "\tadds r4, r1, r0\n"
+ "\tadds r0, r4, 0\n"
+ "\tands r0, r7\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0812E8C2\n"
+ "\tsubs r4, 0x1\n"
+ "\tadds r0, r6, 0\n"
+ "\tands r0, r7\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0812E89A\n"
+ "\tldrh r0, [r4]\n"
+ "\tldr r2, _0812E88C @ =0x00000fff\n"
+ "\tands r2, r0\n"
+ "\tadds r0, r5, 0\n"
+ "\tands r0, r7\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0812E890\n"
+ "\tldrb r1, [r3]\n"
+ "\tmov r0, r10\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 8\n"
+ "\tb _0812E912\n"
+ "\t.align 2, 0\n"
+ "_0812E88C: .4byte 0x00000fff\n"
+ "_0812E890:\n"
+ "\tldrb r1, [r3]\n"
+ "\tmov r0, r9\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 12\n"
+ "\tb _0812E912\n"
+ "_0812E89A:\n"
+ "\tldrh r0, [r4]\n"
+ "\tldr r2, _0812E8B4 @ =0x0000f0ff\n"
+ "\tands r2, r0\n"
+ "\tadds r0, r5, 0\n"
+ "\tands r0, r7\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0812E8B8\n"
+ "\tldrb r1, [r3]\n"
+ "\tmov r0, r10\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 4\n"
+ "\tb _0812E912\n"
+ "\t.align 2, 0\n"
+ "_0812E8B4: .4byte 0x0000f0ff\n"
+ "_0812E8B8:\n"
+ "\tldrb r1, [r3]\n"
+ "\tmov r0, r9\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 8\n"
+ "\tb _0812E912\n"
+ "_0812E8C2:\n"
+ "\tadds r0, r6, 0\n"
+ "\tands r0, r7\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0812E8EE\n"
+ "\tldrh r0, [r4]\n"
+ "\tldr r2, _0812E8E0 @ =0x0000ff0f\n"
+ "\tands r2, r0\n"
+ "\tadds r0, r5, 0\n"
+ "\tands r0, r7\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0812E8E4\n"
+ "\tldrb r1, [r3]\n"
+ "\tmov r0, r10\n"
+ "\tb _0812E910\n"
+ "\t.align 2, 0\n"
+ "_0812E8E0: .4byte 0x0000ff0f\n"
+ "_0812E8E4:\n"
+ "\tldrb r1, [r3]\n"
+ "\tmov r0, r9\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 4\n"
+ "\tb _0812E912\n"
+ "_0812E8EE:\n"
+ "\tldrh r0, [r4]\n"
+ "\tldr r2, _0812E908 @ =0x0000fff0\n"
+ "\tands r2, r0\n"
+ "\tadds r0, r5, 0\n"
+ "\tands r0, r7\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0812E90C\n"
+ "\tldrb r1, [r3]\n"
+ "\tmov r0, r10\n"
+ "\tands r0, r1\n"
+ "\tlsrs r0, 4\n"
+ "\tb _0812E912\n"
+ "\t.align 2, 0\n"
+ "_0812E908: .4byte 0x0000fff0\n"
+ "_0812E90C:\n"
+ "\tldrb r1, [r3]\n"
+ "\tmov r0, r9\n"
+ "_0812E910:\n"
+ "\tands r0, r1\n"
+ "_0812E912:\n"
+ "\torrs r2, r0\n"
+ "\tstrh r2, [r4]\n"
+ "\tadds r5, 0x1\n"
+ "\tadds r6, 0x1\n"
+ "\tldr r0, [sp, 0x10]\n"
+ "\tcmp r5, r0\n"
+ "\tbge _0812E922\n"
+ "\tb _0812E816\n"
+ "_0812E922:\n"
+ "\tldr r1, [sp, 0x20]\n"
+ "\tmov r12, r1\n"
+ "\tldr r2, [sp, 0x24]\n"
+ "\tmov r8, r2\n"
+ "\tldr r0, [sp, 0x14]\n"
+ "\tcmp r12, r0\n"
+ "\tbge _0812E932\n"
+ "\tb _0812E7F4\n"
+ "_0812E932:\n"
+ "\tadd sp, 0x28\n"
+ "\tpop {r3-r5}\n"
+ "\tmov r8, r3\n"
+ "\tmov r9, r4\n"
+ "\tmov r10, r5\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r0}\n"
+ "\tbx r0");
+}
+
+#define tEvA data[0]
+#define tEvB data[1]
+#define tEvAEnd data[2]
+#define tEvBEnd data[3]
+#define tEvADelta data[4]
+#define tEvBDelta data[5]
+#define tEvWhich data[6]
+#define tEvStepCount data[8]
+
+void StartBlendTask(u8 eva_start, u8 evb_start, u8 eva_end, u8 evb_end, u8 ev_step, u8 priority)
+{
+ u8 taskId = CreateTask(Task_SmoothBlendLayers, priority);
+ gTasks[taskId].tEvA = eva_start << 8;
+ gTasks[taskId].tEvB = evb_start << 8;
+ gTasks[taskId].tEvAEnd = eva_end;
+ gTasks[taskId].tEvBEnd = evb_end;
+ gTasks[taskId].tEvADelta = (eva_end - eva_start) * 256 / ev_step;
+ gTasks[taskId].tEvBDelta = (evb_end - evb_start) * 256 / ev_step;
+ gTasks[taskId].tEvStepCount = ev_step;
+ SetGpuReg(REG_OFFSET_BLDALPHA, (evb_start << 8) | eva_start);
+}
+
+bool8 IsBlendTaskActive(void)
+{
+ return FuncIsActiveTask(Task_SmoothBlendLayers);
+}
+
+static void Task_SmoothBlendLayers(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (tEvStepCount != 0)
+ {
+ if (tEvWhich == 0)
+ {
+ tEvA += tEvADelta;
+ tEvWhich = 1;
+ }
+ else
+ {
+ if (--tEvStepCount != 0)
+ {
+ tEvB += tEvBDelta;
+ }
+ else
+ {
+ tEvA = tEvAEnd << 8;
+ tEvB = tEvBEnd << 8;
+ }
+ tEvWhich = 0;
+ }
+ SetGpuReg(REG_OFFSET_BLDALPHA, (tEvB & ~0xFF) | ((u16)tEvA >> 8));
+ if (tEvStepCount == 0)
+ DestroyTask(taskId);
+ }
+}
+
+u8 sub_812EA78(u16 species, u32 personality, u8 a2)
+{
+ if (species == SPECIES_UNOWN)
+ {
+ u8 unownLetter = GetUnownLetterByPersonality(personality);
+ switch (unownLetter)
+ {
+ case 0:
+ break;
+ case 26:
+ species = SPECIES_OLD_UNOWN_EMARK;
+ break;
+ case 27:
+ species = SPECIES_OLD_UNOWN_QMARK;
+ break;
+ default:
+ species = SPECIES_OLD_UNOWN_B + unownLetter - 1;
+ break;
+ }
+ }
+ if (species != SPECIES_NONE && a2 < 5)
+ {
+ species--;
+ if (gUnknown_845FD54[species][a2] != 0xFF)
+ return gUnknown_845FD54[species][a2];
+ }
+ return 32;
+}
+
+s8 sub_812EAE4(u16 species, u32 personality, u8 a2)
+{
+ return sub_812EA78(species, personality, a2) - 32;
+}
diff --git a/src/mevent.c b/src/mevent.c
index a62286f21..fc0c1f2d4 100644
--- a/src/mevent.c
+++ b/src/mevent.c
@@ -28,7 +28,7 @@ struct MEventTaskData1
u16 t02;
u16 t04;
u16 t06;
- u8 t08;
+ u8 state;
u8 t09;
u8 t0A;
u8 t0B;
@@ -91,46 +91,46 @@ struct MEvent_Str_1 gUnknown_3005ED0;
static EWRAM_DATA bool32 gUnknown_203F3BC = FALSE;
-void sub_81435DC(struct MEvent_Str_1 *a0, size_t a1, const void * a2)
+void sub_81435DC(struct MEvent_Str_1 *mgr, size_t size, const void * data)
{
vu16 imeBak = REG_IME;
REG_IME = 0;
- gIntrTable[1] = sub_815C6D4;
- gIntrTable[2] = sub_815C6C4;
- sub_815C8C8();
- sub_815C960();
+ gIntrTable[1] = EReaderHelper_SerialCallback;
+ gIntrTable[2] = EReaderHelper_Timer3Callback;
+ EReaderHelper_SaveRegsState();
+ EReaderHelper_ClearsSendRecvMgr();
REG_IE |= INTR_FLAG_VCOUNT;
REG_IME = imeBak;
- a0->unk_000 = 0;
- a0->unk_004 = a1;
- a0->unk_008 = a2;
+ mgr->status = 0;
+ mgr->size = size;
+ mgr->data = data;
}
void sub_8143644(struct MEvent_Str_1 *unused)
{
vu16 imeBak = REG_IME;
REG_IME = 0;
- sub_815C960();
- sub_815C91C();
+ EReaderHelper_ClearsSendRecvMgr();
+ EReaderHelper_RestoreRegsState();
RestoreSerialTimer3IntrHandlers();
REG_IME = imeBak;
}
-u8 sub_8143674(struct MEvent_Str_1 *a0)
+u8 sub_8143674(struct MEvent_Str_1 *mgr)
{
u8 resp = 0;
- a0->unk_000 = sub_815C498(1, a0->unk_004, a0->unk_008, 0);
- if ((a0->unk_000 & 0x13) == 0x10)
+ mgr->status = EReaderHandleTransfer(1, mgr->size, mgr->data, 0);
+ if ((mgr->status & 0x13) == 0x10)
resp = 1;
- if (a0->unk_000 & 8)
+ if (mgr->status & 8)
resp = 2;
- if (a0->unk_000 & 4)
+ if (mgr->status & 4)
resp = 3;
gUnknown_3003F84 = 0;
return resp;
}
-void sub_81436BC(void)
+static void ResetTTDataBuffer(void)
{
memset(gDecompressionBuffer, 0, 0x2000);
gLinkType = 0x5502;
@@ -143,7 +143,7 @@ bool32 sub_81436EC(void)
vu16 imeBak = REG_IME;
u16 data[4];
REG_IME = 0;
- *(u64 *)data = gUnknown_3003FB4;
+ *(u64 *)data = gSioMlt_Recv;
REG_IME = imeBak;
if ( data[0] == 0xB9A0
&& data[1] == 0xCCD0
@@ -154,7 +154,7 @@ bool32 sub_81436EC(void)
return FALSE;
}
-bool32 sub_814374C(void)
+static bool32 IsEReaderConnectionSane(void)
{
if (sub_800AA48() && GetLinkPlayerCount_2() == 2)
return TRUE;
@@ -240,11 +240,11 @@ u32 sub_8143770(u8 * r4, u16 * r5)
return 0;
}
-void sub_81438A0(void)
+void task_add_00_ereader(void)
{
u8 taskId = CreateTask(sub_8143910, 0);
struct MEventTaskData1 *data = (struct MEventTaskData1 *)gTasks[taskId].data;
- data->t08 = 0;
+ data->state = 0;
data->t09 = 0;
data->t0A = 0;
data->t0B = 0;
@@ -258,12 +258,12 @@ void sub_81438A0(void)
data->t10 = AllocZeroed(sizeof(struct MEvent_Str_2));
}
-void sub_81438E8(u16 *a0)
+static void ResetDelayTimer(u16 *a0)
{
*a0 = 0;
}
-bool32 sub_81438F0(u16 * a0, u16 a1)
+static bool32 AdvanceDelayTimerCheckTimeout(u16 * a0, u16 a1)
{
if (++(*a0) > a1)
{
@@ -276,114 +276,114 @@ bool32 sub_81438F0(u16 * a0, u16 a1)
void sub_8143910(u8 taskId)
{
struct MEventTaskData1 *data = (struct MEventTaskData1 *)gTasks[taskId].data;
- switch (data->t08)
+ switch (data->state)
{
case 0:
- if (mevent_0814257C(&data->t09, gUnknown_841DE52))
- data->t08 = 1;
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE52))
+ data->state = 1;
break;
case 1:
- sub_81436BC();
- sub_81438E8(&data->t00);
- data->t08 = 2;
+ ResetTTDataBuffer();
+ ResetDelayTimer(&data->t00);
+ data->state = 2;
break;
case 2:
- if (sub_81438F0(&data->t00, 10))
- data->t08 = 3;
+ if (AdvanceDelayTimerCheckTimeout(&data->t00, 10))
+ data->state = 3;
break;
case 3:
- if (!sub_814374C())
+ if (!IsEReaderConnectionSane())
{
- sub_80098B8();
- data->t08 = 4;
+ CloseLink();
+ data->state = 4;
}
else
- data->t08 = 13;
+ data->state = 13;
break;
case 4:
- if (mevent_0814257C(&data->t09, gUnknown_841DE53))
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE53))
{
- sub_8142504(gUnknown_841DE54);
- sub_81438E8(&data->t00);
- data->t08 = 5;
+ AddTextPrinterToWindow1(gUnknown_841DE54);
+ ResetDelayTimer(&data->t00);
+ data->state = 5;
}
break;
case 5:
- if (sub_81438F0(&data->t00, 90))
+ if (AdvanceDelayTimerCheckTimeout(&data->t00, 90))
{
- sub_81436BC();
- data->t08 = 6;
+ ResetTTDataBuffer();
+ data->state = 6;
}
else if (JOY_NEW(B_BUTTON))
{
- sub_81438E8(&data->t00);
+ ResetDelayTimer(&data->t00);
PlaySE(SE_SELECT);
- data->t08 = 23;
+ data->state = 23;
}
break;
case 6:
if (JOY_NEW(B_BUTTON))
{
PlaySE(SE_SELECT);
- sub_80098B8();
- sub_81438E8(&data->t00);
- data->t08 = 23;
+ CloseLink();
+ ResetDelayTimer(&data->t00);
+ data->state = 23;
}
else if (GetLinkPlayerCount_2() > 1)
{
- sub_81438E8(&data->t00);
- sub_80098B8();
- data->t08 = 7;
+ ResetDelayTimer(&data->t00);
+ CloseLink();
+ data->state = 7;
}
else if (sub_81436EC())
{
PlaySE(SE_SELECT);
- sub_80098B8();
- sub_81438E8(&data->t00);
- data->t08 = 8;
+ CloseLink();
+ ResetDelayTimer(&data->t00);
+ data->state = 8;
}
- else if (sub_81438F0(&data->t00, 10))
+ else if (AdvanceDelayTimerCheckTimeout(&data->t00, 10))
{
- sub_80098B8();
- sub_81436BC();
- sub_81438E8(&data->t00);
+ CloseLink();
+ ResetTTDataBuffer();
+ ResetDelayTimer(&data->t00);
}
break;
case 7:
- if (mevent_0814257C(&data->t09, gUnknown_841DE7C))
- data->t08 = 4;
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE7C))
+ data->state = 4;
break;
case 8:
- sub_8142504(gUnknown_841DE95);
+ AddTextPrinterToWindow1(gUnknown_841DE95);
sub_81435DC(&gUnknown_3005ED0, gUnknownSerialData_End - gUnknownSerialData_Start, gUnknownSerialData_Start);
- data->t08 = 9;
+ data->state = 9;
break;
case 9:
data->t0E = sub_8143674(&gUnknown_3005ED0);
if (data->t0E != 0)
- data->t08 = 10;
+ data->state = 10;
break;
case 10:
sub_8143644(&gUnknown_3005ED0);
if (data->t0E == 3)
- data->t08 = 20;
+ data->state = 20;
else if (data->t0E == 1)
{
- sub_81438E8(&data->t00);
- sub_8142504(gUnknown_841DE9B);
- data->t08 = 11;
+ ResetDelayTimer(&data->t00);
+ AddTextPrinterToWindow1(gUnknown_841DE9B);
+ data->state = 11;
}
else
- data->t08 = 0;
+ data->state = 0;
break;
case 11:
- if (sub_81438F0(&data->t00, 840))
- data->t08 = 12;
+ if (AdvanceDelayTimerCheckTimeout(&data->t00, 840))
+ data->state = 12;
break;
case 12:
- sub_81436BC();
- sub_8142504(gUnknown_841DE98);
- data->t08 = 13;
+ ResetTTDataBuffer();
+ AddTextPrinterToWindow1(gUnknown_841DE98);
+ data->state = 13;
break;
case 13:
switch (sub_8143770(&data->t09, &data->t00))
@@ -391,94 +391,94 @@ void sub_8143910(u8 taskId)
case 0:
break;
case 2:
- sub_8142504(gUnknown_841DE95);
- data->t08 = 14;
+ AddTextPrinterToWindow1(gUnknown_841DE95);
+ data->state = 14;
break;
case 1:
PlaySE(SE_SELECT);
- sub_80098B8();
- data->t08 = 23;
+ CloseLink();
+ data->state = 23;
break;
case 5:
- sub_80098B8();
- data->t08 = 21;
+ CloseLink();
+ data->state = 21;
break;
case 3:
case 4:
- sub_80098B8();
- data->t08 = 20;
+ CloseLink();
+ data->state = 20;
break;
}
break;
case 14:
if (HasLinkErrorOccurred())
{
- sub_80098B8();
- data->t08 = 20;
+ CloseLink();
+ data->state = 20;
}
else if (GetBlockReceivedStatus())
{
ResetBlockReceivedFlags();
- data->t08 = 15;
+ data->state = 15;
}
break;
case 15:
- data->t0E = sub_815D6B4(gDecompressionBuffer);
+ data->t0E = ValidateTrainerTowerData((struct TrainerTowerData *)gDecompressionBuffer);
sub_800AA80(data->t0E);
- data->t08 = 16;
+ data->state = 16;
break;
case 16:
if (!gReceivedRemoteLinkPlayers)
{
if (data->t0E == 1)
- data->t08 = 17;
+ data->state = 17;
else
- data->t08 = 20;
+ data->state = 20;
}
break;
case 17:
- if (sub_815D794(gDecompressionBuffer))
+ if (CEReaderTool_SaveTrainerTower((struct TrainerTowerData *)gDecompressionBuffer))
{
- sub_8142504(gUnknown_841DE99);
- sub_81438E8(&data->t00);
- data->t08 = 18;
+ AddTextPrinterToWindow1(gUnknown_841DE99);
+ ResetDelayTimer(&data->t00);
+ data->state = 18;
}
else
- data->t08 = 22;
+ data->state = 22;
break;
case 18:
- if (sub_81438F0(&data->t00, 120))
+ if (AdvanceDelayTimerCheckTimeout(&data->t00, 120))
{
- sub_8142504(gUnknown_841DE9A);
+ AddTextPrinterToWindow1(gUnknown_841DE9A);
PlayFanfare(258);
- data->t08 = 19;
+ data->state = 19;
}
break;
case 19:
if (IsFanfareTaskInactive() &&JOY_NEW(A_BUTTON | B_BUTTON))
- data->t08 = 26;
+ data->state = 26;
break;
case 23:
- if (mevent_0814257C(&data->t09, gUnknown_841DE7D))
- data->t08 = 26;
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE7D))
+ data->state = 26;
break;
case 20:
- if (mevent_0814257C(&data->t09, gUnknown_841DE96))
- data->t08 = 0;
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE96))
+ data->state = 0;
break;
case 21:
- if (mevent_0814257C(&data->t09, gUnknown_841DE97))
- data->t08 = 0;
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE97))
+ data->state = 0;
break;
case 22:
- if (mevent_0814257C(&data->t09, gUnknown_841DE9C))
- data->t08 = 0;
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE9C))
+ data->state = 0;
break;
case 26:
sub_812B484();
Free(data->t10);
DestroyTask(taskId);
- SetMainCallback2(sub_81422FC);
+ SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
break;
}
}
@@ -490,12 +490,12 @@ void sub_8143D24(void)
sub_80BDE28();
}
-struct MEventBuffer_3120_Sub * sub_8143D58(void)
+struct MEventBuffer_3120_Sub * GetSavedWonderNews(void)
{
return &gSaveBlock1Ptr->unk_3120.buffer_000.data;
}
-struct MEventBuffer_32E0_Sub * sav1_get_mevent_buffer_1(void)
+struct MEventBuffer_32E0_Sub * GetSavedWonderCard(void)
{
return &gSaveBlock1Ptr->unk_3120.buffer_1c0.data;
}
@@ -515,7 +515,7 @@ u16 * sub_8143DA8(void)
return gSaveBlock1Ptr->unk_3120.unk_338;
}
-void sub_8143DBC(void)
+void DestroyWonderNews(void)
{
sub_8143E9C();
}
@@ -530,7 +530,7 @@ bool32 sub_8143DC8(const struct MEventBuffer_3120_Sub * src)
return TRUE;
}
-bool32 sub_8143E1C(void)
+bool32 ValidateReceivedWonderNews(void)
{
if (CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_3120.buffer_000.data, sizeof(struct MEventBuffer_3120_Sub)) != gSaveBlock1Ptr->unk_3120.buffer_000.crc)
return FALSE;
@@ -546,7 +546,7 @@ bool32 sub_8143E64(const struct MEventBuffer_3120_Sub * data)
return TRUE;
}
-bool32 sub_8143E78(void)
+bool32 WonderNews_Test_Unk_02(void)
{
const struct MEventBuffer_3120_Sub * data = &gSaveBlock1Ptr->unk_3120.buffer_000.data;
if (data->unk_02 == 0)
@@ -556,7 +556,7 @@ bool32 sub_8143E78(void)
void sub_8143E9C(void)
{
- CpuFill32(0, sub_8143D58(), sizeof(gSaveBlock1Ptr->unk_3120.buffer_000.data));
+ CpuFill32(0, GetSavedWonderNews(), sizeof(gSaveBlock1Ptr->unk_3120.buffer_000.data));
gSaveBlock1Ptr->unk_3120.buffer_000.crc = 0;
}
@@ -570,7 +570,7 @@ bool32 sub_8143EF4(const u8 * src)
{
const u8 * r5 = (const u8 *)&gSaveBlock1Ptr->unk_3120.buffer_000.data;
u32 i;
- if (!sub_8143E1C())
+ if (!ValidateReceivedWonderNews())
return FALSE;
for (i = 0; i < sizeof(struct MEventBuffer_3120_Sub); i++)
{
@@ -580,7 +580,7 @@ bool32 sub_8143EF4(const u8 * src)
return TRUE;
}
-void sub_8143F38(void)
+void DestroyWonderCard(void)
{
sub_814407C();
sub_81440B4();
@@ -597,7 +597,7 @@ bool32 sub_8143F68(const struct MEventBuffer_32E0_Sub * data)
struct MEventBuffer_32E0_Sub * r1;
if (!sub_8144018(data))
return FALSE;
- sub_8143F38();
+ DestroyWonderCard();
memcpy(&gSaveBlock1Ptr->unk_3120.buffer_1c0.data, data, sizeof(struct MEventBuffer_32E0_Sub));
gSaveBlock1Ptr->unk_3120.buffer_1c0.crc = CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_3120.buffer_1c0.data, sizeof(struct MEventBuffer_32E0_Sub));
r2 = &gSaveBlock1Ptr->unk_3120.buffer_310.data;
@@ -606,7 +606,7 @@ bool32 sub_8143F68(const struct MEventBuffer_32E0_Sub * data)
return TRUE;
}
-bool32 sub_8143FC8(void)
+bool32 ValidateReceivedWonderCard(void)
{
if (gSaveBlock1Ptr->unk_3120.buffer_1c0.crc != CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_3120.buffer_1c0.data, sizeof(struct MEventBuffer_32E0_Sub)))
return FALSE;
@@ -632,7 +632,7 @@ bool32 sub_8144018(const struct MEventBuffer_32E0_Sub * data)
return TRUE;
}
-bool32 sub_8144054(void)
+bool32 WonderCard_Test_Unk_08_6(void)
{
const struct MEventBuffer_32E0_Sub * data = &gSaveBlock1Ptr->unk_3120.buffer_1c0.data;
if (data->unk_08_6 == 0)
@@ -654,7 +654,7 @@ void sub_81440B4(void)
u16 sub_81440E8(void)
{
- if (sub_8143FC8())
+ if (ValidateReceivedWonderCard())
return gSaveBlock1Ptr->unk_3120.buffer_1c0.data.unk_00;
return 0;
}
@@ -672,7 +672,7 @@ bool32 sub_8144124(u16 a0)
return FALSE;
}
-bool32 sub_8144144(void)
+bool32 CheckReceivedGiftFromWonderCard(void)
{
u16 value = sub_81440E8();
if (!sub_8144124(value))
@@ -721,7 +721,7 @@ bool32 sub_81441F0(const u16 * data)
s32 sub_8144218(void)
{
struct MEventBuffer_32E0_Sub * data;
- if (!sub_8143FC8())
+ if (!ValidateReceivedWonderCard())
return 0;
data = &gSaveBlock1Ptr->unk_3120.buffer_1c0.data;
if (data->unk_08_0 != 1)
@@ -759,11 +759,11 @@ void sub_81442CC(struct MEventStruct_Unk1442CC * data)
data->unk_08 = 1;
data->unk_0C = 1;
data->unk_10 = 1;
- if (sub_8143FC8())
+ if (ValidateReceivedWonderCard())
{
- data->unk_14 = sav1_get_mevent_buffer_1()->unk_00;
+ data->unk_14 = GetSavedWonderCard()->unk_00;
data->unk_20 = *sav1_get_mevent_buffer_2();
- data->unk_44 = sav1_get_mevent_buffer_1()->unk_09;
+ data->unk_44 = GetSavedWonderCard()->unk_09;
}
else
data->unk_14 = 0;
@@ -945,7 +945,7 @@ bool32 sub_81446D0(u16 a0)
gUnknown_203F3BC = FALSE;
if (a0 == 0)
return FALSE;
- if (!sub_8143FC8())
+ if (!ValidateReceivedWonderCard())
return FALSE;
if (gSaveBlock1Ptr->unk_3120.buffer_1c0.data.unk_00 != a0)
return FALSE;
diff --git a/src/mevent_8145654.c b/src/mevent_8145654.c
index c39d76f25..034a07679 100644
--- a/src/mevent_8145654.c
+++ b/src/mevent_8145654.c
@@ -58,7 +58,7 @@ void sub_8145D18(u8 whichWindow);
void sub_8146060(void);
void sub_81461D8(void);
-extern const struct OamData gUnknown_83AC9F8;
+extern const struct OamData gOamData_83AC9F8;
const struct TextColor gUnknown_8467068[] = {
{0, 2, 3},
@@ -113,7 +113,7 @@ const struct SpritePalette gUnknown_8467F60[] = {
{gUnknown_8467ED4, 0x8000}
};
const struct SpriteTemplate gUnknown_8467FA0 = {
- 0x8000, 0x8000, &gUnknown_83AC9F8, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy
+ 0x8000, 0x8000, &gOamData_83AC9F8, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy
};
const struct UnkStruct_8467FB8 gUnknown_8467FB8[8] = {
{1, 0, 0, 0, gUnknown_846718C, gUnknown_8467288, gUnknown_846708C},
@@ -126,7 +126,7 @@ const struct UnkStruct_8467FB8 gUnknown_8467FB8[8] = {
{1, 0, 0, 7, gUnknown_8467A7C, gUnknown_8467CAC, gUnknown_846716C}
};
-bool32 sub_8145654(struct MEventBuffer_32E0_Sub * r5, struct MEventBuffer_3430_Sub * r6)
+bool32 InitWonderCardResources(struct MEventBuffer_32E0_Sub * r5, struct MEventBuffer_3430_Sub * r6)
{
if (r5 == NULL || r6 == NULL)
return FALSE;
@@ -145,7 +145,7 @@ bool32 sub_8145654(struct MEventBuffer_32E0_Sub * r5, struct MEventBuffer_3430_S
return TRUE;
}
-void sub_81456F0(void)
+void DestroyWonderCardResources(void)
{
if (gUnknown_203F3C8 != NULL)
{
@@ -155,7 +155,7 @@ void sub_81456F0(void)
}
}
-s32 sub_814571C(void)
+s32 FadeToWonderCardMenu(void)
{
if (gUnknown_203F3C8 == NULL)
return -1;
@@ -219,7 +219,7 @@ s32 sub_814571C(void)
return 0;
}
-s32 sub_814593C(bool32 flag)
+s32 FadeOutFromWonderCard(bool32 flag)
{
if (gUnknown_203F3C8 == NULL)
return -1;
@@ -252,7 +252,7 @@ s32 sub_814593C(bool32 flag)
FreeMonIconPalettes();
break;
case 5:
- sub_8142344(gUnknown_203F3B8, flag);
+ PrintMysteryGiftOrEReaderTopMenu(gGiftIsFromEReader, flag);
break;
case 6:
CopyBgTilemapBufferToVram(0);
@@ -347,28 +347,28 @@ void sub_8145D18(u8 whichWindow)
case 0:
{
s32 x;
- box_print(windowId, 3, 0, 1, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal1], 0, gUnknown_203F3C8->unk_018B);
+ AddTextPrinterParameterized3(windowId, 3, 0, 1, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal1], 0, gUnknown_203F3C8->unk_018B);
x = 160 - GetStringWidth(3, gUnknown_203F3C8->unk_01B4, GetFontAttribute(3, 2));
if (x < 0)
x = 0;
- box_print(windowId, 3, x, 17, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal1], 0, gUnknown_203F3C8->unk_01B4);
+ AddTextPrinterParameterized3(windowId, 3, x, 17, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal1], 0, gUnknown_203F3C8->unk_01B4);
if (gUnknown_203F3C8->unk_0000.unk_04 != 0)
{
- box_print(windowId, 2, 166, 17, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal1], 0, gUnknown_203F3C8->unk_01DD);
+ AddTextPrinterParameterized3(windowId, 2, 166, 17, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal1], 0, gUnknown_203F3C8->unk_01DD);
}
break;
}
case 1:
for (; sp0C < 4; sp0C++)
{
- box_print(windowId, 3, 0, 16 * sp0C + 2, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal2], 0, gUnknown_203F3C8->unk_01E4[sp0C]);
+ AddTextPrinterParameterized3(windowId, 3, 0, 16 * sp0C + 2, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal2], 0, gUnknown_203F3C8->unk_01E4[sp0C]);
}
break;
case 2:
- box_print(windowId, 3, 0, gUnknown_8467070[gUnknown_203F3C8->unk_0000.unk_08_0], &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal3], 0, gUnknown_203F3C8->unk_0288);
+ AddTextPrinterParameterized3(windowId, 3, 0, gUnknown_8467070[gUnknown_203F3C8->unk_0000.unk_08_0], &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal3], 0, gUnknown_203F3C8->unk_0288);
if (gUnknown_203F3C8->unk_0000.unk_08_0 != 2)
{
- box_print(windowId, 3, 0, 16 + gUnknown_8467070[gUnknown_203F3C8->unk_0000.unk_08_0], &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal3], 0, gUnknown_203F3C8->unk_02B1);
+ AddTextPrinterParameterized3(windowId, 3, 0, 16 + gUnknown_8467070[gUnknown_203F3C8->unk_0000.unk_08_0], &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal3], 0, gUnknown_203F3C8->unk_02B1);
}
else
{
@@ -377,11 +377,11 @@ void sub_8145D18(u8 whichWindow)
s32 spacing = GetFontAttribute(3, 2);
for (; sp0C < gUnknown_203F3C8->unk_0175; sp0C++)
{
- box_print(windowId, 3, x, y, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal3], 0, gUnknown_203F3C8->unk_02DC[sp0C].unk_01);
+ AddTextPrinterParameterized3(windowId, 3, x, y, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal3], 0, gUnknown_203F3C8->unk_02DC[sp0C].unk_01);
if (gUnknown_203F3C8->unk_02DC[sp0C].unk_42[0] != EOS)
{
x += GetStringWidth(3, gUnknown_203F3C8->unk_02DC[sp0C].unk_01, spacing);
- box_print(windowId, 2, x, y, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal3], 0, gUnknown_203F3C8->unk_02DC[sp0C].unk_42);
+ AddTextPrinterParameterized3(windowId, 2, x, y, &gUnknown_8467068[gUnknown_203F3C8->unk_0170->textPal3], 0, gUnknown_203F3C8->unk_02DC[sp0C].unk_42);
x += GetStringWidth(3, gUnknown_203F3C8->unk_02DC[sp0C].unk_42, spacing) + gUnknown_203F3C8->unk_02DC[sp0C].unk_00;
}
}
@@ -460,7 +460,7 @@ struct UnkStruct_203F3CC
/*01cc*/ u8 filler_01CC[2];
/*01ce*/ u8 unk_01CE[41];
/*01f7*/ u8 unk_01F7[10][41];
- /*0394*/ struct ScrollIndicatorArrowPairTemplate unk_0394;
+ /*0394*/ struct ScrollArrowsTemplate unk_0394;
/*03a4*/ u8 buffer_03A4[0x1000];
};
@@ -478,9 +478,9 @@ const struct WindowTemplate gUnknown_8468040[] = {
{0, 1, 0, 28, 3, 15, 0x000},
{2, 1, 3, 28, 20, 15, 0x000}
};
-const struct ScrollIndicatorArrowPairTemplate gUnknown_8468050 = {
+const struct ScrollArrowsTemplate gUnknown_8468050 = {
0x02, 0xe8, 0x18, 0x03, 0xe8, 0x98,
- 0x0000, 0x0002, 0x1000, 0x1000, 0x0, 0x000
+ 0x0000, 0x0002, 0x1000, 0x1000, 0x0,
};
const u16 gUnknown_8468060[] = INCBIN_U16("data/graphics/mevent/pal_468060.gbapal");
@@ -508,7 +508,7 @@ const struct UnkStruct_8467FB8 gUnknown_8468720[] = {
{1, 0, 0, 0, gUnknown_84685B4, gUnknown_8468644, gUnknown_84680A0}
};
-bool32 sub_8146288(const struct MEventBuffer_3120_Sub * a0)
+bool32 InitWonderNewsResources(const struct MEventBuffer_3120_Sub * a0)
{
if (a0 == NULL)
return FALSE;
@@ -523,7 +523,7 @@ bool32 sub_8146288(const struct MEventBuffer_3120_Sub * a0)
return TRUE;
}
-void sub_81462EC(void)
+void DestroyWonderNewsResources(void)
{
if (gUnknown_203F3CC != NULL)
{
@@ -533,7 +533,7 @@ void sub_81462EC(void)
}
}
-s32 sub_8146318(void)
+s32 FadeToWonderNewsMenu(void)
{
if (gUnknown_203F3CC == NULL)
return -1;
@@ -608,7 +608,7 @@ s32 sub_8146318(void)
return 0;
}
-s32 sub_8146604(bool32 flag)
+s32 FadeOutFromWonderNews(bool32 flag)
{
if (gUnknown_203F3CC == NULL)
return -1;
@@ -653,10 +653,10 @@ s32 sub_8146604(bool32 flag)
}
break;
case 5:
- sub_8142344(gUnknown_203F3B8, flag);
+ PrintMysteryGiftOrEReaderTopMenu(gGiftIsFromEReader, flag);
break;
case 6:
- sub_8142420();
+ MG_DrawCheckerboardPattern();
CopyBgTilemapBufferToVram(0);
CopyBgTilemapBufferToVram(3);
BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0);
@@ -671,7 +671,7 @@ s32 sub_8146604(bool32 flag)
return 0;
}
-void sub_81467EC(void)
+void MENews_RemoveScrollIndicatorArrowPair(void)
{
if (!gUnknown_203F3CC->unk_01C0_0 && gUnknown_203F3CC->unk_01C1 != 0xFF)
{
@@ -682,7 +682,7 @@ void sub_81467EC(void)
}
-void sub_8146834(void)
+void MENews_AddScrollIndicatorArrowPair(void)
{
if (gUnknown_203F3CC->unk_01C0_0)
{
@@ -691,7 +691,7 @@ void sub_8146834(void)
}
}
-u8 sub_8146884(u16 input)
+u32 MENews_GetInput(u16 input)
{
if (gUnknown_203F3CC->unk_01C2_0)
{
@@ -743,7 +743,7 @@ void sub_8146980(void)
++gUnknown_203F3CC->unk_01C4;
}
gUnknown_203F3CC->unk_0394 = gUnknown_8468050;
- gUnknown_203F3CC->unk_0394.unk_08 = gUnknown_203F3CC->unk_01C4;
+ gUnknown_203F3CC->unk_0394.fullyDownThreshold = gUnknown_203F3CC->unk_01C4;
}
void sub_8146A30(void)
@@ -757,10 +757,10 @@ void sub_8146A30(void)
x = (0xe0 - GetStringWidth(3, gUnknown_203F3CC->unk_01CE, GetFontAttribute(3, 2))) / 2;
if (x < 0)
x = 0;
- box_print(gUnknown_203F3CC->unk_01C8[0], 3, x, 6, &gUnknown_8468038[gUnknown_203F3CC->unk_01BC->textPal1], 0, gUnknown_203F3CC->unk_01CE);
+ AddTextPrinterParameterized3(gUnknown_203F3CC->unk_01C8[0], 3, x, 6, &gUnknown_8468038[gUnknown_203F3CC->unk_01BC->textPal1], 0, gUnknown_203F3CC->unk_01CE);
for (; i < 10; ++i)
{
- box_print(gUnknown_203F3CC->unk_01C8[1], 3, 0, 16 * i + 2, &gUnknown_8468038[gUnknown_203F3CC->unk_01BC->textPal2], 0, gUnknown_203F3CC->unk_01F7[i]);
+ AddTextPrinterParameterized3(gUnknown_203F3CC->unk_01C8[1], 3, 0, 16 * i + 2, &gUnknown_8468038[gUnknown_203F3CC->unk_01BC->textPal2], 0, gUnknown_203F3CC->unk_01F7[i]);
}
CopyWindowToVram(gUnknown_203F3CC->unk_01C8[0], 3);
CopyWindowToVram(gUnknown_203F3CC->unk_01C8[1], 3);
diff --git a/src/mevent_server.c b/src/mevent_server.c
index 5e384ae0b..1c2dc4ced 100644
--- a/src/mevent_server.c
+++ b/src/mevent_server.c
@@ -11,12 +11,12 @@
#include "mevent.h"
#include "mevent_server.h"
-EWRAM_DATA struct mevent_srv_ish * s_mevent_srv_ish_ptr = NULL;
+EWRAM_DATA struct mevent_client * s_mevent_client_ptr = NULL;
EWRAM_DATA struct mevent_srv_common * s_mevent_srv_common_ptr = NULL;
-static void mevent_srv_ish_init(struct mevent_srv_ish *, u32, u32);
-static u32 mevent_srv_ish_exec(struct mevent_srv_ish *);
-static void mevent_srv_ish_free_resources(struct mevent_srv_ish *);
+static void mevent_client_init(struct mevent_client *, u32, u32);
+static u32 mevent_client_exec(struct mevent_client *);
+static void mevent_client_free_resources(struct mevent_client *);
static void mevent_srv_init_common(struct mevent_srv_common *, const void *, u32, u32);
static void mevent_srv_free_resources(struct mevent_srv_common *);
static u32 mevent_srv_exec_common(struct mevent_srv_common *);
@@ -25,44 +25,44 @@ extern const u8 gUnknown_84687E0[];
extern const struct mevent_cmd gUnknown_8468B6C[];
extern const struct mevent_cmd gUnknown_8468BCC[];
-void mevent_srv_ish_do_init(void)
+void mevent_client_do_init(void)
{
- s_mevent_srv_ish_ptr = AllocZeroed(sizeof(struct mevent_srv_ish));
- mevent_srv_ish_init(s_mevent_srv_ish_ptr, 1, 0);
+ s_mevent_client_ptr = AllocZeroed(sizeof(struct mevent_client));
+ mevent_client_init(s_mevent_client_ptr, 1, 0);
}
-u32 mevent_srv_ish_do_exec(u16 * a0)
+u32 mevent_client_do_exec(u16 * a0)
{
u32 result;
- if (s_mevent_srv_ish_ptr == NULL)
+ if (s_mevent_client_ptr == NULL)
return 6;
- result = mevent_srv_ish_exec(s_mevent_srv_ish_ptr);
+ result = mevent_client_exec(s_mevent_client_ptr);
if (result == 6)
{
- *a0 = s_mevent_srv_ish_ptr->param;
- mevent_srv_ish_free_resources(s_mevent_srv_ish_ptr);
- Free(s_mevent_srv_ish_ptr);
- s_mevent_srv_ish_ptr = NULL;
+ *a0 = s_mevent_client_ptr->param;
+ mevent_client_free_resources(s_mevent_client_ptr);
+ Free(s_mevent_client_ptr);
+ s_mevent_client_ptr = NULL;
}
return result;
}
-void mevent_srv_ish_inc_flag(void)
+void mevent_client_inc_flag(void)
{
- s_mevent_srv_ish_ptr->flag++;
+ s_mevent_client_ptr->flag++;
}
-void * mevent_srv_ish_get_buffer(void)
+void * mevent_client_get_buffer(void)
{
- return s_mevent_srv_ish_ptr->buffer;
+ return s_mevent_client_ptr->buffer;
}
-void mevent_srv_ish_set_param(u32 a0)
+void mevent_client_set_param(u32 a0)
{
- s_mevent_srv_ish_ptr->param = a0;
+ s_mevent_client_ptr->param = a0;
}
-static void mevent_srv_ish_init(struct mevent_srv_ish * svr, u32 sendPlayerNo, u32 recvPlayerNo)
+static void mevent_client_init(struct mevent_client * svr, u32 sendPlayerNo, u32 recvPlayerNo)
{
svr->unk_00 = 0;
svr->mainseqno = 0;
@@ -74,7 +74,7 @@ static void mevent_srv_ish_init(struct mevent_srv_ish * svr, u32 sendPlayerNo, u
mevent_srv_sub_init(&svr->manager, sendPlayerNo, recvPlayerNo);
}
-static void mevent_srv_ish_free_resources(struct mevent_srv_ish * svr)
+static void mevent_client_free_resources(struct mevent_client * svr)
{
Free(svr->sendBuffer);
Free(svr->recvBuffer);
@@ -82,20 +82,20 @@ static void mevent_srv_ish_free_resources(struct mevent_srv_ish * svr)
Free(svr->buffer);
}
-static void mevent_srv_ish_jmp_buffer(struct mevent_srv_ish * svr)
+static void mevent_client_jmp_buffer(struct mevent_client * svr)
{
memcpy(svr->cmdBuffer, svr->recvBuffer, ME_SEND_BUF_SIZE);
svr->cmdidx = 0;
}
-static void mevent_srv_ish_send_word(struct mevent_srv_ish * svr, u32 ident, u32 word)
+static void mevent_client_send_word(struct mevent_client * svr, u32 ident, u32 word)
{
CpuFill32(0, svr->sendBuffer, ME_SEND_BUF_SIZE);
*(u32 *)svr->sendBuffer = word;
mevent_srv_sub_init_send(&svr->manager, ident, svr->sendBuffer, sizeof(u32));
}
-static u32 ish_mainseq_0(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_0(struct mevent_client * svr)
{
// init
memcpy(svr->cmdBuffer, gUnknown_84687E0, ME_SEND_BUF_SIZE);
@@ -105,13 +105,13 @@ static u32 ish_mainseq_0(struct mevent_srv_ish * svr)
return 0;
}
-static u32 ish_mainseq_1(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_1(struct mevent_client * svr)
{
// done
return 6;
}
-static u32 ish_mainseq_2(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_2(struct mevent_client * svr)
{
// do recv
if (mevent_srv_sub_recv(&svr->manager))
@@ -122,7 +122,7 @@ static u32 ish_mainseq_2(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_3(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_3(struct mevent_client * svr)
{
// do send
if (mevent_srv_sub_send(&svr->manager))
@@ -133,7 +133,7 @@ static u32 ish_mainseq_3(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_4(struct mevent_client * svr)
{
// process command
struct mevent_cmd_ish * cmd = &svr->cmdBuffer[svr->cmdidx];
@@ -162,20 +162,20 @@ static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
svr->flag = 0;
break;
case 19:
- mevent_srv_ish_send_word(svr, 0x12, GetGameStat(cmd->parameter));
+ mevent_client_send_word(svr, 0x12, GetGameStat(cmd->parameter));
svr->mainseqno = 3;
svr->flag = 0;
break;
case 6:
if (svr->param == 0)
- mevent_srv_ish_jmp_buffer(svr);
+ mevent_client_jmp_buffer(svr);
break;
case 7:
if (svr->param == 1)
- mevent_srv_ish_jmp_buffer(svr);
+ mevent_client_jmp_buffer(svr);
break;
case 4:
- mevent_srv_ish_jmp_buffer(svr);
+ mevent_client_jmp_buffer(svr);
break;
case 5:
memcpy(svr->buffer, svr->recvBuffer, 0x40);
@@ -201,7 +201,7 @@ static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
mevent_srv_sub_init_send(&svr->manager, 0x11, svr->sendBuffer, sizeof(struct MEventStruct_Unk1442CC));
break;
case 14:
- mevent_srv_ish_send_word(svr, 0x13, svr->param);
+ mevent_client_send_word(svr, 0x13, svr->param);
break;
case 10:
sub_8143F68(svr->recvBuffer);
@@ -210,10 +210,10 @@ static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
if (!sub_8143EF4(svr->recvBuffer))
{
sub_8143DC8(svr->recvBuffer);
- mevent_srv_ish_send_word(svr, 0x13, 0);
+ mevent_client_send_word(svr, 0x13, 0);
}
else
- mevent_srv_ish_send_word(svr, 0x13, 1);
+ mevent_client_send_word(svr, 0x13, 1);
break;
case 15:
svr->mainseqno = 6;
@@ -239,7 +239,7 @@ static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_5(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_5(struct mevent_client * svr)
{
// wait flag
if (svr->flag)
@@ -250,7 +250,7 @@ static u32 ish_mainseq_5(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_6(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_6(struct mevent_client * svr)
{
// ???
switch (svr->flag)
@@ -270,7 +270,7 @@ static u32 ish_mainseq_6(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_7(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_7(struct mevent_client * svr)
{
// exec arbitrary code
u32 (*func)(u32 *, struct SaveBlock2 *, struct SaveBlock1 *) = (void *)gDecompressionBuffer;
@@ -282,9 +282,9 @@ static u32 ish_mainseq_7(struct mevent_srv_ish * svr)
return 1;
}
-static u32 mevent_srv_ish_exec(struct mevent_srv_ish * svr)
+static u32 mevent_client_exec(struct mevent_client * svr)
{
- u32 (*funcs[])(struct mevent_srv_ish *) = {
+ u32 (*funcs[])(struct mevent_client *) = {
ish_mainseq_0,
ish_mainseq_1,
ish_mainseq_2,
@@ -297,19 +297,19 @@ static u32 mevent_srv_ish_exec(struct mevent_srv_ish * svr)
return funcs[svr->mainseqno](svr);
}
-void mevent_srv_common_do_init_1(void)
+void mevent_srv_init_wnews(void)
{
s_mevent_srv_common_ptr = AllocZeroed(sizeof(struct mevent_srv_common));
mevent_srv_init_common(s_mevent_srv_common_ptr, gUnknown_8468B6C, 0, 1);
}
-void mevent_srv_common_do_init_2(void)
+void mevent_srv_new_wcard(void)
{
s_mevent_srv_common_ptr = AllocZeroed(sizeof(struct mevent_srv_common));
mevent_srv_init_common(s_mevent_srv_common_ptr, gUnknown_8468BCC, 0, 1);
}
-u32 mevent_srv_init_do_exec(u16 * a0)
+u32 mevent_srv_common_do_exec(u16 * a0)
{
u32 result;
if (s_mevent_srv_common_ptr == NULL)
@@ -526,12 +526,12 @@ static u32 common_mainseq_4(struct mevent_srv_common * svr)
break;
case 26:
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/mevent_server.c", 506);
- memcpy(svr->mevent_32e0, sav1_get_mevent_buffer_1(), 332);
+ memcpy(svr->mevent_32e0, GetSavedWonderCard(), 332);
sub_814410C(svr->mevent_32e0);
break;
case 27:
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/mevent_server.c", 512);
- memcpy(svr->mevent_3120, sub_8143D58(), 444);
+ memcpy(svr->mevent_3120, GetSavedWonderNews(), 444);
break;
case 28:
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/mevent_server.c", 517);
diff --git a/src/money.c b/src/money.c
index 6d9a0fce9..ffaba2e29 100644
--- a/src/money.c
+++ b/src/money.c
@@ -128,13 +128,13 @@ void DrawMoneyBox(int amount, u8 x, u8 y)
sMoneyBoxWindowId = AddWindow(&template2);
FillWindowPixelBuffer(sMoneyBoxWindowId, 0);
PutWindowTilemap(sMoneyBoxWindowId);
- sub_814FF2C(sMoneyBoxWindowId, 0x21D, 0xD0);
+ TextWindow_SetStdFrame0_WithPal(sMoneyBoxWindowId, 0x21D, 0xD0);
PrintMoneyAmountInMoneyBoxWithBorder(sMoneyBoxWindowId, 0x21D, 13, amount);
}
void HideMoneyBox(void)
{
- sub_810F4D8(sMoneyBoxWindowId, FALSE);
+ ClearMenuWindow(sMoneyBoxWindowId, FALSE);
CopyWindowToVram(sMoneyBoxWindowId, 2);
RemoveWindow(sMoneyBoxWindowId);
}
diff --git a/src/mystery_event_msg.c b/src/mystery_event_msg.c
index a21750b7a..7cde2d9f2 100644
--- a/src/mystery_event_msg.c
+++ b/src/mystery_event_msg.c
@@ -10,4 +10,4 @@ const u8 gText_MysteryGiftSentOver[] = _("{STR_VAR_1} was sent over!");
const u8 gText_MysteryGiftFullParty[] = _("Your party is full.\n{STR_VAR_1} could not be sent over.");
const u8 gText_MysteryGiftNewTrainer[] = _("A new TRAINER has arrived in\nHOENN.");
const u8 gText_MysteryGiftNewAdversaryInBattleTower[] = _("バトルタワーに あらたな\nたいせんしゃが あらわれた!");
-const u8 gText_MysteryGiftCantBeUsed[] = _("This data can’t be used in\nthis version.");
+const u8 gText_MysteryGiftCantBeUsed[] = _("This data can't be used in\nthis version.");
diff --git a/src/mystery_gift_menu.c b/src/mystery_gift_menu.c
new file mode 100644
index 000000000..9ff96eb23
--- /dev/null
+++ b/src/mystery_gift_menu.c
@@ -0,0 +1,1756 @@
+#include "global.h"
+#include "palette.h"
+#include "dma3.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "task.h"
+#include "scanline_effect.h"
+#include "malloc.h"
+#include "text.h"
+#include "window.h"
+#include "text_window.h"
+#include "menu.h"
+#include "new_menu_helpers.h"
+#include "sound.h"
+#include "mystery_gift_menu.h"
+#include "title_screen.h"
+#include "list_menu.h"
+#include "link_rfu.h"
+#include "string_util.h"
+#include "mevent.h"
+#include "save.h"
+#include "link.h"
+#include "event_data.h"
+#include "mevent_server.h"
+#include "menews_jisan.h"
+#include "help_system.h"
+#include "constants/songs.h"
+
+EWRAM_DATA u8 sDownArrowCounterAndYCoordIdx[8] = {};
+EWRAM_DATA bool8 gGiftIsFromEReader = FALSE;
+
+void task_add_00_mystery_gift(void);
+void task00_mystery_gift(u8 taskId);
+void task_add_00_ereader(void);
+
+extern const u8 gText_PickOKExit[];
+extern const u8 gText_PickOKCancel[];
+extern const u8 gText_MysteryGift[];
+extern const u8 gJPText_MysteryGift[];
+extern const u8 gJPText_DecideStop[];
+extern const u8 gText_WhatToDoWithCards[];
+extern const u8 gText_WhatToDoWithNews[];
+extern const u8 gText_OkayToDiscardNews[];
+extern const u8 gText_IfThrowAwayCardEventWontHappen[];
+extern const u8 gText_WonderCardThrownAway[];
+extern const u8 gText_WonderNewsThrownAway[];
+extern const u8 gText_DataWillBeSaved[];
+extern const u8 gText_SaveCompletedPressA[];
+extern const u8 gText_WonderCards[];
+extern const u8 gText_WonderNews[];
+extern const u8 gText_Exit3[];
+extern const u8 gText_WirelessCommunication[];
+extern const u8 gText_Friend2[];
+extern const u8 gFameCheckerText_Cancel[];
+extern const u8 gText_Receive[];
+extern const u8 gText_Send[];
+extern const u8 gText_Toss[];
+extern const u8 gText_VarietyOfEventsImportedWireless[];
+extern const u8 gText_WonderCardsInPossession[];
+extern const u8 gText_ReadNewsThatArrived[];
+extern const u8 gText_ReturnToTitle[];
+extern const u8 gText_NothingSentOver[];
+extern const u8 gText_RecordUploadedViaWireless[];
+extern const u8 gText_WonderCardReceived[];
+extern const u8 gText_WonderCardReceivedFrom[];
+extern const u8 gText_WonderNewsReceived[];
+extern const u8 gText_WonderNewsReceivedFrom[];
+extern const u8 gText_NewStampReceived[];
+extern const u8 gText_AlreadyHadCard[];
+extern const u8 gText_AlreadyHadStamp[];
+extern const u8 gText_AlreadyHadNews[];
+extern const u8 gText_NoMoreRoomForStamps[];
+extern const u8 gText_CommunicationCanceled[];
+extern const u8 gText_CantAcceptCardFromTrainer[];
+extern const u8 gText_CantAcceptNewsFromTrainer[];
+extern const u8 gText_CommunicationError[];
+extern const u8 gText_NewTrainerReceived[];
+extern const u8 gText_WonderCardSentTo[];
+extern const u8 gText_WonderNewsSentTo[];
+extern const u8 gText_StampSentTo[];
+extern const u8 gText_OtherTrainerHasCard[];
+extern const u8 gText_OtherTrainerHasStamp[];
+extern const u8 gText_OtherTrainerHasNews[];
+extern const u8 gText_OtherTrainerCanceled[];
+extern const u8 gText_GiftSentTo[];
+extern const u8 gText_CantSendGiftToTrainer[];
+extern const u8 gText_DontHaveCardNewOneInput[];
+extern const u8 gText_DontHaveNewsNewOneInput[];
+extern const u8 gText_WhereShouldCardBeAccessed[];
+extern const u8 gText_WhereShouldNewsBeAccessed[];
+extern const u8 gText_Communicating[];
+extern const u8 gText_ThrowAwayWonderCard[];
+extern const u8 gText_HaventReceivedCardsGift[];
+extern const u8 gText_CommunicationCompleted[];
+extern const u8 gText_HaventReceivedGiftOkayToDiscard[];
+extern const u8 gText_SendingWonderCard[];
+extern const u8 gText_SendingWonderNews[];
+
+const u16 gUnkTextboxBorderPal[] = INCBIN_U16("graphics/interface/unk_textbox_border.gbapal");
+const u32 gUnkTextboxBorderGfx[] = INCBIN_U32("graphics/interface/unk_textbox_border.4bpp.lz");
+
+struct MysteryGiftTaskData
+{
+ u16 curPromptWindowId;
+ u16 unk2;
+ u16 unk4;
+ u16 unk6;
+ u8 state;
+ u8 textState;
+ u8 unkA;
+ u8 unkB;
+ u8 IsCardOrNews;
+ u8 source;
+ u8 prevPromptWindowId;
+ u8 * buffer;
+};
+
+const struct BgTemplate sBGTemplates[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 15,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 14,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0x000
+ }, {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 13,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x000
+ }, {
+ .bg = 3,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 12,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x000
+ }
+};
+
+const struct WindowTemplate sMainWindows[] = {
+ {
+ .bg = 0x00,
+ .tilemapLeft = 0x00,
+ .tilemapTop = 0x00,
+ .width = 0x1e,
+ .height = 0x02,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0013
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x0f,
+ .width = 0x1c,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x004f
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x00,
+ .tilemapTop = 0x0f,
+ .width = 0x1e,
+ .height = 0x05,
+ .paletteNum = 0x0d,
+ .baseBlock = 0x004f
+ }, {
+ 0xFF
+ }
+};
+
+const struct WindowTemplate sWindowTemplate_PromptYesOrNo_Width28 = {
+ .bg = 0x00,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x0f,
+ .width = 0x1c,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x00e5
+};
+
+const struct WindowTemplate sWindowTemplate_PromptYesOrNo_Width20 = {
+ .bg = 0x00,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x0f,
+ .width = 0x14,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x00e5
+};
+
+const struct WindowTemplate sMysteryGiftMenuWindowTemplate = {
+ .bg = 0x00,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x0f,
+ .width = 0x13,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x00e5
+};
+
+const struct WindowTemplate sWindowTemplate_ThreeOptions = {
+ .bg = 0x00,
+ .tilemapLeft = 0x08,
+ .tilemapTop = 0x05,
+ .width = 0x0e,
+ .height = 0x05,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct WindowTemplate sWindowTemplate_YesNoBox = {
+ .bg = 0x00,
+ .tilemapLeft = 0x17,
+ .tilemapTop = 0x0f,
+ .width = 0x06,
+ .height = 0x04,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct WindowTemplate sWindowTemplate_7by8 = {
+ .bg = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0c,
+ .width = 0x07,
+ .height = 0x07,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct WindowTemplate sWindowTemplate_7by6 = {
+ .bg = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0e,
+ .width = 0x07,
+ .height = 0x05,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct WindowTemplate sWindowTemplate_7by4 = {
+ .bg = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0f,
+ .width = 0x07,
+ .height = 0x04,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct ListMenuItem sListMenuItems_CardsOrNews[] = {
+ { gText_WonderCards, 0 },
+ { gText_WonderNews, 1 },
+ { gText_Exit3, -2 }
+};
+
+const struct ListMenuItem sListMenuItems_WirelessOrFriend[] = {
+ { gText_WirelessCommunication, 0 },
+ { gText_Friend2, 1 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuTemplate sListMenuTemplate_ThreeOptions = {
+ .items = NULL,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const struct ListMenuItem sListMenuItems_ReceiveSendToss[] = {
+ { gText_Receive, 0 },
+ { gText_Send, 1 },
+ { gText_Toss, 2 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuItem sListMenuItems_ReceiveToss[] = {
+ { gText_Receive, 0 },
+ { gText_Toss, 2 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuItem sListMenuItems_ReceiveSend[] = {
+ { gText_Receive, 0 },
+ { gText_Send, 1 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuItem sListMenuItems_Receive[] = {
+ { gText_Receive, 0 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuTemplate sListMenu_ReceiveSendToss = {
+ .items = sListMenuItems_ReceiveSendToss,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 4,
+ .maxShowed = 4,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 2,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const struct ListMenuTemplate sListMenu_ReceiveToss = {
+ .items = sListMenuItems_ReceiveToss,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const struct ListMenuTemplate sListMenu_ReceiveSend = {
+ .items = sListMenuItems_ReceiveSend,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const struct ListMenuTemplate sListMenu_Receive = {
+ .items = sListMenuItems_Receive,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 2,
+ .maxShowed = 2,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 2,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const u8 *const Unref_08366ED8[] = {
+ gText_VarietyOfEventsImportedWireless,
+ gText_WonderCardsInPossession,
+ gText_ReadNewsThatArrived,
+ gText_ReturnToTitle
+};
+
+ALIGNED(4) const struct TextColor sMG_Ereader_TextColor_1 = { 0, 1, 2 };
+ALIGNED(4) const struct TextColor sMG_Ereader_TextColor_1_Copy = { 0, 1, 2 };
+ALIGNED(4) const struct TextColor sMG_Ereader_TextColor_2 = { 1, 2, 3 };
+
+const u8 gUnknown_8466EF3[] = _("テスト");
+const u8 gUnknown_8466EF7[] = _("むげんのチケット");
+
+void vblankcb_mystery_gift_e_reader_run(void)
+{
+ ProcessSpriteCopyRequests();
+ LoadOam();
+ TransferPlttBuffer();
+}
+
+void c2_mystery_gift_e_reader_run(void)
+{
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+}
+
+bool32 HandleMysteryGiftOrEReaderSetup(s32 mg_or_ereader)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL);
+ ResetPaletteFade();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetTasks();
+ ScanlineEffect_Stop();
+ ResetBgsAndClearDma3BusyFlags(1);
+
+ InitBgsFromTemplates(0, sBGTemplates, ARRAY_COUNT(sBGTemplates));
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ ChangeBgX(3, 0, 0);
+ ChangeBgY(3, 0, 0);
+
+ SetBgTilemapBuffer(3, Alloc(0x800));
+ SetBgTilemapBuffer(2, Alloc(0x800));
+ SetBgTilemapBuffer(1, Alloc(0x800));
+ SetBgTilemapBuffer(0, Alloc(0x800));
+
+ LoadUserWindowBorderGfx(0, 10, 0xE0);
+ sub_814FDA0(0, 1, 0xF0);
+ DecompressAndLoadBgGfxUsingHeap(3, gUnkTextboxBorderGfx, 0x100, 0, 0);
+ InitWindows(sMainWindows);
+ DeactivateAllTextPrinters();
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ gMain.state++;
+ break;
+ case 1:
+ LoadPalette(gUnkTextboxBorderPal, 0, 0x20);
+ LoadPalette(stdpal_get(2), 0xd0, 0x20);
+ FillBgTilemapBufferRect(0, 0x000, 0, 0, 32, 32, 0x11);
+ FillBgTilemapBufferRect(1, 0x000, 0, 0, 32, 32, 0x11);
+ FillBgTilemapBufferRect(2, 0x000, 0, 0, 32, 32, 0x11);
+ MG_DrawCheckerboardPattern();
+ PrintMysteryGiftOrEReaderTopMenu(mg_or_ereader, 0);
+ gMain.state++;
+ break;
+ case 2:
+ CopyBgTilemapBufferToVram(3);
+ CopyBgTilemapBufferToVram(2);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(0);
+ gMain.state++;
+ break;
+ case 3:
+ ShowBg(0);
+ ShowBg(3);
+ PlayBGM(BGM_FRLG_MYSTERY_GIFT);
+ SetVBlankCallback(vblankcb_mystery_gift_e_reader_run);
+ EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void c2_mystery_gift(void)
+{
+ if (HandleMysteryGiftOrEReaderSetup(0))
+ {
+ SetMainCallback2(c2_mystery_gift_e_reader_run);
+ gGiftIsFromEReader = FALSE;
+ task_add_00_mystery_gift();
+ }
+}
+
+void c2_ereader(void)
+{
+ if (HandleMysteryGiftOrEReaderSetup(1))
+ {
+ SetMainCallback2(c2_mystery_gift_e_reader_run);
+ gGiftIsFromEReader = TRUE;
+ task_add_00_ereader();
+ }
+}
+
+void MainCB_FreeAllBuffersAndReturnToInitTitleScreen(void)
+{
+ gGiftIsFromEReader = FALSE;
+ FreeAllWindowBuffers();
+ Free(GetBgTilemapBuffer(0));
+ Free(GetBgTilemapBuffer(1));
+ Free(GetBgTilemapBuffer(2));
+ Free(GetBgTilemapBuffer(3));
+ SetMainCallback2(CB2_InitTitleScreen);
+}
+
+void PrintMysteryGiftOrEReaderTopMenu(bool8 mg_or_ereader, bool32 usePickOkCancel)
+{
+ const u8 * src;
+ s32 width;
+ FillWindowPixelBuffer(0, 0x00);
+ if (!mg_or_ereader)
+ {
+ src = usePickOkCancel == TRUE ? gText_PickOKExit : gText_PickOKCancel;
+ AddTextPrinterParameterized4(0, 2, 2, 2, 0, 0, &sMG_Ereader_TextColor_1, 0, gText_MysteryGift);
+ width = 222 - GetStringWidth(0, src, 0);
+ AddTextPrinterParameterized4(0, 0, width, 2, 0, 0, &sMG_Ereader_TextColor_1, 0, src);
+ }
+ else
+ {
+ AddTextPrinterParameterized4(0, 2, 2, 2, 0, 0, &sMG_Ereader_TextColor_1, 0, gJPText_MysteryGift);
+ AddTextPrinterParameterized4(0, 0, 0x78, 2, 0, 0, &sMG_Ereader_TextColor_1, 0, gJPText_DecideStop);
+ }
+ CopyWindowToVram(0, 2);
+ PutWindowTilemap(0);
+}
+
+void MG_DrawTextBorder(u8 windowId)
+{
+ DrawTextBorderOuter(windowId, 0x01, 0xF);
+}
+
+void MG_DrawCheckerboardPattern(void)
+{
+ s32 i = 0, j;
+
+ FillBgTilemapBufferRect(3, 0x003, 0, 0, 32, 2, 0x11);
+
+ for (i = 0; i < 18; i++)
+ {
+ for (j = 0; j < 32; j++)
+ {
+ if ((i & 1) != (j & 1))
+ {
+ FillBgTilemapBufferRect(3, 1, j, i + 2, 1, 1, 0x11);
+ }
+ else
+ {
+ FillBgTilemapBufferRect(3, 2, j, i + 2, 1, 1, 0x11);
+ }
+ }
+ }
+}
+
+void ClearScreenInBg0(bool32 ignoreTopTwoRows)
+{
+ switch (ignoreTopTwoRows)
+ {
+ case 0:
+ FillBgTilemapBufferRect(0, 0, 0, 0, 32, 32, 0x11);
+ break;
+ case 1:
+ FillBgTilemapBufferRect(0, 0, 0, 2, 32, 30, 0x11);
+ break;
+ }
+ CopyBgTilemapBufferToVram(0);
+}
+
+void AddTextPrinterToWindow1(const u8 *str)
+{
+ StringExpandPlaceholders(gStringVar4, str);
+ FillWindowPixelBuffer(1, 0x11);
+ AddTextPrinterParameterized4(1, 2, 0, 2, 0, 2, &sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(1, 0x001, 0xF);
+ PutWindowTilemap(1);
+ CopyWindowToVram(1, 3);
+}
+
+void ClearTextWindow(void)
+{
+ rbox_fill_rectangle(1);
+ ClearWindowTilemap(1);
+ CopyWindowToVram(1, 1);
+}
+
+bool32 MG_PrintTextOnWindow1AndWaitButton(u8 *textState, const u8 *str)
+{
+ switch (*textState)
+ {
+ case 0:
+ AddTextPrinterToWindow1(str);
+ goto inc;
+ case 1:
+ DrawDownArrow(1, 0xD0, 0x14, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ inc:
+ (*textState)++;
+ }
+ break;
+ case 2:
+ DrawDownArrow(1, 0xD0, 0x14, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ *textState = 0;
+ ClearTextWindow();
+ return TRUE;
+ case 0xFF:
+ *textState = 2;
+ break;
+ }
+ return FALSE;
+}
+
+void HideDownArrow(void)
+{
+ DrawDownArrow(1, 0xD0, 0x14, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+}
+
+void ShowDownArrow(void)
+{
+ DrawDownArrow(1, 0xD0, 0x14, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+}
+
+bool32 unref_HideDownArrowAndWaitButton(u8 * textState)
+{
+ switch (*textState)
+ {
+ case 0:
+ HideDownArrow();
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ (*textState)++;
+ }
+ break;
+ case 1:
+ ShowDownArrow();
+ *textState = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool32 PrintStringAndWait2Seconds(u8 * counter, const u8 * str)
+{
+ if (*counter == 0)
+ {
+ AddTextPrinterToWindow1(str);
+ }
+ if (++(*counter) > 120)
+ {
+ *counter = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+u32 MysteryGift_HandleThreeOptionMenu(u8 * unused0, u16 * unused1, u8 whichMenu)
+{
+ struct ListMenuTemplate listMenuTemplate = sListMenuTemplate_ThreeOptions;
+ struct WindowTemplate windowTemplate = sWindowTemplate_ThreeOptions;
+ u32 width;
+ s32 finalWidth;
+ s32 response;
+ u32 i;
+
+ if (whichMenu == 0)
+ {
+ listMenuTemplate.items = sListMenuItems_CardsOrNews;
+ }
+ else
+ {
+ listMenuTemplate.items = sListMenuItems_WirelessOrFriend;
+ }
+ width = 0;
+ for (i = 0; i < listMenuTemplate.totalItems; i++)
+ {
+ u32 curWidth = GetStringWidth(2, listMenuTemplate.items[i].label, listMenuTemplate.lettersSpacing);
+ if (curWidth > width)
+ width = curWidth;
+ }
+ finalWidth = (((width + 9) / 8) + 2) & ~1;
+ windowTemplate.width = finalWidth;
+ windowTemplate.tilemapLeft = (30 - finalWidth) / 2;
+ response = DoMysteryGiftListMenu(&windowTemplate, &listMenuTemplate, 1, 0x00A, 0xE0);
+ if (response != -1)
+ {
+ ClearWindowTilemap(2);
+ CopyWindowToVram(2, 1);
+ }
+ return response;
+}
+
+s8 mevent_message_print_and_prompt_yes_no(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str)
+{
+ struct WindowTemplate windowTemplate;
+ s8 input;
+
+ switch (*textState)
+ {
+ case 0:
+ StringExpandPlaceholders(gStringVar4, str);
+ if (yesNoBoxPlacement == 0)
+ {
+ *windowId = AddWindow(&sWindowTemplate_PromptYesOrNo_Width28);
+ }
+ else
+ {
+ *windowId = AddWindow(&sWindowTemplate_PromptYesOrNo_Width20);
+ }
+ FillWindowPixelBuffer(*windowId, 0x11);
+ AddTextPrinterParameterized4(*windowId, 2, 0, 2, 0, 2, &sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(*windowId, 0x001, 0x0F);
+ CopyWindowToVram(*windowId, 2);
+ PutWindowTilemap(*windowId);
+ (*textState)++;
+ break;
+ case 1:
+ windowTemplate = sWindowTemplate_YesNoBox;
+ if (yesNoBoxPlacement == 0)
+ {
+ windowTemplate.tilemapTop = 9;
+ }
+ else
+ {
+ windowTemplate.tilemapTop = 15;
+ }
+ CreateYesNoMenu(&windowTemplate, 2, 0, 2, 10, 14, 0);
+ (*textState)++;
+ break;
+ case 2:
+ input = Menu_ProcessInputNoWrapClearOnChoose();
+ if (input == -1 || input == 0 || input == 1)
+ {
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return input;
+ }
+ break;
+ case 0xFF:
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return -1;
+ }
+
+ return -2;
+}
+
+s32 HandleMysteryGiftListMenu(u8 * textState, u16 * windowId, bool32 cannotToss, bool32 cannotSend)
+{
+ struct WindowTemplate windowTemplate;
+ s32 input;
+
+ switch (*textState)
+ {
+ case 0:
+ if (cannotToss == 0)
+ {
+ StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithCards);
+ }
+ else
+ {
+ StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithNews);
+ }
+ *windowId = AddWindow(&sMysteryGiftMenuWindowTemplate);
+ FillWindowPixelBuffer(*windowId, 0x11);
+ AddTextPrinterParameterized4(*windowId, 2, 0, 2, 0, 2, &sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(*windowId, 0x001, 0x0F);
+ CopyWindowToVram(*windowId, 2);
+ PutWindowTilemap(*windowId);
+ (*textState)++;
+ break;
+ case 1:
+ windowTemplate = sWindowTemplate_YesNoBox;
+ if (cannotSend)
+ {
+ if (cannotToss == 0)
+ {
+ input = DoMysteryGiftListMenu(&sWindowTemplate_7by6, &sListMenu_ReceiveToss, 1, 0x00A, 0xE0);
+ }
+ else
+ {
+ input = DoMysteryGiftListMenu(&sWindowTemplate_7by4, &sListMenu_Receive, 1, 0x00A, 0xE0);
+ }
+ }
+ else
+ {
+ if (cannotToss == 0)
+ {
+ input = DoMysteryGiftListMenu(&sWindowTemplate_7by8, &sListMenu_ReceiveSendToss, 1, 0x00A, 0xE0);
+ }
+ else
+ {
+ input = DoMysteryGiftListMenu(&sWindowTemplate_7by6, &sListMenu_ReceiveSend, 1, 0x00A, 0xE0);
+ }
+ }
+ if (input != -1)
+ {
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return input;
+ }
+ break;
+ case 0xFF:
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return -2;
+ }
+
+ return -1;
+}
+
+bool32 ValidateCardOrNews(bool32 cardOrNews)
+{
+ if (cardOrNews == 0)
+ {
+ return ValidateReceivedWonderCard();
+ }
+ else
+ {
+ return ValidateReceivedWonderNews();
+ }
+}
+
+bool32 HandleLoadWonderCardOrNews(u8 * state, bool32 cardOrNews)
+{
+ s32 v0;
+
+ switch (*state)
+ {
+ case 0:
+ if (cardOrNews == 0)
+ {
+ InitWonderCardResources(GetSavedWonderCard(), sav1_get_mevent_buffer_2());
+ }
+ else
+ {
+ InitWonderNewsResources(GetSavedWonderNews());
+ }
+ (*state)++;
+ break;
+ case 1:
+ if (cardOrNews == 0)
+ {
+ v0 = FadeToWonderCardMenu();
+ check:
+ if (v0 != 0)
+ {
+ goto done;
+ }
+ break;
+ }
+ else
+ {
+ v0 = FadeToWonderNewsMenu();
+ goto check;
+ }
+ done:
+ *state = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+bool32 DestroyNewsOrCard(bool32 cardOrNews)
+{
+ if (cardOrNews == 0)
+ {
+ DestroyWonderCard();
+ }
+ else
+ {
+ DestroyWonderNews();
+ }
+ return TRUE;
+}
+
+bool32 TearDownCardOrNews_ReturnToTopMenu(bool32 cardOrNews, bool32 arg1)
+{
+ if (cardOrNews == 0)
+ {
+ if (FadeOutFromWonderCard(arg1) != 0)
+ {
+ DestroyWonderCardResources();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (FadeOutFromWonderNews(arg1) != 0)
+ {
+ DestroyWonderNewsResources();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+}
+
+s32 mevent_message_prompt_discard(u8 * textState, u16 * windowId, bool32 cardOrNews)
+{
+ if (cardOrNews == 0)
+ {
+ return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_IfThrowAwayCardEventWontHappen);
+ }
+ else
+ {
+ return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_OkayToDiscardNews);
+ }
+}
+
+bool32 mevent_message_was_thrown_away(u8 * textState, bool32 cardOrNews)
+{
+ if (cardOrNews == 0)
+ {
+ return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderCardThrownAway);
+ }
+ else
+ {
+ return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderNewsThrownAway);
+ }
+}
+
+bool32 mevent_save_game(u8 * state)
+{
+ switch (*state)
+ {
+ case 0:
+ AddTextPrinterToWindow1(gText_DataWillBeSaved);
+ (*state)++;
+ break;
+ case 1:
+ TrySavingData(0);
+ (*state)++;
+ break;
+ case 2:
+ AddTextPrinterToWindow1(gText_SaveCompletedPressA);
+ (*state)++;
+ break;
+ case 3:
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ (*state)++;
+ }
+ break;
+ case 4:
+ *state = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+const u8 * mevent_message(u32 * flag_p, u8 cardOrNews, u8 cardOrNewsSource, u32 msgId)
+{
+ const u8 * msg = NULL;
+ *flag_p = 0;
+
+ switch (msgId)
+ {
+ case 0:
+ *flag_p = 0;
+ msg = gText_NothingSentOver;
+ break;
+ case 1:
+ *flag_p = 0;
+ msg = gText_RecordUploadedViaWireless;
+ break;
+ case 2:
+ *flag_p = 1;
+ msg = cardOrNewsSource == 0 ? gText_WonderCardReceived : gText_WonderCardReceivedFrom;
+ break;
+ case 3:
+ *flag_p = 1;
+ msg = cardOrNewsSource == 0 ? gText_WonderNewsReceived : gText_WonderNewsReceivedFrom;
+ break;
+ case 4:
+ *flag_p = 1;
+ msg = gText_NewStampReceived;
+ break;
+ case 5:
+ *flag_p = 0;
+ msg = gText_AlreadyHadCard;
+ break;
+ case 6:
+ *flag_p = 0;
+ msg = gText_AlreadyHadStamp;
+ break;
+ case 7:
+ *flag_p = 0;
+ msg = gText_AlreadyHadNews;
+ break;
+ case 8:
+ *flag_p = 0;
+ msg = gText_NoMoreRoomForStamps;
+ break;
+ case 9:
+ *flag_p = 0;
+ msg = gText_CommunicationCanceled;
+ break;
+ case 10:
+ *flag_p = 0;
+ msg = cardOrNews == 0 ? gText_CantAcceptCardFromTrainer : gText_CantAcceptNewsFromTrainer;
+ break;
+ case 11:
+ *flag_p = 0;
+ msg = gText_CommunicationError;
+ break;
+ case 12:
+ *flag_p = 1;
+ msg = gText_NewTrainerReceived;
+ break;
+ case 13:
+ *flag_p = 1;
+ break;
+ case 14:
+ *flag_p = 0;
+ break;
+ }
+
+ return msg;
+}
+
+bool32 PrintMGSuccessMessage(u8 * state, const u8 * arg1, u16 * arg2)
+{
+ switch (*state)
+ {
+ case 0:
+ if (arg1 != NULL)
+ {
+ AddTextPrinterToWindow1(arg1);
+ }
+ PlayFanfare(MUS_FANFA4);
+ *arg2 = 0;
+ (*state)++;
+ break;
+ case 1:
+ if (++(*arg2) > 0xF0)
+ {
+ (*state)++;
+ }
+ break;
+ case 2:
+ if (IsFanfareTaskInactive())
+ {
+ *state = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+const u8 * mevent_message_stamp_card_etc_send_status(u32 * a0, u8 unused, u32 msgId)
+{
+ const u8 * result = gText_CommunicationError;
+ *a0 = 0;
+ switch (msgId)
+ {
+ case 0:
+ result = gText_NothingSentOver;
+ break;
+ case 1:
+ result = gText_RecordUploadedViaWireless;
+ break;
+ case 2:
+ result = gText_WonderCardSentTo;
+ *a0 = 1;
+ break;
+ case 3:
+ result = gText_WonderNewsSentTo;
+ *a0 = 1;
+ break;
+ case 4:
+ result = gText_StampSentTo;
+ break;
+ case 5:
+ result = gText_OtherTrainerHasCard;
+ break;
+ case 6:
+ result = gText_OtherTrainerHasStamp;
+ break;
+ case 7:
+ result = gText_OtherTrainerHasNews;
+ break;
+ case 8:
+ result = gText_NoMoreRoomForStamps;
+ break;
+ case 9:
+ result = gText_OtherTrainerCanceled;
+ break;
+ case 10:
+ result = gText_CantSendGiftToTrainer;
+ break;
+ case 11:
+ result = gText_CommunicationError;
+ break;
+ case 12:
+ result = gText_GiftSentTo;
+ break;
+ case 13:
+ result = gText_GiftSentTo;
+ break;
+ case 14:
+ result = gText_CantSendGiftToTrainer;
+ break;
+ }
+ return result;
+}
+
+bool32 PrintMGSendStatus(u8 * state, u16 * arg1, u8 arg2, u32 msgId)
+{
+ u32 flag;
+ const u8 * str = mevent_message_stamp_card_etc_send_status(&flag, arg2, msgId);
+ if (flag)
+ {
+ return PrintMGSuccessMessage(state, str, arg1);
+ }
+ else
+ {
+ return MG_PrintTextOnWindow1AndWaitButton(state, str);
+ }
+}
+
+void task_add_00_mystery_gift(void)
+{
+ u8 taskId = CreateTask(task00_mystery_gift, 0);
+ struct MysteryGiftTaskData * data = (void *)gTasks[taskId].data;
+ data->state = 0;
+ data->textState = 0;
+ data->unkA = 0;
+ data->unkB = 0;
+ data->IsCardOrNews = 0;
+ data->source = 0;
+ data->curPromptWindowId = 0;
+ data->unk2 = 0;
+ data->unk4 = 0;
+ data->unk6 = 0;
+ data->prevPromptWindowId = 0;
+ data->buffer = AllocZeroed(0x40);
+}
+
+void task00_mystery_gift(u8 taskId)
+{
+ struct MysteryGiftTaskData * data = (void *)gTasks[taskId].data;
+ u32 sp0;
+ const u8 * r1;
+
+ switch (data->state)
+ {
+ case 0:
+ data->state = 1;
+ break;
+ case 1:
+ switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->curPromptWindowId, FALSE))
+ {
+ case 0:
+ data->IsCardOrNews = 0;
+ if (ValidateReceivedWonderCard() == TRUE)
+ {
+ data->state = 18;
+ }
+ else
+ {
+ data->state = 2;
+ }
+ break;
+ case 1:
+ data->IsCardOrNews = 1;
+ if (ValidateReceivedWonderNews() == TRUE)
+ {
+ data->state = 18;
+ }
+ else
+ {
+ data->state = 2;
+ }
+ break;
+ case -2u:
+ data->state = 37;
+ break;
+ }
+ break;
+ case 2:
+ {
+ if (data->IsCardOrNews == 0)
+ {
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveCardNewOneInput))
+ {
+ data->state = 3;
+ PrintMysteryGiftOrEReaderTopMenu(0, 1);
+ }
+ }
+ else
+ {
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveNewsNewOneInput))
+ {
+ data->state = 3;
+ PrintMysteryGiftOrEReaderTopMenu(0, 1);
+ }
+ }
+ break;
+ }
+ case 3:
+ if (data->IsCardOrNews == 0)
+ {
+ AddTextPrinterToWindow1(gText_WhereShouldCardBeAccessed);
+ }
+ else
+ {
+ AddTextPrinterToWindow1(gText_WhereShouldNewsBeAccessed);
+ }
+ data->state = 4;
+ break;
+ case 4:
+ switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->curPromptWindowId, TRUE))
+ {
+ case 0:
+ ClearTextWindow();
+ data->state = 5;
+ data->source = 0;
+ break;
+ case 1:
+ ClearTextWindow();
+ data->state = 5;
+ data->source = 1;
+ break;
+ case -2u:
+ ClearTextWindow();
+ if (ValidateCardOrNews(data->IsCardOrNews))
+ {
+ data->state = 18;
+ }
+ else
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ }
+ break;
+ case 5:
+ {
+ register u8 eos asm("r1");
+ gStringVar1[0] = (eos = EOS);
+ gStringVar2[0] = eos;
+ gStringVar3[0] = eos;
+ }
+ switch (data->IsCardOrNews)
+ {
+ case 0:
+ if (data->source == 1)
+ {
+ MEvent_CreateTask_CardOrNewsWithFriend(0x15);
+ }
+ else if (data->source == 0)
+ {
+ MEvent_CreateTask_CardOrNewsOverWireless(0x15);
+ }
+ break;
+ case 1:
+ if (data->source == 1)
+ {
+ MEvent_CreateTask_CardOrNewsWithFriend(0x16);
+ }
+ else if (data->source == 0)
+ {
+ MEvent_CreateTask_CardOrNewsOverWireless(0x16);
+ }
+ break;
+ }
+ data->state = 6;
+ break;
+ case 6:
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = 7;
+ mevent_client_do_init();
+ }
+ else if (gSpecialVar_Result == 5)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = 3;
+ }
+ break;
+ case 7:
+ AddTextPrinterToWindow1(gText_Communicating);
+ data->state = 8;
+ break;
+ case 8:
+ switch (mevent_client_do_exec(&data->curPromptWindowId))
+ {
+ case 6:
+ task_add_05_task_del_08FA224_when_no_RfuFunc();
+ data->prevPromptWindowId = data->curPromptWindowId;
+ data->state = 13;
+ break;
+ case 5:
+ memcpy(data->buffer, mevent_client_get_buffer(), 0x40);
+ mevent_client_inc_flag();
+ break;
+ case 3:
+ data->state = 10;
+ break;
+ case 2:
+ data->state = 9;
+ break;
+ case 4:
+ data->state = 11;
+ StringCopy(gStringVar1, gLinkPlayers[0].name);
+ break;
+ }
+ break;
+ case 9:
+ switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, mevent_client_get_buffer()))
+ {
+ case 0:
+ mevent_client_set_param(0);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case 1:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case -1u:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ }
+ break;
+ case 10:
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, mevent_client_get_buffer()))
+ {
+ mevent_client_inc_flag();
+ data->state = 7;
+ }
+ break;
+ case 11:
+ switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_ThrowAwayWonderCard))
+ {
+ case 0:
+ if (CheckReceivedGiftFromWonderCard() == TRUE)
+ {
+ data->state = 12;
+ }
+ else
+ {
+ mevent_client_set_param(0);
+ mevent_client_inc_flag();
+ data->state = 7;
+ }
+ break;
+ case 1:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case -1u:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ }
+ break;
+ case 12:
+ switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_HaventReceivedCardsGift))
+ {
+ case 0:
+ mevent_client_set_param(0);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case 1:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case -1u:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ }
+ break;
+ case 13:
+ if (IsNoOneConnected())
+ {
+ DestroyWirelessStatusIndicatorSprite();
+ data->state = 14;
+ }
+ break;
+ case 14:
+ if (PrintStringAndWait2Seconds(&data->textState, gText_CommunicationCompleted))
+ {
+ if (data->source == 1)
+ {
+ StringCopy(gStringVar1, gLinkPlayers[0].name);
+ }
+ data->state = 15;
+ }
+ break;
+ case 15:
+ {
+ register bool32 flag asm("r1");
+ r1 = mevent_message(&sp0, data->IsCardOrNews, data->source, data->prevPromptWindowId);
+ if (r1 == NULL)
+ {
+ r1 = data->buffer;
+ }
+ if (sp0)
+ {
+ flag = PrintMGSuccessMessage(&data->textState, r1, &data->curPromptWindowId);
+ }
+ else
+ {
+ flag = MG_PrintTextOnWindow1AndWaitButton(&data->textState, r1);
+ }
+ if (flag)
+ {
+ if (data->prevPromptWindowId == 3)
+ {
+ if (data->source == 1)
+ {
+ GenerateRandomNews(1);
+ }
+ else
+ {
+ GenerateRandomNews(2);
+ }
+ }
+ if (sp0 == 0)
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ else
+ {
+ data->state = 17;
+ }
+ }
+ break;
+ }
+ case 16:
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError))
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ case 17:
+ if (mevent_save_game(&data->textState))
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ case 18:
+ if (HandleLoadWonderCardOrNews(&data->textState, data->IsCardOrNews))
+ {
+ data->state = 20;
+ }
+ break;
+ case 20:
+ if (data->IsCardOrNews == 0)
+ {
+ if (JOY_NEW(A_BUTTON))
+ {
+ data->state = 21;
+ }
+ if (JOY_NEW(B_BUTTON))
+ {
+ data->state = 27;
+ }
+ }
+ else
+ {
+ switch (MENews_GetInput(gMain.newKeys))
+ {
+ case 0:
+ MENews_RemoveScrollIndicatorArrowPair();
+ data->state = 21;
+ break;
+ case 1:
+ data->state = 27;
+ break;
+ }
+ }
+ break;
+ case 21:
+ {
+ u32 result;
+ if (data->IsCardOrNews == 0)
+ {
+ if (WonderCard_Test_Unk_08_6())
+ {
+ result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, FALSE);
+ }
+ else
+ {
+ result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, TRUE);
+ }
+ }
+ else
+ {
+ if (WonderNews_Test_Unk_02())
+ {
+ result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, FALSE);
+ }
+ else
+ {
+ result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, TRUE);
+ }
+ }
+ switch (result)
+ {
+ case 0:
+ data->state = 28;
+ break;
+ case 1:
+ data->state = 29;
+ break;
+ case 2:
+ data->state = 22;
+ break;
+ case -2u:
+ if (data->IsCardOrNews == 1)
+ {
+ MENews_AddScrollIndicatorArrowPair();
+ }
+ data->state = 20;
+ break;
+ }
+ break;
+ }
+ case 22:
+ switch (mevent_message_prompt_discard(&data->textState, &data->curPromptWindowId, data->IsCardOrNews))
+ {
+ case 0:
+ if (data->IsCardOrNews == 0 && CheckReceivedGiftFromWonderCard() == TRUE)
+ {
+ data->state = 23;
+ }
+ else
+ {
+ data->state = 24;
+ }
+ break;
+ case 1:
+ data->state = 21;
+ break;
+ case -1:
+ data->state = 21;
+ break;
+ }
+ break;
+ case 23:
+ switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, TRUE, gText_HaventReceivedGiftOkayToDiscard))
+ {
+ case 0:
+ data->state = 24;
+ break;
+ case 1:
+ data->state = 21;
+ break;
+ case -1u:
+ data->state = 21;
+ break;
+ }
+ break;
+ case 24:
+ if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1))
+ {
+ DestroyNewsOrCard(data->IsCardOrNews);
+ data->state = 25;
+ }
+ break;
+ case 25:
+ if (mevent_save_game(&data->textState))
+ {
+ data->state = 26;
+ }
+ break;
+ case 26:
+ if (mevent_message_was_thrown_away(&data->textState, data->IsCardOrNews))
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ case 27:
+ if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 0))
+ {
+ data->state = 0;
+ }
+ break;
+ case 28:
+ if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1))
+ {
+ data->state = 3;
+ }
+ break;
+ case 29:
+ if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1))
+ {
+ switch (data->IsCardOrNews)
+ {
+ case 0:
+ MEvent_CreateTask_Leader(21);
+ break;
+ case 1:
+ MEvent_CreateTask_Leader(22);
+ break;
+ }
+ data->source = 1;
+ data->state = 30;
+ }
+ break;
+ case 30:
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ ClearScreenInBg0(1);
+ data->state = 31;
+ }
+ else if (gSpecialVar_Result == 5)
+ {
+ ClearScreenInBg0(1);
+ data->state = 18;
+ }
+ break;
+ case 31:
+ {
+ register u8 eos asm("r1");
+ gStringVar1[0] = (eos = EOS);
+ gStringVar2[0] = eos;
+ gStringVar3[0] = eos;
+ }
+ if (data->IsCardOrNews == 0)
+ {
+ AddTextPrinterToWindow1(gText_SendingWonderCard);
+ mevent_srv_new_wcard();
+ }
+ else
+ {
+ AddTextPrinterToWindow1(gText_SendingWonderNews);
+ mevent_srv_init_wnews();
+ }
+ data->state = 32;
+ break;
+ case 32:
+ if (mevent_srv_common_do_exec(&data->curPromptWindowId) == 3)
+ {
+ data->prevPromptWindowId = data->curPromptWindowId;
+ data->state = 33;
+ }
+ break;
+ case 33:
+ task_add_05_task_del_08FA224_when_no_RfuFunc();
+ StringCopy(gStringVar1, gLinkPlayers[1].name);
+ data->state = 34;
+ break;
+ case 34:
+ if (IsNoOneConnected())
+ {
+ DestroyWirelessStatusIndicatorSprite();
+ data->state = 35;
+ }
+ break;
+ case 35:
+ if (PrintMGSendStatus(&data->textState, &data->curPromptWindowId, data->source, data->prevPromptWindowId))
+ {
+ if (data->source == 1 && data->prevPromptWindowId == 3)
+ {
+ GenerateRandomNews(3);
+ data->state = 17;
+ }
+ else
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ }
+ break;
+ case 36:
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError))
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ case 37:
+ CloseLink();
+ sub_812B484();
+ Free(data->buffer);
+ DestroyTask(taskId);
+ SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
+ break;
+ }
+}
+
+u16 GetMysteryGiftBaseBlock(void)
+{
+ return 0x19B;
+}
diff --git a/src/oak_speech.c b/src/oak_speech.c
new file mode 100644
index 000000000..3bf174778
--- /dev/null
+++ b/src/oak_speech.c
@@ -0,0 +1,1891 @@
+#include "global.h"
+#include "main.h"
+#include "decompress.h"
+#include "task.h"
+#include "malloc.h"
+#include "gpu_regs.h"
+#include "wild_encounter.h"
+#include "palette.h"
+#include "blend_palette.h"
+#include "text.h"
+#include "window.h"
+#include "text_window.h"
+#include "bg.h"
+#include "menu.h"
+#include "help_system.h"
+#include "new_menu_helpers.h"
+#include "pokemon_3.h"
+#include "sound.h"
+#include "event_scripts.h"
+#include "scanline_effect.h"
+#include "string_util.h"
+#include "pokeball.h"
+#include "naming_screen.h"
+#include "math_util.h"
+#include "overworld.h"
+#include "random.h"
+#include "oak_speech.h"
+#include "constants/species.h"
+#include "constants/songs.h"
+
+struct OakSpeechResources
+{
+ void * solidColorsGfx;
+ void * trainerPicTilemapBuffer;
+ void * unk_0008;
+ u8 filler_000C[4];
+ u16 unk_0010;
+ u16 unk_0012;
+ u16 unk_0014[4];
+ u8 unk_001C[3];
+ u8 textSpeed;
+ u8 filler_0020[0x1800];
+ u8 bg2TilemapBuffer[0x400];
+ u8 bg1TilemapBuffer[0x800];
+}; //size=0x2420
+
+EWRAM_DATA struct OakSpeechResources * sOakSpeechResources = NULL;
+
+static void Task_OaksSpeech1(u8 taskId);
+static void CreateHelpDocsPage1(void);
+static void Task_OaksSpeech2(u8 taskId);
+static void Task_OakSpeech3(u8 taskId);
+static void Task_OakSpeech5(u8 taskId);
+static void Task_OakSpeech6(u8 taskId);
+static void Task_OakSpeech7(u8 taskId);
+static void Task_OakSpeech8(u8 taskId);
+static void Task_OakSpeech9(u8 taskId);
+static void Task_OakSpeech10(u8 taskId);
+static void Task_OakSpeech10(u8 taskId);
+static void Task_OakSpeech11(u8 taskId);
+static void Task_OakSpeech12(u8 taskId);
+static void Task_OakSpeech13(u8 taskId);
+static void Task_OakSpeech14(u8 taskId);
+static void Task_OakSpeech15(u8 taskId);
+static void Task_OakSpeech16(u8 taskId);
+static void Task_OakSpeech17(u8 taskId);
+static void Task_OakSpeech18(u8 taskId);
+static void Task_OakSpeech19(u8 taskId);
+static void Task_OakSpeech20(u8 taskId);
+static void Task_OakSpeech21(u8 taskId);
+static void Task_OakSpeech22(u8 taskId);
+static void Task_OakSpeech23(u8 taskId);
+static void Task_OakSpeech24(u8 taskId);
+static void Task_OakSpeech29(u8 taskId);
+static void Task_OakSpeech25(u8 taskId);
+static void Task_OakSpeech26(u8 taskId);
+static void Task_OakSpeech27(u8 taskId);
+static void Task_OakSpeech30(u8 taskId);
+static void Task_OakSpeech31(u8 taskId);
+static void Task_OakSpeech32(u8 taskId);
+static void Task_OakSpeech34(u8 taskId);
+static void Task_OakSpeech33(u8 taskId);
+static void Task_OakSpeech36(u8 taskId);
+static void Task_OakSpeech37(u8 taskId);
+static void Task_OakSpeech38(u8 taskId);
+static void Task_OakSpeech38_3(u8 taskId);
+static void Task_OakSpeech39(u8 taskId);
+static void Task_OakSpeech38_1(u8 taskId);
+static void Task_OakSpeech38_sub1(u8 taskId);
+static void Task_OakSpeech38_2(u8 taskId);
+static void Task_OakSpeech38_sub2(u8 taskId);
+static void Task_OakSpeech40(u8 taskId);
+static void Task_OakSpeech41(u8 taskId);
+static void Task_OakSpeech42(u8 taskId);
+
+static void CB2_ReturnFromNamingScreen(void);
+static void CreateNidoranFSprite(u8 taskId);
+static void CreatePikaOrGrassPlatformSpriteAndLinkToCurrentTask(u8 taskId, u8 state);
+static void DestroyLinkedPikaOrGrassPlatformSprites(u8 taskId, u8 state);
+static void LoadOaksSpeechTrainerPic(u16 whichPic, u16 tileOffset);
+static void DestroyOaksSpeechTrainerPic(void);
+static void CreateFadeInTask(u8 taskId, u8 state);
+static void CreateFadeOutTask(u8 taskId, u8 state);
+static void PrintNameChoiceOptions(u8 taskId, u8 state);
+static void GetDefaultName(u8 arg0, u8 namePick);
+
+extern const u8 gText_Controls[];
+extern const u8 gText_ABUTTONNext[];
+extern const u8 gText_ABUTTONNext_BBUTTONBack[];
+extern const u8 gText_Boy[];
+extern const u8 gText_Girl[];
+
+extern const struct CompressedSpriteSheet gUnknown_8235194[];
+extern const struct CompressedSpritePalette gUnknown_82373F4;
+
+ALIGNED(4) static const u16 sHelpDocsPalette[] = INCBIN_U16("data/oak_speech/help_docs_palette.gbapal");
+static const u32 sOakSpeechGfx_GameStartHelpUI[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_game_start_help_u_i.4bpp.lz");
+static const u32 sNewGameAdventureIntroTilemap[] = INCBIN_U32("data/oak_speech/new_game_adventure_intro_tilemap.bin.lz");
+static const u32 sOakSpeechGfx_SolidColors[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_solid_colors.4bpp.lz");
+static const u32 sOakSpeech_BackgroundTilemap[] = INCBIN_U32("data/oak_speech/oak_speech_background_tilemap.bin.lz");
+static const u16 sHelpDocsPage2Tilemap[] = INCBIN_U16("data/oak_speech/help_docs_page2_tilemap.bin");
+static const u16 sHelpDocsPage3Tilemap[] = INCBIN_U16("data/oak_speech/help_docs_page3_tilemap.bin");
+static const u16 sOakSpeechGfx_LeafPal[] = INCBIN_U16("data/oak_speech/oak_speech_gfx_leaf_pal.gbapal");
+static const u32 sOakSpeechGfx_LeafPic[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_leaf_pic.8bpp.lz");
+static const u16 sOakSpeechGfx_RedPal[] = INCBIN_U16("data/oak_speech/oak_speech_gfx_red_pal.gbapal");
+static const u32 sOakSpeechGfx_RedPic[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_red_pic.8bpp.lz");
+static const u16 sOakSpeechGfx_OakPal[] = INCBIN_U16("data/oak_speech/oak_speech_gfx_oak_pal.gbapal");
+static const u32 sOakSpeechGfx_OakPic[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_oak_pic.8bpp.lz");
+static const u16 sOakSpeechGfx_RivalPal[] = INCBIN_U16("data/oak_speech/oak_speech_gfx_rival_pal.gbapal");
+static const u32 sOakSpeechGfx_RivalPic[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_rival_pic.8bpp.lz");
+static const u16 sOakSpeech_GrassPlatformPalette[] = INCBIN_U16("data/oak_speech/oak_speech_grass_platform_palette.gbapal");
+static const u16 sOakSpeech_PikaPalette[] = INCBIN_U16("data/oak_speech/oak_speech_pika_palette.gbapal");
+static const u32 sOakSpeechGfx_GrassPlatform[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_grass_platform.4bpp.lz");
+static const u32 sOakSpeechGfx_Pika1[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_pika1.4bpp.lz");
+static const u32 sOakSpeechGfx_Pika2[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_pika2.4bpp.lz");
+static const u32 sOakSpeechGfx_PikaEyes[] = INCBIN_U32("data/oak_speech/oak_speech_gfx_pika_eyes.4bpp.lz");
+
+static const struct BgTemplate sBgTemplates[3] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x000
+ }, {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 28,
+ .screenSize = 1,
+ .paletteMode = 1,
+ .priority = 1,
+ .baseTile = 0x000
+ }
+};
+
+static const struct WindowTemplate sHelpDocsWindowTemplates1[] = {
+ {
+ .bg = 0x00,
+ .tilemapLeft = 0x00,
+ .tilemapTop = 0x07,
+ .width = 0x1e,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0001
+ }, DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate sHelpDocsWindowTemplates2[] = {
+ {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x03,
+ .width = 0x18,
+ .height = 0x06,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0001
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0a,
+ .width = 0x18,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0092
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0f,
+ .width = 0x18,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x00f3
+ }, DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate sHelpDocsWindowTemplates3[] = {
+ {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x03,
+ .width = 0x18,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0001
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x08,
+ .width = 0x18,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0062
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x06,
+ .tilemapTop = 0x0d,
+ .width = 0x18,
+ .height = 0x06,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x00c3
+ }, DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate *const sHelpDocsWindowTemplatePtrs[3] = {
+ sHelpDocsWindowTemplates1,
+ sHelpDocsWindowTemplates2,
+ sHelpDocsWindowTemplates3
+};
+
+static const struct WindowTemplate sNewGameAdventureIntroWindowTemplates[] = {
+ {
+ .bg = 0x00,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x04,
+ .width = 0x1c,
+ .height = 0x0f,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0001
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x12,
+ .tilemapTop = 0x09,
+ .width = 0x09,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0174
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x02,
+ .tilemapTop = 0x02,
+ .width = 0x06,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0180
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x02,
+ .tilemapTop = 0x02,
+ .width = 0x0c,
+ .height = 0x0a,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0001
+ }, DUMMY_WIN_TEMPLATE
+};
+
+ALIGNED(4) const struct TextColor sTextColor_HelpSystem = {
+ 0x00, 0x01, 0x02
+};
+
+ALIGNED(4) const struct TextColor sTextColor_OakSpeech = {
+ 0x00, 0x02, 0x03
+};
+
+static const u8 *const sNewGameAdventureIntroTextPointers[] = {
+ gNewGameAdventureIntro1,
+ gNewGameAdventureIntro2,
+ gNewGameAdventureIntro3
+};
+
+static const struct CompressedSpriteSheet sOakSpeech_PikaSpriteSheets[3] = {
+ { (const void *)sOakSpeechGfx_Pika1, 0x0400, 0x1001 },
+ { (const void *)sOakSpeechGfx_Pika2, 0x0200, 0x1002 },
+ { (const void *)sOakSpeechGfx_PikaEyes, 0x0080, 0x1003 },
+};
+
+static const struct CompressedSpriteSheet sOakSpeech_GrassPlatformSpriteSheet = {
+ (const void *)sOakSpeechGfx_GrassPlatform, 0x0600, 0x1000
+};
+
+static const struct SpritePalette sOakSpeech_PikaSpritePal = {
+ (const void *)sOakSpeech_PikaPalette, 0x1001
+};
+
+static const struct SpritePalette sOakSpeech_GrassPlatformSpritePal = {
+ (const void *)sOakSpeech_GrassPlatformPalette, 0x1000
+};
+
+static const union AnimCmd sGrassPlatformAnim1[] = {
+ ANIMCMD_FRAME( 0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sGrassPlatformAnim2[] = {
+ ANIMCMD_FRAME(16, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sGrassPlatformAnim3[] = {
+ ANIMCMD_FRAME(32, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sGrassPlatformAnims1[] = {
+ sGrassPlatformAnim1
+};
+static const union AnimCmd *const sGrassPlatformAnims2[] = {
+ sGrassPlatformAnim2
+};
+static const union AnimCmd *const sGrassPlatformAnims3[] = {
+ sGrassPlatformAnim3
+};
+
+extern const struct OamData gOamData_83ACAF8;
+
+static const struct SpriteTemplate sOakSpeech_GrassPlatformSpriteTemplates[3] = {
+ { 0x1000, 0x1000, &gOamData_83ACAF8, sGrassPlatformAnims1, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy },
+ { 0x1000, 0x1000, &gOamData_83ACAF8, sGrassPlatformAnims2, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy },
+ { 0x1000, 0x1000, &gOamData_83ACAF8, sGrassPlatformAnims3, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy },
+};
+
+static const union AnimCmd sPikaAnim1[] = {
+ ANIMCMD_FRAME( 0, 30),
+ ANIMCMD_FRAME(16, 30),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd sPikaAnim2[] = {
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(8, 12),
+ ANIMCMD_FRAME(0, 12),
+ ANIMCMD_FRAME(8, 12),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(8, 12),
+ ANIMCMD_FRAME(0, 12),
+ ANIMCMD_FRAME(8, 12),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd sPikaAnim3[] = {
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(2, 8),
+ ANIMCMD_FRAME(0, 8),
+ ANIMCMD_FRAME(2, 8),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(0, 60),
+ ANIMCMD_FRAME(2, 8),
+ ANIMCMD_FRAME(0, 8),
+ ANIMCMD_FRAME(2, 8),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd *const sPikaAnims1[] = {
+ sPikaAnim1
+};
+static const union AnimCmd *const sPikaAnims2[] = {
+ sPikaAnim2
+};
+static const union AnimCmd *const sPikaAnims3[] = {
+ sPikaAnim3
+};
+
+extern const struct OamData gOamData_83AC9D8;
+extern const struct OamData gOamData_83AC9F8;
+extern const struct OamData gOamData_83AC9E8;
+
+static const struct SpriteTemplate sOakSpeech_PikaSpriteTemplates[3] = {
+ { 0x1001, 0x1001, &gOamData_83AC9D8, sPikaAnims1, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy },
+ { 0x1002, 0x1001, &gOamData_83AC9F8, sPikaAnims2, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy },
+ { 0x1003, 0x1001, &gOamData_83AC9E8, sPikaAnims3, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy }
+};
+
+static const u8 *const sHelpDocsPtrs[] = {
+ gNewGame_HelpDocs2, gNewGame_HelpDocs3, gNewGame_HelpDocs4,
+ gNewGame_HelpDocs5, gNewGame_HelpDocs6, gNewGame_HelpDocs7
+};
+
+static const u8 *const sMaleNameChoices[] = {
+ gNameChoice_Red,
+ gNameChoice_Fire,
+ gNameChoice_Ash,
+ gNameChoice_Kene,
+ gNameChoice_Geki,
+ gNameChoice_Jak,
+ gNameChoice_Janne,
+ gNameChoice_Jonn,
+ gNameChoice_Kamon,
+ gNameChoice_Karl,
+ gNameChoice_Taylor,
+ gNameChoice_Oscar,
+ gNameChoice_Hiro,
+ gNameChoice_Max,
+ gNameChoice_Jon,
+ gNameChoice_Ralph,
+ gNameChoice_Kay,
+ gNameChoice_Tosh,
+ gNameChoice_Roak
+};
+
+static const u8 *const sFemaleNameChoices[] = {
+ gNameChoice_Red,
+ gNameChoice_Fire,
+ gNameChoice_Omi,
+ gNameChoice_Jodi,
+ gNameChoice_Amanda,
+ gNameChoice_Hillary,
+ gNameChoice_Makey,
+ gNameChoice_Michi,
+ gNameChoice_Paula,
+ gNameChoice_June,
+ gNameChoice_Cassie,
+ gNameChoice_Rey,
+ gNameChoice_Seda,
+ gNameChoice_Kiko,
+ gNameChoice_Mina,
+ gNameChoice_Norie,
+ gNameChoice_Sai,
+ gNameChoice_Momo,
+ gNameChoice_Suzi
+};
+
+static const u8 *const sRivalNameChoices[] = {
+ gNameChoice_Green,
+ gNameChoice_Gary,
+ gNameChoice_Kaz,
+ gNameChoice_Toru
+};
+
+static void VBlankCB_NewGameOaksSpeech(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void CB2_NewGameOaksSpeech(void)
+{
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+void StartNewGameScene(void)
+{
+ gPlttBufferUnfaded[0] = RGB_BLACK;
+ gPlttBufferFaded[0] = RGB_BLACK;
+ CreateTask(Task_OaksSpeech1, 0);
+ SetMainCallback2(CB2_NewGameOaksSpeech);
+}
+
+static void Task_OaksSpeech1(u8 taskId)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL);
+ SetHBlankCallback(NULL);
+ DmaFill16(3, 0, VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, OAM, OAM_SIZE);
+ DmaFill16(3, 0, PLTT + sizeof(u16), PLTT_SIZE - 2);
+ ResetPaletteFade();
+ ScanlineEffect_Stop();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ reset_temp_tile_data_buffers();
+ HelpSystem_SetSomeVariable2(2);
+ break;
+ case 1:
+ sOakSpeechResources = AllocZeroed(sizeof(*sOakSpeechResources));
+ SetUpMonSpriteManagerMaybe(1, 1);
+ break;
+ case 2:
+ SetGpuReg(REG_OFFSET_WIN0H, 0);
+ SetGpuReg(REG_OFFSET_WIN0V, 0);
+ SetGpuReg(REG_OFFSET_WIN1H, 0);
+ SetGpuReg(REG_OFFSET_WIN1V, 0);
+ SetGpuReg(REG_OFFSET_WININ, 0);
+ SetGpuReg(REG_OFFSET_WINOUT, 0);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ break;
+ case 3:
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(1, sBgTemplates, NELEMS(sBgTemplates));
+ SetBgTilemapBuffer(1, sOakSpeechResources->bg1TilemapBuffer);
+ SetBgTilemapBuffer(2, sOakSpeechResources->bg2TilemapBuffer);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ gSpriteCoordOffsetX = 0;
+ gSpriteCoordOffsetY = 0;
+ break;
+ case 4:
+ gPaletteFade.bufferTransferDisabled = TRUE;
+ InitStandardTextBoxWindows();
+ ResetBg0();
+ Menu_LoadStdPalAt(0xD0);
+ LoadPalette(sHelpDocsPalette, 0x000, 0x080);
+ LoadPalette(stdpal_get(2) + 15, 0x000, 0x002);
+ break;
+ case 5:
+ sOakSpeechResources->textSpeed = GetTextSpeedSetting();
+ gTextFlags.canABSpeedUpPrint = TRUE;
+ decompress_and_copy_tile_data_to_vram(1, sOakSpeechGfx_GameStartHelpUI, 0, 0, 0);
+ break;
+ case 6:
+ if (free_temp_tile_data_buffers_if_possible())
+ return;
+ ClearDialogWindowAndFrame(0, 1);
+ FillBgTilemapBufferRect_Palette0(1, 0x0000, 0, 0, 32, 32);
+ CopyBgTilemapBufferToVram(1);
+ break;
+ case 7:
+ CreateWindow_SnapRight_StdPal(0, 30, 0, 13, 0x1C4);
+ FillBgTilemapBufferRect_Palette0(1, 0xD00F, 0, 0, 30, 2);
+ FillBgTilemapBufferRect_Palette0(1, 0xD002, 0, 2, 30, 1);
+ FillBgTilemapBufferRect_Palette0(1, 0xD00E, 0, 19, 30, 1);
+ CreateHelpDocsPage1();
+ gPaletteFade.bufferTransferDisabled = FALSE;
+ gTasks[taskId].data[5] = CreateTextCursorSpriteForOakSpeech(0, 0xE6, 0x95, 0, 0);
+ BlendPalettes(0xFFFFFFFF, 0x10, 0x00);
+ break;
+ case 10:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
+ ShowBg(0);
+ ShowBg(1);
+ SetVBlankCallback(VBlankCB_NewGameOaksSpeech);
+ PlayBGM(BGM_FRLG_GAME_EXPLANATION_START);
+ gTasks[taskId].func = Task_OaksSpeech2;
+ gMain.state = 0;
+ return;
+ }
+
+ gMain.state++;
+}
+
+static void CreateHelpDocsPage1(void)
+{
+ Menu_PrintHelpSystemUIHeader(gText_Controls, gText_ABUTTONNext, 0, 0, 1);
+ sOakSpeechResources->unk_0014[0] = AddWindow(sHelpDocsWindowTemplatePtrs[sOakSpeechResources->unk_0012]);
+ PutWindowTilemap(sOakSpeechResources->unk_0014[0]);
+ FillWindowPixelBuffer(sOakSpeechResources->unk_0014[0], 0x00);
+ AddTextPrinterParameterized4(sOakSpeechResources->unk_0014[0], 2, 2, 0, 1, 1, &sTextColor_HelpSystem, 0, gNewGame_HelpDocs1);
+ CopyWindowToVram(sOakSpeechResources->unk_0014[0], 3);
+ FillBgTilemapBufferRect_Palette0(1, 0x3000, 1, 3, 5, 16);
+ CopyBgTilemapBufferToVram(1);
+}
+
+static void Task_OakSpeech4(u8 taskId)
+{
+ u8 i = 0;
+ u8 r7 = sOakSpeechResources->unk_0012 - 1;
+ if (sOakSpeechResources->unk_0012 == 0)
+ {
+ CreateHelpDocsPage1();
+ }
+ else
+ {
+ PrintTextOnRightSnappedWindow(gText_ABUTTONNext_BBUTTONBack, 0, 1);
+ for (i = 0; i < 3; i++)
+ {
+ sOakSpeechResources->unk_0014[i] = AddWindow(&sHelpDocsWindowTemplatePtrs[sOakSpeechResources->unk_0012][i]);
+ PutWindowTilemap(sOakSpeechResources->unk_0014[i]);
+ FillWindowPixelBuffer(sOakSpeechResources->unk_0014[i], 0x00);
+ AddTextPrinterParameterized4(sOakSpeechResources->unk_0014[i], 2, 6, 0, 1, 1, &sTextColor_HelpSystem, 0, sHelpDocsPtrs[i + r7 * 3]);
+ CopyWindowToVram(sOakSpeechResources->unk_0014[i], 3);
+ }
+
+ if (sOakSpeechResources->unk_0012 == 1)
+ {
+ CopyToBgTilemapBufferRect(1, sHelpDocsPage2Tilemap, 1, 3, 5, 16);
+ }
+ else
+ {
+ CopyToBgTilemapBufferRect(1, sHelpDocsPage3Tilemap, 1, 3, 5, 16);
+ }
+ CopyBgTilemapBufferToVram(1);
+ }
+ BeginNormalPaletteFade(0xFFFFDFFF, -1, 16, 0, stdpal_get(2)[15]);
+ gTasks[taskId].func = Task_OaksSpeech2;
+}
+
+static void Task_OaksSpeech2(u8 taskId)
+{
+ if (!gPaletteFade.active && JOY_NEW((A_BUTTON | B_BUTTON)))
+ {
+ if (JOY_NEW(A_BUTTON))
+ {
+ gTasks[taskId].data[15] = 1;
+ if (sOakSpeechResources->unk_0012 < 2)
+ {
+ BeginNormalPaletteFade(0xFFFFDFFF, -1, 0, 16, stdpal_get(2)[15]);
+ }
+ }
+ else
+ {
+ if (sOakSpeechResources->unk_0012 != 0)
+ {
+ gTasks[taskId].data[15] = -1;
+ BeginNormalPaletteFade(0xFFFFDFFF, -1, 0, 16, stdpal_get(2)[15]);
+ }
+ else
+ return;
+ }
+ }
+ else
+ return;
+ PlaySE(SE_SELECT);
+ gTasks[taskId].func = Task_OakSpeech3;
+}
+
+static void Task_OakSpeech3(u8 taskId)
+{
+ u8 r8 = 0;
+ u8 i;
+
+ if (!gPaletteFade.active)
+ {
+ switch (sOakSpeechResources->unk_0012) {
+ case 0:
+ r8 = 1;
+ break;
+ case 1:
+ case 2:
+ r8 = 3;
+ break;
+ }
+ sOakSpeechResources->unk_0012 += gTasks[taskId].data[15];
+ if (sOakSpeechResources->unk_0012 < 3)
+ {
+ for (i = 0; i < r8; i++)
+ {
+ FillWindowPixelBuffer(sOakSpeechResources->unk_0014[i], 0x00);
+ ClearWindowTilemap(sOakSpeechResources->unk_0014[i]);
+ CopyWindowToVram(sOakSpeechResources->unk_0014[i], 3);
+ RemoveWindow(sOakSpeechResources->unk_0014[i]);
+ sOakSpeechResources->unk_0014[i] = 0;
+ }
+ gTasks[taskId].func = Task_OakSpeech4;
+ }
+ else
+ {
+ BeginNormalPaletteFade(0xFFFFFFFF, 2, 0, 16, 0);
+ gTasks[taskId].func = Task_OakSpeech5;
+ }
+ }
+}
+
+static void Task_OakSpeech5(u8 taskId)
+{
+ u8 i = 0;
+
+ if (!gPaletteFade.active)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ FillWindowPixelBuffer(sOakSpeechResources->unk_0014[i], 0x00);
+ ClearWindowTilemap(sOakSpeechResources->unk_0014[i]);
+ CopyWindowToVram(sOakSpeechResources->unk_0014[i], 3);
+ RemoveWindow(sOakSpeechResources->unk_0014[i]);
+ sOakSpeechResources->unk_0014[i] = 0;
+ }
+ FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 2, 30, 18);
+ CopyBgTilemapBufferToVram(1);
+ sub_8006398(gTasks[taskId].data[5]);
+ sOakSpeechResources->unk_0014[0] = RGB_BLACK;
+ LoadPalette(sOakSpeechResources->unk_0014, 0, 2);
+ gTasks[taskId].data[3] = 32;
+ gTasks[taskId].func = Task_OakSpeech6;
+ }
+}
+
+static void Task_OakSpeech6(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u32 sp14 = 0;
+
+ if (data[3] != 0)
+ data[3]--;
+ else
+ {
+ PlayBGM(BGM_FRLG_GAME_EXPLANATION_MIDDLE);
+ sub_810F71C();
+ PrintTextOnRightSnappedWindow(gText_ABUTTONNext, 0, 1);
+ sOakSpeechResources->unk_0008 = malloc_and_decompress(sNewGameAdventureIntroTilemap, &sp14);
+ CopyToBgTilemapBufferRect(1, sOakSpeechResources->unk_0008, 0, 2, 30, 19);
+ CopyBgTilemapBufferToVram(1);
+ Free(sOakSpeechResources->unk_0008);
+ sOakSpeechResources->unk_0008 = NULL;
+ data[14] = AddWindow(&sNewGameAdventureIntroWindowTemplates[0]);
+ PutWindowTilemap(data[14]);
+ FillWindowPixelBuffer(data[14], 0x00);
+ CopyWindowToVram(data[14], 3);
+ sOakSpeechResources->unk_0012 = 0;
+ gMain.state = 0;
+ data[15] = 16;
+ AddTextPrinterParameterized4(data[14], 2, 3, 5, 1, 0, &sTextColor_OakSpeech, 0, sNewGameAdventureIntroTextPointers[0]);
+ data[5] = CreateTextCursorSpriteForOakSpeech(0, 0xe2, 0x91, 0, 0);
+ gSprites[data[5]].oam.objMode = ST_OAM_OBJ_BLEND;
+ gSprites[data[5]].oam.priority = 0;
+ CreatePikaOrGrassPlatformSpriteAndLinkToCurrentTask(taskId, 0);
+ BeginNormalPaletteFade(0xFFFFFFFF, 2, 16, 0, 0);
+ gTasks[taskId].func = Task_OakSpeech7;
+ }
+}
+
+static void Task_OakSpeech7(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ switch (gMain.state)
+ {
+ case 0:
+ if (!gPaletteFade.active)
+ {
+ SetGpuReg(REG_OFFSET_WIN0H, 0x00F0);
+ SetGpuReg(REG_OFFSET_WIN0V, 0x10A0);
+ SetGpuReg(REG_OFFSET_WININ, 0x003F);
+ SetGpuReg(REG_OFFSET_WINOUT, 0x001F);
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ if (JOY_NEW((A_BUTTON | B_BUTTON)))
+ {
+ if (JOY_NEW(A_BUTTON))
+ {
+ sOakSpeechResources->unk_0012++;
+ }
+ else if (sOakSpeechResources->unk_0012 != 0)
+ {
+ sOakSpeechResources->unk_0012--;
+ }
+ else
+ {
+ break;
+ }
+ PlaySE(SE_SELECT);
+ if (sOakSpeechResources->unk_0012 == 3)
+ {
+ gMain.state = 4;
+ }
+ else
+ {
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1);
+ SetGpuReg(REG_OFFSET_BLDALPHA, (16 - data[15]) | data[15]);
+ gMain.state++;
+ }
+ }
+ break;
+ case 2:
+ data[15] -= 2;
+ SetGpuReg(REG_OFFSET_BLDALPHA, ((16 - data[15]) << 8) | data[15]);
+ if (data[15] <= 0)
+ {
+ FillWindowPixelBuffer(data[14], 0x00);
+ AddTextPrinterParameterized4(data[14], 2, 3, 5, 1, 0, &sTextColor_OakSpeech, 0, sNewGameAdventureIntroTextPointers[sOakSpeechResources->unk_0012]);
+ if (sOakSpeechResources->unk_0012 == 0)
+ {
+ sub_810F71C();
+ PrintTextOnRightSnappedWindow(gText_ABUTTONNext, 0, 1);
+ }
+ else
+ {
+ sub_810F71C();
+ PrintTextOnRightSnappedWindow(gText_ABUTTONNext_BBUTTONBack, 0, 1);
+ }
+ gMain.state++;
+ }
+ break;
+ case 3:
+ data[15] += 2;
+ SetGpuReg(REG_OFFSET_BLDALPHA, ((16 - data[15]) << 8) | data[15]);
+ if (data[15] >= 16)
+ {
+ data[15] = 16;
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ gMain.state = 1;
+ }
+ break;
+ case 4:
+ sub_8006398(gTasks[taskId].data[5]);
+ PlayBGM(BGM_FRLG_GAME_EXPLANATION_END);
+ data[15] = 24;
+ gMain.state++;
+ break;
+ default:
+ if (data[15] != 0)
+ data[15]--;
+ else
+ {
+ gMain.state = 0;
+ sOakSpeechResources->unk_0012 = 0;
+ SetGpuReg(REG_OFFSET_WIN0H, 0);
+ SetGpuReg(REG_OFFSET_WIN0V, 0);
+ SetGpuReg(REG_OFFSET_WININ, 0);
+ SetGpuReg(REG_OFFSET_WINOUT, 0);
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ BeginNormalPaletteFade(0xFFFFFFFF, 2, 0, 16, RGB_BLACK);
+ gTasks[taskId].func = Task_OakSpeech8;
+ }
+ break;
+ }
+}
+
+static void Task_OakSpeech8(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!gPaletteFade.active)
+ {
+ sub_810F740();
+ FillWindowPixelBuffer(data[14], 0x00);
+ ClearWindowTilemap(data[14]);
+ CopyWindowToVram(data[14], 3);
+ RemoveWindow(data[14]);
+ data[14] = 0;
+ FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
+ CopyBgTilemapBufferToVram(1);
+ DestroyLinkedPikaOrGrassPlatformSprites(taskId, 0);
+ data[3] = 80;
+ gTasks[taskId].func = Task_OakSpeech9;
+ }
+}
+
+static void Task_OakSpeech9(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u32 size = 0;
+
+ if (data[3] != 0)
+ data[3]--;
+ else
+ {
+ sOakSpeechResources->solidColorsGfx = malloc_and_decompress(sOakSpeechGfx_SolidColors, &size);
+ LoadBgTiles(1, sOakSpeechResources->solidColorsGfx, size, 0);
+ CopyToBgTilemapBuffer(1, sOakSpeech_BackgroundTilemap, 0, 0);
+ CopyBgTilemapBufferToVram(1);
+ CreateNidoranFSprite(taskId);
+ LoadOaksSpeechTrainerPic(3, 0);
+ CreatePikaOrGrassPlatformSpriteAndLinkToCurrentTask(taskId, 1);
+ PlayBGM(BGM_FRLG_ROUTE_24);
+ BeginNormalPaletteFade(0xFFFFFFFF, 5, 16, 0, RGB_BLACK);
+ data[3] = 80;
+ ShowBg(2);
+ gTasks[taskId].func = Task_OakSpeech10;
+ }
+}
+
+#define OaksSpeechPrintMessage(str, speed) ({ \
+ DrawDialogueFrame(0, FALSE);\
+ if (str != gStringVar4) \
+ { \
+ StringExpandPlaceholders(gStringVar4, str); \
+ AddTextPrinterParameterized2(0, 4, gStringVar4, speed, NULL, 2, 1, 3); \
+ } \
+ else \
+ { \
+ AddTextPrinterParameterized2(0, 4, str, speed, NULL, 2, 1, 3); \
+ } \
+ CopyWindowToVram(0, 3); \
+})
+
+static void Task_OakSpeech10(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!gPaletteFade.active)
+ {
+ if (data[3] != 0)
+ data[3]--;
+ else
+ {
+ OaksSpeechPrintMessage(gOakText_WelcomeToTheWorld, sOakSpeechResources->textSpeed);
+ gTasks[taskId].func = Task_OakSpeech11;
+ }
+ }
+}
+
+static void Task_OakSpeech11(u8 taskId)
+{
+ if (!IsTextPrinterActive(0))
+ {
+ OaksSpeechPrintMessage(gOakText_WorldInhabited1, sOakSpeechResources->textSpeed);
+ gTasks[taskId].data[3] = 30;
+ gTasks[taskId].func = Task_OakSpeech12;
+ }
+}
+
+static void Task_OakSpeech12(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u8 spriteId;
+
+ if (!IsTextPrinterActive(0))
+ {
+ if (data[3] != 0)
+ data[3]--;
+ // else {
+ spriteId = gTasks[taskId].data[4];
+ gSprites[spriteId].invisible = FALSE;
+ gSprites[spriteId].data[0] = 0;
+ CreatePokeballSpriteToReleaseMon(spriteId, gSprites[spriteId].oam.paletteNum, 0x64, 0x42, 0, 0, 32, 0xFFFF1FFF);
+ gTasks[taskId].func = Task_OakSpeech13;
+ gTasks[taskId].data[3] = 0;
+ // }
+ }
+}
+
+static void Task_OakSpeech13(u8 taskId)
+{
+ if (IsCryFinished())
+ {
+ if (gTasks[taskId].data[3] >= 96)
+ gTasks[taskId].func = Task_OakSpeech14;
+ }
+ if (gTasks[taskId].data[3] < 0x4000)
+ {
+ gTasks[taskId].data[3]++;
+ if (gTasks[taskId].data[3] == 32)
+ {
+ OaksSpeechPrintMessage(gOakText_WorldInhabited2, sOakSpeechResources->textSpeed);
+ PlayCry1(SPECIES_NIDORAN_F, 0);
+ }
+ }
+}
+
+static void Task_OakSpeech14(u8 taskId)
+{
+ if (!IsTextPrinterActive(0))
+ {
+ OaksSpeechPrintMessage(gOakText_PetsBattlingStudy, sOakSpeechResources->textSpeed);
+ gTasks[taskId].func = Task_OakSpeech15;
+ }
+}
+
+static void Task_OakSpeech15(u8 taskId)
+{
+ u8 spriteId;
+
+ if (!IsTextPrinterActive(0))
+ {
+ ClearDialogWindowAndFrame(0, 1);
+ spriteId = gTasks[taskId].data[4];
+ gTasks[taskId].data[6] = sub_804BB98(spriteId, gSprites[spriteId].oam.paletteNum, 0x64, 0x42, 0, 0, 32, 0xFFFF1F3F);
+ gTasks[taskId].data[3] = 48;
+ gTasks[taskId].data[0] = 64;
+ gTasks[taskId].func = Task_OakSpeech16;
+ }
+}
+
+static void Task_OakSpeech16(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (data[0] != 0)
+ {
+ if (data[0] < 24)
+ {
+ gSprites[data[4]].pos1.y--;
+ }
+ data[0]--;
+ }
+ else
+ {
+ if (data[3] == 48)
+ {
+ DestroySprite(&gSprites[data[4]]);
+ DestroySprite(&gSprites[data[6]]);
+ }
+ if (data[3] != 0)
+ {
+ data[3]--;
+ }
+ else
+ {
+ OaksSpeechPrintMessage(gOakText_TellMeALittleAboutYourself, sOakSpeechResources->textSpeed);
+ gTasks[taskId].func = Task_OakSpeech17;
+ }
+ }
+}
+
+static void Task_OakSpeech17(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!IsTextPrinterActive(0))
+ {
+ ClearDialogWindowAndFrame(0, 1);
+ CreateFadeInTask(taskId, 2);
+ data[3] = 48;
+ gTasks[taskId].func = Task_OakSpeech18;
+ }
+}
+
+static void Task_OakSpeech18(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (data[2] != 0)
+ {
+ if (data[3] != 0)
+ data[3]--;
+ else
+ {
+ data[1] = -60;
+ DestroyOaksSpeechTrainerPic();
+ OaksSpeechPrintMessage(gOakText_AskPlayerGender, sOakSpeechResources->textSpeed);
+ gTasks[taskId].func = Task_OakSpeech19;
+ }
+ }
+}
+
+static void Task_OakSpeech19(u8 taskId)
+{
+ if (!IsTextPrinterActive(0))
+ {
+ gTasks[taskId].data[13] = AddWindow(&sNewGameAdventureIntroWindowTemplates[1]);
+ PutWindowTilemap(gTasks[taskId].data[13]);
+ SetWindowBorderStyle(gTasks[taskId].data[13], 1, sub_80F796C(), 14);
+ FillWindowPixelBuffer(gTasks[taskId].data[13], 0x11);
+ sOakSpeechResources->unk_001C[0] = 1;
+ sOakSpeechResources->unk_001C[1] = 2;
+ sOakSpeechResources->unk_001C[2] = 3;
+ AddTextPrinterParameterized3(gTasks[taskId].data[13], 2, 8, 1, sOakSpeechResources->unk_001C, 0, gText_Boy);
+ sOakSpeechResources->unk_001C[0] = 1;
+ sOakSpeechResources->unk_001C[1] = 2;
+ sOakSpeechResources->unk_001C[2] = 3;
+ AddTextPrinterParameterized3(gTasks[taskId].data[13], 2, 8, 17, sOakSpeechResources->unk_001C, 0, gText_Girl);
+ ProgramAndPlaceMenuCursorOnWindow(gTasks[taskId].data[13], 2, 0, 1, GetFontAttribute(2, 1) + 2, 2, 0);
+ CopyWindowToVram(gTasks[taskId].data[13], 3);
+ gTasks[taskId].func = Task_OakSpeech20;
+ }
+}
+
+static void Task_OakSpeech20(u8 taskId)
+{
+ s8 input = ProcessMenuInputNoWrapAround();
+ switch (input)
+ {
+ case 0:
+ gSaveBlock2Ptr->playerGender = MALE;
+ break;
+ case 1:
+ gSaveBlock2Ptr->playerGender = FEMALE;
+ break;
+ case -1:
+ case -2:
+ return;
+ }
+ gTasks[taskId].func = Task_OakSpeech21;
+
+}
+
+static void Task_OakSpeech21(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ ClearMenuWindow(data[13], 1);
+ RemoveWindow(data[13]);
+ data[13] = 0;
+ ClearDialogWindowAndFrame(0, 1);
+ FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20);
+ CopyBgTilemapBufferToVram(0);
+ gTasks[taskId].func = Task_OakSpeech22;
+}
+
+static void Task_OakSpeech22(u8 taskId)
+{
+ if (gSaveBlock2Ptr->playerGender == MALE)
+ LoadOaksSpeechTrainerPic(MALE, 0);
+ else
+ LoadOaksSpeechTrainerPic(FEMALE, 0);
+ CreateFadeOutTask(taskId, 2);
+ gTasks[taskId].data[3] = 32;
+ gTasks[taskId].func = Task_OakSpeech23;
+}
+
+static void Task_OakSpeech23(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (data[2] != 0)
+ {
+ if (data[3] != 0)
+ data[3]--;
+ else
+ {
+ data[1] = 0;
+ OaksSpeechPrintMessage(gOakText_AskPlayerName, sOakSpeechResources->textSpeed);
+ gTasks[taskId].func = Task_OakSpeech24;
+ }
+ }
+}
+
+static void Task_OakSpeech24(u8 taskId)
+{
+ if (!IsTextPrinterActive(0))
+ {
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+ sOakSpeechResources->unk_0010 = 0;
+ gTasks[taskId].func = Task_OakSpeech25;
+ }
+}
+static void Task_OakSpeech35(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!IsTextPrinterActive(0))
+ {
+ if (data[1] > -60)
+ {
+ data[1] -= 2;
+ gSpriteCoordOffsetX += 2;
+ ChangeBgX(2, 0x200, 2);
+ }
+ else
+ {
+ data[1] = -60;
+ PrintNameChoiceOptions(taskId, sOakSpeechResources->unk_0010);
+ gTasks[taskId].func = Task_OakSpeech29;
+ }
+ }
+}
+
+static void Task_OakSpeech28(u8 taskId)
+{
+ PrintNameChoiceOptions(taskId, sOakSpeechResources->unk_0010);
+ if (sOakSpeechResources->unk_0010 == 0)
+ {
+ OaksSpeechPrintMessage(gOakText_AskPlayerName, 0);
+ }
+ else
+ {
+ OaksSpeechPrintMessage(gOakText_AskRivalName, 0);
+ }
+ gTasks[taskId].func = Task_OakSpeech29;
+}
+
+static void Task_OakSpeech29(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ s8 input = ProcessMenuInput();
+ switch (input)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ PlaySE(SE_SELECT);
+ ClearMenuWindow(data[13], TRUE);
+ RemoveWindow(data[13]);
+ GetDefaultName(sOakSpeechResources->unk_0010, input - 1);
+ data[15] = 1;
+ gTasks[taskId].func = Task_OakSpeech26;
+ break;
+ case 0:
+ PlaySE(SE_SELECT);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0);
+ gTasks[taskId].func = Task_OakSpeech25;
+ break;
+ case -1:
+ break;
+ }
+}
+
+static void Task_OakSpeech25(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ GetDefaultName(sOakSpeechResources->unk_0010, 0);
+ if (sOakSpeechResources->unk_0010 == 0)
+ {
+ DoNamingScreen(0, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnFromNamingScreen);
+ }
+ else
+ {
+ ClearMenuWindow(gTasks[taskId].data[13], 1);
+ RemoveWindow(gTasks[taskId].data[13]);
+ DoNamingScreen(4, gSaveBlock1Ptr->rivalName, 0, 0, 0, CB2_ReturnFromNamingScreen);
+ }
+ DestroyLinkedPikaOrGrassPlatformSprites(taskId, 1);
+ FreeAllWindowBuffers();
+ }
+}
+
+static void Task_OakSpeech26(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!gPaletteFade.active)
+ {
+ if (data[15] == 1)
+ {
+ if (sOakSpeechResources->unk_0010 == 0)
+ {
+ StringExpandPlaceholders(gStringVar4, gOakText_FinalizePlayerName);
+ }
+ else
+ {
+ StringExpandPlaceholders(gStringVar4, gOakText_ConfirmRivalName);
+ }
+ OaksSpeechPrintMessage(gStringVar4, sOakSpeechResources->textSpeed);
+ data[15] = 0;
+ data[3] = 25;
+ }
+ else if (!IsTextPrinterActive(0))
+ {
+ if (data[3] != 0)
+ data[3]--;
+ else
+ {
+ CreateYesNoMenu(&sNewGameAdventureIntroWindowTemplates[2], 2, 0, 2, sub_80F796C(), 14, 0);
+ gTasks[taskId].func = Task_OakSpeech27;
+ }
+ }
+ }
+}
+
+static void Task_OakSpeech27(u8 taskId)
+{
+ s8 input = Menu_ProcessInputNoWrapClearOnChoose();
+ switch (input)
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ gTasks[taskId].data[3] = 40;
+ if (sOakSpeechResources->unk_0010 == 0)
+ {
+ ClearDialogWindowAndFrame(0, 1);
+ CreateFadeInTask(taskId, 2);
+ gTasks[taskId].func = Task_OakSpeech30;
+ }
+ else
+ {
+ StringExpandPlaceholders(gStringVar4, gOakText_RememberRivalName);
+ OaksSpeechPrintMessage(gStringVar4, sOakSpeechResources->textSpeed);
+ gTasks[taskId].func = Task_OakSpeech31;
+ }
+ break;
+ case 1:
+ case -1:
+ PlaySE(SE_SELECT);
+ if (sOakSpeechResources->unk_0010 == 0)
+ gTasks[taskId].func = Task_OakSpeech24;
+ else
+ gTasks[taskId].func = Task_OakSpeech28;
+ break;
+ }
+}
+
+static void Task_OakSpeech30(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (data[2] != 0)
+ {
+ DestroyOaksSpeechTrainerPic();
+ if (data[3] != 0)
+ data[3]--;
+ else
+ gTasks[taskId].func = Task_OakSpeech32;
+ }
+}
+
+static void Task_OakSpeech31(u8 taskId)
+{
+ if (!IsTextPrinterActive(0))
+ {
+ ClearDialogWindowAndFrame(0, 1);
+ CreateFadeInTask(taskId, 2);
+ gTasks[taskId].func = Task_OakSpeech33;
+ }
+}
+
+static void Task_OakSpeech32(u8 taskId)
+{
+ ChangeBgX(2, 0, 0);
+ gTasks[taskId].data[1] = 0;
+ gSpriteCoordOffsetX = 0;
+ LoadOaksSpeechTrainerPic(2, 0);
+ CreateFadeOutTask(taskId, 2);
+ gTasks[taskId].func = Task_OakSpeech34;
+}
+
+static void Task_OakSpeech34(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (data[2] != 0)
+ {
+ OaksSpeechPrintMessage(gOakText_IntroduceRival, sOakSpeechResources->textSpeed);
+ sOakSpeechResources->unk_0010 = 1;
+ gTasks[taskId].func = Task_OakSpeech35;
+ }
+}
+
+static void Task_OakSpeech33(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (data[2] != 0)
+ {
+ DestroyOaksSpeechTrainerPic();
+ if (data[3] != 0)
+ data[3]--;
+ else
+ {
+ if (gSaveBlock2Ptr->playerGender == MALE)
+ LoadOaksSpeechTrainerPic(MALE, 0);
+ else
+ LoadOaksSpeechTrainerPic(FEMALE, 0);
+ gTasks[taskId].data[1] = 0;
+ gSpriteCoordOffsetX = 0;
+ ChangeBgX(2, 0, 0);
+ CreateFadeOutTask(taskId, 2);
+ gTasks[taskId].func = Task_OakSpeech36;
+ }
+ }
+}
+
+static void Task_OakSpeech36(u8 taskId)
+{
+ if (gTasks[taskId].data[2] != 0)
+ {
+ StringExpandPlaceholders(gStringVar4, gOakText_LegendAboutToUnfold);
+ OaksSpeechPrintMessage(gStringVar4, sOakSpeechResources->textSpeed);
+ gTasks[taskId].data[3] = 30;
+ gTasks[taskId].func = Task_OakSpeech37;
+ }
+}
+
+static void Task_OakSpeech37(u8 taskId)
+{
+ if (!IsTextPrinterActive(0))
+ {
+ if (gTasks[taskId].data[3] != 0)
+ gTasks[taskId].data[3]--;
+ else
+ {
+ FadeOutBGM(4);
+ gTasks[taskId].func = Task_OakSpeech38;
+ }
+ }
+}
+
+static void Task_OakSpeech38(u8 taskId)
+{
+ sOakSpeechResources->unk_0012 = 0;
+ Task_OakSpeech38_1(taskId);
+ Task_OakSpeech38_2(taskId);
+ Task_OakSpeech38_3(taskId);
+}
+
+static void Task_OakSpeech38_3(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ SetBgAttribute(2, 6, 1);
+ data[0] = 0;
+ data[1] = 0;
+ data[2] = 256;
+ data[15] = 0;
+ gTasks[taskId].func = Task_OakSpeech39;
+}
+
+static void Task_OakSpeech39(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ s16 x, y;
+ u16 r0;
+
+ sOakSpeechResources->unk_0012++;
+ if (sOakSpeechResources->unk_0012 % 20 == 0)
+ {
+ if (sOakSpeechResources->unk_0012 == 40)
+ PlaySE(SE_FU_ZUZUZU);
+ r0 = data[2];
+ data[2] -= 32;
+ x = sub_80D8B90(r0 - 8);
+ y = sub_80D8B90(data[2] - 16);
+ SetBgAffine(2, 0x7800, 0x5400, 0x78, 0x54, x, y, 0);
+ if (data[2] <= 96)
+ {
+ data[15] = 1;
+ data[0] = 36;
+ gTasks[taskId].func = Task_OakSpeech40;
+ }
+ }
+}
+
+static void Task_OakSpeech38_1(u8 taskId)
+{
+ u8 taskId2 = CreateTask(Task_OakSpeech38_sub1, 1);
+ s16 * data = gTasks[taskId2].data;
+ data[0] = 0;
+ data[1] = 0;
+ data[2] = 0;
+ data[15] = 0;
+ BeginNormalPaletteFade(0xFFFF0FCF, 4, 0, 16, RGB_BLACK);
+}
+
+static void Task_OakSpeech38_sub1(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ if (!gPaletteFade.active)
+ {
+ if (data[1] != 0)
+ {
+ DestroyTask(taskId);
+ DestroyLinkedPikaOrGrassPlatformSprites(taskId, 1);
+ }
+ else
+ {
+ data[1]++;
+ BeginNormalPaletteFade(0x0000F000, 0, 0, 16, RGB_BLACK);
+ }
+ }
+}
+
+static void Task_OakSpeech38_2(u8 taskId)
+{
+ u8 taskId2 = CreateTask(Task_OakSpeech38_sub2, 2);
+ s16 * data = gTasks[taskId2].data;
+ data[0] = 8;
+ data[1] = 0;
+ data[2] = 8;
+ data[14] = 0;
+ data[15] = 0;
+}
+
+static void Task_OakSpeech38_sub2(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u8 i;
+
+ if (data[0] != 0)
+ data[0]--;
+ else
+ {
+ if (data[1] <= 0 && data[2] != 0)
+ data[2]--;
+ BlendPalette(0x40, 0x20, data[14], RGB_WHITE);
+ data[14]++;
+ data[1]--;
+ data[0] = data[2];
+ if (data[14] > 14)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ gPlttBufferFaded[i + 0x40] = RGB_WHITE;
+ gPlttBufferUnfaded[i + 0x40] = RGB_WHITE;
+ }
+ DestroyTask(taskId);
+ }
+ }
+}
+
+static void Task_OakSpeech40(u8 taskId)
+{
+ if (gTasks[taskId].data[0] != 0)
+ gTasks[taskId].data[0]--;
+ else
+ {
+ BeginNormalPaletteFade(0x00000030, 2, 0, 16, RGB_BLACK);
+ gTasks[taskId].func = Task_OakSpeech41;
+ }
+}
+
+static void Task_OakSpeech41(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ gTasks[taskId].func = Task_OakSpeech42;
+ }
+}
+
+static void Task_OakSpeech42(u8 taskId)
+{
+ FreeAllWindowBuffers();
+ sub_8044D80();
+ Free(sOakSpeechResources);
+ sOakSpeechResources = NULL;
+ gTextFlags.canABSpeedUpPrint = FALSE;
+ SetMainCallback2(CB2_NewGame);
+ DestroyTask(taskId);
+}
+
+static void CB2_ReturnFromNamingScreen(void)
+{
+ u8 taskId;
+
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL);
+ DmaFill16(3, 0, VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, OAM, OAM_SIZE);
+ DmaFill16(3, RGB_BLACK, PLTT + sizeof(u16), PLTT_SIZE - sizeof(u16));
+ ResetPaletteFade();
+ ScanlineEffect_Stop();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ reset_temp_tile_data_buffers();
+ break;
+ case 1:
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(1, sBgTemplates, NELEMS(sBgTemplates));
+ SetBgTilemapBuffer(1, sOakSpeechResources->bg1TilemapBuffer);
+ SetBgTilemapBuffer(2, sOakSpeechResources->bg2TilemapBuffer);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ break;
+ case 2:
+ SetGpuReg(REG_OFFSET_WIN0H, 0);
+ SetGpuReg(REG_OFFSET_WIN0V, 0);
+ SetGpuReg(REG_OFFSET_WININ, 0);
+ SetGpuReg(REG_OFFSET_WINOUT, 0);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ break;
+ case 3:
+ FreeAllWindowBuffers();
+ InitStandardTextBoxWindows();
+ ResetBg0();
+ LoadPalette(sHelpDocsPalette, 0, 0xe0);
+ break;
+ case 4:
+ decompress_and_copy_tile_data_to_vram(1, sOakSpeechGfx_SolidColors, 0, 0, 0);
+ break;
+ case 5:
+ if (free_temp_tile_data_buffers_if_possible())
+ return;
+ FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
+ CopyToBgTilemapBuffer(1, sOakSpeech_BackgroundTilemap, 0, 0);
+ FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 20);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(2);
+ break;
+ case 6:
+ taskId = CreateTask(Task_OakSpeech26, 0);
+ if (sOakSpeechResources->unk_0010 == 0)
+ {
+ if (gSaveBlock2Ptr->playerGender == MALE)
+ LoadOaksSpeechTrainerPic(MALE, 0);
+ else
+ LoadOaksSpeechTrainerPic(FEMALE, 0);
+ }
+ else
+ LoadOaksSpeechTrainerPic(2, 0);
+ gTasks[taskId].data[1] = -60;
+ gSpriteCoordOffsetX += 60;
+ ChangeBgX(2, -0x3C00, 0);
+ CreatePikaOrGrassPlatformSpriteAndLinkToCurrentTask(taskId, 1);
+ gTasks[taskId].data[15] = 1;
+ break;
+ case 7:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ EnableInterrupts(INTR_FLAG_VBLANK);
+ SetVBlankCallback(VBlankCB_NewGameOaksSpeech);
+ gTextFlags.canABSpeedUpPrint = TRUE;
+ SetMainCallback2(CB2_NewGameOaksSpeech);
+ return;
+ }
+
+ gMain.state++;
+}
+
+static void CreateNidoranFSprite(u8 taskId)
+{
+ u8 spriteId;
+
+ DecompressPicFromTable(gUnknown_8235194, sub_8044E00(0), SPECIES_NIDORAN_F);
+ sub_800F078(&gUnknown_82373F4);
+ SetMultiuseSpriteTemplateToPokemon(SPECIES_NIDORAN_F, 0);
+ spriteId = CreateSprite(&gMultiuseSpriteTemplate, 0x60, 0x60, 1);
+ gSprites[spriteId].callback = SpriteCallbackDummy;
+ gSprites[spriteId].oam.priority = 1;
+ gSprites[spriteId].invisible = TRUE;
+ gTasks[taskId].data[4] = spriteId;
+}
+
+static void SpriteCB_PikaSync(struct Sprite * sprite)
+{
+ sprite->pos2.y = gSprites[sprite->data[0]].animCmdIndex;
+}
+
+static void CreatePikaOrGrassPlatformSpriteAndLinkToCurrentTask(u8 taskId, u8 state)
+{
+ u8 spriteId;
+ u8 i = 0;
+
+ switch (state)
+ {
+ case 0:
+ LoadCompressedObjectPic(&sOakSpeech_PikaSpriteSheets[0]);
+ LoadCompressedObjectPic(&sOakSpeech_PikaSpriteSheets[1]);
+ LoadCompressedObjectPic(&sOakSpeech_PikaSpriteSheets[2]);
+ LoadSpritePalette(&sOakSpeech_PikaSpritePal);
+ spriteId = CreateSprite(&sOakSpeech_PikaSpriteTemplates[0], 0x10, 0x11, 2);
+ gSprites[spriteId].oam.priority = 0;
+ gTasks[taskId].data[7] = spriteId;
+ spriteId = CreateSprite(&sOakSpeech_PikaSpriteTemplates[1], 0x10, 0x09, 3);
+ gSprites[spriteId].oam.priority = 0;
+ gSprites[spriteId].data[0] = gTasks[taskId].data[7];
+ gSprites[spriteId].callback = SpriteCB_PikaSync;
+ gTasks[taskId].data[8] = spriteId;
+ spriteId = CreateSprite(&sOakSpeech_PikaSpriteTemplates[2], 0x18, 0x0D, 1);
+ gSprites[spriteId].oam.priority = 0;
+ gSprites[spriteId].data[0] = gTasks[taskId].data[7];
+ gSprites[spriteId].callback = SpriteCB_PikaSync;
+ gTasks[taskId].data[9] = spriteId;
+ break;
+ case 1:
+ LoadCompressedObjectPic(&sOakSpeech_GrassPlatformSpriteSheet);
+ LoadSpritePalette(&sOakSpeech_GrassPlatformSpritePal);
+ for (i = 0; i < 3; i++)
+ {
+ spriteId = CreateSprite(&sOakSpeech_GrassPlatformSpriteTemplates[i], i * 32 + 88, 0x70, 1);
+ gSprites[spriteId].oam.priority = 2;
+ gSprites[spriteId].animPaused = TRUE;
+ gSprites[spriteId].coordOffsetEnabled = TRUE;
+ gTasks[taskId].data[7 + i] = spriteId;
+ }
+ break;
+ }
+}
+
+static void DestroyLinkedPikaOrGrassPlatformSprites(u8 taskId, u8 state)
+{
+ u8 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ DestroySprite(&gSprites[gTasks[taskId].data[7 + i]]);
+ }
+
+ switch (state)
+ {
+ case 0:
+ FreeSpriteTilesByTag(0x1003);
+ FreeSpriteTilesByTag(0x1002);
+ FreeSpriteTilesByTag(0x1001);
+ FreeSpritePaletteByTag(0x1001);
+ break;
+ case 1:
+ FreeSpriteTilesByTag(0x1000);
+ FreeSpritePaletteByTag(0x1000);
+ break;
+ }
+}
+
+static void LoadOaksSpeechTrainerPic(u16 whichPic, u16 tileOffset)
+{
+ u32 i;
+
+ switch (whichPic)
+ {
+ case 0: // FIRE
+ LoadPalette(sOakSpeechGfx_RedPal, 0x40, 0x40);
+ LZ77UnCompVram(sOakSpeechGfx_RedPic, (void *)0x06000600 + tileOffset);
+ break;
+ case 1: // LEAF
+ LoadPalette(sOakSpeechGfx_LeafPal, 0x40, 0x40);
+ LZ77UnCompVram(sOakSpeechGfx_LeafPic, (void *)0x06000600 + tileOffset);
+ break;
+ case 2: // BLUE
+ LoadPalette(sOakSpeechGfx_RivalPal, 0x60, 0x40);
+ LZ77UnCompVram(sOakSpeechGfx_RivalPic, (void *)0x06000600 + tileOffset);
+ break;
+ case 3: // OAK
+ LoadPalette(sOakSpeechGfx_OakPal, 0x60, 0x40);
+ LZ77UnCompVram(sOakSpeechGfx_OakPic, (void *)0x06000600 + tileOffset);
+ break;
+ default:
+ return;
+ }
+
+ sOakSpeechResources->trainerPicTilemapBuffer = AllocZeroed(0x60);
+ for (i = 0; i < 0x60; i++)
+ ((u8 *)sOakSpeechResources->trainerPicTilemapBuffer)[i] = i;
+ FillBgTilemapBufferRect(2, 0x000, 0, 0, 32, 32, 0x10);
+ CopyRectToBgTilemapBufferRect(2, sOakSpeechResources->trainerPicTilemapBuffer, 0, 0, 8, 12, 11, 2, 8, 12, 0x10, (tileOffset / 64) + 0x18, 0x00);
+ CopyBgTilemapBufferToVram(2);
+ Free(sOakSpeechResources->trainerPicTilemapBuffer);
+ sOakSpeechResources->trainerPicTilemapBuffer = 0;
+}
+
+static void DestroyOaksSpeechTrainerPic(void)
+{
+ FillBgTilemapBufferRect(2, 0x000, 11, 1, 8, 12, 0x10);
+ CopyBgTilemapBufferToVram(2);
+}
+
+static void Task_SlowFadeIn(u8 taskId)
+{
+ u8 i = 0;
+ if (gTasks[taskId].data[1] == 0)
+ {
+ gTasks[gTasks[taskId].data[0]].data[2] = 1;
+ DestroyTask(taskId);
+ for (i = 0; i < 3; i++)
+ {
+ gSprites[gTasks[taskId].data[7 + i]].invisible = TRUE;
+ }
+ }
+ else
+ {
+ if (gTasks[taskId].data[4] != 0)
+ gTasks[taskId].data[4]--;
+ else
+ {
+ gTasks[taskId].data[4] = gTasks[taskId].data[3];
+ gTasks[taskId].data[1]--;
+ gTasks[taskId].data[2]++;
+ if (gTasks[taskId].data[1] == 8)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ gSprites[gTasks[taskId].data[7 + i]].invisible ^= TRUE;
+ }
+ }
+ SetGpuReg(REG_OFFSET_BLDALPHA, (gTasks[taskId].data[2] * 256) + gTasks[taskId].data[1]);
+ }
+ }
+}
+
+static void CreateFadeInTask(u8 taskId, u8 state)
+{
+ u8 taskId2;
+ u8 i = 0;
+
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_OBJ);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0x10);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ gTasks[taskId].data[2] = 0;
+ taskId2 = CreateTask(Task_SlowFadeIn, 0);
+ gTasks[taskId2].data[0] = taskId;
+ gTasks[taskId2].data[1] = 16;
+ gTasks[taskId2].data[2] = 0;
+ gTasks[taskId2].data[3] = state;
+ gTasks[taskId2].data[4] = state;
+ for (i = 0; i < 3; i++)
+ {
+ gTasks[taskId2].data[7 + i] = gTasks[taskId].data[7 + i];
+ }
+}
+
+static void Task_SlowFadeOut(u8 taskId)
+{
+ u8 i = 0;
+
+ if (gTasks[taskId].data[1] == 16)
+ {
+ if (!gPaletteFade.active)
+ {
+ gTasks[gTasks[taskId].data[0]].data[2] = 1;
+ DestroyTask(taskId);
+ }
+ }
+ else
+ {
+ if (gTasks[taskId].data[4] != 0)
+ gTasks[taskId].data[4]--;
+ else
+ {
+ gTasks[taskId].data[4] = gTasks[taskId].data[3];
+ gTasks[taskId].data[1] += 2;
+ gTasks[taskId].data[2] -= 2;
+ if (gTasks[taskId].data[1] == 8)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ gSprites[gTasks[taskId].data[7 + i]].invisible ^= TRUE;
+ }
+ }
+ SetGpuReg(REG_OFFSET_BLDALPHA, (gTasks[taskId].data[2] * 256) + gTasks[taskId].data[1]);
+ }
+ }
+}
+
+static void CreateFadeOutTask(u8 taskId, u8 state)
+{
+ u8 taskId2;
+ u8 i = 0;
+
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_OBJ);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0x1000);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ gTasks[taskId].data[2] = 0;
+ taskId2 = CreateTask(Task_SlowFadeOut, 0);
+ gTasks[taskId2].data[0] = taskId;
+ gTasks[taskId2].data[1] = 0;
+ gTasks[taskId2].data[2] = 16;
+ gTasks[taskId2].data[3] = state;
+ gTasks[taskId2].data[4] = state;
+ for (i = 0; i < 3; i++)
+ {
+ gTasks[taskId2].data[7 + i] = gTasks[taskId].data[7 + i];
+ }
+}
+
+static void PrintNameChoiceOptions(u8 taskId, u8 state)
+{
+ s16 * data = gTasks[taskId].data;
+ const u8 *const * textPtrs;
+ u8 i;
+
+ data[13] = AddWindow(&sNewGameAdventureIntroWindowTemplates[3]);
+ PutWindowTilemap(data[13]);
+ SetWindowBorderStyle(data[13], 1, sub_80F796C(), 14);
+ FillWindowPixelBuffer(gTasks[taskId].data[13], 0x11);
+ AddTextPrinterParameterized(data[13], 2, gOtherText_NewName, 8, 1, 0, NULL);
+ if (state == 0)
+ textPtrs = gSaveBlock2Ptr->playerGender == MALE ? sMaleNameChoices : sFemaleNameChoices;
+ else
+ textPtrs = sRivalNameChoices;
+ for (i = 0; i < 4; i++)
+ {
+ AddTextPrinterParameterized(data[13], 2, textPtrs[i], 8, 16 * (i + 1) + 1, 0, NULL);
+ }
+ ProgramAndPlaceMenuCursorOnWindow(data[13], 2, 0, 1, 16, 5, 0);
+ CopyWindowToVram(data[13], 3);
+}
+
+static void GetDefaultName(u8 arg0, u8 namePick)
+{
+ const u8 * src;
+ u8 * dest;
+ u8 i;
+
+ if (arg0 == 0)
+ {
+ if (gSaveBlock2Ptr->playerGender == MALE)
+ src = sMaleNameChoices[Random() % 19];
+ else
+ src = sFemaleNameChoices[Random() % 19];
+ dest = gSaveBlock2Ptr->playerName;
+ }
+ else
+ {
+ src = sRivalNameChoices[namePick];
+ dest = gSaveBlock1Ptr->rivalName;
+ }
+ for (i = 0; i < PLAYER_NAME_LENGTH - 1 && src[i] != EOS; i++)
+ dest[i] = src[i];
+ for (; i < PLAYER_NAME_LENGTH; i++)
+ dest[i] = EOS;
+}
diff --git a/src/pokemon.c b/src/pokemon.c
index 5cd2cd2d7..906b97cae 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -80,7 +80,7 @@ extern const u16 sHMMoves[];
extern s8 gPokeblockFlavorCompatibilityTable[];
// External functions
-extern u8 sav1_map_get_name(void); // overworld
+extern u8 GetCurrentRegionMapSectionId(void); // overworld
extern const struct BattleMove gBattleMoves[];
extern u8 sBattler_AI; // battle_ai
extern void set_unknown_box_id(u8); // field_specials
@@ -194,7 +194,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV,
SetBoxMonData(boxMon, MON_DATA_SPECIES, &species);
SetBoxMonData(boxMon, MON_DATA_EXP, &gExperienceTables[gBaseStats[species].growthRate][level]);
SetBoxMonData(boxMon, MON_DATA_FRIENDSHIP, &gBaseStats[species].friendship);
- value = sav1_map_get_name();
+ value = GetCurrentRegionMapSectionId();
SetBoxMonData(boxMon, MON_DATA_MET_LOCATION, &value);
SetBoxMonData(boxMon, MON_DATA_MET_LEVEL, &level);
SetBoxMonData(boxMon, MON_DATA_MET_GAME, &gGameVersion);
@@ -351,7 +351,7 @@ void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedI
CalculateMonStats(mon);
}
-void sub_803E0A4(struct Pokemon *mon, struct UnknownPokemonStruct *src)
+void sub_803E0A4(struct Pokemon *mon, struct BattleTowerPokemon *src)
{
s32 i;
u8 value;
@@ -410,7 +410,7 @@ void CreateObedientMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u
SetMonData(mon, MON_DATA_OBEDIENCE, &obedient);
}
-void sub_803E23C(struct Pokemon *mon, struct UnknownPokemonStruct *dest)
+void sub_803E23C(struct Pokemon *mon, struct BattleTowerPokemon *dest)
{
s32 i;
u16 heldItem;
@@ -1001,7 +1001,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
damage /= 2;
// sunny
- if (gBattleWeather & WEATHER_SUN_ANY)
+ if (gBattleWeather & WEATHER_SUNNY_ANY)
{
switch (type)
{
@@ -1122,7 +1122,7 @@ u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality)
return MON_MALE;
}
-void sub_803F7D4(u16 trainerSpriteId, u8 battlerPosition)
+void SetMultiuseSpriteTemplateToPokemon(u16 trainerSpriteId, u8 battlerPosition)
{
if(gMonSpritesGfxPtr != NULL)
{
@@ -1415,13 +1415,13 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
case MON_DATA_LANGUAGE:
retVal = boxMon->language;
break;
- case MON_DATA_SANITY_BIT1:
+ case MON_DATA_SANITY_IS_BAD_EGG:
retVal = boxMon->isBadEgg;
break;
- case MON_DATA_SANITY_BIT2:
+ case MON_DATA_SANITY_HAS_SPECIES:
retVal = boxMon->hasSpecies;
break;
- case MON_DATA_SANITY_BIT3:
+ case MON_DATA_SANITY_IS_EGG:
retVal = boxMon->isEgg;
break;
case MON_DATA_OT_NAME:
@@ -1809,13 +1809,13 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg)
case MON_DATA_LANGUAGE:
SET8(boxMon->language);
break;
- case MON_DATA_SANITY_BIT1:
+ case MON_DATA_SANITY_IS_BAD_EGG:
SET8(boxMon->isBadEgg);
break;
- case MON_DATA_SANITY_BIT2:
+ case MON_DATA_SANITY_HAS_SPECIES:
SET8(boxMon->hasSpecies);
break;
- case MON_DATA_SANITY_BIT3:
+ case MON_DATA_SANITY_IS_EGG:
SET8(boxMon->isEgg);
break;
case MON_DATA_OT_NAME:
@@ -2769,7 +2769,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo
{
if (GetMonData(pkmn, MON_DATA_POKEBALL, NULL) == 11)
friendship++;
- if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name())
+ if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == GetCurrentRegionMapSectionId())
friendship++;
}
if (friendship < 0)
@@ -2794,7 +2794,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo
{
if (GetMonData(pkmn, MON_DATA_POKEBALL, NULL) == 11)
friendship++;
- if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name())
+ if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == GetCurrentRegionMapSectionId())
friendship++;
}
if (friendship < 0)
@@ -2818,7 +2818,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo
{
if (GetMonData(pkmn, MON_DATA_POKEBALL, NULL) == 11)
friendship++;
- if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name())
+ if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == GetCurrentRegionMapSectionId())
friendship++;
}
if (friendship < 0)
@@ -3320,7 +3320,7 @@ bool8 PokemonUseItemEffects2(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 m
{
if (GetMonData(pkmn, MON_DATA_POKEBALL, NULL) == 11)
friendship++;
- if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name())
+ if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == GetCurrentRegionMapSectionId())
friendship++;
}
if (friendship < 0)
@@ -3347,7 +3347,7 @@ bool8 PokemonUseItemEffects2(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 m
{
if (GetMonData(pkmn, MON_DATA_POKEBALL, NULL) == 11)
friendship++;
- if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name())
+ if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == GetCurrentRegionMapSectionId())
friendship++;
}
if (friendship < 0)
@@ -3373,7 +3373,7 @@ bool8 PokemonUseItemEffects2(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 m
{
if (GetMonData(pkmn, MON_DATA_POKEBALL, NULL) == 11)
friendship++;
- if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name())
+ if (GetMonData(pkmn, MON_DATA_MET_LOCATION, NULL) == GetCurrentRegionMapSectionId())
friendship++;
}
if (friendship < 0)
@@ -4526,7 +4526,7 @@ void sub_8042D50(int stat)
BattleStringExpandPlaceholdersToDisplayedString(BattleText_UnknownString3);
}
-u8 *sub_8042DA4(u16 itemId)
+const u8 *Battle_PrintStatBoosterEffectMessage(u16 itemId)
{
int i;
const u8 *itemEffect;
@@ -5033,7 +5033,7 @@ void AdjustFriendship(struct Pokemon *mon, u8 event)
{
if (GetMonData(mon, MON_DATA_POKEBALL, 0) == ITEM_LUXURY_BALL)
friendship++;
- if (GetMonData(mon, MON_DATA_MET_LOCATION, 0) == sav1_map_get_name())
+ if (GetMonData(mon, MON_DATA_MET_LOCATION, 0) == GetCurrentRegionMapSectionId())
friendship++;
}
@@ -5223,7 +5223,7 @@ void sub_8043B48(struct Pokemon *mon, int species, u8 unused, u32 data)
}
}
-bool32 sub_8043B90(struct Pokemon *mon)
+bool8 TryIncrementMonLevel(struct Pokemon *mon)
{
u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
u8 level = GetMonData(mon, MON_DATA_LEVEL, NULL);
diff --git a/src/prof_pc.c b/src/prof_pc.c
new file mode 100644
index 000000000..cfccbd6e3
--- /dev/null
+++ b/src/prof_pc.c
@@ -0,0 +1,108 @@
+#include "global.h"
+#include "event_data.h"
+#include "pokedex.h"
+#include "field_message_box.h"
+#include "constants/species.h"
+
+extern const u8 gUnknown_81A6D17[];
+extern const u8 gUnknown_81A6D6D[];
+extern const u8 gUnknown_81A6DDF[];
+extern const u8 gUnknown_81A6E36[];
+extern const u8 gUnknown_81A6EA4[];
+extern const u8 gUnknown_81A6F0B[];
+extern const u8 gUnknown_81A6F71[];
+extern const u8 gUnknown_81A6FAB[];
+extern const u8 gUnknown_81A6FF1[];
+extern const u8 gUnknown_81A7031[];
+extern const u8 gUnknown_81A7063[];
+extern const u8 gUnknown_81A70A5[];
+extern const u8 gUnknown_81A70D8[];
+extern const u8 gUnknown_81A7108[];
+extern const u8 gUnknown_81A7137[];
+extern const u8 gUnknown_81A7175[];
+
+u16 Special_GetPokedexCount(void)
+{
+ if (gSpecialVar_0x8004 == 0)
+ {
+ gSpecialVar_0x8005 = sub_8088EDC(0);
+ gSpecialVar_0x8006 = sub_8088EDC(1);
+ }
+ else
+ {
+ gSpecialVar_0x8005 = pokedex_count(0);
+ gSpecialVar_0x8006 = pokedex_count(1);
+ }
+ return sub_806E25C();
+}
+
+const u8 * sub_80CA424(u16 count)
+{
+ gSpecialVar_Result = FALSE;
+
+ if (count < 10)
+ return gUnknown_81A6D17;
+
+ if (count < 20)
+ return gUnknown_81A6D6D;
+
+ if (count < 30)
+ return gUnknown_81A6DDF;
+
+ if (count < 40)
+ return gUnknown_81A6E36;
+
+ if (count < 50)
+ return gUnknown_81A6EA4;
+
+ if (count < 60)
+ return gUnknown_81A6F0B;
+
+ if (count < 70)
+ return gUnknown_81A6F71;
+
+ if (count < 80)
+ return gUnknown_81A6FAB;
+
+ if (count < 90)
+ return gUnknown_81A6FF1;
+
+ if (count < 100)
+ return gUnknown_81A7031;
+
+ if (count < 110)
+ return gUnknown_81A7063;
+
+ if (count < 120)
+ return gUnknown_81A70A5;
+
+ if (count < 130)
+ return gUnknown_81A70D8;
+
+ if (count < 140)
+ return gUnknown_81A7108;
+
+ if (count < 150)
+ return gUnknown_81A7137;
+
+ if (count == 150)
+ {
+ if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_MEW), 1))
+ return gUnknown_81A7137;
+ gSpecialVar_Result = TRUE;
+ return gUnknown_81A7175;
+ }
+
+ if (count == 151)
+ {
+ gSpecialVar_Result = TRUE;
+ return gUnknown_81A7175;
+ }
+
+ return gUnknown_81A6D17;
+}
+
+void sub_80CA524(void)
+{
+ ShowFieldMessage(sub_80CA424(gSpecialVar_0x8004));
+}
diff --git a/src/quest_log.c b/src/quest_log.c
index 4f462505a..0021ee927 100644
--- a/src/quest_log.c
+++ b/src/quest_log.c
@@ -922,7 +922,7 @@ void sub_8111070(u8 a0)
StringAppend(gStringVar4, gStringVar1);
}
- AddTextPrinterParametrized2(gUnknown_203ADFE[0], 2, 2, 2, 1, 2, &gUnknown_8456634, 0, gStringVar4);
+ AddTextPrinterParameterized4(gUnknown_203ADFE[0], 2, 2, 2, 1, 2, &gUnknown_8456634, 0, gStringVar4);
PutWindowTilemap(gUnknown_203ADFE[0]);
PutWindowTilemap(gUnknown_203ADFE[1]);
CopyWindowToVram(gUnknown_203ADFE[0], 2);
@@ -985,19 +985,19 @@ void sub_8111368(void)
{
gUnknown_203ADFA = 2;
sub_806E6FC();
- sub_809A2DC();
- sub_809A2A4();
+ ClearItemSlotsInAllBagPockets();
+ ClearPCItemSlots();
if (sub_8110AC8() == 1)
{
sub_8111274(gUnknown_203ADF8, 0);
- gUnknown_3005024 = sub_8111038;
+ gFieldCallback2 = sub_8111038;
SetMainCallback2(sub_80572A8);
}
else
{
sub_8111274(gUnknown_203ADF8, 1);
warp_in();
- gUnknown_3005024 = sub_8111000;
+ gFieldCallback2 = sub_8111000;
SetMainCallback2(sub_805726C);
}
}
@@ -1055,7 +1055,7 @@ void sub_8111438(void)
{
for (r6 = 0; r6 < 30; r6++)
{
- if (GetBoxMonDataFromAnyBox(r3, r6, MON_DATA_SANITY_BIT2))
+ if (GetBoxMonDataFromAnyBox(r3, r6, MON_DATA_SANITY_HAS_SPECIES))
{
sub_808BCB4(r3, r6);
r5--;
@@ -1074,7 +1074,7 @@ void sub_8111438(void)
for (r6 = 0; r6 < IN_BOX_COUNT; r6++)
{
struct BoxPokemon * boxMon = GetBoxedMonPtr(r3, r6);
- if (!GetBoxMonData(boxMon, MON_DATA_SANITY_BIT2))
+ if (!GetBoxMonData(boxMon, MON_DATA_SANITY_HAS_SPECIES))
{
CopyMon(boxMon, &r9->mon.box, sizeof(struct BoxPokemon));
r5++;
@@ -1104,7 +1104,7 @@ u16 sub_8111618(void)
for (i = 0; i < PARTY_SIZE; i++)
{
- if (GetMonData(&gPlayerParty[i], MON_DATA_SANITY_BIT2))
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SANITY_HAS_SPECIES))
count++;
}
@@ -1120,7 +1120,7 @@ u16 sub_811164C(void)
{
for (j = 0; j < IN_BOX_COUNT; j++)
{
- if (GetBoxMonDataFromAnyBox(i, j, MON_DATA_SANITY_BIT2))
+ if (GetBoxMonDataFromAnyBox(i, j, MON_DATA_SANITY_HAS_SPECIES))
count++;
}
}
@@ -1237,7 +1237,7 @@ void sub_8111984(void)
Save_ResetSaveCounters();
Save_LoadGameData(0);
SetMainCallback2(sub_8057430);
- gUnknown_3005024 = sub_8111F60;
+ gFieldCallback2 = sub_8111F60;
FreeAllWindowBuffers();
gUnknown_203ADFA = 3;
gUnknown_203AE8C = NULL;
@@ -1417,7 +1417,7 @@ void sub_8111D10(void)
PutWindowTilemap(gUnknown_203ADFE[2]);
sub_8111D90(gUnknown_203ADFE[2]);
- AddTextPrinterParametrized2(gUnknown_203ADFE[2], 2, 2, gUnknown_8456698[count], 1, 0, &gUnknown_8456634, 0, gStringVar4);
+ AddTextPrinterParameterized4(gUnknown_203ADFE[2], 2, 2, gUnknown_8456698[count], 1, 0, &gUnknown_8456634, 0, gStringVar4);
schedule_bg_copy_tilemap_to_vram(0);
}
@@ -1599,7 +1599,7 @@ void sub_81120AC(u8 taskId)
gUnknown_203AE94 = (struct UnkStruct_203AE94){};
sub_80696C0();
ScriptContext2_Disable();
- gTextFlags.flag_2 = FALSE;
+ gTextFlags.autoScroll = FALSE;
gUnknown_2036E28 = 0;
sub_8082740(0);
gUnknown_3005ECC = 1;
@@ -1691,7 +1691,7 @@ void sub_81123BC(void)
void sub_8112450(void)
{
- if (sub_80BF708() != 1)
+ if (MenuHelpers_LinkSomething() != 1)
{
sub_8112364();
sub_81123BC();
@@ -2291,7 +2291,7 @@ void sub_8112E3C(u8 a0, struct UnkStruct_300201C * a1, u16 a2)
}
}
-const u16 gUnknown_84566A8[][16] = INCBIN_U16("data/graphics/unknown_84566a8.bin");
+const u16 gUnknown_84566A8[] = INCBIN_U16("data/graphics/unknown_84566a8.bin");
const struct WindowTemplate gUnknown_8456928 = {
0x00, 0, 15, 30, 5, 15, 0x008F
@@ -2349,7 +2349,7 @@ void sub_8112F18(u8 a0)
else
k = 5;
CpuCopy32(
- gUnknown_84566A8[k], // operand swap on "add" instruction
+ (void *)gUnknown_84566A8 + 32 * k, // operand swap on "add" instruction
buffer + 32 * (i * width + j),
32
);
@@ -2468,7 +2468,7 @@ const struct TextColor gUnknown_8456930 = {
void sub_8112FE4(const u8 * a0)
{
- AddTextPrinterParametrized2(gUnknown_203B020, 0x02, 2, 5, 1, 1, &gUnknown_8456930, -1, a0);
+ AddTextPrinterParameterized4(gUnknown_203B020, 0x02, 2, 5, 1, 1, &gUnknown_8456930, -1, a0);
}
void sub_8113018(const u8 * a0, u8 a1)
@@ -2515,7 +2515,7 @@ void sub_81130BC(struct Var4038Struct * varPtr)
FlagClear(FLAG_0x06D);
FlagClear(FLAG_0x06E);
FlagClear(FLAG_0x06F);
- VarSet(VAR_0x4073, 1);
+ VarSet(VAR_MAP_SCENE_SAFFRON_CITY_POKEMON_TRAINER_FAN_CLUB, 1);
}
}
@@ -2523,7 +2523,7 @@ ALIGNED(4) const u8 gUnknown_8456934[] = {2, 1, 2, 1};
u8 sub_8113114(struct Var4038Struct * a0, u8 a1)
{
- if (VarGet(VAR_0x4073) == 2)
+ if (VarGet(VAR_MAP_SCENE_SAFFRON_CITY_POKEMON_TRAINER_FAN_CLUB) == 2)
{
if (a0->unk_0_0 + gUnknown_8456934[a1] >= 20)
{
@@ -2743,10 +2743,10 @@ void sub_81134B8(void)
void sub_81134CC(struct Var4038Struct * a0)
{
- if (VarGet(VAR_0x4073) == 2)
+ if (VarGet(VAR_MAP_SCENE_SAFFRON_CITY_POKEMON_TRAINER_FAN_CLUB) == 2)
{
sub_8113078(a0);
- if (gUnknown_2023E8A == 1)
+ if (gBattleOutcome == B_OUTCOME_WON)
sub_8113194(a0);
else
sub_81131FC(a0);
@@ -2842,7 +2842,7 @@ void sub_8113550(u16 a0, const u16 * a1)
if (sub_81138A0(a0, a1) == TRUE)
return;
- if (sub_80BF708() == TRUE)
+ if (MenuHelpers_LinkSomething() == TRUE)
return;
// NONMATCHING: branch logic here
@@ -2954,7 +2954,7 @@ void sub_8113550(u16 a0, const u16 * a1)
"\tbne _081135AA\n"
"\tb ._return\n"
"_081135AA:\n"
- "\tbl sub_80BF708\n"
+ "\tbl MenuHelpers_LinkSomething\n"
"\tlsls r0, 24\n"
"\tlsrs r0, 24\n"
"\tcmp r0, 0x1\n"
@@ -3708,7 +3708,7 @@ const u16 * sub_8113FBC(const u16 * a0)
case POCKET_ITEMS:
case POCKET_POKE_BALLS:
case POCKET_BERRY_POUCH:
- StringCopy(gStringVar1, ItemId_GetItem(r5[0])->name);
+ StringCopy(gStringVar1, ItemId_GetName(r5[0]));
if (r5[0] == ITEM_ESCAPE_ROPE)
{
sub_80C4DF8(gStringVar2, r5[2]);
@@ -3725,7 +3725,7 @@ const u16 * sub_8113FBC(const u16 * a0)
}
break;
case POCKET_KEY_ITEMS:
- StringCopy(gStringVar1, ItemId_GetItem(r5[0])->name);
+ StringCopy(gStringVar1, ItemId_GetName(r5[0]));
StringExpandPlaceholders(gStringVar4, gUnknown_841A220);
break;
case POCKET_TM_CASE:
@@ -3771,7 +3771,7 @@ const u16 * sub_8114188(const u16 * a0)
{
const u16 * r4 = sub_8113E88(5, a0);
QuestLog_AutoGetSpeciesName(r4[1], gStringVar1, 0);
- StringCopy(gStringVar2, ItemId_GetItem(r4[0])->name);
+ StringCopy(gStringVar2, ItemId_GetName(r4[0]));
StringExpandPlaceholders(gStringVar4, gUnknown_841AB74);
r4 += 2;
return r4;
@@ -3787,7 +3787,7 @@ const u16 * sub_81141E4(const u16 * a0)
const u16 * r4 = sub_8113E88(6, a0);
QuestLog_AutoGetSpeciesName(r4[1], gStringVar1, 0);
- StringCopy(gStringVar2, ItemId_GetItem(r4[0])->name);
+ StringCopy(gStringVar2, ItemId_GetName(r4[0]));
StringExpandPlaceholders(gStringVar4, gUnknown_841AB8E);
r4 += 2;
return r4;
@@ -3803,7 +3803,7 @@ const u16 * sub_8114240(const u16 * a0)
const u16 * r4 = sub_8113E88(7, a0);
QuestLog_AutoGetSpeciesName(r4[1], gStringVar2, 0);
- StringCopy(gStringVar1, ItemId_GetItem(r4[0])->name);
+ StringCopy(gStringVar1, ItemId_GetName(r4[0]));
StringExpandPlaceholders(gStringVar4, gUnknown_841A6A5);
r4 += 2;
return r4;
@@ -3819,7 +3819,7 @@ const u16 * sub_811429C(const u16 * a0)
const u16 * r4 = sub_8113E88(8, a0);
QuestLog_AutoGetSpeciesName(r4[1], gStringVar1, 0);
- StringCopy(gStringVar2, ItemId_GetItem(r4[0])->name);
+ StringCopy(gStringVar2, ItemId_GetName(r4[0]));
StringExpandPlaceholders(gStringVar4, gUnknown_841A1CD);
r4 += 2;
return r4;
@@ -3846,8 +3846,8 @@ const u16 * sub_8114324(const u16 * a0)
{
const u16 * r4 = sub_8113E88(9, a0);
QuestLog_AutoGetSpeciesName(r4[2], gStringVar1, 0);
- StringCopy(gStringVar2, ItemId_GetItem(r4[0])->name);
- StringCopy(gStringVar3, ItemId_GetItem(r4[1])->name);
+ StringCopy(gStringVar2, ItemId_GetName(r4[0]));
+ StringCopy(gStringVar3, ItemId_GetName(r4[1]));
StringExpandPlaceholders(gStringVar4, gUnknown_841A193);
r4 += 3;
return r4;
@@ -3862,8 +3862,8 @@ const u16 * sub_8114394(const u16 * a0)
{
const u16 * r4 = sub_8113E88(10, a0);
QuestLog_AutoGetSpeciesName(r4[2], gStringVar2, 0);
- StringCopy(gStringVar3, ItemId_GetItem(r4[0])->name);
- StringCopy(gStringVar1, ItemId_GetItem(r4[1])->name);
+ StringCopy(gStringVar3, ItemId_GetName(r4[0]));
+ StringCopy(gStringVar1, ItemId_GetName(r4[1]));
StringExpandPlaceholders(gStringVar4, gUnknown_841A6E1);
r4 += 3;
return r4;
@@ -4312,7 +4312,7 @@ u16 * sub_8114C68(u16 * a0, const u16 * a1)
const u16 * sub_8114C8C(const u16 * a0)
{
const u16 *r4 = sub_8113E88(28, a0);
- sub_8099E90(r4[0], gStringVar1);
+ CopyItemName(r4[0], gStringVar1);
StringExpandPlaceholders(gStringVar4, gUnknown_841A391);
return r4 + 1;
}
@@ -4329,7 +4329,7 @@ u16 * sub_8114CC0(u16 * a0, const u16 * a1)
const u16 * sub_8114CE4(const u16 * a0)
{
const u16 *r4 = sub_8113E88(29, a0);
- sub_8099E90(r4[0], gStringVar1);
+ CopyItemName(r4[0], gStringVar1);
StringExpandPlaceholders(gStringVar4, gUnknown_841A3DA);
return r4 + 1;
}
@@ -4817,7 +4817,7 @@ const u16 * sub_8115518(const u16 * a0)
UnkTextUtil_Reset();
sub_80C4DF8(gStringVar1, r7[0]);
UnkTextUtil_SetPtrI(0, gStringVar1);
- UnkTextUtil_SetPtrI(1, ItemId_GetItem(r4[0])->name);
+ UnkTextUtil_SetPtrI(1, ItemId_GetName(r4[0]));
if (r4[1] < 2)
UnkTextUtil_StringExpandPlaceholders(gStringVar4, gUnknown_841A7DD);
else
@@ -4852,7 +4852,7 @@ const u16 * sub_81155E0(const u16 * a0) {
if (r7[1] == 0) {
UnkTextUtil_SetPtrI(0, gSaveBlock2Ptr->playerName);
UnkTextUtil_SetPtrI(1, gStringVar1);
- UnkTextUtil_SetPtrI(2, ItemId_GetItem(r5[0])->name);
+ UnkTextUtil_SetPtrI(2, ItemId_GetName(r5[0]));
if (r5[1] == 1)
UnkTextUtil_SetPtrI(3, gUnknown_841A8D4);
else
@@ -4867,7 +4867,7 @@ const u16 * sub_81155E0(const u16 * a0) {
else
{
UnkTextUtil_SetPtrI(0, gStringVar1);
- UnkTextUtil_SetPtrI(1, ItemId_GetItem(r5[0])->name);
+ UnkTextUtil_SetPtrI(1, ItemId_GetName(r5[0]));
ConvertIntToDecimalStringN(gStringVar2, r6, STR_CONV_MODE_LEFT_ALIGN, 6);
UnkTextUtil_SetPtrI(2, gStringVar2);
UnkTextUtil_StringExpandPlaceholders(gStringVar4, gUnknown_841A896);
@@ -4890,7 +4890,7 @@ const u16 * sub_8115700(const u16 * a0)
const u16 * r4 = sub_8113E88(40, a0);
const u8 * r5 = (const u8 *)r4 + 2;
sub_80C4DF8(gStringVar1, r5[0]);
- StringCopy(gStringVar2, ItemId_GetItem(r4[0])->name);
+ StringCopy(gStringVar2, ItemId_GetName(r4[0]));
StringExpandPlaceholders(gStringVar4, gUnknown_841B03F);
return (const u16 *)(r5 + 2);
}
diff --git a/src/quest_log_battle.c b/src/quest_log_battle.c
index c702b6a5c..4a63042bf 100644
--- a/src/quest_log_battle.c
+++ b/src/quest_log_battle.c
@@ -26,7 +26,7 @@ void sub_812C334(s32 *, s32 *);
void sub_812BFDC(void)
{
- if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_DOME)) && (gUnknown_2023E8A == 1 || gUnknown_2023E8A == 7))
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_DOME)) && (gBattleOutcome == B_OUTCOME_WON || gBattleOutcome == B_OUTCOME_CAUGHT))
{
struct QuestLogStruct_TrainerBattleRecord * questLogTrainerBattleRecord = Alloc(sizeof(struct QuestLogStruct_TrainerBattleRecord));
struct QuestLogStruct_WildBattleRecord * questLogWildBattleRecord = Alloc(sizeof(struct QuestLogStruct_WildBattleRecord));
@@ -71,7 +71,7 @@ void sub_812BFDC(void)
playerEndingHP = gBattleMons[GetBattlerAtPosition(0)].hp;
playerMaxHP = gBattleMons[GetBattlerAtPosition(0)].maxHP;
}
- questLogTrainerBattleRecord->v7 = sav1_map_get_name();
+ questLogTrainerBattleRecord->v7 = GetCurrentRegionMapSectionId();
questLogTrainerBattleRecord->v6 = 0;
if (playerEndingHP < playerMaxHP / 3 * 2)
questLogTrainerBattleRecord->v6 = 1;
@@ -81,7 +81,7 @@ void sub_812BFDC(void)
}
else
{
- if (gUnknown_2023E8A == 1)
+ if (gBattleOutcome == B_OUTCOME_WON)
{
questLogWildBattleRecord->v0 = GetMonData(gEnemyParty + 0, MON_DATA_SPECIES);
questLogWildBattleRecord->v2 = SPECIES_NONE;
@@ -91,7 +91,7 @@ void sub_812BFDC(void)
questLogWildBattleRecord->v0 = SPECIES_NONE;
questLogWildBattleRecord->v2 = GetMonData(gEnemyParty + 0, MON_DATA_SPECIES);
}
- questLogWildBattleRecord->v4 = sav1_map_get_name();
+ questLogWildBattleRecord->v4 = GetCurrentRegionMapSectionId();
sub_8113550(31, (const u16 *)questLogWildBattleRecord);
}
Free(questLogTrainerBattleRecord);
@@ -116,7 +116,7 @@ void sub_812C224(void)
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
{
struct QuestLogStruct_LinkBattleRecord * r5 = Alloc(sizeof(struct QuestLogStruct_LinkBattleRecord));
- r5->v0 = gUnknown_2023E8A - 1;
+ r5->v0 = gBattleOutcome - 1; // 0 = won, 1 = lost, 2 = drew
if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
{
r8 = 15;
diff --git a/src/roamer.c b/src/roamer.c
new file mode 100644
index 000000000..b42855644
--- /dev/null
+++ b/src/roamer.c
@@ -0,0 +1,240 @@
+#include "global.h"
+#include "roamer.h"
+#include "random.h"
+#include "overworld.h"
+#include "field_specials.h"
+#include "constants/species.h"
+#include "constants/maps.h"
+#include "constants/region_map.h"
+
+EWRAM_DATA u8 sLocationHistory[3][2] = {};
+EWRAM_DATA u8 sRoamerLocation[2] = {};
+
+#define saveRoamer (*(&gSaveBlock1Ptr->roamer))
+
+enum
+{
+ MAP_GRP = 0, // map group
+ MAP_NUM = 1, // map number
+};
+
+const u8 sRoamerLocations[][7] = {
+ {MAP_NUM(ROUTE1), MAP_NUM(ROUTE2), MAP_NUM(ROUTE21_NORTH), MAP_NUM(ROUTE22), 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE2), MAP_NUM(ROUTE1), MAP_NUM(ROUTE3), MAP_NUM(ROUTE22), 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE3), MAP_NUM(ROUTE2), MAP_NUM(ROUTE4), 0xff, 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE4), MAP_NUM(ROUTE3), MAP_NUM(ROUTE5), MAP_NUM(ROUTE9), MAP_NUM(ROUTE24), 0xff, 0xff},
+ {MAP_NUM(ROUTE5), MAP_NUM(ROUTE4), MAP_NUM(ROUTE6), MAP_NUM(ROUTE7), MAP_NUM(ROUTE8), MAP_NUM(ROUTE9), MAP_NUM(ROUTE24)},
+ {MAP_NUM(ROUTE6), MAP_NUM(ROUTE5), MAP_NUM(ROUTE7), MAP_NUM(ROUTE8), MAP_NUM(ROUTE11), 0xff, 0xff},
+ {MAP_NUM(ROUTE7), MAP_NUM(ROUTE5), MAP_NUM(ROUTE6), MAP_NUM(ROUTE8), MAP_NUM(ROUTE16), 0xff, 0xff},
+ {MAP_NUM(ROUTE8), MAP_NUM(ROUTE5), MAP_NUM(ROUTE6), MAP_NUM(ROUTE7), MAP_NUM(ROUTE10), MAP_NUM(ROUTE12), 0xff},
+ {MAP_NUM(ROUTE9), MAP_NUM(ROUTE4), MAP_NUM(ROUTE5), MAP_NUM(ROUTE10), MAP_NUM(ROUTE24), 0xff, 0xff},
+ {MAP_NUM(ROUTE10), MAP_NUM(ROUTE8), MAP_NUM(ROUTE9), MAP_NUM(ROUTE12), 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE11), MAP_NUM(ROUTE6), MAP_NUM(ROUTE12), 0xff, 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE12), MAP_NUM(ROUTE10), MAP_NUM(ROUTE11), MAP_NUM(ROUTE13), 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE13), MAP_NUM(ROUTE12), MAP_NUM(ROUTE14), 0xff, 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE14), MAP_NUM(ROUTE13), MAP_NUM(ROUTE15), 0xff, 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE15), MAP_NUM(ROUTE14), MAP_NUM(ROUTE18), MAP_NUM(ROUTE19), 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE16), MAP_NUM(ROUTE7), MAP_NUM(ROUTE17), 0xff, 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE17), MAP_NUM(ROUTE16), MAP_NUM(ROUTE18), 0xff, 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE18), MAP_NUM(ROUTE15), MAP_NUM(ROUTE17), MAP_NUM(ROUTE19), 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE19), MAP_NUM(ROUTE15), MAP_NUM(ROUTE18), MAP_NUM(ROUTE20), 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE20), MAP_NUM(ROUTE19), MAP_NUM(ROUTE21_NORTH), 0xff, 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE21_NORTH), MAP_NUM(ROUTE1), MAP_NUM(ROUTE20), 0xff, 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE22), MAP_NUM(ROUTE1), MAP_NUM(ROUTE2), MAP_NUM(ROUTE23), 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE23), MAP_NUM(ROUTE22), MAP_NUM(ROUTE2), 0xff, 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE24), MAP_NUM(ROUTE4), MAP_NUM(ROUTE5), MAP_NUM(ROUTE9), 0xff, 0xff, 0xff},
+ {MAP_NUM(ROUTE25), MAP_NUM(ROUTE24), MAP_NUM(ROUTE9), 0xff, 0xff, 0xff, 0xff},
+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+};
+
+void ClearRoamerData(void)
+{
+ u32 i;
+ gSaveBlock1Ptr->roamer = (struct Roamer){};
+ sRoamerLocation[MAP_GRP] = 0;
+ sRoamerLocation[MAP_NUM] = 0;
+ for (i = 0; i < 3; i++)
+ {
+ sLocationHistory[i][MAP_GRP] = 0;
+ sLocationHistory[i][MAP_NUM] = 0;
+ }
+}
+
+#define GetRoamerSpecies() ({\
+ u16 a;\
+ switch (ScrSpecial_GetStarter())\
+ {\
+ default:\
+ a = SPECIES_RAIKOU;\
+ break;\
+ case SPECIES_BULBASAUR:\
+ a = SPECIES_ENTEI;\
+ break;\
+ case SPECIES_CHARMANDER:\
+ a = SPECIES_SUICUNE;\
+ break;\
+ }\
+ a;\
+})
+
+void CreateInitialRoamerMon(void)
+{
+ struct Pokemon * tmpMon = &gEnemyParty[0];
+ u16 roamerMon;
+
+ CreateMon(tmpMon, (roamerMon = GetRoamerSpecies()), 50, 0x20, 0, 0, 0, 0);
+ saveRoamer.species = roamerMon;
+ saveRoamer.level = 50;
+ saveRoamer.status = 0;
+ saveRoamer.active = TRUE;
+ saveRoamer.ivs = GetMonData(tmpMon, MON_DATA_IVS);
+ saveRoamer.personality = GetMonData(tmpMon, MON_DATA_PERSONALITY);
+ saveRoamer.hp = GetMonData(tmpMon, MON_DATA_MAX_HP);
+ saveRoamer.cool = GetMonData(tmpMon, MON_DATA_COOL);
+ saveRoamer.beauty = GetMonData(tmpMon, MON_DATA_BEAUTY);
+ saveRoamer.cute = GetMonData(tmpMon, MON_DATA_CUTE);
+ saveRoamer.smart = GetMonData(tmpMon, MON_DATA_SMART);
+ saveRoamer.tough = GetMonData(tmpMon, MON_DATA_TOUGH);
+ sRoamerLocation[MAP_GRP] = 3;
+ sRoamerLocation[MAP_NUM] = sRoamerLocations[Random() % (ARRAY_COUNT(sRoamerLocations) - 1)][0];
+}
+
+void InitRoamer(void)
+{
+ ClearRoamerData();
+ CreateInitialRoamerMon();
+}
+
+void UpdateLocationHistoryForRoamer(void)
+{
+ sLocationHistory[2][MAP_GRP] = sLocationHistory[1][MAP_GRP];
+ sLocationHistory[2][MAP_NUM] = sLocationHistory[1][MAP_NUM];
+ sLocationHistory[1][MAP_GRP] = sLocationHistory[0][MAP_GRP];
+ sLocationHistory[1][MAP_NUM] = sLocationHistory[0][MAP_NUM];
+ sLocationHistory[0][MAP_GRP] = gSaveBlock1Ptr->location.mapGroup;
+ sLocationHistory[0][MAP_NUM] = gSaveBlock1Ptr->location.mapNum;
+}
+
+void RoamerMoveToOtherLocationSet(void)
+{
+ u8 mapNum = 0;
+ struct Roamer *roamer = &saveRoamer;
+
+ if (!roamer->active)
+ return;
+
+ sRoamerLocation[MAP_GRP] = 3;
+
+ while (1)
+ {
+ mapNum = sRoamerLocations[Random() % (ARRAY_COUNT(sRoamerLocations) - 1)][0];
+ if (sRoamerLocation[MAP_NUM] != mapNum)
+ {
+ sRoamerLocation[MAP_NUM] = mapNum;
+ return;
+ }
+ }
+}
+
+
+void RoamerMove(void)
+{
+ u8 locSet = 0;
+
+ if ((Random() % 16) == 0)
+ {
+ RoamerMoveToOtherLocationSet();
+ }
+ else
+ {
+ struct Roamer *roamer = &saveRoamer;
+
+ if (!roamer->active)
+ return;
+
+ while (locSet < (ARRAY_COUNT(sRoamerLocations) - 1))
+ {
+ if (sRoamerLocation[MAP_NUM] == sRoamerLocations[locSet][0])
+ {
+ u8 mapNum;
+ while (1)
+ {
+ mapNum = sRoamerLocations[locSet][(Random() % 6) + 1];
+ if (!(sLocationHistory[2][MAP_GRP] == 3 && sLocationHistory[2][MAP_NUM] == mapNum) && mapNum != 0xFF)
+ break;
+ }
+ sRoamerLocation[MAP_NUM] = mapNum;
+ return;
+ }
+ locSet++;
+ }
+ }
+}
+
+bool8 IsRoamerAt(u8 mapGroup, u8 mapNum)
+{
+ struct Roamer *roamer = &saveRoamer;
+
+ if (roamer->active && mapGroup == sRoamerLocation[MAP_GRP] && mapNum == sRoamerLocation[MAP_NUM])
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void CreateRoamerMonInstance(void)
+{
+ struct Pokemon *mon;
+ struct Roamer *roamer;
+
+ mon = &gEnemyParty[0];
+ ZeroEnemyPartyMons();
+ roamer = &saveRoamer;
+ CreateMonWithIVsPersonality(mon, roamer->species, roamer->level, roamer->ivs, roamer->personality);
+ SetMonData(mon, MON_DATA_STATUS, &gSaveBlock1Ptr->roamer.status);
+ SetMonData(mon, MON_DATA_HP, &gSaveBlock1Ptr->roamer.hp);
+ SetMonData(mon, MON_DATA_COOL, &gSaveBlock1Ptr->roamer.cool);
+ SetMonData(mon, MON_DATA_BEAUTY, &gSaveBlock1Ptr->roamer.beauty);
+ SetMonData(mon, MON_DATA_CUTE, &gSaveBlock1Ptr->roamer.cute);
+ SetMonData(mon, MON_DATA_SMART, &gSaveBlock1Ptr->roamer.smart);
+ SetMonData(mon, MON_DATA_TOUGH, &gSaveBlock1Ptr->roamer.tough);
+}
+
+bool8 TryStartRoamerEncounter(void)
+{
+ if (IsRoamerAt(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum) == TRUE && (Random() % 4) == 0)
+ {
+ CreateRoamerMonInstance();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+void UpdateRoamerHPStatus(struct Pokemon *mon)
+{
+ saveRoamer.hp = GetMonData(mon, MON_DATA_HP);
+ saveRoamer.status = GetMonData(mon, MON_DATA_STATUS);
+
+ RoamerMoveToOtherLocationSet();
+}
+
+void SetRoamerInactive(void)
+{
+ struct Roamer *roamer = &saveRoamer;
+ roamer->active = FALSE;
+}
+
+void GetRoamerLocation(u8 *mapGroup, u8 *mapNum)
+{
+ *mapGroup = sRoamerLocation[MAP_GRP];
+ *mapNum = sRoamerLocation[MAP_NUM];
+}
+
+u16 GetRoamerLocationMapSectionId(void)
+{
+ struct Roamer *roamer = &saveRoamer;
+ if (!saveRoamer.active)
+ return MAPSEC_NONE;
+ return get_mapheader_by_bank_and_number(sRoamerLocation[MAP_GRP], sRoamerLocation[MAP_NUM])->regionMapSectionId;
+}
diff --git a/src/roulette_util.c b/src/roulette_util.c
new file mode 100644
index 000000000..3c5a3c825
--- /dev/null
+++ b/src/roulette_util.c
@@ -0,0 +1,463 @@
+#include "global.h"
+#include "palette.h"
+#include "roulette_util.h"
+#include "util.h"
+
+void sub_80D8BE4(struct UnkStruct0 *r0)
+{
+ r0->var00 = 0;
+ r0->var02 = 0;
+ memset(&r0->var04, 0, sizeof(r0->var04));
+}
+
+u8 sub_80D8BF8(struct UnkStruct0 *r0, u8 r1, const struct UnkStruct1 *r2)
+{
+ if (!(r1 < 16) || (r0->var04[r1].var00_7))
+ return 0xFF;
+
+ r0->var04[r1].var04.var00 = r2->var00;
+ r0->var04[r1].var04.var02 = r2->var02;
+ r0->var04[r1].var04.var04 = r2->var04;
+ r0->var04[r1].var04.var05 = r2->var05;
+ r0->var04[r1].var04.var06 = r2->var06;
+ r0->var04[r1].var04.var07_0 = r2->var07_0;
+ r0->var04[r1].var04.var07_5 = r2->var07_5;
+ r0->var04[r1].var04.var07_7 = r2->var07_7;
+ r0->var04[r1].var00_0 = 0;
+ r0->var04[r1].var00_7 = 1;
+ r0->var04[r1].var02 = 0;
+ r0->var04[r1].var01 = 0;
+ if (r0->var04[r1].var04.var07_7 < 0)
+ r0->var04[r1].var03 = 0xFF;
+ else
+ r0->var04[r1].var03 = 1;
+
+ return r1;
+}
+
+u8 sub_80D8C7C(struct UnkStruct0 *r0, u8 r1)
+{
+ if (r1 >= 16)
+ return 0xFF;
+ if (!r0->var04[r1].var00_7)
+ return 0xFF;
+
+ memset(&r0->var04[r1], 0, sizeof(r0->var04[r1]));
+ return r1;
+}
+
+u8 sub_80D8CB0(struct UnkStruct3 *r0)
+{
+ u8 i;
+ u8 returnval;
+
+ for (i = 0; i < r0->var04.var04; i++)
+ {
+ struct PlttData *faded = (struct PlttData *)&gPlttBufferFaded[r0->var04.var02 + i];
+ struct PlttData *unfaded = (struct PlttData *)&gPlttBufferUnfaded[r0->var04.var02 + i];
+
+ switch (r0->var00_0)
+ {
+ case 1:
+ if (faded->r + r0->var03 >= 0 && faded->r + r0->var03 < 32)
+ faded->r += r0->var03;
+ if (faded->g + r0->var03 >= 0 && faded->g + r0->var03 < 32)
+ faded->g += r0->var03;
+ if (faded->b + r0->var03 >= 0 && faded->b + r0->var03 < 32)
+ faded->b += r0->var03;
+ break;
+ case 2:
+ if (r0->var03 < 0)
+ {
+ if (faded->r + r0->var03 >= unfaded->r)
+ faded->r += r0->var03;
+ if (faded->g + r0->var03 >= unfaded->g)
+ faded->g += r0->var03;
+ if (faded->b + r0->var03 >= unfaded->b)
+ faded->b += r0->var03;
+ }
+ else
+ {
+ if (faded->r + r0->var03 <= unfaded->r)
+ faded->r += r0->var03;
+ if (faded->g + r0->var03 <= unfaded->g)
+ faded->g += r0->var03;
+ if (faded->b + r0->var03 <= unfaded->b)
+ faded->b += r0->var03;
+ }
+ break;
+ }
+ }
+ if ((u32)r0->var02++ != r0->var04.var07_0)
+ {
+ returnval = 0;
+ }
+ else
+ {
+ r0->var02 = 0;
+ r0->var03 *= -1;
+ if (r0->var00_0 == 1)
+ r0->var00_0++;
+ else
+ r0->var00_0--;
+ returnval = 1;
+ }
+ return returnval;
+}
+
+u8 sub_80D8EB8(struct UnkStruct3 *r0)
+{
+ u8 rg2 = 0;
+
+ switch (r0->var00_0)
+ {
+ case 1:
+ for (rg2 = 0; rg2 < r0->var04.var04; rg2++)
+ gPlttBufferFaded[r0->var04.var02 + rg2] = r0->var04.var00;
+ r0->var00_0++;
+ break;
+ case 2:
+ for (rg2 = 0; rg2 < r0->var04.var04; rg2++)
+ gPlttBufferFaded[r0->var04.var02 + rg2] = gPlttBufferUnfaded[r0->var04.var02 + rg2];
+ r0->var00_0--;
+ break;
+ }
+ return 1;
+}
+
+void task_tutorial_controls_fadein(struct UnkStruct0 *r0)
+{
+ u8 i = 0;
+
+ if (r0->var00)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ if ((r0->var02 >> i) & 1)
+ {
+ if (--r0->var04[i].var01 == 0xFF) // if underflow ?
+ {
+ if (r0->var04[i].var04.var00 & 0x8000) // PlttData->unused_15 ?
+ sub_80D8CB0(&r0->var04[i]);
+ else
+ sub_80D8EB8(&r0->var04[i]);
+
+ r0->var04[i].var01 = r0->var04[i].var04.var05;
+ }
+ }
+ }
+ }
+}
+
+void sub_80D8FB4(struct UnkStruct0 *r0, u16 r1)
+{
+ u8 i = 0;
+
+ r0->var00++;
+ for (i = 0; i < 16; i++)
+ {
+ if ((r1 >> i) & 1)
+ {
+ if (r0->var04[i].var00_7)
+ {
+ r0->var02 |= 1 << i;
+ r0->var04[i].var00_0 = 1;
+ }
+ }
+ }
+}
+
+void sub_80D9008(struct UnkStruct0 *r0, u16 r1)
+{
+ u8 i;
+
+ for (i = 0; i < 16; i++)
+ {
+ if ((r0->var02 >> i) & 1)
+ {
+ if (r0->var04[i].var00_7)
+ {
+ if ((r1 >> i) & 1)
+ {
+ u32 offset = r0->var04[i].var04.var02;
+ u16 *faded = &gPlttBufferFaded[offset];
+ u16 *unfaded = &gPlttBufferUnfaded[offset];
+ memcpy(faded, unfaded, r0->var04[i].var04.var04 * 2);
+ r0->var04[i].var00_0 = 0;
+ r0->var04[i].var02 = 0;
+ r0->var04[i].var01 = 0;
+ if (r0->var04[i].var04.var07_7 < 0)
+ r0->var04[i].var03 = 0xFF;
+ else
+ r0->var04[i].var03 = 0x1;
+ }
+ }
+ }
+ }
+ if (r1 == 0xFFFF)
+ {
+ r0->var00 = 0;
+ r0->var02 = 0;
+ }
+ else
+ {
+ r0->var02 = r0->var02 & ~r1;
+ }
+}
+
+void InitPulseBlend(struct PulseBlend *pulseBlend)
+{
+ u8 i = 0;
+ pulseBlend->usedPulseBlendPalettes = 0;
+ memset(&pulseBlend->pulseBlendPalettes, 0, sizeof(pulseBlend->pulseBlendPalettes));
+ for (; i < 16; i++)
+ pulseBlend->pulseBlendPalettes[i].paletteSelector = i;
+}
+
+int InitPulseBlendPaletteSettings(struct PulseBlend *pulseBlend, const struct PulseBlendSettings *settings)
+{
+ u8 i = 0;
+ struct PulseBlendPalette *pulseBlendPalette = NULL;
+
+ if (!pulseBlend->pulseBlendPalettes[0].inUse)
+ {
+ pulseBlendPalette = &pulseBlend->pulseBlendPalettes[0];
+ }
+ else
+ {
+ while (++i < 16)
+ {
+ if (!pulseBlend->pulseBlendPalettes[i].inUse)
+ {
+ pulseBlendPalette = &pulseBlend->pulseBlendPalettes[i];
+ break;
+ }
+ }
+ }
+
+ if (pulseBlendPalette == NULL)
+ return 0xFF;
+
+ pulseBlendPalette->blendCoeff = 0;
+ pulseBlendPalette->fadeDirection = 0;
+ pulseBlendPalette->available = 1;
+ pulseBlendPalette->inUse = 1;
+ pulseBlendPalette->delayCounter = 0;
+ pulseBlendPalette->fadeCycleCounter = 0;
+ memcpy(&pulseBlendPalette->pulseBlendSettings, settings, sizeof(*settings));
+ return i;
+}
+
+static void ClearPulseBlendPalettesSettings(struct PulseBlendPalette *pulseBlendPalette)
+{
+ u16 i;
+
+ if (!pulseBlendPalette->available && pulseBlendPalette->pulseBlendSettings.restorePaletteOnUnload)
+ {
+ for (i = pulseBlendPalette->pulseBlendSettings.paletteOffset; i < pulseBlendPalette->pulseBlendSettings.paletteOffset + pulseBlendPalette->pulseBlendSettings.numColors; i++)
+ gPlttBufferFaded[i] = gPlttBufferUnfaded[i];
+ }
+
+ memset(&pulseBlendPalette->pulseBlendSettings, 0, sizeof(pulseBlendPalette->pulseBlendSettings));
+ pulseBlendPalette->blendCoeff = 0;
+ pulseBlendPalette->fadeDirection = 0;
+ pulseBlendPalette->unk1_5 = 0;
+ pulseBlendPalette->available = 1;
+ pulseBlendPalette->inUse = 0;
+ pulseBlendPalette->fadeCycleCounter = 0;
+ pulseBlendPalette->delayCounter = 0;
+}
+
+void UnloadUsedPulseBlendPalettes(struct PulseBlend *pulseBlend, u16 pulseBlendPaletteSelector, u8 multiSelection)
+{
+ u16 i = 0;
+
+ if (!multiSelection)
+ {
+ ClearPulseBlendPalettesSettings(&pulseBlend->pulseBlendPalettes[pulseBlendPaletteSelector & 0xF]);
+ }
+ else
+ {
+ for (i = 0; i < 16; i++)
+ {
+ if ((pulseBlendPaletteSelector & 1) && pulseBlend->pulseBlendPalettes[i].inUse)
+ ClearPulseBlendPalettesSettings(&pulseBlend->pulseBlendPalettes[i]);
+
+ pulseBlendPaletteSelector >>= 1;
+ }
+ }
+}
+
+void MarkUsedPulseBlendPalettes(struct PulseBlend *pulseBlend, u16 pulseBlendPaletteSelector, u8 multiSelection)
+{
+ u8 i = 0;
+
+ if (!multiSelection)
+ {
+ i = pulseBlendPaletteSelector & 0xF;
+ pulseBlend->pulseBlendPalettes[i].available = 0;
+ pulseBlend->usedPulseBlendPalettes |= 1 << i;
+ }
+ else
+ {
+ for (i = 0; i < 16; i++)
+ {
+ if (!(pulseBlendPaletteSelector & 1) || !pulseBlend->pulseBlendPalettes[i].inUse || !pulseBlend->pulseBlendPalettes[i].available)
+ {
+ pulseBlendPaletteSelector <<= 1;
+ }
+ else
+ {
+ pulseBlend->pulseBlendPalettes[i].available = 0;
+ pulseBlend->usedPulseBlendPalettes |= 1 << i;
+ }
+ }
+ }
+}
+
+void UnmarkUsedPulseBlendPalettes(struct PulseBlend *pulseBlend, u16 pulseBlendPaletteSelector, u8 multiSelection)
+{
+ u16 i;
+ struct PulseBlendPalette *pulseBlendPalette;
+ u8 j = 0;
+
+ if (!multiSelection)
+ {
+ pulseBlendPalette = &pulseBlend->pulseBlendPalettes[pulseBlendPaletteSelector & 0xF];
+ if (!pulseBlendPalette->available && pulseBlendPalette->inUse)
+ {
+ if (pulseBlendPalette->pulseBlendSettings.restorePaletteOnUnload)
+ {
+ for (i = pulseBlendPalette->pulseBlendSettings.paletteOffset; i < pulseBlendPalette->pulseBlendSettings.paletteOffset + pulseBlendPalette->pulseBlendSettings.numColors; i++)
+ gPlttBufferFaded[i] = gPlttBufferUnfaded[i];
+ }
+
+ pulseBlendPalette->available = 1;
+ pulseBlend->usedPulseBlendPalettes &= ~(1 << j);
+ }
+ }
+ else
+ {
+ for (j = 0; j < 16; j++)
+ {
+ pulseBlendPalette = &pulseBlend->pulseBlendPalettes[j];
+ if (!(pulseBlendPaletteSelector & 1) || pulseBlendPalette->available || !pulseBlendPalette->inUse)
+ {
+ pulseBlendPaletteSelector <<= 1;
+ }
+ else
+ {
+ if (pulseBlendPalette->pulseBlendSettings.restorePaletteOnUnload)
+ {
+ for (i = pulseBlendPalette->pulseBlendSettings.paletteOffset; i < pulseBlendPalette->pulseBlendSettings.paletteOffset + pulseBlendPalette->pulseBlendSettings.numColors; i++)
+ gPlttBufferFaded[i] = gPlttBufferUnfaded[i];
+ }
+
+ pulseBlendPalette->available = 1;
+ pulseBlend->usedPulseBlendPalettes &= ~(1 << j);
+ }
+ }
+ }
+}
+
+void UpdatePulseBlend(struct PulseBlend *pulseBlend)
+{
+ struct PulseBlendPalette *pulseBlendPalette;
+ u8 i = 0;
+
+ if (pulseBlend->usedPulseBlendPalettes)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ pulseBlendPalette = &pulseBlend->pulseBlendPalettes[i];
+ if ((!pulseBlendPalette->available && pulseBlendPalette->inUse) && (!gPaletteFade.active || !pulseBlendPalette->pulseBlendSettings.unk7_7))
+ {
+ if (--pulseBlendPalette->delayCounter == 0xFF)
+ {
+ pulseBlendPalette->delayCounter = pulseBlendPalette->pulseBlendSettings.delay;
+ BlendPalette(pulseBlendPalette->pulseBlendSettings.paletteOffset, pulseBlendPalette->pulseBlendSettings.numColors, pulseBlendPalette->blendCoeff, pulseBlendPalette->pulseBlendSettings.blendColor);
+ switch (pulseBlendPalette->pulseBlendSettings.fadeType)
+ {
+ case 0: // Fade all the way to the max blend amount, then wrap around
+ // BUG: This comparison will never be true for maxBlendCoeff values that are >= 8. This is because
+ // maxBlendCoeff is a signed 4-bit field, but blendCoeff is an unsigned 4-bit field. This code is never
+ // reached, anyway, so the bug is not observable in vanilla gameplay.
+ if (pulseBlendPalette->blendCoeff++ == pulseBlendPalette->pulseBlendSettings.maxBlendCoeff)
+ {
+ pulseBlendPalette->fadeCycleCounter++;
+ pulseBlendPalette->blendCoeff = 0;
+ }
+ break;
+ case 1: // Fade in and out
+ if (pulseBlendPalette->fadeDirection)
+ {
+ if (--pulseBlendPalette->blendCoeff == 0)
+ {
+ pulseBlendPalette->fadeCycleCounter++;
+ pulseBlendPalette->fadeDirection ^= 1;
+ }
+ }
+ else
+ {
+ u8 max = (pulseBlendPalette->pulseBlendSettings.maxBlendCoeff - 1) & 0xF;
+ if (pulseBlendPalette->blendCoeff++ == max)
+ {
+ pulseBlendPalette->fadeCycleCounter++;
+ pulseBlendPalette->fadeDirection ^= 1;
+ }
+ }
+ break;
+ case 2: // Flip back and forth
+ if (pulseBlendPalette->fadeDirection)
+ pulseBlendPalette->blendCoeff = 0;
+ else
+ pulseBlendPalette->blendCoeff = pulseBlendPalette->pulseBlendSettings.maxBlendCoeff & 0xF;
+
+ pulseBlendPalette->fadeDirection ^= 1;
+ pulseBlendPalette->fadeCycleCounter++;
+ break;
+ }
+
+ if (pulseBlendPalette->pulseBlendSettings.numFadeCycles != 0xFF
+ && pulseBlendPalette->fadeCycleCounter == pulseBlendPalette->pulseBlendSettings.numFadeCycles)
+ UnmarkUsedPulseBlendPalettes(pulseBlend, pulseBlendPalette->paletteSelector, FALSE);
+ }
+ }
+ }
+ }
+}
+
+void sub_80D9574(u16 *dest, u16 src, u8 left, u8 top, u8 width, u8 height)
+{
+ u16 *_dest;
+ u8 i;
+ u8 j;
+ i = 0;
+ dest = &dest[top * 32 + left];
+ for (; i < height; i++)
+ {
+ _dest = dest + i * 32;
+ for (j = 0; j < width; j++)
+ {
+ *_dest++ = src;
+ }
+ }
+}
+
+void sub_80D95C4(u16 *dest, u16 *src, u8 left, u8 top, u8 width, u8 height)
+{
+ u16 *_dest;
+ u16 *_src = src;
+ u8 i;
+ u8 j;
+ i = 0;
+ dest = &dest[top * 32 + left];
+ for (; i < height; i++)
+ {
+ _dest = dest + i * 32;
+ for (j = 0; j < width; j++)
+ {
+ *_dest++ = *_src++;
+ }
+ }
+}
diff --git a/src/save.c b/src/save.c
index ef38d8b17..d3d31a22e 100644
--- a/src/save.c
+++ b/src/save.c
@@ -69,7 +69,7 @@ const struct SaveSectionOffsets gSaveSectionOffsets[] =
extern void DoSaveFailedScreen(u8 saveType); // save_failed_screen
extern void sub_800AB9C(void); // link
extern bool8 sub_800A4BC(void); // link
-extern void sub_80590D8(void); // fieldmap
+extern void save_serialize_map(void); // fieldmap
extern void sub_804C1C0(void); // load_save
extern void sav2_gender2_inplace_and_xFE(void); // load_save
@@ -828,7 +828,7 @@ u32 TryCopySpecialSaveSection(u8 sector, u8* dst)
return 1;
}
-u32 sub_80DA5E0(u8 sector, u8* src)
+u32 TryWriteSpecialSaveSection(u8 sector, u8* src)
{
s32 i;
s32 size;
@@ -867,7 +867,7 @@ void sub_80DA634(u8 taskId)
case 2:
if (sub_800A4BC())
{
- sub_80590D8();
+ save_serialize_map();
gTasks[taskId].data[0] = 3;
}
break;
diff --git a/src/scanline_effect.c b/src/scanline_effect.c
new file mode 100644
index 000000000..22699b96d
--- /dev/null
+++ b/src/scanline_effect.c
@@ -0,0 +1,262 @@
+#include "global.h"
+#include "battle.h"
+#include "task.h"
+#include "trig.h"
+#include "scanline_effect.h"
+
+extern u16 gBattle_BG0_X;
+extern u16 gBattle_BG0_Y;
+extern u16 gBattle_BG1_X;
+extern u16 gBattle_BG1_Y;
+extern u16 gBattle_BG2_X;
+extern u16 gBattle_BG2_Y;
+extern u16 gBattle_BG3_X;
+extern u16 gBattle_BG3_Y;
+
+static void CopyValue16Bit(void);
+static void CopyValue32Bit(void);
+
+// EWRAM vars
+
+// Per-scanline register values.
+// This is double buffered so that it can be safely written to at any time
+// without overwriting the buffer that the DMA is currently reading
+EWRAM_DATA u16 gScanlineEffectRegBuffers[2][0x3C0] = {0};
+
+EWRAM_DATA struct ScanlineEffect gScanlineEffect = {0};
+EWRAM_DATA static bool8 sShouldStopWaveTask = FALSE;
+
+void ScanlineEffect_Stop(void)
+{
+ gScanlineEffect.state = 0;
+ DmaStop(0);
+ if (gScanlineEffect.waveTaskId != 0xFF)
+ {
+ DestroyTask(gScanlineEffect.waveTaskId);
+ gScanlineEffect.waveTaskId = 0xFF;
+ }
+}
+
+void ScanlineEffect_Clear(void)
+{
+ CpuFill16(0, gScanlineEffectRegBuffers, sizeof(gScanlineEffectRegBuffers));
+ gScanlineEffect.dmaSrcBuffers[0] = NULL;
+ gScanlineEffect.dmaSrcBuffers[1] = NULL;
+ gScanlineEffect.dmaDest = NULL;
+ gScanlineEffect.dmaControl = 0;
+ gScanlineEffect.srcBuffer = 0;
+ gScanlineEffect.state = 0;
+ gScanlineEffect.unused16 = 0;
+ gScanlineEffect.unused17 = 0;
+ gScanlineEffect.waveTaskId = 0xFF;
+}
+
+void ScanlineEffect_SetParams(struct ScanlineEffectParams params)
+{
+ if (params.dmaControl == SCANLINE_EFFECT_DMACNT_16BIT) // 16-bit
+ {
+ // Set the DMA src to the value for the second scanline because the
+ // first DMA transfer occurs in HBlank *after* the first scanline is drawn
+ gScanlineEffect.dmaSrcBuffers[0] = (u16 *)gScanlineEffectRegBuffers[0] + 1;
+ gScanlineEffect.dmaSrcBuffers[1] = (u16 *)gScanlineEffectRegBuffers[1] + 1;
+ gScanlineEffect.setFirstScanlineReg = CopyValue16Bit;
+ }
+ else // assume 32-bit
+ {
+ // Set the DMA src to the value for the second scanline because the
+ // first DMA transfer occurs in HBlank *after* the first scanline is drawn
+ gScanlineEffect.dmaSrcBuffers[0] = (u32 *)gScanlineEffectRegBuffers[0] + 1;
+ gScanlineEffect.dmaSrcBuffers[1] = (u32 *)gScanlineEffectRegBuffers[1] + 1;
+ gScanlineEffect.setFirstScanlineReg = CopyValue32Bit;
+ }
+
+ gScanlineEffect.dmaControl = params.dmaControl;
+ gScanlineEffect.dmaDest = params.dmaDest;
+ gScanlineEffect.state = params.initState;
+ gScanlineEffect.unused16 = params.unused9;
+ gScanlineEffect.unused17 = params.unused9;
+}
+
+void ScanlineEffect_InitHBlankDmaTransfer(void)
+{
+ if (gScanlineEffect.state == 0)
+ {
+ return;
+ }
+ else if (gScanlineEffect.state == 3)
+ {
+ gScanlineEffect.state = 0;
+ DmaStop(0);
+ sShouldStopWaveTask = TRUE;
+ }
+ else
+ {
+ DmaStop(0);
+ // Set DMA to copy to dest register on each HBlank for the next frame.
+ // The HBlank DMA transfers do not occurr during VBlank, so the transfer
+ // will begin on the HBlank after the first scanline
+ DmaSet(0, gScanlineEffect.dmaSrcBuffers[gScanlineEffect.srcBuffer], gScanlineEffect.dmaDest, gScanlineEffect.dmaControl);
+ // Manually set the reg for the first scanline
+ gScanlineEffect.setFirstScanlineReg();
+ // Swap current buffer
+ gScanlineEffect.srcBuffer ^= 1;
+ }
+}
+
+// These two functions are used to copy the register for the first scanline,
+// depending whether it is a 16-bit register or a 32-bit register.
+
+static void CopyValue16Bit(void)
+{
+ u16 *dest = (u16 *)gScanlineEffect.dmaDest;
+ u16 *src = (u16 *)&gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer];
+
+ *dest = *src;
+}
+
+static void CopyValue32Bit(void)
+{
+ u32 *dest = (u32 *)gScanlineEffect.dmaDest;
+ u32 *src = (u32 *)&gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer];
+
+ *dest = *src;
+}
+
+#define tStartLine data[0]
+#define tEndLine data[1]
+#define tWaveLength data[2]
+#define tSrcBufferOffset data[3]
+#define tFramesUntilMove data[4]
+#define tDelayInterval data[5]
+#define tRegOffset data[6]
+#define tApplyBattleBgOffsets data[7]
+
+static void TaskFunc_UpdateWavePerFrame(u8 taskId)
+{
+ int value = 0;
+ int i;
+ int offset;
+
+ if (sShouldStopWaveTask)
+ {
+ DestroyTask(taskId);
+ gScanlineEffect.waveTaskId = 0xFF;
+ }
+ else
+ {
+ if (gTasks[taskId].tApplyBattleBgOffsets)
+ {
+ switch (gTasks[taskId].tRegOffset)
+ {
+ case SCANLINE_EFFECT_REG_BG0HOFS:
+ value = gBattle_BG0_X;
+ break;
+ case SCANLINE_EFFECT_REG_BG0VOFS:
+ value = gBattle_BG0_Y;
+ break;
+ case SCANLINE_EFFECT_REG_BG1HOFS:
+ value = gBattle_BG1_X;
+ break;
+ case SCANLINE_EFFECT_REG_BG1VOFS:
+ value = gBattle_BG1_Y;
+ break;
+ case SCANLINE_EFFECT_REG_BG2HOFS:
+ value = gBattle_BG2_X;
+ break;
+ case SCANLINE_EFFECT_REG_BG2VOFS:
+ value = gBattle_BG2_Y;
+ break;
+ case SCANLINE_EFFECT_REG_BG3HOFS:
+ value = gBattle_BG3_X;
+ break;
+ case SCANLINE_EFFECT_REG_BG3VOFS:
+ value = gBattle_BG3_Y;
+ break;
+ }
+ }
+ if (gTasks[taskId].tFramesUntilMove != 0)
+ {
+ gTasks[taskId].tFramesUntilMove--;
+ offset = gTasks[taskId].tSrcBufferOffset + 320;
+ for (i = gTasks[taskId].tStartLine; i < gTasks[taskId].tEndLine; i++)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gScanlineEffectRegBuffers[0][offset] + value;
+ offset++;
+ }
+ }
+ else
+ {
+ gTasks[taskId].tFramesUntilMove = gTasks[taskId].tDelayInterval;
+ offset = gTasks[taskId].tSrcBufferOffset + 320;
+ for (i = gTasks[taskId].tStartLine; i < gTasks[taskId].tEndLine; i++)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gScanlineEffectRegBuffers[0][offset] + value;
+ offset++;
+ }
+
+ // increment src buffer offset
+ gTasks[taskId].tSrcBufferOffset++;
+ if (gTasks[taskId].tSrcBufferOffset == gTasks[taskId].tWaveLength)
+ gTasks[taskId].tSrcBufferOffset = 0;
+ }
+ }
+}
+
+static void GenerateWave(u16 *buffer, u8 frequency, u8 amplitude, u8 unused)
+{
+ u16 i = 0;
+ u8 theta = 0;
+
+ while (i < 256)
+ {
+ buffer[i] = (gSineTable[theta] * amplitude) / 256;
+ theta += frequency;
+ i++;
+ }
+}
+
+// Initializes a background "wave" effect that affects scanlines startLine (inclusive) to endLine (exclusive).
+// 'frequency' and 'amplitude' control the frequency and amplitude of the wave.
+// 'delayInterval' controls how fast the wave travels up the screen. The wave will shift upwards one scanline every 'delayInterval'+1 frames.
+// 'regOffset' is the offset of the video register to modify.
+u8 ScanlineEffect_InitWave(u8 startLine, u8 endLine, u8 frequency, u8 amplitude, u8 delayInterval, u8 regOffset, bool8 applyBattleBgOffsets)
+{
+ int i;
+ int offset;
+ struct ScanlineEffectParams params;
+ u8 taskId;
+
+ ScanlineEffect_Clear();
+
+ params.dmaDest = (void *)(REG_ADDR_BG0HOFS + regOffset);
+ params.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT;
+ params.initState = 1;
+ params.unused9 = 0;
+ ScanlineEffect_SetParams(params);
+
+ taskId = CreateTask(TaskFunc_UpdateWavePerFrame, 0);
+
+ gTasks[taskId].tStartLine = startLine;
+ gTasks[taskId].tEndLine = endLine;
+ gTasks[taskId].tWaveLength = 256 / frequency;
+ gTasks[taskId].tSrcBufferOffset = 0;
+ gTasks[taskId].tFramesUntilMove = delayInterval;
+ gTasks[taskId].tDelayInterval = delayInterval;
+ gTasks[taskId].tRegOffset = regOffset;
+ gTasks[taskId].tApplyBattleBgOffsets = applyBattleBgOffsets;
+
+ gScanlineEffect.waveTaskId = taskId;
+ sShouldStopWaveTask = FALSE;
+
+ GenerateWave(&gScanlineEffectRegBuffers[0][320], frequency, amplitude, endLine - startLine);
+
+ offset = 320;
+ for (i = startLine; i < endLine; i++)
+ {
+ gScanlineEffectRegBuffers[0][i] = gScanlineEffectRegBuffers[0][offset];
+ gScanlineEffectRegBuffers[1][i] = gScanlineEffectRegBuffers[0][offset];
+ offset++;
+ }
+
+ return taskId;
+}
diff --git a/src/scrcmd.c b/src/scrcmd.c
new file mode 100644
index 000000000..7c27293a7
--- /dev/null
+++ b/src/scrcmd.c
@@ -0,0 +1,2267 @@
+#include "global.h"
+#include "gba/isagbprint.h"
+#include "palette.h"
+#include "script.h"
+#include "mystery_event_script.h"
+#include "event_data.h"
+#include "random.h"
+#include "item.h"
+#include "overworld.h"
+#include "field_screen_effect.h"
+#include "quest_log.h"
+#include "map_preview_screen.h"
+#include "field_weather.h"
+#include "field_tasks.h"
+#include "field_fadetransition.h"
+#include "field_player_avatar.h"
+#include "sound.h"
+#include "script_movement.h"
+#include "field_map_obj.h"
+#include "field_map_obj_helpers.h"
+#include "map_obj_lock.h"
+#include "field_message_box.h"
+#include "new_menu_helpers.h"
+#include "window.h"
+#include "start_menu.h"
+#include "script_menu.h"
+#include "string_util.h"
+#include "data2.h"
+#include "field_specials.h"
+#include "constants/items.h"
+#include "script_pokemon_util_80A0058.h"
+#include "pokemon_storage_system.h"
+#include "party_menu.h"
+#include "money.h"
+#include "coins.h"
+#include "battle_setup.h"
+#include "shop.h"
+#include "script_pokemon_80F8.h"
+#include "slot_machine.h"
+#include "field_effect.h"
+#include "fieldmap.h"
+#include "field_door.h"
+#include "scrcmd.h"
+
+extern u16 (*const gSpecials[])(void);
+extern u16 (*const gSpecialsEnd[])(void);
+extern const u8 *const gStdScripts[];
+extern const u8 *const gStdScriptsEnd[];
+
+static bool8 sub_806B93C(struct ScriptContext * ctx);
+static u8 sub_806B96C(struct ScriptContext * ctx);
+
+EWRAM_DATA ptrdiff_t gVScriptOffset = 0;
+EWRAM_DATA u8 gUnknown_20370AC = 0;
+EWRAM_DATA u16 sPauseCounter = 0;
+EWRAM_DATA u16 sMovingNpcId = 0;
+EWRAM_DATA u16 sMovingNpcMapBank = 0;
+EWRAM_DATA u16 sMovingNpcMapId = 0;
+EWRAM_DATA u16 sFieldEffectScriptId = 0;
+
+IWRAM_DATA struct ScriptContext * gUnknown_3005070;
+
+extern u8 gSelectedEventObject;
+
+// This is defined in here so the optimizer can't see its value when compiling
+// script.c.
+void * const gNullScriptPtr = NULL;
+
+static const u8 sScriptConditionTable[6][3] =
+{
+// < = >
+ 1, 0, 0, // <
+ 0, 1, 0, // =
+ 0, 0, 1, // >
+ 1, 1, 0, // <=
+ 0, 1, 1, // >=
+ 1, 0, 1, // !=
+};
+
+bool8 ScrCmd_nop(struct ScriptContext *ctx)
+{
+ return FALSE;
+}
+
+bool8 ScrCmd_nop1(struct ScriptContext *ctx)
+{
+ return FALSE;
+}
+
+bool8 ScrCmd_end(struct ScriptContext *ctx)
+{
+ StopScript(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_gotonative(struct ScriptContext *ctx)
+{
+ bool8 (*func)(void) = (bool8 (*)(void))ScriptReadWord(ctx);
+ SetupNativeScript(ctx, func);
+ return TRUE;
+}
+
+bool8 ScrCmd_special(struct ScriptContext *ctx)
+{
+ u16 (*const *specialPtr)(void) = gSpecials + ScriptReadHalfword(ctx);
+ if (specialPtr < gSpecialsEnd)
+ (*specialPtr)();
+ else
+ AGB_ASSERT_EX(0, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/scrcmd.c", 241);
+ return FALSE;
+}
+
+bool8 ScrCmd_specialvar(struct ScriptContext *ctx)
+{
+ u16 * varPtr = GetVarPointer(ScriptReadHalfword(ctx));
+ u16 (*const *specialPtr)(void) = gSpecials + ScriptReadHalfword(ctx);
+ if (specialPtr < gSpecialsEnd)
+ *varPtr = (*specialPtr)();
+ else
+ AGB_ASSERT_EX(0, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/scrcmd.c", 263);
+ return FALSE;
+}
+
+bool8 ScrCmd_callnative(struct ScriptContext *ctx)
+{
+ void (*func )(void) = ((void (*)(void))ScriptReadWord(ctx));
+ func();
+ return FALSE;
+}
+
+bool8 ScrCmd_waitstate(struct ScriptContext *ctx)
+{
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_goto(struct ScriptContext *ctx)
+{
+ const u8 * scrptr = (const u8 *)ScriptReadWord(ctx);
+ ScriptJump(ctx, scrptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_return(struct ScriptContext *ctx)
+{
+ ScriptReturn(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_call(struct ScriptContext *ctx)
+{
+ const u8 * scrptr = (const u8 *)ScriptReadWord(ctx);
+ ScriptCall(ctx, scrptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_goto_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ const u8 * scrptr = (const u8 *)ScriptReadWord(ctx);
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ ScriptJump(ctx, scrptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_call_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ const u8 * scrptr = (const u8 *)ScriptReadWord(ctx);
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ ScriptCall(ctx, scrptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_setvaddress(struct ScriptContext *ctx)
+{
+ u32 addr1 = (u32)ctx->scriptPtr - 1;
+ u32 addr2 = ScriptReadWord(ctx);
+
+ gVScriptOffset = addr2 - addr1;
+ return FALSE;
+}
+
+bool8 ScrCmd_vgoto(struct ScriptContext *ctx)
+{
+ const u8 * scrptr = (const u8 *)ScriptReadWord(ctx);
+ ScriptJump(ctx, scrptr - gVScriptOffset);
+ return FALSE;
+}
+
+bool8 ScrCmd_vcall(struct ScriptContext *ctx)
+{
+ const u8 * scrptr = (const u8 *)ScriptReadWord(ctx);
+ ScriptCall(ctx, scrptr - gVScriptOffset);
+ return FALSE;
+}
+
+bool8 ScrCmd_vgoto_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ const u8 * scrptr = (const u8 *)ScriptReadWord(ctx) - gVScriptOffset;
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ ScriptJump(ctx, scrptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_vcall_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ const u8 * scrptr = (const u8 *)ScriptReadWord(ctx) - gVScriptOffset;
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ ScriptCall(ctx, scrptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_gotostd(struct ScriptContext *ctx)
+{
+ u8 stdIdx = ScriptReadByte(ctx);
+ const u8 *const * script = gStdScripts + stdIdx;
+ if (script < gStdScriptsEnd)
+ ScriptJump(ctx, *script);
+ return FALSE;
+}
+
+bool8 ScrCmd_callstd(struct ScriptContext *ctx)
+{
+ u8 stdIdx = ScriptReadByte(ctx);
+ const u8 *const * script = gStdScripts + stdIdx;
+ if (script < gStdScriptsEnd)
+ ScriptCall(ctx, *script);
+ return FALSE;
+}
+
+bool8 ScrCmd_gotostd_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ u8 stdIdx = ScriptReadByte(ctx);
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ {
+ const u8 *const * script = gStdScripts + stdIdx;
+ if (script < gStdScriptsEnd)
+ ScriptJump(ctx, *script);
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_callstd_if(struct ScriptContext *ctx)
+{
+ u8 condition = ScriptReadByte(ctx);
+ u8 stdIdx = ScriptReadByte(ctx);
+ if (sScriptConditionTable[condition][ctx->comparisonResult] == 1)
+ {
+ const u8 *const * script = gStdScripts + stdIdx;
+ if (script < gStdScriptsEnd)
+ ScriptCall(ctx, *script);
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_gotoram(struct ScriptContext *ctx)
+{
+ ScriptJump(ctx, gRAMScriptPtr);
+ return FALSE;
+}
+
+bool8 ScrCmd_killscript(struct ScriptContext *ctx)
+{
+ ClearRamScript();
+ StopScript(ctx);
+ return TRUE;
+}
+
+bool8 ScrCmd_setmysteryeventstatus(struct ScriptContext *ctx)
+{
+ SetMysteryEventScriptStatus(ScriptReadByte(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_execram(struct ScriptContext *ctx)
+{
+ const u8 * script = sub_8069E48();
+ if (script != NULL)
+ {
+ gRAMScriptPtr = ctx->scriptPtr;
+ ScriptJump(ctx, script);
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_loadword(struct ScriptContext *ctx)
+{
+ u8 which = ScriptReadByte(ctx);
+ ctx->data[which] = ScriptReadWord(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_loadbytefromaddr(struct ScriptContext *ctx)
+{
+ u8 which = ScriptReadByte(ctx);
+ ctx->data[which] = *(const u8 *)ScriptReadWord(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_writebytetoaddr(struct ScriptContext *ctx)
+{
+ u8 value = ScriptReadByte(ctx);
+ *(u8 *)ScriptReadWord(ctx) = value;
+ return FALSE;
+}
+
+bool8 ScrCmd_loadbyte(struct ScriptContext *ctx)
+{
+ u8 which = ScriptReadByte(ctx);
+ ctx->data[which] = ScriptReadByte(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_setptrbyte(struct ScriptContext *ctx)
+{
+ u8 which = ScriptReadByte(ctx);
+ *(u8 *)ScriptReadWord(ctx) = ctx->data[which];
+ return FALSE;
+}
+
+bool8 ScrCmd_copylocal(struct ScriptContext *ctx)
+{
+ u8 whichDst = ScriptReadByte(ctx);
+ u8 whichSrc = ScriptReadByte(ctx);
+ ctx->data[whichDst] = ctx->data[whichSrc];
+ return FALSE;
+}
+
+bool8 ScrCmd_copybyte(struct ScriptContext *ctx)
+{
+ u8 * dest = (u8 *)ScriptReadWord(ctx);
+ *dest = *(const u8 *)ScriptReadWord(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_setvar(struct ScriptContext *ctx)
+{
+ u16 * varPtr = GetVarPointer(ScriptReadHalfword(ctx));
+ *varPtr = ScriptReadHalfword(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_copyvar(struct ScriptContext *ctx)
+{
+ u16 * destPtr = GetVarPointer(ScriptReadHalfword(ctx));
+ u16 * srcPtr = GetVarPointer(ScriptReadHalfword(ctx));
+ *destPtr = *srcPtr;
+ return FALSE;
+}
+
+bool8 ScrCmd_setorcopyvar(struct ScriptContext *ctx)
+{
+ u16 * destPtr = GetVarPointer(ScriptReadHalfword(ctx));
+ *destPtr = VarGet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+u8 compare_012(u16 left, u16 right)
+{
+ if (left < right)
+ return 0;
+ else if (left == right)
+ return 1;
+ else
+ return 2;
+}
+
+// comparelocaltolocal
+bool8 ScrCmd_compare_local_to_local(struct ScriptContext *ctx)
+{
+ const u8 value1 = ctx->data[ScriptReadByte(ctx)];
+ const u8 value2 = ctx->data[ScriptReadByte(ctx)];
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+// comparelocaltoimm
+bool8 ScrCmd_compare_local_to_value(struct ScriptContext *ctx)
+{
+ const u8 value1 = ctx->data[ScriptReadByte(ctx)];
+ const u8 value2 = ScriptReadByte(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_local_to_addr(struct ScriptContext *ctx)
+{
+ const u8 value1 = ctx->data[ScriptReadByte(ctx)];
+ const u8 value2 = *(const u8 *)ScriptReadWord(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_addr_to_local(struct ScriptContext *ctx)
+{
+ const u8 value1 = *(const u8 *)ScriptReadWord(ctx);
+ const u8 value2 = ctx->data[ScriptReadByte(ctx)];
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_addr_to_value(struct ScriptContext *ctx)
+{
+ const u8 value1 = *(const u8 *)ScriptReadWord(ctx);
+ const u8 value2 = ScriptReadByte(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_addr_to_addr(struct ScriptContext *ctx)
+{
+ const u8 value1 = *(const u8 *)ScriptReadWord(ctx);
+ const u8 value2 = *(const u8 *)ScriptReadWord(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_var_to_value(struct ScriptContext *ctx)
+{
+ const u16 value1 = *GetVarPointer(ScriptReadHalfword(ctx));
+ const u16 value2 = ScriptReadHalfword(ctx);
+
+ ctx->comparisonResult = compare_012(value1, value2);
+ return FALSE;
+}
+
+bool8 ScrCmd_compare_var_to_var(struct ScriptContext *ctx)
+{
+ const u16 *ptr1 = GetVarPointer(ScriptReadHalfword(ctx));
+ const u16 *ptr2 = GetVarPointer(ScriptReadHalfword(ctx));
+
+ ctx->comparisonResult = compare_012(*ptr1, *ptr2);
+ return FALSE;
+}
+
+bool8 ScrCmd_addvar(struct ScriptContext *ctx)
+{
+ u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx));
+ *ptr += ScriptReadHalfword(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_subvar(struct ScriptContext *ctx)
+{
+ u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx));
+ *ptr -= VarGet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_random(struct ScriptContext *ctx)
+{
+ u16 max = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = Random() % max;
+ return FALSE;
+}
+
+bool8 ScrCmd_giveitem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u32 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = AddBagItem(itemId, (u8)quantity);
+ sub_809A824(itemId);
+ return FALSE;
+}
+
+bool8 ScrCmd_takeitem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u32 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = RemoveBagItem(itemId, (u8)quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkitemspace(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u32 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = CheckBagHasSpace(itemId, (u8)quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkitem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u32 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = CheckBagHasItem(itemId, (u8)quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkitemtype(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = GetPocketByItemId(itemId);
+ return FALSE;
+}
+
+bool8 ScrCmd_givepcitem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u16 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = AddPCItem(itemId, quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkpcitem(struct ScriptContext *ctx)
+{
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u16 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = CheckPCHasItem(itemId, quantity);
+ return FALSE;
+}
+
+bool8 ScrCmd_givedecoration(struct ScriptContext *ctx)
+{
+ u32 decorId = VarGet(ScriptReadHalfword(ctx));
+
+// gSpecialVar_Result = DecorationAdd(decorId);
+ return FALSE;
+}
+
+bool8 ScrCmd_takedecoration(struct ScriptContext *ctx)
+{
+ u32 decorId = VarGet(ScriptReadHalfword(ctx));
+
+// gSpecialVar_Result = DecorationRemove(decorId);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkdecorspace(struct ScriptContext *ctx)
+{
+ u32 decorId = VarGet(ScriptReadHalfword(ctx));
+
+// gSpecialVar_Result = DecorationCheckSpace(decorId);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkdecor(struct ScriptContext *ctx)
+{
+ u32 decorId = VarGet(ScriptReadHalfword(ctx));
+
+// gSpecialVar_Result = CheckHasDecoration(decorId);
+ return FALSE;
+}
+
+bool8 ScrCmd_setflag(struct ScriptContext *ctx)
+{
+ FlagSet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_clearflag(struct ScriptContext *ctx)
+{
+ FlagClear(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_checkflag(struct ScriptContext *ctx)
+{
+ ctx->comparisonResult = FlagGet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_incrementgamestat(struct ScriptContext *ctx)
+{
+ IncrementGameStat(ScriptReadByte(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_comparestattoword(struct ScriptContext *ctx)
+{
+ u8 statIdx = ScriptReadByte(ctx);
+ u32 value = ScriptReadWord(ctx);
+ u32 statValue = GetGameStat(statIdx);
+
+ if (statValue < value)
+ ctx ->comparisonResult = 0;
+ else if (statValue == value)
+ ctx->comparisonResult = 1;
+ else
+ ctx->comparisonResult = 2;
+ return FALSE;
+}
+
+bool8 ScrCmd_setworldmapflag(struct ScriptContext *ctx)
+{
+ u16 value = ScriptReadHalfword(ctx);
+ sub_8115748(value);
+ sub_80F85BC(value);
+ return FALSE;
+}
+
+bool8 ScrCmd_animateflash(struct ScriptContext *ctx)
+{
+ sub_807F028(ScriptReadByte(ctx));
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_setflashradius(struct ScriptContext *ctx)
+{
+ u16 flashLevel = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetFlashLevel(flashLevel);
+ return FALSE;
+}
+
+static bool8 IsPaletteNotActive(void)
+{
+ if (!gPaletteFade.active)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_fadescreen(struct ScriptContext *ctx)
+{
+ fade_screen(ScriptReadByte(ctx), 0);
+ SetupNativeScript(ctx, IsPaletteNotActive);
+ return TRUE;
+}
+
+bool8 ScrCmd_fadescreenspeed(struct ScriptContext *ctx)
+{
+ u8 mode = ScriptReadByte(ctx);
+ u8 speed = ScriptReadByte(ctx);
+
+ fade_screen(mode, speed);
+ SetupNativeScript(ctx, IsPaletteNotActive);
+ return TRUE;
+}
+
+static bool8 RunPauseTimer(void)
+{
+ sPauseCounter--;
+
+ if (sPauseCounter == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_delay(struct ScriptContext *ctx)
+{
+ sPauseCounter = ScriptReadHalfword(ctx);
+ SetupNativeScript(ctx, RunPauseTimer);
+ return TRUE;
+}
+
+bool8 ScrCmd_initclock(struct ScriptContext *ctx)
+{
+// u8 hour = VarGet(ScriptReadHalfword(ctx));
+// u8 minute = VarGet(ScriptReadHalfword(ctx));
+//
+// RtcInitLocalTimeOffset(hour, minute);
+ return FALSE;
+}
+
+bool8 ScrCmd_dodailyevents(struct ScriptContext *ctx)
+{
+// DoTimeBasedEvents();
+ return FALSE;
+}
+
+bool8 ScrCmd_gettime(struct ScriptContext *ctx)
+{
+// RtcCalcLocalTime();
+// gSpecialVar_0x8000 = gLocalTime.hours;
+// gSpecialVar_0x8001 = gLocalTime.minutes;
+// gSpecialVar_0x8002 = gLocalTime.seconds;
+ gSpecialVar_0x8000 = 0;
+ gSpecialVar_0x8001 = 0;
+ gSpecialVar_0x8002 = 0;
+ return FALSE;
+}
+
+bool8 ScrCmd_setweather(struct ScriptContext *ctx)
+{
+ u16 weather = VarGet(ScriptReadHalfword(ctx));
+
+ SetSav1Weather(weather);
+ return FALSE;
+}
+
+bool8 ScrCmd_resetweather(struct ScriptContext *ctx)
+{
+ SetSav1WeatherFromCurrMapHeader();
+ return FALSE;
+}
+
+bool8 ScrCmd_doweather(struct ScriptContext *ctx)
+{
+ DoCurrentWeather();
+ return FALSE;
+}
+
+bool8 ScrCmd_setstepcallback(struct ScriptContext *ctx)
+{
+ ActivatePerStepCallback(ScriptReadByte(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_setmaplayoutindex(struct ScriptContext *ctx)
+{
+ u16 value = VarGet(ScriptReadHalfword(ctx));
+
+ SetCurrentMapLayout(value);
+ return FALSE;
+}
+
+bool8 ScrCmd_warp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ DoWarp();
+ ResetInitialPlayerAvatarState();
+ return TRUE;
+}
+
+bool8 ScrCmd_warpsilent(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ DoDiveWarp();
+ ResetInitialPlayerAvatarState();
+ return TRUE;
+}
+
+bool8 ScrCmd_warpdoor(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ DoDoorWarp();
+ ResetInitialPlayerAvatarState();
+ return TRUE;
+}
+
+bool8 ScrCmd_warphole(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u16 x;
+ u16 y;
+
+ PlayerGetDestCoords(&x, &y);
+ if (mapGroup == 0xFF && mapNum == 0xFF)
+ SetWarpDestinationToFixedHoleWarp(x - 7, y - 7);
+ else
+ Overworld_SetWarpDestination(mapGroup, mapNum, -1, x - 7, y - 7);
+ DoFallWarp();
+ ResetInitialPlayerAvatarState();
+ return TRUE;
+}
+
+bool8 ScrCmd_warpteleport(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ sub_807E59C();
+ ResetInitialPlayerAvatarState();
+ return TRUE;
+}
+
+bool8 ScrCmd_warpteleport2(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ sub_805DAE4(player_get_direction_lower_nybble());
+ sub_807E500();
+ ResetInitialPlayerAvatarState();
+ return TRUE;
+}
+
+bool8 ScrCmd_setwarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setdynamicwarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ SetDynamicWarpWithCoords(0, mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setdivewarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ SetFixedDiveWarp(mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setholewarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ SetFixedHoleWarp(mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setescapewarp(struct ScriptContext *ctx)
+{
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 warpId = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ SetEscapeWarp(mapGroup, mapNum, warpId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_getplayerxy(struct ScriptContext *ctx)
+{
+ u16 *pX = GetVarPointer(ScriptReadHalfword(ctx));
+ u16 *pY = GetVarPointer(ScriptReadHalfword(ctx));
+
+ *pX = gSaveBlock1Ptr->pos.x;
+ *pY = gSaveBlock1Ptr->pos.y;
+ return FALSE;
+}
+
+bool8 ScrCmd_getpartysize(struct ScriptContext *ctx)
+{
+ gSpecialVar_Result = CalculatePlayerPartyCount();
+ return FALSE;
+}
+
+bool8 ScrCmd_playse(struct ScriptContext *ctx)
+{
+ PlaySE(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+static bool8 WaitForSoundEffectFinish(void)
+{
+ if (!IsSEPlaying())
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_waitse(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, WaitForSoundEffectFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_playfanfare(struct ScriptContext *ctx)
+{
+ PlayFanfare(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+static bool8 WaitForFanfareFinish(void)
+{
+ return IsFanfareTaskInactive();
+}
+
+bool8 ScrCmd_waitfanfare(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, WaitForFanfareFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_playbgm(struct ScriptContext *ctx)
+{
+ u16 songId = ScriptReadHalfword(ctx);
+ bool8 val = ScriptReadByte(ctx);
+
+ if (gUnknown_203ADFA == 2 || gUnknown_203ADFA == 3)
+ return FALSE;
+ if (val == TRUE)
+ Overworld_SetSavedMusic(songId);
+ PlayNewMapMusic(songId);
+ return FALSE;
+}
+
+bool8 ScrCmd_savebgm(struct ScriptContext *ctx)
+{
+ Overworld_SetSavedMusic(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+bool8 ScrCmd_fadedefaultbgm(struct ScriptContext *ctx)
+{
+ if (gUnknown_203ADFA == 2 || gUnknown_203ADFA == 3)
+ return FALSE;
+ Overworld_ChangeMusicToDefault();
+ return FALSE;
+}
+
+bool8 ScrCmd_fadenewbgm(struct ScriptContext *ctx)
+{
+ u16 music = ScriptReadHalfword(ctx);
+ if (gUnknown_203ADFA == 2 || gUnknown_203ADFA == 3)
+ return FALSE;
+ Overworld_ChangeMusicTo(music);
+ return FALSE;
+}
+
+bool8 ScrCmd_fadeoutbgm(struct ScriptContext *ctx)
+{
+ u8 speed = ScriptReadByte(ctx);
+
+ if (gUnknown_203ADFA == 2 || gUnknown_203ADFA == 3)
+ return FALSE;
+ if (speed != 0)
+ FadeOutBGMTemporarily(4 * speed);
+ else
+ FadeOutBGMTemporarily(4);
+ SetupNativeScript(ctx, IsBGMPausedOrStopped);
+ return TRUE;
+}
+
+bool8 ScrCmd_fadeinbgm(struct ScriptContext *ctx)
+{
+ u8 speed = ScriptReadByte(ctx);
+
+ if (gUnknown_203ADFA == 2 || gUnknown_203ADFA == 3)
+ return FALSE;
+ if (speed != 0)
+ FadeInBGM(4 * speed);
+ else
+ FadeInBGM(4);
+ return FALSE;
+}
+
+bool8 ScrCmd_applymovement(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ const void *movementScript = (const void *)ScriptReadWord(ctx);
+
+ ScriptMovement_StartObjectMovementScript(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, movementScript);
+ sMovingNpcId = localId;
+ return FALSE;
+}
+
+bool8 ScrCmd_applymovement_at(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ const void *movementScript = (const void *)ScriptReadWord(ctx);
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ ScriptMovement_StartObjectMovementScript(localId, mapNum, mapGroup, movementScript);
+ sMovingNpcId = localId;
+ return FALSE;
+}
+
+static bool8 WaitForMovementFinish(void)
+{
+ return ScriptMovement_IsObjectMovementFinished(sMovingNpcId, sMovingNpcMapId, sMovingNpcMapBank);
+}
+
+bool8 ScrCmd_waitmovement(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+
+ if (localId != 0)
+ sMovingNpcId = localId;
+ sMovingNpcMapBank = gSaveBlock1Ptr->location.mapGroup;
+ sMovingNpcMapId = gSaveBlock1Ptr->location.mapNum;
+ SetupNativeScript(ctx, WaitForMovementFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_waitmovement_at(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapBank;
+ u8 mapId;
+
+ if (localId != 0)
+ sMovingNpcId = localId;
+ mapBank = ScriptReadByte(ctx);
+ mapId = ScriptReadByte(ctx);
+ sMovingNpcMapBank = mapBank;
+ sMovingNpcMapId = mapId;
+ SetupNativeScript(ctx, WaitForMovementFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_removeobject(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+
+ RemoveFieldObjectByLocalIdAndMap(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_removeobject_at(struct ScriptContext *ctx)
+{
+ u16 objectId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ RemoveFieldObjectByLocalIdAndMap(objectId, mapNum, mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_addobject(struct ScriptContext *ctx)
+{
+ u16 objectId = VarGet(ScriptReadHalfword(ctx));
+
+ show_sprite(objectId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_addobject_at(struct ScriptContext *ctx)
+{
+ u16 objectId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ show_sprite(objectId, mapNum, mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_setobjectxy(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ sub_805F7C4(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setobjectxyperm(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ Overworld_SetMapObjTemplateCoords(localId, x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_moveobjectoffscreen(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+
+ sub_805FE94(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_showobject_at(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ npc_by_local_id_and_map_set_field_1_bit_x20(localId, mapNum, mapGroup, 0);
+ return FALSE;
+}
+
+bool8 ScrCmd_hideobject_at(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ npc_by_local_id_and_map_set_field_1_bit_x20(localId, mapNum, mapGroup, 1);
+ return FALSE;
+}
+
+bool8 ScrCmd_setobjectpriority(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+ u8 priority = ScriptReadByte(ctx);
+
+ sub_805F3A8(localId, mapNum, mapGroup, priority + 83);
+ return FALSE;
+}
+
+bool8 ScrCmd_resetobjectpriority(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 mapGroup = ScriptReadByte(ctx);
+ u8 mapNum = ScriptReadByte(ctx);
+
+ sub_805F400(localId, mapNum, mapGroup);
+ return FALSE;
+}
+
+bool8 ScrCmd_faceplayer(struct ScriptContext *ctx)
+{
+ if (gMapObjects[gSelectedEventObject].active)
+ {
+ FieldObjectFaceOppositeDirection(&gMapObjects[gSelectedEventObject],
+ player_get_direction_lower_nybble());
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_turnobject(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 direction = ScriptReadByte(ctx);
+
+ FieldObjectTurnByLocalIdAndMap(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, direction);
+ return FALSE;
+}
+
+bool8 ScrCmd_setobjectmovementtype(struct ScriptContext *ctx)
+{
+ u16 localId = VarGet(ScriptReadHalfword(ctx));
+ u8 movementType = ScriptReadByte(ctx);
+
+ Overworld_SetMapObjTemplateMovementType(localId, movementType);
+ return FALSE;
+}
+
+bool8 ScrCmd_createvobject(struct ScriptContext *ctx)
+{
+ u8 graphicsId = ScriptReadByte(ctx);
+ u8 v2 = ScriptReadByte(ctx);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u32 y = VarGet(ScriptReadHalfword(ctx));
+ u8 elevation = ScriptReadByte(ctx);
+ u8 direction = ScriptReadByte(ctx);
+
+ sprite_new(graphicsId, v2, x, y, elevation, direction);
+ return FALSE;
+}
+
+bool8 ScrCmd_turnvobject(struct ScriptContext *ctx)
+{
+ u8 v1 = ScriptReadByte(ctx);
+ u8 direction = ScriptReadByte(ctx);
+
+ sub_8069058(v1, direction);
+ return FALSE;
+}
+
+bool8 ScrCmd_lockall(struct ScriptContext *ctx)
+{
+ if (is_c1_link_related_active())
+ {
+ return FALSE;
+ }
+ else
+ {
+ ScriptFreezeMapObjects();
+ SetupNativeScript(ctx, sub_8069590);
+ return TRUE;
+ }
+}
+
+bool8 ScrCmd_lock(struct ScriptContext *ctx)
+{
+ if (is_c1_link_related_active())
+ {
+ return FALSE;
+ }
+ else
+ {
+ if (gMapObjects[gSelectedEventObject].active)
+ {
+ LockSelectedMapObject();
+ SetupNativeScript(ctx, sub_8069648);
+ }
+ else
+ {
+ ScriptFreezeMapObjects();
+ SetupNativeScript(ctx, sub_8069590);
+ }
+ return TRUE;
+ }
+}
+
+bool8 ScrCmd_releaseall(struct ScriptContext *ctx)
+{
+ u8 playerObjectId;
+
+ HideFieldMessageBox();
+ playerObjectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[playerObjectId]);
+ sub_80974D8();
+ UnfreezeMapObjects();
+ return FALSE;
+}
+
+bool8 ScrCmd_release(struct ScriptContext *ctx)
+{
+ u8 playerObjectId;
+
+ HideFieldMessageBox();
+ if (gMapObjects[gSelectedEventObject].active)
+ FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gSelectedEventObject]);
+ playerObjectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0);
+ FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[playerObjectId]);
+ sub_80974D8();
+ UnfreezeMapObjects();
+ return FALSE;
+}
+
+bool8 ScrCmd_textcolor(struct ScriptContext *ctx)
+{
+ gUnknown_20370DC = gUnknown_20370DA;
+ gUnknown_20370DA = ScriptReadByte(ctx);
+ return FALSE;
+}
+
+bool8 ScrCmd_message(struct ScriptContext *ctx)
+{
+ const u8 *msg = (const u8 *)ScriptReadWord(ctx);
+
+ if (msg == NULL)
+ msg = (const u8 *)ctx->data[0];
+ ShowFieldMessage(msg);
+ return FALSE;
+}
+
+bool8 ScrCmd_loadhelp(struct ScriptContext *ctx)
+{
+ const u8 *msg = (const u8 *)ScriptReadWord(ctx);
+
+ if (msg == NULL)
+ msg = (const u8 *)ctx->data[0];
+ sub_80F7974(msg);
+ CopyWindowToVram(GetStartMenuWindowId(), 1);
+ return FALSE;
+}
+
+bool8 ScrCmd_unloadhelp(struct ScriptContext *ctx)
+{
+ sub_80F7998();
+ return FALSE;
+}
+
+bool8 ScrCmd_messageautoscroll(struct ScriptContext *ctx)
+{
+ const u8 *msg = (const u8 *)ScriptReadWord(ctx);
+
+ if (msg == NULL)
+ msg = (const u8 *)ctx->data[0];
+ ShowFieldAutoScrollMessage(msg);
+ return FALSE;
+}
+
+bool8 ScrCmd_waitmessage(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, IsFieldMessageBoxHidden);
+ return TRUE;
+}
+
+bool8 ScrCmd_closemessage(struct ScriptContext *ctx)
+{
+ HideFieldMessageBox();
+ return FALSE;
+}
+
+static bool8 WaitForAorBPress(void)
+{
+ if (gMain.newKeys & A_BUTTON)
+ return TRUE;
+ if (gMain.newKeys & B_BUTTON)
+ return TRUE;
+
+ if (sub_806B93C(gUnknown_3005070) == TRUE)
+ {
+ u8 r4 = sub_806B96C(gUnknown_3005070);
+ sub_8069998(r4);
+ if (r4)
+ {
+ if (gUnknown_203ADFA != 2)
+ {
+ sub_80699F8();
+ if (r4 < 9 || r4 > 10)
+ sub_8069964();
+ else
+ {
+ sub_80699A4();
+ sub_8069970();
+ }
+ return TRUE;
+ }
+ }
+ }
+ if (sub_8112CAC() == 1 || gUnknown_203ADFA == 2)
+ {
+ if (gUnknown_20370AC == 120)
+ return TRUE;
+ else
+ gUnknown_20370AC++;
+ }
+
+ return FALSE;
+}
+
+static bool8 sub_806B93C(struct ScriptContext * ctx)
+{
+ const u8 * script = ctx->scriptPtr;
+ u8 nextCmd = *script;
+ if (nextCmd == 3) // return
+ {
+ script = ctx->stack[ctx->stackDepth - 1];
+ nextCmd = *script;
+ }
+ if (nextCmd < 0x6B || nextCmd > 0x6C) // releaseall or release
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static u8 sub_806B96C(struct ScriptContext * ctx)
+{
+ if (gMain.heldKeys & DPAD_UP && gSpecialVar_Facing != 2)
+ return 1;
+
+ if (gMain.heldKeys & DPAD_DOWN && gSpecialVar_Facing != 1)
+ return 2;
+
+ if (gMain.heldKeys & DPAD_LEFT && gSpecialVar_Facing != 3)
+ return 3;
+
+ if (gMain.heldKeys & DPAD_RIGHT && gSpecialVar_Facing != 4)
+ return 4;
+
+ if (gMain.newKeys & L_BUTTON)
+ return 5;
+
+ if (gMain.heldKeys & R_BUTTON)
+ return 6;
+
+ if (gMain.heldKeys & START_BUTTON)
+ return 7;
+
+ if (gMain.heldKeys & SELECT_BUTTON)
+ return 8;
+
+ if (gMain.newKeys & A_BUTTON)
+ return 9;
+
+ if (gMain.newKeys & B_BUTTON)
+ return 10;
+
+ return 0;
+}
+
+bool8 ScrCmd_waitbuttonpress(struct ScriptContext *ctx)
+{
+ gUnknown_3005070 = ctx;
+
+ if (sub_8112CAC() == 1 || gUnknown_203ADFA == 2)
+ gUnknown_20370AC = 0;
+ SetupNativeScript(ctx, WaitForAorBPress);
+ return TRUE;
+}
+
+bool8 ScrCmd_yesnobox(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+
+ if (ScriptMenu_YesNo(left, top) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool8 ScrCmd_multichoice(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 multichoiceId = ScriptReadByte(ctx);
+ u8 ignoreBPress = ScriptReadByte(ctx);
+
+ if (ScriptMenu_Multichoice(left, top, multichoiceId, ignoreBPress) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool8 ScrCmd_multichoicedefault(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 multichoiceId = ScriptReadByte(ctx);
+ u8 defaultChoice = ScriptReadByte(ctx);
+ u8 ignoreBPress = ScriptReadByte(ctx);
+
+ if (ScriptMenu_MultichoiceWithDefault(left, top, multichoiceId, ignoreBPress, defaultChoice) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool8 ScrCmd_drawbox(struct ScriptContext *ctx)
+{
+ /*u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 right = ScriptReadByte(ctx);
+ u8 bottom = ScriptReadByte(ctx);
+
+ MenuDrawTextWindow(left, top, right, bottom);*/
+ return FALSE;
+}
+
+bool8 ScrCmd_multichoicegrid(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 multichoiceId = ScriptReadByte(ctx);
+ u8 numColumns = ScriptReadByte(ctx);
+ u8 ignoreBPress = ScriptReadByte(ctx);
+
+ if (ScriptMenu_MultichoiceGrid(left, top, multichoiceId, ignoreBPress, numColumns) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool8 ScrCmd_erasebox(struct ScriptContext *ctx)
+{
+ u8 left = ScriptReadByte(ctx);
+ u8 top = ScriptReadByte(ctx);
+ u8 right = ScriptReadByte(ctx);
+ u8 bottom = ScriptReadByte(ctx);
+
+ // MenuZeroFillWindowRect(left, top, right, bottom);
+ return FALSE;
+}
+
+bool8 ScrCmd_drawboxtext(struct ScriptContext *ctx)
+{
+// u8 left = ScriptReadByte(ctx);
+// u8 top = ScriptReadByte(ctx);
+// u8 multichoiceId = ScriptReadByte(ctx);
+// u8 ignoreBPress = ScriptReadByte(ctx);
+
+ /*if (Multichoice(left, top, multichoiceId, ignoreBPress) == TRUE)
+ {
+ ScriptContext1_Stop();
+ return TRUE;
+ }*/
+ return FALSE;
+}
+
+bool8 ScrCmd_showmonpic(struct ScriptContext *ctx)
+{
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+
+ ScriptMenu_ShowPokemonPic(species, x, y);
+ PlayCry7(species, 0);
+ return FALSE;
+}
+
+bool8 ScrCmd_hidemonpic(struct ScriptContext *ctx)
+{
+ bool8 (*func)(void) = ScriptMenu_GetPicboxWaitFunc();
+
+ if (func == NULL)
+ return FALSE;
+ SetupNativeScript(ctx, func);
+ return TRUE;
+}
+
+bool8 ScrCmd_showcontestwinner(struct ScriptContext *ctx)
+{
+ u8 v1 = ScriptReadByte(ctx);
+
+ /*
+ if (v1)
+ sub_812FDA8(v1);
+ ShowContestWinner();
+ ScriptContext1_Stop();
+ return TRUE;
+ */
+
+ return FALSE;
+}
+
+bool8 ScrCmd_braillemessage(struct ScriptContext *ctx)
+{
+ u8 *ptr = (u8 *)ScriptReadWord(ctx);
+ if (ptr == NULL)
+ ptr = (u8 *)ctx->data[0];
+
+ sub_80F6E9C();
+ DrawDialogueFrame(0, 1);
+ AddTextPrinterParameterized(0, 6, ptr, 0, 1, 0, NULL);
+ return FALSE;
+}
+
+bool8 ScrCmd_getbraillestringwidth(struct ScriptContext *ctx)
+{
+ u8 *ptr = (u8 *)ScriptReadWord(ctx);
+ if (ptr == NULL)
+ ptr = (u8 *)ctx->data[0];
+
+ gSpecialVar_0x8004 = GetStringWidth(6, ptr, -1);
+ return FALSE;
+}
+
+bool8 ScrCmd_vmessage(struct ScriptContext *ctx)
+{
+ u32 v1 = ScriptReadWord(ctx);
+
+ ShowFieldMessage((u8 *)(v1 - gVScriptOffset));
+ return FALSE;
+}
+
+u8 * const sScriptStringVars[] =
+{
+ gStringVar1,
+ gStringVar2,
+ gStringVar3,
+};
+
+bool8 ScrCmd_bufferspeciesname(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], gSpeciesNames[species]);
+ return FALSE;
+}
+
+bool8 ScrCmd_bufferleadmonspeciesname(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+
+ u8 *dest = sScriptStringVars[stringVarIndex];
+ u8 partyIndex = GetLeadMonIndex();
+ u32 species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL);
+ StringCopy(dest, gSpeciesNames[species]);
+ return FALSE;
+}
+
+bool8 ScrCmd_bufferpartymonnick(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 partyIndex = VarGet(ScriptReadHalfword(ctx));
+
+ GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, sScriptStringVars[stringVarIndex]);
+ StringGetEnd10(sScriptStringVars[stringVarIndex]);
+ return FALSE;
+}
+
+bool8 ScrCmd_bufferitemname(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+
+ CopyItemName(itemId, sScriptStringVars[stringVarIndex]);
+ return FALSE;
+}
+
+const u8 gUnknown_83A72A0[] = _("S");
+const u8 gUnknown_83A72A2[] = _("IES");
+
+bool8 ScrCmd_bufferitemnameplural(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 itemId = VarGet(ScriptReadHalfword(ctx));
+ u16 quantity = VarGet(ScriptReadHalfword(ctx));
+
+ CopyItemName(itemId, sScriptStringVars[stringVarIndex]);
+ if (itemId == ITEM_POKE_BALL && quantity >= 2)
+ StringAppend(sScriptStringVars[stringVarIndex], gUnknown_83A72A0);
+ else if (itemId >= ITEM_CHERI_BERRY && itemId < ITEM_ENIGMA_BERRY && quantity >= 2)
+ {
+ u16 strlength = StringLength(sScriptStringVars[stringVarIndex]);
+ if (strlength != 0)
+ {
+ u8 * endptr = sScriptStringVars[stringVarIndex] + strlength;
+ endptr[-1] = EOS;
+ StringAppend(sScriptStringVars[stringVarIndex], gUnknown_83A72A2);
+ }
+ }
+
+ return FALSE;
+}
+
+bool8 ScrCmd_bufferdecorationname(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 decorId = VarGet(ScriptReadHalfword(ctx));
+
+// StringCopy(sScriptStringVars[stringVarIndex], gDecorations[decorId].name);
+ return FALSE;
+}
+
+bool8 ScrCmd_buffermovename(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 moveId = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], gMoveNames[moveId]);
+ return FALSE;
+}
+
+bool8 ScrCmd_buffernumberstring(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 v1 = VarGet(ScriptReadHalfword(ctx));
+ u8 v2 = CountDigits(v1);
+
+ ConvertIntToDecimalStringN(sScriptStringVars[stringVarIndex], v1, 0, v2);
+ return FALSE;
+}
+
+bool8 ScrCmd_bufferstdstring(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], gStdStringPtrs[index]);
+ return FALSE;
+}
+
+/*
+bool8 ScrCmd_buffercontesttype(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ sub_818E868(sScriptStringVars[stringVarIndex], index);
+ return FALSE;
+}
+*/
+
+bool8 ScrCmd_bufferstring(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ const u8 *text = (u8 *)ScriptReadWord(ctx);
+
+ StringCopy(sScriptStringVars[stringVarIndex], text);
+ return FALSE;
+}
+
+bool8 ScrCmd_vloadword(struct ScriptContext *ctx)
+{
+ const u8 *ptr = (u8 *)(ScriptReadWord(ctx) - gVScriptOffset);
+
+ StringExpandPlaceholders(gStringVar4, ptr);
+ return FALSE;
+}
+
+bool8 ScrCmd_vbufferstring(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u32 addr = ScriptReadWord(ctx);
+
+ const u8 *src = (u8 *)(addr - gVScriptOffset);
+ u8 *dest = sScriptStringVars[stringVarIndex];
+ StringCopy(dest, src);
+ return FALSE;
+}
+
+bool8 ScrCmd_bufferboxname(struct ScriptContext *ctx)
+{
+ u8 stringVarIndex = ScriptReadByte(ctx);
+ u16 boxId = VarGet(ScriptReadHalfword(ctx));
+
+ StringCopy(sScriptStringVars[stringVarIndex], GetBoxNamePtr(boxId));
+ return FALSE;
+}
+
+bool8 ScrCmd_givemon(struct ScriptContext *ctx)
+{
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+ u8 level = ScriptReadByte(ctx);
+ u16 item = VarGet(ScriptReadHalfword(ctx));
+ u32 unkParam1 = ScriptReadWord(ctx);
+ u32 unkParam2 = ScriptReadWord(ctx);
+ u8 unkParam3 = ScriptReadByte(ctx);
+
+ gSpecialVar_Result = ScriptGiveMon(species, level, item, unkParam1, unkParam2, unkParam3);
+ return FALSE;
+}
+
+bool8 ScrCmd_giveegg(struct ScriptContext *ctx)
+{
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = ScriptGiveEgg(species);
+ return FALSE;
+}
+
+bool8 ScrCmd_setmonmove(struct ScriptContext *ctx)
+{
+ u8 partyIndex = ScriptReadByte(ctx);
+ u8 slot = ScriptReadByte(ctx);
+ u16 move = ScriptReadHalfword(ctx);
+
+ ScriptSetMonMoveSlot(partyIndex, move, slot);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkpartymove(struct ScriptContext *ctx)
+{
+ u8 i;
+ u16 moveId = ScriptReadHalfword(ctx);
+
+ gSpecialVar_Result = PARTY_SIZE;
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ u16 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL);
+ if (!species)
+ break;
+ if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG) && MonKnowsMove(&gPlayerParty[i], moveId) == TRUE)
+ {
+ gSpecialVar_Result = i;
+ gSpecialVar_0x8004 = species;
+ break;
+ }
+ }
+ return FALSE;
+}
+
+bool8 ScrCmd_givemoney(struct ScriptContext *ctx)
+{
+ u32 amount = ScriptReadWord(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore)
+ AddMoney(&gSaveBlock1Ptr->money, amount);
+ return FALSE;
+}
+
+bool8 ScrCmd_takemoney(struct ScriptContext *ctx)
+{
+ u32 amount = ScriptReadWord(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore)
+ RemoveMoney(&gSaveBlock1Ptr->money, amount);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkmoney(struct ScriptContext *ctx)
+{
+ u32 amount = ScriptReadWord(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore)
+ gSpecialVar_Result = IsEnoughMoney(&gSaveBlock1Ptr->money, amount);
+ return FALSE;
+}
+
+bool8 ScrCmd_showmoneybox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore && sub_81119D4(sub_809D6D4) != TRUE)
+ DrawMoneyBox(GetMoney(&gSaveBlock1Ptr->money), x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_hidemoneybox(struct ScriptContext *ctx)
+{
+ /*u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);*/
+
+ HideMoneyBox();
+ return FALSE;
+}
+
+bool8 ScrCmd_updatemoneybox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+ u8 ignore = ScriptReadByte(ctx);
+
+ if (!ignore)
+ ChangeAmountInMoneyBox(GetMoney(&gSaveBlock1Ptr->money));
+ return FALSE;
+}
+
+bool8 ScrCmd_showcoinsbox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+
+ if (sub_81119D4(sub_809D6D4) != TRUE)
+ ShowCoinsWindow(GetCoins(), x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_hidecoinsbox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+
+ HideCoinsWindow();
+ return FALSE;
+}
+
+bool8 ScrCmd_updatecoinsbox(struct ScriptContext *ctx)
+{
+ u8 x = ScriptReadByte(ctx);
+ u8 y = ScriptReadByte(ctx);
+
+ PrintCoinsString(GetCoins());
+ return FALSE;
+}
+
+bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx)
+{
+ ctx->scriptPtr = BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr);
+ return FALSE;
+}
+
+bool8 ScrCmd_dotrainerbattle(struct ScriptContext *ctx)
+{
+ BattleSetup_StartTrainerBattle();
+ return TRUE;
+}
+
+bool8 ScrCmd_gotopostbattlescript(struct ScriptContext *ctx)
+{
+ ctx->scriptPtr = BattleSetup_GetScriptAddrAfterBattle();
+ return FALSE;
+}
+
+bool8 ScrCmd_gotobeatenscript(struct ScriptContext *ctx)
+{
+ ctx->scriptPtr = BattleSetup_GetTrainerPostBattleScript();
+ return FALSE;
+}
+
+bool8 ScrCmd_checktrainerflag(struct ScriptContext *ctx)
+{
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ ctx->comparisonResult = HasTrainerAlreadyBeenFought(index);
+ return FALSE;
+}
+
+bool8 ScrCmd_settrainerflag(struct ScriptContext *ctx)
+{
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ SetTrainerFlag(index);
+ return FALSE;
+}
+
+bool8 ScrCmd_cleartrainerflag(struct ScriptContext *ctx)
+{
+ u16 index = VarGet(ScriptReadHalfword(ctx));
+
+ ClearTrainerFlag(index);
+ return FALSE;
+}
+
+bool8 ScrCmd_setwildbattle(struct ScriptContext *ctx)
+{
+ u16 species = ScriptReadHalfword(ctx);
+ u8 level = ScriptReadByte(ctx);
+ u16 item = ScriptReadHalfword(ctx);
+
+ CreateScriptedWildMon(species, level, item);
+ return FALSE;
+}
+
+bool8 ScrCmd_dowildbattle(struct ScriptContext *ctx)
+{
+ BattleSetup_StartScriptedWildBattle();
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_pokemart(struct ScriptContext *ctx)
+{
+ const void *ptr = (void *)ScriptReadWord(ctx);
+
+ CreatePokemartMenu(ptr);
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_pokemartdecoration(struct ScriptContext *ctx)
+{
+ const void *ptr = (void *)ScriptReadWord(ctx);
+
+ CreateDecorationShop1Menu(ptr);
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_pokemartdecoration2(struct ScriptContext *ctx)
+{
+ const void *ptr = (void *)ScriptReadWord(ctx);
+
+ CreateDecorationShop2Menu(ptr);
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_playslotmachine(struct ScriptContext *ctx)
+{
+ u8 slotMachineIndex = VarGet(ScriptReadHalfword(ctx));
+
+ PlaySlotMachine(slotMachineIndex, c2_exit_to_overworld_1_continue_scripts_restart_music);
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+bool8 ScrCmd_setberrytree(struct ScriptContext *ctx)
+{
+// u8 treeId = ScriptReadByte(ctx);
+// u8 berry = ScriptReadByte(ctx);
+// u8 growthStage = ScriptReadByte(ctx);
+//
+// if (berry == 0)
+// PlantBerryTree(treeId, 0, growthStage, FALSE);
+// else
+// PlantBerryTree(treeId, berry, growthStage, FALSE);
+ return FALSE;
+}
+
+bool8 ScrCmd_getpricereduction(struct ScriptContext *ctx)
+{
+// u16 value = VarGet(ScriptReadHalfword(ctx));
+//
+// gSpecialVar_Result = GetPriceReduction(value);
+ return FALSE;
+}
+
+bool8 ScrCmd_choosecontestmon(struct ScriptContext *ctx)
+{
+// sub_81B9404();
+ ScriptContext1_Stop();
+ return TRUE;
+}
+
+
+bool8 ScrCmd_startcontest(struct ScriptContext *ctx)
+{
+// sub_80F840C();
+// ScriptContext1_Stop();
+// return TRUE;
+ return FALSE;
+}
+
+bool8 ScrCmd_showcontestresults(struct ScriptContext *ctx)
+{
+// sub_80F8484();
+// ScriptContext1_Stop();
+// return TRUE;
+ return FALSE;
+}
+
+bool8 ScrCmd_contestlinktransfer(struct ScriptContext *ctx)
+{
+// sub_80F84C4(gSpecialVar_ContestCategory);
+// ScriptContext1_Stop();
+// return TRUE;
+ return FALSE;
+}
+
+bool8 ScrCmd_dofieldeffect(struct ScriptContext *ctx)
+{
+ u16 effectId = VarGet(ScriptReadHalfword(ctx));
+
+ sFieldEffectScriptId = effectId;
+ FieldEffectStart(sFieldEffectScriptId);
+ return FALSE;
+}
+
+bool8 ScrCmd_setfieldeffectarg(struct ScriptContext *ctx)
+{
+ u8 argNum = ScriptReadByte(ctx);
+
+ gFieldEffectArguments[argNum] = (s16)VarGet(ScriptReadHalfword(ctx));
+ return FALSE;
+}
+
+static bool8 WaitForFieldEffectFinish(void)
+{
+ if (!FieldEffectActiveListContains(sFieldEffectScriptId))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_waitfieldeffect(struct ScriptContext *ctx)
+{
+ sFieldEffectScriptId = VarGet(ScriptReadHalfword(ctx));
+ SetupNativeScript(ctx, WaitForFieldEffectFinish);
+ return TRUE;
+}
+
+bool8 ScrCmd_setrespawn(struct ScriptContext *ctx)
+{
+ u16 healLocationId = VarGet(ScriptReadHalfword(ctx));
+
+ SetLastHealLocationWarp(healLocationId);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkplayergender(struct ScriptContext *ctx)
+{
+ gSpecialVar_Result = gSaveBlock2Ptr->playerGender;
+ return FALSE;
+}
+
+bool8 ScrCmd_playmoncry(struct ScriptContext *ctx)
+{
+ u16 species = VarGet(ScriptReadHalfword(ctx));
+ u16 mode = VarGet(ScriptReadHalfword(ctx));
+
+ PlayCry7(species, mode);
+ return FALSE;
+}
+
+bool8 ScrCmd_waitmoncry(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, IsCryFinished);
+ return TRUE;
+}
+
+bool8 ScrCmd_setmetatile(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+ u16 tileId = VarGet(ScriptReadHalfword(ctx));
+ u16 v8 = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ if (!v8)
+ MapGridSetMetatileIdAt(x, y, tileId);
+ else
+ MapGridSetMetatileIdAt(x, y, tileId | 0xC00);
+ return FALSE;
+}
+
+bool8 ScrCmd_opendoor(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ PlaySE(GetDoorSoundEffect(x, y));
+ FieldAnimateDoorOpen(x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_closedoor(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ FieldAnimateDoorClose(x, y);
+ return FALSE;
+}
+
+static bool8 IsDoorAnimationStopped(void)
+{
+ if (!FieldIsDoorAnimationRunning())
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 ScrCmd_waitdooranim(struct ScriptContext *ctx)
+{
+ SetupNativeScript(ctx, IsDoorAnimationStopped);
+ return TRUE;
+}
+
+bool8 ScrCmd_setdooropen(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ FieldSetDoorOpened(x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_setdoorclosed(struct ScriptContext *ctx)
+{
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+
+ x += 7;
+ y += 7;
+ FieldSetDoorClosed(x, y);
+ return FALSE;
+}
+
+bool8 ScrCmd_addelevmenuitem(struct ScriptContext *ctx)
+{
+// u8 v3 = ScriptReadByte(ctx);
+// u16 v5 = VarGet(ScriptReadHalfword(ctx));
+// u16 v7 = VarGet(ScriptReadHalfword(ctx));
+// u16 v9 = VarGet(ScriptReadHalfword(ctx));
+
+ //ScriptAddElevatorMenuItem(v3, v5, v7, v9);
+ return FALSE;
+}
+
+bool8 ScrCmd_showelevmenu(struct ScriptContext *ctx)
+{
+ /*ScriptShowElevatorMenu();
+ ScriptContext1_Stop();
+ return TRUE;*/
+ return FALSE;
+}
+
+bool8 ScrCmd_checkcoins(struct ScriptContext *ctx)
+{
+ u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx));
+ *ptr = GetCoins();
+ return FALSE;
+}
+
+bool8 ScrCmd_givecoins(struct ScriptContext *ctx)
+{
+ u16 coins = VarGet(ScriptReadHalfword(ctx));
+
+ if (GiveCoins(coins) == TRUE)
+ gSpecialVar_Result = 0;
+ else
+ gSpecialVar_Result = 1;
+ return FALSE;
+}
+
+bool8 ScrCmd_takecoins(struct ScriptContext *ctx)
+{
+ u16 coins = VarGet(ScriptReadHalfword(ctx));
+
+ if (TakeCoins(coins) == TRUE)
+ gSpecialVar_Result = 0;
+ else
+ gSpecialVar_Result = 1;
+ return FALSE;
+}
+
+bool8 ScrCmd_signmsg(struct ScriptContext *ctx)
+{
+ sub_8069A20();
+ return FALSE;
+}
+
+bool8 ScrCmd_normalmsg(struct ScriptContext *ctx)
+{
+ sub_8069A2C();
+ return FALSE;
+}
+
+// This command will force the Pokémon to be obedient, you don't get to make it disobedient.
+bool8 ScrCmd_setmonobedient(struct ScriptContext *ctx)
+{
+ bool8 obedient = TRUE;
+ u16 partyIndex = VarGet(ScriptReadHalfword(ctx));
+
+ SetMonData(&gPlayerParty[partyIndex], MON_DATA_OBEDIENCE, &obedient);
+ return FALSE;
+}
+
+bool8 ScrCmd_checkmonobedience(struct ScriptContext *ctx)
+{
+ u16 partyIndex = VarGet(ScriptReadHalfword(ctx));
+
+ gSpecialVar_Result = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OBEDIENCE, NULL);
+ return FALSE;
+}
+
+bool8 ScrCmd_setmonmetlocation(struct ScriptContext *ctx)
+{
+ u16 partyIndex = VarGet(ScriptReadHalfword(ctx));
+ u8 location = ScriptReadByte(ctx);
+
+ if (partyIndex < PARTY_SIZE)
+ SetMonData(&gPlayerParty[partyIndex], MON_DATA_MET_LOCATION, &location);
+ return FALSE;
+}
diff --git a/src/script.c b/src/script.c
index 59ef4e579..608dc6ba0 100644
--- a/src/script.c
+++ b/src/script.c
@@ -9,7 +9,7 @@ extern u8 gUnknown_203ADFA;
extern void sub_80CBDE8(void); // field_specials
extern u16 CalcCRC16WithTable(u8 *data, int length); // util
-extern bool32 sub_8143FC8(void); // mevent
+extern bool32 ValidateReceivedWonderCard(void); // mevent
enum
{
@@ -19,7 +19,7 @@ enum
};
EWRAM_DATA u8 gUnknown_20370A0 = 0;
-EWRAM_DATA u8 *gUnknown_20370A4 = NULL;
+EWRAM_DATA const u8 *gRAMScriptPtr = NULL;
// ewram bss
/*IWRAM_DATA*/ static u8 sScriptContext1Status;
@@ -485,7 +485,7 @@ bool8 InitRamScript(u8 *script, u16 scriptSize, u8 mapGroup, u8 mapNum, u8 objec
u8 *GetRamScript(u8 objectId, u8 *script)
{
struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data;
- gUnknown_20370A4 = NULL;
+ gRAMScriptPtr = NULL;
if (scriptData->magic != RAM_SCRIPT_MAGIC)
return script;
if (scriptData->mapGroup != gSaveBlock1Ptr->location.mapGroup)
@@ -501,7 +501,7 @@ u8 *GetRamScript(u8 objectId, u8 *script)
}
else
{
- gUnknown_20370A4 = script;
+ gRAMScriptPtr = script;
return scriptData->script;
}
}
@@ -525,7 +525,7 @@ bool32 sub_8069DFC(void)
u8 *sub_8069E48(void)
{
struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data;
- if (!sub_8143FC8())
+ if (!ValidateReceivedWonderCard())
return NULL;
if (scriptData->magic != RAM_SCRIPT_MAGIC)
return NULL;
diff --git a/src/seagallop.c b/src/seagallop.c
new file mode 100644
index 000000000..ae880b2a3
--- /dev/null
+++ b/src/seagallop.c
@@ -0,0 +1,499 @@
+#include "global.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "palette.h"
+#include "malloc.h"
+#include "scanline_effect.h"
+#include "trainer_pokemon_sprites.h"
+#include "window.h"
+#include "text_window.h"
+#include "sound.h"
+#include "task.h"
+#include "help_system.h"
+#include "overworld.h"
+#include "event_data.h"
+#include "field_fadetransition.h"
+#include "field_weather.h"
+#include "constants/songs.h"
+#include "constants/maps.h"
+#include "seagallop.h"
+
+#define TILESTAG_FERRY 3000
+#define TILESTAG_WAKE 4000
+
+#define PALTAG_FERRY_WAKE 3000
+
+static EWRAM_DATA void * sBg3TilemapBuffer = NULL;
+
+static void CB2_SetUpSeaGallopScene(void);
+static void VBlankCB_SeaGallop(void);
+static void MainCB2_SeaGallop(void);
+static void Task_SeaGallop_0(u8 taskId);
+static void Task_SeaGallop_1(u8 taskId);
+static void Task_SeaGallop_2(u8 taskId);
+static void Task_SeaGallop_3(void);
+static void ResetGPU(void);
+static void ResetAllAssets(void);
+static void SetDispcnt(void);
+static void ResetBGPos(void);
+static void LoadFerrySpriteResources(void);
+static void FreeFerrySpriteResources(void);
+static void CreateFerrySprite(void);
+static void SpriteCB_Ferry(struct Sprite * sprite);
+static void CreateWakeSprite(s16 x);
+static void SpriteCB_Wake(struct Sprite * sprite);
+static bool8 GetDirectionOfTravel(void);
+
+static const u16 sWaterTiles[] = INCBIN_U16("data/seagallop/water.4bpp");
+static const u16 sWaterPal[] = INCBIN_U16("data/seagallop/water.gbapal");
+static const u16 sWaterTilemap_WB[] = INCBIN_U16("data/seagallop/wb_tilemap.bin");
+static const u16 sWaterTilemap_EB[] = INCBIN_U16("data/seagallop/eb_tilemap.bin");
+static const u16 sFerrySpriteTiles[] = INCBIN_U16("data/seagallop/ferry_sprite.4bpp");
+static const u16 sFerryAndWakePal[] = INCBIN_U16("data/seagallop/ferry_and_wake.gbapal");
+static const u16 sWakeSpriteTiles[] = INCBIN_U16("data/seagallop/wake.4bpp");
+
+static const struct BgTemplate sBGTemplates[] = {
+ {
+ .bg = 3,
+ .charBaseIndex = 3,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x000
+ }
+};
+
+static const s8 sSeaGallopSpawnTable[][4] = {
+ // Map X Y
+ [SEAGALLOP_VERMILION_CITY] = {MAP(VERMILION_CITY), 0x17, 0x20},
+ [SEAGALLOP_ONE_ISLAND] = {MAP(ONE_ISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_TWO_ISLAND] = {MAP(TWO_ISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_THREE_ISLAND] = {MAP(THREE_ISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_FOUR_ISLAND] = {MAP(FOUR_ISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_FIVE_ISLAND] = {MAP(FIVE_ISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_SIX_ISLAND] = {MAP(SIX_ISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_SEVEN_ISLAND] = {MAP(SEVEN_ISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_CINNABAR_ISLAND] = {MAP(CINNABAR_ISLAND), 0x15, 0x07},
+ [SEAGALLOP_NAVEL_ROCK] = {MAP(NAVEL_ROCK_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_BIRTH_ISLAND] = {MAP(BIRTH_ISLAND_HARBOR), 0x08, 0x05}
+};
+
+// Bitpacked array. In the commented section, right-most bit is the
+// flag for traveling from (row port) to Vermilion City, and so on.
+// Flags follow these enums:
+
+enum TravelDirections
+{
+ DIRN_WESTBOUND = 0,
+ DIRN_EASTBOUND = 1
+};
+
+static const u16 sTravelDirectionMatrix[] = {
+ [SEAGALLOP_VERMILION_CITY] = 0x6fe, // 11011111110
+ [SEAGALLOP_ONE_ISLAND] = 0x6fc, // 11011111100
+ [SEAGALLOP_TWO_ISLAND] = 0x6f8, // 11011111000
+ [SEAGALLOP_THREE_ISLAND] = 0x6f0, // 11011110000
+ [SEAGALLOP_FOUR_ISLAND] = 0x6e0, // 11011100000
+ [SEAGALLOP_FIVE_ISLAND] = 0x4c0, // 10011000000
+ [SEAGALLOP_SIX_ISLAND] = 0x400, // 10000000000
+ [SEAGALLOP_SEVEN_ISLAND] = 0x440, // 10001000000
+ [SEAGALLOP_CINNABAR_ISLAND] = 0x7ff, // 11111111111
+ [SEAGALLOP_NAVEL_ROCK] = 0x6e0, // 11011100000
+ [SEAGALLOP_BIRTH_ISLAND] = 0x000 // 00000000000
+};
+
+static const union AnimCmd sSpriteAnims_Ferry_WB[] = {
+ ANIMCMD_FRAME(0, 10),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnims_Ferry_EB[] = {
+ ANIMCMD_FRAME(0, 10, .hFlip = TRUE),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_Ferry[] = {
+ sSpriteAnims_Ferry_WB,
+ sSpriteAnims_Ferry_EB
+};
+
+static const struct OamData sOamData_Ferry = {
+ .size = 3
+};
+
+static const struct SpriteTemplate sFerrySpriteTemplate = {
+ TILESTAG_FERRY,
+ PALTAG_FERRY_WAKE,
+ &sOamData_Ferry,
+ sSpriteAnimTable_Ferry,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCB_Ferry
+};
+
+static const struct SpriteSheet sFerryAndWakeSpriteSheets[] = {
+ {(const void *)sWakeSpriteTiles, sizeof(sWakeSpriteTiles), TILESTAG_WAKE},
+ {(const void *)sFerrySpriteTiles, sizeof(sFerrySpriteTiles), TILESTAG_FERRY},
+ {}
+};
+
+static const struct SpritePalette sFerryAndWakeSpritePalettes[] = {
+ {sFerryAndWakePal, PALTAG_FERRY_WAKE},
+ {}
+};
+
+static const union AnimCmd sSpriteAnims_Wake_WB[] = {
+ ANIMCMD_FRAME(0x00, 0x14),
+ ANIMCMD_FRAME(0x10, 0x14),
+ ANIMCMD_FRAME(0x20, 0x0f),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sSpriteAnims_Wake_EB[] = {
+ ANIMCMD_FRAME(0x00, 0x14, .hFlip = TRUE),
+ ANIMCMD_FRAME(0x10, 0x14, .hFlip = TRUE),
+ ANIMCMD_FRAME(0x20, 0x0f, .hFlip = TRUE),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sSpriteAnimTable_Wake[] = {
+ sSpriteAnims_Wake_WB,
+ sSpriteAnims_Wake_EB
+};
+
+static const struct OamData sOamData_Wake = {
+ .size = 2
+};
+
+static const struct SpriteTemplate sWakeSpriteTemplate = {
+ TILESTAG_WAKE,
+ PALTAG_FERRY_WAKE,
+ &sOamData_Wake,
+ sSpriteAnimTable_Wake,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCB_Wake
+};
+
+void ScrSpecial_SeaGallopFerry(void)
+{
+ SetVBlankCallback(NULL);
+ sub_812B478();
+ SetMainCallback2(CB2_SetUpSeaGallopScene);
+}
+
+static void CB2_SetUpSeaGallopScene(void)
+{
+ void ** ptr;
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL); // redundant since the setup routine already did this
+ ResetGPU();
+ gMain.state++;
+ break;
+ case 1:
+ ResetAllAssets();
+ gMain.state++;
+ break;
+ case 2:
+ ptr = &sBg3TilemapBuffer;
+ *ptr = AllocZeroed(0x800);
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, sBGTemplates, NELEMS(sBGTemplates));
+ SetBgTilemapBuffer(3, *ptr);
+ ResetBGPos();
+ gMain.state++;
+ break;
+ case 3:
+ LoadBgTiles(3, sWaterTiles, sizeof(sWaterTiles), 0);
+ if (GetDirectionOfTravel() == DIRN_EASTBOUND)
+ {
+ CopyToBgTilemapBufferRect(3, sWaterTilemap_EB, 0, 0, 32, 32);
+ }
+ else
+ {
+ CopyToBgTilemapBufferRect(3, sWaterTilemap_WB, 0, 0, 32, 32);
+ }
+ LoadPalette(sWaterPal, 0x40, 0x20);
+ LoadPalette(stdpal_get(2), 0xF0, 0x20);
+ gMain.state++;
+ break;
+ case 4:
+ if (IsDma3ManagerBusyWithBgCopy() != DIRN_EASTBOUND)
+ {
+ ShowBg(0);
+ ShowBg(3);
+ CopyBgTilemapBufferToVram(3);
+ gMain.state++;
+ }
+ break;
+ case 5:
+ LoadFerrySpriteResources();
+ BlendPalettes(0xFFFFFFFF, 16, RGB_BLACK);
+ gMain.state++;
+ break;
+ case 6:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ gMain.state++;
+ break;
+ case 7:
+ SetDispcnt();
+ SetVBlankCallback(VBlankCB_SeaGallop);
+ PlaySE(SE_NAMINORI);
+ CreateFerrySprite();
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ SetGpuReg(REG_OFFSET_WININ, 0x3F);
+ SetGpuReg(REG_OFFSET_WINOUT, 0x00);
+ SetGpuReg(REG_OFFSET_WIN0H, 0x00F0);
+ SetGpuReg(REG_OFFSET_WIN0V, 0x1888);
+ CreateTask(Task_SeaGallop_0, 8);
+ SetMainCallback2(MainCB2_SeaGallop);
+ gMain.state = 0;
+ break;
+ }
+}
+
+static void VBlankCB_SeaGallop(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void MainCB2_SeaGallop(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void Task_SeaGallop_0(u8 taskId)
+{
+ gTasks[taskId].func = Task_SeaGallop_1;
+}
+
+static void ScrollBG(void)
+{
+ if (GetDirectionOfTravel() == DIRN_EASTBOUND)
+ {
+ ChangeBgX(3, 0x600, 1);
+ }
+ else
+ {
+ ChangeBgX(3, 0x600, 2);
+ }
+}
+
+static void Task_SeaGallop_1(u8 taskId)
+{
+ struct Task * task = &gTasks[taskId];
+
+ ScrollBG();
+ if (++task->data[1] == 140)
+ {
+ Overworld_FadeOutMapMusic();
+ sub_807DC18();
+ task->func = Task_SeaGallop_2;
+ }
+}
+
+static void Task_SeaGallop_2(u8 taskId)
+{
+ ScrollBG();
+ if (sub_8055FC4() && !gPaletteFade.active)
+ {
+ Task_SeaGallop_3();
+ sub_812B484();
+ DestroyTask(taskId);
+ }
+}
+
+static void Task_SeaGallop_3(void)
+{
+ const s8 * warpInfo;
+
+ if (gSpecialVar_0x8006 >= NELEMS(sSeaGallopSpawnTable))
+ gSpecialVar_0x8006 = 0;
+
+ warpInfo = sSeaGallopSpawnTable[gSpecialVar_0x8006];
+ Overworld_SetWarpDestination(warpInfo[0], warpInfo[1], -1, warpInfo[2], warpInfo[3]);
+ PlayRainStoppingSoundEffect();
+ PlaySE(SE_KAIDAN);
+ gFieldCallback = sub_807DF64;
+ warp_in();
+ SetMainCallback2(sub_805671C);
+ ResetInitialPlayerAvatarState();
+ FreeFerrySpriteResources();
+ Free(sBg3TilemapBuffer);
+ FreeAllWindowBuffers();
+}
+
+static void ResetGPU(void)
+{
+ void * dest = (void *) VRAM;
+ DmaClearLarge16(3, dest, VRAM_SIZE, 0x1000);
+
+ DmaClear32(3, (void *)OAM, OAM_SIZE);
+ DmaClear16(3, (void *)PLTT, PLTT_SIZE);
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ SetGpuReg(REG_OFFSET_BG0CNT, 0);
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1CNT, 0);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2CNT, 0);
+ SetGpuReg(REG_OFFSET_BG2HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3CNT, 0);
+ SetGpuReg(REG_OFFSET_BG3HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3VOFS, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, 0);
+ SetGpuReg(REG_OFFSET_WIN0V, 0);
+ SetGpuReg(REG_OFFSET_WININ, 0);
+ SetGpuReg(REG_OFFSET_WINOUT, 0);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+}
+
+static void ResetAllAssets(void)
+{
+ ScanlineEffect_Stop();
+ ResetTasks();
+ ResetSpriteData();
+ ResetAllPicSprites();
+ ResetPaletteFade();
+ FreeAllSpritePalettes();
+}
+
+static void SetDispcnt(void)
+{
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON);
+}
+
+static void ResetBGPos(void)
+{
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ ChangeBgX(3, 0, 0);
+ ChangeBgY(3, 0, 0);
+}
+
+static void LoadFerrySpriteResources(void)
+{
+ LoadSpriteSheets(sFerryAndWakeSpriteSheets);
+ LoadSpritePalettes(sFerryAndWakeSpritePalettes);
+}
+
+static void FreeFerrySpriteResources(void)
+{
+ FreeSpriteTilesByTag(TILESTAG_FERRY);
+ FreeSpriteTilesByTag(TILESTAG_WAKE);
+ FreeSpritePaletteByTag(PALTAG_FERRY_WAKE);
+}
+
+static void CreateFerrySprite(void)
+{
+ u8 spriteId = CreateSprite(&sFerrySpriteTemplate, 0, 92, 0);
+ gSprites[spriteId].data[0] = 48;
+ if (GetDirectionOfTravel() == DIRN_EASTBOUND)
+ {
+ StartSpriteAnim(&gSprites[spriteId], 1);
+ }
+ else
+ {
+ gSprites[spriteId].pos1.x = 240;
+ gSprites[spriteId].data[0] *= -1;
+ }
+}
+
+static void SpriteCB_Ferry(struct Sprite * sprite)
+{
+ sprite->data[1] += sprite->data[0];
+ sprite->pos2.x = sprite->data[1] >> 4;
+ if (sprite->data[2] % 5 == 0)
+ {
+ CreateWakeSprite(sprite->pos1.x + sprite->pos2.x);
+ }
+ sprite->data[2]++;
+ if ((u16)(300 + sprite->pos2.x) > 600)
+ {
+ DestroySprite(sprite);
+ }
+}
+
+static void CreateWakeSprite(s16 x)
+{
+ u8 spriteId = CreateSprite(&sWakeSpriteTemplate, x, 92, 8);
+ if (spriteId != MAX_SPRITES)
+ {
+ if (GetDirectionOfTravel() == DIRN_EASTBOUND)
+ {
+ StartSpriteAnim(&gSprites[spriteId], 1);
+ }
+ }
+}
+
+static void SpriteCB_Wake(struct Sprite * sprite)
+{
+ if (sprite->animEnded)
+ {
+ DestroySprite(sprite);
+ }
+}
+
+static bool8 GetDirectionOfTravel(void)
+{
+ if (gSpecialVar_0x8004 >= NELEMS(sTravelDirectionMatrix))
+ {
+ return DIRN_EASTBOUND;
+ }
+ return (sTravelDirectionMatrix[gSpecialVar_0x8004] >> gSpecialVar_0x8006) & 1;
+}
+
+u8 sub_8147500(void)
+{
+ u16 originId, destId;
+
+ originId = gSpecialVar_0x8004;
+ destId = gSpecialVar_0x8006;
+
+ if (originId == SEAGALLOP_CINNABAR_ISLAND || destId == SEAGALLOP_CINNABAR_ISLAND)
+ return 1;
+
+ if (originId == SEAGALLOP_VERMILION_CITY || destId == SEAGALLOP_VERMILION_CITY)
+ return 7;
+
+ if (originId == SEAGALLOP_NAVEL_ROCK || destId == SEAGALLOP_NAVEL_ROCK)
+ return 10;
+
+ if (originId == SEAGALLOP_BIRTH_ISLAND || destId == SEAGALLOP_BIRTH_ISLAND)
+ return 12;
+
+ if ((originId == SEAGALLOP_ONE_ISLAND || originId == SEAGALLOP_TWO_ISLAND || originId == SEAGALLOP_THREE_ISLAND) && (destId == SEAGALLOP_ONE_ISLAND || destId == SEAGALLOP_TWO_ISLAND || destId == SEAGALLOP_THREE_ISLAND))
+ return 2;
+
+ if ((originId == SEAGALLOP_FOUR_ISLAND || originId == SEAGALLOP_FIVE_ISLAND) && (destId == SEAGALLOP_FOUR_ISLAND || destId == SEAGALLOP_FIVE_ISLAND))
+ return 3;
+
+ if ((originId == SEAGALLOP_SIX_ISLAND || originId == SEAGALLOP_SEVEN_ISLAND) && (destId == SEAGALLOP_SIX_ISLAND || destId == SEAGALLOP_SEVEN_ISLAND))
+ return 5;
+
+ return 6;
+}
+
+bool8 sub_8147594(void)
+{
+ if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(VERMILION_CITY) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(VERMILION_CITY) && gSaveBlock1Ptr->pos.x < 24)
+ return TRUE;
+
+ return FALSE;
+}
diff --git a/src/sound.c b/src/sound.c
index f94e44506..ba6511d1c 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -40,7 +40,23 @@ extern struct MusicPlayerInfo gMPlayInfo_SE2;
extern struct MusicPlayerInfo gMPlayInfo_SE3;
extern struct ToneData gCryTable[];
extern struct ToneData gCryTable2[];
-extern const struct Fanfare sFanfares[];
+
+static const struct Fanfare sFanfares[] = {
+ { MUS_FANFA1, 80 },
+ { MUS_FANFA4, 160 },
+ { MUS_FANFA5, 220 },
+ { MUS_ME_WAZA, 220 },
+ { MUS_ME_ASA, 160 },
+ { MUS_ME_BACHI, 340 },
+ { MUS_ME_WASURE, 180 },
+ { MUS_ME_KINOMI, 120 },
+ { MUS_ME_B_BIG, 250 },
+ { MUS_ME_B_SMALL, 150 },
+ { MUS_ME_ZANNEN, 160 },
+ { BGM_FRLG_FLUTE, 450 },
+ { BGM_FRLG_ME_KEYITEM, 170 },
+ { BGM_FRLG_ME_POKEDEX_EVAL, 196 }
+};
extern u16 SpeciesToCryId(u16);
diff --git a/src/ss_anne.c b/src/ss_anne.c
new file mode 100644
index 000000000..f59f17a76
--- /dev/null
+++ b/src/ss_anne.c
@@ -0,0 +1,200 @@
+#include "global.h"
+#include "task.h"
+#include "sound.h"
+#include "field_map_obj.h"
+#include "script.h"
+#include "constants/songs.h"
+
+// Tasks governing the ship's departure after you've gotten HM01 CUT
+
+#define SPRITE_TAG_WAKE 4000
+#define SPRITE_TAG_SMOKE 4001
+
+static void Task_SSAnneInit(u8 taskId);
+static void Task_SSAnneRun(u8 taskId);
+static void Task_SSAnneFinish(u8 taskId);
+static void CreateWakeBehindBoat(void);
+static void WakeSpriteCallback(struct Sprite * sprite);
+static void CreateSmokeSprite(void);
+static void SmokeSpriteCallback(struct Sprite * sprite);
+
+static const u16 sWakeTiles[] = INCBIN_U16("graphics/ss_anne/unk_8479838.4bpp");
+static const u16 sSmokeTiles[] = INCBIN_U16("graphics/ss_anne/unk_8479A38.4bpp");
+
+static const struct SpriteSheet sSpriteSheets[] = {
+ {(const void *)sWakeTiles, sizeof(sWakeTiles), SPRITE_TAG_WAKE},
+ {(const void *)sSmokeTiles, sizeof(sSmokeTiles), SPRITE_TAG_SMOKE},
+ {0}
+};
+
+static const union AnimCmd sWakeAnim[] = {
+ ANIMCMD_FRAME(0, 12),
+ ANIMCMD_FRAME(8, 12),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd *const sWakeAnimTable[] = {
+ sWakeAnim
+};
+
+static const struct OamData sWakeOamData = {
+ .shape = ST_OAM_V_RECTANGLE,
+ .size = 2
+};
+
+static const struct SpriteTemplate sWakeSpriteTemplate = {
+ SPRITE_TAG_WAKE,
+ 0xFFFF,
+ &sWakeOamData,
+ sWakeAnimTable,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ WakeSpriteCallback
+};
+
+static const union AnimCmd sSmokeAnim[] = {
+ ANIMCMD_FRAME( 0, 10),
+ ANIMCMD_FRAME( 4, 20),
+ ANIMCMD_FRAME( 8, 20),
+ ANIMCMD_FRAME(12, 30),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSmokeAnimTable[] = {
+ sSmokeAnim
+};
+
+static const struct OamData sSmokeOamData = {
+ .shape = ST_OAM_SQUARE,
+ .size = 1
+};
+
+static const struct SpriteTemplate sSmokeSpriteTemplate = {
+ SPRITE_TAG_SMOKE,
+ 0xFFFF,
+ &sSmokeOamData,
+ sSmokeAnimTable,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SmokeSpriteCallback
+};
+
+void Special_SSAnneDepartureCutscene(void)
+{
+ u8 taskId;
+
+ PlaySE(SE_SHIP_HORN);
+ taskId = CreateTask(Task_SSAnneInit, 8);
+ gTasks[taskId].data[0] = 50;
+}
+
+static void Task_SSAnneInit(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (--data[0] == 0)
+ {
+ LoadSpriteSheets(sSpriteSheets);
+ CreateWakeBehindBoat();
+ gTasks[taskId].func = Task_SSAnneRun;
+ }
+}
+
+static void Task_SSAnneRun(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u8 mapObjectId;
+ struct MapObject * boatObject;
+ s16 x;
+
+ data[1]++;
+ data[2]++;
+ if (data[1] == 70)
+ {
+ data[1] = 0;
+ CreateSmokeSprite();
+ }
+ TryGetFieldObjectIdByLocalIdAndMap(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &mapObjectId);
+ boatObject = &gMapObjects[mapObjectId];
+ if (gSprites[boatObject->spriteId].pos1.x + gSprites[boatObject->spriteId].pos2.x < -120)
+ {
+ PlaySE(SE_SHIP_HORN);
+ gTasks[taskId].func = Task_SSAnneFinish;
+ }
+ else
+ {
+ x = data[2] / 5;
+ gSprites[boatObject->spriteId].pos2.x = -x;
+ }
+}
+
+static void Task_SSAnneFinish(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (++data[3] == 40)
+ {
+ FreeSpriteTilesByTag(SPRITE_TAG_WAKE);
+ FreeSpriteTilesByTag(SPRITE_TAG_SMOKE);
+ DestroyTask(taskId);
+ EnableBothScriptContexts();
+ }
+}
+
+static void CreateWakeBehindBoat(void)
+{
+ u8 mapObjectId;
+ struct MapObject * boatObject;
+ u16 x;
+ u8 spriteId;
+
+ TryGetFieldObjectIdByLocalIdAndMap(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &mapObjectId);
+ boatObject = &gMapObjects[mapObjectId];
+ x = gSprites[boatObject->spriteId].pos1.x + gSprites[boatObject->spriteId].pos2.x + 80;
+ spriteId = CreateSprite(&sWakeSpriteTemplate, x, 109, 0xFF);
+ gSprites[spriteId].oam.priority = 2;
+ gSprites[spriteId].oam.paletteNum = 10;
+}
+
+static void WakeSpriteCallback(struct Sprite * sprite)
+{
+ u8 mapObjectId;
+ struct MapObject * boatObject;
+ u16 x;
+
+ TryGetFieldObjectIdByLocalIdAndMap(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &mapObjectId);
+ boatObject = &gMapObjects[mapObjectId];
+ x = gSprites[boatObject->spriteId].pos1.x + gSprites[boatObject->spriteId].pos2.x + 80;
+ sprite->pos1.x = x;
+ if (sprite->data[0] / 6 < 22)
+ sprite->data[0]++;
+ sprite->pos2.x = sprite->data[0] / 6;
+ if (sprite->pos1.x + sprite->pos2.x < -18)
+ DestroySprite(sprite);
+}
+
+static void CreateSmokeSprite(void)
+{
+ u8 mapObjectId;
+ struct MapObject * boatObject;
+ u16 x;
+ u8 spriteId;
+
+ TryGetFieldObjectIdByLocalIdAndMap(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &mapObjectId);
+ boatObject = &gMapObjects[mapObjectId];
+ x = gSprites[boatObject->spriteId].pos1.x + gSprites[boatObject->spriteId].pos2.x + 49;
+ if ((s16)x >= -32)
+ {
+ spriteId = CreateSprite(&sSmokeSpriteTemplate, x, 78, 8);
+ if (spriteId != MAX_SPRITES)
+ gSprites[spriteId].oam.paletteNum = 10;
+ }
+}
+
+static void SmokeSpriteCallback(struct Sprite * sprite)
+{
+ sprite->data[0]++;
+ sprite->pos2.x = sprite->data[0] / 4;
+ if (sprite->animEnded)
+ DestroySprite(sprite);
+}
diff --git a/src/teachy_tv.c b/src/teachy_tv.c
new file mode 100644
index 000000000..efffe2840
--- /dev/null
+++ b/src/teachy_tv.c
@@ -0,0 +1,1416 @@
+#include "task.h"
+#include "menu.h"
+#include "palette.h"
+#include "sprite.h"
+#include "menu_helpers.h"
+#include "new_menu_helpers.h"
+#include "sound.h"
+#include "malloc.h"
+#include "scanline_effect.h"
+#include "bg.h"
+#include "gpu_regs.h"
+#include "decompress.h"
+#include "window.h"
+#include "list_menu.h"
+#include "item_menu.h"
+#include "item.h"
+#include "menu_indicators.h"
+#include "field_map_obj.h"
+#include "random.h"
+#include "text.h"
+#include "constants/songs.h"
+#include "constants/items.h"
+#include "event_data.h"
+#include "load_save.h"
+#include "battle_transition.h"
+#include "battle_2.h"
+#include "battle.h"
+#include "global.fieldmap.h"
+#include "teachy_tv.h"
+#include "help_system.h"
+#include "overworld.h"
+#include "unk_8159F40.h"
+#include "graphics.h"
+#include "fieldmap.h"
+#include "strings.h"
+
+enum TeachyTvScript
+{
+ TTVSCR_BATTLE,
+ TTVSCR_STATUS,
+ TTVSCR_MATCHUPS,
+ TTVSCR_CATCHING,
+ TTVSCR_TMS,
+ TTVSCR_REGISTER
+};
+
+struct TeachyTvCtrlBlk
+{
+ MainCallback callback;
+ u8 mode;
+ u8 whichScript;
+ u16 scrollOffset;
+ u16 selectedRow;
+};
+
+struct TeachyTvBuf
+{
+ MainCallback savedCallback;
+ u16 buffer1[0x800];
+ u16 buffer2[0x800];
+ u16 buffer3[0x800];
+ u16 buffer4[0x800];
+ u8 grassAnimCounterLo;
+ u8 grassAnimCounterHi;
+ u8 grassAnimDisabled;
+ u8 scrollIndicatorArrowPairId;
+};
+
+static EWRAM_DATA struct TeachyTvCtrlBlk sStaticResources = {0};
+static EWRAM_DATA struct TeachyTvBuf * sResources = NULL;
+
+static void TTVcmd_TransitionRenderBg2TeachyTvGraphicInitNpcPos(u8 taskId);
+static void TTVcmd_ClearBg2TeachyTvGraphic(u8 taskId);
+static void TTVcmd_NpcMoveAndSetupTextPrinter(u8 taskId);
+static void TTVcmd_IdleIfTextPrinterIsActive(u8 taskId);
+static void TTVcmd_TextPrinterSwitchStringByOptionChosen(u8 taskId);
+static void TTVcmd_TextPrinterSwitchStringByOptionChosen2(u8 taskId);
+static void TTVcmd_IdleIfTextPrinterIsActive2(u8 taskId);
+static void TTVcmd_EraseTextWindowIfKeyPressed(u8 taskId);
+static void TTVcmd_StartAnimNpcWalkIntoGrass(u8 taskId);
+static void TTVcmd_DudeMoveUp(u8 taskId);
+static void TTVcmd_DudeMoveRight(u8 taskId);
+static void TTVcmd_DudeTurnLeft(u8 taskId);
+static void TTVcmd_DudeMoveLeft(u8 taskId);
+static void TTVcmd_RenderAndRemoveBg1EndGraphic(u8 taskId);
+static void TTVcmd_TaskBattleOrFadeByOptionChosen(u8 taskId);
+static void TeachyTvCallback(void);
+static void TeachyTvMainCallback(void);
+static void TeachyTvVblankHandler(void);
+static void TeachyTvCreateAndRenderRbox(void);
+static void TeachyTvInitIo(void);
+static u8 TeachyTvSetupObjEventAndOam(void);
+static void TeachyTvSetupPostBattleWindowAndObj(u8);
+static u8 TeachyTvSetupWindow(void);
+static void TeachyTvSetupScrollIndicatorArrowPair(void);
+static void TeachyTvSetWindowRegs(void);
+static void TeachyTvSetupBg(void);
+static void TeachyTvLoadGraphic(void);
+static void TeachyTvPostBattleFadeControl(u8);
+static void TeachyTvOptionListController(u8);
+static void TeachyTvAudioByInput(s32, bool8, struct ListMenu *);
+static void TeachyTvQuitFadeControlAndTaskDel(u8 taskId);
+static void TeachyTvRenderMsgAndSwitchClusterFuncs(u8 taskId);
+static void TeachyTvClearBg1EndGraphicText(void);
+static void TTVcmd_End(u8 taskId);
+static void TeachyTvSetupBagItemsByOptionChosen(void);
+static void TeachyTvPrepBattle(u8 taskId);
+static void TeachyTvGrassAnimationMain(u8 taskId, s16 x, s16 y, u8 subpriority, bool8 mode);
+static void TeachyTvLoadBg3Map(u16 *);
+static u8 TeachyTvGrassAnimationCheckIfNeedsToGenerateGrassObj(s16 x, s16 y);
+static void TeachyTvGrassAnimationObjCallback(struct Sprite *sprite);
+static void TeachyTvRestorePlayerPartyCallback(void);
+static void TeachyTvPreBattleAnimAndSetBattleCallback(u8 taskId);
+static void TeachyTvLoadMapTilesetToBuffer(struct Tileset *ts, u8 *dstBuffer, u16 size);
+static void TeachyTvPushBackNewMapPalIndexArrayEntry(const struct MapData *mStruct, u16 *buf1, u8 *palIndexArray, u16 mapEntry, u16 offset);
+static void TeachyTvComputeMapTilesFromTilesetAndMetaTiles(u16 *metaTilesArray, u8 *blockBuf, u8 *tileset);
+static void TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(u8 *blockBuf, u8 *tileset, u8 metaTile);
+static u16 TeachyTvComputePalIndexArrayEntryByMetaTile(u8 *palIndexArrayBuf, u16 metaTile);
+static void TeachyTvLoadMapPalette(const struct MapData * mStruct, const u8 *palIndexArray);
+
+static const struct BgTemplate sBgTemplates[] =
+{
+ {
+ .bg = 0,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0x000,
+ },
+ {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000,
+ },
+ {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 29,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x000,
+ },
+ {
+ .bg = 3,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 28,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x000,
+ },
+};
+
+static const struct WindowTemplate sWindowTemplates[] =
+{
+ {
+ .bg = 1,
+ .tilemapLeft = 2,
+ .tilemapTop = 15,
+ .width = 26,
+ .height = 4,
+ .paletteNum = 0x3,
+ .baseBlock = 0x0EA,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 4,
+ .tilemapTop = 1,
+ .width = 22,
+ .height = 12,
+ .paletteNum = 0x3,
+ .baseBlock = 0x152,
+ },
+ DUMMY_WIN_TEMPLATE,
+};
+
+static const struct ListMenuItem sListMenuItems[] =
+{
+ {
+ .label = gTeachyTvString_TeachBattle,
+ .index = TTVSCR_BATTLE
+ },
+ {
+ .label = gTeachyTvString_StatusProblems,
+ .index = TTVSCR_STATUS
+ },
+ {
+ .label = gTeachyTvString_TypeMatchups,
+ .index = TTVSCR_MATCHUPS
+ },
+ {
+ .label = gTeachyTvString_CatchPkmn,
+ .index = TTVSCR_CATCHING
+ },
+ {
+ .label = gTeachyTvString_AboutTMs,
+ .index = TTVSCR_TMS
+ },
+ {
+ .label = gTeachyTvString_RegisterItem,
+ .index = TTVSCR_REGISTER
+ },
+
+ {
+ .label = gTeachyTvString_Cancel,
+ .index = -2
+ },
+};
+
+static const struct ListMenuItem sListMenuItems_NoTMCase[] =
+{
+ {
+ .label = gTeachyTvString_TeachBattle,
+ .index = TTVSCR_BATTLE
+ },
+ {
+ .label = gTeachyTvString_StatusProblems,
+ .index = TTVSCR_STATUS
+ },
+ {
+ .label = gTeachyTvString_TypeMatchups,
+ .index = TTVSCR_MATCHUPS
+ },
+ {
+ .label = gTeachyTvString_CatchPkmn,
+ .index = TTVSCR_CATCHING
+ },
+ {
+ .label = gTeachyTvString_Cancel,
+ .index = -2
+ },
+};
+
+static const struct ListMenuTemplate sListMenuTemplate =
+{
+ .items = sListMenuItems,
+ .moveCursorFunc = NULL,
+ .itemPrintFunc = NULL,
+ .totalItems = 7,
+ .maxShowed = 6,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 6,
+ .cursorPal = 0x1,
+ .fillValue = 0x0,
+ .cursorShadowPal = 0x2,
+ .lettersSpacing = 0x0,
+ .itemVerticalPadding = 0x0,
+ .scrollMultiple = 0x1,
+ .fontId = 0x2,
+ .cursorKind = 0x0,
+};
+
+static const struct ScrollArrowsTemplate sScrollIndicatorArrowPair =
+{
+ .firstArrowType = 0x2,
+ .firstX = 0x78,
+ .firstY = 0xC,
+ .secondArrowType = 0x3,
+ .secondX = 0x78,
+ .secondY = 0x64,
+ .fullyUpThreshold = 0,
+ .fullyDownThreshold = 1,
+ .tileTag = 0x800,
+ .palTag = 0x800,
+ .palNum = 0x0,
+};
+
+static const u8 sWhereToReturnToFromBattle[] =
+{
+ 12,
+ 12,
+ 12,
+ 12,
+ 9,
+ 9
+};
+
+static void (* const sBattleScript[])(u8) =
+{
+ TTVcmd_TransitionRenderBg2TeachyTvGraphicInitNpcPos,
+ TTVcmd_ClearBg2TeachyTvGraphic,
+ TTVcmd_NpcMoveAndSetupTextPrinter,
+ TTVcmd_IdleIfTextPrinterIsActive,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_StartAnimNpcWalkIntoGrass,
+ TTVcmd_DudeMoveUp,
+ TTVcmd_DudeMoveRight,
+ TTVcmd_TaskBattleOrFadeByOptionChosen,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen2,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_DudeTurnLeft,
+ TTVcmd_DudeMoveLeft,
+ TTVcmd_RenderAndRemoveBg1EndGraphic,
+ TTVcmd_End,
+};
+
+static void (* const sStatusScript[])(u8) =
+{
+ TTVcmd_TransitionRenderBg2TeachyTvGraphicInitNpcPos,
+ TTVcmd_ClearBg2TeachyTvGraphic,
+ TTVcmd_NpcMoveAndSetupTextPrinter,
+ TTVcmd_IdleIfTextPrinterIsActive,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_StartAnimNpcWalkIntoGrass,
+ TTVcmd_DudeMoveUp,
+ TTVcmd_DudeMoveRight,
+ TTVcmd_TaskBattleOrFadeByOptionChosen,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen2,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_DudeTurnLeft,
+ TTVcmd_DudeMoveLeft,
+ TTVcmd_RenderAndRemoveBg1EndGraphic,
+ TTVcmd_End,
+};
+
+static void (* const sMatchupsScript[])(u8) =
+{
+ TTVcmd_TransitionRenderBg2TeachyTvGraphicInitNpcPos,
+ TTVcmd_ClearBg2TeachyTvGraphic,
+ TTVcmd_NpcMoveAndSetupTextPrinter,
+ TTVcmd_IdleIfTextPrinterIsActive,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_StartAnimNpcWalkIntoGrass,
+ TTVcmd_DudeMoveUp,
+ TTVcmd_DudeMoveRight,
+ TTVcmd_TaskBattleOrFadeByOptionChosen,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen2,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_DudeTurnLeft,
+ TTVcmd_DudeMoveLeft,
+ TTVcmd_RenderAndRemoveBg1EndGraphic,
+ TTVcmd_End,
+};
+
+static void (* const sCatchingScript[])(u8) =
+{
+ TTVcmd_TransitionRenderBg2TeachyTvGraphicInitNpcPos,
+ TTVcmd_ClearBg2TeachyTvGraphic,
+ TTVcmd_NpcMoveAndSetupTextPrinter,
+ TTVcmd_IdleIfTextPrinterIsActive,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_StartAnimNpcWalkIntoGrass,
+ TTVcmd_DudeMoveUp,
+ TTVcmd_DudeMoveRight,
+ TTVcmd_TaskBattleOrFadeByOptionChosen,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen2,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_DudeTurnLeft,
+ TTVcmd_DudeMoveLeft,
+ TTVcmd_RenderAndRemoveBg1EndGraphic,
+ TTVcmd_End,
+};
+
+static void (* const sTMsScript[])(u8) =
+{
+ TTVcmd_TransitionRenderBg2TeachyTvGraphicInitNpcPos,
+ TTVcmd_ClearBg2TeachyTvGraphic,
+ TTVcmd_NpcMoveAndSetupTextPrinter,
+ TTVcmd_IdleIfTextPrinterIsActive,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_TaskBattleOrFadeByOptionChosen,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen2,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_DudeTurnLeft,
+ TTVcmd_DudeMoveLeft,
+ TTVcmd_RenderAndRemoveBg1EndGraphic,
+ TTVcmd_End,
+};
+
+static void (* const sRegisterKeyItemScript[])(u8) =
+{
+ TTVcmd_TransitionRenderBg2TeachyTvGraphicInitNpcPos,
+ TTVcmd_ClearBg2TeachyTvGraphic,
+ TTVcmd_NpcMoveAndSetupTextPrinter,
+ TTVcmd_IdleIfTextPrinterIsActive,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_TaskBattleOrFadeByOptionChosen,
+ TTVcmd_TextPrinterSwitchStringByOptionChosen2,
+ TTVcmd_IdleIfTextPrinterIsActive2,
+ TTVcmd_EraseTextWindowIfKeyPressed,
+ TTVcmd_DudeTurnLeft,
+ TTVcmd_DudeMoveLeft,
+ TTVcmd_RenderAndRemoveBg1EndGraphic,
+ TTVcmd_End,
+};
+
+static void TeachyTvCallback(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ do_scheduled_bg_tilemap_copies_to_vram();
+ UpdatePaletteFade();
+}
+
+static void TeachyTvVblankHandler(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+void InitTeachyTvController(u8 mode, MainCallback cb)
+{
+ sStaticResources.mode = mode;
+ sStaticResources.callback = cb;
+ if (mode == 0)
+ {
+ sStaticResources.scrollOffset = 0;
+ sStaticResources.selectedRow = 0;
+ sStaticResources.whichScript = TTVSCR_BATTLE;
+ }
+ if (mode == 1)
+ {
+ sStaticResources.mode = 0;
+ }
+ SetMainCallback2(TeachyTvMainCallback);
+}
+
+void CB2_ReturnToTeachyTV(void)
+{
+ if (sStaticResources.mode == 1)
+ InitTeachyTvController(1, sStaticResources.callback);
+ else
+ InitTeachyTvController(2, sStaticResources.callback);
+}
+
+void SetTeachyTvControllerModeToResume(void)
+{
+ sStaticResources.mode = 1;
+}
+
+static void TeachyTvMainCallback(void)
+{
+ u8 taskId;
+ struct Task *taskAddr;
+
+ switch (gMain.state)
+ {
+ case 0:
+ sResources = AllocZeroed(sizeof(struct TeachyTvBuf));
+ sResources->savedCallback = NULL;
+ sResources->grassAnimDisabled = 0;
+ sResources->scrollIndicatorArrowPairId = 0xFF;
+ VblankHblankHandlerSetZero();
+ clear_scheduled_bg_copies_to_vram();
+ ScanlineEffect_Stop();
+ FreeAllSpritePalettes();
+ ResetPaletteFade();
+ ResetSpriteData();
+ ResetTasks();
+ TeachyTvSetupBg();
+ TeachyTvLoadGraphic();
+ ++gMain.state;
+ break;
+ case 1:
+ if (free_temp_tile_data_buffers_if_possible() == TRUE)
+ return;
+ TeachyTvCreateAndRenderRbox();
+ TeachyTvInitIo();
+ if (sStaticResources.mode == 2)
+ {
+ taskId = CreateTask(TeachyTvPostBattleFadeControl, 0);
+ gTasks[taskId].data[1] = TeachyTvSetupObjEventAndOam();
+ TeachyTvSetupPostBattleWindowAndObj(taskId);
+ }
+ else
+ {
+ taskId = CreateTask(TeachyTvOptionListController, 0);
+ gTasks[taskId].data[0] = TeachyTvSetupWindow();
+ gTasks[taskId].data[1] = TeachyTvSetupObjEventAndOam();
+ TeachyTvSetupScrollIndicatorArrowPair();
+ PlayNewMapMusic(BGM_FRLG_TEACHY_TV);
+ TeachyTvSetWindowRegs();
+ }
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ schedule_bg_copy_tilemap_to_vram(2);
+ schedule_bg_copy_tilemap_to_vram(3);
+ sub_812B1E0(9); // help system something
+ BlendPalettes(0xFFFFFFFF, 0x10, 0);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0);
+ SetVBlankCallback(TeachyTvVblankHandler);
+ SetMainCallback2(TeachyTvCallback);
+ break;
+ }
+}
+
+static void TeachyTvSetupBg(void)
+{
+ InitBgReg();
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, sBgTemplates, 4);
+ SetBgTilemapBuffer(1, sResources->buffer1);
+ SetBgTilemapBuffer(2, sResources->buffer2);
+ SetBgTilemapBuffer(3, sResources->buffer3);
+ SetGpuReg(REG_OFFSET_DISPCNT, 0x3040);
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+ ChangeBgX(3, 0x1000, 2);
+ ChangeBgY(3, 0x2800, 1);
+ sResources->grassAnimCounterLo = 0;
+ sResources->grassAnimCounterHi = 3;
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+}
+
+static void TeachyTvLoadGraphic(void)
+{
+ u16 src = RGB_BLACK;
+ reset_temp_tile_data_buffers();
+ decompress_and_copy_tile_data_to_vram(1, gUnknown_8E86240, 0, 0, 0);
+ LZDecompressWram(gUnknown_8E86BE8, sResources->buffer1);
+ LZDecompressWram(gUnknown_8E86D6C, sResources->buffer4);
+ LoadCompressedPalette(gUnknown_8E86F98, 0, 0x80);
+ LoadPalette(&src, 0, sizeof(src));
+ LoadSpritePalette(&gUnknown_83A5348);
+ TeachyTvLoadBg3Map(sResources->buffer3);
+}
+
+static void TeachyTvCreateAndRenderRbox(void)
+{
+ InitWindows(sWindowTemplates);
+ DeactivateAllTextPrinters();
+ FillWindowPixelBuffer(0, 0xCC);
+ PutWindowTilemap(0);
+ PutWindowTilemap(1);
+ CopyWindowToVram(0, 2);
+}
+
+static u8 TeachyTvSetupWindow(void)
+{
+ gMultiuseListMenuTemplate = sListMenuTemplate;
+ gMultiuseListMenuTemplate.windowId = 1;
+ gMultiuseListMenuTemplate.moveCursorFunc = TeachyTvAudioByInput;
+ if (!CheckBagHasItem(ITEM_TM_CASE, 1))
+ {
+ gMultiuseListMenuTemplate.items = sListMenuItems_NoTMCase;
+ gMultiuseListMenuTemplate.totalItems = 5;
+ gMultiuseListMenuTemplate.maxShowed = 5;
+ gMultiuseListMenuTemplate.upText_Y = (gMultiuseListMenuTemplate.upText_Y + 8) & 0xF;
+ }
+ return ListMenuInit(
+ &gMultiuseListMenuTemplate,
+ sStaticResources.scrollOffset,
+ sStaticResources.selectedRow
+ );
+}
+
+static void TeachyTvSetupScrollIndicatorArrowPair(void)
+{
+ if (!CheckBagHasItem(ITEM_TM_CASE, 1))
+ {
+ struct TeachyTvBuf * temp = sResources;
+ temp->scrollIndicatorArrowPairId = 0xFF;
+ }
+ else
+ {
+ sResources->scrollIndicatorArrowPairId = AddScrollIndicatorArrowPair(&sScrollIndicatorArrowPair, &(sStaticResources.scrollOffset));
+ }
+}
+
+static void TeachyTvRemoveScrollIndicatorArrowPair(void)
+{
+ if (sResources->scrollIndicatorArrowPairId != 0xFF)
+ {
+ RemoveScrollIndicatorArrowPair(sResources->scrollIndicatorArrowPairId);
+ sResources->scrollIndicatorArrowPairId = 0xFF;
+ }
+}
+
+static void TeachyTvAudioByInput(s32 notUsed, bool8 play, struct ListMenu *notUsedAlt)
+{
+ if (play != TRUE)
+ PlaySE(SE_SELECT);
+}
+
+static void TeachyTvInitIo(void)
+{
+ SetGpuReg(REG_OFFSET_WININ, 0x3F);
+ SetGpuReg(REG_OFFSET_WINOUT, 0x1F);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0xCC);
+ SetGpuReg(REG_OFFSET_BLDY, 0x5);
+}
+
+static u8 TeachyTvSetupObjEventAndOam(void)
+{
+ u8 objId = AddPseudoEventObject(90, SpriteCallbackDummy, 0, 0, 8);
+ gSprites[objId].oam.priority = 2;
+ gSprites[objId].invisible = 1;
+ return objId;
+}
+
+static void TeachyTvSetSpriteCoordsAndSwitchFrame(u8 objId, u16 x, u16 y, u8 frame)
+{
+ gSprites[objId].pos2.x = x;
+ gSprites[objId].pos2.y = y;
+ gSprites[objId].invisible = 0;
+ StartSpriteAnim(&gSprites[objId], frame);
+}
+
+static void TeachyTvSetWindowRegs(void)
+{
+ SetGpuReg(REG_OFFSET_WIN0V, 0xC64);
+ SetGpuReg(REG_OFFSET_WIN0H, 0x1CD4);
+}
+
+static void TeachyTvClearWindowRegs(void)
+{
+ SetGpuReg(REG_OFFSET_WIN0V, 0x0);
+ SetGpuReg(REG_OFFSET_WIN0H, 0x0);
+}
+
+static void TeachyTvBg2AnimController(void)
+{
+ u16 * tilemapBuffer = GetBgTilemapBuffer(2);
+ u8 i, j;
+ for (i = 1; i < 13; i++)
+ {
+ for (j = 2; j < 28; j++)
+ {
+ tilemapBuffer[32 * i + j] = ((Random() & 3) << 10) + 0x301F;
+ }
+ }
+ schedule_bg_copy_tilemap_to_vram(2);
+}
+
+static void TeachyTvSetupPostBattleWindowAndObj(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ struct Sprite *objAddr = &gSprites[data[1]];
+
+ ClearWindowTilemap(1);
+ TeachyTvClearWindowRegs();
+ switch (sStaticResources.whichScript)
+ {
+ case TTVSCR_BATTLE:
+ case TTVSCR_STATUS:
+ case TTVSCR_MATCHUPS:
+ case TTVSCR_CATCHING:
+ TeachyTvSetSpriteCoordsAndSwitchFrame(data[1], 0x78, 0x38, 0);
+ ChangeBgX(3, 0x3000, 1);
+ ChangeBgY(3, 0x3000, 2);
+ sResources->grassAnimCounterLo += 3;
+ sResources->grassAnimCounterHi -= 3;
+ break;
+ case TTVSCR_TMS:
+ case TTVSCR_REGISTER:
+ TeachyTvSetSpriteCoordsAndSwitchFrame(data[1], 0x78, 0x38, 0);
+ break;
+ }
+
+ data[4] = 0;
+ data[5] = 0;
+ TeachyTvGrassAnimationMain(taskId, objAddr->pos2.x, objAddr->pos2.y, 0, 1);
+}
+
+static void TeachyTvInitTextPrinter(const u8 *text)
+{
+ gTextFlags.autoScroll = 0;
+ AddTextPrinterParameterized2(0, 4, text, GetTextSpeedSetting(), 0, 1, 0xC, 3);
+}
+
+static void TeachyTvFree(void)
+{
+ Free(sResources);
+ sResources = NULL;
+ FreeAllWindowBuffers();
+}
+
+static void TeachyTvQuitBeginFade(u8 taskId)
+{
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0);
+ gTasks[taskId].func = TeachyTvQuitFadeControlAndTaskDel;
+}
+
+static void TeachyTvQuitFadeControlAndTaskDel(u8 taskId)
+{
+ if (!(gPaletteFade.active))
+ {
+ if (sResources->savedCallback != NULL)
+ {
+ SetMainCallback2(sResources->savedCallback);
+ }
+ else
+ {
+ sub_8055DC4();
+ SetMainCallback2(sStaticResources.callback);
+ }
+ TeachyTvFree();
+ DestroyTask(taskId);
+ }
+}
+
+static void TeachyTvOptionListController(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ s32 input;
+
+ TeachyTvBg2AnimController();
+ if (!gPaletteFade.active)
+ {
+ input = ListMenuHandleInput(data[0]);
+ ListMenuGetScrollAndRow(data[0], &sStaticResources.scrollOffset, &sStaticResources.selectedRow);
+ if ((JOY_NEW(SELECT_BUTTON) && sStaticResources.callback != ReturnToBagFromKeyItem))
+ {
+ PlaySE(SE_SELECT);
+ TeachyTvQuitBeginFade(taskId);
+ }
+ else
+ {
+ switch (input)
+ {
+ case -1:
+ break;
+ case -2:
+ PlaySE(SE_SELECT);
+ TeachyTvQuitBeginFade(taskId);
+ break;
+ default:
+ PlaySE(SE_SELECT);
+ sStaticResources.whichScript = input;
+ DestroyListMenu(data[0], &sStaticResources.scrollOffset, &sStaticResources.selectedRow);
+ TeachyTvClearWindowRegs();
+ ClearWindowTilemap(1);
+ schedule_bg_copy_tilemap_to_vram(0);
+ TeachyTvRemoveScrollIndicatorArrowPair();
+ data[3] = 0;
+ data[2] = 0;
+ gTasks[taskId].func = TeachyTvRenderMsgAndSwitchClusterFuncs;
+ break;
+ }
+ }
+ }
+}
+
+static void TTVcmd_TransitionRenderBg2TeachyTvGraphicInitNpcPos(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ TeachyTvBg2AnimController();
+ if (++data[2] > 63)
+ {
+ CopyToBgTilemapBufferRect_ChangePalette(2, sResources->buffer4, 0, 0, 0x20, 0x20, 0x11);
+ TeachyTvSetSpriteCoordsAndSwitchFrame(data[1], 8, 0x38, 7);
+ schedule_bg_copy_tilemap_to_vram(2);
+ data[2] = 0;
+ ++data[3];
+ PlayNewMapMusic(BGM_FRLG_FOLLOW_ME);
+ }
+}
+
+static void TTVcmd_ClearBg2TeachyTvGraphic(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ if (++data[2] == 134)
+ {
+ FillBgTilemapBufferRect_Palette0(2, 0, 2, 1, 0x1A, 0xC);
+ schedule_bg_copy_tilemap_to_vram(2);
+ data[2] = 0;
+ ++data[3];
+ }
+}
+
+static void TTVcmd_NpcMoveAndSetupTextPrinter(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ struct Sprite * spriteAddr = &gSprites[data[1]];
+ if (data[2] != 35)
+ ++data[2];
+ else {
+ if (spriteAddr->pos2.x == 0x78)
+ {
+ StartSpriteAnim(&gSprites[data[1]], 0);
+ TeachyTvInitTextPrinter(gTeachyTvText_PokeDudeSaysHello);
+ data[2] = 0;
+ ++data[3];
+ }
+ else
+ ++spriteAddr->pos2.x;
+ }
+}
+
+static void TTVcmd_IdleIfTextPrinterIsActive(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ if (!sub_80BF518(0))
+ ++data[3];
+}
+
+static void TeachyTvRenderMsgAndSwitchClusterFuncs(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ if (JOY_NEW(B_BUTTON))
+ {
+ sResources->grassAnimDisabled = 1;
+ TeachyTvSetSpriteCoordsAndSwitchFrame(data[1], 0, 0, 0);
+ FillWindowPixelBuffer(0, 0xCC);
+ CopyWindowToVram(0, 2);
+ TeachyTvClearBg1EndGraphicText();
+ data[2] = 0;
+ data[3] = 0;
+ gTasks[taskId].func = TTVcmd_End;
+ }
+ else
+ {
+ static void (* const * const array[])(u8) =
+ {
+ sBattleScript,
+ sStatusScript,
+ sMatchupsScript,
+ sCatchingScript,
+ sTMsScript,
+ sRegisterKeyItemScript,
+ };
+ void (*const *cluster)(u8) = array[sStaticResources.whichScript];
+ cluster[data[3]](taskId);
+ }
+}
+
+static void TTVcmd_TextPrinterSwitchStringByOptionChosen(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ static const u8 *const texts[] = {
+ gTeachyTvText_BattleScript1,
+ gTeachyTvText_StatusScript1,
+ gTeachyTvText_MatchupsScript1,
+ gTeachyTvText_CatchingScript1,
+ gTeachyTvText_TMsScript1,
+ gTeachyTvText_RegisterScript1,
+ };
+ TeachyTvInitTextPrinter(texts[sStaticResources.whichScript]);
+ ++data[3];
+}
+
+static void TTVcmd_TextPrinterSwitchStringByOptionChosen2(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ static const u8 *const texts[] =
+ {
+ gTeachyTvText_BattleScript2,
+ gTeachyTvText_StatusScript2,
+ gTeachyTvText_MatchupsScript2,
+ gTeachyTvText_CatchingScript2,
+ gTeachyTvText_TMsScript2,
+ gTeachyTvText_RegisterScript2,
+ };
+ TeachyTvInitTextPrinter(texts[sStaticResources.whichScript]);
+ ++data[3];
+}
+
+static const u16 sBg1EndGraphic[] =
+{
+ 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
+ 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8,
+};
+
+static const struct Subsprite sSubspriteArray[] =
+{
+ {
+ .x = -0x8,
+ .y = -0x8,
+ .shape = 0x1,
+ .size = 0x0,
+ .tileOffset = 0x0,
+ .priority = 0x3,
+ },
+ {
+ .x = -0x8,
+ .y = 0x0,
+ .shape = 0x1,
+ .size = 0x0,
+ .tileOffset = 0x2,
+ .priority = 0x2,
+ },
+};
+
+static const struct SubspriteTable sSubspriteTableArray[] =
+{
+ {
+ .subspriteCount = 0,
+ .subsprites = NULL,
+ },
+ {
+ .subspriteCount = 2,
+ .subsprites = sSubspriteArray,
+ },
+};
+
+static const u8 sGrassAnimArray[] =
+{
+ 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 0, 0,
+};
+
+static void TTVcmd_IdleIfTextPrinterIsActive2(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ if (!sub_80BF518(0))
+ ++data[3];
+}
+
+static void TTVcmd_EraseTextWindowIfKeyPressed(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ FillWindowPixelBuffer(0, 0xCC);
+ CopyWindowToVram(0, 2);
+ ++data[3];
+ }
+}
+
+static void TTVcmd_StartAnimNpcWalkIntoGrass(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ StartSpriteAnim(&gSprites[data[1]], 5);
+ data[2] = 0;
+ data[4] = 0;
+ data[5] = 1;
+ ++data[3];
+}
+
+static void TTVcmd_DudeMoveUp(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ struct Sprite *obj = &gSprites[data[1]];
+ ChangeBgY(3, 0x100, 2);
+ if (!(++data[2] & 0xF))
+ {
+ --sResources->grassAnimCounterHi;
+ TeachyTvGrassAnimationMain(taskId, obj->pos2.x, obj->pos2.y, 0, 0);
+ }
+ if (data[2] == 48)
+ {
+ data[2] = 0;
+ data[4] = -1;
+ data[5] = 0;
+ StartSpriteAnim(obj, 7);
+ ++data[3];
+ }
+}
+
+static void TTVcmd_DudeMoveRight(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ struct Sprite *obj = &gSprites[data[1]];
+ ChangeBgX(3, 0x100, 1);
+ if (!(++data[2] & 0xF))
+ ++sResources->grassAnimCounterLo;
+ if (!((data[2] + 8) & 0xF))
+ TeachyTvGrassAnimationMain(taskId, obj->pos2.x + 8, obj->pos2.y, 0, 0);
+ if (data[2] == 0x30)
+ {
+ data[2] = 0;
+ data[4] = 0;
+ data[5] = 0;
+ StartSpriteAnim(obj, 3);
+ ++data[3];
+ }
+}
+
+static void TTVcmd_DudeTurnLeft(u8 taskId)
+{
+
+ s16 *data = gTasks[taskId].data;
+ struct Sprite *objAddr = &gSprites[data[1]];
+ StartSpriteAnim(objAddr, 6);
+ ++data[3];
+ data[4] = 0;
+ data[5] = 0;
+ TeachyTvGrassAnimationMain(taskId, objAddr->pos2.x, objAddr->pos2.y, 0, 0);
+}
+
+static void TTVcmd_DudeMoveLeft(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ struct Sprite *objAddr = &gSprites[data[1]];
+
+ if (!(objAddr->pos2.x & 0xF))
+ TeachyTvGrassAnimationMain(taskId, objAddr->pos2.x - 8, objAddr->pos2.y, 0, 0);
+ if (objAddr->pos2.x == 8)
+ ++data[3];
+ else
+ --objAddr->pos2.x;
+}
+
+static void TTVcmd_RenderAndRemoveBg1EndGraphic(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ if (!data[2])
+ {
+ CopyToBgTilemapBufferRect_ChangePalette(1, sBg1EndGraphic, 20, 10, 8, 2, 0x11);
+ schedule_bg_copy_tilemap_to_vram(1);
+ }
+ if (++data[2] > 126)
+ {
+ TeachyTvClearBg1EndGraphicText();
+ data[2] = 0;
+ ++data[3];
+ }
+}
+
+static void TeachyTvClearBg1EndGraphicText(void)
+{
+ FillBgTilemapBufferRect_Palette0(1, 0, 20, 10, 8, 2);
+ schedule_bg_copy_tilemap_to_vram(1);
+}
+
+static void TTVcmd_End(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ if (data[2] == 0)
+ PlayNewMapMusic(BGM_FRLG_TEACHY_TV);
+ TeachyTvBg2AnimController();
+ if (++data[2] > 63)
+ {
+ data[2] = 0;
+ data[3] = 0;
+ data[0] = TeachyTvSetupWindow();
+ gTasks[taskId].func = TeachyTvOptionListController;
+ PutWindowTilemap(0);
+ TeachyTvSetupScrollIndicatorArrowPair();
+ TeachyTvSetWindowRegs();
+ schedule_bg_copy_tilemap_to_vram(0);
+ ChangeBgX(3, 0x0, 0);
+ ChangeBgY(3, 0x0, 0);
+ ChangeBgX(3, 0x1000, 2);
+ ChangeBgY(3, 0x2800, 1);
+ sResources->grassAnimCounterLo = 0;
+ sResources->grassAnimCounterHi = 3;
+ sResources->grassAnimDisabled = 0;
+ }
+}
+
+static void TTVcmd_TaskBattleOrFadeByOptionChosen(u8 taskId)
+{
+ switch (sStaticResources.whichScript)
+ {
+ case TTVSCR_BATTLE:
+ case TTVSCR_STATUS:
+ case TTVSCR_MATCHUPS:
+ case TTVSCR_CATCHING:
+ TeachyTvPrepBattle(taskId);
+ break;
+ case TTVSCR_TMS:
+ case TTVSCR_REGISTER:
+ sResources->savedCallback = TeachyTvSetupBagItemsByOptionChosen;
+ TeachyTvQuitBeginFade(taskId);
+ break;
+ }
+}
+
+static void TeachyTvSetupBagItemsByOptionChosen(void)
+{
+ if (sStaticResources.whichScript == TTVSCR_TMS)
+ sub_810B108(10);
+ else
+ sub_810B108(9);
+}
+
+static void TeachyTvPostBattleFadeControl(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ if (!(gPaletteFade.active))
+ {
+ data[3] = sWhereToReturnToFromBattle[sStaticResources.whichScript];
+ gTasks[taskId].func = TeachyTvRenderMsgAndSwitchClusterFuncs;
+ }
+}
+
+static void TeachyTvGrassAnimationMain(u8 taskId, s16 x, s16 y, u8 subpriority, bool8 mode)
+{
+ struct Sprite *obj;
+ u8 spriteId;
+
+ if (sResources->grassAnimDisabled != 1 && TeachyTvGrassAnimationCheckIfNeedsToGenerateGrassObj(x - 0x10, y))
+ {
+ spriteId = CreateSprite(gUnknown_83A0010[4], 0, 0, subpriority);
+ obj = &gSprites[spriteId];
+ obj->pos2.x = x;
+ obj->pos2.y = y + 8;
+ obj->callback = TeachyTvGrassAnimationObjCallback;
+ obj->data[0] = taskId;
+ if (mode == 1)
+ {
+ SeekSpriteAnim(obj, 4);
+ obj->oam.priority = 2;
+ }
+ else
+ {
+ SetSubspriteTables(obj, sSubspriteTableArray);
+ obj->subspriteTableNum = 0;
+ obj->subspriteMode = 1;
+ }
+ }
+}
+
+static void TeachyTvGrassAnimationObjCallback(struct Sprite *sprite)
+{
+ s16 diff1, diff2;
+ s16 *data = gTasks[sprite->data[0]].data;
+ struct Sprite *objAddr = &gSprites[data[1]];
+
+ if (sResources->grassAnimDisabled == 1)
+ DestroySprite(sprite);
+ else
+ {
+ if (sprite->animCmdIndex == 0)
+ sprite->subspriteTableNum = 1;
+ else
+ sprite->subspriteTableNum = 0;
+ sprite->pos2.x += data[4];
+ sprite->pos2.y += data[5];
+ if (sprite->animEnded)
+ {
+ sprite->subpriority = 0;
+ diff1 = sprite->pos2.x - objAddr->pos2.x;
+ diff2 = sprite->pos2.y - objAddr->pos2.y;
+ if (diff1 <= -16 || diff1 >= 16 || diff2 <= -16 || diff2 >= 24)
+ DestroySprite(sprite);
+ }
+ }
+}
+
+static u8 TeachyTvGrassAnimationCheckIfNeedsToGenerateGrassObj(s16 x, s16 y)
+{
+ const u8 * arr;
+ struct TeachyTvBuf *ptr;
+ int high, low;
+ if ((x < 0) || (y < 0))
+ return 0;
+ arr = sGrassAnimArray;
+ high = ((y >> 4) + sResources->grassAnimCounterHi) << 4;
+ low = ((x >> 4) + sResources->grassAnimCounterLo);
+ return arr[high+low];
+}
+
+static void TeachyTvPrepBattle(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ TeachyTvFree();
+ gSpecialVar_0x8004 = sStaticResources.whichScript;
+ gMain.savedCallback = TeachyTvRestorePlayerPartyCallback;
+ SavePlayerParty();
+ sub_8159F40();
+ PlayMapChosenOrBattleBGM(MUS_DUMMY);
+ if (sStaticResources.whichScript == TTVSCR_BATTLE)
+ data[6] = 9;
+ else
+ data[6] = 8;
+ data[7] = 0;
+ gTasks[taskId].func = TeachyTvPreBattleAnimAndSetBattleCallback;
+}
+
+static void TeachyTvPreBattleAnimAndSetBattleCallback(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ switch (data[7])
+ {
+ case 0:
+ sub_80D08B8(data[6]);
+ ++data[7];
+ break;
+ case 1:
+ if (sub_80D08F8())
+ {
+ SetMainCallback2(sub_800FD9C);
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+static void TeachyTvRestorePlayerPartyCallback(void)
+{
+ LoadPlayerParty();
+ if (gBattleOutcome == B_OUTCOME_DREW)
+ SetTeachyTvControllerModeToResume();
+ else
+ PlayNewMapMusic(BGM_FRLG_FOLLOW_ME);
+ CB2_ReturnToTeachyTV();
+}
+
+static void TeachyTvLoadBg3Map(u16 *buffer)
+{
+ u16 * bgTilesBuffer;
+ u8 * mapTilesRowBuffer;
+ u16 i, j, k;
+ u16 currentBlockIdx;
+ void * tilesetsBuffer;
+ void * palIndicesBuffer;
+ u16 numMapTilesRows = 0;
+ const struct MapData *layout = &Route1_Layout;
+ u16 * blockIndicesBuffer = AllocZeroed(0x800);
+ tilesetsBuffer = AllocZeroed(0x8000);
+ palIndicesBuffer = Alloc(16);
+ memset(palIndicesBuffer, 0xFF, 16);
+
+ TeachyTvLoadMapTilesetToBuffer(layout->primaryTileset, tilesetsBuffer, 0x280);
+ TeachyTvLoadMapTilesetToBuffer(layout->secondaryTileset, tilesetsBuffer + 0x5000, 0x180);
+
+ for (i = 0; i < 9; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+ currentBlockIdx = layout->map[8 + (i + 6) * layout->width + j] & 0x3FF;
+ for (k = 0; k < (i << 4) + j; k++)
+ {
+ if (blockIndicesBuffer[k] == 0)
+ break;
+ if (blockIndicesBuffer[k] == currentBlockIdx)
+ break;
+ }
+ if (blockIndicesBuffer[k] == 0)
+ {
+ blockIndicesBuffer[k] = currentBlockIdx;
+ numMapTilesRows++;
+ }
+ TeachyTvPushBackNewMapPalIndexArrayEntry(layout, &buffer[64 * i + 2 * j], palIndicesBuffer, currentBlockIdx, k);
+ }
+ }
+
+ bgTilesBuffer = Alloc(numMapTilesRows * 0x80);
+ mapTilesRowBuffer = Alloc(0x80);
+ for (i = 0; i < numMapTilesRows; i++)
+ {
+ memset(mapTilesRowBuffer, 0, 0x80);
+ if (blockIndicesBuffer[i] < 0x280)
+ {
+ TeachyTvComputeMapTilesFromTilesetAndMetaTiles(layout->primaryTileset->metatiles + blockIndicesBuffer[i] * 16, mapTilesRowBuffer, tilesetsBuffer);
+ }
+ else
+ {
+ TeachyTvComputeMapTilesFromTilesetAndMetaTiles(layout->secondaryTileset->metatiles + (blockIndicesBuffer[i] - 0x280) * 16, mapTilesRowBuffer, tilesetsBuffer);
+ }
+ CpuFastCopy(mapTilesRowBuffer, bgTilesBuffer + i * 0x40, 0x80);
+ }
+
+ LoadBgTiles(3, bgTilesBuffer, numMapTilesRows * 0x80, 0);
+ TeachyTvLoadMapPalette(layout, palIndicesBuffer);
+
+ Free(mapTilesRowBuffer);
+ Free(bgTilesBuffer);
+ Free(palIndicesBuffer);
+ Free(tilesetsBuffer);
+ Free(blockIndicesBuffer);
+}
+
+static void TeachyTvLoadMapTilesetToBuffer(struct Tileset *ts, u8 *dstBuffer, u16 size)
+{
+ if (ts)
+ {
+ if (!ts->isCompressed)
+ CpuFastSet(ts->tiles, dstBuffer, 8 * size);
+ else
+ LZDecompressWram(ts->tiles, dstBuffer);
+ }
+}
+
+static void TeachyTvPushBackNewMapPalIndexArrayEntry(const struct MapData *mStruct, u16 *buf1, u8 *palIndexArray, u16 mapEntry, u16 offset)
+{
+ u16 * metaTileEntryAddr = mapEntry <= 0x27F ? &((u16*)(mStruct->primaryTileset->metatiles))[8 * mapEntry] : &((u16*)(mStruct->secondaryTileset->metatiles))[8 * (mapEntry - 0x280)];
+ buf1[0] = (TeachyTvComputePalIndexArrayEntryByMetaTile(palIndexArray, metaTileEntryAddr[0]) << 12) + 4 * offset;
+ buf1[1] = (TeachyTvComputePalIndexArrayEntryByMetaTile(palIndexArray, metaTileEntryAddr[1]) << 12) + 4 * offset + 1;
+ buf1[32] = (TeachyTvComputePalIndexArrayEntryByMetaTile(palIndexArray, metaTileEntryAddr[2]) << 12) + 4 * offset + 2;
+ buf1[33] = (TeachyTvComputePalIndexArrayEntryByMetaTile(palIndexArray, metaTileEntryAddr[3]) << 12) + 4 * offset + 3;
+}
+
+static void TeachyTvComputeMapTilesFromTilesetAndMetaTiles(u16 *metaTilesArray, u8 *blockBuf, u8 *tileset)
+{
+ TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(blockBuf, &tileset[0x20 * (*metaTilesArray & 0x3FF)], (*metaTilesArray >> 10) & 3);
+ TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(blockBuf, &tileset[0x20 * (metaTilesArray[4] & 0x3FF)], (metaTilesArray[4] >> 10) & 3);
+ TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(blockBuf + 0x20, &tileset[0x20 * (metaTilesArray[1] & 0x3FF)], (metaTilesArray[1] >> 10) & 3);
+ TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(blockBuf + 0x20, &tileset[0x20 * (metaTilesArray[5] & 0x3FF)], (metaTilesArray[5] >> 10) & 3);
+ TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(blockBuf + 0x40, &tileset[0x20 * (metaTilesArray[2] & 0x3FF)], (metaTilesArray[2] >> 10) & 3);
+ TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(blockBuf + 0x40, &tileset[0x20 * (metaTilesArray[6] & 0x3FF)], (metaTilesArray[6] >> 10) & 3);
+ blockBuf += 0x60;
+ TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(blockBuf, &tileset[0x20 * (metaTilesArray[3] & 0x3FF)], (metaTilesArray[3] >> 10) & 3);
+ TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(blockBuf, &tileset[0x20 * (metaTilesArray[7] & 0x3FF)], (metaTilesArray[7] >> 10) & 3);
+}
+
+static void TeachyTvComputeSingleMapTileBlockFromTilesetAndMetaTiles(u8 *blockBuf, u8 *tileset, u8 metaTile)
+{
+ u8 i, j;
+ u8 * buffer = AllocZeroed(0x20);
+ u8 * src = AllocZeroed(0x20);
+ CpuFastSet(tileset, buffer, 8);
+ if (metaTile & 1)
+ {
+ for (i = 0; i < 8; ++i)
+ {
+ for (j = 0; j < 4; ++j)
+ {
+ u32 offset = j - 3;
+ u8 value = buffer[(i << 2) - offset];
+ src[(i << 2) + j] = ((value & 0xF) << 4) + ((value & 0xF0) >> 4);
+ }
+ }
+ CpuFastSet(src, buffer, 8);
+ }
+ if (metaTile & 2)
+ {
+ for (i = 0; i < 8; ++i)
+ memcpy(&src[4 * i], &buffer[4 * (7 - i)], 4);
+ CpuFastSet(src, buffer, 8);
+ }
+ for (i = 0; i < 32; ++i)
+ {
+ if (buffer[i] & 0xF0)
+ blockBuf[i] = (blockBuf[i] & 0xF) + (buffer[i] & 0xF0);
+ if (buffer[i] & 0xF)
+ blockBuf[i] = (blockBuf[i] & 0xF0) + (buffer[i] & 0xF);
+ }
+ Free(src);
+ Free(buffer);
+}
+
+static u16 TeachyTvComputePalIndexArrayEntryByMetaTile(u8 *palIndexArrayBuf, u16 metaTile)
+{
+ u16 i;
+ int firstEntry;
+ int temp;
+ u32 pal = metaTile >> 12;
+ i = 0;
+ firstEntry = *palIndexArrayBuf;
+ if (firstEntry != pal)
+ {
+ if (firstEntry == 0xFF)
+ {
+ *palIndexArrayBuf = pal;
+ }
+ else
+ {
+ while (++i < 16)
+ {
+ temp = palIndexArrayBuf[i];
+ if (temp == pal)
+ break;
+ if (temp == 0xFF)
+ {
+ palIndexArrayBuf[i] = pal;
+ break;
+ }
+ }
+ }
+ }
+ return (0xF - i);
+}
+
+static void TeachyTvLoadMapPalette(const struct MapData * mStruct, const u8 * palIndexArray)
+{
+ u8 i;
+ const struct Tileset * ts;
+ u16 * dest;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (palIndexArray[i] == 0xFF)
+ break;
+ if (palIndexArray[i] > 6)
+ dest = (u16 *)mStruct->secondaryTileset->palettes + 0x10 * palIndexArray[i];
+ else
+ dest = (u16 *)mStruct->primaryTileset->palettes + 0x10 * palIndexArray[i];
+ LoadPalette(dest, 0x10 * (15 - i), 0x20);
+ }
+}
diff --git a/src/text.c b/src/text.c
index 874e12fd5..f84420352 100644
--- a/src/text.c
+++ b/src/text.c
@@ -5,13 +5,13 @@
#include "window.h"
#include "text.h"
#include "sprite.h"
+#include "blit.h"
extern u8 gGlyphInfo[0x90];
extern u8 gUnknown_203ADFA;
-extern u16 gUnknown_841F408[];
-extern const struct OamData gUnknown_83AC9D0;
+extern u16 gTMCaseMainWindowPalette[];
+extern const struct OamData gOamData_83AC9D0;
-extern void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
extern void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16 height);
extern void BlitBitmapRectToWindow(u8 windowId, const u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight);
extern u8 GetKeypadIconWidth(u8 keypadIconId);
@@ -52,7 +52,7 @@ const struct SpriteSheet gUnknown_81EA68C[] =
const struct SpritePalette gUnknown_81EA6A4[] =
{
- {gUnknown_841F408, 0x8000},
+ {gTMCaseMainWindowPalette, 0x8000},
{NULL}
};
@@ -60,7 +60,7 @@ const struct SpriteTemplate gUnknown_81EA6B4 =
{
.tileTag = 0x8000,
.paletteTag = 0x8000,
- .oam = &gUnknown_83AC9D0,
+ .oam = &gOamData_83AC9D0,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
@@ -453,7 +453,7 @@ void TextPrinterInitDownArrowCounters(struct TextPrinter *textPrinter)
{
struct TextPrinterSubStruct *subStruct = &textPrinter->sub_union.sub;
- if (gTextFlags.flag_2 == 1)
+ if (gTextFlags.autoScroll == 1)
subStruct->frames_visible_counter = 0;
else
{
@@ -467,7 +467,7 @@ void TextPrinterDrawDownArrow(struct TextPrinter *textPrinter)
struct TextPrinterSubStruct *subStruct = &textPrinter->sub_union.sub;
const u8 *arrowTiles;
- if (gTextFlags.flag_2 == 0)
+ if (gTextFlags.autoScroll == 0)
{
if (subStruct->field_1 != 0)
{
@@ -483,7 +483,7 @@ void TextPrinterDrawDownArrow(struct TextPrinter *textPrinter)
10,
12);
- switch (gTextFlags.flag_1)
+ switch (gTextFlags.useAlternateDownArrow)
{
case 0:
default:
@@ -544,7 +544,7 @@ bool8 TextPrinterWaitAutoMode(struct TextPrinter *textPrinter)
bool16 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
{
bool8 result = FALSE;
- if (gTextFlags.flag_2 != 0)
+ if (gTextFlags.autoScroll != 0)
{
result = TextPrinterWaitAutoMode(textPrinter);
}
@@ -563,7 +563,7 @@ bool16 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
bool16 TextPrinterWait(struct TextPrinter *textPrinter)
{
bool16 result = FALSE;
- if (gTextFlags.flag_2 != 0)
+ if (gTextFlags.autoScroll != 0)
{
result = TextPrinterWaitAutoMode(textPrinter);
}
@@ -591,7 +591,7 @@ void DrawDownArrow(u8 windowId, u16 x, u16 y, u8 bgColor, bool8 drawArrow, u8 *c
FillWindowPixelRect(windowId, (bgColor << 4) | bgColor, x, y, 10, 12);
if (drawArrow == 0)
{
- switch (gTextFlags.flag_1)
+ switch (gTextFlags.useAlternateDownArrow)
{
case 0:
default:
@@ -1791,7 +1791,7 @@ void sub_80062B0(struct Sprite *sprite)
}
}
-u8 sub_8006300(u8 sheetId, u16 x, u16 y, u8 priority, u8 subpriority)
+u8 CreateTextCursorSpriteForOakSpeech(u8 sheetId, u16 x, u16 y, u8 priority, u8 subpriority)
{
u8 spriteId;
LoadSpriteSheet(&gUnknown_81EA68C[sheetId & 1]);
diff --git a/src/text_printer.c b/src/text_printer.c
index 04de1af4c..6c124b448 100644
--- a/src/text_printer.c
+++ b/src/text_printer.c
@@ -48,11 +48,11 @@ void DeactivateAllTextPrinters (void)
sTextPrinters[printer].sub_union.sub.active = 0;
}
-u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextSubPrinter *, u16))
+u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
{
- struct TextSubPrinter subPrinter;
+ struct TextPrinterTemplate subPrinter;
- subPrinter.current_text_offset = str;
+ subPrinter.currentChar = str;
subPrinter.windowId = windowId;
subPrinter.fontId = fontId;
subPrinter.x = x;
@@ -61,14 +61,14 @@ u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8
subPrinter.currentY = y;
subPrinter.letterSpacing = gFonts[fontId].letterSpacing;
subPrinter.lineSpacing = gFonts[fontId].lineSpacing;
- subPrinter.fontColor_l = gFonts[fontId].fontColor_l;
- subPrinter.fontColor_h = gFonts[fontId].fontColor_h;
+ subPrinter.unk = gFonts[fontId].unk;
+ subPrinter.fgColor = gFonts[fontId].fgColor;
subPrinter.bgColor = gFonts[fontId].bgColor;
subPrinter.shadowColor = gFonts[fontId].shadowColor;
return AddTextPrinter(&subPrinter, speed, callback);
}
-bool16 AddTextPrinter(struct TextSubPrinter *textSubPrinter, u8 speed, void (*callback)(struct TextSubPrinter *, u16))
+bool16 AddTextPrinter(struct TextPrinterTemplate *textSubPrinter, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
{
int i;
u16 j;
@@ -92,7 +92,7 @@ bool16 AddTextPrinter(struct TextSubPrinter *textSubPrinter, u8 speed, void (*ca
sTempTextPrinter.minLetterSpacing = 0;
sTempTextPrinter.japanese = 0;
- GenerateFontHalfRowLookupTable(textSubPrinter->fontColor_h, textSubPrinter->bgColor, textSubPrinter->shadowColor);
+ GenerateFontHalfRowLookupTable(textSubPrinter->fgColor, textSubPrinter->bgColor, textSubPrinter->shadowColor);
if (speed != TEXT_SPEED_FF && speed != 0x0)
{
--sTempTextPrinter.text_speed;
diff --git a/src/text_window.c b/src/text_window.c
new file mode 100644
index 000000000..0c562b195
--- /dev/null
+++ b/src/text_window.c
@@ -0,0 +1,169 @@
+#include "global.h"
+#include "bg.h"
+#include "palette.h"
+#include "text.h"
+#include "window.h"
+#include "text_window.h"
+#include "text_window_graphics.h"
+#include "quest_log.h"
+
+extern const u16 gUnknown_841F1C8[];
+
+void sub_814FFC4(u8 windowId, u8 frameType, u16 destOffset, u8 palIdx);
+
+void sub_814FD04(u8 bgId, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(bgId, gUnknown_84566A8, 0x280, destOffset);
+ LoadPalette(stdpal_get(2), palIdx, 32);
+}
+
+void sub_814FD38(u8 bgId, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(bgId, gUnknown_841F1C8, 0x280, destOffset);
+ LoadPalette(stdpal_get(0), palIdx, 32);
+}
+
+void sub_814FD6C(u8 bgId, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(bgId, gUnknown_8470B0C, 0x260, destOffset);
+ LoadPalette(stdpal_get(1), palIdx, 32);
+}
+
+void sub_814FDA0(u8 bgId, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(bgId, gStdFrame0, 0x120, destOffset);
+ LoadPalette(stdpal_get(3), palIdx, 32);
+}
+
+void sub_814FDD4(u8 bgId, u16 destOffset)
+{
+ LoadBgTiles(bgId, gStdFrame1, 0x280, destOffset);
+}
+
+void sub_814FDF4(u8 bgId, u8 frameType, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(bgId, gUserFrames[frameType].tiles, 0x120, destOffset);
+ LoadPalette(gUserFrames[frameType].palette, palIdx, 32);
+}
+
+void LoadUserWindowBorderGfx(u8 windowId, u16 destOffset, u8 palIdx)
+{
+ sub_814FFC4(windowId, gSaveBlock2Ptr->optionsWindowFrameType, destOffset, palIdx);
+}
+
+void sub_814FE6C(u8 windowId, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(GetWindowAttribute(windowId, WINDOW_BG), gUnknown_84566A8, 0x280, destOffset);
+ LoadPalette(stdpal_get(2), palIdx, 32);
+}
+
+void TextWindow_SetBubbleFrame_841F1C8(u8 windowId, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(GetWindowAttribute(windowId, WINDOW_BG), gUnknown_841F1C8, 0x280, destOffset);
+ LoadPalette(stdpal_get(0), palIdx, 32);
+}
+
+void sub_814FEEC(u8 windowId, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(GetWindowAttribute(windowId, WINDOW_BG), gUnknown_8470B0C, 0x260, destOffset);
+ LoadPalette(stdpal_get(1), palIdx, 32);
+}
+
+void TextWindow_SetStdFrame0_WithPal(u8 windowId, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(GetWindowAttribute(windowId, WINDOW_BG), gStdFrame0, 0x120, destOffset);
+ LoadPalette(stdpal_get(3), palIdx, 32);
+}
+
+void sub_814FF6C(u8 windowId, u16 destOffset)
+{
+ LoadBgTiles(GetWindowAttribute(windowId, WINDOW_BG), gStdFrame0, 0x120, destOffset);
+}
+
+void sub_814FF98(u8 windowId, u16 destOffset)
+{
+ LoadBgTiles(GetWindowAttribute(windowId, WINDOW_BG), gStdFrame1, 0x280, destOffset);
+}
+
+void sub_814FFC4(u8 windowId, u8 frameType, u16 destOffset, u8 palIdx)
+{
+ LoadBgTiles(GetWindowAttribute(windowId, WINDOW_BG), gUserFrames[frameType].tiles, 0x120, destOffset);
+ LoadPalette(gUserFrames[frameType].palette, palIdx, 32);
+}
+
+void TextWindow_SetUserSelectedFrame(u8 windowId, u16 destOffset, u8 palIdx)
+{
+ sub_814FFC4(windowId, gSaveBlock2Ptr->optionsWindowFrameType, destOffset, palIdx);
+}
+
+void DrawTextBorderOuter(u8 windowId, u16 tileNum, u8 palNum)
+{
+ u8 bgLayer = GetWindowAttribute(windowId, WINDOW_BG);
+ u16 tilemapLeft = GetWindowAttribute(windowId, WINDOW_TILEMAP_LEFT);
+ u16 tilemapTop = GetWindowAttribute(windowId, WINDOW_TILEMAP_TOP);
+ u16 width = GetWindowAttribute(windowId, WINDOW_WIDTH);
+ u16 height = GetWindowAttribute(windowId, WINDOW_HEIGHT);
+
+ FillBgTilemapBufferRect(bgLayer, tileNum + 0, tilemapLeft - 1, tilemapTop - 1, 1, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 1, tilemapLeft, tilemapTop - 1, width, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 2, tilemapLeft + width, tilemapTop - 1, 1, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 3, tilemapLeft - 1, tilemapTop, 1, height, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 5, tilemapLeft + width, tilemapTop, 1, height, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 6, tilemapLeft - 1, tilemapTop + height, 1, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 7, tilemapLeft, tilemapTop + height, width, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 8, tilemapLeft + width, tilemapTop + height, 1, 1, palNum);
+}
+
+void DrawTextBorderInner(u8 windowId, u16 tileNum, u8 palNum)
+{
+ u8 bgLayer = GetWindowAttribute(windowId, WINDOW_BG);
+ u16 tilemapLeft = GetWindowAttribute(windowId, WINDOW_TILEMAP_LEFT);
+ u16 tilemapTop = GetWindowAttribute(windowId, WINDOW_TILEMAP_TOP);
+ u16 width = GetWindowAttribute(windowId, WINDOW_WIDTH);
+ u16 height = GetWindowAttribute(windowId, WINDOW_HEIGHT);
+
+ FillBgTilemapBufferRect(bgLayer, tileNum + 0, tilemapLeft, tilemapTop, 1, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 1, tilemapLeft + 1, tilemapTop, width - 2, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 2, tilemapLeft + width - 1, tilemapTop, 1, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 3, tilemapLeft, tilemapTop + 1, 1, height - 2, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 5, tilemapLeft + width - 1, tilemapTop + 1, 1, height - 2, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 6, tilemapLeft, tilemapTop + height - 1, 1, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 7, tilemapLeft + 1, tilemapTop + height - 1, width - 2, 1, palNum);
+ FillBgTilemapBufferRect(bgLayer, tileNum + 8, tilemapLeft + width - 1, tilemapTop + height - 1, 1, 1, palNum);
+}
+
+void rbox_fill_rectangle(u8 windowId)
+{
+ u8 bgLayer = GetWindowAttribute(windowId, WINDOW_BG);
+ u16 tilemapLeft = GetWindowAttribute(windowId, WINDOW_TILEMAP_LEFT);
+ u16 tilemapTop = GetWindowAttribute(windowId, WINDOW_TILEMAP_TOP);
+ u16 width = GetWindowAttribute(windowId, WINDOW_WIDTH);
+ u16 height = GetWindowAttribute(windowId, WINDOW_HEIGHT);
+
+ FillBgTilemapBufferRect(bgLayer, 0, tilemapLeft - 1, tilemapTop - 1, width + 2, height + 2, 0x11);
+}
+
+const u16 *stdpal_get(u8 id)
+{
+ switch (id)
+ {
+ case 0:
+ id = 0;
+ break;
+ case 1:
+ id = 0x10;
+ break;
+ case 2:
+ id = 0x20;
+ break;
+ case 3:
+ id = 0x30;
+ break;
+ case 4:
+ default:
+ id = 0x40;
+ break;
+ }
+
+ return (const u16 *)(gUnknown_8471DEC) + id;
+}
diff --git a/src/text_window_graphics.c b/src/text_window_graphics.c
new file mode 100644
index 000000000..e16037a34
--- /dev/null
+++ b/src/text_window_graphics.c
@@ -0,0 +1,60 @@
+#include "global.h"
+#include "text_window_graphics.h"
+
+const u16 gUnknown_8470B0C[] = INCBIN_U16("graphics/text_window/unk_8470B0C.4bpp");
+
+static const u16 gUnknown_8470D6C[] = INCBIN_U16("graphics/text_window/unk_8470D6C.4bpp");
+static const u16 gUnknown_8470E8C[] = INCBIN_U16("graphics/text_window/unk_8470E8C.4bpp");
+static const u16 gUnk_Empty_Space_8470FAC[16] = {0};
+static const u16 gUnknown_8470FCC[] = INCBIN_U16("graphics/text_window/unk_8470FCC.4bpp");
+static const u16 gUnknown_84710EC[] = INCBIN_U16("graphics/text_window/unk_84710EC.4bpp");
+static const u16 gUnknown_847120C[] = INCBIN_U16("graphics/text_window/unk_847120C.4bpp");
+static const u16 gUnknown_847132C[] = INCBIN_U16("graphics/text_window/unk_847132C.4bpp");
+static const u16 gUnknown_847144C[] = INCBIN_U16("graphics/text_window/unk_847144C.4bpp");
+static const u16 gUnknown_847156C[] = INCBIN_U16("graphics/text_window/unk_847156C.4bpp");
+static const u16 gUnk_Empty_Space_847168C[16] = {0};
+static const u16 gUnknown_84716AC[] = INCBIN_U16("graphics/text_window/unk_84716AC.4bpp");
+static const u16 gUnknown_84717CC[] = INCBIN_U16("graphics/text_window/unk_84717CC.4bpp");
+static const u16 gUnk_Empty_Space_84718EC[16] = {0};
+static const u16 gUnknown_847190C[] = INCBIN_U16("graphics/text_window/unk_8470D6C.gbapal");
+static const u16 gUnknown_847192C[] = INCBIN_U16("graphics/text_window/unk_8470E8C.gbapal");
+static const u16 gUnknown_847194C[] = INCBIN_U16("graphics/text_window/unk_8470FCC.gbapal");
+static const u16 gUnknown_847196C[] = INCBIN_U16("graphics/text_window/unk_84710EC.gbapal");
+static const u16 gUnknown_847198C[] = INCBIN_U16("graphics/text_window/unk_847120C.gbapal");
+static const u16 gUnknown_84719AC[] = INCBIN_U16("graphics/text_window/unk_847132C.gbapal");
+static const u16 gUnknown_84719CC[] = INCBIN_U16("graphics/text_window/unk_847144C.gbapal");
+static const u16 gUnknown_84719EC[] = INCBIN_U16("graphics/text_window/unk_847156C.gbapal");
+static const u16 gUnknown_8471A0C[] = INCBIN_U16("graphics/text_window/unk_84716AC.gbapal");
+static const u16 gUnknown_8471A2C[] = INCBIN_U16("graphics/text_window/unk_84717CC.gbapal");
+
+const u16 gStdFrame0[] = INCBIN_U16("graphics/text_window/unk_8471A4C.4bpp");
+const u16 gStdFrame1[] = INCBIN_U16("graphics/text_window/unk_8471B6C.4bpp");
+
+const u16 gUnknown_8471DEC[][16] = {
+ INCBIN_U16("graphics/text_window/stdpal_0.gbapal"),
+ INCBIN_U16("graphics/text_window/stdpal_1.gbapal"),
+ INCBIN_U16("graphics/text_window/stdpal_2.gbapal"),
+ INCBIN_U16("graphics/text_window/stdpal_3.gbapal"),
+ INCBIN_U16("graphics/text_window/stdpal_4.gbapal")
+};
+
+const struct TextWindowGraphics gUserFrames[] = {
+ {gUnknown_8470D6C, gUnknown_847190C},
+ {gUnknown_8470E8C, gUnknown_847192C},
+ {gUnknown_8470FCC, gUnknown_847194C},
+ {gUnknown_84710EC, gUnknown_847196C},
+ {gUnknown_847120C, gUnknown_847198C},
+ {gUnknown_847132C, gUnknown_84719AC},
+ {gUnknown_847144C, gUnknown_84719CC},
+ {gUnknown_847156C, gUnknown_84719EC},
+ {gUnknown_84716AC, gUnknown_8471A0C},
+ {gUnknown_84717CC, gUnknown_8471A2C}
+}; // NELEMS = 10
+
+const struct TextWindowGraphics * sub_8069788(u8 idx)
+{
+ if (idx >= 20) // if (idx >= NELEMS(gUserFrames))
+ return &gUserFrames[0];
+ else
+ return &gUserFrames[idx];
+}
diff --git a/src/tm_case.c b/src/tm_case.c
new file mode 100644
index 000000000..28aba57a0
--- /dev/null
+++ b/src/tm_case.c
@@ -0,0 +1,1537 @@
+#include "global.h"
+#include "malloc.h"
+#include "bg.h"
+#include "decompress.h"
+#include "gpu_regs.h"
+#include "palette.h"
+#include "graphics.h"
+#include "task.h"
+#include "text.h"
+#include "text_window.h"
+#include "menu.h"
+#include "menu_helpers.h"
+#include "new_menu_helpers.h"
+#include "list_menu.h"
+#include "item.h"
+#include "item_menu.h"
+#include "link.h"
+#include "money.h"
+#include "shop.h"
+#include "teachy_tv.h"
+#include "pokemon_storage_system.h"
+#include "string_util.h"
+#include "party_menu.h"
+#include "data2.h"
+#include "scanline_effect.h"
+#include "sound.h"
+#include "strings.h"
+#include "tm_case.h"
+#include "menu_indicators.h"
+#include "constants/items.h"
+#include "constants/songs.h"
+
+#define TM_CASE_TM_TAG 400
+
+struct UnkStruct_203B10C
+{
+ void (* savedCallback)(void);
+ u8 tmCaseMenuType;
+ u8 unk_05;
+ u8 unk_06;
+ u16 selectedRow;
+ u16 scrollOffset;
+};
+
+struct UnkStruct_203B118
+{
+ void (* savedCallback)(void);
+ u8 tmSpriteId;
+ u8 maxTMsShown;
+ u8 numTMs;
+ u8 contextMenuWindowId;
+ u8 scrollIndicatorArrowPairId;
+ u16 currItem;
+ const u8 * menuActionIndices;
+ u8 numMenuActions;
+ s16 seqId;
+ u8 filler_14[8];
+};
+
+struct UnkStruct_203B11C
+{
+ struct ItemSlot bagPocket_TMHM[BAG_TMHM_COUNT];
+ struct ItemSlot bagPocket_KeyItems[BAG_KEYITEMS_COUNT];
+ u16 unk_160;
+ u16 unk_162;
+};
+
+static EWRAM_DATA struct UnkStruct_203B10C sTMCaseStaticResources = {};
+static EWRAM_DATA struct UnkStruct_203B118 * sTMCaseDynamicResources = NULL;
+static EWRAM_DATA struct UnkStruct_203B11C * sPokeDudePackBackup = NULL;
+static EWRAM_DATA void * sTilemapBuffer = NULL; // tilemap buffer
+static EWRAM_DATA struct ListMenuItem * sListMenuItemsBuffer = NULL;
+static EWRAM_DATA u8 (* sListMenuStringsBuffer)[29] = NULL;
+static EWRAM_DATA u16 * sTMSpritePaletteBuffer = NULL;
+
+static void CB2_SetUpTMCaseUI_Blocking(void);
+static bool8 DoSetUpTMCaseUI(void);
+static void ResetBufferPointers_NoFree(void);
+static void LoadBGTemplates(void);
+static bool8 HandleLoadTMCaseGraphicsAndPalettes(void);
+static void CreateTMCaseListMenuBuffers(void);
+static void InitTMCaseListMenuItems(void);
+static void GetTMNumberAndMoveString(u8 * dest, u16 itemId);
+static void TMCase_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list);
+static void TMCase_ItemPrintFunc(u8 windowId, s32 itemId, u8 y);
+static void TMCase_MoveCursor_UpdatePrintedDescription(s32 itemIndex);
+static void PrintListMenuCursorAt_WithColorIdx(u8 a0, u8 a1);
+static void CreateTMCaseScrollIndicatorArrowPair_Main(void);
+static void TMCaseSetup_GetTMCount(void);
+static void TMCaseSetup_InitListMenuPositions(void);
+static void TMCaseSetup_UpdateVisualMenuOffset(void);
+static void Task_FadeOutAndCloseTMCase(u8 taskId);
+static void Task_TMCaseMain(u8 taskId);
+static void Task_SelectTMAction_FromFieldBag(u8 taskId);
+static void Task_TMContextMenu_HandleInput(u8 taskId);
+static void TMHMContextMenuAction_Use(u8 taskId);
+static void TMHMContextMenuAction_Give(u8 taskId);
+static void PrintError_ThereIsNoPokemon(u8 taskId);
+static void PrintError_ItemCantBeHeld(u8 taskId);
+static void Task_WaitButtonAfterErrorPrint(u8 taskId);
+static void Subtask_CloseContextMenuAndReturnToMain(u8 taskId);
+static void TMHMContextMenuAction_Exit(u8 taskId);
+static void Task_SelectTMAction_Type1(u8 taskId);
+static void Task_SelectTMAction_Type3(u8 taskId);
+static void Task_SelectTMAction_FromSellMenu(u8 taskId);
+static void Task_AskConfirmSaleWithAmount(u8 taskId);
+static void Task_PlaceYesNoBox(u8 taskId);
+static void Task_SaleOfTMsCancelled(u8 taskId);
+static void Task_InitQuantitySelectUI(u8 taskId);
+static void SellTM_PrintQuantityAndSalePrice(s16 quantity, s32 value);
+static void Task_QuantitySelect_HandleInput(u8 taskId);
+static void Task_PrintSaleConfirmedText(u8 taskId);
+static void Task_DoSaleOfTMs(u8 taskId);
+static void Task_AfterSale_ReturnToList(u8 taskId);
+static void Task_TMCaseDude1(u8 taskId);
+static void Task_TMCaseDude_Playback(u8 taskId);
+static void InitWindowTemplatesAndPals(void);
+static void AddTextPrinterParameterized_ColorByIndex(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, u8 speed, u8 colorIdx);
+static void TMCase_SetWindowBorder1(u8 windowId);
+static void TMCase_SetWindowBorder2(u8 windowId);
+static void TMCase_PrintMessageWithFollowupTask(u8 taskId, u8 windowId, const u8 * str, TaskFunc func);
+static void PrintStringTMCaseOnWindow3(void);
+static void DrawMoveInfoUIMarkers(void);
+static void TMCase_MoveCursor_UpdatePrintedTMInfo(u16 itemId);
+static void PlaceHMTileInWindow(u8 windowId, u8 x, u8 y);
+static void HandlePrintMoneyOnHand(void);
+static void HandleCreateYesNoMenu(u8 taskId, const struct YesNoFuncTable * ptrs);
+static u8 AddTMContextMenu(u8 * a0, u8 a1);
+static void RemoveTMContextMenu(u8 * a0);
+static u8 CreateTMSprite(u16 itemId);
+static void SetTMSpriteAnim(struct Sprite * sprite, u8 var);
+static void TintTMSpriteByType(u8 type);
+static void UpdateTMSpritePosition(struct Sprite * sprite, u8 var);
+static void InitSelectedTMSpriteData(u8 a0, u16 itemId);
+static void SpriteCB_MoveTMSpriteInCase(struct Sprite * sprite);
+static void LoadTMTypePalettes(void);
+
+static const struct BgTemplate sBGTemplates[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0x000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }, {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 29,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x000
+ }
+};
+
+static void (*const sSelectTMActionTasks[])(u8 taskId) = {
+ Task_SelectTMAction_FromFieldBag,
+ Task_SelectTMAction_Type1,
+ Task_SelectTMAction_FromSellMenu,
+ Task_SelectTMAction_Type3
+};
+
+static const struct MenuAction sMenuActions_UseGiveExit[] = {
+ {gOtherText_Use, TMHMContextMenuAction_Use },
+ {gOtherText_Give, TMHMContextMenuAction_Give},
+ {gOtherText_Exit, TMHMContextMenuAction_Exit},
+};
+
+static const u8 sMenuActionIndices_Field[] = {0, 1, 2};
+static const u8 sMenuActionIndices_UnionRoom[] = {1, 2};
+static const struct YesNoFuncTable sYesNoFuncTable = {Task_PrintSaleConfirmedText, Task_SaleOfTMsCancelled};
+
+static const u8 sText_ClearTo18[] = _("{CLEAR_TO 18}");
+static const u8 sText_SingleSpace[] = _(" ");
+
+static ALIGNED(4) const u16 sPal3Override[] = {RGB(8, 8, 8), RGB(30, 16, 6)};
+
+static const struct TextColor sTextColors[] = {
+ {0, 1, 2},
+ {0, 2, 3},
+ {0, 3, 6},
+ {0, 14, 10}
+};
+
+static const struct WindowTemplate sWindowTemplates[] = {
+ {0x00, 0x0a, 0x01, 0x13, 0x0a, 0x0f, 0x0081},
+ {0x00, 0x0c, 0x0c, 0x12, 0x08, 0x0a, 0x013f},
+ {0x01, 0x05, 0x0f, 0x0f, 0x04, 0x0d, 0x01f9},
+ {0x00, 0x00, 0x01, 0x0a, 0x02, 0x0f, 0x0235},
+ {0x00, 0x01, 0x0d, 0x05, 0x06, 0x0c, 0x0249},
+ {0x00, 0x07, 0x0d, 0x05, 0x06, 0x0c, 0x0267},
+ {0x01, 0x02, 0x0f, 0x1a, 0x04, 0x0b, 0x0285},
+ {0x01, 0x11, 0x09, 0x0c, 0x04, 0x0f, 0x02ed},
+ {0x01, 0x01, 0x01, 0x08, 0x03, 0x0d, 0x031d},
+ DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate sYesNoWindowTemplate = {0x01, 0x15, 0x09, 0x06, 0x04, 0x0f, 0x0335};
+
+static const struct WindowTemplate sTMContextWindowTemplates[] = {
+ {0x01, 0x16, 0x0d, 0x07, 0x06, 0x0f, 0x01cf},
+ {0x01, 0x16, 0x0f, 0x07, 0x04, 0x0f, 0x01cf}
+};
+
+static const struct OamData sTMSpriteOamData = {
+ .size = 2,
+ .priority = 2
+};
+
+static const union AnimCmd sTMSpriteAnim0[] = {
+ ANIMCMD_FRAME(0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sTMSpriteAnim1[] = {
+ ANIMCMD_FRAME(16, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sTMSpriteAnims[] = {
+ sTMSpriteAnim0,
+ sTMSpriteAnim1
+};
+
+static const struct CompressedSpriteSheet sTMSpriteSheet = {
+ (const void *)gTMCase_TMSpriteGfx,
+ 0x400,
+ TM_CASE_TM_TAG
+};
+
+static const struct SpriteTemplate sTMSpriteTemplate = {
+ TM_CASE_TM_TAG,
+ TM_CASE_TM_TAG,
+ &sTMSpriteOamData,
+ sTMSpriteAnims,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCallbackDummy
+};
+
+static const u16 sTMSpritePaletteOffsetByType[] = {
+ [TYPE_NORMAL] = 0x000,
+ [TYPE_FIRE] = 0x010,
+ [TYPE_WATER] = 0x020,
+ [TYPE_GRASS] = 0x030,
+ [TYPE_ELECTRIC] = 0x040,
+ [TYPE_ROCK] = 0x050,
+ [TYPE_GROUND] = 0x060,
+ [TYPE_ICE] = 0x070,
+ [TYPE_FLYING] = 0x080,
+ [TYPE_FIGHTING] = 0x090,
+ [TYPE_GHOST] = 0x0a0,
+ [TYPE_BUG] = 0x0b0,
+ [TYPE_POISON] = 0x0c0,
+ [TYPE_PSYCHIC] = 0x0d0,
+ [TYPE_STEEL] = 0x0e0,
+ [TYPE_DARK] = 0x0f0,
+ [TYPE_DRAGON] = 0x100
+};
+
+void InitTMCase(u8 type, void (* callback)(void), u8 a2)
+{
+ ResetBufferPointers_NoFree();
+ sTMCaseDynamicResources = Alloc(sizeof(struct UnkStruct_203B118));
+ sTMCaseDynamicResources->savedCallback = 0;
+ sTMCaseDynamicResources->scrollIndicatorArrowPairId = 0xFF;
+ sTMCaseDynamicResources->contextMenuWindowId = 0xFF;
+ if (type != 5)
+ sTMCaseStaticResources.tmCaseMenuType = type;
+ if (callback != NULL)
+ sTMCaseStaticResources.savedCallback = callback;
+ if (a2 != 0xFF)
+ sTMCaseStaticResources.unk_05 = a2;
+ gTextFlags.autoScroll = FALSE;
+ SetMainCallback2(CB2_SetUpTMCaseUI_Blocking);
+}
+
+static void CB2_Idle(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ do_scheduled_bg_tilemap_copies_to_vram();
+ UpdatePaletteFade();
+}
+
+static void VBlankCB_Idle(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void CB2_SetUpTMCaseUI_Blocking(void)
+{
+ while (1)
+ {
+ if (sub_80BF72C() == TRUE)
+ break;
+ if (DoSetUpTMCaseUI() == TRUE)
+ break;
+ if (MenuHelpers_LinkSomething() == TRUE)
+ break;
+ }
+}
+
+static bool8 DoSetUpTMCaseUI(void)
+{
+ u8 taskId;
+
+ switch (gMain.state)
+ {
+ case 0:
+ VblankHblankHandlerSetZero();
+ clear_scheduled_bg_copies_to_vram();
+ gMain.state++;
+ break;
+ case 1:
+ ScanlineEffect_Stop();
+ gMain.state++;
+ break;
+ case 2:
+ FreeAllSpritePalettes();
+ gMain.state++;
+ break;
+ case 3:
+ ResetPaletteFade();
+ gMain.state++;
+ break;
+ case 4:
+ ResetSpriteData();
+ gMain.state++;
+ break;
+ case 5:
+ ResetTasks();
+ gMain.state++;
+ break;
+ case 6:
+ LoadBGTemplates();
+ sTMCaseDynamicResources->seqId = 0;
+ gMain.state++;
+ break;
+ case 7:
+ InitWindowTemplatesAndPals();
+ gMain.state++;
+ break;
+ case 8:
+ if (HandleLoadTMCaseGraphicsAndPalettes())
+ gMain.state++;
+ break;
+ case 9:
+ SortPocketAndPlaceHMsFirst(&gBagPockets[POCKET_TM_CASE - 1]);
+ gMain.state++;
+ break;
+ case 10:
+ TMCaseSetup_GetTMCount();
+ TMCaseSetup_InitListMenuPositions();
+ TMCaseSetup_UpdateVisualMenuOffset();
+ gMain.state++;
+ break;
+ case 11:
+ DrawMoveInfoUIMarkers();
+ gMain.state++;
+ break;
+ case 12:
+ CreateTMCaseListMenuBuffers();
+ InitTMCaseListMenuItems();
+ gMain.state++;
+ break;
+ case 13:
+ PrintStringTMCaseOnWindow3();
+ gMain.state++;
+ break;
+ case 14:
+ if (sTMCaseStaticResources.tmCaseMenuType == 4)
+ taskId = CreateTask(Task_TMCaseDude1, 0);
+ else
+ taskId = CreateTask(Task_TMCaseMain, 0);
+ gTasks[taskId].data[0] = ListMenuInit(&gMultiuseListMenuTemplate, sTMCaseStaticResources.scrollOffset, sTMCaseStaticResources.selectedRow);
+ gMain.state++;
+ break;
+ case 15:
+ CreateTMCaseScrollIndicatorArrowPair_Main();
+ gMain.state++;
+ break;
+ case 16:
+ sTMCaseDynamicResources->tmSpriteId = CreateTMSprite(BagGetItemIdByPocketPosition(POCKET_TM_CASE, sTMCaseStaticResources.scrollOffset + sTMCaseStaticResources.selectedRow));
+ gMain.state++;
+ break;
+ case 17:
+ BlendPalettes(0xFFFFFFFF, 16, 0);
+ gMain.state++;
+ break;
+ case 18:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ gMain.state++;
+ break;
+ default:
+ SetVBlankCallback(VBlankCB_Idle);
+ SetMainCallback2(CB2_Idle);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void ResetBufferPointers_NoFree(void)
+{
+ sTMCaseDynamicResources = NULL;
+ sTilemapBuffer = NULL;
+ sListMenuItemsBuffer = NULL;
+ sListMenuStringsBuffer = NULL;
+ sTMSpritePaletteBuffer = NULL;
+}
+
+static void LoadBGTemplates(void)
+{
+ void ** ptr;
+ InitBgReg();
+ ptr = &sTilemapBuffer;
+ *ptr = AllocZeroed(0x800);
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, sBGTemplates, NELEMS(sBGTemplates));
+ SetBgTilemapBuffer(2, *ptr);
+ schedule_bg_copy_tilemap_to_vram(1);
+ schedule_bg_copy_tilemap_to_vram(2);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+}
+
+static bool8 HandleLoadTMCaseGraphicsAndPalettes(void)
+{
+ switch (sTMCaseDynamicResources->seqId)
+ {
+ case 0:
+ reset_temp_tile_data_buffers();
+ decompress_and_copy_tile_data_to_vram(1, gUnknown_8E845D8, 0, 0, 0);
+ sTMCaseDynamicResources->seqId++;
+ break;
+ case 1:
+ if (free_temp_tile_data_buffers_if_possible() != TRUE)
+ {
+ LZDecompressWram(gUnknown_8E84A24, sTilemapBuffer);
+ sTMCaseDynamicResources->seqId++;
+ }
+ break;
+ case 2:
+ LZDecompressWram(gUnknown_8E84B70, GetBgTilemapBuffer(1));
+ sTMCaseDynamicResources->seqId++;
+ break;
+ case 3:
+ if (gSaveBlock2Ptr->playerGender == MALE)
+ LoadCompressedPalette(gUnknown_8E84CB0, 0, 0x80);
+ else
+ LoadCompressedPalette(gUnknown_8E84D20, 0, 0x80);
+ sTMCaseDynamicResources->seqId++;
+ break;
+ case 4:
+ LoadCompressedObjectPic(&sTMSpriteSheet);
+ sTMCaseDynamicResources->seqId++;
+ break;
+ default:
+ LoadTMTypePalettes();
+ sTMCaseDynamicResources->seqId = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void CreateTMCaseListMenuBuffers(void)
+{
+ struct BagPocket * pocket = &gBagPockets[POCKET_TM_CASE - 1];
+ sListMenuItemsBuffer = Alloc((pocket->capacity + 1) * sizeof(struct ListMenuItem));
+ sListMenuStringsBuffer = Alloc(sTMCaseDynamicResources->numTMs * 29);
+}
+
+static void InitTMCaseListMenuItems(void)
+{
+ struct BagPocket * pocket = &gBagPockets[POCKET_TM_CASE - 1];
+ u16 i;
+
+ for (i = 0; i < sTMCaseDynamicResources->numTMs; i++)
+ {
+ GetTMNumberAndMoveString(sListMenuStringsBuffer[i], pocket->itemSlots[i].itemId);
+ sListMenuItemsBuffer[i].label = sListMenuStringsBuffer[i];
+ sListMenuItemsBuffer[i].index = i;
+ }
+ sListMenuItemsBuffer[i].label = gText_Close;
+ sListMenuItemsBuffer[i].index = -2;
+ gMultiuseListMenuTemplate.items = sListMenuItemsBuffer;
+ gMultiuseListMenuTemplate.totalItems = sTMCaseDynamicResources->numTMs + 1;
+ gMultiuseListMenuTemplate.windowId = 0;
+ gMultiuseListMenuTemplate.header_X = 0;
+ gMultiuseListMenuTemplate.item_X = 8;
+ gMultiuseListMenuTemplate.cursor_X = 0;
+ gMultiuseListMenuTemplate.lettersSpacing = 0;
+ gMultiuseListMenuTemplate.itemVerticalPadding = 2;
+ gMultiuseListMenuTemplate.upText_Y = 2;
+ gMultiuseListMenuTemplate.maxShowed = sTMCaseDynamicResources->maxTMsShown;
+ gMultiuseListMenuTemplate.fontId = 2;
+ gMultiuseListMenuTemplate.cursorPal = 2;
+ gMultiuseListMenuTemplate.fillValue = 0;
+ gMultiuseListMenuTemplate.cursorShadowPal = 3;
+ gMultiuseListMenuTemplate.moveCursorFunc = TMCase_MoveCursorFunc;
+ gMultiuseListMenuTemplate.itemPrintFunc = TMCase_ItemPrintFunc;
+ gMultiuseListMenuTemplate.cursorKind = 0;
+ gMultiuseListMenuTemplate.scrollMultiple = 0;
+}
+
+static void GetTMNumberAndMoveString(u8 * dest, u16 itemId)
+{
+ StringCopy(gStringVar4, gText_FontSize0);
+ if (itemId >= ITEM_HM01)
+ {
+ StringAppend(gStringVar4, sText_ClearTo18);
+ StringAppend(gStringVar4, gOtherText_UnkF9_08_Clear_01);
+ ConvertIntToDecimalStringN(gStringVar1, itemId - ITEM_HM01 + 1, STR_CONV_MODE_LEADING_ZEROS, 1);
+ StringAppend(gStringVar4, gStringVar1);
+ }
+ else
+ {
+ StringAppend(gStringVar4, gOtherText_UnkF9_08_Clear_01);
+ ConvertIntToDecimalStringN(gStringVar1, itemId - ITEM_TM01 + 1, STR_CONV_MODE_LEADING_ZEROS, 2);
+ StringAppend(gStringVar4, gStringVar1);
+ }
+ StringAppend(gStringVar4, sText_SingleSpace);
+ StringAppend(gStringVar4, gText_FontSize2);
+ StringAppend(gStringVar4, gMoveNames[ItemIdToBattleMoveId(itemId)]);
+ StringCopy(dest, gStringVar4);
+}
+
+static void TMCase_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list)
+{
+ u16 itemId;
+
+ if (itemIndex == -2)
+ itemId = 0;
+ else
+ itemId = BagGetItemIdByPocketPosition(POCKET_TM_CASE, itemIndex);
+
+ if (onInit != TRUE)
+ {
+ PlaySE(SE_SELECT);
+ InitSelectedTMSpriteData(sTMCaseDynamicResources->tmSpriteId, itemId);
+ }
+ TMCase_MoveCursor_UpdatePrintedDescription(itemIndex);
+ TMCase_MoveCursor_UpdatePrintedTMInfo(itemId);
+}
+
+static void TMCase_ItemPrintFunc(u8 windowId, s32 itemId, u8 y)
+{
+ if (itemId != -2)
+ {
+ if (!itemid_is_unique(BagGetItemIdByPocketPosition(POCKET_TM_CASE, itemId)))
+ {
+ ConvertIntToDecimalStringN(gStringVar1, BagGetQuantityByPocketPosition(POCKET_TM_CASE, itemId), STR_CONV_MODE_RIGHT_ALIGN, 3);
+ StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
+ AddTextPrinterParameterized_ColorByIndex(windowId, 0, gStringVar4, 0x7E, y, 0, 0, 0xFF, 1);
+ }
+ else
+ {
+ PlaceHMTileInWindow(windowId, 8, y);
+ }
+ }
+}
+
+static void TMCase_MoveCursor_UpdatePrintedDescription(s32 itemIndex)
+{
+ const u8 * str;
+ if (itemIndex != -2)
+ {
+ str = ItemId_GetDescription(BagGetItemIdByPocketPosition(POCKET_TM_CASE, itemIndex));
+ }
+ else
+ {
+ str = gText_TMCaseWillBePutAway;
+ }
+ FillWindowPixelBuffer(1, 0);
+ AddTextPrinterParameterized_ColorByIndex(1, 2, str, 2, 3, 1, 0, 0, 0);
+}
+
+static void FillBG2RowWithPalette_2timesNplus1(s32 a0)
+{
+ SetBgRectPal(2, 0, 12, 30, 8, 2 * a0 + 1);
+ schedule_bg_copy_tilemap_to_vram(2);
+}
+
+static void PrintListMenuCursorByID_WithColorIdx(u8 a0, u8 a1)
+{
+ PrintListMenuCursorAt_WithColorIdx(ListMenuGetYCoordForPrintingArrowCursor(a0), a1);
+}
+
+static void PrintListMenuCursorAt_WithColorIdx(u8 a0, u8 a1)
+{
+ if (a1 == 0xFF)
+ {
+ FillWindowPixelRect(0, 0, 0, a0, GetFontAttribute(2, 0), GetFontAttribute(2, 1));
+ CopyWindowToVram(0, 2);
+ }
+ else
+ {
+ AddTextPrinterParameterized_ColorByIndex(0, 2, gFameCheckerText_ListMenuCursor, 0, a0, 0, 0, 0, a1);
+ }
+}
+
+static void CreateTMCaseScrollIndicatorArrowPair_Main(void)
+{
+ sTMCaseDynamicResources->scrollIndicatorArrowPairId = AddScrollIndicatorArrowPairParameterized(2, 0xA0, 0x08, 0x58, sTMCaseDynamicResources->numTMs - sTMCaseDynamicResources->maxTMsShown + 1, 0x6E, 0x6E, &sTMCaseStaticResources.scrollOffset);
+}
+
+static void CreateTMCaseScrollIndicatorArrowPair_SellQuantitySelect(void)
+{
+ sTMCaseDynamicResources->currItem = 1;
+ sTMCaseDynamicResources->scrollIndicatorArrowPairId = AddScrollIndicatorArrowPairParameterized(2, 0x98, 0x48, 0x68, 2, 0x6E, 0x6E, &sTMCaseDynamicResources->currItem);
+}
+
+static void RemoveTMCaseScrollIndicatorArrowPair(void)
+{
+ if (sTMCaseDynamicResources->scrollIndicatorArrowPairId != 0xFF)
+ {
+ RemoveScrollIndicatorArrowPair(sTMCaseDynamicResources->scrollIndicatorArrowPairId);
+ sTMCaseDynamicResources->scrollIndicatorArrowPairId = 0xFF;
+ }
+}
+
+void ResetTMCaseCursorPos(void)
+{
+ sTMCaseStaticResources.selectedRow = 0;
+ sTMCaseStaticResources.scrollOffset = 0;
+}
+
+static void TMCaseSetup_GetTMCount(void)
+{
+ struct BagPocket * pocket = &gBagPockets[POCKET_TM_CASE - 1];
+ u16 i;
+
+ BagPocketCompaction(pocket->itemSlots, pocket->capacity);
+ sTMCaseDynamicResources->numTMs = 0;
+ for (i = 0; i < pocket->capacity; i++)
+ {
+ if (pocket->itemSlots[i].itemId == ITEM_NONE)
+ break;
+ sTMCaseDynamicResources->numTMs++;
+ }
+ sTMCaseDynamicResources->maxTMsShown = min(sTMCaseDynamicResources->numTMs + 1, 5);
+}
+
+static void TMCaseSetup_InitListMenuPositions(void)
+{
+ if (sTMCaseStaticResources.scrollOffset != 0)
+ {
+ if (sTMCaseStaticResources.scrollOffset + sTMCaseDynamicResources->maxTMsShown > sTMCaseDynamicResources->numTMs + 1)
+ sTMCaseStaticResources.scrollOffset = sTMCaseDynamicResources->numTMs + 1 - sTMCaseDynamicResources->maxTMsShown;
+ }
+ if (sTMCaseStaticResources.scrollOffset + sTMCaseStaticResources.selectedRow >= sTMCaseDynamicResources->numTMs + 1)
+ {
+ if (sTMCaseDynamicResources->numTMs + 1 < 2)
+ sTMCaseStaticResources.selectedRow = 0;
+ else
+ sTMCaseStaticResources.selectedRow = sTMCaseDynamicResources->numTMs;
+ }
+}
+
+static void TMCaseSetup_UpdateVisualMenuOffset(void)
+{
+ u8 i;
+ if (sTMCaseStaticResources.selectedRow > 3)
+ {
+ for (i = 0; i <= sTMCaseStaticResources.selectedRow - 3 && sTMCaseStaticResources.scrollOffset + sTMCaseDynamicResources->maxTMsShown != sTMCaseDynamicResources->numTMs + 1; i++)
+ {
+ do {} while (0);
+ sTMCaseStaticResources.selectedRow--;
+ sTMCaseStaticResources.scrollOffset++;
+ }
+ }
+}
+
+static void DestroyTMCaseBuffers(void)
+{
+ if (sTMCaseDynamicResources != NULL)
+ Free(sTMCaseDynamicResources);
+ if (sTilemapBuffer != NULL)
+ Free(sTilemapBuffer);
+ if (sListMenuItemsBuffer != NULL)
+ Free(sListMenuItemsBuffer);
+ if (sListMenuStringsBuffer != NULL)
+ Free(sListMenuStringsBuffer);
+ if (sTMSpritePaletteBuffer != NULL)
+ Free(sTMSpritePaletteBuffer);
+ FreeAllWindowBuffers();
+}
+
+static void Task_BeginFadeOutFromTMCase(u8 taskId)
+{
+ BeginNormalPaletteFade(0xFFFFFFFF, -2, 0, 16, RGB_BLACK);
+ gTasks[taskId].func = Task_FadeOutAndCloseTMCase;
+}
+
+static void Task_FadeOutAndCloseTMCase(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!gPaletteFade.active)
+ {
+ DestroyListMenu(data[0], &sTMCaseStaticResources.scrollOffset, &sTMCaseStaticResources.selectedRow);
+ if (sTMCaseDynamicResources->savedCallback != NULL)
+ SetMainCallback2(sTMCaseDynamicResources->savedCallback);
+ else
+ SetMainCallback2(sTMCaseStaticResources.savedCallback);
+ RemoveTMCaseScrollIndicatorArrowPair();
+ DestroyTMCaseBuffers();
+ DestroyTask(taskId);
+ }
+}
+
+static void Task_TMCaseMain(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ s32 input;
+
+ if (!gPaletteFade.active)
+ {
+ if (sub_80BF72C() != TRUE)
+ {
+ input = ListMenuHandleInput(data[0]);
+ ListMenuGetScrollAndRow(data[0], &sTMCaseStaticResources.scrollOffset, &sTMCaseStaticResources.selectedRow);
+ if (JOY_NEW(SELECT_BUTTON) && sTMCaseStaticResources.unk_05 == 1)
+ {
+ PlaySE(SE_SELECT);
+ gSpecialVar_ItemId = ITEM_NONE;
+ Task_BeginFadeOutFromTMCase(taskId);
+ }
+ else
+ {
+ switch (input)
+ {
+ case -1:
+ break;
+ case -2:
+ PlaySE(SE_SELECT);
+ gSpecialVar_ItemId = 0;
+ Task_BeginFadeOutFromTMCase(taskId);
+ break;
+ default:
+ PlaySE(SE_SELECT);
+ FillBG2RowWithPalette_2timesNplus1(1);
+ RemoveTMCaseScrollIndicatorArrowPair();
+ PrintListMenuCursorByID_WithColorIdx(data[0], 2);
+ data[1] = input;
+ data[2] = BagGetQuantityByPocketPosition(POCKET_TM_CASE, input);
+ gSpecialVar_ItemId = BagGetItemIdByPocketPosition(POCKET_TM_CASE, input);
+ gTasks[taskId].func = sSelectTMActionTasks[sTMCaseStaticResources.tmCaseMenuType];
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void Subtask_ReturnToTMCaseMain(u8 taskId)
+{
+ FillBG2RowWithPalette_2timesNplus1(0);
+ CreateTMCaseScrollIndicatorArrowPair_Main();
+ gTasks[taskId].func = Task_TMCaseMain;
+}
+
+static void Task_SelectTMAction_FromFieldBag(u8 taskId)
+{
+ u8 * strbuf;
+ TMCase_SetWindowBorder2(2);
+ if (!MenuHelpers_LinkSomething() && InUnionRoom() != TRUE)
+ {
+ AddTMContextMenu(&sTMCaseDynamicResources->contextMenuWindowId, 0);
+ sTMCaseDynamicResources->menuActionIndices = sMenuActionIndices_Field;
+ sTMCaseDynamicResources->numMenuActions = NELEMS(sMenuActionIndices_Field);
+ }
+ else
+ {
+ AddTMContextMenu(&sTMCaseDynamicResources->contextMenuWindowId, 1);
+ sTMCaseDynamicResources->menuActionIndices = sMenuActionIndices_UnionRoom;
+ sTMCaseDynamicResources->numMenuActions = NELEMS(sMenuActionIndices_UnionRoom);
+ }
+ AddItemMenuActionTextPrinters(sTMCaseDynamicResources->contextMenuWindowId, 2, GetMenuCursorDimensionByFont(2, 0), 2, 0, GetFontAttribute(2, 1) + 2, sTMCaseDynamicResources->numMenuActions, sMenuActions_UseGiveExit, sTMCaseDynamicResources->menuActionIndices);
+ ProgramAndPlaceMenuCursorOnWindow(sTMCaseDynamicResources->contextMenuWindowId, 2, 0, 2, GetFontAttribute(2, 1) + 2, sTMCaseDynamicResources->numMenuActions, 0);
+ strbuf = Alloc(256);
+ GetTMNumberAndMoveString(strbuf, gSpecialVar_ItemId);
+ StringAppend(strbuf, gText_IsSelected);
+ AddTextPrinterParameterized_ColorByIndex(2, 2, strbuf, 0, 2, 1, 0, 0, 1);
+ Free(strbuf);
+ if (itemid_is_unique(gSpecialVar_ItemId))
+ {
+ PlaceHMTileInWindow(2, 0, 2);
+ CopyWindowToVram(2, 2);
+ }
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ gTasks[taskId].func = Task_TMContextMenu_HandleInput;
+}
+
+static void Task_TMContextMenu_HandleInput(u8 taskId)
+{
+ s8 input;
+
+ if (sub_80BF72C() != TRUE)
+ {
+ input = ProcessMenuInputNoWrapAround();
+ switch (input)
+ {
+ case -1:
+ PlaySE(SE_SELECT);
+ sMenuActions_UseGiveExit[sTMCaseDynamicResources->menuActionIndices[sTMCaseDynamicResources->numMenuActions - 1]].func.void_u8(taskId);
+ break;
+ case -2:
+ break;
+ default:
+ PlaySE(SE_SELECT);
+ sMenuActions_UseGiveExit[sTMCaseDynamicResources->menuActionIndices[input]].func.void_u8(taskId);
+ break;
+ }
+ }
+}
+
+static void TMHMContextMenuAction_Use(u8 taskId)
+{
+ RemoveTMContextMenu(&sTMCaseDynamicResources->contextMenuWindowId);
+ ClearMenuWindow(2, 0);
+ ClearWindowTilemap(2);
+ PutWindowTilemap(0);
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ if (CalculatePlayerPartyCount() == 0)
+ {
+ PrintError_ThereIsNoPokemon(taskId);
+ }
+ else
+ {
+ gUnknown_3005E98 = sub_8125B40;
+ sTMCaseDynamicResources->savedCallback = sub_8124C8C;
+ Task_BeginFadeOutFromTMCase(taskId);
+ }
+}
+
+static void TMHMContextMenuAction_Give(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u16 itemId = BagGetItemIdByPocketPosition(POCKET_TM_CASE, data[1]);
+ RemoveTMContextMenu(&sTMCaseDynamicResources->contextMenuWindowId);
+ ClearMenuWindow(2, 0);
+ ClearWindowTilemap(2);
+ PutWindowTilemap(1);
+ PutWindowTilemap(4);
+ PutWindowTilemap(5);
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ if (!itemid_is_unique(itemId))
+ {
+ if (CalculatePlayerPartyCount() == 0)
+ {
+ PrintError_ThereIsNoPokemon(taskId);
+ }
+ else
+ {
+ sTMCaseDynamicResources->savedCallback = sub_8126EDC;
+ Task_BeginFadeOutFromTMCase(taskId);
+ }
+ }
+ else
+ {
+ PrintError_ItemCantBeHeld(taskId);
+ }
+}
+
+static void PrintError_ThereIsNoPokemon(u8 taskId)
+{
+ TMCase_PrintMessageWithFollowupTask(taskId, 2, gText_ThereIsNoPokemon, Task_WaitButtonAfterErrorPrint);
+}
+
+static void PrintError_ItemCantBeHeld(u8 taskId)
+{
+ CopyItemName(gSpecialVar_ItemId, gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_ItemCantBeHeld);
+ TMCase_PrintMessageWithFollowupTask(taskId, 2, gStringVar4, Task_WaitButtonAfterErrorPrint);
+}
+
+static void Task_WaitButtonAfterErrorPrint(u8 taskId)
+{
+ if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ Subtask_CloseContextMenuAndReturnToMain(taskId);
+ }
+}
+
+static void Subtask_CloseContextMenuAndReturnToMain(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ DestroyListMenu(data[0], &sTMCaseStaticResources.scrollOffset, &sTMCaseStaticResources.selectedRow);
+ data[0] = ListMenuInit(&gMultiuseListMenuTemplate, sTMCaseStaticResources.scrollOffset, sTMCaseStaticResources.selectedRow);
+ PrintListMenuCursorByID_WithColorIdx(data[0], 1);
+ ClearMenuWindow_BorderThickness2(6, 0);
+ ClearWindowTilemap(6);
+ PutWindowTilemap(1);
+ PutWindowTilemap(4);
+ PutWindowTilemap(5);
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ Subtask_ReturnToTMCaseMain(taskId);
+}
+
+static void TMHMContextMenuAction_Exit(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ RemoveTMContextMenu(&sTMCaseDynamicResources->contextMenuWindowId);
+ ClearMenuWindow(2, 0);
+ ClearWindowTilemap(2);
+ PutWindowTilemap(0);
+ PrintListMenuCursorByID_WithColorIdx(data[0], 1);
+ PutWindowTilemap(1);
+ PutWindowTilemap(4);
+ PutWindowTilemap(5);
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ Subtask_ReturnToTMCaseMain(taskId);
+}
+
+static void Task_SelectTMAction_Type1(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!itemid_is_unique(BagGetItemIdByPocketPosition(POCKET_TM_CASE, data[1])))
+ {
+ sTMCaseDynamicResources->savedCallback = c2_8123744;
+ Task_BeginFadeOutFromTMCase(taskId);
+ }
+ else
+ {
+ PrintError_ItemCantBeHeld(taskId);
+ }
+}
+
+static void Task_SelectTMAction_Type3(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!itemid_is_unique(BagGetItemIdByPocketPosition(POCKET_TM_CASE, data[1])))
+ {
+ sTMCaseDynamicResources->savedCallback = sub_808CE60;
+ Task_BeginFadeOutFromTMCase(taskId);
+ }
+ else
+ {
+ PrintError_ItemCantBeHeld(taskId);
+ }
+}
+
+static void Task_SelectTMAction_FromSellMenu(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (itemid_get_market_price(gSpecialVar_ItemId) == 0)
+ {
+ CopyItemName(gSpecialVar_ItemId, gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_OhNoICantBuyThat);
+ TMCase_PrintMessageWithFollowupTask(taskId, sub_80BF8E4(), gStringVar4, Subtask_CloseContextMenuAndReturnToMain);
+ }
+ else
+ {
+ data[8] = 1;
+ if (data[2] == 1)
+ {
+ HandlePrintMoneyOnHand();
+ Task_AskConfirmSaleWithAmount(taskId);
+ }
+ else
+ {
+ if (data[2] > 99)
+ data[2] = 99;
+ CopyItemName(gSpecialVar_ItemId, gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_HowManyWouldYouLikeToSell);
+ TMCase_PrintMessageWithFollowupTask(taskId, sub_80BF8E4(), gStringVar4, Task_InitQuantitySelectUI);
+ }
+ }
+}
+
+static void Task_AskConfirmSaleWithAmount(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ ConvertIntToDecimalStringN(gStringVar3, itemid_get_market_price(BagGetItemIdByPocketPosition(POCKET_TM_CASE, data[1])) / 2 * data[8], STR_CONV_MODE_LEFT_ALIGN, 6);
+ StringExpandPlaceholders(gStringVar4, gText_ICanPayThisMuch_WouldThatBeOkay);
+ TMCase_PrintMessageWithFollowupTask(taskId, sub_80BF8E4(), gStringVar4, Task_PlaceYesNoBox);
+}
+
+static void Task_PlaceYesNoBox(u8 taskId)
+{
+ HandleCreateYesNoMenu(taskId, &sYesNoFuncTable);
+}
+
+static void Task_SaleOfTMsCancelled(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ ClearMenuWindow(8, 0);
+ ClearMenuWindow_BorderThickness2(6, 0);
+ PutWindowTilemap(0);
+ PutWindowTilemap(1);
+ PutWindowTilemap(3);
+ PutWindowTilemap(4);
+ PutWindowTilemap(5);
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ PrintListMenuCursorByID_WithColorIdx(data[0], 1);
+ Subtask_ReturnToTMCaseMain(taskId);
+}
+
+static void Task_InitQuantitySelectUI(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ TMCase_SetWindowBorder1(7);
+ ConvertIntToDecimalStringN(gStringVar1, 1, STR_CONV_MODE_LEADING_ZEROS, 2);
+ StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
+ AddTextPrinterParameterized_ColorByIndex(7, 0, gStringVar4, 4, 10, 1, 0, 0, 1);
+ SellTM_PrintQuantityAndSalePrice(1, itemid_get_market_price(BagGetItemIdByPocketPosition(POCKET_TM_CASE, data[1])) / 2 * data[8]);
+ HandlePrintMoneyOnHand();
+ CreateTMCaseScrollIndicatorArrowPair_SellQuantitySelect();
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ gTasks[taskId].func = Task_QuantitySelect_HandleInput;
+}
+
+static void SellTM_PrintQuantityAndSalePrice(s16 quantity, s32 amount)
+{
+ FillWindowPixelBuffer(7, 0x11);
+ ConvertIntToDecimalStringN(gStringVar1, quantity, STR_CONV_MODE_LEADING_ZEROS, 2);
+ StringExpandPlaceholders(gStringVar4, gText_TimesStrVar1);
+ AddTextPrinterParameterized_ColorByIndex(7, 0, gStringVar4, 4, 10, 1, 0, 0, 1);
+ PrintMoneyAmount(7, 0x38, 0x0A, amount, 0);
+}
+
+static void Task_QuantitySelect_HandleInput(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (sub_80BF848(&data[8], data[2]) == 1)
+ {
+ SellTM_PrintQuantityAndSalePrice(data[8], itemid_get_market_price(BagGetItemIdByPocketPosition(POCKET_TM_CASE, data[1])) / 2 * data[8]);
+ }
+ else if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ ClearMenuWindow(7, 0);
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ RemoveTMCaseScrollIndicatorArrowPair();
+ Task_AskConfirmSaleWithAmount(taskId);
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ ClearMenuWindow(7, 0);
+ ClearMenuWindow(8, 0);
+ ClearMenuWindow_BorderThickness2(6, 0);
+ PutWindowTilemap(3);
+ PutWindowTilemap(0);
+ PutWindowTilemap(1);
+ schedule_bg_copy_tilemap_to_vram(0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ RemoveTMCaseScrollIndicatorArrowPair();
+ PrintListMenuCursorByID_WithColorIdx(data[0], 1);
+ Subtask_ReturnToTMCaseMain(taskId);
+ }
+}
+
+static void Task_PrintSaleConfirmedText(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ PutWindowTilemap(0);
+ schedule_bg_copy_tilemap_to_vram(0);
+ CopyItemName(gSpecialVar_ItemId, gStringVar1);
+ ConvertIntToDecimalStringN(gStringVar3, itemid_get_market_price(BagGetItemIdByPocketPosition(POCKET_TM_CASE, data[1])) / 2 * data[8], STR_CONV_MODE_LEFT_ALIGN, 6);
+ StringExpandPlaceholders(gStringVar4, gText_TurnedOverItemsWorthYen);
+ TMCase_PrintMessageWithFollowupTask(taskId, 2, gStringVar4, Task_DoSaleOfTMs);
+}
+
+static void Task_DoSaleOfTMs(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ PlaySE(0xF8);
+ RemoveBagItem(gSpecialVar_ItemId, data[8]);
+ AddMoney(&gSaveBlock1Ptr->money, itemid_get_market_price(gSpecialVar_ItemId) / 2 * data[8]);
+ sub_809C09C(gSpecialVar_ItemId, data[8], 2);
+ DestroyListMenu(data[0], &sTMCaseStaticResources.scrollOffset, &sTMCaseStaticResources.selectedRow);
+ TMCaseSetup_GetTMCount();
+ TMCaseSetup_InitListMenuPositions();
+ InitTMCaseListMenuItems();
+ data[0] = ListMenuInit(&gMultiuseListMenuTemplate, sTMCaseStaticResources.scrollOffset, sTMCaseStaticResources.selectedRow);
+ PrintListMenuCursorByID_WithColorIdx(data[0], 2);
+ PrintMoneyAmountInMoneyBox(8, GetMoney(&gSaveBlock1Ptr->money), 0);
+ gTasks[taskId].func = Task_AfterSale_ReturnToList;
+}
+
+static void Task_AfterSale_ReturnToList(u8 taskId)
+{
+ if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ ClearMenuWindow(8, 0);
+ ClearMenuWindow_BorderThickness2(6, 0);
+ PutWindowTilemap(1);
+ PutWindowTilemap(3);
+ PutWindowTilemap(4);
+ PutWindowTilemap(5);
+ Subtask_CloseContextMenuAndReturnToMain(taskId);
+ }
+}
+
+void PokeDude_InitTMCase(void)
+{
+ sPokeDudePackBackup = AllocZeroed(sizeof(*sPokeDudePackBackup));
+ memcpy(sPokeDudePackBackup->bagPocket_TMHM, gSaveBlock1Ptr->bagPocket_TMHM, sizeof(gSaveBlock1Ptr->bagPocket_TMHM));
+ memcpy(sPokeDudePackBackup->bagPocket_KeyItems, gSaveBlock1Ptr->bagPocket_KeyItems, sizeof(gSaveBlock1Ptr->bagPocket_KeyItems));
+ sPokeDudePackBackup->unk_160 = sTMCaseStaticResources.selectedRow;
+ sPokeDudePackBackup->unk_162 = sTMCaseStaticResources.scrollOffset;
+ ClearItemSlots(gSaveBlock1Ptr->bagPocket_TMHM, NELEMS(gSaveBlock1Ptr->bagPocket_TMHM));
+ ClearItemSlots(gSaveBlock1Ptr->bagPocket_KeyItems, NELEMS(gSaveBlock1Ptr->bagPocket_KeyItems));
+ ResetTMCaseCursorPos();
+ AddBagItem(ITEM_TM01, 1);
+ AddBagItem(ITEM_TM03, 1);
+ AddBagItem(ITEM_TM09, 1);
+ AddBagItem(ITEM_TM35, 1);
+ InitTMCase(4, CB2_ReturnToTeachyTV, 0);
+}
+
+static void Task_TMCaseDude1(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (!gPaletteFade.active)
+ {
+ data[8] = 0;
+ data[9] = 0;
+ gTasks[taskId].func = Task_TMCaseDude_Playback;
+ }
+}
+
+static void Task_TMCaseDude_Playback(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (JOY_NEW(B_BUTTON))
+ {
+ if (data[8] < 21)
+ {
+ data[8] = 21;
+ SetTeachyTvControllerModeToResume();
+ }
+ }
+
+ switch (data[8])
+ {
+ case 0:
+ BeginNormalPaletteFade(0xFFFF8405, 4, 0, 6, 0);
+ FillBG2RowWithPalette_2timesNplus1(1);
+ data[8]++;
+ break;
+ case 1:
+ case 11:
+ if (!gPaletteFade.active)
+ {
+ data[9]++;
+ if (data[9] > 0x65)
+ {
+ data[9] = 0;
+ data[8]++;
+ }
+ }
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 12:
+ case 13:
+ case 14:
+ if (data[9] == 0)
+ {
+ gMain.newKeys = 0;
+ gMain.newAndRepeatedKeys = DPAD_DOWN;
+ ListMenuHandleInput(data[0]);
+ }
+ data[9]++;
+ if (data[9] > 0x65)
+ {
+ data[9] = 0;
+ data[8]++;
+ }
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 15:
+ case 16:
+ case 17:
+ if (data[9] == 0)
+ {
+ gMain.newKeys = 0;
+ gMain.newAndRepeatedKeys = DPAD_UP;
+ ListMenuHandleInput(data[0]);
+ }
+ data[9]++;
+ if (data[9] > 0x65)
+ {
+ data[9] = 0;
+ data[8]++;
+ }
+ break;
+ case 8:
+ FillBG2RowWithPalette_2timesNplus1(1);
+ TMCase_PrintMessageWithFollowupTask(taskId, 4, gPokeDudeText_TMTypes, 0);
+ gTasks[taskId].func = Task_TMCaseDude_Playback;
+ data[8]++;
+ break;
+ case 9:
+ case 19:
+ RunTextPrinters();
+ if (!IsTextPrinterActive(6))
+ data[8]++;
+ break;
+ case 10:
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ FillBG2RowWithPalette_2timesNplus1(0);
+ BeginNormalPaletteFade(0x00000400, 0, 6, 0, 0);
+ ClearMenuWindow_BorderThickness2(6, 0);
+ schedule_bg_copy_tilemap_to_vram(1);
+ data[8]++;
+ }
+ break;
+ case 18:
+ FillBG2RowWithPalette_2timesNplus1(1);
+ TMCase_PrintMessageWithFollowupTask(taskId, 4, gPokeDudeText_ReadTMDescription, NULL);
+ gTasks[taskId].func = Task_TMCaseDude_Playback; // this function
+ data[8]++;
+ break;
+ case 20:
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ data[8]++;
+ break;
+ case 21:
+ if (!gPaletteFade.active)
+ {
+ memcpy(gSaveBlock1Ptr->bagPocket_TMHM, sPokeDudePackBackup->bagPocket_TMHM, sizeof(gSaveBlock1Ptr->bagPocket_TMHM));
+ memcpy(gSaveBlock1Ptr->bagPocket_KeyItems, sPokeDudePackBackup->bagPocket_KeyItems, sizeof(gSaveBlock1Ptr->bagPocket_KeyItems));
+ DestroyListMenu(data[0], NULL, NULL);
+ sTMCaseStaticResources.selectedRow = sPokeDudePackBackup->unk_160;
+ sTMCaseStaticResources.scrollOffset = sPokeDudePackBackup->unk_162;
+ Free(sPokeDudePackBackup);
+ CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, 0x400);
+ sub_8108CF0();
+ BeginNormalPaletteFade(0xFFFFFFFF, -2, 0, 16, 0);
+ data[8]++;
+ }
+ break;
+ default:
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(sTMCaseStaticResources.savedCallback);
+ RemoveTMCaseScrollIndicatorArrowPair();
+ DestroyTMCaseBuffers();
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+static void InitWindowTemplatesAndPals(void)
+{
+ u8 i;
+
+ InitWindows(sWindowTemplates);
+ DeactivateAllTextPrinters();
+ TextWindow_SetUserSelectedFrame(0, 0x5B, 0xE0);
+ TextWindow_SetBubbleFrame_841F1C8(0, 0x64, 0xB0);
+ TextWindow_SetStdFrame0_WithPal(0, 0x78, 0xD0);
+ LoadPalette(gTMCaseMainWindowPalette, 0xF0, 0x20);
+ LoadPalette(gTMCaseMainWindowPalette, 0xA0, 0x20);
+ LoadPalette(sPal3Override, 0xF6, 0x04);
+ LoadPalette(sPal3Override, 0xD6, 0x04);
+ sub_8107D38(0xc0, 0x01);
+ for (i = 0; i < 9; i++)
+ FillWindowPixelBuffer(i, 0x00);
+ PutWindowTilemap(0);
+ PutWindowTilemap(1);
+ PutWindowTilemap(3);
+ PutWindowTilemap(4);
+ PutWindowTilemap(5);
+ schedule_bg_copy_tilemap_to_vram(0);
+}
+
+static void AddTextPrinterParameterized_ColorByIndex(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, u8 speed, u8 colorIdx)
+{
+ AddTextPrinterParameterized4(windowId, fontId, x, y, letterSpacing, lineSpacing, &sTextColors[colorIdx], speed, str);
+}
+
+static void TMCase_SetWindowBorder1(u8 windowId)
+{
+ SetWindowBorderStyle(windowId, FALSE, 0x5B, 0x0E);
+}
+
+static void TMCase_SetWindowBorder2(u8 windowId)
+{
+ SetWindowBorderStyle(windowId, FALSE, 0x78, 0x0D);
+}
+
+static void TMCase_PrintMessageWithFollowupTask(u8 taskId, u8 windowId, const u8 * str, TaskFunc func)
+{
+ DisplayMessageAndContinueTask(taskId, 6, 0x64, 0x0B, windowId, GetTextSpeedSetting(), str, func);
+ schedule_bg_copy_tilemap_to_vram(1);
+}
+
+static void PrintStringTMCaseOnWindow3(void)
+{
+ u32 distance = 72 - GetStringWidth(1, gText_TMCase, 0);
+ AddTextPrinterParameterized3(3, 1, distance / 2, 1, &sTextColors[0], 0, gText_TMCase);
+}
+
+static void DrawMoveInfoUIMarkers(void)
+{
+ blit_move_info_icon(4, 19, 0, 0);
+ blit_move_info_icon(4, 20, 0, 12);
+ blit_move_info_icon(4, 21, 0, 24);
+ blit_move_info_icon(4, 22, 0, 36);
+ CopyWindowToVram(4, 2);
+}
+
+static void TMCase_MoveCursor_UpdatePrintedTMInfo(u16 itemId)
+{
+ u8 i;
+ u16 move;
+ const u8 * str;
+
+ FillWindowPixelRect(5, 0, 0, 0, 40, 48);
+ if (itemId == ITEM_NONE)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ AddTextPrinterParameterized_ColorByIndex(5, 3, gText_ThreeHyphens, 7, 12 * i, 0, 0, 0xFF, 3);
+ }
+ CopyWindowToVram(5, 2);
+ }
+ else
+ {
+ move = ItemIdToBattleMoveId(itemId);
+ blit_move_info_icon(5, gBattleMoves[move].type + 1, 0, 0);
+ if (gBattleMoves[move].power < 2)
+ str = gText_ThreeHyphens;
+ else
+ {
+ ConvertIntToDecimalStringN(gStringVar1, gBattleMoves[move].power, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ str = gStringVar1;
+ }
+ AddTextPrinterParameterized_ColorByIndex(5, 3, str, 7, 12, 0, 0, 0xFF, 3);
+ if (gBattleMoves[move].accuracy == 0)
+ str = gText_ThreeHyphens;
+ else
+ {
+ ConvertIntToDecimalStringN(gStringVar1, gBattleMoves[move].accuracy, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ str = gStringVar1;
+ }
+ AddTextPrinterParameterized_ColorByIndex(5, 3, str, 7, 24, 0, 0, 0xFF, 3);
+ ConvertIntToDecimalStringN(gStringVar1, gBattleMoves[move].pp, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ AddTextPrinterParameterized_ColorByIndex(5, 3, gStringVar1, 7, 36, 0, 0, 0xFF, 3);
+ CopyWindowToVram(5, 2);
+ }
+}
+
+static void PlaceHMTileInWindow(u8 windowId, u8 x, u8 y)
+{
+ BlitBitmapToWindow(windowId, gUnknown_8E99118, x, y, 16, 12);
+}
+
+static void HandlePrintMoneyOnHand(void)
+{
+ PrintMoneyAmountInMoneyBoxWithBorder(8, 0x78, 0xD, GetMoney(&gSaveBlock1Ptr->money));
+}
+
+static void HandleCreateYesNoMenu(u8 taskId, const struct YesNoFuncTable *ptrs)
+{
+ CreateYesNoMenuWithCallbacks(taskId, &sYesNoWindowTemplate, 2, 0, 2, 0x5B, 0x0E, ptrs);
+}
+
+static u8 AddTMContextMenu(u8 * a0, u8 a1)
+{
+ if (*a0 == 0xFF)
+ {
+ *a0 = AddWindow(&sTMContextWindowTemplates[a1]);
+ TMCase_SetWindowBorder1(*a0);
+ schedule_bg_copy_tilemap_to_vram(0);
+ }
+ return *a0;
+}
+
+static void RemoveTMContextMenu(u8 * a0)
+{
+ ClearMenuWindow(*a0, FALSE);
+ ClearWindowTilemap(*a0);
+ RemoveWindow(*a0);
+ schedule_bg_copy_tilemap_to_vram(0);
+ *a0 = 0xFF;
+}
+
+static u8 CreateTMSprite(u16 itemId)
+{
+ u8 spriteId = CreateSprite(&sTMSpriteTemplate, 0x29, 0x2E, 0);
+ u8 r5;
+ if (itemId == ITEM_NONE)
+ {
+ UpdateTMSpritePosition(&gSprites[spriteId], 0xFF);
+ return spriteId;
+ }
+ else
+ {
+ r5 = itemId - 33;
+ SetTMSpriteAnim(&gSprites[spriteId], r5);
+ TintTMSpriteByType(gBattleMoves[ItemIdToBattleMoveId(itemId)].type);
+ UpdateTMSpritePosition(&gSprites[spriteId], r5);
+ return spriteId;
+ }
+}
+
+static void SetTMSpriteAnim(struct Sprite * sprite, u8 idx)
+{
+ if (idx >= 50)
+ StartSpriteAnim(sprite, 1);
+ else
+ StartSpriteAnim(sprite, 0);
+}
+
+static void TintTMSpriteByType(u8 type)
+{
+ u8 palIndex = IndexOfSpritePaletteTag(TM_CASE_TM_TAG) << 4;
+ LoadPalette(sTMSpritePaletteBuffer + sTMSpritePaletteOffsetByType[type], 0x100 | palIndex, 0x20);
+ if (sTMCaseStaticResources.tmCaseMenuType == 4)
+ {
+ BlendPalettes(1 << (0x10 + palIndex), 4, RGB_BLACK);
+ }
+}
+
+static void UpdateTMSpritePosition(struct Sprite * sprite, u8 var)
+{
+ s32 x, y;
+ if (var == 0xFF)
+ {
+ x = 0x1B;
+ y = 0x36;
+ sprite->pos2.y = 0x14;
+ }
+ else
+ {
+ if (var >= 50)
+ var -= 50;
+ else
+ var += 8;
+ x = 0x29 - (((0xE00 * var) / 58) >> 8);
+ y = 0x2E + (((0x800 * var) / 58) >> 8);
+ }
+ sprite->pos1.x = x;
+ sprite->pos1.y = y;
+}
+
+static void InitSelectedTMSpriteData(u8 spriteId, u16 itemId)
+{
+ gSprites[spriteId].data[0] = itemId;
+ gSprites[spriteId].data[1] = 0;
+ gSprites[spriteId].callback = SpriteCB_MoveTMSpriteInCase;
+}
+
+static void SpriteCB_MoveTMSpriteInCase(struct Sprite * sprite)
+{
+ switch (sprite->data[1])
+ {
+ case 0:
+ if (sprite->pos2.y >= 20)
+ {
+ if (sprite->data[0] != ITEM_NONE)
+ {
+ sprite->data[1]++;
+ TintTMSpriteByType(gBattleMoves[ItemIdToBattleMoveId(sprite->data[0])].type);
+ sprite->data[0] -= ITEM_TM01;
+ SetTMSpriteAnim(sprite, sprite->data[0]);
+ UpdateTMSpritePosition(sprite, sprite->data[0]);
+ }
+ else
+ sprite->callback = SpriteCallbackDummy;
+ }
+ else
+ {
+ sprite->pos2.y += 10;
+ }
+ break;
+ case 1:
+ if (sprite->pos2.y <= 0)
+ sprite->callback = SpriteCallbackDummy;
+ else
+ sprite->pos2.y -= 10;
+ }
+}
+
+static void LoadTMTypePalettes(void)
+{
+ struct SpritePalette spritePalette;
+
+ sTMSpritePaletteBuffer = Alloc(0x110 * sizeof(u16));
+ LZDecompressWram(gUnknown_8E84F20, sTMSpritePaletteBuffer);
+ LZDecompressWram(gUnknown_8E85068, sTMSpritePaletteBuffer + 0x100);
+ spritePalette.data = sTMSpritePaletteBuffer + 0x110;
+ spritePalette.tag = TM_CASE_TM_TAG;
+ LoadSpritePalette(&spritePalette);
+}
diff --git a/src/trainer_pokemon_sprites.c b/src/trainer_pokemon_sprites.c
new file mode 100644
index 000000000..ecd889d80
--- /dev/null
+++ b/src/trainer_pokemon_sprites.c
@@ -0,0 +1,324 @@
+#include "global.h"
+#include "sprite.h"
+#include "window.h"
+#include "malloc.h"
+#include "constants/species.h"
+#include "palette.h"
+#include "decompress.h"
+#include "trainer_pokemon_sprites.h"
+#include "pokemon.h"
+#include "constants/trainer_classes.h"
+
+extern const struct CompressedSpriteSheet gMonFrontPicTable[];
+extern const struct CompressedSpriteSheet gMonBackPicTable[];
+extern const struct CompressedSpriteSheet gTrainerFrontPicTable[];
+extern const struct CompressedSpriteSheet gTrainerBackPicTable[];
+extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[];
+extern const union AnimCmd *const gUnknown_82349BC[];
+extern const union AnimCmd *const *const gTrainerFrontAnimsPtrTable[];
+
+// Static type declarations
+
+struct PicData
+{
+ u8 *frames;
+ struct SpriteFrameImage *images;
+ u16 paletteTag;
+ u8 spriteId;
+ u8 active;
+};
+
+// Static RAM declarations
+#define PICS_COUNT 8
+
+static EWRAM_DATA struct SpriteTemplate sCreatingSpriteTemplate = {};
+static EWRAM_DATA struct PicData sSpritePics[PICS_COUNT] = {};
+
+// Static ROM declarations
+
+// .rodata
+
+static const struct PicData gUnknown_8453178 = {};
+
+static const struct OamData gUnknown_8453184 =
+{
+ .shape = SPRITE_SHAPE(64x64),
+ .size = SPRITE_SIZE(64x64)
+};
+
+// .text
+
+void DummyPicSpriteCallback(struct Sprite *sprite)
+{
+
+}
+
+bool16 ResetAllPicSprites(void)
+{
+ int i;
+
+ for (i = 0; i < PICS_COUNT; i ++)
+ sSpritePics[i] = gUnknown_8453178;
+
+ return FALSE;
+}
+
+static bool16 DecompressPic(u16 species, u32 personality, bool8 isFrontPic, u8 *dest, bool8 isTrainer, bool8 ignoreDeoxys)
+{
+ if (!isTrainer)
+ {
+ if (isFrontPic)
+ {
+ if (!ignoreDeoxys)
+ LoadSpecialPokePic(&gMonFrontPicTable[species], dest, species, personality, isFrontPic);
+ else
+ LoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species], dest, species, personality, isFrontPic);
+ }
+ else
+ {
+ if (!ignoreDeoxys)
+ LoadSpecialPokePic(&gMonBackPicTable[species], dest, species, personality, isFrontPic);
+ else
+ LoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[species], dest, species, personality, isFrontPic);
+ }
+ }
+ else
+ {
+ if (isFrontPic)
+ DecompressPicFromTable(&gTrainerFrontPicTable[species], dest, species);
+ else
+ DecompressPicFromTable(&gTrainerBackPicTable[species], dest, species);
+ }
+ return FALSE;
+}
+
+static bool16 DecompressPic_HandleDeoxys(u16 species, u32 personality, bool8 isFrontPic, u8 *dest, bool8 isTrainer)
+{
+ return DecompressPic(species, personality, isFrontPic, dest, isTrainer, FALSE);
+}
+
+void LoadPicPaletteByTagOrSlot(u16 species, u32 otId, u32 personality, u8 paletteSlot, u16 paletteTag, bool8 isTrainer)
+{
+ if (!isTrainer)
+ {
+ if (paletteTag == 0xFFFF)
+ {
+ sCreatingSpriteTemplate.paletteTag = 0xFFFF;
+ LoadCompressedPalette(GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality), 0x100 + paletteSlot * 0x10, 0x20);
+ }
+ else
+ {
+ sCreatingSpriteTemplate.paletteTag = paletteTag;
+ LoadCompressedObjectPalette(GetMonSpritePalStructFromOtIdPersonality(species, otId, personality));
+ }
+ }
+ else
+ {
+ if (paletteTag == 0xFFFF)
+ {
+ sCreatingSpriteTemplate.paletteTag = 0xFFFF;
+ LoadCompressedPalette(gTrainerFrontPicPaletteTable[species].data, 0x100 + paletteSlot * 0x10, 0x20);
+ }
+ else
+ {
+ sCreatingSpriteTemplate.paletteTag = paletteTag;
+ LoadCompressedObjectPalette(&gTrainerFrontPicPaletteTable[species]);
+ }
+ }
+}
+
+void LoadPicPaletteBySlot(u16 species, u32 otId, u32 personality, u8 paletteSlot, bool8 isTrainer)
+{
+ if (!isTrainer)
+ LoadCompressedPalette(GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality), paletteSlot * 0x10, 0x20);
+ else
+ LoadCompressedPalette(gTrainerFrontPicPaletteTable[species].data, paletteSlot * 0x10, 0x20);
+}
+
+void AssignSpriteAnimsTable(bool8 isTrainer)
+{
+ if (!isTrainer)
+ sCreatingSpriteTemplate.anims = gUnknown_82349BC;
+ else
+ sCreatingSpriteTemplate.anims = gTrainerFrontAnimsPtrTable[0];
+}
+
+u16 CreatePicSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 isTrainer, bool8 ignoreDeoxys)
+{
+ u8 i;
+ u8 *framePics;
+ struct SpriteFrameImage *images;
+ int j;
+ u8 spriteId;
+
+ for (i = 0; i < PICS_COUNT; i ++)
+ {
+ if (!sSpritePics[i].active)
+ {
+ break;
+ }
+ }
+ if (i == PICS_COUNT)
+ {
+ return 0xFFFF;
+ }
+ framePics = Alloc(4 * 0x800);
+ if (!framePics)
+ {
+ return 0xFFFF;
+ }
+ images = Alloc(4 * sizeof(struct SpriteFrameImage));
+ if (!images)
+ {
+ Free(framePics);
+ return 0xFFFF;
+ }
+ if (DecompressPic(species, personality, isFrontPic, framePics, isTrainer, ignoreDeoxys))
+ {
+ // debug trap?
+ return 0xFFFF;
+ }
+ for (j = 0; j < 4; j ++)
+ {
+ images[j].data = framePics + 0x800 * j;
+ images[j].size = 0x800;
+ }
+ sCreatingSpriteTemplate.tileTag = 0xFFFF;
+ sCreatingSpriteTemplate.oam = &gUnknown_8453184;
+ AssignSpriteAnimsTable(isTrainer);
+ sCreatingSpriteTemplate.images = images;
+ sCreatingSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable;
+ sCreatingSpriteTemplate.callback = DummyPicSpriteCallback;
+ LoadPicPaletteByTagOrSlot(species, otId, personality, paletteSlot, paletteTag, isTrainer);
+ spriteId = CreateSprite(&sCreatingSpriteTemplate, x, y, 0);
+ if (paletteTag == 0xFFFF)
+ {
+ gSprites[spriteId].oam.paletteNum = paletteSlot;
+ }
+ sSpritePics[i].frames = framePics;
+ sSpritePics[i].images = images;
+ sSpritePics[i].paletteTag = paletteTag;
+ sSpritePics[i].spriteId = spriteId;
+ sSpritePics[i].active = TRUE;
+ return spriteId;
+}
+
+u16 CreatePicSprite_HandleDeoxys(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 isTrainer)
+{
+ return CreatePicSprite(species, otId, personality, isFrontPic, x, y, paletteSlot, paletteTag, isTrainer, FALSE);
+}
+
+u16 FreeAndDestroyPicSpriteInternal(u16 spriteId)
+{
+ u8 i;
+ u8 *framePics;
+ struct SpriteFrameImage *images;
+
+ for (i = 0; i < PICS_COUNT; i ++)
+ {
+ if (sSpritePics[i].spriteId == spriteId)
+ {
+ break;
+ }
+ }
+ if (i == PICS_COUNT)
+ {
+ return 0xFFFF;
+ }
+ framePics = sSpritePics[i].frames;
+ images = sSpritePics[i].images;
+ if (sSpritePics[i].paletteTag != 0xFFFF)
+ {
+ FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(gSprites[spriteId].oam.paletteNum));
+ }
+ DestroySprite(&gSprites[spriteId]);
+ Free(framePics);
+ Free(images);
+ sSpritePics[i] = gUnknown_8453178;
+ return 0;
+}
+
+u16 sub_810C050(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId, bool8 isTrainer)
+{
+ if (DecompressPic_HandleDeoxys(species, personality, isFrontPic, (u8 *)GetWindowAttribute(windowId, WINDOW_TILE_DATA), FALSE))
+ {
+ return 0xFFFF;
+ }
+ LoadPicPaletteBySlot(species, otId, personality, paletteSlot, isTrainer);
+ return 0;
+}
+
+u16 sub_810C0C0(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId, bool8 isTrainer)
+{
+ u8 *framePics;
+
+ framePics = Alloc(4 * 0x800);
+ if (framePics && !DecompressPic_HandleDeoxys(species, personality, isFrontPic, framePics, isTrainer))
+ {
+ BlitBitmapRectToWindow(windowId, framePics, 0, 0, 0x40, 0x40, destX, destY, 0x40, 0x40);
+ LoadPicPaletteBySlot(species, otId, personality, paletteSlot, isTrainer);
+ Free(framePics);
+ return 0;
+ }
+ return 0xFFFF;
+}
+
+u16 CreateMonPicSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 ignoreDeoxys)
+{
+ return CreatePicSprite(species, otId, personality, isFrontPic, x, y, paletteSlot, paletteTag, FALSE, ignoreDeoxys);
+}
+
+u16 CreateMonPicSprite_HandleDeoxys(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag)
+{
+ return CreateMonPicSprite(species, otId, personality, isFrontPic, x, y, paletteSlot, paletteTag, FALSE);
+}
+
+u16 FreeAndDestroyMonPicSprite(u16 spriteId)
+{
+ return FreeAndDestroyPicSpriteInternal(spriteId);
+}
+
+u16 sub_810C228(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId)
+{
+ return sub_810C0C0(species, otId, personality, isFrontPic, 0, 0, paletteSlot, windowId, FALSE);
+}
+
+u16 sub_810C25C(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId)
+{
+ return sub_810C0C0(species, otId, personality, isFrontPic, destX, destY, paletteSlot, windowId, FALSE);
+}
+
+u16 CreateTrainerPicSprite(u16 species, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag)
+{
+ return CreatePicSprite_HandleDeoxys(species, 0, 0, isFrontPic, x, y, paletteSlot, paletteTag, TRUE);
+}
+
+u16 FreeAndDestroyTrainerPicSprite(u16 spriteId)
+{
+ return FreeAndDestroyPicSpriteInternal(spriteId);
+}
+
+u16 sub_810C2FC(u16 species, bool8 isFrontPic, u8 paletteSlot, u8 windowId)
+{
+ return sub_810C050(species, 0, 0, isFrontPic, paletteSlot, windowId, TRUE);
+}
+
+u16 sub_810C330(u16 species, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId)
+{
+ return sub_810C0C0(species, 0, 0, isFrontPic, destX, destY, paletteSlot, windowId, TRUE);
+}
+
+u16 PlayerGenderToFrontTrainerPicId_Debug(u8 gender, bool8 getClass)
+{
+ if (getClass == TRUE)
+ {
+ switch (gender)
+ {
+ default:
+ return gFacilityClassToPicIndex[0x87];
+ case MALE:
+ return gFacilityClassToPicIndex[0x86];
+ }
+ }
+ return gender;
+}
diff --git a/src/trainer_tower.c b/src/trainer_tower.c
index 91132c07b..ef2a12ce0 100644
--- a/src/trainer_tower.c
+++ b/src/trainer_tower.c
@@ -1,7 +1,10 @@
#include "global.h"
#include "main.h"
+#include "task.h"
#include "constants/flags.h"
#include "constants/vars.h"
+#include "constants/items.h"
+#include "constants/species.h"
#include "malloc.h"
#include "save.h"
#include "util.h"
@@ -11,7 +14,16 @@
#include "cereader_tool.h"
#include "easy_chat.h"
#include "text.h"
+#include "battle_setup.h"
+#include "battle_transition.h"
+#include "battle.h"
+#include "battle_2.h"
#include "overworld.h"
+#include "item.h"
+#include "window.h"
+#include "menu.h"
+#include "new_menu_helpers.h"
+#include "sound.h"
struct UnkStruct_8479D34
{
@@ -23,45 +35,10 @@ struct UnkStruct_8479D34
u8 flags3[8];
};
-struct UnkSubstruct_203F458_000C_004
-{
- /* 0x000 */ u8 unk_000[11];
- /* 0x00B */ u8 unk_00B;
- /* 0x00C */ u8 unk_00C;
- /* 0x00D */ u8 unk_00D;
- /* 0x00E */ u16 unk_00E[6];
- /* 0x01A */ u16 unk_01A[6];
- /* 0x026 */ u16 unk_026[6];
- /* 0x032 */ u16 unk_032[6];
- /* 0x040 */ struct BattleTowerPokemon unk_040[PARTY_SIZE];
-}; // size: 328
-
-struct UnkSubstruct_203F458_000C
-{
- /* 0x000 */ u8 filler_000[2];
- /* 0x002 */ u8 unk_002;
- /* 0x003 */ u8 unk_003;
- /* 0x004 */ struct UnkSubstruct_203F458_000C_004 unk_004[3];
- /* 0x3DC */ u8 filler_3DC[4];
-};
-
-struct Unk_203F458_Header
-{
- u8 unk0;
- u8 unk1;
- u32 unk4;
-};
-
-struct UnkStruct_203F458_SaveBlock
-{
- struct Unk_203F458_Header unk_0000;
- struct UnkSubstruct_203F458_000C unk_0008[8];
-};
-
struct UnkStruct_203F458
{
/* 0x0000 */ u8 unk_0000;
- /* 0x0004 */ struct UnkStruct_203F458_SaveBlock unk_0004;
+ /* 0x0004 */ struct TrainerTowerData unk_0004;
};
struct UnkStruct_203F45C
@@ -92,8 +69,15 @@ struct UnkStruct_847A024
bool8 unk4;
};
+struct UnkStruct_847A074
+{
+ u8 unk0;
+ u8 unk1;
+};
+
EWRAM_DATA struct UnkStruct_203F458 * gUnknown_203F458 = NULL;
EWRAM_DATA struct UnkStruct_203F45C * gUnknown_203F45C = NULL;
+EWRAM_DATA u8 unused_variable = 0;
void sub_815D96C(void);
void sub_815DC8C(void); // setup
@@ -122,38 +106,430 @@ void sub_815E8CC(void);
void sub_815E908(void);
void sub_815E948(void);
void sub_815E9C8(void);
+void sub_815E9FC(void);
+static s32 GetPartyMaxLevel(void);
void sub_815EC0C(void);
+u32 sub_815EDDC(u32 *);
+void sub_815EDF4(u32 *, u32);
-extern const struct UnkStruct_8479D34 gUnknown_8479D34[15];
-extern void (*const gUnknown_847A230[])(void);
-extern const struct Unk_203F458_Header gUnknown_84827AC;
-extern const struct UnkSubstruct_203F458_000C *const gUnknown_84827B4[][8];
-extern const u16 gUnknown_847A284[8][3];
-extern const struct UnkStruct_8479ED8 gUnknown_8479ED8[83];
-extern const struct UnkStruct_847A024 gUnknown_847A024[10];
+extern const u8 gUnknown_83FE982[];
+extern const u8 gUnknown_83FE998[];
+extern const u8 *const gUnknown_83FE9C4[];
-bool32 sub_815D7BC(void * dest, void * buffer)
-{
- if (TryCopySpecialSaveSection(30, buffer) != 1)
- return FALSE;
- memcpy(dest + 0x000, buffer, 0xF88);
+const struct UnkStruct_8479D34 gUnknown_8479D34[] = {
+ {
+ 0x03, 0x26,
+ .flags1 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0x99, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x27,
+ .flags1 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0x9a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x01, 0x1f,
+ .flags1 = {0x4c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x01, 0x22,
+ .flags1 = {0x53, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x41,
+ .flags1 = {0x40, 0x41, 0x42, 0x43, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x01, 0x02,
+ .flags1 = {0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0xff, 0xff},
+ .flags2 = {0x54, 0x55, 0x56, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x01, 0x6d,
+ .flags1 = {0x5b, 0x5d, 0x5e, 0x5f, 0x63, 0x64, 0x65, 0x66},
+ .flags2 = {0x5b, 0x5d, 0x5e, 0x5f, 0x63, 0x64, 0x65, 0xff},
+ .flags3 = {0x5a, 0x5c, 0x60, 0x61, 0x62, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x2e,
+ .flags1 = {0x6b, 0x6c, 0x6d, 0x6e, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0xff, 0xff},
+ .flags3 = {0x6b, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x30,
+ .flags1 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0xa6, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x0f,
+ .flags1 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0xa8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xa9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x39,
+ .flags1 = {0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x36,
+ .flags1 = {0xae, 0xb0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0xaf, 0xb1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x3a,
+ .flags1 = {0xb2, 0xb3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x3b,
+ .flags1 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xb4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ {
+ 0x03, 0x3e,
+ .flags1 = {0xb9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags2 = {0xba, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .flags3 = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+};
- if (TryCopySpecialSaveSection(31, buffer) != 1)
- return FALSE;
- memcpy(dest + 0xF88, buffer, 0xF80);
+const struct UnkStruct_8479ED8 gUnknown_8479ED8[] = {
+ {0x1c, 0x03, 0x01},
+ {0x38, 0x04, 0x00},
+ {0x25, 0x06, 0x01},
+ {0x26, 0x07, 0x00},
+ {0x29, 0x08, 0x00},
+ {0x2a, 0x09, 0x01},
+ {0x34, 0x0a, 0x00},
+ {0x1c, 0x0b, 0x01},
+ {0x1d, 0x0c, 0x01},
+ {0x13, 0x0d, 0x00},
+ {0x34, 0x0e, 0x00},
+ {0x2d, 0x0f, 0x00},
+ {0x36, 0x10, 0x00},
+ {0x1a, 0x11, 0x00},
+ {0x1a, 0x12, 0x00},
+ {0x27, 0x13, 0x00},
+ {0x34, 0x14, 0x00},
+ {0x13, 0x15, 0x00},
+ {0x17, 0x16, 0x01},
+ {0x3d, 0x17, 0x00},
+ {0x13, 0x1d, 0x00},
+ {0x17, 0x1e, 0x01},
+ {0x1e, 0x20, 0x00},
+ {0x1f, 0x21, 0x01},
+ {0x20, 0x22, 0x00},
+ {0x23, 0x23, 0x01},
+ {0x12, 0x24, 0x00},
+ {0x39, 0x26, 0x00},
+ {0x29, 0x2d, 0x00},
+ {0x1a, 0x2e, 0x00},
+ {0x10, 0x2f, 0x00},
+ {0x18, 0x30, 0x01},
+ {0x1d, 0x31, 0x01},
+ {0x2e, 0x32, 0x01},
+ {0x28, 0x33, 0x01},
+ {0x3e, 0x35, 0x00},
+ {0x1b, 0x38, 0x00},
+ {0x19, 0x40, 0x00},
+ {0x1c, 0x41, 0x01},
+ {0x27, 0x42, 0x00},
+ {0x28, 0x43, 0x01},
+ {0x16, 0x47, 0x01},
+ {0x14, 0x48, 0x00},
+ {0x38, 0x49, 0x00},
+ {0x12, 0x58, 0x00},
+ {0x14, 0x59, 0x00},
+ {0x16, 0x5a, 0x01},
+ {0x3e, 0x5b, 0x00},
+ {0x27, 0x5c, 0x00},
+ {0x28, 0x5d, 0x01},
+ {0x34, 0x5e, 0x00},
+ {0x34, 0x5f, 0x00},
+ {0x38, 0x60, 0x00},
+ {0x35, 0x61, 0x00},
+ {0x34, 0x62, 0x00},
+ {0x1e, 0x63, 0x00},
+ {0x39, 0x64, 0x00},
+ {0x2d, 0x65, 0x00},
+ {0x35, 0x66, 0x00},
+ {0x20, 0x67, 0x00},
+ {0x1d, 0x68, 0x01},
+ {0x2e, 0x69, 0x01},
+ {0x13, 0x6a, 0x00},
+ {0x1a, 0x6b, 0x00},
+ {0x1a, 0x6c, 0x00},
+ {0x19, 0x6d, 0x00},
+ {0x1a, 0x6e, 0x00},
+ {0x36, 0x6f, 0x00},
+ {0x37, 0x71, 0x00},
+ {0x29, 0x74, 0x00},
+ {0x2a, 0x75, 0x01},
+ {0x3d, 0x7a, 0x00},
+ {0x3a, 0x7d, 0x01},
+ {0x17, 0x89, 0x01},
+ {0x18, 0x8a, 0x01},
+ {0x25, 0x8b, 0x01},
+ {0x1c, 0x8c, 0x01},
+ {0x27, 0x8d, 0x00},
+ {0x28, 0x8e, 0x01},
+ {0x1c, 0x8f, 0x01},
+ {0x38, 0x90, 0x00},
+ {0x1c, 0x91, 0x01},
+ {0x16, 0x92, 0x01}
+};
- if (!sub_815D6B4(dest))
- return FALSE;
- return TRUE;
-}
+const struct UnkStruct_847A024 gUnknown_847A024[] = {
+ {0x1d, 0x17, 0x1f, 0x01, 0x01},
+ {0x11, 0x11, 0x34, 0x01, 0x01},
+ {0x1d, 0x19, 0x4a, 0x01, 0x00},
+ {0x20, 0x23, 0x4b, 0x00, 0x01},
+ {0x26, 0x2e, 0x4c, 0x00, 0x01},
+ {0x11, 0x11, 0x7e, 0x01, 0x01},
+ {0x29, 0x2a, 0x7f, 0x00, 0x01},
+ {0x1d, 0x19, 0x80, 0x01, 0x00},
+ {0x18, 0x36, 0x81, 0x01, 0x00},
+ {0x2e, 0x26, 0x82, 0x01, 0x00}
+};
-bool32 sub_815D80C(void * dest)
-{
- void * buffer = AllocZeroed(0x1000);
- bool32 success = sub_815D7BC(dest, buffer);
- Free(buffer);
- return success;
-}
+const struct UnkStruct_847A074 gUnknown_847A074[105] = {
+ {0x03, 0x06},
+ {0x37, 0x06},
+ {0x02, 0x06},
+ {0x67, 0x01},
+ {0x04, 0x01},
+ {0x24, 0x04},
+ {0x4a, 0x01},
+ {0x26, 0x01},
+ {0x2a, 0x00},
+ {0x42, 0x03},
+ {0x1b, 0x09},
+ {0x4c, 0x03},
+ {0x44, 0x03},
+ {0x21, 0x04},
+ {0x43, 0x03},
+ {0x6a, 0x01},
+ {0x5d, 0x05},
+ {0x56, 0x05},
+ {0x09, 0x05},
+ {0x11, 0x04},
+ {0x48, 0x03},
+ {0x3c, 0x00},
+ {0x29, 0x00},
+ {0x5c, 0x09},
+ {0x28, 0x09},
+ {0x06, 0x0c},
+ {0x68, 0x0b},
+ {0x05, 0x0b},
+ {0x58, 0x0d},
+ {0x16, 0x0d},
+ {0x46, 0x08},
+ {0x0f, 0x01},
+ {0x3f, 0x03},
+ {0x0e, 0x03},
+ {0x5f, 0x04},
+ {0x63, 0x04},
+ {0x50, 0x04},
+ {0x10, 0x04},
+ {0x52, 0x03},
+ {0x35, 0x04},
+ {0x5b, 0x03},
+ {0x14, 0x03},
+ {0x3d, 0x00},
+ {0x13, 0x00},
+ {0x12, 0x0b},
+ {0x30, 0x07},
+ {0x38, 0x07},
+ {0x2f, 0x07},
+ {0x3b, 0x01},
+ {0x31, 0x01},
+ {0x4e, 0x0b},
+ {0x3a, 0x00},
+ {0x32, 0x00},
+ {0x23, 0x03},
+ {0x0d, 0x0d},
+ {0x0a, 0x03},
+ {0x49, 0x01},
+ {0x0c, 0x01},
+ {0x69, 0x01},
+ {0x0b, 0x01},
+ {0x25, 0x01},
+ {0x3e, 0x02},
+ {0x27, 0x02},
+ {0x65, 0x01},
+ {0x2d, 0x01},
+ {0x61, 0x01},
+ {0x2b, 0x03},
+ {0x66, 0x05},
+ {0x2e, 0x05},
+ {0x2c, 0x00},
+ {0x5e, 0x02},
+ {0x34, 0x02},
+ {0x51, 0x00},
+ {0x59, 0x00},
+ {0x40, 0x03},
+ {0x55, 0x06},
+ {0x53, 0x06},
+ {0x4b, 0x04},
+ {0x15, 0x04},
+ {0x1a, 0x09},
+ {0x57, 0x0a},
+ {0x17, 0x01},
+ {0x47, 0x03},
+ {0x62, 0x01},
+ {0x39, 0x00},
+ {0x1d, 0x00},
+ {0x1c, 0x04},
+ {0x20, 0x00},
+ {0x4f, 0x05},
+ {0x22, 0x05},
+ {0x45, 0x0b},
+ {0x1f, 0x0b},
+ {0x5a, 0x00},
+ {0x1e, 0x00},
+ {0x08, 0x00},
+ {0x64, 0x02},
+ {0x07, 0x02},
+ {0x60, 0x08},
+ {0x36, 0x08},
+ {0x41, 0x0b},
+ {0x33, 0x0b},
+ {0x54, 0x00},
+ {0x18, 0x01},
+ {0x4d, 0x0b},
+ {0x19, 0x00}
+};
+
+const struct WindowTemplate gUnknown_847A218[] = {
+ {0, 3, 1, 27, 18, 15, 0x001},
+ DUMMY_WIN_TEMPLATE
+};
+
+const u32 gUnknown_847A228 = 0x70; // unused
+
+const struct TextColor gUnknown_847A22C = {0, 2, 3};
+
+void (*const gUnknown_847A230[])(void) = {
+ sub_815DD44,
+ sub_815DF54,
+ sub_815E160,
+ sub_815E1C0,
+ sub_815E1F0,
+ sub_815E218,
+ sub_815E28C,
+ sub_815E394,
+ sub_815E408,
+ sub_815E4B0,
+ sub_815E56C,
+ sub_815E5C4,
+ sub_815E5F0,
+ sub_815E658,
+ sub_815E720,
+ sub_815E88C,
+ sub_815E8B4,
+ sub_815E8CC,
+ sub_815E908,
+ sub_815E948,
+ sub_815E9C8
+};
+
+const u16 gUnknown_847A284[8][3] = {
+ {0x012a, 0x016e, 0x0176},
+ {0x012b, 0x016f, 0x0177},
+ {0x012c, 0x0170, 0x0178},
+ {0x012d, 0x0171, 0x0179},
+ {0x012e, 0x0172, 0x017a},
+ {0x012f, 0x0173, 0x017b},
+ {0x0130, 0x0174, 0x017c},
+ {0x0131, 0x0175, 0x017d}
+};
+
+const u16 gUnknown_847A2B4[] = {
+ ITEM_HP_UP,
+ ITEM_PROTEIN,
+ ITEM_IRON,
+ ITEM_CARBOS,
+ ITEM_CALCIUM,
+ ITEM_ZINC,
+ ITEM_BRIGHT_POWDER,
+ ITEM_WHITE_HERB,
+ ITEM_MENTAL_HERB,
+ ITEM_CHOICE_BAND,
+ ITEM_KINGS_ROCK,
+ ITEM_SCOPE_LENS,
+ ITEM_METAL_COAT,
+ ITEM_DRAGON_SCALE,
+ ITEM_UP_GRADE
+};
+
+const u16 gUnknown_847A2D2[] = {
+ 0x011d,
+ 0x011c,
+ 0x011c,
+ 0x011b,
+ 0x011d,
+ 0x011d,
+ 0x011b,
+ 0x011b,
+ 0x011d,
+ 0x011c,
+ 0x011d,
+ 0x011d,
+ 0x011d,
+ 0x011d
+};
+
+const u8 gUnknown_847A2EE[][2] = {
+ {0x00, 0x02},
+ {0x01, 0x03},
+ {0x02, 0x04},
+ {0x03, 0x05},
+ {0x04, 0x01},
+ {0x05, 0x02},
+ {0x00, 0x03},
+ {0x01, 0x04}
+};
+
+const u8 gUnknown_847A2FE[][2] = {
+ {0x00, 0x01},
+ {0x01, 0x03},
+ {0x02, 0x00},
+ {0x03, 0x04},
+ {0x04, 0x02},
+ {0x05, 0x02},
+ {0x00, 0x03},
+ {0x01, 0x05}
+};
+
+const u8 gUnknown_847A30E[][3] = {
+ {0x00, 0x02, 0x04},
+ {0x01, 0x03, 0x05},
+ {0x02, 0x03, 0x01},
+ {0x03, 0x04, 0x00},
+ {0x04, 0x01, 0x02},
+ {0x05, 0x00, 0x03},
+ {0x00, 0x05, 0x02},
+ {0x01, 0x04, 0x05}
+};
+
+extern const struct Unk_203F458_Header gUnknown_84827AC;
+extern const struct TrainerTowerTrainer *const gUnknown_84827B4[][8];
bool32 sub_815D834(void)
{
@@ -263,24 +639,24 @@ void sub_815DA54(void)
sub_815DC8C();
gUnknown_203F45C = AllocZeroed(sizeof(*gUnknown_203F45C));
r10 = VarGet(VAR_0x4001);
- StringCopyN(gUnknown_203F45C->unk_00, gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r10].unk_000, 11);
+ StringCopyN(gUnknown_203F45C->unk_00, gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r10].unk_000, 11);
for (r9 = 0; r9 < 6; r9++)
{
- gUnknown_203F45C->unk_0C[r9] = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r10].unk_01A[r9];
- gUnknown_203F45C->unk_18[r9] = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r10].unk_026[r9];
+ gUnknown_203F45C->unk_0C[r9] = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r10].unk_01A[r9];
+ gUnknown_203F45C->unk_18[r9] = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r10].unk_026[r9];
- if (gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_002 == 1)
+ if (gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_002 == 1)
{
- gUnknown_203F45C->unk_24[r9] = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r10 + 1].unk_01A[r9];
- gUnknown_203F45C->unk_30[r9] = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r10 + 1].unk_026[r9];
+ gUnknown_203F45C->unk_24[r9] = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r10 + 1].unk_01A[r9];
+ gUnknown_203F45C->unk_30[r9] = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r10 + 1].unk_026[r9];
}
}
- gUnknown_203F45C->unk_3C = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_002;
- gUnknown_203F45C->unk_3D = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r10].unk_00B;
- gUnknown_203F45C->unk_3E = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r10].unk_00C;
- SetVBlankCounter1Ptr(gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx]);
+ gUnknown_203F45C->unk_3C = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_002;
+ gUnknown_203F45C->unk_3D = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r10].unk_00B;
+ gUnknown_203F45C->unk_3E = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r10].unk_00C;
+ SetVBlankCounter1Ptr(&gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0);
sub_815DD2C();
}
@@ -317,12 +693,12 @@ void sub_815DC8C(void) // fakematching
{
u32 whichTimer = gSaveBlock1Ptr->unkArrayIdx;
s32 r4;
- const struct UnkSubstruct_203F458_000C *const * r7;
+ const struct TrainerTowerTrainer *const * r7;
gUnknown_203F458 = AllocZeroed(sizeof(*gUnknown_203F458));
gUnknown_203F458->unk_0000 = gMapHeader.mapDataId - 0x2A;
if (sub_815D834() == TRUE)
- sub_815D80C(&gUnknown_203F458->unk_0004);
+ CEReaderTool_LoadTrainerTower(&gUnknown_203F458->unk_0004);
else
{
struct UnkStruct_203F458 * r0_ = gUnknown_203F458;
@@ -334,12 +710,12 @@ void sub_815DC8C(void) // fakematching
for (r4 = 0; r4 < 8; r4++)
{
void * r0 = gUnknown_203F458;
- r0 = r4 * sizeof(struct UnkSubstruct_203F458_000C) + r0;
- r0 += offsetof(struct UnkStruct_203F458, unk_0004.unk_0008);
- memcpy(r0, r7[r4], sizeof(struct UnkSubstruct_203F458_000C));
+ r0 = r4 * sizeof(struct TrainerTowerTrainer) + r0;
+ r0 += offsetof(struct UnkStruct_203F458, unk_0004.trainers);
+ memcpy(r0, r7[r4], sizeof(struct TrainerTowerTrainer));
// r0[r4] = *r7[r4];
}
- gUnknown_203F458->unk_0004.unk_0000.unk4 = CalcByteArraySum((void *)gUnknown_203F458->unk_0004.unk_0008, sizeof(gUnknown_203F458->unk_0004.unk_0008));
+ gUnknown_203F458->unk_0004.unk4 = CalcByteArraySum((void *)gUnknown_203F458->unk_0004.trainers, sizeof(gUnknown_203F458->unk_0004.trainers));
sub_815EC0C();
}
}
@@ -366,7 +742,7 @@ void sub_815DC8C(void)
"\tbne _0815DCD0\n"
"\tldr r0, [r4]\n"
"\tadds r0, 0x4\n"
- "\tbl sub_815D80C\n"
+ "\tbl CEReaderTool_LoadTrainerTower\n"
"\tb _0815DD18\n"
"\t.align 2, 0\n"
"_0815DCBC: .4byte gSaveBlock1Ptr\n"
@@ -427,15 +803,15 @@ void sub_815DD2C(void)
void sub_815DD44(void)
{
- if (gMapHeader.mapDataId - 0x129 > gUnknown_203F458->unk_0004.unk_0000.unk0)
+ if (gMapHeader.mapDataId - 0x129 > gUnknown_203F458->unk_0004.count)
{
gSpecialVar_Result = 3;
- sub_8055D40(0x132);
+ SetCurrentMapLayout(0x132);
}
else
{
- gSpecialVar_Result = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_002;
- sub_8055D40(gUnknown_847A284[gUnknown_203F458->unk_0000][gSpecialVar_Result]);
+ gSpecialVar_Result = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_002;
+ SetCurrentMapLayout(gUnknown_847A284[gUnknown_203F458->unk_0000][gSpecialVar_Result]);
sub_815DDB0();
}
}
@@ -444,10 +820,10 @@ void sub_815DDB0(void)
{
s32 r3, r4;
u8 r1, r2, r4_;
- switch (gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_002)
+ switch (gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_002)
{
case 0:
- r2 = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[0].unk_00B;
+ r2 = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[0].unk_00B;
for (r3 = 0; r3 < NELEMS(gUnknown_8479ED8); r3++)
{
if (gUnknown_8479ED8[r3].unk1 == r2)
@@ -460,7 +836,7 @@ void sub_815DDB0(void)
VarSet(VAR_0x4011, r1);
break;
case 1:
- r2 = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[0].unk_00B;
+ r2 = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[0].unk_00B;
for (r3 = 0; r3 < NELEMS(gUnknown_847A024); r3++)
{
if (gUnknown_847A024[r3].unk2 == r2)
@@ -482,7 +858,7 @@ void sub_815DDB0(void)
case 2:
for (r4 = 0; r4 < 3; r4++)
{
- r2 = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r4].unk_00B;
+ r2 = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_00B;
for (r3 = 0; r3 < NELEMS(gUnknown_8479ED8); r3++)
{
if (gUnknown_8479ED8[r3].unk1 == r2)
@@ -529,25 +905,25 @@ void sub_815DF54(void)
{
u16 r4 = gSpecialVar_0x8006;
u8 r1;
- u8 r5 = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_002;
+ u8 r5 = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_002;
// HOW DO I MATCH THIS CONTROL FLOW?!?!
- r1 = gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r5 == 1 ? 0 : r4].unk_00B;
+ r1 = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r5 == 1 ? 0 : r4].unk_00B;
switch (gSpecialVar_0x8005)
{
case 2:
sub_815E068(r5, r1);
- sub_815DEFC(gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r4].unk_00E, gStringVar4);
+ sub_815DEFC(gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_00E, gStringVar4);
break;
case 3:
sub_815E068(r5, r1);
- sub_815DEFC(gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r4].unk_01A, gStringVar4);
+ sub_815DEFC(gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_01A, gStringVar4);
break;
case 4:
sub_815E068(r5, r1);
- sub_815DEFC(gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r4].unk_026, gStringVar4);
+ sub_815DEFC(gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_026, gStringVar4);
break;
case 5:
- sub_815DEFC(gUnknown_203F458->unk_0004.unk_0008[gUnknown_203F458->unk_0000].unk_004[r4].unk_032, gStringVar4);
+ sub_815DEFC(gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_032, gStringVar4);
break;
}
}
@@ -692,3 +1068,402 @@ void sub_815DF54(void)
"_0815E064: .4byte gStringVar4");
}
#endif // NONMATCHING
+
+void sub_815E068(u8 battleType, u8 facilityClass)
+{
+ u16 r5 = FALSE;
+ s32 r4;
+ switch (battleType)
+ {
+ case 0:
+ case 2:
+ for (r4 = 0; r4 < NELEMS(gUnknown_8479ED8); r4++)
+ {
+ if (gUnknown_8479ED8[r4].unk1 == facilityClass)
+ break;
+ }
+ if (r4 != NELEMS(gUnknown_8479ED8))
+ r5 = gUnknown_8479ED8[r4].unk2;
+ break;
+ case 1:
+ for (r4 = 0; r4 < NELEMS(gUnknown_847A024); r4++)
+ {
+ if (gUnknown_847A024[r4].unk2 == facilityClass)
+ break;
+ }
+ if (r4 != NELEMS(gUnknown_847A024))
+ {
+ if (VarGet(VAR_0x4003))
+ r5 = gUnknown_847A024[r4].unk4;
+ else
+ r5 = gUnknown_847A024[r4].unk3;
+ }
+ break;
+ }
+ gUnknown_20370DC = gUnknown_20370DA;
+ gUnknown_20370DA = r5;
+}
+
+void sub_815E114(void)
+{
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+}
+
+void sub_815E124(u8 taskId)
+{
+ if (sub_80D08F8() == TRUE)
+ {
+ gMain.savedCallback = sub_815E114;
+ CleanupOverworldWindowsAndTilemaps();
+ SetMainCallback2(sub_800FD9C);
+ DestroyTask(taskId);
+ }
+}
+
+void sub_815E160(void)
+{
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_FACTORY;
+ if (gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_002 == 1)
+ gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
+ gTrainerBattleOpponent_A = 0;
+ sub_815E9FC();
+ CreateTask(sub_815E124, 1);
+ PlayMapChosenOrBattleBGM(0);
+ sub_80D08B8(sub_8080060());
+}
+
+void sub_815E1C0(void)
+{
+ if (!gSpecialVar_0x8005)
+ gSpecialVar_Result = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_002;
+}
+
+void sub_815E1F0(void)
+{
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk8++;
+}
+
+void sub_815E218(void)
+{
+ u16 mapDataId = gMapHeader.mapDataId;
+ if (mapDataId - 0x12A == gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk8 && mapDataId - 0x129 <= gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_001)
+ gSpecialVar_Result = FALSE;
+ else
+ gSpecialVar_Result = TRUE;
+}
+
+void sub_815E28C(void)
+{
+ gSaveBlock1Ptr->unkArrayIdx = gSpecialVar_0x8005;
+ if (gSaveBlock1Ptr->unkArrayIdx >= NELEMS(gSaveBlock1Ptr->unkArray))
+ gSaveBlock1Ptr->unkArrayIdx = 0;
+ sub_815EC0C();
+ if (!sub_815D834())
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_5 = TRUE;
+ else
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_5 = FALSE;
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk8 = 0;
+ SetVBlankCounter1Ptr(&gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0);
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0 = 0;
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_2 = FALSE;
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_1 = FALSE;
+}
+
+void sub_815E394(void)
+{
+ DisableVBlankCounter1();
+ gSpecialVar_Result = 0;
+ if (gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_2)
+ gSpecialVar_Result++;
+ if (gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_0 && gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_1)
+ gSpecialVar_Result++;
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_2 = TRUE;
+}
+
+void sub_815E408(void)
+{
+ u16 itemId = gUnknown_847A2B4[gUnknown_203F458->unk_0004.trainers->unk_003];
+ if (gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_0)
+ gSpecialVar_Result = 2;
+ else if (AddBagItem(itemId, 1) == 1)
+ {
+ CopyItemName(itemId, gStringVar2);
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_0 = TRUE;
+ gSpecialVar_Result = 0;
+ }
+ else
+ gSpecialVar_Result = 1;
+}
+
+void sub_815E4B0(void)
+{
+ if (gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_1)
+ gSpecialVar_Result = 2;
+ else if (sub_815EDDC(&gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk4) > gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0)
+ {
+ sub_815EDF4(&gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk4, gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0);
+ gSpecialVar_Result = 0;
+ }
+ else
+ gSpecialVar_Result = 1;
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_1 = TRUE;
+}
+
+void sub_815E56C(void)
+{
+ if (!gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_2)
+ {
+ if (gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0 >= 215999)
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0 = 215999;
+ else
+ SetVBlankCounter1Ptr(&gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0);
+ }
+}
+
+void sub_815E5C4(void)
+{
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_3 = 1;
+}
+
+void sub_815E5F0(void)
+{
+ if (gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_3)
+ {
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_3 = FALSE;
+ gSpecialVar_Result = 0;
+ }
+ else if (gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_4)
+ {
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_4 = FALSE;
+ gSpecialVar_Result = 1;
+ }
+ else
+ {
+ gSpecialVar_Result = 2;
+ }
+}
+
+#define PRINT_TOWER_TIME(src) ({ \
+ s32 minutes, seconds, centiseconds, frames; \
+ \
+ frames = (src); \
+ \
+ minutes = frames / 3600; \
+ frames %= 3600; \
+ seconds = frames / 60; \
+ frames %= 60; \
+ centiseconds = frames * 168 / 100; \
+ \
+ ConvertIntToDecimalStringN(gStringVar1, minutes, STR_CONV_MODE_RIGHT_ALIGN, 2); \
+ ConvertIntToDecimalStringN(gStringVar2, seconds, STR_CONV_MODE_RIGHT_ALIGN, 2); \
+ ConvertIntToDecimalStringN(gStringVar3, centiseconds, STR_CONV_MODE_LEADING_ZEROS, 2); \
+})
+
+void sub_815E658(void)
+{
+ if (gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0 >= 215999)
+ {
+ DisableVBlankCounter1();
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0 = 215999;
+ }
+
+ PRINT_TOWER_TIME(gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk0);
+}
+
+void sub_815E720(void)
+{
+ u8 windowId;
+ s32 i;
+ s32 minutes, seconds, centiseconds;
+
+ sub_815EC0C();
+ windowId = AddWindow(gUnknown_847A218);
+ sub_80F6E9C();
+ DrawStdWindowFrame(windowId, FALSE);
+ AddTextPrinterParameterized(windowId, 2, gUnknown_83FE982, 0x4A, 0, 0xFF, NULL);
+
+ for (i = 0; i < 4; i++)
+ {
+ PRINT_TOWER_TIME(sub_815EDDC(&gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk4));
+
+ StringExpandPlaceholders(gStringVar4, gUnknown_83FE998);
+ AddTextPrinterParameterized(windowId, 2, gUnknown_83FE9C4[i - 1], 0x18, 0x24 + 0x14 * i, 0xFF, NULL);
+ AddTextPrinterParameterized(windowId, 2, gStringVar4, 0x60, 0x2E + 0x14 * i, 0xFF, NULL);
+ }
+
+ PutWindowTilemap(windowId);
+ CopyWindowToVram(windowId, 3);
+ VarSet(VAR_0x4001, windowId);
+}
+
+void sub_815E88C(void)
+{
+ u8 windowId = VarGet(VAR_0x4001);
+ ClearMenuWindow(windowId, TRUE);
+ RemoveWindow(windowId);
+}
+
+void sub_815E8B4(void)
+{
+ gSpecialVar_Result = GetMonsStateToDoubles();
+}
+
+void sub_815E8CC(void)
+{
+ if (gUnknown_203F458->unk_0004.count != gUnknown_203F458->unk_0004.trainers[0].unk_001)
+ {
+ ConvertIntToDecimalStringN(gStringVar1, gUnknown_203F458->unk_0004.count, STR_CONV_MODE_LEFT_ALIGN, 1);
+ gSpecialVar_Result = TRUE;
+ }
+ else
+ {
+ gSpecialVar_Result = FALSE;
+ }
+}
+
+void sub_815E908(void)
+{
+ if (gMapHeader.mapDataId == 0x0129 && VarGet(VAR_0x4082) == 0)
+ {
+ gSpecialVar_Result = FALSE;
+ }
+ else
+ {
+ gSpecialVar_Result = FALSE;
+ }
+}
+
+void sub_815E948(void)
+{
+ s32 i;
+ u16 var_4001 = VarGet(VAR_0x4001);
+ u8 r1 = gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[var_4001].unk_00B;
+
+ for (i = 0; i < NELEMS(gUnknown_847A074); i++)
+ {
+ if (gUnknown_847A074[i].unk0 == gFacilityClassToTrainerClass[r1])
+ break;
+ }
+ if (i != NELEMS(gUnknown_847A074))
+ {
+ var_4001 = gUnknown_847A074[i].unk1;
+ }
+ else
+ {
+ var_4001 = 0;
+ }
+ PlayNewMapMusic(gUnknown_847A2D2[var_4001]);
+}
+
+void sub_815E9C8(void)
+{
+ gSpecialVar_Result = gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_2;
+}
+
+void sub_815E9FC(void)
+{
+ u16 r4 = VarGet(VAR_0x4001);
+ s32 r9 = GetPartyMaxLevel();
+ u8 r5 = gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk8;
+ s32 r6;
+ u8 r2;
+
+ ZeroEnemyPartyMons();
+
+ switch (gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_002)
+ {
+ case 0:
+ default:
+ for (r6 = 0; r6 < 2; r6++)
+ {
+ r2 = gUnknown_847A2EE[r5][r6];
+ gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2].level = r9;
+ sub_803E0A4(&gEnemyParty[r6], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2]);
+ }
+ break;
+ case 1:
+ r2 = gUnknown_847A2FE[r5][0];
+ gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[0].unk_040[r2].level = r9;
+ sub_803E0A4(&gEnemyParty[0], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[0].unk_040[r2]);
+ r2 = gUnknown_847A2FE[r5][1];
+ gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[1].unk_040[r2].level = r9;
+ sub_803E0A4(&gEnemyParty[1], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[1].unk_040[r2]);
+ break;
+ case 2:
+ r2 = gUnknown_847A30E[r5][r4];
+ gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2].level = r9;
+ sub_803E0A4(&gEnemyParty[0], &gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_004[r4].unk_040[r2]);
+ break;
+ }
+}
+
+static s32 GetPartyMaxLevel(void)
+{
+ s32 topLevel = 0;
+ s32 i;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) != 0 && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_EGG)
+ {
+ s32 currLevel = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL, NULL);
+ if (currLevel > topLevel)
+ topLevel = currLevel;
+ }
+ }
+
+ return topLevel;
+}
+
+void sub_815EC0C(void)
+{
+ if (gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk9 != gUnknown_203F458->unk_0004.id)
+ {
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk9 = gUnknown_203F458->unk_0004.id;
+ sub_815EDF4(&gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unk4, 215999);
+ gSaveBlock1Ptr->unkArray[gSaveBlock1Ptr->unkArrayIdx].unkA_0 = FALSE;
+ }
+}
+
+void sub_815EC8C(void)
+{
+ s32 i;
+ u8 windowId = 0;
+
+ sub_815DC8C();
+ FillWindowPixelRect(0, 0, 0, 0, 0xd8, 0x90);
+ sub_815EC0C();
+ AddTextPrinterParameterized3(0, 2, 0x4a, 0, &gUnknown_847A22C, 0, gUnknown_83FE982);
+
+ for (i = 0; i < 4; i++)
+ {
+ PRINT_TOWER_TIME(sub_815EDDC(&gSaveBlock1Ptr->unkArray[i].unk4));
+ StringExpandPlaceholders(gStringVar4, gUnknown_83FE998);
+ AddTextPrinterParameterized3(windowId, 2, 0x18, 0x24 + 0x14 * i, &gUnknown_847A22C, 0, gUnknown_83FE9C4[i]);
+ AddTextPrinterParameterized3(windowId, 2, 0x60, 0x24 + 0x14 * i, &gUnknown_847A22C, 0, gStringVar4);
+ }
+
+ PutWindowTilemap(windowId);
+ CopyWindowToVram(windowId, 3);
+ sub_815DD2C();
+}
+
+u32 sub_815EDDC(u32 * counter)
+{
+ return *counter ^ gSaveBlock2Ptr->encryptionKey;
+}
+
+void sub_815EDF4(u32 * counter, u32 value)
+{
+ *counter = value ^ gSaveBlock2Ptr->encryptionKey;
+}
+
+void sub_815EE0C(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ sub_815EDF4(&gSaveBlock1Ptr->unkArray[i].unk4, 215999);
+ }
+}
diff --git a/src/trig.c b/src/trig.c
new file mode 100644
index 000000000..c2bca3059
--- /dev/null
+++ b/src/trig.c
@@ -0,0 +1,543 @@
+#include "global.h"
+#include "trig.h"
+
+// Values of sin(x*(π/128)) as Q8.8 fixed-point numbers from x = 0 to x = 319
+const s16 gSineTable[] =
+{
+ Q_8_8(0), // sin(0*(π/128))
+ Q_8_8(0.0234375), // sin(1*(π/128))
+ Q_8_8(0.046875), // sin(2*(π/128))
+ Q_8_8(0.0703125), // sin(3*(π/128))
+ Q_8_8(0.09765625), // sin(4*(π/128))
+ Q_8_8(0.12109375), // sin(5*(π/128))
+ Q_8_8(0.14453125), // sin(6*(π/128))
+ Q_8_8(0.16796875), // sin(7*(π/128))
+ Q_8_8(0.19140625), // sin(8*(π/128))
+ Q_8_8(0.21875), // sin(9*(π/128))
+ Q_8_8(0.2421875), // sin(10*(π/128))
+ Q_8_8(0.265625), // sin(11*(π/128))
+ Q_8_8(0.2890625), // sin(12*(π/128))
+ Q_8_8(0.3125), // sin(13*(π/128))
+ Q_8_8(0.3359375), // sin(14*(π/128))
+ Q_8_8(0.359375), // sin(15*(π/128))
+ Q_8_8(0.37890625), // sin(16*(π/128))
+ Q_8_8(0.40234375), // sin(17*(π/128))
+ Q_8_8(0.42578125), // sin(18*(π/128))
+ Q_8_8(0.44921875), // sin(19*(π/128))
+ Q_8_8(0.46875), // sin(20*(π/128))
+ Q_8_8(0.4921875), // sin(21*(π/128))
+ Q_8_8(0.51171875), // sin(22*(π/128))
+ Q_8_8(0.53125), // sin(23*(π/128))
+ Q_8_8(0.5546875), // sin(24*(π/128))
+ Q_8_8(0.57421875), // sin(25*(π/128))
+ Q_8_8(0.59375), // sin(26*(π/128))
+ Q_8_8(0.61328125), // sin(27*(π/128))
+ Q_8_8(0.6328125), // sin(28*(π/128))
+ Q_8_8(0.65234375), // sin(29*(π/128))
+ Q_8_8(0.66796875), // sin(30*(π/128))
+ Q_8_8(0.6875), // sin(31*(π/128))
+ Q_8_8(0.70703125), // sin(32*(π/128))
+ Q_8_8(0.72265625), // sin(33*(π/128))
+ Q_8_8(0.73828125), // sin(34*(π/128))
+ Q_8_8(0.75390625), // sin(35*(π/128))
+ Q_8_8(0.76953125), // sin(36*(π/128))
+ Q_8_8(0.78515625), // sin(37*(π/128))
+ Q_8_8(0.80078125), // sin(38*(π/128))
+ Q_8_8(0.81640625), // sin(39*(π/128))
+ Q_8_8(0.828125), // sin(40*(π/128))
+ Q_8_8(0.84375), // sin(41*(π/128))
+ Q_8_8(0.85546875), // sin(42*(π/128))
+ Q_8_8(0.8671875), // sin(43*(π/128))
+ Q_8_8(0.87890625), // sin(44*(π/128))
+ Q_8_8(0.890625), // sin(45*(π/128))
+ Q_8_8(0.90234375), // sin(46*(π/128))
+ Q_8_8(0.9140625), // sin(47*(π/128))
+ Q_8_8(0.921875), // sin(48*(π/128))
+ Q_8_8(0.9296875), // sin(49*(π/128))
+ Q_8_8(0.94140625), // sin(50*(π/128))
+ Q_8_8(0.94921875), // sin(51*(π/128))
+ Q_8_8(0.953125), // sin(52*(π/128))
+ Q_8_8(0.9609375), // sin(53*(π/128))
+ Q_8_8(0.96875), // sin(54*(π/128))
+ Q_8_8(0.97265625), // sin(55*(π/128))
+ Q_8_8(0.98046875), // sin(56*(π/128))
+ Q_8_8(0.984375), // sin(57*(π/128))
+ Q_8_8(0.98828125), // sin(58*(π/128))
+ Q_8_8(0.9921875), // sin(59*(π/128))
+ Q_8_8(0.9921875), // sin(60*(π/128))
+ Q_8_8(0.99609375), // sin(61*(π/128))
+ Q_8_8(0.99609375), // sin(62*(π/128))
+ Q_8_8(0.99609375), // sin(63*(π/128))
+ Q_8_8(1), // sin(64*(π/128))
+ Q_8_8(0.99609375), // sin(65*(π/128))
+ Q_8_8(0.99609375), // sin(66*(π/128))
+ Q_8_8(0.99609375), // sin(67*(π/128))
+ Q_8_8(0.9921875), // sin(68*(π/128))
+ Q_8_8(0.9921875), // sin(69*(π/128))
+ Q_8_8(0.98828125), // sin(70*(π/128))
+ Q_8_8(0.984375), // sin(71*(π/128))
+ Q_8_8(0.98046875), // sin(72*(π/128))
+ Q_8_8(0.97265625), // sin(73*(π/128))
+ Q_8_8(0.96875), // sin(74*(π/128))
+ Q_8_8(0.9609375), // sin(75*(π/128))
+ Q_8_8(0.953125), // sin(76*(π/128))
+ Q_8_8(0.94921875), // sin(77*(π/128))
+ Q_8_8(0.94140625), // sin(78*(π/128))
+ Q_8_8(0.9296875), // sin(79*(π/128))
+ Q_8_8(0.921875), // sin(80*(π/128))
+ Q_8_8(0.9140625), // sin(81*(π/128))
+ Q_8_8(0.90234375), // sin(82*(π/128))
+ Q_8_8(0.890625), // sin(83*(π/128))
+ Q_8_8(0.87890625), // sin(84*(π/128))
+ Q_8_8(0.8671875), // sin(85*(π/128))
+ Q_8_8(0.85546875), // sin(86*(π/128))
+ Q_8_8(0.84375), // sin(87*(π/128))
+ Q_8_8(0.828125), // sin(88*(π/128))
+ Q_8_8(0.81640625), // sin(89*(π/128))
+ Q_8_8(0.80078125), // sin(90*(π/128))
+ Q_8_8(0.78515625), // sin(91*(π/128))
+ Q_8_8(0.76953125), // sin(92*(π/128))
+ Q_8_8(0.75390625), // sin(93*(π/128))
+ Q_8_8(0.73828125), // sin(94*(π/128))
+ Q_8_8(0.72265625), // sin(95*(π/128))
+ Q_8_8(0.70703125), // sin(96*(π/128))
+ Q_8_8(0.6875), // sin(97*(π/128))
+ Q_8_8(0.66796875), // sin(98*(π/128))
+ Q_8_8(0.65234375), // sin(99*(π/128))
+ Q_8_8(0.6328125), // sin(100*(π/128))
+ Q_8_8(0.61328125), // sin(101*(π/128))
+ Q_8_8(0.59375), // sin(102*(π/128))
+ Q_8_8(0.57421875), // sin(103*(π/128))
+ Q_8_8(0.5546875), // sin(104*(π/128))
+ Q_8_8(0.53125), // sin(105*(π/128))
+ Q_8_8(0.51171875), // sin(106*(π/128))
+ Q_8_8(0.4921875), // sin(107*(π/128))
+ Q_8_8(0.46875), // sin(108*(π/128))
+ Q_8_8(0.44921875), // sin(109*(π/128))
+ Q_8_8(0.42578125), // sin(110*(π/128))
+ Q_8_8(0.40234375), // sin(111*(π/128))
+ Q_8_8(0.37890625), // sin(112*(π/128))
+ Q_8_8(0.359375), // sin(113*(π/128))
+ Q_8_8(0.3359375), // sin(114*(π/128))
+ Q_8_8(0.3125), // sin(115*(π/128))
+ Q_8_8(0.2890625), // sin(116*(π/128))
+ Q_8_8(0.265625), // sin(117*(π/128))
+ Q_8_8(0.2421875), // sin(118*(π/128))
+ Q_8_8(0.21875), // sin(119*(π/128))
+ Q_8_8(0.19140625), // sin(120*(π/128))
+ Q_8_8(0.16796875), // sin(121*(π/128))
+ Q_8_8(0.14453125), // sin(122*(π/128))
+ Q_8_8(0.12109375), // sin(123*(π/128))
+ Q_8_8(0.09765625), // sin(124*(π/128))
+ Q_8_8(0.0703125), // sin(125*(π/128))
+ Q_8_8(0.046875), // sin(126*(π/128))
+ Q_8_8(0.0234375), // sin(127*(π/128))
+ Q_8_8(0), // sin(128*(π/128))
+ Q_8_8(-0.0234375), // sin(129*(π/128))
+ Q_8_8(-0.046875), // sin(130*(π/128))
+ Q_8_8(-0.0703125), // sin(131*(π/128))
+ Q_8_8(-0.09765625), // sin(132*(π/128))
+ Q_8_8(-0.12109375), // sin(133*(π/128))
+ Q_8_8(-0.14453125), // sin(134*(π/128))
+ Q_8_8(-0.16796875), // sin(135*(π/128))
+ Q_8_8(-0.19140625), // sin(136*(π/128))
+ Q_8_8(-0.21875), // sin(137*(π/128))
+ Q_8_8(-0.2421875), // sin(138*(π/128))
+ Q_8_8(-0.265625), // sin(139*(π/128))
+ Q_8_8(-0.2890625), // sin(140*(π/128))
+ Q_8_8(-0.3125), // sin(141*(π/128))
+ Q_8_8(-0.3359375), // sin(142*(π/128))
+ Q_8_8(-0.359375), // sin(143*(π/128))
+ Q_8_8(-0.37890625), // sin(144*(π/128))
+ Q_8_8(-0.40234375), // sin(145*(π/128))
+ Q_8_8(-0.42578125), // sin(146*(π/128))
+ Q_8_8(-0.44921875), // sin(147*(π/128))
+ Q_8_8(-0.46875), // sin(148*(π/128))
+ Q_8_8(-0.4921875), // sin(149*(π/128))
+ Q_8_8(-0.51171875), // sin(150*(π/128))
+ Q_8_8(-0.53125), // sin(151*(π/128))
+ Q_8_8(-0.5546875), // sin(152*(π/128))
+ Q_8_8(-0.57421875), // sin(153*(π/128))
+ Q_8_8(-0.59375), // sin(154*(π/128))
+ Q_8_8(-0.61328125), // sin(155*(π/128))
+ Q_8_8(-0.6328125), // sin(156*(π/128))
+ Q_8_8(-0.65234375), // sin(157*(π/128))
+ Q_8_8(-0.66796875), // sin(158*(π/128))
+ Q_8_8(-0.6875), // sin(159*(π/128))
+ Q_8_8(-0.70703125), // sin(160*(π/128))
+ Q_8_8(-0.72265625), // sin(161*(π/128))
+ Q_8_8(-0.73828125), // sin(162*(π/128))
+ Q_8_8(-0.75390625), // sin(163*(π/128))
+ Q_8_8(-0.76953125), // sin(164*(π/128))
+ Q_8_8(-0.78515625), // sin(165*(π/128))
+ Q_8_8(-0.80078125), // sin(166*(π/128))
+ Q_8_8(-0.81640625), // sin(167*(π/128))
+ Q_8_8(-0.828125), // sin(168*(π/128))
+ Q_8_8(-0.84375), // sin(169*(π/128))
+ Q_8_8(-0.85546875), // sin(170*(π/128))
+ Q_8_8(-0.8671875), // sin(171*(π/128))
+ Q_8_8(-0.87890625), // sin(172*(π/128))
+ Q_8_8(-0.890625), // sin(173*(π/128))
+ Q_8_8(-0.90234375), // sin(174*(π/128))
+ Q_8_8(-0.9140625), // sin(175*(π/128))
+ Q_8_8(-0.921875), // sin(176*(π/128))
+ Q_8_8(-0.9296875), // sin(177*(π/128))
+ Q_8_8(-0.94140625), // sin(178*(π/128))
+ Q_8_8(-0.94921875), // sin(179*(π/128))
+ Q_8_8(-0.953125), // sin(180*(π/128))
+ Q_8_8(-0.9609375), // sin(181*(π/128))
+ Q_8_8(-0.96875), // sin(182*(π/128))
+ Q_8_8(-0.97265625), // sin(183*(π/128))
+ Q_8_8(-0.98046875), // sin(184*(π/128))
+ Q_8_8(-0.984375), // sin(185*(π/128))
+ Q_8_8(-0.98828125), // sin(186*(π/128))
+ Q_8_8(-0.9921875), // sin(187*(π/128))
+ Q_8_8(-0.9921875), // sin(188*(π/128))
+ Q_8_8(-0.99609375), // sin(189*(π/128))
+ Q_8_8(-0.99609375), // sin(190*(π/128))
+ Q_8_8(-0.99609375), // sin(191*(π/128))
+ Q_8_8(-1), // sin(192*(π/128))
+ Q_8_8(-0.99609375), // sin(193*(π/128))
+ Q_8_8(-0.99609375), // sin(194*(π/128))
+ Q_8_8(-0.99609375), // sin(195*(π/128))
+ Q_8_8(-0.9921875), // sin(196*(π/128))
+ Q_8_8(-0.9921875), // sin(197*(π/128))
+ Q_8_8(-0.98828125), // sin(198*(π/128))
+ Q_8_8(-0.984375), // sin(199*(π/128))
+ Q_8_8(-0.98046875), // sin(200*(π/128))
+ Q_8_8(-0.97265625), // sin(201*(π/128))
+ Q_8_8(-0.96875), // sin(202*(π/128))
+ Q_8_8(-0.9609375), // sin(203*(π/128))
+ Q_8_8(-0.953125), // sin(204*(π/128))
+ Q_8_8(-0.94921875), // sin(205*(π/128))
+ Q_8_8(-0.94140625), // sin(206*(π/128))
+ Q_8_8(-0.9296875), // sin(207*(π/128))
+ Q_8_8(-0.921875), // sin(208*(π/128))
+ Q_8_8(-0.9140625), // sin(209*(π/128))
+ Q_8_8(-0.90234375), // sin(210*(π/128))
+ Q_8_8(-0.890625), // sin(211*(π/128))
+ Q_8_8(-0.87890625), // sin(212*(π/128))
+ Q_8_8(-0.8671875), // sin(213*(π/128))
+ Q_8_8(-0.85546875), // sin(214*(π/128))
+ Q_8_8(-0.84375), // sin(215*(π/128))
+ Q_8_8(-0.828125), // sin(216*(π/128))
+ Q_8_8(-0.81640625), // sin(217*(π/128))
+ Q_8_8(-0.80078125), // sin(218*(π/128))
+ Q_8_8(-0.78515625), // sin(219*(π/128))
+ Q_8_8(-0.76953125), // sin(220*(π/128))
+ Q_8_8(-0.75390625), // sin(221*(π/128))
+ Q_8_8(-0.73828125), // sin(222*(π/128))
+ Q_8_8(-0.72265625), // sin(223*(π/128))
+ Q_8_8(-0.70703125), // sin(224*(π/128))
+ Q_8_8(-0.6875), // sin(225*(π/128))
+ Q_8_8(-0.66796875), // sin(226*(π/128))
+ Q_8_8(-0.65234375), // sin(227*(π/128))
+ Q_8_8(-0.6328125), // sin(228*(π/128))
+ Q_8_8(-0.61328125), // sin(229*(π/128))
+ Q_8_8(-0.59375), // sin(230*(π/128))
+ Q_8_8(-0.57421875), // sin(231*(π/128))
+ Q_8_8(-0.5546875), // sin(232*(π/128))
+ Q_8_8(-0.53125), // sin(233*(π/128))
+ Q_8_8(-0.51171875), // sin(234*(π/128))
+ Q_8_8(-0.4921875), // sin(235*(π/128))
+ Q_8_8(-0.46875), // sin(236*(π/128))
+ Q_8_8(-0.44921875), // sin(237*(π/128))
+ Q_8_8(-0.42578125), // sin(238*(π/128))
+ Q_8_8(-0.40234375), // sin(239*(π/128))
+ Q_8_8(-0.37890625), // sin(240*(π/128))
+ Q_8_8(-0.359375), // sin(241*(π/128))
+ Q_8_8(-0.3359375), // sin(242*(π/128))
+ Q_8_8(-0.3125), // sin(243*(π/128))
+ Q_8_8(-0.2890625), // sin(244*(π/128))
+ Q_8_8(-0.265625), // sin(245*(π/128))
+ Q_8_8(-0.2421875), // sin(246*(π/128))
+ Q_8_8(-0.21875), // sin(247*(π/128))
+ Q_8_8(-0.19140625), // sin(248*(π/128))
+ Q_8_8(-0.16796875), // sin(249*(π/128))
+ Q_8_8(-0.14453125), // sin(250*(π/128))
+ Q_8_8(-0.12109375), // sin(251*(π/128))
+ Q_8_8(-0.09765625), // sin(252*(π/128))
+ Q_8_8(-0.0703125), // sin(253*(π/128))
+ Q_8_8(-0.046875), // sin(254*(π/128))
+ Q_8_8(-0.0234375), // sin(255*(π/128))
+ Q_8_8(0), // sin(256*(π/128))
+ Q_8_8(0.0234375), // sin(257*(π/128))
+ Q_8_8(0.046875), // sin(258*(π/128))
+ Q_8_8(0.0703125), // sin(259*(π/128))
+ Q_8_8(0.09765625), // sin(260*(π/128))
+ Q_8_8(0.12109375), // sin(261*(π/128))
+ Q_8_8(0.14453125), // sin(262*(π/128))
+ Q_8_8(0.16796875), // sin(263*(π/128))
+ Q_8_8(0.19140625), // sin(264*(π/128))
+ Q_8_8(0.21875), // sin(265*(π/128))
+ Q_8_8(0.2421875), // sin(266*(π/128))
+ Q_8_8(0.265625), // sin(267*(π/128))
+ Q_8_8(0.2890625), // sin(268*(π/128))
+ Q_8_8(0.3125), // sin(269*(π/128))
+ Q_8_8(0.3359375), // sin(270*(π/128))
+ Q_8_8(0.359375), // sin(271*(π/128))
+ Q_8_8(0.37890625), // sin(272*(π/128))
+ Q_8_8(0.40234375), // sin(273*(π/128))
+ Q_8_8(0.42578125), // sin(274*(π/128))
+ Q_8_8(0.44921875), // sin(275*(π/128))
+ Q_8_8(0.46875), // sin(276*(π/128))
+ Q_8_8(0.4921875), // sin(277*(π/128))
+ Q_8_8(0.51171875), // sin(278*(π/128))
+ Q_8_8(0.53125), // sin(279*(π/128))
+ Q_8_8(0.5546875), // sin(280*(π/128))
+ Q_8_8(0.57421875), // sin(281*(π/128))
+ Q_8_8(0.59375), // sin(282*(π/128))
+ Q_8_8(0.61328125), // sin(283*(π/128))
+ Q_8_8(0.6328125), // sin(284*(π/128))
+ Q_8_8(0.65234375), // sin(285*(π/128))
+ Q_8_8(0.66796875), // sin(286*(π/128))
+ Q_8_8(0.6875), // sin(287*(π/128))
+ Q_8_8(0.70703125), // sin(288*(π/128))
+ Q_8_8(0.72265625), // sin(289*(π/128))
+ Q_8_8(0.73828125), // sin(290*(π/128))
+ Q_8_8(0.75390625), // sin(291*(π/128))
+ Q_8_8(0.76953125), // sin(292*(π/128))
+ Q_8_8(0.78515625), // sin(293*(π/128))
+ Q_8_8(0.80078125), // sin(294*(π/128))
+ Q_8_8(0.81640625), // sin(295*(π/128))
+ Q_8_8(0.828125), // sin(296*(π/128))
+ Q_8_8(0.84375), // sin(297*(π/128))
+ Q_8_8(0.85546875), // sin(298*(π/128))
+ Q_8_8(0.8671875), // sin(299*(π/128))
+ Q_8_8(0.87890625), // sin(300*(π/128))
+ Q_8_8(0.890625), // sin(301*(π/128))
+ Q_8_8(0.90234375), // sin(302*(π/128))
+ Q_8_8(0.9140625), // sin(303*(π/128))
+ Q_8_8(0.921875), // sin(304*(π/128))
+ Q_8_8(0.9296875), // sin(305*(π/128))
+ Q_8_8(0.94140625), // sin(306*(π/128))
+ Q_8_8(0.94921875), // sin(307*(π/128))
+ Q_8_8(0.953125), // sin(308*(π/128))
+ Q_8_8(0.9609375), // sin(309*(π/128))
+ Q_8_8(0.96875), // sin(310*(π/128))
+ Q_8_8(0.97265625), // sin(311*(π/128))
+ Q_8_8(0.98046875), // sin(312*(π/128))
+ Q_8_8(0.984375), // sin(313*(π/128))
+ Q_8_8(0.98828125), // sin(314*(π/128))
+ Q_8_8(0.9921875), // sin(315*(π/128))
+ Q_8_8(0.9921875), // sin(316*(π/128))
+ Q_8_8(0.99609375), // sin(317*(π/128))
+ Q_8_8(0.99609375), // sin(318*(π/128))
+ Q_8_8(0.99609375), // sin(319*(π/128))
+};
+
+// values of sin(x) as Q4.12 fixed-point numbers from x = 0° to x = 179°
+const s16 gSineDegreeTable[] =
+{
+ Q_4_12(0), // sin(0°)
+ Q_4_12(0.017333984375), // sin(1°)
+ Q_4_12(0.034912109375), // sin(2°)
+ Q_4_12(0.05224609375), // sin(3°)
+ Q_4_12(0.06982421875), // sin(4°)
+ Q_4_12(0.087158203125), // sin(5°)
+ Q_4_12(0.1044921875), // sin(6°)
+ Q_4_12(0.121826171875), // sin(7°)
+ Q_4_12(0.13916015625), // sin(8°)
+ Q_4_12(0.156494140625), // sin(9°)
+ Q_4_12(0.173583984375), // sin(10°)
+ Q_4_12(0.19091796875), // sin(11°)
+ Q_4_12(0.2080078125), // sin(12°)
+ Q_4_12(0.224853515625), // sin(13°)
+ Q_4_12(0.241943359375), // sin(14°)
+ Q_4_12(0.2587890625), // sin(15°)
+ Q_4_12(0.275634765625), // sin(16°)
+ Q_4_12(0.29248046875), // sin(17°)
+ Q_4_12(0.30908203125), // sin(18°)
+ Q_4_12(0.32568359375), // sin(19°)
+ Q_4_12(0.342041015625), // sin(20°)
+ Q_4_12(0.3583984375), // sin(21°)
+ Q_4_12(0.37451171875), // sin(22°)
+ Q_4_12(0.390625), // sin(23°)
+ Q_4_12(0.40673828125), // sin(24°)
+ Q_4_12(0.422607421875), // sin(25°)
+ Q_4_12(0.4384765625), // sin(26°)
+ Q_4_12(0.4541015625), // sin(27°)
+ Q_4_12(0.469482421875), // sin(28°)
+ Q_4_12(0.48486328125), // sin(29°)
+ Q_4_12(0.5), // sin(30°)
+ Q_4_12(0.51513671875), // sin(31°)
+ Q_4_12(0.530029296875), // sin(32°)
+ Q_4_12(0.544677734375), // sin(33°)
+ Q_4_12(0.55908203125), // sin(34°)
+ Q_4_12(0.573486328125), // sin(35°)
+ Q_4_12(0.587890625), // sin(36°)
+ Q_4_12(0.601806640625), // sin(37°)
+ Q_4_12(0.61572265625), // sin(38°)
+ Q_4_12(0.62939453125), // sin(39°)
+ Q_4_12(0.642822265625), // sin(40°)
+ Q_4_12(0.656005859375), // sin(41°)
+ Q_4_12(0.669189453125), // sin(42°)
+ Q_4_12(0.681884765625), // sin(43°)
+ Q_4_12(0.694580078125), // sin(44°)
+ Q_4_12(0.70703125), // sin(45°)
+ Q_4_12(0.71923828125), // sin(46°)
+ Q_4_12(0.7314453125), // sin(47°)
+ Q_4_12(0.7431640625), // sin(48°)
+ Q_4_12(0.754638671875), // sin(49°)
+ Q_4_12(0.76611328125), // sin(50°)
+ Q_4_12(0.777099609375), // sin(51°)
+ Q_4_12(0.7880859375), // sin(52°)
+ Q_4_12(0.798583984375), // sin(53°)
+ Q_4_12(0.80908203125), // sin(54°)
+ Q_4_12(0.819091796875), // sin(55°)
+ Q_4_12(0.8291015625), // sin(56°)
+ Q_4_12(0.838623046875), // sin(57°)
+ Q_4_12(0.84814453125), // sin(58°)
+ Q_4_12(0.857177734375), // sin(59°)
+ Q_4_12(0.865966796875), // sin(60°)
+ Q_4_12(0.87451171875), // sin(61°)
+ Q_4_12(0.883056640625), // sin(62°)
+ Q_4_12(0.89111328125), // sin(63°)
+ Q_4_12(0.898681640625), // sin(64°)
+ Q_4_12(0.90625), // sin(65°)
+ Q_4_12(0.91357421875), // sin(66°)
+ Q_4_12(0.92041015625), // sin(67°)
+ Q_4_12(0.92724609375), // sin(68°)
+ Q_4_12(0.93359375), // sin(69°)
+ Q_4_12(0.939697265625), // sin(70°)
+ Q_4_12(0.945556640625), // sin(71°)
+ Q_4_12(0.951171875), // sin(72°)
+ Q_4_12(0.956298828125), // sin(73°)
+ Q_4_12(0.961181640625), // sin(74°)
+ Q_4_12(0.9658203125), // sin(75°)
+ Q_4_12(0.97021484375), // sin(76°)
+ Q_4_12(0.974365234375), // sin(77°)
+ Q_4_12(0.97802734375), // sin(78°)
+ Q_4_12(0.981689453125), // sin(79°)
+ Q_4_12(0.98486328125), // sin(80°)
+ Q_4_12(0.98779296875), // sin(81°)
+ Q_4_12(0.990234375), // sin(82°)
+ Q_4_12(0.992431640625), // sin(83°)
+ Q_4_12(0.994384765625), // sin(84°)
+ Q_4_12(0.99609375), // sin(85°)
+ Q_4_12(0.99755859375), // sin(86°)
+ Q_4_12(0.99853515625), // sin(87°)
+ Q_4_12(0.999267578125), // sin(88°)
+ Q_4_12(0.999755859375), // sin(89°)
+ Q_4_12(1), // sin(90°)
+ Q_4_12(0.999755859375), // sin(91°)
+ Q_4_12(0.999267578125), // sin(92°)
+ Q_4_12(0.99853515625), // sin(93°)
+ Q_4_12(0.99755859375), // sin(94°)
+ Q_4_12(0.99609375), // sin(95°)
+ Q_4_12(0.994384765625), // sin(96°)
+ Q_4_12(0.992431640625), // sin(97°)
+ Q_4_12(0.990234375), // sin(98°)
+ Q_4_12(0.98779296875), // sin(99°)
+ Q_4_12(0.98486328125), // sin(100°)
+ Q_4_12(0.981689453125), // sin(101°)
+ Q_4_12(0.97802734375), // sin(102°)
+ Q_4_12(0.974365234375), // sin(103°)
+ Q_4_12(0.97021484375), // sin(104°)
+ Q_4_12(0.9658203125), // sin(105°)
+ Q_4_12(0.961181640625), // sin(106°)
+ Q_4_12(0.956298828125), // sin(107°)
+ Q_4_12(0.951171875), // sin(108°)
+ Q_4_12(0.945556640625), // sin(109°)
+ Q_4_12(0.939697265625), // sin(110°)
+ Q_4_12(0.93359375), // sin(111°)
+ Q_4_12(0.92724609375), // sin(112°)
+ Q_4_12(0.92041015625), // sin(113°)
+ Q_4_12(0.91357421875), // sin(114°)
+ Q_4_12(0.90625), // sin(115°)
+ Q_4_12(0.898681640625), // sin(116°)
+ Q_4_12(0.89111328125), // sin(117°)
+ Q_4_12(0.883056640625), // sin(118°)
+ Q_4_12(0.87451171875), // sin(119°)
+ Q_4_12(0.865966796875), // sin(120°)
+ Q_4_12(0.857177734375), // sin(121°)
+ Q_4_12(0.84814453125), // sin(122°)
+ Q_4_12(0.838623046875), // sin(123°)
+ Q_4_12(0.8291015625), // sin(124°)
+ Q_4_12(0.819091796875), // sin(125°)
+ Q_4_12(0.80908203125), // sin(126°)
+ Q_4_12(0.798583984375), // sin(127°)
+ Q_4_12(0.7880859375), // sin(128°)
+ Q_4_12(0.777099609375), // sin(129°)
+ Q_4_12(0.76611328125), // sin(130°)
+ Q_4_12(0.754638671875), // sin(131°)
+ Q_4_12(0.7431640625), // sin(132°)
+ Q_4_12(0.7314453125), // sin(133°)
+ Q_4_12(0.71923828125), // sin(134°)
+ Q_4_12(0.70703125), // sin(135°)
+ Q_4_12(0.694580078125), // sin(136°)
+ Q_4_12(0.681884765625), // sin(137°)
+ Q_4_12(0.669189453125), // sin(138°)
+ Q_4_12(0.656005859375), // sin(139°)
+ Q_4_12(0.642822265625), // sin(140°)
+ Q_4_12(0.62939453125), // sin(141°)
+ Q_4_12(0.61572265625), // sin(142°)
+ Q_4_12(0.601806640625), // sin(143°)
+ Q_4_12(0.587890625), // sin(144°)
+ Q_4_12(0.573486328125), // sin(145°)
+ Q_4_12(0.55908203125), // sin(146°)
+ Q_4_12(0.544677734375), // sin(147°)
+ Q_4_12(0.530029296875), // sin(148°)
+ Q_4_12(0.51513671875), // sin(149°)
+ Q_4_12(0.5), // sin(150°)
+ Q_4_12(0.48486328125), // sin(151°)
+ Q_4_12(0.469482421875), // sin(152°)
+ Q_4_12(0.4541015625), // sin(153°)
+ Q_4_12(0.4384765625), // sin(154°)
+ Q_4_12(0.422607421875), // sin(155°)
+ Q_4_12(0.40673828125), // sin(156°)
+ Q_4_12(0.390625), // sin(157°)
+ Q_4_12(0.37451171875), // sin(158°)
+ Q_4_12(0.3583984375), // sin(159°)
+ Q_4_12(0.342041015625), // sin(160°)
+ Q_4_12(0.32568359375), // sin(161°)
+ Q_4_12(0.30908203125), // sin(162°)
+ Q_4_12(0.29248046875), // sin(163°)
+ Q_4_12(0.275634765625), // sin(164°)
+ Q_4_12(0.2587890625), // sin(165°)
+ Q_4_12(0.241943359375), // sin(166°)
+ Q_4_12(0.224853515625), // sin(167°)
+ Q_4_12(0.2080078125), // sin(168°)
+ Q_4_12(0.19091796875), // sin(169°)
+ Q_4_12(0.173583984375), // sin(170°)
+ Q_4_12(0.156494140625), // sin(171°)
+ Q_4_12(0.13916015625), // sin(172°)
+ Q_4_12(0.121826171875), // sin(173°)
+ Q_4_12(0.1044921875), // sin(174°)
+ Q_4_12(0.087158203125), // sin(175°)
+ Q_4_12(0.06982421875), // sin(176°)
+ Q_4_12(0.05224609375), // sin(177°)
+ Q_4_12(0.034912109375), // sin(178°)
+ Q_4_12(0.017333984375), // sin(179°)
+};
+
+// amplitude * sin(index*(π/128))
+s16 Sin(s16 index, s16 amplitude)
+{
+ return (amplitude * gSineTable[index]) >> 8;
+}
+
+// amplitude * cos(index*(π/128))
+s16 Cos(s16 index, s16 amplitude)
+{
+ return (amplitude * gSineTable[index + 64]) >> 8;
+}
+
+// angle in degrees
+s16 Sin2(u16 angle)
+{
+ s32 angleMod = angle % 180;
+ s32 negate = ((angle / 180) & 1);
+ s16 value = gSineDegreeTable[angleMod];
+
+ if (negate)
+ return -value;
+ else
+ return value;
+}
+
+// angle in degrees
+s16 Cos2(u16 angle)
+{
+ return Sin2(angle + 90);
+}
diff --git a/src/unk_8159F40.c b/src/unk_8159F40.c
new file mode 100644
index 000000000..a6f6e67fc
--- /dev/null
+++ b/src/unk_8159F40.c
@@ -0,0 +1,622 @@
+#include "global.h"
+#include "battle.h"
+#include "event_data.h"
+#include "quest_log.h"
+#include "fieldmap.h"
+#include "field_player_avatar.h"
+#include "metatile_behavior.h"
+#include "link.h"
+#include "link_rfu.h"
+
+struct UnkStruct_84792D0
+{
+ u8 field_0;
+ u8 field_1;
+ u16 field_2;
+ u16 field_4[4];
+ u8 field_C;
+ u8 field_D;
+};
+
+extern const struct UnkStruct_84792D0 *const gUnknown_84792D0[];
+
+void sub_8159F40(void)
+{
+ s32 i, j;
+ struct Pokemon *mon;
+ s32 myIdx = 0;
+ s32 opIdx = 0;
+ const struct UnkStruct_84792D0 * data;
+
+ gBattleTypeFlags = BATTLE_TYPE_DOME;
+ ZeroPlayerPartyMons();
+ ZeroEnemyPartyMons();
+ data = gUnknown_84792D0[gSpecialVar_0x8004];
+
+ i = 0;
+ do
+ {
+ if (data[i].field_0 == 0)
+ {
+ mon = &gPlayerParty[myIdx];
+ myIdx++;
+ }
+ else
+ {
+ mon = &gEnemyParty[opIdx];
+ opIdx++;
+ }
+ CreateMonWithGenderNatureLetter(mon, data[i].field_2, data[i].field_1, 0, data[i].field_D, data[i].field_C, 0);
+ for (j = 0; j < 4; j++)
+ {
+ SetMonMoveSlot(mon, data[i].field_4[j], j);
+ }
+ i++;
+ } while (data[i].field_0 != 0xFF);
+}
+
+void sub_815A008(struct QuestLog * questLog)
+{
+ u32 i;
+
+ for (i = 0; i < MAP_OBJECTS_COUNT; i++)
+ {
+ questLog->unk_008[i].active = gMapObjects[i].active;
+ questLog->unk_008[i].mapobj_bit_3 = gMapObjects[i].mapobj_bit_3;
+ questLog->unk_008[i].mapobj_bit_4 = gMapObjects[i].mapobj_bit_4;
+ questLog->unk_008[i].mapobj_bit_5 = gMapObjects[i].mapobj_bit_5;
+ questLog->unk_008[i].mapobj_bit_8 = gMapObjects[i].mapobj_bit_8;
+ questLog->unk_008[i].mapobj_bit_9 = gMapObjects[i].mapobj_bit_9;
+ questLog->unk_008[i].mapobj_bit_10 = gMapObjects[i].mapobj_bit_10;
+ questLog->unk_008[i].mapobj_bit_11 = gMapObjects[i].mapobj_bit_11;
+ questLog->unk_008[i].mapobj_bit_12 = gMapObjects[i].mapobj_bit_12;
+ questLog->unk_008[i].mapobj_bit_13 = gMapObjects[i].mapobj_bit_13;
+ questLog->unk_008[i].mapobj_bit_14 = gMapObjects[i].mapobj_bit_14;
+ questLog->unk_008[i].mapobj_bit_15 = gMapObjects[i].mapobj_bit_15;
+ questLog->unk_008[i].mapobj_bit_16 = gMapObjects[i].mapobj_bit_16;
+ questLog->unk_008[i].mapobj_bit_23 = gMapObjects[i].mapobj_bit_23;
+ questLog->unk_008[i].mapobj_bit_24 = gMapObjects[i].mapobj_bit_24;
+ questLog->unk_008[i].mapobj_bit_25 = gMapObjects[i].mapobj_bit_25;
+ questLog->unk_008[i].mapobj_bit_26 = gMapObjects[i].mapobj_bit_26;
+ questLog->unk_008[i].mapobj_unk_18 = gMapObjects[i].mapobj_unk_18;
+ questLog->unk_008[i].mapobj_unk_0B_0 = gMapObjects[i].mapobj_unk_0B_0;
+ questLog->unk_008[i].elevation = gMapObjects[i].elevation;
+ questLog->unk_008[i].graphicsId = gMapObjects[i].graphicsId;
+ questLog->unk_008[i].animPattern = gMapObjects[i].animPattern;
+ questLog->unk_008[i].trainerType = gMapObjects[i].trainerType;
+ questLog->unk_008[i].localId = gMapObjects[i].localId;
+ questLog->unk_008[i].mapNum = gMapObjects[i].mapNum;
+ questLog->unk_008[i].mapGroup = gMapObjects[i].mapGroup;
+ questLog->unk_008[i].x = gMapObjects[i].coords2.x;
+ questLog->unk_008[i].y = gMapObjects[i].coords2.y;
+ questLog->unk_008[i].trainerRange_berryTreeId = gMapObjects[i].trainerRange_berryTreeId;
+ questLog->unk_008[i].mapobj_unk_1F = gMapObjects[i].mapobj_unk_1F;
+ questLog->unk_008[i].mapobj_unk_21 = gMapObjects[i].mapobj_unk_21;
+ questLog->unk_008[i].animId = gMapObjects[i].animId;
+ }
+}
+
+#ifdef NONMATCHING
+void sub_815A1F8(const struct QuestLog * questLog, const struct MapObjectTemplate * templates)
+{
+ u32 i, j;
+ const struct QuestLogMapObject * questLogMapObjects = questLog->unk_008;
+
+ CpuFill16(0, gMapObjects, sizeof(gMapObjects));
+
+ for (i = 0; i < MAP_OBJECTS_COUNT; i++)
+ {
+ gMapObjects[i].active = questLogMapObjects[i].active;
+ gMapObjects[i].mapobj_bit_3 = questLogMapObjects[i].mapobj_bit_3;
+ gMapObjects[i].mapobj_bit_4 = questLogMapObjects[i].mapobj_bit_4;
+ gMapObjects[i].mapobj_bit_5 = questLogMapObjects[i].mapobj_bit_5;
+ gMapObjects[i].mapobj_bit_8 = questLogMapObjects[i].mapobj_bit_8;
+ gMapObjects[i].mapobj_bit_9 = questLogMapObjects[i].mapobj_bit_9;
+ gMapObjects[i].mapobj_bit_10 = questLogMapObjects[i].mapobj_bit_10;
+ gMapObjects[i].mapobj_bit_11 = questLogMapObjects[i].mapobj_bit_11;
+ gMapObjects[i].mapobj_bit_12 = questLogMapObjects[i].mapobj_bit_12;
+ gMapObjects[i].mapobj_bit_13 = questLogMapObjects[i].mapobj_bit_13;
+ gMapObjects[i].mapobj_bit_14 = questLogMapObjects[i].mapobj_bit_14;
+ gMapObjects[i].mapobj_bit_15 = questLogMapObjects[i].mapobj_bit_15;
+ gMapObjects[i].mapobj_bit_16 = questLogMapObjects[i].mapobj_bit_16;
+ gMapObjects[i].mapobj_bit_23 = questLogMapObjects[i].mapobj_bit_23;
+ gMapObjects[i].mapobj_bit_24 = questLogMapObjects[i].mapobj_bit_24;
+ gMapObjects[i].mapobj_bit_25 = questLogMapObjects[i].mapobj_bit_25;
+ gMapObjects[i].mapobj_bit_26 = questLogMapObjects[i].mapobj_bit_26;
+ gMapObjects[i].mapobj_unk_18 = questLogMapObjects[i].mapobj_unk_18;
+ gMapObjects[i].mapobj_unk_0B_0 = questLogMapObjects[i].mapobj_unk_0B_0;
+ gMapObjects[i].elevation = questLogMapObjects[i].elevation;
+ gMapObjects[i].graphicsId = questLogMapObjects[i].graphicsId;
+ gMapObjects[i].animPattern = questLogMapObjects[i].animPattern;
+ gMapObjects[i].trainerType = questLogMapObjects[i].trainerType;
+ gMapObjects[i].localId = questLogMapObjects[i].localId;
+ gMapObjects[i].mapNum = questLogMapObjects[i].mapNum;
+ gMapObjects[i].mapGroup = questLogMapObjects[i].mapGroup;
+ gMapObjects[i].coords2.x = questLogMapObjects[i].x;
+ gMapObjects[i].coords2.y = questLogMapObjects[i].y;
+ gMapObjects[i].trainerRange_berryTreeId = questLogMapObjects[i].trainerRange_berryTreeId;
+ gMapObjects[i].mapobj_unk_1F = questLogMapObjects[i].mapobj_unk_1F;
+ gMapObjects[i].mapobj_unk_21 = questLogMapObjects[i].mapobj_unk_21;
+ gMapObjects[i].animId = questLogMapObjects[i].animId;
+
+ for (j = 0; j < 0x40; j++)
+ {
+ if (gMapObjects[i].localId == templates[j].localId)
+ {
+ gMapObjects[i].coords1.x = templates[j].x + 7;
+ gMapObjects[i].coords1.y = templates[j].y + 7;
+ gMapObjects[i].range.as_nybbles.x = templates[j].range.as_nybbles.x;
+ gMapObjects[i].range.as_nybbles.y = templates[j].range.as_nybbles.y;
+ }
+ }
+
+ gMapObjects[i].mapobj_unk_1E = MapGridGetMetatileBehaviorAt(gMapObjects[i].coords2.x, gMapObjects[i].coords2.y);
+ if (gMapObjects[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gMapObjects[i].coords2.x), (s16)(gMapObjects[i].coords2.y)))
+ {
+ gMapObjects[i].coords3.x = gMapObjects[i].coords2.x;
+ gMapObjects[i].coords3.y = gMapObjects[i].coords2.y;
+ }
+ else if (gMapObjects[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gMapObjects[i].coords2.x - 1), (s16)(gMapObjects[i].coords2.y)))
+ {
+ gMapObjects[i].coords3.x = gMapObjects[i].coords2.x - 1;
+ gMapObjects[i].coords3.y = gMapObjects[i].coords2.y;
+ }
+ else if (gMapObjects[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gMapObjects[i].coords2.x + 1), (s16)(gMapObjects[i].coords2.y)))
+ {
+ gMapObjects[i].coords3.x = gMapObjects[i].coords2.x + 1;
+ gMapObjects[i].coords3.y = gMapObjects[i].coords2.y;
+ }
+ else if (gMapObjects[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gMapObjects[i].coords2.x), (s16)(gMapObjects[i].coords2.y - 1)))
+ {
+ gMapObjects[i].coords3.x = gMapObjects[i].coords2.x;
+ gMapObjects[i].coords3.y = gMapObjects[i].coords2.y - 1;
+ }
+ else if (gMapObjects[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gMapObjects[i].coords2.x), (s16)(gMapObjects[i].coords2.y + 1)))
+ {
+ gMapObjects[i].coords3.x = gMapObjects[i].coords2.x;
+ gMapObjects[i].coords3.y = gMapObjects[i].coords2.y + 1;
+ }
+ }
+
+ CpuCopy16(gMapObjects, gSaveBlock1Ptr->mapObjects, sizeof(gMapObjects));
+}
+#else
+NAKED
+void sub_815A1F8(const struct QuestLog * questLog, const struct MapObjectTemplate * templates)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmov r7, r10\n"
+ "\tmov r6, r9\n"
+ "\tmov r5, r8\n"
+ "\tpush {r5-r7}\n"
+ "\tsub sp, 0x10\n"
+ "\tstr r1, [sp, 0x4]\n"
+ "\tadds r0, 0x8\n"
+ "\tstr r0, [sp, 0x8]\n"
+ "\tmov r1, sp\n"
+ "\tmovs r0, 0\n"
+ "\tstrh r0, [r1]\n"
+ "\tldr r4, _0815A480 @ =gMapObjects\n"
+ "\tldr r2, _0815A484 @ =0x01000120\n"
+ "\tmov r0, sp\n"
+ "\tadds r1, r4, 0\n"
+ "\tbl CpuSet\n"
+ "\tmovs r0, 0\n"
+ "\tmov r12, r0\n"
+ "\tmovs r1, 0x1\n"
+ "\tmov r10, r1\n"
+ "_0815A224:\n"
+ "\tmov r2, r12\n"
+ "\tlsls r7, r2, 3\n"
+ "\tadds r5, r7, r2\n"
+ "\tlsls r5, 2\n"
+ "\tldr r0, _0815A480 @ =gMapObjects\n"
+ "\tadds r5, r0\n"
+ "\tlsls r6, r2, 2\n"
+ "\tadd r6, r12\n"
+ "\tlsls r6, 2\n"
+ "\tldr r1, [sp, 0x8]\n"
+ "\tadds r6, r1\n"
+ "\tldrb r0, [r6]\n"
+ "\tlsls r0, 31\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r2, r10\n"
+ "\tands r0, r2\n"
+ "\tldrb r2, [r5]\n"
+ "\tmovs r1, 0x2\n"
+ "\tnegs r1, r1\n"
+ "\tands r1, r2\n"
+ "\torrs r1, r0\n"
+ "\tstrb r1, [r5]\n"
+ "\tldrb r0, [r6]\n"
+ "\tlsls r0, 30\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r2, r10\n"
+ "\tands r0, r2\n"
+ "\tlsls r0, 3\n"
+ "\tmovs r2, 0x9\n"
+ "\tnegs r2, r2\n"
+ "\tands r2, r1\n"
+ "\torrs r2, r0\n"
+ "\tstrb r2, [r5]\n"
+ "\tldrb r0, [r6]\n"
+ "\tlsls r0, 29\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r1, r10\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 4\n"
+ "\tmovs r1, 0x11\n"
+ "\tnegs r1, r1\n"
+ "\tands r1, r2\n"
+ "\torrs r1, r0\n"
+ "\tstrb r1, [r5]\n"
+ "\tldrb r0, [r6]\n"
+ "\tlsls r0, 28\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r2, r10\n"
+ "\tands r0, r2\n"
+ "\tlsls r0, 5\n"
+ "\tmovs r4, 0x21\n"
+ "\tnegs r4, r4\n"
+ "\tands r1, r4\n"
+ "\torrs r1, r0\n"
+ "\tstrb r1, [r5]\n"
+ "\tldrb r0, [r6]\n"
+ "\tlsls r0, 27\n"
+ "\tlsrs r0, 31\n"
+ "\tands r0, r2\n"
+ "\tldrb r1, [r5, 0x1]\n"
+ "\tmovs r2, 0x2\n"
+ "\tnegs r2, r2\n"
+ "\tands r2, r1\n"
+ "\torrs r2, r0\n"
+ "\tstrb r2, [r5, 0x1]\n"
+ "\tldrb r0, [r6]\n"
+ "\tlsls r0, 26\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r1, r10\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 1\n"
+ "\tmovs r1, 0x3\n"
+ "\tnegs r1, r1\n"
+ "\tmov r8, r1\n"
+ "\tmov r3, r8\n"
+ "\tands r3, r2\n"
+ "\torrs r3, r0\n"
+ "\tstrb r3, [r5, 0x1]\n"
+ "\tldrb r0, [r6]\n"
+ "\tlsls r0, 25\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r2, r10\n"
+ "\tands r0, r2\n"
+ "\tlsls r0, 2\n"
+ "\tsubs r1, 0x2\n"
+ "\tmov r9, r1\n"
+ "\tands r1, r3\n"
+ "\torrs r1, r0\n"
+ "\tstrb r1, [r5, 0x1]\n"
+ "\tldrb r0, [r6]\n"
+ "\tlsrs r0, 7\n"
+ "\tands r0, r2\n"
+ "\tlsls r0, 3\n"
+ "\tmovs r2, 0x9\n"
+ "\tnegs r2, r2\n"
+ "\tands r2, r1\n"
+ "\torrs r2, r0\n"
+ "\tstrb r2, [r5, 0x1]\n"
+ "\tldrb r0, [r6, 0x1]\n"
+ "\tlsls r0, 31\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r1, r10\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 4\n"
+ "\tmovs r1, 0x11\n"
+ "\tnegs r1, r1\n"
+ "\tands r1, r2\n"
+ "\torrs r1, r0\n"
+ "\tstrb r1, [r5, 0x1]\n"
+ "\tldrb r0, [r6, 0x1]\n"
+ "\tlsls r0, 30\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r2, r10\n"
+ "\tands r0, r2\n"
+ "\tlsls r0, 5\n"
+ "\tands r4, r1\n"
+ "\torrs r4, r0\n"
+ "\tstrb r4, [r5, 0x1]\n"
+ "\tldrb r0, [r6, 0x1]\n"
+ "\tlsls r0, 29\n"
+ "\tlsrs r0, 31\n"
+ "\tands r0, r2\n"
+ "\tlsls r0, 6\n"
+ "\tmovs r2, 0x41\n"
+ "\tnegs r2, r2\n"
+ "\tadds r1, r2, 0\n"
+ "\tands r4, r1\n"
+ "\torrs r4, r0\n"
+ "\tstrb r4, [r5, 0x1]\n"
+ "\tldrb r0, [r6, 0x1]\n"
+ "\tlsls r0, 28\n"
+ "\tlsrs r0, 31\n"
+ "\tlsls r0, 7\n"
+ "\tmovs r3, 0x7F\n"
+ "\tands r4, r3\n"
+ "\torrs r4, r0\n"
+ "\tstrb r4, [r5, 0x1]\n"
+ "\tldrb r0, [r6, 0x1]\n"
+ "\tlsls r0, 27\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r1, r10\n"
+ "\tands r0, r1\n"
+ "\tldrb r2, [r5, 0x2]\n"
+ "\tmovs r1, 0x2\n"
+ "\tnegs r1, r1\n"
+ "\tands r1, r2\n"
+ "\torrs r1, r0\n"
+ "\tstrb r1, [r5, 0x2]\n"
+ "\tldrb r0, [r6, 0x1]\n"
+ "\tlsls r0, 26\n"
+ "\tlsrs r0, 31\n"
+ "\tlsls r0, 7\n"
+ "\tands r1, r3\n"
+ "\torrs r1, r0\n"
+ "\tstrb r1, [r5, 0x2]\n"
+ "\tldrb r0, [r6, 0x1]\n"
+ "\tlsls r0, 25\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r2, r10\n"
+ "\tands r0, r2\n"
+ "\tldrb r2, [r5, 0x3]\n"
+ "\tmovs r1, 0x2\n"
+ "\tnegs r1, r1\n"
+ "\tands r1, r2\n"
+ "\torrs r1, r0\n"
+ "\tstrb r1, [r5, 0x3]\n"
+ "\tldrb r0, [r6, 0x1]\n"
+ "\tlsrs r0, 7\n"
+ "\tmov r2, r10\n"
+ "\tands r0, r2\n"
+ "\tlsls r0, 1\n"
+ "\tmov r2, r8\n"
+ "\tands r2, r1\n"
+ "\torrs r2, r0\n"
+ "\tmov r8, r2\n"
+ "\tstrb r2, [r5, 0x3]\n"
+ "\tldrb r0, [r6, 0x2]\n"
+ "\tlsls r0, 31\n"
+ "\tlsrs r0, 31\n"
+ "\tmov r1, r10\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 2\n"
+ "\tmov r1, r9\n"
+ "\tands r2, r1\n"
+ "\torrs r2, r0\n"
+ "\tstrb r2, [r5, 0x3]\n"
+ "\tldrb r1, [r6, 0x2]\n"
+ "\tlsls r1, 27\n"
+ "\tlsrs r1, 28\n"
+ "\tldrb r2, [r5, 0x18]\n"
+ "\tmovs r4, 0x10\n"
+ "\tnegs r4, r4\n"
+ "\tadds r0, r4, 0\n"
+ "\tands r0, r2\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r5, 0x18]\n"
+ "\tldrb r1, [r6, 0x3]\n"
+ "\tlsls r1, 28\n"
+ "\tmovs r3, 0xF\n"
+ "\tlsrs r1, 28\n"
+ "\tldrb r2, [r5, 0xB]\n"
+ "\tadds r0, r4, 0\n"
+ "\tands r0, r2\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r5, 0xB]\n"
+ "\tldrb r1, [r6, 0x3]\n"
+ "\tlsrs r1, 4\n"
+ "\tlsls r1, 4\n"
+ "\tands r0, r3\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r5, 0xB]\n"
+ "\tldrb r0, [r6, 0x4]\n"
+ "\tstrb r0, [r5, 0x5]\n"
+ "\tldrb r0, [r6, 0x5]\n"
+ "\tstrb r0, [r5, 0x6]\n"
+ "\tldrb r0, [r6, 0x6]\n"
+ "\tstrb r0, [r5, 0x7]\n"
+ "\tldrb r0, [r6, 0x7]\n"
+ "\tstrb r0, [r5, 0x8]\n"
+ "\tldrb r0, [r6, 0x8]\n"
+ "\tstrb r0, [r5, 0x9]\n"
+ "\tldrb r0, [r6, 0x9]\n"
+ "\tstrb r0, [r5, 0xA]\n"
+ "\tldrh r0, [r6, 0xA]\n"
+ "\tstrh r0, [r5, 0x10]\n"
+ "\tldrh r0, [r6, 0xC]\n"
+ "\tstrh r0, [r5, 0x12]\n"
+ "\tldrb r0, [r6, 0xE]\n"
+ "\tstrb r0, [r5, 0x1D]\n"
+ "\tldrb r0, [r6, 0xF]\n"
+ "\tstrb r0, [r5, 0x1F]\n"
+ "\tldrb r0, [r6, 0x10]\n"
+ "\tadds r1, r5, 0\n"
+ "\tadds r1, 0x21\n"
+ "\tstrb r0, [r1]\n"
+ "\tldrb r0, [r6, 0x11]\n"
+ "\tadds r1, 0x1\n"
+ "\tstrb r0, [r1]\n"
+ "\tmovs r6, 0\n"
+ "\tmov r8, r7\n"
+ "\tmov r2, r12\n"
+ "\tadds r2, 0x1\n"
+ "\tstr r2, [sp, 0xC]\n"
+ "\tldrb r7, [r5, 0x8]\n"
+ "\tldr r3, [sp, 0x4]\n"
+ "\tmovs r0, 0xF\n"
+ "\tmov r9, r0\n"
+ "_0815A412:\n"
+ "\tldrb r1, [r3]\n"
+ "\tcmp r7, r1\n"
+ "\tbne _0815A444\n"
+ "\tldrh r0, [r3, 0x4]\n"
+ "\tadds r0, 0x7\n"
+ "\tstrh r0, [r5, 0xC]\n"
+ "\tldrh r0, [r3, 0x6]\n"
+ "\tadds r0, 0x7\n"
+ "\tstrh r0, [r5, 0xE]\n"
+ "\tldrb r1, [r3, 0xA]\n"
+ "\tlsls r1, 28\n"
+ "\tlsrs r1, 28\n"
+ "\tmov r2, r9\n"
+ "\tands r1, r2\n"
+ "\tldrb r0, [r5, 0x19]\n"
+ "\tands r0, r4\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r5, 0x19]\n"
+ "\tldrb r1, [r3, 0xA]\n"
+ "\tlsrs r1, 4\n"
+ "\tlsls r1, 4\n"
+ "\tmovs r2, 0xF\n"
+ "\tands r0, r2\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r5, 0x19]\n"
+ "_0815A444:\n"
+ "\tadds r3, 0x18\n"
+ "\tadds r6, 0x1\n"
+ "\tcmp r6, 0x3F\n"
+ "\tbls _0815A412\n"
+ "\tmov r0, r8\n"
+ "\tadd r0, r12\n"
+ "\tlsls r0, 2\n"
+ "\tldr r1, _0815A480 @ =gMapObjects\n"
+ "\tadds r6, r0, r1\n"
+ "\tmovs r2, 0x10\n"
+ "\tldrsh r0, [r6, r2]\n"
+ "\tmovs r2, 0x12\n"
+ "\tldrsh r1, [r6, r2]\n"
+ "\tbl MapGridGetMetatileBehaviorAt\n"
+ "\tstrb r0, [r6, 0x1E]\n"
+ "\tldrb r4, [r6, 0x1F]\n"
+ "\tmovs r1, 0x10\n"
+ "\tldrsh r0, [r6, r1]\n"
+ "\tmovs r2, 0x12\n"
+ "\tldrsh r1, [r6, r2]\n"
+ "\tbl MapGridGetMetatileBehaviorAt\n"
+ "\tcmp r4, r0\n"
+ "\tbne _0815A488\n"
+ "\tldrh r0, [r6, 0x10]\n"
+ "\tstrh r0, [r6, 0x14]\n"
+ "\tldrh r0, [r6, 0x12]\n"
+ "\tb _0815A506\n"
+ "\t.align 2, 0\n"
+ "_0815A480: .4byte gMapObjects\n"
+ "_0815A484: .4byte 0x01000120\n"
+ "_0815A488:\n"
+ "\tldrb r4, [r6, 0x1F]\n"
+ "\tldrh r0, [r6, 0x10]\n"
+ "\tsubs r0, 0x1\n"
+ "\tlsls r0, 16\n"
+ "\tasrs r0, 16\n"
+ "\tmovs r2, 0x12\n"
+ "\tldrsh r1, [r6, r2]\n"
+ "\tbl MapGridGetMetatileBehaviorAt\n"
+ "\tcmp r4, r0\n"
+ "\tbne _0815A4A8\n"
+ "\tldrh r0, [r6, 0x10]\n"
+ "\tsubs r0, 0x1\n"
+ "\tstrh r0, [r6, 0x14]\n"
+ "\tldrh r0, [r6, 0x12]\n"
+ "\tb _0815A506\n"
+ "_0815A4A8:\n"
+ "\tldrb r4, [r6, 0x1F]\n"
+ "\tldrh r0, [r6, 0x10]\n"
+ "\tadds r0, 0x1\n"
+ "\tlsls r0, 16\n"
+ "\tasrs r0, 16\n"
+ "\tmovs r2, 0x12\n"
+ "\tldrsh r1, [r6, r2]\n"
+ "\tbl MapGridGetMetatileBehaviorAt\n"
+ "\tcmp r4, r0\n"
+ "\tbne _0815A4C8\n"
+ "\tldrh r0, [r6, 0x10]\n"
+ "\tadds r0, 0x1\n"
+ "\tstrh r0, [r6, 0x14]\n"
+ "\tldrh r0, [r6, 0x12]\n"
+ "\tb _0815A506\n"
+ "_0815A4C8:\n"
+ "\tldrb r4, [r6, 0x1F]\n"
+ "\tmovs r1, 0x10\n"
+ "\tldrsh r0, [r6, r1]\n"
+ "\tldrh r1, [r6, 0x12]\n"
+ "\tsubs r1, 0x1\n"
+ "\tlsls r1, 16\n"
+ "\tasrs r1, 16\n"
+ "\tbl MapGridGetMetatileBehaviorAt\n"
+ "\tcmp r4, r0\n"
+ "\tbne _0815A4E8\n"
+ "\tldrh r0, [r6, 0x10]\n"
+ "\tstrh r0, [r6, 0x14]\n"
+ "\tldrh r0, [r6, 0x12]\n"
+ "\tsubs r0, 0x1\n"
+ "\tb _0815A506\n"
+ "_0815A4E8:\n"
+ "\tldrb r4, [r6, 0x1F]\n"
+ "\tmovs r2, 0x10\n"
+ "\tldrsh r0, [r6, r2]\n"
+ "\tldrh r1, [r6, 0x12]\n"
+ "\tadds r1, 0x1\n"
+ "\tlsls r1, 16\n"
+ "\tasrs r1, 16\n"
+ "\tbl MapGridGetMetatileBehaviorAt\n"
+ "\tcmp r4, r0\n"
+ "\tbne _0815A508\n"
+ "\tldrh r0, [r6, 0x10]\n"
+ "\tstrh r0, [r6, 0x14]\n"
+ "\tldrh r0, [r6, 0x12]\n"
+ "\tadds r0, 0x1\n"
+ "_0815A506:\n"
+ "\tstrh r0, [r6, 0x16]\n"
+ "_0815A508:\n"
+ "\tldr r0, [sp, 0xC]\n"
+ "\tmov r12, r0\n"
+ "\tcmp r0, 0xF\n"
+ "\tbhi _0815A512\n"
+ "\tb _0815A224\n"
+ "_0815A512:\n"
+ "\tldr r0, _0815A538 @ =gMapObjects\n"
+ "\tldr r1, _0815A53C @ =gSaveBlock1Ptr\n"
+ "\tldr r1, [r1]\n"
+ "\tmovs r2, 0xD4\n"
+ "\tlsls r2, 3\n"
+ "\tadds r1, r2\n"
+ "\tmovs r2, 0x90\n"
+ "\tlsls r2, 1\n"
+ "\tbl CpuSet\n"
+ "\tadd sp, 0x10\n"
+ "\tpop {r3-r5}\n"
+ "\tmov r8, r3\n"
+ "\tmov r9, r4\n"
+ "\tmov r10, r5\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r0}\n"
+ "\tbx r0\n"
+ "\t.align 2, 0\n"
+ "_0815A538: .4byte gMapObjects\n"
+ "_0815A53C: .4byte gSaveBlock1Ptr");
+}
+#endif // NONMATCHING
+
+void sub_815A540(void)
+{
+ if (gUnknown_203ADFA == 2)
+ {
+ s16 x, y;
+
+ PlayerGetDestCoords(&x, &y);
+ if (!MetatileBehavior_IsSurfable(MapGridGetMetatileBehaviorAt(x, y)) && TestPlayerAvatarFlags(0x08))
+ {
+ struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId];
+ SetPlayerAvatarTransitionFlags(0x01);
+ DestroySprite(&gSprites[mapObject->mapobj_unk_1A]);
+ }
+ }
+}
diff --git a/src/unk_815C980.c b/src/unk_815C980.c
new file mode 100644
index 000000000..b90d2fb03
--- /dev/null
+++ b/src/unk_815C980.c
@@ -0,0 +1,437 @@
+#include "global.h"
+#include "malloc.h"
+#include "decompress.h"
+#include "unk_815C980.h"
+#include "main.h"
+#include "battle.h"
+
+struct UnkStruct2
+{
+ bool8 isActive;
+ u8 firstOamId;
+ u8 field_2;
+ u8 oamCount;
+ u8 palTagIndex;
+ u8 size;
+ u8 shape;
+ u8 priority;
+ u8 xDelta;
+ u8 field_9;
+ u16 tileStart;
+ s16 x;
+ s16 y;
+ u16 tileTag;
+ u16 palTag;
+ u32 field_14;
+ s32 field_18;
+};
+
+struct UnkStruct1
+{
+ u32 count;
+ struct UnkStruct2 *array;
+};
+
+// this file's functions
+static u8 sub_815D244(u8 arg0);;
+static void sub_815CC28(struct UnkStruct2 *arg0);
+static void sub_815CDDC(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2);
+static void sub_815CE90(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2);
+static void sub_815CFEC(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2);
+static bool32 SharesTileWithAnyActive(u32 id);
+static bool32 SharesPalWithAnyActive(u32 id);
+static void sub_8035648(void);
+static u8 sub_815D324(u32 shape, u32 size);
+
+// ewram
+static EWRAM_DATA struct UnkStruct1 *gUnknown_203F454 = {0};
+
+// const rom data
+static const u8 gUnknown_8479658[][4] =
+{
+ {0x01, 0x04, 0x10, 0x40},
+ {0x02, 0x04, 0x08, 0x20},
+ {0x02, 0x04, 0x08, 0x20},
+ {0x00, 0x00, 0x00, 0x00}
+};
+
+// code
+bool32 sub_815C980(u32 count)
+{
+ u32 i;
+
+ if (gUnknown_203F454 != NULL)
+ sub_815C9F4();
+
+ gUnknown_203F454 = Alloc(sizeof(*gUnknown_203F454));
+ if (gUnknown_203F454 == NULL)
+ return FALSE;
+
+ gUnknown_203F454->array = Alloc(sizeof(struct UnkStruct2) * count);
+ if (gUnknown_203F454->array == NULL)
+ {
+ Free(gUnknown_203F454);
+ return FALSE;
+ }
+
+ gUnknown_203F454->count = count;
+ for (i = 0; i < count; i++)
+ {
+ gUnknown_203F454->array[i].isActive = FALSE;
+ gUnknown_203F454->array[i].firstOamId = 0xFF;
+ }
+
+ return TRUE;
+}
+
+void sub_815C9F4(void)
+{
+ if (gUnknown_203F454 != NULL)
+ {
+ if (gUnknown_203F454->array != NULL)
+ {
+ u32 i;
+
+ for (i = 0; i < gUnknown_203F454->count; i++)
+ sub_815D108(i);
+
+ Free(gUnknown_203F454->array);
+ }
+
+ FREE_AND_SET_NULL(gUnknown_203F454);
+ }
+}
+
+bool32 sub_815CA40(u32 id, s32 arg1, const struct UnkStruct3 *arg2)
+{
+ u32 i;
+
+ if (gUnknown_203F454 == NULL)
+ return FALSE;
+ if (gUnknown_203F454->array[id].isActive)
+ return FALSE;
+
+ gUnknown_203F454->array[id].firstOamId = sub_815D244(arg2->field_1);
+ if (gUnknown_203F454->array[id].firstOamId == 0xFF)
+ return FALSE;
+
+ gUnknown_203F454->array[id].tileStart = GetSpriteTileStartByTag(arg2->spriteSheet->tag);
+ if (gUnknown_203F454->array[id].tileStart == 0xFFFF)
+ {
+ if (arg2->spriteSheet->size != 0)
+ {
+ gUnknown_203F454->array[id].tileStart = LoadSpriteSheet(arg2->spriteSheet);
+ }
+ else
+ {
+ struct CompressedSpriteSheet compObjectPic;
+
+ compObjectPic = *(struct CompressedSpriteSheet*)(arg2->spriteSheet);
+ compObjectPic.size = GetDecompressedDataSize(arg2->spriteSheet->data);
+ gUnknown_203F454->array[id].tileStart = LoadCompressedObjectPic(&compObjectPic);
+ }
+
+ if (gUnknown_203F454->array[id].tileStart == 0xFFFF)
+ return FALSE;
+ }
+
+ gUnknown_203F454->array[id].palTagIndex = IndexOfSpritePaletteTag(arg2->spritePal->tag);
+ if (gUnknown_203F454->array[id].palTagIndex == 0xFF)
+ gUnknown_203F454->array[id].palTagIndex = LoadSpritePalette(arg2->spritePal);
+
+ gUnknown_203F454->array[id].field_2 = arg2->field_0_0;
+ gUnknown_203F454->array[id].oamCount = arg2->field_1;
+ gUnknown_203F454->array[id].x = arg2->x;
+ gUnknown_203F454->array[id].y = arg2->y;
+ gUnknown_203F454->array[id].shape = arg2->shape;
+ gUnknown_203F454->array[id].size = arg2->size;
+ gUnknown_203F454->array[id].priority = arg2->priority;
+ gUnknown_203F454->array[id].xDelta = arg2->xDelta;
+ gUnknown_203F454->array[id].field_9 = sub_815D324(arg2->shape, arg2->size);
+ gUnknown_203F454->array[id].tileTag = arg2->spriteSheet->tag;
+ gUnknown_203F454->array[id].palTag = arg2->spritePal->tag;
+ gUnknown_203F454->array[id].isActive = TRUE;
+ gUnknown_203F454->array[id].field_14 = 1;
+
+ for (i = 1; i < arg2->field_1; i++)
+ gUnknown_203F454->array[id].field_14 *= 10;
+
+ sub_815CC28(&gUnknown_203F454->array[id]);
+ sub_815CD70(id, arg1);
+
+ return TRUE;
+}
+
+static void sub_815CC28(struct UnkStruct2 *arg0)
+{
+ u32 i;
+ u32 oamId = arg0->firstOamId;
+ u32 x = arg0->x;
+ u32 oamCount = arg0->oamCount + 1;
+
+ CpuFill16(0, &gMain.oamBuffer[oamId], sizeof(struct OamData) * oamCount);
+ for (i = 0, oamId = arg0->firstOamId; i < oamCount; i++, oamId++)
+ {
+ gMain.oamBuffer[oamId].y = arg0->y;
+ gMain.oamBuffer[oamId].x = x;
+ gMain.oamBuffer[oamId].shape = arg0->shape;
+ gMain.oamBuffer[oamId].size = arg0->size;
+ gMain.oamBuffer[oamId].tileNum = arg0->tileStart;
+ gMain.oamBuffer[oamId].priority = arg0->priority;
+ gMain.oamBuffer[oamId].paletteNum = arg0->palTagIndex;
+
+ x += arg0->xDelta;
+ }
+
+ oamId--;
+ gMain.oamBuffer[oamId].x = arg0->x - arg0->xDelta;
+ gMain.oamBuffer[oamId].affineMode = 2;
+ gMain.oamBuffer[oamId].tileNum = arg0->tileStart + (arg0->field_9 * 10);
+}
+
+void sub_815CD70(u32 id, s32 arg1)
+{
+ bool32 r2;
+
+ if (gUnknown_203F454 == NULL)
+ return;
+ if (!gUnknown_203F454->array[id].isActive)
+ return;
+
+ gUnknown_203F454->array[id].field_18 = arg1;
+ if (arg1 < 0)
+ {
+ r2 = TRUE;
+ arg1 *= -1;
+ }
+ else
+ {
+ r2 = FALSE;
+ }
+
+ switch (gUnknown_203F454->array[id].field_2)
+ {
+ case 0:
+ default:
+ sub_815CDDC(&gUnknown_203F454->array[id], arg1, r2);
+ break;
+ case 1:
+ sub_815CE90(&gUnknown_203F454->array[id], arg1, r2);
+ break;
+ case 2:
+ sub_815CFEC(&gUnknown_203F454->array[id], arg1, r2);
+ break;
+ }
+}
+
+static void sub_815CDDC(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2)
+{
+ u32 r5 = arg0->field_14;
+ u32 oamId = arg0->firstOamId;
+
+ while (r5 != 0)
+ {
+ u32 r4 = arg1 / r5;
+ arg1 -= (r4 * r5);
+ r5 /= 10;
+
+ gMain.oamBuffer[oamId].tileNum = (r4 * arg0->field_9) + arg0->tileStart;
+ oamId++;
+ }
+
+ if (arg2)
+ gMain.oamBuffer[oamId].affineMode = 0;
+ else
+ gMain.oamBuffer[oamId].affineMode = 2;
+}
+
+static void sub_815CE90(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2)
+{
+ u32 r5 = arg0->field_14;
+ static int gUnknown_3002078;
+ static int gUnknown_300207C;
+ static int gUnknown_3002080;
+
+ gUnknown_3002078 = arg0->firstOamId;
+ gUnknown_300207C = 0;
+ gUnknown_3002080 = -1;
+
+ while (r5 != 0)
+ {
+ u32 r4 = arg1 / r5;
+ arg1 -= (r4 * r5);
+ r5 /= 10;
+
+ if (r4 != 0 || gUnknown_3002080 != -1 || r5 == 0)
+ {
+ gMain.oamBuffer[gUnknown_3002078].tileNum = (r4 * arg0->field_9) + arg0->tileStart;
+ gMain.oamBuffer[gUnknown_3002078].affineMode = 0;
+
+ if (gUnknown_3002080 == -1)
+ gUnknown_3002080 = gUnknown_300207C;
+ }
+ else
+ {
+ gMain.oamBuffer[gUnknown_3002078].affineMode = 2;
+ }
+
+ gUnknown_3002078++;
+ gUnknown_300207C++;
+ }
+
+ if (arg2)
+ {
+ gMain.oamBuffer[gUnknown_3002078].affineMode = 0;
+ gMain.oamBuffer[gUnknown_3002078].x = arg0->x + ((gUnknown_3002080 - 1) * arg0->xDelta);
+ }
+ else
+ {
+ gMain.oamBuffer[gUnknown_3002078].affineMode = 2;
+ }
+}
+
+static void sub_815CFEC(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2)
+{
+ u32 r5 = arg0->field_14;
+ u32 oamId = arg0->firstOamId;
+ u32 var_28 = 0;
+ s32 r9 = 0;
+
+ while (r5 != 0)
+ {
+ u32 r4 = arg1 / r5;
+ arg1 -= (r4 * r5);
+ r5 /= 10;
+
+ if (r4 != 0 || var_28 != 0 || r5 == 0)
+ {
+ var_28 = 1;
+ gMain.oamBuffer[oamId].tileNum = (r4 * arg0->field_9) + arg0->tileStart;
+ gMain.oamBuffer[oamId].affineMode = 0;
+
+ oamId++;
+ r9++;
+ }
+ }
+
+ while (r9 < arg0->oamCount)
+ {
+ gMain.oamBuffer[oamId].affineMode = 2;
+ oamId++;
+ r9++;
+ }
+
+ if (arg2)
+ gMain.oamBuffer[oamId].affineMode = 0;
+ else
+ gMain.oamBuffer[oamId].affineMode = 2;
+}
+
+void sub_815D108(u32 id)
+{
+ s32 oamId, oamCount, i;
+
+ if (gUnknown_203F454 == NULL)
+ return;
+ if (!gUnknown_203F454->array[id].isActive)
+ return;
+
+ oamCount = gUnknown_203F454->array[id].oamCount + 1;
+ oamId = gUnknown_203F454->array[id].firstOamId;
+
+ for (i = 0; i < oamCount; i++, oamId++)
+ gMain.oamBuffer[oamId].affineMode = 2;
+
+ if (!SharesTileWithAnyActive(id))
+ FreeSpriteTilesByTag(gUnknown_203F454->array[id].tileTag);
+ if (!SharesPalWithAnyActive(id))
+ FreeSpritePaletteByTag(gUnknown_203F454->array[id].palTag);
+
+ gUnknown_203F454->array[id].isActive = FALSE;
+}
+
+void sub_815D1A8(u32 id, bool32 arg1)
+{
+ s32 oamId, oamCount, i;
+
+ if (gUnknown_203F454 == NULL)
+ return;
+ if (!gUnknown_203F454->array[id].isActive)
+ return;
+
+ oamCount = gUnknown_203F454->array[id].oamCount + 1;
+ oamId = gUnknown_203F454->array[id].firstOamId;
+ if (arg1)
+ {
+ for (i = 0; i < oamCount; i++, oamId++)
+ gMain.oamBuffer[oamId].affineMode = 2;
+ }
+ else
+ {
+ for (i = 0; i < oamCount; i++, oamId++)
+ gMain.oamBuffer[oamId].affineMode = 0;
+
+ sub_815CD70(id, gUnknown_203F454->array[id].field_18);
+ }
+}
+
+static u8 sub_815D244(u8 arg0)
+{
+ u32 i;
+ u16 oamCount = 64;
+
+ for (i = 0; i < gUnknown_203F454->count; i++)
+ {
+ if (!gUnknown_203F454->array[i].isActive)
+ {
+ if (gUnknown_203F454->array[i].firstOamId != 0xFF && gUnknown_203F454->array[i].oamCount <= arg0)
+ return gUnknown_203F454->array[i].firstOamId;
+ }
+ else
+ {
+ oamCount += 1 + gUnknown_203F454->array[i].oamCount;
+ }
+ }
+
+ if (oamCount + arg0 + 1 > 128)
+ return 0xFF;
+ else
+ return oamCount;
+}
+
+static bool32 SharesTileWithAnyActive(u32 id)
+{
+ u32 i;
+
+ for (i = 0; i < gUnknown_203F454->count; i++)
+ {
+ if (gUnknown_203F454->array[i].isActive && i != id
+ && gUnknown_203F454->array[i].tileTag == gUnknown_203F454->array[id].tileTag)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static bool32 SharesPalWithAnyActive(u32 id)
+{
+ u32 i;
+
+ for (i = 0; i < gUnknown_203F454->count; i++)
+ {
+ if (gUnknown_203F454->array[i].isActive && i != id
+ && gUnknown_203F454->array[i].palTag == gUnknown_203F454->array[id].palTag)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static u8 sub_815D324(u32 shape, u32 size)
+{
+ return gUnknown_8479658[shape][size];
+}
diff --git a/src/unk_815F138.c b/src/unk_815F138.c
new file mode 100644
index 000000000..8941f1559
--- /dev/null
+++ b/src/unk_815F138.c
@@ -0,0 +1,322 @@
+#include "global.h"
+#include "decompress.h"
+#include "sound.h"
+#include "task.h"
+#include "trig.h"
+#include "constants/songs.h"
+
+void sub_815F1AC(u8 taskId);
+bool32 sub_815F2AC(u8 spriteId);
+void sub_815F3E0(u8 spriteId1, u8 spriteId2, u8 spriteId3);
+bool32 sub_815F444(u8 spriteId);
+void sub_815F470(struct Sprite * sprite);
+void sub_815F564(u16 tilesTag, u16 palTag);
+u8 sub_815F5BC(u16 tilesTag, u16 palTag, s16 x, s16 y, u8 subpriority);
+void sub_815F610(u16 tilesTag, u16 palTag, s16 x, s16 y, u8 subpriority, s16 * spriteId2_p, s16 * spriteId3_p);
+
+void sub_815F138(u16 tilesTag, u16 palTag, s16 x, s16 y, u8 subpriority)
+{
+ u8 taskId = CreateTask(sub_815F1AC, 80);
+ gTasks[taskId].data[2] = tilesTag;
+ gTasks[taskId].data[3] = palTag;
+ gTasks[taskId].data[4] = x;
+ gTasks[taskId].data[5] = y;
+ gTasks[taskId].data[6] = subpriority;
+}
+
+bool8 sub_815F198(void)
+{
+ return FuncIsActiveTask(sub_815F1AC);
+}
+
+void sub_815F1AC(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ sub_815F564(data[2], data[3]);
+ data[7] = sub_815F5BC(data[2], data[3], data[4], data[5], data[6]);
+ sub_815F610(data[2], data[3], data[4], data[5], data[6], &data[8], &data[9]);
+ data[0]++;
+ break;
+ case 1:
+ if (!sub_815F2AC(data[7]))
+ {
+ sub_815F3E0(data[7], data[8], data[9]);
+ FreeSpriteOamMatrix(&gSprites[data[7]]);
+ DestroySprite(&gSprites[data[7]]);
+ data[0]++;
+ }
+ break;
+ case 2:
+ if (!sub_815F444(data[8]))
+ {
+ DestroySprite(&gSprites[data[8]]);
+ DestroySprite(&gSprites[data[9]]);
+ FreeSpriteTilesByTag(data[2]);
+ FreeSpritePaletteByTag(data[3]);
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+bool32 sub_815F2AC(u8 spriteId)
+{
+ struct Sprite * sprite = &gSprites[spriteId];
+
+ switch (sprite->data[0])
+ {
+ case 0:
+ sub_8007FFC(sprite, 0x800, 0x1A);
+ sprite->data[0]++;
+ // fallthrough
+ case 1:
+ if (sprite->data[2] == 0)
+ PlaySE(SE_TRACK_STOP);
+ if (++sprite->data[2] >= 20)
+ {
+ sprite->data[2] = 0;
+ StartSpriteAffineAnim(sprite, 1);
+ sprite->data[0]++;
+ }
+ break;
+ case 2:
+ if (sprite->affineAnimEnded)
+ sprite->data[0]++;
+ break;
+ case 3:
+ if (++sprite->data[2] >= 4)
+ {
+ sprite->data[2] = 0;
+ sprite->data[0]++;
+ StartSpriteAffineAnim(sprite, 2);
+ }
+ break;
+ case 4:
+ sprite->pos1.y -= 4;
+ if (++sprite->data[2] >= 8)
+ {
+ if (sprite->data[4] < 2)
+ {
+ StartSpriteAnim(sprite, sprite->data[4] + 1);
+ sprite->data[2] = 0;
+ sprite->data[0]++;
+ }
+ else
+ {
+ sprite->data[0] = 7;
+ return FALSE;
+ }
+ }
+ break;
+ case 5:
+ sprite->pos1.y += 4;
+ if (++sprite->data[2] >= 8)
+ {
+ sprite->data[2] = 0;
+ StartSpriteAffineAnim(sprite, 3);
+ sprite->data[0]++;
+ }
+ break;
+ case 6:
+ if (sprite->affineAnimEnded)
+ {
+ sprite->data[4]++;
+ sprite->data[0] = 1;
+ }
+ break;
+ case 7:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void sub_815F3E0(u8 spriteId1, u8 spriteId2, u8 spriteId3)
+{
+ gSprites[spriteId2].pos2.y = -40;
+ gSprites[spriteId3].pos2.y = -40;
+ gSprites[spriteId2].invisible = FALSE;
+ gSprites[spriteId3].invisible = FALSE;
+ gSprites[spriteId2].callback = sub_815F470;
+ gSprites[spriteId3].callback = sub_815F470;
+}
+
+bool32 sub_815F444(u8 spriteId)
+{
+ return gSprites[spriteId].callback == sub_815F470;
+}
+
+void sub_815F470(struct Sprite * sprite)
+{
+ s16 * data = sprite->data;
+ s32 y;
+
+ switch (sprite->data[0])
+ {
+ case 0:
+ data[4] = 64;
+ data[5] = sprite->pos2.y << 4;
+ data[0]++;
+ //fallthrough
+ case 1:
+ data[5] += data[4];
+ data[4]++;
+ sprite->pos2.y = data[5] >> 4;
+ if (sprite->pos2.y >= 0)
+ {
+ PlaySE(SE_TRACK_STOP);
+ sprite->pos2.y = 0;
+ data[0]++;
+ }
+ break;
+ case 2:
+ data[1] += 12;
+ if (data[1] >= 128)
+ {
+ PlaySE(SE_TRACK_STOP);
+ data[1] = 0;
+ data[0]++;
+ }
+ y = gSineTable[data[1]];
+ sprite->pos2.y = -(y >> 4);
+ break;
+ case 3:
+ data[1] += 16;
+ if (data[1] >= 128)
+ {
+ PlaySE(SE_TRACK_STOP);
+ data[1] = 0;
+ data[0]++;
+ }
+ sprite->pos2.y = -(gSineTable[data[1]] >> 5);
+ break;
+ case 4:
+ if (++data[1] > 40)
+ sprite->callback = SpriteCallbackDummy;
+ break;
+ }
+}
+
+const u16 gUnknown_847A328[] = INCBIN_U16("data/graphics/unk_847a348.gbapal");
+const u16 gUnknown_847A348[] = INCBIN_U16("data/graphics/unk_847a348.4bpp.lz");
+
+void sub_815F564(u16 tilesTag, u16 palTag)
+{
+ struct CompressedSpriteSheet spriteSheet = {(const void *)gUnknown_847A348, 0xE00};
+ struct SpritePalette spritePalette = {gUnknown_847A328};
+ spriteSheet.tag = tilesTag;
+ spritePalette.tag = palTag;
+ LoadCompressedObjectPic(&spriteSheet);
+ LoadSpritePalette(&spritePalette);
+}
+
+const struct OamData gOamData_847A7AC = {
+ .affineMode = ST_OAM_AFFINE_DOUBLE,
+ .shape = ST_OAM_SQUARE,
+ .size = 2
+};
+
+const struct OamData gOamData_847A7B4 = {
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .shape = ST_OAM_H_RECTANGLE,
+ .size = 3
+};
+
+const union AnimCmd gUnknown_847A7BC[] = {
+ ANIMCMD_FRAME( 0, 1),
+ ANIMCMD_END
+};
+
+const union AnimCmd gUnknown_847A7C4[] = {
+ ANIMCMD_FRAME(16, 1),
+ ANIMCMD_END
+};
+
+const union AnimCmd gUnknown_847A7CC[] = {
+ ANIMCMD_FRAME(32, 1),
+ ANIMCMD_END
+};
+
+const union AnimCmd *const gUnknown_847A7D4[] = {
+ gUnknown_847A7BC,
+ gUnknown_847A7C4,
+ gUnknown_847A7CC
+};
+
+const union AnimCmd gUnknown_847A7E0[] = {
+ ANIMCMD_FRAME(48, 1),
+ ANIMCMD_END
+};
+
+const union AnimCmd gUnknown_847A7E8[] = {
+ ANIMCMD_FRAME(80, 1),
+ ANIMCMD_END
+};
+
+const union AnimCmd *const gUnknown_847A7F0[] = {
+ gUnknown_847A7E0,
+ gUnknown_847A7E8
+};
+
+const union AffineAnimCmd gUnknown_847A7F8[] = {
+ AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd gUnknown_847A808[] = {
+ AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_FRAME( 0x10, -0x10, 0, 8),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd gUnknown_847A820[] = {
+ AFFINEANIMCMD_FRAME(-0x12, 0x12, 0, 8),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd gUnknown_847A830[] = {
+ AFFINEANIMCMD_FRAME( 0x6, -0x6, 0, 8),
+ AFFINEANIMCMD_FRAME( -0x4, 0x4, 0, 8),
+ AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd *const gUnknown_847A850[] = {
+ gUnknown_847A7F8,
+ gUnknown_847A808,
+ gUnknown_847A820,
+ gUnknown_847A830
+};
+
+u8 sub_815F5BC(u16 tilesTag, u16 palTag, s16 x, s16 y, u8 subpriority)
+{
+ struct SpriteTemplate spriteTemplate = {
+ .oam = &gOamData_847A7AC,
+ .anims = gUnknown_847A7D4,
+ .affineAnims = gUnknown_847A850,
+ .callback = SpriteCallbackDummy
+ };
+ spriteTemplate.tileTag = tilesTag;
+ spriteTemplate.paletteTag = palTag;
+ return CreateSprite(&spriteTemplate, x, y, subpriority);
+}
+
+void sub_815F610(u16 tilesTag, u16 palTag, s16 x, s16 y, u8 subpriority, s16 * spriteId2_p, s16 * spriteId3_p)
+{
+ struct SpriteTemplate spriteTemplate = {
+ .oam = &gOamData_847A7B4,
+ .anims = gUnknown_847A7F0,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+ };
+ spriteTemplate.tileTag = tilesTag;
+ spriteTemplate.paletteTag = palTag;
+ *spriteId2_p = CreateSprite(&spriteTemplate, x - 32, y, subpriority);
+ *spriteId3_p = CreateSprite(&spriteTemplate, x + 32, y, subpriority);
+ gSprites[*spriteId2_p].invisible = TRUE;
+ gSprites[*spriteId3_p].invisible = TRUE;
+ StartSpriteAnim(&gSprites[*spriteId3_p], 1);
+}
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 000000000..5b5fdbb9d
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,513 @@
+#include "global.h"
+#include "util.h"
+
+const u32 gBitTable[] =
+{
+ 1 << 0,
+ 1 << 1,
+ 1 << 2,
+ 1 << 3,
+ 1 << 4,
+ 1 << 5,
+ 1 << 6,
+ 1 << 7,
+ 1 << 8,
+ 1 << 9,
+ 1 << 10,
+ 1 << 11,
+ 1 << 12,
+ 1 << 13,
+ 1 << 14,
+ 1 << 15,
+ 1 << 16,
+ 1 << 17,
+ 1 << 18,
+ 1 << 19,
+ 1 << 20,
+ 1 << 21,
+ 1 << 22,
+ 1 << 23,
+ 1 << 24,
+ 1 << 25,
+ 1 << 26,
+ 1 << 27,
+ 1 << 28,
+ 1 << 29,
+ 1 << 30,
+ 1 << 31,
+};
+
+static const struct SpriteTemplate gInvisibleSpriteTemplate =
+{
+ .tileTag = 0,
+ .paletteTag = 0,
+ .oam = &gDummyOamData,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+};
+
+static const u8 sSpriteDimensions[3][4][2] =
+{
+ // square
+ {
+ {1, 1},
+ {2, 2},
+ {4, 4},
+ {8, 8},
+ },
+
+ // horizontal rectangle
+ {
+ {2, 1},
+ {4, 1},
+ {4, 2},
+ {8, 4},
+ },
+
+ // vertical rectangle
+ {
+ {1, 2},
+ {1, 4},
+ {2, 4},
+ {4, 8},
+ },
+};
+
+static const u16 gCrc16Table[] =
+{
+ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
+ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
+ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
+ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
+ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
+ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
+ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
+ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
+ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
+ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
+ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
+ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
+ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
+ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
+ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
+ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
+ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
+ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
+ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
+ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
+ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
+ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
+ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
+ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
+ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
+ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
+ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
+ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
+ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
+ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
+ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
+ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78,
+};
+
+const u8 gMiscBlank_Gfx[] = INCBIN_U8("graphics/interface/blank.4bpp");
+
+u8 CreateInvisibleSpriteWithCallback(void (*callback)(struct Sprite *))
+{
+ u8 sprite = CreateSprite(&gInvisibleSpriteTemplate, 248, 168, 14);
+ gSprites[sprite].invisible = TRUE;
+ gSprites[sprite].callback = callback;
+ return sprite;
+}
+
+void StoreWordInTwoHalfwords(u16 *h, u32 w)
+{
+ h[0] = (u16)(w);
+ h[1] = (u16)(w >> 16);
+}
+
+void LoadWordFromTwoHalfwords(u16 *h, u32 *w)
+{
+ *w = h[0] | (s16)h[1] << 16;
+}
+
+void SetBgAffineStruct(struct BgAffineSrcData *src, u32 texX, u32 texY, s16 scrX, s16 scrY, s16 sx, s16 sy, u16 alpha)
+{
+ src->texX = texX;
+ src->texY = texY;
+ src->scrX = scrX;
+ src->scrY = scrY;
+ src->sx = sx;
+ src->sy = sy;
+ src->alpha = alpha;
+}
+
+void DoBgAffineSet(struct BgAffineDstData *dest, u32 texX, u32 texY, s16 scrX, s16 scrY, s16 sx, s16 sy, u16 alpha)
+{
+ struct BgAffineSrcData src;
+
+ SetBgAffineStruct(&src, texX, texY, scrX, scrY, sx, sy, alpha);
+ BgAffineSet(&src, dest, 1);
+}
+
+#ifdef NONMATCHING
+void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output)
+{
+ u8 x, y;
+ s8 i, j;
+ u8 xflip[32];
+ u8 h = sSpriteDimensions[shape][size][1];
+ u8 w = sSpriteDimensions[shape][size][0];
+
+ for (y = 0; y < h; y++)
+ {
+ int filler = 32 - w;
+
+ for (x = 0; x < w; x++)
+ {
+ int tile = (*tilemap & 0x3ff) * 32;
+ int attr = *tilemap & 0xc00;
+
+ if (attr == 0)
+ {
+ DmaCopy32Defvars(3, tiles + tile, output, 32);
+ }
+ else if (attr == 0x800) // yflip
+ {
+ for (i = 0; i < 8; i++)
+ {
+ DmaCopy32Defvars(3, (7 - i) * 4 + tile + tiles, output + i * 4, 4);
+ }
+ }
+ else // xflip
+ {
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ u8 i2 = i * 4;
+ xflip[i2 + (3-j)] = (tiles[tile + i2 + j] & 0xf) << 4;
+ xflip[i2 + (3-j)] |= tiles[tile + i2 + j] >> 4;
+ }
+ }
+ if (*tilemap & 0x800) // yflip
+ {
+ for (i = 0; i < 8; i++)
+ {
+ DmaCopy32Defvars(3, (7 - i) * 4 + xflip, output + i * 4, 4);
+ }
+ }
+ else
+ {
+ DmaCopy32Defvars(3, xflip, output, 32);
+ }
+ }
+ tilemap++;
+ output += 32;
+ }
+ tilemap += filler;
+ }
+}
+#else
+NAKED
+void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmov r7, r10\n"
+ "\tmov r6, r9\n"
+ "\tmov r5, r8\n"
+ "\tpush {r5-r7}\n"
+ "\tsub sp, 0x3C\n"
+ "\tstr r2, [sp, 0x20]\n"
+ "\tadds r4, r3, 0\n"
+ "\tldr r7, [sp, 0x5C]\n"
+ "\tlsls r0, 24\n"
+ "\tlsls r1, 24\n"
+ "\tldr r2, _0804504C @ =sSpriteDimensions\n"
+ "\tlsrs r1, 23\n"
+ "\tlsrs r0, 21\n"
+ "\tadds r1, r0\n"
+ "\tadds r0, r2, 0x1\n"
+ "\tadds r0, r1, r0\n"
+ "\tldrb r0, [r0]\n"
+ "\tstr r0, [sp, 0x24]\n"
+ "\tadds r1, r2\n"
+ "\tldrb r1, [r1]\n"
+ "\tstr r1, [sp, 0x28]\n"
+ "\tmovs r1, 0\n"
+ "\tcmp r1, r0\n"
+ "\tbcc _08044FF8\n"
+ "\tb _0804517A\n"
+ "_08044FF8:\n"
+ "\tmovs r0, 0x20\n"
+ "\tldr r2, [sp, 0x28]\n"
+ "\tsubs r0, r2\n"
+ "\tlsls r0, 1\n"
+ "\tstr r0, [sp, 0x2C]\n"
+ "_08045002:\n"
+ "\tmovs r2, 0\n"
+ "\tadds r1, 0x1\n"
+ "\tstr r1, [sp, 0x34]\n"
+ "\tldr r3, [sp, 0x28]\n"
+ "\tcmp r2, r3\n"
+ "\tbcc _08045010\n"
+ "\tb _08045168\n"
+ "_08045010:\n"
+ "\tldr r0, _08045050 @ =0x040000d4\n"
+ "\tmov r8, r0\n"
+ "_08045014:\n"
+ "\tldrh r1, [r4]\n"
+ "\tldr r0, _08045054 @ =0x000003ff\n"
+ "\tands r0, r1\n"
+ "\tlsls r0, 5\n"
+ "\tmov r12, r0\n"
+ "\tmovs r0, 0xC0\n"
+ "\tlsls r0, 4\n"
+ "\tands r0, r1\n"
+ "\tmov r3, sp\n"
+ "\tstrh r1, [r3, 0x38]\n"
+ "\tcmp r0, 0\n"
+ "\tbne _0804505C\n"
+ "\tldr r0, [sp, 0x20]\n"
+ "\tadd r0, r12\n"
+ "\tmov r1, r8\n"
+ "\tstr r0, [r1]\n"
+ "\tstr r7, [r1, 0x4]\n"
+ "\tldr r3, _08045058 @ =0x84000008\n"
+ "\tstr r3, [r1, 0x8]\n"
+ "\tldr r0, [r1, 0x8]\n"
+ "\tadds r4, 0x2\n"
+ "\tstr r4, [sp, 0x30]\n"
+ "\tadds r7, 0x20\n"
+ "\tmov r10, r7\n"
+ "\tadds r2, 0x1\n"
+ "\tmov r9, r2\n"
+ "\tb _08045156\n"
+ "\t.align 2, 0\n"
+ "_0804504C: .4byte sSpriteDimensions\n"
+ "_08045050: .4byte 0x040000d4\n"
+ "_08045054: .4byte 0x000003ff\n"
+ "_08045058: .4byte 0x84000008\n"
+ "_0804505C:\n"
+ "\tmovs r1, 0x80\n"
+ "\tlsls r1, 4\n"
+ "\tcmp r0, r1\n"
+ "\tbne _080450AC\n"
+ "\tmovs r3, 0\n"
+ "\tadds r4, 0x2\n"
+ "\tstr r4, [sp, 0x30]\n"
+ "\tmovs r0, 0x20\n"
+ "\tadds r0, r7\n"
+ "\tmov r10, r0\n"
+ "\tadds r2, 0x1\n"
+ "\tmov r9, r2\n"
+ "\tldr r4, _080450A4 @ =0x040000d4\n"
+ "\tldr r6, _080450A8 @ =0x84000001\n"
+ "\tmovs r5, 0x7\n"
+ "_0804507A:\n"
+ "\tlsls r2, r3, 24\n"
+ "\tasrs r2, 24\n"
+ "\tsubs r0, r5, r2\n"
+ "\tlsls r0, 2\n"
+ "\tadd r0, r12\n"
+ "\tldr r1, [sp, 0x20]\n"
+ "\tadds r0, r1, r0\n"
+ "\tlsls r1, r2, 2\n"
+ "\tadds r1, r7, r1\n"
+ "\tstr r0, [r4]\n"
+ "\tstr r1, [r4, 0x4]\n"
+ "\tstr r6, [r4, 0x8]\n"
+ "\tldr r0, [r4, 0x8]\n"
+ "\tadds r2, 0x1\n"
+ "\tlsls r2, 24\n"
+ "\tlsrs r3, r2, 24\n"
+ "\tasrs r2, 24\n"
+ "\tcmp r2, 0x7\n"
+ "\tble _0804507A\n"
+ "\tb _08045156\n"
+ "\t.align 2, 0\n"
+ "_080450A4: .4byte 0x040000d4\n"
+ "_080450A8: .4byte 0x84000001\n"
+ "_080450AC:\n"
+ "\tmovs r3, 0\n"
+ "\tadds r4, 0x2\n"
+ "\tstr r4, [sp, 0x30]\n"
+ "\tmovs r0, 0x20\n"
+ "\tadds r0, r7\n"
+ "\tmov r10, r0\n"
+ "\tadds r2, 0x1\n"
+ "\tmov r9, r2\n"
+ "_080450BC:\n"
+ "\tmovs r2, 0\n"
+ "\tlsls r4, r3, 24\n"
+ "\tlsls r0, r4, 2\n"
+ "\tlsrs r0, 24\n"
+ "\tadds r6, r0, 0x3\n"
+ "\tmov r1, r12\n"
+ "\tadds r5, r1, r0\n"
+ "_080450CA:\n"
+ "\tlsls r1, r2, 24\n"
+ "\tasrs r1, 24\n"
+ "\tsubs r0, r6, r1\n"
+ "\tmov r2, sp\n"
+ "\tadds r3, r2, r0\n"
+ "\tadds r0, r5, r1\n"
+ "\tldr r2, [sp, 0x20]\n"
+ "\tadds r0, r2, r0\n"
+ "\tldrb r2, [r0]\n"
+ "\tmovs r0, 0xF\n"
+ "\tands r0, r2\n"
+ "\tlsls r0, 4\n"
+ "\tlsrs r2, 4\n"
+ "\torrs r0, r2\n"
+ "\tstrb r0, [r3]\n"
+ "\tadds r1, 0x1\n"
+ "\tlsls r1, 24\n"
+ "\tlsrs r2, r1, 24\n"
+ "\tasrs r1, 24\n"
+ "\tcmp r1, 0x3\n"
+ "\tble _080450CA\n"
+ "\tmovs r3, 0x80\n"
+ "\tlsls r3, 17\n"
+ "\tadds r0, r4, r3\n"
+ "\tlsrs r3, r0, 24\n"
+ "\tasrs r0, 24\n"
+ "\tcmp r0, 0x7\n"
+ "\tble _080450BC\n"
+ "\tmovs r0, 0x80\n"
+ "\tlsls r0, 4\n"
+ "\tmov r1, sp\n"
+ "\tldrh r1, [r1, 0x38]\n"
+ "\tands r0, r1\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _08045148\n"
+ "\tmovs r3, 0\n"
+ "\tldr r4, _08045140 @ =0x040000d4\n"
+ "\tldr r6, _08045144 @ =0x84000001\n"
+ "\tmovs r5, 0x7\n"
+ "_08045118:\n"
+ "\tlsls r1, r3, 24\n"
+ "\tasrs r1, 24\n"
+ "\tsubs r0, r5, r1\n"
+ "\tlsls r0, 2\n"
+ "\tmov r3, sp\n"
+ "\tadds r2, r3, r0\n"
+ "\tlsls r0, r1, 2\n"
+ "\tadds r0, r7, r0\n"
+ "\tstr r2, [r4]\n"
+ "\tstr r0, [r4, 0x4]\n"
+ "\tstr r6, [r4, 0x8]\n"
+ "\tldr r0, [r4, 0x8]\n"
+ "\tadds r1, 0x1\n"
+ "\tlsls r1, 24\n"
+ "\tlsrs r3, r1, 24\n"
+ "\tasrs r1, 24\n"
+ "\tcmp r1, 0x7\n"
+ "\tble _08045118\n"
+ "\tb _08045156\n"
+ "\t.align 2, 0\n"
+ "_08045140: .4byte 0x040000d4\n"
+ "_08045144: .4byte 0x84000001\n"
+ "_08045148:\n"
+ "\tmov r0, sp\n"
+ "\tmov r1, r8\n"
+ "\tstr r0, [r1]\n"
+ "\tstr r7, [r1, 0x4]\n"
+ "\tldr r2, _0804518C @ =0x84000008\n"
+ "\tstr r2, [r1, 0x8]\n"
+ "\tldr r0, [r1, 0x8]\n"
+ "_08045156:\n"
+ "\tldr r4, [sp, 0x30]\n"
+ "\tmov r7, r10\n"
+ "\tmov r3, r9\n"
+ "\tlsls r0, r3, 24\n"
+ "\tlsrs r2, r0, 24\n"
+ "\tldr r0, [sp, 0x28]\n"
+ "\tcmp r2, r0\n"
+ "\tbcs _08045168\n"
+ "\tb _08045014\n"
+ "_08045168:\n"
+ "\tldr r1, [sp, 0x2C]\n"
+ "\tadds r4, r1\n"
+ "\tldr r2, [sp, 0x34]\n"
+ "\tlsls r0, r2, 24\n"
+ "\tlsrs r1, r0, 24\n"
+ "\tldr r3, [sp, 0x24]\n"
+ "\tcmp r1, r3\n"
+ "\tbcs _0804517A\n"
+ "\tb _08045002\n"
+ "_0804517A:\n"
+ "\tadd sp, 0x3C\n"
+ "\tpop {r3-r5}\n"
+ "\tmov r8, r3\n"
+ "\tmov r9, r4\n"
+ "\tmov r10, r5\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r0}\n"
+ "\tbx r0\n"
+ "\t.align 2, 0\n"
+ "_0804518C: .4byte 0x84000008");
+}
+#endif // NONMATCHING
+
+int CountTrailingZeroBits(u32 value)
+{
+ u8 i;
+
+ for (i = 0; i < 32; i++)
+ {
+ if ((value & 1) == 0)
+ value >>= 1;
+ else
+ return i;
+ }
+ return 0;
+}
+
+u16 CalcCRC16(const u8 *data, u32 length)
+{
+ u16 i, j;
+ u16 crc = 0x1121;
+
+ for (i = 0; i < length; i++)
+ {
+ crc ^= data[i];
+ for (j = 0; j < 8; j++)
+ {
+ if (crc & 1)
+ crc = (crc >> 1) ^ 0x8408;
+ else
+ crc >>= 1;
+ }
+ }
+ return ~crc;
+}
+
+u16 CalcCRC16WithTable(const u8 *data, u32 length)
+{
+ u16 i;
+ u16 crc = 0x1121;
+ u8 byte;
+
+ for (i = 0; i < length; i++)
+ {
+ byte = crc >> 8;
+ crc ^= data[i];
+ crc = byte ^ gCrc16Table[(u8)crc];
+ }
+ return ~crc;
+}
+
+u32 CalcByteArraySum(const u8 * array, u32 size)
+{
+ s32 i;
+ u32 result = 0;
+
+ for (i = 0; i < size; i++)
+ {
+ result += array[i];
+ }
+
+ return result;
+}
diff --git a/src/vs_seeker.c b/src/vs_seeker.c
index 4d42f270d..e3df77242 100644
--- a/src/vs_seeker.c
+++ b/src/vs_seeker.c
@@ -1,5 +1,4 @@
#include "global.h"
-#include "songs.h"
#include "sound.h"
#include "task.h"
#include "malloc.h"
@@ -19,9 +18,11 @@
#include "random.h"
#include "field_map_obj.h"
#include "field_player_avatar.h"
+#include "map_obj_80688E4.h"
#include "map_obj_8097404.h"
#include "unk_810c3a4.h"
#include "constants/movement_commands.h"
+#include "constants/songs.h"
#include "vs_seeker.h"
typedef enum
@@ -65,11 +66,13 @@ struct VsSeekerStruct
extern u16 gSpecialVar_LastTalked;
extern struct MapObject gMapObjects[MAP_OBJECTS_COUNT];
-extern u8 gUnknown_3005074;
+extern u8 gSelectedEventObject;
// static declarations
static EWRAM_DATA struct VsSeekerStruct *sVsSeeker = NULL;
+static void sub_810C3B8(u8 taskId);
+static void sub_810C594(void);
static void Task_VsSeeker_1(u8 taskId);
static void Task_VsSeeker_2(u8 taskId);
static void GatherNearbyTrainerInfo(void);
@@ -565,6 +568,229 @@ static const u8 gUnknown_8453F67[] = { 0x08, 0x08, 0x07, 0x09, 0x0a };
// text
+
+
+void sub_810C3A4(void)
+{
+ CreateTask(sub_810C3B8, 80);
+}
+
+static void sub_810C3B8(u8 taskId)
+{
+ struct Task * task = &gTasks[taskId];
+ u8 i;
+
+ if (task->data[0] == 0 && walkrun_is_standing_still() == TRUE)
+ {
+ sub_805C270();
+ task->data[0] = 1;
+ }
+
+ if (task->data[1] == 0)
+ {
+ for (i = 0; i < MAP_OBJECTS_COUNT; i++)
+ {
+ if (sub_810CF04(i) == TRUE)
+ {
+ if (gMapObjects[i].mapobj_bit_1)
+ return;
+ FreezeMapObject(&gMapObjects[i]);
+ }
+ }
+ }
+
+ task->data[1] = 1;
+ if (task->data[0] != 0)
+ {
+ DestroyTask(taskId);
+ sub_805C780();
+ EnableBothScriptContexts();
+ }
+}
+
+void sub_810C444(void)
+{
+ struct MapObjectTemplate * templates = gSaveBlock1Ptr->mapObjectTemplates;
+ u8 i;
+ u8 r6;
+ u8 sp0;
+ struct MapObject * mapObject;
+
+ for (i = 0; i < gMapHeader.events->mapObjectCount; i++)
+ {
+ if ((templates[i].unkC == 1 || templates[i].unkC == 3) && (templates[i].movementType == 0x4D || templates[i].movementType == 0x4E || templates[i].movementType == 0x4F))
+ {
+ r6 = sub_810CF54();
+ TryGetFieldObjectIdByLocalIdAndMap(templates[i].localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &sp0);
+ mapObject = &gMapObjects[sp0];
+ if (sub_810CF04(sp0) == TRUE)
+ {
+ npc_set_running_behaviour_etc(mapObject, r6);
+ }
+ templates[i].movementType = r6;
+ }
+ }
+}
+
+#ifdef NONMATCHING
+bool8 sub_810C4EC(void)
+{
+ if (CheckBagHasItem(ITEM_VS_SEEKER, 1) == TRUE)
+ {
+ if ((gSaveBlock1Ptr->trainerRematchStepCounter & 0xFF) < 100)
+ gSaveBlock1Ptr->trainerRematchStepCounter++;
+ }
+
+ if (FlagGet(0x801) == TRUE)
+ {
+ u16 x;
+ do {
+ x = (gSaveBlock1Ptr->trainerRematchStepCounter >> 8) & 0xFF;
+ } while (0);
+ if (x < 100)
+ {
+ x++;
+ gSaveBlock1Ptr->trainerRematchStepCounter = ((u16)(x << 8)) | (gSaveBlock1Ptr->trainerRematchStepCounter & 0xFF);
+ }
+ do {
+ x = (gSaveBlock1Ptr->trainerRematchStepCounter >> 8) & 0xFF;
+ } while (0);
+ if (x == 100)
+ {
+ FlagClear(0x801);
+ sub_810C640();
+ sub_810D0D0();
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+#else
+NAKED
+bool8 sub_810C4EC(void)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmovs r0, 0xB5\n"
+ "\tlsls r0, 1\n"
+ "\tmovs r1, 0x1\n"
+ "\tbl CheckBagHasItem\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r0, 24\n"
+ "\tcmp r0, 0x1\n"
+ "\tbne _0810C516\n"
+ "\tldr r0, _0810C568 @ =gSaveBlock1Ptr\n"
+ "\tldr r0, [r0]\n"
+ "\tmovs r2, 0xC7\n"
+ "\tlsls r2, 3\n"
+ "\tadds r1, r0, r2\n"
+ "\tldrh r2, [r1]\n"
+ "\tldrb r0, [r1]\n"
+ "\tcmp r0, 0x63\n"
+ "\tbhi _0810C516\n"
+ "\tadds r0, r2, 0x1\n"
+ "\tstrh r0, [r1]\n"
+ "_0810C516:\n"
+ "\tldr r7, _0810C56C @ =0x00000801\n"
+ "\tadds r0, r7, 0\n"
+ "\tbl FlagGet\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r0, 24\n"
+ "\tcmp r0, 0x1\n"
+ "\tbne _0810C570\n"
+ "\tldr r6, _0810C568 @ =gSaveBlock1Ptr\n"
+ "\tldr r0, [r6]\n"
+ "\tmovs r5, 0xC7\n"
+ "\tlsls r5, 3\n"
+ "\tadds r3, r0, r5\n"
+ "\tldrh r2, [r3]\n"
+ "\tlsrs r1, r2, 8\n"
+ "\tmovs r4, 0xFF\n"
+ "\tcmp r1, 0x63\n"
+ "\tbhi _0810C548\n"
+ "\tadds r1, 0x1\n"
+ "\tlsls r1, 24\n"
+ "\tmovs r0, 0xFF\n"
+ "\tands r0, r2\n"
+ "\tlsrs r1, 16\n"
+ "\torrs r0, r1\n"
+ "\tstrh r0, [r3]\n"
+ "_0810C548:\n"
+ "\tldr r0, [r6]\n"
+ "\tadds r0, r5\n"
+ "\tldrh r0, [r0]\n"
+ "\tlsrs r0, 8\n"
+ "\tands r0, r4\n"
+ "\tcmp r0, 0x64\n"
+ "\tbne _0810C570\n"
+ "\tadds r0, r7, 0\n"
+ "\tbl FlagClear\n"
+ "\tbl sub_810C640\n"
+ "\tbl sub_810D0D0\n"
+ "\tmovs r0, 0x1\n"
+ "\tb _0810C572\n"
+ "\t.align 2, 0\n"
+ "_0810C568: .4byte gSaveBlock1Ptr\n"
+ "_0810C56C: .4byte 0x00000801\n"
+ "_0810C570:\n"
+ "\tmovs r0, 0\n"
+ "_0810C572:\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r1}\n"
+ "\tbx r1");
+}
+#endif
+
+void sub_810C578(void)
+{
+ FlagClear(0x801);
+ sub_810C640();
+ sub_810D0D0();
+ sub_810C594();
+}
+
+static void sub_810C594(void)
+{
+ u8 i;
+
+ for (i = 0; i < MAP_OBJECTS_COUNT; i++)
+ {
+ struct MapObject * mapObject = &gMapObjects[i];
+ if (mapObject->animPattern == 0x4D || mapObject->animPattern == 0x4E || mapObject->animPattern == 0x4F)
+ {
+ u8 r3 = sub_810CF54();
+ if (mapObject->active && gSprites[mapObject->spriteId].data[0] == i)
+ {
+ gSprites[mapObject->spriteId].pos2.x = 0;
+ gSprites[mapObject->spriteId].pos2.y = 0;
+ npc_set_running_behaviour_etc(mapObject, r3);
+ }
+ }
+ }
+}
+
+void sub_810C604(void)
+{
+ gSaveBlock1Ptr->trainerRematchStepCounter &= 0xFF00;
+}
+
+void sub_810C620(void)
+{
+ gSaveBlock1Ptr->trainerRematchStepCounter &= 0xFF00;
+ gSaveBlock1Ptr->trainerRematchStepCounter |= 100;
+}
+
+void sub_810C640(void)
+{
+ gSaveBlock1Ptr->trainerRematchStepCounter &= 0x00FF;
+}
+
+void sub_810C654(void)
+{
+ gSaveBlock1Ptr->trainerRematchStepCounter &= 0x00FF;
+ gSaveBlock1Ptr->trainerRematchStepCounter |= (100 << 8);
+}
+
void Task_VsSeeker_0(u8 taskId)
{
u8 i;
@@ -588,7 +814,7 @@ void Task_VsSeeker_0(u8 taskId)
}
else if (respval == 2)
{
- sub_80A2294(4, 0, gSpecialVar_ItemId, 0xffff);
+ ItemUse_SetQuestLogEvent(4, 0, gSpecialVar_ItemId, 0xffff);
FieldEffectStart(FLDEFF_UNK_41); // TODO: name this enum
gTasks[taskId].func = Task_VsSeeker_1;
gTasks[taskId].data[0] = 15;
@@ -663,7 +889,7 @@ static void Task_VsSeeker_3(u8 taskId)
{
if (sVsSeeker->responseCode == 2)
StartAllRespondantIdleMovements();
- sub_80F6F54(0, 1);
+ ClearDialogWindowAndFrame(0, 1);
sub_80696C0();
ScriptContext2_Disable();
DestroyTask(taskId);
@@ -1012,7 +1238,7 @@ void sub_810CB90(void)
sub_810CF54(&r4[r8]); // You are using this function incorrectly. Please consult the manual.
sub_805FE7C(r4_2, gUnknown_8453F67[r4_2->mapobj_unk_18]);
gSaveBlock1Ptr->trainerRematches[r4[r8].localId] = 0;
- if (gUnknown_3005074 == sp0)
+ if (gSelectedEventObject == sp0)
r4_2->animPattern = gUnknown_8453F67[r4_2->mapobj_unk_18];
else
r4_2->animPattern = 0x08;
@@ -1225,7 +1451,7 @@ static u16 GetTrainerFlagFromScript(const u8 *script)
* because the ARM processor requires shorts to be 16-bit
* aligned, this function needs to perform explicit bitwise
* operations to get the correct flag.
- *
+ *
* 5c XX YY ZZ ...
* -- --
*/
@@ -1360,7 +1586,7 @@ static void StartAllRespondantIdleMovements(void)
u8 dummy = 0;
s32 i;
s32 j;
-
+
for (i = 0; i < sVsSeeker->numRematchableTrainers; i++)
{
for (j = 0; sVsSeeker->trainerInfo[j].localId != 0xFF; j++)
diff --git a/src/window.c b/src/window.c
index e760fc8e4..4c302885c 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2,17 +2,13 @@
#include "window.h"
#include "malloc.h"
#include "bg.h"
+#include "blit.h"
u8 gWindowClearTile;
void *gWindowBgTilemapBuffers[4];
EWRAM_DATA struct Window gWindows[WINDOWS_MAX] = {0};
-extern void BlitBitmapRect4Bit(struct Bitmap *src, struct Bitmap *dest, u16 srcX, u16 srcY, u16 destX, u16 destY, u16 width, u16 height, u8 colorKey);
-extern void BlitBitmapRect4BitTo8Bit(struct Bitmap *src, struct Bitmap *dest, u16 srcX, u16 srcY, u16 destX, u16 destY, u16 width, u16 height, u8 colorKey, u8 paletteNum);
-extern void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
-extern void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
-
static u8 GetNumActiveWindowsOnBg(u8 bgId);
static const struct WindowTemplate sDummyWindowTemplate = {0xFF, 0, 0, 0, 0, 0, 0};
@@ -47,7 +43,7 @@ bool16 InitWindows(const struct WindowTemplate *templates)
gWindows[i].tileData = NULL;
}
- for (i = 0, allocatedBaseBlock = 0, bgLayer = templates[i].priority; bgLayer != 0xFF && i < 0x20; ++i, bgLayer = templates[i].priority)
+ for (i = 0, allocatedBaseBlock = 0, bgLayer = templates[i].bg; bgLayer != 0xFF && i < 0x20; ++i, bgLayer = templates[i].bg)
{
if (gWindowTileAutoAllocEnabled == TRUE)
{
@@ -116,14 +112,14 @@ u16 AddWindow(const struct WindowTemplate *template)
for (win = 0; win < 0x20; ++win)
{
- if ((bgLayer = gWindows[win].window.priority) == 0xFF)
+ if ((bgLayer = gWindows[win].window.bg) == 0xFF)
break;
}
if (win == 0x20)
return 0xFF;
- bgLayer = template->priority;
+ bgLayer = template->bg;
allocatedBaseBlock = 0;
if (gWindowTileAutoAllocEnabled == TRUE)
@@ -179,7 +175,7 @@ u16 AddWindow(const struct WindowTemplate *template)
void RemoveWindow(u8 windowId)
{
- u8 bgLayer = gWindows[windowId].window.priority;
+ u8 bgLayer = gWindows[windowId].window.bg;
if (gWindowTileAutoAllocEnabled == TRUE)
{
@@ -235,14 +231,14 @@ void CopyWindowToVram(u8 windowId, u8 mode)
switch (mode)
{
case 1:
- CopyBgTilemapBufferToVram(windowLocal.window.priority);
+ CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
case 2:
- LoadBgTiles(windowLocal.window.priority, windowLocal.tileData, windowSize, windowLocal.window.baseBlock);
+ LoadBgTiles(windowLocal.window.bg, windowLocal.tileData, windowSize, windowLocal.window.baseBlock);
break;
case 3:
- LoadBgTiles(windowLocal.window.priority, windowLocal.tileData, windowSize, windowLocal.window.baseBlock);
- CopyBgTilemapBufferToVram(windowLocal.window.priority);
+ LoadBgTiles(windowLocal.window.bg, windowLocal.tileData, windowSize, windowLocal.window.baseBlock);
+ CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
}
}
@@ -252,8 +248,8 @@ void PutWindowTilemap(u8 windowId)
struct Window windowLocal = gWindows[windowId];
WriteSequenceToBgTilemapBuffer(
- windowLocal.window.priority,
- GetBgAttribute(windowLocal.window.priority, 0xA) + windowLocal.window.baseBlock,
+ windowLocal.window.bg,
+ GetBgAttribute(windowLocal.window.bg, 0xA) + windowLocal.window.baseBlock,
windowLocal.window.tilemapLeft,
windowLocal.window.tilemapTop,
windowLocal.window.width,
@@ -265,13 +261,13 @@ void PutWindowTilemap(u8 windowId)
void PutWindowRectTilemapOverridePalette(u8 windowId, u8 x, u8 y, u8 width, u8 height, u8 palette)
{
struct Window windowLocal = gWindows[windowId];
- u16 currentRow = windowLocal.window.baseBlock + (y * windowLocal.window.width) + x + GetBgAttribute(windowLocal.window.priority, 0xA);
+ u16 currentRow = windowLocal.window.baseBlock + (y * windowLocal.window.width) + x + GetBgAttribute(windowLocal.window.bg, 0xA);
int i;
for (i = 0; i < height; ++i)
{
WriteSequenceToBgTilemapBuffer(
- windowLocal.window.priority,
+ windowLocal.window.bg,
currentRow,
windowLocal.window.tilemapLeft + x,
windowLocal.window.tilemapTop + y + i,
@@ -289,7 +285,7 @@ void ClearWindowTilemap(u8 windowId)
struct Window windowLocal = gWindows[windowId];
FillBgTilemapBufferRect(
- windowLocal.window.priority,
+ windowLocal.window.bg,
gWindowClearTile,
windowLocal.window.tilemapLeft,
windowLocal.window.tilemapTop,
@@ -301,13 +297,13 @@ void ClearWindowTilemap(u8 windowId)
void PutWindowRectTilemap(u8 windowId, u8 x, u8 y, u8 width, u8 height)
{
struct Window windowLocal = gWindows[windowId];
- u16 currentRow = windowLocal.window.baseBlock + (y * windowLocal.window.width) + x + GetBgAttribute(windowLocal.window.priority, 0xA);
+ u16 currentRow = windowLocal.window.baseBlock + (y * windowLocal.window.width) + x + GetBgAttribute(windowLocal.window.bg, 0xA);
int i;
for (i = 0; i < height; ++i)
{
WriteSequenceToBgTilemapBuffer(
- windowLocal.window.priority,
+ windowLocal.window.bg,
currentRow,
windowLocal.window.tilemapLeft + x,
windowLocal.window.tilemapTop + y + i,
@@ -320,7 +316,7 @@ void PutWindowRectTilemap(u8 windowId, u8 x, u8 y, u8 width, u8 height)
}
}
-void BlitBitmapToWindow(u8 windowId, u8 *pixels, u16 x, u16 y, u16 width, u16 height)
+void BlitBitmapToWindow(u8 windowId, const u8 *pixels, u16 x, u16 y, u16 width, u16 height)
{
BlitBitmapRectToWindow(windowId, pixels, 0, 0, width, height, x, y, width, height);
}
@@ -1073,10 +1069,10 @@ _08004046:\n\
}
#endif // NONMATCHING
-void CallWindowFunction(u8 windowId, void ( *func)(u8, u8, u8, u8, u8, u8))
+void CallWindowFunction(u8 windowId, WindowFunc func)
{
struct WindowTemplate window = gWindows[windowId].window;
- func(window.priority, window.tilemapLeft, window.tilemapTop, window.width, window.height, window.paletteNum);
+ func(window.bg, window.tilemapLeft, window.tilemapTop, window.width, window.height, window.paletteNum);
}
bool8 SetWindowAttribute(u8 windowId, u8 attributeId, u32 value)
@@ -1096,7 +1092,7 @@ bool8 SetWindowAttribute(u8 windowId, u8 attributeId, u32 value)
gWindows[windowId].window.baseBlock = value;
return FALSE;
case WINDOW_TILE_DATA:
- case WINDOW_PRIORITY:
+ case WINDOW_BG:
case WINDOW_WIDTH:
case WINDOW_HEIGHT:
default:
@@ -1108,8 +1104,8 @@ u32 GetWindowAttribute(u8 windowId, u8 attributeId)
{
switch (attributeId)
{
- case WINDOW_PRIORITY:
- return gWindows[windowId].window.priority;
+ case WINDOW_BG:
+ return gWindows[windowId].window.bg;
case WINDOW_TILEMAP_LEFT:
return gWindows[windowId].window.tilemapLeft;
case WINDOW_TILEMAP_TOP:
@@ -1135,7 +1131,7 @@ static u8 GetNumActiveWindowsOnBg(u8 bgId)
s32 i;
for (i = 0; i < WINDOWS_MAX; i++)
{
- if (gWindows[i].window.priority == bgId)
+ if (gWindows[i].window.bg == bgId)
windowsNum++;
}
return windowsNum;
diff --git a/src/window_8bpp.c b/src/window_8bpp.c
index 5eac3c558..c58c13802 100644
--- a/src/window_8bpp.c
+++ b/src/window_8bpp.c
@@ -2,13 +2,11 @@
#include "window.h"
#include "malloc.h"
#include "bg.h"
+#include "blit.h"
EWRAM_DATA static struct Window* sWindowPtr = NULL;
EWRAM_DATA static u16 sWindowSize = 0;
-extern void BlitBitmapRect4BitTo8Bit(struct Bitmap *src, struct Bitmap *dest, u16 srcX, u16 srcY, u16 destX, u16 destY, u16 width, u16 height, u8 colorKey, u8 paletteNum);
-extern void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
-
static u8 GetNumActiveWindowsOnBg8Bit(u8 bgId);
static void nullsub_9(void)
@@ -23,12 +21,12 @@ u16 AddWindow8Bit(struct WindowTemplate *template)
for (windowId = 0; windowId < 32; windowId++)
{
- if (gWindows[windowId].window.priority == 0xFF)
+ if (gWindows[windowId].window.bg == 0xFF)
break;
}
if (windowId == WINDOWS_MAX)
return 0xFF;
- bgLayer = template->priority;
+ bgLayer = template->bg;
if (gWindowBgTilemapBuffers[bgLayer] == 0)
{
u16 attribute = GetBgAttribute(bgLayer, 8);
@@ -107,14 +105,14 @@ void CopyWindowToVram8Bit(u8 windowId, u8 mode)
switch (mode)
{
case 1:
- CopyBgTilemapBufferToVram(sWindowPtr->window.priority);
+ CopyBgTilemapBufferToVram(sWindowPtr->window.bg);
break;
case 2:
- LoadBgTiles(sWindowPtr->window.priority, sWindowPtr->tileData, sWindowSize, sWindowPtr->window.baseBlock);
+ LoadBgTiles(sWindowPtr->window.bg, sWindowPtr->tileData, sWindowSize, sWindowPtr->window.baseBlock);
break;
case 3:
- LoadBgTiles(sWindowPtr->window.priority, sWindowPtr->tileData, sWindowSize, sWindowPtr->window.baseBlock);
- CopyBgTilemapBufferToVram(sWindowPtr->window.priority);
+ LoadBgTiles(sWindowPtr->window.bg, sWindowPtr->tileData, sWindowSize, sWindowPtr->window.baseBlock);
+ CopyBgTilemapBufferToVram(sWindowPtr->window.bg);
break;
}
}
@@ -125,7 +123,7 @@ static u8 GetNumActiveWindowsOnBg8Bit(u8 bgId)
s32 i;
for (i = 0; i < WINDOWS_MAX; i++)
{
- if (gWindows[i].window.priority == bgId)
+ if (gWindows[i].window.bg == bgId)
windowsNum++;
}
return windowsNum;
diff --git a/src/wireless_communication_status_screen.c b/src/wireless_communication_status_screen.c
new file mode 100644
index 000000000..1eb29be1b
--- /dev/null
+++ b/src/wireless_communication_status_screen.c
@@ -0,0 +1,436 @@
+#include "global.h"
+#include "bg.h"
+#include "palette.h"
+#include "gpu_regs.h"
+#include "malloc.h"
+#include "task.h"
+#include "text.h"
+#include "window.h"
+#include "new_menu_helpers.h"
+#include "scanline_effect.h"
+#include "m4a.h"
+#include "string_util.h"
+#include "unk_text_util.h"
+#include "overworld.h"
+#include "sound.h"
+#include "menu.h"
+#include "librfu.h"
+#include "link_rfu.h"
+#include "union_room.h"
+#include "constants/songs.h"
+
+struct WirelessCommunicationStatusScreenStruct
+{
+ u32 field_00[4];
+ u32 field_10[4];
+ u32 field_20[16];
+ u8 field_60;
+ u8 field_61;
+ u8 filler_62[0xA];
+};
+
+struct WirelessCommunicationStatusScreenStruct * gUnknown_3002040;
+
+extern const u8 gUnknown_841E2B4[];
+extern const u8 gUnknown_841E2BF[];
+extern const u8 gUnknown_841E2C9[];
+extern const u8 gUnknown_841E2D4[];
+extern const u8 gUnknown_841E245[];
+extern const u8 gUnknown_841E263[];
+extern const u8 gUnknown_841E273[];
+extern const u8 gUnknown_841E284[];
+extern const u8 gUnknown_841E29E[];
+
+void sub_814F1E4(void);
+void sub_814F46C(u8 taskId);
+void sub_814F65C(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 palIdx);
+bool32 sub_814F7E4(u32 * a0, u32 * a1, u32 * a2, u8 taskId);
+
+const u16 gUnknown_846F4D0[][16] = {
+ INCBIN_U16("graphics/misc/unk_846f4d0.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f4f0.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f510.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f530.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f550.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f570.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f590.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f5b0.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f5d0.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f5f0.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f610.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f630.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f650.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f670.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f690.gbapal"),
+ INCBIN_U16("graphics/misc/unk_846f6b0.gbapal")
+};
+
+const u32 gUnknown_846F6D0[] = INCBIN_U32("graphics/misc/unk_846f6d0.4bpp.lz");
+const u16 gUnknown_846F8E0[] = INCBIN_U16("graphics/misc/unk_846f8e0.bin");
+
+const struct BgTemplate gUnknown_846FA74[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 8,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0x000
+ }
+};
+
+const struct WindowTemplate gUnknown_846FA7C[] = {
+ {
+ .bg = 0x00,
+ .tilemapLeft = 0x03,
+ .tilemapTop = 0x00,
+ .width = 0x18,
+ .height = 0x03,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0001
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x03,
+ .tilemapTop = 0x04,
+ .width = 0x16,
+ .height = 0x0f,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0049
+ }, {
+ .bg = 0x00,
+ .tilemapLeft = 0x19,
+ .tilemapTop = 0x04,
+ .width = 0x02,
+ .height = 0x0f,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0193
+ }, DUMMY_WIN_TEMPLATE
+};
+
+const u8 *const gUnknown_846FA9C[] = {
+ gUnknown_841E2B4,
+ gUnknown_841E2BF,
+ gUnknown_841E2C9,
+ gUnknown_841E2D4
+};
+const u8 *const gUnknown_846FAAC[] = {
+ gUnknown_841E245,
+ gUnknown_841E263,
+ gUnknown_841E273,
+ gUnknown_841E284,
+ gUnknown_841E29E
+};
+
+const u8 gUnknown_846FAC0[][3] = {
+ {0x01, 0x01, 0x02},
+ {0x02, 0x01, 0x02},
+ {0x03, 0x01, 0x04},
+ {0x04, 0x00, 0x02},
+ {0x15, 0x03, 0x02},
+ {0x16, 0x03, 0x02},
+ {0x09, 0x04, 0x00},
+ {0x0a, 0x04, 0x00},
+ {0x0b, 0x04, 0x00},
+ {0x0c, 0xff, 0x00},
+ {0x0d, 0x00, 0x00},
+ {0x0e, 0xff, 0x00},
+ {0x0f, 0x04, 0x00},
+ {0x10, 0xff, 0x00},
+ {0x40, 0x02, 0x01},
+ {0x41, 0x02, 0x02},
+ {0x44, 0x02, 0x02},
+ {0x45, 0x02, 0x00},
+ {0x48, 0x02, 0x02},
+ {0x54, 0x02, 0x01},
+ {0x53, 0x02, 0x02},
+ {0x51, 0x02, 0x01},
+ {0x52, 0x02, 0x01}
+};
+
+void sub_814F19C(void)
+{
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+ }
+}
+
+void sub_814F1C0(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+void sub_814F1D4(void)
+{
+ SetMainCallback2(sub_814F1E4);
+}
+
+void sub_814F1E4(void)
+{
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ gUnknown_3002040 = AllocZeroed(sizeof(*gUnknown_3002040));
+ SetVBlankCallback(NULL);
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, gUnknown_846FA74, NELEMS(gUnknown_846FA74));
+ SetBgTilemapBuffer(1, Alloc(0x800));
+ SetBgTilemapBuffer(0, Alloc(0x800));
+ DecompressAndLoadBgGfxUsingHeap(1, gUnknown_846F6D0, 0, 0, 0);
+ CopyToBgTilemapBuffer(1, gUnknown_846F8E0, 0, 0);
+ InitWindows(gUnknown_846FA7C);
+ DeactivateAllTextPrinters();
+ ResetPaletteFade();
+ ResetSpriteData();
+ ResetTasks();
+ ScanlineEffect_Stop();
+ m4aSoundVSyncOn();
+ SetVBlankCallback(sub_814F1C0);
+ gUnknown_3002040->field_60 = CreateTask(sub_814F46C, 0);
+ gUnknown_3002040->field_61 = sub_8116DE0();
+ gUnknown_3002040->field_10[3] = 1;
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ LoadPalette(gUnknown_846F4D0, 0, 0x20);
+ Menu_LoadStdPalAt(0xf0);
+ UnkTextUtil_Reset();
+ FillBgTilemapBufferRect(0, 0x000, 0, 0, 32, 32, 0xF);
+ CopyBgTilemapBufferToVram(1);
+ SetMainCallback2(sub_814F19C);
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+void sub_814F32C(void)
+{
+ s32 i;
+
+ FreeAllWindowBuffers();
+ for (i = 0; i < 2; i++)
+ {
+ Free(GetBgTilemapBuffer(i));
+ }
+ Free(gUnknown_3002040);
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+}
+
+void sub_814F364(s16 * unk0, s16 * unk1)
+{
+ s32 idx;
+ (*unk0)++;
+ if (*unk0 > 5)
+ {
+ (*unk1)++;
+ if (*unk1 == 14)
+ {
+ *unk1 = 0;
+ }
+ *unk0 = 0;
+ }
+ idx = *unk1 + 2;
+ LoadPalette(gUnknown_846F4D0[idx], 0, 16);
+}
+
+void sub_814F3A8(void)
+{
+ s32 i;
+ u32 width;
+
+ FillWindowPixelBuffer(0, 0);
+ FillWindowPixelBuffer(1, 0);
+ FillWindowPixelBuffer(2, 0);
+ width = 0xC0 - GetStringWidth(3, gUnknown_846FAAC[0], 0);
+ sub_814F65C(0, 3, gUnknown_846FAAC[0], width / 2, 6, 3);
+ for (i = 0; i < 3; i++)
+ {
+ sub_814F65C(1, 3, gUnknown_846FAAC[i + 1], 0, 30 * i + 10, 1);
+ }
+ sub_814F65C(1, 3, gUnknown_846FAAC[i + 1], 0, 30 * i + 10, 2);
+ PutWindowTilemap(0);
+ CopyWindowToVram(0, 2);
+ PutWindowTilemap(1);
+ CopyWindowToVram(1, 2);
+}
+
+void sub_814F46C(u8 taskId)
+{
+ s32 i;
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ sub_814F3A8();
+ gTasks[taskId].data[0]++;
+ break;
+ case 1:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ ShowBg(1);
+ CopyBgTilemapBufferToVram(0);
+ ShowBg(0);
+ gTasks[taskId].data[0]++;
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ gTasks[taskId].data[0]++;
+ break;
+ case 3:
+ if (sub_814F7E4(gUnknown_3002040->field_00, gUnknown_3002040->field_10, gUnknown_3002040->field_20, gUnknown_3002040->field_61))
+ {
+ FillWindowPixelBuffer(2, 0x00);
+ for (i = 0; i < 4; i++)
+ {
+ ConvertIntToDecimalStringN(gStringVar4, gUnknown_3002040->field_00[i], STR_CONV_MODE_RIGHT_ALIGN, 2);
+ if (i != 3)
+ sub_814F65C(2, 3, gStringVar4, 4, 30 * i + 10, 1);
+ else
+ sub_814F65C(2, 3, gStringVar4, 4, 100, 2);
+ }
+ PutWindowTilemap(2);
+ CopyWindowToVram(2, 3);
+ }
+ if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ gTasks[gUnknown_3002040->field_61].data[15] = 0xFF;
+ gTasks[taskId].data[0]++;
+ }
+ sub_814F364(&gTasks[taskId].data[7], &gTasks[taskId].data[8]);
+ break;
+ case 4:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+ gTasks[taskId].data[0]++;
+ break;
+ case 5:
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(sub_814F32C);
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+void sub_814F65C(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 palIdx)
+{
+ struct TextColor textColor;
+ switch (palIdx)
+ {
+ case 0:
+ textColor.fgColor = 0;
+ textColor.bgColor = 2;
+ textColor.shadowColor = 3;
+ break;
+ case 1:
+ textColor.fgColor = 0;
+ textColor.bgColor = 1;
+ textColor.shadowColor = 3;
+ break;
+ case 2:
+ textColor.fgColor = 0;
+ textColor.bgColor = 4;
+ textColor.shadowColor = 5;
+ break;
+ case 3:
+ textColor.fgColor = 0;
+ textColor.bgColor = 7;
+ textColor.shadowColor = 6;
+ break;
+ case 4:
+ textColor.fgColor = 0;
+ textColor.bgColor = 1;
+ textColor.shadowColor = 2;
+ break;
+ // default: UB
+ }
+ AddTextPrinterParameterized4(windowId, fontId,x, y, fontId == 0 ? 0 : 1, 0, &textColor, -1, str);
+}
+
+u32 sub_814F714(struct UnkStruct_x20 * unk20, u32 * arg1)
+{
+ u32 r8 = unk20->unk.field_0.unk_0a_0;
+ s32 i, j, k;
+
+ for (i = 0; i < NELEMS(gUnknown_846FAC0); i++)
+ {
+ if (r8 == gUnknown_846FAC0[i][0] && unk20->field_1A_0 == 1)
+ {
+ if (gUnknown_846FAC0[i][2] == 0)
+ {
+ k = 0;
+ for (j = 0; j < 4; j++)
+ {
+ if (unk20->unk.field_0.unk_04[j] != 0) k++;
+ }
+ k++;
+ arg1[gUnknown_846FAC0[i][1]] += k;
+ }
+ else
+ {
+ arg1[gUnknown_846FAC0[i][1]] += gUnknown_846FAC0[i][2];
+ }
+ }
+ }
+
+ return r8;
+}
+
+bool32 sub_814F7BC(const u32 * ptr0, const u32 * ptr1)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (ptr0[i] != ptr1[i])
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+bool32 sub_814F7E4(u32 * a0, u32 * a1, u32 * a2, u8 taskId)
+{
+ bool32 r8 = FALSE;
+ u32 sp0[4] = {0, 0, 0, 0};
+ struct UnkStruct_Group * group = (void *)gTasks[taskId].data;
+ s32 i;
+
+ for (i = 0; i < 16; i++)
+ {
+ u32 r1 = sub_814F714(&group->field_0->arr[i], sp0);
+ if (r1 != a2[i])
+ {
+ a2[i] = r1;
+ r8 = TRUE;
+ }
+ }
+
+ if (sub_814F7BC(sp0, a1) == FALSE)
+ {
+ if (r8 == TRUE)
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ memcpy(a0, sp0, sizeof(sp0));
+ memcpy(a1, sp0, sizeof(sp0));
+ a0[3] = a0[0] + a0[1] + a0[2];
+ return TRUE;
+}