From 79280d2f5835f4c8cc93c7886498a6225916c35a Mon Sep 17 00:00:00 2001 From: rgdilisio Date: Sun, 13 Sep 2026 16:55:47 -0300 Subject: [PATCH 1/5] Add bilinear filtering option and integrate with Defaults reset plus Save Ini file --- Source/OptionsMenu.cpp | 24 +++++++++++++++++++++++- Source/OptionsMenu.hpp | 4 ++++ Source/Parameters.cpp | 29 +++++++++++++++++++++++++++++ Source/Parameters.hpp | 8 ++++++++ Source/Window.cpp | 22 ++++++++++++++++++++++ Source/Window.hpp | 6 +++++- 6 files changed, 91 insertions(+), 2 deletions(-) diff --git a/Source/OptionsMenu.cpp b/Source/OptionsMenu.cpp index f3d195dc..8dbd026d 100644 --- a/Source/OptionsMenu.cpp +++ b/Source/OptionsMenu.cpp @@ -160,6 +160,10 @@ void cOptionsMenu::BuildItems() { mItems.push_back({ eOptType::IntRange, eOptSection::Video, "Window scale", OPT_WINDOW_SCALE, 0, 6, 1 }); mItems.push_back({ eOptType::Toggle, eOptSection::Video, "Integer scaling", OPT_INTEGER_SCALING }); + // Bilinear filtering + mItems.push_back({ eOptType::Toggle, eOptSection::Video, "Bilinear filtering", OPT_BILINEAR_FILTERING }); + // Bilinear filtering + // These were in INI but missing from menu //mItems.push_back({ eOptType::IntRange, "Window columns", OPT_WINDOW_COLUMNS, 0, 80, 1 }); // 0=AUTO //mItems.push_back({ eOptType::IntRange, "Window rows", OPT_WINDOW_ROWS, 0, 60, 1 }); // 0=AUTO @@ -275,6 +279,10 @@ int cOptionsMenu::GetInt(int optId) const { return (int)g_Fodder->mStartParams->mWindowScale; case OPT_INTEGER_SCALING: return g_Fodder->mStartParams->mIntegerScaling ? 1 : 0; + // Bilinear filtering + case OPT_BILINEAR_FILTERING: return g_Fodder->mStartParams->mBilinearFilter ? 1 : 0; + // Bilinear filtering + case OPT_WINDOW_COLUMNS: return (int)g_Fodder->mStartParams->mWindowColumns; case OPT_WINDOW_ROWS: return (int)g_Fodder->mStartParams->mWindowRows; case OPT_COPY_PROTECTION: return g_Fodder->mStartParams->mCopyProtection ? 1 : 0; @@ -334,7 +342,7 @@ void cOptionsMenu::SetInt(int optId, int v) { } break; } - + case OPT_WINDOW_SCALE: { const int clamped = clamp_int(v, 0, 6); g_Fodder->mStartParams->mWindowScale = (uint32)clamped; @@ -342,6 +350,15 @@ void cOptionsMenu::SetInt(int optId, int v) { break; } + // Bilinear filtering + case OPT_BILINEAR_FILTERING: { + g_Fodder->mStartParams->mBilinearFilter = (v != 0); + if (g_Fodder->mParams) + g_Fodder->mParams->mBilinearFilter = g_Fodder->mStartParams->mBilinearFilter; + break; + } + // Bilinear filtering + case OPT_WINDOW_COLUMNS: { const int clamped = clamp_int(v, 0, 80); g_Fodder->mStartParams->mWindowColumns = (uint32)clamped; @@ -696,6 +713,11 @@ void cOptionsMenu::ResetDefaults() { g_Fodder->mStartParams->clear(); mApplied = true; g_Fodder->mStartParams->SaveIni(); + + // Bilinear filtering - reset to default (false) for current parameters same as toggling the menu option but forcing false since bilinear filtering is OFF by default + if (g_Fodder->mParams) + g_Fodder->mParams->mBilinearFilter = false; + // Bilinear filtering } void cOptionsMenu::OnRowClick(int16 action, int16 arg) { diff --git a/Source/OptionsMenu.hpp b/Source/OptionsMenu.hpp index bfdf9a12..37573eb8 100644 --- a/Source/OptionsMenu.hpp +++ b/Source/OptionsMenu.hpp @@ -82,6 +82,10 @@ class cOptionsMenu { OPT_WINDOW_SCALE, OPT_INTEGER_SCALING, + // Bilinear filtering + OPT_BILINEAR_FILTERING, + // Bilinear filtering + OPT_ALTERNATE_MOUSE, OPT_MOUSE_LOCKED, OPT_MOUSE_SPEED, diff --git a/Source/Parameters.cpp b/Source/Parameters.cpp index 168679fb..2e19e9d5 100644 --- a/Source/Parameters.cpp +++ b/Source/Parameters.cpp @@ -166,6 +166,11 @@ std::string sFodderParameters::ToJson() { Save["mWindowMode"] = mWindowMode; Save["mIntegerScaling"] = mIntegerScaling; + + // Bilinear filtering + Save["mBilinearFilter"] = mBilinearFilter; + // Bilinear filtering + Save["mRandom"] = mRandom; Save["mRandomMapOptionsEnabled"] = mRandomMapOptionsEnabled; Save["mRandomMapSeed"] = mRandomMapSeed; @@ -210,6 +215,11 @@ bool sFodderParameters::FromJson(const std::string& pJson) { mMissionNumber = LoadedData["mMissionNumber"]; mPhaseNumber = LoadedData["mPhaseNumber"]; mWindowMode = LoadedData["mWindowMode"]; + + // Bilinear filtering + mBilinearFilter = LoadedData["mBilinearFilter"]; + // Bilinear filtering + mRandom = LoadedData["mRandom"]; if (LoadedData.count("mRandomMapOptionsEnabled") > 0) mRandomMapOptionsEnabled = LoadedData["mRandomMapOptionsEnabled"]; @@ -293,6 +303,10 @@ void sFodderParameters::PrepareOptions() { ("window-scale", "Set the window scale", cxxopts::value()->default_value("0")) ("integer-scaling", "Use integer scaling", cxxopts::value()->default_value("true")) + // Bilinear filtering + ("bilinear", "Apply bilinear filtering", cxxopts::value()->default_value("false")) + // Bilinear filtering + ("cheats", "Enable cheat keys", cxxopts::value()->default_value("false")) ("max-sprite", "Set the maximum sprites", cxxopts::value()->default_value("45"), "45") ("max-spawn", "Set the maximum spawn", cxxopts::value()->default_value("10"), "10") @@ -486,6 +500,10 @@ bool sFodderParameters::ProcessCLI(int argc, char *argv[]) { if (result.count("integer-scaling")) mIntegerScaling = result["integer-scaling"].as(); + + if (result.count("bilinear")) + mBilinearFilter = result["bilinear"].as(); + mRandom = result["random"].as(); if (result["random-save"].count()) { @@ -754,6 +772,10 @@ bool sFodderParameters::SaveIni() { ini.set("scale", (mWindowScale == 0) ? "auto" : std::to_string(mWindowScale)); ini.set("integer", mIntegerScaling ? "true" : "false"); + // Bilinear filtering + ini.set("bilinear", mBilinearFilter ? "true" : "false"); + // Bilinear filtering + ini.set("columns", (mWindowColumns == 0) ? "0" : std::to_string(mWindowColumns)); ini.set("rows", (mWindowRows == 0) ? "0" : std::to_string(mWindowRows)); @@ -845,6 +867,13 @@ bool sFodderParameters::ProcessINI() { else mWindowMode = false; + // Bilinear filtering + if (ini.get("bilinear", "false") == "true") + mBilinearFilter = true; + else + mBilinearFilter = false; + // Bilinear filtering + if (ini.get("cheats", "false") == "true") mCheatsEnabled = true; else diff --git a/Source/Parameters.hpp b/Source/Parameters.hpp index 6f5fd556..76d33f17 100644 --- a/Source/Parameters.hpp +++ b/Source/Parameters.hpp @@ -76,6 +76,10 @@ class sFodderParameters { size_t mWindowRows; size_t mWindowColumns; + // Bilinear filtering + bool mBilinearFilter; // Use bilinear filtering + // Bilinear filtering + bool mRandom; // Start a random map bool mRandomSave; // Create a random map bool mRandomMenuOnStart; // Open the create-random-map options menu on startup @@ -207,6 +211,10 @@ class sFodderParameters { mIntegerScaling = true; mWindowScale = 0; + // Bilinear filtering + mBilinearFilter = false; + // Bilinear filtering + mWindowRows = 0; mWindowColumns = 0; diff --git a/Source/Window.cpp b/Source/Window.cpp index eb531e0f..d27c6f63 100644 --- a/Source/Window.cpp +++ b/Source/Window.cpp @@ -41,6 +41,10 @@ cWindow::cWindow() { mHasFocus = true; mResized = false; + + // Bilinear filtering + mBilinearFilter = false; + // Bilinear filtering } cWindow::~cWindow() { @@ -430,6 +434,15 @@ void cWindow::RenderAt( cSurface* pImage ) { } } + // Bilinear filtering + if (g_Fodder->mParams->mBilinearFilter) { + SDL_SetTextureScaleMode(pImage->GetTexture(), SDL_SCALEMODE_LINEAR); + } + else { + SDL_SetTextureScaleMode(pImage->GetTexture(), SDL_SCALEMODE_NEAREST); + } + // Bilinear filtering + SDL_RenderTexture( mRenderer, pImage->GetTexture(), &Src, &Dest ); } @@ -459,6 +472,15 @@ void cWindow::RenderShrunk( cSurface* pImage ) { } } + // Bilinear filtering + if (g_Fodder->mParams->mBilinearFilter) { + SDL_SetTextureScaleMode(pImage->GetTexture(), SDL_SCALEMODE_LINEAR); + } + else { + SDL_SetTextureScaleMode(pImage->GetTexture(), SDL_SCALEMODE_NEAREST); + } + // Bilinear filtering + SDL_RenderTexture( mRenderer, pImage->GetTexture(), &Src, &Dest); } diff --git a/Source/Window.hpp b/Source/Window.hpp index b75cf62d..19326385 100644 --- a/Source/Window.hpp +++ b/Source/Window.hpp @@ -38,6 +38,10 @@ class cWindow { bool mHasFocus; bool mResized; + // Bilinear filtering + bool mBilinearFilter; + // Bilinear filtering + protected: @@ -106,7 +110,7 @@ class cWindow { void ToggleVSync(bool pEnabled); float GetRefreshRate(); - + }; class cWindowNull : public cWindow { From 1f2befdc571346a233b68f486404a23b4e486560 Mon Sep 17 00:00:00 2001 From: rgdilisio Date: Tue, 15 Sep 2026 20:41:30 -0300 Subject: [PATCH 2/5] Remove basic bilinear filtering comments per review --- Source/OptionsMenu.cpp | 11 +---------- Source/OptionsMenu.hpp | 3 --- Source/Parameters.cpp | 15 --------------- Source/Parameters.hpp | 7 +------ Source/Window.cpp | 6 ------ Source/Window.hpp | 3 --- 6 files changed, 2 insertions(+), 43 deletions(-) diff --git a/Source/OptionsMenu.cpp b/Source/OptionsMenu.cpp index 8dbd026d..eab41c50 100644 --- a/Source/OptionsMenu.cpp +++ b/Source/OptionsMenu.cpp @@ -159,10 +159,7 @@ void cOptionsMenu::BuildItems() { mItems.push_back({ eOptType::Toggle, eOptSection::Video, "Display mode", OPT_WINDOW_MODE }); mItems.push_back({ eOptType::IntRange, eOptSection::Video, "Window scale", OPT_WINDOW_SCALE, 0, 6, 1 }); mItems.push_back({ eOptType::Toggle, eOptSection::Video, "Integer scaling", OPT_INTEGER_SCALING }); - - // Bilinear filtering mItems.push_back({ eOptType::Toggle, eOptSection::Video, "Bilinear filtering", OPT_BILINEAR_FILTERING }); - // Bilinear filtering // These were in INI but missing from menu //mItems.push_back({ eOptType::IntRange, "Window columns", OPT_WINDOW_COLUMNS, 0, 80, 1 }); // 0=AUTO @@ -278,10 +275,7 @@ int cOptionsMenu::GetInt(int optId) const { return g_Fodder->mWindow->GetScaler(); return (int)g_Fodder->mStartParams->mWindowScale; case OPT_INTEGER_SCALING: return g_Fodder->mStartParams->mIntegerScaling ? 1 : 0; - - // Bilinear filtering case OPT_BILINEAR_FILTERING: return g_Fodder->mStartParams->mBilinearFilter ? 1 : 0; - // Bilinear filtering case OPT_WINDOW_COLUMNS: return (int)g_Fodder->mStartParams->mWindowColumns; case OPT_WINDOW_ROWS: return (int)g_Fodder->mStartParams->mWindowRows; @@ -350,14 +344,12 @@ void cOptionsMenu::SetInt(int optId, int v) { break; } - // Bilinear filtering case OPT_BILINEAR_FILTERING: { g_Fodder->mStartParams->mBilinearFilter = (v != 0); if (g_Fodder->mParams) g_Fodder->mParams->mBilinearFilter = g_Fodder->mStartParams->mBilinearFilter; break; } - // Bilinear filtering case OPT_WINDOW_COLUMNS: { const int clamped = clamp_int(v, 0, 80); @@ -714,10 +706,9 @@ void cOptionsMenu::ResetDefaults() { mApplied = true; g_Fodder->mStartParams->SaveIni(); - // Bilinear filtering - reset to default (false) for current parameters same as toggling the menu option but forcing false since bilinear filtering is OFF by default + // Reset bilinear filtering to false (default value) for current parameters same as toggling the menu option but forcing false since bilinear filtering is OFF by default if (g_Fodder->mParams) g_Fodder->mParams->mBilinearFilter = false; - // Bilinear filtering } void cOptionsMenu::OnRowClick(int16 action, int16 arg) { diff --git a/Source/OptionsMenu.hpp b/Source/OptionsMenu.hpp index 37573eb8..87b73bc1 100644 --- a/Source/OptionsMenu.hpp +++ b/Source/OptionsMenu.hpp @@ -81,10 +81,7 @@ class cOptionsMenu { OPT_WINDOW_MODE = 1, OPT_WINDOW_SCALE, OPT_INTEGER_SCALING, - - // Bilinear filtering OPT_BILINEAR_FILTERING, - // Bilinear filtering OPT_ALTERNATE_MOUSE, OPT_MOUSE_LOCKED, diff --git a/Source/Parameters.cpp b/Source/Parameters.cpp index 2e19e9d5..0f82318a 100644 --- a/Source/Parameters.cpp +++ b/Source/Parameters.cpp @@ -166,10 +166,7 @@ std::string sFodderParameters::ToJson() { Save["mWindowMode"] = mWindowMode; Save["mIntegerScaling"] = mIntegerScaling; - - // Bilinear filtering Save["mBilinearFilter"] = mBilinearFilter; - // Bilinear filtering Save["mRandom"] = mRandom; Save["mRandomMapOptionsEnabled"] = mRandomMapOptionsEnabled; @@ -215,11 +212,7 @@ bool sFodderParameters::FromJson(const std::string& pJson) { mMissionNumber = LoadedData["mMissionNumber"]; mPhaseNumber = LoadedData["mPhaseNumber"]; mWindowMode = LoadedData["mWindowMode"]; - - // Bilinear filtering mBilinearFilter = LoadedData["mBilinearFilter"]; - // Bilinear filtering - mRandom = LoadedData["mRandom"]; if (LoadedData.count("mRandomMapOptionsEnabled") > 0) mRandomMapOptionsEnabled = LoadedData["mRandomMapOptionsEnabled"]; @@ -302,10 +295,7 @@ void sFodderParameters::PrepareOptions() { ("w,window", "Start in window mode", cxxopts::value()->default_value("false")) ("window-scale", "Set the window scale", cxxopts::value()->default_value("0")) ("integer-scaling", "Use integer scaling", cxxopts::value()->default_value("true")) - - // Bilinear filtering ("bilinear", "Apply bilinear filtering", cxxopts::value()->default_value("false")) - // Bilinear filtering ("cheats", "Enable cheat keys", cxxopts::value()->default_value("false")) ("max-sprite", "Set the maximum sprites", cxxopts::value()->default_value("45"), "45") @@ -771,10 +761,7 @@ bool sFodderParameters::SaveIni() { ini.set("scale", (mWindowScale == 0) ? "auto" : std::to_string(mWindowScale)); ini.set("integer", mIntegerScaling ? "true" : "false"); - - // Bilinear filtering ini.set("bilinear", mBilinearFilter ? "true" : "false"); - // Bilinear filtering ini.set("columns", (mWindowColumns == 0) ? "0" : std::to_string(mWindowColumns)); ini.set("rows", (mWindowRows == 0) ? "0" : std::to_string(mWindowRows)); @@ -867,12 +854,10 @@ bool sFodderParameters::ProcessINI() { else mWindowMode = false; - // Bilinear filtering if (ini.get("bilinear", "false") == "true") mBilinearFilter = true; else mBilinearFilter = false; - // Bilinear filtering if (ini.get("cheats", "false") == "true") mCheatsEnabled = true; diff --git a/Source/Parameters.hpp b/Source/Parameters.hpp index 76d33f17..cc814c64 100644 --- a/Source/Parameters.hpp +++ b/Source/Parameters.hpp @@ -76,9 +76,7 @@ class sFodderParameters { size_t mWindowRows; size_t mWindowColumns; - // Bilinear filtering - bool mBilinearFilter; // Use bilinear filtering - // Bilinear filtering + bool mBilinearFilter; // Use bilinear filtering bool mRandom; // Start a random map bool mRandomSave; // Create a random map @@ -210,10 +208,7 @@ class sFodderParameters { mWindowMode = false; mIntegerScaling = true; mWindowScale = 0; - - // Bilinear filtering mBilinearFilter = false; - // Bilinear filtering mWindowRows = 0; mWindowColumns = 0; diff --git a/Source/Window.cpp b/Source/Window.cpp index d27c6f63..1132b3d8 100644 --- a/Source/Window.cpp +++ b/Source/Window.cpp @@ -42,9 +42,7 @@ cWindow::cWindow() { mHasFocus = true; mResized = false; - // Bilinear filtering mBilinearFilter = false; - // Bilinear filtering } cWindow::~cWindow() { @@ -434,14 +432,12 @@ void cWindow::RenderAt( cSurface* pImage ) { } } - // Bilinear filtering if (g_Fodder->mParams->mBilinearFilter) { SDL_SetTextureScaleMode(pImage->GetTexture(), SDL_SCALEMODE_LINEAR); } else { SDL_SetTextureScaleMode(pImage->GetTexture(), SDL_SCALEMODE_NEAREST); } - // Bilinear filtering SDL_RenderTexture( mRenderer, pImage->GetTexture(), &Src, &Dest ); } @@ -472,14 +468,12 @@ void cWindow::RenderShrunk( cSurface* pImage ) { } } - // Bilinear filtering if (g_Fodder->mParams->mBilinearFilter) { SDL_SetTextureScaleMode(pImage->GetTexture(), SDL_SCALEMODE_LINEAR); } else { SDL_SetTextureScaleMode(pImage->GetTexture(), SDL_SCALEMODE_NEAREST); } - // Bilinear filtering SDL_RenderTexture( mRenderer, pImage->GetTexture(), &Src, &Dest); } diff --git a/Source/Window.hpp b/Source/Window.hpp index 19326385..4b27689f 100644 --- a/Source/Window.hpp +++ b/Source/Window.hpp @@ -37,10 +37,7 @@ class cWindow { bool mWindowMode; bool mHasFocus; bool mResized; - - // Bilinear filtering bool mBilinearFilter; - // Bilinear filtering protected: From 45e5302196982d10a47a09bcb8525e94b8e1e250 Mon Sep 17 00:00:00 2001 From: rgdilisio Date: Sat, 19 Sep 2026 01:28:09 -0300 Subject: [PATCH 3/5] Add F10 to toggle bilinear filtering on the fly --- Source/Fodder.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Source/Fodder.cpp b/Source/Fodder.cpp index 6699ffb6..f9a65f87 100644 --- a/Source/Fodder.cpp +++ b/Source/Fodder.cpp @@ -2362,6 +2362,16 @@ void cFodder::keyProcess(uint8 pKeyCode, bool pPressed) mWindow->WindowDecrease(); } + // Toggle Bilinear Filtering by pressing F10 + if (pKeyCode == SDL_SCANCODE_F10 && pPressed) + { + if (g_Fodder->mParams) + if(!g_Fodder->mParams->mBilinearFilter) + g_Fodder->mParams->mBilinearFilter = true; + else + g_Fodder->mParams->mBilinearFilter = false; + } + if (pKeyCode == SDL_SCANCODE_F11 && pPressed) { mWindow->ToggleFullscreen(); From 32b352039a7feaeee2d2907d01b925e9fde913b4 Mon Sep 17 00:00:00 2001 From: rgdilisio Date: Mon, 21 Sep 2026 19:18:05 -0300 Subject: [PATCH 4/5] Change toggle bilinear filtering from F10 to F8 since F10 was already taken --- Source/Fodder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Fodder.cpp b/Source/Fodder.cpp index f9a65f87..b69e3f08 100644 --- a/Source/Fodder.cpp +++ b/Source/Fodder.cpp @@ -2362,8 +2362,8 @@ void cFodder::keyProcess(uint8 pKeyCode, bool pPressed) mWindow->WindowDecrease(); } - // Toggle Bilinear Filtering by pressing F10 - if (pKeyCode == SDL_SCANCODE_F10 && pPressed) + // Toggle Bilinear Filtering by pressing F8 + if (pKeyCode == SDL_SCANCODE_F8 && pPressed) { if (g_Fodder->mParams) if(!g_Fodder->mParams->mBilinearFilter) From 08b345f97aafe14f897db14d43039b547d25a5a6 Mon Sep 17 00:00:00 2001 From: rgdilisio Date: Mon, 21 Sep 2026 20:09:48 -0300 Subject: [PATCH 5/5] Update README.md to document F8 toggles bilinear filtering and --bilinear for the CLI params --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5cb254f3..e56ea9ae 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ Open Fodder supports six demos from the Amiga platform, and three retail release -w, --window Start in window mode --window-scale arg Set the window scale (default: 0) --integer-scaling Set integer scaling (default: true) + --bilinear Apply bilinear filtering --cheats Enable cheat keys --max-sprite 45 Set the maximum sprites (default: 45) @@ -119,6 +120,7 @@ Open Fodder supports six demos from the Amiga platform, and three retail release ``` * F1: Switch to Amiga version (if available) * F2: Switch to PC version (if available) +* F8: Toggle bilinear filter * F9: Make current squad invincible (with --cheats enabled) * F10: Complete current map (with --cheats enabled) * F11: Toggle full screen