#include "options.h" #include "art.h" #include "color.h" #include "cycle.h" #include "debug.h" #include "draw.h" #include "game.h" #include "game_mouse.h" #include "game_sound.h" #include "graph_lib.h" #include "input.h" #include "kb.h" #include "loadsave.h" #include "memory.h" #include "message.h" #include "mouse.h" #include "preferences.h" #include "svga.h" #include "text_font.h" #include "tile.h" #include "window_manager.h" namespace fallout { #define OPTIONS_WINDOW_BUTTONS_COUNT (10) typedef enum PauseWindowFrm { PAUSE_WINDOW_FRM_BACKGROUND, PAUSE_WINDOW_FRM_DONE_BOX, PAUSE_WINDOW_FRM_LITTLE_RED_BUTTON_UP, PAUSE_WINDOW_FRM_LITTLE_RED_BUTTON_DOWN, PAUSE_WINDOW_FRM_COUNT, } PauseWindowFrm; typedef enum OptionsWindowFrm { OPTIONS_WINDOW_FRM_BACKGROUND, OPTIONS_WINDOW_FRM_BUTTON_ON, OPTIONS_WINDOW_FRM_BUTTON_OFF, OPTIONS_WINDOW_FRM_COUNT, } OptionsWindowFrm; static int optionsWindowInit(); static int optionsWindowFree(); static void _ShadeScreen(bool a1); // 0x48FC0C static const int gPauseWindowFrmIds[PAUSE_WINDOW_FRM_COUNT] = { 208, // charwin.frm - character editor 209, // donebox.frm - character editor 8, // lilredup.frm - little red button up 9, // lilreddn.frm - little red button down }; // 0x5197C0 static const int gOptionsWindowFrmIds[OPTIONS_WINDOW_FRM_COUNT] = { 220, // opbase.frm - character editor 222, // opbtnon.frm - character editor 221, // opbtnoff.frm - character editor }; // 0x6637E8 static MessageList gPreferencesMessageList; // 0x663840 static MessageListItem gPreferencesMessageListItem; // 0x663878 static unsigned char* _opbtns[OPTIONS_WINDOW_BUTTONS_COUNT]; // 0x6638FC static bool gOptionsWindowGameMouseObjectsWasVisible; // 0x663900 static int gOptionsWindow; // 0x663908 static unsigned char* gOptionsWindowBuffer; // 0x66398C static int gOptionsWindowOldFont; // 0x663994 static bool gOptionsWindowIsoWasEnabled; static FrmImage _optionsFrmImages[OPTIONS_WINDOW_FRM_COUNT]; // 0x48FC50 int showOptions() { ScopedGameMode gm(GameMode::kOptions); if (optionsWindowInit() == -1) { debugPrint("\nOPTION MENU: Error loading option dialog data!\n"); return -1; } int rc = -1; while (rc == -1) { sharedFpsLimiter.mark(); int keyCode = inputGetInput(); if (keyCode == KEY_ESCAPE || keyCode == 504 || _game_user_wants_to_quit != 0) { rc = 0; } else { switch (keyCode) { case KEY_RETURN: case KEY_UPPERCASE_O: case KEY_LOWERCASE_O: case KEY_UPPERCASE_D: case KEY_LOWERCASE_D: soundPlayFile("ib1p1xx1"); rc = 0; break; case KEY_UPPERCASE_S: case KEY_LOWERCASE_S: case 500: if (lsgSaveGame(LOAD_SAVE_MODE_NORMAL) == 1) { rc = 1; } break; case KEY_UPPERCASE_L: case KEY_LOWERCASE_L: case 501: if (lsgLoadGame(LOAD_SAVE_MODE_NORMAL) == 1) { rc = 1; } break; case KEY_UPPERCASE_P: case KEY_LOWERCASE_P: soundPlayFile("ib1p1xx1"); // FALLTHROUGH case 502: // PREFERENCES doPreferences(false); break; case KEY_PLUS: case KEY_EQUAL: brightnessIncrease(); break; case KEY_UNDERSCORE: case KEY_MINUS: brightnessDecrease(); break; case KEY_F12: takeScreenshot(); break; case KEY_UPPERCASE_E: case KEY_LOWERCASE_E: case KEY_CTRL_Q: case KEY_CTRL_X: case KEY_F10: case 503: showQuitConfirmationDialog(); break; } } renderPresent(); sharedFpsLimiter.throttle(); } optionsWindowFree(); return rc; } // 0x48FE14 static int optionsWindowInit() { gOptionsWindowOldFont = fontGetCurrent(); if (!messageListInit(&gPreferencesMessageList)) { return -1; } char path[COMPAT_MAX_PATH]; snprintf(path, sizeof(path), "%s%s", asc_5186C8, "options.msg"); if (!messageListLoad(&gPreferencesMessageList, path)) { return -1; } for (int index = 0; index < OPTIONS_WINDOW_FRM_COUNT; index++) { int fid = buildFid(OBJ_TYPE_INTERFACE, gOptionsWindowFrmIds[index], 0, 0, 0); if (!_optionsFrmImages[index].lock(fid)) { while (--index >= 0) { _optionsFrmImages[index].unlock(); } messageListFree(&gPreferencesMessageList); return -1; } } int cycle = 0; for (int index = 0; index < OPTIONS_WINDOW_BUTTONS_COUNT; index++) { _opbtns[index] = (unsigned char*)internal_malloc(_optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth() * _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getHeight() + 1024); if (_opbtns[index] == NULL) { while (--index >= 0) { internal_free(_opbtns[index]); } for (int index = 0; index < OPTIONS_WINDOW_FRM_COUNT; index++) { _optionsFrmImages[index].unlock(); } messageListFree(&gPreferencesMessageList); return -1; } cycle = cycle ^ 1; memcpy(_opbtns[index], _optionsFrmImages[cycle + 1].getData(), _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth() * _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getHeight()); } int optionsWindowX = (screenGetWidth() - _optionsFrmImages[OPTIONS_WINDOW_FRM_BACKGROUND].getWidth()) / 2; int optionsWindowY = (screenGetHeight() - _optionsFrmImages[OPTIONS_WINDOW_FRM_BACKGROUND].getHeight()) / 2 - 60; gOptionsWindow = windowCreate(optionsWindowX, optionsWindowY, _optionsFrmImages[0].getWidth(), _optionsFrmImages[0].getHeight(), 256, WINDOW_MODAL | WINDOW_DONT_MOVE_TOP); if (gOptionsWindow == -1) { for (int index = 0; index < OPTIONS_WINDOW_BUTTONS_COUNT; index++) { internal_free(_opbtns[index]); } for (int index = 0; index < OPTIONS_WINDOW_FRM_COUNT; index++) { _optionsFrmImages[index].unlock(); } messageListFree(&gPreferencesMessageList); return -1; } gOptionsWindowIsoWasEnabled = isoDisable(); gOptionsWindowGameMouseObjectsWasVisible = gameMouseObjectsIsVisible(); if (gOptionsWindowGameMouseObjectsWasVisible) { gameMouseObjectsHide(); } gameMouseSetCursor(MOUSE_CURSOR_ARROW); gOptionsWindowBuffer = windowGetBuffer(gOptionsWindow); memcpy(gOptionsWindowBuffer, _optionsFrmImages[OPTIONS_WINDOW_FRM_BACKGROUND].getData(), _optionsFrmImages[OPTIONS_WINDOW_FRM_BACKGROUND].getWidth() * _optionsFrmImages[OPTIONS_WINDOW_FRM_BACKGROUND].getHeight()); fontSetCurrent(103); int textY = (_optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getHeight() - fontGetLineHeight()) / 2 + 1; int buttonY = 17; for (int index = 0; index < OPTIONS_WINDOW_BUTTONS_COUNT; index += 2) { char text[128]; const char* msg = getmsg(&gPreferencesMessageList, &gPreferencesMessageListItem, index / 2); strcpy(text, msg); int textX = (_optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth() - fontGetStringWidth(text)) / 2; if (textX < 0) { textX = 0; } fontDrawText(_opbtns[index] + _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth() * textY + textX, text, _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth(), _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth(), _colorTable[18979]); fontDrawText(_opbtns[index + 1] + _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth() * textY + textX, text, _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth(), _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth(), _colorTable[14723]); int btn = buttonCreate(gOptionsWindow, 13, buttonY, _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getWidth(), _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getHeight(), -1, -1, -1, index / 2 + 500, _opbtns[index], _opbtns[index + 1], NULL, BUTTON_FLAG_TRANSPARENT); if (btn != -1) { buttonSetCallbacks(btn, _gsound_lrg_butt_press, _gsound_lrg_butt_release); } buttonY += _optionsFrmImages[OPTIONS_WINDOW_FRM_BUTTON_ON].getHeight() + 3; } fontSetCurrent(101); windowRefresh(gOptionsWindow); return 0; } // 0x490244 static int optionsWindowFree() { windowDestroy(gOptionsWindow); fontSetCurrent(gOptionsWindowOldFont); messageListFree(&gPreferencesMessageList); for (int index = 0; index < OPTIONS_WINDOW_BUTTONS_COUNT; index++) { internal_free(_opbtns[index]); } for (int index = 0; index < OPTIONS_WINDOW_FRM_COUNT; index++) { _optionsFrmImages[index].unlock(); } if (gOptionsWindowGameMouseObjectsWasVisible) { gameMouseObjectsShow(); } if (gOptionsWindowIsoWasEnabled) { isoEnable(); } return 0; } // 0x4902B0 int showPause(bool a1) { bool gameMouseWasVisible; if (!a1) { gOptionsWindowIsoWasEnabled = isoDisable(); colorCycleDisable(); gameMouseWasVisible = gameMouseObjectsIsVisible(); if (gameMouseWasVisible) { gameMouseObjectsHide(); } } gameMouseSetCursor(MOUSE_CURSOR_ARROW); _ShadeScreen(a1); FrmImage frmImages[PAUSE_WINDOW_FRM_COUNT]; for (int index = 0; index < PAUSE_WINDOW_FRM_COUNT; index++) { int fid = buildFid(OBJ_TYPE_INTERFACE, gPauseWindowFrmIds[index], 0, 0, 0); if (!frmImages[index].lock(fid)) { debugPrint("\n** Error loading pause window graphics! **\n"); return -1; } } if (!messageListInit(&gPreferencesMessageList)) { // FIXME: Leaking graphics. return -1; } char path[COMPAT_MAX_PATH]; snprintf(path, sizeof(path), "%s%s", asc_5186C8, "options.msg"); if (!messageListLoad(&gPreferencesMessageList, path)) { // FIXME: Leaking graphics. return -1; } int pauseWindowX = (screenGetWidth() - frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth()) / 2; int pauseWindowY = (screenGetHeight() - frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getHeight()) / 2; if (a1) { pauseWindowX -= 65; pauseWindowY -= 24; } else { pauseWindowY -= 54; } int window = windowCreate(pauseWindowX, pauseWindowY, frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth(), frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getHeight(), 256, WINDOW_MODAL | WINDOW_DONT_MOVE_TOP); if (window == -1) { messageListFree(&gPreferencesMessageList); debugPrint("\n** Error opening pause window! **\n"); return -1; } unsigned char* windowBuffer = windowGetBuffer(window); memcpy(windowBuffer, frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getData(), frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth() * frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getHeight()); blitBufferToBufferTrans(frmImages[PAUSE_WINDOW_FRM_DONE_BOX].getData(), frmImages[PAUSE_WINDOW_FRM_DONE_BOX].getWidth(), frmImages[PAUSE_WINDOW_FRM_DONE_BOX].getHeight(), frmImages[PAUSE_WINDOW_FRM_DONE_BOX].getWidth(), windowBuffer + frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth() * 42 + 13, frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth()); gOptionsWindowOldFont = fontGetCurrent(); fontSetCurrent(103); char* messageItemText; messageItemText = getmsg(&gPreferencesMessageList, &gPreferencesMessageListItem, 300); fontDrawText(windowBuffer + frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth() * 45 + 52, messageItemText, frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth(), frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth(), _colorTable[18979]); fontSetCurrent(104); messageItemText = getmsg(&gPreferencesMessageList, &gPreferencesMessageListItem, 301); strcpy(path, messageItemText); int length = fontGetStringWidth(path); fontDrawText(windowBuffer + frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth() * 10 + 2 + (frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth() - length) / 2, path, frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth(), frmImages[PAUSE_WINDOW_FRM_BACKGROUND].getWidth(), _colorTable[18979]); int doneBtn = buttonCreate(window, 26, 46, frmImages[PAUSE_WINDOW_FRM_LITTLE_RED_BUTTON_UP].getWidth(), frmImages[PAUSE_WINDOW_FRM_LITTLE_RED_BUTTON_UP].getHeight(), -1, -1, -1, 504, frmImages[PAUSE_WINDOW_FRM_LITTLE_RED_BUTTON_UP].getData(), frmImages[PAUSE_WINDOW_FRM_LITTLE_RED_BUTTON_DOWN].getData(), NULL, BUTTON_FLAG_TRANSPARENT); if (doneBtn != -1) { buttonSetCallbacks(doneBtn, _gsound_red_butt_press, _gsound_red_butt_release); } windowRefresh(window); bool done = false; while (!done) { sharedFpsLimiter.mark(); int keyCode = inputGetInput(); switch (keyCode) { case KEY_PLUS: case KEY_EQUAL: brightnessIncrease(); break; case KEY_MINUS: case KEY_UNDERSCORE: brightnessDecrease(); break; default: if (keyCode != -1 && keyCode != -2) { done = true; } if (_game_user_wants_to_quit != 0) { done = true; } } renderPresent(); sharedFpsLimiter.throttle(); } if (!a1) { tileWindowRefresh(); } windowDestroy(window); messageListFree(&gPreferencesMessageList); if (!a1) { if (gameMouseWasVisible) { gameMouseObjectsShow(); } if (gOptionsWindowIsoWasEnabled) { isoEnable(); } colorCycleEnable(); gameMouseSetCursor(MOUSE_CURSOR_ARROW); } fontSetCurrent(gOptionsWindowOldFont); return 0; } // 0x490748 static void _ShadeScreen(bool a1) { if (a1) { mouseHideCursor(); } else { mouseHideCursor(); tileWindowRefresh(); int windowWidth = windowGetWidth(gIsoWindow); int windowHeight = windowGetHeight(gIsoWindow); unsigned char* windowBuffer = windowGetBuffer(gIsoWindow); grayscalePaletteApply(windowBuffer, windowWidth, windowHeight, windowWidth); windowRefresh(gIsoWindow); } mouseShowCursor(); } // init_options_menu // 0x4928B8 int _init_options_menu() { preferencesInit(); grayscalePaletteUpdate(0, 255); return 0; } } // namespace fallout