56 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
Muzychenko Andrey
bad55d49cf Updated readme. 2021-02-20 15:58:16 +03:00
Muzychenko Andrey
98f234fce3 Replaced GlobalAlloc with malloc.
WaveMix keeps GlobalAlloc for authenticity.
Fixed float to double casts.
Some cleanup.
2021-02-18 12:53:25 +03:00
Muzychenko Andrey
55984fbb08 Fixed x64 build warnings.
Replaced __intN with intN_t.
Some cleanup.
2021-02-16 19:03:45 +03:00
Muzychenko Andrey
5c3e9fea4c Added FT music loader.
Fixed mouse lock.
Some cleanup.
2021-02-15 18:55:54 +03:00
Muzychenko Andrey
debe52c1e0 Added scalable window, mouse controls. 2021-02-09 18:09:44 +03:00
Muzychenko Andrey
1c5256a4c6 Added table resolution support.
Only works with FT .dat file.
FT music does not work - different format.
2021-02-06 16:53:47 +03:00
Muzychenko Andrey
d594f5fdb7 Converted memory to direct pointers.
Fixed memory leaks in uninit.
Fixed some of the code analysis warnings.
Enabled /MP build.
Cleaned up the code.
2021-02-02 18:29:54 +03:00
Muzychenko Andrey
49f6132d23 Added loader for Full Tilt .dat files, v1.
Works with some data hacks in lowest resolution.
Seems to work ok, even though BL is still 3DPB.
2021-01-31 17:29:53 +03:00
Muzychenko Andrey
6ff457eb68 Cleaned up objlist_class. 2021-01-30 14:19:25 +03:00
Muzychenko Andrey
5b9a1ff95d Create LICENSE
Some docs might be incompatible with MIT, to be reviewed later.
2021-01-29 19:47:23 +03:00
Muzychenko Andrey
232f24a2a2 Added Readme.md 2021-01-29 19:34:45 +03:00
oz
efc56e82d9 Compile releases with Windows subsystem. 2021-01-29 17:49:00 +03:00
100 changed files with 3590 additions and 2078 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

@@ -1,3 +1,3 @@
rc /Fo.\DrMem\SpaceCadetPinball.res ".\SpaceCadetPinball\SpaceCadetPinball.rc"
cl /Zi /MT /EHsc /O /Ob0 /cgthreads4 /Fo.\DrMem\ /Fe.\DrMem\myapp.exe ".\SpaceCadetPinball\*.cpp" Comctl32.lib Winmm.lib Htmlhelp.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ".\DrMem\SpaceCadetPinball.res"
cl /Zi /MT /MP /EHsc /O /Ob0 /cgthreads4 /Fo.\DrMem\ /Fe.\DrMem\myapp.exe ".\SpaceCadetPinball\*.cpp" Comctl32.lib Winmm.lib Htmlhelp.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ".\DrMem\SpaceCadetPinball.res"

View File

@@ -39,21 +39,21 @@ Type Meaning/comments
9 String (content)
10 Array of 16bits integer values
11 Array of 32bits floating point values (collision box, ...)
12 16 bpp bitmap (Heightmap?)
12 16 bpp bitmap (zMap)
//-- 8bpp bitmap data header --//
+0: Unknown (0) BYTE
+0: Resolution BYTE 0=640x480, 1=800x600, 2=1024x768, -1=Load in all resolutions
+1: Width WORD
+3: Height WORD
+5: X position WORD
+7 Y position WORD
+9: Size of bitmap DWORD
+13: Unknown (1) BYTE
+13: Flags BYTE bit0=Raw bmp align; bit1=DibBitmap, raw when 0; bit2=Spliced bitmap (aka skipline), combines bmp and zMap in RLE-like way
+14: Bitmap data BYTE*(DWORD@+9)
//-- 16bpp bitmap data header --//
//-- 16bpp zMap data header --//
+0: Width WORD
+2: Height WORD
+4: Pitch/2 WORD
@@ -62,6 +62,16 @@ Type Meaning/comments
+12: Unknown (80) WORD
+14: Bitmap data BYTE*(DWORD@+9)
//-- 16bpp zMap data header full tilt --//
+0: Resolution BYTE 0=640x480, 1=800x600, 2=1024x768, -1=Load in all resolutions
+1: Width WORD
+3: Height WORD
+5: Pitch/2 WORD
+7: Unknown (0) DWORD
+11: Unknown (0) WORD
+13: Unknown (80) WORD
+15: Bitmap data BYTE*(DWORD@+9)
//-- Pinball 3D remarkable groups --//

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020-2021 Andrey Muzychenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

39
README.md Normal file
View File

@@ -0,0 +1,39 @@
# SpaceCadetPinball
**Summary:** Reverse engineering of `3D Pinball for Windows Space Cadet`, a game bundled with Windows.
**How to play:** Place compiled exe into a folder containing original game resources (not included).\
Supports data files from Windows and Full Tilt versions of the game.
\
\
\
\
\
\
**Source:**
* `pinball.exe` from `Windows XP` (SHA-1 `2A5B525E0F631BB6107639E2A69DF15986FB0D05`) and its public PDB
* `CADET.EXE` 32bit version from `Full Tilt! Pinball` (SHA-1 `3F7B5699074B83FD713657CD94671F2156DBEDC4`)
**Tools used:** `Ghidra`, `Ida`, `Visual Studio`
**What was done:**
* All structures were populated, globals and locals named.
* All subs were decompiled, C pseudo code was converted to compilable C++. Loose (namespace?) subs were assigned to classes.
**Compiling:**\
Project uses `C++11` features and depends on Windows libs.\
Compile with Visual Studio; tested with 2017 and 2019.
**Plans:**
* ~~Decompile original game~~
* ~~Resizable window, scaled graphics~~
* ~~Loader for high-res sprites from CADET.DAT~~
* ~~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
**On 64-bit bug that killed the game:**\
I did not find it, decompiled game worked in x64 mode on the first try.\
It was either lost in decompilation or introduced in x64 port/not present in x86 build.\
Based on public description of the bug (no ball collision), I guess that the bug was in `TEdgeManager::TestGridBox`

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

@@ -1,6 +1,8 @@
#include "pch.h"
#include "Sound.h"
#include "pb.h"
#include "pinball.h"
#include "WaveMix.h"
#include "winmain.h"
@@ -45,7 +47,9 @@ int Sound::Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWA
}
else
{
MessageBoxA(winmain::hwnd_frame, pinball::get_rc_string(42, 0), pinball::WindowName, 0x2000u);
/*FT does not have the file, defaults work OK*/
if (!pb::FullTiltMode)
MessageBoxW(winmain::hwnd_frame, pinball::get_rc_Wstring(42, 0), L"", 0x2000u);
}
WndClass.style = 0;
@@ -143,7 +147,7 @@ void Sound::Close()
}
}
void Sound::PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, __int16 loops)
void Sound::PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops)
{
MIXPLAYPARAMS mixParams{};

View File

@@ -10,7 +10,7 @@ public:
static void Activate();
static void Deactivate();
static void Close();
static void PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, __int16 loops);
static void PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops);
static MIXWAVE* LoadWaveFile(LPCSTR lpName);
static void FreeSound(MIXWAVE* wave);
static void Flush(int channelFrom, int channelTo);

View File

@@ -16,21 +16,21 @@
#include "winmain.h"
int main()
{
{
{
// Testing with UI
char cmdLine[1]{};
WinMain(GetModuleHandleA(nullptr), 0, cmdLine, 10);
WinMain(GetModuleHandleA(nullptr), nullptr, cmdLine, 10);
return 0;
}
std::cout << "Hello World!\n";
gdrv::init(0, 0);
auto dib = gdrv::DibCreate(8, 1, 1);
gdrv::DibSetUsage(dib, 0, 1);
objlist_class d = objlist_class(2, 4);
for (int i = 0; i < 100; i++)
std::cout << "Hello World!\n";
gdrv::init(nullptr, nullptr);
auto dib = gdrv::DibCreate(8, 1, 1);
gdrv::DibSetUsage(dib, nullptr, 1);
auto d = objlist_class<void>(2, 4);
for (size_t i = 0; i < 100; i++)
{
d.Add((void*)i);
}

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>
@@ -94,6 +235,26 @@
<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|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>
@@ -110,6 +271,24 @@
<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)'=='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>
@@ -128,9 +307,73 @@
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<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|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>
@@ -148,9 +391,73 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<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|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>
@@ -219,7 +526,6 @@
<ClInclude Include="TTimer.h" />
<ClInclude Include="TTripwire.h" />
<ClInclude Include="TWall.h" />
<ClInclude Include="TZmapList.h" />
<ClInclude Include="WaveMix.h" />
<ClInclude Include="winmain.h" />
<ClInclude Include="zdrv.h" />
@@ -234,15 +540,22 @@
<ClCompile Include="memory.cpp" />
<ClCompile Include="midi.cpp" />
<ClCompile Include="nudge.cpp" />
<ClCompile Include="objlist_class.cpp" />
<ClCompile Include="options.cpp" />
<ClCompile Include="partman.cpp" />
<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

@@ -81,9 +81,6 @@
<ClInclude Include="TTimer.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TZmapList.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="memory.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -236,9 +233,6 @@
<ClCompile Include="SpaceCadetPinball.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="objlist_class.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="partman.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@@ -2,17 +2,19 @@
#include "TBall.h"
#include "fullscrn.h"
#include "loader.h"
#include "maths.h"
#include "objlist_class.h"
#include "pb.h"
#include "proj.h"
#include "render.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
{
visualStruct visual{};
char ballGroupName[10]{"ball"};
TimeNow = 0.0;
RayMaxDistance = 0.0;
@@ -30,8 +32,13 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
Position.X = 0.0;
Position.Y = 0.0;
ListBitmap = new TZmapList(0, 4);
auto groupIndex = loader::query_handle("ball");
ListBitmap = new objlist_class<gdrv_bitmap8>(0, 4);
/*Full tilt: ball is ballN, where N[0,2] resolution*/
if (pb::FullTiltMode)
ballGroupName[4] = '0' + fullscrn::GetResolution();
auto groupIndex = loader::query_handle(ballGroupName);
Offset = *loader::query_float_attribute(groupIndex, 0, 500);
auto visualCount = loader::query_visual_states(groupIndex);
auto index = 0;
@@ -73,12 +80,12 @@ void TBall::Repaint()
auto zArrPtr = VisualZArray;
int index;
for (index = 0; index < ListBitmap->Count() - 1; ++index, zArrPtr++)
for (index = 0; index < ListBitmap->GetCount() - 1; ++index, zArrPtr++)
{
if (*zArrPtr <= zDepth) break;
}
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(index));
auto bmp = ListBitmap->Get(index);
render::ball_set(
RenderSprite,
bmp,

View File

@@ -4,9 +4,9 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "timer.h"
#include "TZmapList.h"
TBlocker::TBlocker(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
@@ -46,7 +46,7 @@ int TBlocker::Message(int code, float value)
case 52:
ActiveFlag = 1;
loader::play_sound(SoundIndex4);
render::sprite_set_bitmap(RenderSprite, static_cast<gdrv_bitmap8*>(ListBitmap->Get(0)));
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
break;
case 59:
break;
@@ -57,7 +57,7 @@ int TBlocker::Message(int code, float value)
timer::kill(Timer);
float timerTime;
if (value <= 0.0)
if (value <= 0.0f)
timerTime = 0.0;
else
timerTime = value;

View File

@@ -4,10 +4,10 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TBumper::TBumper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
@@ -29,8 +29,8 @@ int TBumper::Message(int code, float value)
case 11:
{
auto nextBmp = static_cast<int>(floor(value));
if (2 * nextBmp > ListBitmap->Count() - 1)
nextBmp = (ListBitmap->Count() - 1) / 2;
if (2 * nextBmp > ListBitmap->GetCount() - 1)
nextBmp = (ListBitmap->GetCount() - 1) / 2;
if (nextBmp < 0)
nextBmp = 0;
if (nextBmp != BmpIndex)
@@ -48,7 +48,7 @@ int TBumper::Message(int code, float value)
case 12:
{
auto nextBmp = BmpIndex + 1;
auto maxBmp = ListBitmap->Count() - 1;
auto maxBmp = ListBitmap->GetCount() - 1;
if (2 * nextBmp > maxBmp)
nextBmp = maxBmp / 2;
TBumper::Message(11, static_cast<float>(nextBmp));
@@ -124,8 +124,8 @@ int TBumper::get_scoring(int index)
void TBumper::TimerExpired(int timerId, void* caller)
{
auto bump = static_cast<TBumper*>(caller);
auto bmp = static_cast<gdrv_bitmap8*>(bump->ListBitmap->Get(bump->BmpIndex * 2));
auto zMap = static_cast<zmap_header_type*>(bump->ListZMap->Get(bump->BmpIndex * 2));
auto bmp = bump->ListBitmap->Get(bump->BmpIndex * 2);
auto zMap = bump->ListZMap->Get(bump->BmpIndex * 2);
bump->Timer = 0;
render::sprite_set(
bump->RenderSprite,
@@ -139,8 +139,8 @@ void TBumper::TimerExpired(int timerId, void* caller)
void TBumper::Fire()
{
int bmpIndex = 2 * BmpIndex + 1;
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(bmpIndex));
auto zMap = static_cast<zmap_header_type*>(ListZMap->Get(bmpIndex));
auto bmp = ListBitmap->Get(bmpIndex);
auto zMap = ListZMap->Get(bmpIndex);
render::sprite_set(
RenderSprite,
bmp,

View File

@@ -12,7 +12,7 @@ TCollisionComponent::TCollisionComponent(TPinballTable* table, int groupIndex, b
{
visualStruct visual{};
EdgeList = new objlist_class(4, 4);
EdgeList = new objlist_class<TEdgeSegment>(4, 4);
ActiveFlag = 1;
if (GroupName != nullptr)
UnusedBaseFlag = 1;
@@ -42,9 +42,9 @@ TCollisionComponent::TCollisionComponent(TPinballTable* table, int groupIndex, b
TCollisionComponent::~TCollisionComponent()
{
for (TEdgeSegment* edge; EdgeList->Count() > 0;)
for (TEdgeSegment* edge; EdgeList->GetCount() > 0;)
{
edge = static_cast<TEdgeSegment*>(EdgeList->Get(0));
edge = EdgeList->Get(0);
EdgeList->Delete(edge);
delete edge;
}
@@ -54,9 +54,9 @@ TCollisionComponent::~TCollisionComponent()
void TCollisionComponent::port_draw()
{
for (int index = EdgeList->Count() - 1; index >= 0; index--)
for (int index = EdgeList->GetCount() - 1; index >= 0; index--)
{
static_cast<TEdgeSegment*>(EdgeList->Get(index))->port_draw();
EdgeList->Get(index)->port_draw();
}
}
@@ -70,7 +70,7 @@ int TCollisionComponent::DefaultCollision(TBall* ball, vector_type* nextPosition
auto projSpeed = maths::basic_collision(ball, nextPosition, direction, Elasticity, Smoothness, Threshold, Boost);
if (projSpeed <= Threshold)
{
if (projSpeed > 0.2)
if (projSpeed > 0.2f)
{
if (SoftHitSoundId)
loader::play_sound(SoftHitSoundId);
@@ -92,7 +92,7 @@ void TCollisionComponent::Collision(TBall* ball, vector_type* nextPosition, vect
maths::basic_collision(ball, nextPosition, direction, Elasticity, Smoothness, 1000000000.0, 0.0);
return;
}
double projSpeed = maths::basic_collision(
auto projSpeed = maths::basic_collision(
ball,
nextPosition,
direction,
@@ -102,7 +102,7 @@ void TCollisionComponent::Collision(TBall* ball, vector_type* nextPosition, vect
Boost);
if (projSpeed <= Threshold)
{
if (projSpeed <= 0.2)
if (projSpeed <= 0.2f)
return;
soundIndex = SoftHitSoundId;
}

View File

@@ -1,7 +1,6 @@
#pragma once
#include "TPinballComponent.h"
class objlist_class;
struct vector_type;
class TEdgeSegment;
class TBall;
@@ -9,7 +8,7 @@ class TBall;
class TCollisionComponent : public TPinballComponent
{
public:
objlist_class* EdgeList;
objlist_class<TEdgeSegment>* EdgeList;
float Elasticity;
float Smoothness;
float Boost;

View File

@@ -10,7 +10,7 @@
TComponentGroup::TComponentGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, false)
{
List = new objlist_class(4, 4);
List = new objlist_class<TPinballComponent>(4, 4);
Timer = 0;
if (groupIndex > 0)
{
@@ -45,14 +45,14 @@ int TComponentGroup::Message(int code, float value)
timer::kill(this->Timer);
this->Timer = 0;
}
if (value > 0.0)
if (value > 0.0f)
this->Timer = timer::set(value, this, NotifyTimerExpired);
}
else if (code <= 1007 || code > 1011 && code != 1020 && code != 1022)
{
for (int i = 0; i < List->Count(); i++)
for (int i = 0; i < List->GetCount(); i++)
{
static_cast<TPinballComponent*>(List->Get(i))->Message(code, value);
List->Get(i)->Message(code, value);
}
}
return 0;

View File

@@ -1,7 +1,6 @@
#pragma once
#include "TPinballComponent.h"
class objlist_class;
class TComponentGroup :
public TPinballComponent
@@ -12,6 +11,6 @@ public:
int Message(int code, float value) override;
static void NotifyTimerExpired(int timerId, void* caller);
objlist_class* List;
objlist_class<TPinballComponent>* List;
int Timer;
};

View File

@@ -100,7 +100,7 @@ void TDemo::Collision(TBall* ball, vector_type* nextPosition, vector_type* direc
ball->Position.Y = nextPosition->Y;
ball->RayMaxDistance -= coef;
switch (reinterpret_cast<int>(edge->WallValue))
switch (reinterpret_cast<size_t>(edge->WallValue))
{
case 1400:
if (!FlipLeftTimer && !FlipLeftFlag)

View File

@@ -5,8 +5,8 @@
TEdgeBox::TEdgeBox()
{
EdgeList = new objlist_class(0, 4);
FieldList = new objlist_class(0, 1);
EdgeList = new objlist_class<TEdgeSegment>(0, 4);
FieldList = new objlist_class<field_effect_type>(0, 1);
}
TEdgeBox::~TEdgeBox()

View File

@@ -1,5 +1,9 @@
#pragma once
class objlist_class;
#include "objlist_class.h"
struct field_effect_type;
class TEdgeSegment;
class TEdgeBox
{
@@ -7,7 +11,7 @@ public:
TEdgeBox();
~TEdgeBox();
objlist_class* EdgeList;
objlist_class* FieldList;
objlist_class<TEdgeSegment>* EdgeList;
objlist_class<field_effect_type>* FieldList;
};

View File

@@ -64,9 +64,9 @@ int TEdgeManager::TestGridBox(int x, int y, float* distPtr, TEdgeSegment** edgeD
{
TEdgeBox* edgeBox = &BoxArray[x + y * MaxBoxX];
TEdgeSegment** edgePtr = &EdgeArray[edgeIndex];
for (auto index = edgeBox->EdgeList->Count() - 1; index >= 0; --index)
for (auto index = edgeBox->EdgeList->GetCount() - 1; index >= 0; --index)
{
auto edge = static_cast<TEdgeSegment*>(edgeBox->EdgeList->Get(index));
auto edge = edgeBox->EdgeList->Get(index);
if (!edge->ProcessedFlag && *edge->ActiveFlag && (edge->CollisionGroup & ray->FieldFlag))
{
if (!ball->already_hit(edge))
@@ -94,9 +94,9 @@ void TEdgeManager::FieldEffects(TBall* ball, vector_type* dstVec)
TEdgeBox* edgeBox = &BoxArray[box_x(ball->Position.X) + box_y(ball->Position.Y) *
MaxBoxX];
for (int index = edgeBox->FieldList->Count() - 1; index >= 0; --index)
for (int index = edgeBox->FieldList->GetCount() - 1; index >= 0; --index)
{
auto field = static_cast<field_effect_type*>(edgeBox->FieldList->Get(index));
auto field = edgeBox->FieldList->Get(index);
if (*field->Flag2Ptr && ball->FieldFlag & field->Mask)
{
if (field->CollisionComp->FieldEffect(ball, &vec))

View File

@@ -19,7 +19,7 @@ void TEdgeSegment::port_draw()
}
TEdgeSegment* TEdgeSegment::install_wall(float* floatArr, TCollisionComponent* collComp, char* activeFlagPtr,
unsigned int collisionGroup, float offset, int wallValue)
unsigned int collisionGroup, float offset, size_t wallValue)
{
vector_type center{}, start{}, end{}, prevCenter{}, vec1{}, vec2{}, dstVec{};
TEdgeSegment* edge = nullptr;
@@ -87,15 +87,15 @@ TEdgeSegment* TEdgeSegment::install_wall(float* floatArr, TCollisionComponent* c
center.X = centerX1;
center.Y = centerY1;
if (offset != 0.0)
if (offset != 0.0f)
{
vec1.X = centerX1 - prevCenter.X;
vec1.Y = center.Y - prevCenter.Y;
vec2.X = centerX2 - centerX1;
vec2.Y = centerY2 - center.Y;
maths::cross(&vec1, &vec2, &dstVec);
if (dstVec.Z > 0.0 && offset > 0.0 ||
dstVec.Z < 0.0 && offset < 0.0)
if (dstVec.Z > 0.0f && offset > 0.0f ||
dstVec.Z < 0.0f && offset < 0.0f)
{
float radius = offset * 1.001f;
auto circle = new TCircle(collComp, activeFlagPtr, collisionGroup, &center, radius);

View File

@@ -28,5 +28,5 @@ public:
virtual float FindCollisionDistance(ray_type* ray) = 0;
static TEdgeSegment* install_wall(float* floatArr, TCollisionComponent* collComp, char* activeFlagPtr,
unsigned int collisionGroup, float offset, int wallValue);
unsigned int collisionGroup, float offset, size_t wallValue);
};

View File

@@ -10,7 +10,6 @@
#include "timer.h"
#include "TLine.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TFlagSpinner::TFlagSpinner(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
{
@@ -19,7 +18,7 @@ TFlagSpinner::TFlagSpinner(TPinballTable* table, int groupIndex) : TCollisionCom
Timer = 0;
loader::query_visual(groupIndex, 0, &visual);
end.X = *visual.FloatArr;
end.X = visual.FloatArr[0];
end.Y = visual.FloatArr[1];
start.X = visual.FloatArr[2];
start.Y = visual.FloatArr[3];
@@ -62,8 +61,8 @@ int TFlagSpinner::Message(int code, float value)
Timer = 0;
}
BmpIndex = 0;
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
auto zMap = static_cast<zmap_header_type*>(ListZMap->Get(0));
auto bmp = ListBitmap->Get(0);
auto zMap = ListZMap->Get(0);
render::sprite_set(
RenderSprite,
bmp,
@@ -83,7 +82,7 @@ void TFlagSpinner::Collision(TBall* ball, vector_type* nextPosition, vector_type
ball->not_again(edge);
SpinDirection = 2 * (PrevCollider != edge) - 1;
if (ball->Speed == 0.0)
if (ball->Speed == 0.0f)
Speed = MinSpeed;
else
Speed = ball->Speed * 20.0f;
@@ -109,7 +108,7 @@ void TFlagSpinner::NextFrame()
{
BmpIndex += SpinDirection;
int bmpIndex = BmpIndex;
int bmpCount = ListBitmap->Count();
int bmpCount = ListBitmap->GetCount();
if (bmpIndex >= bmpCount)
BmpIndex = 0;
else if (bmpIndex < 0)
@@ -124,8 +123,8 @@ void TFlagSpinner::NextFrame()
control::handler(62, this);
}
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(BmpIndex));
auto zMap = static_cast<zmap_header_type*>(ListZMap->Get(BmpIndex));
auto bmp = ListBitmap->Get(BmpIndex);
auto zMap = ListZMap->Get(BmpIndex);
render::sprite_set(
RenderSprite,
bmp,

View File

@@ -4,11 +4,11 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "pb.h"
#include "render.h"
#include "TFlipperEdge.h"
#include "timer.h"
#include "TZmapList.h"
TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
{
@@ -21,12 +21,16 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
Timer = 0;
Smoothness = visual.Smoothness;
auto floatArr = loader::query_float_attribute(groupIndex, 0, 803);
auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 805);
auto floatArr3 = loader::query_float_attribute(groupIndex, 0, 804);
auto collMult = *floatArr;
auto bmpCoef2 = *floatArr2;
auto bmpCoef1 = *floatArr3;
auto collMult = *loader::query_float_attribute(groupIndex, 0, 803);
auto 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)
{
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));
auto origin = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, 0, 800));
@@ -38,8 +42,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
origin,
vecT1,
vecT2,
bmpCoef1,
bmpCoef2,
extendTime,
retractTime,
collMult,
Elasticity,
Smoothness);
@@ -47,8 +51,8 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
FlipperEdge = flipperEdge;
if (flipperEdge)
{
BmpCoef1 = flipperEdge->BmpCoef1 / static_cast<float>(ListBitmap->Count() - 1);
BmpCoef2 = flipperEdge->BmpCoef2 / static_cast<float>(ListBitmap->Count() - 1);
ExtendAnimationFrameTime = flipperEdge->ExtendTime / static_cast<float>(ListBitmap->GetCount() - 1);
RetractAnimationFrameTime = flipperEdge->RetractTime / static_cast<float>(ListBitmap->GetCount() - 1);
}
BmpIndex = 0;
InputTime = 0.0;
@@ -64,46 +68,44 @@ 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;
if (timerTime < 0.0)
// Message arrived before animation is finished
auto inputDt = value - FlipperEdge->InputTime;
timerTime = inputDt - floor(inputDt / TimerTime) * TimerTime;
if (timerTime < 0.0f)
timerTime = 0.0;
}
else
{
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)
@@ -133,52 +135,46 @@ 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->Count();
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->Count() - 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 = static_cast<gdrv_bitmap8*>(flip->ListBitmap->Get(flip->BmpIndex));
auto zMap = static_cast<zmap_header_type*>(flip->ListZMap->Get(flip->BmpIndex));
auto bmp = flip->ListBitmap->Get(flip->BmpIndex);
auto zMap = flip->ListZMap->Get(flip->BmpIndex);
render::sprite_set(
flip->RenderSprite,
bmp,

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;
@@ -48,7 +48,7 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi
AngleMax = acos(maths::DotProduct(&vecDir1, &vecDir2));
maths::cross(&vecDir1, &vecDir2, &crossProd);
if (crossProd.Z < 0.0)
if (crossProd.Z < 0.0f)
AngleMax = -AngleMax;
FlipperFlag = 0;
Angle1 = 0.0;
@@ -67,7 +67,7 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi
B2Src.X = dirY1 * CircleT1Radius + vecT1->X;
B2Src.Y = dirX1 * CircleT1Radius + vecT1->Y;
if (AngleMax < 0.0)
if (AngleMax < 0.0f)
{
maths::vswap(&A1Src, &B1Src);
maths::vswap(&A2Src, &B2Src);
@@ -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;
@@ -122,7 +122,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.MaxDistance = ogRay->MaxDistance;
srcRay.Origin = ogRay->Origin;
auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
if (distance == 0.0)
if (distance == 0.0f)
{
NextBallPosition = dstRay.Origin;
NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
@@ -167,14 +167,14 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09)
if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09f)
{
srcRay.Direction.X = RotOrigin.X - ogRay->Origin.X;
srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y;
maths::normalize_2d(&srcRay.Direction);
srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09)
if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09f)
{
return 1e+09;
}
@@ -221,7 +221,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.Origin.X = posX - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = posY - srcRay.Direction.Y * 5.0f;
srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09)
if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09f)
{
NextBallPosition.X = posX;
NextBallPosition.Y = posY;
@@ -252,7 +252,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
CollisionDirection = dstRay.Direction;
if (distance >= 1e+09)
if (distance >= 1e+09f)
{
return 1e+09;
}
@@ -267,7 +267,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.Origin = ogRay->Origin;
srcRay.MaxDistance = rayMaxDistance;
auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
if (distance < 1e+09)
if (distance < 1e+09f)
{
NextBallPosition = dstRay.Origin;
NextBallPosition.X -= srcRay.Direction.X * 1e-05f;
@@ -276,11 +276,11 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
if (FlipperFlag == 2)
{
linePtr = &lineB.PerpendicularL;
CollisionFlag1 = AngleMax <= 0.0;
CollisionFlag1 = AngleMax <= 0.0f;
}
else
{
CollisionFlag1 = AngleMax > 0.0;
CollisionFlag1 = AngleMax > 0.0f;
linePtr = &lineA.PerpendicularL;
}
CollisionLinePerp = *linePtr;
@@ -310,12 +310,12 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float coef)
float dx = NextBallPosition.X - RotOrigin.X;
float dy = NextBallPosition.Y - RotOrigin.Y;
float distance = dy * dy + dx * dx;
if (circlebase.RadiusSq * 1.01 < distance)
if (circlebase.RadiusSq * 1.01f < distance)
{
float v11;
float v20 = sqrt(distance / DistanceDivSq) * (fabs(AngleMax) / AngleMult);
float dot1 = maths::DotProduct(&CollisionLinePerp, &CollisionDirection);
if (dot1 >= 0.0)
if (dot1 >= 0.0f)
v11 = dot1 * v20;
else
v11 = 0.0;
@@ -323,7 +323,7 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float coef)
}
}
float threshold = boost <= 0.0 ? 1000000000.0f : -1.0f;
float threshold = boost <= 0.0f ? 1000000000.0f : -1.0f;
maths::basic_collision(
ball,
&NextBallPosition,
@@ -339,7 +339,7 @@ void TFlipperEdge::EdgeCollision(TBall* ball, float coef)
float dx = NextBallPosition.X - RotOrigin.X;
float dy = NextBallPosition.Y - RotOrigin.Y;
float distance = dy * dy + dx * dx;
if (circlebase.RadiusSq * 1.01 < distance)
if (circlebase.RadiusSq * 1.01f < distance)
elasticity = (1.0f - sqrt(distance / DistanceDivSq)) * Elasticity;
else
elasticity = Elasticity;
@@ -420,10 +420,10 @@ float TFlipperEdge::flipper_angle(float timeNow)
if (!FlipperFlag)
return Angle1;
float angle = (Angle1 - Angle2) / AngleMax * AngleMult;
if (angle < 0.0)
if (angle < 0.0f)
angle = -angle;
if (angle >= 0.0000001)
if (angle >= 0.0000001f)
angle = (timeNow - InputTime) / angle;
else
angle = 1.0;
@@ -439,23 +439,23 @@ int TFlipperEdge::is_ball_inside(float x, float y)
vector_type testPoint{};
float dx = RotOrigin.X - x;
float dy = RotOrigin.Y - y;
if ((A2.X - A1.X) * (y - A1.Y) - (A2.Y - A1.Y) * (x - A1.X) >= 0.0 &&
(B1.X - A2.X) * (y - A2.Y) - (B1.Y - A2.Y) * (x - A2.X) >= 0.0 &&
(B2.X - B1.X) * (y - B1.Y) - (B2.Y - B1.Y) * (x - B1.X) >= 0.0 &&
(A1.X - B2.X) * (y - B2.Y) - (A1.Y - B2.Y) * (x - B2.X) >= 0.0 ||
if ((A2.X - A1.X) * (y - A1.Y) - (A2.Y - A1.Y) * (x - A1.X) >= 0.0f &&
(B1.X - A2.X) * (y - A2.Y) - (B1.Y - A2.Y) * (x - A2.X) >= 0.0f &&
(B2.X - B1.X) * (y - B1.Y) - (B2.Y - B1.Y) * (x - B1.X) >= 0.0f &&
(A1.X - B2.X) * (y - B2.Y) - (A1.Y - B2.Y) * (x - B2.X) >= 0.0f ||
dy * dy + dx * dx <= CirclebaseRadiusSq ||
(T1.Y - y) * (T1.Y - y) + (T1.X - x) * (T1.X - x) < CircleT1RadiusSq)
{
float flipperLR = AngleMax < 0.0 ? -1.0f : 1.0f;
float flipperLR = AngleMax < 0.0f ? -1.0f : 1.0f;
if (FlipperFlag == 1)
testPoint = AngleMax < 0.0 ? B1 : B2;
testPoint = AngleMax < 0.0f ? B1 : B2;
else if (FlipperFlag == 2)
testPoint = AngleMax < 0.0 ? A2 : A1;
testPoint = AngleMax < 0.0f ? A2 : A1;
else
testPoint = T1;
if (((y - testPoint.Y) * (RotOrigin.X - testPoint.X) -
(x - testPoint.X) * (RotOrigin.Y - testPoint.Y)) * flipperLR < 0.0)
(x - testPoint.X) * (RotOrigin.Y - testPoint.Y)) * flipperLR < 0.0f)
return 4;
return 5;
}
@@ -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

@@ -4,8 +4,8 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "TZmapList.h"
TGate::TGate(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
@@ -15,7 +15,7 @@ TGate::TGate(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
SoundIndex4 = visual.SoundIndex4;
SoundIndex3 = visual.SoundIndex3;
ActiveFlag = 1;
render::sprite_set_bitmap(RenderSprite, static_cast<gdrv_bitmap8*>(ListBitmap->Get(0)));
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
control::handler(1024, this);
}
@@ -32,7 +32,7 @@ int TGate::Message(int code, float value)
else if (code == 54 || code == 1024)
{
ActiveFlag = 1;
render::sprite_set_bitmap(RenderSprite, static_cast<gdrv_bitmap8*>(ListBitmap->Get(0)));
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
if (code == 54)
loader::play_sound(SoundIndex4);
}

View File

@@ -5,6 +5,7 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "pb.h"
#include "TBall.h"
#include "timer.h"
#include "TPinballTable.h"
@@ -19,26 +20,19 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
MessageField = 0;
Timer = 0;
BallCapturedFlag = 0;
auto floatArr1 = loader::query_float_attribute(groupIndex, 0, 407);
if (floatArr1)
Unknown3 = *floatArr1;
else
Unknown3 = 0.25;
auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 701);
if (floatArr2)
GravityMult = *floatArr2;
else
GravityMult = 0.5;
Unknown3 = loader::query_float_attribute(groupIndex, 0, 407, 0.25f);
GravityMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f);
GravityPull = *loader::query_float_attribute(groupIndex, 0, 305);
loader::query_visual(groupIndex, 0, &visual);
Circle.Center.X = visual.FloatArr[0];
Circle.Center.Y = visual.FloatArr[1];
Circle.RadiusSq = *loader::query_float_attribute(groupIndex, 0, 306) * visual.FloatArr[2];
if (Circle.RadiusSq == 0.0)
if (Circle.RadiusSq == 0.0f)
Circle.RadiusSq = 0.001f;
auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup, reinterpret_cast<vector_type*>(visual.FloatArr),
auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup,
reinterpret_cast<vector_type*>(visual.FloatArr),
Circle.RadiusSq);
if (tCircle)
{
@@ -49,6 +43,10 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
ZSetValue = loader::query_float_attribute(groupIndex, 0, 408)[2];
FieldFlag = static_cast<int>(floor(*loader::query_float_attribute(groupIndex, 0, 1304)));
/*Full tilt hack - FieldFlag should be on*/
if (pb::FullTiltMode)
FieldFlag = 1;
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
circle.RadiusSq = Circle.RadiusSq;
circle.Center.X = Circle.Center.X;
@@ -84,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,10 +5,10 @@
#include "control.h"
#include "loader.h"
#include "maths.h"
#include "objlist_class.h"
#include "render.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TKickback::TKickback(TPinballTable* table, int groupIndex): TCollisionComponent(table, groupIndex, true)
{
@@ -66,8 +66,8 @@ void TKickback::TimerExpired(int timerId, void* caller)
loader::play_sound(kick->HardHitSoundId);
if (kick->ListBitmap)
{
auto bmp = static_cast<gdrv_bitmap8*>(kick->ListBitmap->Get(1));
auto zMap = static_cast<zmap_header_type*>(kick->ListZMap->Get(1));
auto bmp = kick->ListBitmap->Get(1);
auto zMap = kick->ListZMap->Get(1);
render::sprite_set(
kick->RenderSprite,
bmp,
@@ -80,8 +80,8 @@ void TKickback::TimerExpired(int timerId, void* caller)
{
if (kick->ListBitmap)
{
auto bmp = static_cast<gdrv_bitmap8*>(kick->ListBitmap->Get(0));
auto zMap = static_cast<zmap_header_type*>(kick->ListZMap->Get(0));
auto bmp = kick->ListBitmap->Get(0);
auto zMap = kick->ListZMap->Get(0);
render::sprite_set(
kick->RenderSprite,
bmp,

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"
@@ -30,10 +31,10 @@ TKickout::TKickout(TPinballTable* table, int groupIndex, bool someFlag): TCollis
SoftHitSoundId = visual.SoftHitSoundId;
HardHitSoundId = visual.Kicker.HardHitSoundId;
Circle.Center.X = *visual.FloatArr;
Circle.Center.X = visual.FloatArr[0];
Circle.Center.Y = visual.FloatArr[1];
Circle.RadiusSq = *loader::query_float_attribute(groupIndex, 0, 306) * visual.FloatArr[2];
if (Circle.RadiusSq == 0.0)
if (Circle.RadiusSq == 0.0f)
Circle.RadiusSq = 0.001f;
auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup,
reinterpret_cast<vector_type*>(visual.FloatArr), Circle.RadiusSq);
@@ -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;
@@ -67,7 +69,7 @@ int TKickout::Message(int code, float value)
case 55:
if (KickFlag1)
{
if (value < 0.0)
if (value < 0.0f)
value = TimerTime1;
Timer = timer::set(value, this, TimerExpired);
}

View File

@@ -4,10 +4,10 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TLight::TLight(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, true)
{
@@ -144,13 +144,13 @@ int TLight::Message(int code, float value)
break;
case 11:
BmpIndex2 = static_cast<int>(floor(value));
if (BmpIndex2 > ListBitmap->Count())
BmpIndex2 = ListBitmap->Count();
if (BmpIndex2 > ListBitmap->GetCount())
BmpIndex2 = ListBitmap->GetCount();
bmpIndex = 0;
if (BmpIndex2 < 0)
BmpIndex2 = 0;
Flasher.BmpArr[0] = nullptr;
Flasher.BmpArr[1] = static_cast<gdrv_bitmap8*>(ListBitmap->Get(BmpIndex2));
Flasher.BmpArr[1] = ListBitmap->Get(BmpIndex2);
if (FlasherActive == 0)
{
if (!FlasherFlag1)
@@ -169,8 +169,8 @@ int TLight::Message(int code, float value)
break;
case 12:
bmpIndex = BmpIndex2 + 1;
if (bmpIndex > ListBitmap->Count())
bmpIndex = ListBitmap->Count();
if (bmpIndex > ListBitmap->GetCount())
bmpIndex = ListBitmap->GetCount();
Message(11, static_cast<float>(bmpIndex));
break;
case 13:
@@ -257,7 +257,7 @@ void TLight::Reset()
Flasher.Sprite = RenderSprite;
Flasher.BmpArr[0] = nullptr;
if (ListBitmap)
Flasher.BmpArr[1] = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
Flasher.BmpArr[1] = ListBitmap->Get(0);
Flasher.Unknown4 = 0;
Flasher.Unknown3 = 0;
MessageField = 0;
@@ -270,7 +270,7 @@ void TLight::schedule_timeout(float time)
if (Timer1)
timer::kill(Timer1);
Timer1 = 0;
if (time > 0.0)
if (time > 0.0f)
Timer1 = timer::set(time, this, TimerExpired);
}

View File

@@ -18,8 +18,8 @@ TLightBargraph::TLightBargraph(TPinballTable* table, int groupIndex) : TLightGro
float* floatArr = loader::query_float_attribute(groupIndex, 0, 904);
if (floatArr)
{
int count = 2 * List->Count();
TimerTimeArray = reinterpret_cast<float*>(memory::allocate(count * sizeof(float)));
int count = 2 * List->GetCount();
TimerTimeArray = memory::allocate<float>(count);
if (TimerTimeArray)
{
for (int i = 0; i < count; ++floatArr)
@@ -49,7 +49,7 @@ int TLightBargraph::Message(int code, float value)
TimerBargraph = 0;
}
auto timeIndex = static_cast<int>(floor(value));
auto maxCount = 2 * List->Count();
auto maxCount = 2 * List->GetCount();
if (timeIndex >= maxCount)
timeIndex = maxCount - 1;
if (timeIndex >= 0)
@@ -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

@@ -11,7 +11,7 @@
TLightGroup::TLightGroup(TPinballTable* table, int groupIndex) : TPinballComponent(table, groupIndex, false)
{
List = new objlist_class(4, 4);
List = new objlist_class<TLight>(4, 4);
Timer = 0;
NotifyTimer = 0;
Reset();
@@ -19,10 +19,10 @@ TLightGroup::TLightGroup(TPinballTable* table, int groupIndex) : TPinballCompone
{
int count;
Timer1TimeDefault = *loader::query_float_attribute(groupIndex, 0, 903);
__int16* groupIndArr = loader::query_iattribute(groupIndex, 1027, &count);
int16_t* groupIndArr = loader::query_iattribute(groupIndex, 1027, &count);
for (int index = 0; index < count; ++groupIndArr)
{
auto comp = table->find_component(*groupIndArr);
auto comp = dynamic_cast<TLight*>(table->find_component(*groupIndArr));
if (comp)
List->Add(comp);
++index;
@@ -71,8 +71,8 @@ int TLightGroup::Message(int code, float value)
break;
case 24:
{
auto count = List->Count();
auto lastLight = static_cast<TLight*>(List->Get(count - 1));
auto count = List->GetCount();
auto lastLight = List->Get(count - 1);
if (lastLight->FlasherActive || lastLight->FlasherFlag2 || lastLight->FlasherFlag1)
break;
if (MessageField2)
@@ -85,12 +85,12 @@ int TLightGroup::Message(int code, float value)
auto bmpIndex1 = lastLight->BmpIndex1;
for (auto index = count - 1; index > 0; --index)
{
auto lightCur = static_cast<TLight*>(List->Get(index));
auto lightPrev = static_cast<TLight*>(List->Get(index - 1));
auto lightCur = List->Get(index);
auto lightPrev = List->Get(index - 1);
lightCur->Message(lightPrev->BmpIndex1 != 0, 0.0);
lightCur->MessageField = lightPrev->MessageField;
}
auto firstLight = static_cast<TLight*>(List->Get(0));
auto firstLight = List->Get(0);
firstLight->Message(bmpIndex1 != 0, 0.0);
firstLight->MessageField = lightMessageField;
reschedule_animation(value);
@@ -98,23 +98,23 @@ int TLightGroup::Message(int code, float value)
}
case 25:
{
auto count = List->Count();
auto lastLight = static_cast<TLight*>(List->Get(count - 1));
auto count = List->GetCount();
auto lastLight = List->Get(count - 1);
if (lastLight->FlasherActive || lastLight->FlasherFlag2 || lastLight->FlasherFlag1)
break;
if (MessageField2)
{
TLightGroup::Message(34, 0.0);
}
auto firstLight = static_cast<TLight*>(List->Get(0));
auto firstLight = List->Get(0);
AnimationFlag = 1;
MessageField2 = code;
auto lightMessageField = firstLight->MessageField;
auto bmpIndex1 = firstLight->BmpIndex1;
for (auto index = 0; index < count - 1; index++)
{
auto lightCur = static_cast<TLight*>(List->Get(index));
auto lightNext = static_cast<TLight*>(List->Get(index + 1));
auto lightCur = List->Get(index);
auto lightNext = List->Get(index + 1);
lightCur->Message(lightNext->BmpIndex1 != 0, 0.0);
lightCur->MessageField = lightNext->MessageField;
}
@@ -129,16 +129,16 @@ int TLightGroup::Message(int code, float value)
start_animation();
MessageField2 = code;
AnimationFlag = 0;
auto count = List->Count();
auto lastLight = static_cast<TLight*>(List->Get(count - 1));
auto count = List->GetCount();
auto lastLight = List->Get(count - 1);
auto flasherFlag2 = lastLight->FlasherFlag2;
for (auto i = count - 1; i > 0; --i)
{
auto lightCur = static_cast<TLight*>(List->Get(i));
auto lightPrev = static_cast<TLight*>(List->Get(i - 1));
auto lightCur = List->Get(i);
auto lightPrev = List->Get(i - 1);
lightCur->Message((lightPrev->FlasherFlag2 != 0) + 8, 0.0);
}
auto firstLight = static_cast<TLight*>(List->Get(0));
auto firstLight = List->Get(0);
firstLight->Message((flasherFlag2 != 0) + 8, 0);
reschedule_animation(value);
break;
@@ -149,16 +149,16 @@ int TLightGroup::Message(int code, float value)
start_animation();
MessageField2 = code;
AnimationFlag = 0;
auto count = List->Count();
auto firstLight = static_cast<TLight*>(List->Get(0));
auto count = List->GetCount();
auto firstLight = List->Get(0);
auto flasherFlag2 = firstLight->FlasherFlag2;
for (auto i = 0; i < count - 1; i++)
{
auto lightCur = static_cast<TLight*>(List->Get(i));
auto lightNext = static_cast<TLight*>(List->Get(i + 1));
auto lightCur = List->Get(i);
auto lightNext = List->Get(i + 1);
lightCur->Message((lightNext->FlasherFlag2 != 0) + 8, 0.0);
}
auto lastLight = static_cast<TLight*>(List->Get(count - 1));
auto lastLight = List->Get(count - 1);
lastLight->Message((flasherFlag2 != 0) + 8, 0);
reschedule_animation(value);
break;
@@ -169,12 +169,12 @@ int TLightGroup::Message(int code, float value)
start_animation();
MessageField2 = code;
AnimationFlag = 0;
auto count = List->Count();
auto count = List->GetCount();
for (auto i = 0; i < count - 1; i++)
{
if (rand() % 100 > 70)
{
auto light = static_cast<TLight*>(List->Get(i));
auto light = List->Get(i);
auto randVal = static_cast<float>(rand()) * 0.00003051850947599719f * value * 3.0f + 0.1f;
light->Message(9, randVal);
}
@@ -188,10 +188,10 @@ int TLightGroup::Message(int code, float value)
start_animation();
MessageField2 = code;
AnimationFlag = 0;
auto count = List->Count();
auto count = List->GetCount();
for (auto i = 0; i < count - 1; i++)
{
auto light = static_cast<TLight*>(List->Get(i));
auto light = List->Get(i);
auto randVal = static_cast<float>(rand() % 100 > 70);
light->Message(18, randVal);
}
@@ -201,13 +201,13 @@ int TLightGroup::Message(int code, float value)
case 30:
{
auto noBmpInd1Count = 0;
auto countSub1 = List->Count() - 1;
auto countSub1 = List->GetCount() - 1;
if (countSub1 < 0)
break;
for (auto i = countSub1; i >= 0; i--)
{
if (!static_cast<TLight*>(List->Get(i))->BmpIndex1)
if (!List->Get(i)->BmpIndex1)
++noBmpInd1Count;
}
if (!noBmpInd1Count)
@@ -216,7 +216,7 @@ int TLightGroup::Message(int code, float value)
auto randModCount = rand() % noBmpInd1Count;
for (auto i = countSub1; i >= 0; i--)
{
auto light = static_cast<TLight*>(List->Get(i));
auto light = List->Get(i);
if (!light->BmpIndex1 && randModCount-- == 0)
{
light->Message(1, 0.0);
@@ -231,13 +231,13 @@ int TLightGroup::Message(int code, float value)
case 31:
{
auto bmpInd1Count = 0;
auto countSub1 = List->Count() - 1;
auto countSub1 = List->GetCount() - 1;
if (countSub1 < 0)
break;
for (auto i = countSub1; i >= 0; i--)
{
if (static_cast<TLight*>(List->Get(i))->BmpIndex1)
if (List->Get(i)->BmpIndex1)
++bmpInd1Count;
}
if (!bmpInd1Count)
@@ -246,7 +246,7 @@ int TLightGroup::Message(int code, float value)
auto randModCount = rand() % bmpInd1Count;
for (auto i = countSub1; i >= 0; i--)
{
auto light = static_cast<TLight*>(List->Get(i));
auto light = List->Get(i);
if (light->BmpIndex1 && randModCount-- == 0)
{
light->Message(0, 0.0);
@@ -263,7 +263,7 @@ int TLightGroup::Message(int code, float value)
auto index = next_light_up();
if (index < 0)
break;
static_cast<TLight*>(List->Get(index))->Message(1, 0.0);
List->Get(index)->Message(1, 0.0);
if (MessageField2)
start_animation();
return 1;
@@ -273,7 +273,7 @@ int TLightGroup::Message(int code, float value)
auto index = next_light_down();
if (index < 0)
break;
static_cast<TLight*>(List->Get(index))->Message(0, 0.0);
List->Get(index)->Message(0, 0.0);
if (MessageField2)
start_animation();
return 1;
@@ -292,10 +292,10 @@ int TLightGroup::Message(int code, float value)
case 35:
{
auto index = static_cast<int>(floor(value));
if (index >= List->Count() || index < 0)
if (index >= List->GetCount() || index < 0)
break;
auto light = static_cast<TLight*>(List->Get(index));
auto light = List->Get(index);
light->Message(1, 0.0);
if (MessageField2)
start_animation();
@@ -304,10 +304,10 @@ int TLightGroup::Message(int code, float value)
case 36:
{
auto index = static_cast<int>(floor(value));
if (index >= List->Count() || index < 0)
if (index >= List->GetCount() || index < 0)
break;
auto light = static_cast<TLight*>(List->Get(index));
auto light = List->Get(index);
light->Message(0, 0.0);
if (MessageField2)
start_animation();
@@ -316,16 +316,16 @@ int TLightGroup::Message(int code, float value)
case 37:
{
auto bmp1Count = 0;
auto countSub1 = List->Count() - 1;
auto countSub1 = List->GetCount() - 1;
for (auto i = countSub1; i >= 0; i--)
{
if (static_cast<TLight*>(List->Get(i))->BmpIndex1)
if (List->Get(i)->BmpIndex1)
++bmp1Count;
}
return bmp1Count;
}
case 38:
return List->Count();
return List->GetCount();
case 39:
return MessageField2;
case 40:
@@ -337,7 +337,7 @@ int TLightGroup::Message(int code, float value)
break;
if (MessageField2 || AnimationFlag)
TLightGroup::Message(34, 0.0);
static_cast<TLight*>(List->Get(index))->Message(15, value);
List->Get(index)->Message(15, value);
return 1;
}
case 42:
@@ -347,22 +347,22 @@ int TLightGroup::Message(int code, float value)
break;
if (MessageField2 || AnimationFlag)
TLightGroup::Message(34, 0.0);
static_cast<TLight*>(List->Get(index))->Message(16, value);
List->Get(index)->Message(16, value);
return 1;
}
case 43:
if (NotifyTimer)
timer::kill(NotifyTimer);
NotifyTimer = 0;
if (value > 0.0)
if (value > 0.0f)
NotifyTimer = timer::set(value, this, NotifyTimerExpired);
break;
case 44:
{
auto countSub1 = List->Count() - 1;
auto countSub1 = List->GetCount() - 1;
for (auto index = countSub1; index >= 0; index--)
{
auto light = static_cast<TLight*>(List->Get(index));
auto light = List->Get(index);
if (light->BmpIndex1)
{
light->Message(0, 0.0);
@@ -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->Count();
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 = static_cast<TLight*>(List->Get(i));
light->Message(20, 0.0);
}
}
if (countSub1 >= 0)
{
for (auto i = countSub1; i != 0; i--)
{
auto light = static_cast<TLight*>(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;
@@ -408,14 +398,14 @@ int TLightGroup::Message(int code, float value)
auto index = next_light_down();
if (index >= 0)
{
static_cast<TLight*>(List->Get(index))->Message(4, 0.0);
List->Get(index)->Message(4, 0.0);
}
break;
}
default:
for (auto index = List->Count() - 1; index >= 0; index--)
for (auto index = List->GetCount() - 1; index >= 0; index--)
{
static_cast<TLight*>(List->Get(index))->Message(code, value);
List->Get(index)->Message(code, value);
}
break;
}
@@ -447,15 +437,15 @@ void TLightGroup::reschedule_animation(float time)
return;
}
Timer1Time = time > 0.0 ? time : Timer1TimeDefault;
Timer1Time = time > 0.0f ? time : Timer1TimeDefault;
Timer = timer::set(Timer1Time, this, TimerExpired);
}
void TLightGroup::start_animation()
{
for (int index = List->Count() - 1; index >= 0; --index)
for (int index = List->GetCount() - 1; index >= 0; --index)
{
auto light = static_cast<TLight*>(List->Get(index));
auto light = List->Get(index);
if (light->BmpIndex1)
light->Message(9, 0.0);
else
@@ -465,9 +455,9 @@ void TLightGroup::start_animation()
int TLightGroup::next_light_up()
{
for (int index = 0; index < List->Count(); ++index)
for (int index = 0; index < List->GetCount(); ++index)
{
if (!static_cast<TLight*>(List->Get(index))->BmpIndex1)
if (!List->Get(index)->BmpIndex1)
return index;
}
return -1;
@@ -475,9 +465,9 @@ int TLightGroup::next_light_up()
int TLightGroup::next_light_down()
{
for (int index = List->Count() - 1; index >= 0; --index)
for (int index = List->GetCount() - 1; index >= 0; --index)
{
if (!static_cast<TLight*>(List->Get(index))->BmpIndex1)
if (List->Get(index)->BmpIndex1)
return index;
}
return -1;

View File

@@ -1,6 +1,8 @@
#pragma once
#include "TPinballComponent.h"
class objlist_class;
class TLight;
struct TLightGroup_player_backup
{
@@ -27,7 +29,7 @@ public:
static void TimerExpired(int timerId, void* caller);
static void NotifyTimerExpired(int timerId, void* caller);
objlist_class* List;
objlist_class<TLight>* List;
float Timer1Time;
float Timer1TimeDefault;
int MessageField2;

View File

@@ -4,11 +4,11 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "TBall.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TLightRollover::TLightRollover(TPinballTable* table, int groupIndex) : TRollover(table, groupIndex, false)
{
@@ -58,7 +58,7 @@ void TLightRollover::Collision(TBall* ball, vector_type* nextPosition, vector_ty
control::handler(63, this);
RolloverFlag = RolloverFlag == 0;
if (ListBitmap)
render::sprite_set_bitmap(RenderSprite, static_cast<gdrv_bitmap8*>(ListBitmap->Get(0)));
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
}
}
}

View File

@@ -67,7 +67,7 @@ void TOneway::Collision(TBall* ball, vector_type* nextPosition, vector_type* dir
Elasticity,
Smoothness,
Threshold,
Boost) > 0.2)
Boost) > 0.2f)
{
if (SoftHitSoundId)
loader::play_sound(SoftHitSoundId);

View File

@@ -3,7 +3,6 @@
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "TZmapList.h"
#include "TPinballTable.h"
TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool loadVisuals)
@@ -32,32 +31,45 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
if (visual.Bitmap)
{
if (!ListBitmap)
ListBitmap = new TZmapList(visualCount, 4);
ListBitmap = new objlist_class<gdrv_bitmap8>(visualCount, 4);
if (ListBitmap)
ListBitmap->Add(visual.Bitmap);
}
if (visual.ZMap)
{
if (!ListZMap)
ListZMap = new TZmapList(visualCount, 4);
ListZMap = new objlist_class<zmap_header_type>(visualCount, 4);
if (ListZMap)
ListZMap->Add(visual.ZMap);
}
}
zmap_header_type* zMap = nullptr;
if (ListZMap)
zMap = static_cast<zmap_header_type*>(ListZMap->Get(0));
zMap = ListZMap->Get(0);
if (ListBitmap)
{
/* Full tilt hack - spliced bitmap includes zMap
* Users access bitmap-zMap in pairs, pad zMap list with 0 for such users
* zdrv does not access zMap when drawing spliced bitmap*/
if (!ListZMap)
{
ListZMap = new objlist_class<zmap_header_type>(0, 4);
for (int index = 0; index < ListBitmap->GetCount(); index++)
{
assertm(ListBitmap->Get(index)->BitmapType == BitmapType::Spliced, "Wrong zMap padding");
ListZMap->Add(visual.ZMap);
}
}
rectangle_type bmp1Rect{}, tmpRect{};
auto rootBmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
auto rootBmp = ListBitmap->Get(0);
bmp1Rect.XPosition = rootBmp->XPosition - table->XOffset;
bmp1Rect.YPosition = rootBmp->YPosition - table->YOffset;
bmp1Rect.Width = rootBmp->Width;
bmp1Rect.Height = rootBmp->Height;
for (int index = 1; index < ListBitmap->Count(); index++)
for (int index = 1; index < ListBitmap->GetCount(); index++)
{
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(index));
auto bmp = ListBitmap->Get(index);
tmpRect.XPosition = bmp->XPosition - table->XOffset;
tmpRect.YPosition = bmp->YPosition - table->YOffset;
tmpRect.Width = bmp->Width;

View File

@@ -1,9 +1,11 @@
#pragma once
#include "objlist_class.h"
struct zmap_header_type;
struct gdrv_bitmap8;
struct render_sprite_type_struct;
struct component_control;
class TPinballTable;
class TZmapList;
enum class message_code
{
@@ -26,8 +28,8 @@ public:
void* operator new(size_t Size);
void operator delete(void* p);
__int8 UnusedBaseFlag;
__int8 ActiveFlag;
char UnusedBaseFlag;
char ActiveFlag;
int MessageField;
char* GroupName;
int Unknown4;
@@ -35,6 +37,6 @@ public:
int GroupIndex;
render_sprite_type_struct* RenderSprite;
TPinballTable* PinballTable;
TZmapList* ListBitmap;
TZmapList* ListZMap;
objlist_class<gdrv_bitmap8>* ListBitmap;
objlist_class<zmap_header_type>* ListZMap;
};

View File

@@ -48,8 +48,8 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
{
int shortArrLength;
ComponentList = new objlist_class(32, 16);
BallList = new objlist_class(3, 1);
ComponentList = new objlist_class<TPinballComponent>(32, 16);
BallList = new objlist_class<TBall>(3, 1);
CurScoreStruct = nullptr;
ScoreBallcount = nullptr;
ScorePlayerNumber1 = nullptr;
@@ -213,9 +213,9 @@ TPinballTable::~TPinballTable()
ScoreBallcount = nullptr;
}
delete LightGroup;
while (ComponentList->Count() > 0)
while (ComponentList->GetCount() > 0)
{
delete static_cast<TPinballComponent*>(ComponentList->Get(0));
delete ComponentList->Get(0);
}
delete BallList;
delete ComponentList;
@@ -223,12 +223,12 @@ TPinballTable::~TPinballTable()
TPinballComponent* TPinballTable::find_component(LPCSTR componentName)
{
int objCount = ComponentList->Count();
int objCount = ComponentList->GetCount();
if (objCount > 0)
{
for (int index = 0; index < objCount; ++index)
{
TPinballComponent* obj = static_cast<TPinballComponent*>(ComponentList->Get(index));
TPinballComponent* obj = ComponentList->Get(index);
const CHAR* groupName = obj->GroupName;
if (groupName && !lstrcmpA(groupName, componentName))
{
@@ -242,13 +242,13 @@ TPinballComponent* TPinballTable::find_component(LPCSTR componentName)
TPinballComponent* TPinballTable::find_component(int groupIndex)
{
char Buffer[40];
int objCount = ComponentList->Count();
char Buffer[40]{};
int objCount = ComponentList->GetCount();
if (objCount > 0)
{
for (int index = 0; index < objCount; ++index)
{
TPinballComponent* obj = static_cast<TPinballComponent*>(ComponentList->Get(index));
TPinballComponent* obj = ComponentList->Get(index);
if (obj->GroupIndex == groupIndex)
return obj;
}
@@ -303,13 +303,13 @@ 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);
for (int i = 0; i < ComponentList->Count(); i++)
for (int i = 0; i < ComponentList->GetCount(); i++)
{
static_cast<TPinballComponent*>(ComponentList->Get(i))->Message(1011, time);
ComponentList->Get(i)->Message(1011, time);
}
LightGroup->Message(8, 0);
TiltLockFlag = 1;
@@ -320,15 +320,15 @@ void TPinballTable::tilt(float time)
void TPinballTable::port_draw()
{
for (int index = ComponentList->Count() - 1; index >= 0; index--)
for (int index = ComponentList->GetCount() - 1; index >= 0; index--)
{
static_cast<TPinballComponent*>(ComponentList->Get(index))->port_draw();
ComponentList->Get(index)->port_draw();
}
}
int TPinballTable::Message(int code, float value)
{
LPSTR rc_text;
LPWSTR rc_text;
switch (code)
{
case 1000:
@@ -362,9 +362,9 @@ int TPinballTable::Message(int code, float value)
case 1008:
case 1009:
case 1010:
for (int i = 0; i < ComponentList->Count(); i++)
for (int i = 0; i < ComponentList->GetCount(); i++)
{
static_cast<TPinballComponent*>(ComponentList->Get(i))->Message(code, value);
ComponentList->Get(i)->Message(code, value);
}
break;
case 1012:
@@ -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);
@@ -406,7 +406,7 @@ int TPinballTable::Message(int code, float value)
{
CheatsUsed = 0;
Message(1024, 0.0);
auto ball = static_cast<TBall*>(BallList->Get(0));
auto ball = BallList->Get(0);
ball->Position.Y = 0.0;
ball->Position.X = 0.0;
ball->Position.Z = -0.8f;
@@ -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;
}
@@ -513,37 +513,37 @@ int TPinballTable::Message(int code, float value)
score::set(ScorePlayerNumber1, nextPlayer + 1);
score::update(ScorePlayerNumber1);
for (int i = 0; i < ComponentList->Count(); i++)
for (int i = 0; i < ComponentList->GetCount(); i++)
{
static_cast<TPinballComponent*>(ComponentList->Get(i))->Message(1020, static_cast<float>(nextPlayer));
ComponentList->Get(i)->Message(1020, static_cast<float>(nextPlayer));
}
char* textboxText = nullptr;
wchar_t* textboxText = nullptr;
switch (nextPlayer)
{
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,13 +560,13 @@ 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:
for (int i = 0; i < ComponentList->Count(); i++)
for (int i = 0; i < ComponentList->GetCount(); i++)
{
static_cast<TPinballComponent*>(ComponentList->Get(i))->Message(1024, 0);
ComponentList->Get(i)->Message(1024, 0);
}
if (ReplayTimer)
timer::kill(ReplayTimer);
@@ -608,14 +608,14 @@ void TPinballTable::EndGame_timeout(int timerId, void* caller)
table->EndGameTimeoutTimer = 0;
pb::end_game();
for (int i = 0; i < table->ComponentList->Count(); i++)
for (int i = 0; i < table->ComponentList->GetCount(); i++)
{
static_cast<TPinballComponent*>(table->ComponentList->Get(i))->Message(1022, 0);
table->ComponentList->Get(i)->Message(1022, 0);
}
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)
@@ -640,9 +640,9 @@ void TPinballTable::tilt_timeout(int timerId, void* caller)
table->TiltTimeoutTimer = 0;
if (table->TiltLockFlag)
{
for (int i = 0; i < table->BallList->Count(); i++)
for (int i = 0; i < table->BallList->GetCount(); i++)
{
table->Drain->Collision(static_cast<TBall*>(table->BallList->Get(i)), &vec, &vec, 0.0, nullptr);
table->Drain->Collision(table->BallList->Get(i), &vec, &vec, 0.0, nullptr);
}
}
}

View File

@@ -2,12 +2,12 @@
#include "TPinballComponent.h"
class TBall;
struct scoreStruct;
class TFlipper;
class TPlunger;
class TDrain;
class TDemo;
class objlist_class;
class TLightGroup;
struct score_struct_super
@@ -65,8 +65,8 @@ public:
int YOffset;
int Width;
int Height;
objlist_class* ComponentList;
objlist_class* BallList;
objlist_class<TPinballComponent>* ComponentList;
objlist_class<TBall>* BallList;
TLightGroup* LightGroup;
float GravityDirVectMult;
float GravityAngleX;

View File

@@ -5,12 +5,12 @@
#include "control.h"
#include "loader.h"
#include "maths.h"
#include "objlist_class.h"
#include "pb.h"
#include "render.h"
#include "TBall.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TPlunger::TPlunger(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
@@ -27,7 +27,7 @@ TPlunger::TPlunger(TPinballTable* table, int groupIndex) : TCollisionComponent(t
MaxPullback = 100;
Elasticity = 0.5f;
Smoothness = 0.5f;
PullbackIncrement = static_cast<int>(100.0 / (ListBitmap->Count() * 8.0));
PullbackIncrement = static_cast<int>(100.0 / (ListBitmap->GetCount() * 8.0));
Unknown4F = 0.025f;
float* floatArr = loader::query_float_attribute(groupIndex, 0, 601);
table->PlungerPositionX = floatArr[0];
@@ -65,8 +65,8 @@ int TPlunger::Message(int code, float value)
PullbackTimer_ = 0;
if (code == 1005)
loader::play_sound(SoundIndexP2);
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
auto zMap = static_cast<zmap_header_type*>(ListZMap->Get(0));
auto bmp = ListBitmap->Get(0);
auto zMap = ListZMap->Get(0);
render::sprite_set(
RenderSprite,
bmp,
@@ -79,7 +79,7 @@ int TPlunger::Message(int code, float value)
}
case 1015:
{
auto ball = static_cast<TBall*>(PinballTable->ComponentList->Get(0));
auto ball = PinballTable->BallList->Get(0);
ball->Message(1024, 0.0);
ball->Position.X = PinballTable->PlungerPositionX;
ball->Position.Y = PinballTable->PlungerPositionY;
@@ -112,8 +112,8 @@ int TPlunger::Message(int code, float value)
PullbackTimer_ = 0;
if (code == 1005)
loader::play_sound(SoundIndexP2);
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
auto zMap = static_cast<zmap_header_type*>(ListZMap->Get(0));
auto bmp = ListBitmap->Get(0);
auto zMap = ListZMap->Get(0);
render::sprite_set(
RenderSprite,
bmp,
@@ -151,10 +151,10 @@ void TPlunger::PullbackTimer(int timerId, void* caller)
plunger->Boost = static_cast<float>(plunger->MaxPullback);
}
int index = static_cast<int>(floor(
static_cast<float>(plunger->ListBitmap->Count() - 1) *
static_cast<float>(plunger->ListBitmap->GetCount() - 1) *
(plunger->Boost / static_cast<float>(plunger->MaxPullback))));
auto bmp = static_cast<gdrv_bitmap8*>(plunger->ListBitmap->Get(index));
auto zMap = static_cast<zmap_header_type*>(plunger->ListZMap->Get(index));
auto bmp = plunger->ListBitmap->Get(index);
auto zMap = plunger->ListZMap->Get(index);
render::sprite_set(
plunger->RenderSprite,
bmp,

View File

@@ -4,10 +4,10 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TPopupTarget::TPopupTarget(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
@@ -91,7 +91,7 @@ void TPopupTarget::TimerExpired(int timerId, void* caller)
auto target = static_cast<TPopupTarget*>(caller);
target->Timer = 0;
target->ActiveFlag = 1;
render::sprite_set_bitmap(target->RenderSprite, static_cast<gdrv_bitmap8*>(target->ListBitmap->Get(0)));
render::sprite_set_bitmap(target->RenderSprite, target->ListBitmap->Get(0));
if (timerId)
{
if (target->SoftHitSoundId)

View File

@@ -22,16 +22,8 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
loader::query_visual(groupIndex, 0, &visual);
CollisionGroup = visual.CollisionGroup;
auto floatArr1 = loader::query_float_attribute(groupIndex, 0, 701);
if (floatArr1)
BallFieldMult = *floatArr1;
else
BallFieldMult = 0.2f;
auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 1305);
if (floatArr2)
RampFlag1 = static_cast<int>(floor(*floatArr2));
else
RampFlag1 = 0;
BallFieldMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f);
RampFlag1 = static_cast<int>(loader::query_float_attribute(groupIndex, 0, 1305, 0));
auto floatArr3Plane = loader::query_float_attribute(groupIndex, 0, 1300);
RampPlaneCount = static_cast<int>(floor(*floatArr3Plane));

View File

@@ -5,12 +5,12 @@
#include "control.h"
#include "gdrv.h"
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "TBall.h"
#include "TEdgeSegment.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TRollover::TRollover(TPinballTable* table, int groupIndex, bool createWall) : TCollisionComponent(
table, groupIndex, createWall)
@@ -22,7 +22,7 @@ TRollover::TRollover(TPinballTable* table, int groupIndex) : TCollisionComponent
{
RolloverFlag = 0;
if (ListBitmap)
render::sprite_set_bitmap(RenderSprite, static_cast<gdrv_bitmap8*>(ListBitmap->Get(0)));
render::sprite_set_bitmap(RenderSprite, ListBitmap->Get(0));
build_walls(groupIndex);
}
@@ -34,7 +34,7 @@ int TRollover::Message(int code, float value)
this->ActiveFlag = 1;
this->RolloverFlag = 0;
if (this->ListBitmap)
render::sprite_set_bitmap(this->RenderSprite, static_cast<gdrv_bitmap8*>(this->ListBitmap->Get(0)));
render::sprite_set_bitmap(this->RenderSprite, this->ListBitmap->Get(0));
}
return 0;
}
@@ -63,7 +63,7 @@ void TRollover::Collision(TBall* ball, vector_type* nextPosition, vector_type* d
if (ListBitmap)
{
if (!RolloverFlag)
bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
bmp = ListBitmap->Get(0);
render::sprite_set_bitmap(RenderSprite, bmp);
}
}

View File

@@ -34,7 +34,7 @@ int TSink::Message(int code, float value)
switch (code)
{
case 56:
if (value < 0.0)
if (value < 0.0f)
value = TimerTime;
Timer = timer::set(value, this, TimerExpired);
break;
@@ -95,7 +95,7 @@ void TSink::Collision(TBall* ball, vector_type* nextPosition, vector_type* direc
void TSink::TimerExpired(int timerId, void* caller)
{
auto sink = static_cast<TSink*>(caller);
auto ball = static_cast<TBall*>(sink->PinballTable->BallList->Get(0));
auto ball = sink->PinballTable->BallList->Get(0);
ball->CollisionComp = nullptr;
ball->ActiveFlag = 1;
ball->Position.X = sink->BallPosition.X;

View File

@@ -4,10 +4,10 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "render.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TSoloTarget::TSoloTarget(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
@@ -41,8 +41,8 @@ int TSoloTarget::Message(int code, float value)
if (ListBitmap)
{
auto index = 1 - ActiveFlag;
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(index));
auto zMap = static_cast<zmap_header_type*>(ListZMap->Get(index));
auto bmp = ListBitmap->Get(index);
auto zMap = ListZMap->Get(index);
render::sprite_set(
RenderSprite,
bmp,

View File

@@ -1,8 +1,11 @@
#include "pch.h"
#include "TTableLayer.h"
#include "fullscrn.h"
#include "loader.h"
#include "objlist_class.h"
#include "pb.h"
#include "proj.h"
#include "render.h"
#include "TBall.h"
@@ -19,7 +22,8 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f
auto groupIndex = loader::query_handle("table");
loader::query_visual(groupIndex, 0, &visual);
auto projCenter = loader::query_float_attribute(groupIndex, 0, 700);
/*Full tilt: proj center first value is offset by resolution*/
auto projCenter = loader::query_float_attribute(groupIndex, 0, 700 + fullscrn::GetResolution());
proj::recenter(projCenter[0], projCenter[1]);
render::set_background_zmap(visual.ZMap, 0, 0);
@@ -49,11 +53,12 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f
PinballTable->GravityAnglY = 1.570796f;
}
auto table3 = PinballTable;
GraityDirX = cos(table3->GravityAnglY) * sin(table3->GravityAngleX) * table3->GravityDirVectMult;
GraityDiY = sin(table3->GravityAnglY) * sin(table3->GravityAngleX) * table3->GravityDirVectMult;
GraityDirX = cos(PinballTable->GravityAnglY) * sin(PinballTable->GravityAngleX) * PinballTable->GravityDirVectMult;
GraityDirY = sin(PinballTable->GravityAnglY) * sin(PinballTable->GravityAngleX) * PinballTable->GravityDirVectMult;
auto angleMultArr = loader::query_float_attribute(groupIndex, 0, 701);
if (angleMultArr)
/*Full tilt hack - GraityMult should be 0.2*/
if (angleMultArr && !pb::FullTiltMode)
GraityMult = *angleMultArr;
else
GraityMult = 0.2f;
@@ -109,7 +114,7 @@ int TTableLayer::FieldEffect(TBall* ball, vector_type* vecDst)
{
vecDst->X = GraityDirX - (0.5f - static_cast<float>(rand()) * 0.00003051850947599719f + ball->Acceleration.X) *
ball->Speed * GraityMult;
vecDst->Y = GraityDiY - ball->Acceleration.Y * ball->Speed * GraityMult;
vecDst->Y = GraityDirY - ball->Acceleration.Y * ball->Speed * GraityMult;
return 1;
}
@@ -214,47 +219,47 @@ void TTableLayer::edges_insert_circle(circle_type* circle, TEdgeSegment* edge, f
ray.Direction.X = 1.0;
ray.Direction.Y = 0.0;
ray.MaxDistance = edge_manager->AdvanceX;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0f)
break;
ray.Direction.X = -1.0;
ray.Origin.X = ray.Origin.X + edge_manager->AdvanceX;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0f)
break;
ray.Direction.X = 0.0;
ray.Direction.Y = 1.0;
ray.MaxDistance = edge_manager->AdvanceY;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0f)
break;
ray.Direction.Y = -1.0;
ray.Origin.Y = ray.Origin.Y + edge_manager->AdvanceY;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0f)
break;
ray.Direction.Y = 0.0;
ray.Direction.X = -1.0;
ray.MaxDistance = edge_manager->AdvanceX;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0f)
break;
ray.Direction.X = 1.0;
ray.Origin.X = ray.Origin.X - edge_manager->AdvanceX;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0f)
break;
ray.Direction.X = 0.0;
ray.Direction.Y = -1.0;
ray.MaxDistance = edge_manager->AdvanceY;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0f)
break;
ray.Direction.Y = 1.0;
ray.Origin.Y = ray.Origin.Y - edge_manager->AdvanceY;
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0)
if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0f)
break;
collision = false;
}
while (false);

View File

@@ -26,7 +26,7 @@ public:
float Unknown3F;
float Unknown4F;
float GraityDirX;
float GraityDiY;
float GraityDirY;
int Unknown7;
float GraityMult;
field_effect_type Field;

View File

@@ -2,7 +2,9 @@
#include "TTextBox.h"
#include "control.h"
#include "fullscrn.h"
#include "loader.h"
#include "pb.h"
#include "render.h"
#include "score.h"
#include "timer.h"
@@ -22,8 +24,9 @@ TTextBox::TTextBox(TPinballTable* table, int groupIndex) : TPinballComponent(tab
if (groupIndex > 0)
{
/*Full tilt: text box dimensions index is offset by resolution*/
int arrLength;
auto dimensions = loader::query_iattribute(groupIndex, 1500, &arrLength);
auto dimensions = loader::query_iattribute(groupIndex + fullscrn::GetResolution(), 1500, &arrLength);
OffsetX = dimensions[0];
OffsetY = dimensions[1];
Width = dimensions[2];
@@ -106,19 +109,19 @@ 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)
{
if (Timer && Timer != -1)
timer::kill(Timer);
if (time == -1.0)
if (time == -1.0f)
Timer = -1;
else
Timer = timer::set(time, this, TimerExpired);
@@ -150,10 +153,8 @@ void TTextBox::Display(char* text, float time)
}
}
void TTextBox::Draw()
void TTextBox::Draw(bool redraw)
{
TTextBoxMessage* nextMessage = nullptr;
auto bmp = BgBmp;
if (bmp)
gdrv::copy_bitmap(
@@ -168,119 +169,119 @@ void TTextBox::Draw()
else
gdrv::fill_bitmap(&render::vscreen, Width, Height, OffsetX, OffsetY, 0);
bool display = false;
while (Message1)
{
auto message = Message1;
if (message->Time == -1.0)
if (redraw)
{
nextMessage = message->NextMessage;
if (!message->NextMessage)
display = true;
break;
}
if (Message1->Time == -1.0f)
{
if (!Message1->NextMessage)
{
Timer = -1;
LABEL_18:
auto font = Font;
if (!font)
{
gdrv::blit(
&render::vscreen,
OffsetX,
OffsetY,
OffsetX + render::vscreen.XPosition,
OffsetY + render::vscreen.YPosition,
Width,
Height);
gdrv::grtext_draw_ttext_in_box(
Message1->Text,
render::vscreen.XPosition + OffsetX,
render::vscreen.YPosition + OffsetY,
Width,
Height,
255);
return;
}
auto text = Message1->Text;
for (auto y = OffsetY; ; y += font->Height)
{
auto curChar = *text;
if (!curChar || y + font->Height > OffsetY + Height)
break;
auto totalWidth = 0;
char* textEndSpace = nullptr;
auto textEnd = text;
while (true)
{
auto maskedChar = curChar & 0x7F;
if (!maskedChar || maskedChar == '\n')
break;
auto charBmp = font->Chars[maskedChar];
if (charBmp)
{
auto width = charBmp->Width + font->GapWidth + totalWidth;
if (width > Width)
{
if (textEndSpace)
textEnd = textEndSpace;
break;
}
if (*textEnd == ' ')
textEndSpace = textEnd;
curChar = *(textEnd + 1);
totalWidth = width;
++textEnd;
}
else
{
curChar = *textEnd;
}
}
auto offX = OffsetX;
while (text < textEnd)
{
auto charBmp = font->Chars[*text++ & 0x7F];
if (charBmp)
{
auto height = charBmp->Height;
auto width = charBmp->Width;
if (render::background_bitmap)
gdrv::copy_bitmap_w_transparency(&render::vscreen, width, height, offX, y, charBmp, 0,
0);
else
gdrv::copy_bitmap(&render::vscreen, width, height, offX, y, charBmp, 0, 0);
font = Font;
offX += charBmp->Width + font->GapWidth;
}
}
while ((*text & 0x7F) == ' ')
++text;
if ((*text & 0x7F) == '\n')
++text;
}
display = true;
break;
}
}
else
else if (Message1->TimeLeft() >= -2.0f)
{
auto timeLeft = (Message1->TimeLeft());
if (timeLeft >= -2.0f)
if (Timer > 0)
timer::kill(Timer);
Timer = timer::set(max(Message1->TimeLeft(), 0.25f), this, TimerExpired);
display = true;
break;
}
auto tmp = Message1;
Message1 = Message1->NextMessage;
delete tmp;
}
if (display)
{
auto font = Font;
if (!font)
{
gdrv::blit(
&render::vscreen,
OffsetX,
OffsetY,
OffsetX + render::vscreen.XPosition,
OffsetY + render::vscreen.YPosition,
Width,
Height);
gdrv::grtext_draw_ttext_in_box(
Message1->Text,
render::vscreen.XPosition + OffsetX,
render::vscreen.YPosition + OffsetY,
Width,
Height);
return;
}
auto text = Message1->Text;
for (auto y = OffsetY; ; y += font->Height)
{
auto curChar = *text;
if (!curChar || y + font->Height > OffsetY + Height)
break;
auto totalWidth = 0;
wchar_t* textEndSpace = nullptr;
auto textEnd = text;
while (true)
{
int timer;
if (timeLeft >= 0.25f)
auto maskedChar = curChar & 0x7F;
if (!maskedChar || maskedChar == '\n')
break;
auto charBmp = font->Chars[maskedChar];
if (charBmp)
{
timer = timer::set(timeLeft, this, TimerExpired);
auto width = charBmp->Width + font->GapWidth + totalWidth;
if (width > Width)
{
if (textEndSpace)
textEnd = textEndSpace;
break;
}
if (*textEnd == ' ')
textEndSpace = textEnd;
curChar = *(textEnd + 1);
totalWidth = width;
++textEnd;
}
else
{
timer = timer::set(0.25, this, TimerExpired);
curChar = *textEnd;
}
Timer = timer;
goto LABEL_18;
}
nextMessage = message->NextMessage;
auto offX = OffsetX;
while (text < textEnd)
{
auto charBmp = font->Chars[*text++ & 0x7F];
if (charBmp)
{
auto height = charBmp->Height;
auto width = charBmp->Width;
if (render::background_bitmap)
gdrv::copy_bitmap_w_transparency(&render::vscreen, width, height, offX, y, charBmp, 0,
0);
else
gdrv::copy_bitmap(&render::vscreen, width, height, offX, y, charBmp, 0, 0);
font = Font;
offX += charBmp->Width + font->GapWidth;
}
}
while ((*text & 0x7F) == ' ')
++text;
if ((*text & 0x7F) == '\n')
++text;
}
delete message;
Message1 = nextMessage;
}
gdrv::blit(

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

@@ -3,16 +3,16 @@
#include "control.h"
#include "objlist_class.h"
#include "render.h"
#include "timer.h"
#include "TZmapList.h"
TWall::TWall(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{
if (RenderSprite)
render::sprite_set_bitmap(RenderSprite, nullptr);
if (ListBitmap)
BmpPtr = static_cast<gdrv_bitmap8*>(ListBitmap->Get(0));
BmpPtr = ListBitmap->Get(0);
Timer = 0;
}

View File

@@ -1,15 +0,0 @@
#pragma once
#include "objlist_class.h"
class TZmapList : // TImageList, template?
public objlist_class
{
public:
TZmapList(int SizeInt, int growSize): objlist_class(SizeInt, growSize)
{
};
~TZmapList()
{
};
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
#pragma once
/* flag values for play params */
#define WMIX_QUEUEWAVE 0x00
#define WMIX_CLEARQUEUE 0x01
@@ -15,8 +16,8 @@ struct GLOBALS;
struct volume_struct
{
unsigned __int16 L;
unsigned __int16 R;
uint16_t L;
uint16_t R;
};
@@ -59,14 +60,14 @@ struct MIXCONFIG
DWORD dwFlags;
WORD wChannels;
WORD wSamplingRate;
unsigned __int16 WaveBlockCount;
unsigned __int16 WaveBlockLen;
__int16 CmixPtrDefaultFlag;
unsigned __int16 ResetMixDefaultFlag;
unsigned __int16 GoodWavePos;
unsigned __int16 wDeviceID;
unsigned __int16 PauseBlocks;
__int16 ShowDebugDialogs;
uint16_t WaveBlockCount;
uint16_t WaveBlockLen;
int16_t CmixPtrDefaultFlag;
uint16_t ResetMixDefaultFlag;
uint16_t GoodWavePos;
uint16_t wDeviceID;
uint16_t PauseBlocks;
int16_t ShowDebugDialogs;
HKEY RegistryKey;
};
@@ -88,14 +89,14 @@ struct PLAYQUEUE
struct GLOBALS
{
WORD wMagic1;
__int16 unknown0;
int16_t unknown0;
HWND hWndApp;
int unknown2;
HWAVEOUT hWaveOut;
int fActive;
int SettingsDialogActiveFlag;
unsigned int wDeviceID;
char szDevicePName[96];
char szDevicePName[96];
WAVEOUTCAPSA WaveoutCaps;
volume_struct DefaultVolume;
volume_struct ChannelVolume[MAXCHANNELS];
@@ -112,13 +113,13 @@ struct GLOBALS
DWORD dwBaseTime;
int fGoodGetPos;
DWORD dwWaveOutPos;
void (*CmixPtr)(unsigned __int8* lpDest, unsigned __int8** rgWaveSrc, volume_struct* volume, int iNumWaves,
unsigned __int16 length);
void (*CmixPtr)(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volume, int iNumWaves,
uint16_t length);
int (* pfnRemix)(DWORD, CHANNELNODE*);
DWORD (* pfnSampleAdjust)(DWORD, DWORD);
CHANNELNODE* pWaitList;
__int16 wMagic2;
__int16 unknown112;
int16_t wMagic2;
int16_t unknown112;
};
struct dialog_template
@@ -182,16 +183,16 @@ private:
static DWORD SubFactor(DWORD a1, DWORD a2);
static DWORD AddFactor(DWORD a1, DWORD a2);
static dialog_template* MakeSettingsDlgTemplate();
static dialog_template* MakeDlgTemplate(unsigned* totalSize, unsigned style, __int16 x, __int16 y, __int16 cx,
__int16 cy,
static dialog_template* MakeDlgTemplate(size_t* totalSize, unsigned style, int16_t x, int16_t y, int16_t cx,
int16_t cy,
const wchar_t* String);
static dialog_template* AddDlgControl(unsigned int* totalSize, dialog_template* dlgTemplate, __int16 idClass,
static dialog_template* AddDlgControl(size_t* totalSize, dialog_template* dlgTemplate, int16_t idClass,
unsigned style,
WORD id, __int16 x, __int16 y, __int16 cx, __int16 cy,
WORD id, int16_t x, int16_t y, int16_t cx, int16_t cy,
const wchar_t* String);
static void DestroySettingsDlgTemplate(LPCVOID pMem);
static int Settings_OnInitDialog(HWND hWnd, int wParam, MIXCONFIG* lpMixconfig);
static int Settings_OnCommand(HWND hWnd, int command, int lParam, int wParam);
static int Settings_OnInitDialog(HWND hWnd, WPARAM wParam, MIXCONFIG* lpMixconfig);
static int Settings_OnCommand(HWND hWnd, int command, LPARAM lParam, int wParam);
static int ReadRegistryToGetMachineSpecificInfSection(unsigned wDeviceId, LPSTR lpString1, int maxLength);
static const char* GetOperatingSystemPrefix();
static unsigned int FigureOutDMABufferSize(unsigned int waveBlockLen, PCMWAVEFORMAT* pcm);
@@ -215,8 +216,8 @@ private:
static int HasCurrentOutputFormat(MIXWAVE* lpMixWave);
static CHANNELNODE* GetChannelNode();
static void ResetWavePosIfNoChannelData();
static void cmixit(unsigned __int8* lpDest, unsigned __int8** rgWaveSrc, volume_struct* volumeArr, int iNumWaves,
unsigned __int16 length);
static void cmixit(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volumeArr, int iNumWaves,
uint16_t length);
static LRESULT __stdcall WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
static INT_PTR __stdcall SettingsDlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
@@ -226,8 +227,8 @@ private:
static CHANNELNODE* free_channel_nodes;
static unsigned char volume_table[11][256];
static int debug_flag;
static void (*cmixit_ptr)(unsigned __int8* lpDest, unsigned __int8** rgWaveSrc, volume_struct* volume,
int iNumWaves, unsigned __int16 length);
static void (*cmixit_ptr)(uint8_t* lpDest, uint8_t** rgWaveSrc, volume_struct* volume,
int iNumWaves, uint16_t length);
static HMODULE HModule;
static GLOBALS *Globals, *GlobalsActive;
static PCMWAVEFORMAT gpFormat;

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,7 @@ struct component_tag : component_tag_base
static_assert(std::is_base_of<TPinballComponent, T>::value, "T must inherit from TPinballComponent");
T* Component;
component_tag(LPCSTR name, TPinballComponent* component): component_tag_base(name)
component_tag(LPCSTR name, TPinballComponent* component): component_tag_base(name), Component(nullptr)
{
component_tag::SetComponent(component);
}
@@ -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

@@ -1,5 +1,9 @@
#include "pch.h"
#include "fullscrn.h"
#include "options.h"
#include "pb.h"
#include "render.h"
#include "winmain.h"
@@ -10,10 +14,22 @@ tagRECT fullscrn::WindowRect1, fullscrn::WindowRect2;
rectangle_type fullscrn::WHRect;
int fullscrn::fullscrn_flag1;
int fullscrn::display_changed;
int fullscrn::ChangeDisplay, fullscrn::SmthFullScrnFlag2;
int fullscrn::ChangeDisplay, fullscrn::ignoreNextDisplayChangeFg;
int fullscrn::trick = 1;
int fullscrn::MenuEnabled;
HMENU fullscrn::MenuHandle;
int fullscrn::resolution = 0;
int fullscrn::maxResolution = 0;
const resolution_info fullscrn::resolution_array[3] =
{
{640, 480, 600, 416, 501},
{800, 600, 752, 520, 502},
{1024, 768, 960, 666, 503},
};
float fullscrn::ScaleX = 1;
float fullscrn::ScaleY = 1;
int fullscrn::OffsetX = 0;
int fullscrn::OffsetY = 0;
void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay)
{
@@ -36,15 +52,21 @@ void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HME
WindowRect2.right = (WindowRect1.right - WindowRect1.left - widht2) / 2 - 2 + widht2 + 4;
WindowRect2.left = (WindowRect1.right - WindowRect1.left - widht2) / 2 - 2;
WindowRect2.top = borderHeight / 2 - (captionHeight + menuHeight) - 2;
/*RECT client{0,0,width,height};
AdjustWindowRect(&client, winmain::WndStyle, true);*/
MoveWindow(
hWnd,
(WindowRect1.right - WindowRect1.left - widht2) / 2 - 2,
WindowRect2.top,
widht2 + 4 + 10,
WindowRect2.right - WindowRect2.left + 10,
WindowRect2.bottom - WindowRect2.top + 10,
0);
// Todo: WH + 10 hack: original request 640x480 window but somehow receives 650x490, even thought spyxx says it is 640x480
fullscrn_flag1 = 0;
window_size_changed();
assertm(ScaleX == 1 && ScaleY == 1, "Wrong default client size");
}
void fullscrn::shutdown()
@@ -84,13 +106,13 @@ int fullscrn::set_screen_mode(int isFullscreen)
int fullscrn::disableWindowFlagsDisDlg()
{
long style = GetWindowLongA(hWnd, -16);
return SetWindowLongA(hWnd, -16, style & 0xFF3FFFFF);
return SetWindowLongA(hWnd, -16, style & ~(WS_CAPTION | WS_THICKFRAME));
}
int fullscrn::setWindowFlagsDisDlg()
{
int style = GetWindowLongA(hWnd, -16);
return SetWindowLongA(hWnd, -16, style | 0xC00000);
return SetWindowLongA(hWnd, -16, style | WS_CAPTION | WS_THICKFRAME);
}
int fullscrn::enableFullscreen()
@@ -100,33 +122,33 @@ int fullscrn::enableFullscreen()
if (ChangeDisplay && !display_changed)
{
DevMode.dmSize = 156;
DevMode.dmFields = 1835008;
DevMode.dmPelsWidth = 640;
DevMode.dmPelsHeight = 480;
DevMode.dmBitsPerPel = 8;
DevMode.dmSize = sizeof DevMode;
DevMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
DevMode.dmPelsWidth = resolution_array[resolution].ScreenWidth;
DevMode.dmPelsHeight = resolution_array[resolution].ScreenHeight;
DevMode.dmBitsPerPel = 32;
disableWindowFlagsDisDlg();
if (trick)
{
GetWindowRect(GetDesktopWindow(), &Rect);
SetWindowPos(hWnd, (HWND)-1, 0, 0, Rect.right - Rect.left + 1,
Rect.bottom - Rect.top + 1, 8u);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, Rect.right - Rect.left + 1,
Rect.bottom - Rect.top + 1, SWP_NOREDRAW);
}
SmthFullScrnFlag2 = 1;
LONG changeDispResult = ChangeDisplaySettingsA(&DevMode, 4u);
if (changeDispResult == 1)
ignoreNextDisplayChangeFg = 1;
LONG changeDispResult = ChangeDisplaySettingsA(&DevMode, CDS_FULLSCREEN);
if (changeDispResult == DISP_CHANGE_RESTART)
{
BYTE2(DevMode.dmFields) &= 0xFBu;
SmthFullScrnFlag2 = 1;
changeDispResult = ChangeDisplaySettingsA(&DevMode, 4u);
DevMode.dmFields &= ~DM_BITSPERPEL;
ignoreNextDisplayChangeFg = 1;
changeDispResult = ChangeDisplaySettingsA(&DevMode, CDS_FULLSCREEN);
}
display_changed = changeDispResult == 0;
if (changeDispResult == 0)
display_changed = changeDispResult == DISP_CHANGE_SUCCESSFUL;
if (display_changed)
return 1;
}
GetWindowRect(GetDesktopWindow(), &Rect);
disableWindowFlagsDisDlg();
SetWindowPos(hWnd, (HWND)-1, 0, 0, Rect.right - Rect.left + 1, Rect.bottom - Rect.top + 1, 8u);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, Rect.right - Rect.left + 1, Rect.bottom - Rect.top + 1, SWP_NOREDRAW);
return 0;
}
@@ -135,20 +157,20 @@ int fullscrn::disableFullscreen()
if (display_changed)
{
display_changed = 0;
SmthFullScrnFlag2 = 1;
ChangeDisplaySettingsA(nullptr, 4u);
ignoreNextDisplayChangeFg = 1;
ChangeDisplaySettingsA(nullptr, CDS_FULLSCREEN);
if (trick)
SetWindowPos(hWnd, (HWND)-1, 0, 0, 0, 0, 0x13u);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
}
setWindowFlagsDisDlg();
SetWindowPos(
hWnd,
nullptr,
HWND_TOP,
WindowRect2.left,
WindowRect2.top,
WindowRect2.right - WindowRect2.left,
WindowRect2.bottom - WindowRect2.top,
0x14u);
SWP_NOZORDER | SWP_NOACTIVATE);
return 0;
}
@@ -242,9 +264,9 @@ void fullscrn::center_in(HWND parent, HWND child)
int fullscrn::displaychange()
{
int result = 0;
if (SmthFullScrnFlag2)
if (ignoreNextDisplayChangeFg)
{
SmthFullScrnFlag2 = 0;
ignoreNextDisplayChangeFg = 0;
}
else
{
@@ -258,24 +280,24 @@ int fullscrn::displaychange()
set_menu_mode(1);
SetWindowPos(
hWnd,
nullptr,
HWND_TOP,
WindowRect2.left,
WindowRect2.top,
WindowRect2.right - WindowRect2.left,
WindowRect2.bottom - WindowRect2.top,
0x1Cu);
SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
result = 1;
}
else
{
SetWindowPos(
hWnd,
nullptr,
HWND_TOP,
WindowRect2.left,
WindowRect2.top,
WindowRect2.right - WindowRect2.left,
WindowRect2.bottom - WindowRect2.top,
0x14u);
SWP_NOZORDER | SWP_NOACTIVATE);
}
center_in(GetDesktopWindow(), hWnd);
}
@@ -289,50 +311,48 @@ void fullscrn::activate(int flag)
if (!flag)
{
set_screen_mode(0);
SetWindowPos(hWnd, (HWND)1, 0, 0, 0, 0, 0x13u);
SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
}
}
}
void fullscrn::fillRect(int right, int bottom)
void fullscrn::fillRect(int right, int bottom, int left, int top)
{
// Weird reg usage, should be zero
int v2 = 0;
int v3 = 0;
RECT rc;
HGDIOBJ brush = CreateSolidBrush(0);
auto brush = CreateSolidBrush(0);
if (brush)
{
HDC dc = winmain::_GetDC(hWnd);
HGDIOBJ brushHandle = SelectObject(dc, brush);
auto dc = winmain::_GetDC(hWnd);
if (dc)
{
rc.right = right + v2 + 1;
rc.bottom = bottom + v3 + 1;
rc.left = v2;
rc.top = v3;
FillRect(dc, &rc, static_cast<HBRUSH>(brush));
auto prevBrush = SelectObject(dc, brush);
rc.right = left + right + 1;
rc.bottom = top + bottom + 1;
rc.left = left;
rc.top = top;
FillRect(dc, &rc, brush);
SelectObject(dc, prevBrush);
ReleaseDC(hWnd, dc);
}
SelectObject(dc, brushHandle);
DeleteObject(brush);
}
}
unsigned fullscrn::convert_mouse_pos(unsigned int mouseXY)
{
unsigned __int16 x = mouseXY & 0xffFF - render::vscreen.XPosition;
unsigned __int16 y = (mouseXY >> 16) - render::vscreen.YPosition;
uint16_t x = mouseXY & 0xffFF - render::vscreen.XPosition;
uint16_t y = (mouseXY >> 16) - render::vscreen.YPosition;
return x | y << 16;
}
void fullscrn::getminmaxinfo(MINMAXINFO* maxMin)
{
maxMin->ptMaxSize.x = WindowRect2.right - WindowRect2.left;
maxMin->ptMaxSize.y = WindowRect2.bottom - WindowRect2.top;
maxMin->ptMaxPosition.x = WindowRect2.left;
maxMin->ptMaxPosition.y = WindowRect2.top;
/*Block down-scaling lower than min resolution*/
maxMin->ptMinTrackSize = POINT
{
resolution_array[0].ScreenWidth / 2,
resolution_array[0].ScreenHeight / 2
};
}
void fullscrn::paint()
@@ -345,7 +365,7 @@ void fullscrn::paint()
if (fullscrn_flag1 & 1)
{
menuHeight = GetSystemMetrics(SM_CYMENU);
fillRect(WindowRect1.right - 1, menuHeight);
fillRect(WindowRect1.right - 1, menuHeight, 0, 0);
}
}
else
@@ -354,9 +374,83 @@ void fullscrn::paint()
menuHeight = GetSystemMetrics(SM_CYMENU);
else
menuHeight = 0;
fillRect(WindowRect1.right, menuHeight + WindowRect1.bottom);
fillRect(WindowRect1.right, menuHeight + WindowRect1.bottom, 0, 0);
}
}
render::paint();
pb::paint();
fullscrn_flag1 = 0;
}
int fullscrn::GetResolution()
{
return resolution;
}
void fullscrn::SetResolution(int resolution)
{
if (!pb::FullTiltMode)
resolution = 0;
assertm(resolution >= 0 && resolution <= 2, "Resolution value out of bounds");
fullscrn::resolution = resolution;
}
int fullscrn::GetMaxResolution()
{
return maxResolution;
}
void fullscrn::SetMaxResolution(int resolution)
{
assertm(resolution >= 0 && resolution <= 2, "Resolution value out of bounds");
maxResolution = resolution;
}
int fullscrn::get_max_supported_resolution()
{
if (!pb::FullTiltMode)
return 0;
auto resolutionWH = get_screen_resolution();
auto width = LOWORD(resolutionWH);
auto height = HIWORD(resolutionWH);
auto result = 0;
for (auto index = 1; index < 3; ++index)
{
auto resPtr = &resolution_array[index];
if (resPtr->ScreenWidth <= width && resPtr->ScreenHeight <= height)
result = index;
}
return result;
}
int fullscrn::get_screen_resolution()
{
auto height = static_cast<uint16_t>(GetSystemMetrics(SM_CYSCREEN));
return static_cast<uint16_t>(GetSystemMetrics(SM_CXSCREEN)) | (height << 16);
}
void fullscrn::window_size_changed()
{
/*No scaling in fullscreen mode*/
if (display_changed)
{
ScaleY = ScaleX = 1;
OffsetX = OffsetY = 0;
return;
}
RECT client{};
GetClientRect(hWnd, &client);
auto res = &resolution_array[resolution];
ScaleX = static_cast<float>(client.right) / res->TableWidth;
ScaleY = static_cast<float>(client.bottom) / res->TableHeight;
OffsetX = OffsetY = 0;
if (options::Options.UniformScaling)
{
ScaleY = ScaleX = min(ScaleX, ScaleY);
OffsetX = static_cast<int>(floor((client.right - res->TableWidth * ScaleX) / 2));
OffsetY = static_cast<int>(floor((client.bottom - res->TableHeight * ScaleY) / 2));
}
}

View File

@@ -5,6 +5,16 @@
#define BYTE1(x) BYTEn(x, 1) // byte 1 (counting from 0)
#define BYTE2(x) BYTEn(x, 2)
struct resolution_info
{
int16_t ScreenWidth;
int16_t ScreenHeight;
int16_t TableWidth;
int16_t TableHeight;
int16_t ResolutionMenuId;
};
class fullscrn
{
public:
@@ -15,8 +25,13 @@ public:
static rectangle_type WHRect;
static int fullscrn_flag1;
static int display_changed;
static int ChangeDisplay, SmthFullScrnFlag2;
static int ChangeDisplay, ignoreNextDisplayChangeFg;
static int trick;
static const resolution_info resolution_array[3];
static float ScaleX;
static float ScaleY;
static int OffsetX;
static int OffsetY;
static void init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay);
static void shutdown();
@@ -29,14 +44,23 @@ public:
static void getminmaxinfo(MINMAXINFO* maxMin);
static void paint();
static bool set_menu_mode(int menuEnabled);
static int GetResolution();
static void SetResolution(int resolution);
static int GetMaxResolution();
static void SetMaxResolution(int resolution);
static int get_max_supported_resolution();
static int get_screen_resolution();
static void window_size_changed();
private :
static int MenuEnabled;
static HMENU MenuHandle;
static int resolution;
static int maxResolution;
static void GetWindowCenter();
static int disableWindowFlagsDisDlg();
static int setWindowFlagsDisDlg();
static int enableFullscreen();
static int disableFullscreen();
static void fillRect(int right, int bottom);
static void fillRect(int right, int bottom, int left, int top);
};

View File

@@ -1,13 +1,15 @@
#include "pch.h"
#include "gdrv.h"
#include "fullscrn.h"
#include "memory.h"
#include "options.h"
#include "pinball.h"
#include "winmain.h"
HPALETTE gdrv::palette_handle = nullptr;
HINSTANCE gdrv::hinst;
HWND gdrv::hwnd;
LOGPALETTEx256 gdrv::current_palette{};
int gdrv::sequence_handle;
HDC gdrv::sequence_hdc;
int gdrv::use_wing = 0;
@@ -18,10 +20,12 @@ int gdrv::grtext_red = -1;
int gdrv::init(HINSTANCE hInst, HWND hWnd)
{
LOGPALETTEx256 current_palette{};
hinst = hInst;
hwnd = hWnd;
if (!palette_handle)
palette_handle = CreatePalette((LOGPALETTE*)&current_palette);
palette_handle = CreatePalette(&current_palette);
return 0;
}
@@ -37,17 +41,16 @@ void gdrv::get_focus()
}
BITMAPINFO* gdrv::DibCreate(__int16 bpp, int width, int height)
BITMAPINFO* gdrv::DibCreate(int16_t bpp, int width, int height)
{
auto sizeBytes = height * ((width * bpp / 8 + 3) & 0xFFFFFFFC);
auto buf = GlobalAlloc(0x42u, sizeBytes + 1064);
auto dib = static_cast<BITMAPINFO*>(GlobalLock(buf));
auto sizeBytes = height * (width * bpp / 8 + 3 & (~3));
auto dib = memory::allocate<BITMAPINFO>(1, (256 - 1) * sizeof(RGBQUAD) + sizeBytes);
if (!dib)
return nullptr;
dib->bmiHeader.biSizeImage = sizeBytes;
dib->bmiHeader.biWidth = width;
dib->bmiHeader.biSize = 40;
dib->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dib->bmiHeader.biHeight = height;
dib->bmiHeader.biPlanes = 1;
dib->bmiHeader.biBitCount = bpp;
@@ -65,25 +68,15 @@ BITMAPINFO* gdrv::DibCreate(__int16 bpp, int width, int height)
dib->bmiHeader.biClrUsed = 256;
}
int index = 0;
for (auto i = (int*)dib->bmiColors; index < static_cast<signed int>(dib->bmiHeader.biClrUsed) / 16; ++index)
uint32_t paletteColors[]
{
*i++ = 0;
*i++ = 0x800000;
*i++ = 0x8000;
*i++ = 8421376;
*i++ = 128;
*i++ = 8388736;
*i++ = 32896;
*i++ = 12632256;
*i++ = 8421504;
*i++ = 16711680;
*i++ = 65280;
*i++ = 16776960;
*i++ = 255;
*i++ = 16711935;
*i++ = 0xFFFF;
*i++ = 0xFFFFFF;
0, 0x800000, 0x8000, 8421376, 128, 8388736, 32896, 12632256,
8421504, 16711680, 65280, 16776960, 255, 16711935, 0xFFFF, 0xFFFFFF,
};
for (auto index = 0u; index < dib->bmiHeader.biClrUsed; index += 16)
{
memcpy(&dib->bmiColors[index], paletteColors, sizeof paletteColors);
}
return dib;
}
@@ -108,31 +101,24 @@ void gdrv::DibSetUsage(BITMAPINFO* dib, HPALETTE hpal, int someFlag)
{
if (someFlag && someFlag <= 2)
{
auto pltPtr = (short*)((char*)dib + dib->bmiHeader.biSize);
for (int i = 0; i < numOfColors; ++i)
auto pltPtr = reinterpret_cast<short*>(dib->bmiColors);
for (auto i = 0; i < numOfColors; ++i)
{
*pltPtr++ = i;
}
}
else
{
assertm(false, "Entered bad code");
char* dibPtr = (char*)dib + dib->bmiHeader.biSize;
if (numOfColors >= 256)
numOfColors = 256;
GetPaletteEntries(hpal, 0, numOfColors, pPalEntries);
int index = 0;
char* dibPtr2 = dibPtr + 1;
do
for (auto index = 0; index < numOfColors; index++)
{
char v9 = pPalEntries[index++].peRed;
dibPtr2[1] = v9;
*dibPtr2 = dibPtr2[(char*)pPalEntries - dibPtr];
*(dibPtr2 - 1) = dibPtr2[&pPalEntries[0].peGreen - (unsigned char*)dibPtr];
dibPtr2[2] = 0;
dibPtr2 += 4;
dib->bmiColors[index].rgbRed = pPalEntries[index].peRed;
dib->bmiColors[index].rgbGreen = pPalEntries[index].peGreen;
dib->bmiColors[index].rgbBlue = pPalEntries[index].peBlue;
dib->bmiColors[index].rgbReserved = 0;
}
while (index < numOfColors);
}
}
}
@@ -156,7 +142,7 @@ int gdrv::create_bitmap_dib(gdrv_bitmap8* bmp, int width, int height)
if (dib->bmiHeader.biCompression == 3)
bmpBufPtr = (char*)&dib->bmiHeader.biPlanes + dib->bmiHeader.biSize;
else
bmpBufPtr = (char*)&dib->bmiHeader.biSize + 4 * dib->bmiHeader.biClrUsed + dib->bmiHeader.biSize;
bmpBufPtr = reinterpret_cast<char*>(&dib->bmiColors[dib->bmiHeader.biClrUsed]);
bmp->BmpBufPtr1 = bmpBufPtr;
bmp->BmpBufPtr2 = bmpBufPtr;
return 0;
@@ -185,20 +171,37 @@ int gdrv::create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag)
return 0;
}
int gdrv::create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size)
{
bmp->Dib = nullptr;
bmp->Width = width;
bmp->Stride = width;
bmp->BitmapType = BitmapType::Spliced;
bmp->Height = height;
char* buf = memory::allocate(size);
bmp->BmpBufPtr1 = buf;
if (!buf)
return -1;
bmp->BmpBufPtr2 = bmp->BmpBufPtr1;
return 0;
}
int gdrv::display_palette(PALETTEENTRY* plt)
{
LOGPALETTEx256 current_palette{};
if (palette_handle)
DeleteObject(palette_handle);
palette_handle = CreatePalette((LOGPALETTE*)&current_palette);
palette_handle = CreatePalette(&current_palette);
auto windowHandle = GetDesktopWindow();
auto dc = winmain::_GetDC(windowHandle);
SetSystemPaletteUse(dc, 2u);
SetSystemPaletteUse(dc, 1u);
auto pltHandle = SelectPalette(dc, palette_handle, 0);
auto originalPalette = SelectPalette(dc, palette_handle, 0);
RealizePalette(dc);
SelectPalette(dc, pltHandle, 0);
GetSystemPaletteEntries(dc, 0, 0x100u, current_palette.palPalEntry);
SelectPalette(dc, originalPalette, 0);
GetSystemPaletteEntries(dc, 0, 256, current_palette.palPalEntry);
for (int i = 0; i < 256; i++)
{
current_palette.palPalEntry[i].peFlags = 0;
@@ -219,15 +222,15 @@ int gdrv::display_palette(PALETTEENTRY* plt)
pltDst++;
}
if (!(GetDeviceCaps(dc, 38) & 0x100))
if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE))
{
current_palette.palPalEntry[255].peBlue = -1;
current_palette.palPalEntry[255].peGreen = -1;
current_palette.palPalEntry[255].peRed = -1;
}
ResizePalette(palette_handle, 0x100u);
SetPaletteEntries(palette_handle, 0, 0x100u, current_palette.palPalEntry);
ResizePalette(palette_handle, 256);
SetPaletteEntries(palette_handle, 0, 256, current_palette.palPalEntry);
windowHandle = GetDesktopWindow();
ReleaseDC(windowHandle, dc);
return 0;
@@ -238,32 +241,32 @@ int gdrv::destroy_bitmap(gdrv_bitmap8* bmp)
{
if (!bmp)
return -1;
if (bmp->BitmapType == BitmapType::RawBitmap)
if (bmp->BitmapType == BitmapType::RawBitmap || bmp->BitmapType == BitmapType::Spliced)
{
memory::free(bmp->BmpBufPtr1);
}
else if (bmp->BitmapType == BitmapType::DibBitmap)
{
GlobalUnlock(GlobalHandle(bmp->Dib));
GlobalFree(GlobalHandle(bmp->Dib));
memory::free(bmp->Dib);
}
memset(bmp, 0, sizeof(gdrv_bitmap8));
return 0;
}
UINT gdrv::start_blit_sequence()
void gdrv::start_blit_sequence()
{
HDC dc = winmain::_GetDC(hwnd);
sequence_handle = 0;
sequence_hdc = dc;
SelectPalette(dc, palette_handle, 0);
return RealizePalette(sequence_hdc);
RealizePalette(sequence_hdc);
SetStretchBltMode(dc, stretchMode);
}
void gdrv::blit_sequence(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, int DestHeight)
{
if (!use_wing)
StretchDIBits(
StretchDIBitsScaled(
sequence_hdc,
xDest,
yDest,
@@ -273,10 +276,10 @@ void gdrv::blit_sequence(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, in
bmp->Height - ySrcOff - DestHeight,
DestWidth,
DestHeight,
bmp->BmpBufPtr1,
bmp->Dib,
1u,
SRCCOPY);
bmp,
DIB_PAL_COLORS,
SRCCOPY
);
}
@@ -285,28 +288,29 @@ 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);
if (dc)
{
SelectPalette(dc, palette_handle, 0);
RealizePalette(dc);
if (!use_wing)
StretchDIBits(
StretchDIBitsScaled(
dc,
xDest,
yDest,
DestWidth,
DestHeight,
xSrc,
bmp->Height - ySrcOff - DestHeight,
bmp->Height - ySrc - DestHeight,
DestWidth,
DestHeight,
bmp->BmpBufPtr1,
bmp->Dib,
1u,
SRCCOPY);
bmp,
DIB_PAL_COLORS,
SRCCOPY
);
ReleaseDC(hwnd, dc);
}
}
@@ -314,10 +318,30 @@ 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);
if (!use_wing)
StretchDIBits(
StretchDIBitsScaled(
dc,
xDest,
yDest,
@@ -327,10 +351,10 @@ void gdrv::blat(gdrv_bitmap8* bmp, int xDest, int yDest)
0,
bmp->Width,
bmp->Height,
bmp->BmpBufPtr1,
bmp->Dib,
1u,
SRCCOPY);
bmp,
DIB_PAL_COLORS,
SRCCOPY
);
ReleaseDC(hwnd, dc);
}
@@ -340,16 +364,11 @@ void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int y
if (bmpHeight < 0)
bmpHeight = -bmpHeight;
char* bmpPtr = &bmp->BmpBufPtr1[bmp->Width * (bmpHeight - height - yOff) + xOff];
if (height > 0)
for (; height > 0; --height)
{
do
{
if (width > 0)
memset(bmpPtr, fillChar, width);
bmpPtr += bmp->Stride;
--height;
}
while (height);
if (width > 0)
memset(bmpPtr, fillChar, width);
bmpPtr += bmp->Stride;
}
}
@@ -395,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;
@@ -413,10 +445,78 @@ 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);
COLORREF color = SetTextColor(dc, (grtext_red) | (grtext_green << 8) | (grtext_blue << 16));
DrawTextA(dc, text, lstrlenA(text), &rc, 0x810u);
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);
DrawTextW(dc, text, lstrlenW(text), &rc, DT_NOPREFIX | DT_WORDBREAK);
SelectObject(dc, hOldFont);
DeleteObject(hNewFont);
SetBkMode(dc, prevMode);
SetTextColor(dc, color);
ReleaseDC(hwnd, dc);
}
int gdrv::StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc,
int SrcWidth, int SrcHeight, gdrv_bitmap8* bmp, UINT iUsage,
DWORD rop)
{
/*Scaled partial updates may leave 1px border artifacts around update area.
* Pad update area to compensate.*/
const int pad = 1, padX2 = pad * 2;
if (fullscrn::ScaleX > 1 && xSrc > pad && xSrc + pad < bmp->Width)
{
xSrc -= pad;
xDest -= pad;
SrcWidth += padX2;
DestWidth += padX2;
}
if (fullscrn::ScaleY > 1 && ySrc > pad && ySrc + pad < bmp->Height)
{
ySrc -= pad;
yDest -= pad;
SrcHeight += padX2;
DestHeight += padX2;
}
return StretchDIBits(
hdc,
static_cast<int>(round(xDest * fullscrn::ScaleX + fullscrn::OffsetX)),
static_cast<int>(round(yDest * fullscrn::ScaleY + fullscrn::OffsetY)),
static_cast<int>(round(DestWidth * fullscrn::ScaleX)),
static_cast<int>(round(DestHeight * fullscrn::ScaleY)),
xSrc,
ySrc,
SrcWidth,
SrcHeight,
bmp->BmpBufPtr1,
bmp->Dib,
iUsage,
rop);
}

View File

@@ -5,6 +5,7 @@ enum class BitmapType : char
None = 0,
RawBitmap = 1,
DibBitmap = 2,
Spliced = 4,
};
struct gdrv_bitmap8
@@ -21,14 +22,14 @@ struct gdrv_bitmap8
int YPosition;
};
struct LOGPALETTEx256
struct LOGPALETTEx256 : LOGPALETTE
{
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[256];
PALETTEENTRY palPalEntry2[256 - 1];
LOGPALETTEx256() : palVersion(0x300), palNumEntries(256), palPalEntry{}
LOGPALETTEx256() : palPalEntry2{}
{
palVersion = 0x300;
palNumEntries = 256;
}
};
@@ -37,7 +38,6 @@ class gdrv
{
public:
static HPALETTE palette_handle;
static LOGPALETTEx256 current_palette;
static int sequence_handle;
static HDC sequence_hdc;
static int use_wing;
@@ -45,14 +45,15 @@ public:
static int init(HINSTANCE hInst, HWND hWnd);
static int uninit();
static void get_focus();
static BITMAPINFO* DibCreate(__int16 bpp, int width, int height);
static BITMAPINFO* DibCreate(int16_t bpp, int width, int height);
static void DibSetUsage(BITMAPINFO* dib, HPALETTE hpal, int someFlag);
static int create_bitmap_dib(gdrv_bitmap8* bmp, int width, int height);
static int create_bitmap(gdrv_bitmap8* bmp, int width, int height);
static int create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag);
static int create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size);
static int destroy_bitmap(gdrv_bitmap8* bmp);
static int display_palette(PALETTEENTRY* plt);
static UINT start_blit_sequence();
static void start_blit_sequence();
static void blit_sequence(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth,
int DestHeight);
static void end_blit_sequence();
@@ -63,11 +64,17 @@ 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;
static HWND hwnd;
static HINSTANCE hinst;
static int grtext_blue;
static int grtext_green;
static int grtext_red;
static int StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc,
int SrcWidth, int SrcHeight, gdrv_bitmap8* bmp, UINT iUsage,
DWORD rop);
};

View File

@@ -9,8 +9,8 @@
int high_score::dlg_enter_name;
int high_score::dlg_score;
int high_score::position;
LPCSTR high_score::default_name;
int high_score::dlg_position;
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);
@@ -48,30 +49,26 @@ int high_score::read(high_score_struct* table, int* ptrToSmth)
if (!buf1)
return 1;
char* buf2 = memory::allocate(300u);
int position = 0;
high_score_struct* tablePtr = table;
const CHAR* optPath = pinball::get_rc_string(166, 0);
do
auto optPath = pinball::get_rc_string(166, 0);
for (auto position = 0; position < 5; ++position)
{
_itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Name");
options::get_string(optPath, Buffer, buf1, pinball::WindowName, 32);
buf1[32] = 0;
lstrcpyA(tablePtr->Name, buf1);
_itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Score");
options::get_string(optPath, Buffer, buf1, pinball::WindowName, 300);
auto tablePtr = &table[position];
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;
++position;
++tablePtr;
}
while (position < 5);
scramble_number_string(scoreSum, buf1);
options::get_string(optPath, "Verification", buf2, pinball::WindowName, 300);
options::get_string(optPath, "Verification", buf2, "", 300);
if (lstrcmpA(buf1, buf2))
clear_table(table);
memory::free(buf1);
@@ -81,32 +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;
int position = 0;
const CHAR* optPath = pinball::get_rc_string(166, 0);
do
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;
}
while (position < 5);
scramble_number_string(scoreSum, buf);
options::set_string(optPath, "Verification", buf);
memory::free(buf);
@@ -136,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)
{
@@ -154,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;
@@ -172,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)
{
position = pos;
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))
{
}
}
@@ -191,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)
{
@@ -210,22 +204,22 @@ 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)
{
if (position == -1)
if (dlg_position == -1)
{
dlg_enter_name = 0;
return 1;
}
HWND nameTextBox = GetDlgItem(hWnd, position + DLG_HIGHSCORES_EditName1);
ShowWindow(nameTextBox, 5);
HWND nameTextBox = GetDlgItem(hWnd, dlg_position + DLG_HIGHSCORES_EditName1);
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);
@@ -246,15 +240,15 @@ INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
break;
}
GetDlgItemTextA(hWnd, 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, position);
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)
@@ -281,9 +275,9 @@ void high_score::show_high_scores(HWND hDlg, high_score_struct* table)
int nextPosition = 0;
for (int i = 0; i < 5; ++i)
{
if (dlg_enter_name == 1 && position == i)
if (dlg_enter_name == 1 && dlg_position == i)
{
hsdlg_show_score(hDlg, " ", dlg_score, i);
hsdlg_show_score(hDlg, L" ", dlg_score, i);
nextPosition = 1;
}
hsdlg_show_score(hDlg, tablePtr->Name, tablePtr->Score, i + nextPosition);
@@ -291,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)
@@ -299,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 position;
static LPCSTR default_name;
static int dlg_position;
static LPCWSTR default_name;
static high_score_struct* dlg_hst;
static winhelp_entry help[21];
};

View File

@@ -2,6 +2,7 @@
#include "loader.h"
#include "memory.h"
#include "partman.h"
#include "pb.h"
#include "pinball.h"
#include "Sound.h"
#include "zdrv.h"
@@ -47,20 +48,19 @@ soundListStruct loader::sound_list[65];
int loader::error(int errorCode, int captionCode)
{
int curCode = loader_errors[0].Code;
auto curCode = loader_errors;
const char *errorText = nullptr, *errorCaption = nullptr;
int index = 0, index2 = 0;
if (loader_errors[0].Code >= 0)
do
{
if (errorCode == curCode)
errorText = loader_errors[index2].Message;
if (captionCode == curCode)
errorCaption = loader_errors[index2].Message;
index2 = ++index;
curCode = loader_errors[index].Code;
}
while (curCode >= 0);
auto index = 0;
while (curCode->Code >= 0)
{
if (errorCode == curCode->Code)
errorText = curCode->Message;
if (captionCode == curCode->Code)
errorCaption = curCode->Message;
curCode++;
index++;
}
if (!errorText)
errorText = loader_errors[index].Message;
MessageBoxA(nullptr, errorText, errorCaption, 0x2000u);
@@ -89,7 +89,7 @@ void loader::loadfrom(datFileStruct* datFile)
for (auto groupIndex = 0; groupIndex < datFile->NumberOfGroups; ++groupIndex)
{
auto value = reinterpret_cast<__int16*>(partman::field(datFile, groupIndex, datFieldTypes::ShortValue));
auto value = reinterpret_cast<int16_t*>(partman::field(datFile, groupIndex, datFieldTypes::ShortValue));
if (value && *value == 202)
{
if (sound_count < 65)
@@ -116,7 +116,7 @@ void loader::unload()
int loader::get_sound_id(int groupIndex)
{
__int16 soundIndex = 1;
int16_t soundIndex = 1;
if (sound_count <= 1)
{
error(25, 26);
@@ -135,20 +135,28 @@ 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)
{
auto value = reinterpret_cast<__int16*>(partman::field(loader_table, soundGroupId,
auto value = reinterpret_cast<int16_t*>(partman::field(loader_table, soundGroupId,
datFieldTypes::ShortValue));
if (value && *value == 202)
{
/*FT sounds are in SOUND subfolder*/
char filePath[300]{}, fileName2[100]{};
auto fileName = partman::field(loader_table, soundGroupId, datFieldTypes::String);
HFILE hFile = _lopen(fileName, 0);
sound_list[soundIndex].Duration = static_cast<float>(static_cast<double>(_llseek(hFile, 0, SEEK_END)) *
0.0000909090909090909);
sprintf_s(fileName2, pb::FullTiltMode ? "SOUND\\%s" : "%s", fileName);
pinball::make_path_name(filePath, fileName2);
HFILE hFile = _lopen(filePath, 0);
_lread(hFile, &wavHeader, sizeof wavHeader);
_lclose(hFile);
sound_list[soundIndex].WavePtr = Sound::LoadWaveFile(fileName);
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);
}
}
}
@@ -168,7 +176,7 @@ short loader::query_visual_states(int groupIndex)
short result;
if (groupIndex < 0)
return error(0, 17);
auto shortArr = reinterpret_cast<__int16*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortArray));
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortArray));
if (shortArr && *shortArr == 100)
result = shortArr[1];
else
@@ -187,7 +195,7 @@ char* loader::query_name(int groupIndex)
return partman::field(loader_table, groupIndex, datFieldTypes::GroupName);
}
__int16* loader::query_iattribute(int groupIndex, int firstValue, int* arraySize)
int16_t* loader::query_iattribute(int groupIndex, int firstValue, int* arraySize)
{
if (groupIndex < 0)
{
@@ -197,7 +205,7 @@ __int16* loader::query_iattribute(int groupIndex, int firstValue, int* arraySize
for (auto skipIndex = 0;; ++skipIndex)
{
auto shortArr = reinterpret_cast<__int16*>(partman::field_nth(loader_table, groupIndex,
auto shortArr = reinterpret_cast<int16_t*>(partman::field_nth(loader_table, groupIndex,
datFieldTypes::ShortArray, skipIndex));
if (!shortArr)
break;
@@ -234,7 +242,7 @@ float* loader::query_float_attribute(int groupIndex, int groupIndexOffset, int f
skipIndex));
if (!floatArr)
break;
if (static_cast<__int16>(floor(*floatArr)) == firstValue)
if (static_cast<int16_t>(floor(*floatArr)) == firstValue)
return floatArr + 1;
}
@@ -242,11 +250,42 @@ float* loader::query_float_attribute(int groupIndex, int groupIndexOffset, int f
return nullptr;
}
float loader::query_float_attribute(int groupIndex, int groupIndexOffset, int firstValue, float defVal)
{
if (groupIndex < 0)
{
error(0, 22);
return NAN;
}
int stateId = state_id(groupIndex, groupIndexOffset);
if (stateId < 0)
{
error(16, 22);
return NAN;
}
for (auto skipIndex = 0;; ++skipIndex)
{
auto floatArr = reinterpret_cast<float*>(partman::field_nth(loader_table, stateId,
datFieldTypes::FloatArray, skipIndex));
if (!floatArr)
break;
if (static_cast<int16_t>(floor(*floatArr)) == firstValue)
return floatArr[1];
}
if (!isnan(defVal))
return defVal;
error(13, 22);
return NAN;
}
int loader::material(int groupIndex, visualStruct* visual)
{
if (groupIndex < 0)
return error(0, 21);
auto shortArr = reinterpret_cast<__int16*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
if (!shortArr)
return error(1, 21);
if (*shortArr != 300)
@@ -290,7 +329,7 @@ int loader::state_id(int groupIndex, int groupIndexOffset)
auto visualState = query_visual_states(groupIndex);
if (visualState <= 0)
return error(12, 24);
auto shortArr = reinterpret_cast<__int16*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
if (!shortArr)
return error(1, 24);
if (*shortArr != 200)
@@ -301,7 +340,7 @@ int loader::state_id(int groupIndex, int groupIndexOffset)
return groupIndex;
groupIndex += groupIndexOffset;
shortArr = reinterpret_cast<__int16*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
if (!shortArr)
return error(1, 24);
if (*shortArr != 201)
@@ -313,7 +352,7 @@ int loader::kicker(int groupIndex, visualKickerStruct* kicker)
{
if (groupIndex < 0)
return error(0, 20);
auto shortArr = reinterpret_cast<__int16*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
if (!shortArr)
return error(1, 20);
if (*shortArr != 400)
@@ -381,7 +420,7 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vis
visual->ZMap->ZPtr2 = visual->ZMap->ZPtr1;
}
auto shortArr = reinterpret_cast<__int16*>(partman::field(loader_table, stateId, datFieldTypes::ShortArray));
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, stateId, datFieldTypes::ShortArray));
if (shortArr)
{
unsigned int shortArrSize = partman::field_size(loader_table, stateId, datFieldTypes::ShortArray);
@@ -433,11 +472,11 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vis
auto floatArr = reinterpret_cast<float*>(partman::field(loader_table, stateId, datFieldTypes::FloatArray));
if (!floatArr)
return 0;
if (*floatArr != 600.0)
if (*floatArr != 600.0f)
return 0;
visual->FloatArrCount = (partman::field_size(loader_table, stateId, datFieldTypes::FloatArray) / 4) / 2 - 2;
auto floatVal = static_cast<int>(floor(floatArr[1]) - 1.0);
visual->FloatArrCount = partman::field_size(loader_table, stateId, datFieldTypes::FloatArray) / 4 / 2 - 2;
auto floatVal = static_cast<int>(floor(floatArr[1]) - 1.0f);
switch (floatVal)
{
case 0:

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
{
@@ -65,7 +99,8 @@ public:
static int query_visual(int groupIndex, int groupIndexOffset, visualStruct* visual);
static char* query_name(int groupIndex);
static float* query_float_attribute(int groupIndex, int groupIndexOffset, int firstValue);
static __int16* query_iattribute(int groupIndex, int firstValue, int* arraySize);
static float query_float_attribute(int groupIndex, int groupIndexOffset, int firstValue, float defVal);
static int16_t* query_iattribute(int groupIndex, int firstValue, int* arraySize);
static float play_sound(int soundIndex);
static datFileStruct* loader_table;
private:

View File

@@ -131,7 +131,7 @@ float maths::ray_intersect_circle(ray_type* ray, circle_type* circle)
// Tca, L dot D, projection of L on D
float Tca = Ly * ray->Direction.Y + Lx * ray->Direction.X;
if (Tca < 0.0) // No intersection if Tca is negative
if (Tca < 0.0f) // No intersection if Tca is negative
return 1000000000.0f;
// L dot L, distance from ray origin to circle center
@@ -144,12 +144,12 @@ float maths::ray_intersect_circle(ray_type* ray, circle_type* circle)
// Thc^2 = rad^2 - d = rad^2 - L dot L + Tca dot Tca
float ThcSq = circle->RadiusSq - LMagSq + Tca * Tca;
if (ThcSq < 0.0) // No intersection if Thc is negative
if (ThcSq < 0.0f) // No intersection if Thc is negative
return 1000000000.0f;
// T0 = Tca - Thc, distance from origin to first intersection
float T0 = Tca - sqrt(ThcSq);
if (T0 < 0.0 || T0 > ray->MaxDistance)
if (T0 < 0.0f || T0 > ray->MaxDistance)
return 1000000000.0f;
return T0;
}
@@ -158,7 +158,7 @@ float maths::ray_intersect_circle(ray_type* ray, circle_type* circle)
float maths::normalize_2d(vector_type* vec)
{
float mag = sqrt(vec->X * vec->X + vec->Y * vec->Y);
if (0.0 != mag)
if (mag != 0.0f)
{
vec->X = 1.0f / mag * vec->X;
vec->Y = 1.0f / mag * vec->Y;
@@ -179,7 +179,7 @@ void maths::line_init(line_type* line, float x0, float y0, float x1, float y1)
line->PerpendicularL.X = line->Direction.Y;
line->PerpendicularL.Y = -line->Direction.X;
line->PreComp1 = -(line->Direction.Y * x0) + line->Direction.X * y0;
if (line->Direction.X >= 0.000000001 || line->Direction.X <= -0.000000001)
if (line->Direction.X >= 0.000000001f || line->Direction.X <= -0.000000001f)
{
v9 = x1;
lineDirection = x0 >= x1;
@@ -210,7 +210,7 @@ float maths::ray_intersect_line(ray_type* ray, line_type* line)
bool v6;
float perpDot = line->PerpendicularL.Y * ray->Direction.Y + ray->Direction.X * line->PerpendicularL.X;
if (perpDot < 0.0)
if (perpDot < 0.0f)
{
float result = -((ray->Origin.X * line->PerpendicularL.X + ray->Origin.Y * line->PerpendicularL.Y + line->
PreComp1)
@@ -220,7 +220,7 @@ float maths::ray_intersect_line(ray_type* ray, line_type* line)
line->RayIntersect.X = result * ray->Direction.X + ray->Origin.X;
float v4 = result * ray->Direction.Y + ray->Origin.Y;
line->RayIntersect.Y = v4;
if (0.0 == line->Direction.X)
if (line->Direction.X == 0.0f)
{
if (v4 >= line->OriginX)
{
@@ -256,7 +256,7 @@ float maths::magnitude(vector_type* vec)
{
float result;
auto magSq = vec->X * vec->X + vec->Y * vec->Y + vec->Z * vec->Z;
if (magSq == 0.0)
if (magSq == 0.0f)
result = 0.0;
else
result = sqrt(magSq);
@@ -342,7 +342,7 @@ float maths::distance_to_flipper(ray_type* ray1, ray_type* ray2)
auto distance = 1000000000.0f;
auto distanceType = -1;
auto newDistance = ray_intersect_line(ray1, &TFlipperEdge::lineA);
if (newDistance < 1000000000.0)
if (newDistance < 1000000000.0f)
{
distance = newDistance;
distanceType = 0;
@@ -365,7 +365,7 @@ float maths::distance_to_flipper(ray_type* ray1, ray_type* ray2)
distance = newDistance;
distanceType = 1;
}
if (!ray2 || distance >= 1000000000.0)
if (!ray2 || distance >= 1000000000.0f)
return distance;
if (distanceType != -1)

View File

@@ -1,58 +1,40 @@
#include "pch.h"
#include "memory.h"
unsigned int memory::use_total;
size_t memory::use_total;
int memory::critical_allocation;
void (*memory::critical_callback)();
std::map<void*, size_t> memory::alloc_map{};
void memory::init(void (*callback)())
{
critical_callback = callback;
}
char* memory::allocate(unsigned int size)
char* memory::allocate(size_t size)
{
char* buf = static_cast<char*>(malloc(size + 4));
if (buf)
auto buf = static_cast<char*>(malloc(size));
if (!buf)
{
*(unsigned int*)buf = size << 8;
use_total += size + 4;
*buf = size >= 0xFFDC ? -91 : 90;
return buf + 4;
if (critical_allocation && critical_callback)
critical_callback();
return nullptr;
}
if (critical_allocation && critical_callback)
critical_callback();
return nullptr;
use_total += size;
alloc_map[buf] = size;
return buf;
}
void memory::free(void* buf)
{
unsigned int* bufStart = static_cast<unsigned int*>(buf) - 1;
use_total -= (*bufStart >> 8) + 4;
char firstChar = *(char*)bufStart;
if (firstChar == 90 || firstChar == -91)
std::free(bufStart);
else
assertm(false, "Unknown memory type");
}
char* memory::realloc(void* buf, unsigned int size)
{
if (!buf)
return allocate(size);
char* bufStart = static_cast<char*>(buf) - 4;
use_total -= *(unsigned int*)bufStart >> 8;
if (*bufStart != 90 && *bufStart != -91 ||
(bufStart = static_cast<char*>(std::realloc(bufStart, size + 4))) != nullptr)
auto alloc = alloc_map.find(buf);
if (alloc == alloc_map.end())
{
char bufType = *bufStart;
*(unsigned int*)bufStart = size << 8;
use_total += size;
*bufStart = bufType;
return bufStart + 4;
assertm(false, "Unknown memory type");
return;
}
if (critical_allocation && critical_callback)
critical_callback();
return nullptr;
use_total -= alloc->second;
std::free(alloc->first);
}

View File

@@ -1,22 +1,60 @@
#pragma once
#include <map>
class memory
{
public:
static void init(void (*callback)(void));
static char* allocate(unsigned int size);
static char* allocate(size_t size);
static void free(void* buf);
static char* realloc(void* buf, unsigned int size);
static unsigned int use_total;
template <typename T>
static T* allocate(size_t count = 1, size_t add = 0)
{
size_t size = sizeof(T) * count + add;
auto buf = static_cast<T*>(malloc(size));
if (!buf)
{
if (critical_allocation && critical_callback)
critical_callback();
return nullptr;
}
use_total += size;
alloc_map[buf] = size;
return buf;
}
template <typename T>
static T* realloc(T* buf, size_t size)
{
if (!buf)
return reinterpret_cast<T*>(allocate(size));
auto alloc = alloc_map.find(buf);
if (alloc == alloc_map.end())
{
assertm(false, "Unknown memory type");
return buf;
}
auto newBuf = static_cast<T*>(std::realloc(alloc->first, size));
if (!newBuf)
{
if (critical_allocation && critical_callback)
critical_callback();
return nullptr;
}
use_total += size - alloc->second;
alloc_map.erase(alloc);
alloc_map[newBuf] = size;
return newBuf;
}
static size_t use_total;
static int critical_allocation;
private:
static void (*critical_callback)();
static std::map<void*, size_t> alloc_map;
};
// Fill memory block with an integer value
inline void memset32(void* ptr, unsigned int value, int count)
{
auto p = (unsigned int*)ptr;
for (int i = 0; i < count; i++)
*p++ = value;
}

View File

@@ -1,15 +1,22 @@
#include "pch.h"
#include "midi.h"
#include "pb.h"
#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;
MCIERROR midi::play_pb_theme(int flag)
{
if (pb::FullTiltMode)
{
return play_ft(track1);
}
MCI_PLAY_PARMS playParams;
MCIERROR result = 0;
@@ -26,6 +33,11 @@ MCIERROR midi::play_pb_theme(int flag)
MCIERROR midi::music_stop()
{
if (pb::FullTiltMode)
{
return stop_ft();
}
MCIERROR result = 0;
if (midi_seq1_playing)
result = mciSendCommandA(mci_open_info.wDeviceID, MCI_STOP, 0, 0);
@@ -34,18 +46,28 @@ MCIERROR midi::music_stop()
int midi::music_init(HWND hwnd)
{
if (pb::FullTiltMode)
{
return music_init_ft(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;
}
MCIERROR midi::restart_midi_seq(int param)
MCIERROR midi::restart_midi_seq(LPARAM param)
{
if (pb::FullTiltMode)
{
return play_ft(active_track);
}
MCI_PLAY_PARMS playParams;
MCIERROR result = 0;
@@ -58,7 +80,431 @@ MCIERROR midi::restart_midi_seq(int param)
void midi::music_shutdown()
{
if (pb::FullTiltMode)
{
music_shutdown_ft();
return;
}
if (midi_seq1_open)
mciSendCommandA(mci_open_info.wDeviceID, MCI_CLOSE, 0, 0);
midi_seq1_open = 0;
}
objlist_class<midi_struct>* midi::TrackList;
midi_struct *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::active_track2;
int midi::some_flag1;
int midi::music_init_ft(HWND hwnd)
{
midi_notify_hwnd = hwnd;
active_track = nullptr;
TrackList = new objlist_class<midi_struct>(0, 1);
track1 = load_track("taba1");
track2 = load_track("taba2");
track3 = load_track("taba3");
if (!track2)
track2 = track1;
if (!track3)
track3 = track1;
return 1;
}
void midi::music_shutdown_ft()
{
if (active_track)
stream_close(active_track);
while (TrackList->GetCount())
{
midi_struct* midi = TrackList->Get(0);
unload_track(midi);
TrackList->Delete(midi);
}
active_track = nullptr;
delete TrackList;
}
midi_struct* midi::load_track(LPCSTR fileName)
{
midi_struct* midi;
char filePath[256];
char fileName2[256];
lstrcpyA(fileName2, "sound\\");
lstrcatA(fileName2, fileName);
pinball::make_path_name(filePath, fileName2, 254u);
lstrcatA(filePath, ".MDS");
if (load_file(&midi, filePath, 0, 1))
return nullptr;
if (midi)
TrackList->Add(midi);
return midi;
}
int midi::load_file(midi_struct** midi_res, void* filePtrOrPath, int fileSizeP, int flags)
{
int returnCode;
unsigned int fileSize;
HANDLE mapHandle = nullptr;
midi_struct* midi = nullptr;
HANDLE fileHandle = INVALID_HANDLE_VALUE;
int fileFlag = 0;
do
{
if ((flags & 3) == 0 || (flags & 3) == 3)
{
returnCode = 4;
break;
}
midi = static_cast<midi_struct*>(LocalAlloc(0x40u, sizeof(midi_struct)));
if (!midi)
{
returnCode = 1;
break;
}
midi->Magic = mmioFOURCC('M', 'D', 'S', 'I');
midi->StreamHandle = nullptr;
midi->PreparedBlocksCount = 0;
if ((flags & 2) != 0)
{
fileSize = fileSizeP;
}
else
{
fileFlag = 1;
fileHandle = CreateFileA(static_cast<LPCSTR>(filePtrOrPath), GENERIC_READ, 1u, nullptr, OPEN_EXISTING,
0x80u, nullptr);
if (fileHandle == INVALID_HANDLE_VALUE)
{
returnCode = 2;
break;
}
fileSize = GetFileSize(fileHandle, nullptr);
mapHandle = CreateFileMappingA(fileHandle, nullptr, 2u, 0, 0, nullptr);
if (!mapHandle)
{
returnCode = 2;
break;
}
filePtrOrPath = MapViewOfFile(mapHandle, 4u, 0, 0, 0);
if (!filePtrOrPath)
{
returnCode = 2;
break;
}
}
returnCode = read_file(midi, static_cast<riff_header*>(filePtrOrPath), fileSize);
}
while (false);
if (returnCode)
{
if (midi)
LocalFree(midi);
}
else
{
*midi_res = midi;
}
if (fileFlag)
{
if (filePtrOrPath)
UnmapViewOfFile(filePtrOrPath);
if (mapHandle)
CloseHandle(mapHandle);
if (fileHandle != INVALID_HANDLE_VALUE)
CloseHandle(fileHandle);
}
return returnCode;
}
int midi::read_file(midi_struct* midi, riff_header* filePtr, unsigned fileSize)
{
auto returnCode = 0;
do
{
midi->DataPtr1 = nullptr;
if (fileSize < 12)
{
returnCode = 3;
break;
}
if (filePtr->Riff != mmioFOURCC('R', 'I', 'F', 'F'))
{
returnCode = 3;
break;
}
if (filePtr->Mids != mmioFOURCC('M', 'I', 'D', 'S'))
{
returnCode = 3;
break;
}
if (filePtr->FileSize > fileSize - 8)
{
returnCode = 3;
break;
}
if (fileSize - 12 < 8)
{
returnCode = 3;
break;
}
if (filePtr->Fmt != mmioFOURCC('f', 'm', 't', ' '))
{
returnCode = 3;
break;
}
if (filePtr->FmtSize > fileSize - 12)
{
returnCode = 3;
break;
}
if (filePtr->FmtSize < 12)
{
returnCode = 3;
break;
}
midi->DwTimeFormat = filePtr->dwTimeFormat;
midi->CbMaxBuffer = filePtr->cbMaxBuffer;
midi->DwFlagsFormat = filePtr->dwFlags;
auto blocksSize = fileSize - 20 - filePtr->FmtSize;
if (blocksSize < 8)
{
returnCode = 3;
break;
}
auto dataChunk = reinterpret_cast<riff_data*>(reinterpret_cast<char*>(&filePtr->dwTimeFormat) + filePtr->FmtSize
);
if (dataChunk->Data != mmioFOURCC('d','a','t','a'))
{
returnCode = 3;
break;
}
if (dataChunk->DataSize > blocksSize || dataChunk->DataSize < 4)
{
returnCode = 3;
break;
}
midi->BlockCount = dataChunk->BlocksPerChunk;
midi->DataPtr1 = reinterpret_cast<midihdr_tag*>(memory::allocate(
dataChunk->BlocksPerChunk * (midi->CbMaxBuffer + sizeof(midihdr_tag))));
if (!midi->DataPtr1)
{
returnCode = 1;
break;
}
if (!midi->BlockCount)
{
returnCode = 3;
break;
}
auto blocksSizeIndex = blocksSize - 12;
auto srcPtr = dataChunk->Blocks;
auto* dstPtr = midi->DataPtr1;
for (auto blockIndex = midi->BlockCount; blockIndex; blockIndex--)
{
dstPtr->lpData = reinterpret_cast<LPSTR>(&dstPtr[1]);
dstPtr->dwBufferLength = midi->CbMaxBuffer;
dstPtr->dwFlags = 0;
dstPtr->dwUser = reinterpret_cast<DWORD_PTR>(midi);
dstPtr->lpNext = nullptr;
if (blocksSizeIndex < 8)
{
returnCode = 3;
break;
}
auto blockSize = srcPtr->CbBuffer;
if (blockSize > midi->CbMaxBuffer || blockSize > blocksSizeIndex - 8)
{
returnCode = 3;
break;
}
if ((midi->DwFlagsFormat & 1) != 0)
{
/*Not used in FT, some kind of compression*/
assertm(false, "Unimplemented code reached");
/*int a1[16];
a1[0] = (int)blockDataPtr;
a1[2] = blockSize;
a1[1] = blockSize;
if (!sub_4031A0(a1, dataPtr))
{
returnCode = 3; break;
}*/
}
else
{
dstPtr->dwBytesRecorded = blockSize;
memcpy(dstPtr->lpData, srcPtr->AData, blockSize);
}
blocksSizeIndex -= blockSize + 8;
srcPtr = reinterpret_cast<riff_block*>(&srcPtr->AData[blockSize]);
dstPtr = reinterpret_cast<midihdr_tag*>(reinterpret_cast<char*>(&dstPtr[1]) + midi->CbMaxBuffer);
}
}
while (false);
if (returnCode && midi->DataPtr1)
{
memory::free(midi->DataPtr1);
}
return returnCode;
}
int midi::play_ft(midi_struct* midi)
{
int result;
stop_ft();
if (!midi)
return 0;
if (some_flag1)
{
active_track2 = midi;
return 0;
}
if (stream_open(midi, 1))
{
active_track = nullptr;
result = 0;
}
else
{
active_track = midi;
result = 1;
}
return result;
}
int midi::stop_ft()
{
int returnCode = 0;
if (active_track)
returnCode = stream_close(active_track);
active_track = nullptr;
return returnCode;
}
int midi::unload_track(midi_struct* midi)
{
if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I'))
return 6;
if (midi->StreamHandle)
stream_close(midi);
if (midi->DataPtr1)
{
memory::free(midi->DataPtr1);
}
midi->Magic = mmioFOURCC('d','a','t','a');
LocalFree(midi);
return 0;
}
int midi::stream_open(midi_struct* midi, char flags)
{
auto returnCode = 0;
if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I'))
return 6;
UINT puDeviceID = -1;
auto steamOpenedFg = !midi->StreamHandle;
MIDIPROPTIMEDIV propdata{8, midi->DwTimeFormat};
if (steamOpenedFg &&
!midiStreamOpen(&midi->StreamHandle, &puDeviceID, 1u, reinterpret_cast<DWORD_PTR>(midi_callback), 0,
CALLBACK_FUNCTION) &&
!midiStreamProperty(midi->StreamHandle, reinterpret_cast<LPBYTE>(&propdata),MIDIPROP_TIMEDIV | MIDIPROP_SET))
{
midihdr_tag* blockPtr = midi->DataPtr1;
for (auto blockIndex = midi->BlockCount; blockIndex; blockIndex--)
{
if (midiOutPrepareHeader(reinterpret_cast<HMIDIOUT>(midi->StreamHandle), blockPtr, sizeof(MIDIHDR)) ||
midiStreamOut(midi->StreamHandle, blockPtr, sizeof(MIDIHDR)))
{
returnCode = 5;
break;
}
++midi->PreparedBlocksCount;
blockPtr = reinterpret_cast<midihdr_tag*>(reinterpret_cast<char*>(&blockPtr[1]) + blockPtr->dwBufferLength);
}
}
if (!returnCode)
{
if (!steamOpenedFg && (midi->SomeFlag2 & 4) == 0)
return 7;
midi->SomeFlag2 &= ~2;
if ((flags & 1) != 0)
midi->SomeFlag2 |= 2;
midi->SomeFlag2 &= ~4;
if (midiStreamRestart(midi->StreamHandle))
returnCode = 5;
}
if (returnCode && steamOpenedFg)
{
if (midi->StreamHandle)
stream_close(midi);
}
return returnCode;
}
int midi::stream_close(midi_struct* midi)
{
int returnCode;
if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I'))
return 6;
if (!midi->StreamHandle)
return 7;
midi->SomeFlag2 |= 1u;
if (midiOutReset(reinterpret_cast<HMIDIOUT>(midi->StreamHandle)))
{
returnCode = 5;
midi->SomeFlag2 &= ~1;
}
else
{
midihdr_tag* blockPtr = midi->DataPtr1;
for (int i = midi->BlockCount; i; --i)
{
midiOutUnprepareHeader(reinterpret_cast<HMIDIOUT>(midi->StreamHandle), blockPtr, sizeof(MIDIHDR));
blockPtr = reinterpret_cast<midihdr_tag*>(reinterpret_cast<char*>(&blockPtr[1]) + blockPtr->dwBufferLength);
}
midiStreamClose(midi->StreamHandle);
returnCode = 0;
midi->StreamHandle = nullptr;
midi->SomeFlag2 = 0;
}
return returnCode;
}
void midi::midi_callback(HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
if (wMsg == 969)
{
auto mhdr = reinterpret_cast<LPMIDIHDR>(dwParam1);
auto midi = reinterpret_cast<midi_struct*>(mhdr->dwUser);
if ((midi->SomeFlag2 & 2) == 0 || (midi->SomeFlag2 & 1) != 0 || midiStreamOut(
midi->StreamHandle, mhdr, sizeof(MIDIHDR)))
--midi->PreparedBlocksCount;
}
}

View File

@@ -1,16 +1,81 @@
#pragma once
#include "objlist_class.h"
struct midi_struct
{
DWORD Magic;
DWORD DwTimeFormat;
DWORD CbMaxBuffer;
DWORD DwFlagsFormat;
midihdr_tag* DataPtr1;
HMIDISTRM StreamHandle;
int SomeFlag2;
int BlockCount;
int PreparedBlocksCount;
};
#pragma pack(push)
#pragma pack(1)
struct riff_block
{
DWORD TkStart;
DWORD CbBuffer;
char AData[4];
};
struct riff_data
{
DWORD Data;
DWORD DataSize;
DWORD BlocksPerChunk;
riff_block Blocks[1];
};
struct riff_header
{
DWORD Riff;
DWORD FileSize;
DWORD Mids;
DWORD Fmt;
DWORD FmtSize;
DWORD dwTimeFormat;
DWORD cbMaxBuffer;
DWORD dwFlags;
riff_data Data;
};
static_assert(sizeof(riff_block) == 0xC, "Wrong size of riff_block");
static_assert(sizeof(riff_data) == 0x18, "Wrong size of riff_data");
static_assert(sizeof(riff_header) == 0x38, "Wrong size of riff_header");
#pragma pack(pop)
class midi
{
public:
static MCIERROR play_pb_theme(int flag);
static MCIERROR music_stop();
static int music_init(HWND hwnd);
static MCIERROR restart_midi_seq(int param);
static MCIERROR restart_midi_seq(LPARAM param);
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;
static objlist_class<midi_struct>* TrackList;
static midi_struct *track1, *track2, *track3, *active_track, *active_track2;
static int some_flag1;
static int music_init_ft(HWND hwnd);
static void music_shutdown_ft();
static midi_struct* load_track(LPCSTR fileName);
static int load_file(midi_struct** midi_res, void* filePtrOrPath, int fileSizeP, int flags);
static int read_file(midi_struct* midi, riff_header* filePtr, unsigned int fileSize);
static int play_ft(midi_struct* midi);
static int stop_ft();
static int unload_track(midi_struct* midi);
static int stream_open(midi_struct* midi, char flags);
static int stream_close(midi_struct* midi);
static void CALLBACK midi_callback(HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,
DWORD_PTR dwParam2);
};

View File

@@ -71,21 +71,21 @@ void nudge::_nudge(float xDiff, float yDiff)
auto ballList = pb::MainTable->BallList;
accelMod.X = xDiff * 0.5f;
accelMod.Y = yDiff * 0.5f;
for (auto index = 0; index < ballList->Count(); index++)
for (auto index = 0; index < ballList->GetCount(); index++)
{
auto ball = static_cast<TBall*>(ballList->Get(index));
auto ball = ballList->Get(index);
if (ball->ActiveFlag && !ball->CollisionComp)
{
ball->Acceleration.X = ball->Acceleration.X * ball->Speed;
ball->Acceleration.Y = ball->Acceleration.Y * ball->Speed;
maths::vector_add(&ball->Acceleration, &accelMod);
ball->Speed = maths::normalize_2d(&ball->Acceleration);
if (0.0 == ball->Acceleration.X)
if (ball->Acceleration.X == 0.0f)
invAccelX = 1000000000.0;
else
invAccelX = 1.0f / ball->Acceleration.X;
ball->InvAcceleration.X = invAccelX;
if (0.0 == ball->Acceleration.Y)
if (ball->Acceleration.Y == 0.0f)
invAccelY = 1000000000.0;
else
invAccelY = 1.0f / ball->Acceleration.Y;
@@ -94,6 +94,6 @@ void nudge::_nudge(float xDiff, float yDiff)
}
}
render::shift(static_cast<int>(floor(xDiff + 0.5)), static_cast<int>(floor(0.5 - yDiff)), 0, 0, table->Width,
render::shift(static_cast<int>(floor(xDiff + 0.5f)), static_cast<int>(floor(0.5f - yDiff)), 0, 0, table->Width,
table->Height);
}

View File

@@ -1,94 +0,0 @@
#include "pch.h"
#include "objlist_class.h"
#include <cstdlib>
#include "memory.h"
// v1 from Ida
objlist_class::objlist_class(int SizeInt, int growSize)
{
ListPtr = objlist_new(SizeInt);
GrowSize = growSize;
}
objlist_class::~objlist_class()
{
if (ListPtr)
memory::free(ListPtr);
}
void objlist_class::Add(void* value)
{
if (this->ListPtr->Count == this->ListPtr->Size)
Grow();
objlist_add_object(ListPtr, value);
}
void objlist_class::Grow()
{
this->ListPtr = objlist_grow(this->ListPtr, this->GrowSize);
}
int objlist_class::Delete(void* value)
{
return objlist_delete_object(ListPtr, value);
}
void* objlist_class::Get(int index)
{
if (index >= ListPtr->Count)
return nullptr;
return this->ListPtr->Array[index];
}
objlist_struct1* objlist_class::objlist_new(int sizeInt)
{
objlist_struct1* result = (objlist_struct1 *)memory::allocate(sizeof(void*) * sizeInt + sizeof(objlist_struct1));
if (!result)
return result;
result->Count = 0;
result->Size = sizeInt;
return result;
}
int objlist_class::objlist_add_object(objlist_struct1* ptrToStruct, void* value)
{
int addIndex = ptrToStruct->Count;
if (addIndex >= ptrToStruct->Size)
return 0;
ptrToStruct->Array[addIndex] = value;
return ++ptrToStruct->Count;
}
objlist_struct1* objlist_class::objlist_grow(objlist_struct1* ptrToStruct, int growSize)
{
objlist_struct1* resultPtr = ptrToStruct;
if (!ptrToStruct)
return resultPtr;
int newSizeInt = growSize + ptrToStruct->Count;
if (newSizeInt <= ptrToStruct->Size)
return resultPtr;
objlist_struct1* resultPtr2 = (objlist_struct1*)memory::realloc(ptrToStruct, sizeof(void*) * newSizeInt + sizeof(objlist_struct1));
if (!resultPtr2)
return resultPtr;
resultPtr = resultPtr2;
resultPtr2->Size = growSize + resultPtr2->Count;
return resultPtr;
}
int objlist_class::objlist_delete_object(objlist_struct1* ptrToStruct, void* value)
{
int count = ptrToStruct->Count;
int index = count - 1;
if (count - 1 < 0)
return 0;
for (void** i = &ptrToStruct->Array[index]; *i != value; --i)
{
if (--index < 0)
return 0;
}
ptrToStruct->Array[index] = ptrToStruct->Array[count - 1];
--ptrToStruct->Count;
return 1;
}

View File

@@ -1,28 +1,78 @@
#pragma once
struct objlist_struct1
{
int Size;
int Count;
void* Array[1];
};
#include "memory.h"
template <class T>
class objlist_class
{
public:
objlist_class(int SizeInt, int growSize);
~objlist_class();
void Add(void* value);
void Grow();
int Delete(void* value);
void* Get(int index);
int Count() const { return !ListPtr ? 0 : ListPtr->Count; }
int Size() const { return !ListPtr ? 0 : ListPtr->Size; }
objlist_class(int sizeInt, int growSize)
{
ListPtr = memory::allocate<T*>(sizeInt);
Count = 0;
Size = sizeInt;
GrowSize = growSize;
}
~objlist_class()
{
if (ListPtr)
memory::free(ListPtr);
}
void Add(T* value)
{
if (Count == Size)
Grow();
if (Count >= Size)
return;
ListPtr[Count] = value;
Count++;
}
void Grow()
{
if (!ListPtr)
return;
auto newSize = Count + GrowSize;
if (newSize <= Size)
return;
auto newList = memory::realloc(ListPtr, sizeof(T*) * newSize);
if (!newList)
return;
ListPtr = newList;
Size = newSize;
}
int Delete(T* value)
{
for (auto index = Count - 1; index >= 0; index--)
{
if (ListPtr[index] == value)
{
ListPtr[index] = ListPtr[Count - 1];
Count--;
return 1;
}
}
return 0;
}
T* Get(int index) const
{
if (index >= Count)
return nullptr;
return ListPtr[index];
}
int GetCount() const { return Count; }
int GetSize() const { return Size; }
private:
objlist_struct1* ListPtr;
T** ListPtr;
int GrowSize;
static objlist_struct1* objlist_new(int sizeInt);
static int objlist_add_object(objlist_struct1* ptrToStruct, void* value);
static objlist_struct1* objlist_grow(objlist_struct1* ptrToStruct, int growSize);
static int objlist_delete_object(objlist_struct1* ptrToStruct, void* value);
int Size;
int Count;
};

File diff suppressed because it is too large Load Diff

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
{
@@ -21,27 +56,36 @@ struct optionsStruct
int LeftTableBumpKeyDft;
int RightTableBumpKeyDft;
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);
static void path_uninit();
static int get_int(LPCSTR optPath, LPCSTR lpValueName, int defaultValue);
static void set_int(LPCSTR optPath, LPCSTR lpValueName, int data);
static void get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR lpString1, LPCSTR lpString2, int iMaxLength);
static void get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR dst, LPCSTR defaultValue, int iMaxLength);
static void set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value);
static void 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);
static void update_resolution_menu();
static void init_resolution();
static void keyboard();
static INT_PTR _stdcall KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
static LPSTR get_vk_key_name(unsigned __int16 vk, LPSTR keyName);
static LPWSTR get_vk_key_name(uint16_t vk, LPWSTR keyName);
static optionsStruct Options;
private:
@@ -52,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

@@ -9,8 +9,7 @@ short partman::_field_size[] =
2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0
};
datFileStruct* partman::load_records(LPCSTR lpFileName)
datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool fullTiltMode)
{
_OFSTRUCT ReOpenBuff{};
datFileHeader header{};
@@ -26,7 +25,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
_lclose(fileHandle);
return nullptr;
}
auto datFile = (datFileStruct*)memory::allocate(sizeof(datFileStruct));
auto datFile = memory::allocate<datFileStruct>();
if (!datFile)
{
_lclose(fileHandle);
@@ -39,7 +38,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
else
{
int lenOfStr = lstrlenA(header.Description);
auto descriptionBuf = static_cast<char*>(memory::allocate(lenOfStr + 1));
auto descriptionBuf = memory::allocate(lenOfStr + 1);
datFile->Description = descriptionBuf;
if (!descriptionBuf)
{
@@ -52,7 +51,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
if (header.Unknown)
{
auto unknownBuf = static_cast<char*>(memory::allocate(header.Unknown));
auto unknownBuf = memory::allocate(header.Unknown);
if (!unknownBuf)
{
_lclose(fileHandle);
@@ -65,7 +64,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
memory::free(unknownBuf);
}
auto groupDataBuf = (datGroupData**)memory::allocate(sizeof(void*) * header.NumberOfGroups);
auto groupDataBuf = memory::allocate<datGroupData*>(header.NumberOfGroups);
datFile->GroupData = groupDataBuf;
if (!groupDataBuf)
{
@@ -80,16 +79,15 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
{
auto entryCount = _lread_char(fileHandle);
auto groupDataSize = entryCount <= 0 ? 0 : entryCount - 1;
auto groupData = reinterpret_cast<datGroupData*>(memory::allocate(
sizeof(datEntryData) * groupDataSize + sizeof(datGroupData)));
auto groupData = memory::allocate<datGroupData>(1, sizeof(datEntryData) * groupDataSize);
datFile->GroupData[groupIndex] = groupData;
if (!groupData)
break;
groupData->EntryCount = entryCount;
datEntryData* entryData = groupData->Entries;
groupData->EntryCount = 0;
for (auto entryIndex = 0; entryIndex < entryCount; ++entryIndex)
{
auto entryData = &groupData->Entries[groupData->EntryCount];
auto entryType = static_cast<datFieldTypes>(_lread_char(fileHandle));
entryData->EntryType = entryType;
@@ -100,17 +98,28 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
if (entryType == datFieldTypes::Bitmap8bit)
{
_hread(fileHandle, &bmpHeader, sizeof(dat8BitBmpHeader));
auto bmp = reinterpret_cast<gdrv_bitmap8*>(memory::allocate(sizeof(gdrv_bitmap8)));
if (bmpHeader.Resolution != resolution && bmpHeader.Resolution != -1)
{
_llseek(fileHandle, bmpHeader.Size, 1);
continue;
}
auto bmp = memory::allocate<gdrv_bitmap8>();
entryData->Buffer = reinterpret_cast<char*>(bmp);
if (!bmp)
{
abort = true;
break;
}
if (bmpHeader.IsFlagSet(bmp8Flags::DibBitmap)
? gdrv::create_bitmap(bmp, bmpHeader.Width, bmpHeader.Height)
: gdrv::create_raw_bitmap(bmp, bmpHeader.Width, bmpHeader.Height,
bmpHeader.IsFlagSet(bmp8Flags::RawBmpUnaligned)))
int bmpRez;
if (bmpHeader.IsFlagSet(bmp8Flags::Spliced))
bmpRez = gdrv::create_spliced_bitmap(bmp, bmpHeader.Width, bmpHeader.Height, bmpHeader.Size);
else if (bmpHeader.IsFlagSet(bmp8Flags::DibBitmap))
bmpRez = gdrv::create_bitmap(bmp, bmpHeader.Width, bmpHeader.Height);
else
bmpRez = gdrv::create_raw_bitmap(bmp, bmpHeader.Width, bmpHeader.Height,
bmpHeader.IsFlagSet(bmp8Flags::RawBmpUnaligned));
if (bmpRez)
{
abort = true;
break;
@@ -121,10 +130,22 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
}
else if (entryType == datFieldTypes::Bitmap16bit)
{
/*Full tilt has extra byte(@0:resolution) in zMap*/
if (fullTiltMode)
{
char zMapResolution = _lread_char(fileHandle);
fieldSize--;
if (zMapResolution != resolution && zMapResolution != -1)
{
_llseek(fileHandle, fieldSize, 1);
continue;
}
}
_hread(fileHandle, &zMapHeader, sizeof(dat16BitBmpHeader));
int length = fieldSize - sizeof(dat16BitBmpHeader);
auto zmap = reinterpret_cast<zmap_header_type*>(memory::allocate(sizeof(zmap_header_type) + length));
auto zmap = memory::allocate<zmap_header_type>(1, length);
zmap->Width = zMapHeader.Width;
zmap->Height = zMapHeader.Height;
zmap->Stride = zMapHeader.Stride;
@@ -133,7 +154,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
}
else
{
char* entryBuffer = static_cast<char*>(memory::allocate(fieldSize));
char* entryBuffer = memory::allocate(fieldSize);
entryData->Buffer = entryBuffer;
if (!entryBuffer)
{
@@ -144,9 +165,9 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
}
entryData->FieldSize = fieldSize;
datFile->NumberOfGroups = groupIndex + 1;
++entryData;
groupData->EntryCount++;
}
datFile->NumberOfGroups = groupIndex + 1;
}
_lclose(fileHandle);
@@ -159,30 +180,23 @@ datFileStruct* partman::load_records(LPCSTR lpFileName)
void partman::unload_records(datFileStruct* datFile)
{
for (int groupIndex = 0; groupIndex < datFile->NumberOfGroups; ++groupIndex)
for (auto groupIndex = 0; groupIndex < datFile->NumberOfGroups; ++groupIndex)
{
datGroupData* group = datFile->GroupData[groupIndex];
if (group)
auto group = datFile->GroupData[groupIndex];
if (!group)
continue;
for (auto entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
{
int entryIndex = 0;
if (group->EntryCount > 0)
auto entry = &group->Entries[entryIndex];
if (entry->Buffer)
{
datEntryData* entry = group->Entries;
do
{
if (entry->Buffer)
{
if (entry->EntryType == datFieldTypes::Bitmap8bit)
gdrv::destroy_bitmap((gdrv_bitmap8*)entry->Buffer);
memory::free(entry->Buffer);
}
++entryIndex;
++entry;
}
while (entryIndex < group->EntryCount);
if (entry->EntryType == datFieldTypes::Bitmap8bit)
gdrv::destroy_bitmap(reinterpret_cast<gdrv_bitmap8*>(entry->Buffer));
memory::free(entry->Buffer);
}
memory::free(group);
}
memory::free(group);
}
if (datFile->Description)
memory::free(datFile->Description);
@@ -192,91 +206,45 @@ void partman::unload_records(datFileStruct* datFile)
char* partman::field(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType)
{
datGroupData* groupData = datFile->GroupData[groupIndex];
int entryCount = groupData->EntryCount;
int entryIndex = 0;
if (entryCount <= 0)
return nullptr;
datEntryData* entry = groupData->Entries;
while (true)
auto group = datFile->GroupData[groupIndex];
for (auto entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
{
auto entryType = entry->EntryType;
if (entryType == targetEntryType)
auto entry = &group->Entries[entryIndex];
if (entry->EntryType == targetEntryType)
return entry->Buffer;
if (entry->EntryType > targetEntryType)
break;
if (entryType > targetEntryType)
return nullptr;
++entryIndex;
++entry;
if (entryIndex < entryCount)
continue;
return nullptr;
}
return entry->Buffer;
return nullptr;
}
char* partman::field_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN)
{
datGroupData* groupData = datFile->GroupData[groupIndex];
int entryCount = groupData->EntryCount, skipCount = 0, entryIndex = 0;
if (0 < entryCount)
auto group = datFile->GroupData[groupIndex];
for (auto skipCount = 0, entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
{
datEntryData* entry = groupData->Entries;
do
{
auto entryType = entry->EntryType;
if (entryType == targetEntryType)
{
if (skipCount == skipFirstN)
{
return entry->Buffer;
}
skipCount++;
}
else
{
if (targetEntryType < entryType)
{
return nullptr;
}
}
entryIndex++;
entry++;
}
while (entryIndex < entryCount);
auto entry = &group->Entries[entryIndex];
if (entry->EntryType > targetEntryType)
break;
if (entry->EntryType == targetEntryType)
if (skipCount++ == skipFirstN)
return entry->Buffer;
}
return nullptr;
}
int partman::field_size_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN)
{
datGroupData* groupData = datFile->GroupData[groupIndex];
int entryCount = groupData->EntryCount, skipCount = 0, entryIndex = 0;
if (0 < entryCount)
auto group = datFile->GroupData[groupIndex];
for (auto skipCount = 0, entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
{
datEntryData* entry = groupData->Entries;
do
{
auto entryType = entry->EntryType;
if (entryType == targetEntryType)
{
if (skipCount == skipFirstN)
{
return entry->FieldSize;
}
skipCount++;
}
else
{
if (targetEntryType < entryType)
{
return 0;
}
}
entryIndex++;
entry++;
}
while (entryIndex < entryCount);
auto entry = &group->Entries[entryIndex];
if (entry->EntryType > targetEntryType)
return 0;
if (entry->EntryType == targetEntryType)
if (skipCount++ == skipFirstN)
return entry->FieldSize;
}
return 0;
}
@@ -288,46 +256,28 @@ int partman::field_size(datFileStruct* datFile, int groupIndex, datFieldTypes ta
int partman::record_labeled(datFileStruct* datFile, LPCSTR targetGroupName)
{
int trgGroupNameLen = lstrlenA(targetGroupName);
int groupIndex = datFile->NumberOfGroups;
while (true)
auto targetLength = lstrlenA(targetGroupName);
for (int groupIndex = datFile->NumberOfGroups - 1; groupIndex >= 0; --groupIndex)
{
if (--groupIndex < 0)
return -1;
char* groupName = field(datFile, groupIndex, datFieldTypes::GroupName);
if (groupName)
{
int index = 0;
bool found = trgGroupNameLen == 0;
if (trgGroupNameLen > 0)
{
LPCSTR targetNamePtr = targetGroupName;
do
{
if (*targetNamePtr != targetNamePtr[groupName - targetGroupName])
break;
++index;
++targetNamePtr;
}
while (index < trgGroupNameLen);
found = index == trgGroupNameLen;
}
if (found && !targetGroupName[index] && !groupName[index])
auto groupName = field(datFile, groupIndex, datFieldTypes::GroupName);
if (!groupName)
continue;
int index;
for (index = 0; index < targetLength; index++)
if (targetGroupName[index] != groupName[index])
break;
}
if (index == targetLength && !targetGroupName[index] && !groupName[index])
return groupIndex;
}
return groupIndex;
return -1;
}
char* partman::field_labeled(datFileStruct* datFile, LPCSTR lpString, datFieldTypes fieldType)
{
char* result;
int groupIndex = record_labeled(datFile, lpString);
if (groupIndex < 0)
result = nullptr;
else
result = field(datFile, groupIndex, fieldType);
return result;
auto groupIndex = record_labeled(datFile, lpString);
return groupIndex < 0 ? nullptr : field(datFile, groupIndex, fieldType);
}
char partman::_lread_char(HFILE hFile)

View File

@@ -1,6 +1,6 @@
#pragma once
enum class datFieldTypes : __int16
enum class datFieldTypes : int16_t
{
ShortValue = 0,
//, does not have the 32bits size value, but a 16bits value(see above).
@@ -28,7 +28,8 @@ enum class datFieldTypes : __int16
enum class bmp8Flags : unsigned char
{
RawBmpUnaligned = 1 << 0,
DibBitmap = 1 << 1,
DibBitmap = 1 << 1,
Spliced = 1 << 2,
};
@@ -56,7 +57,7 @@ struct datEntryData
struct datGroupData
{
__int16 EntryCount;
int16_t EntryCount;
datEntryData Entries[1];
};
@@ -71,11 +72,11 @@ struct datFileStruct
#pragma pack(1)
struct dat8BitBmpHeader
{
char Unknown1;
__int16 Width;
__int16 Height;
__int16 XPosition;
__int16 YPosition;
char Resolution;
int16_t Width;
int16_t Height;
int16_t XPosition;
int16_t YPosition;
int Size;
bmp8Flags Flags;
@@ -93,12 +94,12 @@ static_assert(sizeof(dat8BitBmpHeader) == 14, "Wrong size of dat8BitBmpHeader");
#pragma pack(push, 1)
struct __declspec(align(1)) dat16BitBmpHeader
{
__int16 Width;
__int16 Height;
__int16 Stride;
int16_t Width;
int16_t Height;
int16_t Stride;
int Unknown0;
__int16 Unknown1_0;
__int16 Unknown1_1;
int16_t Unknown1_0;
int16_t Unknown1_1;
};
#pragma pack(pop)
@@ -108,7 +109,7 @@ static_assert(sizeof(dat16BitBmpHeader) == 14, "Wrong size of zmap_header_type")
class partman
{
public:
static datFileStruct* load_records(LPCSTR lpFileName);
static datFileStruct* load_records(LPCSTR lpFileName, int resolution, bool fullTiltMode);
static void unload_records(datFileStruct* datFile);
static char* field_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN);
static char* field(datFileStruct* datFile, int groupIndex, datFieldTypes entryType);

View File

@@ -3,6 +3,7 @@
#include "control.h"
#include "fullscrn.h"
#include "high_score.h"
#include "memory.h"
#include "pinball.h"
@@ -25,9 +26,11 @@
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, pb::cheat_mode = false;
int pb::init()
{
@@ -38,7 +41,7 @@ int pb::init()
++memory::critical_allocation;
lstrcpyA(datFileName, winmain::DatFileName);
pinball::make_path_name(dataFilePath, datFileName, 300);
record_table = partman::load_records(dataFilePath);
record_table = partman::load_records(dataFilePath, fullscrn::GetResolution(), FullTiltMode);
auto useBmpFont = 0;
pinball::get_rc_int(158, &useBmpFont);
@@ -46,29 +49,32 @@ int pb::init()
score::load_msg_font("pbmsg_ft");
if (!record_table)
return (int)&record_table->NumberOfGroups + 1;
return 1;
auto plt = (PALETTEENTRY*)partman::field_labeled(record_table, "background", datFieldTypes::Palette);
gdrv::display_palette(plt);
auto tableSize = (__int16*)partman::field_labeled(record_table, "table_size", datFieldTypes::ShortArray);
auto backgroundBmp = (gdrv_bitmap8*)partman::field_labeled(record_table, "background", datFieldTypes::Bitmap8bit);
auto cameraInfo = (float*)partman::field_labeled(record_table, "camera_info", datFieldTypes::FloatArray);
auto cameraInfoId = partman::record_labeled(record_table, "camera_info") + fullscrn::GetResolution();
auto cameraInfo = (float*)partman::field(record_table, cameraInfoId, datFieldTypes::FloatArray);
/*Full tilt: table size depends on resolution*/
auto resInfo = &fullscrn::resolution_array[fullscrn::GetResolution()];
if (cameraInfo)
{
memcpy(&projMat, cameraInfo, sizeof(float) * 4 * 3);
cameraInfo += 12;
auto projCenterX = tableSize[0] * 0.5f;
auto projCenterY = tableSize[1] * 0.5f;
auto projCenterX = resInfo->TableWidth * 0.5f;
auto projCenterY = resInfo->TableHeight * 0.5f;
auto projD = cameraInfo[0];
proj::init(projMat, projD, projCenterX, projCenterY);
zMin = cameraInfo[1];
zScaler = cameraInfo[2];
}
render::init(nullptr, zMin, zScaler, tableSize[0], tableSize[1]);
render::init(nullptr, zMin, zScaler, resInfo->TableWidth, resInfo->TableHeight);
gdrv::copy_bitmap(
&render::vscreen,
backgroundBmp->Width,
@@ -94,7 +100,7 @@ int pb::init()
MainTable = new TPinballTable();
high_score::read(highscore_table, &state);
ball_speed_limit = static_cast<TBall*>(MainTable->BallList->Get(0))->Offset * 200.0f;
ball_speed_limit = MainTable->BallList->Get(0)->Offset * 200.0f;
--memory::critical_allocation;
return 0;
}
@@ -123,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)
@@ -189,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
@@ -209,7 +219,7 @@ void pb::replay_level(int demoMode)
void pb::ballset(int x, int y)
{
TBall* ball = static_cast<TBall*>(MainTable->BallList->Get(0));
TBall* ball = MainTable->BallList->Get(0);
ball->Acceleration.X = x * 30.0f;
ball->Acceleration.Y = y * 30.0f;
ball->Speed = maths::normalize_2d(&ball->Acceleration);
@@ -217,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;
@@ -233,20 +245,42 @@ int pb::frame(int time)
else
{
auto nudgeDec = nudge::nudge_count - timeMul;
if (nudgeDec <= 0.0)
if (nudgeDec <= 0.0f)
nudgeDec = 0.0;
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.5)
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.0)
if (nudge::nudge_count > 1.0f)
MainTable->tilt(time_now);
}
}
@@ -257,9 +291,9 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
{
vector_type vec1{}, vec2{};
for (int i = 0; i < MainTable->BallList->Count(); i++)
for (int i = 0; i < MainTable->BallList->GetCount(); i++)
{
auto ball = static_cast<TBall*>(MainTable->BallList->Get(i));
auto ball = MainTable->BallList->Get(i);
if (ball->ActiveFlag != 0)
{
auto collComp = ball->CollisionComp;
@@ -282,13 +316,13 @@ 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.0 ? 1000000000.0f : 1.0f / ball->Acceleration.X;
ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0 ? 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;
auto timeNow2 = timeNow;
for (auto index = 10; timeDelta2 > 0.000001 && index; --index)
for (auto index = 10; timeDelta2 > 0.000001f && index; --index)
{
auto time = collide(timeNow2, timeDelta2, ball);
timeDelta2 -= time;
@@ -300,9 +334,9 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
if (drawBalls)
{
for (int i = 0; i < MainTable->BallList->Count(); i++)
for (int i = 0; i < MainTable->BallList->GetCount(); i++)
{
auto ball = static_cast<TBall*>(MainTable->BallList->Get(i));
auto ball = MainTable->BallList->Get(i);
if (ball->ActiveFlag)
ball->Repaint();
}
@@ -311,8 +345,8 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
void pb::window_size(int* width, int* height)
{
*width = 600;
*height = 416;
*width = fullscrn::resolution_array[fullscrn::GetResolution()].TableWidth;
*height = fullscrn::resolution_array[fullscrn::GetResolution()].TableHeight;
}
void pb::pause_continue()
@@ -324,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
@@ -333,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);
}
@@ -398,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);
@@ -440,7 +474,7 @@ void pb::keydown(int key)
{
case 'B':
TBall* ball;
if (MainTable->BallList->Count() <= 0)
if (MainTable->BallList->GetCount() <= 0)
{
ball = new TBall(MainTable);
}
@@ -448,11 +482,11 @@ void pb::keydown(int key)
{
for (auto index = 0; ;)
{
ball = static_cast<TBall*>(MainTable->BallList->Get(index));
ball = MainTable->BallList->Get(index);
if (!ball->ActiveFlag)
break;
++index;
if (index >= MainTable->BallList->Count())
if (index >= MainTable->BallList->GetCount())
{
ball = new TBall(MainTable);
break;
@@ -468,13 +502,13 @@ 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':
char buffer[20];
sprintf_s(buffer, "%ld", memory::use_total);
sprintf_s(buffer, "%zu", memory::use_total);
MessageBoxA(winmain::hwnd_frame, buffer, "Mem:", 0x2000u);
break;
case 'R':
@@ -522,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;
@@ -545,7 +579,7 @@ void pb::end_game()
scores[j] = scores[i];
scores[i] = score;
int index = scoreIndex[j];
int index = scoreIndex[j];
scoreIndex[j] = scoreIndex[i];
scoreIndex[i] = index;
}
@@ -559,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);
}
}
@@ -626,7 +660,7 @@ float pb::collide(float timeNow, float timeDelta, TBall* ball)
TEdgeSegment* edge = nullptr;
auto distance = TTableLayer::edge_manager->FindCollisionDistance(&ray, ball, &edge);
ball->EdgeCollisionCount = 0;
if (distance >= 1000000000.0)
if (distance >= 1000000000.0f)
{
maxDistance = timeDelta * ball->Speed;
ball->RayMaxDistance = maxDistance;
@@ -638,7 +672,7 @@ float pb::collide(float timeNow, float timeDelta, TBall* ball)
else
{
edge->EdgeCollision(ball, distance);
if (ball->Speed > 0.000000001)
if (ball->Speed > 0.000000001f)
return fabs(distance / ball->Speed);
}
}

View File

@@ -10,10 +10,12 @@ 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];
static bool FullTiltMode;
static int init();
static int uninit();
@@ -38,7 +40,7 @@ public:
static void tilt_no_more();
static bool chk_highscore();
static float collide(float timeNow, float timeDelta, TBall* ball);
private :
private:
static int demo_mode, mode_countdown_;
static int state;
};

View File

@@ -16,6 +16,7 @@
#include <cmath>
#include <CommCtrl.h>
#include <htmlhelp.h>
#include <cstdint>
#include <type_traits> /*For control template*/
//#include <cstdlib>
@@ -25,4 +26,13 @@
/*Sound uses PlaySound*/
#undef PlaySound
inline size_t pgm_save(int width, int height, char* data, FILE* outfile)
{
size_t n = 0;
n += fprintf(outfile, "P5\n%d %d\n%d\n", width, height, 0xFF);
n += fwrite(data, 1, width * height, outfile);
return n;
}
#endif //PCH_H

View File

@@ -8,8 +8,8 @@ int pinball::quickFlag = 0;
TTextBox* pinball::InfoTextBox;
TTextBox* pinball::MissTextBox;
char pinball::getRcBuffer[6 * 256];
int pinball::rc_string_slot = 0;
char pinball::WindowName[2]{};
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;
@@ -23,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

@@ -13,16 +13,17 @@ public:
static int quickFlag;
static TTextBox* InfoTextBox;
static TTextBox* MissTextBox;
static char WindowName[2];
static int RightShift;
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

@@ -47,7 +47,7 @@ void proj::xform_to_2d(vector_type* vec, int* dst)
vector_type dstVec2{};
matrix_vector_multiply(&matrix, vec, &dstVec2);
if (0.0 == dstVec2.Z)
if (dstVec2.Z == 0.0f)
projCoef = 999999.88f;
else
projCoef = d_ / dstVec2.Z;

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;
@@ -18,9 +17,9 @@ void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int h
zscaler = zScaler;
zmin = zMin;
zmax = 4294967300.0f / zScaler + zMin;
sprite_list = reinterpret_cast<render_sprite_type_struct**>(memory::allocate(1000 * sizeof(void*)));
dirty_list = reinterpret_cast<render_sprite_type_struct**>(memory::allocate(1000 * sizeof(void*)));
ball_list = reinterpret_cast<render_sprite_type_struct**>(memory::allocate(20 * sizeof(void*)));
sprite_list = memory::allocate<render_sprite_type_struct*>(1000);
dirty_list = memory::allocate<render_sprite_type_struct*>(1000);
ball_list = memory::allocate<render_sprite_type_struct*>(20);
gdrv::create_bitmap(&vscreen, width, height);
zdrv::create_zmap(&zscreen, width, height);
zdrv::fill(&zscreen, zscreen.Width, zscreen.Height, 0, 0, 0xFFFF);
@@ -48,9 +47,9 @@ void render::uninit()
{
gdrv::destroy_bitmap(&vscreen);
zdrv::destroy_zmap(&zscreen);
for (int i = 0; i < many_sprites; ++i)
for (auto i = many_sprites - 1; i >= 0; --i)
remove_sprite(sprite_list[i]);
for (int j = 0; j < many_balls; ++j)
for (auto j = many_balls - 1; j >= 0; --j)
remove_ball(ball_list[j]);
memory::free(ball_list);
memory::free(dirty_list);
@@ -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();
@@ -221,7 +210,7 @@ void render::sprite_modified(render_sprite_type_struct* sprite)
render_sprite_type_struct* render::create_sprite(VisualType visualType, gdrv_bitmap8* bmp, zmap_header_type* zMap,
int xPosition, int yPosition, rectangle_type* rect)
{
auto sprite = (render_sprite_type_struct*)memory::allocate(sizeof(render_sprite_type_struct));
auto sprite = memory::allocate<render_sprite_type_struct>();
if (!sprite)
return nullptr;
sprite->BmpRect.YPosition = yPosition;
@@ -278,7 +267,6 @@ render_sprite_type_struct* render::create_sprite(VisualType visualType, gdrv_bit
void render::remove_sprite(render_sprite_type_struct* sprite)
{
int spriteCount = many_sprites;
int index = 0;
if (many_sprites > 0)
{
@@ -287,13 +275,12 @@ void render::remove_sprite(render_sprite_type_struct* sprite)
if (++index >= many_sprites)
return;
}
while (index < spriteCount)
while (index < many_sprites)
{
sprite_list[index] = sprite_list[index + 1];
spriteCount = many_sprites;
++index;
}
many_sprites = spriteCount - 1;
many_sprites--;
if (sprite->SpriteArray)
memory::free(sprite->SpriteArray);
memory::free(sprite);
@@ -302,7 +289,6 @@ void render::remove_sprite(render_sprite_type_struct* sprite)
void render::remove_ball(struct render_sprite_type_struct* ball)
{
int ballCount = many_balls;
int index = 0;
if (many_balls > 0)
{
@@ -311,13 +297,12 @@ void render::remove_ball(struct render_sprite_type_struct* ball)
if (++index >= many_balls)
return;
}
while (index < ballCount)
while (index < many_balls)
{
ball_list[index] = ball_list[index + 1];
ballCount = many_balls;
++index;
}
many_balls = ballCount - 1;
many_balls--;
memory::free(ball);
}
}
@@ -477,35 +462,21 @@ void render::paint_balls()
void render::unpaint_balls()
{
auto ballPtr = &ball_list[many_balls - 1];
if (many_balls - 1 >= 0)
for (int index = many_balls - 1; index >= 0; index--)
{
gdrv_bitmap8* bitmapPtr = &ball_bitmap[many_balls - 1];
for (int index = many_balls; index > 0; index--)
{
struct render_sprite_type_struct* curBall = *ballPtr;
rectangle_type* rect2 = &(*ballPtr)->DirtyRect;
int width = (*ballPtr)->DirtyRect.Width;
if (width > 0)
gdrv::copy_bitmap(
&vscreen,
width,
(*ballPtr)->DirtyRect.Height,
(*ballPtr)->DirtyRect.XPosition,
(*ballPtr)->DirtyRect.YPosition,
bitmapPtr,
0,
0);
auto curBall = ball_list[index];
if (curBall->DirtyRect.Width > 0)
gdrv::copy_bitmap(
&vscreen,
curBall->DirtyRect.Width,
curBall->DirtyRect.Height,
curBall->DirtyRect.XPosition,
curBall->DirtyRect.YPosition,
&ball_bitmap[index],
0,
0);
rectangle_type* rectCopy = &curBall->BmpRectCopy;
rectCopy->XPosition = rect2->XPosition;
rectCopy->YPosition = rect2->YPosition;
rectCopy->Width = rect2->Width;
rectCopy->Height = rect2->Height;
--ballPtr;
--bitmapPtr;
}
curBall->BmpRectCopy = curBall->DirtyRect;
}
}
@@ -542,7 +513,7 @@ void render::build_occlude_list()
if (!curSprite->UnknownFlag && curSprite->BoundingRect.Width != -1)
{
if (!spriteArr)
spriteArr = reinterpret_cast<render_sprite_type_struct**>(memory::allocate(1000 * sizeof(void*)));
spriteArr = memory::allocate<render_sprite_type_struct*>(1000);
int occludeCount = 0;
auto spritePtr2 = sprite_list;
for (int i = 0; i < many_sprites; ++i, ++spritePtr2)
@@ -560,8 +531,7 @@ void render::build_occlude_list()
occludeCount = 0;
if (occludeCount)
{
curSprite->SpriteArray = reinterpret_cast<render_sprite_type_struct**>(memory::realloc(
spriteArr, sizeof(void*) * occludeCount));
curSprite->SpriteArray = memory::realloc(spriteArr, sizeof(void*) * occludeCount);
curSprite->SpriteCount = occludeCount;
spriteArr = nullptr;
}

View File

@@ -17,7 +17,7 @@ struct render_sprite_type_struct
zmap_header_type* ZMap;
char UnknownFlag;
VisualType VisualType;
__int16 Depth;
int16_t Depth;
rectangle_type BmpRectCopy;
int ZMapOffestY;
int ZMapOffestX;
@@ -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

@@ -224,25 +224,33 @@
#define Menu1_2Players 409
#define Menu1_3Players 410
#define Menu1_4Players 411
#define Menu1_MaximumResolution 500
#define DLG_HIGHSCORES_Score1 501
#define KEYMAPPER_Default 501
#define Menu1_640x480 501
#define DLG_HIGHSCORES_Score2 502
#define Menu1_800x600 502
#define DLG_HIGHSCORES_Score3 503
#define Menu1_1024x768 503
#define DLG_HIGHSCORES_Score4 504
#define DLG_HIGHSCORES_Score5 505
#define Menu1_WindowUniformScale 600
#define DLG_HIGHSCORES_EditName1 601
#define DLG_HIGHSCORES_EditName2 602
#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
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 204
#define _APS_NEXT_COMMAND_VALUE 40004
#define _APS_NEXT_COMMAND_VALUE 40006
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 102
#define _APS_NEXT_SYMED_VALUE 104
#endif
#endif

View File

@@ -1,8 +1,11 @@
#include "pch.h"
#include "score.h"
#include "fullscrn.h"
#include "loader.h"
#include "memory.h"
#include "partman.h"
#include "pb.h"
#include "render.h"
#include "TDrain.h"
#include "winmain.h"
@@ -16,23 +19,26 @@ int score::init()
scoreStruct* score::create(LPCSTR fieldName, gdrv_bitmap8* renderBgBmp)
{
auto score = reinterpret_cast<scoreStruct*>(memory::allocate(sizeof(scoreStruct)));
auto score = memory::allocate<scoreStruct>();
if (!score)
return nullptr;
score->Score = -9999;
score->BackgroundBmp = renderBgBmp;
auto shortArr = reinterpret_cast<__int16*>(partman::field_labeled(loader::loader_table, fieldName,
datFieldTypes::ShortArray));
if (!shortArr)
/*Full tilt: score box dimensions index is offset by resolution*/
auto dimensionsId = partman::record_labeled(pb::record_table, fieldName) + fullscrn::GetResolution();
auto dimensions = reinterpret_cast<int16_t*>(partman::field(loader::loader_table, dimensionsId,
datFieldTypes::ShortArray));
if (!dimensions)
{
memory::free(score);
return nullptr;
}
int groupIndex = *shortArr++;
score->OffsetX = *shortArr++;
score->OffsetY = *shortArr++;
score->Width = *shortArr++;
score->Height = *shortArr;
int groupIndex = *dimensions++;
score->OffsetX = *dimensions++;
score->OffsetY = *dimensions++;
score->Width = *dimensions++;
score->Height = *dimensions;
for (int index = 0; index < 10; index++)
{
@@ -45,13 +51,22 @@ scoreStruct* score::create(LPCSTR fieldName, gdrv_bitmap8* renderBgBmp)
scoreStruct* score::dup(scoreStruct* score, int scoreIndex)
{
auto result = reinterpret_cast<scoreStruct*>(memory::allocate(sizeof(scoreStruct)));
auto result = memory::allocate<scoreStruct>();
if (result)
memcpy(result, score, sizeof(scoreStruct));
return result;
}
void score::load_msg_font(LPCSTR lpName)
{
/*3DPB stores font in resources, FT in dat. FT font has multiple resolutions*/
if (pb::FullTiltMode)
load_msg_font_FT(lpName);
else
load_msg_font_3DPB(lpName);
}
void score::load_msg_font_3DPB(LPCSTR lpName)
{
auto resHandle = FindResourceA(winmain::hinst, lpName, RT_RCDATA);
if (!resHandle)
@@ -61,16 +76,16 @@ void score::load_msg_font(LPCSTR lpName)
if (!resGlobal)
return;
auto rcData = static_cast<__int16*>(LockResource(resGlobal));
auto rcData = static_cast<int16_t*>(LockResource(resGlobal));
auto fontp = reinterpret_cast<score_msg_font_type*>(memory::allocate(sizeof(score_msg_font_type)));
auto fontp = memory::allocate<score_msg_font_type>();
msg_fontp = fontp;
if (!fontp)
{
FreeResource(resGlobal);
return;
}
memset(fontp->Chars, 0, sizeof(fontp->Chars));
memset(fontp->Chars, 0, sizeof fontp->Chars);
auto maxWidth = 0;
auto ptrToWidths = (char*)rcData + 6;
@@ -102,7 +117,7 @@ void score::load_msg_font(LPCSTR lpName)
if (!width)
continue;
auto bmp = reinterpret_cast<gdrv_bitmap8*>(memory::allocate(sizeof(gdrv_bitmap8)));
auto bmp = memory::allocate<gdrv_bitmap8>();
msg_fontp->Chars[charInd] = bmp;
if (!bmp)
{
@@ -130,23 +145,56 @@ void score::load_msg_font(LPCSTR lpName)
}
}
memory::free(tmpCharBur);
if (charInd != 128)
unload_msg_font();
FreeResource(resGlobal);
}
void score::load_msg_font_FT(LPCSTR lpName)
{
if (!pb::record_table)
return;
int groupIndex = partman::record_labeled(pb::record_table, lpName);
if (groupIndex < 0)
return;
msg_fontp = reinterpret_cast<score_msg_font_type*>(memory::allocate(sizeof(score_msg_font_type)));
if (!msg_fontp)
return;
memset(msg_fontp, 0, sizeof(score_msg_font_type));
auto gapArray = reinterpret_cast<int16_t*>(partman::field(pb::record_table, groupIndex, datFieldTypes::ShortArray));
if (gapArray)
msg_fontp->GapWidth = gapArray[fullscrn::GetResolution()];
else
msg_fontp->GapWidth = 0;
for (auto charIndex = 32; charIndex < 128; charIndex++, ++groupIndex)
{
auto bmp = reinterpret_cast<gdrv_bitmap8*>(partman::field(pb::record_table, groupIndex,
datFieldTypes::Bitmap8bit));
if (!bmp)
break;
if (!msg_fontp->Height)
msg_fontp->Height = bmp->Height;
msg_fontp->Chars[charIndex] = bmp;
}
}
void score::unload_msg_font()
{
if (msg_fontp)
{
for (int i = 0; i < 128; i++)
{
if (msg_fontp->Chars[i])
/*3DB creates bitmaps, FT just references them from partman*/
if (!pb::FullTiltMode)
for (int i = 0; i < 128; i++)
{
gdrv::destroy_bitmap(msg_fontp->Chars[i]);
memory::free(msg_fontp->Chars[i]);
if (msg_fontp->Chars[i])
{
gdrv::destroy_bitmap(msg_fontp->Chars[i]);
memory::free(msg_fontp->Chars[i]);
}
}
}
memory::free(msg_fontp);
msg_fontp = nullptr;
}
}
@@ -191,7 +239,7 @@ void score::set(scoreStruct* score, int value)
void score::update(scoreStruct* score)
{
char scoreBuf[12];
char scoreBuf[12]{};
if (score && score->DirtyFlag && score->Score <= 1000000000)
{
score->DirtyFlag = false;
@@ -201,12 +249,11 @@ void score::update(scoreStruct* score)
if (score->Score >= 0)
{
_ltoa_s(score->Score, scoreBuf, 10);
int len = strlen(scoreBuf);
for (int index = len - 1; index >= 0; index--)
for (ptrdiff_t index = strlen(scoreBuf) - 1; index >= 0; index--)
{
unsigned char curChar = scoreBuf[index];
curChar -= '0';
gdrv_bitmap8* bmp = score->CharBmp[curChar];
gdrv_bitmap8* bmp = score->CharBmp[curChar % 10];
x -= bmp->Width;
int height = bmp->Height;
int width = bmp->Width;

View File

@@ -42,4 +42,7 @@ public:
static void set(scoreStruct* score, int value);
static void update(scoreStruct* score);
static void string_format(int score, char* str);
private :
static void load_msg_font_3DPB(LPCSTR lpName);
static void load_msg_font_FT(LPCSTR lpName);
};

View File

@@ -6,13 +6,14 @@
#include "pinball.h"
HINSTANCE splash::HInstance;
HGDIOBJ splash::OriginalDcBitmap = nullptr;
splash_struct* splash::splash_screen(HINSTANCE hInstance, LPCSTR bmpName1, LPCSTR bmpName2)
{
WNDCLASSA WndClass{};
tagRECT Rect{};
auto splashStruct = reinterpret_cast<splash_struct*>(memory::allocate(sizeof(splash_struct)));
auto splashStruct = memory::allocate<splash_struct>();
if (!splashStruct)
return nullptr;
@@ -29,12 +30,12 @@ splash_struct* splash::splash_screen(HINSTANCE hInstance, LPCSTR bmpName1, LPCST
WndClass.hIcon = nullptr;
WndClass.hCursor = LoadCursorA(nullptr, IDC_ARROW);
WndClass.hbrBackground = nullptr;
WndClass.lpszMenuName = pinball::WindowName;
WndClass.lpszMenuName = "";
WndClass.lpszClassName = "3DPB_SPLASH_CLASS";
RegisterClassA(&WndClass);
}
splashStruct->Bitmap = nullptr;
HWND windowHandle = CreateWindowExA(0, "3DPB_SPLASH_CLASS", pinball::WindowName, 0x80000000, -10, -10, 1, 1,
HWND windowHandle = CreateWindowExA(0, "3DPB_SPLASH_CLASS", "", 0x80000000, -10, -10, 1, 1,
nullptr, nullptr, HInstance, nullptr);
splashStruct->WindowHandle = windowHandle;
if (!windowHandle)
@@ -75,7 +76,7 @@ void splash::splash_bitmap_setup(splash_struct* splashStruct)
{
if (splashStruct->DrawingContext)
{
SelectObject(splashStruct->DrawingContext, bmpHandle1);
OriginalDcBitmap = SelectObject(splashStruct->DrawingContext, bmpHandle1);
if ((GetDeviceCaps(splashStruct->DrawingContext, RASTERCAPS) & RC_PALETTE) != 0
|| GetDeviceCaps(splashStruct->DrawingContext, NUMCOLORS) >= 256)
{
@@ -85,6 +86,7 @@ void splash::splash_bitmap_setup(splash_struct* splashStruct)
else
{
bmpHandle2 = LoadBitmapA(HInstance, splashStruct->BmpName2);
splashStruct->Palette = nullptr;
}
splashStruct->Bitmap = bmpHandle2;
@@ -162,11 +164,11 @@ HBITMAP splash::load_title_bitmap(HMODULE hModule, HDC hdc, LPCSTR lpName, UINT
return resBmp;
}
HPALETTE splash::splash_init_palette(LOGPALETTEx256* plpal)
HPALETTE splash::splash_init_palette(LOGPALETTE* plpal)
{
plpal->palVersion = 768;
plpal->palNumEntries = 256;
auto hPalette = CreatePalette(reinterpret_cast<const LOGPALETTE*>(plpal));
auto hPalette = CreatePalette(static_cast<const LOGPALETTE*>(plpal));
auto dc = GetDC(GetDesktopWindow());
GetDeviceCaps(dc, RASTERCAPS);
if (GetDeviceCaps(dc, SIZEPALETTE) != 256)
@@ -243,7 +245,11 @@ void splash::splash_destroy(splash_struct* splashStruct)
splashStruct->Palette = nullptr;
if (splashStruct->DrawingContext)
{
if (OriginalDcBitmap)
SelectObject(splashStruct->DrawingContext, OriginalDcBitmap);
DeleteDC(splashStruct->DrawingContext);
}
if (splashStruct->Bitmap)
DeleteObject(splashStruct->Bitmap);
}
@@ -278,12 +284,15 @@ LRESULT splash::splash_message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARA
BeginPaint(hWnd, &Paint);
EndPaint(hWnd, &Paint);
auto dc = GetDC(hWnd);
if (dc && splashStruct)
if (dc)
{
BitBlt(dc, 0, 0, 10000, 10000, dc, 0, 0, BLACKNESS);
splash_paint(splashStruct, dc);
if (splashStruct)
{
BitBlt(dc, 0, 0, 10000, 10000, dc, 0, 0, BLACKNESS);
splash_paint(splashStruct, dc);
}
ReleaseDC(hWnd, dc);
}
ReleaseDC(hWnd, dc);
break;
}
case WM_ERASEBKGND:

View File

@@ -22,12 +22,14 @@ class splash
public:
static splash_struct* splash_screen(HINSTANCE hInstance, LPCSTR bmpName1, LPCSTR bmpName2);
static void splash_bitmap_setup(splash_struct* splashStruct);
static HBITMAP load_title_bitmap(HMODULE hModule, HDC hdc, LPCSTR lpName, UINT iStart, int iEnd, HPALETTE* palettePtr);
static HPALETTE splash_init_palette(LOGPALETTEx256* plpal);
static HBITMAP load_title_bitmap(HMODULE hModule, HDC hdc, LPCSTR lpName, UINT iStart, int iEnd,
HPALETTE* palettePtr);
static HPALETTE splash_init_palette(LOGPALETTE* plpal);
static void splash_paint(splash_struct* splashStruct, HDC dc);
static void splash_destroy(splash_struct* splashStruct);
static void splash_hide(splash_struct* splashStruct);
static LRESULT __stdcall splash_message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
private:
static HINSTANCE HInstance;
static HGDIOBJ OriginalDcBitmap;
};

View File

@@ -13,7 +13,7 @@ timer_struct* timer::TimerBuffer;
int timer::init(int count)
{
auto buf = (timer_struct*)memory::allocate(sizeof(timer_struct) * count);
auto buf = memory::allocate<timer_struct>(count);
TimerBuffer = buf;
if (!buf)
return 1;

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,8 @@
class winmain
{
public:
static const DWORD WndStyle = WS_GROUP | WS_SYSMENU | WS_DLGFRAME | WS_BORDER | WS_MAXIMIZE | WS_CLIPCHILDREN |
WS_THICKFRAME | WS_MAXIMIZEBOX;
static char DatFileName[300];
static int single_step;
static HINSTANCE hinst;
@@ -20,6 +22,7 @@ public:
static void new_game();
static void pause();
static void help_introduction(HINSTANCE a1, HWND a2);
static void Restart();
private:
static int return_value, bQuit, DispFrameRate, DispGRhistory, activated;
static int has_focus, mouse_down, last_mouse_x, last_mouse_y, no_time_loss;
@@ -27,6 +30,7 @@ private:
static UINT iFrostUniqueMsg;
static gdrv_bitmap8 gfr_display;
static HCURSOR mouse_hsave;
static bool restart;
static HDC _BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
};

View File

@@ -1,13 +1,14 @@
#include "pch.h"
#include "zdrv.h"
#include "memory.h"
#include "pb.h"
int zdrv::create_zmap(zmap_header_type* zmap, int width, int height)
{
int stride = pad(width);
zmap->Stride = stride;
auto bmpBuf = (unsigned short*)memory::allocate(2 * height * stride);
auto bmpBuf = memory::allocate<unsigned short>(height * stride);
zmap->ZPtr1 = bmpBuf;
if (!bmpBuf)
return -1;
@@ -35,22 +36,16 @@ int zdrv::destroy_zmap(zmap_header_type* zmap)
return 0;
}
void zdrv::fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, unsigned __int16 fillChar)
void zdrv::fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, uint16_t fillWord)
{
int fillCharInt = fillChar | (fillChar << 16);
auto zmapPtr = &zmap->ZPtr1[xOff + zmap->Stride * (zmap->Height - height - yOff)];
for (int y = height; width > 0 && y > 0; y--)
auto dstPtr = &zmap->ZPtr1[zmap->Stride * (zmap->Height - height - yOff) + xOff];
for (int y = height; y > 0; --y)
{
char widthMod2 = width & 1;
unsigned int widthDiv2 = static_cast<unsigned int>(width) >> 1;
memset32(zmapPtr, fillCharInt, widthDiv2);
auto lastShort = &zmapPtr[2 * widthDiv2];
for (int i = widthMod2; i; --i)
*lastShort++ = fillChar;
zmapPtr += zmap->Stride;
for (int x = width; x > 0; --x)
{
*dstPtr++ = fillWord;
}
dstPtr += zmap->Stride - width;
}
}
@@ -59,6 +54,13 @@ void zdrv::paint(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, in
int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff, int srcBmpYOff,
zmap_header_type* srcZMap, int srcZMapXOff, int srcZMapYOff)
{
if (srcBmp->BitmapType == BitmapType::Spliced)
{
/*Spliced bitmap is also a zMap, how convenient*/
paint_spliced_bmp(srcBmp->XPosition, srcBmp->YPosition, dstBmp, dstZMap, srcBmp);
return;
}
int dstHeightAbs = abs(dstBmp->Height);
int srcHeightAbs = abs(srcBmp->Height);
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeightAbs - height - srcBmpYOff) + srcBmpXOff];
@@ -90,7 +92,7 @@ void zdrv::paint(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, in
void zdrv::paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff,
zmap_header_type* zMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff,
int srcBmpYOff, unsigned __int16 depth)
int srcBmpYOff, uint16_t depth)
{
int dstHeightAbs = abs(dstBmp->Height);
int srcHeightAbs = abs(srcBmp->Height);
@@ -116,3 +118,41 @@ void zdrv::paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOf
zPtr += zMap->Stride - width;
}
}
void zdrv::paint_spliced_bmp(int xPos, int yPos, gdrv_bitmap8* dstBmp, zmap_header_type* dstZmap, gdrv_bitmap8* srcBmp)
{
assertm(srcBmp->BitmapType == BitmapType::Spliced, "Wrong bmp type");
int xOffset = xPos - pb::MainTable->XOffset;
int yOffset = dstBmp->Height - srcBmp->Height - (yPos - pb::MainTable->YOffset);
if (yOffset < 0)
return;
auto bmpDstPtr = &dstBmp->BmpBufPtr2[xOffset + yOffset * dstBmp->Stride];
auto zMapDstPtr = &dstZmap->ZPtr2[xOffset + yOffset * dstZmap->Stride];
auto bmpSrcPtr = reinterpret_cast<unsigned short*>(srcBmp->BmpBufPtr2);
while (true)
{
auto stride = static_cast<short>(*bmpSrcPtr++);
if (stride < 0)
break;
/*Stride is in terms of dst stride, hardcoded to match vScreen width in current resolution*/
zMapDstPtr += stride;
bmpDstPtr += stride;
for (auto count = *bmpSrcPtr++; count; count--)
{
auto depth = *bmpSrcPtr++;
auto charPtr = reinterpret_cast<char**>(&bmpSrcPtr);
if (*zMapDstPtr >= depth)
{
*bmpDstPtr = **charPtr;
*zMapDstPtr = depth;
}
(*charPtr)++;
++zMapDstPtr;
++bmpDstPtr;
}
}
}

View File

@@ -3,12 +3,12 @@
struct zmap_header_type
{
__int16 Width;
__int16 Height;
__int16 Stride;
unsigned __int16* ZPtr1;
unsigned __int16* ZPtr2;
unsigned __int16 ZBuffer[1];
int Width;
int Height;
int Stride;
uint16_t* ZPtr1;
uint16_t* ZPtr2;
uint16_t ZBuffer[1];
};
class zdrv
@@ -17,11 +17,13 @@ public:
static int pad(int width);
static int create_zmap(zmap_header_type* zmap, int width, int height);
static int destroy_zmap(zmap_header_type* zmap);
static void fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, unsigned __int16 fillChar);
static void fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, uint16_t fillWord);
static void paint(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff,
zmap_header_type* dstZMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff,
int srcBmpYOff, zmap_header_type* srcZMap, int srcZMapXOff, int srcZMapYOff);
static void paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff,
zmap_header_type* zMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp,
int srcBmpXOff, int srcBmpYOff, unsigned __int16 depth);
int srcBmpXOff, int srcBmpYOff, uint16_t depth);
static void paint_spliced_bmp(int xPos, int yPos, gdrv_bitmap8* dstBmp, zmap_header_type* dstZmap,
gdrv_bitmap8* srcBmp);
};