From 595421da3908a2d3e7a1b063605bb3f2a3adb65b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 30 Sep 2020 20:02:47 +0300 Subject: [PATCH 1/5] Fixes, mouse AUX buttons, joystick detect menu --- src/audio/MusicManager.cpp | 2 +- src/core/Frontend.cpp | 21 ++- src/core/Game.cpp | 1 - src/core/Pad.h | 2 + src/core/config.h | 3 + src/core/re3.cpp | 73 +++++++- src/core/timebars.cpp | 2 +- src/extras/frontendoption.cpp | 14 +- src/extras/frontendoption.h | 12 +- src/extras/ini_parser.hpp | 314 ++++++++++++++++++++++++++++++++++ src/render/Hud.cpp | 8 +- src/skel/crossplatform.h | 4 + src/skel/glfw/glfw.cpp | 50 +++--- src/vehicles/CarGen.cpp | 10 +- 14 files changed, 456 insertions(+), 60 deletions(-) create mode 100644 src/extras/ini_parser.hpp diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index 9cf092b3..5519d899 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -161,7 +161,7 @@ cMusicManager::DisplayRadioStationName() CFont::SetPropOn(); CFont::SetFontStyle(FONT_HEADING); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_STRETCH_X(640.0f)); + CFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 9ead2a0a..2cb27730 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -854,6 +854,13 @@ CMenuManager::Draw() str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); break; default: +#ifdef CUSTOM_FRONTEND_OPTIONS + if (aScreens[m_nCurrScreen].m_aEntries[0].m_SaveSlot == SAVESLOT_CFO) { + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[0].m_TargetMenu]; + str = (wchar*)option.leftText; + } + else +#endif str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); break; } @@ -3443,6 +3450,7 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1); +/* #ifdef CUSTOM_FRONTEND_OPTIONS for (int i = 0; i < numCustomFrontendOptions; i++) { FrontendOption& option = customFrontendOptions[i]; @@ -3456,6 +3464,7 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1); CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading; #endif +*/ } } @@ -3546,6 +3555,7 @@ CMenuManager::SaveSettings() CFileMgr::Write(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1); +/* #ifdef CUSTOM_FRONTEND_OPTIONS for (int i = 0; i < numCustomFrontendOptions; i++) { FrontendOption &option = customFrontendOptions[i]; @@ -3557,6 +3567,7 @@ CMenuManager::SaveSettings() #ifdef NO_ISLAND_LOADING CFileMgr::Write(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1); #endif +*/ } CFileMgr::CloseFile(fileHandle); @@ -3880,7 +3891,10 @@ CMenuManager::Process(void) MouseButtonJustClicked = 4; else if (CPad::GetPad(0)->GetMouseWheelDownJustUp()) MouseButtonJustClicked = 5; - // TODO two more buttons + else if (CPad::GetPad(0)->GetMouseX1JustUp()) + MouseButtonJustClicked = 6; + else if (CPad::GetPad(0)->GetMouseX2JustUp()) + MouseButtonJustClicked = 7; JoyButtonJustClicked = ControlsManager.GetJoyButtonJustDown(); @@ -5106,7 +5120,8 @@ CMenuManager::ProcessButtonPresses(void) *option.value = option.lastSavedValue = option.displayedValue; } else if (option.type == FEOPTION_DYNAMIC) { - option.buttonPressFunc(FEOPTION_ACTION_SELECT); + if (option.buttonPressFunc) + option.buttonPressFunc(FEOPTION_ACTION_SELECT); } else if (option.type == FEOPTION_REDIRECT) { ChangeScreen(option.to, option.option, true, option.fadeIn); } else if (option.type == FEOPTION_GOBACK) { @@ -5349,7 +5364,7 @@ CMenuManager::ProcessButtonPresses(void) option.changeFunc(option.displayedValue); *option.value = option.lastSavedValue = option.displayedValue; } - } else if (option.type == FEOPTION_DYNAMIC) { + } else if (option.type == FEOPTION_DYNAMIC && option.buttonPressFunc) { option.buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); } DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index e944512a..bb9df1a2 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -297,7 +297,6 @@ bool CGame::InitialiseOnceAfterRW(void) #ifdef CUSTOM_FRONTEND_OPTIONS if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) { CustomFrontendOptionsPopulate(); - FrontEndMenuManager.LoadSettings(); } #endif return true; diff --git a/src/core/Pad.h b/src/core/Pad.h index 8c3bc752..8c5d7ba3 100644 --- a/src/core/Pad.h +++ b/src/core/Pad.h @@ -277,6 +277,8 @@ public: bool GetMiddleMouseJustUp() { return !!(!NewMouseControllerState.MMB && OldMouseControllerState.MMB); } bool GetMouseWheelUpJustUp() { return !!(!NewMouseControllerState.WHEELUP && OldMouseControllerState.WHEELUP); } bool GetMouseWheelDownJustUp() { return !!(!NewMouseControllerState.WHEELDN && OldMouseControllerState.WHEELDN); } + bool GetMouseX1JustUp() { return !!(!NewMouseControllerState.MXB1 && OldMouseControllerState.MXB1); } + bool GetMouseX2JustUp() { return !!(!NewMouseControllerState.MXB2 && OldMouseControllerState.MXB2); } bool GetLeftMouse() { return NewMouseControllerState.LMB; } bool GetRightMouse() { return NewMouseControllerState.RMB; } diff --git a/src/core/config.h b/src/core/config.h index e8e15ebe..0f3cb2ef 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -226,6 +226,9 @@ enum Config { #if !defined(RW_GL3) && defined(_WIN32) #define XINPUT #endif +#if defined(RW_GL3) && !defined(__SWITCH__) // TODO +#define DONT_TRUST_RECOGNIZED_JOYSTICKS // Then we'll only rely on GLFW gamepad DB, and want user to enter Cpntroller->Detect joysticks if his joystick isn't on that list. +#endif #define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m #define KANGAROO_CHEAT #define ALLCARSHELI_CHEAT diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 13cb6283..b892ca36 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -32,6 +32,7 @@ #include "MBlur.h" #include "postfx.h" #include "custompipes.h" +#include "ControllerConfig.h" #ifndef _WIN32 #include "assert.h" @@ -195,6 +196,7 @@ wchar* MultiSamplingDraw(bool *disabled, bool userHovering) { return unicodeTemp; } } +char* multisamplingKey = "MultiSampling"; #endif #ifdef MORE_LANGUAGES @@ -247,6 +249,8 @@ void FreeCamChange(int8 displayedValue) TheCamera.bFreeCam = !!displayedValue; FrontEndMenuManager.SaveSettings(); } +const wchar* freeCamText = (wchar*)L"FREE CAM"; +char* freeCamKey = "FreeCam"; #endif #ifdef CUTSCENE_BORDERS_SWITCH @@ -255,6 +259,7 @@ void BorderModeChange(int8 displayedValue) CMenuManager::m_PrefsCutsceneBorders = !!displayedValue; FrontEndMenuManager.SaveSettings(); } +char* cutsceneBordersKey = "CutsceneBorders"; #endif #ifdef PS2_ALPHA_TEST @@ -263,11 +268,52 @@ void PS2AlphaTestChange(int8 displayedValue) gPS2alphaTest = !!displayedValue; FrontEndMenuManager.SaveSettings(); } +char* ps2alphaKey = "PS2AlphaTest"; #endif +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS +const wchar* detectJoystickText = (wchar*)L"Detect Joystick"; +const wchar* detectJoystickExplanation = (wchar*)L"Press any key on your preferred joystick that you would like to use on the game."; +const wchar* detectedJoystickText = (wchar*)L"Detected Joystick"; +wchar selectedJoystickUnicode[128]; + +wchar* DetectJoystickDraw(bool* disabled, bool userHovering) { + int numButtons; + int found = -1; + const char *joyname; + if (userHovering) { + for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { + if (joyname = glfwGetJoystickName(i)) { + const uint8* buttons = glfwGetJoystickButtons(i, &numButtons); + for (int j = 0; j < numButtons; j++) { + if (buttons[j]) { + strcpy(gSelectedJoystickName, joyname); + found = i; + break; + } + } + if (found != -1) + break; + } + } + + if (found != -1 && PSGLOBAL(joy1id) != found) { + if (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found) + PSGLOBAL(joy2id) = PSGLOBAL(joy1id); + else + PSGLOBAL(joy2id) = -1; + + PSGLOBAL(joy1id) = found; + } + } + AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode); + + return selectedJoystickUnicode; +} +#endif // Important: Make sure to read the warnings/informations in frontendoption.h!! -// For texts: Either use TheText.Get, or use wcsdup(wchar version of strdup) +// If you won't use GXT entry as text, you may want to declare them globally, to not alloc them on each reload. (static declared texts has some problems on Linux etc.) void CustomFrontendOptionsPopulate(void) { @@ -342,14 +388,14 @@ CustomFrontendOptionsPopulate(void) #ifdef MULTISAMPLING SWITCH_TO_GRAPHICS_MENU - FrontendOptionAddDynamic(TheText.Get("FED_AAS"), MultiSamplingDraw, (int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, MultiSamplingButtonPress, MultiSamplingGoBack, true); + FrontendOptionAddDynamic(TheText.Get("FED_AAS"), MultiSamplingDraw, (int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, MultiSamplingButtonPress, MultiSamplingGoBack, multisamplingKey); #endif CLONE_OPTION(TheText.Get("FED_TRA"), MENUACTION_TRAILS, nil, nil); #ifdef PS2_ALPHA_TEST SWITCH_TO_GRAPHICS_MENU - FrontendOptionAddSelect(TheText.Get("FEM_2PR"), off_on, 2, (int8*)&gPS2alphaTest, false, PS2AlphaTestChange, nil, true); + FrontendOptionAddSelect(TheText.Get("FEM_2PR"), off_on, 2, (int8*)&gPS2alphaTest, false, PS2AlphaTestChange, nil, ps2alphaKey); #endif ADD_RESTORE_DEFAULTS(RestoreDefGraphics) @@ -365,13 +411,12 @@ CustomFrontendOptionsPopulate(void) #ifdef CUTSCENE_BORDERS_SWITCH SWITCH_TO_DISPLAY_MENU - FrontendOptionAddSelect(TheText.Get("FEM_CSB"), off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil, true); + FrontendOptionAddSelect(TheText.Get("FEM_CSB"), off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil, cutsceneBordersKey); #endif #ifdef FREE_CAM SWITCH_TO_DISPLAY_MENU - static const wchar* text = (wchar*)wcsdup(L"FREE CAM"); - FrontendOptionAddSelect(text, off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, true); + FrontendOptionAddSelect(freeCamText, off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, freeCamKey); #endif CLONE_OPTION(TheText.Get("FED_SUB"), MENUACTION_SUBTITLES, nil, nil); @@ -388,7 +433,21 @@ CustomFrontendOptionsPopulate(void) #endif ADD_RESTORE_DEFAULTS(RestoreDefDisplay) - ADD_BACK + ADD_BACK + +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + int detectJoystickMenu = FrontendScreenAdd("FET_CON", MENUSPRITE_MAINMENU, MENUPAGE_CONTROLLER_PC, 50, 60, 20, + FONT_BANK, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, false); + + FrontendOptionSetCursor(detectJoystickMenu, 0); + + FrontendOptionAddBuiltinAction(detectJoystickExplanation, MENUACTION_LABEL, nil, nil); + FrontendOptionAddDynamic(detectedJoystickText, DetectJoystickDraw, nil, nil, nil); + FrontendOptionAddBackButton(TheText.Get("FEDS_TB")); + + FrontendOptionSetCursor(MENUPAGE_CONTROLLER_PC, 2); + FrontendOptionAddRedirect(detectJoystickText, detectJoystickMenu, 1); +#endif } #endif diff --git a/src/core/timebars.cpp b/src/core/timebars.cpp index 5ac5565d..94051b25 100644 --- a/src/core/timebars.cpp +++ b/src/core/timebars.cpp @@ -89,7 +89,7 @@ void tbDisplay() CFont::SetScale(0.48f, 1.12f); CFont::SetCentreOff(); CFont::SetJustifyOff(); - CFont::SetWrapx(640.0f); + CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); CFont::SetRightJustifyOff(); CFont::SetPropOn(); CFont::SetFontStyle(FONT_BANK); diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp index b365a3fe..70d444de 100644 --- a/src/extras/frontendoption.cpp +++ b/src/extras/frontendoption.cpp @@ -213,10 +213,10 @@ void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPre TextCopy(option.leftText, leftText); option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = returnPrevPageFunc; - option.save = false; + option.save = nil; } -void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save) +void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName) { int8 screenOptionOrder = RegisterNewOption(); @@ -229,14 +229,14 @@ void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, in option.value = var; option.displayedValue = *var; option.lastSavedValue = *var; - option.save = save; + option.save = saveName; option.onlyApplyOnEnter = onlyApplyOnEnter; option.changeFunc = changeFunc; option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = returnPrevPageFunc; } -void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save) +void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName) { int8 screenOptionOrder = RegisterNewOption(); @@ -246,7 +246,7 @@ void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *va option.buttonPressFunc = buttonPressFunc; TextCopy(option.leftText, leftText); option.value = var; - option.save = save; + option.save = saveName; option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = returnPrevPageFunc; } @@ -263,7 +263,7 @@ void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption, b TextCopy(option.leftText, text); option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = nil; - option.save = false; + option.save = nil; } void FrontendOptionAddBackButton(const wchar* text, bool fadeIn) @@ -276,7 +276,7 @@ void FrontendOptionAddBackButton(const wchar* text, bool fadeIn) TextCopy(option.leftText, text); option.screenOptionOrder = screenOptionOrder; option.returnPrevPageFunc = nil; - option.save = false; + option.save = nil; } uint8 FrontendScreenAdd(const char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight, diff --git a/src/extras/frontendoption.h b/src/extras/frontendoption.h index b2bfbf5e..f721abb0 100644 --- a/src/extras/frontendoption.h +++ b/src/extras/frontendoption.h @@ -10,7 +10,7 @@ // About texts: // All text parameters accept wchar(including hardcoded wchar* and TheText.Get) -// except FrontendScreenAdd(it's char[8] by the design of Frontend). +// except FrontendScreenAdd(it's char[8] GXT key by the design of Frontend). // All texts reload if custom options reloaded too, which includes language changes and via live reload feature in debug menu! // Execute direction: @@ -26,7 +26,7 @@ // // Static/select: You allocate the variable, pass it to function and game sets it from user input among the strings given to function, // then you can handle ChangeFunc(only called on enter if onlyApplyOnEnter set, or set immediately) -// and ReturnPrevPageFunc optionally. You can store the option in gta3.set if you pass true to corresponding parameter. +// and ReturnPrevPageFunc optionally. You can store the option in an INI file if you pass the key(as a char array) to corresponding parameter. // // Dynamic: Passing variable to function is only needed if you want to store it, otherwise you should do // all the operations with ButtonPressFunc, this includes allocating the variable. @@ -95,7 +95,7 @@ struct FrontendOption ReturnPrevPageFunc returnPrevPageFunc; int8* value; int8 displayedValue; // only if onlyApplyOnEnter enabled for now - bool save; + char* save; int32 ogOptionId; // for replacements, see overwrite parameter of SetCursor union { @@ -151,10 +151,10 @@ uint8 GetNumberOfMenuOptions(int screen); void FrontendOptionSetCursor(int screen, int8 option, bool overwrite = false); -// var is optional in AddDynamic, you can enable save parameter if you pass one, otherwise pass nil/0 +// var is optional in AddDynamic, enables you to save them in an INI file(also needs passing char array to saveName param. obv), otherwise pass nil/0 void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc); -void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save = false); -void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save = false); +void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName = nil); +void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName = nil); void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption = 0, bool fadeIn = true); void FrontendOptionAddBackButton(const wchar* text, bool fadeIn = true); diff --git a/src/extras/ini_parser.hpp b/src/extras/ini_parser.hpp new file mode 100644 index 00000000..99acf1ee --- /dev/null +++ b/src/extras/ini_parser.hpp @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2013-2015 Denilson das Mercês Amorim + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ +#ifndef LINB_INI_PARSER_HPP +#define LINB_INI_PARSER_HPP + +/* + * STL-like INI Container + */ + +#include // for std::string +#include // for std::map +#include // for std::FILE +#include // for std::find_if +#include // for std::function + +namespace linb +{ + template< + class CharT = char, /* Not compatible with other type here, since we're using C streams */ + class StringType = std::basic_string, + class KeyContainer = std::map, + class SectionContainer = std::map + > class basic_ini + { + public: + typedef CharT char_type; + typedef StringType string_type; + typedef KeyContainer key_container; + typedef SectionContainer section_container; + + // Typedef container values types + typedef typename section_container::value_type value_type; + typedef typename section_container::key_type key_type; + typedef typename section_container::mapped_type mapped_type; + + // Typedef common types + typedef typename section_container::size_type size_type; + typedef typename section_container::difference_type difference_type; + + // Typedef iterators + typedef typename section_container::iterator iterator; + typedef typename section_container::const_iterator const_iterator; + typedef typename section_container::reverse_iterator reverse_iterator; + typedef typename section_container::const_reverse_iterator const_reverse_iterator; + + // typedef References and pointers + typedef typename section_container::reference reference; + typedef typename section_container::const_reference const_reference; + typedef typename section_container::pointer pointer; + typedef typename section_container::const_pointer const_pointer; + + private: + section_container data; + + public: + + basic_ini() + { } + + basic_ini(const char_type* filename) + { this->read_file(filename); } + + /* Iterator methods */ + iterator begin() + { return data.begin(); } + const_iterator begin() const + { return data.begin(); } + iterator end() + { return data.end(); } + const_iterator end() const + { return data.end(); } + const_iterator cbegin() const + { return data.cbegin(); } + const_iterator cend() const + { return data.cend(); } + + /* Reverse iterator methods */ + reverse_iterator rbegin() + { return data.rbegin(); } + const_reverse_iterator rbegin() const + { return data.rbegin(); } + reverse_iterator rend() + { return data.rend(); } + const_reverse_iterator rend() const + { return data.rend(); } + const_reverse_iterator crbegin() const + { return data.crbegin(); } + const_reverse_iterator crend() const + { return data.crend(); } + + /* Acessing index methods */ + mapped_type& operator[](const string_type& sect) + { return data[sect]; } + mapped_type& operator[](string_type&& sect) + { return data[std::forward(sect)]; } + mapped_type& at( const string_type& sect) + { return data.at(sect); } + const mapped_type& at(const string_type& sect) const + { return data.at(sect); } + + /* Capacity information */ + bool empty() const + { return data.empty(); } + size_type size() const + { return data.size(); } + size_type max_size() const + { return data.max_size(); } + + /* Modifiers */ + void clear() + { return data.clear(); } + + /* Lookup */ + size_type count(const string_type& sect) + { return data.count(sect); } + iterator find(const string_type& sect) + { return data.find(sect); } + + /* Gets a value from the specified section & key, default_value is returned if the sect & key doesn't exist */ + string_type get(const string_type& sect, const key_type& key, const string_type& default_value) + { + auto it = this->find(sect); + if(it != this->end()) + { + auto itv = it->second.find(key); + if(itv != it->second.end()) + return itv->second; + } + return default_value; + } + + /* Sets the value of a value in the ini */ + void set(const string_type& sect, const key_type& key, const string_type& value) + { + (*this)[sect][key] = value; // no emplace since overwrite! + } + + /* Too lazy to continue this container... If you need more methods, just add it */ + + +#if 1 + bool read_file(const char_type* filename) + { + /* Using C stream in a STL-like container, funny? + */ + if(FILE* f = fopen(filename, "r")) + { + key_container* keys = nullptr; + char_type buf[2048]; + string_type line; + string_type key; + string_type value; + string_type null_string; + size_type pos; + + // Trims an string + auto trim = [](string_type& s, bool trimLeft, bool trimRight) -> string_type& + { + if(s.size()) + { + // Ignore UTF-8 BOM + while(s.size() >= 3 && s[0] == (char)(0xEF) && s[1] == (char)(0xBB) && s[2] == (char)(0xBF)) + s.erase(s.begin(), s.begin() + 3); + + if(trimLeft) + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::function(::isspace)))); + if(trimRight) + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::function(::isspace))).base(), s.end()); + } + return s; + }; + + // Start parsing + while(fgets(buf, sizeof(buf), f)) + { + // What a thing, reading into a char buffer and then putting in the string... + line = buf; + + // Find comment and remove anything after it from the line + if((pos = line.find_first_of(';')) != line.npos) + line.erase(pos); + + // Trim the string, and if it gets empty, skip this line + if(trim(line, true, true).empty()) + continue; + + // Find section name + if(line.front() == '[' && line.back() == ']') + { + pos = line.length() - 1; //line.find_first_of(']'); + if(pos != line.npos) + { + trim(key.assign(line, 1, pos-1), true, true); + keys = &data[std::move(key)]; // Create section + } + else + keys = nullptr; + } + else + { + // Find key and value positions + pos = line.find_first_of('='); + if(pos == line.npos) + { + // There's only the key + key = line; // No need for trim, line is already trimmed + value.clear(); + } + else + { + // There's the key and the value + trim(key.assign(line, 0, pos), false, true); // trim the right + trim(value.assign(line, pos + 1, line.npos), true, false); // trim the left + } + + // Put the key/value into the current keys object, or into the section "" if no section has been found + #if __cplusplus >= 201103L || _MSC_VER >= 1800 + (keys ? *keys : data[null_string]).emplace(std::move(key), std::move(value)); + #else + (keys ? *keys : data[null_string])[key] = value; + key.clear(); value.clear(); + #endif + } + } + + fclose(f); + return true; + } + return false; + } + + /* + * Dumps the content of this container into an ini file + */ + bool write_file(const char_type* filename) + { + if(FILE* f = fopen(filename, "w")) + { + bool first = true; + for(auto& sec : this->data) + { + fprintf(f, first? "[%s]\n" : "\n[%s]\n", sec.first.c_str()); + first = false; + for(auto& kv : sec.second) + { + if(kv.second.empty()) + fprintf(f, "%s\n", kv.first.c_str()); + else + fprintf(f, "%s = %s\n", kv.first.c_str(), kv.second.c_str()); + } + } + fclose(f); + return true; + } + return false; + } + + + /* + */ + bool load_file(const char_type* filename) + { + return read_file(filename); + } + + bool load_file(const StringType& filename) + { + return load_file(filename.c_str()); + } + + bool write_file(const StringType& filename) + { + return write_file(filename.c_str()); + } +#endif + + + + }; + + + /* Use default basic_ini + * + * Limitations: + * * Not unicode aware + * * Case sensitive + * * Sections must have unique keys + */ + typedef basic_ini<> ini; +} + +#endif + diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 5c0dd86e..63bf0b06 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -997,7 +997,7 @@ void CHud::Draw() } else { BigMessageAlpha[0] = 0.0f; - BigMessageX[0] = SCALE_AND_CENTER_X(-60.0f); + BigMessageX[0] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f); BigMessageInUse[0] = 1.0f; } } @@ -1008,7 +1008,7 @@ void CHud::Draw() // WastedBustedText if (m_BigMessage[2][0]) { if (BigMessageInUse[2] != 0.0f) { - BigMessageAlpha[2] += (CTimer::GetTimeStepInSeconds() * 255.0f); + BigMessageAlpha[2] += (CTimer::GetTimeStepInMilliseconds() * 0.4f); if (BigMessageAlpha[2] > 255.0f) BigMessageAlpha[2] = 255.0f; @@ -1261,7 +1261,7 @@ void CHud::DrawAfterFade() } break; case 2: - OddJob2Timer += (20.0f * CTimer::GetTimeStep()); + OddJob2Timer += CTimer::GetTimeStepInMilliseconds(); if (OddJob2Timer > 1500) { OddJob2On = 3; } @@ -1355,7 +1355,7 @@ void CHud::DrawAfterFade() } else { BigMessageAlpha[1] = 0.0f; - BigMessageX[1] = SCALE_AND_CENTER_X(-60.0f); + BigMessageX[1] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f); BigMessageInUse[1] = 1.0f; } } diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 69600385..1635781b 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -67,6 +67,10 @@ void CapturePad(RwInt32 padID); void joysChangeCB(int jid, int event); #endif +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS +extern char gSelectedJoystickName[128]; +#endif + enum eGameState { GS_START_UP = 0, diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index b9dbf5ac..944e87b5 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -87,6 +87,11 @@ long _dwOperatingSystemVersion; #include #include #endif + +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS +char gSelectedJoystickName[128] = ""; +#endif + /* ***************************************************************************** */ @@ -822,31 +827,19 @@ void joysChangeCB(int jid, int event); bool IsThisJoystickBlacklisted(int i) { +#ifndef DONT_TRUST_RECOGNIZED_JOYSTICKS + return false; +#else if (glfwJoystickIsGamepad(i)) return false; const char* joyname = glfwGetJoystickName(i); - // this is just a keyboard and mouse - // Microsoft Microsoft® 2.4GHz Transceiver v8.0 Consumer Control - // Microsoft Microsoft® 2.4GHz Transceiver v8.0 System Control - if (strstr(joyname, "2.4GHz Transceiver")) - return true; - // COMPANY USB Device System Control - // COMPANY USB Device Consumer Control - if (strstr(joyname, "COMPANY USB")) - return true; - // i.e. Synaptics TM2438-005 - if (strstr(joyname, "Synaptics ")) - return true; - // i.e. ELAN Touchscreen - if (strstr(joyname, "ELAN ")) - return true; - // i.e. Primax Electronics, Ltd HP Wireless Keyboard Mouse Kit Consumer Control - if (strstr(joyname, "Keyboard")) - return true; + if (strncmp(joyname, gSelectedJoystickName, sizeof(gSelectedJoystickName)) == 0) + return false; - return false; + return true; +#endif } void _InputInitialiseJoys() @@ -865,6 +858,7 @@ void _InputInitialiseJoys() if (PSGLOBAL(joy1id) != -1) { int count; glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); + strcpy(gSelectedJoystickName, glfwGetJoystickName(PSGLOBAL(joy1id))); ControlsManager.InitDefaultControlConfigJoyPad(count); } } @@ -2070,18 +2064,18 @@ void CapturePad(RwInt32 padID) void joysChangeCB(int jid, int event) { - if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) - { - if (PSGLOBAL(joy1id) == -1) + if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) { + if (PSGLOBAL(joy1id) == -1) { PSGLOBAL(joy1id) = jid; - else if (PSGLOBAL(joy2id) == -1) + strcpy(gSelectedJoystickName, glfwGetJoystickName(jid)); + } else if (PSGLOBAL(joy2id) == -1) PSGLOBAL(joy2id) = jid; - } - else if (event == GLFW_DISCONNECTED) - { - if (PSGLOBAL(joy1id) == jid) + + } else if (event == GLFW_DISCONNECTED) { + if (PSGLOBAL(joy1id) == jid) { PSGLOBAL(joy1id) = -1; - else if (PSGLOBAL(joy2id) == jid) + strcpy(gSelectedJoystickName, ""); + } else if (PSGLOBAL(joy2id) == jid) PSGLOBAL(joy2id) = -1; } } diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index 5de478b7..338eaba4 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -74,11 +74,12 @@ void CCarGenerator::DoInternalProcessing() } m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pBoat); }else{ - bool groundFound = false; + bool groundFound; CVector pos = m_vecPos; if (pos.z > -100.0f){ pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &groundFound); }else{ + groundFound = false; CColPoint cp; CEntity* pEntity; groundFound = CWorld::ProcessVerticalLine(CVector(pos.x, pos.y, 1000.0f), -1000.0f, @@ -89,7 +90,12 @@ void CCarGenerator::DoInternalProcessing() if (!groundFound) { debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y); }else{ - CAutomobile* pCar = new CAutomobile(m_nModelIndex, PARKED_VEHICLE); + CAutomobile* pCar; + + // So game crashes if it's bike :D + if (((CVehicleModelInfo*)CModelInfo::GetModelInfo(m_nModelIndex))->m_vehicleType != VEHICLE_TYPE_BIKE) + pCar = new CAutomobile(m_nModelIndex, PARKED_VEHICLE); + pCar->bIsStatic = false; pCar->bEngineOn = false; pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel(); From 3bd333022778cee8dd95b58b02a7263870546c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 2 Oct 2020 17:36:56 +0300 Subject: [PATCH 2/5] Load and write our settings in re3.ini & fixes --- src/core/Frontend.cpp | 37 +++-------- src/core/Game.cpp | 5 ++ src/core/common.h | 4 +- src/core/config.h | 7 ++- src/core/main.h | 5 ++ src/core/re3.cpp | 113 +++++++++++++++++++++++++++------- src/extras/frontendoption.cpp | 6 +- src/extras/frontendoption.h | 10 +-- src/skel/crossplatform.cpp | 10 +++ src/skel/glfw/glfw.cpp | 27 ++++---- src/skel/win/win.cpp | 2 +- src/text/Text.cpp | 2 +- 12 files changed, 150 insertions(+), 78 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 2cb27730..db3774a7 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -3450,21 +3450,6 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1); -/* -#ifdef CUSTOM_FRONTEND_OPTIONS - for (int i = 0; i < numCustomFrontendOptions; i++) { - FrontendOption& option = customFrontendOptions[i]; - if (option.save) { - CFileMgr::Read(fileHandle, (char*)option.value, 1); - option.lastSavedValue = option.displayedValue = *option.value; - } - } -#endif -#ifdef NO_ISLAND_LOADING - CFileMgr::Read(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1); - CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading; -#endif -*/ } } @@ -3481,8 +3466,11 @@ CMenuManager::LoadSettings() m_bLanguageLoaded = false; else { m_bLanguageLoaded = true; + // Already called in InitialiseChangedLanguageSettings + /* TheText.Unload(); TheText.Load(); + */ m_bFrontEnd_ReloadObrTxtGxt = true; InitialiseChangedLanguageSettings(); @@ -3555,23 +3543,14 @@ CMenuManager::SaveSettings() CFileMgr::Write(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1); -/* -#ifdef CUSTOM_FRONTEND_OPTIONS - for (int i = 0; i < numCustomFrontendOptions; i++) { - FrontendOption &option = customFrontendOptions[i]; - if (option.save) { - CFileMgr::Write(fileHandle, (char*)option.value, 1); - } - } -#endif -#ifdef NO_ISLAND_LOADING - CFileMgr::Write(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1); -#endif -*/ } CFileMgr::CloseFile(fileHandle); CFileMgr::SetDir(""); + +#ifdef LOAD_INI_SETTINGS + SaveINISettings(); +#endif } bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); @@ -6332,4 +6311,4 @@ CMenuManager::ConstructStatLine(int rowIdx) #undef GetBackJustDown #undef ChangeScreen -#endif \ No newline at end of file +#endif diff --git a/src/core/Game.cpp b/src/core/Game.cpp index bb9df1a2..93f0d1b0 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -295,9 +295,14 @@ bool CGame::InitialiseOnceAfterRW(void) CWorld::Players[0].SetPlayerSkin(CMenuManager::m_PrefsSkinFile); #ifdef CUSTOM_FRONTEND_OPTIONS + // Apparently this func. can be run multiple times at the start. if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) { + // needs stored language and TheText to be loaded, and last TheText reload is at the start of here CustomFrontendOptionsPopulate(); } +#endif +#ifdef LOAD_INI_SETTINGS + LoadINISettings(); // needs frontend options to be loaded #endif return true; } diff --git a/src/core/common.h b/src/core/common.h index 9b5c2369..ef3da265 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -219,6 +219,8 @@ public: extern int strcasecmp(const char *str1, const char *str2); #endif +extern wchar *AllocUnicode(const char*src); + #define clamp(v, low, high) ((v)<(low) ? (low) : (v)>(high) ? (high) : (v)) inline float sq(float x) { return x*x; } @@ -444,4 +446,4 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value) assert(ReadSaveBuf(buf) == size); -void cprintf(char*, ...); \ No newline at end of file +void cprintf(char*, ...); diff --git a/src/core/config.h b/src/core/config.h index 0f3cb2ef..171c6be9 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -198,6 +198,7 @@ enum Config { #define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more #define MORE_LANGUAGES // Add more translations to the game #define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible +#define LOAD_INI_SETTINGS // Rendering/display #define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios @@ -226,8 +227,8 @@ enum Config { #if !defined(RW_GL3) && defined(_WIN32) #define XINPUT #endif -#if defined(RW_GL3) && !defined(__SWITCH__) // TODO -#define DONT_TRUST_RECOGNIZED_JOYSTICKS // Then we'll only rely on GLFW gamepad DB, and want user to enter Cpntroller->Detect joysticks if his joystick isn't on that list. +#if !defined(_WIN32) && !defined(__SWITCH__) +#define DONT_TRUST_RECOGNIZED_JOYSTICKS // Then we'll only rely on GLFW gamepad DB, and expect user to enter Controller->Detect joysticks if his joystick isn't on that list. #endif #define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m #define KANGAROO_CHEAT @@ -309,4 +310,4 @@ enum Config { #undef NO_ISLAND_LOADING #define PC_PARTICLE #define VC_PED_PORTS // To not process collisions always. But should be tested if that's really beneficial -#endif \ No newline at end of file +#endif diff --git a/src/core/main.h b/src/core/main.h index 96fbef05..7eb080cb 100644 --- a/src/core/main.h +++ b/src/core/main.h @@ -36,3 +36,8 @@ void ResetLoadingScreenBar(void); #ifndef MASTER void TheModelViewer(void); #endif + +#ifdef LOAD_INI_SETTINGS +void LoadINISettings(); +void SaveINISettings(); +#endif diff --git a/src/core/re3.cpp b/src/core/re3.cpp index b892ca36..069320ec 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -1,6 +1,7 @@ #include #define WITHWINDOWS #include "common.h" +#include "platform.h" #include "crossplatform.h" #include "Renderer.h" #include "Credits.h" @@ -16,7 +17,6 @@ #include "Heli.h" #include "Automobile.h" #include "Ped.h" -#include "Particle.h" #include "Console.h" #include "Debug.h" #include "Hud.h" @@ -32,15 +32,12 @@ #include "MBlur.h" #include "postfx.h" #include "custompipes.h" -#include "ControllerConfig.h" #ifndef _WIN32 #include "assert.h" #include #endif -#include - #ifdef RWLIBS extern "C" int vsprintf(char* const _Buffer, char const* const _Format, va_list _ArgList); #endif @@ -74,7 +71,6 @@ mysrand(unsigned int seed) #ifdef CUSTOM_FRONTEND_OPTIONS #include "frontendoption.h" -#include "platform.h" #include "Font.h" void ReloadFrontendOptions(void) @@ -196,7 +192,7 @@ wchar* MultiSamplingDraw(bool *disabled, bool userHovering) { return unicodeTemp; } } -char* multisamplingKey = "MultiSampling"; +const char* multisamplingKey = "MultiSampling"; #endif #ifdef MORE_LANGUAGES @@ -249,8 +245,7 @@ void FreeCamChange(int8 displayedValue) TheCamera.bFreeCam = !!displayedValue; FrontEndMenuManager.SaveSettings(); } -const wchar* freeCamText = (wchar*)L"FREE CAM"; -char* freeCamKey = "FreeCam"; +const char* freeCamKey = "FreeCam"; #endif #ifdef CUTSCENE_BORDERS_SWITCH @@ -259,7 +254,7 @@ void BorderModeChange(int8 displayedValue) CMenuManager::m_PrefsCutsceneBorders = !!displayedValue; FrontEndMenuManager.SaveSettings(); } -char* cutsceneBordersKey = "CutsceneBorders"; +const char* cutsceneBordersKey = "CutsceneBorders"; #endif #ifdef PS2_ALPHA_TEST @@ -268,13 +263,10 @@ void PS2AlphaTestChange(int8 displayedValue) gPS2alphaTest = !!displayedValue; FrontEndMenuManager.SaveSettings(); } -char* ps2alphaKey = "PS2AlphaTest"; +const char* ps2alphaKey = "PS2AlphaTest"; #endif #ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS -const wchar* detectJoystickText = (wchar*)L"Detect Joystick"; -const wchar* detectJoystickExplanation = (wchar*)L"Press any key on your preferred joystick that you would like to use on the game."; -const wchar* detectedJoystickText = (wchar*)L"Detected Joystick"; wchar selectedJoystickUnicode[128]; wchar* DetectJoystickDraw(bool* disabled, bool userHovering) { @@ -287,7 +279,6 @@ wchar* DetectJoystickDraw(bool* disabled, bool userHovering) { const uint8* buttons = glfwGetJoystickButtons(i, &numButtons); for (int j = 0; j < numButtons; j++) { if (buttons[j]) { - strcpy(gSelectedJoystickName, joyname); found = i; break; } @@ -303,17 +294,21 @@ wchar* DetectJoystickDraw(bool* disabled, bool userHovering) { else PSGLOBAL(joy2id) = -1; + strcpy(gSelectedJoystickName, joyname); PSGLOBAL(joy1id) = found; } } - AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode); + if (PSGLOBAL(joy1id) == -1) + AsciiToUnicode("Not found", selectedJoystickUnicode); + else + AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode); return selectedJoystickUnicode; } #endif // Important: Make sure to read the warnings/informations in frontendoption.h!! -// If you won't use GXT entry as text, you may want to declare them globally, to not alloc them on each reload. (static declared texts has some problems on Linux etc.) +// If you will hardcode any text, please use AllocUnicode! wchar_t size differs between platforms void CustomFrontendOptionsPopulate(void) { @@ -416,7 +411,7 @@ CustomFrontendOptionsPopulate(void) #ifdef FREE_CAM SWITCH_TO_DISPLAY_MENU - FrontendOptionAddSelect(freeCamText, off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, freeCamKey); + FrontendOptionAddSelect(TheText.Get("FEC_FRC"), off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, freeCamKey); #endif CLONE_OPTION(TheText.Get("FED_SUB"), MENUACTION_SUBTITLES, nil, nil); @@ -433,24 +428,96 @@ CustomFrontendOptionsPopulate(void) #endif ADD_RESTORE_DEFAULTS(RestoreDefDisplay) - ADD_BACK + ADD_BACK #ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS - int detectJoystickMenu = FrontendScreenAdd("FET_CON", MENUSPRITE_MAINMENU, MENUPAGE_CONTROLLER_PC, 50, 60, 20, + int detectJoystickMenu = FrontendScreenAdd("FEC_JOD", MENUSPRITE_MAINMENU, MENUPAGE_CONTROLLER_PC, 40, 60, 20, FONT_BANK, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, false); FrontendOptionSetCursor(detectJoystickMenu, 0); - FrontendOptionAddBuiltinAction(detectJoystickExplanation, MENUACTION_LABEL, nil, nil); - FrontendOptionAddDynamic(detectedJoystickText, DetectJoystickDraw, nil, nil, nil); + FrontendOptionAddBuiltinAction(TheText.Get("FEC_JPR"), MENUACTION_LABEL, nil, nil); + FrontendOptionAddDynamic(TheText.Get("FEC_JDE"), DetectJoystickDraw, nil, nil, nil); FrontendOptionAddBackButton(TheText.Get("FEDS_TB")); FrontendOptionSetCursor(MENUPAGE_CONTROLLER_PC, 2); - FrontendOptionAddRedirect(detectJoystickText, detectJoystickMenu, 1); + FrontendOptionAddRedirect(TheText.Get("FEC_JOD"), detectJoystickMenu, 1); #endif } #endif +#ifdef LOAD_INI_SETTINGS +#include "ini_parser.hpp" +void LoadINISettings() +{ + linb::ini cfg; + cfg.load_file("re3.ini"); + char defaultStr[4]; + +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + strcpy(gSelectedJoystickName, cfg.get("DetectJoystick", "JoystickName", "").c_str()); + _InputInitialiseJoys(); +#endif + +#ifdef CUSTOM_FRONTEND_OPTIONS + for (int i = 0; i < numCustomFrontendOptions; i++) { + FrontendOption& option = customFrontendOptions[i]; + if (option.save) { + // CFO only supports saving uint8 right now + sprintf(defaultStr, "%u", *option.value); + option.lastSavedValue = option.displayedValue = *option.value = atoi(cfg.get("FrontendOptions", option.save, defaultStr).c_str()); + } + } +#endif + +#ifdef NO_ISLAND_LOADING + sprintf(defaultStr, "%u", CMenuManager::m_PrefsIslandLoading); + CMenuManager::m_PrefsIslandLoading = atoi(cfg.get("FrontendOptions", "NoIslandLoading", defaultStr).c_str()); + CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading; +#endif + +} + +void SaveINISettings() +{ + linb::ini cfg; + cfg.load_file("re3.ini"); + bool changed = false; + char temp[4]; + +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + if (strncmp(cfg.get("DetectJoystick", "JoystickName", "").c_str(), gSelectedJoystickName, strlen(gSelectedJoystickName)) != 0) { + changed = true; + cfg.set("DetectJoystick", "JoystickName", gSelectedJoystickName); + } +#endif +#ifdef CUSTOM_FRONTEND_OPTIONS + for (int i = 0; i < numCustomFrontendOptions; i++) { + FrontendOption &option = customFrontendOptions[i]; + if (option.save) { + if (atoi(cfg.get("FrontendOptions", option.save, "xxx").c_str()) != *option.value) { // if .ini doesn't have that key compare with xxx, so we can add it + changed = true; + sprintf(temp, "%u", *option.value); + cfg.set("FrontendOptions", option.save, temp); + } + } + } +#endif +#ifdef NO_ISLAND_LOADING + if (atoi(cfg.get("FrontendOptions", "NoIslandLoading", "xxx").c_str()) != CMenuManager::m_PrefsIslandLoading) { + changed = true; + sprintf(temp, "%u", CMenuManager::m_PrefsIslandLoading); + cfg.set("FrontendOptions", "NoIslandLoading", temp); + } +#endif + + if (changed) + cfg.write_file("re3.ini"); +} + +#endif + + #ifdef DEBUGMENU void WeaponCheat(); void HealthCheat(); @@ -598,6 +665,8 @@ static const char *carnames[] = { "yankee", "escape", "borgnine", "toyz", "ghost", }; +//#include + static CTweakVar** TweakVarsList; static int TweakVarsListSize = -1; static bool bAddTweakVarsNow = false; diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp index 70d444de..ed8aa2a9 100644 --- a/src/extras/frontendoption.cpp +++ b/src/extras/frontendoption.cpp @@ -216,7 +216,7 @@ void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPre option.save = nil; } -void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName) +void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName) { int8 screenOptionOrder = RegisterNewOption(); @@ -236,7 +236,7 @@ void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, in option.returnPrevPageFunc = returnPrevPageFunc; } -void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName) +void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName) { int8 screenOptionOrder = RegisterNewOption(); @@ -300,4 +300,4 @@ uint8 FrontendScreenAdd(const char* gxtKey, eMenuSprites sprite, int prevPage, i return screenOrder; } -#endif \ No newline at end of file +#endif diff --git a/src/extras/frontendoption.h b/src/extras/frontendoption.h index f721abb0..dac6be62 100644 --- a/src/extras/frontendoption.h +++ b/src/extras/frontendoption.h @@ -91,11 +91,11 @@ struct FrontendOption int8 type; int8 screenOptionOrder; int32 screen; - wchar leftText[64]; + wchar leftText[128]; ReturnPrevPageFunc returnPrevPageFunc; int8* value; int8 displayedValue; // only if onlyApplyOnEnter enabled for now - char* save; + const char* save; int32 ogOptionId; // for replacements, see overwrite parameter of SetCursor union { @@ -153,10 +153,10 @@ void FrontendOptionSetCursor(int screen, int8 option, bool overwrite = false); // var is optional in AddDynamic, enables you to save them in an INI file(also needs passing char array to saveName param. obv), otherwise pass nil/0 void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc); -void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName = nil); -void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName = nil); +void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName = nil); +void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName = nil); void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption = 0, bool fadeIn = true); void FrontendOptionAddBackButton(const wchar* text, bool fadeIn = true); uint8 FrontendScreenAdd(const char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight, int8 font, float fontScaleX, float fontScaleY, int8 alignment, bool showLeftRightHelper, ReturnPrevPageFunc returnPrevPageFunc = nil); -#endif \ No newline at end of file +#endif diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 6188992d..452ad9fa 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -84,6 +84,16 @@ void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) { } #endif +// Because wchar length differs between platforms. +wchar* +AllocUnicode(const char* src) +{ + wchar *dst = (wchar*)malloc(strlen(src)*2 + 2); + wchar *i = dst; + while((*i++ = (unsigned char)*src++) != '\0'); + return dst; +} + // Funcs/features from Windows that we need on other platforms #ifndef _WIN32 char *strupr(char *s) { diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 944e87b5..cd8380b2 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -41,7 +41,6 @@ #include "AnimViewer.h" #include "Font.h" - #define MAX_SUBSYSTEMS (16) @@ -425,6 +424,10 @@ psInitialize(void) _dwOperatingSystemVersion = OS_WIN95; } } +#else + _dwOperatingSystemVersion = OS_WINXP; // To fool other classes +#endif + #ifndef PS2_MENU @@ -434,6 +437,8 @@ psInitialize(void) #endif + +#ifdef _WIN32 MEMORYSTATUS memstats; GlobalMemoryStatus(&memstats); @@ -442,20 +447,10 @@ psInitialize(void) debug("Physical memory size %u\n", memstats.dwTotalPhys); debug("Available physical memory %u\n", memstats.dwAvailPhys); #else - -#ifndef PS2_MENU - -#ifdef GTA3_1_1_PATCH - FrontEndMenuManager.LoadSettings(); -#endif - -#endif struct sysinfo systemInfo; sysinfo(&systemInfo); _dwMemAvailPhys = systemInfo.freeram; - _dwOperatingSystemVersion = OS_WINXP; // To fool other classes - debug("Physical memory size %u\n", systemInfo.totalram); debug("Available physical memory %u\n", systemInfo.freeram); @@ -835,7 +830,7 @@ bool IsThisJoystickBlacklisted(int i) const char* joyname = glfwGetJoystickName(i); - if (strncmp(joyname, gSelectedJoystickName, sizeof(gSelectedJoystickName)) == 0) + if (strncmp(joyname, gSelectedJoystickName, strlen(gSelectedJoystickName)) == 0) return false; return true; @@ -844,6 +839,9 @@ bool IsThisJoystickBlacklisted(int i) void _InputInitialiseJoys() { + PSGLOBAL(joy1id) = -1; + PSGLOBAL(joy2id) = -1; + for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { if (glfwJoystickPresent(i) && !IsThisJoystickBlacklisted(i)) { if (PSGLOBAL(joy1id) == -1) @@ -858,7 +856,9 @@ void _InputInitialiseJoys() if (PSGLOBAL(joy1id) != -1) { int count; glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS strcpy(gSelectedJoystickName, glfwGetJoystickName(PSGLOBAL(joy1id))); +#endif ControlsManager.InitDefaultControlConfigJoyPad(count); } } @@ -2067,14 +2067,15 @@ void joysChangeCB(int jid, int event) if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) { if (PSGLOBAL(joy1id) == -1) { PSGLOBAL(joy1id) = jid; +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS strcpy(gSelectedJoystickName, glfwGetJoystickName(jid)); +#endif } else if (PSGLOBAL(joy2id) == -1) PSGLOBAL(joy2id) = jid; } else if (event == GLFW_DISCONNECTED) { if (PSGLOBAL(joy1id) == jid) { PSGLOBAL(joy1id) = -1; - strcpy(gSelectedJoystickName, ""); } else if (PSGLOBAL(joy2id) == jid) PSGLOBAL(joy2id) = -1; } diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 119e666e..ac46d23a 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -3378,4 +3378,4 @@ int strcasecmp(const char *str1, const char *str2) return _strcmpi(str1, str2); } #endif -#endif \ No newline at end of file +#endif diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 1f6cda89..a4f2af7f 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -354,4 +354,4 @@ void TextCopy(wchar *dst, const wchar *src) { while((*dst++ = *src++) != '\0'); -} \ No newline at end of file +} From 0ac2be00934ce3789d87ce4efb8b991f308de521 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Sat, 3 Oct 2020 16:17:24 +0200 Subject: [PATCH 3/5] Fix unsigned comparison in CStreaming::MakeSpaceFor(int32 size) --- src/core/Streaming.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 507815fa..4e12ab6d 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -2436,12 +2436,17 @@ CStreaming::DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem) void CStreaming::MakeSpaceFor(int32 size) { - // BUG: ms_memoryAvailable can be uninitialized - // the code still happens to work in that case because ms_memoryAvailable is unsigned - // but it's not nice.... - +#ifdef FIX_BUGS +#define MB (1024 * 1024) + if(ms_memoryAvailable == 0) { + extern size_t _dwMemAvailPhys; + ms_memoryAvailable = (_dwMemAvailPhys - 10 * MB) / 2; + if(ms_memoryAvailable < 50 * MB) ms_memoryAvailable = 50 * MB; + } +#undef MB +#endif while(ms_memoryUsed >= ms_memoryAvailable - size) - if(!RemoveLeastUsedModel()){ + if(!RemoveLeastUsedModel()) { DeleteRwObjectsBehindCamera(ms_memoryAvailable - size); return; } From 1a0b71bd47fc181ea7e8042e0faa35eb7f94cac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 5 Oct 2020 13:59:40 +0300 Subject: [PATCH 4/5] Fix Audio --- src/audio/oal/stream.cpp | 12 ++++++------ src/audio/oal/stream.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index eeaaafb0..c4f1b67c 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -155,13 +155,13 @@ public: void Seek(uint32 milliseconds) { if ( !IsOpened() ) return; - mpg123_seek(m_pMH, ms2samples(milliseconds)*GetSampleSize(), SEEK_SET); + mpg123_seek(m_pMH, ms2samples(milliseconds), SEEK_SET); } uint32 Tell() { if ( !IsOpened() ) return 0; - return samples2ms(mpg123_tell(m_pMH)/GetSampleSize()); + return samples2ms(mpg123_tell(m_pMH)); } uint32 Decode(void *buffer) @@ -247,13 +247,13 @@ public: void Seek(uint32 milliseconds) { if ( !IsOpened() ) return; - op_pcm_seek(m_FileH, ms2samples(milliseconds) * GetSampleSize()); + op_pcm_seek(m_FileH, ms2samples(milliseconds) / GetChannels()); } uint32 Tell() { if ( !IsOpened() ) return 0; - return samples2ms(op_pcm_tell(m_FileH)/GetSampleSize()); + return samples2ms(op_pcm_tell(m_FileH) * GetChannels()); } uint32 Decode(void *buffer) @@ -461,8 +461,8 @@ uint32 CStream::GetPosMS() alGetSourcei(m_alSource, AL_BYTE_OFFSET, &offset); return m_pSoundFile->Tell() - - m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS-1)) - + m_pSoundFile->samples2ms(offset/m_pSoundFile->GetSampleSize()); + - m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS-1)) / m_pSoundFile->GetChannels() + + m_pSoundFile->samples2ms(offset/m_pSoundFile->GetSampleSize()) / m_pSoundFile->GetChannels(); } uint32 CStream::GetLengthMS() diff --git a/src/audio/oal/stream.h b/src/audio/oal/stream.h index 456c080a..2476abcc 100644 --- a/src/audio/oal/stream.h +++ b/src/audio/oal/stream.h @@ -24,12 +24,12 @@ public: uint32 ms2samples(uint32 ms) { - return float(ms) / 1000.0f * float(GetChannels()) * float(GetSampleRate()); + return float(ms) / 1000.0f * float(GetSampleRate()); } uint32 samples2ms(uint32 sm) { - return float(sm) * 1000.0f / float(GetChannels()) / float(GetSampleRate()); + return float(sm) * 1000.0f / float(GetSampleRate()); } uint32 GetBufferSamples() @@ -108,4 +108,4 @@ public: void ProviderTerm(); }; -#endif \ No newline at end of file +#endif From ee27cae7325e69a4f0d29698c01f686fd2ca6c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 5 Oct 2020 01:25:56 +0300 Subject: [PATCH 5/5] Fix Linux audio path --- src/audio/sampman_oal.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index b10aa1ff..9f3156cb 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -27,6 +27,7 @@ #include "MusicManager.h" #include "Frontend.h" #include "Timer.h" +#include "crossplatform.h" #ifdef AUDIO_OPUS #include #endif @@ -1423,11 +1424,11 @@ cSampleManager::InitialiseSampleBanks(void) { int32 nBank = SFX_BANK_0; - fpSampleDescHandle = fopen(SampleBankDescFilename, "rb"); + fpSampleDescHandle = fcaseopen(SampleBankDescFilename, "rb"); if ( fpSampleDescHandle == NULL ) return false; #ifndef AUDIO_OPUS - fpSampleDataHandle = fopen(SampleBankDataFilename, "rb"); + fpSampleDataHandle = fcaseopen(SampleBankDataFilename, "rb"); if ( fpSampleDataHandle == NULL ) { fclose(fpSampleDescHandle);