1
0
Fork 0
mirror of https://github.com/k4zmu2a/SpaceCadetPinball.git synced 2024-12-18 10:37:53 +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:
Muzychenko Andrey 2021-11-21 15:40:56 +03:00
parent 3b7dc0dae2
commit 64c3f2031b
9 changed files with 102 additions and 71 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -29,6 +29,7 @@
#include <string>
#include <thread>
#include <map>
#include <array>
#define SDL_MAIN_HANDLED
#include "SDL.h"

View file

@ -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;
}

View file

@ -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);

View file

@ -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/

View file

@ -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);