diff --git a/CMakeLists.txt b/CMakeLists.txt index b9ae928..0f55093 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,6 +140,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC "src/loadsave.h" "src/main.cc" "src/main.h" + "src/mainmenu.cc" + "src/mainmenu.h" "src/map_defs.h" "src/map.cc" "src/map.h" diff --git a/src/main.cc b/src/main.cc index aff1459..a016f16 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,5 @@ #include "main.h" -#include #include #include @@ -21,6 +20,7 @@ #include "input.h" #include "kb.h" #include "loadsave.h" +#include "mainmenu.h" #include "map.h" #include "mouse.h" #include "object.h" @@ -35,7 +35,6 @@ #include "sfall_config.h" #include "svga.h" #include "text_font.h" -#include "version.h" #include "window.h" #include "window_manager.h" #include "window_manager_private.h" @@ -44,35 +43,9 @@ namespace fallout { -#define MAIN_MENU_WINDOW_WIDTH 640 -#define MAIN_MENU_WINDOW_HEIGHT 480 - #define DEATH_WINDOW_WIDTH 640 #define DEATH_WINDOW_HEIGHT 480 -typedef enum MainMenuButton { - MAIN_MENU_BUTTON_INTRO, - MAIN_MENU_BUTTON_NEW_GAME, - MAIN_MENU_BUTTON_LOAD_GAME, - MAIN_MENU_BUTTON_OPTIONS, - MAIN_MENU_BUTTON_CREDITS, - MAIN_MENU_BUTTON_EXIT, - MAIN_MENU_BUTTON_COUNT, -} MainMenuButton; - -typedef enum MainMenuOption { - MAIN_MENU_INTRO, - MAIN_MENU_NEW_GAME, - MAIN_MENU_LOAD_GAME, - MAIN_MENU_SCREENSAVER, - MAIN_MENU_TIMEOUT, - MAIN_MENU_CREDITS, - MAIN_MENU_QUOTES, - MAIN_MENU_EXIT, - MAIN_MENU_SELFRUN, - MAIN_MENU_OPTIONS, -} MainMenuOption; - static bool falloutInit(int argc, char** argv); static int main_reset_system(); static void main_exit_system(); @@ -87,14 +60,6 @@ static void showDeath(); static void _main_death_voiceover_callback(); static int _mainDeathGrabTextFile(const char* fileName, char* dest); static int _mainDeathWordWrap(char* text, int width, short* beginnings, short* count); -static int mainMenuWindowInit(); -static void mainMenuWindowFree(); -static void mainMenuWindowHide(bool animate); -static void mainMenuWindowUnhide(bool animate); -static int _main_menu_is_enabled(); -static int mainMenuWindowHandleEvents(); -static int main_menu_fatal_error(); -static void main_menu_play_sound(const char* fileName); // 0x5194C8 static char _mainMap[] = "artemple.map"; @@ -124,54 +89,9 @@ static bool _main_show_death_scene = false; // 0x5194EC static bool gMainMenuScreensaverCycle = false; -// 0x5194F0 -static int gMainMenuWindow = -1; - -// 0x5194F4 -static unsigned char* gMainMenuWindowBuffer = NULL; - -// 0x519504 -static bool _in_main_menu = false; - -// 0x519508 -static bool gMainMenuWindowInitialized = false; - -// 0x51950C -static unsigned int gMainMenuScreensaverDelay = 120000; - -// 0x519510 -static const int gMainMenuButtonKeyBindings[MAIN_MENU_BUTTON_COUNT] = { - KEY_LOWERCASE_I, // intro - KEY_LOWERCASE_N, // new game - KEY_LOWERCASE_L, // load game - KEY_LOWERCASE_O, // options - KEY_LOWERCASE_C, // credits - KEY_LOWERCASE_E, // exit -}; - -// 0x519528 -static const int _return_values[MAIN_MENU_BUTTON_COUNT] = { - MAIN_MENU_INTRO, - MAIN_MENU_NEW_GAME, - MAIN_MENU_LOAD_GAME, - MAIN_MENU_OPTIONS, - MAIN_MENU_CREDITS, - MAIN_MENU_EXIT, -}; - // 0x614838 static bool _main_death_voiceover_done; -// 0x614840 -static int gMainMenuButtons[MAIN_MENU_BUTTON_COUNT]; - -// 0x614858 -static bool gMainMenuWindowHidden; - -static FrmImage _mainMenuBackgroundFrmImage; -static FrmImage _mainMenuButtonNormalFrmImage; -static FrmImage _mainMenuButtonPressedFrmImage; - // 0x48099C int falloutMain(int argc, char** argv) { @@ -790,319 +710,4 @@ static int _mainDeathWordWrap(char* text, int width, short* beginnings, short* c return 0; } -// 0x481650 -static int mainMenuWindowInit() -{ - int fid; - MessageListItem msg; - int len; - - if (gMainMenuWindowInitialized) { - return 0; - } - - colorPaletteLoad("color.pal"); - - int mainMenuWindowX = (screenGetWidth() - MAIN_MENU_WINDOW_WIDTH) / 2; - int mainMenuWindowY = (screenGetHeight() - MAIN_MENU_WINDOW_HEIGHT) / 2; - gMainMenuWindow = windowCreate(mainMenuWindowX, - mainMenuWindowY, - MAIN_MENU_WINDOW_WIDTH, - MAIN_MENU_WINDOW_HEIGHT, - 0, - WINDOW_HIDDEN | WINDOW_MOVE_ON_TOP); - if (gMainMenuWindow == -1) { - // NOTE: Uninline. - return main_menu_fatal_error(); - } - - gMainMenuWindowBuffer = windowGetBuffer(gMainMenuWindow); - - // mainmenu.frm - int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 140, 0, 0, 0); - if (!_mainMenuBackgroundFrmImage.lock(backgroundFid)) { - // NOTE: Uninline. - return main_menu_fatal_error(); - } - - blitBufferToBuffer(_mainMenuBackgroundFrmImage.getData(), 640, 480, 640, gMainMenuWindowBuffer, 640); - _mainMenuBackgroundFrmImage.unlock(); - - int oldFont = fontGetCurrent(); - fontSetCurrent(100); - - // SFALL: Allow to change font color/flags of copyright/version text - // It's the last byte ('3C' by default) that picks the colour used. The first byte supplies additional flags for this option - // 0x010000 - change the color for version string only - // 0x020000 - underline text (only for the version string) - // 0x040000 - monospace font (only for the version string) - int fontSettings = _colorTable[21091], fontSettingsSFall = 0; - configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_FONT_COLOR_KEY, &fontSettingsSFall); - if (fontSettingsSFall && !(fontSettingsSFall & 0x010000)) - fontSettings = fontSettingsSFall & 0xFF; - - // SFALL: Allow to move copyright text - int offsetX = 0, offsetY = 0; - configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_CREDITS_OFFSET_X_KEY, &offsetX); - configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_CREDITS_OFFSET_Y_KEY, &offsetY); - - // Copyright. - msg.num = 20; - if (messageListGetItem(&gMiscMessageList, &msg)) { - windowDrawText(gMainMenuWindow, msg.text, 0, offsetX + 15, offsetY + 460, fontSettings | 0x06000000); - } - - // SFALL: Make sure font settings are applied when using 0x010000 flag - if (fontSettingsSFall) - fontSettings = fontSettingsSFall; - - // TODO: Allow to move version text - // Version. - char version[VERSION_MAX]; - versionGetVersion(version, sizeof(version)); - len = fontGetStringWidth(version); - windowDrawText(gMainMenuWindow, version, 0, 615 - len, 460, fontSettings | 0x06000000); - - // menuup.frm - fid = buildFid(OBJ_TYPE_INTERFACE, 299, 0, 0, 0); - if (!_mainMenuButtonNormalFrmImage.lock(fid)) { - // NOTE: Uninline. - return main_menu_fatal_error(); - } - - // menudown.frm - fid = buildFid(OBJ_TYPE_INTERFACE, 300, 0, 0, 0); - if (!_mainMenuButtonPressedFrmImage.lock(fid)) { - // NOTE: Uninline. - return main_menu_fatal_error(); - } - - for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) { - gMainMenuButtons[index] = -1; - } - - // SFALL: Allow to move menu buttons - offsetX = offsetY = 0; - configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_OFFSET_X_KEY, &offsetX); - configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_OFFSET_Y_KEY, &offsetY); - - for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) { - gMainMenuButtons[index] = buttonCreate(gMainMenuWindow, - offsetX + 30, - offsetY + 19 + index * 42 - index, - 26, - 26, - -1, - -1, - 1111, - gMainMenuButtonKeyBindings[index], - _mainMenuButtonNormalFrmImage.getData(), - _mainMenuButtonPressedFrmImage.getData(), - 0, - BUTTON_FLAG_TRANSPARENT); - if (gMainMenuButtons[index] == -1) { - // NOTE: Uninline. - return main_menu_fatal_error(); - } - - buttonSetMask(gMainMenuButtons[index], _mainMenuButtonNormalFrmImage.getData()); - } - - fontSetCurrent(104); - - // SFALL: Allow to change font color of buttons - fontSettings = _colorTable[21091]; - fontSettingsSFall = 0; - configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_BIG_FONT_COLOR_KEY, &fontSettingsSFall); - if (fontSettingsSFall) - fontSettings = fontSettingsSFall & 0xFF; - - for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) { - msg.num = 9 + index; - if (messageListGetItem(&gMiscMessageList, &msg)) { - len = fontGetStringWidth(msg.text); - fontDrawText(gMainMenuWindowBuffer + offsetX + 640 * (offsetY + 42 * index - index + 20) + 126 - (len / 2), msg.text, 640 - (126 - (len / 2)) - 1, 640, fontSettings); - } - } - - fontSetCurrent(oldFont); - - gMainMenuWindowInitialized = true; - gMainMenuWindowHidden = true; - - return 0; -} - -// 0x481968 -static void mainMenuWindowFree() -{ - if (!gMainMenuWindowInitialized) { - return; - } - - for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) { - // FIXME: Why it tries to free only invalid buttons? - if (gMainMenuButtons[index] == -1) { - buttonDestroy(gMainMenuButtons[index]); - } - } - - _mainMenuButtonPressedFrmImage.unlock(); - _mainMenuButtonNormalFrmImage.unlock(); - - if (gMainMenuWindow != -1) { - windowDestroy(gMainMenuWindow); - } - - gMainMenuWindowInitialized = false; -} - -// 0x481A00 -static void mainMenuWindowHide(bool animate) -{ - if (!gMainMenuWindowInitialized) { - return; - } - - if (gMainMenuWindowHidden) { - return; - } - - soundContinueAll(); - - if (animate) { - paletteFadeTo(gPaletteBlack); - soundContinueAll(); - } - - windowHide(gMainMenuWindow); - - gMainMenuWindowHidden = true; -} - -// 0x481A48 -static void mainMenuWindowUnhide(bool animate) -{ - if (!gMainMenuWindowInitialized) { - return; - } - - if (!gMainMenuWindowHidden) { - return; - } - - windowShow(gMainMenuWindow); - - if (animate) { - colorPaletteLoad("color.pal"); - paletteFadeTo(_cmap); - } - - gMainMenuWindowHidden = false; -} - -// 0x481AA8 -static int _main_menu_is_enabled() -{ - return 1; -} - -// 0x481AEC -static int mainMenuWindowHandleEvents() -{ - _in_main_menu = true; - - bool oldCursorIsHidden = cursorIsHidden(); - if (oldCursorIsHidden) { - mouseShowCursor(); - } - - unsigned int tick = getTicks(); - - int rc = -1; - while (rc == -1) { - sharedFpsLimiter.mark(); - - int keyCode = inputGetInput(); - - for (int buttonIndex = 0; buttonIndex < MAIN_MENU_BUTTON_COUNT; buttonIndex++) { - if (keyCode == gMainMenuButtonKeyBindings[buttonIndex] || keyCode == toupper(gMainMenuButtonKeyBindings[buttonIndex])) { - // NOTE: Uninline. - main_menu_play_sound("nmselec1"); - - rc = _return_values[buttonIndex]; - - if (buttonIndex == MAIN_MENU_BUTTON_CREDITS && (gPressedPhysicalKeys[SDL_SCANCODE_RSHIFT] != KEY_STATE_UP || gPressedPhysicalKeys[SDL_SCANCODE_LSHIFT] != KEY_STATE_UP)) { - rc = MAIN_MENU_QUOTES; - } - - break; - } - } - - if (rc == -1) { - if (keyCode == KEY_CTRL_R) { - rc = MAIN_MENU_SELFRUN; - continue; - } else if (keyCode == KEY_PLUS || keyCode == KEY_EQUAL) { - brightnessIncrease(); - } else if (keyCode == KEY_MINUS || keyCode == KEY_UNDERSCORE) { - brightnessDecrease(); - } else if (keyCode == KEY_UPPERCASE_D || keyCode == KEY_LOWERCASE_D) { - rc = MAIN_MENU_SCREENSAVER; - continue; - } else if (keyCode == 1111) { - if (!(mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_REPEAT)) { - // NOTE: Uninline. - main_menu_play_sound("nmselec0"); - } - continue; - } - } - - if (keyCode == KEY_ESCAPE || _game_user_wants_to_quit == 3) { - rc = MAIN_MENU_EXIT; - - // NOTE: Uninline. - main_menu_play_sound("nmselec1"); - break; - } else if (_game_user_wants_to_quit == 2) { - _game_user_wants_to_quit = 0; - } else { - if (getTicksSince(tick) >= gMainMenuScreensaverDelay) { - rc = MAIN_MENU_TIMEOUT; - } - } - - renderPresent(); - sharedFpsLimiter.throttle(); - } - - if (oldCursorIsHidden) { - mouseHideCursor(); - } - - _in_main_menu = false; - - return rc; -} - -// NOTE: Inlined. -// -// 0x481C88 -static int main_menu_fatal_error() -{ - mainMenuWindowFree(); - - return -1; -} - -// NOTE: Inlined. -// -// 0x481C94 -static void main_menu_play_sound(const char* fileName) -{ - soundPlayFile(fileName); -} - } // namespace fallout diff --git a/src/mainmenu.cc b/src/mainmenu.cc new file mode 100644 index 0000000..c3ac817 --- /dev/null +++ b/src/mainmenu.cc @@ -0,0 +1,399 @@ +#include "mainmenu.h" + +#include + +#include "art.h" +#include "color.h" +#include "draw.h" +#include "game.h" +#include "game_sound.h" +#include "input.h" +#include "kb.h" +#include "mouse.h" +#include "palette.h" +#include "preferences.h" +#include "sfall_config.h" +#include "svga.h" +#include "text_font.h" +#include "version.h" +#include "window_manager.h" + +namespace fallout { + +#define MAIN_MENU_WINDOW_WIDTH 640 +#define MAIN_MENU_WINDOW_HEIGHT 480 + +typedef enum MainMenuButton { + MAIN_MENU_BUTTON_INTRO, + MAIN_MENU_BUTTON_NEW_GAME, + MAIN_MENU_BUTTON_LOAD_GAME, + MAIN_MENU_BUTTON_OPTIONS, + MAIN_MENU_BUTTON_CREDITS, + MAIN_MENU_BUTTON_EXIT, + MAIN_MENU_BUTTON_COUNT, +} MainMenuButton; + +static int main_menu_fatal_error(); +static void main_menu_play_sound(const char* fileName); + +// 0x5194F0 +static int gMainMenuWindow = -1; + +// 0x5194F4 +static unsigned char* gMainMenuWindowBuffer = NULL; + +// 0x519504 +static bool _in_main_menu = false; + +// 0x519508 +static bool gMainMenuWindowInitialized = false; + +// 0x51950C +static unsigned int gMainMenuScreensaverDelay = 120000; + +// 0x519510 +static const int gMainMenuButtonKeyBindings[MAIN_MENU_BUTTON_COUNT] = { + KEY_LOWERCASE_I, // intro + KEY_LOWERCASE_N, // new game + KEY_LOWERCASE_L, // load game + KEY_LOWERCASE_O, // options + KEY_LOWERCASE_C, // credits + KEY_LOWERCASE_E, // exit +}; + +// 0x519528 +static const int _return_values[MAIN_MENU_BUTTON_COUNT] = { + MAIN_MENU_INTRO, + MAIN_MENU_NEW_GAME, + MAIN_MENU_LOAD_GAME, + MAIN_MENU_OPTIONS, + MAIN_MENU_CREDITS, + MAIN_MENU_EXIT, +}; + +// 0x614840 +static int gMainMenuButtons[MAIN_MENU_BUTTON_COUNT]; + +// 0x614858 +static bool gMainMenuWindowHidden; + +static FrmImage _mainMenuBackgroundFrmImage; +static FrmImage _mainMenuButtonNormalFrmImage; +static FrmImage _mainMenuButtonPressedFrmImage; + +// 0x481650 +int mainMenuWindowInit() +{ + int fid; + MessageListItem msg; + int len; + + if (gMainMenuWindowInitialized) { + return 0; + } + + colorPaletteLoad("color.pal"); + + int mainMenuWindowX = (screenGetWidth() - MAIN_MENU_WINDOW_WIDTH) / 2; + int mainMenuWindowY = (screenGetHeight() - MAIN_MENU_WINDOW_HEIGHT) / 2; + gMainMenuWindow = windowCreate(mainMenuWindowX, + mainMenuWindowY, + MAIN_MENU_WINDOW_WIDTH, + MAIN_MENU_WINDOW_HEIGHT, + 0, + WINDOW_HIDDEN | WINDOW_MOVE_ON_TOP); + if (gMainMenuWindow == -1) { + // NOTE: Uninline. + return main_menu_fatal_error(); + } + + gMainMenuWindowBuffer = windowGetBuffer(gMainMenuWindow); + + // mainmenu.frm + int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 140, 0, 0, 0); + if (!_mainMenuBackgroundFrmImage.lock(backgroundFid)) { + // NOTE: Uninline. + return main_menu_fatal_error(); + } + + blitBufferToBuffer(_mainMenuBackgroundFrmImage.getData(), 640, 480, 640, gMainMenuWindowBuffer, 640); + _mainMenuBackgroundFrmImage.unlock(); + + int oldFont = fontGetCurrent(); + fontSetCurrent(100); + + // SFALL: Allow to change font color/flags of copyright/version text + // It's the last byte ('3C' by default) that picks the colour used. The first byte supplies additional flags for this option + // 0x010000 - change the color for version string only + // 0x020000 - underline text (only for the version string) + // 0x040000 - monospace font (only for the version string) + int fontSettings = _colorTable[21091], fontSettingsSFall = 0; + configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_FONT_COLOR_KEY, &fontSettingsSFall); + if (fontSettingsSFall && !(fontSettingsSFall & 0x010000)) + fontSettings = fontSettingsSFall & 0xFF; + + // SFALL: Allow to move copyright text + int offsetX = 0, offsetY = 0; + configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_CREDITS_OFFSET_X_KEY, &offsetX); + configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_CREDITS_OFFSET_Y_KEY, &offsetY); + + // Copyright. + msg.num = 20; + if (messageListGetItem(&gMiscMessageList, &msg)) { + windowDrawText(gMainMenuWindow, msg.text, 0, offsetX + 15, offsetY + 460, fontSettings | 0x06000000); + } + + // SFALL: Make sure font settings are applied when using 0x010000 flag + if (fontSettingsSFall) + fontSettings = fontSettingsSFall; + + // TODO: Allow to move version text + // Version. + char version[VERSION_MAX]; + versionGetVersion(version, sizeof(version)); + len = fontGetStringWidth(version); + windowDrawText(gMainMenuWindow, version, 0, 615 - len, 460, fontSettings | 0x06000000); + + // menuup.frm + fid = buildFid(OBJ_TYPE_INTERFACE, 299, 0, 0, 0); + if (!_mainMenuButtonNormalFrmImage.lock(fid)) { + // NOTE: Uninline. + return main_menu_fatal_error(); + } + + // menudown.frm + fid = buildFid(OBJ_TYPE_INTERFACE, 300, 0, 0, 0); + if (!_mainMenuButtonPressedFrmImage.lock(fid)) { + // NOTE: Uninline. + return main_menu_fatal_error(); + } + + for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) { + gMainMenuButtons[index] = -1; + } + + // SFALL: Allow to move menu buttons + offsetX = offsetY = 0; + configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_OFFSET_X_KEY, &offsetX); + configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_OFFSET_Y_KEY, &offsetY); + + for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) { + gMainMenuButtons[index] = buttonCreate(gMainMenuWindow, + offsetX + 30, + offsetY + 19 + index * 42 - index, + 26, + 26, + -1, + -1, + 1111, + gMainMenuButtonKeyBindings[index], + _mainMenuButtonNormalFrmImage.getData(), + _mainMenuButtonPressedFrmImage.getData(), + 0, + BUTTON_FLAG_TRANSPARENT); + if (gMainMenuButtons[index] == -1) { + // NOTE: Uninline. + return main_menu_fatal_error(); + } + + buttonSetMask(gMainMenuButtons[index], _mainMenuButtonNormalFrmImage.getData()); + } + + fontSetCurrent(104); + + // SFALL: Allow to change font color of buttons + fontSettings = _colorTable[21091]; + fontSettingsSFall = 0; + configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_BIG_FONT_COLOR_KEY, &fontSettingsSFall); + if (fontSettingsSFall) + fontSettings = fontSettingsSFall & 0xFF; + + for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) { + msg.num = 9 + index; + if (messageListGetItem(&gMiscMessageList, &msg)) { + len = fontGetStringWidth(msg.text); + fontDrawText(gMainMenuWindowBuffer + offsetX + 640 * (offsetY + 42 * index - index + 20) + 126 - (len / 2), msg.text, 640 - (126 - (len / 2)) - 1, 640, fontSettings); + } + } + + fontSetCurrent(oldFont); + + gMainMenuWindowInitialized = true; + gMainMenuWindowHidden = true; + + return 0; +} + +// 0x481968 +void mainMenuWindowFree() +{ + if (!gMainMenuWindowInitialized) { + return; + } + + for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) { + // FIXME: Why it tries to free only invalid buttons? + if (gMainMenuButtons[index] == -1) { + buttonDestroy(gMainMenuButtons[index]); + } + } + + _mainMenuButtonPressedFrmImage.unlock(); + _mainMenuButtonNormalFrmImage.unlock(); + + if (gMainMenuWindow != -1) { + windowDestroy(gMainMenuWindow); + } + + gMainMenuWindowInitialized = false; +} + +// 0x481A00 +void mainMenuWindowHide(bool animate) +{ + if (!gMainMenuWindowInitialized) { + return; + } + + if (gMainMenuWindowHidden) { + return; + } + + soundContinueAll(); + + if (animate) { + paletteFadeTo(gPaletteBlack); + soundContinueAll(); + } + + windowHide(gMainMenuWindow); + + gMainMenuWindowHidden = true; +} + +// 0x481A48 +void mainMenuWindowUnhide(bool animate) +{ + if (!gMainMenuWindowInitialized) { + return; + } + + if (!gMainMenuWindowHidden) { + return; + } + + windowShow(gMainMenuWindow); + + if (animate) { + colorPaletteLoad("color.pal"); + paletteFadeTo(_cmap); + } + + gMainMenuWindowHidden = false; +} + +// 0x481AA8 +int _main_menu_is_enabled() +{ + return 1; +} + +// 0x481AEC +int mainMenuWindowHandleEvents() +{ + _in_main_menu = true; + + bool oldCursorIsHidden = cursorIsHidden(); + if (oldCursorIsHidden) { + mouseShowCursor(); + } + + unsigned int tick = getTicks(); + + int rc = -1; + while (rc == -1) { + sharedFpsLimiter.mark(); + + int keyCode = inputGetInput(); + + for (int buttonIndex = 0; buttonIndex < MAIN_MENU_BUTTON_COUNT; buttonIndex++) { + if (keyCode == gMainMenuButtonKeyBindings[buttonIndex] || keyCode == toupper(gMainMenuButtonKeyBindings[buttonIndex])) { + // NOTE: Uninline. + main_menu_play_sound("nmselec1"); + + rc = _return_values[buttonIndex]; + + if (buttonIndex == MAIN_MENU_BUTTON_CREDITS && (gPressedPhysicalKeys[SDL_SCANCODE_RSHIFT] != KEY_STATE_UP || gPressedPhysicalKeys[SDL_SCANCODE_LSHIFT] != KEY_STATE_UP)) { + rc = MAIN_MENU_QUOTES; + } + + break; + } + } + + if (rc == -1) { + if (keyCode == KEY_CTRL_R) { + rc = MAIN_MENU_SELFRUN; + continue; + } else if (keyCode == KEY_PLUS || keyCode == KEY_EQUAL) { + brightnessIncrease(); + } else if (keyCode == KEY_MINUS || keyCode == KEY_UNDERSCORE) { + brightnessDecrease(); + } else if (keyCode == KEY_UPPERCASE_D || keyCode == KEY_LOWERCASE_D) { + rc = MAIN_MENU_SCREENSAVER; + continue; + } else if (keyCode == 1111) { + if (!(mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_REPEAT)) { + // NOTE: Uninline. + main_menu_play_sound("nmselec0"); + } + continue; + } + } + + if (keyCode == KEY_ESCAPE || _game_user_wants_to_quit == 3) { + rc = MAIN_MENU_EXIT; + + // NOTE: Uninline. + main_menu_play_sound("nmselec1"); + break; + } else if (_game_user_wants_to_quit == 2) { + _game_user_wants_to_quit = 0; + } else { + if (getTicksSince(tick) >= gMainMenuScreensaverDelay) { + rc = MAIN_MENU_TIMEOUT; + } + } + + renderPresent(); + sharedFpsLimiter.throttle(); + } + + if (oldCursorIsHidden) { + mouseHideCursor(); + } + + _in_main_menu = false; + + return rc; +} + +// NOTE: Inlined. +// +// 0x481C88 +static int main_menu_fatal_error() +{ + mainMenuWindowFree(); + + return -1; +} + +// NOTE: Inlined. +// +// 0x481C94 +static void main_menu_play_sound(const char* fileName) +{ + soundPlayFile(fileName); +} + +} // namespace fallout diff --git a/src/mainmenu.h b/src/mainmenu.h new file mode 100644 index 0000000..d5b81a4 --- /dev/null +++ b/src/mainmenu.h @@ -0,0 +1,28 @@ +#ifndef FALLOUT_MAINMENU_H_ +#define FALLOUT_MAINMENU_H_ + +namespace fallout { + +typedef enum MainMenuOption { + MAIN_MENU_INTRO, + MAIN_MENU_NEW_GAME, + MAIN_MENU_LOAD_GAME, + MAIN_MENU_SCREENSAVER, + MAIN_MENU_TIMEOUT, + MAIN_MENU_CREDITS, + MAIN_MENU_QUOTES, + MAIN_MENU_EXIT, + MAIN_MENU_SELFRUN, + MAIN_MENU_OPTIONS, +} MainMenuOption; + +int mainMenuWindowInit(); +void mainMenuWindowFree(); +void mainMenuWindowHide(bool animate); +void mainMenuWindowUnhide(bool animate); +int _main_menu_is_enabled(); +int mainMenuWindowHandleEvents(); + +} // namespace fallout + +#endif /* FALLOUT_MAINMENU_H_ */