mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-12-21 05:12:20 -05:00
parent
43af97127b
commit
0a2d6847ba
8 changed files with 99 additions and 46 deletions
|
@ -4,9 +4,11 @@
|
||||||
int Sound::num_channels;
|
int Sound::num_channels;
|
||||||
bool Sound::enabled_flag = false;
|
bool Sound::enabled_flag = false;
|
||||||
int* Sound::TimeStamps = nullptr;
|
int* Sound::TimeStamps = nullptr;
|
||||||
|
int Sound::Volume = MIX_MAX_VOLUME;
|
||||||
|
|
||||||
bool Sound::Init(int channels, bool enableFlag)
|
bool Sound::Init(int channels, bool enableFlag, int volume)
|
||||||
{
|
{
|
||||||
|
Volume = volume;
|
||||||
Mix_Init(MIX_INIT_MID_Proxy);
|
Mix_Init(MIX_INIT_MID_Proxy);
|
||||||
auto result = Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024);
|
auto result = Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024);
|
||||||
SetChannels(channels);
|
SetChannels(channels);
|
||||||
|
@ -80,4 +82,11 @@ void Sound::SetChannels(int channels)
|
||||||
delete[] TimeStamps;
|
delete[] TimeStamps;
|
||||||
TimeStamps = new int[num_channels]();
|
TimeStamps = new int[num_channels]();
|
||||||
Mix_AllocateChannels(num_channels);
|
Mix_AllocateChannels(num_channels);
|
||||||
|
SetVolume(Volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::SetVolume(int volume)
|
||||||
|
{
|
||||||
|
Volume = volume;
|
||||||
|
Mix_Volume(-1, volume);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
class Sound
|
class Sound
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool Init(int channels, bool enableFlag);
|
static bool Init(int channels, bool enableFlag, int volume);
|
||||||
static void Enable(bool enableFlag);
|
static void Enable(bool enableFlag);
|
||||||
static void Activate();
|
static void Activate();
|
||||||
static void Deactivate();
|
static void Deactivate();
|
||||||
|
@ -13,8 +13,10 @@ public:
|
||||||
static Mix_Chunk* LoadWaveFile(const std::string& lpName);
|
static Mix_Chunk* LoadWaveFile(const std::string& lpName);
|
||||||
static void FreeSound(Mix_Chunk* wave);
|
static void FreeSound(Mix_Chunk* wave);
|
||||||
static void SetChannels(int channels);
|
static void SetChannels(int channels);
|
||||||
|
static void SetVolume(int volume);
|
||||||
private:
|
private:
|
||||||
static int num_channels;
|
static int num_channels;
|
||||||
static bool enabled_flag;
|
static bool enabled_flag;
|
||||||
static int* TimeStamps;
|
static int* TimeStamps;
|
||||||
|
static int Volume;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
std::vector<Mix_Music*> midi::LoadedTracks{};
|
std::vector<Mix_Music*> midi::LoadedTracks{};
|
||||||
Mix_Music *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::NextTrack;
|
Mix_Music *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::NextTrack;
|
||||||
bool midi::SetNextTrackFlag;
|
bool midi::SetNextTrackFlag;
|
||||||
|
int midi::Volume = MIX_MAX_VOLUME;
|
||||||
|
|
||||||
constexpr uint32_t FOURCC(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
|
constexpr uint32_t FOURCC(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
|
||||||
{
|
{
|
||||||
|
@ -47,8 +48,9 @@ int midi::music_stop()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int midi::music_init()
|
int midi::music_init(int volume)
|
||||||
{
|
{
|
||||||
|
SetVolume(volume);
|
||||||
active_track = nullptr;
|
active_track = nullptr;
|
||||||
|
|
||||||
if (pb::FullTiltMode)
|
if (pb::FullTiltMode)
|
||||||
|
@ -87,6 +89,12 @@ void midi::music_shutdown()
|
||||||
LoadedTracks.clear();
|
LoadedTracks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void midi::SetVolume(int volume)
|
||||||
|
{
|
||||||
|
Volume = volume;
|
||||||
|
Mix_VolumeMusic(volume);
|
||||||
|
}
|
||||||
|
|
||||||
Mix_Music* midi::load_track(std::string fileName)
|
Mix_Music* midi::load_track(std::string fileName)
|
||||||
{
|
{
|
||||||
Mix_Music* audio = nullptr;
|
Mix_Music* audio = nullptr;
|
||||||
|
@ -157,6 +165,9 @@ bool midi::play_track(Mix_Music* midi)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On Windows, MIDI volume can only be set during playback.
|
||||||
|
// And it changes application master volume for some reason.
|
||||||
|
SetVolume(Volume);
|
||||||
active_track = midi;
|
active_track = midi;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,12 +88,15 @@ class midi
|
||||||
public:
|
public:
|
||||||
static int play_pb_theme();
|
static int play_pb_theme();
|
||||||
static int music_stop();
|
static int music_stop();
|
||||||
static int music_init();
|
static int music_init(int volume);
|
||||||
static void music_shutdown();
|
static void music_shutdown();
|
||||||
|
static void SetVolume(int volume);
|
||||||
private:
|
private:
|
||||||
static std::vector<Mix_Music*> LoadedTracks;
|
static std::vector<Mix_Music*> LoadedTracks;
|
||||||
static Mix_Music *track1, *track2, *track3, *active_track, *NextTrack;
|
static Mix_Music *track1, *track2, *track3, *active_track, *NextTrack;
|
||||||
static bool SetNextTrackFlag;
|
static bool SetNextTrackFlag;
|
||||||
|
static int Volume;
|
||||||
|
|
||||||
static Mix_Music* load_track(std::string fileName);
|
static Mix_Music* load_track(std::string fileName);
|
||||||
static bool play_track(Mix_Music* midi);
|
static bool play_track(Mix_Music* midi);
|
||||||
static std::vector<uint8_t>* MdsToMidi(std::string file);
|
static std::vector<uint8_t>* MdsToMidi(std::string file);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
constexpr int options::MaxUps, options::MaxFps, options::MinUps, options::MinFps, options::DefUps, options::DefFps;
|
constexpr int options::MaxUps, options::MaxFps, options::MinUps, options::MinFps, options::DefUps, options::DefFps;
|
||||||
constexpr int options::MaxSoundChannels, options::MinSoundChannels, options::DefSoundChannels;
|
constexpr int options::MaxSoundChannels, options::MinSoundChannels, options::DefSoundChannels;
|
||||||
|
constexpr int options::MaxVolume, options::MinVolume, options::DefVolume;
|
||||||
|
|
||||||
optionsStruct options::Options{};
|
optionsStruct options::Options{};
|
||||||
std::map<std::string, std::string> options::settings{};
|
std::map<std::string, std::string> options::settings{};
|
||||||
|
@ -92,16 +93,17 @@ void options::InitPrimary()
|
||||||
ImGui::GetIO().FontGlobalScale = get_float("UI Scale", 1.0f);
|
ImGui::GetIO().FontGlobalScale = get_float("UI Scale", 1.0f);
|
||||||
Options.Resolution = get_int("Screen Resolution", -1);
|
Options.Resolution = get_int("Screen Resolution", -1);
|
||||||
Options.LinearFiltering = get_int("Linear Filtering", true);
|
Options.LinearFiltering = get_int("Linear Filtering", true);
|
||||||
Options.FramesPerSecond = std::min(MaxFps, std::max(MinUps, get_int("Frames Per Second", DefFps)));
|
Options.FramesPerSecond = Clamp(get_int("Frames Per Second", DefFps), MinFps, MaxFps);
|
||||||
Options.UpdatesPerSecond = std::min(MaxUps, std::max(MinUps, get_int("Updates Per Second", DefUps)));
|
Options.UpdatesPerSecond = Clamp(get_int("Updates Per Second", DefUps), MinUps, MaxUps);
|
||||||
Options.UpdatesPerSecond = std::max(Options.UpdatesPerSecond, Options.FramesPerSecond);
|
Options.UpdatesPerSecond = std::max(Options.UpdatesPerSecond, Options.FramesPerSecond);
|
||||||
Options.ShowMenu = get_int("ShowMenu", true);
|
Options.ShowMenu = get_int("ShowMenu", true);
|
||||||
Options.UncappedUpdatesPerSecond = get_int("Uncapped Updates Per Second", false);
|
Options.UncappedUpdatesPerSecond = get_int("Uncapped Updates Per Second", false);
|
||||||
Options.SoundChannels = get_int("Sound Channels", DefSoundChannels);
|
Options.SoundChannels = Clamp(get_int("Sound Channels", DefSoundChannels), MinSoundChannels, MaxSoundChannels);
|
||||||
Options.SoundChannels = std::min(MaxSoundChannels, std::max(MinSoundChannels, Options.SoundChannels));
|
|
||||||
Options.HybridSleep = get_int("HybridSleep", false);
|
Options.HybridSleep = get_int("HybridSleep", false);
|
||||||
Options.Prefer3DPBGameData = get_int("Prefer 3DPB Game Data", false);
|
Options.Prefer3DPBGameData = get_int("Prefer 3DPB Game Data", false);
|
||||||
Options.IntegerScaling = get_int("Integer Scaling", false);
|
Options.IntegerScaling = get_int("Integer Scaling", false);
|
||||||
|
Options.SoundVolume = Clamp(get_int("Sound Volume", DefVolume), MinVolume, MaxVolume);
|
||||||
|
Options.MusicVolume = Clamp(get_int("Music Volume", DefVolume), MinVolume, MaxVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void options::InitSecondary()
|
void options::InitSecondary()
|
||||||
|
@ -139,6 +141,8 @@ void options::uninit()
|
||||||
set_int("HybridSleep", Options.HybridSleep);
|
set_int("HybridSleep", Options.HybridSleep);
|
||||||
set_int("Prefer 3DPB Game Data", Options.Prefer3DPBGameData);
|
set_int("Prefer 3DPB Game Data", Options.Prefer3DPBGameData);
|
||||||
set_int("Integer Scaling", Options.IntegerScaling);
|
set_int("Integer Scaling", Options.IntegerScaling);
|
||||||
|
set_int("Sound Volume", Options.SoundVolume);
|
||||||
|
set_int("Music Volume", Options.MusicVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,8 @@ struct optionsStruct
|
||||||
bool HybridSleep;
|
bool HybridSleep;
|
||||||
bool Prefer3DPBGameData;
|
bool Prefer3DPBGameData;
|
||||||
bool IntegerScaling;
|
bool IntegerScaling;
|
||||||
|
int SoundVolume;
|
||||||
|
int MusicVolume;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ControlRef
|
struct ControlRef
|
||||||
|
@ -95,6 +97,7 @@ public:
|
||||||
DefUps = 120, DefFps = 60;
|
DefUps = 120, DefFps = 60;
|
||||||
// Original uses 8 sound channels
|
// Original uses 8 sound channels
|
||||||
static constexpr int MaxSoundChannels = 32, MinSoundChannels = 1, DefSoundChannels = 8;
|
static constexpr int MaxSoundChannels = 32, MinSoundChannels = 1, DefSoundChannels = 8;
|
||||||
|
static constexpr int MaxVolume = MIX_MAX_VOLUME, MinVolume = 0, DefVolume = MaxVolume;
|
||||||
static optionsStruct Options;
|
static optionsStruct Options;
|
||||||
|
|
||||||
static void InitPrimary();
|
static void InitPrimary();
|
||||||
|
|
|
@ -78,12 +78,18 @@ inline float RandFloat()
|
||||||
return static_cast<float>(std::rand() / static_cast<double>(RAND_MAX));
|
return static_cast<float>(std::rand() / static_cast<double>(RAND_MAX));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> constexpr
|
template <typename T>
|
||||||
int Sign(T val)
|
constexpr int Sign(T val)
|
||||||
{
|
{
|
||||||
return (T(0) < val) - (val < T(0));
|
return (T(0) < val) - (val < T(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const T& Clamp(const T& n, const T& lower, const T& upper)
|
||||||
|
{
|
||||||
|
return std::max(lower, std::min(n, upper));
|
||||||
|
}
|
||||||
|
|
||||||
// UTF-8 path adapter for fopen on Windows, implemented in SpaceCadetPinball.cpp
|
// UTF-8 path adapter for fopen on Windows, implemented in SpaceCadetPinball.cpp
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
extern FILE* fopenu(const char* path, const char* opt);
|
extern FILE* fopenu(const char* path, const char* opt);
|
||||||
|
|
|
@ -133,10 +133,10 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
||||||
// Second step: run updates depending on FullTiltMode
|
// Second step: run updates depending on FullTiltMode
|
||||||
options::InitSecondary();
|
options::InitSecondary();
|
||||||
|
|
||||||
if (!Sound::Init(Options.SoundChannels, Options.Sounds))
|
if (!Sound::Init(Options.SoundChannels, Options.Sounds, Options.SoundVolume))
|
||||||
Options.Sounds = false;
|
Options.Sounds = false;
|
||||||
|
|
||||||
if (!pinball::quickFlag && !midi::music_init())
|
if (!pinball::quickFlag && !midi::music_init(Options.MusicVolume))
|
||||||
Options.Music = false;
|
Options.Music = false;
|
||||||
|
|
||||||
if (pb::init())
|
if (pb::init())
|
||||||
|
@ -291,8 +291,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit duration to 2 * target time
|
// Limit duration to 2 * target time
|
||||||
sleepRemainder = std::max(std::min(DurationMs(frameEnd - updateEnd) - targetTimeDelta, TargetFrameTime),
|
sleepRemainder = Clamp(DurationMs(frameEnd - updateEnd) - targetTimeDelta, -TargetFrameTime, TargetFrameTime);
|
||||||
-TargetFrameTime);
|
|
||||||
frameDuration = std::min<DurationMs>(DurationMs(frameEnd - frameStart), 2 * TargetFrameTime);
|
frameDuration = std::min<DurationMs>(DurationMs(frameEnd - frameStart), 2 * TargetFrameTime);
|
||||||
frameStart = frameEnd;
|
frameStart = frameEnd;
|
||||||
UpdateToFrameCounter++;
|
UpdateToFrameCounter++;
|
||||||
|
@ -431,50 +430,46 @@ void winmain::RenderUi()
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
if (ImGui::MenuItem("Sound", "F5", Options.Sounds))
|
|
||||||
{
|
|
||||||
options::toggle(Menu1::Sounds);
|
|
||||||
}
|
|
||||||
if (ImGui::MenuItem("Music", "F6", Options.Music))
|
|
||||||
{
|
|
||||||
options::toggle(Menu1::Music);
|
|
||||||
}
|
|
||||||
ImGui::TextUnformatted("Sound Channels");
|
|
||||||
if (ImGui::SliderInt("##Sound Channels", &Options.SoundChannels, options::MinSoundChannels,
|
|
||||||
options::MaxSoundChannels, "%d", ImGuiSliderFlags_AlwaysClamp))
|
|
||||||
{
|
|
||||||
Options.SoundChannels = std::min(options::MaxSoundChannels,
|
|
||||||
std::max(options::MinSoundChannels, Options.SoundChannels));
|
|
||||||
Sound::SetChannels(Options.SoundChannels);
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
if (ImGui::MenuItem("Player Controls...", "F8"))
|
if (ImGui::MenuItem("Player Controls...", "F8"))
|
||||||
{
|
{
|
||||||
pause(false);
|
pause(false);
|
||||||
options::ShowControlDialog();
|
options::ShowControlDialog();
|
||||||
}
|
}
|
||||||
if (ImGui::BeginMenu("Table Resolution"))
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if (ImGui::BeginMenu("Audio"))
|
||||||
{
|
{
|
||||||
char buffer[20]{};
|
if (ImGui::MenuItem("Sound", "F5", Options.Sounds))
|
||||||
auto maxResText = pinball::get_rc_string(fullscrn::GetMaxResolution() + 2030, 0);
|
|
||||||
if (ImGui::MenuItem(maxResText, nullptr, Options.Resolution == -1))
|
|
||||||
{
|
{
|
||||||
options::toggle(Menu1::MaximumResolution);
|
options::toggle(Menu1::Sounds);
|
||||||
}
|
}
|
||||||
for (auto i = 0; i <= fullscrn::GetMaxResolution(); i++)
|
ImGui::TextUnformatted("Sound Volume");
|
||||||
|
if (ImGui::SliderInt("##Sound Volume", &Options.SoundVolume, options::MinVolume, options::MaxVolume, "%d",
|
||||||
|
ImGuiSliderFlags_AlwaysClamp))
|
||||||
{
|
{
|
||||||
auto& res = fullscrn::resolution_array[i];
|
Sound::SetVolume(Options.SoundVolume);
|
||||||
snprintf(buffer, sizeof buffer - 1, "%d x %d", res.ScreenWidth, res.ScreenHeight);
|
|
||||||
if (ImGui::MenuItem(buffer, nullptr, Options.Resolution == i))
|
|
||||||
{
|
|
||||||
options::toggle(static_cast<Menu1>(static_cast<int>(Menu1::R640x480) + i));
|
|
||||||
}
|
}
|
||||||
|
ImGui::TextUnformatted("Sound Channels");
|
||||||
|
if (ImGui::SliderInt("##Sound Channels", &Options.SoundChannels, options::MinSoundChannels,
|
||||||
|
options::MaxSoundChannels, "%d", ImGuiSliderFlags_AlwaysClamp))
|
||||||
|
{
|
||||||
|
Sound::SetChannels(Options.SoundChannels);
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("Music", "F6", Options.Music))
|
||||||
|
{
|
||||||
|
options::toggle(Menu1::Music);
|
||||||
|
}
|
||||||
|
ImGui::TextUnformatted("Music Volume");
|
||||||
|
if (ImGui::SliderInt("##Music Volume", &Options.MusicVolume, options::MinVolume, options::MaxVolume, "%d",
|
||||||
|
ImGuiSliderFlags_AlwaysClamp))
|
||||||
|
{
|
||||||
|
midi::SetVolume(Options.MusicVolume);
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Graphics"))
|
if (ImGui::BeginMenu("Graphics"))
|
||||||
{
|
{
|
||||||
if (ImGui::MenuItem("Uniform Scaling", nullptr, Options.UniformScaling))
|
if (ImGui::MenuItem("Uniform Scaling", nullptr, Options.UniformScaling))
|
||||||
|
@ -533,6 +528,26 @@ void winmain::RenderUi()
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginMenu("Table Resolution"))
|
||||||
|
{
|
||||||
|
char buffer[20]{};
|
||||||
|
auto maxResText = pinball::get_rc_string(fullscrn::GetMaxResolution() + 2030, 0);
|
||||||
|
if (ImGui::MenuItem(maxResText, nullptr, Options.Resolution == -1))
|
||||||
|
{
|
||||||
|
options::toggle(Menu1::MaximumResolution);
|
||||||
|
}
|
||||||
|
for (auto i = 0; i <= fullscrn::GetMaxResolution(); i++)
|
||||||
|
{
|
||||||
|
auto& res = fullscrn::resolution_array[i];
|
||||||
|
snprintf(buffer, sizeof buffer - 1, "%d x %d", res.ScreenWidth, res.ScreenHeight);
|
||||||
|
if (ImGui::MenuItem(buffer, nullptr, Options.Resolution == i))
|
||||||
|
{
|
||||||
|
options::toggle(static_cast<Menu1>(static_cast<int>(Menu1::R640x480) + i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Game Data"))
|
if (ImGui::BeginMenu("Game Data"))
|
||||||
{
|
{
|
||||||
if (ImGui::MenuItem("Prefer 3DPB Data", nullptr, Options.Prefer3DPBGameData))
|
if (ImGui::MenuItem("Prefer 3DPB Data", nullptr, Options.Prefer3DPBGameData))
|
||||||
|
|
Loading…
Reference in a new issue