SDL port v1, Windows only for now.

Working: graphics, sound, music (3dpb only).
Not working: GUI, user settings.
This commit is contained in:
Muzychenko Andrey 2021-08-27 13:29:41 +03:00
parent 10c83e8bf5
commit a09ea75d80
30 changed files with 872 additions and 4172 deletions

6
.gitignore vendored
View file

@ -263,3 +263,9 @@ __pycache__/
/Export
/DrMem
/Doc private
# Windows local libraries
/Libs
#CMake generated
out/
/cmake-build-debug

145
CMakeLists.txt Normal file
View file

@ -0,0 +1,145 @@
cmake_minimum_required(VERSION 3.16)
project(SpaceCadetPinball)
set(CMAKE_CXX_STANDARD 14)
set(SDL2_DIR "${CMAKE_CURRENT_LIST_DIR}/Libs/SDL2-2.0.16")
set(SDL2_mixer_DIR "${CMAKE_CURRENT_LIST_DIR}/Libs/SDL2_mixer-2.0.4")
find_package(SDL2 REQUIRED)
FIND_PACKAGE(SDL2_mixer REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS} ${SDL2_MIXER_INCLUDE_DIRS})
set(SOURCE_FILES
SpaceCadetPinball/control.cpp
SpaceCadetPinball/control.h
SpaceCadetPinball/fullscrn.cpp
SpaceCadetPinball/fullscrn.h
SpaceCadetPinball/gdrv.cpp
SpaceCadetPinball/gdrv.h
SpaceCadetPinball/high_score.cpp
SpaceCadetPinball/high_score.h
SpaceCadetPinball/loader.cpp
SpaceCadetPinball/loader.h
SpaceCadetPinball/maths.cpp
SpaceCadetPinball/maths.h
SpaceCadetPinball/memory.cpp
SpaceCadetPinball/memory.h
SpaceCadetPinball/midi.cpp
SpaceCadetPinball/midi.h
SpaceCadetPinball/nudge.cpp
SpaceCadetPinball/nudge.h
SpaceCadetPinball/objlist_class.h
SpaceCadetPinball/options.cpp
SpaceCadetPinball/options.h
SpaceCadetPinball/partman.cpp
SpaceCadetPinball/partman.h
SpaceCadetPinball/pb.cpp
SpaceCadetPinball/pb.h
SpaceCadetPinball/pch.cpp
SpaceCadetPinball/pch.h
SpaceCadetPinball/pinball.cpp
SpaceCadetPinball/pinball.h
SpaceCadetPinball/proj.cpp
SpaceCadetPinball/proj.h
SpaceCadetPinball/render.cpp
SpaceCadetPinball/render.h
SpaceCadetPinball/resource.h
SpaceCadetPinball/score.cpp
SpaceCadetPinball/score.h
SpaceCadetPinball/Sound.cpp
SpaceCadetPinball/Sound.h
SpaceCadetPinball/SpaceCadetPinball.cpp
SpaceCadetPinball/splash.cpp
SpaceCadetPinball/splash.h
SpaceCadetPinball/TBall.cpp
SpaceCadetPinball/TBall.h
SpaceCadetPinball/TBlocker.cpp
SpaceCadetPinball/TBlocker.h
SpaceCadetPinball/TBumper.cpp
SpaceCadetPinball/TBumper.h
SpaceCadetPinball/TCircle.cpp
SpaceCadetPinball/TCircle.h
SpaceCadetPinball/TCollisionComponent.cpp
SpaceCadetPinball/TCollisionComponent.h
SpaceCadetPinball/TComponentGroup.cpp
SpaceCadetPinball/TComponentGroup.h
SpaceCadetPinball/TDemo.cpp
SpaceCadetPinball/TDemo.h
SpaceCadetPinball/TDrain.cpp
SpaceCadetPinball/TDrain.h
SpaceCadetPinball/TEdgeBox.cpp
SpaceCadetPinball/TEdgeBox.h
SpaceCadetPinball/TEdgeManager.cpp
SpaceCadetPinball/TEdgeManager.h
SpaceCadetPinball/TEdgeSegment.cpp
SpaceCadetPinball/TEdgeSegment.h
SpaceCadetPinball/TFlagSpinner.cpp
SpaceCadetPinball/TFlagSpinner.h
SpaceCadetPinball/TFlipper.cpp
SpaceCadetPinball/TFlipper.h
SpaceCadetPinball/TFlipperEdge.cpp
SpaceCadetPinball/TFlipperEdge.h
SpaceCadetPinball/TGate.cpp
SpaceCadetPinball/TGate.h
SpaceCadetPinball/THole.cpp
SpaceCadetPinball/THole.h
SpaceCadetPinball/timer.cpp
SpaceCadetPinball/timer.h
SpaceCadetPinball/TKickback.cpp
SpaceCadetPinball/TKickback.h
SpaceCadetPinball/TKickout.cpp
SpaceCadetPinball/TKickout.h
SpaceCadetPinball/TLight.cpp
SpaceCadetPinball/TLight.h
SpaceCadetPinball/TLightBargraph.cpp
SpaceCadetPinball/TLightBargraph.h
SpaceCadetPinball/TLightGroup.cpp
SpaceCadetPinball/TLightGroup.h
SpaceCadetPinball/TLightRollover.cpp
SpaceCadetPinball/TLightRollover.h
SpaceCadetPinball/TLine.cpp
SpaceCadetPinball/TLine.h
SpaceCadetPinball/TOneway.cpp
SpaceCadetPinball/TOneway.h
SpaceCadetPinball/TPinballComponent.cpp
SpaceCadetPinball/TPinballComponent.h
SpaceCadetPinball/TPinballTable.cpp
SpaceCadetPinball/TPinballTable.h
SpaceCadetPinball/TPlunger.cpp
SpaceCadetPinball/TPlunger.h
SpaceCadetPinball/TPopupTarget.cpp
SpaceCadetPinball/TPopupTarget.h
SpaceCadetPinball/TRamp.cpp
SpaceCadetPinball/TRamp.h
SpaceCadetPinball/TRollover.cpp
SpaceCadetPinball/TRollover.h
SpaceCadetPinball/TSink.cpp
SpaceCadetPinball/TSink.h
SpaceCadetPinball/TSoloTarget.cpp
SpaceCadetPinball/TSoloTarget.h
SpaceCadetPinball/TSound.cpp
SpaceCadetPinball/TSound.h
SpaceCadetPinball/TTableLayer.cpp
SpaceCadetPinball/TTableLayer.h
SpaceCadetPinball/TTextBox.cpp
SpaceCadetPinball/TTextBox.h
SpaceCadetPinball/TTextBoxMessage.cpp
SpaceCadetPinball/TTextBoxMessage.h
SpaceCadetPinball/TTimer.cpp
SpaceCadetPinball/TTimer.h
SpaceCadetPinball/TTripwire.cpp
SpaceCadetPinball/TTripwire.h
SpaceCadetPinball/TWall.cpp
SpaceCadetPinball/TWall.h
SpaceCadetPinball/winmain.cpp
SpaceCadetPinball/winmain.h
SpaceCadetPinball/zdrv.cpp
SpaceCadetPinball/zdrv.h)
add_executable(SpaceCadetPinball ${SOURCE_FILES})
target_link_libraries(SpaceCadetPinball ${SDL2_LIBRARIES} ${SDL2_MIXER_LIBRARIES})

27
CMakeSettings.json Normal file
View file

@ -0,0 +1,27 @@
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": ""
},
{
"name": "x86-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x86" ],
"variables": []
}
]
}

View file

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

View file

@ -1,31 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.705
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpaceCadetPinball", "SpaceCadetPinball\SpaceCadetPinball.vcxproj", "{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.ActiveCfg = Debug|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x64.Build.0 = Debug|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.ActiveCfg = Debug|Win32
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Debug|x86.Build.0 = Debug|Win32
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.ActiveCfg = Release|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x64.Build.0 = Release|x64
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.ActiveCfg = Release|Win32
{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4B620E0B-FD42-4AEC-BC4A-261C1669A1B5}
EndGlobalSection
EndGlobal

View file

@ -3,268 +3,54 @@
#include "pb.h"
#include "pinball.h"
#include "WaveMix.h"
#include "winmain.h"
int Sound::num_channels;
HWND Sound::wavemix_window;
HANDLE Sound::pMem;
unsigned int Sound::enabled_flag;
int Sound::channel_time[8];
MIXWAVE* Sound::channel_wavePtr[8];
void (*Sound::callback_ptr)(int, MIXWAVE*, int);
HMODULE Sound::HInstance;
int Sound::Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWAVE*, int))
int Sound::Init(int voices)
{
WNDCLASSA WndClass;
char FileName[300];
int channelCount = voices;
if (voices > 8)
channelCount = 8;
num_channels = channelCount;
if (wavemix_window || pMem)
return 0;
enabled_flag = -1;
for (int i = 0; i < channelCount; ++i)
{
channel_time[i] = 0;
channel_wavePtr[i] = nullptr;
}
callback_ptr = someFuncPtr;
if (!someFuncPtr)
callback_ptr = NullCallback;
pinball::make_path_name(FileName, "wavemix.inf", 300);
FILE* wavemixIniFile = nullptr;
fopen_s(&wavemixIniFile, FileName, "r");
if (wavemixIniFile)
{
fclose(wavemixIniFile);
}
else
{
/*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;
WndClass.lpfnWndProc = SoundCallBackWndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = nullptr;
WndClass.hCursor = nullptr;
WndClass.hbrBackground = nullptr;
WndClass.lpszMenuName = nullptr;
WndClass.lpszClassName = "WaveMixSoundGuy";
RegisterClassA(&WndClass);
wavemix_window = CreateWindowExA(
0,
"WaveMixSoundGuy",
nullptr,
0x80000000,
0x80000000,
0,
0x80000000,
0,
nullptr,
nullptr,
hInstance,
nullptr);
if (!wavemix_window)
return 0;
HInstance = hInstance;
HANDLE hMixSession = WaveMix::Init();
pMem = hMixSession;
if (!hMixSession)
return 0;
WaveMix::OpenChannel(hMixSession, num_channels, 2u);
return 1;
return Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024) == -1;
}
void Sound::Enable(int channelFrom, int channelTo, int enableFlag)
{
if (pMem)
{
if (channelTo >= num_channels)
channelTo = num_channels - 1;
if (channelFrom >= 0 && channelTo < num_channels)
{
for (int index = channelFrom; index <= channelTo; ++index)
{
int channelFlag = 1 << index;
if (enableFlag)
{
enabled_flag |= channelFlag;
}
else
{
enabled_flag &= ~channelFlag;
Flush(index, index);
}
}
}
}
}
void Sound::Idle()
{
if (pMem)
WaveMix::Pump();
enabled_flag = enableFlag;
}
void Sound::Activate()
{
if (pMem)
WaveMix::Activate(pMem, true);
Mix_Resume(-1);
}
void Sound::Deactivate()
{
if (pMem)
WaveMix::Activate(pMem, false);
Mix_Pause(-1);
}
void Sound::Close()
{
if (wavemix_window)
{
DestroyWindow(wavemix_window);
wavemix_window = nullptr;
}
if (pMem)
{
WaveMix::CloseChannel(pMem, 0, 1);
WaveMix::CloseSession(pMem);
pMem = nullptr;
}
Mix_Quit();
}
void Sound::PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops)
void Sound::PlaySound(Mix_Chunk* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops)
{
MIXPLAYPARAMS mixParams{};
if (!pMem)
return;
if (maxChannel >= num_channels)
maxChannel = num_channels - 1;
if (!wavePtr || minChannel < 0 || maxChannel >= num_channels)
return;
if ((dwFlags & 0x8000) != 0 && num_channels > 0)
{
int index2 = 0;
bool ok = false;
while (channel_wavePtr[index2] != wavePtr)
{
if (++index2 >= num_channels)
{
ok = true;
break;
}
}
if (!ok)
return;
}
int playChannel = minChannel;
if (minChannel < maxChannel)
{
int curChannel = minChannel;
do
{
++curChannel;
if ((1 << curChannel) & enabled_flag &&
channel_time[curChannel] < channel_time[playChannel])
{
playChannel = curChannel;
}
}
while (curChannel < maxChannel);
}
if ((1 << playChannel) & enabled_flag)
{
mixParams.hMixSession = pMem;
mixParams.hWndNotify = wavemix_window;
mixParams.dwFlags = dwFlags;
mixParams.wSize = 28;
mixParams.wLoops = loops;
mixParams.iChannel = playChannel;
mixParams.lpMixWave = wavePtr;
callback_ptr(1, wavePtr, playChannel);
channel_time[playChannel] = timeGetTime();
channel_wavePtr[playChannel] = wavePtr;
WaveMix::Play(&mixParams);
}
if (enabled_flag)
Mix_PlayChannel(-1, wavePtr, loops);
}
MIXWAVE* Sound::LoadWaveFile(LPCSTR lpName)
Mix_Chunk* Sound::LoadWaveFile(LPCSTR lpName)
{
return pMem ? WaveMix::OpenWave(pMem, lpName, HInstance, 1u) : nullptr;
return Mix_LoadWAV(lpName);
}
void Sound::FreeSound(MIXWAVE* wave)
void Sound::FreeSound(Mix_Chunk* wave)
{
if (wave && pMem)
WaveMix::FreeWave(pMem, wave);
}
void Sound::Flush(int channelFrom, int channelTo)
{
if (pMem)
{
if (channelTo >= num_channels)
channelTo = num_channels - 1;
if (channelFrom >= 0 && channelTo < num_channels)
{
for (auto index = channelFrom; index <= channelTo; index++)
{
WaveMix::FlushChannel(pMem, index, 0);
channel_time[index] = 0;
channel_wavePtr[index] = nullptr;
}
}
}
}
void Sound::NullCallback(int a1, MIXWAVE* a2, int a3)
{
}
LRESULT Sound::SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg != MM_WOM_DONE)
return DefWindowProcA(hWnd, Msg, wParam, lParam);
auto wavePtr = reinterpret_cast<MIXWAVE*>(lParam);
int channel = -1;
for (auto index = 0; index < num_channels; ++index)
{
if (channel_wavePtr[index] == wavePtr &&
(channel < 0 || channel_time[index] < channel_time[channel]))
{
channel = index;
}
}
if (channel >= 0)
{
channel_time[channel] = 0;
channel_wavePtr[channel] = nullptr;
}
callback_ptr(2, wavePtr, channel);
return 0;
if (wave)
Mix_FreeChunk(wave);
}

View file

@ -1,28 +1,18 @@
#pragma once
#include "WaveMix.h"
class Sound
{
public:
static int Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWAVE*, int));
static int Init(int voices);
static void Enable(int channelFrom, int channelTo, int enableFlag);
static void Idle();
static void Activate();
static void Deactivate();
static void Close();
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);
static void NullCallback(int a1, MIXWAVE* a2, int a3);
static LRESULT __stdcall SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
static void PlaySound(Mix_Chunk* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops);
static Mix_Chunk* LoadWaveFile(LPCSTR lpName);
static void FreeSound(Mix_Chunk* wave);
private:
static int num_channels;
static HWND wavemix_window;
static HANDLE pMem;
static unsigned int enabled_flag;
static int channel_time[8];
static MIXWAVE* channel_wavePtr[8];
static void (* callback_ptr)(int, MIXWAVE*, int);
static HMODULE HInstance;
};

View file

@ -25,7 +25,7 @@ int main()
}
std::cout << "Hello World!\n";
gdrv::init(nullptr, nullptr);
gdrv::init(nullptr,0,0);
auto dib = gdrv::DibCreate(8, 1, 1);
gdrv::DibSetUsage(dib, nullptr, 1);
@ -39,7 +39,7 @@ int main()
auto xx = sizeof(datFileHeader);
lstrcpyA(winmain::DatFileName, "PINBALL.DAT");
pb::init();
pb::init(nullptr);
auto datFile = pb::record_table;
assert(partman::field_size_nth(datFile, 0, datFieldTypes::String, 0) == 43);

View file

@ -1,316 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{F7B78CC7-6984-4F79-9486-ABCF87DF9F06}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>SpaceCadetPinball</RootNamespace>
<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>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<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>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<BufferSecurityCheck>true</BufferSecurityCheck>
<PreprocessToFile>false</PreprocessToFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Comctl32.lib;Winmm.lib;Htmlhelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="control.h" />
<ClInclude Include="fullscrn.h" />
<ClInclude Include="gdrv.h" />
<ClInclude Include="high_score.h" />
<ClInclude Include="loader.h" />
<ClInclude Include="maths.h" />
<ClInclude Include="memory.h" />
<ClInclude Include="midi.h" />
<ClInclude Include="nudge.h" />
<ClInclude Include="objlist_class.h" />
<ClInclude Include="options.h" />
<ClInclude Include="partman.h" />
<ClInclude Include="pb.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="pinball.h" />
<ClInclude Include="proj.h" />
<ClInclude Include="render.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="score.h" />
<ClInclude Include="Sound.h" />
<ClInclude Include="splash.h" />
<ClInclude Include="TBall.h" />
<ClInclude Include="TBlocker.h" />
<ClInclude Include="TBumper.h" />
<ClInclude Include="TCircle.h" />
<ClInclude Include="TCollisionComponent.h" />
<ClInclude Include="TComponentGroup.h" />
<ClInclude Include="TDemo.h" />
<ClInclude Include="TDrain.h" />
<ClInclude Include="TEdgeBox.h" />
<ClInclude Include="TEdgeManager.h" />
<ClInclude Include="TEdgeSegment.h" />
<ClInclude Include="TFlagSpinner.h" />
<ClInclude Include="TFlipper.h" />
<ClInclude Include="TFlipperEdge.h" />
<ClInclude Include="TGate.h" />
<ClInclude Include="THole.h" />
<ClInclude Include="timer.h" />
<ClInclude Include="TKickback.h" />
<ClInclude Include="TKickout.h" />
<ClInclude Include="TLight.h" />
<ClInclude Include="TLightBargraph.h" />
<ClInclude Include="TLightGroup.h" />
<ClInclude Include="TLightRollover.h" />
<ClInclude Include="TLine.h" />
<ClInclude Include="TOneway.h" />
<ClInclude Include="TPinballComponent.h" />
<ClInclude Include="TPinballTable.h" />
<ClInclude Include="TPlunger.h" />
<ClInclude Include="TPopupTarget.h" />
<ClInclude Include="TRamp.h" />
<ClInclude Include="TRollover.h" />
<ClInclude Include="TSink.h" />
<ClInclude Include="TSoloTarget.h" />
<ClInclude Include="TSound.h" />
<ClInclude Include="TTableLayer.h" />
<ClInclude Include="TTextBox.h" />
<ClInclude Include="TTextBoxMessage.h" />
<ClInclude Include="TTimer.h" />
<ClInclude Include="TTripwire.h" />
<ClInclude Include="TWall.h" />
<ClInclude Include="WaveMix.h" />
<ClInclude Include="winmain.h" />
<ClInclude Include="zdrv.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="control.cpp" />
<ClCompile Include="fullscrn.cpp" />
<ClCompile Include="gdrv.cpp" />
<ClCompile Include="high_score.cpp" />
<ClCompile Include="loader.cpp" />
<ClCompile Include="maths.cpp" />
<ClCompile Include="memory.cpp" />
<ClCompile Include="midi.cpp" />
<ClCompile Include="nudge.cpp" />
<ClCompile Include="options.cpp" />
<ClCompile Include="partman.cpp" />
<ClCompile Include="pb.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="pinball.cpp" />
<ClCompile Include="proj.cpp" />
<ClCompile Include="render.cpp" />
<ClCompile Include="score.cpp" />
<ClCompile Include="Sound.cpp" />
<ClCompile Include="SpaceCadetPinball.cpp" />
<ClCompile Include="splash.cpp" />
<ClCompile Include="TBall.cpp" />
<ClCompile Include="TBlocker.cpp" />
<ClCompile Include="TBumper.cpp" />
<ClCompile Include="TCircle.cpp" />
<ClCompile Include="TCollisionComponent.cpp" />
<ClCompile Include="TComponentGroup.cpp" />
<ClCompile Include="TDemo.cpp" />
<ClCompile Include="TDrain.cpp" />
<ClCompile Include="TEdgeBox.cpp" />
<ClCompile Include="TEdgeManager.cpp" />
<ClCompile Include="TEdgeSegment.cpp" />
<ClCompile Include="TFlagSpinner.cpp" />
<ClCompile Include="TFlipper.cpp" />
<ClCompile Include="TFlipperEdge.cpp" />
<ClCompile Include="TGate.cpp" />
<ClCompile Include="THole.cpp" />
<ClCompile Include="timer.cpp" />
<ClCompile Include="TKickback.cpp" />
<ClCompile Include="TKickout.cpp" />
<ClCompile Include="TLight.cpp" />
<ClCompile Include="TLightBargraph.cpp" />
<ClCompile Include="TLightGroup.cpp" />
<ClCompile Include="TLightRollover.cpp" />
<ClCompile Include="TLine.cpp" />
<ClCompile Include="TOneway.cpp" />
<ClCompile Include="TPinballComponent.cpp" />
<ClCompile Include="TPinballTable.cpp" />
<ClCompile Include="TPlunger.cpp" />
<ClCompile Include="TPopupTarget.cpp" />
<ClCompile Include="TRamp.cpp" />
<ClCompile Include="TRollover.cpp" />
<ClCompile Include="TSink.cpp" />
<ClCompile Include="TSoloTarget.cpp" />
<ClCompile Include="TSound.cpp" />
<ClCompile Include="TTableLayer.cpp" />
<ClCompile Include="TTextBox.cpp" />
<ClCompile Include="TTextBoxMessage.cpp" />
<ClCompile Include="TTimer.cpp" />
<ClCompile Include="TTripwire.cpp" />
<ClCompile Include="TWall.cpp" />
<ClCompile Include="WaveMix.cpp" />
<ClCompile Include="winmain.cpp" />
<ClCompile Include="zdrv.cpp" />
</ItemGroup>
<ItemGroup>
<Natvis Include="NatvisFile.natvis" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SpaceCadetPinball.rc" />
</ItemGroup>
<ItemGroup>
<None Include="PB_MSGFT.bin" />
</ItemGroup>
<ItemGroup>
<Image Include="Icon_1.ico" />
<Image Include="splash_bitmap.bmp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -1,441 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Header Files\TEdgeSegment">
<UniqueIdentifier>{0aa40751-a44a-400e-8809-ee817161e8e0}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\TEdgeSegment">
<UniqueIdentifier>{d70e7fca-2294-41a4-9cf8-78052bdb9aa4}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\TCollisionComponent">
<UniqueIdentifier>{01aed326-d2ec-457a-b99f-08ef32ed97fa}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\TCollisionComponent">
<UniqueIdentifier>{7ed2796a-da4b-4edd-8783-53e45d8d1c88}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\TPinballComponent">
<UniqueIdentifier>{9ee086c2-1a95-48fb-92d8-4b7e7f6682ff}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\TPinballComponent">
<UniqueIdentifier>{33813da8-81ac-449c-b19a-9756272519b9}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="objlist_class.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="partman.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="loader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pinball.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="score.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TPinballComponent.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TBall.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TComponentGroup.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TLight.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TLightBargraph.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TLightGroup.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TSound.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TTextBox.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TTimer.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="memory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="winmain.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="options.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Sound.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pb.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="render.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="fullscrn.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="gdrv.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="maths.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="zdrv.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TEdgeSegment.h">
<Filter>Header Files\TEdgeSegment</Filter>
</ClInclude>
<ClInclude Include="TCollisionComponent.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TCircle.h">
<Filter>Header Files\TEdgeSegment</Filter>
</ClInclude>
<ClInclude Include="TLine.h">
<Filter>Header Files\TEdgeSegment</Filter>
</ClInclude>
<ClInclude Include="TWall.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TBumper.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TBlocker.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TDemo.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TDrain.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TFlagSpinner.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TFlipper.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TGate.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="THole.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TKickback.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TKickout.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TOneway.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TPlunger.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TPopupTarget.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TRamp.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TRollover.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TSink.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TSoloTarget.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TTableLayer.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TPinballTable.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TTripwire.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TLightRollover.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="proj.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="timer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="midi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="nudge.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TTextBoxMessage.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="high_score.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="control.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TEdgeManager.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TEdgeBox.h">
<Filter>Header Files\TPinballComponent</Filter>
</ClInclude>
<ClInclude Include="TFlipperEdge.h">
<Filter>Header Files\TEdgeSegment</Filter>
</ClInclude>
<ClInclude Include="WaveMix.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="splash.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SpaceCadetPinball.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="partman.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="loader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pinball.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="score.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TPinballComponent.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TPinballTable.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TBall.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TComponentGroup.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TLight.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TLightBargraph.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TLightGroup.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TSound.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TTextBox.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TTimer.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="memory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="winmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="options.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Sound.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pb.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="render.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="fullscrn.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="gdrv.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="maths.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="zdrv.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TEdgeSegment.cpp">
<Filter>Source Files\TEdgeSegment</Filter>
</ClCompile>
<ClCompile Include="TCollisionComponent.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TCircle.cpp">
<Filter>Source Files\TEdgeSegment</Filter>
</ClCompile>
<ClCompile Include="TLine.cpp">
<Filter>Source Files\TEdgeSegment</Filter>
</ClCompile>
<ClCompile Include="TWall.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TBlocker.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TBumper.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TDemo.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TDrain.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TFlagSpinner.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TFlipper.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TGate.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="THole.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TKickback.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TKickout.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TOneway.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TPlunger.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TPopupTarget.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TRamp.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TRollover.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TSink.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TSoloTarget.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TTableLayer.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TTripwire.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TLightRollover.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="proj.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="timer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="midi.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="nudge.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TTextBoxMessage.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="high_score.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="control.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TEdgeManager.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TEdgeBox.cpp">
<Filter>Source Files\TPinballComponent</Filter>
</ClCompile>
<ClCompile Include="TFlipperEdge.cpp">
<Filter>Source Files\TEdgeSegment</Filter>
</ClCompile>
<ClCompile Include="WaveMix.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="splash.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Natvis Include="NatvisFile.natvis" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SpaceCadetPinball.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="PB_MSGFT.bin">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Image Include="Icon_1.ico">
<Filter>Resource Files</Filter>
</Image>
<Image Include="splash_bitmap.bmp">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
</Project>

View file

@ -443,25 +443,20 @@ int TPinballTable::Message(int code, float value)
}
BallCount = MaxBallCount;
Sound::Idle();
ChangeBallCount(BallCount);
score::set(ScorePlayerNumber1, CurrentPlayer + 1);
score::update(ScorePlayerNumber1);
Sound::Idle();
for (auto scoreIndex = 4 - PlayerCount; scoreIndex > 0; scoreIndex--)
{
score::set(PlayerScores[scoreIndex].ScoreStruct, -1);
}
Sound::Idle();
ScoreSpecial3Flag = 0;
ScoreSpecial2Flag = 0;
UnknownP71 = 0;
pinball::InfoTextBox->Clear();
Sound::Idle();
pinball::MissTextBox->Clear();
Sound::Idle();
LightGroup->Message(28, 0.2f);
auto time = loader::play_sound(SoundIndex1);
LightShowTimer = timer::set(time, this, LightShow_timeout);

File diff suppressed because it is too large Load diff

View file

@ -1,244 +0,0 @@
#pragma once
/* flag values for play params */
#define WMIX_QUEUEWAVE 0x00
#define WMIX_CLEARQUEUE 0x01
#define WMIX_USELRUCHANNEL 0x02
#define WMIX_HIPRIORITY 0x04
#define WMIX_WAIT 0x08
#define WMIX_CustomVolume 0x10
#define MAXCHANNELS 16
#define MAXQUEUEDWAVES 100
struct GLOBALS;
struct volume_struct
{
uint16_t L;
uint16_t R;
};
struct MIXWAVE
{
PCMWAVEFORMAT pcm;
WAVEHDR wh;
char szWaveFilename[16];
short wMagic;
};
struct MIXPLAYPARAMS
{
WORD wSize;
HANDLE hMixSession;
int iChannel;
MIXWAVE* lpMixWave;
HWND hWndNotify;
DWORD dwFlags;
WORD wLoops;
volume_struct Volume;
};
struct CHANNELNODE
{
CHANNELNODE* next;
MIXPLAYPARAMS PlayParams;
MIXWAVE* lpMixWave;
DWORD dwNumSamples;
DWORD dwStartPos;
DWORD dwEndPos;
unsigned char* lpPos;
unsigned char* lpEnd;
volume_struct Volume;
};
struct MIXCONFIG
{
WORD wSize;
DWORD dwFlags;
WORD wChannels;
WORD wSamplingRate;
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;
};
struct XWAVEHDR
{
WAVEHDR wh;
BOOL fAvailable;
DWORD dwWavePos;
GLOBALS* g;
struct XWAVEHDR* QNext;
};
struct PLAYQUEUE
{
XWAVEHDR* first;
XWAVEHDR* last;
};
struct GLOBALS
{
WORD wMagic1;
int16_t unknown0;
HWND hWndApp;
int unknown2;
HWAVEOUT hWaveOut;
int fActive;
int SettingsDialogActiveFlag;
unsigned int wDeviceID;
char szDevicePName[96];
WAVEOUTCAPSA WaveoutCaps;
volume_struct DefaultVolume;
volume_struct ChannelVolume[MAXCHANNELS];
CHANNELNODE* aChannel[MAXCHANNELS];
int iChannels;
DWORD MRUChannel[MAXCHANNELS];
DWORD dwMRU;
PCMWAVEFORMAT PCM;
DWORD dwWaveBlockLen;
int WaveBlockCount;
int PauseBlocks;
XWAVEHDR** WaveBlockArray;
DWORD dwCurrentSample;
DWORD dwBaseTime;
int fGoodGetPos;
DWORD dwWaveOutPos;
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_t wMagic2;
int16_t unknown112;
};
struct dialog_template
{
DLGTEMPLATE Dialog;
WORD menu;
WORD windowClass;
WCHAR Header[1];
};
struct dialog_item_template
{
DLGITEMTEMPLATE Item;
WORD sysClass;
WORD idClass;
WCHAR Header[1];
};
class WaveMix
{
public:
static HANDLE Init();
static HANDLE ConfigureInit(MIXCONFIG* lpConfig);
static int CloseSession(HANDLE hMixSession);
static int OpenChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags);
static int CloseChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags);
static int FlushChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags);
static MIXWAVE* OpenWave(HANDLE hMixSession, LPCSTR szWaveFilename, HINSTANCE hInst, unsigned int dwFlags);
static int FreeWave(HANDLE hMixSession, MIXWAVE* lpMixWave);
static int Activate(HANDLE hMixSession, bool fActivate);
static void Pump();
static int Play(MIXPLAYPARAMS* lpMixPlayParams);
private:
static GLOBALS* SessionToGlobalDataPtr(HANDLE hMixSession);
static int Startup(HMODULE hModule);
static int SetIniFileName(HMODULE hModule);
static void InitChannelNodes();
static void InitVolumeTable();
static void ShowWaveOutDevices();
static int RemoveInvalidIniNameCharacters(char* lpString);
static int ReadConfigSettings(MIXCONFIG* lpConfig);
static int ReadRegistryForAppSpecificConfigs(MIXCONFIG* lpConfig);
static int ReadRegistryInt(HKEY hKey, LPCSTR lpSubKey, int defaultValue);
static int DefaultGoodWavePos(unsigned int uDeviceID);
static int DefaultPauseBlocks(int waveBlocks);
static int Configure(GLOBALS* hMixSession, HWND hWndParent, MIXCONFIG* lpConfig, int* flag1Ptr, int saveConfigFlag);
static int GetConfig(HANDLE hMixSession, MIXCONFIG* lpConfig);
static unsigned MyWaveOutGetPosition(HWAVEOUT hWaveOut, int fGoodGetPos);
static void FreeChannelNode(CHANNELNODE* channel);
static int ResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel);
static XWAVEHDR* RemoveFromPlayingQueue(XWAVEHDR* lpXWH);
static void DestroyPlayQueue();
static void SwapWaveBlocks();
static XWAVEHDR* GetWaveBlock();
static int MixerPlay(XWAVEHDR* lpXWH, int fWriteBlocks);
static XWAVEHDR* AddToPlayingQueue(XWAVEHDR* lpXWH);
static void MyWaveOutReset(HWAVEOUT hWaveOut);
static void SetWaveOutPosition(unsigned int newPosition);
static DWORD SubFactor(DWORD a1, DWORD a2);
static DWORD AddFactor(DWORD a1, DWORD a2);
static dialog_template* MakeSettingsDlgTemplate();
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(size_t* totalSize, dialog_template* dlgTemplate, int16_t idClass,
unsigned style,
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, 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);
static int NoResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel);
static void SaveConfigSettings(unsigned dwFlags);
static void ShowCurrentSettings();
static unsigned int GetWaveDevice();
static void FreeWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks);
static int AllocWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks);
static void ReleaseWaveDevice(GLOBALS* globals);
static HPSTR WaveFormatConvert(PCMWAVEFORMAT* lpOutWF, PCMWAVEFORMAT* lpInWF, HPSTR lpInData, DWORD* dwDataSize);
static HPSTR BitsPerSampleAlign(HPSTR lpInData, WORD nInBPS, WORD nOutBPS, DWORD* dwDataSize);
static HPSTR ChannelAlign(HPSTR lpInData, WORD nInChannels, WORD nOutChannels, WORD nBytesPerSample,
DWORD* dwDataSize);
static HPSTR SamplesPerSecAlign(HPSTR lpInData, DWORD nInSamplesPerSec, DWORD nOutSamplesPerSec,
WORD nBytesPerSample, WORD nChannels, DWORD* dwDataSize);
static void AvgSample(HPSTR lpOutData, HPSTR lpInData, unsigned nSkip, int nBytesPerSample, int nChannels);
static void RepSample(HPSTR lpOutData, HPSTR lpInData, unsigned nRep, int nBytesPerSample, int nChannels);
static bool IsValidLPMIXWAVE(MIXWAVE* lpMixWave);
static void FreePlayedBlocks();
static int HasCurrentOutputFormat(MIXWAVE* lpMixWave);
static CHANNELNODE* GetChannelNode();
static void ResetWavePosIfNoChannelData();
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);
static int initialized_flag;
static char FileName[276];
static CHANNELNODE channel_nodes[MAXQUEUEDWAVES];
static CHANNELNODE* free_channel_nodes;
static unsigned char volume_table[11][256];
static int debug_flag;
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;
static int ShowDebugDialogs;
static char string_buffer[256];
static PLAYQUEUE play_queue;
static CHANNELNODE* play_channel_array[MAXCHANNELS];
static XWAVEHDR* block_array1[10];
static XWAVEHDR* block_array2[10];
static unsigned char* play_data[MAXCHANNELS];
static volume_struct play_volume[MAXCHANNELS];
static int play_counter;
};

View file

@ -639,9 +639,9 @@ void control::pbctrl_bdoor_controller(int key)
if (!control_lite198_tag.Component->MessageField)
{
if (key <= 'M')
if (key <= 'm')
{
if (key == 'M')
if (key == 'm')
{
v2 = pbctrl_state;
if (pbctrl_state == 4 || pbctrl_state == 61 || pbctrl_state == 81 || pbctrl_state == 101)
@ -650,9 +650,9 @@ void control::pbctrl_bdoor_controller(int key)
}
else
{
if (key <= 'D')
if (key <= 'd')
{
if (key != 'D')
if (key != 'd')
{
if (key == ' ')
{
@ -665,11 +665,11 @@ void control::pbctrl_bdoor_controller(int key)
}
if (key != '1')
{
if (key != 'A')
if (key != 'a')
{
if (key != 'B')
if (key != 'b')
{
if (key == 'C')
if (key == 'c')
{
if (!pbctrl_state)
{
@ -704,17 +704,17 @@ void control::pbctrl_bdoor_controller(int key)
++pbctrl_state;
return;
}
if (key != 'E')
if (key != 'e')
{
switch (key)
{
case 'G':
case 'g':
v1 = pbctrl_state != 0 ? 0 : 101;
break;
case 'H':
case 'h':
v1 = pbctrl_state != 0 ? 0 : 21;
break;
case 'I':
case 'i':
v2 = pbctrl_state;
if (pbctrl_state == 1 || pbctrl_state == 10)
goto LABEL_87;
@ -732,9 +732,9 @@ void control::pbctrl_bdoor_controller(int key)
}
goto LABEL_86;
}
if (key <= 'S')
if (key <= 's')
{
if (key == 'S')
if (key == 's')
{
v2 = pbctrl_state;
if (pbctrl_state == 12 || pbctrl_state == 29)
@ -743,13 +743,13 @@ void control::pbctrl_bdoor_controller(int key)
}
else
{
if (key != 'N')
if (key != 'n')
{
if (key != 'O')
if (key != 'o')
{
if (key != 'Q')
if (key != 'q')
{
if (key == 'R')
if (key == 'r')
{
if (!pbctrl_state)
{
@ -789,7 +789,7 @@ void control::pbctrl_bdoor_controller(int key)
}
switch (key)
{
case 'T':
case 't':
v2 = pbctrl_state;
if (pbctrl_state != 30)
{
@ -800,14 +800,14 @@ void control::pbctrl_bdoor_controller(int key)
}
pb::cheat_mode = 1;
break;
case 'U':
case 'u':
if (pbctrl_state == 41)
{
pbctrl_state = 42;
return;
}
goto LABEL_77;
case 'X':
case 'x':
if (pbctrl_state == 63)
{
table_add_extra_ball(2.0);

View file

@ -66,7 +66,7 @@ void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HME
fullscrn_flag1 = 0;
window_size_changed();
assertm(ScaleX == 1 && ScaleY == 1, "Wrong default client size");
//assertm(ScaleX == 1 && ScaleY == 1, "Wrong default client size");
}
void fullscrn::shutdown()

View file

@ -7,8 +7,7 @@
#include "winmain.h"
HPALETTE gdrv::palette_handle = nullptr;
HINSTANCE gdrv::hinst;
HWND gdrv::hwnd;
SDL_Renderer* gdrv::renderer;
int gdrv::sequence_handle;
HDC gdrv::sequence_hdc;
int gdrv::use_wing = 0;
@ -16,13 +15,26 @@ int gdrv::grtext_blue = 0;
int gdrv::grtext_green = 0;
int gdrv::grtext_red = -1;
HWND hwnd = 0;
SDL_Texture* vScreenTex = nullptr;
char* pixels = nullptr;
int Width, Height;
LOGPALETTEx256 current_palette{};
int gdrv::init(HINSTANCE hInst, HWND hWnd)
int gdrv::init(SDL_Renderer* render, int width, int height)
{
LOGPALETTEx256 current_palette{};
hinst = hInst;
hwnd = hWnd;
renderer = render;
vScreenTex = SDL_CreateTexture
(
renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
width, height
);
pixels = memory::allocate(width * height * 4);
Width = width;
Height = height;
if (!palette_handle)
palette_handle = CreatePalette(&current_palette);
return 0;
@ -32,6 +44,7 @@ int gdrv::uninit()
{
if (palette_handle)
DeleteObject(palette_handle);
memory::free(pixels);
return 0;
}
@ -185,11 +198,8 @@ int gdrv::create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int si
return 0;
}
int gdrv::display_palette(PALETTEENTRY* plt)
{
LOGPALETTEx256 current_palette{};
if (palette_handle)
DeleteObject(palette_handle);
palette_handle = CreatePalette(&current_palette);
@ -212,9 +222,9 @@ int gdrv::display_palette(PALETTEENTRY* plt)
{
if (plt)
{
pltDst->peRed = pltSrc->peBlue;
pltDst->peRed = pltSrc->peRed;
pltDst->peGreen = pltSrc->peGreen;
pltDst->peBlue = pltSrc->peRed;
pltDst->peBlue = pltSrc->peBlue;
}
pltDst->peFlags = 4;
pltSrc++;
@ -426,7 +436,7 @@ int gdrv::StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int
{
/*Scaled partial updates may leave 1px border artifacts around update area.
* Pad update area to compensate.*/
const int pad = 1, padX2 = pad * 2;
/*const int pad = 1, padX2 = pad * 2;
if (fullscrn::ScaleX > 1 && xSrc > pad && xSrc + pad < bmp->Width)
{
xSrc -= pad;
@ -443,7 +453,7 @@ int gdrv::StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int
DestHeight += padX2;
}
return StretchDIBits(
StretchDIBits(
hdc,
static_cast<int>(round(xDest * fullscrn::ScaleX + fullscrn::OffsetX)),
static_cast<int>(round(yDest * fullscrn::ScaleY + fullscrn::OffsetY)),
@ -456,5 +466,60 @@ int gdrv::StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int
bmp->BmpBufPtr1,
bmp->Dib,
iUsage,
rop);
rop);*/
//auto srcPtr = reinterpret_cast<uint8_t*>(bmp->BmpBufPtr1);
//auto dstPtr = reinterpret_cast<uint32_t*>(pixels);
//for (int y = Height; y > 0; --y)
//{
// for (int x = Width; x > 0; --x)
// *dstPtr++ = *(uint32_t*)&current_palette.palPalEntry[*srcPtr++];
// //srcPtr += srcBmp->Stride - width;
// //dstPtr += dstBmp->Stride - width;
//}
// Clamp out of bounds rectangles
ySrc = max(0, min(ySrc, bmp->Height));
xSrc = max(0, min(xSrc, bmp->Height));
if (ySrc + SrcHeight > Height)
SrcHeight = Height - ySrc;
if (xSrc + SrcWidth > Width)
SrcWidth = Width - xSrc;
auto srcPtr = reinterpret_cast<uint8_t*>(&bmp->BmpBufPtr1[bmp->Stride * (ySrc)+xSrc]);
auto dstPtr = &reinterpret_cast<uint32_t*>(pixels)[Width * (ySrc)+xSrc];
for (int y = SrcHeight; y > 0; --y)
{
for (int x = SrcWidth; x > 0; --x)
{
if ((char*)dstPtr >= (pixels + Width * Height * 4) || (char*)srcPtr >= (bmp->BmpBufPtr1 + bmp->Stride * bmp->Width))
{
dstPtr = dstPtr;
}
*dstPtr++ = *(uint32_t*)&current_palette.palPalEntry[*srcPtr++];
}
srcPtr += bmp->Stride - SrcWidth;
dstPtr += Width - SrcWidth;
}
unsigned char* lockedPixels = nullptr;
int pitch = 0;
SDL_LockTexture
(
vScreenTex,
nullptr,
reinterpret_cast<void**>(&lockedPixels),
&pitch
);
std::memcpy(lockedPixels, pixels, Width * Height * 4);
SDL_UnlockTexture(vScreenTex);
SDL_Rect dstRect
{ xDest,yDest,Width,Height };
SDL_RenderCopyEx(renderer, vScreenTex, nullptr, nullptr, 0, 0, SDL_FLIP_VERTICAL);
return 0;
}

View file

@ -42,7 +42,7 @@ public:
static HDC sequence_hdc;
static int use_wing;
static int init(HINSTANCE hInst, HWND hWnd);
static int init(SDL_Renderer* renderer, int width, int height);
static int uninit();
static void get_focus();
static BITMAPINFO* DibCreate(int16_t bpp, int width, int height);
@ -68,8 +68,7 @@ public:
private:
/*COLORONCOLOR or HALFTONE*/
static const int stretchMode = COLORONCOLOR;
static HWND hwnd;
static HINSTANCE hinst;
static SDL_Renderer* renderer;
static int grtext_blue;
static int grtext_green;
static int grtext_red;

View file

@ -177,9 +177,9 @@ void high_score::show_and_set_high_score_dialog(high_score_struct* table, int sc
dlg_hst = table;
dlg_enter_name = 1;
default_name = defaultName;
while (DialogBoxParamA(winmain::hinst, "dlg_highscores", winmain::hwnd_frame, HighScore, 0))
/*while (DialogBoxParamA(winmain::hinst, "dlg_highscores", winmain::hwnd_frame, HighScore, 0))
{
}
}*/
}
INT_PTR high_score::HighScore(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

View file

@ -320,7 +320,7 @@ float loader::play_sound(int soundIndex)
{
if (soundIndex <= 0)
return 0.0;
Sound::PlaySound(sound_list[soundIndex].WavePtr, 0, 7, WMIX_HIPRIORITY | WMIX_CLEARQUEUE, 0);
Sound::PlaySound(sound_list[soundIndex].WavePtr, 0, 7, 0, 0);
return sound_list[soundIndex].Duration;
}

View file

@ -1,7 +1,6 @@
#pragma once
#include "gdrv.h"
#include "maths.h"
#include "WaveMix.h"
#include "zdrv.h"
@ -15,7 +14,7 @@ struct errorMsg
struct soundListStruct
{
MIXWAVE* WavePtr;
Mix_Chunk* WavePtr;
int GroupIndex;
int Loaded;
float Duration;

View file

@ -5,10 +5,7 @@
#include "pb.h"
#include "pinball.h"
tagMCI_OPEN_PARMSA midi::mci_open_info;
char midi::midi_file_name[28];
HWND midi::midi_notify_hwnd;
int midi::midi_seq1_open, midi::midi_seq1_playing;
Mix_Music* midi::currentMidi;
MCIERROR midi::play_pb_theme(int flag)
{
@ -17,17 +14,11 @@ MCIERROR midi::play_pb_theme(int flag)
return play_ft(track1);
}
MCI_PLAY_PARMS playParams;
MCIERROR result = 0;
music_stop();
playParams.dwFrom = 0;
playParams.dwCallback = (DWORD_PTR)midi_notify_hwnd;
if (!flag && midi_seq1_open)
{
result = mciSendCommandA(mci_open_info.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, (DWORD_PTR)&playParams);
midi_seq1_playing = result == 0;
}
if (currentMidi)
result = Mix_PlayMusic(currentMidi, -1);
return result;
}
@ -37,11 +28,8 @@ MCIERROR midi::music_stop()
{
return stop_ft();
}
MCIERROR result = 0;
if (midi_seq1_playing)
result = mciSendCommandA(mci_open_info.wDeviceID, MCI_STOP, 0, 0);
return result;
return Mix_HaltMusic();
}
int midi::music_init(HWND hwnd)
@ -50,15 +38,9 @@ int midi::music_init(HWND hwnd)
{
return music_init_ft(hwnd);
}
mci_open_info.wDeviceID = 0;
midi_notify_hwnd = hwnd;
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;
currentMidi = Mix_LoadMUS(pinball::get_rc_string(156, 0));
return currentMidi != nullptr;
}
MCIERROR midi::restart_midi_seq(LPARAM param)
@ -68,13 +50,11 @@ MCIERROR midi::restart_midi_seq(LPARAM param)
return play_ft(active_track);
}
MCI_PLAY_PARMS playParams;
MCIERROR result = 0;
music_stop();
if (currentMidi)
result = Mix_PlayMusic(currentMidi, -1);
playParams.dwFrom = 0;
playParams.dwCallback = (DWORD_PTR)midi_notify_hwnd;
if (midi_seq1_playing)
result = mciSendCommandA(mci_open_info.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, (DWORD_PTR)&playParams);
return result;
}
@ -86,9 +66,7 @@ void midi::music_shutdown()
return;
}
if (midi_seq1_open)
mciSendCommandA(mci_open_info.wDeviceID, MCI_CLOSE, 0, 0);
midi_seq1_open = 0;
Mix_FreeMusic(currentMidi);
}
@ -98,7 +76,6 @@ 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);
@ -423,7 +400,7 @@ int midi::stream_open(midi_struct* midi, char flags)
if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I'))
return 6;
UINT puDeviceID = -1;
/*UINT puDeviceID = -1;
auto steamOpenedFg = !midi->StreamHandle;
MIDIPROPTIMEDIV propdata{8, midi->DwTimeFormat};
if (steamOpenedFg &&
@ -463,15 +440,15 @@ int midi::stream_open(midi_struct* midi, char flags)
{
if (midi->StreamHandle)
stream_close(midi);
}
}*/
return returnCode;
}
int midi::stream_close(midi_struct* midi)
{
int returnCode;
int returnCode = 0;
if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I'))
/*if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I'))
return 6;
if (!midi->StreamHandle)
return 7;
@ -493,7 +470,7 @@ int midi::stream_close(midi_struct* midi)
returnCode = 0;
midi->StreamHandle = nullptr;
midi->SomeFlag2 = 0;
}
}*/
return returnCode;
}
@ -503,8 +480,8 @@ void midi::midi_callback(HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PT
{
auto mhdr = reinterpret_cast<LPMIDIHDR>(dwParam1);
auto midi = reinterpret_cast<midi_struct*>(mhdr->dwUser);
if ((midi->SomeFlag2 & 2) == 0 || (midi->SomeFlag2 & 1) != 0 || midiStreamOut(
/*if ((midi->SomeFlag2 & 2) == 0 || (midi->SomeFlag2 & 1) != 0 || midiStreamOut(
midi->StreamHandle, mhdr, sizeof(MIDIHDR)))
--midi->PreparedBlocksCount;
--midi->PreparedBlocksCount;*/
}
}

View file

@ -57,11 +57,8 @@ public:
static int music_init(HWND hwnd);
static MCIERROR restart_midi_seq(LPARAM param);
static void music_shutdown();
private:
static tagMCI_OPEN_PARMSA mci_open_info;
static char midi_file_name[28];
static HWND midi_notify_hwnd;
static int midi_seq1_open, midi_seq1_playing;
private:
static Mix_Music* currentMidi;
static objlist_class<midi_struct>* TrackList;
static midi_struct *track1, *track2, *track3, *active_track, *active_track2;

View file

@ -76,18 +76,18 @@ void options::init(HMENU menuHandle)
Options.FullScreen = 0;
Options.Average = 5;
Options.PriorityAdj = 2;
Options.LeftFlipperKeyDft = 90;
Options.RightFlipperKeyDft = 191;
Options.PlungerKeyDft = 32;
Options.LeftTableBumpKeyDft = 88;
Options.RightTableBumpKeyDft = 190;
Options.BottomTableBumpKeyDft = 38;
pinball::get_rc_int(159, &Options.LeftFlipperKeyDft);
Options.LeftFlipperKeyDft = SDLK_z;
Options.RightFlipperKeyDft = SDLK_SLASH;
Options.PlungerKeyDft = SDLK_SPACE;
Options.LeftTableBumpKeyDft = SDLK_x;
Options.RightTableBumpKeyDft = SDLK_GREATER;
Options.BottomTableBumpKeyDft = SDLK_UP;
/*pinball::get_rc_int(159, &Options.LeftFlipperKeyDft);
pinball::get_rc_int(160, &Options.RightFlipperKeyDft);
pinball::get_rc_int(161, &Options.PlungerKeyDft);
pinball::get_rc_int(162, &Options.LeftTableBumpKeyDft);
pinball::get_rc_int(163, &Options.RightTableBumpKeyDft);
pinball::get_rc_int(164, &Options.BottomTableBumpKeyDft);
pinball::get_rc_int(164, &Options.BottomTableBumpKeyDft);*/
Options.LeftFlipperKey = Options.LeftFlipperKeyDft;
Options.RightFlipperKey = Options.RightFlipperKeyDft;
Options.PlungerKey = Options.PlungerKeyDft;
@ -95,7 +95,7 @@ void options::init(HMENU menuHandle)
Options.RightTableBumpKey = Options.RightTableBumpKeyDft;
Options.Players = 1;
Options.BottomTableBumpKey = Options.BottomTableBumpKeyDft;
Options.Sounds = get_int(nullptr, "Sounds", Options.Sounds);
/*Options.Sounds = get_int(nullptr, "Sounds", Options.Sounds);
Options.Music = get_int(nullptr, "Music", Options.Music);
Options.Average = get_int(nullptr, "Average", Options.Average);
Options.FullScreen = get_int(nullptr, "FullScreen", Options.FullScreen);
@ -107,7 +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);
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);
@ -137,7 +137,7 @@ void options::init(HMENU menuHandle)
void options::uninit()
{
set_int(nullptr, "Sounds", Options.Sounds);
/*set_int(nullptr, "Sounds", Options.Sounds);
set_int(nullptr, "Music", Options.Music);
set_int(nullptr, "FullScreen", Options.FullScreen);
set_int(nullptr, "Players", Options.Players);
@ -148,7 +148,7 @@ void options::uninit()
set_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey);
set_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
set_int(nullptr, "Screen Resolution", Options.Resolution);
set_int(nullptr, "Uniform scaling", Options.UniformScaling);
set_int(nullptr, "Uniform scaling", Options.UniformScaling);*/
}
void options::path_init(LPCSTR regPath)

View file

@ -17,6 +17,7 @@
#include "timer.h"
#include "winmain.h"
#include "resource.h"
#include "Sound.h"
#include "TBall.h"
#include "TDemo.h"
#include "TEdgeSegment.h"
@ -32,7 +33,7 @@ high_score_struct pb::highscore_table[5];
bool pb::FullTiltMode = false;
int pb::init()
int pb::init(SDL_Renderer* render)
{
float projMat[12], zMin = 0, zScaler = 0;
CHAR datFileName[300];
@ -74,6 +75,7 @@ int pb::init()
zScaler = cameraInfo[2];
}
gdrv::init(render, resInfo->TableWidth, resInfo->TableHeight);
render::init(nullptr, zMin, zScaler, resInfo->TableWidth, resInfo->TableHeight);
gdrv::copy_bitmap(
&render::vscreen,
@ -332,6 +334,7 @@ void pb::pause_continue()
MainTable->Message(1008, time_now);
pinball::InfoTextBox->Display(pinball::get_rc_string(22, 0), -1.0);
midi::music_stop();
Sound::Deactivate();
}
else
{
@ -355,6 +358,7 @@ void pb::pause_continue()
}
if (options::Options.Music && !winmain::single_step)
midi::play_pb_theme(0);
Sound::Activate();
}
}

View file

@ -16,7 +16,7 @@ public:
static high_score_struct highscore_table[5];
static bool FullTiltMode;
static int init();
static int init(SDL_Renderer* render);
static int uninit();
static void reset_table();
static void firsttime_setup();

View file

@ -18,8 +18,15 @@
#include <htmlhelp.h>
#include <cstdint>
#include <type_traits> /*For control template*/
#include <chrono>
#include <iostream>
#include <iomanip>
//#include <cstdlib>
#define SDL_MAIN_HANDLED
#include "SDL.h"
#include <SDL_mixer.h>
/*Use (void) to silent unused warnings.*/
#define assertm(exp, msg) assert(((void)msg, exp))

View file

@ -3,6 +3,220 @@
#include "memory.h"
#include "winmain.h"
// Todo: load translations from file
std::map<uint32_t, LPCSTR> rc_strings
{
{0, "Replay Awarded"},
{1, "Ball Locked"},
{2, "Center Post\n%ld"},
{3, "Bonus Awarded\n%ld"},
{4, "Bonus Activated"},
{5, "Weapons Upgraded"},
{6, "Engine Upgraded"},
{7, "Bonus up 1 Million"},
{8, "Extra Ball Available\n%ld"},
{9, "Extra Ball"},
{10, "Reflex Shot Award\n%ld"},
{11, "Final Battle Won"},
{12, "Hyperspace Bonus\n%ld"},
{13, "Hyperspace Bonus Available"},
{14, "Jackpot Awarded\n%ld"},
{15, "Jackpot Activated"},
{16, "Multiball"},
{17, "Ramp Bonus Awarded"},
{18, "Light Added"},
{19, "Ramp Bonus On"},
{20, "Light Reset Off"},
{21, "Skill Shot\n%ld"},
{22, "Game Paused\nF3 to Resume"},
{23, "Continue Play"},
{24, "F2 Starts New Game"},
{25, "Careful..."},
{26, "Player 1"},
{27, "Player 2"},
{28, "Player 3"},
{29, "Player 4"},
{30, "Demo\nPlayer 1"},
{31, "Demo\nPlayer 2"},
{32, "Demo\nPlayer 3"},
{33, "Demo\nPlayer 4"},
{34, "Game Over"},
{35, "TILT!"},
{36, "This program requires an 80386 or later CPU."},
{37, "80386 Required"},
{38, "3D Pinball for Windows - Space Cadet"},
{
39,
"One or more of the player controls is set to the same key,\nfor best performance use unique keys for each control."
},
{40, "Clear High Scores?"},
{41, "Confirm"},
{42, "WAVEMIX.INF is missing - it must be in the pinball directory!"},
{43, "Warning:"},
{44, "Ship Re-Fueled"},
{45, "Gravity Well"},
{46, "Time Warp Forward"},
{47, "Time Warp Backward"},
{48, "Maelstrom!"},
{49, "Wormhole"},
{50, "Awaiting Deployment"},
{51, "Flags Upgraded"},
{52, "Bonus Hold"},
{53, "Level One Commation"},
{54, "Level Two Commation"},
{55, "Level Three Commation"},
{56, "Field Multiplier 2x"},
{57, "Field Multiplier 3x"},
{58, "Field Multiplier 5x"},
{59, "Field Multiplier 10x"},
{60, "Target Practice"},
{61, "Launch Training"},
{62, "Re-Entry Training"},
{63, "Science"},
{64, "Stray Comet"},
{65, "Black Hole"},
{66, "Space Radiation"},
{67, "Bug Hunt"},
{68, "Alien Menace"},
{69, "Rescue"},
{70, "Satellite Retrieval"},
{71, "Recon"},
{72, "Doomsday Machine"},
{73, "Cosmic Plague"},
{74, "Secret"},
{75, "Time Warp"},
{76, "Maelstrom"},
{77, "Mission Accepted\n%ld"},
{78, "Mission Completed\n%ld"},
{79, "%s Mission Selected"},
{80, "Black Hole\n%ld"},
{81, "Gravity Normalized\n%ld"},
{82, "Gravity Well\n%ld"},
{83, "Promotion to %s"},
{84, "Cadet"},
{85, "Ensign"},
{86, "Lieutenant"},
{87, "Captain"},
{88, "Lt Commander"},
{89, "Commander"},
{90, "Commodore"},
{91, "Admiral"},
{92, "Fleet Admiral"},
{93, "Wormhole Opened"},
{94, "Crash Bonus\n%ld"},
{95, "Replay Ball"},
{96, "Re-Deploy"},
{97, "Player 1 Shoot Again"},
{98, "Player 2 Shoot Again"},
{99, "Player 3 Shoot Again"},
{100, "Player 4 Shoot Again"},
{
101,
"This 3D Pinball Table was created for Microsoft by Maxis.\nFor more information call (800)-336-2947\n(US and Canadian customers only).\nCopyright (c) 1995 Maxis."
},
{102, "3D Pinball Table created for Microsoft by Maxis. Copyright (c) 1995 Maxis."},
{103, "About 3D Pinball"},
{104, "Hit Mission Targets To Select Mission"},
{105, "Re-Fuel Ship"},
{106, "Launch Ramp To Accept %s Mission"},
{107, "Attack Bumpers Hits\nLeft: %d"},
{108, "Target Training Passed"},
{109, "Mission Aborted"},
{110, "Launches Left: %d"},
{111, "Launch Training Passed"},
{112, "Re-Entries Left: %d"},
{113, "Re-Entry Training Passed"},
{114, "Drop Targets\nLeft: %d"},
{115, "Science Mission Completed"},
{116, "Warning -- Low Fuel"},
{117, "Fill Right Hazard Banks"},
{118, "Hyperspace Launch"},
{119, "Comet Destroyed"},
{120, "Enter Wormhole"},
{121, "Radiation Eliminated"},
{122, "Upgrade Launch Bumpers"},
{123, "Enter Black Hole"},
{124, "Black Hole Eliminated"},
{125, "Targets\nLeft: %d"},
{126, "Xenomorphs Destroyed"},
{127, "Upgrade Flags"},
{128, "Hyperspace Launch"},
{129, "Survivors Rescued"},
{130, "Aliens Repelled"},
{131, "Hit Fuel Targets"},
{132, "Remote Attack Bumper Hits\nLeft: %d"},
{133, "Satellite Repaired"},
{134, "Lane Passes\nLeft: %d"},
{135, "Shoot Ball Up Fuel Chute"},
{136, "Survey Complete"},
{137, "Out Lane Passes\nLeft: %d"},
{138, "Doomsday Machine Destroyed"},
{139, "Roll Flags: %d"},
{140, "Hit Space Warp Rollover"},
{141, "Plague Eliminated"},
{142, "Hit Yellow Wormhole"},
{143, "Hit Red Wormhole"},
{144, "Hit Green Wormhole"},
{145, "Plans Recovered"},
{146, "Rebound Hits\nLeft: %d"},
{147, "Hit Hyperspace Chute or Launch Ramp"},
{148, "Drop Target Hits\nLeft: %d"},
{149, "Spot Target Hits\nLeft: %d"},
{150, "Lanes Passes\nLeft: %d"},
{151, "Shoot Ball Up Fuel Chute"},
{152, "Hit Launch Ramp"},
{153, "Hit Flags"},
{154, "Hit Worm Hole"},
{155, "Hyperspace Chute to Maelstrom"},
{156, "pinball.mid"},
{158, "1 UseBitmapFont"},
{159, "90 Left Flipper Key"},
{160, "191 Right Flipper Key"},
{161, "32 Plunger Key"},
{162, "88 Bump Left Key"},
{163, "190 Bump Right Key"},
{164, "38 Bump Bottom Key"},
{165, "Software\\Microsoft\\Plus!\\Pinball"},
{166, "SpaceCadet"},
{167, "1c7c22a0-9576-11ce-bf80-444553540000"},
{168, "PINBALL.DAT"},
{169, "Space Cadet"},
{170, "Error:"},
{171, "Unable to find other tables."},
{172, "3D Pinball\nSpace Cadet"},
{173, "Promotion to %s"},
{174, "Demotion to %s"},
{175, "Upgrade Attack Bumpers"},
{176, "Fill Left Hazard Banks"},
{177, "HIGH SCORE"},
{178, "pinball.chm"},
{179, "Not enough memory to run 3D Pinball."},
{180, "Player 1's Score\n%ld"},
{181, "Player 2's Score\n%ld"},
{182, "Player 3's Score\n%ld"},
{183, "Player 4's Score\n%ld"},
{184, "High Score 1\n%ld"},
{185, "High Score 2\n%ld"},
{186, "High Score 3\n%ld"},
{187, "High Score 4\n%ld"},
{188, "High Score 5\n%ld"},
{189, "255 255 255 (R G B default font color)"},
{2030, "Use &Maximum Resolution (640 x 480)"},
{2031, "Use &Maximum Resolution (800 x 600)"},
{2032, "Use &Maximum Resolution (1024 x 768)"}
};
int LoadStringL(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int cchBufferMax)
{
auto str = rc_strings.find(uID);
if (str == rc_strings.end())
{
return 0;
}
lstrcpyA(lpBuffer, str->second);
return 1;
}
int pinball::quickFlag = 0;
TTextBox* pinball::InfoTextBox;
@ -15,7 +229,7 @@ int pinball::RightShift = -1;
char* pinball::get_rc_string(int uID, int a2)
{
char* result = &getRcBuffer[256 * rc_string_slot];
if (!LoadStringA(winmain::hinst, uID, &getRcBuffer[256 * rc_string_slot], 255))
if (!LoadStringL(winmain::hinst, uID, &getRcBuffer[256 * rc_string_slot], 255))
*result = 0;
if (++rc_string_slot >= 6)
rc_string_slot = 0;
@ -25,7 +239,7 @@ char* pinball::get_rc_string(int uID, int a2)
int pinball::get_rc_int(int uID, int* dst)
{
char buffer[255];
int result = LoadStringA(winmain::hinst, uID, buffer, 255);
int result = LoadStringL(winmain::hinst, uID, buffer, 255);
if (!result)
return result;
*dst = atoi(buffer);

File diff suppressed because one or more lines are too long

View file

@ -11,9 +11,12 @@
#include "resource.h"
#include "splash.h"
const double TargetFps = 60, TargetFrameTime = 1000 / TargetFps;
HINSTANCE winmain::hinst = nullptr;
HWND winmain::hwnd_frame = nullptr;
HCURSOR winmain::mouse_hsave;
SDL_Window* winmain::MainWindow = nullptr;
int winmain::return_value = 0;
int winmain::bQuit = 0;
@ -36,6 +39,15 @@ gdrv_bitmap8 winmain::gfr_display{};
char winmain::DatFileName[300]{};
uint32_t timeGetTimeAlt()
{
auto now = std::chrono::high_resolution_clock::now();
auto duration = now.time_since_epoch();
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
return static_cast<uint32_t>(millis);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
return winmain::WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
@ -46,75 +58,20 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
memory::init(memalloc_failure);
++memory::critical_allocation;
auto optionsRegPath = pinball::get_rc_string(165, 0);
options::path_init(optionsRegPath);
auto regSpaceCadet = pinball::get_rc_string(166, 0);
if (options::get_int(regSpaceCadet, "Table Version", 1) <= 1)
{
auto tmpBuf = memory::allocate(0x1F4u);
if (!tmpBuf)
{
options::path_uninit();
return 0;
}
options::set_int(regSpaceCadet, "Table Version", 1u);
GetModuleFileNameA(hinst, tmpBuf, 0x1F4u);
options::set_string(regSpaceCadet, "Table Exe", tmpBuf);
options::set_string(regSpaceCadet, "Table Name", pinball::get_rc_string(169, 0));
options::set_string(nullptr, "Last Table Played", regSpaceCadet);
memory::free(static_cast<void*>(tmpBuf));
tmpBuf = memory::allocate(0x1F4u);
if (tmpBuf)
{
auto tmpBuf2 = memory::allocate(0x1F4u);
if (tmpBuf2)
{
char Buffer[40];
bool setOption = false;
for (int i = 0; i < 32700; ++i)
{
sprintf_s(Buffer, "Table%d", i);
options::get_string(nullptr, Buffer, tmpBuf, "", 500);
if (!*tmpBuf)
break;
options::get_string(tmpBuf, "Table Name", tmpBuf2, "", 500);
if (!lstrcmpA(tmpBuf2, pinball::get_rc_string(169, 0)))
{
setOption = false;
break;
}
if (!*tmpBuf2)
break;
}
if (setOption)
options::set_string(nullptr, Buffer, regSpaceCadet);
memory::free(tmpBuf2);
}
memory::free(tmpBuf);
}
}
else
{
auto tmpBuf = memory::allocate(0x1F4u);
if (!tmpBuf)
{
options::path_uninit();
return 0;
}
options::get_string(regSpaceCadet, "Shell Exe", tmpBuf, "", 500);
auto execRes = WinExec(tmpBuf, 5u);
memory::free(tmpBuf);
if (execRes >= 32)
{
options::path_uninit();
return 0;
}
}
options::path_init(optionsRegPath);
--memory::critical_allocation;
// SDL init
SDL_SetMainReady();
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not initialize SDL2", SDL_GetError(), nullptr);
return 1;
}
pinball::quickFlag = strstr(lpCmdLine, "-quick") != nullptr;
hinst = hInstance;
auto regSpaceCadet = pinball::get_rc_string(166, 0);
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*/
@ -141,38 +98,66 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
if (check_expiration_date())
return 0;
INITCOMMONCONTROLSEX picce;
picce.dwSize = 8;
picce.dwICC = 5885;
InitCommonControlsEx(&picce);
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");
RegisterClassExA(&wndClass);
pinball::FindShiftKeys();
options::init_resolution();
char windowName[40];
lstrcpyA(windowName, pinball::get_rc_string(38, 0));
windowHandle = CreateWindowExA(0, windowClass, windowName, WndStyle, 0, 0, 640, 480, nullptr, nullptr, hInstance,
nullptr);
hwnd_frame = windowHandle;
if (!windowHandle)
// SDL window
SDL_Window* window = SDL_CreateWindow
(
pinball::get_rc_string(38, 0),
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
800, 600,
SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE
);
MainWindow = window;
if (!window)
{
PostQuitMessage(0);
return 0;
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not create window", SDL_GetError(), nullptr);
return 1;
}
SDL_Renderer* renderer = SDL_CreateRenderer
(
window,
-1,
SDL_RENDERER_ACCELERATED
);
if (!renderer)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not create renderer", SDL_GetError(), window);
return 1;
}
// PB init from message handler
{
RECT rect{};
++memory::critical_allocation;
auto prevCursor = SetCursor(LoadCursorA(nullptr, IDC_WAIT));
auto voiceCount = options::get_int(nullptr, "Voices", 8);
if (!Sound::Init(voiceCount))
options::menu_set(Menu1_Sounds, 0);
Sound::Activate();
if (!pinball::quickFlag && !midi::music_init((HWND)window))
options::menu_set(Menu1_Music, 0);
if (pb::init(renderer))
_exit(0);
SetCursor(prevCursor);
auto changeDisplayFg = options::get_int(nullptr, "Change Display", 1);
auto menuHandle = GetMenu((HWND)window);
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)window, menuHandle,
changeDisplayFg);
--memory::critical_allocation;
}
auto menuHandle = GetMenu(windowHandle);
@ -186,9 +171,8 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
options::menu_check(Menu1_Full_Screen, 1);
}
ShowWindow(hwnd_frame, nShowCmd);
SDL_ShowWindow(window);
fullscrn::set_screen_mode(options::Options.FullScreen);
UpdateWindow(hwnd_frame);
if (splash)
{
@ -197,9 +181,9 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
}
pinball::adjust_priority(options::Options.PriorityAdj);
const auto startTime = timeGetTime();
const auto startTime = timeGetTimeAlt();
MSG wndMessage{};
while (timeGetTime() >= startTime && timeGetTime() - startTime < 0) // Don't wait for now, was 2000
while (timeGetTimeAlt() >= startTime && timeGetTimeAlt() - startTime < 0) // Don't wait for now, was 2000
PeekMessageA(&wndMessage, hwnd_frame, 0, 0, 1u);
if (strstr(lpCmdLine, "-demo"))
@ -207,21 +191,27 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
else
pb::replay_level(0);
DWORD someTimeCounter = 300u, prevTime = 0u;
then = timeGetTime();
DWORD updateCounter = 300u, frameCounter = 0, prevTime = 0u;
then = timeGetTimeAlt();
double sdlTimerResMs = 1000.0 / static_cast<double>(SDL_GetPerformanceFrequency());
auto frameStart = static_cast<double>(SDL_GetPerformanceCounter());
while (true)
{
if (!someTimeCounter)
{
if (!updateCounter)
{
someTimeCounter = 300;
updateCounter = 300;
if (DispFrameRate)
{
auto curTime = timeGetTime();
auto curTime = timeGetTimeAlt();
if (prevTime)
{
char buf[60];
sprintf_s(buf, "Frames/sec = %02.02f", 300.0f / (static_cast<float>(curTime - prevTime) * 0.001f));
SetWindowTextA(hwnd_frame, buf);
auto elapsedSec = static_cast<float>(curTime - prevTime) * 0.001f;
sprintf_s(buf, "Updates/sec = %02.02f Frames/sec = %02.02f ",
300.0f / elapsedSec, frameCounter / elapsedSec);
SDL_SetWindowTitle(window, buf);
frameCounter = 0;
if (DispGRhistory)
{
@ -256,8 +246,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
prevTime = 0;
}
}
Sound::Idle();
if (!ProcessWindowMessages() || bQuit)
break;
@ -265,22 +254,18 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
{
if (mouse_down)
{
now = timeGetTime();
now = timeGetTimeAlt();
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);
Point = POINT{last_mouse_x, last_mouse_y};
ClientToScreen(hwnd_frame, &Point);
SetCursorPos(Point.x, Point.y);
int x, y;
SDL_GetMouseState(&x, &y);
pb::ballset(last_mouse_x - x, y - last_mouse_y);
SDL_WarpMouseInWindow(window, last_mouse_x, last_mouse_y);
}
}
if (!single_step)
{
auto curTime = timeGetTime();
auto curTime = timeGetTimeAlt();
now = curTime;
if (no_time_loss)
{
@ -302,10 +287,20 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
{
fillChar = -7;
}
gdrv::fill_bitmap(&gfr_display, 1, 10, 299 - someTimeCounter, 0, fillChar);
gdrv::fill_bitmap(&gfr_display, 1, 10, 299 - updateCounter, 0, fillChar);
}
--someTimeCounter;
--updateCounter;
then = now;
auto frameEnd = static_cast<double>(SDL_GetPerformanceCounter());
auto elapsedMs = (frameEnd - frameStart) * sdlTimerResMs;
if (elapsedMs >= TargetFrameTime)
{
// Keep track of remainder, limited to one frame time.
frameStart = frameEnd - min(elapsedMs - TargetFrameTime, TargetFrameTime) / sdlTimerResMs;
SDL_RenderPresent(renderer);
frameCounter++;
}
}
}
}
@ -390,17 +385,17 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
++memory::critical_allocation;
auto prevCursor = SetCursor(LoadCursorA(nullptr, IDC_WAIT));
gdrv::init(hinst, hWnd);
gdrv::init(nullptr,0,0);
auto voiceCount = options::get_int(nullptr, "Voices", 8);
if (!Sound::Init(hinst, voiceCount, nullptr))
if (!Sound::Init(voiceCount))
options::menu_set(Menu1_Sounds, 0);
Sound::Activate();
if (!pinball::quickFlag && !midi::music_init(hWnd))
options::menu_set(Menu1_Music, 0);
if (pb::init())
if (pb::init(nullptr))
_exit(0);
SetCursor(prevCursor);
auto changeDisplayFg = options::get_int(nullptr, "Change Display", 1);
@ -725,33 +720,187 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
return DefWindowProcA(hWnd, Msg, wParam, lParam);
}
int winmain::event_handler(const SDL_Event* event)
{
switch (event->type)
{
case SDL_QUIT:
end_pause();
bQuit = 1;
PostQuitMessage(0);
fullscrn::shutdown();
return_value = 0;
return 0;
case SDL_KEYUP:
pb::keyup(event->key.keysym.sym);
break;
case SDL_KEYDOWN:
if (!event->key.repeat)
pb::keydown(event->key.keysym.sym);
switch (event->key.keysym.sym)
{
case SDLK_ESCAPE:
if (options::Options.FullScreen)
options::toggle(Menu1_Full_Screen);
SDL_MinimizeWindow(MainWindow);
break;
case SDLK_F1:
help_introduction(hinst, (HWND)MainWindow);
break;
case SDLK_F2:
new_game();
break;
case SDLK_F3:
pause();
break;
case SDLK_F4:
options::toggle(Menu1_Full_Screen);
break;
case SDLK_F5:
options::toggle(Menu1_Sounds);
break;
case SDLK_F6:
options::toggle(Menu1_Music);
break;
case SDLK_F8:
if (!single_step)
pause();
options::keyboard();
break;
default:
break;
}
if (!pb::cheat_mode)
break;
switch (event->key.keysym.sym)
{
case SDLK_h:
DispGRhistory = 1;
break;
case SDLK_y:
SDL_SetWindowTitle(MainWindow, "Pinball");
DispFrameRate = DispFrameRate == 0;
break;
case SDLK_F1:
pb::frame(10);
break;
case SDLK_F10:
single_step = single_step == 0;
if (single_step == 0)
no_time_loss = 1;
break;
default:
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
switch (event->button.button)
{
case SDL_BUTTON_LEFT:
if (pb::cheat_mode)
{
mouse_down = 1;
last_mouse_x = event->button.x;
last_mouse_y = event->button.y;
SDL_ShowCursor(SDL_DISABLE);
SDL_SetWindowGrab(MainWindow, SDL_TRUE);
}
else
pb::keydown(options::Options.LeftFlipperKey);
break;
case SDL_BUTTON_RIGHT:
if (!pb::cheat_mode)
pb::keydown(options::Options.RightFlipperKey);
break;
case SDL_BUTTON_MIDDLE:
pb::keydown(options::Options.PlungerKey);
break;
default:
break;
}
break;
case SDL_MOUSEBUTTONUP:
switch (event->button.button)
{
case SDL_BUTTON_LEFT:
if (mouse_down)
{
mouse_down = 0;
SDL_ShowCursor(SDL_ENABLE);
SDL_SetWindowGrab(MainWindow, SDL_FALSE);
}
if (!pb::cheat_mode)
pb::keyup(options::Options.LeftFlipperKey);
break;
case SDL_BUTTON_RIGHT:
if (!pb::cheat_mode)
pb::keyup(options::Options.RightFlipperKey);
break;
case SDL_BUTTON_MIDDLE:
pb::keyup(options::Options.PlungerKey);
break;
default:
break;
}
break;
case SDL_WINDOWEVENT:
switch (event->window.event)
{
case SDL_WINDOWEVENT_FOCUS_GAINED:
case SDL_WINDOWEVENT_TAKE_FOCUS:
case SDL_WINDOWEVENT_EXPOSED:
case SDL_WINDOWEVENT_SHOWN:
activated = 1;
Sound::Activate();
if (options::Options.Music && !single_step)
midi::play_pb_theme(0);
no_time_loss = 1;
pinball::adjust_priority(options::Options.PriorityAdj);
has_focus = 1;
gdrv::get_focus();
fullscrn::force_redraw();
pb::paint();
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
case SDL_WINDOWEVENT_HIDDEN:
activated = 0;
fullscrn::activate(0);
options::menu_check(Menu1_Full_Screen, 0);
options::Options.FullScreen = 0;
SetThreadPriority(GetCurrentThread(), 0);
Sound::Deactivate();
midi::music_stop();
has_focus = 0;
gdrv::get_focus();
pb::loose_focus();
break;
default: ;
}
break;
default: ;
}
return 1;
}
int winmain::ProcessWindowMessages()
{
MSG Msg{};
SDL_Event event;
if (has_focus && !single_step)
{
while (PeekMessageA(&Msg, nullptr, 0, 0, 1u))
while (SDL_PollEvent(&event))
{
TranslateMessage(&Msg);
DispatchMessageA(&Msg);
if (Msg.message == 18)
{
return_value = static_cast<int>(Msg.wParam);
if (!event_handler(&event))
return 0;
}
}
return 1;
}
GetMessageA(&Msg, hwnd_frame, 0, 0);
TranslateMessage(&Msg);
DispatchMessageA(&Msg);
if (Msg.message == 18)
{
return_value = static_cast<int>(Msg.wParam);
return 0;
}
return 1;
SDL_WaitEvent(&event);
return event_handler(&event);
}
void winmain::memalloc_failure()
@ -842,7 +991,7 @@ void winmain::help_introduction(HINSTANCE a1, HWND a2)
options::get_string(pinball::get_rc_string(166, 0), "HelpFile", buf1, buf1, 500);
lstrcpyA(buf2, buf1);
memory::free(buf1);
HtmlHelpA(GetDesktopWindow(), buf2, 0, 0);
//HtmlHelpA(GetDesktopWindow(), buf2, 0, 0);
memory::free(buf2);
}
else

View file

@ -13,6 +13,7 @@ public:
static int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
static LRESULT CALLBACK message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
static int event_handler(const SDL_Event* event);
static void memalloc_failure();
static int ProcessWindowMessages();
static int check_expiration_date();
@ -31,6 +32,7 @@ private:
static gdrv_bitmap8 gfr_display;
static HCURSOR mouse_hsave;
static bool restart;
static SDL_Window* MainWindow;
static HDC _BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
};