From ade4689a52c182101e82835b1e03460f30b678e9 Mon Sep 17 00:00:00 2001 From: BlisterB Date: Tue, 30 Dec 2025 21:37:27 +0100 Subject: [PATCH 1/9] Fix the calculation of the Panorama's offset in case of fakeResolution and small map --- src/game_map.cpp | 14 +++++++++++--- src/spriteset_map.cpp | 4 ++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/game_map.cpp b/src/game_map.cpp index 861b037e86..8124397616 100644 --- a/src/game_map.cpp +++ b/src/game_map.cpp @@ -2144,9 +2144,13 @@ void Game_Map::Parallax::ResetPositionX() { parallax_fake_x = false; if (!params.scroll_horz && !LoopHorizontal()) { + // What is the width of the panorama to display on screen? int pan_screen_width = Player::screen_width; - if (Player::game_config.fake_resolution.Get()) { - pan_screen_width = SCREEN_TARGET_WIDTH; + if (Player::game_config.fake_resolution.Get()) { + int map_width = Game_Map::GetTilesX() * TILE_SIZE; + if (map_width < pan_screen_width) { + pan_screen_width = map_width; + } } int tiles_per_screen = pan_screen_width / TILE_SIZE; @@ -2182,9 +2186,13 @@ void Game_Map::Parallax::ResetPositionY() { parallax_fake_y = false; if (!params.scroll_vert && !Game_Map::LoopVertical()) { + // What is the height of the panorama to display on screen? int pan_screen_height = Player::screen_height; if (Player::game_config.fake_resolution.Get()) { - pan_screen_height = SCREEN_TARGET_HEIGHT; + int map_height = Game_Map::GetTilesY() * TILE_SIZE; + if (map_height < pan_screen_height) { + pan_screen_height = map_height; + } } int tiles_per_screen = pan_screen_height / TILE_SIZE; diff --git a/src/spriteset_map.cpp b/src/spriteset_map.cpp index 50ea8a8842..4eb1e2fb8c 100644 --- a/src/spriteset_map.cpp +++ b/src/spriteset_map.cpp @@ -328,10 +328,10 @@ void Spriteset_Map::CalculatePanoramaRenderOffset() { // Resolution hack for Panorama if (Player::game_config.fake_resolution.Get()) { if (Game_Map::Parallax::FakeXPosition()) { - panorama->SetRenderOx((Player::screen_width - SCREEN_TARGET_WIDTH) / 2); + panorama->SetRenderOx((Player::screen_width - (Game_Map::GetTilesX() * TILE_SIZE)) / 2); } if (Game_Map::Parallax::FakeYPosition()) { - panorama->SetRenderOy((Player::screen_height - SCREEN_TARGET_HEIGHT) / 2); + panorama->SetRenderOy((Player::screen_height - (Game_Map::GetTilesY() * TILE_SIZE)) / 2); } } } From d1bd7cbe1acc71b6c98f3513752839da1e3413e6 Mon Sep 17 00:00:00 2001 From: BlisterB Date: Wed, 31 Dec 2025 19:40:22 +0100 Subject: [PATCH 2/9] [WideScreen] Fix the calculation of Picture's offsets when using fakeResolution --- src/sprite_picture.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/sprite_picture.cpp b/src/sprite_picture.cpp index 4c7c21dd47..0329fe333d 100644 --- a/src/sprite_picture.cpp +++ b/src/sprite_picture.cpp @@ -24,6 +24,7 @@ #include "game_windows.h" #include "player.h" #include "bitmap.h" +#include "game_map.h" Sprite_Picture::Sprite_Picture(int pic_id, Drawable::Flags flags) : Sprite(flags), @@ -106,8 +107,26 @@ void Sprite_Picture::Draw(Bitmap& dst) { } if (Player::game_config.fake_resolution.Get()) { - SetX(x + Player::menu_offset_x); - SetY(y + Player::menu_offset_y); + if (data.fixed_to_map) { + // If the picture scrolls with the map, apply the black border if the map is too small + int offset_x = 0; + int map_width = Game_Map::GetTilesX() * TILE_SIZE; + if (map_width < Player::screen_width) { + offset_x += (Player::screen_width - map_width) / 2; + } + SetX(x + offset_x); + + int offset_y = 0; + int map_height = Game_Map::GetTilesY() * TILE_SIZE; + if (map_height < Player::screen_height) { + offset_y += (Player::screen_height - map_height) / 2; + } + SetY(y + offset_y); + } else { + // If the picture doesn't scroll with the map, simulate the 340x240 screen + SetX(x + Player::menu_offset_x); + SetY(y + Player::menu_offset_y); + } } else { SetX(x); SetY(y); From c23a8e6808647afe1dc84e36050abbf9d503e178 Mon Sep 17 00:00:00 2001 From: BlisterB Date: Wed, 31 Dec 2025 19:41:33 +0100 Subject: [PATCH 3/9] [FakeResolution] When retrieving an Event X/Y screen position, don't apply an offset --- src/game_interpreter_control_variables.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/game_interpreter_control_variables.cpp b/src/game_interpreter_control_variables.cpp index aa241b3af3..e459695109 100644 --- a/src/game_interpreter_control_variables.cpp +++ b/src/game_interpreter_control_variables.cpp @@ -190,21 +190,11 @@ int ControlVariables::Event(int op, int event_id, const Game_BaseInterpreterCont break; case 4: { // Screen X - if (Player::game_config.fake_resolution.Get()) { - int pan_delta = (Game_Player::GetDefaultPanX() - lcf::rpg::SavePartyLocation::kPanXDefault) / TILE_SIZE; - return character->GetScreenX() - pan_delta; - } else { - return character->GetScreenX(); - } + return character->GetScreenX(); } case 5: { // Screen Y - if (Player::game_config.fake_resolution.Get()) { - int pan_delta = (Game_Player::GetDefaultPanY() - lcf::rpg::SavePartyLocation::kPanYDefault) / TILE_SIZE; - return character->GetScreenY() - pan_delta; - } else { - return character->GetScreenY(); - } + return character->GetScreenY(); } case 6: // Event ID From dd685f35349f7752e59f7f22e56074de4d78e0ca Mon Sep 17 00:00:00 2001 From: BlisterB Date: Sat, 3 Jan 2026 19:30:24 +0100 Subject: [PATCH 4/9] [FakeResolution] Correctly centers the camera at the startup of a looping map --- src/game_map.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/game_map.cpp b/src/game_map.cpp index 8124397616..7d49e5ad73 100644 --- a/src/game_map.cpp +++ b/src/game_map.cpp @@ -1723,6 +1723,14 @@ void Game_Map::SetPositionX(int x, bool reset_panorama) { const int map_width = GetTilesX() * SCREEN_TILE_SIZE; if (LoopHorizontal()) { x = Utils::PositiveModulo(x, map_width); + + // If the map is too small to fit in the screen, add an offset corresponding to the black border's size + if (Player::game_config.fake_resolution.Get()) { + int map_width_in_pixels = Game_Map::GetTilesX() * TILE_SIZE; + if (map_width_in_pixels < Player::screen_width) { + x += ((Player::screen_width - map_width_in_pixels) / 2 / TILE_SIZE) * SCREEN_TILE_SIZE; + } + } } else { // Do not use std::clamp here. When the map is smaller than the screen the // upper bound is smaller than the lower bound making the function fail. @@ -1747,6 +1755,14 @@ void Game_Map::SetPositionY(int y, bool reset_panorama) { const int map_height = GetTilesY() * SCREEN_TILE_SIZE; if (LoopVertical()) { y = Utils::PositiveModulo(y, map_height); + + // If the map is too small to fit in the screen, add an offset corresponding to the black border's size + if (Player::game_config.fake_resolution.Get()) { + int map_height_in_pixels = Game_Map::GetTilesY() * TILE_SIZE; + if (map_height_in_pixels < Player::screen_height) { + y += ((Player::screen_height - map_height_in_pixels) / 2 / TILE_SIZE) * SCREEN_TILE_SIZE; + } + } } else { // Do not use std::clamp here. When the map is smaller than the screen the // upper bound is smaller than the lower bound making the function fail. From f1eea3c9fbe1448ab8d7d89d192fd5a6dc85d051 Mon Sep 17 00:00:00 2001 From: BlisterB Date: Sun, 4 Jan 2026 11:18:23 +0100 Subject: [PATCH 5/9] [FakeResolution] Fix the camera's scrolling on a small looping map --- src/game_player.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/game_player.cpp b/src/game_player.cpp index 6ffa40082c..ce34065a00 100644 --- a/src/game_player.cpp +++ b/src/game_player.cpp @@ -191,15 +191,33 @@ void Game_Player::UpdateScroll(int amount, bool was_jumping) { return; } - auto dx = (GetX() * SCREEN_TILE_SIZE) - Game_Map::GetPositionX() - GetPanX(); - auto dy = (GetY() * SCREEN_TILE_SIZE) - Game_Map::GetPositionY() - GetPanY(); + const auto map_width = Game_Map::GetTilesX() * SCREEN_TILE_SIZE; + const auto map_height = Game_Map::GetTilesY() * SCREEN_TILE_SIZE; + + // When using FakeResolution mode, if the map is too small to fit the screen + // we need to calculate the black border offset, in case of a looping map for example + int screen_offset_x = 0; + if (Player::game_config.fake_resolution.Get()) { + int map_width_in_pixels = Game_Map::GetTilesX() * TILE_SIZE; + if (map_width_in_pixels < Player::screen_width) { + screen_offset_x = ((Player::screen_width - map_width_in_pixels) / 2 / TILE_SIZE) * SCREEN_TILE_SIZE; + } + } + int screen_offset_y = 0; + if (Player::game_config.fake_resolution.Get()) { + int map_height_in_pixels = Game_Map::GetTilesY() * TILE_SIZE; + if (map_height_in_pixels < Player::screen_height) { + screen_offset_y = ((Player::screen_height - map_height_in_pixels) / 2 / TILE_SIZE) * SCREEN_TILE_SIZE; + } + } - const auto w = Game_Map::GetTilesX() * SCREEN_TILE_SIZE; - const auto h = Game_Map::GetTilesY() * SCREEN_TILE_SIZE; + auto dx = (GetX() * SCREEN_TILE_SIZE) - Game_Map::GetPositionX() - GetPanX() + screen_offset_x; + auto dy = (GetY() * SCREEN_TILE_SIZE) - Game_Map::GetPositionY() - GetPanY() + screen_offset_y; - dx = Utils::PositiveModulo(dx + w / 2, w) - w / 2; - dy = Utils::PositiveModulo(dy + h / 2, h) - h / 2; + dx = Utils::PositiveModulo(dx + map_width / 2, map_width) - map_width / 2; + dy = Utils::PositiveModulo(dy + map_height / 2, map_height) - map_height / 2; + // If sx or sy equals zero, no scrolling is needed in the corresponding direction const auto sx = Utils::Signum(dx); const auto sy = Utils::Signum(dy); From 5608ccde3698a135935052df87ef80e43f83aa7e Mon Sep 17 00:00:00 2001 From: BlisterB Date: Sun, 11 Jan 2026 21:17:09 +0100 Subject: [PATCH 6/9] [WideScreen][FakeResolution] Apply the offset on the Panorama only if the map is too small to fit the screen --- src/spriteset_map.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/spriteset_map.cpp b/src/spriteset_map.cpp index 4eb1e2fb8c..47a0f1f644 100644 --- a/src/spriteset_map.cpp +++ b/src/spriteset_map.cpp @@ -326,12 +326,16 @@ void Spriteset_Map::CalculateMapRenderOffset() { void Spriteset_Map::CalculatePanoramaRenderOffset() { // Resolution hack for Panorama + // If the map is too small to fit in the screen, add an offset corresponding to the black border's size if (Player::game_config.fake_resolution.Get()) { - if (Game_Map::Parallax::FakeXPosition()) { - panorama->SetRenderOx((Player::screen_width - (Game_Map::GetTilesX() * TILE_SIZE)) / 2); + int map_width_in_pixels = Game_Map::GetTilesX() * TILE_SIZE; + if (map_width_in_pixels < Player::screen_width) { + panorama->SetRenderOx((Player::screen_width - map_width_in_pixels) / 2); } - if (Game_Map::Parallax::FakeYPosition()) { - panorama->SetRenderOy((Player::screen_height - (Game_Map::GetTilesY() * TILE_SIZE)) / 2); + + int map_height_in_pixels = Game_Map::GetTilesY() * TILE_SIZE; + if (map_height_in_pixels < Player::screen_height) { + panorama->SetRenderOy((Player::screen_height - map_height_in_pixels) / 2); } } } From 9e551ad4f032250c7830c87bb453d5a938226bb0 Mon Sep 17 00:00:00 2001 From: BlisterB Date: Sat, 14 Mar 2026 19:13:13 +0100 Subject: [PATCH 7/9] plane.cpp: Remove a conflicting part of the code --- src/plane.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/plane.cpp b/src/plane.cpp index d4c9806cd2..a2650722c3 100644 --- a/src/plane.cpp +++ b/src/plane.cpp @@ -84,11 +84,6 @@ void Plane::Draw(Bitmap& dst) { dst_rect.x = bg_x; dst_rect.width = bg_width; - if (Game_Map::GetDisplayX() / 16 + Player::screen_width > Game_Map::GetTilesX() * TILE_SIZE) { - // Do not draw out of bounds to the right - dst_rect.width -= (Game_Map::GetDisplayX() / 16 + Player::screen_width) - (Game_Map::GetTilesX() * TILE_SIZE); - } - // Correct the offset if the top-left corner moved. offset_x = shake_x + bg_x; } From 883b6ebd7504dbce1e7e300dd279eef2e1f0625e Mon Sep 17 00:00:00 2001 From: BlisterB Date: Sat, 14 Mar 2026 19:25:36 +0100 Subject: [PATCH 8/9] game_map: remove unused functions --- src/game_map.cpp | 8 -------- src/game_map.h | 6 ------ 2 files changed, 14 deletions(-) diff --git a/src/game_map.cpp b/src/game_map.cpp index 7d49e5ad73..4fcefad802 100644 --- a/src/game_map.cpp +++ b/src/game_map.cpp @@ -2320,11 +2320,3 @@ void Game_Map::Parallax::ClearChangedBG() { Params params {}; // default Param indicates no override ChangeBG(params); } - -bool Game_Map::Parallax::FakeXPosition() { - return parallax_fake_x; -} - -bool Game_Map::Parallax::FakeYPosition() { - return parallax_fake_y; -} diff --git a/src/game_map.h b/src/game_map.h index d7cb29126a..81384edeb3 100644 --- a/src/game_map.h +++ b/src/game_map.h @@ -826,12 +826,6 @@ namespace Game_Map { * the map properties. */ void ClearChangedBG(); - - /** @return Whether ox adjustment is required for fake resolution mode */ - bool FakeXPosition(); - - /** @return Whether oy adjustment is required for fake resolution mode */ - bool FakeYPosition(); } } From 48a938619452d5d03457af3e3973b4698760edac Mon Sep 17 00:00:00 2001 From: BlisterB Date: Sat, 14 Mar 2026 19:31:38 +0100 Subject: [PATCH 9/9] game_map: remove unused variables --- src/game_map.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/game_map.cpp b/src/game_map.cpp index 4fcefad802..0a4e982d20 100644 --- a/src/game_map.cpp +++ b/src/game_map.cpp @@ -2051,9 +2051,6 @@ void Game_Map::Caching::MapEventCache::RemoveEvent(const lcf::rpg::Event& ev) { namespace { int parallax_width; int parallax_height; - - bool parallax_fake_x; - bool parallax_fake_y; } /* Helper function to get the current parallax parameters. If the default @@ -2157,8 +2154,6 @@ void Game_Map::Parallax::ResetPositionX() { return; } - parallax_fake_x = false; - if (!params.scroll_horz && !LoopHorizontal()) { // What is the width of the panorama to display on screen? int pan_screen_width = Player::screen_width; @@ -2185,10 +2180,7 @@ void Game_Map::Parallax::ResetPositionX() { } } else { panorama.pan_x = 0; - parallax_fake_x = true; } - } else { - parallax_fake_x = true; } } @@ -2199,8 +2191,6 @@ void Game_Map::Parallax::ResetPositionY() { return; } - parallax_fake_y = false; - if (!params.scroll_vert && !Game_Map::LoopVertical()) { // What is the height of the panorama to display on screen? int pan_screen_height = Player::screen_height; @@ -2222,10 +2212,7 @@ void Game_Map::Parallax::ResetPositionY() { SetPositionY(pv); } else { panorama.pan_y = 0; - parallax_fake_y = true; } - } else { - parallax_fake_y = true; } }