From 1c5256a4c6b8d409387419bccab49a902e1594bc Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Sat, 6 Feb 2021 16:53:47 +0300 Subject: [PATCH] Added table resolution support. Only works with FT .dat file. FT music does not work - different format. --- SpaceCadetPinball/Sound.cpp | 6 +- SpaceCadetPinball/SpaceCadetPinball.rc | 20 ++++++- SpaceCadetPinball/TBall.cpp | 12 ++-- SpaceCadetPinball/TFlipper.cpp | 16 +++--- SpaceCadetPinball/THole.cpp | 3 +- SpaceCadetPinball/TTableLayer.cpp | 8 ++- SpaceCadetPinball/TTextBox.cpp | 7 ++- SpaceCadetPinball/fullscrn.cpp | 65 ++++++++++++++++++++- SpaceCadetPinball/fullscrn.h | 19 +++++++ SpaceCadetPinball/gdrv.cpp | 2 +- SpaceCadetPinball/loader.cpp | 10 +++- SpaceCadetPinball/options.cpp | 78 ++++++++++++++++++++++++-- SpaceCadetPinball/options.h | 3 + SpaceCadetPinball/pb.cpp | 25 +++++---- SpaceCadetPinball/pb.h | 3 +- SpaceCadetPinball/resource.h | 6 +- SpaceCadetPinball/score.cpp | 74 +++++++++++++++++++----- SpaceCadetPinball/score.h | 3 + SpaceCadetPinball/winmain.cpp | 55 ++++++++++++++++-- SpaceCadetPinball/winmain.h | 2 + 20 files changed, 353 insertions(+), 64 deletions(-) diff --git a/SpaceCadetPinball/Sound.cpp b/SpaceCadetPinball/Sound.cpp index f53756a..6febff9 100644 --- a/SpaceCadetPinball/Sound.cpp +++ b/SpaceCadetPinball/Sound.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "Sound.h" + +#include "pb.h" #include "pinball.h" #include "WaveMix.h" #include "winmain.h" @@ -45,7 +47,9 @@ int Sound::Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWA } else { - MessageBoxA(winmain::hwnd_frame, pinball::get_rc_string(42, 0), pinball::WindowName, 0x2000u); + /*FT does not have the file, defaults work OK*/ + if (!pb::FullTiltMode) + MessageBoxA(winmain::hwnd_frame, pinball::get_rc_string(42, 0), pinball::WindowName, 0x2000u); } WndClass.style = 0; diff --git a/SpaceCadetPinball/SpaceCadetPinball.rc b/SpaceCadetPinball/SpaceCadetPinball.rc index 30ab4b3..18b9fc2 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.rc +++ b/SpaceCadetPinball/SpaceCadetPinball.rc @@ -88,6 +88,13 @@ BEGIN MENUITEM "&Music", Menu1_Music MENUITEM SEPARATOR MENUITEM "P&layer Controls...\tF8", Menu1_Player_Controls + POPUP "Table &Resolution" + BEGIN + MENUITEM "Use &Maximum Resolution", Menu1_MaximumResolution + MENUITEM "&640 x 480", Menu1_640x480 + MENUITEM "&800 x 600", Menu1_800x600 + MENUITEM "&1024 x 768", Menu1_1024x768 + END END POPUP "&Help" BEGIN @@ -342,7 +349,7 @@ END // Bitmap // -splash_bitmap BITMAP "splash_bitmap.bmp" +SPLASH_BITMAP BITMAP "splash_bitmap.bmp" ///////////////////////////////////////////////////////////////////////////// @@ -587,6 +594,17 @@ BEGIN IDS_STRING289 "255 255 255 (R G B default font color)" END +STRINGTABLE +BEGIN + 2030 "Use &Maximum Resolution (640 x 480)" + 2031 "Use &Maximum Resolution (800 x 600)" +END + +STRINGTABLE +BEGIN + 2032 "Use &Maximum Resolution (1024 x 768)" +END + #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/SpaceCadetPinball/TBall.cpp b/SpaceCadetPinball/TBall.cpp index edc7c04..893b254 100644 --- a/SpaceCadetPinball/TBall.cpp +++ b/SpaceCadetPinball/TBall.cpp @@ -2,9 +2,11 @@ #include "TBall.h" +#include "fullscrn.h" #include "loader.h" #include "maths.h" #include "objlist_class.h" +#include "pb.h" #include "proj.h" #include "render.h" #include "TPinballTable.h" @@ -12,6 +14,7 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false) { visualStruct visual{}; + char ballGroupName[10]{"ball"}; TimeNow = 0.0; RayMaxDistance = 0.0; @@ -30,11 +33,12 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false) Position.Y = 0.0; ListBitmap = new objlist_class(0, 4); - auto groupIndex = loader::query_handle("ball"); - /*Full tilt hack - ball is ball0*/ - if (groupIndex < 0) - groupIndex = loader::query_handle("ball0"); + /*Full tilt: ball is ballN, where N[0,2] resolution*/ + if (pb::FullTiltMode) + ballGroupName[4] = '0' + fullscrn::GetResolution(); + auto groupIndex = loader::query_handle(ballGroupName); + Offset = *loader::query_float_attribute(groupIndex, 0, 500); auto visualCount = loader::query_visual_states(groupIndex); auto index = 0; diff --git a/SpaceCadetPinball/TFlipper.cpp b/SpaceCadetPinball/TFlipper.cpp index 97856e3..7dc5d0b 100644 --- a/SpaceCadetPinball/TFlipper.cpp +++ b/SpaceCadetPinball/TFlipper.cpp @@ -21,18 +21,16 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t Timer = 0; Smoothness = visual.Smoothness; - auto floatArr = loader::query_float_attribute(groupIndex, 0, 803); - auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 805); - auto floatArr3 = loader::query_float_attribute(groupIndex, 0, 804); - auto collMult = *floatArr; - auto bmpCoef2 = *floatArr2; - auto bmpCoef1 = *floatArr3; - + auto collMult = *loader::query_float_attribute(groupIndex, 0, 803); + auto bmpCoef2 = *loader::query_float_attribute(groupIndex, 0, 805); + auto bmpCoef1 = *loader::query_float_attribute(groupIndex, 0, 804); + /*Full tilt hack: different flipper speed*/ - if (bmpCoef2 > 1) + if (pb::FullTiltMode) + { bmpCoef2 = 0.08f; - if (bmpCoef1 > 1) bmpCoef1 = 0.04f; + } auto vecT2 = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 802)); auto vecT1 = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 801)); auto origin = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 800)); diff --git a/SpaceCadetPinball/THole.cpp b/SpaceCadetPinball/THole.cpp index 40c6a49..7f75bef 100644 --- a/SpaceCadetPinball/THole.cpp +++ b/SpaceCadetPinball/THole.cpp @@ -5,6 +5,7 @@ #include "control.h" #include "loader.h" #include "objlist_class.h" +#include "pb.h" #include "TBall.h" #include "timer.h" #include "TPinballTable.h" @@ -43,7 +44,7 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table, FieldFlag = static_cast(floor(*loader::query_float_attribute(groupIndex, 0, 1304))); /*Full tilt hack - FieldFlag should be on*/ - if (!FieldFlag) + if (pb::FullTiltMode) FieldFlag = 1; Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2]; diff --git a/SpaceCadetPinball/TTableLayer.cpp b/SpaceCadetPinball/TTableLayer.cpp index 70ec6fb..883a913 100644 --- a/SpaceCadetPinball/TTableLayer.cpp +++ b/SpaceCadetPinball/TTableLayer.cpp @@ -1,8 +1,11 @@ #include "pch.h" #include "TTableLayer.h" + +#include "fullscrn.h" #include "loader.h" #include "objlist_class.h" +#include "pb.h" #include "proj.h" #include "render.h" #include "TBall.h" @@ -19,7 +22,8 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f auto groupIndex = loader::query_handle("table"); loader::query_visual(groupIndex, 0, &visual); - auto projCenter = loader::query_float_attribute(groupIndex, 0, 700); + /*Full tilt: proj center first value is offset by resolution*/ + auto projCenter = loader::query_float_attribute(groupIndex, 0, 700 + fullscrn::GetResolution()); proj::recenter(projCenter[0], projCenter[1]); render::set_background_zmap(visual.ZMap, 0, 0); @@ -54,7 +58,7 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f auto angleMultArr = loader::query_float_attribute(groupIndex, 0, 701); /*Full tilt hack - GraityMult should be 0.2*/ - if (angleMultArr && *angleMultArr < 1) + if (angleMultArr && !pb::FullTiltMode) GraityMult = *angleMultArr; else GraityMult = 0.2f; diff --git a/SpaceCadetPinball/TTextBox.cpp b/SpaceCadetPinball/TTextBox.cpp index c687c16..fe4abe9 100644 --- a/SpaceCadetPinball/TTextBox.cpp +++ b/SpaceCadetPinball/TTextBox.cpp @@ -2,7 +2,9 @@ #include "TTextBox.h" #include "control.h" +#include "fullscrn.h" #include "loader.h" +#include "pb.h" #include "render.h" #include "score.h" #include "timer.h" @@ -22,8 +24,9 @@ TTextBox::TTextBox(TPinballTable* table, int groupIndex) : TPinballComponent(tab if (groupIndex > 0) { - int arrLength; - auto dimensions = loader::query_iattribute(groupIndex, 1500, &arrLength); + /*Full tilt: text box dimensions index is offset by resolution*/ + int arrLength; + auto dimensions = loader::query_iattribute(groupIndex + fullscrn::GetResolution(), 1500, &arrLength); OffsetX = dimensions[0]; OffsetY = dimensions[1]; Width = dimensions[2]; diff --git a/SpaceCadetPinball/fullscrn.cpp b/SpaceCadetPinball/fullscrn.cpp index d090d1e..367f7e7 100644 --- a/SpaceCadetPinball/fullscrn.cpp +++ b/SpaceCadetPinball/fullscrn.cpp @@ -1,5 +1,7 @@ #include "pch.h" #include "fullscrn.h" + +#include "pb.h" #include "render.h" #include "winmain.h" @@ -14,6 +16,14 @@ int fullscrn::ChangeDisplay, fullscrn::SmthFullScrnFlag2; int fullscrn::trick = 1; int fullscrn::MenuEnabled; HMENU fullscrn::MenuHandle; +int fullscrn::resolution = 0; +int fullscrn::maxResolution = 0; +const resolution_info fullscrn::resolution_array[3] = +{ + {640, 480, 600, 416, 501}, + {800, 600, 752, 520, 502}, + {1024, 768, 960, 666, 503}, +}; void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay) { @@ -102,9 +112,9 @@ int fullscrn::enableFullscreen() { DevMode.dmSize = 156; DevMode.dmFields = 1835008; - DevMode.dmPelsWidth = 640; - DevMode.dmPelsHeight = 480; - DevMode.dmBitsPerPel = 8; + DevMode.dmPelsWidth = resolution_array[resolution].ScreenWidth; + DevMode.dmPelsHeight = resolution_array[resolution].ScreenHeight; + DevMode.dmBitsPerPel = 32; disableWindowFlagsDisDlg(); if (trick) { @@ -360,3 +370,52 @@ void fullscrn::paint() render::paint(); fullscrn_flag1 = 0; } + +int fullscrn::GetResolution() +{ + return resolution; +} + +void fullscrn::SetResolution(int resolution) +{ + if (!pb::FullTiltMode) + resolution = 0; + assertm(resolution >= 0 && resolution <= 2, "Resolution value out of bounds"); + fullscrn::resolution = resolution; +} + +int fullscrn::GetMaxResolution() +{ + return maxResolution; +} + +void fullscrn::SetMaxResolution(int resolution) +{ + assertm(resolution >= 0 && resolution <= 2, "Resolution value out of bounds"); + maxResolution = resolution; +} + +int fullscrn::get_max_supported_resolution() +{ + if (!pb::FullTiltMode) + return 0; + + auto resolutionWH = get_screen_resolution(); + auto width = LOWORD(resolutionWH); + auto height = HIWORD(resolutionWH); + 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() +{ + auto height = static_cast(GetSystemMetrics(SM_CYSCREEN)); + return static_cast(GetSystemMetrics(SM_CXSCREEN)) | (height << 16); +} diff --git a/SpaceCadetPinball/fullscrn.h b/SpaceCadetPinball/fullscrn.h index 8ed0a87..4be2643 100644 --- a/SpaceCadetPinball/fullscrn.h +++ b/SpaceCadetPinball/fullscrn.h @@ -5,6 +5,16 @@ #define BYTE1(x) BYTEn(x, 1) // byte 1 (counting from 0) #define BYTE2(x) BYTEn(x, 2) + +struct resolution_info +{ + __int16 ScreenWidth; + __int16 ScreenHeight; + __int16 TableWidth; + __int16 TableHeight; + __int16 ResolutionMenuId; +}; + class fullscrn { public: @@ -17,6 +27,7 @@ public: static int display_changed; static int ChangeDisplay, SmthFullScrnFlag2; static int trick; + static const resolution_info resolution_array[3]; static void init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay); static void shutdown(); @@ -29,9 +40,17 @@ public: static void getminmaxinfo(MINMAXINFO* maxMin); static void paint(); static bool set_menu_mode(int menuEnabled); + static int GetResolution(); + static void SetResolution(int resolution); + static int GetMaxResolution(); + static void SetMaxResolution(int resolution); + static int get_max_supported_resolution(); + static int get_screen_resolution(); private : static int MenuEnabled; static HMENU MenuHandle; + static int resolution; + static int maxResolution; static void GetWindowCenter(); static int disableWindowFlagsDisDlg(); diff --git a/SpaceCadetPinball/gdrv.cpp b/SpaceCadetPinball/gdrv.cpp index c4f9196..8820e64 100644 --- a/SpaceCadetPinball/gdrv.cpp +++ b/SpaceCadetPinball/gdrv.cpp @@ -239,7 +239,7 @@ int gdrv::destroy_bitmap(gdrv_bitmap8* bmp) { if (!bmp) return -1; - if (bmp->BitmapType == BitmapType::RawBitmap) + if (bmp->BitmapType == BitmapType::RawBitmap || bmp->BitmapType == BitmapType::Spliced) { memory::free(bmp->BmpBufPtr1); } diff --git a/SpaceCadetPinball/loader.cpp b/SpaceCadetPinball/loader.cpp index 5e8dcac..ba5dfc8 100644 --- a/SpaceCadetPinball/loader.cpp +++ b/SpaceCadetPinball/loader.cpp @@ -2,6 +2,7 @@ #include "loader.h" #include "memory.h" #include "partman.h" +#include "pb.h" #include "pinball.h" #include "Sound.h" #include "zdrv.h" @@ -142,12 +143,17 @@ int loader::get_sound_id(int groupIndex) datFieldTypes::ShortValue)); if (value && *value == 202) { + /*FT sounds are in SOUND subfolder*/ + char filePath[300]{}, fileName2[100]{}; auto fileName = partman::field(loader_table, soundGroupId, datFieldTypes::String); - HFILE hFile = _lopen(fileName, 0); + sprintf_s(fileName2, pb::FullTiltMode ? "SOUND\\%s" : "%s", fileName); + pinball::make_path_name(filePath, fileName2); + + HFILE hFile = _lopen(filePath, 0); sound_list[soundIndex].Duration = static_cast(static_cast(_llseek(hFile, 0, SEEK_END)) * 0.0000909090909090909); _lclose(hFile); - sound_list[soundIndex].WavePtr = Sound::LoadWaveFile(fileName); + sound_list[soundIndex].WavePtr = Sound::LoadWaveFile(filePath); } } } diff --git a/SpaceCadetPinball/options.cpp b/SpaceCadetPinball/options.cpp index ccb1798..df508b1 100644 --- a/SpaceCadetPinball/options.cpp +++ b/SpaceCadetPinball/options.cpp @@ -4,6 +4,7 @@ #include "fullscrn.h" #include "memory.h" #include "midi.h" +#include "pb.h" #include "resource.h" #include "Sound.h" #include "winmain.h" @@ -128,6 +129,8 @@ void options::init(HMENU menuHandle) } memory::free(tmpBuf); } + + update_resolution_menu(); } void options::uninit() @@ -142,6 +145,7 @@ void options::uninit() set_int(nullptr, "Left Table Bump key", Options.LeftTableBumpKey); set_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey); set_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey); + set_int(nullptr, "Screen Resolution", Options.Resolution); } void options::path_init(LPCSTR regPath) @@ -187,7 +191,7 @@ void options::path_free() int options::get_int(LPCSTR optPath, LPCSTR lpValueName, int defaultValue) { - DWORD dwDisposition; + DWORD dwDisposition; HKEY result = (HKEY)defaultValue, Data = (HKEY)defaultValue; if (!OptionsRegPath) @@ -296,14 +300,78 @@ void options::toggle(UINT uIDCheckItem) fullscrn::set_screen_mode(newValue); menu_check(uIDCheckItem, newValue); return; - } - if (uIDCheckItem > 407 && uIDCheckItem <= 411) - { - Options.Players = uIDCheckItem - 407; + case Menu1_1Player: + case Menu1_2Players: + case Menu1_3Players: + case Menu1_4Players: + Options.Players = uIDCheckItem - Menu1_1Player + 1; menu_check(Menu1_1Player, Options.Players == 1); menu_check(Menu1_2Players, Options.Players == 2); menu_check(Menu1_3Players, Options.Players == 3); menu_check(Menu1_4Players, Options.Players == 4); + break; + case Menu1_MaximumResolution: + case Menu1_640x480: + case Menu1_800x600: + case Menu1_1024x768: + { + menu_check(500u, uIDCheckItem == 500); + menu_check(501u, uIDCheckItem == 501); + menu_check(502u, uIDCheckItem == 502); + menu_check(503u, uIDCheckItem == 503); + int newResolution = uIDCheckItem - Menu1_640x480; + if (uIDCheckItem == Menu1_MaximumResolution) + { + Options.Resolution = -1; + if (fullscrn::GetMaxResolution() != fullscrn::GetResolution()) + winmain::Restart(); + } + else if (newResolution != fullscrn::GetResolution() && newResolution <= fullscrn::GetMaxResolution()) + { + Options.Resolution = newResolution; + winmain::Restart(); + } + break; + } + default: + break; + } +} + +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(nullptr, "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); } } diff --git a/SpaceCadetPinball/options.h b/SpaceCadetPinball/options.h index 76a12f5..8e4a17f 100644 --- a/SpaceCadetPinball/options.h +++ b/SpaceCadetPinball/options.h @@ -21,6 +21,7 @@ struct optionsStruct int LeftTableBumpKeyDft; int RightTableBumpKeyDft; int BottomTableBumpKeyDft; + int Resolution; }; @@ -38,6 +39,8 @@ public: static void menu_check(UINT uIDCheckItem, int check); static void menu_set(UINT uIDEnableItem, int enable); static void toggle(UINT uIDCheckItem); + static void update_resolution_menu(); + static void init_resolution(); static void keyboard(); static INT_PTR _stdcall KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index db3b576..75915c8 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -3,6 +3,7 @@ #include "control.h" +#include "fullscrn.h" #include "high_score.h" #include "memory.h" #include "pinball.h" @@ -28,6 +29,8 @@ datFileStruct* pb::record_table = nullptr; int pb::time_ticks = 0, pb::demo_mode = 0, pb::cheat_mode = 0, pb::game_mode = 2, pb::mode_countdown_, pb::state; float pb::time_now, pb::time_next, pb::ball_speed_limit; high_score_struct pb::highscore_table[5]; +bool pb::FullTiltMode = false; + int pb::init() { @@ -37,9 +40,8 @@ int pb::init() ++memory::critical_allocation; lstrcpyA(datFileName, winmain::DatFileName); - //lstrcpyA(datFileName, "cadet.dat"); pinball::make_path_name(dataFilePath, datFileName, 300); - record_table = partman::load_records(dataFilePath, 0, strstr(datFileName, "cadet")); + record_table = partman::load_records(dataFilePath, fullscrn::GetResolution(), FullTiltMode); auto useBmpFont = 0; pinball::get_rc_int(158, &useBmpFont); @@ -52,28 +54,27 @@ int pb::init() auto plt = (PALETTEENTRY*)partman::field_labeled(record_table, "background", datFieldTypes::Palette); gdrv::display_palette(plt); - auto tableSize = (__int16*)partman::field_labeled(record_table, "table_size", datFieldTypes::ShortArray); auto backgroundBmp = (gdrv_bitmap8*)partman::field_labeled(record_table, "background", datFieldTypes::Bitmap8bit); - auto cameraInfo = (float*)partman::field_labeled(record_table, "camera_info", datFieldTypes::FloatArray); + auto cameraInfoId = partman::record_labeled(record_table, "camera_info") + fullscrn::GetResolution(); + auto cameraInfo = (float*)partman::field(record_table, cameraInfoId, datFieldTypes::FloatArray); - /*Full tilt hack - table size is hardcoded*/ - if (!tableSize) - tableSize = new short[2]{600, 800}; + /*Full tilt: table size depends on resolution*/ + auto resInfo = &fullscrn::resolution_array[fullscrn::GetResolution()]; if (cameraInfo) { memcpy(&projMat, cameraInfo, sizeof(float) * 4 * 3); cameraInfo += 12; - auto projCenterX = tableSize[0] * 0.5f; - auto projCenterY = tableSize[1] * 0.5f; + auto projCenterX = resInfo->TableWidth * 0.5f; + auto projCenterY = resInfo->TableHeight * 0.5f; auto projD = cameraInfo[0]; proj::init(projMat, projD, projCenterX, projCenterY); zMin = cameraInfo[1]; zScaler = cameraInfo[2]; } - render::init(nullptr, zMin, zScaler, tableSize[0], tableSize[1]); + render::init(nullptr, zMin, zScaler, resInfo->TableWidth, resInfo->TableHeight); gdrv::copy_bitmap( &render::vscreen, backgroundBmp->Width, @@ -316,8 +317,8 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls) void pb::window_size(int* width, int* height) { - *width = 600; - *height = 416; + *width = fullscrn::resolution_array[fullscrn::GetResolution()].TableWidth; + *height = fullscrn::resolution_array[fullscrn::GetResolution()].TableHeight; } void pb::pause_continue() diff --git a/SpaceCadetPinball/pb.h b/SpaceCadetPinball/pb.h index 7bbcdec..6aafc64 100644 --- a/SpaceCadetPinball/pb.h +++ b/SpaceCadetPinball/pb.h @@ -14,6 +14,7 @@ public: static datFileStruct* record_table; static TPinballTable* MainTable; static high_score_struct highscore_table[5]; + static bool FullTiltMode; static int init(); static int uninit(); @@ -38,7 +39,7 @@ public: static void tilt_no_more(); static bool chk_highscore(); static float collide(float timeNow, float timeDelta, TBall* ball); -private : +private: static int demo_mode, mode_countdown_; static int state; }; diff --git a/SpaceCadetPinball/resource.h b/SpaceCadetPinball/resource.h index c8b2b97..7b93141 100644 --- a/SpaceCadetPinball/resource.h +++ b/SpaceCadetPinball/resource.h @@ -224,10 +224,14 @@ #define Menu1_2Players 409 #define Menu1_3Players 410 #define Menu1_4Players 411 +#define Menu1_MaximumResolution 500 #define DLG_HIGHSCORES_Score1 501 #define KEYMAPPER_Default 501 +#define Menu1_640x480 501 #define DLG_HIGHSCORES_Score2 502 +#define Menu1_800x600 502 #define DLG_HIGHSCORES_Score3 503 +#define Menu1_1024x768 503 #define DLG_HIGHSCORES_Score4 504 #define DLG_HIGHSCORES_Score5 505 #define DLG_HIGHSCORES_EditName1 601 @@ -243,6 +247,6 @@ #define _APS_NEXT_RESOURCE_VALUE 204 #define _APS_NEXT_COMMAND_VALUE 40004 #define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 102 +#define _APS_NEXT_SYMED_VALUE 104 #endif #endif diff --git a/SpaceCadetPinball/score.cpp b/SpaceCadetPinball/score.cpp index b17ec41..cc4ebcd 100644 --- a/SpaceCadetPinball/score.cpp +++ b/SpaceCadetPinball/score.cpp @@ -1,8 +1,11 @@ #include "pch.h" #include "score.h" + +#include "fullscrn.h" #include "loader.h" #include "memory.h" #include "partman.h" +#include "pb.h" #include "render.h" #include "TDrain.h" #include "winmain.h" @@ -21,18 +24,21 @@ scoreStruct* score::create(LPCSTR fieldName, gdrv_bitmap8* renderBgBmp) return nullptr; score->Score = -9999; score->BackgroundBmp = renderBgBmp; - auto shortArr = reinterpret_cast<__int16*>(partman::field_labeled(loader::loader_table, fieldName, - datFieldTypes::ShortArray)); - if (!shortArr) + + /*Full tilt: score box dimensions index is offset by resolution*/ + auto dimensionsId = partman::record_labeled(pb::record_table, fieldName) + fullscrn::GetResolution(); + auto dimensions = reinterpret_cast<__int16*>(partman::field(loader::loader_table, dimensionsId, + datFieldTypes::ShortArray)); + if (!dimensions) { memory::free(score); return nullptr; } - int groupIndex = *shortArr++; - score->OffsetX = *shortArr++; - score->OffsetY = *shortArr++; - score->Width = *shortArr++; - score->Height = *shortArr; + int groupIndex = *dimensions++; + score->OffsetX = *dimensions++; + score->OffsetY = *dimensions++; + score->Width = *dimensions++; + score->Height = *dimensions; for (int index = 0; index < 10; index++) { @@ -52,6 +58,15 @@ scoreStruct* score::dup(scoreStruct* score, int scoreIndex) } void score::load_msg_font(LPCSTR lpName) +{ + /*3DPB stores font in resources, FT in dat. FT font has multiple resolutions*/ + if (pb::FullTiltMode) + load_msg_font_FT(lpName); + else + load_msg_font_3DPB(lpName); +} + +void score::load_msg_font_3DPB(LPCSTR lpName) { auto resHandle = FindResourceA(winmain::hinst, lpName, RT_RCDATA); if (!resHandle) @@ -136,18 +151,49 @@ void score::load_msg_font(LPCSTR lpName) FreeResource(resGlobal); } +void score::load_msg_font_FT(LPCSTR lpName) +{ + if (!pb::record_table) + return; + int groupIndex = partman::record_labeled(pb::record_table, lpName); + if (groupIndex < 0) + return; + msg_fontp = reinterpret_cast(memory::allocate(sizeof(score_msg_font_type))); + if (!msg_fontp) + return; + + memset(msg_fontp, 0, sizeof(score_msg_font_type)); + auto gapArray = reinterpret_cast<__int16*>(partman::field(pb::record_table, groupIndex, datFieldTypes::ShortArray)); + if (gapArray) + msg_fontp->GapWidth = gapArray[fullscrn::GetResolution()]; + else + msg_fontp->GapWidth = 0; + for (auto charIndex = 32; charIndex < 128; charIndex++, ++groupIndex) + { + auto bmp = reinterpret_cast(partman::field(pb::record_table, groupIndex, + datFieldTypes::Bitmap8bit)); + if (!bmp) + break; + if (!msg_fontp->Height) + msg_fontp->Height = bmp->Height; + msg_fontp->Chars[charIndex] = bmp; + } +} + void score::unload_msg_font() { if (msg_fontp) { - for (int i = 0; i < 128; i++) - { - if (msg_fontp->Chars[i]) + /*3DB creates bitmaps, FT just references them from partman*/ + if (!pb::FullTiltMode) + for (int i = 0; i < 128; i++) { - gdrv::destroy_bitmap(msg_fontp->Chars[i]); - memory::free(msg_fontp->Chars[i]); + if (msg_fontp->Chars[i]) + { + gdrv::destroy_bitmap(msg_fontp->Chars[i]); + memory::free(msg_fontp->Chars[i]); + } } - } memory::free(msg_fontp); msg_fontp = nullptr; } diff --git a/SpaceCadetPinball/score.h b/SpaceCadetPinball/score.h index 83212f9..33bf39e 100644 --- a/SpaceCadetPinball/score.h +++ b/SpaceCadetPinball/score.h @@ -42,4 +42,7 @@ public: static void set(scoreStruct* score, int value); static void update(scoreStruct* score); static void string_format(int score, char* str); +private : + static void load_msg_font_3DPB(LPCSTR lpName); + static void load_msg_font_FT(LPCSTR lpName); }; diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index 1ef2d84..5023fe5 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -30,6 +30,7 @@ int winmain::no_time_loss; DWORD winmain::then; DWORD winmain::now; UINT winmain::iFrostUniqueMsg; +bool winmain::restart = false; gdrv_bitmap8 winmain::gfr_display{}; char winmain::DatFileName[300]{}; @@ -116,6 +117,18 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi hinst = hInstance; options::get_string(regSpaceCadet, "Pinball Data", DatFileName, pinball::get_rc_string(168, 0), 300); + /*Check for full tilt .dat file and switch to it automatically*/ + char cadetFilePath[300]{}; + pinball::make_path_name(cadetFilePath, "CADET.DAT", 300); + FILE* cadetDat; + fopen_s(&cadetDat, cadetFilePath, "r"); + if (cadetDat) + { + fclose(cadetDat); + strcpy_s(DatFileName, "CADET.DAT"); + pb::FullTiltMode = true; + } + iFrostUniqueMsg = RegisterWindowMessageA("PinballThemeSwitcherUniqueMsgString"); auto windowClass = pinball::get_rc_string(167, 0); auto windowHandle = FindWindowA(windowClass, nullptr); @@ -148,6 +161,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi RegisterClassA(&WndClass); pinball::FindShiftKeys(); + options::init_resolution(); char windowName[40]; lstrcpyA(windowName, pinball::get_rc_string(38, 0)); @@ -301,6 +315,24 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi DestroyWindow(hwnd_frame); options::path_uninit(); UnregisterClassA(windowClass, hinst); + + if (restart) + { + 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; } @@ -350,11 +382,6 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP RECT rect{}; ++memory::critical_allocation; - GetWindowRect(GetDesktopWindow(), &rect); - int width = rect.right - rect.left; - int height = rect.bottom - rect.top; - pb::window_size(&width, &height); - auto prevCursor = SetCursor(LoadCursorA(nullptr, IDC_WAIT)); gdrv::init(hinst, hWnd); @@ -371,6 +398,11 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP SetCursor(prevCursor); auto changeDisplayFg = options::get_int(nullptr, "Change Display", 1); auto menuHandle = GetMenu(hWnd); + + GetWindowRect(GetDesktopWindow(), &rect); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + pb::window_size(&width, &height); fullscrn::init(width, height, options::Options.FullScreen, hWnd, menuHandle, changeDisplayFg); @@ -428,6 +460,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP fullscrn::getminmaxinfo((MINMAXINFO*)lParam); return DefWindowProcA(hWnd, Msg, wParam, lParam); case WM_DISPLAYCHANGE: + options::update_resolution_menu(); if (fullscrn::displaychange()) { options::Options.FullScreen = 0; @@ -558,6 +591,12 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP options::toggle(wParam); new_game(); break; + case Menu1_MaximumResolution: + case Menu1_640x480: + case Menu1_800x600: + case Menu1_1024x768: + options::toggle(wParam); + break; case Menu1_Help_Topics: if (!single_step) pause(); @@ -779,3 +818,9 @@ void winmain::help_introduction(HINSTANCE a1, HWND a2) } } } + +void winmain::Restart() +{ + restart = true; + PostMessageA(hwnd_frame, WM_QUIT, 0, 0); +} diff --git a/SpaceCadetPinball/winmain.h b/SpaceCadetPinball/winmain.h index 83019ed..6914745 100644 --- a/SpaceCadetPinball/winmain.h +++ b/SpaceCadetPinball/winmain.h @@ -20,6 +20,7 @@ public: static void new_game(); static void pause(); static void help_introduction(HINSTANCE a1, HWND a2); + static void 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; @@ -27,6 +28,7 @@ private: static UINT iFrostUniqueMsg; static gdrv_bitmap8 gfr_display; static HCURSOR mouse_hsave; + static bool restart; static HDC _BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint); };