Compare commits
23 Commits
Release_1.
...
Release_1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
331f1dc125 | ||
|
|
0d9610ddb6 | ||
|
|
de76557325 | ||
|
|
b995b02fd1 | ||
|
|
de6c31802c | ||
|
|
86eaad5b79 | ||
|
|
60e9f63607 | ||
|
|
10c83e8bf5 | ||
|
|
d5b44e44e1 | ||
|
|
dcd488c48c | ||
|
|
db08631ab9 | ||
|
|
bad55d49cf | ||
|
|
98f234fce3 | ||
|
|
55984fbb08 | ||
|
|
5c3e9fea4c | ||
|
|
debe52c1e0 | ||
|
|
1c5256a4c6 | ||
|
|
d594f5fdb7 | ||
|
|
49f6132d23 | ||
|
|
6ff457eb68 | ||
|
|
5b9a1ff95d | ||
|
|
232f24a2a2 | ||
|
|
efc56e82d9 |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -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/
|
||||
|
||||
@@ -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"
|
||||
@@ -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
21
LICENSE
Normal 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.
|
||||
40
README.md
Normal file
40
README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# 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~~
|
||||
* Misc features of Full Tilt: 3 music tracs, multiball, centered textboxes, etc.
|
||||
* Maybe: cross-platform port
|
||||
* Needs UI framework with menu bar and dialog windows, like QT or Avalonia
|
||||
* Needs a way play sounds and midi
|
||||
* 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`
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "pch.h"
|
||||
#include "Sound.h"
|
||||
|
||||
|
||||
#include "pb.h"
|
||||
#include "pinball.h"
|
||||
#include "WaveMix.h"
|
||||
#include "winmain.h"
|
||||
@@ -45,7 +47,9 @@ int Sound::Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWA
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBoxA(winmain::hwnd_frame, pinball::get_rc_string(42, 0), pinball::WindowName, 0x2000u);
|
||||
/*FT does not have the file, defaults work OK*/
|
||||
if (!pb::FullTiltMode)
|
||||
MessageBoxA(winmain::hwnd_frame, pinball::get_rc_string(42, 0), "", 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{};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -20,17 +20,17 @@ 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);
|
||||
gdrv::init(nullptr, nullptr);
|
||||
auto dib = gdrv::DibCreate(8, 1, 1);
|
||||
gdrv::DibSetUsage(dib, 0, 1);
|
||||
gdrv::DibSetUsage(dib, nullptr, 1);
|
||||
|
||||
objlist_class d = objlist_class(2, 4);
|
||||
for (int i = 0; i < 100; i++)
|
||||
auto d = objlist_class<void>(2, 4);
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
{
|
||||
d.Add((void*)i);
|
||||
}
|
||||
|
||||
@@ -88,6 +88,18 @@ BEGIN
|
||||
MENUITEM "&Music", Menu1_Music
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "P&layer Controls...\tF8", Menu1_Player_Controls
|
||||
POPUP "Table &Resolution"
|
||||
BEGIN
|
||||
MENUITEM "Use &Maximum Resolution", Menu1_MaximumResolution
|
||||
MENUITEM "&640 x 480", Menu1_640x480
|
||||
MENUITEM "&800 x 600", Menu1_800x600
|
||||
MENUITEM "&1024 x 768", Menu1_1024x768
|
||||
END
|
||||
POPUP "&Window"
|
||||
BEGIN
|
||||
MENUITEM "&Uniform Scaling", Menu1_WindowUniformScale
|
||||
MENUITEM "&Alternative Rendering", Menu1_AlternativeRender
|
||||
END
|
||||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
@@ -342,7 +354,7 @@ END
|
||||
// Bitmap
|
||||
//
|
||||
|
||||
splash_bitmap BITMAP "splash_bitmap.bmp"
|
||||
SPLASH_BITMAP BITMAP "splash_bitmap.bmp"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -587,6 +599,17 @@ BEGIN
|
||||
IDS_STRING289 "255 255 255 (R G B default font color)"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
2030 "Use &Maximum Resolution (640 x 480)"
|
||||
2031 "Use &Maximum Resolution (800 x 600)"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
2032 "Use &Maximum Resolution (1024 x 768)"
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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, ¢er, radius);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -19,8 +19,8 @@ public:
|
||||
int BmpIndex;
|
||||
TFlipperEdge* FlipperEdge;
|
||||
int Timer;
|
||||
float BmpCoef1;
|
||||
float BmpCoef2;
|
||||
float ExtendAnimationFrameTime;
|
||||
float RetractAnimationFrameTime;
|
||||
float TimerTime;
|
||||
float InputTime;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
List->Get(i)->Message(20, 0.0);
|
||||
}
|
||||
}
|
||||
if (countSub1 >= 0)
|
||||
|
||||
// Turn on lights [begin, index]
|
||||
for (auto i = index; i >= 0; i--)
|
||||
{
|
||||
for (auto i = countSub1; i != 0; i--)
|
||||
{
|
||||
auto light = static_cast<TLight*>(List->Get(i));
|
||||
light->Message(19, 0.0);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -307,9 +307,9 @@ void TPinballTable::tilt(float time)
|
||||
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,9 +320,9 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
@@ -513,9 +513,9 @@ 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;
|
||||
@@ -564,9 +564,9 @@ int TPinballTable::Message(int code, float value)
|
||||
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,9 +608,9 @@ 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);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,45 +219,45 @@ 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;
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
float Unknown3F;
|
||||
float Unknown4F;
|
||||
float GraityDirX;
|
||||
float GraityDiY;
|
||||
float GraityDirY;
|
||||
int Unknown7;
|
||||
float GraityMult;
|
||||
field_effect_type Field;
|
||||
|
||||
@@ -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,7 +109,7 @@ void TTextBox::Clear()
|
||||
}
|
||||
}
|
||||
|
||||
void TTextBox::Display(char* text, float time)
|
||||
void TTextBox::Display(const char* text, float time)
|
||||
{
|
||||
if (!text)
|
||||
return;
|
||||
@@ -118,7 +121,7 @@ void TTextBox::Display(char* text, float time)
|
||||
{
|
||||
if (Timer && Timer != -1)
|
||||
timer::kill(Timer);
|
||||
if (time == -1.0)
|
||||
if (time == -1.0f)
|
||||
Timer = -1;
|
||||
else
|
||||
Timer = timer::set(time, this, TimerExpired);
|
||||
@@ -152,8 +155,6 @@ void TTextBox::Display(char* text, float time)
|
||||
|
||||
void TTextBox::Draw()
|
||||
{
|
||||
TTextBoxMessage* nextMessage = nullptr;
|
||||
|
||||
auto bmp = BgBmp;
|
||||
if (bmp)
|
||||
gdrv::copy_bitmap(
|
||||
@@ -168,16 +169,32 @@ 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 (Message1->Time == -1.0f)
|
||||
{
|
||||
nextMessage = message->NextMessage;
|
||||
if (!message->NextMessage)
|
||||
if (!Message1->NextMessage)
|
||||
{
|
||||
Timer = -1;
|
||||
LABEL_18:
|
||||
display = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Message1->TimeLeft() >= -2.0f)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -198,6 +215,7 @@ void TTextBox::Draw()
|
||||
255);
|
||||
return;
|
||||
}
|
||||
|
||||
auto text = Message1->Text;
|
||||
for (auto y = OffsetY; ; y += font->Height)
|
||||
{
|
||||
@@ -257,30 +275,6 @@ void TTextBox::Draw()
|
||||
if ((*text & 0x7F) == '\n')
|
||||
++text;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto timeLeft = (Message1->TimeLeft());
|
||||
if (timeLeft >= -2.0f)
|
||||
{
|
||||
int timer;
|
||||
if (timeLeft >= 0.25f)
|
||||
{
|
||||
timer = timer::set(timeLeft, this, TimerExpired);
|
||||
}
|
||||
else
|
||||
{
|
||||
timer = timer::set(0.25, this, TimerExpired);
|
||||
}
|
||||
Timer = timer;
|
||||
goto LABEL_18;
|
||||
}
|
||||
nextMessage = message->NextMessage;
|
||||
}
|
||||
delete message;
|
||||
Message1 = nextMessage;
|
||||
}
|
||||
|
||||
gdrv::blit(
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
~TTextBox() override;
|
||||
int Message(int code, float value) override;
|
||||
void Clear();
|
||||
void Display(char* text, float time);
|
||||
void Display(const char* text, float time);
|
||||
void Draw();
|
||||
|
||||
static void TimerExpired(int timerId, void* tb);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "memory.h"
|
||||
#include "pb.h"
|
||||
|
||||
TTextBoxMessage::TTextBoxMessage(char* text, float time)
|
||||
TTextBoxMessage::TTextBoxMessage(const char* text, float time)
|
||||
{
|
||||
NextMessage = nullptr;
|
||||
Time = time;
|
||||
|
||||
@@ -7,7 +7,7 @@ public:
|
||||
float Time;
|
||||
int EndTicks;
|
||||
|
||||
TTextBoxMessage(char* text, float time);
|
||||
TTextBoxMessage(const char* text, float time);
|
||||
~TTextBoxMessage();
|
||||
float TimeLeft() const;
|
||||
void Refresh(float time);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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,7 +89,7 @@ struct PLAYQUEUE
|
||||
struct GLOBALS
|
||||
{
|
||||
WORD wMagic1;
|
||||
__int16 unknown0;
|
||||
int16_t unknown0;
|
||||
HWND hWndApp;
|
||||
int unknown2;
|
||||
HWAVEOUT hWaveOut;
|
||||
@@ -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;
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#include "TPlunger.h"
|
||||
#include "TWall.h"
|
||||
|
||||
int control::pbctrl_state;
|
||||
|
||||
int control_bump_scores1[] = {500, 1000, 1500, 2000};
|
||||
int control_roll_scores1[] = {2000};
|
||||
int control_bump_scores2[] = {1500, 2500, 3500, 4500};
|
||||
@@ -528,7 +526,8 @@ component_tag_base* control::simple_components[142]
|
||||
&control_soundwave7_tag
|
||||
};
|
||||
|
||||
int control::table_unlimited_balls, control::waiting_deployment_flag;
|
||||
int control::waiting_deployment_flag;
|
||||
bool control::table_unlimited_balls = false;
|
||||
int control::extraball_light_flag;
|
||||
int control::RankRcArray[9] = {84, 85, 86, 87, 88, 89, 90, 91, 92};
|
||||
int control::MissionRcArray[17] = {60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76};
|
||||
@@ -597,9 +596,9 @@ TPinballComponent* control::make_component_link(component_tag_base* tag)
|
||||
return tag->GetComponent();
|
||||
|
||||
auto compList = TableG->ComponentList;
|
||||
for (int index = 0; index < compList->Count(); index++)
|
||||
for (int index = 0; index < compList->GetCount(); index++)
|
||||
{
|
||||
auto comp = static_cast<TPinballComponent*>(compList->Get(index));
|
||||
auto comp = compList->Get(index);
|
||||
if (comp->GroupName)
|
||||
{
|
||||
if (!strcmp(comp->GroupName, tag->Name))
|
||||
@@ -616,229 +615,80 @@ TPinballComponent* control::make_component_link(component_tag_base* tag)
|
||||
void control::handler(int code, TPinballComponent* cmp)
|
||||
{
|
||||
component_control* control = cmp->Control;
|
||||
int scoreInd = 0;
|
||||
|
||||
if (control)
|
||||
{
|
||||
if (code == 1019 && control->ScoreCount > 0)
|
||||
if (code == 1019)
|
||||
{
|
||||
do
|
||||
for (auto scoreInd = 0; scoreInd < control->ScoreCount; ++scoreInd)
|
||||
{
|
||||
cmp->put_scoring(scoreInd, control->Scores[scoreInd]);
|
||||
++scoreInd;
|
||||
}
|
||||
while (scoreInd < control->ScoreCount);
|
||||
}
|
||||
control->ControlFunc(code, cmp);
|
||||
}
|
||||
MissionControl(code, cmp);
|
||||
}
|
||||
|
||||
void control::pbctrl_bdoor_controller(int key)
|
||||
void control::pbctrl_bdoor_controller(char key)
|
||||
{
|
||||
int v1; // eax
|
||||
int v2; // eax
|
||||
bool v3; // zf
|
||||
// Buffer large enough for longest cheat + null
|
||||
static char cheatBuffer[11 + 1]{};
|
||||
static char* bufferEnd = &cheatBuffer[11];
|
||||
static const char* quotes[8]
|
||||
{
|
||||
"Hey, is that a screen saver?",
|
||||
"I guess it has been a good week",
|
||||
"She may already be a glue bottle",
|
||||
"If you don't come in Saturday,\n...\n",
|
||||
"don't even bother coming in Sunday.",
|
||||
"Tomorrow already sucks",
|
||||
"I knew it worked too good to be right.",
|
||||
"World's most expensive flippers"
|
||||
};
|
||||
|
||||
if (!control_lite198_tag.Component->MessageField)
|
||||
if (control_lite198_tag.Component->MessageField)
|
||||
{
|
||||
if (key <= 'M')
|
||||
{
|
||||
if (key == 'M')
|
||||
{
|
||||
v2 = pbctrl_state;
|
||||
if (pbctrl_state == 4 || pbctrl_state == 61 || pbctrl_state == 81 || pbctrl_state == 101)
|
||||
goto LABEL_87;
|
||||
v3 = pbctrl_state == 121;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (key <= 'D')
|
||||
{
|
||||
if (key != 'D')
|
||||
{
|
||||
if (key == ' ')
|
||||
{
|
||||
if (pbctrl_state == 26)
|
||||
{
|
||||
pbctrl_state = 27;
|
||||
return;
|
||||
}
|
||||
goto LABEL_77;
|
||||
}
|
||||
if (key != '1')
|
||||
|
||||
std::memmove(&cheatBuffer[0], &cheatBuffer[1], 10);
|
||||
cheatBuffer[10] = key;
|
||||
|
||||
if (strcmp(bufferEnd - 11, "HIDDEN TEST") == 0)
|
||||
{
|
||||
if (key != 'A')
|
||||
{
|
||||
if (key != 'B')
|
||||
{
|
||||
if (key == 'C')
|
||||
{
|
||||
if (!pbctrl_state)
|
||||
{
|
||||
pbctrl_state = 1;
|
||||
return;
|
||||
pb::cheat_mode ^= true;
|
||||
}
|
||||
if (pbctrl_state == 11)
|
||||
{
|
||||
pbctrl_state = 12;
|
||||
return;
|
||||
}
|
||||
}
|
||||
goto LABEL_77;
|
||||
}
|
||||
v1 = pbctrl_state != 0 ? 0 : 81;
|
||||
goto LABEL_88;
|
||||
}
|
||||
v2 = pbctrl_state;
|
||||
if (pbctrl_state == 5 || pbctrl_state == 62 || pbctrl_state == 82 || pbctrl_state == 102)
|
||||
goto LABEL_87;
|
||||
v3 = pbctrl_state == 122;
|
||||
goto LABEL_86;
|
||||
}
|
||||
v1 = pbctrl_state != 0 ? 0 : 61;
|
||||
LABEL_88:
|
||||
pbctrl_state = v1;
|
||||
return;
|
||||
}
|
||||
if (pbctrl_state != 22 && pbctrl_state != 23)
|
||||
goto LABEL_77;
|
||||
LABEL_58:
|
||||
++pbctrl_state;
|
||||
return;
|
||||
}
|
||||
if (key != 'E')
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case 'G':
|
||||
v1 = pbctrl_state != 0 ? 0 : 101;
|
||||
break;
|
||||
case 'H':
|
||||
v1 = pbctrl_state != 0 ? 0 : 21;
|
||||
break;
|
||||
case 'I':
|
||||
v2 = pbctrl_state;
|
||||
if (pbctrl_state == 1 || pbctrl_state == 10)
|
||||
goto LABEL_87;
|
||||
v3 = pbctrl_state == 21;
|
||||
goto LABEL_86;
|
||||
default:
|
||||
goto LABEL_77;
|
||||
}
|
||||
goto LABEL_88;
|
||||
}
|
||||
v2 = pbctrl_state;
|
||||
if (pbctrl_state == 3 || pbctrl_state == 24 || pbctrl_state == 28)
|
||||
goto LABEL_87;
|
||||
v3 = pbctrl_state == 44;
|
||||
}
|
||||
goto LABEL_86;
|
||||
}
|
||||
if (key <= 'S')
|
||||
{
|
||||
if (key == 'S')
|
||||
{
|
||||
v2 = pbctrl_state;
|
||||
if (pbctrl_state == 12 || pbctrl_state == 29)
|
||||
goto LABEL_87;
|
||||
v3 = pbctrl_state == 45;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (key != 'N')
|
||||
{
|
||||
if (key != 'O')
|
||||
{
|
||||
if (key != 'Q')
|
||||
{
|
||||
if (key == 'R')
|
||||
{
|
||||
if (!pbctrl_state)
|
||||
{
|
||||
pbctrl_state = 121;
|
||||
return;
|
||||
}
|
||||
if (pbctrl_state == 7)
|
||||
{
|
||||
pbctrl_state = 8;
|
||||
return;
|
||||
}
|
||||
}
|
||||
goto LABEL_77;
|
||||
}
|
||||
v1 = pbctrl_state != 0 ? 0 : 41;
|
||||
goto LABEL_88;
|
||||
}
|
||||
if (pbctrl_state != 8 && pbctrl_state != 42)
|
||||
goto LABEL_77;
|
||||
goto LABEL_58;
|
||||
}
|
||||
v2 = pbctrl_state;
|
||||
if (pbctrl_state == 2 || pbctrl_state == 9)
|
||||
goto LABEL_87;
|
||||
v3 = pbctrl_state == 25;
|
||||
}
|
||||
LABEL_86:
|
||||
if (v3)
|
||||
{
|
||||
LABEL_87:
|
||||
v1 = v2 + 1;
|
||||
goto LABEL_88;
|
||||
}
|
||||
LABEL_77:
|
||||
pbctrl_state = 0;
|
||||
return;
|
||||
}
|
||||
switch (key)
|
||||
{
|
||||
case 'T':
|
||||
v2 = pbctrl_state;
|
||||
if (pbctrl_state != 30)
|
||||
{
|
||||
if (pbctrl_state == 27 || pbctrl_state == 6)
|
||||
goto LABEL_87;
|
||||
v3 = pbctrl_state == 43;
|
||||
goto LABEL_86;
|
||||
}
|
||||
pb::cheat_mode = 1;
|
||||
break;
|
||||
case 'U':
|
||||
if (pbctrl_state == 41)
|
||||
{
|
||||
pbctrl_state = 42;
|
||||
return;
|
||||
}
|
||||
goto LABEL_77;
|
||||
case 'X':
|
||||
if (pbctrl_state == 63)
|
||||
{
|
||||
table_add_extra_ball(2.0);
|
||||
goto LABEL_76;
|
||||
}
|
||||
if (pbctrl_state != 83)
|
||||
{
|
||||
if (pbctrl_state == 103)
|
||||
else if (strcmp(bufferEnd - 4, "GMAX") == 0)
|
||||
{
|
||||
GravityWellKickoutControl(64, nullptr);
|
||||
}
|
||||
else
|
||||
else if (strcmp(bufferEnd - 4, "1MAX") == 0)
|
||||
{
|
||||
table_add_extra_ball(2.0);
|
||||
}
|
||||
else if (strcmp(bufferEnd - 4, "BMAX") == 0)
|
||||
{
|
||||
table_unlimited_balls ^= true;
|
||||
}
|
||||
else if (strcmp(bufferEnd - 4, "RMAX") == 0)
|
||||
{
|
||||
if (pbctrl_state != 123)
|
||||
goto LABEL_77;
|
||||
cheat_bump_rank();
|
||||
}
|
||||
LABEL_76:
|
||||
else if (pb::FullTiltMode && strcmp(bufferEnd - 5, "QUOTE") == 0)
|
||||
{
|
||||
// A sad developer easter egg type 'cheat' from Full Tilt
|
||||
float time = 0;
|
||||
for (auto quote : quotes)
|
||||
control_mission_text_box_tag.Component->Display(quote, time += 3);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TableG->CheatsUsed = 1;
|
||||
goto LABEL_77;
|
||||
}
|
||||
table_unlimited_balls = 1;
|
||||
break;
|
||||
default:
|
||||
goto LABEL_77;
|
||||
}
|
||||
TableG->CheatsUsed = 1;
|
||||
goto LABEL_77;
|
||||
}
|
||||
}
|
||||
|
||||
void control::table_add_extra_ball(float count)
|
||||
@@ -904,9 +754,19 @@ void control::table_set_replay(float value)
|
||||
control_info_text_box_tag.Component->Display(pinball::get_rc_string(0, 0), value);
|
||||
}
|
||||
|
||||
int control::cheat_bump_rank()
|
||||
void control::cheat_bump_rank()
|
||||
{
|
||||
return 0;
|
||||
char Buffer[64]{};
|
||||
|
||||
auto rank = control_middle_circle_tag.Component->Message(37, 0.0);
|
||||
if (rank < 9)
|
||||
{
|
||||
control_middle_circle_tag.Component->Message(41, 2.0f);
|
||||
auto rankText = pinball::get_rc_string(RankRcArray[rank], 1);
|
||||
snprintf(Buffer, sizeof Buffer, pinball::get_rc_string(83, 0), rankText);
|
||||
control_mission_text_box_tag.Component->Display(Buffer, 8.0);
|
||||
control_soundwave10_tag.Component->Play();
|
||||
}
|
||||
}
|
||||
|
||||
bool control::light_on(component_tag<TLight>* tag)
|
||||
@@ -1924,7 +1784,7 @@ void control::GravityWellKickoutControl(int code, TPinballComponent* caller)
|
||||
}
|
||||
case 64:
|
||||
{
|
||||
auto score = reinterpret_cast<int>(caller);
|
||||
auto score = reinterpret_cast<size_t>(caller);
|
||||
if (score)
|
||||
{
|
||||
sprintf_s(Buffer, pinball::get_rc_string(82, 0), score);
|
||||
@@ -2232,7 +2092,7 @@ void control::HyperspaceKickOutControl(int code, TPinballComponent* caller)
|
||||
case 4:
|
||||
{
|
||||
control_hyper_lights_tag.Component->Message(0, 0.0);
|
||||
auto addedScore = TableG->AddScore(caller->get_scoring(4));
|
||||
size_t addedScore = TableG->AddScore(caller->get_scoring(4));
|
||||
GravityWellKickoutControl(64, reinterpret_cast<TPinballComponent*>(addedScore));
|
||||
break;
|
||||
}
|
||||
@@ -2331,7 +2191,7 @@ void control::PlungerControl(int code, TPinballComponent* caller)
|
||||
}
|
||||
else if (code == 1016)
|
||||
{
|
||||
table_unlimited_balls = 0;
|
||||
table_unlimited_balls = false;
|
||||
if (!control_middle_circle_tag.Component->Message(37, 0.0))
|
||||
control_middle_circle_tag.Component->Message(32, 0.0);
|
||||
if (!light_on(&control_lite200_tag))
|
||||
@@ -2630,7 +2490,7 @@ void control::table_control_handler(int code)
|
||||
{
|
||||
if (code == 1011)
|
||||
{
|
||||
table_unlimited_balls = 0;
|
||||
table_unlimited_balls = false;
|
||||
control_lite77_tag.Component->Message(7, 0.0);
|
||||
}
|
||||
}
|
||||
@@ -3019,7 +2879,7 @@ void control::GameoverController(int code, TPinballComponent* caller)
|
||||
int missionMsg = control_mission_text_box_tag.Component->MessageField;
|
||||
if (missionMsg & 0x100)
|
||||
{
|
||||
int playerId = missionMsg & 0xF;
|
||||
int playerId = missionMsg % 4;
|
||||
int playerScore = TableG->PlayerScores[playerId].ScoreStruct->Score;
|
||||
auto nextPlayerId = playerId + 1;
|
||||
if (playerScore >= 0)
|
||||
@@ -3056,7 +2916,7 @@ void control::GameoverController(int code, TPinballComponent* caller)
|
||||
|
||||
if (missionMsg & 0x200)
|
||||
{
|
||||
int highscoreId = missionMsg & 0xF;
|
||||
int highscoreId = missionMsg % 4;
|
||||
int highScore = pb::highscore_table[highscoreId].Score;
|
||||
auto nextHidhscoreId = highscoreId + 1;
|
||||
if (highScore > 0)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "gdrv.h"
|
||||
|
||||
#include "fullscrn.h"
|
||||
#include "memory.h"
|
||||
#include "pinball.h"
|
||||
#include "winmain.h"
|
||||
@@ -7,7 +9,6 @@
|
||||
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 +19,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*)¤t_palette);
|
||||
palette_handle = CreatePalette(¤t_palette);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,17 +40,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 +67,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 +100,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 +141,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 +170,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*)¤t_palette);
|
||||
palette_handle = CreatePalette(¤t_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 +221,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 +240,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 +275,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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -288,12 +290,13 @@ void gdrv::end_blit_sequence()
|
||||
void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, int DestHeight)
|
||||
{
|
||||
HDC dc = winmain::_GetDC(hwnd);
|
||||
SetStretchBltMode(dc, stretchMode);
|
||||
if (dc)
|
||||
{
|
||||
SelectPalette(dc, palette_handle, 0);
|
||||
RealizePalette(dc);
|
||||
if (!use_wing)
|
||||
StretchDIBits(
|
||||
StretchDIBitsScaled(
|
||||
dc,
|
||||
xDest,
|
||||
yDest,
|
||||
@@ -303,10 +306,10 @@ void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest,
|
||||
bmp->Height - ySrcOff - DestHeight,
|
||||
DestWidth,
|
||||
DestHeight,
|
||||
bmp->BmpBufPtr1,
|
||||
bmp->Dib,
|
||||
1u,
|
||||
SRCCOPY);
|
||||
bmp,
|
||||
DIB_PAL_COLORS,
|
||||
SRCCOPY
|
||||
);
|
||||
ReleaseDC(hwnd, dc);
|
||||
}
|
||||
}
|
||||
@@ -314,10 +317,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 +350,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 +363,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)
|
||||
{
|
||||
do
|
||||
for (; height > 0; --height)
|
||||
{
|
||||
if (width > 0)
|
||||
memset(bmpPtr, fillChar, width);
|
||||
bmpPtr += bmp->Stride;
|
||||
--height;
|
||||
}
|
||||
while (height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,9 +432,48 @@ void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width,
|
||||
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));
|
||||
COLORREF color = SetTextColor(dc, grtext_red | grtext_green << 8 | grtext_blue << 16);
|
||||
DrawTextA(dc, text, lstrlenA(text), &rc, 0x810u);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
@@ -65,9 +66,15 @@ public:
|
||||
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff);
|
||||
static void grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6);
|
||||
private:
|
||||
/*COLORONCOLOR or HALFTONE*/
|
||||
static const int stretchMode = COLORONCOLOR;
|
||||
static HWND hwnd;
|
||||
static HINSTANCE hinst;
|
||||
static int grtext_blue;
|
||||
static int grtext_green;
|
||||
static int grtext_red;
|
||||
|
||||
static int StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc,
|
||||
int SrcWidth, int SrcHeight, gdrv_bitmap8* bmp, UINT iUsage,
|
||||
DWORD rop);
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
int high_score::dlg_enter_name;
|
||||
int high_score::dlg_score;
|
||||
int high_score::position;
|
||||
int high_score::dlg_position;
|
||||
LPCSTR high_score::default_name;
|
||||
high_score_struct* high_score::dlg_hst;
|
||||
|
||||
@@ -48,30 +48,27 @@ 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)
|
||||
{
|
||||
auto tablePtr = &table[position];
|
||||
_itoa_s(position, Buffer, 10);
|
||||
lstrcatA(Buffer, ".Name");
|
||||
options::get_string(optPath, Buffer, buf1, pinball::WindowName, 32);
|
||||
options::get_string(optPath, Buffer, buf1, "", 32);
|
||||
buf1[32] = 0;
|
||||
lstrcpyA(tablePtr->Name, buf1);
|
||||
_itoa_s(position, Buffer, 10);
|
||||
lstrcatA(Buffer, ".Score");
|
||||
options::get_string(optPath, Buffer, buf1, pinball::WindowName, 300);
|
||||
options::get_string(optPath, Buffer, buf1, "", 300);
|
||||
tablePtr->Score = atol(buf1);
|
||||
for (int i = lstrlenA(tablePtr->Name); --i >= 0; 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);
|
||||
@@ -88,9 +85,8 @@ int high_score::write(high_score_struct* table, int* ptrToSmth)
|
||||
CHAR* buf = memory::allocate(300u);
|
||||
if (!buf)
|
||||
return 1;
|
||||
int position = 0;
|
||||
const CHAR* optPath = pinball::get_rc_string(166, 0);
|
||||
do
|
||||
for (auto position = 0; position < 5; ++position)
|
||||
{
|
||||
_itoa_s(position, Buffer, 10);
|
||||
lstrcatA(Buffer, ".Name");
|
||||
@@ -103,10 +99,8 @@ int high_score::write(high_score_struct* table, int* ptrToSmth)
|
||||
{
|
||||
}
|
||||
scoreSum += tablePtr->Score;
|
||||
++position;
|
||||
++tablePtr;
|
||||
}
|
||||
while (position < 5);
|
||||
scramble_number_string(scoreSum, buf);
|
||||
options::set_string(optPath, "Verification", buf);
|
||||
memory::free(buf);
|
||||
@@ -177,7 +171,7 @@ void high_score::show_high_score_dialog(high_score_struct* table)
|
||||
|
||||
void high_score::show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCSTR defaultName)
|
||||
{
|
||||
position = pos;
|
||||
dlg_position = pos;
|
||||
dlg_score = score;
|
||||
dlg_hst = table;
|
||||
dlg_enter_name = 1;
|
||||
@@ -214,12 +208,12 @@ INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
}
|
||||
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);
|
||||
HWND nameTextBox = GetDlgItem(hWnd, dlg_position + DLG_HIGHSCORES_EditName1);
|
||||
ShowWindow(nameTextBox, 5);
|
||||
EnableWindow(nameTextBox, 1);
|
||||
SetFocus(nameTextBox);
|
||||
@@ -246,9 +240,9 @@ INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
break;
|
||||
}
|
||||
GetDlgItemTextA(hWnd, position + DLG_HIGHSCORES_EditName1, name, 32);
|
||||
GetDlgItemTextA(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;
|
||||
@@ -281,7 +275,7 @@ 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);
|
||||
nextPosition = 1;
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
private :
|
||||
static int dlg_enter_name;
|
||||
static int dlg_score;
|
||||
static int position;
|
||||
static int dlg_position;
|
||||
static LPCSTR default_name;
|
||||
static high_score_struct* dlg_hst;
|
||||
static winhelp_entry help[21];
|
||||
|
||||
@@ -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
|
||||
auto index = 0;
|
||||
while (curCode->Code >= 0)
|
||||
{
|
||||
if (errorCode == curCode)
|
||||
errorText = loader_errors[index2].Message;
|
||||
if (captionCode == curCode)
|
||||
errorCaption = loader_errors[index2].Message;
|
||||
index2 = ++index;
|
||||
curCode = loader_errors[index].Code;
|
||||
if (errorCode == curCode->Code)
|
||||
errorText = curCode->Message;
|
||||
if (captionCode == curCode->Code)
|
||||
errorCaption = curCode->Message;
|
||||
curCode++;
|
||||
index++;
|
||||
}
|
||||
while (curCode >= 0);
|
||||
|
||||
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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
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
|
||||
auto alloc = alloc_map.find(buf);
|
||||
if (alloc == alloc_map.end())
|
||||
{
|
||||
assertm(false, "Unknown memory type");
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
char bufType = *bufStart;
|
||||
*(unsigned int*)bufStart = size << 8;
|
||||
use_total += size;
|
||||
*bufStart = bufType;
|
||||
return bufStart + 4;
|
||||
}
|
||||
if (critical_allocation && critical_callback)
|
||||
critical_callback();
|
||||
return nullptr;
|
||||
use_total -= alloc->second;
|
||||
std::free(alloc->first);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
static int critical_allocation;
|
||||
static void (*critical_callback)();
|
||||
};
|
||||
|
||||
|
||||
// Fill memory block with an integer value
|
||||
inline void memset32(void* ptr, unsigned int value, int count)
|
||||
template <typename T>
|
||||
static T* allocate(size_t count = 1, size_t add = 0)
|
||||
{
|
||||
auto p = (unsigned int*)ptr;
|
||||
for (int i = 0; i < count; i++)
|
||||
*p++ = value;
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "fullscrn.h"
|
||||
#include "memory.h"
|
||||
#include "midi.h"
|
||||
#include "pb.h"
|
||||
#include "resource.h"
|
||||
#include "Sound.h"
|
||||
#include "winmain.h"
|
||||
@@ -11,7 +12,7 @@
|
||||
LPCSTR options::OptionsRegPath;
|
||||
LPSTR options::OptionsRegPathCur;
|
||||
HMENU options::MenuHandle;
|
||||
optionsStruct options::Options;
|
||||
optionsStruct options::Options{};
|
||||
|
||||
winhelp_entry options::keymap_help[18]
|
||||
{
|
||||
@@ -106,6 +107,9 @@ void options::init(HMENU menuHandle)
|
||||
Options.LeftTableBumpKey = get_int(nullptr, "Left Table Bump key", Options.LeftTableBumpKey);
|
||||
Options.RightTableBumpKey = get_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey);
|
||||
Options.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
|
||||
Options.UniformScaling = get_int(nullptr, "Uniform scaling", true);
|
||||
Options.AlternativeRender = get_int(nullptr, "Alternative Render", false);
|
||||
|
||||
menu_check(Menu1_Sounds, Options.Sounds);
|
||||
Sound::Enable(0, 7, Options.Sounds);
|
||||
menu_check(Menu1_Music, Options.Music);
|
||||
@@ -114,10 +118,12 @@ void options::init(HMENU menuHandle)
|
||||
menu_check(Menu1_2Players, Options.Players == 2);
|
||||
menu_check(Menu1_3Players, Options.Players == 3);
|
||||
menu_check(Menu1_4Players, Options.Players == 4);
|
||||
menu_check(Menu1_WindowUniformScale, Options.UniformScaling);
|
||||
menu_check(Menu1_AlternativeRender, Options.AlternativeRender);
|
||||
auto tmpBuf = memory::allocate(0x1F4u);
|
||||
if (tmpBuf)
|
||||
{
|
||||
get_string(nullptr, "Shell Exe", tmpBuf, pinball::WindowName, 500);
|
||||
get_string(nullptr, "Shell Exe", tmpBuf, "", 500);
|
||||
if (!*tmpBuf)
|
||||
{
|
||||
if (MenuHandle)
|
||||
@@ -128,6 +134,8 @@ void options::init(HMENU menuHandle)
|
||||
}
|
||||
memory::free(tmpBuf);
|
||||
}
|
||||
|
||||
update_resolution_menu();
|
||||
}
|
||||
|
||||
void options::uninit()
|
||||
@@ -142,6 +150,9 @@ void options::uninit()
|
||||
set_int(nullptr, "Left Table Bump key", Options.LeftTableBumpKey);
|
||||
set_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey);
|
||||
set_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
|
||||
set_int(nullptr, "Screen Resolution", Options.Resolution);
|
||||
set_int(nullptr, "Uniform scaling", Options.UniformScaling);
|
||||
set_int(nullptr, "Alternative Render", Options.AlternativeRender);
|
||||
}
|
||||
|
||||
void options::path_init(LPCSTR regPath)
|
||||
@@ -188,73 +199,75 @@ void options::path_free()
|
||||
int options::get_int(LPCSTR optPath, LPCSTR lpValueName, int defaultValue)
|
||||
{
|
||||
DWORD dwDisposition;
|
||||
HKEY hKey;
|
||||
|
||||
HKEY result = (HKEY)defaultValue, Data = (HKEY)defaultValue;
|
||||
auto result = defaultValue;
|
||||
if (!OptionsRegPath)
|
||||
return defaultValue;
|
||||
LPCSTR regPath = path(optPath);
|
||||
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, 0xF003Fu, nullptr, &result, &dwDisposition))
|
||||
return result;
|
||||
|
||||
auto regPath = path(optPath);
|
||||
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
|
||||
{
|
||||
optPath = (LPCSTR)4;
|
||||
RegQueryValueExA(result, lpValueName, nullptr, nullptr, (LPBYTE)&Data, (LPDWORD)&optPath);
|
||||
RegCloseKey(result);
|
||||
DWORD bufferSize = 4;
|
||||
RegQueryValueExA(hKey, lpValueName, nullptr, nullptr, reinterpret_cast<LPBYTE>(&result), &bufferSize);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
path_free();
|
||||
return (int)Data;
|
||||
return result;
|
||||
}
|
||||
|
||||
void options::set_int(LPCSTR optPath, LPCSTR lpValueName, int data)
|
||||
{
|
||||
DWORD dwDisposition;
|
||||
HKEY hKey;
|
||||
|
||||
if (OptionsRegPath)
|
||||
if (!OptionsRegPath)
|
||||
return;
|
||||
|
||||
auto regPath = path(optPath);
|
||||
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
|
||||
{
|
||||
const CHAR* regPath = path(optPath);
|
||||
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, 0xF003Fu, nullptr, (PHKEY)&optPath,
|
||||
&dwDisposition))
|
||||
{
|
||||
RegSetValueExA((HKEY)optPath, lpValueName, 0, 4u, (const BYTE*)&data, 4u);
|
||||
RegCloseKey((HKEY)optPath);
|
||||
RegSetValueExA(hKey, lpValueName, 0, 4u, reinterpret_cast<LPBYTE>(&data), 4u);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
path_free();
|
||||
}
|
||||
}
|
||||
|
||||
void options::get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR lpString1, LPCSTR lpString2, int iMaxLength)
|
||||
void options::get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR dst, LPCSTR defaultValue, int iMaxLength)
|
||||
{
|
||||
const CHAR* v5 = (const CHAR*)iMaxLength;
|
||||
lstrcpynA(lpString1, lpString2, iMaxLength);
|
||||
if (OptionsRegPath)
|
||||
DWORD dwDisposition;
|
||||
HKEY hKey;
|
||||
|
||||
lstrcpynA(dst, defaultValue, iMaxLength);
|
||||
if (!OptionsRegPath)
|
||||
return;
|
||||
|
||||
auto regPath = path(optPath);
|
||||
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
|
||||
{
|
||||
const CHAR* regPath = path(optPath);
|
||||
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, 0xF003Fu, nullptr, (PHKEY)&iMaxLength,
|
||||
(LPDWORD)&optPath))
|
||||
{
|
||||
lpString2 = v5;
|
||||
RegQueryValueExA((HKEY)iMaxLength, lpValueName, nullptr, nullptr, (LPBYTE)lpString1, (LPDWORD)&lpString2);
|
||||
RegCloseKey((HKEY)iMaxLength);
|
||||
DWORD bufferSize = iMaxLength;
|
||||
RegQueryValueExA(hKey, lpValueName, nullptr, nullptr, reinterpret_cast<LPBYTE>(dst), &bufferSize);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
path_free();
|
||||
}
|
||||
}
|
||||
|
||||
void options::set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value)
|
||||
{
|
||||
DWORD dwDisposition;
|
||||
HKEY hKey;
|
||||
|
||||
if (OptionsRegPath)
|
||||
if (!OptionsRegPath)
|
||||
return;
|
||||
|
||||
auto regPath = path(optPath);
|
||||
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
|
||||
{
|
||||
const CHAR* regPath = path(optPath);
|
||||
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, 0xF003Fu, nullptr, (PHKEY)&optPath,
|
||||
&dwDisposition))
|
||||
{
|
||||
int v4 = lstrlenA(value);
|
||||
RegSetValueExA((HKEY)optPath, lpValueName, 0, 1u, (const BYTE*)value, v4 + 1);
|
||||
RegCloseKey((HKEY)optPath);
|
||||
RegSetValueExA(hKey, lpValueName, 0, 1u, LPBYTE(value), lstrlenA(value) + 1);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
path_free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void options::menu_check(UINT uIDCheckItem, int check)
|
||||
@@ -296,14 +309,89 @@ void options::toggle(UINT uIDCheckItem)
|
||||
fullscrn::set_screen_mode(newValue);
|
||||
menu_check(uIDCheckItem, newValue);
|
||||
return;
|
||||
}
|
||||
if (uIDCheckItem > 407 && uIDCheckItem <= 411)
|
||||
{
|
||||
Options.Players = uIDCheckItem - 407;
|
||||
case Menu1_1Player:
|
||||
case Menu1_2Players:
|
||||
case Menu1_3Players:
|
||||
case Menu1_4Players:
|
||||
Options.Players = uIDCheckItem - Menu1_1Player + 1;
|
||||
menu_check(Menu1_1Player, Options.Players == 1);
|
||||
menu_check(Menu1_2Players, Options.Players == 2);
|
||||
menu_check(Menu1_3Players, Options.Players == 3);
|
||||
menu_check(Menu1_4Players, Options.Players == 4);
|
||||
break;
|
||||
case Menu1_MaximumResolution:
|
||||
case Menu1_640x480:
|
||||
case Menu1_800x600:
|
||||
case Menu1_1024x768:
|
||||
{
|
||||
for (unsigned i = Menu1_MaximumResolution; i <= Menu1_1024x768; ++i)
|
||||
menu_check(i, i == uIDCheckItem);
|
||||
|
||||
int newResolution = uIDCheckItem - Menu1_640x480;
|
||||
if (uIDCheckItem == Menu1_MaximumResolution)
|
||||
{
|
||||
Options.Resolution = -1;
|
||||
if (fullscrn::GetMaxResolution() != fullscrn::GetResolution())
|
||||
winmain::Restart();
|
||||
}
|
||||
else if (newResolution != fullscrn::GetResolution() && newResolution <= fullscrn::GetMaxResolution())
|
||||
{
|
||||
Options.Resolution = newResolution;
|
||||
winmain::Restart();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Menu1_WindowUniformScale:
|
||||
Options.UniformScaling ^= true;
|
||||
menu_check(Menu1_WindowUniformScale, Options.UniformScaling);
|
||||
fullscrn::window_size_changed();
|
||||
fullscrn::paint();
|
||||
break;
|
||||
case Menu1_AlternativeRender:
|
||||
Options.AlternativeRender ^= true;
|
||||
menu_check(Menu1_AlternativeRender, Options.AlternativeRender);
|
||||
fullscrn::window_size_changed();
|
||||
fullscrn::paint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void options::update_resolution_menu()
|
||||
{
|
||||
auto maxResolution = fullscrn::get_max_supported_resolution();
|
||||
fullscrn::SetMaxResolution(maxResolution);
|
||||
const CHAR* maxResText = pinball::get_rc_string(maxResolution + 2030, 0);
|
||||
if (MenuHandle)
|
||||
ModifyMenuA(MenuHandle, Menu1_MaximumResolution, 0, Menu1_MaximumResolution, maxResText);
|
||||
|
||||
for (auto resIndex = 0; resIndex < 3; resIndex++)
|
||||
{
|
||||
menu_set(fullscrn::resolution_array[resIndex].ResolutionMenuId, fullscrn::GetMaxResolution() >= resIndex);
|
||||
}
|
||||
for (auto i = Menu1_MaximumResolution; i <= Menu1_1024x768; ++i)
|
||||
{
|
||||
menu_check(i, 0);
|
||||
}
|
||||
if (Options.Resolution >= 0)
|
||||
menu_check(fullscrn::resolution_array[fullscrn::GetResolution()].ResolutionMenuId, 1);
|
||||
else
|
||||
menu_check(Menu1_MaximumResolution, 1);
|
||||
}
|
||||
|
||||
void options::init_resolution()
|
||||
{
|
||||
Options.Resolution = get_int(nullptr, "Screen Resolution", -1);
|
||||
int maxRes = fullscrn::get_max_supported_resolution();
|
||||
if (Options.Resolution == -1 || maxRes <= Options.Resolution)
|
||||
{
|
||||
fullscrn::SetMaxResolution(maxRes);
|
||||
fullscrn::SetResolution(maxRes);
|
||||
}
|
||||
else
|
||||
{
|
||||
fullscrn::SetResolution(Options.Resolution);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +420,7 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
|
||||
{
|
||||
short vk = *vkPtr;
|
||||
auto vk2And = vk & 0x4000;
|
||||
auto vkChar = static_cast<unsigned __int8>(vk);
|
||||
auto vkChar = static_cast<uint8_t>(vk);
|
||||
unsigned short maxVk;
|
||||
|
||||
if (vk2And)
|
||||
@@ -411,17 +499,17 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
|
||||
case KEYMAPPER_Ok:
|
||||
{
|
||||
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETCURSEL, 0, 0);
|
||||
keyBindings[0] = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETITEMDATA, ind, 0);
|
||||
keyBindings[0] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETITEMDATA, ind, 0));
|
||||
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETCURSEL, 0, 0);
|
||||
keyBindings[1] = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETITEMDATA, ind, 0);
|
||||
keyBindings[1] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETITEMDATA, ind, 0));
|
||||
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETCURSEL, 0, 0);
|
||||
keyBindings[2] = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETITEMDATA, ind, 0);
|
||||
keyBindings[2] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETITEMDATA, ind, 0));
|
||||
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETCURSEL, 0, 0);
|
||||
keyBindings[3] = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETITEMDATA, ind, 0);
|
||||
keyBindings[3] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETITEMDATA, ind, 0));
|
||||
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETCURSEL, 0, 0);
|
||||
keyBindings[4] = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETITEMDATA, ind, 0);
|
||||
keyBindings[4] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETITEMDATA, ind, 0));
|
||||
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETCURSEL, 0, 0);
|
||||
keyBindings[5] = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETITEMDATA, ind, 0);
|
||||
keyBindings[5] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETITEMDATA, ind, 0));
|
||||
|
||||
auto sameKeyBound = 0;
|
||||
auto index = 1;
|
||||
@@ -493,7 +581,7 @@ INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPAR
|
||||
}
|
||||
|
||||
|
||||
LPSTR options::get_vk_key_name(unsigned __int16 vk, LPSTR keyName)
|
||||
LPSTR options::get_vk_key_name(uint16_t vk, LPSTR keyName)
|
||||
{
|
||||
LONG scanCode = MapVirtualKeyA(vk, MAPVK_VK_TO_VSC) << 16;
|
||||
if (vk >= 0x21u && vk <= 0x2Eu)
|
||||
|
||||
@@ -21,6 +21,9 @@ struct optionsStruct
|
||||
int LeftTableBumpKeyDft;
|
||||
int RightTableBumpKeyDft;
|
||||
int BottomTableBumpKeyDft;
|
||||
int Resolution;
|
||||
bool UniformScaling;
|
||||
bool AlternativeRender;
|
||||
};
|
||||
|
||||
|
||||
@@ -33,15 +36,17 @@ public:
|
||||
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 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 LPSTR get_vk_key_name(uint16_t vk, LPSTR keyName);
|
||||
|
||||
static optionsStruct Options;
|
||||
private:
|
||||
|
||||
@@ -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,31 +180,24 @@ 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)
|
||||
{
|
||||
int entryIndex = 0;
|
||||
if (group->EntryCount > 0)
|
||||
{
|
||||
datEntryData* entry = group->Entries;
|
||||
do
|
||||
auto group = datFile->GroupData[groupIndex];
|
||||
if (!group)
|
||||
continue;
|
||||
|
||||
for (auto entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
|
||||
{
|
||||
auto entry = &group->Entries[entryIndex];
|
||||
if (entry->Buffer)
|
||||
{
|
||||
if (entry->EntryType == datFieldTypes::Bitmap8bit)
|
||||
gdrv::destroy_bitmap((gdrv_bitmap8*)entry->Buffer);
|
||||
gdrv::destroy_bitmap(reinterpret_cast<gdrv_bitmap8*>(entry->Buffer));
|
||||
memory::free(entry->Buffer);
|
||||
}
|
||||
++entryIndex;
|
||||
++entry;
|
||||
}
|
||||
while (entryIndex < group->EntryCount);
|
||||
}
|
||||
memory::free(group);
|
||||
}
|
||||
}
|
||||
if (datFile->Description)
|
||||
memory::free(datFile->Description);
|
||||
memory::free(datFile->GroupData);
|
||||
@@ -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)
|
||||
break;
|
||||
if (entryType > targetEntryType)
|
||||
return nullptr;
|
||||
++entryIndex;
|
||||
++entry;
|
||||
if (entryIndex < entryCount)
|
||||
continue;
|
||||
return nullptr;
|
||||
}
|
||||
auto entry = &group->Entries[entryIndex];
|
||||
if (entry->EntryType == targetEntryType)
|
||||
return entry->Buffer;
|
||||
if (entry->EntryType > targetEntryType)
|
||||
break;
|
||||
}
|
||||
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)
|
||||
{
|
||||
datEntryData* entry = groupData->Entries;
|
||||
do
|
||||
{
|
||||
auto entryType = entry->EntryType;
|
||||
if (entryType == targetEntryType)
|
||||
{
|
||||
if (skipCount == skipFirstN)
|
||||
auto group = datFile->GroupData[groupIndex];
|
||||
for (auto skipCount = 0, entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
|
||||
{
|
||||
auto entry = &group->Entries[entryIndex];
|
||||
if (entry->EntryType > targetEntryType)
|
||||
break;
|
||||
if (entry->EntryType == targetEntryType)
|
||||
if (skipCount++ == skipFirstN)
|
||||
return entry->Buffer;
|
||||
}
|
||||
skipCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (targetEntryType < entryType)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
entryIndex++;
|
||||
entry++;
|
||||
}
|
||||
while (entryIndex < entryCount);
|
||||
}
|
||||
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)
|
||||
{
|
||||
datEntryData* entry = groupData->Entries;
|
||||
do
|
||||
{
|
||||
auto entryType = entry->EntryType;
|
||||
if (entryType == targetEntryType)
|
||||
{
|
||||
if (skipCount == skipFirstN)
|
||||
{
|
||||
return entry->FieldSize;
|
||||
}
|
||||
skipCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (targetEntryType < entryType)
|
||||
auto group = datFile->GroupData[groupIndex];
|
||||
for (auto skipCount = 0, entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
|
||||
{
|
||||
auto entry = &group->Entries[entryIndex];
|
||||
if (entry->EntryType > targetEntryType)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
entryIndex++;
|
||||
entry++;
|
||||
}
|
||||
while (entryIndex < entryCount);
|
||||
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])
|
||||
auto groupName = field(datFile, groupIndex, datFieldTypes::GroupName);
|
||||
if (!groupName)
|
||||
continue;
|
||||
|
||||
int index;
|
||||
for (index = 0; index < targetLength; index++)
|
||||
if (targetGroupName[index] != groupName[index])
|
||||
break;
|
||||
++index;
|
||||
++targetNamePtr;
|
||||
}
|
||||
while (index < trgGroupNameLen);
|
||||
found = index == trgGroupNameLen;
|
||||
}
|
||||
if (found && !targetGroupName[index] && !groupName[index])
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index == targetLength && !targetGroupName[index] && !groupName[index])
|
||||
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)
|
||||
|
||||
@@ -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).
|
||||
@@ -29,6 +29,7 @@ enum class bmp8Flags : unsigned char
|
||||
{
|
||||
RawBmpUnaligned = 1 << 0,
|
||||
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);
|
||||
|
||||
@@ -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,9 +129,7 @@ void pb::reset_table()
|
||||
|
||||
void pb::firsttime_setup()
|
||||
{
|
||||
render::blit = 0;
|
||||
render::update();
|
||||
render::blit = 1;
|
||||
render::update(false);
|
||||
}
|
||||
|
||||
void pb::paint()
|
||||
@@ -209,7 +213,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 +221,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 +239,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);
|
||||
}
|
||||
if (nudge::nudge_count > 1.0)
|
||||
if (nudge::nudge_count > 1.0f)
|
||||
MainTable->tilt(time_now);
|
||||
}
|
||||
}
|
||||
@@ -257,9 +285,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 +310,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 +328,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 +339,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()
|
||||
@@ -398,7 +426,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 +468,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 +476,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;
|
||||
@@ -474,7 +502,7 @@ void pb::keydown(int key)
|
||||
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':
|
||||
@@ -626,7 +654,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 +666,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -9,7 +9,6 @@ TTextBox* pinball::InfoTextBox;
|
||||
TTextBox* pinball::MissTextBox;
|
||||
char pinball::getRcBuffer[6 * 256];
|
||||
int pinball::rc_string_slot = 0;
|
||||
char pinball::WindowName[2]{};
|
||||
int pinball::LeftShift = -1;
|
||||
int pinball::RightShift = -1;
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ public:
|
||||
static int quickFlag;
|
||||
static TTextBox* InfoTextBox;
|
||||
static TTextBox* MissTextBox;
|
||||
static char WindowName[2];
|
||||
static int RightShift;
|
||||
static int LeftShift;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,46 +59,35 @@ 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)
|
||||
for (int index = 0; index < many_dirty; ++index)
|
||||
{
|
||||
auto curSprite = *dirtyPtr;
|
||||
if ((*dirtyPtr)->VisualType != VisualType::None)
|
||||
{
|
||||
if ((*dirtyPtr)->VisualType == VisualType::Sprite)
|
||||
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))
|
||||
{
|
||||
if (maths::rectangle_clip(&curSprite->DirtyRect, &vscreen_rect, &curSprite->DirtyRect))
|
||||
clearSprite = true;
|
||||
else
|
||||
curSprite->DirtyRect.Width = -1;
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
if (clearSprite)
|
||||
{
|
||||
auto yPos = curSprite->DirtyRect.YPosition;
|
||||
auto width = curSprite->DirtyRect.Width;
|
||||
@@ -112,31 +100,28 @@ void render::update()
|
||||
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 ==
|
||||
auto sprite = dirty_list[index];
|
||||
if (sprite->DirtyRect.Width > 0 && (sprite->VisualType == VisualType::None || sprite->VisualType ==
|
||||
VisualType::Sprite))
|
||||
repaint(*dirtyPtr);
|
||||
++dirtyPtr;
|
||||
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)
|
||||
auto curBall = ball_list[index];
|
||||
if (curBall->DirtyRect.Width > 0)
|
||||
gdrv::copy_bitmap(
|
||||
&vscreen,
|
||||
width,
|
||||
(*ballPtr)->DirtyRect.Height,
|
||||
(*ballPtr)->DirtyRect.XPosition,
|
||||
(*ballPtr)->DirtyRect.YPosition,
|
||||
bitmapPtr,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -224,25 +224,31 @@
|
||||
#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
|
||||
|
||||
// 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
|
||||
|
||||
@@ -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,
|
||||
|
||||
/*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 (!shortArr)
|
||||
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,15 +145,47 @@ 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)
|
||||
{
|
||||
/*3DB creates bitmaps, FT just references them from partman*/
|
||||
if (!pb::FullTiltMode)
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
if (msg_fontp->Chars[i])
|
||||
@@ -147,6 +194,7 @@ void score::unload_msg_font()
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
if (splashStruct)
|
||||
{
|
||||
BitBlt(dc, 0, 0, 10000, 10000, dc, 0, 0, BLACKNESS);
|
||||
splash_paint(splashStruct, dc);
|
||||
}
|
||||
ReleaseDC(hWnd, dc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_ERASEBKGND:
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -30,6 +30,7 @@ int winmain::no_time_loss;
|
||||
DWORD winmain::then;
|
||||
DWORD winmain::now;
|
||||
UINT winmain::iFrostUniqueMsg;
|
||||
bool winmain::restart = false;
|
||||
|
||||
gdrv_bitmap8 winmain::gfr_display{};
|
||||
char winmain::DatFileName[300]{};
|
||||
@@ -74,10 +75,10 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
||||
for (int i = 0; i < 32700; ++i)
|
||||
{
|
||||
sprintf_s(Buffer, "Table%d", i);
|
||||
options::get_string(nullptr, Buffer, tmpBuf, pinball::WindowName, 500);
|
||||
options::get_string(nullptr, Buffer, tmpBuf, "", 500);
|
||||
if (!*tmpBuf)
|
||||
break;
|
||||
options::get_string(tmpBuf, "Table Name", tmpBuf2, pinball::WindowName, 500);
|
||||
options::get_string(tmpBuf, "Table Name", tmpBuf2, "", 500);
|
||||
if (!lstrcmpA(tmpBuf2, pinball::get_rc_string(169, 0)))
|
||||
{
|
||||
setOption = false;
|
||||
@@ -101,7 +102,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
||||
options::path_uninit();
|
||||
return 0;
|
||||
}
|
||||
options::get_string(regSpaceCadet, "Shell Exe", tmpBuf, pinball::WindowName, 500);
|
||||
options::get_string(regSpaceCadet, "Shell Exe", tmpBuf, "", 500);
|
||||
auto execRes = WinExec(tmpBuf, 5u);
|
||||
memory::free(tmpBuf);
|
||||
if (execRes >= 32)
|
||||
@@ -116,6 +117,18 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
||||
hinst = hInstance;
|
||||
options::get_string(regSpaceCadet, "Pinball Data", DatFileName, pinball::get_rc_string(168, 0), 300);
|
||||
|
||||
/*Check for full tilt .dat file and switch to it automatically*/
|
||||
char cadetFilePath[300]{};
|
||||
pinball::make_path_name(cadetFilePath, "CADET.DAT", 300);
|
||||
FILE* cadetDat;
|
||||
fopen_s(&cadetDat, cadetFilePath, "r");
|
||||
if (cadetDat)
|
||||
{
|
||||
fclose(cadetDat);
|
||||
strcpy_s(DatFileName, "CADET.DAT");
|
||||
pb::FullTiltMode = true;
|
||||
}
|
||||
|
||||
iFrostUniqueMsg = RegisterWindowMessageA("PinballThemeSwitcherUniqueMsgString");
|
||||
auto windowClass = pinball::get_rc_string(167, 0);
|
||||
auto windowHandle = FindWindowA(windowClass, nullptr);
|
||||
@@ -133,25 +146,27 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
||||
picce.dwICC = 5885;
|
||||
InitCommonControlsEx(&picce);
|
||||
|
||||
WNDCLASSA WndClass{};
|
||||
WndClass.style = 4104;
|
||||
WndClass.lpfnWndProc = message_handler;
|
||||
WndClass.cbClsExtra = 0;
|
||||
WndClass.cbWndExtra = 0;
|
||||
WndClass.hInstance = hInstance;
|
||||
WndClass.hIcon = LoadIconA(hInstance, "ICON_1");
|
||||
WndClass.hCursor = LoadCursorA(nullptr, IDC_ARROW);
|
||||
WndClass.hbrBackground = (HBRUSH)16;
|
||||
WndClass.lpszMenuName = "MENU_1";
|
||||
WndClass.lpszClassName = windowClass;
|
||||
WNDCLASSEXA wndClass{};
|
||||
wndClass.cbSize = sizeof wndClass;
|
||||
wndClass.style = CS_DBLCLKS | CS_BYTEALIGNCLIENT;
|
||||
wndClass.lpfnWndProc = message_handler;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hInstance = hInstance;
|
||||
wndClass.hIcon = LoadIconA(hInstance, "ICON_1");
|
||||
wndClass.hCursor = LoadCursorA(nullptr, IDC_ARROW);
|
||||
wndClass.hbrBackground = (HBRUSH)16;
|
||||
wndClass.lpszMenuName = "MENU_1";
|
||||
wndClass.lpszClassName = windowClass;
|
||||
auto splash = splash::splash_screen(hInstance, "splash_bitmap", "splash_bitmap");
|
||||
RegisterClassA(&WndClass);
|
||||
RegisterClassExA(&wndClass);
|
||||
|
||||
pinball::FindShiftKeys();
|
||||
options::init_resolution();
|
||||
|
||||
char windowName[40];
|
||||
lstrcpyA(windowName, pinball::get_rc_string(38, 0));
|
||||
windowHandle = CreateWindowExA(0, windowClass, windowName, 0x3CA0000u, 0, 0, 640, 480, nullptr, nullptr, hInstance,
|
||||
windowHandle = CreateWindowExA(0, windowClass, windowName, WndStyle, 0, 0, 640, 480, nullptr, nullptr, hInstance,
|
||||
nullptr);
|
||||
hwnd_frame = windowHandle;
|
||||
if (!windowHandle)
|
||||
@@ -205,7 +220,16 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
||||
if (prevTime)
|
||||
{
|
||||
char buf[60];
|
||||
sprintf_s(buf, "Frames/sec = %02.02f", 300.0f / (static_cast<float>(curTime - prevTime) * 0.001f));
|
||||
auto dt = static_cast<float>(curTime - prevTime) * 0.001f;
|
||||
if (!options::Options.AlternativeRender)
|
||||
sprintf_s(buf, "Frames/sec = %02.02f", 300.0f / dt);
|
||||
else
|
||||
{
|
||||
sprintf_s(buf, "Updates/sec = %02.02f Frames/sec = %02.02f",
|
||||
300.0f / dt, pb::frameCounter / dt);
|
||||
pb::frameCounter = 0;
|
||||
}
|
||||
|
||||
SetWindowTextA(hwnd_frame, buf);
|
||||
|
||||
if (DispGRhistory)
|
||||
@@ -253,10 +277,14 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
||||
now = timeGetTime();
|
||||
if (now - then >= 2)
|
||||
{
|
||||
/*last_mouse_n is in client coordinates*/
|
||||
POINT Point;
|
||||
GetCursorPos(&Point);
|
||||
ScreenToClient(hwnd_frame, &Point);
|
||||
pb::ballset(last_mouse_x - Point.x, Point.y - last_mouse_y);
|
||||
SetCursorPos(last_mouse_x, last_mouse_y);
|
||||
Point = POINT{last_mouse_x, last_mouse_y};
|
||||
ClientToScreen(hwnd_frame, &Point);
|
||||
SetCursorPos(Point.x, Point.y);
|
||||
}
|
||||
}
|
||||
if (!single_step)
|
||||
@@ -301,11 +329,31 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
|
||||
DestroyWindow(hwnd_frame);
|
||||
options::path_uninit();
|
||||
UnregisterClassA(windowClass, hinst);
|
||||
|
||||
if (restart)
|
||||
{
|
||||
char restartPath[300]{};
|
||||
if (GetModuleFileNameA(nullptr, restartPath, 300))
|
||||
{
|
||||
STARTUPINFO si{};
|
||||
PROCESS_INFORMATION pi{};
|
||||
si.cb = sizeof si;
|
||||
if (CreateProcess(restartPath, nullptr, nullptr, nullptr,
|
||||
FALSE, 0, nullptr, nullptr, &si, &pi))
|
||||
{
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int wParamI = static_cast<int>(wParam);
|
||||
|
||||
if (Msg == iFrostUniqueMsg)
|
||||
{
|
||||
if (IsIconic(hWnd))
|
||||
@@ -350,11 +398,6 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
RECT rect{};
|
||||
++memory::critical_allocation;
|
||||
|
||||
GetWindowRect(GetDesktopWindow(), &rect);
|
||||
int width = rect.right - rect.left;
|
||||
int height = rect.bottom - rect.top;
|
||||
pb::window_size(&width, &height);
|
||||
|
||||
auto prevCursor = SetCursor(LoadCursorA(nullptr, IDC_WAIT));
|
||||
gdrv::init(hinst, hWnd);
|
||||
|
||||
@@ -371,6 +414,11 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
SetCursor(prevCursor);
|
||||
auto changeDisplayFg = options::get_int(nullptr, "Change Display", 1);
|
||||
auto menuHandle = GetMenu(hWnd);
|
||||
|
||||
GetWindowRect(GetDesktopWindow(), &rect);
|
||||
int width = rect.right - rect.left;
|
||||
int height = rect.bottom - rect.top;
|
||||
pb::window_size(&width, &height);
|
||||
fullscrn::init(width, height, options::Options.FullScreen, hWnd, menuHandle,
|
||||
changeDisplayFg);
|
||||
|
||||
@@ -405,6 +453,11 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
case WM_ERASEBKGND:
|
||||
break;
|
||||
case WM_SIZE:
|
||||
fullscrn::window_size_changed();
|
||||
fullscrn::force_redraw();
|
||||
pb::paint();
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
default:
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
@@ -428,6 +481,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
fullscrn::getminmaxinfo((MINMAXINFO*)lParam);
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
case WM_DISPLAYCHANGE:
|
||||
options::update_resolution_menu();
|
||||
if (fullscrn::displaychange())
|
||||
{
|
||||
options::Options.FullScreen = 0;
|
||||
@@ -435,11 +489,11 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
}
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
case WM_KEYUP:
|
||||
pb::keyup(wParam);
|
||||
pb::keyup(wParamI);
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
case WM_KEYDOWN:
|
||||
if (!(lParam & 0x40000000))
|
||||
pb::keydown(wParam);
|
||||
pb::keydown(wParamI);
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_ESCAPE:
|
||||
@@ -464,6 +518,8 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
pause();
|
||||
options::keyboard();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!pb::cheat_mode)
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
@@ -531,11 +587,11 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
if (tmpBuf)
|
||||
{
|
||||
char cmdLine[0x1F4u];
|
||||
options::get_string(nullptr, "Shell Exe", tmpBuf, pinball::WindowName, 500);
|
||||
options::get_string(nullptr, "Shell Exe", tmpBuf, "", 500);
|
||||
auto iHwnd = reinterpret_cast<size_t>(hwnd_frame);
|
||||
sprintf_s(
|
||||
cmdLine,
|
||||
"%s %s%lX %s%lX",
|
||||
"%s %s%zX %s%zX",
|
||||
tmpBuf,
|
||||
"select=",
|
||||
iHwnd,
|
||||
@@ -555,9 +611,17 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
case Menu1_2Players:
|
||||
case Menu1_3Players:
|
||||
case Menu1_4Players:
|
||||
options::toggle(wParam);
|
||||
options::toggle(wParamI);
|
||||
new_game();
|
||||
break;
|
||||
case Menu1_MaximumResolution:
|
||||
case Menu1_640x480:
|
||||
case Menu1_800x600:
|
||||
case Menu1_1024x768:
|
||||
case Menu1_WindowUniformScale:
|
||||
case Menu1_AlternativeRender:
|
||||
options::toggle(wParamI);
|
||||
break;
|
||||
case Menu1_Help_Topics:
|
||||
if (!single_step)
|
||||
pause();
|
||||
@@ -571,7 +635,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
case Menu1_Music:
|
||||
if (!single_step)
|
||||
pause();
|
||||
options::toggle(wParam);
|
||||
options::toggle(wParamI);
|
||||
break;
|
||||
case Menu1_Player_Controls:
|
||||
case 204: // Second controls button?
|
||||
@@ -609,11 +673,14 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
{
|
||||
mouse_down = 1;
|
||||
mouse_hsave = SetCursor(nullptr);
|
||||
auto mouseXY = fullscrn::convert_mouse_pos(lParam);
|
||||
auto mouseXY = fullscrn::convert_mouse_pos(static_cast<unsigned>(lParam));
|
||||
last_mouse_x = mouseXY & 0xffFFu;
|
||||
last_mouse_y = mouseXY >> 16;
|
||||
SetCapture(hWnd);
|
||||
}
|
||||
else
|
||||
pb::keydown(options::Options.LeftFlipperKey);
|
||||
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
@@ -624,12 +691,27 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
SetCursor(mouse_hsave);
|
||||
ReleaseCapture();
|
||||
}
|
||||
if (!pb::cheat_mode)
|
||||
pb::keyup(options::Options.LeftFlipperKey);
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
if (!pb::cheat_mode)
|
||||
pb::keydown(options::Options.RightFlipperKey);
|
||||
if (pb::game_mode)
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
if (!pb::cheat_mode)
|
||||
pb::keyup(options::Options.RightFlipperKey);
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
case WM_MBUTTONDOWN:
|
||||
pb::keydown(options::Options.PlungerKey);
|
||||
if (pb::game_mode)
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
break;
|
||||
case WM_MBUTTONUP:
|
||||
pb::keyup(options::Options.PlungerKey);
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
case WM_POWERBROADCAST:
|
||||
if (wParam == 4 && options::Options.FullScreen)
|
||||
{
|
||||
@@ -641,7 +723,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
|
||||
case WM_PALETTECHANGED:
|
||||
InvalidateRect(hWnd, nullptr, 0);
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
case WM_POINTERDEVICEINRANGE | LB_ADDSTRING:
|
||||
case MM_MCINOTIFY:
|
||||
if (wParam == 1)
|
||||
midi::restart_midi_seq(lParam);
|
||||
return DefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||
@@ -665,7 +747,7 @@ int winmain::ProcessWindowMessages()
|
||||
DispatchMessageA(&Msg);
|
||||
if (Msg.message == 18)
|
||||
{
|
||||
return_value = Msg.wParam;
|
||||
return_value = static_cast<int>(Msg.wParam);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -676,7 +758,7 @@ int winmain::ProcessWindowMessages()
|
||||
DispatchMessageA(&Msg);
|
||||
if (Msg.message == 18)
|
||||
{
|
||||
return_value = Msg.wParam;
|
||||
return_value = static_cast<int>(Msg.wParam);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -718,10 +800,11 @@ HDC winmain::_GetDC(HWND hWnd)
|
||||
int winmain::a_dialog(HINSTANCE hInstance, HWND hWnd)
|
||||
{
|
||||
char appName[100];
|
||||
char szOtherStuff[100];
|
||||
char szOtherStuff[130];
|
||||
|
||||
lstrcpyA(appName, pinball::get_rc_string(38, 0));
|
||||
lstrcpyA(szOtherStuff, pinball::get_rc_string(102, 0));
|
||||
strcat_s(szOtherStuff, " Decompilation version 1.1.2");
|
||||
auto icon = LoadIconA(hInstance, "ICON_1");
|
||||
return ShellAboutA(hWnd, appName, szOtherStuff, icon);
|
||||
}
|
||||
@@ -779,3 +862,9 @@ void winmain::help_introduction(HINSTANCE a1, HWND a2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void winmain::Restart()
|
||||
{
|
||||
restart = true;
|
||||
PostMessageA(hwnd_frame, WM_QUIT, 0, 0);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user