diff options
Diffstat (limited to 'src/option_menu.c')
-rw-r--r-- | src/option_menu.c | 662 |
1 files changed, 662 insertions, 0 deletions
diff --git a/src/option_menu.c b/src/option_menu.c new file mode 100644 index 000000000..7f92756ab --- /dev/null +++ b/src/option_menu.c @@ -0,0 +1,662 @@ +#include "global.h" +#include "option_menu.h" +#include "main.h" +#include "menu.h" +#include "unknown_task.h" +#include "palette.h" +#include "sprite.h" +#include "task.h" +#include "bg.h" +#include "gpu_regs.h" +#include "window.h" +#include "text.h" +#include "text_window.h" +#include "international_string_util.h" +#include "strings.h" + +extern void SetPokemonCryStereo(u32 val); + +// Task data +enum +{ + TD_MENUSELECTION, + TD_TEXTSPEED, + TD_BATTLESCENE, + TD_BATTLESTYLE, + TD_SOUND, + TD_BUTTONMODE, + TD_FRAMETYPE, +}; + +// Menu items +enum +{ + MENUITEM_TEXTSPEED, + MENUITEM_BATTLESCENE, + MENUITEM_BATTLESTYLE, + MENUITEM_SOUND, + MENUITEM_BUTTONMODE, + MENUITEM_FRAMETYPE, + MENUITEM_CANCEL, + MENUITEM_COUNT, +}; + +// Window Ids +enum +{ + WIN_TEXT_OPTION, + WIN_OPTIONS +}; + +// this file's functions +static void Task_OptionMenuFadeIn(u8 taskId); +static void Task_OptionMenuProcessInput(u8 taskId); +static void Task_OptionMenuSave(u8 taskId); +static void Task_OptionMenuFadeOut(u8 taskId); +static void HighlightOptionMenuItem(u8 selection); +static u8 TextSpeed_ProcessInput(u8 selection); +static void TextSpeed_DrawChoices(u8 selection); +static u8 BattleScene_ProcessInput(u8 selection); +static void BattleScene_DrawChoices(u8 selection); +static u8 BattleStyle_ProcessInput(u8 selection); +static void BattleStyle_DrawChoices(u8 selection); +static u8 Sound_ProcessInput(u8 selection); +static void Sound_DrawChoices(u8 selection); +static u8 FrameType_ProcessInput(u8 selection); +static void FrameType_DrawChoices(u8 selection); +static u8 ButtonMode_ProcessInput(u8 selection); +static void ButtonMode_DrawChoices(u8 selection); +static void DrawTextOption(void); +static void DrawOptionMenuTexts(void); +static void sub_80BB154(void); + +// EWRAM vars +EWRAM_DATA static bool8 sArrowPressed = FALSE; + +// const rom data +static const u16 sUnknown_0855C604[] = INCBIN_U16("graphics/misc/option_menu_text.gbapal"); +// note: this is only used in the Japanese release +static const u8 sEqualSignGfx[] = INCBIN_U8("graphics/misc/option_menu_equals_sign.4bpp"); + +static const u8 *const sOptionMenuItemsNames[MENUITEM_COUNT] = +{ + gText_TextSpeed, + gText_BattleScene, + gText_BattleStyle, + gText_Sound, + gText_ButtonMode, + gText_Frame, + gText_OptionMenuCancel, +}; + +static const struct WindowTemplate sOptionMenuWinTemplates[] = +{ + {1, 2, 1, 0x1A, 2, 1, 2}, + {0, 2, 5, 0x1A, 0xE, 1, 0x36}, + DUMMY_WIN_TEMPLATE +}; + +static const struct BgTemplate sOptionMenuBgTemplates[] = +{ + { + .bg = 1, + .charBaseIndex = 1, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + }, + { + .bg = 0, + .charBaseIndex = 1, + .mapBaseIndex = 31, + .screenSize = 0, + .paletteMode = 0, + .priority = 1, + .baseTile = 0 + } +}; + +static const u16 sUnknown_0855C6A0[] = {0x7E51}; + +// code +static void MainCB2(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void VBlankCB(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +void CB2_InitOptionMenu(void) +{ + switch (gMain.state) + { + default: + case 0: + SetVBlankCallback(NULL); + gMain.state++; + break; + case 1: + { + u8 *addr; + u32 size; + + addr = (u8 *)VRAM; + size = 0x18000; + while (1) + { + DmaFill16(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill16(3, 0, addr, size); + break; + } + } + DmaClear32(3, OAM, OAM_SIZE); + DmaClear16(3, PLTT, PLTT_SIZE); + SetGpuReg(REG_OFFSET_DISPCNT, 0); + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, sOptionMenuBgTemplates, ARRAY_COUNT(sOptionMenuBgTemplates)); + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + ChangeBgX(1, 0, 0); + ChangeBgY(1, 0, 0); + ChangeBgX(2, 0, 0); + ChangeBgY(2, 0, 0); + ChangeBgX(3, 0, 0); + ChangeBgY(3, 0, 0); + InitWindows(sOptionMenuWinTemplates); + DeactivateAllTextPrinters(); + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN0V, 0); + SetGpuReg(REG_OFFSET_WININ, 1); + SetGpuReg(REG_OFFSET_WINOUT, 35); + SetGpuReg(REG_OFFSET_BLDCNT, 193); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 4); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); + ShowBg(0); + ShowBg(1); + gMain.state++; + } + break; + case 2: + ResetPaletteFade(); + ScanlineEffect_Stop(); + ResetTasks(); + ResetSpriteData(); + gMain.state++; + break; + case 3: + LoadBgTiles(1, GetWindowFrameTilesPal(gSaveBlock2Ptr->optionsWindowFrameType)->tiles, 0x120, 0x1A2); + gMain.state++; + break; + case 4: + LoadPalette(sUnknown_0855C6A0, 0, sizeof(sUnknown_0855C6A0)); + LoadPalette(GetWindowFrameTilesPal(gSaveBlock2Ptr->optionsWindowFrameType)->pal, 0x70, 0x20); + gMain.state++; + break; + case 5: + LoadPalette(sUnknown_0855C604, 0x10, sizeof(sUnknown_0855C604)); + gMain.state++; + break; + case 6: + PutWindowTilemap(0); + DrawTextOption(); + gMain.state++; + break; + case 7: + gMain.state++; + break; + case 8: + PutWindowTilemap(1); + DrawOptionMenuTexts(); + gMain.state++; + case 9: + sub_80BB154(); + gMain.state++; + break; + case 10: + { + u8 taskId = CreateTask(Task_OptionMenuFadeIn, 0); + + gTasks[taskId].data[TD_MENUSELECTION] = 0; + gTasks[taskId].data[TD_TEXTSPEED] = gSaveBlock2Ptr->optionsTextSpeed; + gTasks[taskId].data[TD_BATTLESCENE] = gSaveBlock2Ptr->optionsBattleSceneOff; + gTasks[taskId].data[TD_BATTLESTYLE] = gSaveBlock2Ptr->optionsBattleStyle; + gTasks[taskId].data[TD_SOUND] = gSaveBlock2Ptr->optionsSound; + gTasks[taskId].data[TD_BUTTONMODE] = gSaveBlock2Ptr->optionsButtonMode; + gTasks[taskId].data[TD_FRAMETYPE] = gSaveBlock2Ptr->optionsWindowFrameType; + + TextSpeed_DrawChoices(gTasks[taskId].data[TD_TEXTSPEED]); + BattleScene_DrawChoices(gTasks[taskId].data[TD_BATTLESCENE]); + BattleStyle_DrawChoices(gTasks[taskId].data[TD_BATTLESTYLE]); + Sound_DrawChoices(gTasks[taskId].data[TD_SOUND]); + ButtonMode_DrawChoices(gTasks[taskId].data[TD_BUTTONMODE]); + FrameType_DrawChoices(gTasks[taskId].data[TD_FRAMETYPE]); + HighlightOptionMenuItem(gTasks[taskId].data[TD_MENUSELECTION]); + + CopyWindowToVram(WIN_OPTIONS, 3); + gMain.state++; + break; + } + case 11: + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); + SetVBlankCallback(VBlankCB); + SetMainCallback2(MainCB2); + return; + } +} + +static void Task_OptionMenuFadeIn(u8 taskId) +{ + if (!gPaletteFade.active) + gTasks[taskId].func = Task_OptionMenuProcessInput; +} + +static void Task_OptionMenuProcessInput(u8 taskId) +{ + if (gMain.newKeys & A_BUTTON) + { + if (gTasks[taskId].data[TD_MENUSELECTION] == MENUITEM_CANCEL) + gTasks[taskId].func = Task_OptionMenuSave; + } + else if (gMain.newKeys & B_BUTTON) + { + gTasks[taskId].func = Task_OptionMenuSave; + } + else if (gMain.newKeys & DPAD_UP) + { + if (gTasks[taskId].data[TD_MENUSELECTION] > 0) + gTasks[taskId].data[TD_MENUSELECTION]--; + else + gTasks[taskId].data[TD_MENUSELECTION] = 6; + HighlightOptionMenuItem(gTasks[taskId].data[TD_MENUSELECTION]); + } + else if (gMain.newKeys & DPAD_DOWN) + { + if (gTasks[taskId].data[TD_MENUSELECTION] <= 5) + gTasks[taskId].data[TD_MENUSELECTION]++; + else + gTasks[taskId].data[TD_MENUSELECTION] = 0; + HighlightOptionMenuItem(gTasks[taskId].data[TD_MENUSELECTION]); + } + else + { + u8 previousOption; + + switch (gTasks[taskId].data[TD_MENUSELECTION]) + { + case MENUITEM_TEXTSPEED: + previousOption = gTasks[taskId].data[TD_TEXTSPEED]; + gTasks[taskId].data[TD_TEXTSPEED] = TextSpeed_ProcessInput(gTasks[taskId].data[TD_TEXTSPEED]); + + if (previousOption != gTasks[taskId].data[TD_TEXTSPEED]) + TextSpeed_DrawChoices(gTasks[taskId].data[TD_TEXTSPEED]); + break; + case MENUITEM_BATTLESCENE: + previousOption = gTasks[taskId].data[TD_BATTLESCENE]; + gTasks[taskId].data[TD_BATTLESCENE] = BattleScene_ProcessInput(gTasks[taskId].data[TD_BATTLESCENE]); + + if (previousOption != gTasks[taskId].data[TD_BATTLESCENE]) + BattleScene_DrawChoices(gTasks[taskId].data[TD_BATTLESCENE]); + break; + case MENUITEM_BATTLESTYLE: + previousOption = gTasks[taskId].data[TD_BATTLESTYLE]; + gTasks[taskId].data[TD_BATTLESTYLE] = BattleStyle_ProcessInput(gTasks[taskId].data[TD_BATTLESTYLE]); + + if (previousOption != gTasks[taskId].data[TD_BATTLESTYLE]) + BattleStyle_DrawChoices(gTasks[taskId].data[TD_BATTLESTYLE]); + break; + case MENUITEM_SOUND: + previousOption = gTasks[taskId].data[TD_SOUND]; + gTasks[taskId].data[TD_SOUND] = Sound_ProcessInput(gTasks[taskId].data[TD_SOUND]); + + if (previousOption != gTasks[taskId].data[TD_SOUND]) + Sound_DrawChoices(gTasks[taskId].data[TD_SOUND]); + break; + case MENUITEM_BUTTONMODE: + previousOption = gTasks[taskId].data[TD_BUTTONMODE]; + gTasks[taskId].data[TD_BUTTONMODE] = ButtonMode_ProcessInput(gTasks[taskId].data[TD_BUTTONMODE]); + + if (previousOption != gTasks[taskId].data[TD_BUTTONMODE]) + ButtonMode_DrawChoices(gTasks[taskId].data[TD_BUTTONMODE]); + break; + case MENUITEM_FRAMETYPE: + previousOption = gTasks[taskId].data[TD_FRAMETYPE]; + gTasks[taskId].data[TD_FRAMETYPE] = FrameType_ProcessInput(gTasks[taskId].data[TD_FRAMETYPE]); + + if (previousOption != gTasks[taskId].data[TD_FRAMETYPE]) + FrameType_DrawChoices(gTasks[taskId].data[TD_FRAMETYPE]); + break; + default: + return; + } + + if (sArrowPressed) + { + sArrowPressed = FALSE; + CopyWindowToVram(WIN_OPTIONS, 2); + } + } +} + +static void Task_OptionMenuSave(u8 taskId) +{ + gSaveBlock2Ptr->optionsTextSpeed = gTasks[taskId].data[TD_TEXTSPEED]; + gSaveBlock2Ptr->optionsBattleSceneOff = gTasks[taskId].data[TD_BATTLESCENE]; + gSaveBlock2Ptr->optionsBattleStyle = gTasks[taskId].data[TD_BATTLESTYLE]; + gSaveBlock2Ptr->optionsSound = gTasks[taskId].data[TD_SOUND]; + gSaveBlock2Ptr->optionsButtonMode = gTasks[taskId].data[TD_BUTTONMODE]; + gSaveBlock2Ptr->optionsWindowFrameType = gTasks[taskId].data[TD_FRAMETYPE]; + + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + gTasks[taskId].func = Task_OptionMenuFadeOut; +} + +static void Task_OptionMenuFadeOut(u8 taskId) +{ + if (!gPaletteFade.active) + { + DestroyTask(taskId); + FreeAllWindowBuffers(); + SetMainCallback2(gMain.savedCallback); + } +} + +static void HighlightOptionMenuItem(u8 index) +{ + SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(16, 224)); + SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(index * 16 + 40, index * 16 + 56)); +} + +static void DrawOptionMenuChoice(const u8 *text, u8 x, u8 y, u8 style) +{ + u8 dst[16]; + u16 i; + + for (i = 0; *text != EOS && i <= 14; i++) + dst[i] = *(text++); + + if (style != 0) + { + dst[2] = 4; + dst[5] = 5; + } + + dst[i] = EOS; + PrintTextOnWindow(WIN_OPTIONS, 1, dst, x, y + 1, TEXT_SPEED_FF, NULL); +} + +static u8 TextSpeed_ProcessInput(u8 selection) +{ + if (gMain.newKeys & DPAD_RIGHT) + { + if (selection <= 1) + selection++; + else + selection = 0; + + sArrowPressed = TRUE; + } + if (gMain.newKeys & DPAD_LEFT) + { + if (selection != 0) + selection--; + else + selection = 2; + + sArrowPressed = TRUE; + } + return selection; +} + +static void TextSpeed_DrawChoices(u8 selection) +{ + u8 styles[3]; + s32 widthSlow, widthMid, widthFast, xMid; + + styles[0] = 0; + styles[1] = 0; + styles[2] = 0; + styles[selection] = 1; + + DrawOptionMenuChoice(gText_TextSpeedSlow, 104, 0, styles[0]); + + widthSlow = GetStringWidth(1, gText_TextSpeedSlow, 0); + widthMid = GetStringWidth(1, gText_TextSpeedMid, 0); + widthFast = GetStringWidth(1, gText_TextSpeedFast, 0); + + widthMid -= 94; + xMid = (widthSlow - widthMid - widthFast) / 2 + 104; + DrawOptionMenuChoice(gText_TextSpeedMid, xMid, 0, styles[1]); + + DrawOptionMenuChoice(gText_TextSpeedFast, GetStringRightAlignXOffset(1, gText_TextSpeedFast, 198), 0, styles[2]); +} + +static u8 BattleScene_ProcessInput(u8 selection) +{ + if (gMain.newKeys & (DPAD_LEFT | DPAD_RIGHT)) + { + selection ^= 1; + sArrowPressed = TRUE; + } + + return selection; +} + +static void BattleScene_DrawChoices(u8 selection) +{ + u8 styles[2]; + + styles[0] = 0; + styles[1] = 0; + styles[selection] = 1; + + DrawOptionMenuChoice(gText_BattleSceneOn, 104, 16, styles[0]); + DrawOptionMenuChoice(gText_BattleSceneOff, GetStringRightAlignXOffset(1, gText_BattleSceneOff, 198), 16, styles[1]); +} + +static u8 BattleStyle_ProcessInput(u8 selection) +{ + if (gMain.newKeys & (DPAD_LEFT | DPAD_RIGHT)) + { + selection ^= 1; + sArrowPressed = TRUE; + } + + return selection; +} + +static void BattleStyle_DrawChoices(u8 selection) +{ + u8 styles[2]; + + styles[0] = 0; + styles[1] = 0; + styles[selection] = 1; + + DrawOptionMenuChoice(gText_BattleStyleShift, 104, 32, styles[0]); + DrawOptionMenuChoice(gText_BattleStyleSet, GetStringRightAlignXOffset(1, gText_BattleStyleSet, 198), 32, styles[1]); +} + +static u8 Sound_ProcessInput(u8 selection) +{ + if (gMain.newKeys & (DPAD_LEFT | DPAD_RIGHT)) + { + selection ^= 1; + SetPokemonCryStereo(selection); + sArrowPressed = TRUE; + } + + return selection; +} + +static void Sound_DrawChoices(u8 selection) +{ + u8 styles[2]; + + styles[0] = 0; + styles[1] = 0; + styles[selection] = 1; + + DrawOptionMenuChoice(gText_SoundMono, 104, 48, styles[0]); + DrawOptionMenuChoice(gText_SoundStereo, GetStringRightAlignXOffset(1, gText_SoundStereo, 198), 48, styles[1]); +} + +static u8 FrameType_ProcessInput(u8 selection) +{ + if (gMain.newKeys & DPAD_RIGHT) + { + if (selection < WINDOW_FRAMES_COUNT - 1) + selection++; + else + selection = 0; + + LoadBgTiles(1, GetWindowFrameTilesPal(selection)->tiles, 0x120, 0x1A2); + LoadPalette(GetWindowFrameTilesPal(selection)->pal, 0x70, 0x20); + sArrowPressed = TRUE; + } + if (gMain.newKeys & DPAD_LEFT) + { + if (selection != 0) + selection--; + else + selection = WINDOW_FRAMES_COUNT - 1; + + LoadBgTiles(1, GetWindowFrameTilesPal(selection)->tiles, 0x120, 0x1A2); + LoadPalette(GetWindowFrameTilesPal(selection)->pal, 0x70, 0x20); + sArrowPressed = TRUE; + } + return selection; +} + +static void FrameType_DrawChoices(u8 selection) +{ + u8 text[16]; + u8 n = selection + 1; + u16 i; + + for (i = 0; gText_FrameTypeNumber[i] != EOS && i <= 5; i++) + text[i] = gText_FrameTypeNumber[i]; + + // Convert a number to decimal string + if (n / 10 != 0) + { + text[i] = n / 10 + CHAR_0; + i++; + text[i] = n % 10 + CHAR_0; + i++; + } + else + { + text[i] = n % 10 + CHAR_0; + i++; + text[i] = 0x77; + i++; + } + + text[i] = EOS; + + DrawOptionMenuChoice(gText_FrameType, 104, 80, 0); + DrawOptionMenuChoice(text, 128, 80, 1); +} + +static u8 ButtonMode_ProcessInput(u8 selection) +{ + if (gMain.newKeys & DPAD_RIGHT) + { + if (selection <= 1) + selection++; + else + selection = 0; + + sArrowPressed = TRUE; + } + if (gMain.newKeys & DPAD_LEFT) + { + if (selection != 0) + selection--; + else + selection = 2; + + sArrowPressed = TRUE; + } + return selection; +} + +static void ButtonMode_DrawChoices(u8 selection) +{ + s32 widthNormal, widthLR, widthLA, xLR; + u8 styles[3]; + + styles[0] = 0; + styles[1] = 0; + styles[2] = 0; + styles[selection] = 1; + + DrawOptionMenuChoice(gText_ButtonTypeNormal, 104, 64, styles[0]); + + widthNormal = GetStringWidth(1, gText_ButtonTypeNormal, 0); + widthLR = GetStringWidth(1, gText_ButtonTypeLR, 0); + widthLA = GetStringWidth(1, gText_ButtonTypeLEqualsA, 0); + + widthLR -= 94; + xLR = (widthNormal - widthLR - widthLA) / 2 + 104; + DrawOptionMenuChoice(gText_ButtonTypeLR, xLR, 64, styles[1]); + + DrawOptionMenuChoice(gText_ButtonTypeLEqualsA, GetStringRightAlignXOffset(1, gText_ButtonTypeLEqualsA, 198), 64, styles[2]); +} + +static void DrawTextOption(void) +{ + FillWindowPixelBuffer(WIN_TEXT_OPTION, 0x11); + PrintTextOnWindow(WIN_TEXT_OPTION, 1, gText_Option, 8, 1, TEXT_SPEED_FF, NULL); + CopyWindowToVram(WIN_TEXT_OPTION, 3); +} + +static void DrawOptionMenuTexts(void) +{ + u8 i; + + FillWindowPixelBuffer(WIN_OPTIONS, 0x11); + for (i = 0; i < MENUITEM_COUNT; i++) + { + PrintTextOnWindow(WIN_OPTIONS, 1, sOptionMenuItemsNames[i], 8, (i * 16) + 1, TEXT_SPEED_FF, NULL); + } + CopyWindowToVram(WIN_OPTIONS, 3); +} + +static void sub_80BB154(void) +{ + // bg, tileNum, x, y, width, height, pal + FillBgTilemapBufferRect(1, 0x1A2, 1, 0, 1, 1, 7); + FillBgTilemapBufferRect(1, 0x1A3, 2, 0, 0x1B, 1, 7); + FillBgTilemapBufferRect(1, 0x1A4, 28, 0, 1, 1, 7); + FillBgTilemapBufferRect(1, 0x1A5, 1, 1, 1, 2, 7); + FillBgTilemapBufferRect(1, 0x1A7, 28, 1, 1, 2, 7); + FillBgTilemapBufferRect(1, 0x1A8, 1, 3, 1, 1, 7); + FillBgTilemapBufferRect(1, 0x1A9, 2, 3, 0x1B, 1, 7); + FillBgTilemapBufferRect(1, 0x1AA, 28, 3, 1, 1, 7); + FillBgTilemapBufferRect(1, 0x1A2, 1, 4, 1, 1, 7); + FillBgTilemapBufferRect(1, 0x1A3, 2, 4, 0x1A, 1, 7); + FillBgTilemapBufferRect(1, 0x1A4, 28, 4, 1, 1, 7); + FillBgTilemapBufferRect(1, 0x1A5, 1, 5, 1, 0x12, 7); + FillBgTilemapBufferRect(1, 0x1A7, 28, 5, 1, 0x12, 7); + FillBgTilemapBufferRect(1, 0x1A8, 1, 19, 1, 1, 7); + FillBgTilemapBufferRect(1, 0x1A9, 2, 19, 0x1A, 1, 7); + FillBgTilemapBufferRect(1, 0x1AA, 28, 19, 1, 1, 7); + + CopyBgTilemapBufferToVram(1); +} |