44 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
Muzychenko Andrey
10c83e8bf5 Fixed sound pops introduced by WaveMix upsampler.
This does not fix WINE issues, but at least you don’t have to up sample manually.
2021-08-19 09:29:32 +03:00
Muzychenko Andrey
d5b44e44e1 Improved wav duration calculation - now supports sample rates other than 11025.
Bumped build tool version to VS2019.
2021-08-18 12:44:26 +03:00
Muzychenko Andrey
dcd488c48c Merge pull request #5 from GeorgeMcMullen/midifix
Fix to the routine that opens the MIDI file.
2021-08-18 10:08:55 +03:00
George McMullen
db08631ab9 Fix to the routine that opens the MIDI file.
In the original source code for Space Cadet and its related games, the MIDI sound track is opened with MCI_OPEN_TYPE. According to Microsoft's documentation (https://docs.microsoft.com/en-us/windows/win32/multimedia/mci-open), this is for opening devices and not files. Windows' libraries were obviously robust enough to accommodate the error, but other platforms (i.e. WINE) expects things to be called the right way. The simple fix is to switch out MCI_OPEN_TYPE with MCI_OPEN_ELEMENT and move the info for the filename to the lpstrElementName variable.
2021-08-16 05:39:18 -07:00
42 changed files with 1361 additions and 827 deletions

11
.gitignore vendored
View File

@@ -21,6 +21,9 @@ bld/
[Bb]in/
[Oo]bj/
[Ll]og/
ARM/
ARM64/
win32/
# Visual Studio 2015 cache/options directory
.vs/
@@ -263,3 +266,11 @@ __pycache__/
/Export
/DrMem
/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~~
* ~~Resizable window, scaled graphics~~
* ~~Loader for high-res sprites from CADET.DAT~~
* Misc features of Full Tilt: 3 music tracs, multiball, centered textboxes, etc.
* Maybe: cross-platform port
* Needs UI framework with menu bar and dialog windows, like QT or Avalonia
* Needs a way play sounds and midi
* ~~Cross-platform port using SDL2, SDL2_mixer, ImGui~~
* Text translations
* Misc features of Full Tilt: 3 music tracks, multiball, centered textboxes, etc.
* Maybe x2: support for other two tables
* 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
# Visual Studio 15
VisualStudioVersion = 15.0.28307.705
# Visual Studio Version 16
VisualStudioVersion = 16.0.31624.102
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpaceCadetPinball", "SpaceCadetPinball\SpaceCadetPinball.vcxproj", "{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
ReleaseWinXp|ARM = ReleaseWinXp|ARM
ReleaseWinXp|ARM64 = ReleaseWinXp|ARM64
ReleaseWinXp|x64 = ReleaseWinXp|x64
ReleaseWinXp|x86 = ReleaseWinXp|x86
EndGlobalSection
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.Build.0 = Debug|x64
{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}.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.Build.0 = Release|x64
{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}.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
GlobalSection(SolutionProperties) = preSolution
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*/
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;

View File

@@ -1,10 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<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">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</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">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
@@ -23,32 +55,86 @@
<ProjectGuid>{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>SpaceCadetPinball</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</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">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</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">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</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">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</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>
@@ -60,29 +146,84 @@
<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" />
</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'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</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'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</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'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</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 Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<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 Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</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'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
@@ -102,6 +243,25 @@
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</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'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
@@ -119,6 +279,23 @@
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</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'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
@@ -140,6 +317,69 @@
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</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'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
@@ -161,6 +401,69 @@
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</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>
<ClInclude Include="control.h" />
<ClInclude Include="fullscrn.h" />
@@ -242,9 +545,17 @@
<ClCompile Include="pb.cpp" />
<ClCompile Include="pch.cpp">
<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|ARM64'">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|ARM64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseWinXp|ARM64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="pinball.cpp" />
<ClCompile Include="proj.cpp" />

View File

@@ -22,14 +22,14 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
Smoothness = visual.Smoothness;
auto collMult = *loader::query_float_attribute(groupIndex, 0, 803);
auto bmpCoef2 = *loader::query_float_attribute(groupIndex, 0, 805);
auto bmpCoef1 = *loader::query_float_attribute(groupIndex, 0, 804);
auto retractTime = *loader::query_float_attribute(groupIndex, 0, 805);
auto extendTime = *loader::query_float_attribute(groupIndex, 0, 804);
/*Full tilt hack: different flipper speed*/
if (pb::FullTiltMode)
{
bmpCoef2 = 0.08f;
bmpCoef1 = 0.04f;
retractTime = 0.08f;
extendTime = 0.04f;
}
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));
@@ -42,8 +42,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
origin,
vecT1,
vecT2,
bmpCoef1,
bmpCoef2,
extendTime,
retractTime,
collMult,
Elasticity,
Smoothness);
@@ -51,8 +51,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
FlipperEdge = flipperEdge;
if (flipperEdge)
{
BmpCoef1 = flipperEdge->BmpCoef1 / static_cast<float>(ListBitmap->GetCount() - 1);
BmpCoef2 = flipperEdge->BmpCoef2 / static_cast<float>(ListBitmap->GetCount() - 1);
ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast<float>(ListBitmap->GetCount() - 1);
RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast<float>(ListBitmap->GetCount() - 1);
}
BmpIndex = 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)
{
float timerTime;
int soundIndex = 0, code2 = code;
int command = code;
if (code == 1)
{
control::handler(1, this);
TimerTime = BmpCoef1;
soundIndex = HardHitSoundId;
TimerTime = ExtendAnimationFrameTime;
loader::play_sound(HardHitSoundId);
}
else if (code == 2)
{
TimerTime = BmpCoef2;
soundIndex = SoftHitSoundId;
TimerTime = RetractAnimationFrameTime;
loader::play_sound(SoftHitSoundId);
}
else
{
code2 = 2;
TimerTime = BmpCoef2;
// Retract for all non-input messages
command = 2;
TimerTime = RetractAnimationFrameTime;
}
if (soundIndex)
loader::play_sound(soundIndex);
if (Timer)
{
timer::kill(Timer);
Timer = 0;
}
if (MessageField)
{
auto v10 = value - FlipperEdge->InputTime;
timerTime = v10 - floor(v10 / TimerTime) * TimerTime;
// Message arrived before animation is finished
auto inputDt = value - FlipperEdge->InputTime;
timerTime = inputDt - floor(inputDt / TimerTime) * TimerTime;
if (timerTime < 0.0f)
timerTime = 0.0;
}
@@ -104,10 +99,13 @@ int TFlipper::Message(int code, float value)
{
timerTime = TimerTime;
}
MessageField = code2;
MessageField = command;
InputTime = value;
if (Timer)
timer::kill(Timer);
Timer = timer::set(timerTime, this, TimerExpired);
FlipperEdge->SetMotion(code2, value);
FlipperEdge->SetMotion(command, value);
}
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)
{
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;
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)
{
flip->BmpIndex += bmpIndexAdvance;
int countSub1 = flip->ListBitmap->GetCount() - 1;
if (flip->BmpIndex >= countSub1)
flip->BmpIndex = newBmpIndex;
if (flip->BmpIndex >= bmpCountSub1)
{
flip->BmpIndex = countSub1;
flip->BmpIndex = bmpCountSub1;
bmpIndexOutOfBounds = true;
}
}
if (flip->MessageField == 2)
{
flip->BmpIndex -= bmpIndexAdvance;
timer = 0;
flip->BmpIndex = bmpCountSub1 - newBmpIndex;
if (flip->BmpIndex <= 0)
{
flip->BmpIndex = 0;
bmpIndexOutOfBounds = true;
}
}
else
{
timer = 0;
}
if (bmpIndexOutOfBounds)
{
flip->MessageField = 0;
flip->Timer = 0;
}
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 zMap = flip->ListZMap->Get(flip->BmpIndex);

View File

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

View File

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

View File

@@ -8,7 +8,7 @@ class TFlipperEdge : public TEdgeSegment
{
public:
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);
void port_draw() override;
float FindCollisionDistance(ray_type* ray) override;
@@ -50,8 +50,8 @@ public:
float InputTime;
float AngleStopTime;
float AngleMult;
float BmpCoef1;
float BmpCoef2;
float ExtendTime;
float RetractTime;
vector_type NextBallPosition;
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.Y = Circle.Center.Y;
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)
{
loader::play_sound(HardHitSoundId);

View File

@@ -5,6 +5,7 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "pb.h"
#include "TBall.h"
#include "TCircle.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];
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;
BallAcceleration = visual.Kicker.ThrowBallAcceleration;
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));
if (!(timeIndex & 1))
TLightGroup::Message(46, 0.0);
float* timeArray = TimerTimeArray;
if (timeArray)
TimerBargraph = timer::set(timeArray[timeIndex], this, BargraphTimerExpired);
if (TimerTimeArray)
TimerBargraph = timer::set(TimerTimeArray[timeIndex], this, BargraphTimerExpired);
TimeIndex = timeIndex;
}
else

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@@ -2377,6 +2377,12 @@ HPSTR WaveMix::SamplesPerSecAlign(HPSTR lpInData, DWORD nInSamplesPerSec, DWORD
}
}
// Dump raw PCM for analysis.
/*FILE* file;
fopen_s(&file,"wav1_dump.raw", "w");
fwrite(dataBufBup, 1, sampleSize * dwNumSamples2, file);
fclose(file);*/
GlobalUnlock(GlobalHandle(lpInDataBup));
GlobalFree(GlobalHandle(lpInDataBup));
return dataBufBup;
@@ -2427,7 +2433,7 @@ void WaveMix::RepSample(HPSTR lpOutData, HPSTR lpInData, unsigned nRep, int nByt
{
auto sample = *src;
auto dst2 = &dst[nChannels];
auto delta = (src[nChannels] - src[0]) / nRep;
auto delta = (src[nChannels] - src[0]) / static_cast<int>(nRep);
*dst = *src;
dst++;
for (auto repeatIndex = nRep - 1; repeatIndex; repeatIndex--)
@@ -2447,7 +2453,7 @@ void WaveMix::RepSample(HPSTR lpOutData, HPSTR lpInData, unsigned nRep, int nByt
{
auto sample = *src;
auto dst2 = &dst[nChannels];
auto delta = (src[nChannels] - src[0]) / nRep; /*Was dst[nChannels] - */
auto delta = (src[nChannels] - src[0]) / static_cast<int>(nRep); /*Was dst[nChannels] - */
*dst = *src;
++dst;
for (auto repeatIndex2 = nRep - 1; repeatIndex2; --repeatIndex2)

File diff suppressed because it is too large Load Diff

View File

@@ -65,14 +65,15 @@ public:
static TPinballTable* TableG;
static component_info score_components[88];
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 component_tag_base *wormhole_tag_array1[3], *wormhole_tag_array2[3], *wormhole_tag_array3[3];
static void make_links(TPinballTable* table);
static TPinballComponent* make_component_link(component_tag_base* tag);
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_set_bonus_hold();
static void table_set_bonus();
@@ -81,7 +82,7 @@ public:
static void table_set_multiball();
static void table_bump_ball_sink_lock();
static void table_set_replay(float value);
static int cheat_bump_rank();
static void cheat_bump_rank();
static bool light_on(component_tag<TLight>* tag);
static int SpecialAddScore(int score);
static int AddRankProgress(int rank);
@@ -182,6 +183,5 @@ public:
static void UnselectMissionController(int code, TPinballComponent* caller);
static void WaitingDeploymentController(int code, TPinballComponent* caller);
private:
static int pbctrl_state;
static int extraball_light_flag;
};

View File

@@ -28,8 +28,8 @@ const resolution_info fullscrn::resolution_array[3] =
};
float fullscrn::ScaleX = 1;
float fullscrn::ScaleY = 1;
float fullscrn::OffsetX = 0;
float fullscrn::OffsetY = 0;
int fullscrn::OffsetX = 0;
int fullscrn::OffsetY = 0;
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);
}
}
render::paint();
pb::paint();
fullscrn_flag1 = 0;
}
@@ -450,13 +450,7 @@ void fullscrn::window_size_changed()
if (options::Options.UniformScaling)
{
ScaleY = ScaleX = min(ScaleX, ScaleY);
OffsetX = floor((client.right - res->TableWidth * ScaleX) / 2);
OffsetY = floor((client.bottom - res->TableHeight * ScaleY) / 2);
auto dc = GetDC(hWnd);
if (dc)
{
BitBlt(dc, 0, 0, client.right, client.bottom, dc, 0, 0, BLACKNESS);
ReleaseDC(hWnd, dc);
}
OffsetX = static_cast<int>(floor((client.right - res->TableWidth * ScaleX) / 2));
OffsetY = static_cast<int>(floor((client.bottom - res->TableHeight * ScaleY) / 2));
}
}

View File

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

View File

@@ -3,6 +3,7 @@
#include "fullscrn.h"
#include "memory.h"
#include "options.h"
#include "pinball.h"
#include "winmain.h"
@@ -287,7 +288,7 @@ void gdrv::end_blit_sequence()
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);
SetStretchBltMode(dc, stretchMode);
@@ -303,7 +304,7 @@ void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest,
DestWidth,
DestHeight,
xSrc,
bmp->Height - ySrcOff - DestHeight,
bmp->Height - ySrc - DestHeight,
DestWidth,
DestHeight,
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)
{
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);
RealizePalette(dc);
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);
tagRECT rc{};
rc.left = xOff;
rc.right = width + xOff;
rc.top = yOff;
@@ -412,9 +445,38 @@ void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width,
if (fontColor)
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);
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);
SetTextColor(dc, color);
ReleaseDC(hwnd, dc);

View File

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

View File

@@ -10,7 +10,7 @@
int high_score::dlg_enter_name;
int high_score::dlg_score;
int high_score::dlg_position;
LPCSTR high_score::default_name;
LPCWSTR high_score::default_name;
high_score_struct* high_score::dlg_hst;
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)
{
char Buffer[20];
char scoreBuffer[20];
wchar_t nameBuffer[20];
int scoreSum = 0;
clear_table(table);
@@ -52,18 +53,17 @@ int high_score::read(high_score_struct* table, int* ptrToSmth)
for (auto position = 0; position < 5; ++position)
{
auto tablePtr = &table[position];
_itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Name");
options::get_string(optPath, Buffer, buf1, "", 32);
buf1[32] = 0;
lstrcpyA(tablePtr->Name, buf1);
_itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Score");
options::get_string(optPath, Buffer, buf1, "", 300);
wsprintfW(nameBuffer, L"%d.Name", position);
options::get_string(optPath, nameBuffer, tablePtr->Name, L"", 32);
tablePtr->Name[31] = 0;
sprintf_s(scoreBuffer, "%d.Score", position);
options::get_string(optPath, scoreBuffer, buf1, "", 300);
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;
}
@@ -78,30 +78,30 @@ int high_score::read(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;
CHAR* buf = memory::allocate(300u);
if (!buf)
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)
{
_itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Name");
options::set_string(optPath, Buffer, tablePtr->Name);
_itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Score");
auto tablePtr = &table[position];
wsprintfW(nameBuffer, L"%d.Name", position);
options::set_string(optPath, nameBuffer, tablePtr->Name);
sprintf_s(scoreBuffer, "%d.Score", position);
_ltoa_s(tablePtr->Score, buf, 300, 10);
options::set_string(optPath, Buffer, buf);
for (int i = lstrlenA(tablePtr->Name); --i >= 0; scoreSum += tablePtr->Name[i])
{
}
options::set_string(optPath, scoreBuffer, buf);
for (auto i = lstrlenW(tablePtr->Name) - 1; i >= 0; i--)
scoreSum += tablePtr->Name[i];
scoreSum += tablePtr->Score;
++position;
++tablePtr;
}
scramble_number_string(scoreSum, buf);
options::set_string(optPath, "Verification", buf);
memory::free(buf);
@@ -131,7 +131,7 @@ int high_score::get_score_position(high_score_struct* table, int score)
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)
{
@@ -149,9 +149,9 @@ int high_score::place_new_score_into(high_score_struct* table, int score, LPSTR
}
high_score_struct* posTable = &table[position];
posTable->Score = score;
if (lstrlenA(scoreStr) >= 31)
scoreStr[31] = 0;
lstrcpyA(posTable->Name, scoreStr);
if (lstrlenW(name) >= 31)
name[31] = 0;
lstrcpyW(posTable->Name, name);
posTable->Name[31] = 0;
}
return position;
@@ -167,17 +167,17 @@ void high_score::show_high_score_dialog(high_score_struct* table)
dlg_enter_name = 0;
dlg_score = 0;
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_score = score;
dlg_hst = table;
dlg_enter_name = 1;
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;
int nIDDlgItem;
CHAR String1[256];
CHAR name[32];
wchar_t name[32];
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);
for (nIDDlgItem = DLG_HIGHSCORES_EditName1; nIDDlgItem < 611; ++nIDDlgItem)
{
ShowWindow(GetDlgItem(hWnd, nIDDlgItem), 0);
ShowWindow(GetDlgItem(hWnd, nIDDlgItem), SW_HIDE);
}
if (dlg_enter_name == 1)
{
@@ -215,12 +214,12 @@ INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
return 1;
}
HWND nameTextBox = GetDlgItem(hWnd, dlg_position + DLG_HIGHSCORES_EditName1);
ShowWindow(nameTextBox, 5);
ShowWindow(nameTextBox, SW_SHOW);
EnableWindow(nameTextBox, 1);
SetFocus(nameTextBox);
if (default_name)
{
SetWindowTextA(nameTextBox, default_name);
SetWindowTextW(nameTextBox, default_name);
SendMessageA(nameTextBox, EM_SETSEL, 0, -1);
}
SendMessageA(nameTextBox, EM_SETLIMITTEXT, 31u, 0);
@@ -241,15 +240,15 @@ INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
break;
}
GetDlgItemTextA(hWnd, dlg_position + DLG_HIGHSCORES_EditName1, name, 32);
GetDlgItemTextW(hWnd, dlg_position + DLG_HIGHSCORES_EditName1, name, 32);
name[31] = 0;
place_new_score_into(dlg_hst, dlg_score, name, dlg_position);
break;
case DLG_HIGHSCORES_Cancel:
break;
case DLG_HIGHSCORES_Clear:
lstrcpyA(String1, pinball::get_rc_string(41, 0));
if (MessageBoxA(hWnd, pinball::get_rc_string(40, 0), String1, MB_DEFBUTTON2 | MB_OKCANCEL) == 1)
if (MessageBoxW(hWnd, pinball::get_rc_Wstring(40, 0),
pinball::get_rc_Wstring(41, 0), MB_DEFBUTTON2 | MB_OKCANCEL) == 1)
{
clear_table(dlg_hst);
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)
{
hsdlg_show_score(hDlg, " ", dlg_score, i);
hsdlg_show_score(hDlg, L" ", dlg_score, i);
nextPosition = 1;
}
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];
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);
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);
}
}

View File

@@ -3,7 +3,7 @@
struct high_score_struct
{
char Name[32];
wchar_t Name[32];
int Score;
};
@@ -15,19 +15,19 @@ public:
static int write(high_score_struct* table, int* ptrToSmth);
static void clear_table(high_score_struct* table);
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 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 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 :
static int dlg_enter_name;
static int dlg_score;
static int dlg_position;
static LPCSTR default_name;
static LPCWSTR default_name;
static high_score_struct* dlg_hst;
static winhelp_entry help[21];
};

View File

@@ -135,6 +135,8 @@ int loader::get_sound_id(int groupIndex)
if (!sound_list[soundIndex].Loaded && !sound_list[soundIndex].WavePtr)
{
WaveHeader wavHeader{};
int soundGroupId = sound_list[soundIndex].GroupIndex;
sound_list[soundIndex].Duration = 0.0;
if (soundGroupId > 0 && !pinball::quickFlag)
@@ -150,9 +152,10 @@ int loader::get_sound_id(int groupIndex)
pinball::make_path_name(filePath, fileName2);
HFILE hFile = _lopen(filePath, 0);
sound_list[soundIndex].Duration = static_cast<float>(static_cast<double>(_llseek(hFile, 0, SEEK_END)) *
0.0000909090909090909);
_lread(hFile, &wavHeader, sizeof wavHeader);
_lclose(hFile);
auto sampleCount = wavHeader.data_size / (wavHeader.channels * (wavHeader.bits_per_sample / 8.0));
sound_list[soundIndex].Duration = static_cast<float>(sampleCount / wavHeader.sample_rate);
sound_list[soundIndex].WavePtr = Sound::LoadWaveFile(filePath);
}
}

View File

@@ -48,6 +48,40 @@ struct visualStruct
zmap_header_type* ZMap;
};
#pragma pack(push)
#pragma pack(1)
// WAVE file header format
struct WaveHeader
{
unsigned char riff[4]; // RIFF string
unsigned int overall_size; // overall size of file in bytes
unsigned char wave[4]; // WAVE string
unsigned char fmt_chunk_marker[4]; // fmt string with trailing null char
unsigned int length_of_fmt; // length of the format data
unsigned short format_type; // format type. 1-PCM, 3- IEEE float, 6 - 8bit A law, 7 - 8bit mu law
unsigned short channels; // no.of channels
unsigned int sample_rate; // sampling rate (blocks per second)
unsigned int byterate; // SampleRate * NumChannels * BitsPerSample/8
unsigned short block_align; // NumChannels * BitsPerSample/8
unsigned short bits_per_sample; // bits per sample, 8- 8bits, 16- 16 bits etc
unsigned char data_chunk_header[4]; // DATA string or FLLR string
unsigned int data_size; // NumSamples * NumChannels * BitsPerSample/8 - size of the next chunk that will be read
};
#pragma pack(pop)
static_assert(sizeof(WaveHeader) == 44, "Wrong size of WaveHeader");
class loader
{

View File

@@ -6,7 +6,7 @@
#include "pinball.h"
tagMCI_OPEN_PARMSA midi::mci_open_info;
char midi::midi_device_type[28];
char midi::midi_file_name[28];
HWND midi::midi_notify_hwnd;
int midi::midi_seq1_open, midi::midi_seq1_playing;
@@ -53,10 +53,10 @@ int midi::music_init(HWND hwnd)
mci_open_info.wDeviceID = 0;
midi_notify_hwnd = hwnd;
lstrcpyA(midi_device_type, pinball::get_rc_string(156, 0));
mci_open_info.lpstrElementName = nullptr;
mci_open_info.lpstrDeviceType = midi_device_type;
auto result = mciSendCommandA(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_NOTIFY_SUPERSEDED, (DWORD_PTR)&mci_open_info);
lstrcpyA(midi_file_name, pinball::get_rc_string(156, 0));
mci_open_info.lpstrElementName = midi_file_name;
mci_open_info.lpstrDeviceType = nullptr;
auto result = mciSendCommandA(0, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_NOTIFY_SUPERSEDED, (DWORD_PTR)&mci_open_info);
midi_seq1_open = result == 0;
return midi_seq1_open;
}

View File

@@ -59,7 +59,7 @@ public:
static void music_shutdown();
private:
static tagMCI_OPEN_PARMSA mci_open_info;
static char midi_device_type[28];
static char midi_file_name[28];
static HWND midi_notify_hwnd;
static int midi_seq1_open, midi_seq1_playing;

View File

@@ -1,4 +1,4 @@
#include "pch.h"
#include "pch.h"
#include "options.h"
#include "fullscrn.h"
@@ -68,9 +68,36 @@ short options::vk_list[28]
-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.Music = 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.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
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);
Sound::Enable(0, 7, Options.Sounds);
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_4Players, Options.Players == 4);
menu_check(Menu1_WindowUniformScale, Options.UniformScaling);
menu_check(Menu1_AlternativeRender, Options.AlternativeRender);
auto tmpBuf = memory::allocate(0x1F4u);
if (tmpBuf)
{
@@ -133,6 +202,21 @@ void options::init(HMENU menuHandle)
}
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()
@@ -149,6 +233,8 @@ void options::uninit()
set_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
set_int(nullptr, "Screen Resolution", Options.Resolution);
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)
@@ -265,6 +351,43 @@ void options::set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value)
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)
{
@@ -343,18 +466,31 @@ void options::toggle(UINT uIDCheckItem)
fullscrn::window_size_changed();
fullscrn::paint();
break;
case Menu1_AlternativeRender:
Options.AlternativeRender ^= true;
menu_check(Menu1_AlternativeRender, Options.AlternativeRender);
fullscrn::window_size_changed();
fullscrn::paint();
break;
default:
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()
{
auto maxResolution = fullscrn::get_max_supported_resolution();
fullscrn::SetMaxResolution(maxResolution);
const CHAR* maxResText = pinball::get_rc_string(maxResolution + 2030, 0);
PCWSTR maxResText = pinball::get_rc_Wstring(maxResolution + 2030, 0);
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++)
{
@@ -387,14 +523,14 @@ void options::init_resolution()
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)
{
char keyName[20];
WCHAR keyName[20];
int keyBindings[6];
char rcString[256];
WCHAR rcString[256];
switch (msg)
{
@@ -418,7 +554,7 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
auto index = 128;
do
{
if (vkChar == MapVirtualKeyA(index, MAPVK_VK_TO_CHAR))
if (vkChar == MapVirtualKeyW(index, MAPVK_VK_TO_CHAR))
break;
++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))
{
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL,CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_SETITEMDATA, ind, curVK);
auto ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL,CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.LeftFlipperKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_SETITEMDATA, ind, curVK);
SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.RightFlipperKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_SETITEMDATA, ind, curVK);
SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.PlungerKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_SETITEMDATA, ind, curVK);
SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.LeftTableBumpKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_SETITEMDATA, ind, curVK);
SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.RightTableBumpKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_SETITEMDATA, ind, curVK);
SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_SETITEMDATA, ind, curVK);
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:
{
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETCURSEL, 0, 0);
keyBindings[0] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETCURSEL, 0, 0);
keyBindings[1] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETCURSEL, 0, 0);
keyBindings[2] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETCURSEL, 0, 0);
keyBindings[3] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETCURSEL, 0, 0);
keyBindings[4] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETCURSEL, 0, 0);
keyBindings[5] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETITEMDATA, ind, 0));
auto ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_GETCURSEL, 0, 0);
keyBindings[0] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_GETCURSEL, 0, 0);
keyBindings[1] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_GETCURSEL, 0, 0);
keyBindings[2] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_GETCURSEL, 0, 0);
keyBindings[3] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_GETCURSEL, 0, 0);
keyBindings[4] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_GETCURSEL, 0, 0);
keyBindings[5] = static_cast<int>(SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_GETITEMDATA, ind, 0));
auto sameKeyBound = 0;
auto index = 1;
@@ -512,8 +648,8 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
break;
if (*optPtr == keyBindings[keyInd])
{
lstrcpyA(rcString, pinball::get_rc_string(43, 0));
MessageBoxA(hDlg, pinball::get_rc_string(39, 0), rcString, 0x2000u);
lstrcpyW(rcString, pinball::get_rc_Wstring(43, 0));
MessageBoxW(hDlg, pinball::get_rc_Wstring(39, 0), rcString, 0x2000u);
sameKeyBound = 1;
}
}
@@ -541,23 +677,23 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
case KEYMAPPER_Default:
{
auto name = (LPARAM)get_vk_key_name(Options.LeftFlipperKeyDft, keyName);
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0);
auto ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.RightFlipperKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageW(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.PlungerKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageW(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.LeftTableBumpKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageW(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.RightTableBumpKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageW(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.BottomTableBumpKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageW(hDlg, KEYMAPPER_BumpBottom, CB_SETCURSEL, ind, 0);
return 0;
}
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)
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
#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
{
@@ -23,12 +58,15 @@ struct optionsStruct
int BottomTableBumpKeyDft;
int Resolution;
bool UniformScaling;
bool AlternativeRender;
Languages Language;
};
class options
{
public:
static void ReadOptions();
static void init(HMENU menuHandle);
static void uninit();
static void path_init(LPCSTR regPath);
@@ -37,6 +75,8 @@ public:
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 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_set(UINT uIDEnableItem, int enable);
static void toggle(UINT uIDCheckItem);
@@ -45,7 +85,7 @@ public:
static void keyboard();
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;
private:
@@ -56,4 +96,5 @@ private:
static HMENU MenuHandle;
static winhelp_entry keymap_help[18];
static short vk_list[28];
static LanguageMenuEntry LanguageMenu[Menu1_LanguageMax - Menu1_Language];
};

View File

@@ -26,10 +26,10 @@
TPinballTable* pb::MainTable = 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;
high_score_struct pb::highscore_table[5];
bool pb::FullTiltMode = false;
bool pb::FullTiltMode = false, pb::cheat_mode = false;
int pb::init()
@@ -129,14 +129,18 @@ void pb::reset_table()
void pb::firsttime_setup()
{
render::blit = 0;
render::update();
render::blit = 1;
render::update(false);
}
void pb::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)
@@ -195,7 +199,7 @@ void pb::toggle_demo()
MainTable->Message(1024, 0.0);
mode_change(2);
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);
}
else
@@ -223,6 +227,8 @@ void pb::ballset(int x, int y)
int pb::frame(int time)
{
static int frameTime = 0;
if (time > 100)
time = 100;
float timeMul = time * 0.001f;
@@ -244,13 +250,35 @@ int pb::frame(int time)
nudge::nudge_count = nudgeDec;
}
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);
if (!MainTable->TiltLockFlag)
{
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)
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;
maths::vector_add(&ball->Acceleration, &vec2);
ball->Speed = maths::normalize_2d(&ball->Acceleration);
ball->InvAcceleration.X = ball->Acceleration.X == 0.0f ? 1000000000.0f : 1.0f / ball->Acceleration.X;
ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0f ? 1000000000.0f : 1.0f / ball->Acceleration.Y;
ball->InvAcceleration.X = ball->Acceleration.X == 0.0f ? 1.0e9f : 1.0f / ball->Acceleration.X;
ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0f ? 1.0e9f : 1.0f / ball->Acceleration.Y;
}
auto timeDelta2 = timeDelta;
@@ -330,7 +358,7 @@ void pb::pause_continue()
{
if (MainTable)
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();
}
else
@@ -339,17 +367,17 @@ void pb::pause_continue()
MainTable->Message(1009, 0.0);
if (!demo_mode)
{
char* text;
wchar_t* text;
float textTime;
if (game_mode == 2)
{
textTime = -1.0;
text = pinball::get_rc_string(24, 0);
text = pinball::get_rc_Wstring(24, 0);
}
else
{
textTime = 5.0;
text = pinball::get_rc_string(23, 0);
text = pinball::get_rc_Wstring(23, 0);
}
pinball::InfoTextBox->Display(text, textTime);
}
@@ -404,7 +432,7 @@ void pb::keydown(int key)
mode_countdown(-1);
return;
}
control::pbctrl_bdoor_controller(key);
control::pbctrl_bdoor_controller(static_cast<char>(key));
if (key == options::Options.LeftFlipperKey)
{
MainTable->Message(1000, time_now);
@@ -474,8 +502,8 @@ void pb::keydown(int key)
ball->Acceleration.X = 0.0;
break;
case 'H':
char String1[200];
lstrcpyA(String1, pinball::get_rc_string(26, 0));
wchar_t String1[200];
lstrcpyW(String1, pinball::get_rc_Wstring(26, 0));
high_score::show_and_set_high_score_dialog(highscore_table, 1000000000, 1, String1);
break;
case 'M':
@@ -528,7 +556,7 @@ void pb::end_game()
{
int scores[4]{};
int scoreIndex[4]{};
char String1[200];
wchar_t String1[200];
mode_change(2);
int playerCount = MainTable->PlayerCount;
@@ -565,7 +593,7 @@ void pb::end_game()
int position = high_score::get_score_position(highscore_table, scores[i]);
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);
}
}

View File

@@ -10,7 +10,8 @@ class pb
public:
static int time_ticks;
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 TPinballTable* MainTable;
static high_score_struct highscore_table[5];

View File

@@ -8,7 +8,8 @@ int pinball::quickFlag = 0;
TTextBox* pinball::InfoTextBox;
TTextBox* pinball::MissTextBox;
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::RightShift = -1;
@@ -22,6 +23,16 @@ char* pinball::get_rc_string(int uID, int a2)
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)
{
char buffer[255];

View File

@@ -17,11 +17,13 @@ public:
static int LeftShift;
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 void FindShiftKeys();
static void adjust_priority(int priority);
static int make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize = 0x12Cu);
private:
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 "memory.h"
int render::blit = 0;
int render::many_dirty, render::many_sprites, render::many_balls;
render_sprite_type_struct **render::dirty_list, **render::sprite_list, **render::ball_list;
zmap_header_type* render::background_zmap;
@@ -60,83 +59,69 @@ void render::uninit()
many_balls = 0;
}
void render::update()
void render::update(bool blit)
{
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)
{
auto sprite = *dirtyPtr;
if ((*dirtyPtr)->DirtyRect.Width > 0 && (sprite->VisualType == VisualType::None || sprite->VisualType ==
VisualType::Sprite))
repaint(*dirtyPtr);
++dirtyPtr;
auto curSprite = dirty_list[index];
bool clearSprite = false;
switch (curSprite->VisualType)
{
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)
{
paint_balls();
gdrv::start_blit_sequence();
auto xPos = vscreen.XPosition + offset_x;
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 dirtyRect = &(*dirtyPtr)->DirtyRect;
auto width2 = (*dirtyPtr)->DirtyRect.Width;
auto sprite = dirty_list[index];
auto dirtyRect = &sprite->DirtyRect;
auto width2 = sprite->DirtyRect.Width;
if (width2 > 0)
gdrv::blit_sequence(
&vscreen,
@@ -147,21 +132,16 @@ void render::update()
width2,
dirtyRect->Height);
auto rect = &sprite->BmpRectCopy;
rect->XPosition = dirtyRect->XPosition;
rect->YPosition = dirtyRect->YPosition;
rect->Width = dirtyRect->Width;
rect->Height = dirtyRect->Height;
sprite->BmpRectCopy = *dirtyRect;
if (sprite->UnknownFlag != 0)
remove_sprite(sprite);
}
dirtyPtr = ball_list;
for (int index = 0; index < many_balls; ++dirtyPtr, ++index)
for (int index = 0; index < many_balls; ++index)
{
auto rectCopy = &(*dirtyPtr)->BmpRectCopy;
auto dirtyRect = &(*dirtyPtr)->DirtyRect;
auto sprite = ball_list[index];
auto rectCopy = &sprite->BmpRectCopy;
auto dirtyRect = &sprite->DirtyRect;
if (maths::overlapping_box(dirtyRect, rectCopy, &overlapRect) && dirtyRect->Width > 0)
{
if (overlapRect.Width > 0)
@@ -198,13 +178,22 @@ void render::update()
}
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;
unpaint_balls();
}
void render::paint()
{
paint_balls();
@@ -473,7 +462,7 @@ void render::paint_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];
if (curBall->DirtyRect.Width > 0)

View File

@@ -31,7 +31,6 @@ struct render_sprite_type_struct
class render
{
public:
static int blit;
static int many_dirty, many_sprites, many_balls;
static render_sprite_type_struct **dirty_list, **sprite_list, **ball_list;
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 uninit();
static void update();
static void update(bool blit);
static void paint();
static void sprite_modified(render_sprite_type_struct* sprite);
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_EditName4 604
#define DLG_HIGHSCORES_EditName5 605
#define Menu1_AlternativeRender 601
#define Menu1_Language 700
#define Menu1_LanguageMax 724
// Next default values for new objects
//

View File

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