diff options
Diffstat (limited to 'src/wireless_communication_status_screen.c')
-rw-r--r-- | src/wireless_communication_status_screen.c | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/src/wireless_communication_status_screen.c b/src/wireless_communication_status_screen.c new file mode 100644 index 000000000..87b200f14 --- /dev/null +++ b/src/wireless_communication_status_screen.c @@ -0,0 +1,432 @@ +#include "global.h" +#include "task.h" +#include "bg.h" +#include "palette.h" +#include "gpu_regs.h" +#include "malloc.h" +#include "scanline_effect.h" +#include "m4a.h" +#include "dynamic_placeholder_text_util.h" +#include "overworld.h" +#include "strings.h" +#include "string_util.h" +#include "international_string_util.h" +#include "sound.h" +#include "menu.h" +#include "librfu.h" +#include "link_rfu.h" +#include "union_room.h" +#include "constants/songs.h" +#include "constants/union_room.h" + +enum { + COLORMODE_NORMAL, + COLORMODE_WHITE_LGRAY, + COLORMODE_RED, + COLORMODE_GREEN, + COLORMODE_WHITE_DGRAY, +}; + +#define GROUPTYPE_TRADE 0 +#define GROUPTYPE_BATTLE 1 +#define GROUPTYPE_UNION 2 +#define GROUPTYPE_TOTAL 3 +#define GROUPTYPE_NONE -1 +#define NUM_GROUPTYPES 4 + +struct WirelessCommunicationStatusScreen +{ + u32 groupCounts[NUM_GROUPTYPES]; + u32 prevGroupCounts[NUM_GROUPTYPES]; + u32 activities[NUM_TASK_DATA]; + u8 taskId; + u8 rfuTaskId; + u8 filler[10]; +}; + +static struct WirelessCommunicationStatusScreen * sStatusScreen; + +static void CB2_InitWirelessCommunicationScreen(void); +static void Task_WirelessCommunicationScreen(u8); +static void WCSS_AddTextPrinterParameterized(u8, u8, const u8 *, u8, u8, u8); +static bool32 UpdateCommunicationCounts(u32 *, u32 *, u32 *, u8); + +static const u16 sBgTiles_Pal[] = INCBIN_U16("graphics/interface/wireless_info_screen.gbapal"); +static const u32 sBgTiles_Gfx[] = INCBIN_U32("graphics/interface/wireless_info_screen.4bpp.lz"); +static const u32 sBgTiles_Tilemap[] = INCBIN_U32("graphics/interface/wireless_info_screen.bin.lz"); + +static const struct BgTemplate sBgTemplates[] = { + { + .bg = 0, + .charBaseIndex = 2, + .mapBaseIndex = 31, + .priority = 0 + }, { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 8, + .priority = 1 + } +}; + +static const struct WindowTemplate sWindowTemplates[] = { + { + .bg = 0, + .tilemapLeft = 3, + .tilemapTop = 0, + .width = 24, + .height = 3, + .paletteNum = 15, + .baseBlock = 0x0001 + }, { + .bg = 0, + .tilemapLeft = 3, + .tilemapTop = 4, + .width = 21, + .height = 15, + .paletteNum = 15, + .baseBlock = 0x0049 + }, { + .bg = 0, + .tilemapLeft = 24, + .tilemapTop = 4, + .width = 3, + .height = 15, + .paletteNum = 15, + .baseBlock = 0x0184 + }, DUMMY_WIN_TEMPLATE +}; + +static const u8 *const sHeaderTexts[NUM_GROUPTYPES + 1] = { + [0] = gText_WirelessCommStatus, + [GROUPTYPE_TRADE + 1] = gText_PeopleTrading, + [GROUPTYPE_BATTLE + 1] = gText_PeopleBattling, + [GROUPTYPE_UNION + 1] = gText_PeopleInUnionRoom, + [GROUPTYPE_TOTAL + 1] = gText_PeopleCommunicating +}; + +// Activity, group type, number of players +// 0 players means the number of players can change and should be counted dynamically +// GROUPTYPE_TOTAL have no unique group and are simply counted in the total of "people communicating" +// UB: GROUPTYPE_NONE (-1) can potentially be used as an index into a u8[4] in CountPlayersInGroupAndGetActivity +static const u8 sActivityGroupInfo[][3] = { + {ACTIVITY_BATTLE_SINGLE, GROUPTYPE_BATTLE, 2}, + {ACTIVITY_BATTLE_DOUBLE, GROUPTYPE_BATTLE, 2}, + {ACTIVITY_BATTLE_MULTI, GROUPTYPE_BATTLE, 4}, + {ACTIVITY_TRADE, GROUPTYPE_TRADE, 2}, + {ACTIVITY_WONDER_CARD, GROUPTYPE_TOTAL, 2}, + {ACTIVITY_WONDER_NEWS, GROUPTYPE_TOTAL, 2}, + {ACTIVITY_POKEMON_JUMP, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_BERRY_CRUSH, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_BERRY_PICK, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_SEARCH, GROUPTYPE_NONE, 0}, + {ACTIVITY_SPIN_TRADE, GROUPTYPE_TRADE, 0}, + {ACTIVITY_BERRY_BLENDER, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_RECORD_CORNER, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_NONE | IN_UNION_ROOM, GROUPTYPE_UNION, 1}, + {ACTIVITY_BATTLE_SINGLE | IN_UNION_ROOM, GROUPTYPE_UNION, 2}, + {ACTIVITY_TRADE | IN_UNION_ROOM, GROUPTYPE_UNION, 2}, + {ACTIVITY_CHAT | IN_UNION_ROOM, GROUPTYPE_UNION, 0}, + {ACTIVITY_CARD | IN_UNION_ROOM, GROUPTYPE_UNION, 2}, + {ACTIVITY_PLYRTALK | IN_UNION_ROOM, GROUPTYPE_UNION, 1}, + {ACTIVITY_NPCTALK | IN_UNION_ROOM, GROUPTYPE_UNION, 2}, + {ACTIVITY_ACCEPT | IN_UNION_ROOM, GROUPTYPE_UNION, 1}, + {ACTIVITY_DECLINE | IN_UNION_ROOM, GROUPTYPE_UNION, 1}, + {ACTIVITY_WONDER_CARD2, GROUPTYPE_TOTAL, 2}, + {ACTIVITY_WONDER_NEWS2, GROUPTYPE_TOTAL, 2}, + {ACTIVITY_CONTEST_COOL, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_CONTEST_BEAUTY, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_CONTEST_CUTE, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_CONTEST_SMART, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_CONTEST_TOUGH, GROUPTYPE_TOTAL, 0}, + {ACTIVITY_BATTLE_TOWER, GROUPTYPE_BATTLE, 2}, + {ACTIVITY_BATTLE_TOWER_OPEN, GROUPTYPE_BATTLE, 2} +}; + +static void CB2_RunWirelessCommunicationScreen(void) +{ + if (!IsDma3ManagerBusyWithBgCopy()) + { + RunTasks(); + RunTextPrinters(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); + } +} + +static void VBlankCB_WirelessCommunicationScreen(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +void ShowWirelessCommunicationScreen(void) +{ + SetMainCallback2(CB2_InitWirelessCommunicationScreen); +} + +static void CB2_InitWirelessCommunicationScreen(void) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + sStatusScreen = AllocZeroed(sizeof(struct WirelessCommunicationStatusScreen)); + SetVBlankCallback(NULL); + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); + SetBgTilemapBuffer(1, Alloc(0x800)); + SetBgTilemapBuffer(0, Alloc(0x800)); + DecompressAndLoadBgGfxUsingHeap(1, sBgTiles_Gfx, 0, 0, 0); + CopyToBgTilemapBuffer(1, sBgTiles_Tilemap, 0, 0); + InitWindows(sWindowTemplates); + DeactivateAllTextPrinters(); + ResetPaletteFade(); + ResetSpriteData(); + ResetTasks(); + ScanlineEffect_Stop(); + m4aSoundVSyncOn(); + SetVBlankCallback(VBlankCB_WirelessCommunicationScreen); + sStatusScreen->taskId = CreateTask(Task_WirelessCommunicationScreen, 0); + sStatusScreen->rfuTaskId = CreateTask_ListenToWireless(); + sStatusScreen->prevGroupCounts[GROUPTYPE_TOTAL] = 1; + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + ChangeBgX(1, 0, 0); + ChangeBgY(1, 0, 0); + LoadPalette(sBgTiles_Pal, 0x00, 0x20); + Menu_LoadStdPalAt(0xF0); + DynamicPlaceholderTextUtil_Reset(); + FillBgTilemapBufferRect(0, 0, 0, 0, 32, 32, 0x0F); + CopyBgTilemapBufferToVram(1); + SetMainCallback2(CB2_RunWirelessCommunicationScreen); + RunTasks(); + RunTextPrinters(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void CB2_ExitWirelessCommunicationStatusScreen(void) +{ + s32 i; + FreeAllWindowBuffers(); + for (i = 0; i < (int)ARRAY_COUNT(sBgTemplates); i++) + { + Free(GetBgTilemapBuffer(i)); + } + Free(sStatusScreen); + SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); +} + +static void WCSS_CyclePalette(s16 * counter, s16 * palIdx) +{ + if (++(*counter) > 5) + { + if (++(*palIdx) == 14) + *palIdx = 0; + + *counter = 0; + } + LoadPalette(sBgTiles_Pal + 16 * (*palIdx + 2), 0, 0x10); +} + +static void PrintHeaderTexts(void) +{ + s32 i; + FillWindowPixelBuffer(0, PIXEL_FILL(0)); + FillWindowPixelBuffer(1, PIXEL_FILL(0)); + FillWindowPixelBuffer(2, PIXEL_FILL(0)); + WCSS_AddTextPrinterParameterized(0, 1, sHeaderTexts[0], GetStringCenterAlignXOffset(1, sHeaderTexts[0], 0xC0), 6, COLORMODE_GREEN); + for (i = 0; i < (int)ARRAY_COUNT(*sHeaderTexts) - 1; i++) + { + WCSS_AddTextPrinterParameterized(1, 1, sHeaderTexts[i + 1], 0, 30 * i + 8, COLORMODE_WHITE_LGRAY); + } + WCSS_AddTextPrinterParameterized(1, 1, sHeaderTexts[i + 1], 0, 30 * i + 8, COLORMODE_RED); + PutWindowTilemap(0); + CopyWindowToVram(0, 2); + PutWindowTilemap(1); + CopyWindowToVram(1, 2); +} + +#define tState data[0] + +static void Task_WirelessCommunicationScreen(u8 taskId) +{ + s32 i; + switch (gTasks[taskId].tState) + { + case 0: + PrintHeaderTexts(); + gTasks[taskId].tState++; + break; + case 1: + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0); + ShowBg(1); + CopyBgTilemapBufferToVram(0); + ShowBg(0); + gTasks[taskId].tState++; + break; + case 2: + if (!gPaletteFade.active) + { + gTasks[taskId].tState++; + } + break; + case 3: + if (UpdateCommunicationCounts(sStatusScreen->groupCounts, sStatusScreen->prevGroupCounts, sStatusScreen->activities, sStatusScreen->rfuTaskId)) + { + FillWindowPixelBuffer(2, PIXEL_FILL(0)); + for (i = 0; i < NUM_GROUPTYPES; i++) + { + ConvertIntToDecimalStringN(gStringVar4, sStatusScreen->groupCounts[i], STR_CONV_MODE_RIGHT_ALIGN, 2); + if (i != GROUPTYPE_TOTAL) + WCSS_AddTextPrinterParameterized(2, 1, gStringVar4, 12, 30 * i + 8, COLORMODE_WHITE_LGRAY); + else + WCSS_AddTextPrinterParameterized(2, 1, gStringVar4, 12, 98, COLORMODE_RED); + } + PutWindowTilemap(2); + CopyWindowToVram(2, 3); + } + if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + gTasks[sStatusScreen->rfuTaskId].data[15] = 0xFF; + gTasks[taskId].tState++; + } + WCSS_CyclePalette(&gTasks[taskId].data[7], &gTasks[taskId].data[8]); + break; + case 4: + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].tState++; + break; + case 5: + if (!gPaletteFade.active) + { + SetMainCallback2(CB2_ExitWirelessCommunicationStatusScreen); + DestroyTask(taskId); + } + break; + } +} + +#undef tState + +static void WCSS_AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 mode) +{ + u8 color[3]; + + switch (mode) + { + case COLORMODE_NORMAL: + color[0] = TEXT_COLOR_TRANSPARENT; + color[1] = TEXT_COLOR_DARK_GREY; + color[2] = TEXT_COLOR_LIGHT_GREY; + break; + case COLORMODE_WHITE_LGRAY: + color[0] = TEXT_COLOR_TRANSPARENT; + color[1] = TEXT_COLOR_WHITE; + color[2] = TEXT_COLOR_LIGHT_GREY; + break; + case COLORMODE_RED: + color[0] = TEXT_COLOR_TRANSPARENT; + color[1] = TEXT_COLOR_RED; + color[2] = TEXT_COLOR_LIGHT_RED; + break; + case COLORMODE_GREEN: + color[0] = TEXT_COLOR_TRANSPARENT; + color[1] = TEXT_COLOR_LIGHT_GREEN; + color[2] = TEXT_COLOR_GREEN; + break; + case COLORMODE_WHITE_DGRAY: + color[0] = TEXT_COLOR_TRANSPARENT; + color[1] = TEXT_COLOR_WHITE; + color[2] = TEXT_COLOR_DARK_GREY; + break; + } + + AddTextPrinterParameterized4(windowId, fontId, x, y, 0, 0, color, -1, str); +} + +static u32 CountPlayersInGroupAndGetActivity(struct UnkStruct_x20 * unk20, u32 * groupCounts) +{ + int i, j, k; + u32 activity = unk20->gname_uname.gname.activity; + + #define group_activity(i) (sActivityGroupInfo[(i)][0]) + #define group_type(i) (sActivityGroupInfo[(i)][1]) + #define group_players(i) (sActivityGroupInfo[(i)][2]) + + for (i = 0; i < ARRAY_COUNT(sActivityGroupInfo); i++) + { + if (activity == group_activity(i) && unk20->groupScheduledAnim == UNION_ROOM_SPAWN_IN) + { + if (group_players(i) == 0) + { + k = 0; + for (j = 0; j < RFU_CHILD_MAX; j++) + { + if (unk20->gname_uname.gname.child_sprite_gender[j] != 0) k++; + } + k++; + groupCounts[group_type(i)] += k; + } + else + { + groupCounts[group_type(i)] += group_players(i); + } + } + } + return activity; + + #undef group_activity + #undef group_type + #undef group_players +} + +static bool32 HaveCountsChanged(u32 * currCounts, u32 * prevCounts) +{ + s32 i; + for (i = 0; i < NUM_GROUPTYPES; i++) + { + if (currCounts[i] != prevCounts[i]) + return TRUE; + } + return FALSE; +} + +static bool32 UpdateCommunicationCounts(u32 * groupCounts, u32 * prevGroupCounts, u32 * activities, u8 taskId) +{ + bool32 activitiesChanged = FALSE; + u32 groupCountBuffer[NUM_GROUPTYPES] = {0, 0, 0, 0}; + struct UnkStruct_x20 ** data = (void *)gTasks[taskId].data; + s32 i; + + for (i = 0; i < NUM_TASK_DATA; i++) + { + u32 activity = CountPlayersInGroupAndGetActivity(&(*data)[i], groupCountBuffer); + if (activity != activities[i]) + { + activities[i] = activity; + activitiesChanged = TRUE; + } + } + + if (!HaveCountsChanged(groupCountBuffer, prevGroupCounts)) + { + if (activitiesChanged == TRUE) + return TRUE; + else + return FALSE; + } + else + { + memcpy(groupCounts, groupCountBuffer, sizeof(groupCountBuffer)); + memcpy(prevGroupCounts, groupCountBuffer, sizeof(groupCountBuffer)); + + groupCounts[GROUPTYPE_TOTAL] = groupCounts[GROUPTYPE_TRADE] + + groupCounts[GROUPTYPE_BATTLE] + + groupCounts[GROUPTYPE_UNION] + + groupCounts[GROUPTYPE_TOTAL]; + return TRUE; + } +} |