From 5708e3df34ef008d7ed6a956ef489025241d4e1f Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 09:56:53 +0100 Subject: [PATCH 01/24] Prevent tile layer corruption (use after free) when using Load event command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix รค2695 --- src/game_map.cpp | 2 +- src/game_map.h | 4 ++-- src/player.cpp | 2 ++ src/tilemap_layer.cpp | 2 ++ src/tilemap_layer.h | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/game_map.cpp b/src/game_map.cpp index 67bf55c46c..eadfb4b851 100644 --- a/src/game_map.cpp +++ b/src/game_map.cpp @@ -418,7 +418,7 @@ void Game_Map::PlayBgm() { } } -const std::vector& Game_Map::GetTilesLayer(int layer) { +std::vector Game_Map::GetTilesLayer(int layer) { return layer >= 1 ? map_info.upper_tiles : map_info.lower_tiles; } diff --git a/src/game_map.h b/src/game_map.h index 9591e60a48..669e666d40 100644 --- a/src/game_map.h +++ b/src/game_map.h @@ -106,7 +106,7 @@ namespace Game_Map { /** * Setups a map from a savegame. - * + * * @param map - The map data * @param save_map - The map state * @param save_boat - The boat state @@ -227,7 +227,7 @@ namespace Game_Map { * * @param layer which layer to return */ - const std::vector& GetTilesLayer(int layer); + std::vector GetTilesLayer(int layer); /** * Gets the bush depth at a certain tile. diff --git a/src/player.cpp b/src/player.cpp index 0243e38796..c9d10d778e 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -1211,6 +1211,8 @@ void Player::LoadSavegame(const std::string& save_name, int save_id) { map->Start(); if (!load_on_map) { Scene::Push(std::make_shared(save_id)); + } else { + Scene::instance->Start(); } } diff --git a/src/tilemap_layer.cpp b/src/tilemap_layer.cpp index aba0717402..056d70c2c4 100644 --- a/src/tilemap_layer.cpp +++ b/src/tilemap_layer.cpp @@ -665,6 +665,8 @@ void TilemapLayer::SetPassable(std::vector npassable) { } void TilemapLayer::OnSubstitute() { + substitutions = Game_Map::GetTilesLayer(layer); + // Recalculate z values of all tiles CreateTileCache(map_data); } diff --git a/src/tilemap_layer.h b/src/tilemap_layer.h index 1be346b206..833adf8bba 100644 --- a/src/tilemap_layer.h +++ b/src/tilemap_layer.h @@ -100,7 +100,7 @@ class TilemapLayer { std::unordered_set chipset_tone_tiles; std::vector map_data; std::vector passable; - Span substitutions; + std::vector substitutions; int ox = 0; int oy = 0; int width = 0; From 6f5c2054fd30e182c70f6c776e46f20bcebf71da Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 09:59:28 +0100 Subject: [PATCH 02/24] Pictures: Reset map layer to 7 when the picture is invisible in map and battle Fix #2874 --- src/game_pictures.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/game_pictures.cpp b/src/game_pictures.cpp index 2a5f068dc8..529e98af07 100644 --- a/src/game_pictures.cpp +++ b/src/game_pictures.cpp @@ -206,6 +206,11 @@ bool Game_Pictures::Picture::Show(const ShowParams& params) { data.spritesheet_speed = params.spritesheet_speed; data.map_layer = params.map_layer; data.battle_layer = params.battle_layer; + + if (data.map_layer == 0 && data.battle_layer == 0) { + data.map_layer = 7; + } + data.flags.erase_on_map_change = (params.flags & 1) == 1; data.flags.erase_on_battle_end = (params.flags & 2) == 2; data.flags.affected_by_tint = (params.flags & 16) == 16; From a48f3cf01f2c3aa7c0ce92ff3d9e85214a80d128 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 10:00:17 +0100 Subject: [PATCH 03/24] Set panorama coordinates correctly when the map has no panorama by default Fix #2889 --- src/spriteset_map.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/spriteset_map.cpp b/src/spriteset_map.cpp index 6cef1cde63..9f96f90144 100644 --- a/src/spriteset_map.cpp +++ b/src/spriteset_map.cpp @@ -144,11 +144,7 @@ void Spriteset_Map::ParallaxUpdated() { std::string name = Game_Map::Parallax::GetName(); if (name != panorama_name) { panorama_name = name; - if (name.empty()) { - panorama->SetBitmap(BitmapRef()); - Game_Map::Parallax::Initialize(0, 0); - } - else { + if (!name.empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("Panorama", panorama_name); request->SetGraphicFile(true); request->SetImportantFile(true); @@ -156,6 +152,11 @@ void Spriteset_Map::ParallaxUpdated() { request->Start(); } } + + if (name.empty()) { + panorama->SetBitmap(BitmapRef()); + Game_Map::Parallax::Initialize(0, 0); + } } void Spriteset_Map::SystemGraphicUpdated() { From cb076b8a3ec95d128d741d99882741c08eb5d272 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 10:01:59 +0100 Subject: [PATCH 04/24] Fix async loading when two backgrounds (foreground and background) are used Fixes the battles in Mother: Cognitive Dissonance which uses fancy background effects Fix #2893 --- src/background.cpp | 8 ++++---- src/background.h | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/background.cpp b/src/background.cpp index 0b0f8001ad..56a13f4d32 100644 --- a/src/background.cpp +++ b/src/background.cpp @@ -36,7 +36,7 @@ Background::Background(const std::string& name) : Drawable(Priority_Background) if (!name.empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("Backdrop", name); request->SetGraphicFile(true); - request_id = request->Bind(&Background::OnBackgroundGraphicReady, this); + bg_request_id = request->Bind(&Background::OnBackgroundGraphicReady, this); request->Start(); } } @@ -56,7 +56,7 @@ Background::Background(int terrain_id) : Drawable(Priority_Background) if (terrain->background_type == lcf::rpg::Terrain::BGAssociation_background && !terrain->background_name.empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("Backdrop", terrain->background_name); request->SetGraphicFile(true); - request_id = request->Bind(&Background::OnBackgroundGraphicReady, this); + bg_request_id = request->Bind(&Background::OnBackgroundGraphicReady, this); request->Start(); return; } @@ -65,7 +65,7 @@ Background::Background(int terrain_id) : Drawable(Priority_Background) if (!terrain->background_a_name.empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("Frame", terrain->background_a_name); request->SetGraphicFile(true); - request_id = request->Bind(&Background::OnBackgroundGraphicReady, this); + bg_request_id = request->Bind(&Background::OnBackgroundGraphicReady, this); request->Start(); bg_hscroll = terrain->background_a_scrollh ? terrain->background_a_scrollh_speed : 0; @@ -75,7 +75,7 @@ Background::Background(int terrain_id) : Drawable(Priority_Background) if (terrain->background_b && !terrain->background_b_name.empty()) { FileRequestAsync* request = AsyncHandler::RequestFile("Frame", terrain->background_b_name); request->SetGraphicFile(true); - request_id = request->Bind(&Background::OnForegroundFrameGraphicReady, this); + fg_request_id = request->Bind(&Background::OnForegroundFrameGraphicReady, this); request->Start(); fg_hscroll = terrain->background_b_scrollh ? terrain->background_b_scrollh_speed : 0; diff --git a/src/background.h b/src/background.h index f881487176..1885d5326d 100644 --- a/src/background.h +++ b/src/background.h @@ -55,7 +55,8 @@ class Background : public Drawable { int fg_x = 0; int fg_y = 0; - FileRequestBinding request_id; + FileRequestBinding fg_request_id; + FileRequestBinding bg_request_id; }; inline Tone Background::GetTone() const { From 6713236fd7798f39c353b670d67b051d5d1a3af5 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 10:03:38 +0100 Subject: [PATCH 05/24] Battle 2k3: Fix softlock when CBA uses an idle animation Fixes the game "Despoina" when "Blind Strike" is used. Fix #2896 --- src/scene_battle_rpg2k3.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scene_battle_rpg2k3.cpp b/src/scene_battle_rpg2k3.cpp index c9db45e2de..89c1570247 100644 --- a/src/scene_battle_rpg2k3.cpp +++ b/src/scene_battle_rpg2k3.cpp @@ -2341,6 +2341,8 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction action_state, Sprite_Actor::LoopState_WaitAfterFinish); } + } else { + sprite->SetAnimationLoop(Sprite_Actor::LoopState_DefaultAnimationAfterFinish); } } } From c535e240300708e9c26f4a96e4b4de0aba8ef0d0 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 10:04:57 +0100 Subject: [PATCH 06/24] KeyInputProcEx: Fix reading of a single key Wrong variable was checked Fix #2899 --- src/game_interpreter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index e3b04b6f00..18456cda1f 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -4422,8 +4422,8 @@ bool Game_Interpreter::CommandManiacKeyInputProcEx(lcf::rpg::EventCommand const& } } else if (operation == 2) { int key_id = ValueOrVariable(com.parameters[2], com.parameters[3]); - ManiacPatch::GetKeyState(key_id); - Main_Data::game_variables->Set(start_var_id, key_id ? 1 : 0); + bool key_state = ManiacPatch::GetKeyState(key_id); + Main_Data::game_variables->Set(start_var_id, key_state ? 1 : 0); } else { Output::Warning("Maniac KeyInputProcEx: Joypad not supported"); } From f3ce7bee12d47cc334b63fe922d34cef63410158 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 10:06:31 +0100 Subject: [PATCH 07/24] Patches (Maniac/DynRpg) were not reset when loading a new game Fix #2909 --- src/player.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/player.cpp b/src/player.cpp index c9d10d778e..49e5cc682f 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -830,6 +830,8 @@ void Player::CreateGameObjects() { Main_Data::filefinder_rtp = std::make_unique(no_rtp_flag, no_rtp_warning_flag, rtp_path); if ((patch & PatchOverride) == 0) { + patch = PatchNone; + if (!FileFinder::Game().FindFile("dynloader.dll").empty()) { patch |= PatchDynRpg; Output::Warning("This game uses DynRPG and will not run properly."); From 9ab162c824a9b0b6b40d7c71fbad1488c53e3248 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 10:07:47 +0100 Subject: [PATCH 08/24] Sort teleport targets when adding them --- src/game_targets.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/game_targets.cpp b/src/game_targets.cpp index da5b5cefd6..13307625df 100644 --- a/src/game_targets.cpp +++ b/src/game_targets.cpp @@ -40,6 +40,9 @@ void Game_Targets::AddTeleportTarget(int map_id, int x, int y, bool switch_on, i iter->map_y = y; iter->switch_on = switch_on; iter->switch_id = switch_id; + + // Teleports must be sorted by map id. + std::sort(teleports.begin(), teleports.end(), [](auto& l, auto& r) { return l.map_id < r.map_id; }); } void Game_Targets::RemoveTeleportTarget(int map_id) { From f14e85a4b396f7f2807f53623e0080e69496b32b Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 17:50:02 +0100 Subject: [PATCH 09/24] Game_Config: Fix loading of settings-in-menu & Cleanup --- src/game_config.cpp | 2 +- src/game_config.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/game_config.cpp b/src/game_config.cpp index 45a2661531..882843025e 100644 --- a/src/game_config.cpp +++ b/src/game_config.cpp @@ -411,7 +411,7 @@ void Game_Config::LoadFromStream(Filesystem_Stream::InputStream& is) { player.settings_in_title.Set(ini.GetBoolean("player", "settings-in-title", 0)); } if (ini.HasValue("player", "settings-in-menu")) { - player.settings_in_title.Set(ini.GetBoolean("player", "settings-in-menu", 0)); + player.settings_in_menu.Set(ini.GetBoolean("player", "settings-in-menu", 0)); } if (ini.HasValue("player", "autobattle-algo")) { player.autobattle_algo.Set(ini.GetString("player", "autobattle-algo", "")); diff --git a/src/game_config.h b/src/game_config.h index f24d6d063e..81f603b53c 100644 --- a/src/game_config.h +++ b/src/game_config.h @@ -41,10 +41,6 @@ struct Game_ConfigPlayer { BoolConfigParam settings_autosave{ "Save settings on exit", "Automatically save the settings on exit"}; BoolConfigParam settings_in_title{ "Show settings on title screen", "Display settings menu item on the title screen" }; BoolConfigParam settings_in_menu{ "Show settings in menu", "Display settings menu item on the menu screen"}; - //EnumConfigParam atb_mode("Default ATB mode for new games", - // lcf::rpg::SaveSystem::AtbMode_atb_wait, lcf::rpg::SaveSystem::AtbMode_); - - // autosave config on exit void Hide(); }; From 2bc7bfe64110f6c48da3ec3cbedb17d2d353d43b Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 18:17:27 +0100 Subject: [PATCH 10/24] Fix -Wall -Wextra warnings There is one warning left in "platform.cpp" about GetEntryType(...) where I'm not sure how to solve it. Removing it breaks the build on platforms that do not provide d_type. --- src/audio_decoder.cpp | 2 +- src/audio_decoder_midi.cpp | 8 +++++--- src/audio_decoder_midi.h | 2 -- src/audio_generic.cpp | 2 +- src/audio_midi.cpp | 14 ++++++------- src/audio_midi.h | 9 ++++----- src/cache.cpp | 2 +- src/config_param.h | 2 +- src/decoder_drwav.cpp | 2 +- src/decoder_drwav.h | 1 - src/filesystem_zip.cpp | 5 ++--- src/game_actor.cpp | 1 + src/game_enemy.cpp | 4 ++-- src/game_interpreter.cpp | 40 ++++++++++++++++++------------------- src/game_system.cpp | 2 +- src/game_variables.cpp | 22 ++++++++++---------- src/input_buttons.h | 2 +- src/input_source.cpp | 2 +- src/meta.cpp | 5 +++++ src/scene_battle_rpg2k3.cpp | 5 ++--- src/scene_gameover.cpp | 1 - src/scene_settings.cpp | 8 ++------ src/scene_title.cpp | 3 +-- src/sprite_actor.cpp | 2 +- src/tilemap_layer.cpp | 2 +- src/translation.cpp | 6 +++--- src/window_settings.cpp | 15 +++----------- src/window_settings.h | 5 ----- 28 files changed, 78 insertions(+), 96 deletions(-) diff --git a/src/audio_decoder.cpp b/src/audio_decoder.cpp index 20e9779224..c51e891c6d 100644 --- a/src/audio_decoder.cpp +++ b/src/audio_decoder.cpp @@ -68,7 +68,7 @@ std::unique_ptr AudioDecoder::Create(Filesystem_Stream::InputS // Try to use MIDI decoder, use fallback(s) if available if (!strncmp(magic, "MThd", 4)) { - auto midi = MidiDecoder::Create(stream, resample); + auto midi = MidiDecoder::Create(resample); if (midi) { return midi; } diff --git a/src/audio_decoder_midi.cpp b/src/audio_decoder_midi.cpp index b0c669408b..588752310b 100644 --- a/src/audio_decoder_midi.cpp +++ b/src/audio_decoder_midi.cpp @@ -40,7 +40,7 @@ constexpr int samples_per_play = 64 / sample_divider; static const uint8_t midi_event_control_change = 0b1011; static const uint8_t midi_control_volume = 7; static const uint8_t midi_control_all_sound_off = 120; -static const uint8_t midi_control_all_note_off = 123; +//static const uint8_t midi_control_all_note_off = 123; static const uint8_t midi_control_reset_all_controller = 121; static uint32_t midimsg_make(uint8_t event_type, uint8_t channel, uint8_t value1, uint8_t value2) { @@ -51,9 +51,9 @@ static uint32_t midimsg_make(uint8_t event_type, uint8_t channel, uint8_t value1 return msg; } -static uint32_t midimsg_all_note_off(uint8_t channel) { +/*static uint32_t midimsg_all_note_off(uint8_t channel) { return midimsg_make(midi_event_control_change, channel, midi_control_all_note_off, 0); -} +}*/ static uint32_t midimsg_all_sound_off(uint8_t channel) { return midimsg_make(midi_event_control_change, channel, midi_control_all_sound_off, 0); @@ -217,6 +217,8 @@ bool AudioDecoderMidi::IsFinished() const { } void AudioDecoderMidi::Update(std::chrono::microseconds delta) { + (void)delta; // FIXME: Why is delta unused? + if (paused) { return; } diff --git a/src/audio_decoder_midi.h b/src/audio_decoder_midi.h index fb25dae725..018b978d4b 100644 --- a/src/audio_decoder_midi.h +++ b/src/audio_decoder_midi.h @@ -181,8 +181,6 @@ class AudioDecoderMidi final : public AudioDecoderBase, public midisequencer::ou int frequency = EP_MIDI_FREQ; - // What was the mtime when the last set of volume MIDI messages were sent out - std::chrono::microseconds last_fade_msg_sent; std::array channel_volumes; struct MidiTempoData { diff --git a/src/audio_generic.cpp b/src/audio_generic.cpp index 7f568cbf08..bf355058c6 100644 --- a/src/audio_generic.cpp +++ b/src/audio_generic.cpp @@ -211,7 +211,7 @@ bool GenericAudio::PlayOnChannel(BgmChannel& chan, Filesystem_Stream::InputStrea // FIXME: Try Fluidsynth and WildMidi first // If they work fallback to the normal AudioDecoder handler below // There should be a way to configure the order - if (!MidiDecoder::CreateFluidsynth(filestream, true) && !MidiDecoder::CreateWildMidi(filestream, true)) { + if (!MidiDecoder::CreateFluidsynth(true) && !MidiDecoder::CreateWildMidi(true)) { if (!midi_thread) { midi_thread = std::make_unique(); if (midi_thread->IsInitialized()) { diff --git a/src/audio_midi.cpp b/src/audio_midi.cpp index 3edebe1d06..0468a8e7fd 100644 --- a/src/audio_midi.cpp +++ b/src/audio_midi.cpp @@ -45,21 +45,21 @@ static struct { bool wildmidi = true; } works; -std::unique_ptr MidiDecoder::Create(Filesystem_Stream::InputStream& stream, bool resample) { +std::unique_ptr MidiDecoder::Create(bool resample) { std::unique_ptr mididec; - mididec = CreateFluidsynth(stream, resample); + mididec = CreateFluidsynth(resample); if (!mididec) { - mididec = CreateWildMidi(stream, resample); + mididec = CreateWildMidi(resample); if (!mididec) { - mididec = CreateFmMidi(stream, resample); + mididec = CreateFmMidi(resample); } } return mididec; } -std::unique_ptr MidiDecoder::CreateFluidsynth(Filesystem_Stream::InputStream& stream, bool resample) { +std::unique_ptr MidiDecoder::CreateFluidsynth(bool resample) { std::unique_ptr mididec; #if defined(HAVE_FLUIDSYNTH) || defined(HAVE_FLUIDLITE) @@ -83,7 +83,7 @@ std::unique_ptr MidiDecoder::CreateFluidsynth(Filesystem_Strea return mididec; } -std::unique_ptr MidiDecoder::CreateWildMidi(Filesystem_Stream::InputStream& stream, bool resample) { +std::unique_ptr MidiDecoder::CreateWildMidi(bool resample) { std::unique_ptr mididec; #ifdef HAVE_LIBWILDMIDI @@ -107,7 +107,7 @@ std::unique_ptr MidiDecoder::CreateWildMidi(Filesystem_Stream: return mididec; } -std::unique_ptr MidiDecoder::CreateFmMidi(Filesystem_Stream::InputStream& stream, bool resample) { +std::unique_ptr MidiDecoder::CreateFmMidi(bool resample) { std::unique_ptr mididec; #if WANT_FMMIDI diff --git a/src/audio_midi.h b/src/audio_midi.h index 32ab7d9a72..25fdd1ab7d 100644 --- a/src/audio_midi.h +++ b/src/audio_midi.h @@ -183,17 +183,16 @@ class MidiDecoder { /** * Attempts to initialize a Midi library for processing the Midi data. * - * @param stream handle to parse * @param resample Whether the decoder shall be wrapped into a resampler (if supported) * @return A Midi decoder instance when the Midi data is supported, otherwise null */ - static std::unique_ptr Create(Filesystem_Stream::InputStream& stream, bool resample); + static std::unique_ptr Create(bool resample); - static std::unique_ptr CreateFluidsynth(Filesystem_Stream::InputStream& stream, bool resample); + static std::unique_ptr CreateFluidsynth(bool resample); - static std::unique_ptr CreateWildMidi(Filesystem_Stream::InputStream& stream, bool resample); + static std::unique_ptr CreateWildMidi(bool resample); - static std::unique_ptr CreateFmMidi(Filesystem_Stream::InputStream& stream, bool resample); + static std::unique_ptr CreateFmMidi(bool resample); protected: int frequency = EP_MIDI_FREQ; diff --git a/src/cache.cpp b/src/cache.cpp index a6ae6693f5..cae0799a88 100644 --- a/src/cache.cpp +++ b/src/cache.cpp @@ -228,7 +228,7 @@ namespace { } template - BitmapRef LoadDummyBitmap(StringView folder_name, StringView filename, bool transparent) { + BitmapRef LoadDummyBitmap(StringView, StringView, bool) { static_assert(Material::REND < T && T < Material::END, "Invalid material."); const Spec& s = spec[T]; return s.dummy_renderer(); diff --git a/src/config_param.h b/src/config_param.h index d590c168da..bc0cbeec2f 100644 --- a/src/config_param.h +++ b/src/config_param.h @@ -178,9 +178,9 @@ class ConfigParamBase { protected: virtual bool vIsValid(const T& value) const = 0; - T _value = {}; StringView _name; StringView _description; + T _value = {}; private: bool _visible = true; diff --git a/src/decoder_drwav.cpp b/src/decoder_drwav.cpp index 432414fdd0..c7a69ebfcc 100644 --- a/src/decoder_drwav.cpp +++ b/src/decoder_drwav.cpp @@ -93,7 +93,7 @@ int DrWavDecoder::FillBuffer(uint8_t* buffer, int length) { return 0; } - drwav_uint64 decoded = drwav_read_pcm_frames_s16(&handle, length / (handle.channels * 2), reinterpret_cast(buffer)); + int decoded = static_cast(drwav_read_pcm_frames_s16(&handle, length / (handle.channels * 2), reinterpret_cast(buffer))); decoded_samples += decoded; decoded *= handle.channels * 2; diff --git a/src/decoder_drwav.h b/src/decoder_drwav.h index 421b434cf2..9fad7e7799 100644 --- a/src/decoder_drwav.h +++ b/src/decoder_drwav.h @@ -56,7 +56,6 @@ class DrWavDecoder : public AudioDecoder { int decoded_samples = 0; bool init = false; drwav handle = {}; - uint32_t bytes_per_frame = 0; }; #endif diff --git a/src/filesystem_zip.cpp b/src/filesystem_zip.cpp index 88d2f911be..b7a11a0b7f 100644 --- a/src/filesystem_zip.cpp +++ b/src/filesystem_zip.cpp @@ -248,8 +248,8 @@ bool ZipFilesystem::ReadCentralDirectoryEntry(std::istream& zipfile, std::string zipfile.seekg(8, std::ios_base::cur); // Jump over currently not needed entries zipfile.read(reinterpret_cast(&entry.fileoffset), sizeof(uint32_t)); Utils::SwapByteOrder(entry.fileoffset); - if (filename_buffer.capacity() < filepath_length + 1) { - filename_buffer.resize(filepath_length + 1); + if (filename_buffer.capacity() < filepath_length + 1u) { + filename_buffer.resize(filepath_length + 1u); } zipfile.read(reinterpret_cast(filename_buffer.data()), filepath_length); filename = std::string(filename_buffer.data(), filepath_length); @@ -340,7 +340,6 @@ std::streambuf* ZipFilesystem::CreateInputStreambuffer(StringView path, std::ios auto zip_file = GetParent().OpenInputStream(GetPath()); zip_file.seekg(central_entry->fileoffset); StorageMethod method; - uint32_t local_offset = 0; ZipEntry local_entry = {}; if (ReadLocalHeader(zip_file, method, local_entry)) { if (central_entry->compressed_size != local_entry.compressed_size) { diff --git a/src/game_actor.cpp b/src/game_actor.cpp index 7702440269..49fda1c8a3 100644 --- a/src/game_actor.cpp +++ b/src/game_actor.cpp @@ -623,6 +623,7 @@ void Game_Actor::MakeExpList() { } std::string Game_Actor::GetExpString(bool status_scene) const { + (void)status_scene; // RPG_RT displays dashes for max level. As a customization // we always display the amount of EXP. // if (GetNextExp() == -1) { return (MaxExpValue() >= 1000000 || status_scene) ? "-------" : "------"; } diff --git a/src/game_enemy.cpp b/src/game_enemy.cpp index 1585c918f9..3da6b4a7fd 100644 --- a/src/game_enemy.cpp +++ b/src/game_enemy.cpp @@ -154,11 +154,11 @@ float Game_Enemy::GetCriticalHitChance(Weapon) const { return enemy->critical_hit ? (1.0f / enemy->critical_hit_chance) : 0.0f; } -bool Game_Enemy::HasAttackAll(Weapon weapon) const { +bool Game_Enemy::HasAttackAll(Weapon) const { return enemy->easyrpg_attack_all; } -bool Game_Enemy::AttackIgnoresEvasion(Weapon weapon) const { +bool Game_Enemy::AttackIgnoresEvasion(Weapon) const { return enemy->easyrpg_ignore_evasion; } diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index 18456cda1f..d95490a827 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -3173,8 +3173,8 @@ bool Game_Interpreter::CommandKeyInputProc(lcf::rpg::EventCommand const& com) { } }; - _keyinput.keys[Keys::eDecision] = check_key(3, true); - _keyinput.keys[Keys::eCancel] = check_key(4, true); + _keyinput.keys[Keys::eDecision] = check_key(3u, true); + _keyinput.keys[Keys::eCancel] = check_key(4u, true); // All engines support older versions of the command depending on the // length of the parameter list @@ -3190,10 +3190,10 @@ bool Game_Interpreter::CommandKeyInputProc(lcf::rpg::EventCommand const& com) { } else { // For Rpg2k >=1.50 _keyinput.keys[Keys::eShift] = com.parameters[5] != 0; - _keyinput.keys[Keys::eDown] = check_key(6); - _keyinput.keys[Keys::eLeft] = check_key(7); - _keyinput.keys[Keys::eRight] = check_key(8); - _keyinput.keys[Keys::eUp] = check_key(9); + _keyinput.keys[Keys::eDown] = check_key(6u); + _keyinput.keys[Keys::eLeft] = check_key(7u); + _keyinput.keys[Keys::eRight] = check_key(8u); + _keyinput.keys[Keys::eUp] = check_key(9u); } } else { if (param_size != 10 || Player::IsRPG2k3Legacy()) { @@ -3204,19 +3204,19 @@ bool Game_Interpreter::CommandKeyInputProc(lcf::rpg::EventCommand const& com) { _keyinput.keys[Keys::eRight] = true; _keyinput.keys[Keys::eUp] = true; } - _keyinput.keys[Keys::eNumbers] = check_key(5); - _keyinput.keys[Keys::eOperators] = check_key(6); + _keyinput.keys[Keys::eNumbers] = check_key(5u); + _keyinput.keys[Keys::eOperators] = check_key(6u); _keyinput.time_variable = param_size > 7 ? com.parameters[7] : 0; // Attention: int, not bool - _keyinput.timed = check_key(8); + _keyinput.timed = check_key(8u); if (param_size > 10 && Player::IsMajorUpdatedVersion()) { // For Rpg2k3 >=1.05 // ManiacPatch Middle & Wheel only handled for 2k3 Major Updated, // the only version that has this patch - _keyinput.keys[Keys::eShift] = check_key(9, true); - _keyinput.keys[Keys::eDown] = check_key(10, true); - _keyinput.keys[Keys::eLeft] = check_key(11); - _keyinput.keys[Keys::eRight] = check_key(12); - _keyinput.keys[Keys::eUp] = check_key(13, true); + _keyinput.keys[Keys::eShift] = check_key(9u, true); + _keyinput.keys[Keys::eDown] = check_key(10u, true); + _keyinput.keys[Keys::eLeft] = check_key(11u); + _keyinput.keys[Keys::eRight] = check_key(12u); + _keyinput.keys[Keys::eUp] = check_key(13u, true); } } else { // Since RPG2k3 1.05 @@ -3244,11 +3244,11 @@ bool Game_Interpreter::CommandKeyInputProc(lcf::rpg::EventCommand const& com) { #endif return result; }; - _keyinput.keys[Keys::eMouseLeft] = check_mouse(3); - _keyinput.keys[Keys::eMouseRight] = check_mouse(4); - _keyinput.keys[Keys::eMouseMiddle] = check_mouse(9); - _keyinput.keys[Keys::eMouseScrollDown] = check_mouse(10); - _keyinput.keys[Keys::eMouseScrollUp] = check_mouse(13); + _keyinput.keys[Keys::eMouseLeft] = check_mouse(3u); + _keyinput.keys[Keys::eMouseRight] = check_mouse(4u); + _keyinput.keys[Keys::eMouseMiddle] = check_mouse(9u); + _keyinput.keys[Keys::eMouseScrollDown] = check_mouse(10u); + _keyinput.keys[Keys::eMouseScrollUp] = check_mouse(13u); } if (_keyinput.wait) { @@ -3722,7 +3722,7 @@ bool Game_Interpreter::CommandEndLoop(lcf::rpg::EventCommand const& com) { // co int type = com.parameters[0]; int offset = com.indent * 2; - if (frame.maniac_loop_info.size() < (offset + 1) * 2) { + if (static_cast(frame.maniac_loop_info.size()) < (offset + 1) * 2) { frame.maniac_loop_info.resize((offset + 1) * 2); frame.maniac_loop_info_size = frame.maniac_loop_info.size() / 2; } diff --git a/src/game_system.cpp b/src/game_system.cpp index 239dd7cd64..a7bd0cca41 100644 --- a/src/game_system.cpp +++ b/src/game_system.cpp @@ -567,7 +567,7 @@ void Game_System::OnSeReady(FileRequestResult* result, lcf::rpg::Sound se, bool Output::Debug("Sound not found: {}", result->file); return; } - se_cache = std::move(AudioSeCache::Create(std::move(stream), result->file)); + se_cache = AudioSeCache::Create(std::move(stream), result->file); } if (!se_cache) { diff --git a/src/game_variables.cpp b/src/game_variables.cpp index 720a0ad8e8..736f87e609 100644 --- a/src/game_variables.cpp +++ b/src/game_variables.cpp @@ -439,57 +439,57 @@ void Game_Variables::BitShiftRightRangeVariableIndirect(int first_id, int last_i void Game_Variables::SetRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] = rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarSet); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarSet); } void Game_Variables::AddRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] += rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarAdd); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarAdd); } void Game_Variables::SubRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] -= rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarSub); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarSub); } void Game_Variables::MultRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] *= rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarMult); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarMult); } void Game_Variables::DivRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] /= rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarDiv); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarDiv); } void Game_Variables::ModRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] %= rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarMod); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarMod); } void Game_Variables::BitOrRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] |= rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitOr); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitOr); } void Game_Variables::BitAndRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] &= rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitAnd); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitAnd); } void Game_Variables::BitXorRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] ^= rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitXor); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitXor); } void Game_Variables::BitShiftLeftRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] <<= rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitShiftLeft); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitShiftLeft); } void Game_Variables::BitShiftRightRangeRandom(int first_id, int last_id, Var_t minval, Var_t maxval) { PrepareRange(first_id, last_id, "Invalid write var[{},{}] >>= rand({},{})!", minval, maxval); - WriteRange(first_id, last_id, [this,minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitShiftRight); + WriteRange(first_id, last_id, [minval,maxval](){ return Rand::GetRandomNumber(minval, maxval); }, VarBitShiftRight); } void Game_Variables::EnumerateRange(int first_id, int last_id, Var_t value) { diff --git a/src/input_buttons.h b/src/input_buttons.h index 02893e78e0..755331c404 100644 --- a/src/input_buttons.h +++ b/src/input_buttons.h @@ -31,7 +31,7 @@ #include "flat_map.h" #include "keys.h" -class Game_ConfigInput; +struct Game_ConfigInput; #if USE_SDL==1 #include "platform/sdl/axis.h" diff --git a/src/input_source.cpp b/src/input_source.cpp index 1eb2b0f5af..016f87aef0 100644 --- a/src/input_source.cpp +++ b/src/input_source.cpp @@ -61,7 +61,7 @@ void Input::UiSource::DoUpdate(bool system_only) { } if (!system_only || Input::IsSystemButton(bm.first)) { - pressed_buttons[bm.first] = pressed_buttons[bm.first] | keystates[bm.second]; + pressed_buttons[bm.first] = pressed_buttons[bm.first] || keystates[bm.second]; } } diff --git a/src/meta.cpp b/src/meta.cpp index 3bfa3830e2..31a36e05f9 100644 --- a/src/meta.cpp +++ b/src/meta.cpp @@ -142,6 +142,11 @@ std::vector Meta::SearchImportPaths(const FilesystemView& parent std::vector Meta::BuildImportCandidateList(const FilesystemView& parent_fs, StringView child_path, StringView parent_game_name, int pivot_map_id) const { + (void)parent_fs; + (void)child_path; + (void)parent_game_name; + (void)pivot_map_id; + // Scan each folder, looking for an ini file // For now, this only works with "standard" folder layouts, since we need Game files + Save files std::vector res; diff --git a/src/scene_battle_rpg2k3.cpp b/src/scene_battle_rpg2k3.cpp index 89c1570247..45664e5b96 100644 --- a/src/scene_battle_rpg2k3.cpp +++ b/src/scene_battle_rpg2k3.cpp @@ -2278,14 +2278,14 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction return BattleActionReturn::eWait; } -Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleActionCBAInit(Game_BattleAlgorithm::AlgorithmBase* action) { +Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleActionCBAInit(Game_BattleAlgorithm::AlgorithmBase*) { CBAInit(); SetBattleActionState(BattleActionState_CBAMove); return BattleActionReturn::eWait; } -Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleActionCBAMove(Game_BattleAlgorithm::AlgorithmBase* action) { +Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleActionCBAMove(Game_BattleAlgorithm::AlgorithmBase*) { CBAMove(); if (cba_move_frame >= cba_num_move_frames) { @@ -2666,7 +2666,6 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction if (source_sprite) { source_sprite->SetNormalAttacking(false); auto* weapon = actor->GetWeaponSprite(); - int weapon_animation_id = 0; if (weapon) { auto* weapon_animation_data = action->GetWeaponAnimationData(); if (weapon_animation_data) { diff --git a/src/scene_gameover.cpp b/src/scene_gameover.cpp index 30eb822400..89213f1524 100644 --- a/src/scene_gameover.cpp +++ b/src/scene_gameover.cpp @@ -54,7 +54,6 @@ void Scene_Gameover::OnBackgroundReady(FileRequestResult* result) { background->SetBitmap(bitmapRef); // If the sprite doesn't fill the screen, center it to support custom resolutions - Rect rect = background->GetBitmap()->GetRect(); if (bitmapRef->GetWidth() < Player::screen_width) { background->SetX(Player::menu_offset_x); } diff --git a/src/scene_settings.cpp b/src/scene_settings.cpp index cdd804ff2e..7ecbf67229 100644 --- a/src/scene_settings.cpp +++ b/src/scene_settings.cpp @@ -41,8 +41,6 @@ # include #endif -constexpr int option_window_num_items = 10; - Scene_Settings::Scene_Settings() { Scene::type = Scene::Settings; } @@ -87,7 +85,7 @@ void Scene_Settings::CreateOptionsWindow() { input_mode_window->SetX(Player::menu_offset_x + 32); input_mode_window->SetY(Player::screen_height - 32); input_mode_window->SetHelpWindow(help_window.get()); - input_mode_window->UpdateHelpFn = [this](Window_Help& win, int index) { + input_mode_window->UpdateHelpFn = [](Window_Help& win, int index) { if (index == 0) { win.SetText("Add a new keybinding"); } else if (index == 1) { @@ -215,6 +213,7 @@ void Scene_Settings::vUpdate() { switch (opt_mode) { case Window_Settings::eNone: + case Window_Settings::eSave: break; case Window_Settings::eMain: UpdateMain(); @@ -250,7 +249,6 @@ void Scene_Settings::OnTitleSpriteReady(FileRequestResult* result) { title->SetBitmap(bitmapRef); // If the title sprite doesn't fill the screen, center it to support custom resolutions - Rect rect = title->GetBitmap()->GetRect(); if (bitmapRef->GetWidth() < Player::screen_width) { title->SetX(Player::menu_offset_x); } @@ -284,8 +282,6 @@ void Scene_Settings::UpdateMain() { } void Scene_Settings::UpdateOptions() { - options_window->UpdateMode(); - if (number_window) { number_window->Update(); auto& option = options_window->GetCurrentOption(); diff --git a/src/scene_title.cpp b/src/scene_title.cpp index d735b8ac95..90cff4c39b 100644 --- a/src/scene_title.cpp +++ b/src/scene_title.cpp @@ -110,7 +110,7 @@ void Scene_Title::TransitionIn(SceneType prev_scene) { Transition::instance().InitShow(Transition::TransitionFadeIn, this); } -void Scene_Title::Suspend(Scene::SceneType next_scene) { +void Scene_Title::Suspend(Scene::SceneType) { // Unload title graphic to save memory title.reset(); } @@ -386,7 +386,6 @@ void Scene_Title::OnTitleSpriteReady(FileRequestResult* result) { title->SetBitmap(bitmapRef); // If the title sprite doesn't fill the screen, center it to support custom resolutions - Rect rect = title->GetBitmap()->GetRect(); if (bitmapRef->GetWidth() < Player::screen_width) { title->SetX(Player::menu_offset_x); } diff --git a/src/sprite_actor.cpp b/src/sprite_actor.cpp index eb1d52e322..fda747fb2d 100644 --- a/src/sprite_actor.cpp +++ b/src/sprite_actor.cpp @@ -300,7 +300,7 @@ void Sprite_Actor::UpdatePosition() { if (afterimage_fade >= 0) { ++afterimage_fade; - if (afterimage_fade >= images.size()) { + if (static_cast(afterimage_fade) >= images.size()) { // CBA finished, remove afterimages images.resize(1); afterimage_fade = -1; diff --git a/src/tilemap_layer.cpp b/src/tilemap_layer.cpp index 056d70c2c4..fe42a75ee4 100644 --- a/src/tilemap_layer.cpp +++ b/src/tilemap_layer.cpp @@ -684,7 +684,7 @@ void TilemapSubLayer::Draw(Bitmap& dst) { return; } - tilemap->Draw(dst, GetZ()); + tilemap->Draw(dst, internal_z); } void TilemapLayer::SetTone(Tone tone) { diff --git a/src/translation.cpp b/src/translation.cpp index bfe722dc8c..6097522e3a 100644 --- a/src/translation.cpp +++ b/src/translation.cpp @@ -832,7 +832,7 @@ void Dictionary::FromPo(Dictionary& res, std::istream& in) { Entry e; - auto extract_string = [&](int offset) -> std::string { + auto extract_string = [&](size_t offset) -> std::string { if (offset >= line_view.size()) { Output::Error("Parse error (Line {}) is empty", line_number); return ""; @@ -850,7 +850,7 @@ void Dictionary::FromPo(Dictionary& res, std::istream& in) { first_quote = true; continue; } - Output::Error("Parse error (Line {}): Expected \", got \"{}\": {}", line_number, c, line); + Output::Error(R"(Parse error (Line {}): Expected ", got "{}": {})", line_number, c, line); return ""; } @@ -869,7 +869,7 @@ void Dictionary::FromPo(Dictionary& res, std::istream& in) { out << '"'; break; default: - Output::Error("Parse error (Line {}): Expected \\, \\n or \", got \"{}\": {}", line_number, c, line); + Output::Error(R"(Parse error (Line {}): Expected \, \n or ", got "{}": {})", line_number, c, line); break; } } else { diff --git a/src/window_settings.cpp b/src/window_settings.cpp index 8a6a6c3f3e..b97e39f889 100644 --- a/src/window_settings.cpp +++ b/src/window_settings.cpp @@ -38,11 +38,6 @@ Window_Settings::Window_Settings(int ix, int iy, int iwidth, int iheight) : column_max = 1; } -void Window_Settings::UpdateMode() { - auto& frame = GetFrame(); - auto mode = frame.uimode; -} - void Window_Settings::DrawOption(int index) { Rect rect = GetItemRect(index); contents->ClearRect(rect); @@ -68,10 +63,6 @@ const Window_Settings::StackFrame& Window_Settings::GetFrame(int n) const { return stack[i]; } -int Window_Settings::GetStackSize() const { - return stack_index + 1; -} - void Window_Settings::Push(UiMode ui, int arg) { SavePosition(); @@ -278,9 +269,9 @@ void Window_Settings::RefreshAudio() { void Window_Settings::RefreshEngine() { auto& cfg = Player::player_config; - AddOption(cfg.settings_autosave, [&cfg](){ cfg.settings_autosave.Toggle(); }); - AddOption(cfg.settings_in_title, [&cfg](){ cfg.settings_in_title.Toggle(); }); - AddOption(cfg.settings_in_menu, [&cfg](){ cfg.settings_in_menu.Toggle(); }); + AddOption(cfg.settings_autosave, [](){ cfg.settings_autosave.Toggle(); }); + AddOption(cfg.settings_in_title, [](){ cfg.settings_in_title.Toggle(); }); + AddOption(cfg.settings_in_menu, [](){ cfg.settings_in_menu.Toggle(); }); } void Window_Settings::RefreshLicense() { diff --git a/src/window_settings.h b/src/window_settings.h index 9935eb708d..58b0c6d768 100644 --- a/src/window_settings.h +++ b/src/window_settings.h @@ -86,8 +86,6 @@ class Window_Settings : public Window_Selectable { && static_cast(options[index].action)); } - void UpdateMode(); - /** Execute the action pointed to by index */ Option& GetCurrentOption() { return options[index]; @@ -149,11 +147,8 @@ class Window_Settings : public Window_Selectable { std::array stack; int stack_index = 0; - int timer = 0; std::vector picker_options; - int GetStackSize() const; - void SavePosition(); void RestorePosition(); }; From a877118cbda54204e17e2229a393f205e0b12e7c Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 18:19:47 +0100 Subject: [PATCH 11/24] Rename OpusDecoder to OpusAudioDecoder Fix #1967 --- src/audio_decoder.cpp | 2 +- src/decoder_opus.cpp | 18 +++++++++--------- src/decoder_opus.h | 8 +++++--- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/audio_decoder.cpp b/src/audio_decoder.cpp index c51e891c6d..37ea21bcbf 100644 --- a/src/audio_decoder.cpp +++ b/src/audio_decoder.cpp @@ -84,7 +84,7 @@ std::unique_ptr AudioDecoder::Create(Filesystem_Stream::InputS stream.seekg(0, std::ios::ios_base::beg); if (!strncmp(magic, "Opus", 4)) { - return add_resampler(std::make_unique()); + return add_resampler(std::make_unique()); } #endif diff --git a/src/decoder_opus.cpp b/src/decoder_opus.cpp index a703c13a33..b989965d92 100644 --- a/src/decoder_opus.cpp +++ b/src/decoder_opus.cpp @@ -51,17 +51,17 @@ static OpusFileCallbacks vio = { nullptr // close not supported by istream interface }; -OpusDecoder::OpusDecoder() { +OpusAudioDecoder::OpusAudioDecoder() { music_type = "opus"; } -OpusDecoder::~OpusDecoder() { +OpusAudioDecoder::~OpusAudioDecoder() { if (oof) { op_free(oof); } } -bool OpusDecoder::Open(Filesystem_Stream::InputStream stream) { +bool OpusAudioDecoder::Open(Filesystem_Stream::InputStream stream) { this->stream = std::move(stream); finished = false; @@ -115,7 +115,7 @@ bool OpusDecoder::Open(Filesystem_Stream::InputStream stream) { return true; } -bool OpusDecoder::Seek(std::streamoff offset, std::ios_base::seekdir origin) { +bool OpusAudioDecoder::Seek(std::streamoff offset, std::ios_base::seekdir origin) { if (offset == 0 && origin == std::ios::beg) { finished = false; @@ -134,7 +134,7 @@ bool OpusDecoder::Seek(std::streamoff offset, std::ios_base::seekdir origin) { return false; } -bool OpusDecoder::IsFinished() const { +bool OpusAudioDecoder::IsFinished() const { if (!oof) { return false; } @@ -146,20 +146,20 @@ bool OpusDecoder::IsFinished() const { return finished; } -void OpusDecoder::GetFormat(int& freq, AudioDecoder::Format& format, int& chans) const { +void OpusAudioDecoder::GetFormat(int& freq, AudioDecoder::Format& format, int& chans) const { freq = frequency; format = Format::S16; chans = channels; } -bool OpusDecoder::SetFormat(int freq, AudioDecoder::Format format, int chans) { +bool OpusAudioDecoder::SetFormat(int freq, AudioDecoder::Format format, int chans) { if (freq != frequency || chans != channels || format != Format::S16) return false; return true; } -int OpusDecoder::GetTicks() const { +int OpusAudioDecoder::GetTicks() const { if (!oof) { return 0; } @@ -168,7 +168,7 @@ int OpusDecoder::GetTicks() const { return op_pcm_tell(oof) / 48000; } -int OpusDecoder::FillBuffer(uint8_t* buffer, int length) { +int OpusAudioDecoder::FillBuffer(uint8_t* buffer, int length) { if (!oof) return -1; diff --git a/src/decoder_opus.h b/src/decoder_opus.h index 68e8cc7a54..2dadda2297 100644 --- a/src/decoder_opus.h +++ b/src/decoder_opus.h @@ -25,12 +25,14 @@ /** * Audio decoder for Opus powered by opusfile + * + * Class renamed from OpusDecoder because of a conflict with the library. */ -class OpusDecoder : public AudioDecoder { +class OpusAudioDecoder : public AudioDecoder { public: - OpusDecoder(); + OpusAudioDecoder(); - ~OpusDecoder(); + ~OpusAudioDecoder(); // Audio Decoder interface bool Open(Filesystem_Stream::InputStream stream) override; From c2b92e2786a6f4750a914d859d1a8b51f7d613bd Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 18:32:24 +0100 Subject: [PATCH 12/24] CMake: Use OBJECT library Because this is just an intermediate library it avoids unnecessary linking --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ee27756fe..030021b376 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.15.0") endif() # Source Files -add_library(${PROJECT_NAME} STATIC +add_library(${PROJECT_NAME} OBJECT src/lcf_data.cpp src/lcf/data.h src/async_handler.cpp From e63d53348cb7e5b0b61b2e2e9ab266ea9bd6afa3 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 8 Mar 2023 18:36:52 +0100 Subject: [PATCH 13/24] Bump libretro-common to 20a43ba --- builds/libretro/libretro-common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builds/libretro/libretro-common b/builds/libretro/libretro-common index 50c15a88eb..20a43ba79f 160000 --- a/builds/libretro/libretro-common +++ b/builds/libretro/libretro-common @@ -1 +1 @@ -Subproject commit 50c15a88eb741cbe675743a282d8cc4c89421e3f +Subproject commit 20a43ba79fe6b4ec094b3b20b7bc88f4cfe916fa From 33f5f7e8809cd1349985412c4adcb551ed48c422 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Thu, 9 Mar 2023 19:31:45 +0100 Subject: [PATCH 14/24] Game Actor: Fix corrupted save data where the actor IDs do not match Not sure how this is possible but I received a savegame with this issue. RPG_RT has no problems with this and fixes them. --- src/game_actor.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/game_actor.cpp b/src/game_actor.cpp index 49fda1c8a3..c349b4afce 100644 --- a/src/game_actor.cpp +++ b/src/game_actor.cpp @@ -131,6 +131,11 @@ Game_Actor::Game_Actor(int actor_id) { } void Game_Actor::SetSaveData(lcf::rpg::SaveActor save) { + if (data.ID != save.ID) { + Output::Debug("Game_Actor: Fixing actor ID mismatch {} != {}", save.ID, data.ID); + save.ID = data.ID; + } + data = std::move(save); if (Player::IsRPG2k()) { From 356eee26c697dd52bae46f0ca7c446f20efd8912 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Fri, 10 Mar 2023 14:31:49 +0100 Subject: [PATCH 15/24] Fix Windows build --- src/decoder_xmp.cpp | 2 +- src/window_settings.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/decoder_xmp.cpp b/src/decoder_xmp.cpp index 237f232ef2..739ed5a0fc 100644 --- a/src/decoder_xmp.cpp +++ b/src/decoder_xmp.cpp @@ -29,7 +29,7 @@ static unsigned long xmp_vio_read_impl(void* ptr, unsigned long size, unsigned l char* ptrc = reinterpret_cast(ptr); for (unsigned long i = 0; i < count; ++i) { f->read(reinterpret_cast(ptrc + i * size), size); - if (f->gcount() != size) { + if (f->gcount() != static_cast(size)) { return i; } } diff --git a/src/window_settings.cpp b/src/window_settings.cpp index b97e39f889..f7fbc5323a 100644 --- a/src/window_settings.cpp +++ b/src/window_settings.cpp @@ -269,9 +269,10 @@ void Window_Settings::RefreshAudio() { void Window_Settings::RefreshEngine() { auto& cfg = Player::player_config; - AddOption(cfg.settings_autosave, [](){ cfg.settings_autosave.Toggle(); }); - AddOption(cfg.settings_in_title, [](){ cfg.settings_in_title.Toggle(); }); - AddOption(cfg.settings_in_menu, [](){ cfg.settings_in_menu.Toggle(); }); + // FIXME: Remove the &cfg after moving to VS2022 + AddOption(cfg.settings_autosave, [&cfg](){ cfg.settings_autosave.Toggle(); }); + AddOption(cfg.settings_in_title, [&cfg](){ cfg.settings_in_title.Toggle(); }); + AddOption(cfg.settings_in_menu, [&cfg](){ cfg.settings_in_menu.Toggle(); }); } void Window_Settings::RefreshLicense() { From 1efd6d5b9b27699a2c2d5beaf7dde54bf1ec8bc7 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Fri, 10 Mar 2023 14:32:15 +0100 Subject: [PATCH 16/24] Config: The config-path argument was not remembered when saving --- src/game_config.cpp | 75 +++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/src/game_config.cpp b/src/game_config.cpp index 882843025e..da0d76316c 100644 --- a/src/game_config.cpp +++ b/src/game_config.cpp @@ -33,6 +33,7 @@ #endif namespace { + std::string config_path; StringView config_name = "config.ini"; } @@ -80,13 +81,15 @@ Game_Config Game_Config::Create(CmdlineParser& cp) { cp.Rewind(); - auto arg_path = GetConfigPath(cp); - if (!arg_path.empty()) { - arg_path = FileFinder::MakePath(arg_path, config_name); + config_path = GetConfigPath(cp); + std::string config_file; + if (!config_path.empty()) { + config_file = FileFinder::MakePath(config_path, config_name); } - auto cli_config = FileFinder::Root().OpenOrCreateInputStream(arg_path); + auto cli_config = FileFinder::Root().OpenOrCreateInputStream(config_file); if (!cli_config) { + config_path.clear(); auto global_config = GetGlobalConfigFileInput(); if (global_config) { cfg.LoadFromStream(global_config); @@ -108,49 +111,53 @@ FilesystemView Game_Config::GetGlobalConfigFilesystem() { // FIXME: Game specific configs? std::string path; + if (config_path.empty()) { #ifdef GEKKO - path = "sd:/data/easyrpg-player"; + path = "sd:/data/easyrpg-player"; #elif defined(__SWITCH__) - path = "/switch/easyrpg-player"; + path = "/switch/easyrpg-player"; #elif defined(__3DS__) - path = "sdmc:/data/easyrpg-player"; + path = "sdmc:/data/easyrpg-player"; #elif defined(__vita__) - path = "ux0:/data/easyrpg-player"; + path = "ux0:/data/easyrpg-player"; #elif defined(USE_LIBRETRO) - const char* dir = nullptr; - if (LibretroUi::environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) { - path = FileFinder::MakePath(dir, "easyrpg-player"); - } + const char* dir = nullptr; + if (LibretroUi::environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) { + path = FileFinder::MakePath(dir, "easyrpg-player"); + } #elif defined(__ANDROID__) - // Never called, passed as argument on startup + // Never called, passed as argument on startup #elif defined(_WIN32) - PWSTR knownPath; - const auto hresult = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &knownPath); - if (SUCCEEDED(hresult)) { - path = Utils::FromWideString(knownPath); - CoTaskMemFree(knownPath); - } else { - Output::Debug("Config: SHGetKnownFolderPath failed"); - } + PWSTR knownPath; + const auto hresult = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &knownPath); + if (SUCCEEDED(hresult)) { + path = Utils::FromWideString(knownPath); + CoTaskMemFree(knownPath); + } else { + Output::Debug("Config: SHGetKnownFolderPath failed"); + } - if (!path.empty()) { - path = FileFinder::MakePath(path, FileFinder::MakePath(ORGANIZATION_NAME, APPLICATION_NAME)); - } + if (!path.empty()) { + path = FileFinder::MakePath(path, FileFinder::MakePath(ORGANIZATION_NAME, APPLICATION_NAME)); + } #else - char* home = getenv("XDG_CONFIG_HOME"); - if (home) { - path = home; - } else { - home = getenv("HOME"); + char* home = getenv("XDG_CONFIG_HOME"); if (home) { - path = FileFinder::MakePath(home, ".config"); + path = home; + } else { + home = getenv("HOME"); + if (home) { + path = FileFinder::MakePath(home, ".config"); + } } - } - if (!path.empty()) { - path = FileFinder::MakePath(path, FileFinder::MakePath(ORGANIZATION_NAME, APPLICATION_NAME)); - } + if (!path.empty()) { + path = FileFinder::MakePath(path, FileFinder::MakePath(ORGANIZATION_NAME, APPLICATION_NAME)); + } #endif + } else { + path = config_path; + } auto print_err = [&path]() { if (path.empty()) { From c4b73a7c18b252988c09266188891e762b174e3e Mon Sep 17 00:00:00 2001 From: Ghabry Date: Sat, 11 Mar 2023 19:39:57 +0100 Subject: [PATCH 17/24] Fix SDL2 linker error in flatpak build 21.08 lacks sdl2main.a and the sdl2-config requires it Our find module works without it --- builds/flatpak/org.easyrpg.player.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builds/flatpak/org.easyrpg.player.yml b/builds/flatpak/org.easyrpg.player.yml index 1bddaf7c36..25b4a0b653 100644 --- a/builds/flatpak/org.easyrpg.player.yml +++ b/builds/flatpak/org.easyrpg.player.yml @@ -86,6 +86,8 @@ modules: - name: player buildsystem: cmake-ninja config-opts: + # remove this line after switching to 22.08 or newer + - -DCMAKE_FIND_PACKAGE_PREFER_CONFIG=OFF - -DCMAKE_BUILD_TYPE=RelWithDebInfo sources: - type: git From 97a97b86ad20a90538eb45c4e89b2269c62a4512 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Sun, 12 Mar 2023 14:59:55 +0100 Subject: [PATCH 18/24] Panorama: Fix off-by-one error in panorama position calculation --- src/game_map.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/game_map.cpp b/src/game_map.cpp index eadfb4b851..52a6f4ecd2 100644 --- a/src/game_map.cpp +++ b/src/game_map.cpp @@ -23,6 +23,7 @@ #include #include "async_handler.h" +#include "options.h" #include "system.h" #include "game_battle.h" #include "game_battler.h" @@ -1730,7 +1731,11 @@ void Game_Map::Parallax::ResetPositionX() { } if (!params.scroll_horz && !LoopHorizontal()) { - int tiles_per_screen = (Player::screen_width / TILE_SIZE * TILE_SIZE + 16) / TILE_SIZE; + int tiles_per_screen = Player::screen_width / TILE_SIZE; + if (Player::screen_width % TILE_SIZE != 0) { + ++tiles_per_screen; + } + if (GetWidth() > tiles_per_screen && parallax_width > Player::screen_width) { const int w = (GetWidth() - tiles_per_screen) * TILE_SIZE; const int ph = 2 * std::min(w, parallax_width - Player::screen_width) * map_info.position_x / w; @@ -1754,9 +1759,13 @@ void Game_Map::Parallax::ResetPositionY() { } if (!params.scroll_vert && !Game_Map::LoopVertical()) { - int tiles_per_screen = (Player::screen_height / TILE_SIZE * TILE_SIZE + 16) / TILE_SIZE; + int tiles_per_screen = Player::screen_height / TILE_SIZE; + if (Player::screen_width % TILE_SIZE != 0) { + ++tiles_per_screen; + } + if (GetHeight() > tiles_per_screen && parallax_height > Player::screen_height) { - const int h = (GetHeight() - tiles_per_screen) * TILE_SIZE; + const int h = (GetHeight() - 15) * TILE_SIZE; const int pv = 2 * std::min(h, parallax_height - Player::screen_height) * map_info.position_y / h; SetPositionY(pv); } else { From 0630a0ebadfea285af2b7518aa50878e5d01d7ef Mon Sep 17 00:00:00 2001 From: Ghabry Date: Sun, 12 Mar 2023 21:24:28 +0100 Subject: [PATCH 19/24] Settings: Limit to 16 input mappings Otherwise it crashes because the window buffer is too small --- src/scene_settings.cpp | 21 +++++++++++++-------- src/scene_settings.h | 3 +-- src/window_input_settings.cpp | 4 ++++ src/window_input_settings.h | 2 ++ 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/scene_settings.cpp b/src/scene_settings.cpp index 7ecbf67229..512d3fd7b5 100644 --- a/src/scene_settings.cpp +++ b/src/scene_settings.cpp @@ -141,7 +141,7 @@ void Scene_Settings::SetMode(Window_Settings::UiMode new_mode) { input_mode_window->SetVisible(true); input_help_window->SetVisible(true); input_help_window->SetText("Emergency reset: Hold 4 keys and follow instructions"); - RefreshInputRemoveAllowed(); + RefreshInputActionAllowed(); break; case Window_Settings::eInputButtonAdd: help_window->SetVisible(true); @@ -402,11 +402,15 @@ void Scene_Settings::UpdateButtonOption() { if (Input::IsTriggered(Input::DECISION)) { switch (input_mode_window->GetIndex()) { case 0: - Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Game_System::SFX_Decision)); - options_window->Push(Window_Settings::eInputButtonAdd, options_window->GetFrame().arg); + if (!input_mode_window->IsItemEnabled(0)) { + Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Game_System::SFX_Buzzer)); + } else { + Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Game_System::SFX_Decision)); + options_window->Push(Window_Settings::eInputButtonAdd, options_window->GetFrame().arg); + } break; case 1: - if (!input_mode_window_remove_allowed) { + if (!input_mode_window->IsItemEnabled(1)) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Game_System::SFX_Buzzer)); } else { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Game_System::SFX_Decision)); @@ -416,9 +420,9 @@ void Scene_Settings::UpdateButtonOption() { case 2: Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Game_System::SFX_Decision)); input_window->ResetMapping(); - RefreshInputRemoveAllowed(); break; } + RefreshInputActionAllowed(); } } @@ -511,10 +515,11 @@ bool Scene_Settings::RefreshInputEmergencyReset() { return input_reset_counter > 0; } -void Scene_Settings::RefreshInputRemoveAllowed() { +void Scene_Settings::RefreshInputActionAllowed() { auto button = static_cast(options_window->GetFrame().arg); - input_mode_window_remove_allowed = Input::GetInputSource()->GetButtonMappings().Count(button) > Input::IsProtectedButton(button) ? 1 : 0; - input_mode_window->SetItemEnabled(1, input_mode_window_remove_allowed); + auto mapping_count = Input::GetInputSource()->GetButtonMappings().Count(button); + input_mode_window->SetItemEnabled(0, mapping_count < Window_InputSettings::mapping_limit); + input_mode_window->SetItemEnabled(1, mapping_count > Input::IsProtectedButton(button) ? 1 : 0); } bool Scene_Settings::SaveConfig(bool silent) { diff --git a/src/scene_settings.h b/src/scene_settings.h index 862166b499..caa2562bb4 100644 --- a/src/scene_settings.h +++ b/src/scene_settings.h @@ -67,7 +67,7 @@ class Scene_Settings : public Scene { void UpdateButtonRemove(); bool RefreshInputEmergencyReset(); - void RefreshInputRemoveAllowed(); + void RefreshInputActionAllowed(); std::unique_ptr main_window; std::unique_ptr help_window; @@ -80,7 +80,6 @@ class Scene_Settings : public Scene { std::unique_ptr title; FileRequestBinding request_id; - bool input_mode_window_remove_allowed = true; int input_reset_counter = 0; Window_Settings::UiMode mode = Window_Settings::eNone; diff --git a/src/window_input_settings.cpp b/src/window_input_settings.cpp index 7f62f2f4ed..307384429a 100644 --- a/src/window_input_settings.cpp +++ b/src/window_input_settings.cpp @@ -86,6 +86,10 @@ void Window_InputSettings::Refresh() { } } + if (items.size() > mapping_limit) { + items.resize(mapping_limit); + } + item_max = static_cast(items.size()); for (int i = 0; i < item_max; ++i) { diff --git a/src/window_input_settings.h b/src/window_input_settings.h index 4157fafa25..67d1845885 100644 --- a/src/window_input_settings.h +++ b/src/window_input_settings.h @@ -30,6 +30,8 @@ */ class Window_InputSettings : public Window_Selectable { public: + static constexpr int mapping_limit = 16; + /** Constructor */ Window_InputSettings(int ix, int iy, int iwidth, int iheight); From c080fd6e496f63698e27d389e00f7ea4530bc878 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Sun, 12 Mar 2023 21:30:52 +0100 Subject: [PATCH 20/24] Fix command window item state not set to enabled in some cases --- src/scene_battle_rpg2k3.cpp | 4 +++- src/scene_debug.cpp | 4 +--- src/scene_title.cpp | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/scene_battle_rpg2k3.cpp b/src/scene_battle_rpg2k3.cpp index 45664e5b96..8b6672ee37 100644 --- a/src/scene_battle_rpg2k3.cpp +++ b/src/scene_battle_rpg2k3.cpp @@ -570,7 +570,7 @@ void Scene_Battle_Rpg2k3::CreateBattleStatusWindow() { int h = 80; int x = Player::menu_offset_x; int y = Player::screen_height - Player::menu_offset_y - h; - + switch (lcf::Data::battlecommands.battle_type) { case lcf::rpg::BattleCommands::BattleType_traditional: x = Player::menu_offset_x + target_window->GetWidth(); @@ -612,6 +612,8 @@ void Scene_Battle_Rpg2k3::SetBattleCommandsDisable(Window_Command& window, const auto* cmd = cmds[i]; if (cmd->type == lcf::rpg::BattleCommand::Type_escape && !IsEscapeAllowedFromActorCommand()) { window.DisableItem(i); + } else { + window.EnableItem(i); } } } diff --git a/src/scene_debug.cpp b/src/scene_debug.cpp index a8c74e1bbc..55524dbf16 100644 --- a/src/scene_debug.cpp +++ b/src/scene_debug.cpp @@ -484,9 +484,7 @@ void Scene_Debug::UpdateRangeListWindow() { auto addItem = [&](const auto& name, bool enabled = true) { range_window->SetItemText(idx, name); - if (!enabled) { - range_window->DisableItem(idx); - } + range_window->SetItemEnabled(idx, enabled); ++idx; }; diff --git a/src/scene_title.cpp b/src/scene_title.cpp index 90cff4c39b..4d8a5aa1c9 100644 --- a/src/scene_title.cpp +++ b/src/scene_title.cpp @@ -237,9 +237,8 @@ void Scene_Title::CreateCommandWindow() { continue_enabled = FileFinder::HasSavegame(); if (continue_enabled) { command_window->SetIndex(1); - } else { - command_window->DisableItem(1); } + command_window->SetItemEnabled(1, continue_enabled); // Set the number of frames for the opening animation to last if (!Player::hide_title_flag) { From 6b780907131153462d81984931a632cada41ef99 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Mon, 13 Mar 2023 13:52:51 +0100 Subject: [PATCH 21/24] Fluidsynth: Fix use-after-free during shutdown --- src/decoder_fluidsynth.cpp | 32 +++++++++++++++++++++----------- src/decoder_fluidsynth.h | 5 ++++- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/decoder_fluidsynth.cpp b/src/decoder_fluidsynth.cpp index 8c50a79fce..d7830517e7 100644 --- a/src/decoder_fluidsynth.cpp +++ b/src/decoder_fluidsynth.cpp @@ -94,25 +94,21 @@ static fluid_fileapi_t fluidlite_vio = { #endif namespace { - bool shutdown = false; std::string preferred_soundfont; } -struct FluidSettingsDeleter { +struct FluidSynthDeleter { void operator()(fluid_settings_t* s) const { delete_fluid_settings(s); } -}; -struct FluidSynthDeleter { void operator()(fluid_synth_t* s) const { delete_fluid_synth(s); - shutdown = true; } }; namespace { - std::unique_ptr global_settings; + std::unique_ptr global_settings; std::unique_ptr global_synth; #if defined(HAVE_FLUIDSYNTH) && FLUIDSYNTH_VERSION_MAJOR > 1 fluid_sfloader_t* global_loader; // owned by global_settings @@ -191,13 +187,13 @@ FluidSynthDecoder::FluidSynthDecoder() { // Sharing is only not possible when a Midi is played as a SE (unlikely) if (instances > 1) { std::string error_message; - instance_synth = create_synth(error_message); - if (!instance_synth) { + local_synth = create_synth(error_message); + if (!local_synth) { // unlikely, the SF was already allocated once Output::Debug("FluidSynth failed: {}", error_message); } } else { - instance_synth = global_synth.get(); + use_global_synth = true; fluid_synth_program_reset(global_synth.get()); } } @@ -206,8 +202,8 @@ FluidSynthDecoder::~FluidSynthDecoder() { --instances; assert(instances >= 0); - if (instance_synth != global_synth.get()) { - delete_fluid_synth(instance_synth); + if (!use_global_synth) { + delete_fluid_synth(local_synth); } } @@ -270,6 +266,8 @@ void FluidSynthDecoder::SetSoundfont(StringView sf) { } int FluidSynthDecoder::FillBuffer(uint8_t* buffer, int length) { + auto* instance_synth = GetSynthInstance(); + if (!instance_synth) { return -1; } @@ -282,6 +280,8 @@ int FluidSynthDecoder::FillBuffer(uint8_t* buffer, int length) { } void FluidSynthDecoder::SendMidiMessage(uint32_t message) { + auto* instance_synth = GetSynthInstance(); + if (!instance_synth) { return; } @@ -329,8 +329,18 @@ void FluidSynthDecoder::SendSysExMessage(const uint8_t* data, std::size_t size) return; } + auto* instance_synth = GetSynthInstance(); + fluid_synth_sysex(instance_synth, reinterpret_cast(data + 1), static_cast(size - 2), nullptr, nullptr, nullptr, 0); } +fluid_synth_t *FluidSynthDecoder::GetSynthInstance() { + if (use_global_synth) { + return global_synth.get(); + } else { + return local_synth; + } +} + #endif diff --git a/src/decoder_fluidsynth.h b/src/decoder_fluidsynth.h index 52e1920abd..740291b3a9 100644 --- a/src/decoder_fluidsynth.h +++ b/src/decoder_fluidsynth.h @@ -70,7 +70,10 @@ class FluidSynthDecoder : public MidiDecoder { private: #if defined(HAVE_FLUIDSYNTH) || defined(HAVE_FLUIDLITE) - fluid_synth_t* instance_synth; + fluid_synth_t* GetSynthInstance(); + + fluid_synth_t* local_synth = nullptr; + bool use_global_synth = false; #endif }; From f5921524413111e076e242500ba65abb2164184d Mon Sep 17 00:00:00 2001 From: Ghabry Date: Mon, 13 Mar 2023 14:55:47 +0100 Subject: [PATCH 22/24] Zip: Convert \ to / after conversion to Unicode Shift-Jis can have bytes that map to \, corrupting the sequence Fix #2907 --- src/filesystem_zip.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/filesystem_zip.cpp b/src/filesystem_zip.cpp index b7a11a0b7f..7c0e4cf674 100644 --- a/src/filesystem_zip.cpp +++ b/src/filesystem_zip.cpp @@ -133,6 +133,10 @@ ZipFilesystem::ZipFilesystem(std::string base_path, FilesystemView parent_fs, St filepath = lcf::ReaderUtil::Recode(filepath, encoding); } + // Workaround ZIP archives containing invalid "\" paths created by .net or Powershell + std::replace(filepath_cp437.begin(), filepath_cp437.end(), '\\', '/'); + std::replace(filepath.begin(), filepath.end(), '\\', '/'); + // check if the entry is an directory or not (indicated by trailing /) // this will fail when the (game) directory has cp437, but the users can rename it before if (filepath.back() == '/') { @@ -255,8 +259,6 @@ bool ZipFilesystem::ReadCentralDirectoryEntry(std::istream& zipfile, std::string filename = std::string(filename_buffer.data(), filepath_length); // Jump over currently not needed entries zipfile.seekg(comment_length + extra_field_length, std::ios_base::cur); - // Workaround ZIP archives containing invalid "\" paths created by .net or Powershell - std::replace(filename.begin(), filename.end(), '\\', '/'); return true; } From 6e79e0ef3b6e91ab268a849b13f251ef0a20f3f0 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Tue, 14 Mar 2023 11:47:58 +0100 Subject: [PATCH 23/24] Windows: Fix crash when left/right border is missing because the Window is too small Resolve some stringpic related warnings Fix #2920 --- src/bitmap.cpp | 1 - src/game_interpreter.cpp | 2 -- src/window.cpp | 22 +++++++++++++++------- src/window_selectable.cpp | 5 ++++- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/bitmap.cpp b/src/bitmap.cpp index 9a25bbb9d3..0dd4c30667 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -291,7 +291,6 @@ Color Bitmap::GetColorAt(int x, int y) const { } Color color; - int pix = y * width(); const uint8_t* pos = &reinterpret_cast(pixels())[y * pitch() + x * bpp()]; uint32_t pixel = *reinterpret_cast(pos); diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index d95490a827..ac688e9f5b 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -4212,8 +4212,6 @@ bool Game_Interpreter::CommandManiacShowStringPicture(lcf::rpg::EventCommand con text.font_size = font_px; - size_t param_size = com.parameters.size(); - auto components = Utils::Tokenize(com.string, [](char32_t ch) { return ch == '\x01'; }); diff --git a/src/window.cpp b/src/window.cpp index 1e36ac3dc9..6da69f0373 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -87,8 +87,13 @@ void Window::Draw(Bitmap& dst) { if (ianimation_count > 8) { Rect src_rect(0, height / 2 - ianimation_count, 8, ianimation_count * 2 - 16); - dst.Blit(x, y + 8 + src_rect.y, *frame_left, src_rect, fopacity); - dst.Blit(x + width - 8, y + 8 + src_rect.y, *frame_right, src_rect, fopacity); + if (frame_left) { + dst.Blit(x, y + 8 + src_rect.y, *frame_left, src_rect, fopacity); + } + + if (frame_right) { + dst.Blit(x + width - 8, y + 8 + src_rect.y, *frame_right, src_rect, fopacity); + } dst.Blit(x, y + height / 2 - ianimation_count, *frame_up, frame_up->GetRect(), fopacity); dst.Blit(x, y + height / 2 + ianimation_count - 8, *frame_down, frame_down->GetRect(), fopacity); @@ -99,8 +104,14 @@ void Window::Draw(Bitmap& dst) { } else { dst.Blit(x, y, *frame_up, frame_up->GetRect(), fopacity); dst.Blit(x, y + height - 8, *frame_down, frame_down->GetRect(), fopacity); - dst.Blit(x, y + 8, *frame_left, frame_left->GetRect(), fopacity); - dst.Blit(x + width - 8, y + 8, *frame_right, frame_right->GetRect(), fopacity); + + if (frame_left) { + dst.Blit(x, y + 8, *frame_left, frame_left->GetRect(), fopacity); + } + + if (frame_right) { + dst.Blit(x + width - 8, y + 8, *frame_right, frame_right->GetRect(), fopacity); + } } } @@ -210,9 +221,6 @@ void Window::RefreshFrame() { BitmapRef left_bitmap = Bitmap::Create(8, height - 16); BitmapRef right_bitmap = Bitmap::Create(8, height - 16); - left_bitmap->Clear(); - right_bitmap->Clear(); - // Border Left src_rect = { 32, 8, 8, 16 }; dst_rect = { 0, 0, 8, height - 16 }; diff --git a/src/window_selectable.cpp b/src/window_selectable.cpp index 6f6d5aa4dc..c8ca714e10 100644 --- a/src/window_selectable.cpp +++ b/src/window_selectable.cpp @@ -29,7 +29,10 @@ Window_Selectable::Window_Selectable(int ix, int iy, int iwidth, int iheight) : Window_Base(ix, iy, iwidth, iheight) { } void Window_Selectable::CreateContents() { - SetContents(Bitmap::Create(width - border_x * 2, max(height - border_y * 2, GetRowMax() * menu_item_height))); + int w = std::max(0, width - border_x * 2); + int h = std::max(0, std::max(height - border_y * 2, GetRowMax() * menu_item_height)); + + SetContents(Bitmap::Create(w, h)); } // Properties From 6356529be2998b63a7a45a5c554ba86afb354c29 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Tue, 14 Mar 2023 13:48:21 +0100 Subject: [PATCH 24/24] Fix Transition inwards by making the alpha channel of a framebuffer copy opaque Fix #2901 --- src/baseui.cpp | 4 +++- src/game_interpreter.cpp | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/baseui.cpp b/src/baseui.cpp index c9bc81ebdb..3cdd17c8bc 100644 --- a/src/baseui.cpp +++ b/src/baseui.cpp @@ -58,7 +58,9 @@ BaseUi::BaseUi(const Game_Config& cfg) } BitmapRef BaseUi::CaptureScreen() { - return Bitmap::Create(*main_surface, main_surface->GetRect()); + BitmapRef capture = Bitmap::Create(main_surface->width(), main_surface->height(), false); + capture->BlitFast(0, 0, *main_surface, main_surface->GetRect(), Opacity::Opaque()); + return capture; } void BaseUi::CleanDisplay() { diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index ac688e9f5b..b8ffdc7a47 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -2064,8 +2064,6 @@ bool Game_Interpreter::CommandPlaySound(lcf::rpg::EventCommand const& com) { // sound.balance = com.parameters[2]; } - Output::Debug("SE {} {} {} {}", sound.name, sound.volume, sound.tempo, sound.balance); - Main_Data::game_system->SePlay(sound, true); return true; }