40 Commits

Author SHA1 Message Date
Muzychenko Andrey
c7f5f8cd30 Merge from master: fixed bug with mission accept scores.
Ref issue #81.
2021-11-04 18:49:49 +03:00
Muzychenko Andrey
da4b99e983 Added Unicode support in high score dialog.
Cherry picked form ecea9c812a.
2021-11-03 12:53:04 +03:00
Muzychenko Andrey
2abcaac437 Added Turkish translation.
This is the last WinXP language, for a total of 24.
2021-11-02 15:33:22 +03:00
Muzychenko Andrey
98da410251 Added Swedish translation. 2021-11-02 14:24:47 +03:00
Muzychenko Andrey
e020c0fe33 Added Portuguese translation. 2021-11-02 14:04:25 +03:00
Muzychenko Andrey
33b8b29f11 Added Norwegian translation. 2021-11-01 12:21:50 +03:00
Muzychenko Andrey
84a46082ab Added Dutch translation. 2021-11-01 11:09:13 +03:00
Muzychenko Andrey
a079117507 Added Korean translation. 2021-10-31 18:29:41 +03:00
Muzychenko Andrey
620ec011ec Added Spanish translation. 2021-10-31 17:35:41 +03:00
Muzychenko Andrey
1af8bb67d7 Added Greek translation. 2021-10-31 17:25:24 +03:00
Muzychenko Andrey
089ccbf549 Added Arabic translation. 2021-10-31 17:03:32 +03:00
Muzychenko Andrey
1428fb3770 Added Hebrew translation.
Switched to MessageBoxW in some places.
2021-10-31 13:18:21 +03:00
Muzychenko Andrey
1c1fbcb811 TTextBox: fixed DrawText texts getting overwritten by full redraw.
This bug is from the original 3DPB.
2021-10-30 18:25:49 +03:00
Muzychenko Andrey
c0ec8ec932 Added Finnish translation. 2021-10-30 16:50:49 +03:00
Muzychenko Andrey
71e25fd7fa Merge from master: control bugfix, no delay FT THole. 2021-10-30 16:21:01 +03:00
Muzychenko Andrey
b40b54ce51 Updated plans 2021-10-30 12:54:30 +03:00
Muzychenko Andrey
b4a85bcf2f Added Danish translation. 2021-10-29 17:40:02 +03:00
Muzychenko Andrey
acc2725bbe Added Czech translation. 2021-10-29 17:33:09 +03:00
Muzychenko Andrey
68c2055ce6 Added Brazilian Portuguese translation. 2021-10-29 17:25:26 +03:00
Muzychenko Andrey
09668f3468 Added Hungarian translation.
Disabled bitmap font in Italian translation.
2021-10-29 10:47:17 +03:00
Muzychenko Andrey
4878b6a835 Added Italian translation. 2021-10-28 18:17:36 +03:00
Muzychenko Andrey
bd606436bd Added French translation. 2021-10-28 11:41:30 +03:00
Raymai (Chee Boon)
457a982f72 Change only a few key places to make the program works as if it's Unicode build. (#75) 2021-10-28 10:58:19 +03:00
Muzychenko Andrey
e2f10333d9 Added Japanese translation. 2021-10-28 09:56:14 +03:00
Muzychenko Andrey
356977290e Added German translation. 2021-10-28 08:56:49 +03:00
Muzychenko Andrey
a65c40fe32 Added incomplete Polish translation.
Removed unused dialogs.
Fixed char sprintf in control.
Ref #28.
2021-10-27 09:22:53 +03:00
Muzychenko Andrey
d0c1ac60b6 TTextBox: converted to accept wchar input.
Ref #69.
2021-10-26 08:12:37 +03:00
Lim Chunwei
3c2fff9d07 Use a single Unicode charset and specify language-specific font for better viewing (?) (#69)
* Use a single Unicode charset and specify language-specific font for better (?) viewing

* Fix missing include for strcpy_s function

* Better (?) implementation of using strings (so that font names aren't limited to 30 chars)
2021-10-26 06:53:52 +03:00
Muzychenko Andrey
09c62f5909 Fixed mixed up Chinese language texts. 2021-10-25 17:40:38 +03:00
Muzychenko Andrey
cf215aaa6a Added Traditional Chinese and Simplified Chinese languages to options.
They don’t work without Chinese locale.
Ref #68.
2021-10-25 17:30:39 +03:00
Lim Chunwei
893d898d0a Simplified Chinese and Traditional Chinese translations (#68) 2021-10-25 14:10:47 +03:00
Muzychenko Andrey
502fc71afc Added experimental translation support.
Added Russian translation.
Ref issues #28, #56.
2021-10-24 18:23:46 +03:00
Muzychenko Andrey
cf8b53de01 Added scaling support in grtext_draw_ttext_in_box.
Issue #56.
2021-10-21 16:47:45 +03:00
Muzychenko Andrey
331f1dc125 Added release version to about dialog. 2021-10-16 16:19:53 +03:00
Muzychenko Andrey
0d9610ddb6 Added new render mode with reduced tearing.
Available under new option Window->Alternative Rendering.
Issue #29.
2021-10-12 16:30:20 +03:00
Muzychenko Andrey
de76557325 Bug fixes from master:
Demangled and simplified cheat controller.
TKickout temp Z in FT mode.
Flipper animation frame advance.
Fuel bar graph light states.
2021-10-09 08:14:47 +03:00
Muzychenko Andrey
b995b02fd1 Added ARM/ARM64 build configurations.
Ref #21.
2021-10-04 10:03:16 +03:00
Muzychenko Andrey
de6c31802c Bug fixes from master: score saving and missing sub. 2021-09-30 08:59:56 +03:00
Muzychenko Andrey
86eaad5b79 Fixed off-by-one error in background blit. 2021-09-07 10:19:06 +03:00
Muzychenko Andrey
60e9f63607 Added Windows XP build configuration.
Improved background blit for unform scaling.
2021-09-07 10:09:07 +03:00
37 changed files with 1303 additions and 812 deletions

11
.gitignore vendored
View File

@@ -21,6 +21,9 @@ bld/
[Bb]in/ [Bb]in/
[Oo]bj/ [Oo]bj/
[Ll]og/ [Ll]og/
ARM/
ARM64/
win32/
# Visual Studio 2015 cache/options directory # Visual Studio 2015 cache/options directory
.vs/ .vs/
@@ -263,3 +266,11 @@ __pycache__/
/Export /Export
/DrMem /DrMem
/Doc private /Doc private
# Cmake stuff
/Libs
/out
# WinXp stuff
DebugWinXp/
ReleaseWinXp/

View File

@@ -27,10 +27,9 @@ Compile with Visual Studio; tested with 2017 and 2019.
* ~~Decompile original game~~ * ~~Decompile original game~~
* ~~Resizable window, scaled graphics~~ * ~~Resizable window, scaled graphics~~
* ~~Loader for high-res sprites from CADET.DAT~~ * ~~Loader for high-res sprites from CADET.DAT~~
* Misc features of Full Tilt: 3 music tracs, multiball, centered textboxes, etc. * ~~Cross-platform port using SDL2, SDL2_mixer, ImGui~~
* Maybe: cross-platform port * Text translations
* Needs UI framework with menu bar and dialog windows, like QT or Avalonia * Misc features of Full Tilt: 3 music tracks, multiball, centered textboxes, etc.
* Needs a way play sounds and midi
* Maybe x2: support for other two tables * Maybe x2: support for other two tables
* Table specific BL (control interactions and missions) is hardcoded, othere parts might be also patched * Table specific BL (control interactions and missions) is hardcoded, othere parts might be also patched

View File

@@ -1,26 +1,50 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.28307.705 VisualStudioVersion = 16.0.31624.102
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpaceCadetPinball", "SpaceCadetPinball\SpaceCadetPinball.vcxproj", "{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpaceCadetPinball", "SpaceCadetPinball\SpaceCadetPinball.vcxproj", "{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64 Release|x64 = Release|x64
Release|x86 = Release|x86 Release|x86 = Release|x86
ReleaseWinXp|ARM = ReleaseWinXp|ARM
ReleaseWinXp|ARM64 = ReleaseWinXp|ARM64
ReleaseWinXp|x64 = ReleaseWinXp|x64
ReleaseWinXp|x86 = ReleaseWinXp|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|ARM.ActiveCfg = Debug|ARM
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|ARM.Build.0 = Debug|ARM
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|ARM64.ActiveCfg = Debug|ARM64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|ARM64.Build.0 = Debug|ARM64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.ActiveCfg = Debug|x64 {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.ActiveCfg = Debug|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.Build.0 = Debug|x64 {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.Build.0 = Debug|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.ActiveCfg = Debug|Win32 {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.ActiveCfg = Debug|Win32
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.Build.0 = Debug|Win32 {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.Build.0 = Debug|Win32
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|ARM.ActiveCfg = Release|ARM
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|ARM.Build.0 = Release|ARM
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|ARM64.ActiveCfg = Release|ARM64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|ARM64.Build.0 = Release|ARM64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.ActiveCfg = Release|x64 {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.ActiveCfg = Release|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.Build.0 = Release|x64 {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.Build.0 = Release|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.ActiveCfg = Release|Win32 {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.ActiveCfg = Release|Win32
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.Build.0 = Release|Win32 {F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.Build.0 = Release|Win32
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|ARM.ActiveCfg = ReleaseWinXp|ARM
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|ARM.Build.0 = ReleaseWinXp|ARM
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|ARM64.ActiveCfg = ReleaseWinXp|ARM64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|ARM64.Build.0 = ReleaseWinXp|ARM64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|x64.ActiveCfg = ReleaseWinXp|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|x64.Build.0 = ReleaseWinXp|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|x86.ActiveCfg = ReleaseWinXp|Win32
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.ReleaseWinXp|x86.Build.0 = ReleaseWinXp|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -49,7 +49,7 @@ int Sound::Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWA
{ {
/*FT does not have the file, defaults work OK*/ /*FT does not have the file, defaults work OK*/
if (!pb::FullTiltMode) if (!pb::FullTiltMode)
MessageBoxA(winmain::hwnd_frame, pinball::get_rc_string(42, 0), "", 0x2000u); MessageBoxW(winmain::hwnd_frame, pinball::get_rc_Wstring(42, 0), L"", 0x2000u);
} }
WndClass.style = 0; WndClass.style = 0;

View File

@@ -1,10 +1,42 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="ReleaseWinXp|ARM">
<Configuration>ReleaseWinXp</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseWinXp|ARM64">
<Configuration>ReleaseWinXp</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseWinXp|Win32">
<Configuration>ReleaseWinXp</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseWinXp|x64">
<Configuration>ReleaseWinXp</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32"> <ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
@@ -32,6 +64,12 @@
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet> <CharacterSet>NotSet</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
@@ -39,12 +77,39 @@
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet> <CharacterSet>NotSet</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet> <CharacterSet>NotSet</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
@@ -52,6 +117,27 @@
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet> <CharacterSet>NotSet</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
</ImportGroup> </ImportGroup>
@@ -60,29 +146,84 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<RunCodeAnalysis>false</RunCodeAnalysis> <RunCodeAnalysis>false</RunCodeAnalysis>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<LinkIncremental>true</LinkIncremental>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
@@ -102,6 +243,25 @@
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<BufferSecurityCheck>true</BufferSecurityCheck>
<PreprocessToFile>false</PreprocessToFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
@@ -119,6 +279,23 @@
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile> <ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
@@ -140,6 +317,69 @@
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
@@ -161,6 +401,69 @@
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="control.h" /> <ClInclude Include="control.h" />
<ClInclude Include="fullscrn.h" /> <ClInclude Include="fullscrn.h" />
@@ -242,9 +545,17 @@
<ClCompile Include="pb.cpp" /> <ClCompile Include="pb.cpp" />
<ClCompile Include="pch.cpp"> <ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM64'">Create</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="pinball.cpp" /> <ClCompile Include="pinball.cpp" />
<ClCompile Include="proj.cpp" /> <ClCompile Include="proj.cpp" />

View File

@@ -22,14 +22,14 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
Smoothness = visual.Smoothness; Smoothness = visual.Smoothness;
auto collMult = *loader::query_float_attribute(groupIndex, 0, 803); auto collMult = *loader::query_float_attribute(groupIndex, 0, 803);
auto bmpCoef2 = *loader::query_float_attribute(groupIndex, 0, 805); auto retractTime = *loader::query_float_attribute(groupIndex, 0, 805);
auto bmpCoef1 = *loader::query_float_attribute(groupIndex, 0, 804); auto extendTime = *loader::query_float_attribute(groupIndex, 0, 804);
/*Full tilt hack: different flipper speed*/ /*Full tilt hack: different flipper speed*/
if (pb::FullTiltMode) if (pb::FullTiltMode)
{ {
bmpCoef2 = 0.08f; retractTime = 0.08f;
bmpCoef1 = 0.04f; extendTime = 0.04f;
} }
auto vecT2 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 802)); auto vecT2 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 802));
auto vecT1 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 801)); auto vecT1 = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 801));
@@ -42,8 +42,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
origin, origin,
vecT1, vecT1,
vecT2, vecT2,
bmpCoef1, extendTime,
bmpCoef2, retractTime,
collMult, collMult,
Elasticity, Elasticity,
Smoothness); Smoothness);
@@ -51,8 +51,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
FlipperEdge = flipperEdge; FlipperEdge = flipperEdge;
if (flipperEdge) if (flipperEdge)
{ {
BmpCoef1 = flipperEdge->BmpCoef1 / static_cast<float>(ListBitmap->GetCount() - 1); ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast<float>(ListBitmap->GetCount() - 1);
BmpCoef2 = flipperEdge->BmpCoef2 / static_cast<float>(ListBitmap->GetCount() - 1); RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast<float>(ListBitmap->GetCount() - 1);
} }
BmpIndex = 0; BmpIndex = 0;
InputTime = 0.0; InputTime = 0.0;
@@ -68,35 +68,30 @@ int TFlipper::Message(int code, float value)
if (code == 1 || code == 2 || code > 1008 && code <= 1011 || code == 1022) if (code == 1 || code == 2 || code > 1008 && code <= 1011 || code == 1022)
{ {
float timerTime; float timerTime;
int soundIndex = 0, code2 = code; int command = code;
if (code == 1) if (code == 1)
{ {
control::handler(1, this); control::handler(1, this);
TimerTime = BmpCoef1; TimerTime = ExtendAnimationFrameTime;
soundIndex = HardHitSoundId; loader::play_sound(HardHitSoundId);
} }
else if (code == 2) else if (code == 2)
{ {
TimerTime = BmpCoef2; TimerTime = RetractAnimationFrameTime;
soundIndex = SoftHitSoundId; loader::play_sound(SoftHitSoundId);
} }
else else
{ {
code2 = 2; // Retract for all non-input messages
TimerTime = BmpCoef2; command = 2;
TimerTime = RetractAnimationFrameTime;
} }
if (soundIndex)
loader::play_sound(soundIndex);
if (Timer)
{
timer::kill(Timer);
Timer = 0;
}
if (MessageField) if (MessageField)
{ {
auto v10 = value - FlipperEdge->InputTime; // Message arrived before animation is finished
timerTime = v10 - floor(v10 / TimerTime) * TimerTime; auto inputDt = value - FlipperEdge->InputTime;
timerTime = inputDt - floor(inputDt / TimerTime) * TimerTime;
if (timerTime < 0.0f) if (timerTime < 0.0f)
timerTime = 0.0; timerTime = 0.0;
} }
@@ -104,10 +99,13 @@ int TFlipper::Message(int code, float value)
{ {
timerTime = TimerTime; timerTime = TimerTime;
} }
MessageField = code2;
MessageField = command;
InputTime = value; InputTime = value;
if (Timer)
timer::kill(Timer);
Timer = timer::set(timerTime, this, TimerExpired); Timer = timer::set(timerTime, this, TimerExpired);
FlipperEdge->SetMotion(code2, value); FlipperEdge->SetMotion(command, value);
} }
if (code == 1020 || code == 1024) if (code == 1020 || code == 1024)
@@ -137,49 +135,43 @@ void TFlipper::Collision(TBall* ball, vector_type* nextPosition, vector_type* di
void TFlipper::TimerExpired(int timerId, void* caller) void TFlipper::TimerExpired(int timerId, void* caller)
{ {
auto flip = static_cast<TFlipper*>(caller); auto flip = static_cast<TFlipper*>(caller);
int timer; // eax int bmpCountSub1 = flip->ListBitmap->GetCount() - 1;
auto newBmpIndex = static_cast<int>(floor((pb::time_now - flip->InputTime) / flip->TimerTime));
if (newBmpIndex > bmpCountSub1)
newBmpIndex = bmpCountSub1;
if (newBmpIndex < 0)
newBmpIndex = 0;
bool bmpIndexOutOfBounds = false; bool bmpIndexOutOfBounds = false;
auto bmpIndexAdvance = static_cast<int>(floor((pb::time_now - flip->InputTime) / flip->TimerTime + 0.5f));
int bmpCount = flip->ListBitmap->GetCount();
if (bmpIndexAdvance > bmpCount)
bmpIndexAdvance = bmpCount;
if (bmpIndexAdvance < 0)
bmpIndexAdvance = 0;
if (!bmpIndexAdvance)
bmpIndexAdvance = 1;
if (flip->MessageField == 1) if (flip->MessageField == 1)
{ {
flip->BmpIndex += bmpIndexAdvance; flip->BmpIndex = newBmpIndex;
int countSub1 = flip->ListBitmap->GetCount() - 1; if (flip->BmpIndex >= bmpCountSub1)
if (flip->BmpIndex >= countSub1)
{ {
flip->BmpIndex = countSub1; flip->BmpIndex = bmpCountSub1;
bmpIndexOutOfBounds = true; bmpIndexOutOfBounds = true;
} }
} }
if (flip->MessageField == 2) if (flip->MessageField == 2)
{ {
flip->BmpIndex -= bmpIndexAdvance; flip->BmpIndex = bmpCountSub1 - newBmpIndex;
timer = 0;
if (flip->BmpIndex <= 0) if (flip->BmpIndex <= 0)
{ {
flip->BmpIndex = 0; flip->BmpIndex = 0;
bmpIndexOutOfBounds = true; bmpIndexOutOfBounds = true;
} }
} }
else
{
timer = 0;
}
if (bmpIndexOutOfBounds) if (bmpIndexOutOfBounds)
{
flip->MessageField = 0; flip->MessageField = 0;
flip->Timer = 0;
}
else else
timer = timer::set(flip->TimerTime, flip, TimerExpired); {
flip->Timer = timer; flip->Timer = timer::set(flip->TimerTime, flip, TimerExpired);
}
auto bmp = flip->ListBitmap->Get(flip->BmpIndex); auto bmp = flip->ListBitmap->Get(flip->BmpIndex);
auto zMap = flip->ListZMap->Get(flip->BmpIndex); auto zMap = flip->ListZMap->Get(flip->BmpIndex);

View File

@@ -19,8 +19,8 @@ public:
int BmpIndex; int BmpIndex;
TFlipperEdge* FlipperEdge; TFlipperEdge* FlipperEdge;
int Timer; int Timer;
float BmpCoef1; float ExtendAnimationFrameTime;
float BmpCoef2; float RetractAnimationFrameTime;
float TimerTime; float TimerTime;
float InputTime; float InputTime;
}; };

View File

@@ -12,15 +12,15 @@ line_type TFlipperEdge::lineA, TFlipperEdge::lineB;
circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1; circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1;
TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table, TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table,
vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2, vector_type* origin, vector_type* vecT1, vector_type* vecT2, float extendTime, float retractTime,
float collMult, float elasticity, float smoothness): TEdgeSegment(collComp, activeFlag, collisionGroup) float collMult, float elasticity, float smoothness): TEdgeSegment(collComp, activeFlag, collisionGroup)
{ {
vector_type crossProd{}, vecDir1{}, vecDir2{}; vector_type crossProd{}, vecDir1{}, vecDir2{};
Elasticity = elasticity; Elasticity = elasticity;
Smoothness = smoothness; Smoothness = smoothness;
BmpCoef1 = bmpCoef1; ExtendTime = extendTime;
BmpCoef2 = bmpCoef2; RetractTime = retractTime;
CollisionMult = collMult; CollisionMult = collMult;
T1Src = *vecT1; T1Src = *vecT1;
@@ -78,9 +78,9 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi
auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z; auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z;
DistanceDivSq = distance1 * distance1; DistanceDivSq = distance1 * distance1;
float bmpCoef = min(BmpCoef1, BmpCoef2); float minMoveTime = min(ExtendTime, RetractTime);
auto distance = maths::Distance(vecT1, vecT2); auto distance = maths::Distance(vecT1, vecT2);
CollisionTimeAdvance = bmpCoef / (distance / CircleT1Radius + distance / CircleT1Radius); CollisionTimeAdvance = minMoveTime / (distance / CircleT1Radius + distance / CircleT1Radius);
TFlipperEdge::place_in_grid(); TFlipperEdge::place_in_grid();
EdgeCollisionFlag = 0; EdgeCollisionFlag = 0;
@@ -469,12 +469,12 @@ void TFlipperEdge::SetMotion(int code, float value)
case 1: case 1:
Angle2 = flipper_angle(value); Angle2 = flipper_angle(value);
Angle1 = AngleMax; Angle1 = AngleMax;
AngleMult = BmpCoef1; AngleMult = ExtendTime;
break; break;
case 2: case 2:
Angle2 = flipper_angle(value); Angle2 = flipper_angle(value);
Angle1 = 0.0; Angle1 = 0.0;
AngleMult = BmpCoef2; AngleMult = RetractTime;
break; break;
case 1024: case 1024:
FlipperFlag = 0; FlipperFlag = 0;

View File

@@ -8,7 +8,7 @@ class TFlipperEdge : public TEdgeSegment
{ {
public: public:
TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table, TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup, TPinballTable* table,
vector_type* origin, vector_type* vecT1, vector_type* vecT2, float bmpCoef1, float bmpCoef2, float collMult, vector_type* origin, vector_type* vecT1, vector_type* vecT2, float extendTime, float retractTime, float collMult,
float elasticity, float smoothness); float elasticity, float smoothness);
void port_draw() override; void port_draw() override;
float FindCollisionDistance(ray_type* ray) override; float FindCollisionDistance(ray_type* ray) override;
@@ -50,8 +50,8 @@ public:
float InputTime; float InputTime;
float AngleStopTime; float AngleStopTime;
float AngleMult; float AngleMult;
float BmpCoef1; float ExtendTime;
float BmpCoef2; float RetractTime;
vector_type NextBallPosition; vector_type NextBallPosition;
static float flipper_sin_angle, flipper_cos_angle; static float flipper_sin_angle, flipper_cos_angle;

View File

@@ -82,7 +82,11 @@ void THole::Collision(TBall* ball, vector_type* nextPosition, vector_type* direc
ball->Position.X = Circle.Center.X; ball->Position.X = Circle.Center.X;
ball->Position.Y = Circle.Center.Y; ball->Position.Y = Circle.Center.Y;
ball->Acceleration.Z = 0.0; ball->Acceleration.Z = 0.0;
Timer = timer::set(0.5f, this, TimerExpired);
// Ramp hole has no delay in FT.
auto captureTime = pb::FullTiltMode ? 0 : 0.5f;
Timer = timer::set(captureTime, this, TimerExpired);
if (!PinballTable->TiltLockFlag) if (!PinballTable->TiltLockFlag)
{ {
loader::play_sound(HardHitSoundId); loader::play_sound(HardHitSoundId);

View File

@@ -5,6 +5,7 @@
#include "control.h" #include "control.h"
#include "loader.h" #include "loader.h"
#include "objlist_class.h" #include "objlist_class.h"
#include "pb.h"
#include "TBall.h" #include "TBall.h"
#include "TCircle.h" #include "TCircle.h"
#include "timer.h" #include "timer.h"
@@ -44,7 +45,8 @@ TKickout::TKickout(TPinballTable* table, int groupIndex, bool someFlag): TCollis
} }
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2]; Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
CollisionBallSetZ = loader::query_float_attribute(groupIndex, 0, 408)[2]; auto zAttr = loader::query_float_attribute(groupIndex, 0, 408);
CollisionBallSetZ = pb::FullTiltMode ? zAttr[3] : zAttr[2];
ThrowSpeedMult2 = visual.Kicker.ThrowBallMult * 0.01f; ThrowSpeedMult2 = visual.Kicker.ThrowBallMult * 0.01f;
BallAcceleration = visual.Kicker.ThrowBallAcceleration; BallAcceleration = visual.Kicker.ThrowBallAcceleration;
ThrowAngleMult = visual.Kicker.ThrowBallAngleMult; ThrowAngleMult = visual.Kicker.ThrowBallAngleMult;

View File

@@ -57,9 +57,8 @@ int TLightBargraph::Message(int code, float value)
TLightGroup::Message(45, static_cast<float>(timeIndex / 2)); TLightGroup::Message(45, static_cast<float>(timeIndex / 2));
if (!(timeIndex & 1)) if (!(timeIndex & 1))
TLightGroup::Message(46, 0.0); TLightGroup::Message(46, 0.0);
float* timeArray = TimerTimeArray; if (TimerTimeArray)
if (timeArray) TimerBargraph = timer::set(TimerTimeArray[timeIndex], this, BargraphTimerExpired);
TimerBargraph = timer::set(timeArray[timeIndex], this, BargraphTimerExpired);
TimeIndex = timeIndex; TimeIndex = timeIndex;
} }
else else

View File

@@ -374,31 +374,21 @@ int TLightGroup::Message(int code, float value)
} }
case 45: case 45:
{ {
auto count = List->GetCount();
control::handler(code, this); control::handler(code, this);
auto index = static_cast<int>(floor(value)); auto index = static_cast<int>(floor(value));
if (index >= 0) if (index >= 0 && index < count)
{ {
auto count = List->GetCount(); // Turn off lights (index, end]
if (index <= count) for (auto i = count - 1; i > index; i--)
{ {
auto countSub1 = count - 1; List->Get(i)->Message(20, 0.0);
if (countSub1 > index) }
{
countSub1 = index; // Turn on lights [begin, index]
for (auto i = countSub1, k = countSub1 - index; k != 0; i--, k--) for (auto i = index; i >= 0; i--)
{ {
auto light = List->Get(i); List->Get(i)->Message(19, 0.0);
light->Message(20, 0.0);
}
}
if (countSub1 >= 0)
{
for (auto i = countSub1; i != 0; i--)
{
auto light = List->Get(i);
light->Message(19, 0.0);
}
}
} }
} }
break; break;
@@ -477,7 +467,7 @@ int TLightGroup::next_light_down()
{ {
for (int index = List->GetCount() - 1; index >= 0; --index) for (int index = List->GetCount() - 1; index >= 0; --index)
{ {
if (!List->Get(index)->BmpIndex1) if (List->Get(index)->BmpIndex1)
return index; return index;
} }
return -1; return -1;

View File

@@ -303,7 +303,7 @@ void TPinballTable::tilt(float time)
{ {
pinball::InfoTextBox->Clear(); pinball::InfoTextBox->Clear();
pinball::MissTextBox->Clear(); pinball::MissTextBox->Clear();
pinball::InfoTextBox->Display(pinball::get_rc_string(35, 0), -1.0); pinball::InfoTextBox->Display(pinball::get_rc_Wstring(35, 0), -1.0);
loader::play_sound(SoundIndex3); loader::play_sound(SoundIndex3);
TiltTimeoutTimer = timer::set(30.0, this, tilt_timeout); TiltTimeoutTimer = timer::set(30.0, this, tilt_timeout);
@@ -328,7 +328,7 @@ void TPinballTable::port_draw()
int TPinballTable::Message(int code, float value) int TPinballTable::Message(int code, float value)
{ {
LPSTR rc_text; LPWSTR rc_text;
switch (code) switch (code)
{ {
case 1000: case 1000:
@@ -382,9 +382,9 @@ int TPinballTable::Message(int code, float value)
LightGroup->Message(20, 0.0); LightGroup->Message(20, 0.0);
Plunger->Message(1016, 0.0); Plunger->Message(1016, 0.0);
if (Demo->ActiveFlag) if (Demo->ActiveFlag)
rc_text = pinball::get_rc_string(30, 0); rc_text = pinball::get_rc_Wstring(30, 0);
else else
rc_text = pinball::get_rc_string(26, 0); rc_text = pinball::get_rc_Wstring(26, 0);
pinball::InfoTextBox->Display(rc_text, -1.0); pinball::InfoTextBox->Display(rc_text, -1.0);
if (Demo) if (Demo)
Demo->Message(1014, 0.0); Demo->Message(1014, 0.0);
@@ -477,11 +477,11 @@ int TPinballTable::Message(int code, float value)
{ {
if (PlayerCount <= 1) if (PlayerCount <= 1)
{ {
char* textboxText; wchar_t* textboxText;
if (Demo->ActiveFlag) if (Demo->ActiveFlag)
textboxText = pinball::get_rc_string(30, 0); textboxText = pinball::get_rc_Wstring(30, 0);
else else
textboxText = pinball::get_rc_string(26, 0); textboxText = pinball::get_rc_Wstring(26, 0);
pinball::InfoTextBox->Display(textboxText, -1.0); pinball::InfoTextBox->Display(textboxText, -1.0);
break; break;
} }
@@ -518,32 +518,32 @@ int TPinballTable::Message(int code, float value)
ComponentList->Get(i)->Message(1020, static_cast<float>(nextPlayer)); ComponentList->Get(i)->Message(1020, static_cast<float>(nextPlayer));
} }
char* textboxText = nullptr; wchar_t* textboxText = nullptr;
switch (nextPlayer) switch (nextPlayer)
{ {
case 0: case 0:
if (Demo->ActiveFlag) if (Demo->ActiveFlag)
textboxText = pinball::get_rc_string(30, 0); textboxText = pinball::get_rc_Wstring(30, 0);
else else
textboxText = pinball::get_rc_string(26, 0); textboxText = pinball::get_rc_Wstring(26, 0);
break; break;
case 1: case 1:
if (Demo->ActiveFlag) if (Demo->ActiveFlag)
textboxText = pinball::get_rc_string(31, 0); textboxText = pinball::get_rc_Wstring(31, 0);
else else
textboxText = pinball::get_rc_string(27, 0); textboxText = pinball::get_rc_Wstring(27, 0);
break; break;
case 2: case 2:
if (Demo->ActiveFlag) if (Demo->ActiveFlag)
textboxText = pinball::get_rc_string(32, 0); textboxText = pinball::get_rc_Wstring(32, 0);
else else
textboxText = pinball::get_rc_string(28, 0); textboxText = pinball::get_rc_Wstring(28, 0);
break; break;
case 3: case 3:
if (Demo->ActiveFlag) if (Demo->ActiveFlag)
textboxText = pinball::get_rc_string(33, 0); textboxText = pinball::get_rc_Wstring(33, 0);
else else
textboxText = pinball::get_rc_string(29, 0); textboxText = pinball::get_rc_Wstring(29, 0);
break; break;
default: default:
break; break;
@@ -560,7 +560,7 @@ int TPinballTable::Message(int code, float value)
case 1022: case 1022:
loader::play_sound(SoundIndex2); loader::play_sound(SoundIndex2);
pinball::MissTextBox->Clear(); pinball::MissTextBox->Clear();
pinball::InfoTextBox->Display(pinball::get_rc_string(34, 0), -1.0); pinball::InfoTextBox->Display(pinball::get_rc_Wstring(34, 0), -1.0);
EndGameTimeoutTimer = timer::set(3.0, this, EndGame_timeout); EndGameTimeoutTimer = timer::set(3.0, this, EndGame_timeout);
break; break;
case 1024: case 1024:
@@ -615,7 +615,7 @@ void TPinballTable::EndGame_timeout(int timerId, void* caller)
if (table->Demo) if (table->Demo)
table->Demo->Message(1022, 0.0); table->Demo->Message(1022, 0.0);
control::handler(67, pinball::MissTextBox); control::handler(67, pinball::MissTextBox);
pinball::InfoTextBox->Display(pinball::get_rc_string(24, 0), -1.0); pinball::InfoTextBox->Display(pinball::get_rc_Wstring(24, 0), -1.0);
} }
void TPinballTable::LightShow_timeout(int timerId, void* caller) void TPinballTable::LightShow_timeout(int timerId, void* caller)

View File

@@ -109,12 +109,12 @@ void TTextBox::Clear()
} }
} }
void TTextBox::Display(char* text, float time) void TTextBox::Display(const wchar_t* text, float time)
{ {
if (!text) if (!text)
return; return;
if (Message1 && !strcmp(text, Message2->Text)) if (Message1 && !lstrcmpW(text, Message2->Text))
{ {
Message2->Refresh(time); Message2->Refresh(time);
if (Message2 == Message1) if (Message2 == Message1)
@@ -153,7 +153,7 @@ void TTextBox::Display(char* text, float time)
} }
} }
void TTextBox::Draw() void TTextBox::Draw(bool redraw)
{ {
auto bmp = BgBmp; auto bmp = BgBmp;
if (bmp) if (bmp)
@@ -172,6 +172,12 @@ void TTextBox::Draw()
bool display = false; bool display = false;
while (Message1) while (Message1)
{ {
if (redraw)
{
display = true;
break;
}
if (Message1->Time == -1.0f) if (Message1->Time == -1.0f)
{ {
if (!Message1->NextMessage) if (!Message1->NextMessage)
@@ -183,6 +189,8 @@ void TTextBox::Draw()
} }
else if (Message1->TimeLeft() >= -2.0f) else if (Message1->TimeLeft() >= -2.0f)
{ {
if (Timer > 0)
timer::kill(Timer);
Timer = timer::set(max(Message1->TimeLeft(), 0.25f), this, TimerExpired); Timer = timer::set(max(Message1->TimeLeft(), 0.25f), this, TimerExpired);
display = true; display = true;
break; break;
@@ -211,8 +219,7 @@ void TTextBox::Draw()
render::vscreen.XPosition + OffsetX, render::vscreen.XPosition + OffsetX,
render::vscreen.YPosition + OffsetY, render::vscreen.YPosition + OffsetY,
Width, Width,
Height, Height);
255);
return; return;
} }
@@ -224,7 +231,7 @@ void TTextBox::Draw()
break; break;
auto totalWidth = 0; auto totalWidth = 0;
char* textEndSpace = nullptr; wchar_t* textEndSpace = nullptr;
auto textEnd = text; auto textEnd = text;
while (true) while (true)
{ {

View File

@@ -21,8 +21,8 @@ public:
~TTextBox() override; ~TTextBox() override;
int Message(int code, float value) override; int Message(int code, float value) override;
void Clear(); void Clear();
void Display(char* text, float time); void Display(const wchar_t* text, float time);
void Draw(); void Draw(bool redraw = false);
static void TimerExpired(int timerId, void* tb); static void TimerExpired(int timerId, void* tb);
}; };

View File

@@ -3,17 +3,17 @@
#include "memory.h" #include "memory.h"
#include "pb.h" #include "pb.h"
TTextBoxMessage::TTextBoxMessage(char* text, float time) TTextBoxMessage::TTextBoxMessage(const wchar_t* text, float time)
{ {
NextMessage = nullptr; NextMessage = nullptr;
Time = time; Time = time;
EndTicks = pb::time_ticks + static_cast<int>(time * 1000.0f); EndTicks = pb::time_ticks + static_cast<int>(time * 1000.0f);
if (text) if (text)
{ {
const auto textLen = strlen(text) + 1; const auto textLen = lstrlenW(text) + 1;
Text = memory::allocate(textLen); Text = memory::allocate<wchar_t>(textLen);
if (Text) if (Text)
strcpy_s(Text, textLen, text); lstrcpynW(Text, text, textLen);
} }
else else
Text = nullptr; Text = nullptr;

View File

@@ -3,11 +3,11 @@ class TTextBoxMessage
{ {
public: public:
TTextBoxMessage* NextMessage; TTextBoxMessage* NextMessage;
char* Text; wchar_t* Text;
float Time; float Time;
int EndTicks; int EndTicks;
TTextBoxMessage(char* text, float time); TTextBoxMessage(const wchar_t* text, float time);
~TTextBoxMessage(); ~TTextBoxMessage();
float TimeLeft() const; float TimeLeft() const;
void Refresh(float time); void Refresh(float time);

File diff suppressed because it is too large Load Diff

View File

@@ -65,14 +65,15 @@ public:
static TPinballTable* TableG; static TPinballTable* TableG;
static component_info score_components[88]; static component_info score_components[88];
static component_tag_base* simple_components[142]; static component_tag_base* simple_components[142];
static int table_unlimited_balls, waiting_deployment_flag; static int waiting_deployment_flag;
static bool table_unlimited_balls;
static int RankRcArray[9], MissionRcArray[17], mission_select_scores[17]; static int RankRcArray[9], MissionRcArray[17], mission_select_scores[17];
static component_tag_base *wormhole_tag_array1[3], *wormhole_tag_array2[3], *wormhole_tag_array3[3]; static component_tag_base *wormhole_tag_array1[3], *wormhole_tag_array2[3], *wormhole_tag_array3[3];
static void make_links(TPinballTable* table); static void make_links(TPinballTable* table);
static TPinballComponent* make_component_link(component_tag_base* tag); static TPinballComponent* make_component_link(component_tag_base* tag);
static void handler(int code, TPinballComponent* cmp); static void handler(int code, TPinballComponent* cmp);
static void pbctrl_bdoor_controller(int key); static void pbctrl_bdoor_controller(char key);
static void table_add_extra_ball(float count); static void table_add_extra_ball(float count);
static void table_set_bonus_hold(); static void table_set_bonus_hold();
static void table_set_bonus(); static void table_set_bonus();
@@ -81,7 +82,7 @@ public:
static void table_set_multiball(); static void table_set_multiball();
static void table_bump_ball_sink_lock(); static void table_bump_ball_sink_lock();
static void table_set_replay(float value); 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 bool light_on(component_tag<TLight>* tag);
static int SpecialAddScore(int score); static int SpecialAddScore(int score);
static int AddRankProgress(int rank); static int AddRankProgress(int rank);
@@ -182,6 +183,5 @@ public:
static void UnselectMissionController(int code, TPinballComponent* caller); static void UnselectMissionController(int code, TPinballComponent* caller);
static void WaitingDeploymentController(int code, TPinballComponent* caller); static void WaitingDeploymentController(int code, TPinballComponent* caller);
private: private:
static int pbctrl_state;
static int extraball_light_flag; static int extraball_light_flag;
}; };

View File

@@ -28,8 +28,8 @@ const resolution_info fullscrn::resolution_array[3] =
}; };
float fullscrn::ScaleX = 1; float fullscrn::ScaleX = 1;
float fullscrn::ScaleY = 1; float fullscrn::ScaleY = 1;
float fullscrn::OffsetX = 0; int fullscrn::OffsetX = 0;
float fullscrn::OffsetY = 0; int fullscrn::OffsetY = 0;
void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay) void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay)
{ {
@@ -377,7 +377,7 @@ void fullscrn::paint()
fillRect(WindowRect1.right, menuHeight + WindowRect1.bottom, 0, 0); fillRect(WindowRect1.right, menuHeight + WindowRect1.bottom, 0, 0);
} }
} }
render::paint(); pb::paint();
fullscrn_flag1 = 0; fullscrn_flag1 = 0;
} }
@@ -450,13 +450,7 @@ void fullscrn::window_size_changed()
if (options::Options.UniformScaling) if (options::Options.UniformScaling)
{ {
ScaleY = ScaleX = min(ScaleX, ScaleY); ScaleY = ScaleX = min(ScaleX, ScaleY);
OffsetX = floor((client.right - res->TableWidth * ScaleX) / 2); OffsetX = static_cast<int>(floor((client.right - res->TableWidth * ScaleX) / 2));
OffsetY = floor((client.bottom - res->TableHeight * ScaleY) / 2); OffsetY = static_cast<int>(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

@@ -30,8 +30,8 @@ public:
static const resolution_info resolution_array[3]; static const resolution_info resolution_array[3];
static float ScaleX; static float ScaleX;
static float ScaleY; static float ScaleY;
static float OffsetX; static int OffsetX;
static float OffsetY; static int OffsetY;
static void init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay); static void init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay);
static void shutdown(); static void shutdown();

View File

@@ -3,6 +3,7 @@
#include "fullscrn.h" #include "fullscrn.h"
#include "memory.h" #include "memory.h"
#include "options.h"
#include "pinball.h" #include "pinball.h"
#include "winmain.h" #include "winmain.h"
@@ -287,7 +288,7 @@ void gdrv::end_blit_sequence()
ReleaseDC(hwnd, sequence_hdc); ReleaseDC(hwnd, sequence_hdc);
} }
void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, int DestHeight) void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrc, int xDest, int yDest, int DestWidth, int DestHeight)
{ {
HDC dc = winmain::_GetDC(hwnd); HDC dc = winmain::_GetDC(hwnd);
SetStretchBltMode(dc, stretchMode); SetStretchBltMode(dc, stretchMode);
@@ -303,7 +304,7 @@ void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest,
DestWidth, DestWidth,
DestHeight, DestHeight,
xSrc, xSrc,
bmp->Height - ySrcOff - DestHeight, bmp->Height - ySrc - DestHeight,
DestWidth, DestWidth,
DestHeight, DestHeight,
bmp, bmp,
@@ -317,6 +318,25 @@ void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest,
void gdrv::blat(gdrv_bitmap8* bmp, int xDest, int yDest) void gdrv::blat(gdrv_bitmap8* bmp, int xDest, int yDest)
{ {
HDC dc = winmain::_GetDC(hwnd); HDC dc = winmain::_GetDC(hwnd);
// Black background for uniform scaling
if (fullscrn::OffsetX > 0 || fullscrn::OffsetY > 0)
{
const auto rop = BLACKNESS;
RECT client{};
GetClientRect(hwnd, &client);
if (fullscrn::OffsetX > 0)
{
BitBlt(dc, 0, 0, min(fullscrn::OffsetX + 2, client.right), client.bottom, dc, 0, 0, rop);
BitBlt(dc, max(client.right - fullscrn::OffsetX - 2, 0), 0, client.right, client.bottom, dc, 0, 0, rop);
}
else
{
BitBlt(dc, 0, 0, client.right, min(fullscrn::OffsetY + 2, client.bottom), dc, 0, 0, rop);
BitBlt(dc, 0, max(client.bottom - fullscrn::OffsetY - 2, 0), client.right, client.bottom, dc, 0, 0, rop);
}
}
SelectPalette(dc, palette_handle, 0); SelectPalette(dc, palette_handle, 0);
RealizePalette(dc); RealizePalette(dc);
SetStretchBltMode(dc, stretchMode); SetStretchBltMode(dc, stretchMode);
@@ -394,11 +414,24 @@ void gdrv::copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int heigh
} }
void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6) void gdrv::grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, int height)
{ {
tagRECT rc{}; // Original font was 16 points, used with lowest table resolution
static const int fontSizes[3] =
{
16,
22,
28
};
xOff = static_cast<int>(xOff * fullscrn::ScaleX) + fullscrn::OffsetX;
yOff = static_cast<int>(yOff * fullscrn::ScaleY) + fullscrn::OffsetY;
width = static_cast<int>(width * fullscrn::ScaleX);
height = static_cast<int>(height * fullscrn::ScaleY);
auto fontSize = static_cast<int>(round(fontSizes[fullscrn::GetResolution()] * fullscrn::ScaleY));
HDC dc = GetDC(hwnd); HDC dc = GetDC(hwnd);
tagRECT rc{};
rc.left = xOff; rc.left = xOff;
rc.right = width + xOff; rc.right = width + xOff;
rc.top = yOff; rc.top = yOff;
@@ -412,9 +445,38 @@ void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width,
if (fontColor) if (fontColor)
sscanf_s(fontColor, "%d %d %d", &grtext_red, &grtext_green, &grtext_blue); sscanf_s(fontColor, "%d %d %d", &grtext_red, &grtext_green, &grtext_blue);
} }
int prevMode = SetBkMode(dc, 1);
const char* font;
switch (options::Options.Language)
{
case Languages::TraditionalChinese:
font = "Microsoft JhengHei";
break;
case Languages::SimplifiedChinese:
font = "Microsoft YaHei";
break;
case Languages::Japanese:
font = "MS UI Gothic";
break;
case Languages::Korean:
font = "Gulim";
break;
default:
font = "Arial";
}
// Default font does not scale well
auto hNewFont = CreateFont(fontSize, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS, font);
HFONT hOldFont = static_cast<HFONT>(SelectObject(dc, hNewFont));
int prevMode = SetBkMode(dc, TRANSPARENT);
COLORREF color = SetTextColor(dc, grtext_red | grtext_green << 8 | grtext_blue << 16); COLORREF color = SetTextColor(dc, grtext_red | grtext_green << 8 | grtext_blue << 16);
DrawTextA(dc, text, lstrlenA(text), &rc, 0x810u);
DrawTextW(dc, text, lstrlenW(text), &rc, DT_NOPREFIX | DT_WORDBREAK);
SelectObject(dc, hOldFont);
DeleteObject(hNewFont);
SetBkMode(dc, prevMode); SetBkMode(dc, prevMode);
SetTextColor(dc, color); SetTextColor(dc, color);
ReleaseDC(hwnd, dc); ReleaseDC(hwnd, dc);

View File

@@ -64,7 +64,7 @@ public:
int srcXOff, int srcYOff); int srcXOff, int srcYOff);
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff); 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); static void grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, int height);
private: private:
/*COLORONCOLOR or HALFTONE*/ /*COLORONCOLOR or HALFTONE*/
static const int stretchMode = COLORONCOLOR; static const int stretchMode = COLORONCOLOR;

View File

@@ -10,7 +10,7 @@
int high_score::dlg_enter_name; int high_score::dlg_enter_name;
int high_score::dlg_score; int high_score::dlg_score;
int high_score::dlg_position; int high_score::dlg_position;
LPCSTR high_score::default_name; LPCWSTR high_score::default_name;
high_score_struct* high_score::dlg_hst; high_score_struct* high_score::dlg_hst;
winhelp_entry high_score::help[21] winhelp_entry high_score::help[21]
@@ -40,7 +40,8 @@ winhelp_entry high_score::help[21]
int high_score::read(high_score_struct* table, int* ptrToSmth) int high_score::read(high_score_struct* table, int* ptrToSmth)
{ {
char Buffer[20]; char scoreBuffer[20];
wchar_t nameBuffer[20];
int scoreSum = 0; int scoreSum = 0;
clear_table(table); clear_table(table);
@@ -52,18 +53,17 @@ int high_score::read(high_score_struct* table, int* ptrToSmth)
for (auto position = 0; position < 5; ++position) for (auto position = 0; position < 5; ++position)
{ {
auto tablePtr = &table[position]; auto tablePtr = &table[position];
_itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Name"); wsprintfW(nameBuffer, L"%d.Name", position);
options::get_string(optPath, Buffer, buf1, "", 32); options::get_string(optPath, nameBuffer, tablePtr->Name, L"", 32);
buf1[32] = 0; tablePtr->Name[31] = 0;
lstrcpyA(tablePtr->Name, buf1);
_itoa_s(position, Buffer, 10); sprintf_s(scoreBuffer, "%d.Score", position);
lstrcatA(Buffer, ".Score"); options::get_string(optPath, scoreBuffer, buf1, "", 300);
options::get_string(optPath, Buffer, buf1, "", 300);
tablePtr->Score = atol(buf1); tablePtr->Score = atol(buf1);
for (int i = lstrlenA(tablePtr->Name); --i >= 0; scoreSum += tablePtr->Name[i])
{ for (auto i = lstrlenW(tablePtr->Name) - 1; i >= 0; i--)
} scoreSum += tablePtr->Name[i];
scoreSum += tablePtr->Score; scoreSum += tablePtr->Score;
} }
@@ -78,30 +78,30 @@ int high_score::read(high_score_struct* table, int* ptrToSmth)
int high_score::write(high_score_struct* table, int* ptrToSmth) int high_score::write(high_score_struct* table, int* ptrToSmth)
{ {
char Buffer[20]; char scoreBuffer[20];
wchar_t nameBuffer[20];
high_score_struct* tablePtr = table;
int scoreSum = 0; int scoreSum = 0;
CHAR* buf = memory::allocate(300u); CHAR* buf = memory::allocate(300u);
if (!buf) if (!buf)
return 1; return 1;
const CHAR* optPath = pinball::get_rc_string(166, 0); auto optPath = pinball::get_rc_string(166, 0);
for (auto position = 0; position < 5; ++position) for (auto position = 0; position < 5; ++position)
{ {
_itoa_s(position, Buffer, 10); auto tablePtr = &table[position];
lstrcatA(Buffer, ".Name");
options::set_string(optPath, Buffer, tablePtr->Name); wsprintfW(nameBuffer, L"%d.Name", position);
_itoa_s(position, Buffer, 10); options::set_string(optPath, nameBuffer, tablePtr->Name);
lstrcatA(Buffer, ".Score");
sprintf_s(scoreBuffer, "%d.Score", position);
_ltoa_s(tablePtr->Score, buf, 300, 10); _ltoa_s(tablePtr->Score, buf, 300, 10);
options::set_string(optPath, Buffer, buf); options::set_string(optPath, scoreBuffer, buf);
for (int i = lstrlenA(tablePtr->Name); --i >= 0; scoreSum += tablePtr->Name[i])
{ for (auto i = lstrlenW(tablePtr->Name) - 1; i >= 0; i--)
} scoreSum += tablePtr->Name[i];
scoreSum += tablePtr->Score; scoreSum += tablePtr->Score;
++position;
++tablePtr;
} }
scramble_number_string(scoreSum, buf); scramble_number_string(scoreSum, buf);
options::set_string(optPath, "Verification", buf); options::set_string(optPath, "Verification", buf);
memory::free(buf); memory::free(buf);
@@ -131,7 +131,7 @@ int high_score::get_score_position(high_score_struct* table, int score)
return -1; return -1;
} }
int high_score::place_new_score_into(high_score_struct* table, int score, LPSTR scoreStr, int position) int high_score::place_new_score_into(high_score_struct* table, int score, LPWSTR name, int position)
{ {
if (position >= 0) if (position >= 0)
{ {
@@ -149,9 +149,9 @@ int high_score::place_new_score_into(high_score_struct* table, int score, LPSTR
} }
high_score_struct* posTable = &table[position]; high_score_struct* posTable = &table[position];
posTable->Score = score; posTable->Score = score;
if (lstrlenA(scoreStr) >= 31) if (lstrlenW(name) >= 31)
scoreStr[31] = 0; name[31] = 0;
lstrcpyA(posTable->Name, scoreStr); lstrcpyW(posTable->Name, name);
posTable->Name[31] = 0; posTable->Name[31] = 0;
} }
return position; return position;
@@ -167,17 +167,17 @@ void high_score::show_high_score_dialog(high_score_struct* table)
dlg_enter_name = 0; dlg_enter_name = 0;
dlg_score = 0; dlg_score = 0;
dlg_hst = table; dlg_hst = table;
DialogBoxParamA(winmain::hinst, "dlg_highscores", winmain::hwnd_frame, HighScore, 0); DialogBoxParamW(winmain::hinst, L"dlg_highscores", winmain::hwnd_frame, HighScore, 0);
} }
void high_score::show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCSTR defaultName) void high_score::show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCWSTR defaultName)
{ {
dlg_position = pos; dlg_position = pos;
dlg_score = score; dlg_score = score;
dlg_hst = table; dlg_hst = table;
dlg_enter_name = 1; dlg_enter_name = 1;
default_name = defaultName; default_name = defaultName;
while (DialogBoxParamA(winmain::hinst, "dlg_highscores", winmain::hwnd_frame, HighScore, 0)) while (DialogBoxParamW(winmain::hinst, L"dlg_highscores", winmain::hwnd_frame, HighScore, 0))
{ {
} }
} }
@@ -186,8 +186,7 @@ INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
HWND parent; HWND parent;
int nIDDlgItem; int nIDDlgItem;
CHAR String1[256]; wchar_t name[32];
CHAR name[32];
switch (msg) switch (msg)
{ {
@@ -205,7 +204,7 @@ INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
show_high_scores(hWnd, dlg_hst); show_high_scores(hWnd, dlg_hst);
for (nIDDlgItem = DLG_HIGHSCORES_EditName1; nIDDlgItem < 611; ++nIDDlgItem) for (nIDDlgItem = DLG_HIGHSCORES_EditName1; nIDDlgItem < 611; ++nIDDlgItem)
{ {
ShowWindow(GetDlgItem(hWnd, nIDDlgItem), 0); ShowWindow(GetDlgItem(hWnd, nIDDlgItem), SW_HIDE);
} }
if (dlg_enter_name == 1) if (dlg_enter_name == 1)
{ {
@@ -215,12 +214,12 @@ INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
return 1; return 1;
} }
HWND nameTextBox = GetDlgItem(hWnd, dlg_position + DLG_HIGHSCORES_EditName1); HWND nameTextBox = GetDlgItem(hWnd, dlg_position + DLG_HIGHSCORES_EditName1);
ShowWindow(nameTextBox, 5); ShowWindow(nameTextBox, SW_SHOW);
EnableWindow(nameTextBox, 1); EnableWindow(nameTextBox, 1);
SetFocus(nameTextBox); SetFocus(nameTextBox);
if (default_name) if (default_name)
{ {
SetWindowTextA(nameTextBox, default_name); SetWindowTextW(nameTextBox, default_name);
SendMessageA(nameTextBox, EM_SETSEL, 0, -1); SendMessageA(nameTextBox, EM_SETSEL, 0, -1);
} }
SendMessageA(nameTextBox, EM_SETLIMITTEXT, 31u, 0); SendMessageA(nameTextBox, EM_SETLIMITTEXT, 31u, 0);
@@ -241,15 +240,15 @@ INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
break; break;
} }
GetDlgItemTextA(hWnd, dlg_position + DLG_HIGHSCORES_EditName1, name, 32); GetDlgItemTextW(hWnd, dlg_position + DLG_HIGHSCORES_EditName1, name, 32);
name[31] = 0; name[31] = 0;
place_new_score_into(dlg_hst, dlg_score, name, dlg_position); place_new_score_into(dlg_hst, dlg_score, name, dlg_position);
break; break;
case DLG_HIGHSCORES_Cancel: case DLG_HIGHSCORES_Cancel:
break; break;
case DLG_HIGHSCORES_Clear: case DLG_HIGHSCORES_Clear:
lstrcpyA(String1, pinball::get_rc_string(41, 0)); if (MessageBoxW(hWnd, pinball::get_rc_Wstring(40, 0),
if (MessageBoxA(hWnd, pinball::get_rc_string(40, 0), String1, MB_DEFBUTTON2 | MB_OKCANCEL) == 1) pinball::get_rc_Wstring(41, 0), MB_DEFBUTTON2 | MB_OKCANCEL) == 1)
{ {
clear_table(dlg_hst); clear_table(dlg_hst);
if (dlg_enter_name) if (dlg_enter_name)
@@ -278,7 +277,7 @@ void high_score::show_high_scores(HWND hDlg, high_score_struct* table)
{ {
if (dlg_enter_name == 1 && dlg_position == i) if (dlg_enter_name == 1 && dlg_position == i)
{ {
hsdlg_show_score(hDlg, " ", dlg_score, i); hsdlg_show_score(hDlg, L" ", dlg_score, i);
nextPosition = 1; nextPosition = 1;
} }
hsdlg_show_score(hDlg, tablePtr->Name, tablePtr->Score, i + nextPosition); hsdlg_show_score(hDlg, tablePtr->Name, tablePtr->Score, i + nextPosition);
@@ -286,7 +285,7 @@ void high_score::show_high_scores(HWND hDlg, high_score_struct* table)
} }
} }
void high_score::hsdlg_show_score(HWND hDlg, LPCSTR name, int score, int position) void high_score::hsdlg_show_score(HWND hDlg, LPCWSTR name, int score, int position)
{ {
CHAR scoreStr[36]; CHAR scoreStr[36];
if (position < 5) if (position < 5)
@@ -294,7 +293,7 @@ void high_score::hsdlg_show_score(HWND hDlg, LPCSTR name, int score, int positio
score::string_format(score, scoreStr); score::string_format(score, scoreStr);
if (scoreStr[0]) if (scoreStr[0])
{ {
SetWindowTextA(GetDlgItem(hDlg, position + DLG_HIGHSCORES_StaticName1), name); SetWindowTextW(GetDlgItem(hDlg, position + DLG_HIGHSCORES_StaticName1), name);
SetWindowTextA(GetDlgItem(hDlg, position + DLG_HIGHSCORES_Score1), scoreStr); SetWindowTextA(GetDlgItem(hDlg, position + DLG_HIGHSCORES_Score1), scoreStr);
} }
} }

View File

@@ -3,7 +3,7 @@
struct high_score_struct struct high_score_struct
{ {
char Name[32]; wchar_t Name[32];
int Score; int Score;
}; };
@@ -15,19 +15,19 @@ public:
static int write(high_score_struct* table, int* ptrToSmth); static int write(high_score_struct* table, int* ptrToSmth);
static void clear_table(high_score_struct* table); static void clear_table(high_score_struct* table);
static int get_score_position(high_score_struct* table, int score); static int get_score_position(high_score_struct* table, int score);
static int place_new_score_into(high_score_struct* table, int score, LPSTR scoreStr, int position); static int place_new_score_into(high_score_struct* table, int score, LPWSTR name, int position);
static void scramble_number_string(int Value, char* Buffer); static void scramble_number_string(int Value, char* Buffer);
static void show_high_score_dialog(high_score_struct* table); static void show_high_score_dialog(high_score_struct* table);
static void show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCSTR defaultName); static void show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCWSTR defaultName);
static INT_PTR __stdcall HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static INT_PTR __stdcall HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static void show_high_scores(HWND hDlg, high_score_struct* table); static void show_high_scores(HWND hDlg, high_score_struct* table);
static void hsdlg_show_score(HWND hDlg, LPCSTR name, int score, int position); static void hsdlg_show_score(HWND hDlg, LPCWSTR name, int score, int position);
private : private :
static int dlg_enter_name; static int dlg_enter_name;
static int dlg_score; static int dlg_score;
static int dlg_position; static int dlg_position;
static LPCSTR default_name; static LPCWSTR default_name;
static high_score_struct* dlg_hst; static high_score_struct* dlg_hst;
static winhelp_entry help[21]; static winhelp_entry help[21];
}; };

View File

@@ -1,4 +1,4 @@
#include "pch.h" #include "pch.h"
#include "options.h" #include "options.h"
#include "fullscrn.h" #include "fullscrn.h"
@@ -68,9 +68,36 @@ short options::vk_list[28]
-1 -1
}; };
void options::init(HMENU menuHandle) LanguageMenuEntry options::LanguageMenu[]
{
{L"English", Languages::English},
{L"Русский", Languages::Russian},
{L"简化字", Languages::SimplifiedChinese},
{L"正體字", Languages::TraditionalChinese},
{L"Polski", Languages::Polish},
{L"Deutsch", Languages::German},
{L"日本", Languages::Japanese},
{L"Français", Languages::French},
{L"Italiano", Languages::Italian},
{L"Magyar", Languages::Hungarian},
{L"Português", Languages::Portuguese},
{L"Português do Brasil", Languages::BrazilianPortuguese},
{L"Čeština", Languages::Czech},
{L"Dansk", Languages::Danish},
{L"Suomi", Languages::Finnish},
{L"עִברִית", Languages::Hebrew},
{L"اَلْعَرَبِيَّة", Languages::Arabic},
{L"Ελληνικά", Languages::Greek},
{L"Español", Languages::Spanish},
{L"한국어", Languages::Korean},
{L"Nederlands", Languages::Dutch},
{L"Norsk", Languages::Norwegian},
{L"Svenska", Languages::Swedish},
{L"Türkçe", Languages::Turkish},
};
void options::ReadOptions()
{ {
MenuHandle = menuHandle;
Options.Sounds = 1; Options.Sounds = 1;
Options.Music = 0; Options.Music = 0;
Options.FullScreen = 0; Options.FullScreen = 0;
@@ -108,6 +135,47 @@ void options::init(HMENU menuHandle)
Options.RightTableBumpKey = get_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey); Options.RightTableBumpKey = get_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey);
Options.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey); Options.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
Options.UniformScaling = get_int(nullptr, "Uniform scaling", true); Options.UniformScaling = get_int(nullptr, "Uniform scaling", true);
Options.AlternativeRender = get_int(nullptr, "Alternative Render", false);
auto defaultLanguage = Languages::English;
auto language = static_cast<Languages>(get_int(nullptr, "Language", static_cast<int>(defaultLanguage)));
bool languageDefined = false;
for (auto menuEntry : LanguageMenu)
{
if (menuEntry.Language == language)
{
languageDefined = true;
break;
}
}
if (!languageDefined)
language = defaultLanguage;
Options.Language = language;
// Alternative approaches: resource DLLs, single-language builds.
// SetThreadUILanguage does not work properly on Windows XP.
bool winXp = false;
OSVERSIONINFO version{};
version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
#pragma warning (disable : 4996) // XP has no versionhelpers.h
if (GetVersionEx(&version))
#pragma warning (default : 4996)
{
if (version.dwMajorVersion < 6)
winXp = true;
}
if (winXp)
SetThreadLocale(MAKELCID(static_cast<LANGID>(Options.Language), SORT_DEFAULT));
else
SetThreadUILanguage(static_cast<LANGID>(Options.Language));
}
void options::init(HMENU menuHandle)
{
MenuHandle = menuHandle;
menu_check(Menu1_Sounds, Options.Sounds); menu_check(Menu1_Sounds, Options.Sounds);
Sound::Enable(0, 7, Options.Sounds); Sound::Enable(0, 7, Options.Sounds);
menu_check(Menu1_Music, Options.Music); menu_check(Menu1_Music, Options.Music);
@@ -117,6 +185,7 @@ void options::init(HMENU menuHandle)
menu_check(Menu1_3Players, Options.Players == 3); menu_check(Menu1_3Players, Options.Players == 3);
menu_check(Menu1_4Players, Options.Players == 4); menu_check(Menu1_4Players, Options.Players == 4);
menu_check(Menu1_WindowUniformScale, Options.UniformScaling); menu_check(Menu1_WindowUniformScale, Options.UniformScaling);
menu_check(Menu1_AlternativeRender, Options.AlternativeRender);
auto tmpBuf = memory::allocate(0x1F4u); auto tmpBuf = memory::allocate(0x1F4u);
if (tmpBuf) if (tmpBuf)
{ {
@@ -133,6 +202,21 @@ void options::init(HMENU menuHandle)
} }
update_resolution_menu(); update_resolution_menu();
// Add language menu from code to decouple it from rc.
// AppendMenuW works with A window
auto hSubmenu = CreatePopupMenu();
auto index = Menu1_Language;
for (auto menuEntry : LanguageMenu)
{
UINT flags = MF_STRING;
if (menuEntry.Language == Options.Language)
flags |= MF_CHECKED;
AppendMenuW(hSubmenu, flags, index++, menuEntry.Name);
}
auto optionsMenu = GetSubMenu(MenuHandle, 1);
AppendMenu(optionsMenu, MF_STRING | MF_POPUP, reinterpret_cast<UINT_PTR>(hSubmenu), "Language");
} }
void options::uninit() void options::uninit()
@@ -149,6 +233,8 @@ void options::uninit()
set_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey); set_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
set_int(nullptr, "Screen Resolution", Options.Resolution); set_int(nullptr, "Screen Resolution", Options.Resolution);
set_int(nullptr, "Uniform scaling", Options.UniformScaling); set_int(nullptr, "Uniform scaling", Options.UniformScaling);
set_int(nullptr, "Alternative Render", Options.AlternativeRender);
set_int(nullptr, "Language", static_cast<int>(Options.Language));
} }
void options::path_init(LPCSTR regPath) void options::path_init(LPCSTR regPath)
@@ -265,6 +351,43 @@ void options::set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value)
path_free(); path_free();
} }
void options::get_string(LPCSTR optPath, LPCWSTR lpValueName, LPWSTR dst, LPCWSTR defaultValue, int iMaxLength)
{
DWORD dwDisposition;
HKEY hKey;
lstrcpynW(dst, defaultValue, iMaxLength);
if (!OptionsRegPath)
return;
auto regPath = path(optPath);
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
{
DWORD bufferSize = iMaxLength * sizeof(wchar_t);
RegQueryValueExW(hKey, lpValueName, nullptr, nullptr, reinterpret_cast<LPBYTE>(dst), &bufferSize);
RegCloseKey(hKey);
}
path_free();
}
void options::set_string(LPCSTR optPath, LPCWSTR lpValueName, LPCWSTR value)
{
DWORD dwDisposition;
HKEY hKey;
if (!OptionsRegPath)
return;
auto regPath = path(optPath);
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
{
DWORD bufferSize = (lstrlenW(value) + 1) * sizeof(wchar_t);
RegSetValueExW(hKey, lpValueName, 0, 1u, LPBYTE(value), bufferSize);
RegCloseKey(hKey);
}
path_free();
}
void options::menu_check(UINT uIDCheckItem, int check) void options::menu_check(UINT uIDCheckItem, int check)
{ {
@@ -343,18 +466,31 @@ void options::toggle(UINT uIDCheckItem)
fullscrn::window_size_changed(); fullscrn::window_size_changed();
fullscrn::paint(); fullscrn::paint();
break; break;
case Menu1_AlternativeRender:
Options.AlternativeRender ^= true;
menu_check(Menu1_AlternativeRender, Options.AlternativeRender);
fullscrn::window_size_changed();
fullscrn::paint();
break;
default: default:
break; break;
} }
if (uIDCheckItem >= Menu1_Language && uIDCheckItem < Menu1_LanguageMax)
{
auto languageId = uIDCheckItem - Menu1_Language;
Options.Language = LanguageMenu[languageId].Language;
winmain::Restart();
}
} }
void options::update_resolution_menu() void options::update_resolution_menu()
{ {
auto maxResolution = fullscrn::get_max_supported_resolution(); auto maxResolution = fullscrn::get_max_supported_resolution();
fullscrn::SetMaxResolution(maxResolution); fullscrn::SetMaxResolution(maxResolution);
const CHAR* maxResText = pinball::get_rc_string(maxResolution + 2030, 0); PCWSTR maxResText = pinball::get_rc_Wstring(maxResolution + 2030, 0);
if (MenuHandle) if (MenuHandle)
ModifyMenuA(MenuHandle, Menu1_MaximumResolution, 0, Menu1_MaximumResolution, maxResText); ModifyMenuW(MenuHandle, Menu1_MaximumResolution, 0, Menu1_MaximumResolution, maxResText);
for (auto resIndex = 0; resIndex < 3; resIndex++) for (auto resIndex = 0; resIndex < 3; resIndex++)
{ {
@@ -387,14 +523,14 @@ void options::init_resolution()
void options::keyboard() void options::keyboard()
{ {
DialogBoxParamA(winmain::hinst, "KEYMAPPER", winmain::hwnd_frame, KeyMapDlgProc, 0); DialogBoxParamW(winmain::hinst, L"KEYMAPPER", winmain::hwnd_frame, KeyMapDlgProc, 0);
} }
INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
char keyName[20]; WCHAR keyName[20];
int keyBindings[6]; int keyBindings[6];
char rcString[256]; WCHAR rcString[256];
switch (msg) switch (msg)
{ {
@@ -418,7 +554,7 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
auto index = 128; auto index = 128;
do do
{ {
if (vkChar == MapVirtualKeyA(index, MAPVK_VK_TO_CHAR)) if (vkChar == MapVirtualKeyW(index, MAPVK_VK_TO_CHAR))
break; break;
++index; ++index;
} }
@@ -455,30 +591,30 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
{ {
if (vk2And || get_vk_key_name(curVK, keyName)) if (vk2And || get_vk_key_name(curVK, keyName))
{ {
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL,CB_INSERTSTRING, -1, (LPARAM)keyName); auto ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL,CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_SETITEMDATA, ind, curVK); SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.LeftFlipperKey) if (curVK == Options.LeftFlipperKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_INSERTSTRING, -1, (LPARAM)keyName); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_SETITEMDATA, ind, curVK); SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.RightFlipperKey) if (curVK == Options.RightFlipperKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_INSERTSTRING, -1, (LPARAM)keyName); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_SETITEMDATA, ind, curVK); SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.PlungerKey) if (curVK == Options.PlungerKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_INSERTSTRING, -1, (LPARAM)keyName); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_SETITEMDATA, ind, curVK); SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.LeftTableBumpKey) if (curVK == Options.LeftTableBumpKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_INSERTSTRING, -1, (LPARAM)keyName); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_SETITEMDATA, ind, curVK); SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.RightTableBumpKey) if (curVK == Options.RightTableBumpKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_INSERTSTRING, -1, (LPARAM)keyName); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_SETITEMDATA, ind, curVK); SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.BottomTableBumpKey) if (curVK == Options.BottomTableBumpKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_SETCURSEL, ind, 0);
} }
} }
} }
@@ -488,18 +624,18 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
{ {
case KEYMAPPER_Ok: case KEYMAPPER_Ok:
{ {
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETCURSEL, 0, 0); auto ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_GETCURSEL, 0, 0);
keyBindings[0] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETITEMDATA, ind, 0)); keyBindings[0] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETCURSEL, 0, 0); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_GETCURSEL, 0, 0);
keyBindings[1] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETITEMDATA, ind, 0)); keyBindings[1] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETCURSEL, 0, 0); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_GETCURSEL, 0, 0);
keyBindings[2] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETITEMDATA, ind, 0)); keyBindings[2] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETCURSEL, 0, 0); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_GETCURSEL, 0, 0);
keyBindings[3] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETITEMDATA, ind, 0)); keyBindings[3] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETCURSEL, 0, 0); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_GETCURSEL, 0, 0);
keyBindings[4] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETITEMDATA, ind, 0)); keyBindings[4] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETCURSEL, 0, 0); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_GETCURSEL, 0, 0);
keyBindings[5] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETITEMDATA, ind, 0)); keyBindings[5] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_GETITEMDATA, ind, 0));
auto sameKeyBound = 0; auto sameKeyBound = 0;
auto index = 1; auto index = 1;
@@ -512,8 +648,8 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
break; break;
if (*optPtr == keyBindings[keyInd]) if (*optPtr == keyBindings[keyInd])
{ {
lstrcpyA(rcString, pinball::get_rc_string(43, 0)); lstrcpyW(rcString, pinball::get_rc_Wstring(43, 0));
MessageBoxA(hDlg, pinball::get_rc_string(39, 0), rcString, 0x2000u); MessageBoxW(hDlg, pinball::get_rc_Wstring(39, 0), rcString, 0x2000u);
sameKeyBound = 1; sameKeyBound = 1;
} }
} }
@@ -541,23 +677,23 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
case KEYMAPPER_Default: case KEYMAPPER_Default:
{ {
auto name = (LPARAM)get_vk_key_name(Options.LeftFlipperKeyDft, keyName); auto name = (LPARAM)get_vk_key_name(Options.LeftFlipperKeyDft, keyName);
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_FINDSTRINGEXACT, 0, name); auto ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.RightFlipperKeyDft, keyName); name = (LPARAM)get_vk_key_name(Options.RightFlipperKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_FINDSTRINGEXACT, 0, name); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.PlungerKeyDft, keyName); name = (LPARAM)get_vk_key_name(Options.PlungerKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_FINDSTRINGEXACT, 0, name); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.LeftTableBumpKeyDft, keyName); name = (LPARAM)get_vk_key_name(Options.LeftTableBumpKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_FINDSTRINGEXACT, 0, name); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.RightTableBumpKeyDft, keyName); name = (LPARAM)get_vk_key_name(Options.RightTableBumpKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_FINDSTRINGEXACT, 0, name); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.BottomTableBumpKeyDft, keyName); name = (LPARAM)get_vk_key_name(Options.BottomTableBumpKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_FINDSTRINGEXACT, 0, name); ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_SETCURSEL, ind, 0); SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_SETCURSEL, ind, 0);
return 0; return 0;
} }
default: default:
@@ -571,10 +707,10 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
} }
LPSTR options::get_vk_key_name(uint16_t vk, LPSTR keyName) LPWSTR options::get_vk_key_name(uint16_t vk, LPWSTR keyName)
{ {
LONG scanCode = MapVirtualKeyA(vk, MAPVK_VK_TO_VSC) << 16; LONG scanCode = MapVirtualKeyW(vk, MAPVK_VK_TO_VSC) << 16;
if (vk >= 0x21u && vk <= 0x2Eu) if (vk >= 0x21u && vk <= 0x2Eu)
scanCode |= 0x1000000u; scanCode |= 0x1000000u;
return GetKeyNameTextA(scanCode, keyName, 19) != 0 ? keyName : nullptr; return GetKeyNameTextW(scanCode, keyName, 19) != 0 ? keyName : nullptr;
} }

View File

@@ -1,5 +1,40 @@
#pragma once #pragma once
#include "pinball.h" #include "pinball.h"
#include "resource.h"
enum class Languages
{
English = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
Russian = MAKELANGID(LANG_RUSSIAN, SUBLANG_RUSSIAN_RUSSIA),
TraditionalChinese = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL),
SimplifiedChinese = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
Polish = MAKELANGID(LANG_POLISH, SUBLANG_POLISH_POLAND),
German = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN),
Japanese = MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN),
French = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH),
Italian = MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN),
Hungarian = MAKELANGID(LANG_HUNGARIAN, SUBLANG_HUNGARIAN_HUNGARY),
Portuguese = MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE),
BrazilianPortuguese = MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN),
Czech = MAKELANGID(LANG_CZECH, SUBLANG_CZECH_CZECH_REPUBLIC),
Danish = MAKELANGID(LANG_DANISH, SUBLANG_DANISH_DENMARK),
Finnish = MAKELANGID(LANG_FINNISH, SUBLANG_FINNISH_FINLAND),
Hebrew = MAKELANGID(LANG_HEBREW, SUBLANG_HEBREW_ISRAEL),
Arabic = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA),
Greek = MAKELANGID(LANG_GREEK, SUBLANG_GREEK_GREECE),
Spanish = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN),
Korean = MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN),
Dutch = MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH),
Norwegian = MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL),
Swedish = MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH),
Turkish = MAKELANGID(LANG_TURKISH, SUBLANG_TURKISH_TURKEY),
};
struct LanguageMenuEntry
{
LPCWSTR Name;
Languages Language;
};
struct optionsStruct struct optionsStruct
{ {
@@ -23,12 +58,15 @@ struct optionsStruct
int BottomTableBumpKeyDft; int BottomTableBumpKeyDft;
int Resolution; int Resolution;
bool UniformScaling; bool UniformScaling;
bool AlternativeRender;
Languages Language;
}; };
class options class options
{ {
public: public:
static void ReadOptions();
static void init(HMENU menuHandle); static void init(HMENU menuHandle);
static void uninit(); static void uninit();
static void path_init(LPCSTR regPath); static void path_init(LPCSTR regPath);
@@ -37,6 +75,8 @@ public:
static void set_int(LPCSTR optPath, LPCSTR lpValueName, int data); static void set_int(LPCSTR optPath, LPCSTR lpValueName, int data);
static void get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR dst, LPCSTR defaultValue, int iMaxLength); static void get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR dst, LPCSTR defaultValue, int iMaxLength);
static void set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value); static void set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value);
static void get_string(LPCSTR optPath, LPCWSTR lpValueName, LPWSTR dst, LPCWSTR defaultValue, int iMaxLength);
static void set_string(LPCSTR optPath, LPCWSTR lpValueName, LPCWSTR value);
static void menu_check(UINT uIDCheckItem, int check); static void menu_check(UINT uIDCheckItem, int check);
static void menu_set(UINT uIDEnableItem, int enable); static void menu_set(UINT uIDEnableItem, int enable);
static void toggle(UINT uIDCheckItem); static void toggle(UINT uIDCheckItem);
@@ -45,7 +85,7 @@ public:
static void keyboard(); static void keyboard();
static INT_PTR _stdcall KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); static INT_PTR _stdcall KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
static LPSTR get_vk_key_name(uint16_t vk, LPSTR keyName); static LPWSTR get_vk_key_name(uint16_t vk, LPWSTR keyName);
static optionsStruct Options; static optionsStruct Options;
private: private:
@@ -56,4 +96,5 @@ private:
static HMENU MenuHandle; static HMENU MenuHandle;
static winhelp_entry keymap_help[18]; static winhelp_entry keymap_help[18];
static short vk_list[28]; static short vk_list[28];
static LanguageMenuEntry LanguageMenu[Menu1_LanguageMax - Menu1_Language];
}; };

View File

@@ -26,10 +26,10 @@
TPinballTable* pb::MainTable = nullptr; TPinballTable* pb::MainTable = nullptr;
datFileStruct* pb::record_table = nullptr; 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; int pb::time_ticks = 0, pb::demo_mode = 0, pb::game_mode = 2, pb::mode_countdown_, pb::state, pb::frameCounter = 0;
float pb::time_now, pb::time_next, pb::ball_speed_limit; float pb::time_now, pb::time_next, pb::ball_speed_limit;
high_score_struct pb::highscore_table[5]; high_score_struct pb::highscore_table[5];
bool pb::FullTiltMode = false; bool pb::FullTiltMode = false, pb::cheat_mode = false;
int pb::init() int pb::init()
@@ -129,14 +129,18 @@ void pb::reset_table()
void pb::firsttime_setup() void pb::firsttime_setup()
{ {
render::blit = 0; render::update(false);
render::update();
render::blit = 1;
} }
void pb::paint() void pb::paint()
{ {
render::paint(); render::paint();
if (score::msg_fontp == nullptr)
{
// DrawText writes to screen directly, text gets overwritten by full vScreen blit.
pinball::InfoTextBox->Draw(true);
pinball::MissTextBox->Draw(true);
}
} }
void pb::mode_change(int mode) void pb::mode_change(int mode)
@@ -195,7 +199,7 @@ void pb::toggle_demo()
MainTable->Message(1024, 0.0); MainTable->Message(1024, 0.0);
mode_change(2); mode_change(2);
pinball::MissTextBox->Clear(); pinball::MissTextBox->Clear();
auto text = pinball::get_rc_string(24, 0); auto text = pinball::get_rc_Wstring(24, 0);
pinball::InfoTextBox->Display(text, -1.0); pinball::InfoTextBox->Display(text, -1.0);
} }
else else
@@ -223,6 +227,8 @@ void pb::ballset(int x, int y)
int pb::frame(int time) int pb::frame(int time)
{ {
static int frameTime = 0;
if (time > 100) if (time > 100)
time = 100; time = 100;
float timeMul = time * 0.001f; float timeMul = time * 0.001f;
@@ -244,13 +250,35 @@ int pb::frame(int time)
nudge::nudge_count = nudgeDec; nudge::nudge_count = nudgeDec;
} }
timer::check(); timer::check();
render::update();
if (!options::Options.AlternativeRender)
{
render::update(true);
}
else
{
// Screen update at UPS > screen refresh rate cause tearing.
// Especially noticeable on fast moving ball in scaled up window.
// Retained render prevents frame skip. The next best thing - complete refresh at fixed rate.
render::update(false);
// Frame time at 60 FPS = 16.(6) ms = (16 + 17 + 17) / 3
auto targetTime = frameCounter % 3 == 0 ? 16 : 17;
frameTime += time;
if (frameTime >= targetTime)
{
frameTime = min(frameTime - targetTime, 100);
render::shift(0, 0, 0, 0, MainTable->Width, MainTable->Height);
frameCounter++;
}
}
score::update(MainTable->CurScoreStruct); score::update(MainTable->CurScoreStruct);
if (!MainTable->TiltLockFlag) if (!MainTable->TiltLockFlag)
{ {
if (nudge::nudge_count > 0.5f) if (nudge::nudge_count > 0.5f)
{ {
pinball::InfoTextBox->Display(pinball::get_rc_string(25, 0), 2.0); pinball::InfoTextBox->Display(pinball::get_rc_Wstring(25, 0), 2.0);
} }
if (nudge::nudge_count > 1.0f) if (nudge::nudge_count > 1.0f)
MainTable->tilt(time_now); MainTable->tilt(time_now);
@@ -288,8 +316,8 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
ball->Acceleration.Y = ball->Speed * ball->Acceleration.Y; ball->Acceleration.Y = ball->Speed * ball->Acceleration.Y;
maths::vector_add(&ball->Acceleration, &vec2); maths::vector_add(&ball->Acceleration, &vec2);
ball->Speed = maths::normalize_2d(&ball->Acceleration); ball->Speed = maths::normalize_2d(&ball->Acceleration);
ball->InvAcceleration.X = ball->Acceleration.X == 0.0f ? 1000000000.0f : 1.0f / ball->Acceleration.X; ball->InvAcceleration.X = ball->Acceleration.X == 0.0f ? 1.0e9f : 1.0f / ball->Acceleration.X;
ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0f ? 1000000000.0f : 1.0f / ball->Acceleration.Y; ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0f ? 1.0e9f : 1.0f / ball->Acceleration.Y;
} }
auto timeDelta2 = timeDelta; auto timeDelta2 = timeDelta;
@@ -330,7 +358,7 @@ void pb::pause_continue()
{ {
if (MainTable) if (MainTable)
MainTable->Message(1008, time_now); MainTable->Message(1008, time_now);
pinball::InfoTextBox->Display(pinball::get_rc_string(22, 0), -1.0); pinball::InfoTextBox->Display(pinball::get_rc_Wstring(22, 0), -1.0);
midi::music_stop(); midi::music_stop();
} }
else else
@@ -339,17 +367,17 @@ void pb::pause_continue()
MainTable->Message(1009, 0.0); MainTable->Message(1009, 0.0);
if (!demo_mode) if (!demo_mode)
{ {
char* text; wchar_t* text;
float textTime; float textTime;
if (game_mode == 2) if (game_mode == 2)
{ {
textTime = -1.0; textTime = -1.0;
text = pinball::get_rc_string(24, 0); text = pinball::get_rc_Wstring(24, 0);
} }
else else
{ {
textTime = 5.0; textTime = 5.0;
text = pinball::get_rc_string(23, 0); text = pinball::get_rc_Wstring(23, 0);
} }
pinball::InfoTextBox->Display(text, textTime); pinball::InfoTextBox->Display(text, textTime);
} }
@@ -404,7 +432,7 @@ void pb::keydown(int key)
mode_countdown(-1); mode_countdown(-1);
return; return;
} }
control::pbctrl_bdoor_controller(key); control::pbctrl_bdoor_controller(static_cast<char>(key));
if (key == options::Options.LeftFlipperKey) if (key == options::Options.LeftFlipperKey)
{ {
MainTable->Message(1000, time_now); MainTable->Message(1000, time_now);
@@ -474,8 +502,8 @@ void pb::keydown(int key)
ball->Acceleration.X = 0.0; ball->Acceleration.X = 0.0;
break; break;
case 'H': case 'H':
char String1[200]; wchar_t String1[200];
lstrcpyA(String1, pinball::get_rc_string(26, 0)); lstrcpyW(String1, pinball::get_rc_Wstring(26, 0));
high_score::show_and_set_high_score_dialog(highscore_table, 1000000000, 1, String1); high_score::show_and_set_high_score_dialog(highscore_table, 1000000000, 1, String1);
break; break;
case 'M': case 'M':
@@ -528,7 +556,7 @@ void pb::end_game()
{ {
int scores[4]{}; int scores[4]{};
int scoreIndex[4]{}; int scoreIndex[4]{};
char String1[200]; wchar_t String1[200];
mode_change(2); mode_change(2);
int playerCount = MainTable->PlayerCount; int playerCount = MainTable->PlayerCount;
@@ -565,7 +593,7 @@ void pb::end_game()
int position = high_score::get_score_position(highscore_table, scores[i]); int position = high_score::get_score_position(highscore_table, scores[i]);
if (position >= 0) if (position >= 0)
{ {
lstrcpyA(String1, pinball::get_rc_string(scoreIndex[i] + 26, 0)); lstrcpyW(String1, pinball::get_rc_Wstring(scoreIndex[i] + 26, 0));
high_score::show_and_set_high_score_dialog(highscore_table, scores[i], position, String1); high_score::show_and_set_high_score_dialog(highscore_table, scores[i], position, String1);
} }
} }

View File

@@ -10,7 +10,8 @@ class pb
public: public:
static int time_ticks; static int time_ticks;
static float ball_speed_limit, time_now, time_next; static float ball_speed_limit, time_now, time_next;
static int cheat_mode, game_mode; static int game_mode, frameCounter;
static bool cheat_mode;
static datFileStruct* record_table; static datFileStruct* record_table;
static TPinballTable* MainTable; static TPinballTable* MainTable;
static high_score_struct highscore_table[5]; static high_score_struct highscore_table[5];

View File

@@ -8,7 +8,8 @@ int pinball::quickFlag = 0;
TTextBox* pinball::InfoTextBox; TTextBox* pinball::InfoTextBox;
TTextBox* pinball::MissTextBox; TTextBox* pinball::MissTextBox;
char pinball::getRcBuffer[6 * 256]; char pinball::getRcBuffer[6 * 256];
int pinball::rc_string_slot = 0; wchar_t pinball::getRcWBuffer[256 * 6];
int pinball::rc_string_slot = 0, pinball::rc_Wstring_slot = 0;
int pinball::LeftShift = -1; int pinball::LeftShift = -1;
int pinball::RightShift = -1; int pinball::RightShift = -1;
@@ -22,6 +23,16 @@ char* pinball::get_rc_string(int uID, int a2)
return result; return result;
} }
wchar_t* pinball::get_rc_Wstring(int uID, int a2)
{
auto result = &getRcWBuffer[256 * rc_Wstring_slot];
if (!LoadStringW(winmain::hinst, uID, result, 255))
*result = 0;
if (++rc_Wstring_slot >= 6)
rc_Wstring_slot = 0;
return result;
}
int pinball::get_rc_int(int uID, int* dst) int pinball::get_rc_int(int uID, int* dst)
{ {
char buffer[255]; char buffer[255];

View File

@@ -17,11 +17,13 @@ public:
static int LeftShift; static int LeftShift;
static char* get_rc_string(int uID, int a2); static char* get_rc_string(int uID, int a2);
static wchar_t* get_rc_Wstring(int uID, int a2);
static int get_rc_int(int uID, int* dst); static int get_rc_int(int uID, int* dst);
static void FindShiftKeys(); static void FindShiftKeys();
static void adjust_priority(int priority); static void adjust_priority(int priority);
static int make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize = 0x12Cu); static int make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize = 0x12Cu);
private: private:
static char getRcBuffer[256 * 6]; static char getRcBuffer[256 * 6];
static int rc_string_slot; static wchar_t getRcWBuffer[256 * 6];
static int rc_string_slot, rc_Wstring_slot;
}; };

View File

@@ -2,7 +2,6 @@
#include "render.h" #include "render.h"
#include "memory.h" #include "memory.h"
int render::blit = 0;
int render::many_dirty, render::many_sprites, render::many_balls; int render::many_dirty, render::many_sprites, render::many_balls;
render_sprite_type_struct **render::dirty_list, **render::sprite_list, **render::ball_list; render_sprite_type_struct **render::dirty_list, **render::sprite_list, **render::ball_list;
zmap_header_type* render::background_zmap; zmap_header_type* render::background_zmap;
@@ -60,83 +59,69 @@ void render::uninit()
many_balls = 0; many_balls = 0;
} }
void render::update() void render::update(bool blit)
{ {
rectangle_type overlapRect{}; rectangle_type overlapRect{};
auto dirtyPtr = dirty_list;
for (int index = 0; index < many_dirty; ++dirtyPtr, ++index)
{
auto curSprite = *dirtyPtr;
if ((*dirtyPtr)->VisualType != VisualType::None)
{
if ((*dirtyPtr)->VisualType == VisualType::Sprite)
{
if (curSprite->BmpRectCopy.Width > 0)
maths::enclosing_box(&curSprite->BmpRectCopy, &curSprite->BmpRect, &curSprite->DirtyRect);
if (!maths::rectangle_clip(&curSprite->DirtyRect, &vscreen_rect, &curSprite->DirtyRect))
{
curSprite->DirtyRect.Width = -1;
continue;
}
auto yPos = curSprite->DirtyRect.YPosition;
auto width = curSprite->DirtyRect.Width;
auto xPos = curSprite->DirtyRect.XPosition;
auto height = curSprite->DirtyRect.Height;
zdrv::fill(&zscreen, width, height, xPos, yPos, 0xFFFF);
if (background_bitmap)
gdrv::copy_bitmap(&vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos);
else
gdrv::fill_bitmap(&vscreen, width, height, xPos, yPos, 0);
}
}
else
{
if (!maths::rectangle_clip(&curSprite->BmpRect, &vscreen_rect, &curSprite->DirtyRect))
{
curSprite->DirtyRect.Width = -1;
continue;
}
if (!curSprite->Bmp)
{
auto yPos = curSprite->DirtyRect.YPosition;
auto width = curSprite->DirtyRect.Width;
auto xPos = curSprite->DirtyRect.XPosition;
auto height = curSprite->DirtyRect.Height;
zdrv::fill(&zscreen, width, height, xPos, yPos, 0xFFFF);
if (background_bitmap)
gdrv::copy_bitmap(&vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos);
else
gdrv::fill_bitmap(&vscreen, width, height, xPos, yPos, 0);
}
}
}
dirtyPtr = dirty_list;
for (int index = 0; index < many_dirty; ++index) for (int index = 0; index < many_dirty; ++index)
{ {
auto sprite = *dirtyPtr; auto curSprite = dirty_list[index];
if ((*dirtyPtr)->DirtyRect.Width > 0 && (sprite->VisualType == VisualType::None || sprite->VisualType == bool clearSprite = false;
VisualType::Sprite)) switch (curSprite->VisualType)
repaint(*dirtyPtr); {
++dirtyPtr; case VisualType::Sprite:
if (curSprite->BmpRectCopy.Width > 0)
maths::enclosing_box(&curSprite->BmpRectCopy, &curSprite->BmpRect, &curSprite->DirtyRect);
if (maths::rectangle_clip(&curSprite->DirtyRect, &vscreen_rect, &curSprite->DirtyRect))
clearSprite = true;
else
curSprite->DirtyRect.Width = -1;
break;
case VisualType::None:
if (maths::rectangle_clip(&curSprite->BmpRect, &vscreen_rect, &curSprite->DirtyRect))
clearSprite = !curSprite->Bmp;
else
curSprite->DirtyRect.Width = -1;
break;
default: break;
}
if (clearSprite)
{
auto yPos = curSprite->DirtyRect.YPosition;
auto width = curSprite->DirtyRect.Width;
auto xPos = curSprite->DirtyRect.XPosition;
auto height = curSprite->DirtyRect.Height;
zdrv::fill(&zscreen, width, height, xPos, yPos, 0xFFFF);
if (background_bitmap)
gdrv::copy_bitmap(&vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos);
else
gdrv::fill_bitmap(&vscreen, width, height, xPos, yPos, 0);
}
}
for (int index = 0; index < many_dirty; ++index)
{
auto sprite = dirty_list[index];
if (sprite->DirtyRect.Width > 0 && (sprite->VisualType == VisualType::None || sprite->VisualType ==
VisualType::Sprite))
repaint(sprite);
} }
paint_balls();
if (blit) if (blit)
{ {
paint_balls();
gdrv::start_blit_sequence(); gdrv::start_blit_sequence();
auto xPos = vscreen.XPosition + offset_x; auto xPos = vscreen.XPosition + offset_x;
auto yPos = vscreen.YPosition + offset_y; auto yPos = vscreen.YPosition + offset_y;
dirtyPtr = dirty_list;
for (int index = 0; index < many_dirty; ++dirtyPtr, ++index) for (int index = 0; index < many_dirty; ++index)
{ {
auto sprite = *dirtyPtr; auto sprite = dirty_list[index];
auto dirtyRect = &(*dirtyPtr)->DirtyRect; auto dirtyRect = &sprite->DirtyRect;
auto width2 = (*dirtyPtr)->DirtyRect.Width; auto width2 = sprite->DirtyRect.Width;
if (width2 > 0) if (width2 > 0)
gdrv::blit_sequence( gdrv::blit_sequence(
&vscreen, &vscreen,
@@ -147,21 +132,16 @@ void render::update()
width2, width2,
dirtyRect->Height); dirtyRect->Height);
auto rect = &sprite->BmpRectCopy; sprite->BmpRectCopy = *dirtyRect;
rect->XPosition = dirtyRect->XPosition;
rect->YPosition = dirtyRect->YPosition;
rect->Width = dirtyRect->Width;
rect->Height = dirtyRect->Height;
if (sprite->UnknownFlag != 0) if (sprite->UnknownFlag != 0)
remove_sprite(sprite); remove_sprite(sprite);
} }
dirtyPtr = ball_list; for (int index = 0; index < many_balls; ++index)
for (int index = 0; index < many_balls; ++dirtyPtr, ++index)
{ {
auto rectCopy = &(*dirtyPtr)->BmpRectCopy; auto sprite = ball_list[index];
auto dirtyRect = &(*dirtyPtr)->DirtyRect; auto rectCopy = &sprite->BmpRectCopy;
auto dirtyRect = &sprite->DirtyRect;
if (maths::overlapping_box(dirtyRect, rectCopy, &overlapRect) && dirtyRect->Width > 0) if (maths::overlapping_box(dirtyRect, rectCopy, &overlapRect) && dirtyRect->Width > 0)
{ {
if (overlapRect.Width > 0) if (overlapRect.Width > 0)
@@ -198,13 +178,22 @@ void render::update()
} }
gdrv::end_blit_sequence(); gdrv::end_blit_sequence();
unpaint_balls();
}
else
{
for (int index = 0; index < many_dirty; ++index)
{
auto sprite = dirty_list[index];
sprite->BmpRectCopy = sprite->DirtyRect;
if (sprite->UnknownFlag != 0)
remove_sprite(sprite);
}
} }
many_dirty = 0; many_dirty = 0;
unpaint_balls();
} }
void render::paint() void render::paint()
{ {
paint_balls(); paint_balls();
@@ -473,7 +462,7 @@ void render::paint_balls()
void render::unpaint_balls() void render::unpaint_balls()
{ {
for (int index = many_balls-1; index >= 0; index--) for (int index = many_balls - 1; index >= 0; index--)
{ {
auto curBall = ball_list[index]; auto curBall = ball_list[index];
if (curBall->DirtyRect.Width > 0) if (curBall->DirtyRect.Width > 0)

View File

@@ -31,7 +31,6 @@ struct render_sprite_type_struct
class render class render
{ {
public: public:
static int blit;
static int many_dirty, many_sprites, many_balls; static int many_dirty, many_sprites, many_balls;
static render_sprite_type_struct **dirty_list, **sprite_list, **ball_list; static render_sprite_type_struct **dirty_list, **sprite_list, **ball_list;
static zmap_header_type* background_zmap; static zmap_header_type* background_zmap;
@@ -43,7 +42,7 @@ public:
static void init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height); static void init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height);
static void uninit(); static void uninit();
static void update(); static void update(bool blit);
static void paint(); static void paint();
static void sprite_modified(render_sprite_type_struct* sprite); static void sprite_modified(render_sprite_type_struct* sprite);
static render_sprite_type_struct* create_sprite(VisualType visualType, gdrv_bitmap8* bmp, static render_sprite_type_struct* create_sprite(VisualType visualType, gdrv_bitmap8* bmp,

View File

@@ -240,6 +240,9 @@
#define DLG_HIGHSCORES_EditName3 603 #define DLG_HIGHSCORES_EditName3 603
#define DLG_HIGHSCORES_EditName4 604 #define DLG_HIGHSCORES_EditName4 604
#define DLG_HIGHSCORES_EditName5 605 #define DLG_HIGHSCORES_EditName5 605
#define Menu1_AlternativeRender 601
#define Menu1_Language 700
#define Menu1_LanguageMax 724
// Next default values for new objects // Next default values for new objects
// //

View File

@@ -47,6 +47,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
++memory::critical_allocation; ++memory::critical_allocation;
auto optionsRegPath = pinball::get_rc_string(165, 0); auto optionsRegPath = pinball::get_rc_string(165, 0);
options::path_init(optionsRegPath); options::path_init(optionsRegPath);
options::ReadOptions();
auto regSpaceCadet = pinball::get_rc_string(166, 0); auto regSpaceCadet = pinball::get_rc_string(166, 0);
if (options::get_int(regSpaceCadet, "Table Version", 1) <= 1) if (options::get_int(regSpaceCadet, "Table Version", 1) <= 1)
@@ -130,11 +131,11 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
} }
iFrostUniqueMsg = RegisterWindowMessageA("PinballThemeSwitcherUniqueMsgString"); iFrostUniqueMsg = RegisterWindowMessageA("PinballThemeSwitcherUniqueMsgString");
auto windowClass = pinball::get_rc_string(167, 0); auto windowClass = pinball::get_rc_Wstring(167, 0);
auto windowHandle = FindWindowA(windowClass, nullptr); auto windowHandle = FindWindowW(windowClass, nullptr);
if (windowHandle) if (windowHandle)
{ {
SendMessageA(windowHandle, iFrostUniqueMsg, 0, 0); SendMessageW(windowHandle, iFrostUniqueMsg, 0, 0);
return 0; return 0;
} }
@@ -146,28 +147,39 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
picce.dwICC = 5885; picce.dwICC = 5885;
InitCommonControlsEx(&picce); InitCommonControlsEx(&picce);
WNDCLASSEXA wndClass{}; WNDCLASSEXW wndClass{};
wndClass.cbSize = sizeof wndClass; wndClass.cbSize = sizeof wndClass;
wndClass.style = CS_DBLCLKS | CS_BYTEALIGNCLIENT; wndClass.style = CS_DBLCLKS | CS_BYTEALIGNCLIENT;
wndClass.lpfnWndProc = message_handler; wndClass.lpfnWndProc = message_handler;
wndClass.cbClsExtra = 0; wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0; wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance; wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIconA(hInstance, "ICON_1"); wndClass.hIcon = LoadIconW(hInstance, L"ICON_1");
wndClass.hCursor = LoadCursorA(nullptr, IDC_ARROW); wndClass.hCursor = LoadCursorW(nullptr, (PWSTR)IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)16; wndClass.hbrBackground = (HBRUSH)16;
wndClass.lpszMenuName = "MENU_1"; wndClass.lpszMenuName = L"MENU_1";
wndClass.lpszClassName = windowClass; wndClass.lpszClassName = windowClass;
auto splash = splash::splash_screen(hInstance, "splash_bitmap", "splash_bitmap"); auto splash = splash::splash_screen(hInstance, "splash_bitmap", "splash_bitmap");
RegisterClassExA(&wndClass); RegisterClassExW(&wndClass);
pinball::FindShiftKeys(); pinball::FindShiftKeys();
options::init_resolution(); options::init_resolution();
char windowName[40]; // Some languages use RTL layout
lstrcpyA(windowName, pinball::get_rc_string(38, 0)); DWORD dwExStyle;
windowHandle = CreateWindowExA(0, windowClass, windowName, WndStyle, 0, 0, 640, 480, nullptr, nullptr, hInstance, switch (options::Options.Language)
nullptr); {
case Languages::Hebrew:
case Languages::Arabic:
dwExStyle = WS_EX_LAYOUTRTL;
break;
default:
dwExStyle = 0;
}
auto windowName = pinball::get_rc_Wstring(38, 0);
windowHandle = CreateWindowExW(dwExStyle, windowClass, windowName,
WndStyle, 0, 0, 640, 480, nullptr, nullptr, hInstance, nullptr);
hwnd_frame = windowHandle; hwnd_frame = windowHandle;
if (!windowHandle) if (!windowHandle)
{ {
@@ -220,7 +232,16 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
if (prevTime) if (prevTime)
{ {
char buf[60]; char buf[60];
sprintf_s(buf, "Frames/sec = %02.02f", 300.0f / (static_cast<float>(curTime - prevTime) * 0.001f)); auto dt = static_cast<float>(curTime - prevTime) * 0.001f;
if (!options::Options.AlternativeRender)
sprintf_s(buf, "Frames/sec = %02.02f", 300.0f / dt);
else
{
sprintf_s(buf, "Updates/sec = %02.02f Frames/sec = %02.02f",
300.0f / dt, pb::frameCounter / dt);
pb::frameCounter = 0;
}
SetWindowTextA(hwnd_frame, buf); SetWindowTextA(hwnd_frame, buf);
if (DispGRhistory) if (DispGRhistory)
@@ -319,7 +340,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
gdrv::uninit(); gdrv::uninit();
DestroyWindow(hwnd_frame); DestroyWindow(hwnd_frame);
options::path_uninit(); options::path_uninit();
UnregisterClassA(windowClass, hinst); UnregisterClassW(windowClass, hinst);
if (restart) if (restart)
{ {
@@ -378,12 +399,12 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
midi::music_stop(); midi::music_stop();
} }
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_KILLFOCUS: case WM_KILLFOCUS:
has_focus = 0; has_focus = 0;
gdrv::get_focus(); gdrv::get_focus();
pb::loose_focus(); pb::loose_focus();
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_CREATE: case WM_CREATE:
{ {
RECT rect{}; RECT rect{};
@@ -414,18 +435,18 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
changeDisplayFg); changeDisplayFg);
--memory::critical_allocation; --memory::critical_allocation;
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
} }
case WM_MOVE: case WM_MOVE:
no_time_loss = 1; no_time_loss = 1;
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_SETFOCUS: case WM_SETFOCUS:
has_focus = 1; has_focus = 1;
no_time_loss = 1; no_time_loss = 1;
gdrv::get_focus(); gdrv::get_focus();
fullscrn::force_redraw(); fullscrn::force_redraw();
pb::paint(); pb::paint();
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_PAINT: case WM_PAINT:
{ {
PAINTSTRUCT paint{}; PAINTSTRUCT paint{};
@@ -441,16 +462,16 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
bQuit = 1; bQuit = 1;
PostQuitMessage(0); PostQuitMessage(0);
fullscrn::shutdown(); fullscrn::shutdown();
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_ERASEBKGND: case WM_ERASEBKGND:
break; break;
case WM_SIZE: case WM_SIZE:
fullscrn::window_size_changed(); fullscrn::window_size_changed();
fullscrn::force_redraw(); fullscrn::force_redraw();
pb::paint(); pb::paint();
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
default: default:
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
} }
return 0; return 0;
} }
@@ -459,7 +480,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
{ {
case WM_MENUSELECT: case WM_MENUSELECT:
if (lParam) if (lParam)
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
if (fullscrn::screen_mode) if (fullscrn::screen_mode)
fullscrn::set_menu_mode(0); fullscrn::set_menu_mode(0);
return 0; return 0;
@@ -467,10 +488,10 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
no_time_loss = 1; no_time_loss = 1;
if (fullscrn::screen_mode) if (fullscrn::screen_mode)
fullscrn::set_menu_mode(1); fullscrn::set_menu_mode(1);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_GETMINMAXINFO: case WM_GETMINMAXINFO:
fullscrn::getminmaxinfo((MINMAXINFO*)lParam); fullscrn::getminmaxinfo((MINMAXINFO*)lParam);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_DISPLAYCHANGE: case WM_DISPLAYCHANGE:
options::update_resolution_menu(); options::update_resolution_menu();
if (fullscrn::displaychange()) if (fullscrn::displaychange())
@@ -478,10 +499,10 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
options::Options.FullScreen = 0; options::Options.FullScreen = 0;
options::menu_check(Menu1_Full_Screen, 0); options::menu_check(Menu1_Full_Screen, 0);
} }
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_KEYUP: case WM_KEYUP:
pb::keyup(wParamI); pb::keyup(wParamI);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_KEYDOWN: case WM_KEYDOWN:
if (!(lParam & 0x40000000)) if (!(lParam & 0x40000000))
pb::keydown(wParamI); pb::keydown(wParamI);
@@ -513,26 +534,26 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
break; break;
} }
if (!pb::cheat_mode) if (!pb::cheat_mode)
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
switch (wParam) switch (wParam)
{ {
case 'H': case 'H':
DispGRhistory = 1; DispGRhistory = 1;
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case 'Y': case 'Y':
SetWindowTextA(hWnd, "Pinball"); SetWindowTextA(hWnd, "Pinball");
DispFrameRate = DispFrameRate == 0; DispFrameRate = DispFrameRate == 0;
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case VK_F1: case VK_F1:
pb::frame(10); pb::frame(10);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case VK_F15: case VK_F15:
single_step = single_step == 0; single_step = single_step == 0;
if (single_step == 0) if (single_step == 0)
no_time_loss = 1; no_time_loss = 1;
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
default: default:
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
} }
case WM_SYSCOMMAND: case WM_SYSCOMMAND:
switch (wParam & 0xFFF0) switch (wParam & 0xFFF0)
@@ -544,17 +565,17 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
case SC_MINIMIZE: case SC_MINIMIZE:
if (!single_step) if (!single_step)
pause(); pause();
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case SC_SCREENSAVE: case SC_SCREENSAVE:
fullscrn::activate(0); fullscrn::activate(0);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
default: break; default: break;
} }
end_pause(); end_pause();
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_INITMENU: case WM_INITMENU:
no_time_loss = 1; no_time_loss = 1;
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_COMMAND: case WM_COMMAND:
no_time_loss = 1; no_time_loss = 1;
switch (wParam) switch (wParam)
@@ -590,9 +611,9 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
iHwnd * iHwnd * iHwnd * iHwnd * iHwnd * iHwnd * iHwnd); iHwnd * iHwnd * iHwnd * iHwnd * iHwnd * iHwnd * iHwnd);
if (static_cast<int>(WinExec(cmdLine, 5u)) < 32) if (static_cast<int>(WinExec(cmdLine, 5u)) < 32)
{ {
auto caption = pinball::get_rc_string(170, 0); auto caption = pinball::get_rc_Wstring(170, 0);
auto text = pinball::get_rc_string(171, 0); auto text = pinball::get_rc_Wstring(171, 0);
MessageBoxA(hwnd_frame, text, caption, 0x2010u); MessageBoxW(hwnd_frame, text, caption, 0x2010u);
} }
memory::free(tmpBuf); memory::free(tmpBuf);
} }
@@ -610,6 +631,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
case Menu1_800x600: case Menu1_800x600:
case Menu1_1024x768: case Menu1_1024x768:
case Menu1_WindowUniformScale: case Menu1_WindowUniformScale:
case Menu1_AlternativeRender:
options::toggle(wParamI); options::toggle(wParamI);
break; break;
case Menu1_Help_Topics: case Menu1_Help_Topics:
@@ -655,7 +677,11 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
default: default:
break; break;
} }
return DefWindowProcA(hWnd, Msg, wParam, lParam);
if (wParam >= Menu1_Language && wParam < Menu1_LanguageMax)
options::toggle(wParamI);
return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
if (pb::game_mode) if (pb::game_mode)
{ {
@@ -671,7 +697,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
else else
pb::keydown(options::Options.LeftFlipperKey); pb::keydown(options::Options.LeftFlipperKey);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
} }
break; break;
case WM_LBUTTONUP: case WM_LBUTTONUP:
@@ -683,25 +709,25 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
} }
if (!pb::cheat_mode) if (!pb::cheat_mode)
pb::keyup(options::Options.LeftFlipperKey); pb::keyup(options::Options.LeftFlipperKey);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
if (!pb::cheat_mode) if (!pb::cheat_mode)
pb::keydown(options::Options.RightFlipperKey); pb::keydown(options::Options.RightFlipperKey);
if (pb::game_mode) if (pb::game_mode)
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
break; break;
case WM_RBUTTONUP: case WM_RBUTTONUP:
if (!pb::cheat_mode) if (!pb::cheat_mode)
pb::keyup(options::Options.RightFlipperKey); pb::keyup(options::Options.RightFlipperKey);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
pb::keydown(options::Options.PlungerKey); pb::keydown(options::Options.PlungerKey);
if (pb::game_mode) if (pb::game_mode)
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
break; break;
case WM_MBUTTONUP: case WM_MBUTTONUP:
pb::keyup(options::Options.PlungerKey); pb::keyup(options::Options.PlungerKey);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_POWERBROADCAST: case WM_POWERBROADCAST:
if (wParam == 4 && options::Options.FullScreen) if (wParam == 4 && options::Options.FullScreen)
{ {
@@ -709,20 +735,20 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
options::menu_check(Menu1_Full_Screen, 0); options::menu_check(Menu1_Full_Screen, 0);
fullscrn::set_screen_mode(options::Options.FullScreen); fullscrn::set_screen_mode(options::Options.FullScreen);
} }
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case WM_PALETTECHANGED: case WM_PALETTECHANGED:
InvalidateRect(hWnd, nullptr, 0); InvalidateRect(hWnd, nullptr, 0);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
case MM_MCINOTIFY: case MM_MCINOTIFY:
if (wParam == 1) if (wParam == 1)
midi::restart_midi_seq(lParam); midi::restart_midi_seq(lParam);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
default: default:
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
} }
pb::mode_countdown(-1); pb::mode_countdown(-1);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcW(hWnd, Msg, wParam, lParam);
} }
int winmain::ProcessWindowMessages() int winmain::ProcessWindowMessages()
@@ -759,9 +785,9 @@ void winmain::memalloc_failure()
midi::music_stop(); midi::music_stop();
Sound::Close(); Sound::Close();
gdrv::uninit(); gdrv::uninit();
char* caption = pinball::get_rc_string(170, 0); auto caption = pinball::get_rc_Wstring(170, 0);
char* text = pinball::get_rc_string(179, 0); auto text = pinball::get_rc_Wstring(179, 0);
MessageBoxA(nullptr, text, caption, 0x2030u); MessageBoxW(nullptr, text, caption, 0x2030u);
_exit(1); _exit(1);
} }
@@ -789,13 +815,12 @@ HDC winmain::_GetDC(HWND hWnd)
int winmain::a_dialog(HINSTANCE hInstance, HWND hWnd) int winmain::a_dialog(HINSTANCE hInstance, HWND hWnd)
{ {
char appName[100]; PCWSTR appName = pinball::get_rc_Wstring(38, 0);
char szOtherStuff[100]; PWSTR szOtherStuff = pinball::get_rc_Wstring(102, 0);
lstrcpyA(appName, pinball::get_rc_string(38, 0)); lstrcatW(szOtherStuff, L" Decompilation version 1.1.2");
lstrcpyA(szOtherStuff, pinball::get_rc_string(102, 0)); auto icon = LoadIconW(hInstance, L"ICON_1");
auto icon = LoadIconA(hInstance, "ICON_1"); return ShellAboutW(hWnd, appName, szOtherStuff, icon);
return ShellAboutA(hWnd, appName, szOtherStuff, icon);
} }
void winmain::end_pause() void winmain::end_pause()