mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-11-17 15:20:17 +01:00
Added “Prefer 3DPB game data” option.
Useful for quickly switching between the two datasets. 3DPB and FT data can be stored in one folder without collisions.
This commit is contained in:
parent
3b7dc0dae2
commit
64c3f2031b
9 changed files with 102 additions and 71 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<char*, 2> 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)
|
||||
|
|
|
@ -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<char*, 2> dataSearchPaths);
|
||||
static void reset_table();
|
||||
static void firsttime_setup();
|
||||
static void mode_change(int mode);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <string>
|
||||
#include <thread>
|
||||
#include <map>
|
||||
#include <array>
|
||||
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include "SDL.h"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<char*, 2>
|
||||
{
|
||||
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<float>(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>(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<float>(TargetFrameTime.count());
|
||||
auto scale = 1 / (64 / 2 / target);
|
||||
auto scale = 1 / (gfr_display->Height / 2 / target);
|
||||
|
||||
auto spin = Options.HybridSleep ? static_cast<float>(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/
|
||||
|
|
|
@ -65,7 +65,6 @@ class winmain
|
|||
using TimePoint = std::chrono::time_point<Clock>;
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue