summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPikalaxALT <PikalaxALT@users.noreply.github.com>2019-04-15 13:59:00 -0400
committerGitHub <noreply@github.com>2019-04-15 13:59:00 -0400
commit5bf1c29cee223cba17a1ec93af0196e380e8cbf1 (patch)
tree15e666997001cf39d482f2636953c654d255af3e /src
parent0cb1417de441af6e688fc4784da498bb677cc888 (diff)
parent0f569270391f68ef10a703a9e37f1a4e298a0cee (diff)
Merge pull request #49 from PikalaxALT/tm_case
Tm case
Diffstat (limited to 'src')
-rw-r--r--src/fame_checker.c2
-rw-r--r--src/text.c4
-rw-r--r--src/tm_case.c1537
-rw-r--r--src/window.c2
4 files changed, 1541 insertions, 4 deletions
diff --git a/src/fame_checker.c b/src/fame_checker.c
index 29b888a32..c47e52f06 100644
--- a/src/fame_checker.c
+++ b/src/fame_checker.c
@@ -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);
diff --git a/src/text.c b/src/text.c
index d83b36f88..d74d77e2f 100644
--- a/src/text.c
+++ b/src/text.c
@@ -8,7 +8,7 @@
extern u8 gGlyphInfo[0x90];
extern u8 gUnknown_203ADFA;
-extern u16 gUnknown_841F408[];
+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);
@@ -52,7 +52,7 @@ const struct SpriteSheet gUnknown_81EA68C[] =
const struct SpritePalette gUnknown_81EA6A4[] =
{
- {gUnknown_841F408, 0x8000},
+ {gTMCaseMainWindowPalette, 0x8000},
{NULL}
};
diff --git a/src/tm_case.c b/src/tm_case.c
new file mode 100644
index 000000000..2fc30da2d
--- /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.flag_2 = 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 (sub_80BF708() == TRUE)
+ break;
+ }
+}
+
+static bool8 DoSetUpTMCaseUI(void)
+{
+ u8 taskId;
+
+ switch (gMain.state)
+ {
+ case 0:
+ sub_80BF768();
+ 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:
+ sub_809A5E4(&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;
+ sub_80BF7C8();
+ 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].unk_00 = sListMenuStringsBuffer[i];
+ sListMenuItemsBuffer[i].unk_04 = i;
+ }
+ sListMenuItemsBuffer[i].unk_00 = gText_Close;
+ sListMenuItemsBuffer[i].unk_04 = -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)
+{
+ sub_80F6B08(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 = AddScrollIndicatorArrowPairParametrized(2, 0xA0, 0x08, 0x58, sTMCaseDynamicResources->numTMs - sTMCaseDynamicResources->maxTMsShown + 1, 0x6E, 0x6E, &sTMCaseStaticResources.scrollOffset);
+}
+
+static void CreateTMCaseScrollIndicatorArrowPair_SellQuantitySelect(void)
+{
+ sTMCaseDynamicResources->currItem = 1;
+ sTMCaseDynamicResources->scrollIndicatorArrowPairId = AddScrollIndicatorArrowPairParametrized(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;
+
+ sub_809A584(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]);
+ get_coro_args_x18_x1A(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 (!sub_80BF708() && 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);
+ sub_810F4D8(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);
+ sub_810F4D8(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);
+ sub_810F260(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);
+ sub_810F4D8(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;
+
+ sub_810F4D8(8, 0);
+ sub_810F260(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);
+ sub_810F4D8(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);
+ sub_810F4D8(7, 0);
+ sub_810F4D8(8, 0);
+ sub_810F260(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);
+ sub_810F4D8(8, 0);
+ sub_810F260(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;
+ sub_815AC20();
+ }
+ }
+
+ 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);
+ sub_810F260(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();
+ sub_815001C(0, 0x5B, 0xE0);
+ sub_814FEAC(0, 0x64, 0xB0);
+ sub_814FF2C(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)
+{
+ AddTextPrinterParametrized2(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);
+ box_print(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)
+{
+ sub_810F4D8(*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/window.c b/src/window.c
index e760fc8e4..71cfa6898 100644
--- a/src/window.c
+++ b/src/window.c
@@ -320,7 +320,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);
}