From 64c3f2031b3c34c2e99f2f17fc2853144ff6c242 Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Sun, 21 Nov 2021 15:40:56 +0300 Subject: [PATCH] =?UTF-8?q?Added=20=E2=80=9CPrefer=203DPB=20game=20data?= =?UTF-8?q?=E2=80=9D=20option.=20Useful=20for=20quickly=20switching=20betw?= =?UTF-8?q?een=20the=20two=20datasets.=203DPB=20and=20FT=20data=20can=20be?= =?UTF-8?q?=20stored=20in=20one=20folder=20without=20collisions.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SpaceCadetPinball/options.cpp | 11 +++- SpaceCadetPinball/options.h | 5 +- SpaceCadetPinball/pb.cpp | 41 ++++++++++++- SpaceCadetPinball/pb.h | 2 + SpaceCadetPinball/pch.h | 1 + SpaceCadetPinball/pinball.cpp | 5 +- SpaceCadetPinball/pinball.h | 1 + SpaceCadetPinball/winmain.cpp | 105 ++++++++++++++-------------------- SpaceCadetPinball/winmain.h | 2 - 9 files changed, 102 insertions(+), 71 deletions(-) diff --git a/SpaceCadetPinball/options.cpp b/SpaceCadetPinball/options.cpp index 733b432..636d0e8 100644 --- a/SpaceCadetPinball/options.cpp +++ b/SpaceCadetPinball/options.cpp @@ -26,7 +26,7 @@ const ControlRef options::Controls[6] }; -void options::init() +void options::InitPrimary() { auto imContext = ImGui::GetCurrentContext(); ImGuiSettingsHandler ini_handler; @@ -100,7 +100,11 @@ void options::init() Options.SoundChannels = get_int("Sound Channels", DefSoundChannels); Options.SoundChannels = std::min(MaxSoundChannels, std::max(MinSoundChannels, Options.SoundChannels)); Options.HybridSleep = get_int("HybridSleep", false); + Options.Prefer3DPBGameData = get_int("Prefer 3DPB Game Data", false); +} +void options::InitSecondary() +{ winmain::UpdateFrameRate(); auto maxRes = fullscrn::GetMaxResolution(); @@ -132,6 +136,7 @@ void options::uninit() set_int("Uncapped Updates Per Second", Options.UncappedUpdatesPerSecond); set_int("Sound Channels", Options.SoundChannels); set_int("HybridSleep", Options.HybridSleep); + set_int("Prefer 3DPB Game Data", Options.Prefer3DPBGameData); } @@ -251,6 +256,10 @@ void options::toggle(Menu1 uIDCheckItem) Options.LinearFiltering ^= true; render::recreate_screen_texture(); break; + case Menu1::Prefer3DPBGameData: + Options.Prefer3DPBGameData ^= true; + winmain::Restart(); + break; default: break; } diff --git a/SpaceCadetPinball/options.h b/SpaceCadetPinball/options.h index 2ea0505..fff3d15 100644 --- a/SpaceCadetPinball/options.h +++ b/SpaceCadetPinball/options.h @@ -26,6 +26,7 @@ enum class Menu1:int R1024x768 = 503, WindowUniformScale = 600, WindowLinearFilter = 601, + Prefer3DPBGameData = 700, }; enum class InputTypes: unsigned @@ -74,6 +75,7 @@ struct optionsStruct bool UncappedUpdatesPerSecond; int SoundChannels; bool HybridSleep; + bool Prefer3DPBGameData; }; struct ControlRef @@ -93,7 +95,8 @@ public: static constexpr int MaxSoundChannels = 32, MinSoundChannels = 1, DefSoundChannels = 8; static optionsStruct Options; - static void init(); + static void InitPrimary(); + static void InitSecondary(); static void uninit(); static int get_int(LPCSTR lpValueName, int defaultValue); static void set_int(LPCSTR lpValueName, int data); diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index 9fa7fb2..02bfd05 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -33,15 +33,16 @@ int pb::time_ticks = 0, pb::demo_mode = 0, pb::game_mode = 2; float pb::mode_countdown_, pb::time_now = 0, pb::time_next = 0, pb::ball_speed_limit, pb::time_ticks_remainder = 0; high_score_struct pb::highscore_table[5]; bool pb::FullTiltMode = false, pb::cheat_mode = false; +std::string pb::DatFileName; int pb::init() { float projMat[12], zMin = 0, zScaler = 0; - if (winmain::DatFileName.empty()) + if (DatFileName.empty()) return 1; - auto dataFilePath = pinball::make_path_name(winmain::DatFileName); + auto dataFilePath = pinball::make_path_name(DatFileName); record_table = partman::load_records(dataFilePath.c_str(), FullTiltMode); auto useBmpFont = 0; @@ -117,6 +118,42 @@ int pb::uninit() return 0; } +void pb::SelectDatFile(std::array dataSearchPaths) +{ + DatFileName.clear(); + + std::string datFileNames[2] + { + "CADET.DAT", + options::get_string("Pinball Data", pinball::get_rc_string(168, 0)) + }; + + // Default game data test order: CADET.DAT, PINBALL.DAT + if (options::Options.Prefer3DPBGameData) + std::swap(datFileNames[0], datFileNames[1]); + for (auto path : dataSearchPaths) + { + if (DatFileName.empty() && path) + { + pinball::BasePath = path; + for (int i = 0; i < 2; i++) + { + auto datFileName = datFileNames[i]; + auto datFilePath = pinball::make_path_name(datFileName); + auto datFile = fopenu(datFilePath.c_str(), "r"); + if (datFile) + { + fclose(datFile); + DatFileName = datFileName; + FullTiltMode = datFileName == "CADET.DAT"; + printf("Loading game from: %s\n", datFilePath.c_str()); + break; + } + } + } + } +} + void pb::reset_table() { if (MainTable) diff --git a/SpaceCadetPinball/pb.h b/SpaceCadetPinball/pb.h index e787dc4..5c2a173 100644 --- a/SpaceCadetPinball/pb.h +++ b/SpaceCadetPinball/pb.h @@ -41,9 +41,11 @@ public: static TPinballTable* MainTable; static high_score_struct highscore_table[5]; static bool FullTiltMode; + static std::string DatFileName; static int init(); static int uninit(); + static void SelectDatFile(std::array dataSearchPaths); static void reset_table(); static void firsttime_setup(); static void mode_change(int mode); diff --git a/SpaceCadetPinball/pch.h b/SpaceCadetPinball/pch.h index 582609b..60d9a7b 100644 --- a/SpaceCadetPinball/pch.h +++ b/SpaceCadetPinball/pch.h @@ -29,6 +29,7 @@ #include #include #include +#include #define SDL_MAIN_HANDLED #include "SDL.h" diff --git a/SpaceCadetPinball/pinball.cpp b/SpaceCadetPinball/pinball.cpp index 384b15a..0fc39bd 100644 --- a/SpaceCadetPinball/pinball.cpp +++ b/SpaceCadetPinball/pinball.cpp @@ -209,7 +209,7 @@ int LoadStringAlt(uint32_t uID, LPSTR lpBuffer, int cchBufferMax) { auto str = rc_strings.find(uID); if (str == rc_strings.end()) - { + { return 0; } @@ -224,6 +224,7 @@ char pinball::getRcBuffer[6 * 256]; int pinball::rc_string_slot = 0; int pinball::LeftShift = -1; int pinball::RightShift = -1; +std::string pinball::BasePath; char* pinball::get_rc_string(int uID, int a2) { @@ -247,5 +248,5 @@ int pinball::get_rc_int(int uID, int* dst) std::string pinball::make_path_name(const std::string& fileName) { - return winmain::BasePath + fileName; + return BasePath + fileName; } diff --git a/SpaceCadetPinball/pinball.h b/SpaceCadetPinball/pinball.h index 8b92e50..6f9a866 100644 --- a/SpaceCadetPinball/pinball.h +++ b/SpaceCadetPinball/pinball.h @@ -10,6 +10,7 @@ public: static TTextBox* MissTextBox; static int RightShift; static int LeftShift; + static std::string BasePath; static char* get_rc_string(int uID, int a2); static int get_rc_int(int uID, int* dst); diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index e302c59..b7c7930 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -29,14 +29,12 @@ bool winmain::no_time_loss = false; bool winmain::restart = false; gdrv_bitmap8* winmain::gfr_display = nullptr; -std::string winmain::DatFileName; bool winmain::ShowAboutDialog = false; bool winmain::ShowImGuiDemo = false; bool winmain::ShowSpriteViewer = false; bool winmain::LaunchBallEnabled = true; bool winmain::HighScoresEnabled = true; bool winmain::DemoActive = false; -std::string winmain::BasePath; int winmain::MainMenuHeight = 0; std::string winmain::FpsDetails; double winmain::UpdateToFrameRatio; @@ -63,43 +61,6 @@ int winmain::WinMain(LPCSTR lpCmdLine) pinball::quickFlag = strstr(lpCmdLine, "-quick") != nullptr; - // Search for game data in: game folder, user folder - // Game data test order: CADET.DAT, PINBALL.DAT - char* dataSearchPaths[2] - { - SDL_GetBasePath(), - SDL_GetPrefPath(nullptr, "SpaceCadetPinball") - }; - std::string datFileNames[2] - { - "CADET.DAT", - options::get_string("Pinball Data", pinball::get_rc_string(168, 0)) - }; - for (auto path : dataSearchPaths) - { - if (DatFileName.empty() && path) - { - BasePath = path; - for (int i = 0; i < 2; i++) - { - auto datFileName = datFileNames[i]; - auto datFilePath = pinball::make_path_name(datFileName); - auto datFile = fopenu(datFilePath.c_str(), "r"); - if (datFile) - { - fclose(datFile); - DatFileName = datFileName; - if (i == 0) - pb::FullTiltMode = true; - printf("Loading game from: %s\n", datFilePath.c_str()); - break; - } - } - } - - SDL_free(path); - } - // SDL window SDL_Window* window = SDL_CreateWindow ( @@ -152,27 +113,32 @@ int winmain::WinMain(LPCSTR lpCmdLine) auto prefPath = SDL_GetPrefPath(nullptr, "SpaceCadetPinball"); auto iniPath = std::string(prefPath) + "imgui_pb.ini"; io.IniFilename = iniPath.c_str(); - SDL_free(prefPath); - // PB init from message handler + // First step: just load the options, second: run updates depending on FullTiltMode + options::InitPrimary(); + auto basePath = SDL_GetBasePath(); + pb::SelectDatFile(std::array { - options::init(); - if (!Sound::Init(Options.SoundChannels, Options.Sounds)) - Options.Sounds = false; + basePath, + prefPath + }); + options::InitSecondary(); - if (!pinball::quickFlag && !midi::music_init()) - Options.Music = false; + if (!Sound::Init(Options.SoundChannels, Options.Sounds)) + Options.Sounds = false; - if (pb::init()) - { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not load game data", - "The .dat file is missing", window); - return 1; - } + if (!pinball::quickFlag && !midi::music_init()) + Options.Music = false; - fullscrn::init(); + if (pb::init()) + { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not load game data", + "The .dat file is missing", window); + return 1; } + fullscrn::init(); + pb::reset_table(); pb::firsttime_setup(); @@ -249,7 +215,8 @@ int winmain::WinMain(LPCSTR lpCmdLine) gdrv::ScrollBitmapHorizontal(gfr_display, -1); gdrv::fill_bitmap(gfr_display, 1, halfHeight, width - 1, 0, ColorRgba::Black()); // Background - gdrv::fill_bitmap(gfr_display, 1, halfHeight, width - 1, halfHeight, ColorRgba::White()); // Target + // Target + gdrv::fill_bitmap(gfr_display, 1, halfHeight, width - 1, halfHeight, ColorRgba::White()); auto target = static_cast(TargetFrameTime.count()); auto scale = halfHeight / target; @@ -303,13 +270,16 @@ int winmain::WinMain(LPCSTR lpCmdLine) } // Limit duration to 2 * target time - sleepRemainder = std::max(std::min(DurationMs(frameEnd - updateEnd) - targetTimeDelta, TargetFrameTime), -TargetFrameTime); + sleepRemainder = std::max(std::min(DurationMs(frameEnd - updateEnd) - targetTimeDelta, TargetFrameTime), + -TargetFrameTime); frameDuration = std::min(DurationMs(frameEnd - frameStart), 2 * TargetFrameTime); frameStart = frameEnd; UpdateToFrameCounter++; } } + SDL_free(basePath); + SDL_free(prefPath); delete gfr_display; gfr_display = nullptr; options::uninit(); @@ -352,7 +322,7 @@ void winmain::RenderUi() // This window can not loose nav focus for some reason, clear it manually. if (ImGui::IsNavInputDown(ImGuiNavInput_Cancel)) - ImGui::FocusWindow(NULL); + ImGui::FocusWindow(nullptr); } // No demo window in release to save space @@ -539,6 +509,15 @@ void winmain::RenderUi() ImGui::EndMenu(); } + + if (ImGui::BeginMenu("Game Data")) + { + if (ImGui::MenuItem("Prefer 3DPB Data", nullptr, Options.Prefer3DPBGameData)) + { + options::toggle(Menu1::Prefer3DPBGameData); + } + ImGui::EndMenu(); + } ImGui::EndMenu(); } @@ -705,7 +684,7 @@ int winmain::event_handler(const SDL_Event* event) redGreen = i1; } - *pltPtr++ = ColorRgba{ blue, redGreen, redGreen, 0 }; + *pltPtr++ = ColorRgba{blue, redGreen, redGreen, 0}; } gdrv::display_palette(plt); delete[] plt; @@ -826,11 +805,11 @@ int winmain::event_handler(const SDL_Event* event) case SDL_CONTROLLER_BUTTON_BACK: if (single_step) { - SDL_Event event{ SDL_QUIT }; + SDL_Event event{SDL_QUIT}; SDL_PushEvent(&event); } break; - default:; + default: ; } break; case SDL_CONTROLLERBUTTONUP: @@ -953,15 +932,15 @@ void winmain::RenderFrameTimeDialog() if (!gfr_display) return; - ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2{ 300, 70 }); + ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2{300, 70}); if (ImGui::Begin("Frame Times", &DispGRhistory, ImGuiWindowFlags_NoScrollbar)) { auto target = static_cast(TargetFrameTime.count()); - auto scale = 1 / (64 / 2 / target); + auto scale = 1 / (gfr_display->Height / 2 / target); auto spin = Options.HybridSleep ? static_cast(SpinThreshold.count()) : 0; ImGui::Text("Target frame time:%03.04fms, 1px:%03.04fms, SpinThreshold:%03.04fms", - target, scale, spin); + target, scale, spin); gfr_display->BlitToTexture(); auto region = ImGui::GetContentRegionAvail(); ImGui::Image(gfr_display->Texture, region); @@ -971,7 +950,7 @@ void winmain::RenderFrameTimeDialog() } void winmain::HybridSleep(DurationMs sleepTarget) -{ +{ static constexpr double StdDevFactor = 0.5; // This nice concept is from https://blat-blatnik.github.io/computerBear/making-accurate-sleep-function/ diff --git a/SpaceCadetPinball/winmain.h b/SpaceCadetPinball/winmain.h index 289d142..730e3d6 100644 --- a/SpaceCadetPinball/winmain.h +++ b/SpaceCadetPinball/winmain.h @@ -65,7 +65,6 @@ class winmain using TimePoint = std::chrono::time_point; public: - static std::string DatFileName; static bool single_step; static SDL_Window* MainWindow; static SDL_Renderer* Renderer; @@ -73,7 +72,6 @@ public: static bool LaunchBallEnabled; static bool HighScoresEnabled; static bool DemoActive; - static std::string BasePath; static int MainMenuHeight; static int WinMain(LPCSTR lpCmdLine);