diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/link.c | 8 | ||||
| -rw-r--r-- | src/main_menu.c | 1662 | ||||
| -rw-r--r-- | src/menu.c | 1003 | ||||
| -rw-r--r-- | src/pokemon.c | 607 | ||||
| -rw-r--r-- | src/text.c | 2 | ||||
| -rw-r--r-- | src/text_window.c | 196 | 
6 files changed, 3473 insertions, 5 deletions
| diff --git a/src/link.c b/src/link.c index a5d848b83..13fcf8c05 100644 --- a/src/link.c +++ b/src/link.c @@ -27,7 +27,7 @@ struct LinkTestBGInfo      u32 dummy_C;  }; -extern void sub_8071C4C(const struct WindowConfig *); +extern void InitMenuWindow(const struct WindowConfig *);  extern void sub_80516C4(u8, u16);  extern u8 unk_2000000[]; @@ -237,7 +237,7 @@ static void LinkTestScreen(void)      ResetTasks();      SetVBlankCallback(VBlankCB_LinkTest);      SetUpWindowConfig(&gWindowConfig_81E6CE4); -    sub_8071C4C(&gWindowConfig_81E6CE4); +    InitMenuWindow(&gWindowConfig_81E6CE4);      ResetBlockSend();      gLinkType = 0x1111;      OpenLink(); @@ -1224,8 +1224,8 @@ void CB2_LinkError(void)      ResetTasks();      SetVBlankCallback(VBlankCB_LinkTest);      SetUpWindowConfig(&gWindowConfig_81E7198); -    sub_8071C4C(&gWindowConfig_81E7198); -    sub_8071EF4(); +    InitMenuWindow(&gWindowConfig_81E7198); +    MenuZeroFillScreen();      REG_BLDALPHA = 0;      REG_BG0VOFS = 0;      REG_BG0HOFS = 0; diff --git a/src/main_menu.c b/src/main_menu.c new file mode 100644 index 000000000..559bf5a0a --- /dev/null +++ b/src/main_menu.c @@ -0,0 +1,1662 @@ +#include "global.h" +#include "text.h" +#include "sprite.h" +#include "task.h" +#include "main.h" +#include "rtc.h" +#include "songs.h" +#include "palette.h" +#include "string_util.h" +#include "species.h" + +extern u8 MenuUpdateWindowText(void); +extern void MenuPrint(u8 *, u8, u8); +extern void CB2_ContinueSavedGame(void); +extern void CB2_InitMysteryEventMenu(void); +extern void CB2_InitOptionMenu(void); +extern void CB2_InitTitleScreen(void); +extern void FormatPlayTime(u8 *str, u16 hours, u16 minutes, bool16 colon); +extern u8 *sub_8072C74(u8 *, u8 *, u8, u8); +extern u16 GetPokedexSeenCount(void); +extern u8 *sub_8072C14(u8 *, s32, u8, u8); +extern u8 sub_80729D8(u8 *, u8, u16, u8); +extern u8 GetBadgeCount(void); +extern void Task_Birch1(u8); +void MenuPrintMessage(const u8 *string, u8 a, u8 b); +u8 MenuUpdateWindowText_OverrideLineLength(u8 a); +void sub_8072DEC(void); +u8 sub_8075374(void); +void MenuSetText(u32); +void cry_related(u16, u8); +void audio_play(u8 a); +void MenuZeroFillWindowRect(u8 a, u8 b, u8 c, u8 d); +u8 GetMenuCursorPos(void); +void DoNamingScreen(u8 r0, struct SaveBlock2 *r1, u16 r2, u16 r3, u8 s0, MainCallback s4); +void DisplayYesNoMenu(u8 r0, u8 r1, u32 r2); +s8 ProcessMenuInputNoWrap_(void); +void c2_load_new_map_2(void); +void LZ77UnCompVram(const void *src, void *dest); +void InitMenuWindow(const struct WindowConfig *); +void CB2_MainMenu(void); +void VBlankCB_MainMenu(void); +void DecompressPicFromTable_2(const struct SpriteSheet *, u8, u8, void *, void *, u32); +void LoadCompressedObjectPalette(const struct SpritePalette *); +void gpu_pal_obj_decompress_and_apply(u16, u8); +u8 AddNewGameBirchObject(u8, u8, u8); +u8 sub_80859BC(u8, u16, u16, u8, void *); +void MenuDrawTextWindow(u8 a, u8 b, u8 c, u8 d); + +extern struct PaletteFadeControl gPaletteFade; +extern u8 gSaveFileDeletedMessage[]; +extern u8 gSaveFileCorruptMessage[]; +extern u8 gBoardNotInstalledMessage[]; +extern u8 gBatteryDryMessage[]; +extern u16 gSaveFileStatus; +extern u8 gMainMenuString_Continue[]; +extern u8 gMainMenuString_NewGame[]; +extern u8 gMainMenuString_MysteryEvents[]; +extern u8 gMainMenuString_Option[]; +extern u8 gMainMenuString_Player[]; +extern u8 gMainMenuString_Time[]; +extern u8 gMainMenuString_Pokedex[]; +extern u8 gMainMenuString_Badges[]; + +void CB2_MainMenu(void); +void VBlankCB_MainMenu(void); +void CB2_InitMainMenu(void); +static void sub_80096FC(void); +static u32 InitMainMenu(bool8 a1); +static void Task_CheckSave(u8 taskId); +static void Task_WaitForSaveErrorAck(u8 taskId); +static void Task_CheckRtc(u8 taskId); +static void Task_WaitForRtcErrorAck(u8 taskId); +static void Task_DrawMainMenu(u8 taskId); +static void Task_HighlightCurrentMenuItem(u8 taskId); +static bool8 MainMenuProcessKeyInput(u8 taskId); +static void Task_MainMenuProcessKeyInput(u8 taskId); +static void MainMenuPressedA(u8 taskId); +static void MainMenuPressedB(u8 taskId); +static void HighlightCurrentMenuItem(u8, u8); +static void PrintMainMenuItem(u8 *text, u8, u8); +static void PrintSaveFileInfo(void); +static void PrintPlayerName(void); +static void PrintPlayTime(void); +static void PrintPokedexCount(void); +static void PrintBadgeCount(void); + +extern u16 gMainMenuPalette[]; + +void CB2_MainMenu(void) +{ +    RunTasks(); +    AnimateSprites(); +    BuildOamBuffer(); +    UpdatePaletteFade(); +} + +void VBlankCB_MainMenu(void) +{ +    LoadOam(); +    ProcessSpriteCopyRequests(); +    TransferPlttBuffer(); +} + +void CB2_InitMainMenu(void) +{ +    InitMainMenu(FALSE); +} + +static void sub_80096FC(void) +{ +    InitMainMenu(TRUE); +} + +u32 InitMainMenu(u8 a1) +{ +    u16 savedIme; +    u8 taskId; + +    SetVBlankCallback(NULL); + +    REG_DISPCNT = 0; +    REG_BG2CNT = 0; +    REG_BG1CNT = 0; +    REG_BG0CNT = 0; +    REG_BG2HOFS = 0; +    REG_BG2VOFS = 0; +    REG_BG1HOFS = 0; +    REG_BG1VOFS = 0; +    REG_BG0HOFS = 0; +    REG_BG0VOFS = 0; + +    DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE); +    DmaFill32(3, 0, (void *)OAM, OAM_SIZE); +    DmaFill16(3, 0, (void *)(PLTT + 2), PLTT_SIZE - 2); + +    ResetPaletteFade(); +    LoadPalette(gMainMenuPalette, 0, 32); +    remove_some_task(); +    ResetTasks(); +    ResetSpriteData(); +    FreeAllSpritePalettes(); +    SetUpWindowConfig(&gWindowConfig_81E6C3C); +    InitMenuWindow(&gWindowConfig_81E6CE4); + +    if (a1) +        BeginNormalPaletteFade(-1, 0, 0x10, 0, 0x0000); // fade to black +    else +        BeginNormalPaletteFade(-1, 0, 0x10, 0, 0xFFFF); // fade to white + +    REG_WIN0H = 0; +    REG_WIN0V = 0; +    REG_WININ = 0; +    REG_WINOUT = 0; +    REG_BLDCNT = 0; +    REG_BLDALPHA = 0; +    REG_BLDY = 0; + +    savedIme = REG_IME; +    REG_IME = 0; +    REG_IE |= INTR_FLAG_VBLANK; +    REG_IME = savedIme; + +    SetVBlankCallback(VBlankCB_MainMenu); +    SetMainCallback2(CB2_MainMenu); + +    REG_DISPCNT = DISPCNT_OBJ_1D_MAP +                | DISPCNT_BG0_ON +                | DISPCNT_OBJ_ON +                | DISPCNT_WIN0_ON; + +    taskId = CreateTask(Task_CheckSave, 0); +    gTasks[taskId].data[1] = 0; + +    return 0; +} + +void Task_CheckSave(u8 taskId) +{ +    if (gPaletteFade.active) +        return; + +    REG_WIN0H = 0; +    REG_WIN0V = 0; +    REG_WININ = 0x1111; +    REG_WINOUT = 49; +    REG_BLDCNT = 241; +    REG_BLDALPHA = 0; +    REG_BLDY = 7; + +    switch (gSaveFileStatus) +    { +    case 1: +        if (sub_806918C() == TRUE) +            gTasks[taskId].data[0] = 2; +        else +            gTasks[taskId].data[0] = 1; + +        gTasks[taskId].func = Task_CheckRtc; +        break; +    case 2: +        MenuDrawTextWindow(2, 14, 27, 19); +        MenuPrintMessage(gSaveFileDeletedMessage, 3, 15); +        REG_WIN0H = WIN_RANGE(17, 223); +        REG_WIN0V = WIN_RANGE(113, 159); +        gTasks[taskId].data[0] = 0; +        gTasks[taskId].func = Task_WaitForSaveErrorAck; +        break; +    case 255: +        MenuDrawTextWindow(2, 14, 27, 19); +        MenuPrintMessage(gSaveFileCorruptMessage, 3, 15); +        REG_WIN0H = WIN_RANGE(17, 223); +        REG_WIN0V = WIN_RANGE(113, 159); +        gTasks[taskId].data[0] = 1; +        gTasks[taskId].func = Task_WaitForSaveErrorAck; + +        if (sub_806918C() == TRUE) +            gTasks[taskId].data[0] = 2; +        else +            gTasks[taskId].data[0] = 1; +        break; +    case 0: +    default: +        gTasks[taskId].data[0] = 0; +        gTasks[taskId].func = Task_CheckRtc; +        break; +    case 4: +        MenuDrawTextWindow(2, 14, 27, 19); +        MenuPrintMessage(gBoardNotInstalledMessage, 3, 15); +        REG_WIN0H = WIN_RANGE(17, 223); +        REG_WIN0V = WIN_RANGE(113, 159); +        gTasks[taskId].data[0] = 0; +        gTasks[taskId].func = Task_WaitForSaveErrorAck; +        return; +    } +} + +void Task_WaitForSaveErrorAck(u8 taskId) +{ +    if (MenuUpdateWindowText()) +    { +        if (gMain.newKeys & A_BUTTON) +        { +            MenuZeroFillWindowRect(2, 14, 27, 19); +            gTasks[taskId].func = Task_CheckRtc; +        } +    } +} + +void Task_CheckRtc(u8 taskId) +{ +    if (!gPaletteFade.active) +    { +        REG_WIN0H = 0; +        REG_WIN0V = 0; +        REG_WININ = 0x1111; +        REG_WINOUT = 49; +        REG_BLDCNT = 241; +        REG_BLDALPHA = 0; +        REG_BLDY = 7; + +        if (!(RtcGetErrorStatus() & RTC_ERR_FLAG_MASK)) +        { +            gTasks[taskId].func = Task_DrawMainMenu; +        } +        else +        { +            MenuDrawTextWindow(2, 14, 27, 19); +            MenuPrintMessage(gBatteryDryMessage, 3, 15); +            REG_WIN0H = WIN_RANGE(17, 223); +            REG_WIN0V = WIN_RANGE(113, 159); +            gTasks[taskId].func = Task_WaitForRtcErrorAck; +        } +    } +} + +void Task_WaitForRtcErrorAck(u8 taskId) +{ +    if (MenuUpdateWindowText()) +    { +        if ( gMain.newKeys & 1 ) +        { +            MenuZeroFillWindowRect(2, 14, 27, 19); +            gTasks[taskId].func = Task_DrawMainMenu; +        } +    } +} + +void Task_DrawMainMenu(u8 taskId) +{ +    u16 palette; + +    if (!gPaletteFade.active) +    { +        REG_WIN0H = 0; +        REG_WIN0V = 0; +        REG_WININ = 0x1111; +        REG_WINOUT = 49; +        REG_BLDCNT = 241; +        REG_BLDALPHA = 0; +        REG_BLDY = 7; + +        palette = RGB(0, 0, 0); +        LoadPalette(&palette, 254, 2); + +        if (gSaveBlock2.playerGender == MALE) +        { +            palette = RGB(4, 16, 31); +            LoadPalette(&palette, 241, 2); +        } +        else +        { +            palette = RGB(31, 3, 21); +            LoadPalette(&palette, 241, 2); +        } + +        switch (gTasks[taskId].data[0]) +        { +        case 0: +        default: +            MenuDrawTextWindow(1, 0, 28, 3); +            PrintMainMenuItem(gMainMenuString_NewGame, 2, 1); +            MenuDrawTextWindow(1, 4, 28, 7); +            PrintMainMenuItem(gMainMenuString_Option, 2, 5); +            break; +        case 1: +            MenuDrawTextWindow(1, 0, 28, 7); +            PrintMainMenuItem(gMainMenuString_Continue, 2, 1); +            MenuDrawTextWindow(1, 8, 28, 11); +            PrintMainMenuItem(gMainMenuString_NewGame, 2, 9); +            MenuDrawTextWindow(1, 12, 28, 15); +            PrintMainMenuItem(gMainMenuString_Option, 2, 13); +            PrintSaveFileInfo(); +            break; +        case 2: +            MenuDrawTextWindow(1, 0, 28, 7); +            PrintMainMenuItem(gMainMenuString_Continue, 2, 1); +            MenuDrawTextWindow(1, 8, 28, 11); +            PrintMainMenuItem(gMainMenuString_NewGame, 2, 9); +            MenuDrawTextWindow(1, 12, 28, 15); +            PrintMainMenuItem(gMainMenuString_MysteryEvents, 2, 13); +            MenuDrawTextWindow(1, 16, 28, 19); +            PrintMainMenuItem(gMainMenuString_Option, 2, 0x11); +            PrintSaveFileInfo(); +            break; +        } + +        gTasks[taskId].func = Task_HighlightCurrentMenuItem; +    } +} + +void Task_HighlightCurrentMenuItem(u8 taskId) +{ +    HighlightCurrentMenuItem(gTasks[taskId].data[0], gTasks[taskId].data[1]); +    gTasks[taskId].func = Task_MainMenuProcessKeyInput; +} + +bool8 MainMenuProcessKeyInput(u8 taskId) +{ +    if (gMain.newKeys & A_BUTTON) +    { +        audio_play(SE_SELECT); +        BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0x0000); +        gTasks[taskId].func = MainMenuPressedA; +    } +    else if (gMain.newKeys & B_BUTTON) +    { +        audio_play(SE_SELECT); +        BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0xFFFF); +        REG_WIN0H = WIN_RANGE(0, 240); +        REG_WIN0V = WIN_RANGE(0, 160); +        gTasks[taskId].func = MainMenuPressedB; +    } +    else +    { +        s32 menuItemCount; + +        switch (gTasks[taskId].data[0]) +        { +        case 0: +        default: +            menuItemCount = 2; +            break; +        case 1: +            menuItemCount = 3; +            break; +        case 2: +            menuItemCount = 4; +            break; +        } + +        if (gMain.newKeys & DPAD_UP) +        { +            if (gTasks[taskId].data[1] > 0) +            { +                gTasks[taskId].data[1]--; +                return TRUE; +            } +        } +        if (gMain.newKeys & DPAD_DOWN) +        { +            if (gTasks[taskId].data[1] < menuItemCount - 1) +            { +                gTasks[taskId].data[1]++; +                return TRUE; +            } +        } +    } + +    return FALSE; +} + +void Task_MainMenuProcessKeyInput(u8 taskId) +{ +    bool8 currentMenuItemChanged = MainMenuProcessKeyInput(taskId); +    if (currentMenuItemChanged) +        gTasks[taskId].func = Task_HighlightCurrentMenuItem; +} + +void MainMenuPressedA(u8 taskId) +{ +    enum +    { +        NEW_GAME, +        CONTINUE, +        OPTION, +        MYSTERY_EVENTS, +    } action; + +    if (gPaletteFade.active) +        return; + +    switch (gTasks[taskId].data[0]) +    { +    case 0: +    default: +        switch (gTasks[taskId].data[1]) +        { +        case 0: +        default: +            action = NEW_GAME; +            break; +        case 1: +            action = OPTION; +            break; +        } +        break; +    case 1: +        switch (gTasks[taskId].data[1]) +        { +        case 0: +        default: +            action = CONTINUE; +            break; +        case 1: +            action = NEW_GAME; +            break; +        case 2: +            action = OPTION; +            break; +        } +        break; +    case 2: +        switch (gTasks[taskId].data[1]) +        { +        case 0: +        default: +            action = CONTINUE; +            break; +        case 1: +            action = NEW_GAME; +            break; +        case 2: +            action = MYSTERY_EVENTS; +            break; +        case 3: +            action = OPTION; +            break; +        } +        break; +    } + +    switch ((int)action) +    { +    case NEW_GAME: +    default: +        gPlttBufferUnfaded[0] = 0; +        gPlttBufferFaded[0] = 0; +        gTasks[taskId].func = Task_Birch1; +        break; +    case CONTINUE: +        gPlttBufferUnfaded[0] = 0; +        gPlttBufferFaded[0] = 0; +        SetMainCallback2(CB2_ContinueSavedGame); +        DestroyTask(taskId); +        break; +    case OPTION: +        gMain.field_8 = (u32)sub_80096FC; +        SetMainCallback2(CB2_InitOptionMenu); +        DestroyTask(taskId); +        break; +    case MYSTERY_EVENTS: +        SetMainCallback2(CB2_InitMysteryEventMenu); +        DestroyTask(taskId); +        break; +    } +} + +void MainMenuPressedB(u8 taskId) +{ +    if (!gPaletteFade.active) +    { +        SetMainCallback2(CB2_InitTitleScreen); +        DestroyTask(taskId); +    } +} + +void HighlightCurrentMenuItem(u8 layout, u8 menuItem) +{ +    REG_WIN0H = WIN_RANGE(9, 231); + +    switch (layout) +    { +    case 0: +    default: +        switch (menuItem) +        { +        case 0: +        default: +            REG_WIN0V = WIN_RANGE(1, 31); +            break; +        case 1: +            REG_WIN0V = WIN_RANGE(33, 63); +            break; +        } +        break; +    case 1: +        switch (menuItem) +        { +        case 0: +        default: +            REG_WIN0V = WIN_RANGE(1, 63); +            break; +        case 1: +            REG_WIN0V = WIN_RANGE(65, 95); +            break; +        case 2: +            REG_WIN0V = WIN_RANGE(97, 127); +            break; +        } +        break; +    case 2: +        switch (menuItem) +        { +        case 0: +        default: +            REG_WIN0V = WIN_RANGE(1, 63); +            break; +        case 1: +            REG_WIN0V = WIN_RANGE(65, 95); +            break; +        case 2: +            REG_WIN0V = WIN_RANGE(97, 127); +            break; +        case 3: +            REG_WIN0V = WIN_RANGE(129, 159); +            break; +        } +        break; +    } +} + +void PrintMainMenuItem(u8 *text, u8 left, u8 top) +{ +    u8 i; +    u8 buffer[32]; + +    buffer[0] = 0xFC; +    buffer[1] = 1; +    buffer[2] = 14; + +    for (i = 0; i < 26; i++) +        buffer[3 + i] = text[i]; + +    buffer[29] = EOS; + +    MenuPrint(buffer, left, top); +} + +void PrintSaveFileInfo(void) +{ +    PrintPlayerName(); +    PrintPokedexCount(); +    PrintPlayTime(); +    PrintBadgeCount(); +} + +void PrintPlayerName(void) +{ +    MenuPrint(gMainMenuString_Player, 2, 3); +    MenuPrint(gSaveBlock2.playerName, 9, 3); +} + +void PrintPlayTime(void) +{ +    u8 playTime[16]; +    u8 alignedPlayTime[32]; + +    MenuPrint(gMainMenuString_Time, 16, 3); +    FormatPlayTime(playTime, gSaveBlock2.playTimeHours, gSaveBlock2.playTimeMinutes, 1); +    sub_8072C74(alignedPlayTime, playTime, 48, 1); +    MenuPrint(alignedPlayTime, 22, 3); +} + +void PrintPokedexCount(void) +{ +    u8 buffer[16]; + +    MenuPrint(gMainMenuString_Pokedex, 2, 5); +    sub_8072C14(buffer, GetPokedexSeenCount(), 18, 0); +    MenuPrint(buffer, 9, 5); +} + +void PrintBadgeCount(void) +{ +    u8 buffer[16]; + +    MenuPrint(gMainMenuString_Badges, 16, 5); +    ConvertIntToDecimalString(buffer, GetBadgeCount()); +    sub_80729D8(buffer, 205, 40, 1); +} + +//Text Strings +extern const u8 gUnknown_081C6D78[];    //Hi! Sorry to keep you waiting!... +extern const u8 gUnknown_081C6DF8[]; +extern const u8 gUnknown_081C6E1A[]; +extern const u8 gUnknown_081C6FCB[]; +extern const u8 gUnknown_081C6FD8[]; +extern const u8 gUnknown_081C6FFA[]; +extern u8 gUnknown_081C7017[]; +extern u8 gUnknown_081C7025[]; +extern u8 gUnknown_081C7074[]; + +struct MonCoords +{ +    u8 x, y; +}; + +extern const struct MonCoords gMonFrontPicCoords[]; +extern const struct SpriteSheet gMonFrontPicTable[]; +extern const struct SpritePalette gMonPaletteTable[]; +extern struct SpriteTemplate gUnknown_02024E8C; +extern void * const gUnknown_081FAF4C[]; +extern u16 gUnknown_081E795C[]; +extern u8 * const gUnknown_081E79B0[][2]; +extern u8 * const gUnknown_081E79C0[][2]; +extern u8 * const gUnknown_081E79E8[][2]; + +extern const u8 gUnknown_081E764C[]; +extern const u8 gUnknown_081E768C[]; +extern const u8 gUnknown_081E7834[]; +extern const u8 gUnknown_081E796C[]; +extern const u8 gUnknown_0840DFF7[]; + +extern u8 gSpriteAffineAnimTable_81E79AC[]; + +extern struct Sprite gSprites[]; +extern u8 gStringVar4[]; + +extern u8 unk_2000000[]; + +void task_new_game_prof_birch_speech_2(u8 taskId); +void task_new_game_prof_birch_speech_3(u8 taskId); +void task_new_game_prof_birch_speech_4(u8 taskId); +void task_new_game_prof_birch_speech_5(u8 taskId); +void task_new_game_prof_birch_speech_6(u8 taskId); +void task_new_game_prof_birch_speech_7(u8 taskId); +void task_new_game_prof_birch_speech_8(u8 taskId); +void task_new_game_prof_birch_speech_9(u8 taskId); +void task_new_game_prof_birch_speech_10(u8 taskId); +void task_new_game_prof_birch_speech_11(u8 taskId); +void task_new_game_prof_birch_speech_12(u8 taskId); +void task_new_game_prof_birch_speech_13(u8 taskId); +void task_new_game_prof_birch_speech_14(u8 taskId); +void task_new_game_prof_birch_speech_15(u8 taskId); +void task_new_game_prof_birch_speech_16(u8 taskId); +void task_new_game_prof_birch_speech_17(u8 taskId); +void task_new_game_prof_birch_speech_18(u8 taskId); +void sub_800A974(u8 taskId); +void Task_800A9B4(u8 taskId); +void sub_800A9EC(u8 taskId); +void sub_800AAAC(u8 taskId); +void task_new_game_prof_birch_speech_part2_1(u8 taskId); +void sub_800AB38(u8 taskId); +void task_new_game_prof_birch_speech_part2_4(u8 taskId); +void sub_800AC20(u8 taskId); +void task_new_game_prof_birch_speech_part2_6(u8 taskId); +void task_new_game_prof_birch_speech_part2_7(u8 taskId); +void task_new_game_prof_birch_speech_part2_8(u8 taskId); +void task_new_game_prof_birch_speech_part2_9(u8 taskId); +void task_new_game_prof_birch_speech_part2_10(u8 taskId); +void sub_800AFC0(u8 taskId); +void sub_800B034(u8 taskId); +void new_game_prof_birch_speech_part2_start(); +void nullsub_34(struct Sprite *sprite); +void sub_800B240(struct Sprite *sprite); +u8 CreateAzurillSprite(u8, u8); +void AddBirchSpeechObjects(u8); +void sub_800B3EC(u8); +void sub_800B458(u8, u8); +void sub_800B4C8(u8); +void sub_800B534(u8 taskId, u8 a); +void sub_800B5A8(u8); +void sub_800B614(u8, u8); +void sub_800B654(u8); +void sub_800B6C0(u8 taskId, u8 a); +void CreateGenderMenu(u8 left, u8 top); +s8 GenderMenuProcessInput(void); +void CreateNameMenu(u8 a, u8 b); +s8 NameMenuProcessInput(void); +void set_default_player_name(u8 a); + +void Task_Birch1(u8 taskId) +{ +    SetUpWindowConfig(&gWindowConfig_81E6C3C); +    InitMenuWindow(&gWindowConfig_81E6CE4); +    REG_WIN0H = 0; +    REG_WIN0V = 0; +    REG_WININ = 0; +    REG_WINOUT = 0; +    REG_BLDCNT = 0; +    REG_BLDALPHA = 0; +    REG_BLDY = 0; +    LZ77UnCompVram(gUnknown_081E768C, (void *)BG_VRAM); +    LZ77UnCompVram(gUnknown_081E7834, (void *)(BG_VRAM + 0x3800)); +    LoadPalette(gUnknown_081E764C, 0, 0x40); +    LoadPalette(gUnknown_081E796C, 1, 0x10); +    remove_some_task(); +    ResetSpriteData(); +    FreeAllSpritePalettes(); +    AddBirchSpeechObjects(taskId); +    BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); +    REG_BG1CNT = 0x00000703; +    REG_DISPCNT = DISPCNT_BG0_ON | DISPCNT_BG1_ON | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP; +    gTasks[taskId].data[4] = 0; +    gTasks[taskId].func = task_new_game_prof_birch_speech_2; +    gTasks[taskId].data[2] = 0xFF; +    gTasks[taskId].data[3] = 0xFF; +    gTasks[taskId].data[7] = 0xD8; + +    sub_8075474(BGM_DOORO_X4); +} + +void task_new_game_prof_birch_speech_2(u8 taskId) +{ +    struct Task *tasks = gTasks; +    struct Task *task = &tasks[taskId]; + +    if (task->data[7] != 0) +    { +        task->data[7]--; +    } +    else +    { +        u8 spriteId = task->data[8]; +        struct Sprite *sprites = gSprites; +        struct Sprite *sprite = &sprites[spriteId]; +        sprite->pos1.x = 0x88; +        sprite->pos1.y = 0x3C; +        sprite->invisible = 0; +        sprite->oam.objMode = 1; +        sub_800B534(taskId, 0xA); +        sub_800B6C0(taskId, 0x14); +        task->data[7] = 0x50; +        task->func = task_new_game_prof_birch_speech_3; +    } +} + +void task_new_game_prof_birch_speech_3(u8 taskId) +{ +    struct Task *tasks = gTasks; +    struct Task *task = &tasks[taskId]; + +    if (task->data[5] != 0) +    { +        struct Sprite *sprites = gSprites; +        struct Sprite *sprite = &sprites[task->data[8]]; + +        sprite->oam.objMode = 0; +        if (task->data[7]) +        { +            task->data[7]--; +        } +        else +        { +            MenuDrawTextWindow(0x2, 0xD, 0x1B, 0x12); +            MenuPrintMessage(gUnknown_081C6D78, 3, 14); +            task->func = task_new_game_prof_birch_speech_4; +        } +    } +} + +void task_new_game_prof_birch_speech_4(u8 taskId) +{ +    if (!gPaletteFade.active && MenuUpdateWindowText_OverrideLineLength(24)) +    { +        gTasks[taskId].func = task_new_game_prof_birch_speech_5; +        MenuPrintMessage(gUnknown_081C6DF8, 3, 14); +    } +} + +void task_new_game_prof_birch_speech_5(u8 taskId) +{ +    if (MenuUpdateWindowText_OverrideLineLength(24)) +        gTasks[taskId].func = task_new_game_prof_birch_speech_6; +} + +void task_new_game_prof_birch_speech_6(u8 taskId) +{ +    struct Task *tasks = gTasks; +    struct Task *task = &tasks[taskId]; +    u8 data = task->data[9]; +    struct Sprite *sprites = gSprites; +    struct Sprite *sprite = &sprites[data]; + +    sprite->pos1.x = 0x68; +    sprite->pos1.y = 0x48; +    sprite->invisible = 0; +    sprite->data0 = 0; +    CreatePokeballSprite(data, sprite->oam.paletteNum, 0x70, 0x3A, 0, 0, 0x20, 0x0000FFFF); +    task->func = task_new_game_prof_birch_speech_7; +    task->data[7] = 0; +} + +void task_new_game_prof_birch_speech_7(u8 taskId) +{ +    struct Task *tasks; +    struct Task *task; + +    if (sub_8075374()) +    { +        struct Task *tasks = gTasks; +        struct Task *task = &tasks[taskId]; + +        if (task->data[7] > 0x5F) +        { +            MenuSetText((u32)&gUnknown_0840DFF7); +            task->func = task_new_game_prof_birch_speech_8; +        } +    } + +    tasks = gTasks; +    task = &tasks[taskId]; + +    if (task->data[7] < 0x4000) +    { +        task->data[7]++; +        if (task->data[7] == 0x20) +        { +            cry_related(SPECIES_AZURILL, 0); +        } +    } +} + +void task_new_game_prof_birch_speech_8(u8 taskId) +{ +    if (MenuUpdateWindowText_OverrideLineLength(24)) +    { +        MenuPrintMessage(gUnknown_081C6E1A, 3, 14); +        gTasks[taskId].func = task_new_game_prof_birch_speech_9; +    } +} + +void task_new_game_prof_birch_speech_9(u8 taskId) +{ +    if (MenuUpdateWindowText_OverrideLineLength(24)) +    { +        MenuDrawTextWindow(0x2, 0xD, 0x1B, 0x12); +        MenuPrintMessage(gUnknown_081C6FCB, 3, 14); +        gTasks[taskId].func = task_new_game_prof_birch_speech_10; +    } +} + +void task_new_game_prof_birch_speech_10(u8 taskId) +{ +    if (MenuUpdateWindowText_OverrideLineLength(24)) +    { +        struct Sprite *sprites = gSprites; +        struct Task *tasks = gTasks; +        struct Task *task = &tasks[taskId]; +        struct Sprite *sprite = &sprites[task->data[8]]; +        struct Sprite *sprite2; + +        sprite->oam.objMode = 1; +        sprite2 = &sprites[task->data[9]]; +        sprite2->oam.objMode = 1; +        sub_800B458(taskId, 0x2); +        sub_800B614(taskId, 0x1); +        task->data[7] = 0x40; +        task->func = task_new_game_prof_birch_speech_11; +    } +} + +void task_new_game_prof_birch_speech_11(u8 taskId) +{ +    struct Task *tasks = gTasks; +    struct Task *task = &tasks[taskId]; + +    if (task->data[4] != -0x3C) +    { +        task->data[4] -= 2; +        REG_BG1HOFS = task->data[4]; +    } +    else +    { +        task->data[4] = 0x0000ffc4; +        task->func = task_new_game_prof_birch_speech_12; +    } +} + +void task_new_game_prof_birch_speech_12(u8 taskId) +{ +    if (gTasks[taskId].data[5]) +    { +        gSprites[gTasks[taskId].data[8]].invisible = 1; +        gSprites[gTasks[taskId].data[9]].invisible = 1; + +        if (gTasks[taskId].data[7]) +        { +            gTasks[taskId].data[7]--; +        } +        else +        { +            u8 data10 = gTasks[taskId].data[10]; + +            gSprites[data10].pos1.x = 0xB4; +            gSprites[data10].pos1.y = 0x3C; +            gSprites[data10].invisible = 0; +            gSprites[data10].oam.objMode = 1; +            gTasks[taskId].data[2] = data10; +            gTasks[taskId].data[6] = 0; +            sub_800B534(taskId, 2); +            sub_800B6C0(taskId, 1); +            gTasks[taskId].func = task_new_game_prof_birch_speech_13; +        } +    } +} + +void task_new_game_prof_birch_speech_13(u8 taskId) +{ +    struct Task *tasks = gTasks; +    struct Task *task = &tasks[taskId]; + +    if (task->data[5]) +    { +        struct Sprite *sprites = gSprites; +        struct Sprite *sprite = &sprites[task->data[2]]; + +        sprite->oam.objMode = 0; +        task->func = task_new_game_prof_birch_speech_14; +    } +} + +void task_new_game_prof_birch_speech_14(u8 taskId) +{ +    MenuDrawTextWindow(2, 0xD, 0x1B, 0x12); +    MenuPrintMessage(gUnknown_081C6FD8, 3, 14); +    gTasks[taskId].func = task_new_game_prof_birch_speech_15; +} + +void task_new_game_prof_birch_speech_15(u8 taskId) +{ +    if (MenuUpdateWindowText_OverrideLineLength(24)) +    { +        CreateGenderMenu(2, 4); +        gTasks[taskId].func = task_new_game_prof_birch_speech_16; +    } +} + +void task_new_game_prof_birch_speech_16(u8 taskId) +{ +    u8 cursorPos; + +    switch (GenderMenuProcessInput()) +    { +    case MALE: +        sub_8072DEC(); +        audio_play(SE_SELECT); +        gSaveBlock2.playerGender = MALE; +        MenuZeroFillWindowRect(2, 4, 8, 9); +        gTasks[taskId].func = sub_800A974; +        break; +    case FEMALE: +        sub_8072DEC(); +        audio_play(SE_SELECT); +        gSaveBlock2.playerGender = FEMALE; +        MenuZeroFillWindowRect(2, 4, 8, 9); +        gTasks[taskId].func = sub_800A974; +        break; +    } + +    cursorPos = GetMenuCursorPos(); + +    if (cursorPos != gTasks[taskId].data[6]) +    { +        gTasks[taskId].data[6] = cursorPos; +        gSprites[gTasks[taskId].data[2]].oam.objMode = 1; +        sub_800B458(taskId, 0); +        gTasks[taskId].func = task_new_game_prof_birch_speech_17; +    } +} + +void task_new_game_prof_birch_speech_17(u8 taskId) +{ +    u8 spriteId = gTasks[taskId].data[2]; + +    if (gTasks[taskId].data[5] == 0) +    { +        gSprites[spriteId].pos1.x += 4; +    } +    else +    { +        gSprites[spriteId].invisible = 1; +        if (gTasks[taskId].data[6]) +        { +            spriteId = gTasks[taskId].data[11]; +        } +        else +        { +            spriteId = gTasks[taskId].data[10]; +        } + +        gSprites[spriteId].pos1.x = 0xF0; +        gSprites[spriteId].pos1.y = 0x3C; +        gSprites[spriteId].invisible = 0; +        gTasks[taskId].data[2] = spriteId; +        gSprites[spriteId].oam.objMode = 1; +        sub_800B534(taskId, 0); +        gTasks[taskId].func = task_new_game_prof_birch_speech_18; +    } +} + +void task_new_game_prof_birch_speech_18(u8 taskId) +{ +    u8 spriteId = gTasks[taskId].data[2]; + +    if (gSprites[spriteId].pos1.x > 0xB4) +    { +        gSprites[spriteId].pos1.x -= 4; +    } +    else +    { +        gSprites[spriteId].pos1.x = 0xB4; +        if (gTasks[taskId].data[5]) +        { +            gSprites[spriteId].oam.objMode = 0; +            gTasks[taskId].func = task_new_game_prof_birch_speech_16; +        } +    } +} + +void sub_800A974(u8 taskId) +{ +    MenuDrawTextWindow(2, 13, 27, 18); +    MenuPrintMessage(gUnknown_081C6FFA, 3, 14); +    gTasks[taskId].func = Task_800A9B4; +} + +void Task_800A9B4(u8 taskId) +{ +    if (MenuUpdateWindowText_OverrideLineLength(24)) +    { +        CreateNameMenu(2, 1); +        gTasks[taskId].func = sub_800A9EC; +    } +} + +void sub_800A9EC(u8 taskId) +{ +    s8 n = NameMenuProcessInput(); + +    switch (n) +    { +    case 1: +    case 2: +    case 3: +    case 4: +        sub_8072DEC(); +        audio_play(SE_SELECT); +        MenuZeroFillWindowRect(2, 1, 22, 12); +        set_default_player_name(n); +        gTasks[taskId].func = task_new_game_prof_birch_speech_part2_1; +        break; +    case 0: +        audio_play(SE_SELECT); +        BeginNormalPaletteFade(-1, 0, 0, 16, 0); +        gTasks[taskId].func = sub_800AAAC; +        break; +    case -1: +        sub_8072DEC(); +        audio_play(SE_SELECT); +        MenuZeroFillWindowRect(2, 1, 22, 12); +        gTasks[taskId].func = task_new_game_prof_birch_speech_14; +        break; +    } +} + +void sub_800AAAC(u8 taskId) +{ +    if (!gPaletteFade.active) +    { +        set_default_player_name(1); +        DoNamingScreen(0, &gSaveBlock2, gSaveBlock2.playerGender, 0, 0, new_game_prof_birch_speech_part2_start); +    } +} + +void task_new_game_prof_birch_speech_part2_1(u8 taskId) +{ +    MenuDrawTextWindow(2, 13, 27, 18); +    StringExpandPlaceholders(gStringVar4, gUnknown_081C7017); +    MenuPrintMessage(gStringVar4, 3, 14); +    gTasks[taskId].func = sub_800AB38; +} + +void sub_800AB38(u8 taskId) +{ +    if (MenuUpdateWindowText_OverrideLineLength(24)) +    { +        DisplayYesNoMenu(2, 1, 1); +        gTasks[taskId].func = task_new_game_prof_birch_speech_part2_4; +    } +} + +void task_new_game_prof_birch_speech_part2_4(u8 taskId) +{ +    switch (ProcessMenuInputNoWrap_()) +    { +    case 0: +        audio_play(SE_SELECT); +        MenuZeroFillWindowRect(2, 1, 8, 7); +        gSprites[gTasks[taskId].data[2]].oam.objMode = ST_OAM_OBJ_BLEND; +        sub_800B458(taskId, 2); +        sub_800B614(taskId, 1); +        gTasks[taskId].func = sub_800AC20; +        break; +    case -1: +    case 1: +        audio_play(SE_SELECT); +        MenuZeroFillWindowRect(2, 1, 8, 7); +        gTasks[taskId].func = task_new_game_prof_birch_speech_14; +        break; +    } +} + +void sub_800AC20(u8 taskId) +{ +    if (gTasks[taskId].data[4]) +    { +        gTasks[taskId].data[4] += 2; +        REG_BG1HOFS = gTasks[taskId].data[4]; +    } +    else +    { +        gTasks[taskId].func = task_new_game_prof_birch_speech_part2_6; +    } +} + +void task_new_game_prof_birch_speech_part2_6(u8 taskId) +{ +    if (gTasks[taskId].data[5]) +    { +        s16 spriteId; + +        spriteId = gTasks[taskId].data[10]; +        gSprites[spriteId].invisible = 1; + +        spriteId = gTasks[taskId].data[11]; +        gSprites[spriteId].invisible = 1; + +        spriteId = (u8)gTasks[taskId].data[8]; +        gSprites[spriteId].pos1.x = 0x88; +        gSprites[spriteId].pos1.y = 0x40; +        gSprites[spriteId].invisible = 0; +        gSprites[spriteId].oam.objMode = 1; + +        spriteId = (u8)gTasks[taskId].data[9]; +        gSprites[spriteId].pos1.x = 0x68; +        gSprites[spriteId].pos1.y = 0x48; +        gSprites[spriteId].invisible = 0; +        gSprites[spriteId].oam.objMode = 1; + +        sub_800B534(taskId, 2); +        sub_800B6C0(taskId, 1); +        MenuDrawTextWindow(2, 13, 27, 18); +        StringExpandPlaceholders(gStringVar4, gUnknown_081C7025); +        MenuPrintMessage(gStringVar4, 3, 14); +        gTasks[taskId].func = task_new_game_prof_birch_speech_part2_7; +    } +} + +void task_new_game_prof_birch_speech_part2_7(u8 taskId) +{ +    if (gTasks[taskId].data[5]) +    { +        s16 spriteId; + +        spriteId = gTasks[taskId].data[8]; +        gSprites[spriteId].oam.objMode = 0; + +        spriteId = gTasks[taskId].data[9]; +        gSprites[spriteId].oam.objMode = 0; + +        if (MenuUpdateWindowText_OverrideLineLength(24)) +        { +            spriteId = gTasks[taskId].data[8]; +            gSprites[spriteId].oam.objMode = 1; + +            spriteId = gTasks[taskId].data[9]; +            gSprites[spriteId].oam.objMode = 1; + +            sub_800B458(taskId, 2); +            sub_800B614(taskId, 1); +            gTasks[taskId].data[7] = 0x40; +            gTasks[taskId].func = task_new_game_prof_birch_speech_part2_8; +        } +    } +} + +void task_new_game_prof_birch_speech_part2_8(u8 taskId) +{ +    if (gTasks[taskId].data[5]) +    { +        s16 spriteId; + +        spriteId = gTasks[taskId].data[8]; +        gSprites[spriteId].invisible = 1; + +        spriteId = gTasks[taskId].data[9]; +        gSprites[spriteId].invisible = 1; + +        if (gTasks[taskId].data[7]) +        { +            gTasks[taskId].data[7]--; +        } +        else +        { +            u8 spriteId; + +            if (gSaveBlock2.playerGender) +                spriteId = (u8)gTasks[taskId].data[11]; +            else +                spriteId = (u8)gTasks[taskId].data[10]; + +            gSprites[spriteId].pos1.x = 0x78; +            gSprites[spriteId].pos1.y = 0x3C; +            gSprites[spriteId].invisible = 0; +            gSprites[spriteId].oam.objMode = 1; +            gTasks[taskId].data[2] = spriteId; + +            sub_800B534(taskId, 2); +            sub_800B6C0(taskId, 1); +            MenuDrawTextWindow(2, 13, 27, 18); +            MenuPrintMessage(gUnknown_081C7074, 3, 14); +            gTasks[taskId].func = task_new_game_prof_birch_speech_part2_9; +        } +    } +} + +void task_new_game_prof_birch_speech_part2_9(u8 taskId) +{ +    if (gTasks[taskId].data[5]) +    { +        s16 spriteId; + +        spriteId = gTasks[taskId].data[2]; +        gSprites[spriteId].oam.objMode = 0; + +        if (MenuUpdateWindowText_OverrideLineLength(24)) +        { +            u8 spriteId; + +            spriteId = gTasks[taskId].data[2]; +            gSprites[spriteId].oam.affineMode = 1; +            gSprites[spriteId].affineAnims = (union AffineAnimCmd **)gSpriteAffineAnimTable_81E79AC; +            InitSpriteAffineAnim(&gSprites[spriteId]); +            StartSpriteAffineAnim(&gSprites[spriteId], 0); +            gSprites[spriteId].callback = sub_800B240; +            BeginNormalPaletteFade(0x0000ffff, 0, 0, 0x10, 0); +            play_sound_effect(4); +            gTasks[taskId].func = task_new_game_prof_birch_speech_part2_10; +        } +    } +} + +void task_new_game_prof_birch_speech_part2_10(u8 taskId) +{ +    u8 spriteId = gTasks[taskId].data[2]; + +    if (gSprites[spriteId].affineAnimEnded) +        gTasks[taskId].func = sub_800AFC0; +} + +void sub_800AFC0(u8 taskId) +{ +    if (!gPaletteFade.active) +    { +        u8 spriteId = gTasks[taskId].data[2]; +        gSprites[spriteId].callback = nullsub_34; +        REG_DISPCNT = 4160; +        BeginNormalPaletteFade(0xFFFF0000, 0, 0, 0x10, 0xFFFF); +        gTasks[taskId].func = sub_800B034; +    } +} + +void sub_800B034(u8 taskId) +{ +    if (!gPaletteFade.active) +    { +        SetMainCallback2(c2_load_new_map_2); +        DestroyTask(taskId); +    } +} + +// CB2 +void new_game_prof_birch_speech_part2_start() +{ +    u8 taskId; +    u8 spriteId; +    u16 savedIme; + +    SetVBlankCallback(NULL); + +    REG_DISPCNT = 0; +    REG_BG2CNT = 0; +    REG_BG1CNT = 0; +    REG_BG0CNT = 0; +    REG_BG2HOFS = 0; +    REG_BG2VOFS = 0; +    REG_BG1HOFS = 0; +    REG_BG1VOFS = 0; +    REG_BG0HOFS = 0; +    REG_BG0VOFS = 0; + +    DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE); +    DmaFill32(3, 0, (void *)OAM, OAM_SIZE); +    DmaFill16(3, 0, (void *)PLTT, PLTT_SIZE); + +    ResetPaletteFade(); + +    LZ77UnCompVram(gUnknown_081E768C, (void *)BG_VRAM); +    LZ77UnCompVram(gUnknown_081E7834, (void *)(BG_VRAM + 0x3800)); + +    LoadPalette(gUnknown_081E764C, 0, 0x40); + +    ResetTasks(); + +    taskId = CreateTask(task_new_game_prof_birch_speech_part2_1, 0); + +    gTasks[taskId].data[4] = -60; + +    remove_some_task(); +    ResetSpriteData(); +    FreeAllSpritePalettes(); +    AddBirchSpeechObjects(taskId); + +    SetUpWindowConfig(&gWindowConfig_81E6C3C); +    InitMenuWindow(&gWindowConfig_81E6CE4); + +    if (gSaveBlock2.playerGender != MALE) +    { +        gTasks[taskId].data[6] = FEMALE; +        spriteId = gTasks[taskId].data[11]; +    } +    else +    { +        gTasks[taskId].data[6] = MALE; +        spriteId = gTasks[taskId].data[10]; +    } + +    gSprites[spriteId].pos1.x = 180; +    gSprites[spriteId].pos1.y = 60; +    gSprites[spriteId].invisible = 0; + +    gTasks[taskId].data[2] = spriteId; + +    REG_BG1HOFS = -60; + +    BeginNormalPaletteFade(0xFFFFFFFFu, 0, 0x10, 0, 0); + +    REG_WIN0H = 0; +    REG_WIN0V = 0; +    REG_WININ = 0; +    REG_WINOUT = 0; +    REG_BLDCNT = 0; +    REG_BLDALPHA = 0; +    REG_BLDY = 0; + +    savedIme = REG_IME; +    REG_IME = 0; +    REG_IE |= INTR_FLAG_VBLANK; +    REG_IME = savedIme; + +    SetVBlankCallback(VBlankCB_MainMenu); +    SetMainCallback2(CB2_MainMenu); +    REG_BG1CNT = 1795; +    REG_DISPCNT = 4928; +} + +void nullsub_34(struct Sprite *sprite) +{ +} + +void sub_800B240(struct Sprite *sprite) +{ +    u32 y = (sprite->pos1.y << 16) + sprite->data0 + 0xC000; +    sprite->pos1.y = y >> 16; +    sprite->data0 = y; +} + +u8 CreateAzurillSprite(u8 a1, u8 a2) +{ +    DecompressPicFromTable_2( +        &gMonFrontPicTable[SPECIES_AZURILL], +        gMonFrontPicCoords[SPECIES_AZURILL].x, +        gMonFrontPicCoords[SPECIES_AZURILL].y, +        gUnknown_081FAF4C[0], +        gUnknown_081FAF4C[1], +        SPECIES_AZURILL); +    LoadCompressedObjectPalette(&gMonPaletteTable[SPECIES_AZURILL]); +    gpu_pal_obj_decompress_and_apply(SPECIES_AZURILL, 1); +    return CreateSprite(&gUnknown_02024E8C, a1, a2, 0); +} + +void AddBirchSpeechObjects(u8 taskId) +{ +    u8 spriteId; + +    spriteId = AddNewGameBirchObject(136, 60, 1); +    gSprites[spriteId].callback = nullsub_34; +    gSprites[spriteId].oam.priority = 0; +    gSprites[spriteId].invisible = 1; +    gTasks[taskId].data[8] = spriteId; + +    spriteId = CreateAzurillSprite(0x68, 0x48); +    gSprites[spriteId].callback = nullsub_34; +    gSprites[spriteId].oam.priority = 0; +    gSprites[spriteId].invisible = 1; +    gTasks[taskId].data[9] = spriteId; + +    spriteId = sub_80859BC(0, 120, 60, 0, unk_2000000); +    gSprites[spriteId].callback = nullsub_34; +    gSprites[spriteId].invisible = 1; +    gSprites[spriteId].oam.priority = 0; +    gTasks[taskId].data[10] = spriteId; + +    spriteId = sub_80859BC(1, 120, 60, 0, unk_2000000 + 0x800); +    gSprites[spriteId].callback = nullsub_34; +    gSprites[spriteId].invisible = 1; +    gSprites[spriteId].oam.priority = 0; +    gTasks[taskId].data[11] = spriteId; +} + +void sub_800B3EC(u8 taskId) +{ +    if (gTasks[taskId].data[1] == 0) +    { +        gTasks[gTasks[taskId].data[0]].data[5] = 1; +        DestroyTask(taskId); +    } +    else +    { +        if (gTasks[taskId].data[4]) +        { +            gTasks[taskId].data[4]--; +        } +        else +        { +            gTasks[taskId].data[4] = gTasks[taskId].data[3]; +            gTasks[taskId].data[1]--; +            gTasks[taskId].data[2]++; +            REG_BLDALPHA = gTasks[taskId].data[1] + (gTasks[taskId].data[2] * 256); +        } +    } +} + +void sub_800B458(u8 taskId, u8 a2) +{ +    u8 newTaskId; + +    REG_BLDCNT = 592; +    REG_BLDALPHA = 16; +    REG_BLDY = 0; +    gTasks[taskId].data[5] = 0; +    newTaskId = CreateTask(sub_800B3EC, 0); + +    gTasks[newTaskId].data[0] = taskId; +    gTasks[newTaskId].data[1] = 16; +    gTasks[newTaskId].data[2] = 0; +    gTasks[newTaskId].data[3] = a2; +    gTasks[newTaskId].data[4] = a2; +} + +void sub_800B4C8(u8 taskId) +{ +    if (gTasks[taskId].data[1] == 16) +    { +        gTasks[gTasks[taskId].data[0]].data[5] = 1; +        DestroyTask(taskId); +    } +    else if (gTasks[taskId].data[4]) +    { +        gTasks[taskId].data[4]--; +    } +    else +    { +        gTasks[taskId].data[4] = gTasks[taskId].data[3]; +        gTasks[taskId].data[1]++; +        gTasks[taskId].data[2]--; +        REG_BLDALPHA = gTasks[taskId].data[1] + (gTasks[taskId].data[2] * 256); +    } +} + +void sub_800B534(u8 taskId, u8 a2) +{ +    u8 newTaskId; + +    REG_BLDCNT = 592; +    REG_BLDALPHA = 4096; +    REG_BLDY = 0; +    gTasks[taskId].data[5] = 0; +    newTaskId = CreateTask(sub_800B4C8, 0); + +    gTasks[newTaskId].data[0] = taskId; +    gTasks[newTaskId].data[1] = 0; +    gTasks[newTaskId].data[2] = 16; +    gTasks[newTaskId].data[3] = a2; +    gTasks[newTaskId].data[4] = a2; +} + +void sub_800B5A8(u8 taskId) +{ +    if (gTasks[taskId].data[2]) +    { +        gTasks[taskId].data[2]--; +    } +    else +    { +        if (gTasks[taskId].data[1] == 8) +        { +            DestroyTask(taskId); +        } +        else if (gTasks[taskId].data[4]) +        { +            gTasks[taskId].data[4]--; +        } +        else +        { +            gTasks[taskId].data[4] = gTasks[taskId].data[3]; +            gTasks[taskId].data[1]++; +            LoadPalette(&gUnknown_081E795C[gTasks[taskId].data[1]], 1, 0x10); +        } +    } +} + +void sub_800B614(u8 a1, u8 a2) +{ +    u8 newTaskId = CreateTask(sub_800B5A8, 0); +    gTasks[newTaskId].data[0] = a1; +    gTasks[newTaskId].data[1] = 0; +    gTasks[newTaskId].data[2] = 8; +    gTasks[newTaskId].data[3] = a2; +    gTasks[newTaskId].data[4] = a2; +} + +void sub_800B654(u8 taskId) +{ +    if (gTasks[taskId].data[2]) +    { +        gTasks[taskId].data[2]--; +    } +    else +    { +        if (gTasks[taskId].data[1] == 0) +        { +            DestroyTask(taskId); +        } +        else +        { +            if (gTasks[taskId].data[4]) +            { +                gTasks[taskId].data[4]--; +            } +            else +            { +                gTasks[taskId].data[4] = gTasks[taskId].data[3]; +                gTasks[taskId].data[1]--; +                LoadPalette(&gUnknown_081E795C[gTasks[taskId].data[1]], 1, 0x10); +            } +        } +    } +} + +void sub_800B6C0(u8 a1, u8 a2) +{ +    u8 newTaskId = CreateTask(sub_800B654, 0); +    gTasks[newTaskId].data[0] = a1; +    gTasks[newTaskId].data[1] = 8; +    gTasks[newTaskId].data[2] = 8; +    gTasks[newTaskId].data[3] = a2; +    gTasks[newTaskId].data[4] = a2; +} + +void CreateGenderMenu(u8 left, u8 top) +{ +    u8 menuLeft, menuTop; +    MenuDrawTextWindow(left, top, left + 6, top + 5); +    menuLeft = left + 1; +    menuTop = top + 1; +    PrintMenuItems(menuLeft, menuTop, 2, gUnknown_081E79B0); +    InitMenu(0, menuLeft, menuTop, 2, 0, 5); +} + +s8 GenderMenuProcessInput(void) +{ +    return ProcessMenuInputNoWrap(); +} + +void CreateNameMenu(u8 left, u8 top) +{ +    MenuDrawTextWindow(left, top, left + 10, top + 11); + +    if (gSaveBlock2.playerGender == MALE) +    { +        PrintMenuItems((u8)(left + 1), (u8)(top + 1), 5, gUnknown_081E79C0); +    } +    else +    { +        PrintMenuItems((u8)(left + 1), (u8)(top + 1), 5, gUnknown_081E79E8); +    } + +    InitMenu(0, (u8)(left + 1), (u8)(top + 1), 5, 0, 9); +} + +s8 NameMenuProcessInput(void) +{ +    return ProcessMenuInput(); +} + +void set_default_player_name(u8 index) +{ +    u8 i; +    u8 *name; + +    if (gSaveBlock2.playerGender == MALE) +        name = gUnknown_081E79C0[index][0]; +    else +        name = gUnknown_081E79E8[index][0]; + +    for (i = 0; i < 7; i++) +        gSaveBlock2.playerName[i] = name[i]; + +    gSaveBlock2.playerName[i] = EOS; +} diff --git a/src/menu.c b/src/menu.c new file mode 100644 index 000000000..b101165f2 --- /dev/null +++ b/src/menu.c @@ -0,0 +1,1003 @@ +#include "global.h" +#include "main.h" +#include "text.h" +#include "songs.h" +#include "text_window.h" + +struct Menu +{ +    u8 left; +    u8 top; +    s8 cursorPos; +    s8 minCursorPos; +    s8 maxCursorPos; +    u8 width; +    u8 height; +    u8 menu_field_7; +    u8 columnXCoords[8]; +}; + +void InitMenuWindow(struct WindowConfig *); +void MultistepInitMenuWindowBegin(struct WindowConfig *); +void MultistepInitMenuWindowInternal(struct WindowConfig *, u16); +bool32 MultistepInitMenuWindowContinue(void); +void InitMenuWindowInternal(struct WindowConfig *, u16); +void unref_sub_8071DA4(struct WindowConfig *, u16); +void MenuLoadTextWindowGraphics_OverrideFrameType(u8); +void MenuLoadTextWindowGraphics(void); +void BasicInitMenuWindow(struct WindowConfig *); +void MenuPrint(u8 *, u8, u8); +void MenuZeroFillWindowRect(u8, u8, u8, u8); +void MenuFillWindowRectWithBlankTile(u8, u8, u8, u8); +void MenuZeroFillScreen(void); +void MenuDrawTextWindow(u8, u8, u8, u8); +void sub_8071F40(u8 *); +void sub_8071F60(u8, u8, u8, u8); +u16 unref_sub_8071F98(u8, u8); +void unref_sub_8071FBC(u16, u8, u8, u8, u8); +void MenuDisplayMessageBox(void); +void MenuPrintMessage(u8 *, u8, u8); +void sub_8072044(u8 *); +void MenuSetText(u8 *); +u8 MenuUpdateWindowText(void); +u8 unref_sub_8072098(void); +void sub_80720B0(void); +u8 MoveMenuCursor(s8); +u8 MoveMenuCursorNoWrap(s8); +u8 GetMenuCursorPos(void); +s8 ProcessMenuInput(void); +s8 ProcessMenuInputNoWrap(void); +u8 MoveMenuCursor3(s8); +u8 MoveMenuCursor4(s8); +bool8 sub_80723D4(void); +u8 sub_8072484(u8, u8, u8, u8, u8, u8, u32); +u8 sub_80724F4(u8, u8, u8, u8*[][2], u8); +void sub_8072620(u8, u8, u8, u8*[][2], u8); +void sub_807274C(u8, u8, u8, u8, u8*[][2], u8, u32); +s8 sub_80727CC(void); +u8 sub_807288C(u8); +void PrintMenuItems(u8, u8, u8, u8*[][2]); +void PrintMenuItemsReordered(u8, u8, u8, u8*[][2], u8*); +void InitYesNoMenu(u8, u8, u8); +void DisplayYesNoMenu(u8, u8, u32); +s8 ProcessMenuInputNoWrap_(void); +u8 sub_80729D8(u8 *, u8, u16, u8); +u8 sub_8072A18(u8 *, u8, u16, u8, u32); +u8 unref_sub_8072A5C(u8 *, u8 *, u8, u16, u8, u32); +int sub_8072AB0(u8 *, u8, u16, u8, u8, u32); +void sub_8072B4C(u8 *, u8, u8); +void sub_8072B80(u8 *, u8, u8, u8 *); +void sub_8072BD8(u8 *, u8, u8, u16); +u8 *sub_8072C14(u8 *, s32, u8, u8); +u8 *sub_8072C44(u8 *, s32, u8, u8); +u8 *sub_8072C74(u8 *, u8 *, u8, u8); +u8 sub_8072CA4(u8 *s); +u8 sub_8072CBC(void); +void sub_8072CD4(u8 *, u8 *, u8 *); +u32 MenuUpdateWindowText_OverrideLineLength(u8); +struct Window * unref_sub_8072D0C(void); +void sub_8072D18(u8, u8); +u8 InitMenu(u8, u8, u8, u8, u8, u8); +void RedrawMenuCursor(u8, u8); +void unref_sub_8072DC0(void); +void sub_8072DCC(u8); +void sub_8072DDC(u8); +void sub_8072DEC(void); + +extern void sub_814A5C0(u8, u16, u8, u16, u8); +extern void sub_814A880(u8, u8); +extern void sub_814A904(void); +extern void sub_814A958(u8); +extern void sub_814A7FC(void); + +static struct Menu gMenu; + +extern struct Window gMenuWindow; +extern struct Window *gMenuWindowPtr; +extern u8 gMenuMultistepInitState; +extern u16 gMenuTextTileOffset; +extern u16 gMenuTextWindowTileOffset; +extern u16 gMenuTextWindowContentTileOffset; +extern u16 gMenuMessageBoxContentTileOffset; + +extern const u8 *gUnknown_08376D74[][2]; + +void InitMenuWindow(struct WindowConfig *winConfig) +{ +    InitMenuWindowInternal(winConfig, 1); +} + +void MultistepInitMenuWindowBegin(struct WindowConfig *winConfig) +{ +    MultistepInitMenuWindowInternal(winConfig, 1); +} + +void MultistepInitMenuWindowInternal(struct WindowConfig *winConfig, u16 tileOffset) +{ +    gMenuMultistepInitState = 0; +    gMenuTextTileOffset = tileOffset; +    gMenuWindowPtr = &gMenuWindow; +    InitWindowFromConfig(&gMenuWindow, winConfig); +} + +bool32 MultistepInitMenuWindowContinue(void) +{ +    switch (gMenuMultistepInitState) +    { +    case 0: +        gMenuMultistepInitState++; +        return 0; +    case 1: +        gMenuTextWindowTileOffset = MultistepInitWindowTileData(gMenuWindowPtr, gMenuTextTileOffset); +        goto next; +    case 2: +        if (!MultistepLoadFont()) +            goto fail; +        goto next; +    case 3: +        gMenuTextWindowContentTileOffset = SetTextWindowBaseTileNum(gMenuTextWindowTileOffset); +    next: +        gMenuMultistepInitState++; +        return 0; +    case 4: +        LoadTextWindowGraphics(gMenuWindowPtr); +        gMenuMessageBoxContentTileOffset = SetMessageBoxBaseTileNum(gMenuTextWindowContentTileOffset); +        return 1; +    default: +    fail: +        return 0; +    } +} + +void InitMenuWindowInternal(struct WindowConfig *winConfig, u16 tileOffset) +{ +    gMenuWindowPtr = &gMenuWindow; +    InitWindowFromConfig(&gMenuWindow, winConfig); +    gMenuTextTileOffset = tileOffset; +    gMenuTextWindowTileOffset = InitWindowTileData(gMenuWindowPtr, gMenuTextTileOffset); +    gMenuTextWindowContentTileOffset = SetTextWindowBaseTileNum(gMenuTextWindowTileOffset); +    LoadTextWindowGraphics(gMenuWindowPtr); +    gMenuMessageBoxContentTileOffset = SetMessageBoxBaseTileNum(gMenuTextWindowContentTileOffset); +} + +void unref_sub_8071DA4(struct WindowConfig *winConfig, u16 tileOffset) +{ +    gMenuWindowPtr = &gMenuWindow; +    InitWindowFromConfig(&gMenuWindow, winConfig); +    gMenuTextWindowTileOffset = tileOffset; +    gMenuTextWindowContentTileOffset = SetTextWindowBaseTileNum(gMenuTextWindowTileOffset); +    LoadTextWindowGraphics(gMenuWindowPtr); +    gMenuTextTileOffset = SetMessageBoxBaseTileNum(gMenuTextWindowContentTileOffset); +    gMenuMessageBoxContentTileOffset = InitWindowTileData(gMenuWindowPtr, gMenuTextTileOffset); +} + +void MenuLoadTextWindowGraphics_OverrideFrameType(u8 frameType) +{ +    LoadTextWindowGraphics_OverrideFrameType(gMenuWindowPtr, frameType); +} + +void MenuLoadTextWindowGraphics(void) +{ +    LoadTextWindowGraphics(gMenuWindowPtr); +} + +void BasicInitMenuWindow(struct WindowConfig *winConfig) +{ +    InitWindowFromConfig(gMenuWindowPtr, winConfig); +    gMenuWindowPtr->tileDataStartOffset = gMenuTextTileOffset; +} + +void MenuPrint(u8 *str, u8 left, u8 top) +{ +    sub_8003460(gMenuWindowPtr, str, gMenuTextTileOffset, left, top); +} + +void MenuZeroFillWindowRect(u8 a1, u8 a2, u8 a3, u8 a4) +{ +    ZeroFillWindowRect(gMenuWindowPtr, a1, a2, a3, a4); +} + +void MenuFillWindowRectWithBlankTile(u8 left, u8 top, u8 right, u8 bottom) +{ +    FillWindowRectWithBlankTile(gMenuWindowPtr, left, top, right, bottom); +} + +void MenuZeroFillScreen(void) +{ +    MenuZeroFillWindowRect(0, 0, 29, 19); +} + +void MenuDrawTextWindow(u8 left, u8 top, u8 right, u8 bottom) +{ +    DrawTextWindow(gMenuWindowPtr, left, top, right, bottom); +} + +void sub_8071F40(u8 *str) +{ +    MenuDrawTextWindow(2, 14, 28, 19); +    MenuPrint(str, 3, 15); +} + +void sub_8071F60(u8 a1, u8 a2, u8 a3, u8 a4) +{ +    sub_8003490(gMenuWindowPtr, a1, gMenuTextTileOffset, a2, a3); +} + +u16 unref_sub_8071F98(u8 x, u8 y) +{ +    return GetWindowTilemapEntry(gMenuWindowPtr, x, y); +} + +void unref_sub_8071FBC(u16 a1, u8 a2, u8 a3, u8 a4, u8 a5) +{ +    DrawWindowRect(gMenuWindowPtr, a1, a2, a3, a4, a5); +} + +void MenuDisplayMessageBox(void) +{ +    DisplayMessageBox(gMenuWindowPtr); +} + +void MenuPrintMessage(u8 *str, u8 left, u8 top) +{ +    sub_8002EB0(gMenuWindowPtr, str, gMenuTextTileOffset, left, top); +} + +void sub_8072044(u8 *str) +{ +    sub_8002EB0(gMenuWindowPtr, str, gMenuTextTileOffset, 2, 15); +} + +void MenuSetText(u8 *str) +{ +    sub_8002E90(gMenuWindowPtr, str); +} + +u8 MenuUpdateWindowText(void) +{ +    return sub_80035AC(gMenuWindowPtr); +} + +u8 unref_sub_8072098(void) +{ +    return sub_8003418(gMenuWindowPtr); +} + +void sub_80720B0(void) +{ +    ClearWindowTextLines(gMenuWindowPtr); +} + +u8 MoveMenuCursor(s8 delta) +{ +    s32 newPos = gMenu.cursorPos + delta; + +    if (newPos < gMenu.minCursorPos) +        gMenu.cursorPos = gMenu.maxCursorPos; +    else if (newPos > gMenu.maxCursorPos) +        gMenu.cursorPos = gMenu.minCursorPos; +    else +        gMenu.cursorPos += delta; + +    RedrawMenuCursor(gMenu.left, 2 * gMenu.cursorPos + gMenu.top); +    return gMenu.cursorPos; +} + +u8 MoveMenuCursorNoWrap(s8 delta) +{ +    s32 newPos = gMenu.cursorPos + delta; + +    if (newPos < gMenu.minCursorPos) +        gMenu.cursorPos = gMenu.minCursorPos; +    else if (newPos > gMenu.maxCursorPos) +        gMenu.cursorPos = gMenu.maxCursorPos; +    else +        gMenu.cursorPos += delta; + +    RedrawMenuCursor(gMenu.left, 2 * gMenu.cursorPos + gMenu.top); +    return gMenu.cursorPos; +} + +u8 GetMenuCursorPos(void) +{ +    return gMenu.cursorPos; +} + +s8 ProcessMenuInput(void) +{ +    if (gMain.newKeys & A_BUTTON) +    { +        audio_play(SE_SELECT); +        if (gMenu.menu_field_7) +            sub_8072DEC(); +        return gMenu.cursorPos; +    } + +    if (gMain.newKeys & B_BUTTON) +    { +        if (gMenu.menu_field_7) +            sub_8072DEC(); +        return -1; +    } + +    if (gMain.newKeys & DPAD_UP) +    { +        audio_play(SE_SELECT); +        MoveMenuCursor(-1); +        return -2; +    } +    else if (gMain.newKeys & DPAD_DOWN) +    { +        audio_play(SE_SELECT); +        MoveMenuCursor(1); +        return -2; +    } + +    return -2; +} + +s8 ProcessMenuInputNoWrap(void) +{ +    u8 cursorPos = gMenu.cursorPos; + +    if (gMain.newKeys & A_BUTTON) +    { +        audio_play(SE_SELECT); +        if (gMenu.menu_field_7) +            sub_8072DEC(); +        return gMenu.cursorPos; +    } + +    if (gMain.newKeys & B_BUTTON) +    { +        if (gMenu.menu_field_7) +            sub_8072DEC(); +        return -1; +    } + +    if (gMain.newKeys & DPAD_UP) +    { +        if (cursorPos != MoveMenuCursorNoWrap(-1)) +            audio_play(SE_SELECT); +        return -2; +    } +    else if (gMain.newKeys & DPAD_DOWN) +    { +        if (cursorPos != MoveMenuCursorNoWrap(1)) +            audio_play(SE_SELECT); +        return -2; +    } + +    MoveMenuCursorNoWrap(0); +    return -2; +} + +u8 MoveMenuCursor3(s8 delta) +{ +    u8 menuHeight = (gMenu.maxCursorPos + 1) >> 1; +    s32 newPos = gMenu.cursorPos + delta; + +    if (newPos < gMenu.minCursorPos) +        gMenu.cursorPos = gMenu.maxCursorPos; +    else if (newPos > gMenu.maxCursorPos) +        gMenu.cursorPos = gMenu.minCursorPos; +    else +        gMenu.cursorPos += delta; + +    RedrawMenuCursor( +        6 * (gMenu.cursorPos / menuHeight) + gMenu.left, +        2 * (gMenu.cursorPos % menuHeight) + gMenu.top); + +    return gMenu.cursorPos; +} + +u8 MoveMenuCursor4(s8 delta) +{ +    if (gMenu.cursorPos + delta <= gMenu.maxCursorPos) +    { +        if (sub_80723D4() == TRUE) +            return gMenu.cursorPos; +    } +    else +    { +        return gMenu.cursorPos; +    } + +    gMenu.cursorPos += delta; + +    if ((gMenu.maxCursorPos + 1) / gMenu.width == 0) +        RedrawMenuCursor( +            gMenu.left + gMenu.columnXCoords[gMenu.cursorPos % gMenu.width], +            2 * ((gMenu.cursorPos / gMenu.width) % gMenu.height) + gMenu.top); +    else +        RedrawMenuCursor( +            gMenu.left + gMenu.columnXCoords[gMenu.cursorPos % gMenu.width], +            2 * (gMenu.cursorPos / gMenu.width) + gMenu.top); + +    return gMenu.cursorPos; +} + +bool8 sub_80723D4(void) +{ +    if ((gMain.newKeys & DPAD_UP) && gMenu.cursorPos < gMenu.width) +        return TRUE; + +    if ((gMain.newKeys & DPAD_DOWN) && gMenu.cursorPos >= (gMenu.maxCursorPos + 1) - gMenu.width) +        return TRUE; + +    if ((gMain.newKeys & DPAD_LEFT) +     && ((gMenu.cursorPos - (gMenu.cursorPos % gMenu.width)) % gMenu.width == 1 // always false +         || gMenu.cursorPos == 0 +         || gMenu.cursorPos % gMenu.width == 0)) +         return TRUE; + +    if ((gMain.newKeys & DPAD_RIGHT) && gMenu.cursorPos % gMenu.width == gMenu.width - 1) +        return TRUE; + +    return FALSE; +} + +u8 sub_8072484(u8 a1, u8 a2, u8 menuItemCount, u8 a4, u8 width, u8 a6, u32 a7) +{ +    u8 v7; + +    gMenu.width = width; +    gMenu.height = menuItemCount / width; +    InitMenu(0, a1, a2, menuItemCount, a4, a6); +    v7 = 0; +    if (a7) +        v7 = -1; +    gMenu.menu_field_7 = v7; +    return a4; +} + +#ifdef NONMATCHING +u8 sub_80724F4(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2], u8 columnCount) +{ +    u8 i; +    u8 maxWidth; +    s32 height; + +    for (i = 0; i < 7; i++) +        gMenu.columnXCoords[i] = 0; + +    maxWidth = 0; +    for (i = 0; i < menuItemCount; i++) +    { +        u8 width = (sub_8072CA4(menuItems[i][0]) + 7) / 8; + +        if (width > maxWidth) +            maxWidth = width; +    } + +    for (i = 1; i <= columnCount; i++) +        gMenu.columnXCoords[i] = maxWidth; + +    for (i = 1; i <= columnCount; i++) +        gMenu.columnXCoords[i] += 1 + gMenu.columnXCoords[i - 1]; + +    gMenu.columnXCoords[columnCount]--; + +    if (!((menuItemCount / 2) < columnCount || (menuItemCount % 2 != 0)) +     || columnCount == 1 +     || columnCount == menuItemCount) +    { +        height = 2 * (menuItemCount / columnCount) + 1; +    } +    else +    { +        height = 2 * ((menuItemCount / columnCount) + 1) + 1; +    } + +    { +        u8 right; +        u8 bottom; +        u32 totalWidth; +        register s32 val asm("r1"); + +        val = (s8)top + height; +        bottom = val; + +        totalWidth = (gMenu.columnXCoords[columnCount] + 1); +        right = left + totalWidth; + +        MenuDrawTextWindow(left, top, right, bottom); +    } + +    return maxWidth; +} +#else +__attribute__((naked)) +u8 sub_80724F4(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2], u8 columnCount) +{ +    asm("push {r4-r7,lr}\n\ +	mov r7, r10\n\ +	mov r6, r9\n\ +	mov r5, r8\n\ +	push {r5-r7}\n\ +	sub sp, #0xC\n\ +	mov r8, r3\n\ +	ldr r3, [sp, #0x2C]\n\ +	lsl r0, #24\n\ +	lsr r0, #24\n\ +	str r0, [sp]\n\ +	lsl r1, #24\n\ +	lsr r1, #24\n\ +	str r1, [sp, #0x4]\n\ +	lsl r2, #24\n\ +	lsr r6, r2, #24\n\ +	lsl r3, #24\n\ +	lsr r5, r3, #24\n\ +	movs r4, #0\n\ +	ldr r0, _080725D4\n\ +	mov r9, r0\n\ +	mov r1, r9\n\ +	add r1, #0x8\n\ +	movs r2, #0\n\ +_08072524:\n\ +	add r0, r4, r1\n\ +	strb r2, [r0]\n\ +	add r0, r4, #0x1\n\ +	lsl r0, #24\n\ +	lsr r4, r0, #24\n\ +	cmp r4, #0x6\n\ +	bls _08072524\n\ +	movs r7, #0\n\ +	movs r4, #0\n\ +	lsr r2, r6, #1\n\ +	mov r10, r2\n\ +	ldr r0, [sp, #0x4]\n\ +	lsl r0, #24\n\ +	str r0, [sp, #0x8]\n\ +	cmp r7, r6\n\ +	bcs _08072566\n\ +_08072544:\n\ +	lsl r0, r4, #3\n\ +	add r0, r8\n\ +	ldr r0, [r0]\n\ +	bl sub_8072CA4\n\ +	lsl r0, #24\n\ +	lsr r0, #24\n\ +	add r1, r0, #0x7\n\ +	lsr r0, r1, #3\n\ +	cmp r0, r7\n\ +	bls _0807255C\n\ +	add r7, r0, #0\n\ +_0807255C:\n\ +	add r0, r4, #0x1\n\ +	lsl r0, #24\n\ +	lsr r4, r0, #24\n\ +	cmp r4, r6\n\ +	bcc _08072544\n\ +_08072566:\n\ +	movs r4, #0x1\n\ +	ldr r2, _080725D4\n\ +	mov r9, r2\n\ +	cmp r4, r5\n\ +	bhi _08072582\n\ +	mov r1, r9\n\ +	add r1, #0x8\n\ +_08072574:\n\ +	add r0, r4, r1\n\ +	strb r7, [r0]\n\ +	add r0, r4, #0x1\n\ +	lsl r0, #24\n\ +	lsr r4, r0, #24\n\ +	cmp r4, r5\n\ +	bls _08072574\n\ +_08072582:\n\ +	movs r4, #0x1\n\ +	cmp r4, r5\n\ +	bhi _080725A4\n\ +	ldr r3, _080725D8\n\ +_0807258A:\n\ +	add r2, r4, r3\n\ +	ldrb r1, [r2]\n\ +	sub r0, r4, #0x1\n\ +	add r0, r3\n\ +	add r1, #0x1\n\ +	ldrb r0, [r0]\n\ +	add r1, r0\n\ +	strb r1, [r2]\n\ +	add r0, r4, #0x1\n\ +	lsl r0, #24\n\ +	lsr r4, r0, #24\n\ +	cmp r4, r5\n\ +	bls _0807258A\n\ +_080725A4:\n\ +	mov r1, r9\n\ +	add r1, #0x8\n\ +	add r1, r5, r1\n\ +	ldrb r0, [r1]\n\ +	sub r0, #0x1\n\ +	strb r0, [r1]\n\ +	cmp r10, r5\n\ +	bcc _080725BC\n\ +	movs r0, #0x1\n\ +	and r0, r6\n\ +	cmp r0, #0\n\ +	beq _080725C4\n\ +_080725BC:\n\ +	cmp r5, #0x1\n\ +	beq _080725C4\n\ +	cmp r5, r6\n\ +	bne _080725DC\n\ +_080725C4:\n\ +	add r0, r6, #0\n\ +	add r1, r5, #0\n\ +	bl __udivsi3\n\ +	lsl r0, #24\n\ +	lsr r0, #23\n\ +	add r0, #0x1\n\ +	b _080725EA\n\ +	.align 2, 0\n\ +_080725D4: .4byte 0x030006b0\n\ +_080725D8: .4byte 0x030006b8\n\ +_080725DC:\n\ +	add r0, r6, #0\n\ +	add r1, r5, #0\n\ +	bl __udivsi3\n\ +	lsl r0, #24\n\ +	lsr r0, #23\n\ +	add r0, #0x3\n\ +_080725EA:\n\ +	ldr r2, [sp, #0x8]\n\ +	asr r1, r2, #24\n\ +	add r1, r0\n\ +	lsl r1, #24\n\ +	lsr r3, r1, #24\n\ +	mov r0, r9\n\ +	add r0, #0x8\n\ +	add r0, r5, r0\n\ +	ldrb r2, [r0]\n\ +	add r2, #0x1\n\ +	ldr r0, [sp]\n\ +	add r2, r0, r2\n\ +	lsl r2, #24\n\ +	lsr r2, #24\n\ +	ldr r1, [sp, #0x4]\n\ +	bl MenuDrawTextWindow\n\ +	add r0, r7, #0\n\ +	add sp, #0xC\n\ +	pop {r3-r5}\n\ +	mov r8, r3\n\ +	mov r9, r4\n\ +	mov r10, r5\n\ +	pop {r4-r7}\n\ +	pop {r1}\n\ +	bx r1\n"); +} +#endif // NONMATCHING + +void sub_8072620(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2], u8 columnCount) +{ +    u8 i; +    u8 maxWidth; + +    for (i = 0; i < 7; i++) +        gMenu.columnXCoords[i] = 0; + +    maxWidth = 0; +    for (i = 0; i < menuItemCount; i++) +    { +        u8 width = (sub_8072CA4(menuItems[i][0]) + 7) / 8; + +        if (width > maxWidth) +            maxWidth = width; +    } + +    for (i = 1; i <= columnCount; i++) +        gMenu.columnXCoords[i] = maxWidth; + +    for (i = 1; i <= columnCount; i++) +        gMenu.columnXCoords[i] += 1 + gMenu.columnXCoords[i - 1]; + +    gMenu.columnXCoords[columnCount]--; + +    for (i = 0; i < columnCount; i++) +    { +        u8 row = 0; +        u8 j; +        for (j = 0; i + j < menuItemCount; j += columnCount, row++) +            MenuPrint(menuItems[i + j][0], left + gMenu.columnXCoords[i % columnCount], top + 2 * row); +    } +} + +void sub_807274C(u8 left, u8 top, u8 menuItemCount, u8 a4, u8 *menuItems[][2], u8 columnCount, u32 a7) +{ +    u8 maxWidth = sub_80724F4(left, top, menuItemCount, menuItems, columnCount); + +    sub_8072484(left + 1, top + 1, menuItemCount, a4, columnCount, maxWidth, a7); +    sub_8072620(left + 1, top + 1, menuItemCount, menuItems, columnCount); +} + +s8 sub_80727CC(void) +{ +    if (gMain.newKeys & A_BUTTON) +    { +        if (gMenu.menu_field_7) +            sub_8072DEC(); +        audio_play(SE_SELECT); +        return GetMenuCursorPos(); +    } + +    if (gMain.newKeys & B_BUTTON) +    { +        if (gMenu.menu_field_7) +            sub_8072DEC(); +        return -1; +    } + +    if (gMain.newKeys & DPAD_UP) +    { +        audio_play(SE_SELECT); +        MoveMenuCursor4(-gMenu.width); +        return -2; +    } +    else if (gMain.newKeys & DPAD_DOWN) +    { +        audio_play(SE_SELECT); +        MoveMenuCursor4(gMenu.width); +        return -2; +    } +    else if (gMain.newKeys & DPAD_LEFT) +    { +        audio_play(SE_SELECT); +        MoveMenuCursor4(-1); +        return -2; +    } +    else if (gMain.newKeys & DPAD_RIGHT) +    { +        audio_play(SE_SELECT); +        MoveMenuCursor4(1); +        return -2; +    } + +    return -2; +} + +u8 sub_807288C(u8 column) +{ +    return gMenu.columnXCoords[column]; +} + +void PrintMenuItems(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2]) +{ +    u8 i; + +    for (i = 0; i < menuItemCount; i++) +        MenuPrint(menuItems[i][0], left, top + 2 * i); +} + +void PrintMenuItemsReordered(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2], u8 *order) +{ +    u8 i; + +    for (i = 0; i < menuItemCount; i++) +        MenuPrint(menuItems[order[i]][0], left, top + 2 * i); +} + +void InitYesNoMenu(u8 left, u8 top, u8 a3) +{ +    PrintMenuItems(left + 1, top + 1, 2, (void *)gUnknown_08376D74); +    InitMenu(0, left + 1, top + 1, 2, 0, a3); +} + +void DisplayYesNoMenu(u8 left, u8 top, u32 a3) +{ +    MenuDrawTextWindow(left, top, left + 6, top + 5); +    InitYesNoMenu(left, top, 5); +    gMenu.menu_field_7 = a3 ? -1 : 0; +} + +s8 ProcessMenuInputNoWrap_(void) +{ +    return ProcessMenuInputNoWrap(); +} + +u8 sub_80729D8(u8 *text, u8 left, u16 top, u8 a4) +{ +    return sub_8004D04(gMenuWindowPtr, text, gMenuTextTileOffset, left, top, a4); +} + +u8 sub_8072A18(u8 *text, u8 left, u16 top, u8 width, u32 a5) +{ +    return sub_8004FD0(gMenuWindowPtr, 0, text, gMenuTextTileOffset, left, top, width, a5); +} + +u8 unref_sub_8072A5C(u8 *dest, u8 *src, u8 left, u16 top, u8 width, u32 a6) +{ +    return sub_8004FD0(gMenuWindowPtr, dest, src, gMenuTextTileOffset, left, top, width, a6); +} + +__attribute__((naked)) +int sub_8072AB0(u8 *str, u8 left, u16 top, u8 width, u8 height, u32 a6) +{ +    asm("push {r4-r7,lr}\n\ +	mov r7, r9\n\ +	mov r6, r8\n\ +	push {r6,r7}\n\ +	sub sp, #0x10\n\ +	mov r9, r0\n\ +	add r4, r1, #0\n\ +	add r5, r2, #0\n\ +	ldr r0, [sp, #0x2C]\n\ +	ldr r2, [sp, #0x30]\n\ +	lsl r4, #24\n\ +	lsr r1, r4, #24\n\ +	mov r12, r1\n\ +	lsl r5, #16\n\ +	lsr r7, r5, #16\n\ +	lsl r3, #24\n\ +	lsr r6, r3, #24\n\ +	lsl r0, #24\n\ +	lsr r0, #24\n\ +	mov r8, r0\n\ +	ldr r0, _08072B44\n\ +	ldr r0, [r0]\n\ +	ldr r1, _08072B48\n\ +	ldrh r3, [r1]\n\ +	mov r1, r12\n\ +	str r1, [sp]\n\ +	str r7, [sp, #0x4]\n\ +	str r6, [sp, #0x8]\n\ +	str r2, [sp, #0xC]\n\ +	movs r1, #0\n\ +	mov r2, r9\n\ +	bl sub_8004FD0\n\ +	add r1, r0, #0\n\ +	lsl r1, #24\n\ +	lsr r2, r1, #24\n\ +	lsr r4, #27\n\ +	mov r12, r4\n\ +	lsr r7, r5, #19\n\ +	add r1, r6, #0x7\n\ +	lsr r6, r1, #3\n\ +	mov r1, r8\n\ +	add r1, #0x7\n\ +	asr r1, #3\n\ +	lsl r1, #24\n\ +	lsr r1, #24\n\ +	mov r8, r1\n\ +	cmp r2, r8\n\ +	bcs _08072B34\n\ +	lsl r1, r2, #1\n\ +	add r1, r7, r1\n\ +	lsl r1, #24\n\ +	lsr r1, #24\n\ +	mov r0, r12\n\ +	add r2, r0, r6\n\ +	sub r2, #0x1\n\ +	lsl r2, #24\n\ +	lsr r2, #24\n\ +	mov r0, r8\n\ +	add r3, r0, r7\n\ +	sub r3, #0x1\n\ +	lsl r3, #24\n\ +	lsr r3, #24\n\ +	mov r0, r12\n\ +	bl MenuFillWindowRectWithBlankTile\n\ +_08072B34:\n\ +	add sp, #0x10\n\ +	pop {r3,r4}\n\ +	mov r8, r3\n\ +	mov r9, r4\n\ +	pop {r4-r7}\n\ +	pop {r1}\n\ +	bx r1\n\ +	.align 2, 0\n\ +_08072B44: .4byte 0x0202e9c8\n\ +_08072B48: .4byte 0x0202e9ce\n"); +} + +void sub_8072B4C(u8 *str, u8 left, u8 top) +{ +    sub_8004D38(gMenuWindowPtr, str, gMenuTextTileOffset, left, top); +} + +void sub_8072B80(u8 *a1, u8 a2, u8 a3, u8 *a4) +{ +    u8 buffer[64]; +    u8 width = GetStringWidth(gMenuWindowPtr, a4); +    AlignString(gMenuWindowPtr, buffer, a1, width, 1); +    sub_8003460(gMenuWindowPtr, buffer, gMenuTextTileOffset, a2, a3); +} + +void sub_8072BD8(u8 *a1, u8 a2, u8 a3, u16 a4) +{ +    sub_8004DB0(gMenuWindowPtr, a1, gMenuTextTileOffset, a2, a3, a4); +} + +u8 *sub_8072C14(u8 *a1, s32 a2, u8 a3, u8 a4) +{ +    return AlignInt1(gMenuWindowPtr, a1, a2, a3, a4); +} + +u8 *sub_8072C44(u8 *a1, s32 a2, u8 a3, u8 a4) +{ +    return AlignInt2(gMenuWindowPtr, a1, a2, a3, a4); +} + +u8 *sub_8072C74(u8 *a1, u8 *a2, u8 a3, u8 a4) +{ +    return AlignString(gMenuWindowPtr, a1, a2, a3, a4); +} + +u8 sub_8072CA4(u8 *str) +{ +    return GetStringWidth(gMenuWindowPtr, str); +} + +u8 sub_8072CBC() +{ +    return sub_8004E24(gMenuWindowPtr); +} + +void sub_8072CD4(u8 *a1, u8 *a2, u8 *a3) +{ +    sub_8004E28(gMenuWindowPtr, a1, a2, a3); +} + +u32 MenuUpdateWindowText_OverrideLineLength(u8 lineLength) +{ +    return sub_80037C8(gMenuWindowPtr, lineLength); +} + +struct Window *unref_sub_8072D0C(void) +{ +    return gMenuWindowPtr; +} + +void sub_8072D18(u8 a1, u8 a2) +{ +    sub_814A5C0(a1, 0xFFFF, 12, 11679, 8 * a2); +} + +u8 InitMenu(u8 a1, u8 left, u8 top, u8 numChoices, u8 cursorPos, u8 a6) +{ +    s32 pos; + +    if (a6) +        sub_8072D18(a1, a6); + +    gMenu.left = left - 1; +    gMenu.top = top; +    gMenu.minCursorPos = 0; +    gMenu.maxCursorPos = numChoices - 1; +    gMenu.menu_field_7 = 0; + +    pos = cursorPos; + +    if (pos < 0 || pos > gMenu.maxCursorPos) +        pos = 0; + +    gMenu.cursorPos = pos; +    MoveMenuCursor(0); + +    return pos; +} + +void RedrawMenuCursor(u8 a1, u8 a2) +{ +    sub_814A880((a1 + 1) * 8, 8 * a2); +} + +void unref_sub_8072DC0() +{ +    sub_814A904(); +} + +void sub_8072DCC(u8 a1) +{ +    sub_814A958(a1); +} + +void sub_8072DDC(u8 a1) +{ +    sub_8072DCC(8 * a1); +} + +void sub_8072DEC(void) +{ +    sub_814A7FC(); +} diff --git a/src/pokemon.c b/src/pokemon.c new file mode 100644 index 000000000..a2c98a71b --- /dev/null +++ b/src/pokemon.c @@ -0,0 +1,607 @@ +#include "global.h" +#include "text.h" +#include "string_util.h" +#include "pokemon.h" + +struct PokemonSubstruct0 +{ +    u16 species; +    u16 heldItem; +    u32 experience; +    u8 ppBonuses; +    u8 friendship; +}; + +struct PokemonSubstruct1 +{ +    u16 moves[4]; +    u8 pp[4]; +}; + +struct PokemonSubstruct2 +{ +    u8 hpEV; +    u8 attackEV; +    u8 defenseEV; +    u8 speedEV; +    u8 spAttackEV; +    u8 spDefenseEV; +    u8 cool; +    u8 beauty; +    u8 cute; +    u8 smart; +    u8 tough; +    u8 sheen; +}; + +struct PokemonSubstruct3 +{ +    u8 pokerus; +    u8 metLocation; + +    u16 metLevel:7; +    u16 metGame:4; +    u16 pokeball:4; +    u16 otGender:1; + +    u32 hpIV:5; +    u32 attackIV:5; +    u32 defenseIV:5; +    u32 speedIV:5; +    u32 spAttackIV:5; +    u32 spDefenseIV:5; +    u32 isEgg:1; +    u32 altAbility:1; + +    u32 coolRibbon:3; +    u32 beautyRibbon:3; +    u32 cuteRibbon:3; +    u32 smartRibbon:3; +    u32 toughRibbon:3; +    u32 championRibbon:1; +    u32 winningRibbon:1; +    u32 victoryRibbon:1; +    u32 artistRibbon:1; +    u32 effortRibbon:1; +    u32 giftRibbon1:1; +    u32 giftRibbon2:1; +    u32 giftRibbon3:1; +    u32 giftRibbon4:1; +    u32 giftRibbon5:1; +    u32 giftRibbon6:1; +    u32 giftRibbon7:1; +    u32 fatefulEncounter:5; // unused in Ruby/Sapphire, but the high bit must be set for Mew/Deoxys to obey in FR/LG/Emerald +}; + +union PokemonSubstruct +{ +    struct PokemonSubstruct0 type0; +    struct PokemonSubstruct1 type1; +    struct PokemonSubstruct2 type2; +    struct PokemonSubstruct3 type3; +}; + +struct BoxPokemon +{ +    u32 personality; +    u32 otId; +    u8 nickname[10]; +    u8 language; +    u8 isBadEgg:1; +    u8 sanity2:1; +    u8 sanity3:1; +    u8 unused:5; +    u8 otName[7]; +    u8 markings; +    u16 checksum; +    u16 unknown; + +    union +    { +        u32 raw[12]; +        union PokemonSubstruct substructs[4]; +    } secure; +}; + +struct Pokemon +{ +    struct BoxPokemon box; +    u32 status; +    u8 level; +    u8 pokerus; +    u16 hp; +    u16 maxHP; +    u16 attack; +    u16 defense; +    u16 speed; +    u16 spAttack; +    u16 spDefense; +}; + +void ZeroPokemonBoxData(struct BoxPokemon *mon); + +u16 pokemon_calc_checksum(struct Pokemon *mon); + +void EncryptMon(struct Pokemon *mon); +void DecryptMon(struct Pokemon *mon); +union PokemonSubstruct *GetSubstruct(struct Pokemon *mon, u32 personality, u8 substructType); +u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data); +u32 GetMonBoxData(struct Pokemon *mon, s32 field, u8 *data); + +extern u8 gBadEggNickname[]; +extern u8 gEggNickname[]; +extern u32 gBitTable[]; + +/* +void ZeroPokemonBoxData(struct BoxPokemon *mon) +{ +    u8 *raw = (u8 *)mon; +    u32 i; +    for (i = 0; i < sizeof(struct BoxPokemon); i++) +        raw[i] = 0; +} +*/ + +void EncryptMon(struct Pokemon *mon) +{ +    u32 i; +    for (i = 0; i < 12; i++) +    { +        mon->box.secure.raw[i] ^= mon->box.personality; +        mon->box.secure.raw[i] ^= mon->box.otId; +    } +} + +void DecryptMon(struct Pokemon *mon) +{ +    u32 i; +    for (i = 0; i < 12; i++) +    { +        mon->box.secure.raw[i] ^= mon->box.otId; +        mon->box.secure.raw[i] ^= mon->box.personality; +    } +} + +#define SUBSTRUCT_CASE(n, v1, v2, v3, v4)  \ +case n:                                    \ +    switch (substructType)                 \ +    {                                      \ +    case 0:                                \ +        substruct = &substructs ## n [v1]; \ +        break;                             \ +    case 1:                                \ +        substruct = &substructs ## n [v2]; \ +        break;                             \ +    case 2:                                \ +        substruct = &substructs ## n [v3]; \ +        break;                             \ +    case 3:                                \ +        substruct = &substructs ## n [v4]; \ +        break;                             \ +    }                                      \ +    break; + +union PokemonSubstruct *GetSubstruct(struct Pokemon *mon, u32 personality, u8 substructType) +{ +    union PokemonSubstruct *substruct = NULL; + +    union PokemonSubstruct *substructs0 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs1 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs2 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs3 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs4 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs5 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs6 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs7 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs8 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs9 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs10 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs11 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs12 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs13 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs14 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs15 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs16 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs17 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs18 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs19 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs20 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs21 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs22 = mon->box.secure.substructs; +    union PokemonSubstruct *substructs23 = mon->box.secure.substructs; + +    switch (personality % 24) +    { +    SUBSTRUCT_CASE( 0,0,1,2,3) +    SUBSTRUCT_CASE( 1,0,1,3,2) +    SUBSTRUCT_CASE( 2,0,2,1,3) +    SUBSTRUCT_CASE( 3,0,3,1,2) +    SUBSTRUCT_CASE( 4,0,2,3,1) +    SUBSTRUCT_CASE( 5,0,3,2,1) +    SUBSTRUCT_CASE( 6,1,0,2,3) +    SUBSTRUCT_CASE( 7,1,0,3,2) +    SUBSTRUCT_CASE( 8,2,0,1,3) +    SUBSTRUCT_CASE( 9,3,0,1,2) +    SUBSTRUCT_CASE(10,2,0,3,1) +    SUBSTRUCT_CASE(11,3,0,2,1) +    SUBSTRUCT_CASE(12,1,2,0,3) +    SUBSTRUCT_CASE(13,1,3,0,2) +    SUBSTRUCT_CASE(14,2,1,0,3) +    SUBSTRUCT_CASE(15,3,1,0,2) +    SUBSTRUCT_CASE(16,2,3,0,1) +    SUBSTRUCT_CASE(17,3,2,0,1) +    SUBSTRUCT_CASE(18,1,2,3,0) +    SUBSTRUCT_CASE(19,1,3,2,0) +    SUBSTRUCT_CASE(20,2,1,3,0) +    SUBSTRUCT_CASE(21,3,1,2,0) +    SUBSTRUCT_CASE(22,2,3,1,0) +    SUBSTRUCT_CASE(23,3,2,1,0) +    } + +    return substruct; +} + +u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data) +{ +    switch (field) +    { +    case MON_DATA_STATUS: +        return mon->status; +    case MON_DATA_LEVEL: +        return mon->level; +    case MON_DATA_HP: +        return mon->hp; +    case MON_DATA_MAX_HP: +        return mon->maxHP; +    case MON_DATA_ATK: +        return mon->attack; +    case MON_DATA_DEF: +        return mon->defense; +    case MON_DATA_SPD: +        return mon->speed; +    case MON_DATA_SPATK: +        return mon->spAttack; +    case MON_DATA_SPDEF: +        return mon->spDefense; +    case MON_DATA_64: +        return mon->pokerus; +    default: +        return GetMonBoxData(mon, field, data); +    } +} + +u32 GetMonBoxData(struct Pokemon *mon, s32 field, u8 *data) +{ +    u32 retVal = 0; +    struct PokemonSubstruct0 *substruct0 = NULL; +    struct PokemonSubstruct1 *substruct1 = NULL; +    struct PokemonSubstruct2 *substruct2 = NULL; +    struct PokemonSubstruct3 *substruct3 = NULL; + +    if (field > MON_DATA_10) +    { +        substruct0 = &(GetSubstruct(mon, mon->box.personality, 0)->type0); +        substruct1 = &(GetSubstruct(mon, mon->box.personality, 1)->type1); +        substruct2 = &(GetSubstruct(mon, mon->box.personality, 2)->type2); +        substruct3 = &(GetSubstruct(mon, mon->box.personality, 3)->type3); + +        DecryptMon(mon); + +        if (pokemon_calc_checksum(mon) != mon->box.checksum) +        { +            mon->box.isBadEgg = 1; +            mon->box.sanity3 = 1; +            substruct3->isEgg = 1; +        } +    } + +    switch (field) +    { +        case MON_DATA_PERSONALITY: +            retVal = mon->box.personality; +            break; +        case MON_DATA_OT_ID: +            retVal = mon->box.otId; +            break; +        case MON_DATA_NICKNAME: +        { +            if (mon->box.isBadEgg) +            { +                StringCopy(data, gBadEggNickname); +                retVal = StringLength(data); +            } +            else if (mon->box.sanity3) +            { +                StringCopy(data, gEggNickname); +                retVal = StringLength(data); +            } +            else +            { +                retVal = 0; + +                while (retVal < 10 && mon->box.nickname[retVal] != EOS) +                { +                    data[retVal] = mon->box.nickname[retVal]; +                    retVal++; +                } + +                data[retVal] = EOS; +                ConvertInternationalString(data, mon->box.language); +                retVal = StringLength(data); +            } +            break; +        } +        case MON_DATA_LANGUAGE: +            retVal = mon->box.language; +            break; +        case MON_DATA_SANITY_BIT1: +            retVal = mon->box.isBadEgg; +            break; +        case MON_DATA_SANITY_BIT2: +            retVal = mon->box.sanity2; +            break; +        case MON_DATA_SANITY_BIT3: +            retVal = mon->box.sanity3; +            break; +        case MON_DATA_OT_NAME: +        { +            retVal = 0; + +            while (retVal < 7 && mon->box.otName[retVal] != EOS) +            { +                data[retVal] = mon->box.otName[retVal]; +                retVal++; +            } + +            data[retVal] = EOS; +            break; +        } +        case MON_DATA_MARKINGS: +            retVal = mon->box.markings; +            break; +        case MON_DATA_CHECKSUM: +            retVal = mon->box.checksum; +            break; +        case MON_DATA_10: +            retVal = mon->box.unknown; +            break; +        case MON_DATA_SPECIES: +            retVal = mon->box.isBadEgg ? 412 : substruct0->species; +            break; +        case MON_DATA_HELD_ITEM: +            retVal = substruct0->heldItem; +            break; +        case MON_DATA_EXP: +            retVal = substruct0->experience; +            break; +        case MON_DATA_PP_BONUSES: +            retVal = substruct0->ppBonuses; +            break; +        case MON_DATA_FRIENDSHIP: +            retVal = substruct0->friendship; +            break; +        case MON_DATA_MOVE1: +        case MON_DATA_MOVE2: +        case MON_DATA_MOVE3: +        case MON_DATA_MOVE4: +            retVal = substruct1->moves[field - MON_DATA_MOVE1]; +            break; +        case MON_DATA_PP1: +        case MON_DATA_PP2: +        case MON_DATA_PP3: +        case MON_DATA_PP4: +            retVal = substruct1->pp[field - MON_DATA_PP1]; +            break; +        case MON_DATA_HP_EV: +            retVal = substruct2->hpEV; +            break; +        case MON_DATA_ATK_EV: +            retVal = substruct2->attackEV; +            break; +        case MON_DATA_DEF_EV: +            retVal = substruct2->defenseEV; +            break; +        case MON_DATA_SPD_EV: +            retVal = substruct2->speedEV; +            break; +        case MON_DATA_SPATK_EV: +            retVal = substruct2->spAttackEV; +            break; +        case MON_DATA_SPDEF_EV: +            retVal = substruct2->spDefenseEV; +            break; +        case MON_DATA_COOL: +            retVal = substruct2->cool; +            break; +        case MON_DATA_BEAUTY: +            retVal = substruct2->beauty; +            break; +        case MON_DATA_CUTE: +            retVal = substruct2->cute; +            break; +        case MON_DATA_SMART: +            retVal = substruct2->smart; +            break; +        case MON_DATA_TOUGH: +            retVal = substruct2->tough; +            break; +        case MON_DATA_SHEEN: +            retVal = substruct2->sheen; +            break; +        case MON_DATA_POKERUS: +            retVal = substruct3->pokerus; +            break; +        case MON_DATA_MET_LOCATION: +            retVal = substruct3->metLocation; +            break; +        case MON_DATA_MET_LEVEL: +            retVal = substruct3->metLevel; +            break; +        case MON_DATA_MET_GAME: +            retVal = substruct3->metGame; +            break; +        case MON_DATA_POKEBALL: +            retVal = substruct3->pokeball; +            break; +        case MON_DATA_OT_GENDER: +            retVal = substruct3->otGender; +            break; +        case MON_DATA_HP_IV: +            retVal = substruct3->hpIV; +            break; +        case MON_DATA_ATK_IV: +            retVal = substruct3->attackIV; +            break; +        case MON_DATA_DEF_IV: +            retVal = substruct3->defenseIV; +            break; +        case MON_DATA_SPD_IV: +            retVal = substruct3->speedIV; +            break; +        case MON_DATA_SPATK_IV: +            retVal = substruct3->spAttackIV; +            break; +        case MON_DATA_SPDEF_IV: +            retVal = substruct3->spDefenseIV; +            break; +        case MON_DATA_IS_EGG: +            retVal = substruct3->isEgg; +            break; +        case MON_DATA_ALT_ABILITY: +            retVal = substruct3->altAbility; +            break; +        case MON_DATA_COOL_RIBBON: +            retVal = substruct3->coolRibbon; +            break; +        case MON_DATA_BEAUTY_RIBBON: +            retVal = substruct3->beautyRibbon; +            break; +        case MON_DATA_CUTE_RIBBON: +            retVal = substruct3->cuteRibbon; +            break; +        case MON_DATA_SMART_RIBBON: +            retVal = substruct3->smartRibbon; +            break; +        case MON_DATA_TOUGH_RIBBON: +            retVal = substruct3->toughRibbon; +            break; +        case MON_DATA_CHAMPION_RIBBON: +            retVal = substruct3->championRibbon; +            break; +        case MON_DATA_WINNING_RIBBON: +            retVal = substruct3->winningRibbon; +            break; +        case MON_DATA_VICTORY_RIBBON: +            retVal = substruct3->victoryRibbon; +            break; +        case MON_DATA_ARTIST_RIBBON: +            retVal = substruct3->artistRibbon; +            break; +        case MON_DATA_EFFORT_RIBBON: +            retVal = substruct3->effortRibbon; +            break; +        case MON_DATA_GIFT_RIBBON_1: +            retVal = substruct3->giftRibbon1; +            break; +        case MON_DATA_GIFT_RIBBON_2: +            retVal = substruct3->giftRibbon2; +            break; +        case MON_DATA_GIFT_RIBBON_3: +            retVal = substruct3->giftRibbon3; +            break; +        case MON_DATA_GIFT_RIBBON_4: +            retVal = substruct3->giftRibbon4; +            break; +        case MON_DATA_GIFT_RIBBON_5: +            retVal = substruct3->giftRibbon5; +            break; +        case MON_DATA_GIFT_RIBBON_6: +            retVal = substruct3->giftRibbon6; +            break; +        case MON_DATA_GIFT_RIBBON_7: +            retVal = substruct3->giftRibbon7; +            break; +        case MON_DATA_FATEFUL_ENCOUNTER: +            retVal = substruct3->fatefulEncounter; +            break; +        case MON_DATA_SPECIES2: +            retVal = substruct0->species; +            if (substruct0->species && (substruct3->isEgg || mon->box.isBadEgg)) +                retVal = 412; +            break; +        case MON_DATA_IVS: +            retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) | (substruct3->speedIV << 15) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25); +            break; +        case MON_DATA_KNOWN_MOVES: +            if (substruct0->species && !substruct3->isEgg) +            { +                u16 *moves = (u16 *)data; +                s32 i = 0; + +                while (moves[i] != 355) +                { +                    u16 move = moves[i]; +                    if (substruct1->moves[0] == move +                        || substruct1->moves[1] == move +                        || substruct1->moves[2] == move +                        || substruct1->moves[3] == move) +                        retVal |= gBitTable[i]; +                    i++; +                } +            } +            break; +        case MON_DATA_RIBBON_COUNT: +            retVal = 0; +            if (substruct0->species && !substruct3->isEgg) +            { +                retVal += substruct3->coolRibbon; +                retVal += substruct3->beautyRibbon; +                retVal += substruct3->cuteRibbon; +                retVal += substruct3->smartRibbon; +                retVal += substruct3->toughRibbon; +                retVal += substruct3->championRibbon; +                retVal += substruct3->winningRibbon; +                retVal += substruct3->victoryRibbon; +                retVal += substruct3->artistRibbon; +                retVal += substruct3->effortRibbon; +                retVal += substruct3->giftRibbon1; +                retVal += substruct3->giftRibbon2; +                retVal += substruct3->giftRibbon3; +                retVal += substruct3->giftRibbon4; +                retVal += substruct3->giftRibbon5; +                retVal += substruct3->giftRibbon6; +                retVal += substruct3->giftRibbon7; +            } +            break; +        case MON_DATA_RIBBONS: +            retVal = 0; +            if (substruct0->species && !substruct3->isEgg) +            { +                retVal = substruct3->championRibbon +                    | (substruct3->coolRibbon << 1) +                    | (substruct3->beautyRibbon << 4) +                    | (substruct3->cuteRibbon << 7) +                    | (substruct3->smartRibbon << 10) +                    | (substruct3->toughRibbon << 13) +                    | (substruct3->winningRibbon << 16) +                    | (substruct3->victoryRibbon << 17) +                    | (substruct3->artistRibbon << 18) +                    | (substruct3->effortRibbon << 19) +                    | (substruct3->giftRibbon1 << 20) +                    | (substruct3->giftRibbon2 << 21) +                    | (substruct3->giftRibbon3 << 22) +                    | (substruct3->giftRibbon4 << 23) +                    | (substruct3->giftRibbon5 << 24) +                    | (substruct3->giftRibbon6 << 25) +                    | (substruct3->giftRibbon7 << 26); +            } +            break; +        default: +            break; +    } + +    if (field > MON_DATA_10) +        EncryptMon(mon); + +    return retVal; +} diff --git a/src/text.c b/src/text.c index 372d3e7e2..64a302fed 100644 --- a/src/text.c +++ b/src/text.c @@ -2523,7 +2523,7 @@ u8 sub_80037A0(struct Window *win)      return retVal;  } -u8 sub_80037C8(struct Window *win, u8 lineLength) +u32 sub_80037C8(struct Window *win, u8 lineLength)  {      u8 retVal; diff --git a/src/text_window.c b/src/text_window.c new file mode 100644 index 000000000..ab14fe1fb --- /dev/null +++ b/src/text_window.c @@ -0,0 +1,196 @@ +#include "global.h" +#include "main.h" +#include "text.h" +#include "text_window.h" + +u16 SetTextWindowBaseTileNum(u16); +void LoadTextWindowGraphics(struct Window *); +void LoadTextWindowGraphics_OverridePalSlot(struct Window *, u8); +void LoadTextWindowGraphics_OverrideFrameType(struct Window *, u8); +void DrawTextWindow(struct Window *win, u8 left, u8 top, u8 right, u8 bottom); +const struct FrameGraphics *GetTextWindowFrameGraphics(u8 frameType); +static void LoadTextWindowTiles(u8, void *); +static void LoadTextWindowPalette(u8, u8); +static void DrawTextWindowInternal(u16 *dest, u16 baseTileNum, u8 left, u8 top, u8 right, u8 bottom); +u16 SetMessageBoxBaseTileNum(u16); +void unref_sub_80651DC(struct Window *, u8 *); +void DisplayMessageBox(struct Window *); +static u16 GetMessageBoxTilemapEntry(u16 tilemapEntry, u8 x, u8 y, u8 width, u8 height); +static void DrawMessageBox(struct Window *win, u8 left, u8 top, u8 width, u8 height); +void DrawStandardMessageBox(struct Window *win); +void LoadMessageBoxTiles(struct Window *win); +void sub_806536C(struct Window *win); + +static u16 sTextWindowBaseTileNum; +static u16 sMessageBoxBaseTileNum; + +struct FrameGraphics +{ +    u8 *tiles; +    u16 *palette; +}; + +extern const struct FrameGraphics gUnknown_083761F0[20]; + +extern const u16 gMessageBoxTilemap[5][7]; +extern const u8 gMessageBox_Gfx[]; + +u16 SetTextWindowBaseTileNum(u16 baseTileNum) +{ +    sTextWindowBaseTileNum = baseTileNum; +    return baseTileNum + 9; +} + +void LoadTextWindowGraphics(struct Window *win) +{ +    u8 *tileData = win->config->tileData + TILE_SIZE_4BPP * sTextWindowBaseTileNum; +    LoadTextWindowTiles(gSaveBlock2.optionsWindowFrameType, tileData); +    LoadTextWindowPalette(gSaveBlock2.optionsWindowFrameType, 0xE); +} + +void LoadTextWindowGraphics_OverridePalSlot(struct Window *win, u8 palSlot) +{ +    u8 *tileData = win->config->tileData + TILE_SIZE_4BPP * sTextWindowBaseTileNum; +    LoadTextWindowTiles(gSaveBlock2.optionsWindowFrameType, tileData); +    LoadTextWindowPalette(gSaveBlock2.optionsWindowFrameType, palSlot); +} + +void LoadTextWindowGraphics_OverrideFrameType(struct Window *win, u8 frameType) +{ +    u8 *tileData = win->config->tileData + TILE_SIZE_4BPP * sTextWindowBaseTileNum; +    LoadTextWindowTiles(frameType, tileData); +    LoadTextWindowPalette(frameType, 0xE); +} + +void DrawTextWindow(struct Window *win, u8 left, u8 top, u8 right, u8 bottom) +{ +    DrawTextWindowInternal(win->config->tilemap, sTextWindowBaseTileNum, left, top, right, bottom); +} + +const struct FrameGraphics *GetTextWindowFrameGraphics(u8 frameType) +{ +    if (frameType > 19) +        return &gUnknown_083761F0[0]; +    else +        return &gUnknown_083761F0[frameType]; +} + +static void LoadTextWindowTiles(u8 frameType, void *dest) +{ +    const struct FrameGraphics *frameGraphics = GetTextWindowFrameGraphics(frameType); +    CpuFastCopy(frameGraphics->tiles, dest, 9 * TILE_SIZE_4BPP); +} + +static void LoadTextWindowPalette(u8 frameType, u8 palSlot) +{ +    const struct FrameGraphics *frameGraphics = GetTextWindowFrameGraphics(frameType); +    LoadPalette(frameGraphics->palette, 16 * palSlot, 0x20); +} + +static void DrawTextWindowInternal(u16 *dest, u16 baseTileNum, u8 left, u8 top, u8 right, u8 bottom) +{ +    u8 x, y; +    u8 startX, endX; +    u8 startY, endY; + +    startX = (left < right) ? left : right; +    endX = (right > left) ? right : left; + +    startY = (top < bottom) ? top : bottom; +    endY = (bottom > top) ? bottom : top; + +    dest[32 * startY + startX] = baseTileNum | 0xE000; + +    for (x = startX + 1; x < endX; x++) +        dest[32 * startY + x] = (baseTileNum + 1) | 0xE000; + +    dest[32 * startY + endX] = (baseTileNum + 2) | 0xE000; + +    for (y = startY + 1; y < endY; y++) +    { +        dest[32 * y + startX] = (baseTileNum + 3) | 0xE000; + +        for (x = startX + 1; x < endX; x++) +            dest[32 * y + x] = (baseTileNum + 4) | 0xE000; + +        dest[32 * y + endX] = (baseTileNum + 5) | 0xE000; +    } + +    dest[32 * endY + startX] = (baseTileNum + 6) | 0xE000; + +    for (x = startX + 1; x < endX; x++) +        dest[32 * endY + x] = (baseTileNum + 7) | 0xE000; + +    dest[32 * endY + endX] = (baseTileNum + 8) | 0xE000; +} + +u16 SetMessageBoxBaseTileNum(u16 baseTileNum) +{ +    sMessageBoxBaseTileNum = baseTileNum; +    return baseTileNum + 14; +} + +void unref_sub_80651DC(struct Window *win, u8 *text) +{ +    sub_8002EB0(win, text, sMessageBoxBaseTileNum + 14, 2, 15); +} + +void DisplayMessageBox(struct Window *win) +{ +    LoadMessageBoxTiles(win); +    DrawStandardMessageBox(win); +} + +static u16 GetMessageBoxTilemapEntry(u16 baseTilemapEntry, u8 x, u8 y, u8 width, u8 height) +{ +    u16 tilemapEntry = 9; + +    if (y >= height) +        y = y - height + 3; +    else if (y > 1) +        y = 2; + +    if (x >= width + 2) +        x = x - (width + 2) + 4; +    else if (x > 2) +        x = 3; + +    if (x <= 6 && y <= 4) +        tilemapEntry = gMessageBoxTilemap[y][x]; + +    tilemapEntry += baseTilemapEntry; + +    return tilemapEntry; +} + +static void DrawMessageBox(struct Window *win, u8 left, u8 top, u8 width, u8 height) +{ +    u8 i, j; +    u16 tilemapEntry = (win->paletteNum << 12) | sMessageBoxBaseTileNum; +    u16 *tilemap = win->config->tilemap; + +    for (i = 0; i < height + 2; i++) +        for (j = 0; j < width + 6; j++) +            tilemap[(left + j) + 32 * (top + i)] = (win->paletteNum << 12) | GetMessageBoxTilemapEntry(tilemapEntry, j, i, width, height); +} + +void DrawStandardMessageBox(struct Window *win) +{ +    DrawMessageBox(win, 0, 14, 26, 4); +} + +void LoadMessageBoxTiles(struct Window *win) +{ +    u8 *tileData = win->config->tileData; +    CpuFastCopy(gMessageBox_Gfx, tileData + 32 * sMessageBoxBaseTileNum, 14 * TILE_SIZE_4BPP); +} + +void sub_806536C(struct Window *win) +{ +    u8 i; +    u16 *tilemap = win->config->tilemap + 0x1C0; +    u16 tilemapEntry = win->paletteNum << 12; + +    for (i = 0; i < 0xC0; i++) +        tilemap[i] = tilemapEntry; +} | 
