16 Commits

Author SHA1 Message Date
Muzychenko Andrey
10c83e8bf5 Fixed sound pops introduced by WaveMix upsampler.
This does not fix WINE issues, but at least you don’t have to up sample manually.
2021-08-19 09:29:32 +03:00
Muzychenko Andrey
d5b44e44e1 Improved wav duration calculation - now supports sample rates other than 11025.
Bumped build tool version to VS2019.
2021-08-18 12:44:26 +03:00
Muzychenko Andrey
dcd488c48c Merge pull request #5 from GeorgeMcMullen/midifix
Fix to the routine that opens the MIDI file.
2021-08-18 10:08:55 +03:00
George McMullen
db08631ab9 Fix to the routine that opens the MIDI file.
In the original source code for Space Cadet and its related games, the MIDI sound track is opened with MCI_OPEN_TYPE. According to Microsoft's documentation (https://docs.microsoft.com/en-us/windows/win32/multimedia/mci-open), this is for opening devices and not files. Windows' libraries were obviously robust enough to accommodate the error, but other platforms (i.e. WINE) expects things to be called the right way. The simple fix is to switch out MCI_OPEN_TYPE with MCI_OPEN_ELEMENT and move the info for the filename to the lpstrElementName variable.
2021-08-16 05:39:18 -07:00
Muzychenko Andrey
bad55d49cf Updated readme. 2021-02-20 15:58:16 +03:00
Muzychenko Andrey
98f234fce3 Replaced GlobalAlloc with malloc.
WaveMix keeps GlobalAlloc for authenticity.
Fixed float to double casts.
Some cleanup.
2021-02-18 12:53:25 +03:00
Muzychenko Andrey
55984fbb08 Fixed x64 build warnings.
Replaced __intN with intN_t.
Some cleanup.
2021-02-16 19:03:45 +03:00
Muzychenko Andrey
5c3e9fea4c Added FT music loader.
Fixed mouse lock.
Some cleanup.
2021-02-15 18:55:54 +03:00
Muzychenko Andrey
debe52c1e0 Added scalable window, mouse controls. 2021-02-09 18:09:44 +03:00
Muzychenko Andrey
1c5256a4c6 Added table resolution support.
Only works with FT .dat file.
FT music does not work - different format.
2021-02-06 16:53:47 +03:00
Muzychenko Andrey
d594f5fdb7 Converted memory to direct pointers.
Fixed memory leaks in uninit.
Fixed some of the code analysis warnings.
Enabled /MP build.
Cleaned up the code.
2021-02-02 18:29:54 +03:00
Muzychenko Andrey
49f6132d23 Added loader for Full Tilt .dat files, v1.
Works with some data hacks in lowest resolution.
Seems to work ok, even though BL is still 3DPB.
2021-01-31 17:29:53 +03:00
Muzychenko Andrey
6ff457eb68 Cleaned up objlist_class. 2021-01-30 14:19:25 +03:00
Muzychenko Andrey
5b9a1ff95d Create LICENSE
Some docs might be incompatible with MIT, to be reviewed later.
2021-01-29 19:47:23 +03:00
Muzychenko Andrey
232f24a2a2 Added Readme.md 2021-01-29 19:34:45 +03:00
oz
efc56e82d9 Compile releases with Windows subsystem. 2021-01-29 17:49:00 +03:00
93 changed files with 2370 additions and 1327 deletions

View File

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

View File

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

21
LICENSE Normal file
View File

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

40
README.md Normal file
View 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`

View File

@@ -1,6 +1,8 @@
#include "pch.h"
#include "Sound.h"
#include "pb.h"
#include "pinball.h"
#include "WaveMix.h"
#include "winmain.h"
@@ -45,7 +47,9 @@ int Sound::Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWA
}
else
{
MessageBoxA(winmain::hwnd_frame, pinball::get_rc_string(42, 0), pinball::WindowName, 0x2000u);
/*FT does not have the file, defaults work OK*/
if (!pb::FullTiltMode)
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{};

View File

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

View File

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

View File

@@ -88,6 +88,17 @@ 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
END
END
POPUP "&Help"
BEGIN
@@ -342,7 +353,7 @@ END
// Bitmap
//
splash_bitmap BITMAP "splash_bitmap.bmp"
SPLASH_BITMAP BITMAP "splash_bitmap.bmp"
/////////////////////////////////////////////////////////////////////////////
@@ -587,6 +598,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
/////////////////////////////////////////////////////////////////////////////

View File

@@ -23,32 +23,32 @@
<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)'=='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)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<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>
@@ -94,6 +94,7 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<BufferSecurityCheck>true</BufferSecurityCheck>
<PreprocessToFile>false</PreprocessToFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -110,6 +111,7 @@
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -128,9 +130,10 @@
<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>
@@ -148,9 +151,10 @@
<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>
@@ -219,7 +223,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,7 +237,6 @@
<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" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,11 +4,11 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "pb.h"
#include "render.h"
#include "TFlipperEdge.h"
#include "timer.h"
#include "TZmapList.h"
TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
{
@@ -21,12 +21,16 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t
Timer = 0;
Smoothness = visual.Smoothness;
auto floatArr = loader::query_float_attribute(groupIndex, 0, 803);
auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 805);
auto floatArr3 = loader::query_float_attribute(groupIndex, 0, 804);
auto collMult = *floatArr;
auto bmpCoef2 = *floatArr2;
auto bmpCoef1 = *floatArr3;
auto collMult = *loader::query_float_attribute(groupIndex, 0, 803);
auto bmpCoef2 = *loader::query_float_attribute(groupIndex, 0, 805);
auto bmpCoef1 = *loader::query_float_attribute(groupIndex, 0, 804);
/*Full tilt hack: different flipper speed*/
if (pb::FullTiltMode)
{
bmpCoef2 = 0.08f;
bmpCoef1 = 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));
@@ -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);
BmpCoef1 = flipperEdge->BmpCoef1 / static_cast<float>(ListBitmap->GetCount() - 1);
BmpCoef2 = flipperEdge->BmpCoef2 / static_cast<float>(ListBitmap->GetCount() - 1);
}
BmpIndex = 0;
InputTime = 0.0;
@@ -93,7 +97,7 @@ int TFlipper::Message(int code, float value)
{
auto v10 = value - FlipperEdge->InputTime;
timerTime = v10 - floor(v10 / TimerTime) * TimerTime;
if (timerTime < 0.0)
if (timerTime < 0.0f)
timerTime = 0.0;
}
else
@@ -137,7 +141,7 @@ void TFlipper::TimerExpired(int timerId, void* caller)
bool bmpIndexOutOfBounds = false;
auto bmpIndexAdvance = static_cast<int>(floor((pb::time_now - flip->InputTime) / flip->TimerTime + 0.5f));
int bmpCount = flip->ListBitmap->Count();
int bmpCount = flip->ListBitmap->GetCount();
if (bmpIndexAdvance > bmpCount)
bmpIndexAdvance = bmpCount;
if (bmpIndexAdvance < 0)
@@ -149,7 +153,7 @@ void TFlipper::TimerExpired(int timerId, void* caller)
if (flip->MessageField == 1)
{
flip->BmpIndex += bmpIndexAdvance;
int countSub1 = flip->ListBitmap->Count() - 1;
int countSub1 = flip->ListBitmap->GetCount() - 1;
if (flip->BmpIndex >= countSub1)
{
flip->BmpIndex = countSub1;
@@ -177,8 +181,8 @@ void TFlipper::TimerExpired(int timerId, void* caller)
timer = timer::set(flip->TimerTime, flip, TimerExpired);
flip->Timer = timer;
auto bmp = static_cast<gdrv_bitmap8*>(flip->ListBitmap->Get(flip->BmpIndex));
auto zMap = static_cast<zmap_header_type*>(flip->ListZMap->Get(flip->BmpIndex));
auto bmp = flip->ListBitmap->Get(flip->BmpIndex);
auto zMap = flip->ListZMap->Get(flip->BmpIndex);
render::sprite_set(
flip->RenderSprite,
bmp,

View File

@@ -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);
@@ -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;
}

View File

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

View File

@@ -5,6 +5,7 @@
#include "control.h"
#include "loader.h"
#include "objlist_class.h"
#include "pb.h"
#include "TBall.h"
#include "timer.h"
#include "TPinballTable.h"
@@ -19,26 +20,19 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
MessageField = 0;
Timer = 0;
BallCapturedFlag = 0;
auto floatArr1 = loader::query_float_attribute(groupIndex, 0, 407);
if (floatArr1)
Unknown3 = *floatArr1;
else
Unknown3 = 0.25;
auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 701);
if (floatArr2)
GravityMult = *floatArr2;
else
GravityMult = 0.5;
Unknown3 = loader::query_float_attribute(groupIndex, 0, 407, 0.25f);
GravityMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f);
GravityPull = *loader::query_float_attribute(groupIndex, 0, 305);
loader::query_visual(groupIndex, 0, &visual);
Circle.Center.X = visual.FloatArr[0];
Circle.Center.Y = visual.FloatArr[1];
Circle.RadiusSq = *loader::query_float_attribute(groupIndex, 0, 306) * visual.FloatArr[2];
if (Circle.RadiusSq == 0.0)
if (Circle.RadiusSq == 0.0f)
Circle.RadiusSq = 0.001f;
auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup, reinterpret_cast<vector_type*>(visual.FloatArr),
auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup,
reinterpret_cast<vector_type*>(visual.FloatArr),
Circle.RadiusSq);
if (tCircle)
{
@@ -49,6 +43,10 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
ZSetValue = loader::query_float_attribute(groupIndex, 0, 408)[2];
FieldFlag = static_cast<int>(floor(*loader::query_float_attribute(groupIndex, 0, 1304)));
/*Full tilt hack - FieldFlag should be on*/
if (pb::FullTiltMode)
FieldFlag = 1;
Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2];
circle.RadiusSq = Circle.RadiusSq;
circle.Center.X = Circle.Center.X;

View File

@@ -5,10 +5,10 @@
#include "control.h"
#include "loader.h"
#include "maths.h"
#include "objlist_class.h"
#include "render.h"
#include "timer.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TKickback::TKickback(TPinballTable* table, int groupIndex): TCollisionComponent(table, groupIndex, true)
{
@@ -66,8 +66,8 @@ void TKickback::TimerExpired(int timerId, void* caller)
loader::play_sound(kick->HardHitSoundId);
if (kick->ListBitmap)
{
auto bmp = static_cast<gdrv_bitmap8*>(kick->ListBitmap->Get(1));
auto zMap = static_cast<zmap_header_type*>(kick->ListZMap->Get(1));
auto bmp = kick->ListBitmap->Get(1);
auto zMap = kick->ListZMap->Get(1);
render::sprite_set(
kick->RenderSprite,
bmp,
@@ -80,8 +80,8 @@ void TKickback::TimerExpired(int timerId, void* caller)
{
if (kick->ListBitmap)
{
auto bmp = static_cast<gdrv_bitmap8*>(kick->ListBitmap->Get(0));
auto zMap = static_cast<zmap_header_type*>(kick->ListZMap->Get(0));
auto bmp = kick->ListBitmap->Get(0);
auto zMap = kick->ListZMap->Get(0);
render::sprite_set(
kick->RenderSprite,
bmp,

View File

@@ -30,10 +30,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);
@@ -67,7 +67,7 @@ int TKickout::Message(int code, float value)
case 55:
if (KickFlag1)
{
if (value < 0.0)
if (value < 0.0f)
value = TimerTime1;
Timer = timer::set(value, this, TimerExpired);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -48,8 +48,8 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
{
int shortArrLength;
ComponentList = new objlist_class(32, 16);
BallList = new objlist_class(3, 1);
ComponentList = new objlist_class<TPinballComponent>(32, 16);
BallList = new objlist_class<TBall>(3, 1);
CurScoreStruct = nullptr;
ScoreBallcount = nullptr;
ScorePlayerNumber1 = nullptr;
@@ -213,9 +213,9 @@ TPinballTable::~TPinballTable()
ScoreBallcount = nullptr;
}
delete LightGroup;
while (ComponentList->Count() > 0)
while (ComponentList->GetCount() > 0)
{
delete static_cast<TPinballComponent*>(ComponentList->Get(0));
delete ComponentList->Get(0);
}
delete BallList;
delete ComponentList;
@@ -223,12 +223,12 @@ TPinballTable::~TPinballTable()
TPinballComponent* TPinballTable::find_component(LPCSTR componentName)
{
int objCount = ComponentList->Count();
int objCount = ComponentList->GetCount();
if (objCount > 0)
{
for (int index = 0; index < objCount; ++index)
{
TPinballComponent* obj = static_cast<TPinballComponent*>(ComponentList->Get(index));
TPinballComponent* obj = ComponentList->Get(index);
const CHAR* groupName = obj->GroupName;
if (groupName && !lstrcmpA(groupName, componentName))
{
@@ -242,13 +242,13 @@ TPinballComponent* TPinballTable::find_component(LPCSTR componentName)
TPinballComponent* TPinballTable::find_component(int groupIndex)
{
char Buffer[40];
int objCount = ComponentList->Count();
char Buffer[40]{};
int objCount = ComponentList->GetCount();
if (objCount > 0)
{
for (int index = 0; index < objCount; ++index)
{
TPinballComponent* obj = static_cast<TPinballComponent*>(ComponentList->Get(index));
TPinballComponent* obj = ComponentList->Get(index);
if (obj->GroupIndex == groupIndex)
return obj;
}
@@ -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);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -597,9 +597,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,17 +616,15 @@ 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);
}
@@ -1924,7 +1922,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 +2230,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;
}
@@ -3019,7 +3017,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 +3054,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)

View File

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

View File

@@ -1,5 +1,9 @@
#include "pch.h"
#include "fullscrn.h"
#include "options.h"
#include "pb.h"
#include "render.h"
#include "winmain.h"
@@ -10,10 +14,22 @@ tagRECT fullscrn::WindowRect1, fullscrn::WindowRect2;
rectangle_type fullscrn::WHRect;
int fullscrn::fullscrn_flag1;
int fullscrn::display_changed;
int fullscrn::ChangeDisplay, fullscrn::SmthFullScrnFlag2;
int fullscrn::ChangeDisplay, fullscrn::ignoreNextDisplayChangeFg;
int fullscrn::trick = 1;
int fullscrn::MenuEnabled;
HMENU fullscrn::MenuHandle;
int fullscrn::resolution = 0;
int fullscrn::maxResolution = 0;
const resolution_info fullscrn::resolution_array[3] =
{
{640, 480, 600, 416, 501},
{800, 600, 752, 520, 502},
{1024, 768, 960, 666, 503},
};
float fullscrn::ScaleX = 1;
float fullscrn::ScaleY = 1;
float fullscrn::OffsetX = 0;
float 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,89 @@ 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 = floor((client.right - res->TableWidth * ScaleX) / 2);
OffsetY = floor((client.bottom - res->TableHeight * ScaleY) / 2);
auto dc = GetDC(hWnd);
if (dc)
{
BitBlt(dc, 0, 0, client.right, client.bottom, dc, 0, 0, BLACKNESS);
ReleaseDC(hWnd, dc);
}
}
}

View File

@@ -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 float OffsetX;
static float OffsetY;
static void init(int width, int height, int isFullscreen, HWND winHandle, HMENU menuHandle, int changeDisplay);
static void shutdown();
@@ -29,14 +44,23 @@ public:
static void getminmaxinfo(MINMAXINFO* maxMin);
static void paint();
static bool set_menu_mode(int menuEnabled);
static int GetResolution();
static void SetResolution(int resolution);
static int GetMaxResolution();
static void SetMaxResolution(int resolution);
static int get_max_supported_resolution();
static int get_screen_resolution();
static void window_size_changed();
private :
static int MenuEnabled;
static HMENU MenuHandle;
static int resolution;
static int maxResolution;
static void GetWindowCenter();
static int disableWindowFlagsDisDlg();
static int setWindowFlagsDisDlg();
static int enableFullscreen();
static int disableFullscreen();
static void fillRect(int right, int bottom);
static void fillRect(int right, int bottom, int left, int top);
};

View File

@@ -1,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*)&current_palette);
palette_handle = CreatePalette(&current_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*)&current_palette);
palette_handle = CreatePalette(&current_palette);
auto windowHandle = GetDesktopWindow();
auto dc = winmain::_GetDC(windowHandle);
SetSystemPaletteUse(dc, 2u);
SetSystemPaletteUse(dc, 1u);
auto pltHandle = SelectPalette(dc, palette_handle, 0);
auto originalPalette = SelectPalette(dc, palette_handle, 0);
RealizePalette(dc);
SelectPalette(dc, pltHandle, 0);
GetSystemPaletteEntries(dc, 0, 0x100u, current_palette.palPalEntry);
SelectPalette(dc, originalPalette, 0);
GetSystemPaletteEntries(dc, 0, 256, current_palette.palPalEntry);
for (int i = 0; i < 256; i++)
{
current_palette.palPalEntry[i].peFlags = 0;
@@ -219,15 +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);
}
}
@@ -316,8 +319,9 @@ void gdrv::blat(gdrv_bitmap8* bmp, int xDest, int yDest)
HDC dc = winmain::_GetDC(hwnd);
SelectPalette(dc, palette_handle, 0);
RealizePalette(dc);
SetStretchBltMode(dc, stretchMode);
if (!use_wing)
StretchDIBits(
StretchDIBitsScaled(
dc,
xDest,
yDest,
@@ -327,10 +331,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 +344,11 @@ void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int y
if (bmpHeight < 0)
bmpHeight = -bmpHeight;
char* bmpPtr = &bmp->BmpBufPtr1[bmp->Width * (bmpHeight - height - yOff) + xOff];
if (height > 0)
for (; height > 0; --height)
{
do
{
if (width > 0)
memset(bmpPtr, fillChar, width);
bmpPtr += bmp->Stride;
--height;
}
while (height);
if (width > 0)
memset(bmpPtr, fillChar, width);
bmpPtr += bmp->Stride;
}
}
@@ -414,9 +413,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);
}

View File

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

View File

@@ -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");
@@ -106,7 +102,6 @@ int high_score::write(high_score_struct* table, int* ptrToSmth)
++position;
++tablePtr;
}
while (position < 5);
scramble_number_string(scoreSum, buf);
options::set_string(optPath, "Verification", buf);
memory::free(buf);
@@ -177,7 +172,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 +209,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 +241,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 +276,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;

View File

@@ -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];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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,7 @@ void options::init(HMENU menuHandle)
Options.LeftTableBumpKey = get_int(nullptr, "Left Table Bump key", Options.LeftTableBumpKey);
Options.RightTableBumpKey = get_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey);
Options.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
Options.UniformScaling = get_int(nullptr, "Uniform scaling", true);
menu_check(Menu1_Sounds, Options.Sounds);
Sound::Enable(0, 7, Options.Sounds);
menu_check(Menu1_Music, Options.Music);
@@ -114,10 +116,11 @@ void options::init(HMENU menuHandle)
menu_check(Menu1_2Players, Options.Players == 2);
menu_check(Menu1_3Players, Options.Players == 3);
menu_check(Menu1_4Players, Options.Players == 4);
menu_check(Menu1_WindowUniformScale, Options.UniformScaling);
auto tmpBuf = memory::allocate(0x1F4u);
if (tmpBuf)
{
get_string(nullptr, "Shell Exe", tmpBuf, pinball::WindowName, 500);
get_string(nullptr, "Shell Exe", tmpBuf, "", 500);
if (!*tmpBuf)
{
if (MenuHandle)
@@ -128,6 +131,8 @@ void options::init(HMENU menuHandle)
}
memory::free(tmpBuf);
}
update_resolution_menu();
}
void options::uninit()
@@ -142,6 +147,8 @@ 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);
}
void options::path_init(LPCSTR regPath)
@@ -187,73 +194,75 @@ void options::path_free()
int options::get_int(LPCSTR optPath, LPCSTR lpValueName, int defaultValue)
{
DWORD dwDisposition;
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);
}
path_free();
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);
}
path_free();
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);
}
path_free();
RegSetValueExA(hKey, lpValueName, 0, 1u, LPBYTE(value), lstrlenA(value) + 1);
RegCloseKey(hKey);
}
path_free();
}
@@ -296,14 +305,83 @@ 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;
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 +410,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 +489,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 +571,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)

View File

@@ -21,6 +21,8 @@ struct optionsStruct
int LeftTableBumpKeyDft;
int RightTableBumpKeyDft;
int BottomTableBumpKeyDft;
int Resolution;
bool UniformScaling;
};
@@ -33,15 +35,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:

View File

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

View File

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

View File

@@ -3,6 +3,7 @@
#include "control.h"
#include "fullscrn.h"
#include "high_score.h"
#include "memory.h"
#include "pinball.h"
@@ -28,6 +29,8 @@ 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;
float pb::time_now, pb::time_next, pb::ball_speed_limit;
high_score_struct pb::highscore_table[5];
bool pb::FullTiltMode = 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;
}
@@ -209,7 +215,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);
@@ -233,7 +239,7 @@ 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;
}
@@ -242,11 +248,11 @@ int pb::frame(int time)
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 +263,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 +288,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 ? 1000000000.0f : 1.0f / ball->Acceleration.X;
ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0f ? 1000000000.0f : 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 +306,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 +317,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()
@@ -440,7 +446,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 +454,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 +480,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':
@@ -545,7 +551,7 @@ void pb::end_game()
scores[j] = scores[i];
scores[i] = score;
int index = scoreIndex[j];
int index = scoreIndex[j];
scoreIndex[j] = scoreIndex[i];
scoreIndex[i] = index;
}
@@ -626,7 +632,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 +644,7 @@ float pb::collide(float timeNow, float timeDelta, TBall* ball)
else
{
edge->EdgeCollision(ball, distance);
if (ball->Speed > 0.000000001)
if (ball->Speed > 0.000000001f)
return fabs(distance / ball->Speed);
}
}

View File

@@ -14,6 +14,7 @@ public:
static datFileStruct* record_table;
static TPinballTable* MainTable;
static high_score_struct highscore_table[5];
static bool FullTiltMode;
static int init();
static int uninit();
@@ -38,7 +39,7 @@ public:
static void tilt_no_more();
static bool chk_highscore();
static float collide(float timeNow, float timeDelta, TBall* ball);
private :
private:
static int demo_mode, mode_countdown_;
static int state;
};

View File

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

View File

@@ -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;

View File

@@ -13,7 +13,6 @@ public:
static int quickFlag;
static TTextBox* InfoTextBox;
static TTextBox* MissTextBox;
static char WindowName[2];
static int RightShift;
static int LeftShift;

View File

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

View File

@@ -18,9 +18,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 +48,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);
@@ -221,7 +221,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 +278,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 +286,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 +300,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 +308,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 +473,21 @@ void render::paint_balls()
void render::unpaint_balls()
{
auto ballPtr = &ball_list[many_balls - 1];
if (many_balls - 1 >= 0)
for (int index = many_balls-1; index >= 0; index--)
{
gdrv_bitmap8* bitmapPtr = &ball_bitmap[many_balls - 1];
for (int index = many_balls; index > 0; index--)
{
struct render_sprite_type_struct* curBall = *ballPtr;
rectangle_type* rect2 = &(*ballPtr)->DirtyRect;
int width = (*ballPtr)->DirtyRect.Width;
if (width > 0)
gdrv::copy_bitmap(
&vscreen,
width,
(*ballPtr)->DirtyRect.Height,
(*ballPtr)->DirtyRect.XPosition,
(*ballPtr)->DirtyRect.YPosition,
bitmapPtr,
0,
0);
auto curBall = ball_list[index];
if (curBall->DirtyRect.Width > 0)
gdrv::copy_bitmap(
&vscreen,
curBall->DirtyRect.Width,
curBall->DirtyRect.Height,
curBall->DirtyRect.XPosition,
curBall->DirtyRect.YPosition,
&ball_bitmap[index],
0,
0);
rectangle_type* rectCopy = &curBall->BmpRectCopy;
rectCopy->XPosition = rect2->XPosition;
rectCopy->YPosition = rect2->YPosition;
rectCopy->Width = rect2->Width;
rectCopy->Height = rect2->Height;
--ballPtr;
--bitmapPtr;
}
curBall->BmpRectCopy = curBall->DirtyRect;
}
}
@@ -542,7 +524,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 +542,7 @@ void render::build_occlude_list()
occludeCount = 0;
if (occludeCount)
{
curSprite->SpriteArray = reinterpret_cast<render_sprite_type_struct**>(memory::realloc(
spriteArr, sizeof(void*) * occludeCount));
curSprite->SpriteArray = memory::realloc(spriteArr, sizeof(void*) * occludeCount);
curSprite->SpriteCount = occludeCount;
spriteArr = nullptr;
}

View File

@@ -17,7 +17,7 @@ struct render_sprite_type_struct
zmap_header_type* ZMap;
char UnknownFlag;
VisualType VisualType;
__int16 Depth;
int16_t Depth;
rectangle_type BmpRectCopy;
int ZMapOffestY;
int ZMapOffestX;

View File

@@ -224,12 +224,17 @@
#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
@@ -241,8 +246,8 @@
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 204
#define _APS_NEXT_COMMAND_VALUE 40004
#define _APS_NEXT_COMMAND_VALUE 40006
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 102
#define _APS_NEXT_SYMED_VALUE 104
#endif
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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)
@@ -253,10 +268,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 +320,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 +389,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 +405,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 +444,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 +472,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 +480,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 +509,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 +578,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 +602,16 @@ 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:
options::toggle(wParamI);
break;
case Menu1_Help_Topics:
if (!single_step)
pause();
@@ -571,7 +625,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 +663,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 +681,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 +713,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 +737,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 +748,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;
@@ -779,3 +851,9 @@ void winmain::help_introduction(HINSTANCE a1, HWND a2)
}
}
}
void winmain::Restart()
{
restart = true;
PostMessageA(hwnd_frame, WM_QUIT, 0, 0);
}

View File

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

View File

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

View File

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