Added table resolution and UI scale options.

gdrv: blit directly to backing store of vScreen texture.
Added missing cheat_bump_rank sub, oops.
Fixed some warnings.
This commit is contained in:
Muzychenko Andrey 2021-09-22 15:50:07 +03:00
parent c63c6701ac
commit 4c196a9290
21 changed files with 138 additions and 183 deletions

View File

@ -2,8 +2,6 @@
#include "Sound.h"
#include "pb.h"
int Sound::num_channels;
unsigned int Sound::enabled_flag = -1;
@ -14,6 +12,7 @@ int Sound::Init(int voices)
channelCount = 8;
num_channels = channelCount;
auto init = Mix_Init(MIX_INIT_MID);
return Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024);
}
@ -34,17 +33,23 @@ void Sound::Deactivate()
void Sound::Close()
{
Mix_CloseAudio();
Mix_Quit();
}
void Sound::PlaySound(Mix_Chunk* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops)
{
if (enabled_flag)
if (wavePtr && enabled_flag)
Mix_PlayChannel(-1, wavePtr, loops);
}
Mix_Chunk* Sound::LoadWaveFile(std::string lpName)
{
auto wavFile = fopen(lpName.c_str(), "r");
if (!wavFile)
return nullptr;
fclose(wavFile);
return Mix_LoadWAV(lpName.c_str());
}

View File

@ -12,8 +12,15 @@ int main(int argc, char* argv[])
std::string cmdLine;
for (int i = 0; i < argc; i++)
cmdLine += argv[i];
winmain::WinMain(cmdLine.c_str());
return 0;
// Todo: get rid of restart to change resolution.
int returnCode;
do
{
returnCode = winmain::WinMain(cmdLine.c_str());
}
while (winmain::RestartRequested());
return returnCode;
}
}

View File

@ -48,19 +48,6 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
zMap = ListZMap->Get(0);
if (ListBitmap)
{
/* Full tilt hack - spliced bitmap includes zMap
* Users access bitmap-zMap in pairs, pad zMap list with 0 for such users
* zdrv does not access zMap when drawing spliced bitmap*/
if (!ListZMap)
{
ListZMap = new objlist_class<zmap_header_type>(0, 4);
for (int index = 0; index < ListBitmap->GetCount(); index++)
{
assertm(ListBitmap->Get(index)->BitmapType == BitmapTypes::Spliced, "Wrong zMap padding");
ListZMap->Add(visual.ZMap);
}
}
rectangle_type bmp1Rect{}, tmpRect{};
auto rootBmp = ListBitmap->Get(0);
bmp1Rect.XPosition = rootBmp->XPosition - table->XOffset;

View File

@ -219,6 +219,7 @@ TPinballTable::~TPinballTable()
}
delete BallList;
delete ComponentList;
control::ClearLinks();
}
TPinballComponent* TPinballTable::find_component(LPCSTR componentName)

View File

@ -592,6 +592,14 @@ void control::make_links(TPinballTable* table)
make_component_link(simple_components[i]);
}
void control::ClearLinks()
{
TableG = nullptr;
for (auto& component : score_components)
component.Tag->SetComponent(nullptr);
for (auto& component : simple_components)
component->SetComponent(nullptr);
}
TPinballComponent* control::make_component_link(component_tag_base* tag)
{
@ -904,9 +912,19 @@ void control::table_set_replay(float value)
control_info_text_box_tag.Component->Display(pinball::get_rc_string(0, 0), value);
}
int control::cheat_bump_rank()
void control::cheat_bump_rank()
{
return 0;
char Buffer[64]{};
auto rank = control_middle_circle_tag.Component->Message(37, 0.0);
if (rank < 9)
{
control_middle_circle_tag.Component->Message(41, 2.0f);
auto rankText = pinball::get_rc_string(RankRcArray[rank], 1);
snprintf(Buffer,sizeof Buffer, pinball::get_rc_string(83, 0), rankText);
control_mission_text_box_tag.Component->Display(Buffer, 8.0);
control_soundwave10_tag.Component->Play();
}
}
bool control::light_on(component_tag<TLight>* tag)

View File

@ -70,6 +70,7 @@ public:
static component_tag_base *wormhole_tag_array1[3], *wormhole_tag_array2[3], *wormhole_tag_array3[3];
static void make_links(TPinballTable* table);
static void ClearLinks();
static TPinballComponent* make_component_link(component_tag_base* tag);
static void handler(int code, TPinballComponent* cmp);
static void pbctrl_bdoor_controller(int key);
@ -81,7 +82,7 @@ public:
static void table_set_multiball();
static void table_bump_ball_sink_lock();
static void table_set_replay(float value);
static int cheat_bump_rank();
static void cheat_bump_rank();
static bool light_on(component_tag<TLight>* tag);
static int SpecialAddScore(int score);
static int AddRankProgress(int rank);

View File

@ -12,7 +12,6 @@ int fullscrn::screen_mode;
int fullscrn::display_changed;
int fullscrn::resolution = 0;
int fullscrn::maxResolution = 0;
const resolution_info fullscrn::resolution_array[3] =
{
{640, 480, 600, 416, 501},
@ -103,43 +102,7 @@ void fullscrn::SetResolution(int value)
int fullscrn::GetMaxResolution()
{
return maxResolution;
}
void fullscrn::SetMaxResolution(int value)
{
assertm(value >= 0 && value <= 2, "Resolution value out of bounds");
maxResolution = value;
}
int fullscrn::get_max_supported_resolution()
{
if (!pb::FullTiltMode)
return 0;
int width = 0, height = 0;
get_screen_resolution(&width, &height);
auto result = 0;
for (auto index = 1; index < 3; ++index)
{
auto resPtr = &resolution_array[index];
if (resPtr->ScreenWidth <= width && resPtr->ScreenHeight <= height)
result = index;
}
return result;
}
int fullscrn::get_screen_resolution(int* width, int* height)
{
SDL_DisplayMode dm;
if (SDL_GetDesktopDisplayMode(0, &dm) == 0)
{
*width = dm.w;
*height = dm.h;
return 0;
}
return 1;
return pb::FullTiltMode ? 2 : 0;
}
void fullscrn::window_size_changed()

View File

@ -27,13 +27,9 @@ public:
static int GetResolution();
static void SetResolution(int value);
static int GetMaxResolution();
static void SetMaxResolution(int value);
static int get_max_supported_resolution();
static int get_screen_resolution(int* width, int* height);
static void window_size_changed();
private :
static int resolution;
static int maxResolution;
static int enableFullscreen();
static int disableFullscreen();

View File

@ -24,17 +24,25 @@ int gdrv::init(int width, int height)
SDL_TEXTUREACCESS_STREAMING,
width, height
);
vScreenPixels = memory::allocate<ColorRgba>(width * height);
vScreenWidth = width;
vScreenHeight = height;
int pitch = 0;
SDL_LockTexture
(
vScreenTex,
nullptr,
reinterpret_cast<void**>(&vScreenPixels),
&pitch
);
assertm(pitch = width* sizeof(ColorRgba), "gdrv: wrong pitch of SDL texture");
return 0;
}
int gdrv::uninit()
{
SDL_DestroyTexture(vScreenTex);
memory::free(vScreenPixels);
return 0;
}
@ -191,14 +199,6 @@ int gdrv::destroy_bitmap(gdrv_bitmap8* bmp)
return 0;
}
void gdrv::start_blit_sequence()
{
}
void gdrv::end_blit_sequence()
{
}
void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrc, int xDest, int yDest, int width, int height)
{
StretchDIBitsScaled(
@ -321,18 +321,16 @@ int gdrv::StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
void gdrv::BlitScreen()
{
unsigned char* lockedPixels = nullptr;
int pitch = 0;
SDL_UnlockTexture(vScreenTex);
SDL_RenderCopy(winmain::Renderer, vScreenTex, nullptr, &DestinationRect);
SDL_LockTexture
(
vScreenTex,
nullptr,
reinterpret_cast<void**>(&lockedPixels),
reinterpret_cast<void**>(&vScreenPixels),
&pitch
);
std::memcpy(lockedPixels, vScreenPixels, vScreenWidth * vScreenHeight * 4);
SDL_UnlockTexture(vScreenTex);
SDL_RenderCopyEx(winmain::Renderer, vScreenTex, nullptr, &DestinationRect, 0, nullptr, SDL_FLIP_NONE);
}
void gdrv::ApplyPalette(gdrv_bitmap8& bmp)

View File

@ -66,8 +66,6 @@ public:
static int create_bitmap(gdrv_bitmap8& bmp, const struct dat8BitBmpHeader& header);
static int destroy_bitmap(gdrv_bitmap8* bmp);
static int display_palette(ColorRgba* plt);
static void start_blit_sequence();
static void end_blit_sequence();
static void blit(gdrv_bitmap8* bmp, int xSrc, int ySrc, int xDest, int yDest, int width, int height);
static void blat(gdrv_bitmap8* bmp, int xDest, int yDest);
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar);

View File

@ -135,7 +135,7 @@ void high_score::show_and_set_high_score_dialog(high_score_struct* table, int sc
dlg_score = score;
dlg_hst = table;
dlg_enter_name = 1;
strncpy(default_name, defaultName, sizeof default_name);
strncpy(default_name, defaultName, sizeof default_name - 1);
ShowDialog = true;
}

View File

@ -105,12 +105,13 @@ void loader::loadfrom(DatFile* datFile)
void loader::unload()
{
int index;
for (index = 1; index < sound_count; ++index)
for (int index = 1; index < sound_count; ++index)
{
Sound::FreeSound(sound_list[index].WavePtr);
sound_list[index].Loaded = 0;
sound_list[index].WavePtr = nullptr;
}
if (sound_list[index].PtrToSmth)
memory::free(sound_list[index].PtrToSmth);
sound_count = 1;
}

View File

@ -18,7 +18,6 @@ struct soundListStruct
int GroupIndex;
int Loaded;
float Duration;
char* PtrToSmth;
};
struct visualKickerStruct

View File

@ -99,9 +99,15 @@ void options::init()
Options.RightTableBumpKey = get_int("Right Table Bump key", Options.RightTableBumpKey);
Options.BottomTableBumpKey = get_int("Bottom Table Bump key", Options.BottomTableBumpKey);
Options.UniformScaling = get_int("Uniform scaling", Options.UniformScaling);
ImGui::GetIO().FontGlobalScale = get_float("UI Scale", 1.0f);
Options.Resolution = get_int("Screen Resolution", -1);
Sound::Enable(0, 7, Options.Sounds);
update_resolution_menu();
auto maxRes = fullscrn::GetMaxResolution();
if (Options.Resolution >= 0 && Options.Resolution > maxRes)
Options.Resolution = maxRes;
fullscrn::SetResolution(Options.Resolution == -1 ? maxRes : Options.Resolution);
}
void options::uninit()
@ -118,6 +124,7 @@ void options::uninit()
set_int("Bottom Table Bump key", Options.BottomTableBumpKey);
set_int("Screen Resolution", Options.Resolution);
set_int("Uniform scaling", Options.UniformScaling);
set_float("UI Scale", ImGui::GetIO().FontGlobalScale);
}
@ -142,6 +149,17 @@ void options::set_string(LPCSTR lpValueName, LPCSTR value)
SetSetting(lpValueName, value);
}
float options::get_float(LPCSTR lpValueName, float defaultValue)
{
auto value = GetSetting(lpValueName, std::to_string(defaultValue));
return std::stof(value);
}
void options::set_float(LPCSTR lpValueName, float data)
{
SetSetting(lpValueName, std::to_string(data));
}
void options::toggle(uint32_t uIDCheckItem)
{
@ -177,21 +195,23 @@ void options::toggle(uint32_t uIDCheckItem)
case Menu1_800x600:
case Menu1_1024x768:
{
/*for (unsigned i = Menu1_MaximumResolution; i <= Menu1_1024x768; ++i)
menu_check(i, i == uIDCheckItem);*/
auto restart = false;
int newResolution = uIDCheckItem - Menu1_640x480;
if (uIDCheckItem == Menu1_MaximumResolution)
{
restart = fullscrn::GetResolution() != fullscrn::GetMaxResolution();
Options.Resolution = -1;
if (fullscrn::GetMaxResolution() != fullscrn::GetResolution())
winmain::Restart();
}
else if (newResolution != fullscrn::GetResolution() && newResolution <= fullscrn::GetMaxResolution())
else if (newResolution <= fullscrn::GetMaxResolution())
{
restart = newResolution != (Options.Resolution == -1
? fullscrn::GetMaxResolution()
: fullscrn::GetResolution());
Options.Resolution = newResolution;
winmain::Restart();
}
if (restart)
winmain::Restart();
break;
}
case Menu1_WindowUniformScale:
@ -204,43 +224,6 @@ void options::toggle(uint32_t uIDCheckItem)
}
}
void options::update_resolution_menu()
{
auto maxResolution = fullscrn::get_max_supported_resolution();
fullscrn::SetMaxResolution(maxResolution);
const char* maxResText = pinball::get_rc_string(maxResolution + 2030, 0);
/*if (MenuHandle)
ModifyMenuA(MenuHandle, Menu1_MaximumResolution, 0, Menu1_MaximumResolution, maxResText);
for (auto resIndex = 0; resIndex < 3; resIndex++)
{
menu_set(fullscrn::resolution_array[resIndex].ResolutionMenuId, fullscrn::GetMaxResolution() >= resIndex);
}
for (auto i = Menu1_MaximumResolution; i <= Menu1_1024x768; ++i)
{
menu_check(i, 0);
}
if (Options.Resolution >= 0)
menu_check(fullscrn::resolution_array[fullscrn::GetResolution()].ResolutionMenuId, 1);
else
menu_check(Menu1_MaximumResolution, 1);*/
}
void options::init_resolution()
{
Options.Resolution = get_int("Screen Resolution", -1);
int maxRes = fullscrn::get_max_supported_resolution();
if (Options.Resolution == -1 || maxRes <= Options.Resolution)
{
fullscrn::SetMaxResolution(maxRes);
fullscrn::SetResolution(maxRes);
}
else
{
fullscrn::SetResolution(Options.Resolution);
}
}
void options::keyboard()
{
//DialogBoxParamA(nullptr, "KEYMAPPER", nullptr, KeyMapDlgProc, 0);

View File

@ -35,9 +35,9 @@ public:
static void set_int(LPCSTR lpValueName, int data);
static std::string get_string(LPCSTR lpValueName, LPCSTR defaultValue);
static void set_string(LPCSTR lpValueName, LPCSTR value);
static float get_float(LPCSTR lpValueName, float defaultValue);
static void set_float(LPCSTR lpValueName, float data);
static void toggle(uint32_t uIDCheckItem);
static void update_resolution_menu();
static void init_resolution();
static void keyboard();
private:

View File

@ -480,7 +480,7 @@ void pb::keydown(int key)
break;
case 'h':
char String1[200];
strncpy(String1, pinball::get_rc_string(26, 0), sizeof String1);
strncpy(String1, pinball::get_rc_string(26, 0), sizeof String1 - 1);
high_score::show_and_set_high_score_dialog(highscore_table, 1000000000, 1, String1);
break;
case 'm':
@ -491,6 +491,9 @@ void pb::keydown(int key)
case 'r':
control::cheat_bump_rank();
break;
case 's':
MainTable->AddScore(static_cast<int>(RandFloat() * 1000000.0f));
break;
case SDLK_F11:
gdrv::get_focus();
break;
@ -570,7 +573,7 @@ void pb::end_game()
int position = high_score::get_score_position(highscore_table, scores[i]);
if (position >= 0)
{
strncpy(String1, pinball::get_rc_string(scoreIndex[i] + 26, 0), sizeof String1);
strncpy(String1, pinball::get_rc_string(scoreIndex[i] + 26, 0), sizeof String1 - 1);
high_score::show_and_set_high_score_dialog(highscore_table, scores[i], position, String1);
}
}

View File

@ -201,9 +201,9 @@ std::map<uint32_t, LPCSTR> rc_strings
{187, "High Score 4\n%ld"},
{188, "High Score 5\n%ld"},
{189, "255 255 255 (R G B default font color)"},
{2030, "Use &Maximum Resolution (640 x 480)"},
{2031, "Use &Maximum Resolution (800 x 600)"},
{2032, "Use &Maximum Resolution (1024 x 768)"}
{2030, "Use Maximum Resolution (640 x 480)"},
{2031, "Use Maximum Resolution (800 x 600)"},
{2032, "Use Maximum Resolution (1024 x 768)"}
};
int LoadStringAlt(uint32_t uID, LPSTR lpBuffer, int cchBufferMax)

View File

@ -33,12 +33,9 @@ void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int h
vscreen_rect.Height = height;
vscreen.YPosition = 0;
vscreen.XPosition = 0;
gdrv_bitmap8* ballBmp = ball_bitmap;
while (ballBmp < &ball_bitmap[20])
{
gdrv::create_bitmap(ballBmp, 64, 64, 64, false);
++ballBmp;
}
for (auto& ballBmp : ball_bitmap)
gdrv::create_bitmap(&ballBmp, 64, 64, 64, false);
background_bitmap = bmp;
if (bmp)
gdrv::copy_bitmap(&vscreen, width, height, 0, 0, bmp, 0, 0);
@ -55,6 +52,8 @@ void render::uninit()
remove_sprite(sprite_list[i]);
for (auto j = many_balls - 1; j >= 0; --j)
remove_ball(ball_list[j]);
for (auto& ballBmp : ball_bitmap)
gdrv::destroy_bitmap(&ballBmp);
memory::free(ball_list);
memory::free(dirty_list);
memory::free(sprite_list);
@ -130,8 +129,6 @@ void render::update()
paint_balls();
if (blit)
{
gdrv::start_blit_sequence();
auto xPos = vscreen.XPosition + offset_x;
auto yPos = vscreen.YPosition + offset_y;
dirtyPtr = dirty_list;
@ -199,8 +196,6 @@ void render::update()
rectCopy->Height);
}
}
gdrv::end_blit_sequence();
}
many_dirty = 0;

View File

@ -269,29 +269,25 @@ void score::update(scoreStruct* score)
void score::string_format(int score, char* str)
{
char separator[12];
if (score == -999)
{
*str = 0;
}
else
{
strncpy(separator, ",", sizeof separator);
int scoreMillions = score % 1000000000 / 1000000;
if (score / 1000000000 <= 0)
{
if (static_cast<int>(scoreMillions) <= 0)
if (scoreMillions <= 0)
{
if (score % 1000000 / 1000 <= 0)
snprintf(str, 36, "%d", score);
else
snprintf(str, 36, "%d%s%03d", score % 1000000 / 1000, separator, score % 1000);
snprintf(str, 36, "%d,%03d", score % 1000000 / 1000, score % 1000);
}
else
{
snprintf(str, 36, "%d%s%03d%s%03d", scoreMillions, separator, score % 1000000 / 1000, separator,
score % 1000);
snprintf(str, 36, "%d,%03d,%03d", scoreMillions, score % 1000000 / 1000, score % 1000);
}
}
else
@ -299,13 +295,10 @@ void score::string_format(int score, char* str)
snprintf(
str,
36,
"%d%s%03d%s%03d%s%03d",
"%d,%03d,%03d,%03d",
score / 1000000000,
separator,
scoreMillions,
separator,
score % 1000000 / 1000,
separator,
score % 1000);
}
}

View File

@ -54,6 +54,9 @@ uint32_t timeGetTimeAlt()
int winmain::WinMain(LPCSTR lpCmdLine)
{
restart = false;
bQuit = false;
memory::init(memalloc_failure);
// SDL init
@ -78,8 +81,6 @@ int winmain::WinMain(LPCSTR lpCmdLine)
pb::FullTiltMode = true;
}
options::init_resolution();
// SDL window
SDL_Window* window = SDL_CreateWindow
(
@ -107,6 +108,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not create renderer", SDL_GetError(), window);
return 1;
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
// ImGui init
IMGUI_CHECKVERSION();
@ -288,6 +290,13 @@ int winmain::WinMain(LPCSTR lpCmdLine)
SDL_RenderPresent(renderer);
frameCounter++;
}
auto sdlError = SDL_GetError();
if (sdlError[0])
{
SDL_ClearError();
printf("SDL Error: %s\n", sdlError);
}
}
}
@ -304,24 +313,6 @@ int winmain::WinMain(LPCSTR lpCmdLine)
ImGui::DestroyContext();
SDL_Quit();
if (restart)
{
// Todo: get rid of restart to change resolution.
/*char restartPath[300]{};
if (GetModuleFileNameA(nullptr, restartPath, 300))
{
STARTUPINFO si{};
PROCESS_INFORMATION pi{};
si.cb = sizeof si;
if (CreateProcess(restartPath, nullptr, nullptr, nullptr,
FALSE, 0, nullptr, nullptr, &si, &pi))
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}*/
}
return return_value;
}
@ -421,8 +412,20 @@ void winmain::RenderUi()
}
if (ImGui::BeginMenu("Table Resolution"))
{
if (ImGui::MenuItem("Not implemented"))
char buffer[20]{};
auto maxResText = pinball::get_rc_string(fullscrn::GetMaxResolution() + 2030, 0);
if (ImGui::MenuItem(maxResText, nullptr, options::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::Options.Resolution == i))
{
options::toggle(Menu1_640x480 + i);
}
}
ImGui::EndMenu();
}
@ -432,6 +435,9 @@ void winmain::RenderUi()
{
options::toggle(Menu1_WindowUniformScale);
}
ImGui::DragFloat("", &ImIO->FontGlobalScale, 0.005f, 0.8f, 5,
"UI Scale %.2f", ImGuiSliderFlags_AlwaysClamp);
ImGui::EndMenu();
}
ImGui::EndMenu();

View File

@ -24,6 +24,7 @@ public:
static void pause();
static void help_introduction();
static void Restart();
static bool RestartRequested() { return restart; }
private:
static int return_value, bQuit, DispFrameRate, DispGRhistory, activated;
static int has_focus, mouse_down, last_mouse_x, last_mouse_y, no_time_loss;