Added scalable window, mouse controls.

This commit is contained in:
Muzychenko Andrey 2021-02-09 18:09:44 +03:00
parent 1c5256a4c6
commit debe52c1e0
11 changed files with 200 additions and 73 deletions

View file

@ -95,6 +95,10 @@ BEGIN
MENUITEM "&800 x 600", Menu1_800x600
MENUITEM "&1024 x 768", Menu1_1024x768
END
POPUP "&Window"
BEGIN
MENUITEM "&Uniform Scaling", Menu1_WindowUniformScale
END
END
POPUP "&Help"
BEGIN

View file

@ -1,6 +1,8 @@
#include "pch.h"
#include "fullscrn.h"
#include "options.h"
#include "pb.h"
#include "render.h"
#include "winmain.h"
@ -24,6 +26,10 @@ const resolution_info fullscrn::resolution_array[3] =
{800, 600, 752, 520, 502},
{1024, 768, 960, 666, 503},
};
float fullscrn::ScaleX = 1;
float fullscrn::ScaleY = 1;
float fullscrn::OffsetX = 0;
float fullscrn::OffsetY = 0;
void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay)
{
@ -46,15 +52,21 @@ void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HME
WindowRect2.right = (WindowRect1.right - WindowRect1.left - widht2) / 2 - 2 + widht2 + 4;
WindowRect2.left = (WindowRect1.right - WindowRect1.left - widht2) / 2 - 2;
WindowRect2.top = borderHeight / 2 - (captionHeight + menuHeight) - 2;
/*RECT client{0,0,width,height};
AdjustWindowRect(&client, winmain::WndStyle, true);*/
MoveWindow(
hWnd,
(WindowRect1.right - WindowRect1.left - widht2) / 2 - 2,
WindowRect2.top,
widht2 + 4 + 10,
WindowRect2.right - WindowRect2.left + 10,
WindowRect2.bottom - WindowRect2.top + 10,
0);
// Todo: WH + 10 hack: original request 640x480 window but somehow receives 650x490, even thought spyxx says it is 640x480
fullscrn_flag1 = 0;
window_size_changed();
assertm(ScaleX == 1 && ScaleY == 1, "Wrong default client size");
}
void fullscrn::shutdown()
@ -94,13 +106,13 @@ int fullscrn::set_screen_mode(int isFullscreen)
int fullscrn::disableWindowFlagsDisDlg()
{
long style = GetWindowLongA(hWnd, -16);
return SetWindowLongA(hWnd, -16, style & 0xFF3FFFFF);
return SetWindowLongA(hWnd, -16, style & ~(WS_CAPTION | WS_THICKFRAME));
}
int fullscrn::setWindowFlagsDisDlg()
{
int style = GetWindowLongA(hWnd, -16);
return SetWindowLongA(hWnd, -16, style | 0xC00000);
return SetWindowLongA(hWnd, -16, style | WS_CAPTION | WS_THICKFRAME);
}
int fullscrn::enableFullscreen()
@ -339,10 +351,12 @@ unsigned fullscrn::convert_mouse_pos(unsigned int mouseXY)
void fullscrn::getminmaxinfo(MINMAXINFO* maxMin)
{
maxMin->ptMaxSize.x = WindowRect2.right - WindowRect2.left;
maxMin->ptMaxSize.y = WindowRect2.bottom - WindowRect2.top;
maxMin->ptMaxPosition.x = WindowRect2.left;
maxMin->ptMaxPosition.y = WindowRect2.top;
/*Block down-scaling lower than min resolution*/
maxMin->ptMinTrackSize = POINT
{
resolution_array[0].ScreenWidth / 2,
resolution_array[0].ScreenHeight / 2
};
}
void fullscrn::paint()
@ -419,3 +433,34 @@ int fullscrn::get_screen_resolution()
auto height = static_cast<unsigned __int16>(GetSystemMetrics(SM_CYSCREEN));
return static_cast<unsigned __int16>(GetSystemMetrics(SM_CXSCREEN)) | (height << 16);
}
void fullscrn::window_size_changed()
{
/*No scaling in fullscreen mode*/
if (display_changed)
{
ScaleY = ScaleX = 1;
OffsetX = OffsetY = 0;
return;
}
RECT client{};
GetClientRect(hWnd, &client);
auto res = &resolution_array[resolution];
ScaleX = static_cast<float>(client.right) / res->TableWidth;
ScaleY = static_cast<float>(client.bottom) / res->TableHeight;
OffsetX = OffsetY = 0;
if (options::Options.UniformScaling)
{
ScaleY = ScaleX = min(ScaleX, ScaleY);
OffsetX = floor((client.right - res->TableWidth * ScaleX) / 2);
OffsetY = floor((client.bottom - res->TableHeight * ScaleY) / 2);
auto dc = GetDC(hWnd);
if (dc)
{
BitBlt(dc, 0, 0, client.right, client.bottom, dc, 0, 0, BLACKNESS);
ReleaseDC(hWnd, dc);
}
}
}

View file

@ -28,6 +28,10 @@ public:
static int ChangeDisplay, SmthFullScrnFlag2;
static int trick;
static const resolution_info resolution_array[3];
static float ScaleX;
static float ScaleY;
static float OffsetX;
static float OffsetY;
static void init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay);
static void shutdown();
@ -46,6 +50,7 @@ public:
static void SetMaxResolution(int resolution);
static int get_max_supported_resolution();
static int get_screen_resolution();
static void window_size_changed();
private :
static int MenuEnabled;
static HMENU MenuHandle;

View file

@ -1,5 +1,7 @@
#include "pch.h"
#include "gdrv.h"
#include "fullscrn.h"
#include "memory.h"
#include "pinball.h"
#include "winmain.h"
@ -252,19 +254,20 @@ int gdrv::destroy_bitmap(gdrv_bitmap8* bmp)
return 0;
}
UINT gdrv::start_blit_sequence()
void gdrv::start_blit_sequence()
{
HDC dc = winmain::_GetDC(hwnd);
sequence_handle = 0;
sequence_hdc = dc;
SelectPalette(dc, palette_handle, 0);
return RealizePalette(sequence_hdc);
RealizePalette(sequence_hdc);
SetStretchBltMode(dc, stretchMode);
}
void gdrv::blit_sequence(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, int DestHeight)
{
if (!use_wing)
StretchDIBits(
StretchDIBitsScaled(
sequence_hdc,
xDest,
yDest,
@ -274,10 +277,10 @@ void gdrv::blit_sequence(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, in
bmp->Height - ySrcOff - DestHeight,
DestWidth,
DestHeight,
bmp->BmpBufPtr1,
bmp->Dib,
1u,
SRCCOPY);
bmp,
DIB_PAL_COLORS,
SRCCOPY
);
}
@ -289,12 +292,13 @@ void gdrv::end_blit_sequence()
void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, int DestHeight)
{
HDC dc = winmain::_GetDC(hwnd);
SetStretchBltMode(dc, stretchMode);
if (dc)
{
SelectPalette(dc, palette_handle, 0);
RealizePalette(dc);
if (!use_wing)
StretchDIBits(
StretchDIBitsScaled(
dc,
xDest,
yDest,
@ -304,10 +308,10 @@ void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest,
bmp->Height - ySrcOff - DestHeight,
DestWidth,
DestHeight,
bmp->BmpBufPtr1,
bmp->Dib,
1u,
SRCCOPY);
bmp,
DIB_PAL_COLORS,
SRCCOPY
);
ReleaseDC(hwnd, dc);
}
}
@ -317,8 +321,9 @@ void gdrv::blat(gdrv_bitmap8* bmp, int xDest, int yDest)
HDC dc = winmain::_GetDC(hwnd);
SelectPalette(dc, palette_handle, 0);
RealizePalette(dc);
SetStretchBltMode(dc, stretchMode);
if (!use_wing)
StretchDIBits(
StretchDIBitsScaled(
dc,
xDest,
yDest,
@ -328,10 +333,10 @@ void gdrv::blat(gdrv_bitmap8* bmp, int xDest, int yDest)
0,
bmp->Width,
bmp->Height,
bmp->BmpBufPtr1,
bmp->Dib,
1u,
SRCCOPY);
bmp,
DIB_PAL_COLORS,
SRCCOPY
);
ReleaseDC(hwnd, dc);
}
@ -416,3 +421,42 @@ void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width,
SetTextColor(dc, color);
ReleaseDC(hwnd, dc);
}
int gdrv::StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc,
int SrcWidth, int SrcHeight, gdrv_bitmap8* bmp, UINT iUsage,
DWORD rop)
{
/*Scaled partial updates may leave 1px border artifacts around update area.
* Pad update area to compensate.*/
const int pad = 1, padX2 = pad * 2;
if (fullscrn::ScaleX > 1 && xSrc > pad && xSrc + pad < bmp->Width)
{
xSrc -= pad;
xDest -= pad;
SrcWidth += padX2;
DestWidth += padX2;
}
if (fullscrn::ScaleY > 1 && ySrc > pad && ySrc + pad < bmp->Height)
{
ySrc -= pad;
yDest -= pad;
SrcHeight += padX2;
DestHeight += padX2;
}
return StretchDIBits(
hdc,
static_cast<int>(round(xDest * fullscrn::ScaleX + fullscrn::OffsetX)),
static_cast<int>(round(yDest * fullscrn::ScaleY + fullscrn::OffsetY)),
static_cast<int>(round(DestWidth * fullscrn::ScaleX)),
static_cast<int>(round(DestHeight * fullscrn::ScaleY)),
xSrc,
ySrc,
SrcWidth,
SrcHeight,
bmp->BmpBufPtr1,
bmp->Dib,
iUsage,
rop);
}

View file

@ -53,7 +53,7 @@ public:
static int create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size);
static int destroy_bitmap(gdrv_bitmap8* bmp);
static int display_palette(PALETTEENTRY* plt);
static UINT start_blit_sequence();
static void start_blit_sequence();
static void blit_sequence(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth,
int DestHeight);
static void end_blit_sequence();
@ -66,9 +66,15 @@ public:
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff);
static void grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6);
private:
/*COLORONCOLOR or HALFTONE*/
static const int stretchMode = COLORONCOLOR;
static HWND hwnd;
static HINSTANCE hinst;
static int grtext_blue;
static int grtext_green;
static int grtext_red;
static int StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc,
int SrcWidth, int SrcHeight, gdrv_bitmap8* bmp, UINT iUsage,
DWORD rop);
};

View file

@ -12,7 +12,7 @@
LPCSTR options::OptionsRegPath;
LPSTR options::OptionsRegPathCur;
HMENU options::MenuHandle;
optionsStruct options::Options;
optionsStruct options::Options{};
winhelp_entry options::keymap_help[18]
{
@ -107,6 +107,7 @@ void options::init(HMENU menuHandle)
Options.LeftTableBumpKey = get_int(nullptr, "Left Table Bump key", Options.LeftTableBumpKey);
Options.RightTableBumpKey = get_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey);
Options.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
Options.UniformScaling = get_int(nullptr, "Uniform scaling", true);
menu_check(Menu1_Sounds, Options.Sounds);
Sound::Enable(0, 7, Options.Sounds);
menu_check(Menu1_Music, Options.Music);
@ -115,6 +116,7 @@ void options::init(HMENU menuHandle)
menu_check(Menu1_2Players, Options.Players == 2);
menu_check(Menu1_3Players, Options.Players == 3);
menu_check(Menu1_4Players, Options.Players == 4);
menu_check(Menu1_WindowUniformScale, Options.UniformScaling);
auto tmpBuf = memory::allocate(0x1F4u);
if (tmpBuf)
{
@ -146,6 +148,7 @@ void options::uninit()
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);
set_int(nullptr, "Uniform scaling", Options.UniformScaling);
}
void options::path_init(LPCSTR regPath)
@ -315,10 +318,9 @@ void options::toggle(UINT uIDCheckItem)
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);
for (unsigned i = Menu1_MaximumResolution; i <= Menu1_1024x768; ++i)
menu_check(i, i == uIDCheckItem);
int newResolution = uIDCheckItem - Menu1_640x480;
if (uIDCheckItem == Menu1_MaximumResolution)
{
@ -333,6 +335,12 @@ void options::toggle(UINT uIDCheckItem)
}
break;
}
case Menu1_WindowUniformScale:
Options.UniformScaling ^= true;
menu_check(Menu1_WindowUniformScale, Options.UniformScaling);
fullscrn::window_size_changed();
fullscrn::paint();
break;
default:
break;
}

View file

@ -22,6 +22,7 @@ struct optionsStruct
int RightTableBumpKeyDft;
int BottomTableBumpKeyDft;
int Resolution;
bool UniformScaling;
};

View file

@ -473,35 +473,21 @@ void render::paint_balls()
void render::unpaint_balls()
{
auto ballPtr = &ball_list[many_balls - 1];
if (many_balls - 1 >= 0)
for (int index = many_balls-1; index >= 0; index--)
{
gdrv_bitmap8* bitmapPtr = &ball_bitmap[many_balls - 1];
for (int index = many_balls; index > 0; index--)
{
struct render_sprite_type_struct* curBall = *ballPtr;
rectangle_type* rect2 = &(*ballPtr)->DirtyRect;
int width = (*ballPtr)->DirtyRect.Width;
if (width > 0)
gdrv::copy_bitmap(
&vscreen,
width,
(*ballPtr)->DirtyRect.Height,
(*ballPtr)->DirtyRect.XPosition,
(*ballPtr)->DirtyRect.YPosition,
bitmapPtr,
0,
0);
auto curBall = ball_list[index];
if (curBall->DirtyRect.Width > 0)
gdrv::copy_bitmap(
&vscreen,
curBall->DirtyRect.Width,
curBall->DirtyRect.Height,
curBall->DirtyRect.XPosition,
curBall->DirtyRect.YPosition,
&ball_bitmap[index],
0,
0);
rectangle_type* rectCopy = &curBall->BmpRectCopy;
rectCopy->XPosition = rect2->XPosition;
rectCopy->YPosition = rect2->YPosition;
rectCopy->Width = rect2->Width;
rectCopy->Height = rect2->Height;
--ballPtr;
--bitmapPtr;
}
curBall->BmpRectCopy = curBall->DirtyRect;
}
}

View file

@ -234,6 +234,7 @@
#define Menu1_1024x768 503
#define DLG_HIGHSCORES_Score4 504
#define DLG_HIGHSCORES_Score5 505
#define Menu1_WindowUniformScale 600
#define DLG_HIGHSCORES_EditName1 601
#define DLG_HIGHSCORES_EditName2 602
#define DLG_HIGHSCORES_EditName3 603
@ -245,7 +246,7 @@
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 204
#define _APS_NEXT_COMMAND_VALUE 40004
#define _APS_NEXT_COMMAND_VALUE 40006
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 104
#endif

View file

@ -146,26 +146,27 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
picce.dwICC = 5885;
InitCommonControlsEx(&picce);
WNDCLASSA WndClass{};
WndClass.style = 4104;
WndClass.lpfnWndProc = message_handler;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIconA(hInstance, "ICON_1");
WndClass.hCursor = LoadCursorA(nullptr, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)16;
WndClass.lpszMenuName = "MENU_1";
WndClass.lpszClassName = windowClass;
WNDCLASSEXA wndClass{};
wndClass.cbSize = sizeof wndClass;
wndClass.style = CS_DBLCLKS | CS_BYTEALIGNCLIENT;
wndClass.lpfnWndProc = message_handler;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIconA(hInstance, "ICON_1");
wndClass.hCursor = LoadCursorA(nullptr, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)16;
wndClass.lpszMenuName = "MENU_1";
wndClass.lpszClassName = windowClass;
auto splash = splash::splash_screen(hInstance, "splash_bitmap", "splash_bitmap");
RegisterClassA(&WndClass);
RegisterClassExA(&wndClass);
pinball::FindShiftKeys();
options::init_resolution();
char windowName[40];
lstrcpyA(windowName, pinball::get_rc_string(38, 0));
windowHandle = CreateWindowExA(0, windowClass, windowName, 0x3CA0000u, 0, 0, 640, 480, nullptr, nullptr, hInstance,
lstrcpyA(windowName, pinball::get_rc_string(38, 0));
windowHandle = CreateWindowExA(0, windowClass, windowName, WndStyle, 0, 0, 640, 480, nullptr, nullptr, hInstance,
nullptr);
hwnd_frame = windowHandle;
if (!windowHandle)
@ -437,6 +438,11 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
return DefWindowProcA(hWnd, Msg, wParam, lParam);
case WM_ERASEBKGND:
break;
case WM_SIZE:
fullscrn::window_size_changed();
fullscrn::force_redraw();
pb::paint();
return DefWindowProcA(hWnd, Msg, wParam, lParam);
default:
return DefWindowProcA(hWnd, Msg, wParam, lParam);
}
@ -595,6 +601,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
case Menu1_640x480:
case Menu1_800x600:
case Menu1_1024x768:
case Menu1_WindowUniformScale:
options::toggle(wParam);
break;
case Menu1_Help_Topics:
@ -653,6 +660,9 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
last_mouse_y = mouseXY >> 16;
SetCapture(hWnd);
}
else
pb::keydown(options::Options.LeftFlipperKey);
return DefWindowProcA(hWnd, Msg, wParam, lParam);
}
break;
@ -663,12 +673,27 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
SetCursor(mouse_hsave);
ReleaseCapture();
}
if (!pb::cheat_mode)
pb::keyup(options::Options.LeftFlipperKey);
return DefWindowProcA(hWnd, Msg, wParam, lParam);
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
if (!pb::cheat_mode)
pb::keydown(options::Options.RightFlipperKey);
if (pb::game_mode)
return DefWindowProcA(hWnd, Msg, wParam, lParam);
break;
case WM_RBUTTONUP:
if (!pb::cheat_mode)
pb::keyup(options::Options.RightFlipperKey);
return DefWindowProcA(hWnd, Msg, wParam, lParam);
case WM_MBUTTONDOWN:
pb::keydown(options::Options.PlungerKey);
if (pb::game_mode)
return DefWindowProcA(hWnd, Msg, wParam, lParam);
break;
case WM_MBUTTONUP:
pb::keyup(options::Options.PlungerKey);
return DefWindowProcA(hWnd, Msg, wParam, lParam);
case WM_POWERBROADCAST:
if (wParam == 4 && options::Options.FullScreen)
{

View file

@ -4,6 +4,8 @@
class winmain
{
public:
static const DWORD WndStyle = WS_GROUP | WS_SYSMENU | WS_DLGFRAME | WS_BORDER | WS_MAXIMIZE | WS_CLIPCHILDREN |
WS_THICKFRAME | WS_MAXIMIZEBOX;
static char DatFileName[300];
static int single_step;
static HINSTANCE hinst;