#include "global.h" #include "pokenav.h" #include "window.h" #include "strings.h" #include "text.h" #include "bg.h" #include "menu.h" #include "decompress.h" struct UnknownSubSubStruct_0203CF40 { u8 bg; u8 unk1; u8 unk2; u8 unk3; u8 unk4; u8 fontId; u16 unk6; u16 windowId; u16 unkA; u16 unkC; u16 unkE; }; struct MatchCallWindowState { // The index of the element at the top of the window. u16 windowTopIndex; u16 listLength; u16 unk4; // The index of the cursor, relative to the top of the window. u16 selectedIndexOffset; u16 visibleEntries; u16 unkA; u32 unkC; u32 unk10; }; struct UnknownInnerStruct_81C81D4 { struct UnknownSubSubStruct_0203CF40 unk0; u32 unk10; u32 unk14; u32 unk18; u32 unk1C; s32 unk20; s32 unk24; u32 unk28; s32 unk2C; u32 unk30; void (*unk34)(u32, u8*); void (*unk38)(u16, u32, u32); struct Sprite *rightArrow; struct Sprite *upArrow; struct Sprite *downArrow; u8 unkTextBuffer[0x40]; }; // Generally at index 0x11 (17) struct UnknownSubStruct_81C81D4 { struct UnknownInnerStruct_81C81D4 unk0; u8 tilemapBuffer[0x800]; struct MatchCallWindowState unk888; u32 unk89C; u32 unk8A0; }; extern void sub_81DB620(u32 windowId, u32 a1, u32 a2, u32 a3, u32 a4); void sub_81C82E4(struct UnknownSubStruct_81C81D4 *a0); u32 sub_81C91AC(struct UnknownInnerStruct_81C81D4 *a0, const struct BgTemplate *a1, struct MatchCallListTemplate *a2, s32 a3); void sub_81C9160(struct MatchCallWindowState *a0, struct MatchCallListTemplate *a1); void SpriteCB_MatchCallUpArrow(struct Sprite *sprite); void SpriteCB_MatchCallDownArrow(struct Sprite *sprite); void SpriteCB_MatchCallRightArrow(struct Sprite *sprite); void ToggleMatchCallArrows(struct UnknownInnerStruct_81C81D4 *a0, u32 a1); void sub_81C8FE0(struct UnknownInnerStruct_81C81D4 *a0); void sub_81C8EF8(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1); void sub_81C8ED0(void); void sub_81C8E54(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1, u32 a2); void PrintMatchCallFieldNames(struct UnknownInnerStruct_81C81D4 *a0, u32 a1); void sub_81C8D4C(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1); void sub_81C8CB4(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1); void sub_81C8B70(struct UnknownSubSubStruct_0203CF40 *a0, u32 a1, u32 a2); void sub_81C8568(s32 a0, struct UnknownInnerStruct_81C81D4 *a1); void sub_81C83AC(u32 a0, u32 a1, u32 a2, u32 a3, u32 a4, struct UnknownInnerStruct_81C81D4 *a5); void sub_81C837C(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1); void sub_81C835C(struct UnknownSubSubStruct_0203CF40 *a0); u32 LoopedTask_sub_81C8254(s32 a0); bool32 sub_81C83E0(void); u32 LoopedTask_sub_81C83F0(s32 a0); u32 LoopedTask_sub_81C85A0(s32 a0); u32 LoopedTask_sub_81C8870(s32 a0); u32 LoopedTask_sub_81C8A28(s32 a0); u32 LoopedTask_sub_81C8958(s32 a0); static const u16 sMatchcallArrowPaletteData[] = INCBIN_U16("graphics/pokenav/arrows_matchcall.gbapal"); static const u32 sMatchcallArrowSpriteSheetData[] = INCBIN_U32("graphics/pokenav/arrows_matchcall.4bpp.lz"); static const u8 sPokenavColors_0861FBE4[] = { 0, 2, 5 }; static const u8 *const sMatchCallFieldNames[] = { gText_PokenavMatchCall_Strategy, gText_PokenavMatchCall_TrainerPokemon, gText_PokenavMatchCall_SelfIntroduction }; static const u8 sMatchCallFieldColors[] = { 1, 4, 5 }; static const u8 sUnknown_0861FBF7[] = { 2, 4, 6, 7, 0 }; static const struct CompressedSpriteSheet sMatchcallArrowSpriteSheets[] = { { .data = sMatchcallArrowSpriteSheetData, .size = 192, .tag = 0xA } }; static const struct SpritePalette sMatchcallArrowPalettes[] = { { .data = sMatchcallArrowPaletteData, .tag = 0x14 }, {} }; static const struct OamData sMatchCallRightArrowSpriteOam = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, .objMode = ST_OAM_OBJ_NORMAL, .bpp = ST_OAM_4BPP, .shape = SPRITE_SHAPE(8x16), .x = 0, .size = SPRITE_SIZE(8x16), .tileNum = 0, .priority = 2, .paletteNum = 0 }; static const struct SpriteTemplate sMatchCallRightArrowSprite = { .tileTag = 0xA, .paletteTag = 0x14, .oam = &sMatchCallRightArrowSpriteOam, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_MatchCallRightArrow }; static const struct OamData sMatchCallUpDownArrowSpriteOam = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, .objMode = ST_OAM_OBJ_NORMAL, .bpp = ST_OAM_4BPP, .shape = SPRITE_SHAPE(16x8), .x = 0, .size = SPRITE_SIZE(16x8), .tileNum = 0, .priority = 2, .paletteNum = 0 }; static const struct SpriteTemplate sMatchCallUpDownArrowSprite = { .tileTag = 0xA, .paletteTag = 0x14, .oam = &sMatchCallUpDownArrowSpriteOam, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy }; EWRAM_DATA u32 gUnknown_0203CF44 = 0; bool32 sub_81C81D4(const struct BgTemplate *arg0, struct MatchCallListTemplate *arg1, s32 arg2) { u32 v1; struct UnknownSubStruct_81C81D4 *structPtr; structPtr = AllocSubstruct(0x11, sizeof(struct UnknownSubStruct_81C81D4)); if (structPtr == NULL) return FALSE; sub_81C9160(&structPtr->unk888, arg1); v1 = sub_81C91AC(&structPtr->unk0, arg0, arg1, arg2); if (v1 == 0) return FALSE; CreateLoopedTask(LoopedTask_sub_81C8254, 6); return TRUE; } bool32 sub_81C8224(void) { return FuncIsActiveLoopedTask(LoopedTask_sub_81C8254); } void sub_81C8234(void) { struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); sub_81C8FE0(&structPtr->unk0); RemoveWindow(structPtr->unk0.unk0.windowId); FreePokenavSubstruct(0x11); } u32 LoopedTask_sub_81C8254(s32 a0) { struct UnknownSubStruct_81C81D4 *structPtr; if (IsDma3ManagerBusyWithBgCopy()) return 2; structPtr = GetSubstructPtr(0x11); switch (a0) { case 0: sub_81C82E4(structPtr); return 0; case 1: sub_81C835C(&structPtr->unk0.unk0); return 0; case 2: sub_81C837C(&structPtr->unk888, &structPtr->unk0); return 0; case 3: if (sub_81C83E0()) { return 2; } else { sub_81C8ED0(); return 1; } case 4: sub_81C8EF8(&structPtr->unk888, &structPtr->unk0); return 4; default: return 4; } } void sub_81C82E4(struct UnknownSubStruct_81C81D4 *a0) { u16 v1 = (a0->unk0.unk0.unk1 << 12) | a0->unk0.unk0.unk6; sub_8199DF0(a0->unk0.unk0.bg, PIXEL_FILL(1), a0->unk0.unk0.unk6, 1); sub_8199DF0(a0->unk0.unk0.bg, PIXEL_FILL(4), a0->unk0.unk0.unk6 + 1, 1); SetBgTilemapBuffer(a0->unk0.unk0.bg, a0->tilemapBuffer); FillBgTilemapBufferRect_Palette0(a0->unk0.unk0.bg, v1, 0, 0, 32, 32); ChangeBgY(a0->unk0.unk0.bg, 0, 0); ChangeBgX(a0->unk0.unk0.bg, 0, 0); ChangeBgY(a0->unk0.unk0.bg, a0->unk0.unk0.unk3 << 11, 2); CopyBgTilemapBufferToVram(a0->unk0.unk0.bg); } void sub_81C835C(struct UnknownSubSubStruct_0203CF40 *a0) { FillWindowPixelBuffer(a0->windowId, PIXEL_FILL(1)); PutWindowTilemap(a0->windowId); CopyWindowToVram(a0->windowId, 1); } void sub_81C837C(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1) { s32 v1; s32 v2; // TODO: Clean this up. v1 = a0->listLength - a0->windowTopIndex; v2 = a0->visibleEntries; if (v1 > a0->visibleEntries) v1 = v2; sub_81C83AC(a0->unk10, a0->windowTopIndex, v1, a0->unkC, 0, a1); } void sub_81C83AC(u32 a0, u32 a1, u32 a2, u32 a3, u32 a4, struct UnknownInnerStruct_81C81D4 *a5) { if (a2 == 0) return; a5->unk1C = a0 + a1 * a3; a5->unk18 = a3; a5->unk0.unkC = 0; a5->unk0.unkE = a2; a5->unk14 = a1; a5->unk10 = a4; CreateLoopedTask(LoopedTask_sub_81C83F0, 5); } bool32 sub_81C83E0(void) { return FuncIsActiveLoopedTask(LoopedTask_sub_81C83F0); } u32 LoopedTask_sub_81C83F0(s32 a0) { struct UnknownInnerStruct_81C81D4 *structPtr; u32 v1; structPtr = &((struct UnknownSubStruct_81C81D4*)GetSubstructPtr(0x11))->unk0; switch (a0) { case 0: v1 = (structPtr->unk0.unkA + structPtr->unk0.unkC + structPtr->unk10) & 0xF; structPtr->unk34(structPtr->unk1C, structPtr->unkTextBuffer); if (structPtr->unk38 != NULL) // Accessing unk0.windowId as if it were a u16...? // It's accessed as a u8 again in the very next line... structPtr->unk38(*(u16*)(&structPtr->unk0.windowId), structPtr->unk14, v1); AddTextPrinterParameterized(structPtr->unk0.windowId, structPtr->unk0.fontId, structPtr->unkTextBuffer, 8, (v1 << 4) + 1, 255, NULL); if (++structPtr->unk0.unkC >= structPtr->unk0.unkE) { if (structPtr->unk38 != NULL) CopyWindowToVram(structPtr->unk0.windowId, 3); else CopyWindowToVram(structPtr->unk0.windowId, 2); return 0; } else { structPtr->unk1C += structPtr->unk18; structPtr->unk14++; return 3; } case 1: if (IsDma3ManagerBusyWithBgCopy()) return 2; else return 4; default: return 4; } } bool32 ShouldShowUpArrow(void) { u16 v1; s32 v2; struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); return structPtr->unk888.windowTopIndex != 0; } bool32 ShouldShowDownArrow(void) { struct MatchCallWindowState *subPtr; struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); subPtr = &structPtr->unk888; return subPtr->windowTopIndex + subPtr->visibleEntries < subPtr->listLength; } void MatchCall_MoveWindow(s32 a0, bool32 a1_) { register bool32 a1 asm("r4")= a1_; s32 v1; struct UnknownSubStruct_81C81D4 *structPtr = GetSubstructPtr(0x11); register struct MatchCallWindowState *subPtr asm("r5") = &structPtr->unk888; if (a0 < 0) { u16 temp = subPtr->windowTopIndex; if (temp + a0 < 0) v1 = -1 * temp; else v1 = a0; if (a1) sub_81C83AC(subPtr->unk10, temp + v1, v1 * -1, subPtr->unkC, v1, &structPtr->unk0); } else if (a1) { s32 temp = gUnknown_0203CF44 = subPtr->windowTopIndex + subPtr->visibleEntries; s32 listLength; if (temp + a0 >= (listLength = subPtr->listLength)) v1 = listLength - temp; else v1 = a0; sub_81C83AC(subPtr->unk10, gUnknown_0203CF44, v1, subPtr->unkC, subPtr->visibleEntries, &structPtr->unk0); // Needed to prevent GCC from combining the two sub_81C83AC calls. asm(""); } else { v1 = a0; } sub_81C8568(v1, &structPtr->unk0); subPtr->windowTopIndex += v1; } void sub_81C8568(s32 a0, struct UnknownInnerStruct_81C81D4 *a1) { a1->unk20 = GetBgY(a1->unk0.bg); a1->unk24 = a1->unk20 + (a0 << 12); if (a0 > 0) a1->unk30 = 1; else a1->unk30 = 2; a1->unk2C = a0; a1->unk28 = CreateLoopedTask(LoopedTask_sub_81C85A0, 6); } u32 LoopedTask_sub_81C85A0(s32 a0) { s32 y; s32 v1; bool32 flag; struct UnknownInnerStruct_81C81D4 *structPtr; structPtr = &((struct UnknownSubStruct_81C81D4 *)GetSubstructPtr(0x11))->unk0; switch (a0) { case 0: if (sub_81C83E0() == FALSE) return 1; else return 2; case 1: flag = FALSE; y = GetBgY(structPtr->unk0.bg); v1 = ChangeBgY(structPtr->unk0.bg, 0x1000, structPtr->unk30); if (structPtr->unk30 == 2) { if ((y > structPtr->unk24 || y <= structPtr->unk20) && v1 <= structPtr->unk24) { flag = TRUE; } } else { if ((y < structPtr->unk24 || y >= structPtr->unk20) && v1 >= structPtr->unk24) { flag = TRUE; } } if (flag) { structPtr->unk0.unkA = (structPtr->unk0.unkA + structPtr->unk2C) & 0xF; ChangeBgY(structPtr->unk0.bg, structPtr->unk24, 0); return 4; } else { return 2; } default: return 4; } } bool32 sub_81C8630(void) { struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); return IsLoopedTaskActive(structPtr->unk0.unk28); } struct MatchCallWindowState *GetMatchCallWindowStruct(void) { struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); return &structPtr->unk888; } int MatchCall_MoveCursorUp(void) { struct MatchCallWindowState *structPtr; structPtr = GetMatchCallWindowStruct(); if (structPtr->selectedIndexOffset != 0) { structPtr->selectedIndexOffset--; return 1; } else { if (ShouldShowUpArrow()) { MatchCall_MoveWindow(-1, TRUE); return 2; } else { return 0; } } } int MatchCall_MoveCursorDown(void) { struct MatchCallWindowState *structPtr; structPtr = GetMatchCallWindowStruct(); if (structPtr->windowTopIndex + structPtr->selectedIndexOffset < structPtr->listLength - 1) { if (structPtr->selectedIndexOffset < structPtr->visibleEntries - 1) { structPtr->selectedIndexOffset++; return 1; } else if (!ShouldShowDownArrow()) { return 0; } } else { return 0; } MatchCall_MoveWindow(1, TRUE); return 2; } int MatchCall_PageUp(void) { struct MatchCallWindowState *structPtr; s32 scroll; structPtr = GetMatchCallWindowStruct(); if (ShouldShowUpArrow()) { if (structPtr->windowTopIndex >= structPtr->visibleEntries) scroll = structPtr->visibleEntries; else scroll = structPtr->windowTopIndex; MatchCall_MoveWindow(scroll * -1, TRUE); return 2; } else if (structPtr->selectedIndexOffset != 0) { structPtr->selectedIndexOffset = 0; return 1; } else { return 0; } } int MatchCall_PageDown(void) { struct MatchCallWindowState *structPtr; structPtr = GetMatchCallWindowStruct(); if (ShouldShowDownArrow()) { s32 scroll; s32 windowBottomIndex; s32 v3; windowBottomIndex = structPtr->windowTopIndex + structPtr->visibleEntries; scroll = structPtr->unk4 - structPtr->windowTopIndex; if (windowBottomIndex <= structPtr->unk4) scroll = structPtr->visibleEntries; MatchCall_MoveWindow(scroll, TRUE); return 2; } else { s32 cursor; s32 lastVisibleIndex; if (structPtr->listLength >= structPtr->visibleEntries) { cursor = structPtr->selectedIndexOffset; lastVisibleIndex = structPtr->visibleEntries; } else { cursor = structPtr->selectedIndexOffset; lastVisibleIndex = structPtr->listLength; } lastVisibleIndex -= 1; if (cursor >= lastVisibleIndex) { return 0; } else { structPtr->selectedIndexOffset = lastVisibleIndex; return 1; } } } u32 GetSelectedMatchCall(void) { struct MatchCallWindowState *structPtr; structPtr = GetMatchCallWindowStruct(); return structPtr->windowTopIndex + structPtr->selectedIndexOffset; } u32 GetMatchCallListTopIndex(void) { struct MatchCallWindowState *structPtr; structPtr = GetMatchCallWindowStruct(); return structPtr->windowTopIndex; } void sub_81C877C(void) { struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); structPtr->unk89C = 0; structPtr->unk8A0 = CreateLoopedTask(LoopedTask_sub_81C8870, 6); } void sub_81C87AC(s16 a0) { u16 temp; struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); temp = structPtr->unk888.windowTopIndex; temp += a0; structPtr->unk888.windowTopIndex = temp; structPtr->unk89C = 0; structPtr->unk8A0 = CreateLoopedTask(LoopedTask_sub_81C8958, 6); } void sub_81C87F0(void) { struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); structPtr->unk89C = 0; structPtr->unk8A0 = CreateLoopedTask(LoopedTask_sub_81C8A28, 6); } bool32 sub_81C8820(void) { struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); return IsLoopedTaskActive(structPtr->unk8A0); } void sub_81C8838(void) { struct UnknownSubStruct_81C81D4 *structPtr; struct MatchCallWindowState *subStr; structPtr = GetSubstructPtr(0x11); subStr = &structPtr->unk888; structPtr->unk0.unk38(structPtr->unk0.unk0.windowId, subStr->windowTopIndex + subStr->selectedIndexOffset, (structPtr->unk0.unk0.unkA + subStr->selectedIndexOffset) & 0xF); CopyWindowToVram(structPtr->unk0.unk0.windowId, 1); } u32 LoopedTask_sub_81C8870(s32 a0) { struct UnknownSubStruct_81C81D4 *structPtr; u16 v1; u32 v2; // Needed to fix a register renaming issue. register u16* temp asm("r1"); structPtr = GetSubstructPtr(0x11); switch (a0) { case 0: ToggleMatchCallArrows(&structPtr->unk0, 1); // fall-through case 1: if (structPtr->unk89C != structPtr->unk888.selectedIndexOffset) sub_81C8B70(&structPtr->unk0.unk0, structPtr->unk89C, 1); structPtr->unk89C++; return 0; case 2: if (IsDma3ManagerBusyWithBgCopy()) return 2; if (structPtr->unk89C != structPtr->unk888.visibleEntries) return 6; if (structPtr->unk888.selectedIndexOffset != 0) sub_81C8B70(&structPtr->unk0.unk0, structPtr->unk89C, structPtr->unk888.selectedIndexOffset); return 0; case 3: if (IsDma3ManagerBusyWithBgCopy()) return 2; temp = &structPtr->unk888.selectedIndexOffset; v1 = *temp; if (v1 == 0) return 4; MatchCall_MoveWindow(v1, FALSE); return 0; case 4: v2 = sub_81C8630(); if (v2) return 2; structPtr->unk888.selectedIndexOffset = v2; return 4; default: return 4; } } u32 LoopedTask_sub_81C8958(s32 a0) { struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); if (IsDma3ManagerBusyWithBgCopy()) return 2; switch (a0) { case 0: sub_81C8CB4(&structPtr->unk888, &structPtr->unk0); break; case 1: PrintMatchCallFieldNames(&structPtr->unk0, 0); break; case 2: sub_81C8E54(&structPtr->unk888, &structPtr->unk0, 0); break; case 3: PrintMatchCallFieldNames(&structPtr->unk0, 1); break; case 4: sub_81C8E54(&structPtr->unk888, &structPtr->unk0, 1); break; case 5: PrintMatchCallFieldNames(&structPtr->unk0, 2); break; case 6: sub_81C8E54(&structPtr->unk888, &structPtr->unk0, 2); break; case 7: sub_81C8E54(&structPtr->unk888, &structPtr->unk0, 3); break; default: return 4; } return 0; } u32 LoopedTask_sub_81C8A28(s32 a0) { struct UnknownSubStruct_81C81D4 *structPtr; struct MatchCallWindowState *subPtr888; register struct UnknownInnerStruct_81C81D4 *subPtr0 asm("r2"); s32 v4; if (IsDma3ManagerBusyWithBgCopy()) { return 2; } structPtr = GetSubstructPtr(0x11); subPtr888 = &structPtr->unk888; subPtr0 = &structPtr->unk0; switch (a0) { default: return 4; case 0: sub_81C8D4C(subPtr888, subPtr0); return 0; case 1: { s32 v1; s32 v2; u32 *v3; register s32 v4 asm("r5"); v3 = &structPtr->unk89C; v1 = *v3 + 1; *v3 = v1; if (v1 < structPtr->unk888.visibleEntries) { sub_81C8B70(&subPtr0->unk0, v1, 1); return 2; } *v3 = 0; if (subPtr888->listLength <= subPtr888->visibleEntries) { register u32 temp asm("r0"); temp = subPtr888->windowTopIndex; if (temp == 0) return 9; v2 = temp; } else { register s32 temp asm("r1"); v2 = subPtr888->windowTopIndex + subPtr888->visibleEntries; temp = (s32)subPtr888->listLength; if (v2 <= temp) return 9; v2 -= temp; } v4 = v2 * -1; sub_81C8B70(&subPtr0->unk0, v4, v2); subPtr888->selectedIndexOffset = v2; *v3 = v4; return 0; } case 2: MatchCall_MoveWindow(structPtr->unk89C, FALSE); return 0; case 3: if (sub_81C8630()) return 2; structPtr->unk89C = 0; return 1; case 4: sub_81C83AC(subPtr888->unk10, subPtr888->windowTopIndex + structPtr->unk89C, 1, subPtr888->unkC, structPtr->unk89C, &structPtr->unk0); return 0; case 5: if (sub_81C83E0()) return 2; v4 = ++structPtr->unk89C; if (v4 >= subPtr888->listLength || v4 >= subPtr888->visibleEntries) return 1; return 9; case 6: ToggleMatchCallArrows(subPtr0, 0); return 4; } } void sub_81C8B70(struct UnknownSubSubStruct_0203CF40 *a0, u32 a1, u32 a2) { u8 *v1; u32 v2; v1 = (u8*)GetWindowAttribute(a0->windowId, WINDOW_TILE_DATA); v2 = a0->unk4 * 64; a1 = (a0->unkA + a1) & 0xF; if ((s32)(a1 + a2) <= 16) { CpuFastFill8(PIXEL_FILL(1), v1 + a1 * v2, a2 * v2); CopyWindowToVram(a0->windowId, 2); } else { u32 v3; u32 v4; v3 = 16 - a1; v4 = a2 - v3; CpuFastFill8(PIXEL_FILL(1), v1 + a1 * v2, v3 * v2); CpuFastFill8(PIXEL_FILL(1), v1, v4 * v2); CopyWindowToVram(a0->windowId, 2); } a2 -= 1; for (a2; a2 != -1; a1 = (a1 + 1) & 0xF, a2--) { sub_81CBD48(a0->windowId, a1); } CopyWindowToVram(a0->windowId, 1); } void sub_81C8C64(struct UnknownSubSubStruct_0203CF40 *a0, u32 a1) { u16 *v1; register u32 v2 asm("r0"); u32 v3; v1 = (u16*)GetBgTilemapBuffer(GetWindowAttribute(a0->windowId, WINDOW_BG)); v1 = &v1[(a0->unkA << 6) + a0->unk2 - 1]; if (a1 != 0) { v2 = a0->unk1 << 12; v3 = a0->unk6 + 1; } else { v2 = a0->unk1 << 12; v3 = a0->unk6; } { register u16 v5 asm("r1"); register u32 v6 asm("r0"); v6 = (v3 | v2); v6 = v6 << 16; v5 = v6 >> 16; v1[0] = v5; v1[0x20] = v5; } } void sub_81C8CB4(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1) { u8 colors[3]; memcpy(colors, sPokenavColors_0861FBE4, ARRAY_COUNT(sPokenavColors_0861FBE4)); a1->unk34(a0->unk10 + a0->unkC * a0->windowTopIndex, a1->unkTextBuffer); a1->unk38(a1->unk0.windowId, a0->windowTopIndex, a1->unk0.unkA); FillWindowPixelRect(a1->unk0.windowId, PIXEL_FILL(4), 0, a1->unk0.unkA * 16, a1->unk0.unk4 * 8, 16); AddTextPrinterParameterized3(a1->unk0.windowId, a1->unk0.fontId, 8, (a1->unk0.unkA * 16) + 1, colors, TEXT_SPEED_FF, a1->unkTextBuffer); sub_81C8C64(&a1->unk0, 1); CopyWindowRectToVram(a1->unk0.windowId, 3, 0, a1->unk0.unkA * 2, a1->unk0.unk4, 2); } void sub_81C8D4C(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1) { a1->unk34(a0->unk10 + a0->unkC * a0->windowTopIndex, a1->unkTextBuffer); FillWindowPixelRect(a1->unk0.windowId, PIXEL_FILL(1), 0, a1->unk0.unkA * 16, a1->unk0.unk4 * 8, 16); AddTextPrinterParameterized(a1->unk0.windowId, a1->unk0.fontId, a1->unkTextBuffer, 8, a1->unk0.unkA * 16 + 1, TEXT_SPEED_FF, NULL); sub_81C8C64(&a1->unk0, 0); CopyWindowToVram(a1->unk0.windowId, 3); } void PrintMatchCallFieldNames(struct UnknownInnerStruct_81C81D4 *a0, u32 fieldId) { const u8 *fieldNames[3]; u8 colors[3]; u32 r4; u32 r5; u32 tmp; u32 one; memcpy(fieldNames, sMatchCallFieldNames, sizeof(sMatchCallFieldNames)); memcpy(colors, sMatchCallFieldColors, sizeof(sMatchCallFieldColors)); r4 = a0->unk0.unkA; tmp = fieldId * 2 + 1; r4 += tmp; r4 &= 0xF; FillWindowPixelRect(a0->unk0.windowId, PIXEL_FILL(1), 0, r4 << 4, a0->unk0.unk4, 16); // This is a fake match. It should be this: // AddTextPrinterParameterized3(a0->unk0.windowId, 7, 2, r4 << 4 + 1, colors, TEXT_SPEED_FF, fieldNames[fieldId]); // But the original GCC does some clever reuse of the `1` constant that the current GCC doesn't. one = 1; AddTextPrinterParameterized3(a0->unk0.windowId, 7, 2, (r4 << 4) + one, colors, one - 2, fieldNames[fieldId]); CopyWindowRectToVram(a0->unk0.windowId, 2, 0, r4 << 1, a0->unk0.unk4, 2); } void sub_81C8E54(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1, u32 a2) { const u8 *str; u32 r6; r6 = (a1->unk0.unkA + sUnknown_0861FBF7[a2]) & 0xF; str = sub_81CAFD8(a0->windowTopIndex, a2); if (str != NULL) { sub_81DB620(a1->unk0.windowId, 1, r6 * 2, a1->unk0.unk4 - 1, 2); AddTextPrinterParameterized(a1->unk0.windowId, 7, str, 2, (r6 << 4) + 1, TEXT_SPEED_FF, NULL); CopyWindowRectToVram(a1->unk0.windowId, 2, 0, r6 * 2, a1->unk0.unk4, 2); } } void sub_81C8ED0(void) { u32 i; const struct CompressedSpriteSheet *ptr; for (i = 0, ptr = sMatchcallArrowSpriteSheets; i < ARRAY_COUNT(sMatchcallArrowSpriteSheets); ptr++, i++) { LoadCompressedSpriteSheet(ptr); } Pokenav_AllocAndLoadPalettes(sMatchcallArrowPalettes); } void sub_81C8EF8(struct MatchCallWindowState *a0, struct UnknownInnerStruct_81C81D4 *a1) { register u32 spriteId asm("r3"); s16 temp; spriteId = (u8)CreateSprite(&sMatchCallRightArrowSprite, a1->unk0.unk2 * 8 + 3, (a1->unk0.unk3 + 1) * 8, 7); a1->rightArrow = &gSprites[spriteId]; temp = a1->unk0.unk2 * 8 + (a1->unk0.unk4 - 1) * 4; spriteId = (u8)CreateSprite(&sMatchCallUpDownArrowSprite, temp, a1->unk0.unk3 * 8 + a0->visibleEntries * 16, 7); a1->downArrow = &gSprites[spriteId]; a1->downArrow->oam.tileNum += 2; a1->downArrow->callback = SpriteCB_MatchCallDownArrow; spriteId = (u8)CreateSprite(&sMatchCallUpDownArrowSprite, temp, a1->unk0.unk3 * 8, 7); a1->upArrow = &gSprites[spriteId]; a1->upArrow->oam.tileNum += 4; a1->upArrow->callback = SpriteCB_MatchCallUpArrow; } void sub_81C8FE0(struct UnknownInnerStruct_81C81D4 *a0) { DestroySprite(a0->rightArrow); DestroySprite(a0->upArrow); DestroySprite(a0->downArrow); FreeSpriteTilesByTag(0xA); FreeSpritePaletteByTag(0x14); } void ToggleMatchCallArrows(struct UnknownInnerStruct_81C81D4 *a0, bool32 shouldHide) { if (shouldHide) { a0->rightArrow->callback = SpriteCallbackDummy; a0->upArrow->callback = SpriteCallbackDummy; a0->downArrow->callback = SpriteCallbackDummy; } else { a0->rightArrow->callback = SpriteCB_MatchCallRightArrow; a0->upArrow->callback = SpriteCB_MatchCallUpArrow; a0->downArrow->callback = SpriteCB_MatchCallDownArrow; } a0->rightArrow->invisible = shouldHide; a0->upArrow->invisible = shouldHide; a0->downArrow->invisible = shouldHide; } void SpriteCB_MatchCallRightArrow(struct Sprite *sprite) { struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); sprite->pos2.y = structPtr->unk888.selectedIndexOffset << 4; } void SpriteCB_MatchCallDownArrow(struct Sprite *sprite) { if (sprite->data[7] == 0 && ShouldShowDownArrow()) sprite->invisible = FALSE; else sprite->invisible = TRUE; if (++sprite->data[0] > 3) { s16 offset; sprite->data[0] = 0; offset = (sprite->data[1] + 1) & 7; sprite->data[1] = offset; sprite->pos2.y = offset; } } void SpriteCB_MatchCallUpArrow(struct Sprite *sprite) { if (sprite->data[7] == 0 && ShouldShowUpArrow()) sprite->invisible = FALSE; else sprite->invisible = TRUE; if (++sprite->data[0] > 3) { s16 offset; sprite->data[0] = 0; offset = (sprite->data[1] + 1) & 7; sprite->data[1] = offset; sprite->pos2.y = -1 * offset; } } void ToggleMatchCallVerticalArrows(bool32 shouldHide) { struct UnknownSubStruct_81C81D4 *structPtr; structPtr = GetSubstructPtr(0x11); structPtr->unk0.upArrow->data[7] = shouldHide; structPtr->unk0.downArrow->data[7] = shouldHide; } void sub_81C9160(struct MatchCallWindowState *a0, struct MatchCallListTemplate *a1) { u32 unused1 = a0->unk10 = a1->unk0; u32 v0 = a1->unk6; u32 zero = 0; u32 unused2 = a0->windowTopIndex = v0; u32 v1 = a0->listLength = a1->unk4; a0->unkC = a1->unk8; a0->visibleEntries = a1->unkC; if (a0->visibleEntries >= (u16)v1) { a0->windowTopIndex = 0; a0->unk4 = 0; a0->selectedIndexOffset = v0; } else { s32 v2; a0->unk4 = a0->listLength - a0->visibleEntries; v2 = a0->windowTopIndex + a0->visibleEntries; if (v2 > a0->listLength) { a0->selectedIndexOffset = v2 - a0->listLength; a0->windowTopIndex = v0 - a0->selectedIndexOffset; } else { a0->selectedIndexOffset = 0; } } } u32 sub_81C91AC(struct UnknownInnerStruct_81C81D4 *a0, const struct BgTemplate *a1, struct MatchCallListTemplate *a2, s32 a3) { register u32 raw_bg asm("r4") = ((a1->bg) << 30); u8 bg = raw_bg >> 30; u32 unknown = 0; struct WindowTemplate window; u8 bg_again; a0->unk0.bg = bg; a0->unk0.unk6 = a3; a0->unk34 = a2->unk10; a0->unk38 = a2->unk14; a0->unk0.unk1 = a2->unkD; a0->unk0.unk2 = a2->unk9; a0->unk0.unk3 = a2->unkB; a0->unk0.unk4 = a2->unkA; a0->unk0.fontId = a2->unkE; window.bg = raw_bg >> 30; window.tilemapLeft = a2->unk9; window.tilemapTop = 0; window.width = a2->unkA; window.height = 32; window.paletteNum = a2->unkD; window.baseBlock = a3 + 2; a0->unk0.windowId = AddWindow(&window); if (a0->unk0.windowId == 0xFF) { return 0; } else { a0->unk0.unkA = unknown; a0->rightArrow = NULL; a0->upArrow = NULL; a0->downArrow = NULL; return 1; } }