From fccb353e70b7c45257da8f5823168cf2d01cb598 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Sun, 19 Nov 2023 21:30:11 +0100 Subject: [PATCH 1/9] Fix crash in audio settings when --no-audio is passed. Fix build error when PLAYER_AUDIO_BACKEND is OFF. Fix #3116 --- src/audio.cpp | 5 ++--- src/platform/sdl/sdl2_ui.cpp | 11 ++++------- src/platform/sdl/sdl2_ui.h | 2 ++ src/platform/sdl/sdl_ui.cpp | 2 -- src/platform/sdl/sdl_ui.h | 2 ++ src/scene_settings.cpp | 16 +++++++++++++++- src/window_settings.cpp | 6 +++--- 7 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/audio.cpp b/src/audio.cpp index 6169ba4206..0ce51b1f0e 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -50,9 +50,8 @@ int EmptyAudio::BGM_GetTicks() const { return (Player::GetFrames() - bgm_starttick + 1) / Game_Clock::GetTargetGameFps(); } -void EmptyAudio::vGetConfig(Game_ConfigAudio& cfg) const { - cfg.music_volume.SetOptionVisible(false); - cfg.sound_volume.SetOptionVisible(false); +void EmptyAudio::vGetConfig(Game_ConfigAudio&) const { + // Not supported. The audio menu is disabled. } bool EmptyAudio::BGM_PlayedOnce() const { diff --git a/src/platform/sdl/sdl2_ui.cpp b/src/platform/sdl/sdl2_ui.cpp index f51d3b0942..7b7900cb8c 100644 --- a/src/platform/sdl/sdl2_ui.cpp +++ b/src/platform/sdl/sdl2_ui.cpp @@ -41,14 +41,13 @@ #include "bitmap.h" #include "lcf/scope_guard.h" +#if defined(__APPLE__) && TARGET_OS_OSX +# include "platform/macos/macos_utils.h" +#endif + #ifdef SUPPORT_AUDIO # include "sdl_audio.h" -# if defined(__APPLE__) && TARGET_OS_OSX -# include "platform/macos/macos_utils.h" -# endif - - AudioInterface& Sdl2Ui::GetAudio() { return *audio_; } @@ -170,8 +169,6 @@ Sdl2Ui::Sdl2Ui(long width, long height, const Game_Config& cfg) : BaseUi(cfg) audio_ = std::make_unique(cfg.audio); return; } -#else - audio_ = std::make_unique(cfg.audio); #endif } diff --git a/src/platform/sdl/sdl2_ui.h b/src/platform/sdl/sdl2_ui.h index 976c691794..c9543f2aa9 100644 --- a/src/platform/sdl/sdl2_ui.h +++ b/src/platform/sdl/sdl2_ui.h @@ -143,7 +143,9 @@ class Sdl2Ui final : public BaseUi { uint32_t texture_format = SDL_PIXELFORMAT_UNKNOWN; +#ifdef SUPPORT_AUDIO std::unique_ptr audio_; +#endif }; #endif diff --git a/src/platform/sdl/sdl_ui.cpp b/src/platform/sdl/sdl_ui.cpp index dc8cee1b42..7d7f96ef65 100644 --- a/src/platform/sdl/sdl_ui.cpp +++ b/src/platform/sdl/sdl_ui.cpp @@ -175,8 +175,6 @@ SdlUi::SdlUi(long width, long height, const Game_Config& cfg) : BaseUi(cfg) audio_ = std::make_unique(cfg.audio); return; } -#else - audio_ = std::make_unique(cfg.audio); #endif } diff --git a/src/platform/sdl/sdl_ui.h b/src/platform/sdl/sdl_ui.h index 909f758cd9..c396a88645 100644 --- a/src/platform/sdl/sdl_ui.h +++ b/src/platform/sdl/sdl_ui.h @@ -127,7 +127,9 @@ class SdlUi final : public BaseUi { /** SDL_Surface handle to main_surface */ SDL_Surface* main_surface_sdl; +#ifdef SUPPORT_AUDIO std::unique_ptr audio_; +#endif SdlAxis sdl_axis; }; diff --git a/src/scene_settings.cpp b/src/scene_settings.cpp index c50ca8123f..4d244816d4 100644 --- a/src/scene_settings.cpp +++ b/src/scene_settings.cpp @@ -77,6 +77,13 @@ void Scene_Settings::CreateMainWindow() { main_window->SetHeight(176); main_window->SetY((Player::screen_height - main_window->GetHeight()) / 2); main_window->SetX((Player::screen_width - main_window->GetWidth()) / 2); + + if (Player::no_audio_flag) { + main_window->SetItemEnabled(1, !Player::no_audio_flag); + } +#ifndef SUPPORT_AUDIO + main_window->DisableItem(1); +#endif } void Scene_Settings::CreateOptionsWindow() { @@ -288,6 +295,13 @@ void Scene_Settings::UpdateMain() { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Game_System::SFX_Decision)); auto idx = main_window->GetIndex(); + if (main_window->IsItemEnabled(idx)) { + Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Game_System::SFX_Decision)); + } else { + Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Game_System::SFX_Buzzer)); + return; + } + if (modes[idx] == Window_Settings::eSave) { SaveConfig(); return; @@ -560,7 +574,7 @@ bool Scene_Settings::SaveConfig(bool silent) { Game_Config cfg; cfg.video = DisplayUi->GetConfig(); - cfg.audio = DisplayUi->GetAudio().GetConfig(); + cfg.audio = Audio().GetConfig(); cfg.input = Input::GetInputSource()->GetConfig(); cfg.player = Player::player_config; diff --git a/src/window_settings.cpp b/src/window_settings.cpp index f8c423e81b..e2b27cd3df 100644 --- a/src/window_settings.cpp +++ b/src/window_settings.cpp @@ -261,10 +261,10 @@ void Window_Settings::RefreshVideo() { } void Window_Settings::RefreshAudio() { - auto cfg = DisplayUi->GetAudio().GetConfig(); + auto cfg = Audio().GetConfig(); - AddOption(cfg.music_volume, [this](){ DisplayUi->GetAudio().BGM_SetGlobalVolume(GetCurrentOption().current_value); }); - AddOption(cfg.sound_volume, [this](){ DisplayUi->GetAudio().SE_SetGlobalVolume(GetCurrentOption().current_value); }); + AddOption(cfg.music_volume, [this](){ Audio().BGM_SetGlobalVolume(GetCurrentOption().current_value); }); + AddOption(cfg.sound_volume, [this](){ Audio().SE_SetGlobalVolume(GetCurrentOption().current_value); }); /*AddOption("Midi Backend", LockedConfigParam("Unknown"), "", [](){}, "Which MIDI backend to use"); From b478eb982a8388cfe7a0aa6b49ca2a1f2d794f26 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Sun, 19 Nov 2023 21:30:54 +0100 Subject: [PATCH 2/9] Config: Simplify code that displays help text for the FF multiplier --- src/input_buttons.h | 4 ++-- src/window_settings.cpp | 29 ++++++++++++----------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/input_buttons.h b/src/input_buttons.h index 2d9b420af9..286031fc90 100644 --- a/src/input_buttons.h +++ b/src/input_buttons.h @@ -172,8 +172,8 @@ namespace Input { "Middle mouse key", "Scroll up key", "Scroll down key", - "PLACEHOLDER", - "PLACEHOLDER", + "Run the game at x{} speed", + "Run the game at x{} speed", "Toggle Fullscreen mode", "Toggle Window Zoom level", "Total Button Count"); diff --git a/src/window_settings.cpp b/src/window_settings.cpp index e2b27cd3df..671aeb3b3c 100644 --- a/src/window_settings.cpp +++ b/src/window_settings.cpp @@ -276,7 +276,7 @@ void Window_Settings::RefreshAudio() { void Window_Settings::RefreshEngine() { auto& cfg = Player::player_config; - // FIXME: Binding &cfg is not needed and generates a warning but requires it + // FIXME: Binding &cfg is not needed and generates a warning but MSVC requires it #ifdef _MSC_VER AddOption(cfg.settings_autosave, [&cfg](){ cfg.settings_autosave.Toggle(); }); AddOption(cfg.settings_in_title, [&cfg](){ cfg.settings_in_title.Toggle(); }); @@ -391,15 +391,6 @@ void Window_Settings::RefreshButtonCategory() { [this]() { Push(eInputListButtonsDeveloper, 2); }); } -const char * GetFastForwardDescription(int index){ - Game_ConfigInput& cfg = Input::GetInputSource()->GetConfig(); - RangeConfigParam config_arr[] = {cfg.speed_modifier_a, cfg.speed_modifier_b}; - static char fast_forward_strs[2][64]; - - snprintf(fast_forward_strs[index], sizeof(fast_forward_strs[index]), "Run the game at x%i speed", config_arr[index].Get()); - return fast_forward_strs[index]; -} - void Window_Settings::RefreshButtonList() { auto& mappings = Input::GetInputSource()->GetButtonMappings(); auto custom_names = Input::GetInputKeyNames(); @@ -443,8 +434,8 @@ void Window_Settings::RefreshButtonList() { } } - auto help = Input::kButtonHelp.tag(button); - std::string value = ""; + std::string help = Input::kButtonHelp.tag(button); + std::string value; // Append as many buttons as fit on the screen, then add ... int contents_w = GetContents()->width(); @@ -477,13 +468,17 @@ void Window_Settings::RefreshButtonList() { value_size += cur_value_size; } - switch(button){ - case Input::FAST_FORWARD_A: - help = GetFastForwardDescription(0); + switch (button) { + case Input::FAST_FORWARD_A: { + Game_ConfigInput& cfg = Input::GetInputSource()->GetConfig(); + help = fmt::format(help, cfg.speed_modifier_a.Get()); break; - case Input::FAST_FORWARD_B: - help = GetFastForwardDescription(1); + } + case Input::FAST_FORWARD_B: { + Game_ConfigInput& cfg = Input::GetInputSource()->GetConfig(); + help = fmt::format(help, cfg.speed_modifier_b.Get()); break; + } default: break; } From 55d8c98bdaa4ae09017b11744148dc508d8274bf Mon Sep 17 00:00:00 2001 From: Ghabry Date: Sun, 19 Nov 2023 21:39:18 +0100 Subject: [PATCH 3/9] Do not reload the chipset, except when using RPG2k3E. This issue was previously misunderstood and instead tile substitution was not reloaded. This part now reverted. Fix #3042 --- src/game_map.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/game_map.cpp b/src/game_map.cpp index d06bdc0595..29858b3133 100644 --- a/src/game_map.cpp +++ b/src/game_map.cpp @@ -226,13 +226,6 @@ void Game_Map::SetupFromSave( map = std::move(map_in); map_info = std::move(save_map); - - if (!Player::IsRPG2k3E()) { - // RPG_RT bug: Substitutions are not loaded except in 2k3E - std::iota(map_info.lower_tiles.begin(), map_info.lower_tiles.end(), 0); - std::iota(map_info.upper_tiles.begin(), map_info.upper_tiles.end(), 0); - } - panorama = std::move(save_pan); SetupCommon(); @@ -267,7 +260,13 @@ void Game_Map::SetupFromSave( } SetEncounterSteps(map_info.encounter_steps); - SetChipset(map_info.chipset_id); + + // RPG_RT bug: Chipset is not loaded. Fixed in 2k3E + if (Player::IsRPG2k3E()) { + SetChipset(map_info.chipset_id); + } else { + SetChipset(0); + } if (!is_map_save_compat) { panorama = {}; From c2d26817c181be16fc7f849454615bc5f42e3331 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Sun, 19 Nov 2023 21:42:19 +0100 Subject: [PATCH 4/9] Do not reset keys when changing the scene. This breaks debug features in games that rely on keys being held. Partially revert 1f7b29038 Fix #3037 --- src/scene.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/scene.cpp b/src/scene.cpp index 07066ffd87..cdb270fe80 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -204,8 +204,6 @@ void Scene::MainFunction() { TransitionOut(next_scene); } - Input::ResetNonSystemKeys(); - init = false; } } From ee47b70521f44692c7357f8ef63b8f7717621cdc Mon Sep 17 00:00:00 2001 From: Ghabry Date: Mon, 20 Nov 2023 22:28:38 +0100 Subject: [PATCH 5/9] Debug scene: Call Map Event works again Fix #3101 --- src/scene_debug.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scene_debug.cpp b/src/scene_debug.cpp index a6ef94c3d4..209417ea78 100644 --- a/src/scene_debug.cpp +++ b/src/scene_debug.cpp @@ -813,7 +813,7 @@ void Scene_Debug::DoCallCommonEvent() { } void Scene_Debug::DoCallMapEvent() { - if (Scene::Find(Scene::Map) != nullptr) { + if (!Scene::Find(Scene::Map)) { return; } From 008fd3d42176faa8f802c38ff7aabf58b681c929 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Mon, 20 Nov 2023 23:20:22 +0100 Subject: [PATCH 6/9] String Variables: Allow usage of filenames with extensions. The extension list was reduced to the extensions supported by Maniac Patch. --- src/filefinder.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/filefinder.cpp b/src/filefinder.cpp index 475f2560eb..e87679d8c9 100644 --- a/src/filefinder.cpp +++ b/src/filefinder.cpp @@ -68,7 +68,7 @@ namespace { constexpr const auto SOUND_TYPES = Utils::MakeSvArray( ".opus", ".oga", ".ogg", ".wav", ".mp3", ".wma"); constexpr const auto FONTS_TYPES = Utils::MakeSvArray(".fon", ".fnt", ".bdf", ".ttf", ".ttc", ".otf", ".woff2", ".woff"); - constexpr const auto TEXT_TYPES = Utils::MakeSvArray(".txt", ".csv", ".svg", ".xml", ".json", ".yml", ".yaml"); + constexpr const auto TEXT_TYPES = Utils::MakeSvArray(".txt", ".csv", ""); // "" = Complete Filename (incl. extension) provided by the user } FilesystemView FileFinder::Game() { @@ -352,7 +352,7 @@ std::string find_generic(const DirectoryTree::Args& args) { } std::string find_generic_with_fallback(DirectoryTree::Args& args) { - std::string found = FileFinder::Save().FindFile(args); + std::string found = FileFinder::Save().FindFile(args); if (found.empty()) { return find_generic(args); } @@ -406,7 +406,7 @@ Filesystem_Stream::InputStream open_generic(StringView dir, StringView name, Dir } Filesystem_Stream::InputStream open_generic_with_fallback(StringView dir, StringView name, DirectoryTree::Args& args) { - auto is = FileFinder::Save().OpenFile(args); + auto is = FileFinder::Save().OpenFile(args); if (!is) { is = open_generic(dir, name, args); } if (!is) { Output::Debug("Unable to open in either Game or Save: {}/{}", dir, name); From d1ae1c3535cec38685a73f7d7e5295621387157c Mon Sep 17 00:00:00 2001 From: Ghabry Date: Thu, 30 Nov 2023 00:03:47 +0100 Subject: [PATCH 7/9] Emscripten: Only clear finished requests when changing the translation Fix #3165 --- src/async_handler.cpp | 9 +++++++++ src/async_handler.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/async_handler.cpp b/src/async_handler.cpp index ffd5e1a143..bb7fea5104 100644 --- a/src/async_handler.cpp +++ b/src/async_handler.cpp @@ -217,6 +217,15 @@ void AsyncHandler::CreateRequestMapping(const std::string& file) { } void AsyncHandler::ClearRequests() { + auto it = async_requests.begin(); + while (it != async_requests.end()) { + auto& req = *it; + if (it->second.IsReady()) { + it = async_requests.erase(it); + } else { + ++it; + } + } async_requests.clear(); } diff --git a/src/async_handler.h b/src/async_handler.h index 3282cd5822..22848eee9a 100644 --- a/src/async_handler.h +++ b/src/async_handler.h @@ -39,7 +39,7 @@ namespace AsyncHandler { void CreateRequestMapping(const std::string& file); /** - * Clears all requests. They will hit the server again. + * Clears all finished requests. They will hit the server again. * Called after changing the language to ensure the assets are replaced. */ void ClearRequests(); From 9c22b67a7a40f59cf6d434c27320456726bd6c72 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Thu, 30 Nov 2023 00:05:32 +0100 Subject: [PATCH 8/9] Readd "SetName" to ChangeHeroName command. Was lost during the refactor. Fix #3161 --- src/game_interpreter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index 06d69bc833..a12785e08e 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -2173,6 +2173,7 @@ bool Game_Interpreter::CommandChangeHeroName(lcf::rpg::EventCommand const& com) return true; } + actor->SetName(ToString(CommandStringOrVariableBitfield(com, 1, 1, 2))); return true; } From aa5ac75c78a8959988174bdf31fe6da3fa20070c Mon Sep 17 00:00:00 2001 From: Ghabry Date: Thu, 30 Nov 2023 00:10:15 +0100 Subject: [PATCH 9/9] Strings: Support splitting when the delimiter is empty. This operates on UTF-8 codepoints to ensure it works in most cases. It will break for grapheme clusters but most programming languages will fail here. Fix #3162 --- src/game_strings.cpp | 45 +++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/game_strings.cpp b/src/game_strings.cpp index a7f8437612..351fc43cfa 100644 --- a/src/game_strings.cpp +++ b/src/game_strings.cpp @@ -25,6 +25,7 @@ #include "game_switches.h" #include "game_variables.h" #include "output.h" +#include "utils.h" void Game_Strings::WarnGet(int id) const { Output::Debug("Invalid read strvar[{}]!", id); @@ -104,21 +105,43 @@ int Game_Strings::Split(Str_Params params, const std::string& delimiter, int str return -1; } - size_t index; - std::string token; - - // always returns at least 1 - int splits = 1; + int splits = 0; std::string str = ToString(Get(params.string_id)); params.string_id = string_out_id; - for (index = str.find(delimiter); index != std::string::npos; index = str.find(delimiter)) { - token = str.substr(0, index); - Set(params, token); - params.string_id++; - splits++; - str.erase(0, index + delimiter.length()); + if (delimiter.empty()) { + const char* iter = str.data(); + const auto end = str.data() + str.size(); + + while (iter != end) { + const char* start_copy = iter; + auto ret = Utils::UTF8Next(iter, end); + iter = ret.next; + + if (iter == end) { + break; + } + + Set(params, std::string(start_copy, iter - start_copy)); + + params.string_id++; + splits++; + } + } else { + if (str.find(delimiter) == std::string::npos) { + // token not found -> 1 split + splits = 1; + } else { + std::string token; + for (auto index = str.find(delimiter); index != std::string::npos; index = str.find(delimiter)) { + token = str.substr(0, index); + Set(params, token); + params.string_id++; + splits++; + str.erase(0, index + delimiter.length()); + } + } } // set the remaining string