diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c5dee64
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,622 @@
+
+### C template
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
+
+### VisualStudio template
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+### Linux template
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### SublimeText template
+# Cache files for Sublime Text
+*.tmlanguage.cache
+*.tmPreferences.cache
+*.stTheme.cache
+
+# Workspace files are user-specific
+*.sublime-workspace
+
+# Project files should be checked into the repository, unless a significant
+# proportion of contributors will probably not be using Sublime Text
+# *.sublime-project
+
+# SFTP configuration file
+sftp-config.json
+
+# Package control specific files
+Package Control.last-run
+Package Control.ca-list
+Package Control.ca-bundle
+Package Control.system-ca-bundle
+Package Control.cache/
+Package Control.ca-certs/
+Package Control.merged-ca-bundle
+Package Control.user-ca-bundle
+oscrypto-ca-bundle.crt
+bh_unicode_properties.cache
+
+# Sublime-github package stores a github token in this file
+# https://packagecontrol.io/packages/sublime-github
+GitHub.sublime-settings
+
+### Windows template
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+### NotepadPP template
+# Notepad++ backups #
+*.bak
+
+### macOS template
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### C++ template
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+### JetBrains template
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### VisualStudioCode template
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..79b3c94
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..eac44bb
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/pinball.iml b/.idea/pinball.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/pinball.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Classes/Objlist/Objlist.cpp b/Classes/Objlist/Objlist.cpp
new file mode 100644
index 0000000..dbe1615
--- /dev/null
+++ b/Classes/Objlist/Objlist.cpp
@@ -0,0 +1,33 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "objlist.h"
+
+//----- (010098D3) --------------------------------------------------------
+objlist_class *__thiscall objlist_class::objlist_class(objlist_class *this, int a2, int a3)
+{
+objlist_class *v3; // esi
+
+v3 = this;
+*((_DWORD *)this + 1) = objlist_new(a2);
+*(_DWORD *)v3 = a3;
+return v3;
+}
+
+//----- (010098F7) --------------------------------------------------------
+void __thiscall objlist_class::Grow(objlist_class *this)
+{
+ *((_DWORD *)this + 1) = objlist_grow(*((int **)this + 1), *(_DWORD *)this);
+}
+
+//----- (0100ACF3) --------------------------------------------------------
+void __thiscall objlist_class::Add(objlist_class *this, void *a2)
+{
+ objlist_class *v2; // esi
+
+ v2 = this;
+ if ( *(_DWORD *)(*((_DWORD *)this + 1) + 4) == **((_DWORD **)this + 1) )
+ objlist_class::Grow(this);
+ objlist_add_object(*((_DWORD **)v2 + 1), (int)a2);
+}
diff --git a/Classes/Objlist/objlist.h b/Classes/Objlist/objlist.h
new file mode 100644
index 0000000..8258a81
--- /dev/null
+++ b/Classes/Objlist/objlist.h
@@ -0,0 +1,8 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_OBJLIST_CLASS_H
+#define PINBALL_OBJLIST_CLASS_H
+
+#endif //PINBALL_OBJLIST_CLASS_H
diff --git a/Classes/TBall/TBall.cpp b/Classes/TBall/TBall.cpp
new file mode 100644
index 0000000..6aaf3d9
--- /dev/null
+++ b/Classes/TBall/TBall.cpp
@@ -0,0 +1,203 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "TBall.h"
+
+//----- (0100B072) --------------------------------------------------------
+bool __thiscall TBall::already_hit(TBall *this, struct TEdgeSegment *a2)
+{
+int v2; // esi
+bool result; // al
+
+v2 = *(_DWORD *)((char *)this + 134);
+if ( !v2 )
+return 0;
+result = 1;
+if ( *(struct TEdgeSegment **)((char *)this + 114) != a2 )
+{
+if ( v2 == 1 )
+return 0;
+if ( *(struct TEdgeSegment **)((char *)this + 118) == a2 )
+return result;
+if ( v2 == 2 )
+return 0;
+if ( *(struct TEdgeSegment **)((char *)this + 122) == a2 )
+return result;
+if ( v2 == 3 )
+return 0;
+if ( *(struct TEdgeSegment **)((char *)this + 126) == a2 )
+return result;
+if ( v2 == 4 )
+return 0;
+if ( *(struct TEdgeSegment **)((char *)this + 130) != a2 )
+{
+result = 0;
+if ( v2 != 5 )
+result = v2 == (_DWORD)a2;
+}
+}
+return result;
+}
+
+//----- (0101590F) --------------------------------------------------------
+void __thiscall TBall::not_again(TBall *this, struct TEdgeSegment *a2)
+{
+signed int v2; // edx
+
+v2 = *(_DWORD *)((char *)this + 134);
+if ( v2 < 5 )
+{
+*(_DWORD *)((char *)this + 4 * v2 + 114) = a2;
+++*(_DWORD *)((char *)this + 134);
+}
+}
+
+//----- (01015B9C) --------------------------------------------------------
+int __thiscall TBall::Message(TBall *this, int a2, float a3)
+{
+TBall *v3; // esi
+int v4; // eax
+
+v3 = this;
+if ( a2 == 1024 )
+{
+render_ball_set(*(_DWORD *)((char *)this + 26), 0, 0.0, 0, 0);
+v4 = *(_DWORD *)((char *)v3 + 154);
+*(float *)((char *)v3 + 42) = 0.0;
+*(_DWORD *)((char *)v3 + 106) = 0;
+*(float *)((char *)v3 + 46) = 0.0;
+*((_BYTE *)v3 + 5) = 0;
+*(_DWORD *)((char *)v3 + 150) = 0;
+*(_DWORD *)((char *)v3 + 110) = 1;
+*(float *)((char *)v3 + 58) = 0.0;
+*(_DWORD *)((char *)v3 + 50) = v4;
+*(float *)((char *)v3 + 54) = 0.0;
+*(float *)((char *)v3 + 66) = 0.0;
+*(float *)((char *)v3 + 70) = 0.0;
+}
+return 0;
+}
+
+//----- (01015C08) --------------------------------------------------------
+void __thiscall TBall::Repaint(TBall *this)
+{
+TBall *v1; // esi
+double v2; // st7
+int v3; // edx
+int v4; // edi
+float *v5; // ebx
+int v6; // ecx
+float v7; // ST08_4
+int v8; // [esp+14h] [ebp-8h]
+int v9; // [esp+18h] [ebp-4h]
+
+v1 = this;
+if ( *(_DWORD *)((char *)this + 150) )
+*(float *)((char *)this + 50) = *(float *)((char *)this + 142) * *(float *)((char *)this + 46)
++ *(float *)((char *)this + 138) * *(float *)((char *)this + 42)
++ *(float *)((char *)this + 154)
++ *(float *)((char *)this + 146);
+proj_xform_to_2d((float *)((char *)this + 42), &v8);
+v2 = proj_z_distance((char *)v1 + 42);
+v3 = *(_DWORD *)(*(_DWORD *)((char *)v1 + 34) + 4);
+v4 = 0;
+if ( *(_DWORD *)(v3 + 4) - 1 > 0 )
+{
+v5 = (float *)((char *)v1 + 162);
+do
+{
+if ( v2 >= *v5 )
+break;
+++v4;
+++v5;
+}
+while ( v4 < *(_DWORD *)(v3 + 4) - 1 );
+}
+v6 = *(_DWORD *)(v3 + 4 * v4 + 8);
+v8 += *(_DWORD *)(v6 + 12) / -2;
+v9 += *(_DWORD *)(v6 + 16) / -2;
+v7 = v2;
+render_ball_set(*(_DWORD *)((char *)v1 + 26), v6, v7, v8, v9);
+}
+// 1008ED8: using guessed type double __stdcall proj_z_distance(_DWORD);
+
+//----- (01019309) --------------------------------------------------------
+TBall *__thiscall TBall::TBall(TBall *this, struct TPinballTable *a2)
+{
+TBall *v2; // esi
+objlist_class *v3; // eax
+objlist_class *v4; // ebx
+objlist_class *v5; // eax
+int v6; // ebx
+objlist_class *v7; // ecx
+int v8; // eax
+double v9; // st7
+int v10; // eax
+int v11; // ecx
+char v13; // [esp+Ch] [ebp-50h]
+void *v14; // [esp+4Ch] [ebp-10h]
+int v15; // [esp+54h] [ebp-8h]
+float *v16; // [esp+58h] [ebp-4h]
+struct TPinballTable *v17; // [esp+64h] [ebp+8h]
+
+v2 = this;
+TPinballComponent::TPinballComponent(this, a2, -1, 0);
+*(float *)((char *)v2 + 78) = 0.0;
+*(_DWORD *)v2 = &TBall::`vftable';
+*(float *)((char *)v2 + 70) = 0.0;
+*((_BYTE *)v2 + 5) = 1;
+*(_DWORD *)((char *)v2 + 106) = 0;
+*(_DWORD *)((char *)v2 + 134) = 0;
+*(float *)((char *)v2 + 74) = 0.0;
+*(_DWORD *)((char *)v2 + 110) = 1;
+*(_DWORD *)((char *)v2 + 150) = 0;
+*(float *)((char *)v2 + 66) = 0.0;
+*(float *)((char *)v2 + 58) = 0.0;
+*(float *)((char *)v2 + 54) = 0.0;
+*(float *)((char *)v2 + 86) = 1000000000.0;
+*(float *)((char *)v2 + 82) = 1000000000.0;
+*(float *)((char *)v2 + 42) = 0.0;
+*(float *)((char *)v2 + 46) = 0.0;
+v3 = (objlist_class *)operator new(8u);
+v4 = v3;
+if ( v3 )
+{
+objlist_class::objlist_class(v3, 0, 4);
+v5 = v4;
+}
+else
+{
+v5 = 0;
+}
+*(_DWORD *)((char *)v2 + 34) = v5;
+v6 = loader_query_handle("ball");
+*(_DWORD *)((char *)v2 + 154) = *(_DWORD *)loader_query_float_attribute(v6, 0, 500);
+v15 = loader_query_visual_states(v6);
+v17 = 0;
+if ( v15 > 0 )
+{
+v16 = (float *)((char *)v2 + 162);
+do
+{
+loader_query_visual(v6, (signed int)v17, &v13);
+v7 = *(objlist_class **)((char *)v2 + 34);
+if ( v7 )
+objlist_class::Add(v7, v14);
+v8 = loader_query_float_attribute(v6, (signed int)v17, 501);
+v9 = proj_z_distance(v8);
+v17 = (struct TPinballTable *)((char *)v17 + 1);
+*v16 = v9;
+++v16;
+}
+while ( (signed int)v17 < v15 );
+}
+v10 = render_create_sprite(2, 0, 0, 0, 0, 0);
+v11 = *(_DWORD *)((char *)v2 + 154);
+*(_DWORD *)((char *)v2 + 26) = v10;
+*(_DWORD *)(*(_DWORD *)((char *)v2 + 30) + 282) = v11;
+*(_DWORD *)((char *)v2 + 50) = *(_DWORD *)((char *)v2 + 154);
+return v2;
+}
+// 1002554: using guessed type void *TBall::`vftable';
+// 1008ED8: using guessed type double __stdcall proj_z_distance(_DWORD);
diff --git a/Classes/TBall/TBall.h b/Classes/TBall/TBall.h
new file mode 100644
index 0000000..dab579c
--- /dev/null
+++ b/Classes/TBall/TBall.h
@@ -0,0 +1,8 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_TBALL_H
+#define PINBALL_TBALL_H
+
+#endif //PINBALL_TBALL_H
diff --git a/Classes/TBlocker/TBlocker.cpp b/Classes/TBlocker/TBlocker.cpp
new file mode 100644
index 0000000..6487287
--- /dev/null
+++ b/Classes/TBlocker/TBlocker.cpp
@@ -0,0 +1,90 @@
+#include "../../pinball.h"
+
+//----- (0101631C) --------------------------------------------------------
+int __thiscall TBlocker::Message(TBlocker *this, int a2, float a3)
+{
+TBlocker *v3; // esi
+_DWORD *v4; // ST04_4
+int v6; // ST08_4
+double v7; // st7
+float v8; // ST00_4
+
+v3 = this;
+switch ( a2 )
+{
+case 51:
+LABEL_7:
+if ( *(_DWORD *)((char *)this + 86) )
+{
+timer_kill(*(_DWORD *)((char *)this + 86));
+*(_DWORD *)((char *)v3 + 86) = 0;
+}
+*(_DWORD *)((char *)v3 + 6) = 0;
+v4 = *(_DWORD **)((char *)v3 + 26);
+*((_BYTE *)v3 + 5) = 0;
+render_sprite_set_bitmap(v4, 0);
+if ( a2 == 51 )
+loader_play_sound(*(_DWORD *)((char *)v3 + 94));
+return 0;
+case 52:
+v6 = *(_DWORD *)((char *)this + 90);
+*((_BYTE *)this + 5) = 1;
+loader_play_sound(v6);
+render_sprite_set_bitmap(
+*(_DWORD **)((char *)v3 + 26),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 34) + 4) + 8));
+break;
+case 59:
+break;
+case 1011:
+case 1020:
+case 1024:
+goto LABEL_7;
+default:
+return 0;
+}
+if ( *(_DWORD *)((char *)v3 + 86) )
+timer_kill(*(_DWORD *)((char *)v3 + 86));
+if ( a3 <= 0.0 )
+v7 = 0.0;
+else
+v7 = a3;
+v8 = v7;
+*(_DWORD *)((char *)v3 + 86) = timer_set(v8, (int)v3, (int)TBlocker::TimerExpired);
+return 0;
+}
+
+//----- (010162FF) --------------------------------------------------------
+void __stdcall TBlocker::TimerExpired(int a1, struct TPinballComponent *a2)
+{
+*(_DWORD *)((char *)a2 + 86) = 0;
+control_handler(60, a2);
+}
+
+//----- (01019677) --------------------------------------------------------
+TBlocker *__thiscall TBlocker::TBlocker(TBlocker *this, struct TPinballTable *a2, int a3)
+{
+TBlocker *v3; // esi
+_DWORD *v4; // ST04_4
+char v6; // [esp+8h] [ebp-48h]
+int v7; // [esp+40h] [ebp-10h]
+int v8; // [esp+44h] [ebp-Ch]
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+*(_DWORD *)v3 = &TBlocker::`vftable';
+loader_query_visual(a3, 0, &v6);
+v4 = *(_DWORD **)((char *)v3 + 26);
+*(_DWORD *)((char *)v3 + 90) = v7;
+*(_DWORD *)((char *)v3 + 94) = v8;
+*(_DWORD *)((char *)v3 + 78) = 55;
+*(_DWORD *)((char *)v3 + 82) = 5;
+*(_DWORD *)((char *)v3 + 66) = 1315859240;
+*(_DWORD *)((char *)v3 + 86) = 0;
+*(_DWORD *)((char *)v3 + 6) = 0;
+*((_BYTE *)v3 + 5) = 0;
+render_sprite_set_bitmap(v4, 0);
+return v3;
+}
+// 10025DC: using guessed type void *TBlocker::`vftable';
+
diff --git a/Classes/TBumper/TBumper.cpp b/Classes/TBumper/TBumper.cpp
new file mode 100644
index 0000000..e92f316
--- /dev/null
+++ b/Classes/TBumper/TBumper.cpp
@@ -0,0 +1,196 @@
+#include "../../pinball.h"
+
+//----- (01015CB2) --------------------------------------------------------
+void __stdcall TBumper::TimerExpired(int a1, void *a2)
+{
+int v2; // edx
+int v3; // ecx
+int v4; // eax
+
+v2 = *(_DWORD *)((char *)a2 + 30);
+v3 = 8 * *(_DWORD *)((char *)a2 + 78) + 8;
+v4 = *(_DWORD *)(v3 + *(_DWORD *)(*(_DWORD *)((char *)a2 + 34) + 4));
+*(_DWORD *)((char *)a2 + 82) = 0;
+render_sprite_set(
+*(_DWORD **)((char *)a2 + 26),
+v4,
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)a2 + 38) + 4) + v3),
+*(_DWORD *)(v4 + 29) - *(_DWORD *)(v2 + 234),
+*(_DWORD *)(v4 + 33) - *(_DWORD *)(v2 + 238));
+*(_DWORD *)((char *)a2 + 66) = *(_DWORD *)((char *)a2 + 90);
+}
+
+//----- (01015D0F) --------------------------------------------------------
+void __thiscall TBumper::Fire(TBumper *this)
+{
+TBumper *v1; // esi
+int v2; // edx
+int v3; // eax
+int v4; // ecx
+int v5; // eax
+
+v1 = this;
+v2 = *(_DWORD *)((char *)this + 30);
+v3 = 2 * *(_DWORD *)((char *)this + 78) + 1;
+*(_DWORD *)((char *)this + 66) = 1315859240;
+v4 = 4 * v3 + 8;
+v5 = *(_DWORD *)(v4 + *(_DWORD *)(*(_DWORD *)((char *)v1 + 34) + 4));
+render_sprite_set(
+*(_DWORD **)((char *)v1 + 26),
+*(_DWORD *)(v4 + *(_DWORD *)(*(_DWORD *)((char *)v1 + 34) + 4)),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v1 + 38) + 4) + v4),
+*(_DWORD *)(v5 + 29) - *(_DWORD *)(v2 + 234),
+*(_DWORD *)(v5 + 33) - *(_DWORD *)(v2 + 238));
+*(_DWORD *)((char *)v1 + 82) = timer_set(*(float *)((char *)v1 + 86), (int)v1, (int)TBumper::TimerExpired);
+}
+
+//----- (01015D79) --------------------------------------------------------
+int __thiscall TBumper::Message(TBumper *this, int a2, float a3)
+{
+TBumper *v3; // esi
+int v4; // eax
+int v5; // ecx
+_DWORD *v6; // eax
+char *v7; // eax
+char *v8; // eax
+double v9; // st7
+float v10; // ST04_4
+int v11; // eax
+int v12; // edi
+int v13; // eax
+int v15; // [esp+1Ch] [ebp+Ch]
+
+v3 = this;
+if ( a2 != 11 )
+{
+if ( a2 == 12 )
+{
+v15 = *(_DWORD *)((char *)this + 78) + 1;
+v11 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)this + 34) + 4) + 4) - 1;
+if ( 2 * v15 > v11 )
+v15 = v11 / 2;
+}
+else
+{
+if ( a2 != 13 )
+{
+if ( a2 != 1020 )
+{
+if ( a2 == 1024 )
+{
+if ( *(_DWORD *)((char *)this + 82) )
+{
+timer_kill(*(_DWORD *)((char *)this + 82));
+TBumper::TimerExpired(*(_DWORD *)((char *)v3 + 82), (void *)v3);
+}
+v4 = *(_DWORD *)((char *)v3 + 30);
+*(_DWORD *)((char *)v3 + 78) = 0;
+*(_DWORD *)((char *)v3 + 6) = 0;
+v5 = 0;
+if ( *(_DWORD *)(v4 + 214) > 0 )
+{
+v6 = (_DWORD *)((char *)v3 + 118);
+do
+{
+v6[1] = 0;
+*v6 = 0;
+++v5;
+v6 += 2;
+}
+while ( v5 < *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 214) );
+}
+TBumper::TimerExpired(0, (void *)v3);
+}
+return 0;
+}
+v7 = (char *)this + 8 * *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 218);
+*(_DWORD *)(v7 + 122) = *(_DWORD *)((char *)this + 78);
+*(_DWORD *)(v7 + 118) = *(_DWORD *)((char *)this + 6);
+v8 = (char *)this + 8 * (unsigned __int64)(signed __int64)_floor(a3);
+*(_DWORD *)((char *)v3 + 78) = *(_DWORD *)(v8 + 122);
+v9 = (double)*(signed int *)((char *)v3 + 78);
+*(_DWORD *)((char *)v3 + 6) = *(_DWORD *)(v8 + 118);
+LABEL_16:
+v10 = v9;
+TBumper::Message(v3, 11, v10);
+return 0;
+}
+v15 = *(_DWORD *)((char *)this + 78) - 1;
+if ( v15 < 0 )
+v15 = 0;
+}
+v9 = (double)v15;
+goto LABEL_16;
+}
+v12 = (signed __int64)_floor(a3);
+if ( 2 * v12 > *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 34) + 4) + 4) - 1 )
+v12 = (*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 34) + 4) + 4) - 1) / 2;
+if ( v12 < 0 )
+v12 = 0;
+v13 = *(_DWORD *)((char *)v3 + 78);
+if ( v12 != v13 )
+{
+if ( v12 >= v13 )
+loader_play_sound(*(_DWORD *)((char *)v3 + 94));
+if ( v12 < *(_DWORD *)((char *)v3 + 78) )
+loader_play_sound(*(_DWORD *)((char *)v3 + 98));
+*(_DWORD *)((char *)v3 + 78) = v12;
+TBumper::Fire(v3);
+control_handler(11, v3);
+}
+return 0;
+}
+
+//----- (01015EF9) --------------------------------------------------------
+int __thiscall TBumper::get_scoring(TBumper *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 4 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 102);
+return result;
+}
+
+//----- (01015F17) --------------------------------------------------------
+void __thiscall TBumper::put_scoring(TBumper *this, int a2, int a3)
+{
+if ( a2 < 4 )
+*(_DWORD *)((char *)this + 4 * a2 + 102) = a3;
+}
+
+//----- (0101811D) --------------------------------------------------------
+void __thiscall TBumper::Collision(TBumper *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TBumper *v6; // esi
+
+v6 = this;
+if ( TCollisionComponent::DefaultCollision(this, a2, a3, a4) )
+{
+TBumper::Fire(v6);
+control_handler(63, v6);
+}
+}
+
+//----- (0101944A) --------------------------------------------------------
+TBumper *__thiscall TBumper::TBumper(TBumper *this, struct TPinballTable *a2, int a3)
+{
+TBumper *v3; // esi
+char v5; // [esp+4h] [ebp-48h]
+int v6; // [esp+3Ch] [ebp-10h]
+int v7; // [esp+40h] [ebp-Ch]
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+*(_DWORD *)((char *)v3 + 78) = 0;
+*(_DWORD *)((char *)v3 + 82) = 0;
+*(_DWORD *)v3 = &TBumper::`vftable';
+*(_DWORD *)((char *)v3 + 86) = *(_DWORD *)loader_query_float_attribute(a3, 0, 407);
+loader_query_visual(a3, 0, &v5);
+*(_DWORD *)((char *)v3 + 94) = v6;
+*(_DWORD *)((char *)v3 + 98) = v7;
+*(_DWORD *)((char *)v3 + 90) = *(_DWORD *)((char *)v3 + 66);
+return v3;
+}
+// 100256C: using guessed type void *TBumper::`vftable';
diff --git a/Classes/TCircle/TCircle.cpp b/Classes/TCircle/TCircle.cpp
new file mode 100644
index 0000000..b406f12
--- /dev/null
+++ b/Classes/TCircle/TCircle.cpp
@@ -0,0 +1,53 @@
+#include "../../pinball.h"
+
+//----- (01015898) --------------------------------------------------------
+TCircle *__thiscall TCircle::TCircle(TCircle *this, struct TCollisionComponent *a2, char *a3, unsigned int a4, struct vector_type *a5, float a6)
+{
+TCircle *v6; // ebx
+
+v6 = this;
+TEdgeSegment::TEdgeSegment(this, a2, a3, a4);
+*(_DWORD *)v6 = &TCircle::`vftable';
+*(float *)((char *)v6 + 33) = a6 * a6;
+*(_DWORD *)((char *)v6 + 21) = *(_DWORD *)a5;
+*(_DWORD *)((char *)v6 + 25) = *((_DWORD *)a5 + 1);
+*(_DWORD *)((char *)v6 + 29) = *((_DWORD *)a5 + 2);
+return v6;
+}
+// 1002454: using guessed type void *TCircle::`vftable';
+
+//----- (010158D6) --------------------------------------------------------
+double __thiscall TCircle::FindCollisionDistance(TCircle *this, struct ray_type *a2)
+{
+return ray_intersect_circle((float *)a2, (float *)((char *)this + 21));
+}
+
+//----- (0101CB7C) --------------------------------------------------------
+void __thiscall TCircle::place_in_grid(TCircle *this)
+{
+edges_insert_circle((TCircle *)((char *)this + 21), this, 0);
+}
+
+//----- (0101CC8D) --------------------------------------------------------
+void __thiscall TCircle::EdgeCollision(TCircle *this, struct TBall *a2, float a3)
+{
+TCircle *v3; // esi
+int v4; // edx
+float v5; // [esp+Ch] [ebp-18h]
+float v6; // [esp+10h] [ebp-14h]
+float v7; // [esp+18h] [ebp-Ch]
+float v8; // [esp+1Ch] [ebp-8h]
+
+v3 = this;
+v7 = a3 * *(float *)((char *)a2 + 54) + *(float *)((char *)a2 + 42);
+v8 = a3 * *(float *)((char *)a2 + 58) + *(float *)((char *)a2 + 46);
+v5 = v7 - *(float *)((char *)this + 21);
+v6 = v8 - *(float *)((char *)this + 25);
+normalize_2d(&v5);
+(*(void (__stdcall **)(int, float *, float *, _DWORD, TCircle *))(**((_DWORD **)v3 + 1) + 20))(
+v4,
+&v7,
+&v5,
+LODWORD(a3),
+v3);
+}
diff --git a/Classes/TCollisionComponent/TCollisionComponent.cpp b/Classes/TCollisionComponent/TCollisionComponent.cpp
new file mode 100644
index 0000000..555c3b9
--- /dev/null
+++ b/Classes/TCollisionComponent/TCollisionComponent.cpp
@@ -0,0 +1,415 @@
+#include "../../pinball.h"
+
+//----- (01015A9A) --------------------------------------------------------
+void __thiscall TCollisionComponent::port_draw(TCollisionComponent *this)
+{
+TCollisionComponent *v1; // edi
+int v2; // eax
+int v3; // esi
+int v4; // ebx
+
+v1 = this;
+v2 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4) - 1;
+if ( v2 >= 0 )
+{
+v3 = 4 * v2 + 8;
+v4 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4);
+do
+{
+(*(void (**)(void))(**(_DWORD **)(v3 + *(_DWORD *)((char *)v1 + 46)) + 4))();
+v3 -= 4;
+--v4;
+}
+while ( v4 );
+}
+}
+
+//----- (01017883) --------------------------------------------------------
+double __stdcall basic_collision(struct TBall *a1, struct vector_type *a2, struct vector_type *a3, float a4, float a5, float a6, float a7)
+{
+int v7; // ST30_4
+float *v8; // esi
+double v9; // st7
+unsigned __int8 v11; // c0
+unsigned __int8 v12; // c3
+double v13; // st7
+double v14; // st6
+float v15; // ST1C_4
+float v16; // ST20_4
+float v17; // ST10_4
+float v18; // ST20_4
+double v19; // st7
+float v21; // [esp+24h] [ebp-Ch]
+float v22; // [esp+28h] [ebp-8h]
+float v23; // [esp+3Ch] [ebp+Ch]
+float v24; // [esp+3Ch] [ebp+Ch]
+
+*(float *)((char *)a1 + 42) = *(float *)a2;
+*(_DWORD *)((char *)a1 + 46) = *((_DWORD *)a2 + 1);
+v21 = *(float *)a3;
+v22 = *((float *)a3 + 1);
+v7 = *((_DWORD *)a3 + 2);
+v8 = (float *)((char *)a1 + 54);
+v9 = -(v22 * *(float *)((char *)a1 + 58) + *(float *)a3 * *(float *)((char *)a1 + 54));
+v23 = v9;
+if ( v11 | v12 )
+{
+v23 = -v9;
+}
+else
+{
+v13 = v9 * v21;
+v14 = v22 * v23;
+v15 = v13 + *v8;
+v16 = v14 + *(float *)((char *)a1 + 58);
+v17 = v13 * a4;
+v18 = v16 * a5;
+*v8 = v15 * a5 + v17;
+*(float *)((char *)a1 + 58) = v18 + v14 * a4;
+normalize_2d((float *)((char *)a1 + 54));
+}
+v24 = v23 * *(float *)((char *)a1 + 66);
+v19 = *(float *)((char *)a1 + 66) - (1.0 - a4) * v24;
+*(float *)((char *)a1 + 66) = v19;
+if ( v24 >= (double)a6 )
+{
+*v8 = v19 * *v8 + v21 * a7;
+*(float *)((char *)a1 + 58) = v19 * *(float *)((char *)a1 + 58) + v22 * a7;
+*(float *)((char *)a1 + 66) = normalize_2d((float *)((char *)a1 + 54));
+}
+return v24;
+}
+
+//----- (010179A9) --------------------------------------------------------
+struct TEdgeSegment *__stdcall install_wall(float *a1, struct TCollisionComponent *a2, char *a3, unsigned int a4, float a5, void *a6)
+{
+signed __int64 v6; // rax
+float *v7; // esi
+float *v8; // ecx
+TCircle *v9; // eax
+struct TCollisionComponent *v10; // edi
+float v11; // ST14_4
+TCircle *v12; // esi
+TLine *v13; // eax
+double v14; // st7
+float v15; // eax
+double v16; // st6
+float v17; // eax
+TCircle *v18; // eax
+float v19; // ST10_4
+TCircle *v20; // edi
+int v21; // ebx
+TLine *v22; // eax
+TLine *v23; // esi
+char v25; // [esp+10h] [ebp-6Ch]
+float v26; // [esp+18h] [ebp-64h]
+float v27; // [esp+20h] [ebp-5Ch]
+float v28; // [esp+28h] [ebp-54h]
+float v29; // [esp+2Ch] [ebp-50h]
+float v30; // [esp+30h] [ebp-4Ch]
+float v31; // [esp+34h] [ebp-48h]
+float v32; // [esp+38h] [ebp-44h]
+float v33; // [esp+3Ch] [ebp-40h]
+float v34; // [esp+40h] [ebp-3Ch]
+float v35; // [esp+44h] [ebp-38h]
+int v36; // [esp+48h] [ebp-34h]
+int v37; // [esp+4Ch] [ebp-30h]
+int v38; // [esp+50h] [ebp-2Ch]
+int v39; // [esp+58h] [ebp-24h]
+int v40; // [esp+5Ch] [ebp-20h]
+int v41; // [esp+64h] [ebp-18h]
+float v42; // [esp+68h] [ebp-14h]
+int v43; // [esp+6Ch] [ebp-10h]
+float *v44; // [esp+70h] [ebp-Ch]
+int v45; // [esp+74h] [ebp-8h]
+TCircle *v46; // [esp+78h] [ebp-4h]
+float *v47; // [esp+84h] [ebp+8h]
+
+v6 = (signed __int64)(_floor(*a1) - 1.0);
+v7 = a1 + 1;
+v8 = a1 + 1;
+v45 = v6;
+v44 = a1 + 1;
+if ( !(_DWORD)v6 )
+{
+v41 = *(int *)v7;
+v42 = a1[2];
+v9 = (TCircle *)operator new(0x25u);
+v10 = a2;
+if ( v9 )
+{
+v11 = a5 + a1[3];
+v12 = TCircle::TCircle(v9, a2, a3, a4, (struct vector_type *)&v41, v11);
+}
+else
+{
+v12 = 0;
+}
+v46 = v12;
+if ( !v12 )
+goto LABEL_14;
+*(_DWORD *)((char *)v12 + 13) = a6;
+LABEL_13:
+(*(void (__thiscall **)(TCircle *))(*(_DWORD *)v12 + 8))(v12);
+LABEL_14:
+objlist_class::Add((struct TCollisionComponent *)((char *)v10 + 42), (void *)v12);
+return v46;
+}
+if ( (_DWORD)v6 == 1 )
+{
+v37 = *(_DWORD *)v7;
+v38 = *((_DWORD *)a1 + 2);
+v39 = *((_DWORD *)a1 + 3);
+v40 = *((_DWORD *)a1 + 4);
+v13 = (TLine *)operator new(0x55u);
+v10 = a2;
+if ( v13 )
+v12 = TLine::TLine(v13, a2, a3, a4, (struct vector_type *)&v37, (struct vector_type *)&v39);
+else
+v12 = 0;
+v46 = v12;
+if ( v12 )
+{
+*(_DWORD *)((char *)v12 + 13) = a6;
+TLine::Offset(v12, a5);
+goto LABEL_13;
+}
+}
+else
+{
+*((float *)&v6 + 1) = v7[2 * (_DWORD)v6 - 2];
+v47 = 0;
+v33 = 0.0;
+v34 = *((float *)&v6 + 1);
+v30 = 0.0;
+v35 = v7[2 * (_DWORD)v6 - 1];
+if ( (signed int)v6 > 0 )
+{
+while ( 1 )
+{
+if ( (signed int)v47 >= (signed int)v6 - 1 )
+{
+v14 = *v8;
+v15 = v8[1];
+}
+else
+{
+v14 = v7[2];
+v15 = v7[3];
+}
+v16 = *v7;
+v27 = v15;
+v17 = v7[1];
+*(float *)&v41 = v16;
+v42 = v17;
+if ( 0.0 != a5 )
+{
+if ( (v28 = v16 - v34,
+v29 = v42 - v35,
+v31 = v14 - v16,
+v32 = v27 - v42,
+cross(&v28, &v31, (float *)&v25),
+v26 > 0.0)
+&& a5 > 0.0
+|| v26 < 0.0 && a5 < 0.0 )
+{
+v18 = (TCircle *)operator new(0x25u);
+if ( v18 )
+{
+v19 = a5 * 1.001;
+v20 = TCircle::TCircle(v18, a2, a3, a4, (struct vector_type *)&v41, v19);
+}
+else
+{
+v20 = 0;
+}
+if ( v20 )
+{
+*(_DWORD *)((char *)v20 + 13) = a6;
+(*(void (__thiscall **)(TCircle *))(*(_DWORD *)v20 + 8))(v20);
+objlist_class::Add((struct TCollisionComponent *)((char *)a2 + 42), (void *)v20);
+}
+}
+}
+v37 = *(_DWORD *)v7;
+v38 = *((_DWORD *)v7 + 1);
+v21 = (int)(v7 + 2);
+v39 = *((_DWORD *)v7 + 2);
+v40 = *((_DWORD *)v7 + 3);
+v22 = (TLine *)operator new(0x55u);
+if ( v22 )
+v23 = TLine::TLine(v22, a2, a3, a4, (struct vector_type *)&v37, (struct vector_type *)&v39);
+else
+v23 = 0;
+v46 = v23;
+if ( v23 )
+{
+*(_DWORD *)((char *)v23 + 13) = a6;
+TLine::Offset(v23, a5);
+(*(void (__thiscall **)(TLine *))(*(_DWORD *)v23 + 8))(v23);
+objlist_class::Add((struct TCollisionComponent *)((char *)a2 + 42), (void *)v23);
+}
+v47 = (float *)((char *)v47 + 1);
+v34 = *(float *)&v41;
+v35 = v42;
+v36 = v43;
+v7 = (float *)v21;
+if ( (signed int)v47 >= v45 )
+break;
+v8 = v44;
+LODWORD(v6) = v45;
+}
+}
+}
+return v46;
+}
+
+//----- (01017E85) --------------------------------------------------------
+void __thiscall TCollisionComponent::Collision(TCollisionComponent *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TCollisionComponent *v6; // esi
+double v7; // st7
+int v8; // esi
+
+v6 = this;
+if ( *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 370) )
+{
+basic_collision(a2, a3, a4, *(float *)((char *)this + 54), *(float *)((char *)this + 58), 1000000000.0, 0.0);
+return;
+}
+v7 = basic_collision(
+a2,
+a3,
+a4,
+*(float *)((char *)this + 54),
+*(float *)((char *)this + 58),
+*(float *)((char *)this + 66),
+*(float *)((char *)this + 62));
+if ( v7 <= *(float *)((char *)v6 + 66) )
+{
+if ( v7 <= 0.2 )
+return;
+v8 = *(_DWORD *)((char *)v6 + 70);
+}
+else
+{
+v8 = *(_DWORD *)((char *)v6 + 74);
+}
+if ( v8 )
+loader_play_sound(v8);
+}
+
+//----- (01017F29) --------------------------------------------------------
+int __thiscall TCollisionComponent::DefaultCollision(TCollisionComponent *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4)
+{
+TCollisionComponent *v4; // esi
+double v5; // st7
+int v6; // esi
+int v8; // esi
+
+v4 = this;
+if ( *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 370) )
+{
+basic_collision(a2, a3, a4, *(float *)((char *)this + 54), *(float *)((char *)this + 58), 1000000000.0, 0.0);
+return 0;
+}
+v5 = basic_collision(
+a2,
+a3,
+a4,
+*(float *)((char *)this + 54),
+*(float *)((char *)this + 58),
+*(float *)((char *)this + 66),
+*(float *)((char *)this + 62));
+if ( v5 <= *(float *)((char *)v4 + 66) )
+{
+if ( v5 > 0.2 )
+{
+v8 = *(_DWORD *)((char *)v4 + 70);
+if ( v8 )
+loader_play_sound(v8);
+}
+return 0;
+}
+v6 = *(_DWORD *)((char *)v4 + 74);
+if ( v6 )
+loader_play_sound(v6);
+return 1;
+}
+
+//----- (010190B3) --------------------------------------------------------
+TCollisionComponent *__thiscall TCollisionComponent::TCollisionComponent(TCollisionComponent *this, struct TPinballTable *a2, int a3, int a4)
+{
+TCollisionComponent *v4; // esi
+bool v5; // zf
+float v6; // ST18_4
+unsigned int v7; // ST14_4
+float *v8; // eax
+int v10; // [esp+14h] [ebp-48h]
+int v11; // [esp+18h] [ebp-44h]
+int v12; // [esp+24h] [ebp-38h]
+int v13; // [esp+28h] [ebp-34h]
+int v14; // [esp+2Ch] [ebp-30h]
+int v15; // [esp+44h] [ebp-18h]
+unsigned int v16; // [esp+48h] [ebp-14h]
+
+v4 = this;
+TPinballComponent::TPinballComponent(this, a2, a3, 1);
+*(_DWORD *)v4 = &TCollisionComponent::`vftable';
+objlist_class::objlist_class((TCollisionComponent *)((char *)v4 + 42), 4, 4);
+v5 = *(_DWORD *)((char *)v4 + 10) == 0;
+*((_BYTE *)v4 + 5) = 1;
+if ( !v5 )
+*((_BYTE *)v4 + 4) = 1;
+if ( a3 <= 0 )
+{
+loader_default_vsi(&v10);
+}
+else
+{
+loader_query_visual(a3, 0, &v10);
+if ( a4 )
+{
+v6 = *(float *)((char *)a2 + 282);
+v7 = v16;
+v8 = (float *)loader_query_float_attribute(a3, 0, 600);
+install_wall(v8, v4, (char *)v4 + 5, v7, v6, 0);
+}
+}
+*(_DWORD *)((char *)v4 + 66) = v13;
+*(_DWORD *)((char *)v4 + 54) = v11;
+*(_DWORD *)((char *)v4 + 58) = v10;
+*(_DWORD *)((char *)v4 + 62) = v14;
+*(_DWORD *)((char *)v4 + 74) = v15;
+*(_DWORD *)((char *)v4 + 70) = v12;
+*(_DWORD *)((char *)v4 + 22) = a3;
+return v4;
+}
+// 10024EC: using guessed type void *TCollisionComponent::`vftable';
+
+//----- (01019172) --------------------------------------------------------
+TZmapList *__thiscall TCollisionComponent::~TCollisionComponent(TCollisionComponent *this)
+{
+TCollisionComponent *v1; // esi
+int v2; // eax
+int v3; // eax
+void *v4; // edi
+
+v1 = this;
+v2 = *(_DWORD *)((char *)this + 46);
+*(_DWORD *)this = &TCollisionComponent::`vftable';
+if ( *(_DWORD *)(v2 + 4) )
+{
+do
+{
+v3 = *(_DWORD *)((char *)v1 + 46);
+v4 = *(void **)(v3 + 8);
+objlist_delete_object(*(_DWORD *)((char *)v1 + 46), *(_DWORD *)(v3 + 8));
+operator delete(v4);
+}
+while ( *(_DWORD *)(*(_DWORD *)((char *)v1 + 46) + 4) );
+}
+objlist_destroy(*(_DWORD *)((char *)v1 + 46));
+return TPinballComponent::~TPinballComponent(v1);
+}
+// 10024EC: using guessed type void *TCollisionComponent::`vftable';
diff --git a/Classes/TComponentGroup/TComponentGroup.cpp b/Classes/TComponentGroup/TComponentGroup.cpp
new file mode 100644
index 0000000..0c368b8
--- /dev/null
+++ b/Classes/TComponentGroup/TComponentGroup.cpp
@@ -0,0 +1,58 @@
+#include "../../pinball.h"
+
+//----- (010159DC) --------------------------------------------------------
+void __stdcall TComponentGroup::NotifyTimerExpired(int a1, struct TPinballComponent *a2)
+{
+*(_DWORD *)((char *)a2 + 50) = 0;
+control_handler(61, a2);
+}
+
+//----- (010159F9) --------------------------------------------------------
+int __thiscall TComponentGroup::Message(TComponentGroup *this, int a2, float a3)
+{
+TComponentGroup *v3; // esi
+int v4; // eax
+int v5; // edi
+int v6; // ebx
+
+v3 = this;
+if ( a2 == 48 )
+{
+if ( *(_DWORD *)((char *)this + 50) )
+{
+timer_kill(*(_DWORD *)((char *)this + 50));
+*(_DWORD *)((char *)v3 + 50) = 0;
+}
+if ( a3 > 0.0 )
+*(_DWORD *)((char *)v3 + 50) = timer_set(a3, (int)v3, (int)TComponentGroup::NotifyTimerExpired);
+}
+else if ( a2 <= 1007 || a2 > 1011 && a2 != 1020 && a2 != 1022 )
+{
+v4 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4) - 1;
+if ( v4 >= 0 )
+{
+v5 = 4 * v4 + 8;
+v6 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4);
+do
+{
+(***(void (__stdcall ****)(int, _DWORD))(v5 + *(_DWORD *)((char *)v3 + 46)))(a2, LODWORD(a3));
+v5 -= 4;
+--v6;
+}
+while ( v6 );
+}
+}
+return 0;
+}
+
+//----- (0101AA81) --------------------------------------------------------
+TComponentGroup *__thiscall TComponentGroup::`scalar deleting destructor`(TComponentGroup *this, char a2)
+{
+TComponentGroup *v2; // esi
+
+v2 = this;
+TComponentGroup::~TComponentGroup(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
diff --git a/Classes/TDemo/TDemo.cpp b/Classes/TDemo/TDemo.cpp
new file mode 100644
index 0000000..6224c2d
--- /dev/null
+++ b/Classes/TDemo/TDemo.cpp
@@ -0,0 +1,256 @@
+#include "../../pinball.h"
+
+//----- (01016D62) --------------------------------------------------------
+void __stdcall TDemo::PlungerRelease(int a1, void *a2)
+{
+void (__stdcall ***v2)(signed int, _DWORD); // ecx
+
+v2 = *(void (__stdcall ****)(signed int, _DWORD))((char *)a2 + 30);
+*(_DWORD *)((char *)a2 + 110) = 0;
+(**v2)(1005, LODWORD(time_next));
+}
+// 1025634: using guessed type float time_next;
+
+//----- (01016D8D) --------------------------------------------------------
+void __stdcall TDemo::UnFlipRight(int a1, void *a2)
+{
+if ( *(_DWORD *)((char *)a2 + 98) )
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)a2 + 30))(1003, LODWORD(time_next));
+*(_DWORD *)((char *)a2 + 98) = 0;
+}
+// 1025634: using guessed type float time_next;
+
+//----- (01016DC0) --------------------------------------------------------
+void __stdcall TDemo::UnFlipLeft(int a1, void *a2)
+{
+if ( *(_DWORD *)((char *)a2 + 94) )
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)a2 + 30))(1001, LODWORD(time_next));
+*(_DWORD *)((char *)a2 + 94) = 0;
+}
+// 1025634: using guessed type float time_next;
+
+//----- (01016DF3) --------------------------------------------------------
+void __stdcall TDemo::FlipRight(int a1, void *a2)
+{
+double v2; // st7
+float v3; // ST08_4
+
+if ( !*(_DWORD *)((char *)a2 + 98) )
+{
+if ( *(_DWORD *)((char *)a2 + 106) )
+{
+timer_kill(*(_DWORD *)((char *)a2 + 106));
+*(_DWORD *)((char *)a2 + 106) = 0;
+}
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)a2 + 30))(1002, LODWORD(time_next));
+v2 = *(float *)((char *)a2 + 86) + *(float *)((char *)a2 + 90);
+*(_DWORD *)((char *)a2 + 98) = 1;
+v3 = v2 - (double)_rand() * 0.00003051850947599719 * (*(float *)((char *)a2 + 90) + *(float *)((char *)a2 + 90));
+timer_set(v3, (int)a2, (int)TDemo::UnFlipRight);
+}
+}
+// 1025634: using guessed type float time_next;
+
+//----- (01016E70) --------------------------------------------------------
+void __stdcall TDemo::FlipLeft(int a1, void *a2)
+{
+double v2; // st7
+float v3; // ST08_4
+
+if ( !*(_DWORD *)((char *)a2 + 94) )
+{
+if ( *(_DWORD *)((char *)a2 + 102) )
+{
+timer_kill(*(_DWORD *)((char *)a2 + 102));
+*(_DWORD *)((char *)a2 + 102) = 0;
+}
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)a2 + 30))(1000, LODWORD(time_next));
+v2 = *(float *)((char *)a2 + 86) + *(float *)((char *)a2 + 90);
+*(_DWORD *)((char *)a2 + 94) = 1;
+v3 = v2 - (double)_rand() * 0.00003051850947599719 * (*(float *)((char *)a2 + 90) + *(float *)((char *)a2 + 90));
+timer_set(v3, (int)a2, (int)TDemo::UnFlipLeft);
+}
+}
+// 1025634: using guessed type float time_next;
+
+//----- (01016EED) --------------------------------------------------------
+void __stdcall TDemo::NewGameRestartTimer(int a1, void *a2)
+{
+int v2; // ecx
+float v3; // ST04_4
+
+pb_replay_level(1);
+v2 = *(_DWORD *)((char *)a2 + 30);
+v3 = (double)*(signed int *)(v2 + 214);
+(**(void (__stdcall ***)(signed int, _DWORD))v2)(1014, LODWORD(v3));
+*(_DWORD *)((char *)a2 + 114) = 0;
+}
+
+//----- (01016F21) --------------------------------------------------------
+void __thiscall TDemo::Collision(TDemo *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+int v6; // ebx
+TDemo *v7; // edi
+int v8; // ebx
+double v9; // st7
+int v10; // eax
+int v11; // ebx
+int v12; // ebx
+int v13; // ebx
+float v14; // ST08_4
+double v15; // ST20_8
+float v16; // ST08_4
+double v17; // ST20_8
+float v18; // ST08_4
+
+v6 = *(_DWORD *)((char *)a6 + 13);
+v7 = this;
+TBall::not_again(a2, a6);
+v8 = v6 - 1400;
+v9 = *(float *)((char *)a2 + 70) - a5;
+*(_DWORD *)((char *)a2 + 42) = *(_DWORD *)a3;
+v10 = *((_DWORD *)a3 + 1);
+*(float *)((char *)a2 + 70) = v9;
+*(_DWORD *)((char *)a2 + 46) = v10;
+if ( v8 )
+{
+v11 = v8 - 1;
+if ( v11 )
+{
+v12 = v11 - 1;
+if ( v12 )
+{
+v13 = v12 - 1;
+if ( v13 )
+{
+if ( v13 == 1 && !*(_DWORD *)((char *)v7 + 110) )
+{
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)v7 + 30))(1004, *(float *)((char *)a2 + 78));
+v14 = (double)_rand() * 0.00003051850947599719 + 2.0;
+*(_DWORD *)((char *)v7 + 110) = timer_set(v14, (int)v7, (int)TDemo::PlungerRelease);
+}
+}
+else
+{
+TDemo::FlipRight(0, (void *)v7);
+}
+}
+else if ( !*(_DWORD *)((char *)v7 + 106) && !*(_DWORD *)((char *)v7 + 98) )
+{
+v15 = *(float *)((char *)v7 + 78) + *(float *)((char *)v7 + 82);
+v16 = v15
+- (double)_rand() * 0.00003051850947599719 * (*(float *)((char *)v7 + 82) + *(float *)((char *)v7 + 82));
+*(_DWORD *)((char *)v7 + 106) = timer_set(v16, (int)v7, (int)TDemo::FlipRight);
+}
+}
+else
+{
+TDemo::FlipLeft(0, (void *)v7);
+}
+}
+else if ( !*(_DWORD *)((char *)v7 + 102) && !*(_DWORD *)((char *)v7 + 94) )
+{
+v17 = *(float *)((char *)v7 + 78) + *(float *)((char *)v7 + 82);
+v18 = v17 - (double)_rand() * 0.00003051850947599719 * (*(float *)((char *)v7 + 82) + *(float *)((char *)v7 + 82));
+*(_DWORD *)((char *)v7 + 102) = timer_set(v18, (int)v7, (int)TDemo::FlipLeft);
+}
+}
+
+//----- (01017074) --------------------------------------------------------
+int __thiscall TDemo::Message(TDemo *this, int a2, float a3)
+{
+TDemo *v3; // esi
+int v4; // eax
+bool v5; // zf
+
+v3 = this;
+switch ( a2 )
+{
+case 1014:
+if ( *(_DWORD *)((char *)this + 114) )
+timer_kill(*(_DWORD *)((char *)this + 114));
+*(_DWORD *)((char *)v3 + 114) = 0;
+break;
+case 1022:
+if ( *(_DWORD *)((char *)this + 114) )
+timer_kill(*(_DWORD *)((char *)this + 114));
+v5 = *((_BYTE *)v3 + 5) == 0;
+*(_DWORD *)((char *)v3 + 114) = 0;
+if ( !v5 )
+*(_DWORD *)((char *)v3 + 114) = timer_set(5.0, (int)v3, (int)TDemo::NewGameRestartTimer);
+break;
+case 1024:
+if ( *(_DWORD *)((char *)this + 102) )
+timer_kill(*(_DWORD *)((char *)this + 102));
+v4 = *(_DWORD *)((char *)v3 + 106);
+*(_DWORD *)((char *)v3 + 102) = 0;
+if ( v4 )
+timer_kill(v4);
+v5 = *(_DWORD *)((char *)v3 + 94) == 0;
+*(_DWORD *)((char *)v3 + 106) = 0;
+if ( !v5 )
+TDemo::UnFlipLeft(0, (void *)v3);
+if ( *(_DWORD *)((char *)v3 + 98) )
+TDemo::UnFlipRight(0, (void *)v3);
+if ( *(_DWORD *)((char *)v3 + 110) )
+TDemo::PlungerRelease(0, (void *)v3);
+break;
+}
+return 0;
+}
+
+//----- (0101A2B5) --------------------------------------------------------
+TDemo *__thiscall TDemo::TDemo(TDemo *this, struct TPinballTable *a2, int a3)
+{
+TDemo *v3; // esi
+_DWORD *v4; // eax
+float *v5; // eax
+float *v6; // eax
+float *v7; // eax
+float *v8; // eax
+float *v9; // eax
+char v11; // [esp+14h] [ebp-48h]
+unsigned int v12; // [esp+48h] [ebp-14h]
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 0);
+*(_DWORD *)v3 = &TDemo::`vftable';
+*(_DWORD *)((char *)v3 + 114) = 0;
+*(_DWORD *)((char *)v3 + 110) = 0;
+*(_DWORD *)((char *)v3 + 102) = 0;
+*(_DWORD *)((char *)v3 + 106) = 0;
+*(_DWORD *)((char *)v3 + 6) = 0;
+*((_BYTE *)v3 + 4) = 0;
+*((_BYTE *)v3 + 5) = 0;
+*(_DWORD *)((char *)v3 + 98) = 0;
+*(_DWORD *)((char *)v3 + 94) = 0;
+*(_DWORD *)((char *)a2 + 230) = v3;
+v4 = (_DWORD *)loader_query_float_attribute(a3, 0, 407);
+if ( v4 )
+{
+*(_DWORD *)((char *)v3 + 78) = *v4;
+*(_DWORD *)((char *)v3 + 82) = v4[1];
+*(_DWORD *)((char *)v3 + 86) = v4[2];
+*(_DWORD *)((char *)v3 + 90) = v4[3];
+}
+else
+{
+*(float *)((char *)v3 + 78) = 0.2;
+*(float *)((char *)v3 + 82) = 0.1;
+*(float *)((char *)v3 + 86) = 0.2;
+*(float *)((char *)v3 + 90) = 0.1;
+}
+loader_query_visual(a3, 0, &v11);
+v5 = (float *)loader_query_float_attribute(a3, 0, 1400);
+*(_DWORD *)((char *)v3 + 118) = install_wall(v5, v3, (char *)v3 + 5, v12, 0.0, (void *)0x578);
+v6 = (float *)loader_query_float_attribute(a3, 0, 1401);
+install_wall(v6, v3, (char *)v3 + 5, v12, 0.0, (void *)0x579);
+v7 = (float *)loader_query_float_attribute(a3, 0, 1402);
+*(_DWORD *)((char *)v3 + 122) = install_wall(v7, v3, (char *)v3 + 5, v12, 0.0, (void *)0x57A);
+v8 = (float *)loader_query_float_attribute(a3, 0, 1403);
+install_wall(v8, v3, (char *)v3 + 5, v12, 0.0, (void *)0x57B);
+v9 = (float *)loader_query_float_attribute(a3, 0, 1404);
+*(_DWORD *)((char *)v3 + 126) = install_wall(v9, v3, (char *)v3 + 5, v12, *(float *)((char *)a2 + 282), (void *)0x57C);
+return v3;
+}
+// 10026E8: using guessed type void *TDemo::`vftable';
diff --git a/Classes/TDrain/TDrain.cpp b/Classes/TDrain/TDrain.cpp
new file mode 100644
index 0000000..07091b6
--- /dev/null
+++ b/Classes/TDrain/TDrain.cpp
@@ -0,0 +1,51 @@
+#include "../../pinball.h"
+
+//----- (010172A3) --------------------------------------------------------
+int __thiscall TDrain::Message(TDrain *this, int a2, float a3)
+{
+TDrain *v3; // esi
+
+v3 = this;
+if ( a2 == 1024 )
+{
+if ( *(_DWORD *)((char *)this + 86) )
+{
+timer_kill(*(_DWORD *)((char *)this + 86));
+*(_DWORD *)((char *)v3 + 86) = 0;
+}
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 78) = 0;
+}
+return 0;
+}
+
+//----- (010172D8) --------------------------------------------------------
+void __stdcall TDrain::TimerCallback(int a1, struct TPinballComponent *a2)
+{
+control_handler(60, a2);
+}
+
+//----- (01018562) --------------------------------------------------------
+void __thiscall TDrain::Collision(TDrain *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TDrain *v6; // esi
+
+v6 = this;
+(**(void (__stdcall ***)(signed int, _DWORD))a2)(1024, 0.0);
+*(_DWORD *)(*(_DWORD *)((char *)v6 + 30) + 78) = 1;
+*(_DWORD *)((char *)v6 + 86) = timer_set(*(float *)((char *)v6 + 78), (int)v6, (int)TDrain::TimerCallback);
+control_handler(63, v6);
+}
+
+//----- (0101A4B4) --------------------------------------------------------
+TDrain *__thiscall TDrain::TDrain(TDrain *this, struct TPinballTable *a2, int a3)
+{
+TDrain *v3; // esi
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+*(_DWORD *)((char *)v3 + 86) = 0;
+*(_DWORD *)v3 = &TDrain::`vftable';
+*(_DWORD *)((char *)v3 + 78) = *(_DWORD *)loader_query_float_attribute(a3, 0, 407);
+return v3;
+}
+// 1002720: using guessed type void *TDrain::`vftable';
diff --git a/Classes/TEdgeBox/TEdgeBox.cpp b/Classes/TEdgeBox/TEdgeBox.cpp
new file mode 100644
index 0000000..2119a12
--- /dev/null
+++ b/Classes/TEdgeBox/TEdgeBox.cpp
@@ -0,0 +1,54 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "TEdgeBox.h"
+
+//----- (0100B0D1) --------------------------------------------------------
+TEdgeBox *__thiscall TEdgeBox::TEdgeBox(TEdgeBox *this)
+{
+ TEdgeBox *v1; // esi
+
+ v1 = this;
+ objlist_class::objlist_class(this, 0, 4);
+ objlist_class::objlist_class((TEdgeBox *)((char *)v1 + 8), 0, 1);
+ return v1;
+}
+
+//----- (0100B2C9) --------------------------------------------------------
+void __thiscall TEdgeBox::~TEdgeBox(TEdgeBox *this)
+{
+ TEdgeBox *v1; // esi
+
+ v1 = this;
+ objlist_destroy(*((_DWORD *)this + 3));
+ objlist_destroy(*((_DWORD *)v1 + 1));
+}
+
+//----- (0100B90E) --------------------------------------------------------
+TEdgeBox *__thiscall TEdgeBox::`vector deleting destructor'(TEdgeBox *this, char a2)
+{
+TEdgeBox *v2; // edi
+TEdgeBox *result; // eax
+
+v2 = this;
+if ( a2 & 2 )
+{
+`vector destructor iterator'(
+(void *)this,
+0x10u,
+*((_DWORD *)this - 1),
+(void (__thiscall *)(void *))TEdgeBox::~TEdgeBox);
+if ( a2 & 1 )
+operator delete((char *)v2 - 4);
+result = (TEdgeBox *)((char *)v2 - 4);
+}
+else
+{
+TEdgeBox::~TEdgeBox(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+result = v2;
+}
+return result;
+}
diff --git a/Classes/TEdgeBox/TEdgeBox.h b/Classes/TEdgeBox/TEdgeBox.h
new file mode 100644
index 0000000..cb43d76
--- /dev/null
+++ b/Classes/TEdgeBox/TEdgeBox.h
@@ -0,0 +1,8 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_TEDGEBOX_H
+#define PINBALL_TEDGEBOX_H
+
+#endif //PINBALL_TEDGEBOX_H
diff --git a/Classes/TEdgeManager/TEdgeManager.cpp b/Classes/TEdgeManager/TEdgeManager.cpp
new file mode 100644
index 0000000..683421f
--- /dev/null
+++ b/Classes/TEdgeManager/TEdgeManager.cpp
@@ -0,0 +1,541 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "TEdgeManager.h"
+
+//----- (0100B0F4) --------------------------------------------------------
+signed __int64 __thiscall TEdgeManager::box_x(TEdgeManager *this, float a2)
+{
+TEdgeManager *v2; // esi
+double v3; // st7
+double v4; // st7
+double v6; // [esp+Ch] [ebp-8h]
+double v7; // [esp+Ch] [ebp-8h]
+
+v2 = this;
+v6 = (double)(*((_DWORD *)this + 4) - 1);
+if ( _floor((a2 - *((float *)this + 6)) * *((float *)this + 2)) >= v6 )
+v3 = v6;
+else
+v3 = _floor((a2 - *((float *)v2 + 6)) * *((float *)v2 + 2));
+if ( v3 <= 0.0 )
+{
+v4 = 0.0;
+}
+else
+{
+v7 = (double)(*((_DWORD *)v2 + 4) - 1);
+if ( _floor((a2 - *((float *)v2 + 6)) * *((float *)v2 + 2)) >= v7 )
+v4 = v7;
+else
+v4 = _floor((a2 - *((float *)v2 + 6)) * *((float *)v2 + 2));
+}
+return (signed __int64)v4;
+}
+
+//----- (0100B1AE) --------------------------------------------------------
+signed __int64 __thiscall TEdgeManager::box_y(TEdgeManager *this, float a2)
+{
+TEdgeManager *v2; // esi
+double v3; // st7
+double v4; // st7
+double v6; // [esp+Ch] [ebp-8h]
+double v7; // [esp+Ch] [ebp-8h]
+
+v2 = this;
+v6 = (double)(*((_DWORD *)this + 5) - 1);
+if ( _floor((a2 - *((float *)this + 7)) * *((float *)this + 3)) >= v6 )
+v3 = v6;
+else
+v3 = _floor((a2 - *((float *)v2 + 7)) * *((float *)v2 + 3));
+if ( v3 <= 0.0 )
+{
+v4 = 0.0;
+}
+else
+{
+v7 = (double)(*((_DWORD *)v2 + 5) - 1);
+if ( _floor((a2 - *((float *)v2 + 7)) * *((float *)v2 + 3)) >= v7 )
+v4 = v7;
+else
+v4 = _floor((a2 - *((float *)v2 + 7)) * *((float *)v2 + 3));
+}
+return (signed __int64)v4;
+}
+
+//----- (0100B268) --------------------------------------------------------
+int __thiscall TEdgeManager::increment_box_x(TEdgeManager *this, int a2)
+{
+int result; // eax
+
+result = *((_DWORD *)this + 4) - 1;
+if ( a2 + 1 < result )
+result = a2 + 1;
+return result;
+}
+
+//----- (0100B284) --------------------------------------------------------
+int __thiscall TEdgeManager::increment_box_y(TEdgeManager *this, int a2)
+{
+int result; // eax
+
+result = *((_DWORD *)this + 5) - 1;
+if ( a2 + 1 < result )
+result = a2 + 1;
+return result;
+}
+
+
+//----- (0100B2A0) --------------------------------------------------------
+void __stdcall `vector constructor iterator`(void *a1, unsigned int a2, int a3, void *(__thiscall *a4)(void *))
+{
+char *v4; // esi
+int v5; // edi
+
+if ( a3 - 1 >= 0 )
+{
+v4 = (char *)a1;
+v5 = a3;
+do
+{
+a4(v4);
+v4 += a2;
+--v5;
+}
+while ( v5 );
+}
+}
+
+//----- (0100B2E5) --------------------------------------------------------
+void __stdcall `vector destructor iterator`(void *a1, unsigned int a2, int a3, void (__thiscall *a4)(void *))
+{
+char *v4; // edi
+int v5; // esi
+
+v4 = (char *)a1 + a3 * a2;
+if ( a3 - 1 >= 0 )
+{
+v5 = a3;
+do
+{
+v4 -= a2;
+a4(v4);
+--v5;
+}
+while ( v5 );
+}
+}
+
+//----- (0100B316) --------------------------------------------------------
+void __thiscall TEdgeManager::FieldEffects(TEdgeManager *this, struct TBall *a2, struct vector_type *a3)
+{
+struct TBall *v3; // ebx
+TEdgeManager *v4; // edi
+int v5; // eax
+int v6; // esi
+int v7; // eax
+int v8; // edi
+int v9; // eax
+char v10; // [esp+10h] [ebp-Ch]
+struct TBall *v11; // [esp+24h] [ebp+8h]
+
+v3 = a2;
+v4 = this;
+v5 = TEdgeManager::box_x(this, *(float *)((char *)a2 + 42));
+v6 = *((_DWORD *)v4 + 8)
+ + 16 * (v5 + (unsigned __int64)TEdgeManager::box_y(v4, *(float *)((char *)a2 + 46)) * *((_DWORD *)v4 + 4));
+v7 = *(_DWORD *)(*(_DWORD *)(v6 + 12) + 4) - 1;
+if ( v7 >= 0 )
+{
+v8 = 4 * v7 + 8;
+v11 = *(struct TBall **)(*(_DWORD *)(v6 + 12) + 4);
+do
+{
+v9 = *(_DWORD *)(v8 + *(_DWORD *)(v6 + 12));
+if ( **(_BYTE **)v9 && *(_DWORD *)((_BYTE *)v3 + 110) & *(_DWORD *)(v9 + 4) )
+{
+if ( (*(int (__thiscall **)(_DWORD, struct TBall *, char *))(**(_DWORD **)(v9 + 8) + 24))(
+*(_DWORD *)(v9 + 8),
+v3,
+&v10) )
+{
+vector_add(a3, (struct vector_type *)&v10);
+}
+}
+v8 -= 4;
+v11 = (struct TBall *)((char *)v11 - 1);
+}
+while ( v11 );
+}
+}
+
+//----- (0100B3AE) --------------------------------------------------------
+int __userpurge TEdgeManager::TestGridBox@(TEdgeManager *this@, double a2@, int a3, int a4, float *a5, struct TEdgeSegment **a6, struct ray_type *a7, struct TBall *a8, int a9)
+{
+int v9; // edi
+int v10; // eax
+int **v11; // ebx
+int *v12; // esi
+int v13; // eax
+int v14; // eax
+int v16; // [esp+8h] [ebp+8h]
+int v17; // [esp+Ch] [ebp+Ch]
+
+if ( a3 >= 0 && a3 < 10 && a4 >= 0 && a4 < 15 )
+{
+v9 = *((_DWORD *)this + 8) + 16 * (a3 + a4 * *((_DWORD *)this + 4));
+v10 = *(_DWORD *)(*(_DWORD *)(v9 + 4) + 4) - 1;
+if ( v10 >= 0 )
+{
+v17 = 4 * v10 + 8;
+v11 = (int **)((char *)this + 4 * a9 + 36);
+v16 = *(_DWORD *)(*(_DWORD *)(v9 + 4) + 4);
+do
+{
+v12 = *(int **)(v17 + *(_DWORD *)(v9 + 4));
+if ( !*((_BYTE *)v12 + 12) )
+{
+if ( *(_BYTE *)v12[2] )
+{
+if ( *(int *)((char *)v12 + 17) & *((_DWORD *)a7 + 10) )
+{
+LOBYTE(v13) = TBall::already_hit(a8, (struct TEdgeSegment *)v12);
+if ( !v13 )
+{
+++a9;
+*v11 = v12;
+v14 = *v12;
+++v11;
+*((_BYTE *)v12 + 12) = 1;
+(*(void (__thiscall **)(int *, struct ray_type *))(v14 + 12))(v12, a7);
+if ( a2 < *a5 )
+{
+*a5 = a2;
+*a6 = (struct TEdgeSegment *)v12;
+}
+}
+}
+}
+}
+v17 -= 4;
+--v16;
+}
+while ( v16 );
+}
+}
+return a9;
+}
+
+//----- (0100B486) --------------------------------------------------------
+double __thiscall TEdgeManager::FindCollisionDistance(TEdgeManager *this, struct ray_type *a2, struct TBall *a3, struct TEdgeSegment **a4)
+{
+struct ray_type *v4; // esi
+float *v5; // edi
+int v6; // ebx
+double v7; // st7
+float v8; // ST18_4
+double v9; // st7
+float v10; // ST18_4
+double v11; // st7
+int v12; // eax
+int v13; // eax
+int v14; // eax
+int v15; // ecx
+int v16; // eax
+int v17; // eax
+double v18; // st7
+double v19; // st7
+double v20; // st7
+double v21; // st7
+double v22; // st6
+double v23; // st7
+double v24; // st6
+double v25; // st7
+double v26; // st6
+double v27; // st7
+double v28; // st6
+int *v29; // eax
+int v30; // ecx
+signed int v32; // [esp+10h] [ebp-28h]
+float v33; // [esp+14h] [ebp-24h]
+float v34; // [esp+14h] [ebp-24h]
+signed int v35; // [esp+18h] [ebp-20h]
+float v36; // [esp+1Ch] [ebp-1Ch]
+float v37; // [esp+1Ch] [ebp-1Ch]
+int v38; // [esp+20h] [ebp-18h]
+int v39; // [esp+20h] [ebp-18h]
+int v40; // [esp+20h] [ebp-18h]
+int v41; // [esp+20h] [ebp-18h]
+int v42; // [esp+24h] [ebp-14h]
+int v43; // [esp+24h] [ebp-14h]
+int v44; // [esp+28h] [ebp-10h]
+int v45; // [esp+2Ch] [ebp-Ch]
+float v46; // [esp+30h] [ebp-8h]
+int v47; // [esp+34h] [ebp-4h]
+float v48; // [esp+40h] [ebp+8h]
+struct ray_type *v49; // [esp+40h] [ebp+8h]
+struct ray_type *v50; // [esp+40h] [ebp+8h]
+struct ray_type *v51; // [esp+40h] [ebp+8h]
+
+v4 = a2;
+v48 = *(float *)a2;
+v5 = (float *)this;
+v46 = 1000000000.0;
+v6 = 0;
+v42 = TEdgeManager::box_x(this, v48);
+v47 = *((int *)v4 + 1);
+v38 = TEdgeManager::box_y((TEdgeManager *)v5, *(float *)&v47);
+v7 = *((float *)v4 + 3) * *((float *)v4 + 6) + *(float *)v4;
+v36 = v7;
+v8 = v7;
+v45 = TEdgeManager::box_x((TEdgeManager *)v5, v8);
+v9 = *((float *)v4 + 4) * *((float *)v4 + 6) + *((float *)v4 + 1);
+v33 = v9;
+v10 = v9;
+v44 = TEdgeManager::box_y((TEdgeManager *)v5, v10);
+if ( v48 >= (double)v36 )
+v32 = -1;
+else
+v32 = 1;
+v11 = *(float *)&v47;
+if ( *(float *)&v47 >= (double)v33 )
+v35 = -1;
+else
+v35 = 1;
+v12 = v38;
+if ( v38 == v44 )
+{
+v49 = (struct ray_type *)v42;
+if ( v32 == 1 )
+{
+if ( v42 <= v45 )
+{
+while ( 1 )
+{
+v13 = TEdgeManager::TestGridBox((TEdgeManager *)v5, v11, (int)v49, v12, &v46, a4, v4, a3, v6);
+v49 = (struct ray_type *)((char *)v49 + 1);
+v6 = v13;
+if ( (signed int)v49 > v45 )
+break;
+v12 = v38;
+}
+}
+}
+else if ( v42 >= v45 )
+{
+while ( 1 )
+{
+v14 = TEdgeManager::TestGridBox((TEdgeManager *)v5, v11, (int)v49, v12, &v46, a4, v4, a3, v6);
+v49 = (struct ray_type *)((char *)v49 - 1);
+v6 = v14;
+if ( (signed int)v49 < v45 )
+break;
+v12 = v38;
+}
+}
+}
+else
+{
+v15 = v42;
+if ( v42 == v45 )
+{
+v50 = (struct ray_type *)v38;
+if ( v35 == 1 )
+{
+if ( v38 <= v44 )
+{
+while ( 1 )
+{
+v16 = TEdgeManager::TestGridBox((TEdgeManager *)v5, v11, v15, (int)v50, &v46, a4, v4, a3, v6);
+v50 = (struct ray_type *)((char *)v50 + 1);
+v6 = v16;
+if ( (signed int)v50 > v44 )
+break;
+v15 = v42;
+}
+}
+}
+else if ( v38 >= v44 )
+{
+while ( 1 )
+{
+v17 = TEdgeManager::TestGridBox((TEdgeManager *)v5, v11, v15, (int)v50, &v46, a4, v4, a3, v6);
+v50 = (struct ray_type *)((char *)v50 - 1);
+v6 = v17;
+if ( (signed int)v50 < v44 )
+break;
+v15 = v42;
+}
+}
+}
+else
+{
+v18 = (*(float *)&v47 - v33) / (v48 - v36);
+v37 = v18;
+v19 = v18 * v48;
+v51 = (struct ray_type *)v42;
+v20 = *(float *)&v47 - v19;
+v47 = v38;
+v34 = v20;
+v6 = TEdgeManager::TestGridBox((TEdgeManager *)v5, v20, v42, v38, &v46, a4, v4, a3, 0);
+if ( v32 == 1 )
+{
+if ( v35 == 1 )
+{
+v43 = v42 + 1;
+v39 = v38 + 1;
+do
+{
+v21 = (double)v39 * v5[1] + v5[7];
+v22 = ((double)v43 * *v5 + v5[6]) * v37 + v34;
+if ( v22 >= v21 )
+{
+if ( v22 == v21 )
+{
+v51 = (struct ray_type *)((char *)v51 + 1);
+++v43;
+}
+++v47;
+++v39;
+}
+else
+{
+v51 = (struct ray_type *)((char *)v51 + 1);
+++v43;
+}
+v6 = TEdgeManager::TestGridBox((TEdgeManager *)v5, v21, (int)v51, v47, &v46, a4, v4, a3, v6);
+}
+while ( (signed int)v51 < v45 || v47 < v44 );
+}
+else
+{
+v40 = v42 + 1;
+do
+{
+v23 = (double)v47 * v5[1] + v5[7];
+v24 = ((double)v40 * *v5 + v5[6]) * v37 + v34;
+if ( v24 <= v23 )
+{
+if ( v24 == v23 )
+{
+v51 = (struct ray_type *)((char *)v51 + 1);
+++v40;
+}
+--v47;
+}
+else
+{
+v51 = (struct ray_type *)((char *)v51 + 1);
+++v40;
+}
+v6 = TEdgeManager::TestGridBox((TEdgeManager *)v5, v23, (int)v51, v47, &v46, a4, v4, a3, v6);
+}
+while ( (signed int)v51 < v45 || v47 > v44 );
+}
+}
+else if ( v35 == 1 )
+{
+v41 = v38 + 1;
+do
+{
+v25 = (double)v41 * v5[1] + v5[7];
+v26 = ((double)(signed int)v51 * *v5 + v5[6]) * v37 + v34;
+if ( v26 >= v25 )
+{
+if ( v26 == v25 )
+v51 = (struct ray_type *)((char *)v51 - 1);
+++v47;
+++v41;
+}
+else
+{
+v51 = (struct ray_type *)((char *)v51 - 1);
+}
+v6 = TEdgeManager::TestGridBox((TEdgeManager *)v5, v25, (int)v51, v47, &v46, a4, v4, a3, v6);
+}
+while ( (signed int)v51 > v45 || v47 < v44 );
+}
+else
+{
+do
+{
+v27 = (double)v47 * v5[1] + v5[7];
+v28 = ((double)(signed int)v51 * *v5 + v5[6]) * v37 + v34;
+if ( v28 <= v27 )
+{
+if ( v28 == v27 )
+v51 = (struct ray_type *)((char *)v51 - 1);
+--v47;
+}
+else
+{
+v51 = (struct ray_type *)((char *)v51 - 1);
+}
+v6 = TEdgeManager::TestGridBox((TEdgeManager *)v5, v27, (int)v51, v47, &v46, a4, v4, a3, v6);
+}
+while ( (signed int)v51 > v45 || v47 > v44 );
+}
+}
+}
+if ( v6 > 0 )
+{
+v29 = (int *)(v5 + 9);
+do
+{
+v30 = *v29;
+++v29;
+--v6;
+*(_BYTE *)(v30 + 12) = 0;
+}
+while ( v6 );
+}
+return v46;
+}
+
+//----- (0100B883) --------------------------------------------------------
+TEdgeManager *__thiscall TEdgeManager::TEdgeManager(TEdgeManager *this, float a2, float a3, float a4, float a5)
+{
+double v5; // st7
+TEdgeManager *v6; // esi
+double v7; // st6
+_DWORD *v8; // eax
+int v9; // edi
+
+v5 = a4 * 0.1;
+v6 = this;
+*((float *)this + 6) = a2;
+*(float *)this = v5;
+v7 = a5 * 0.06666667;
+*((float *)this + 7) = a3;
+*((_DWORD *)this + 4) = 10;
+*((float *)this + 1) = v7;
+*((_DWORD *)this + 5) = 15;
+*((float *)this + 2) = 1.0 / v5;
+*((float *)this + 3) = 1.0 / v7;
+v8 = operator new(0x964u);
+if ( v8 )
+{
+v9 = (int)(v8 + 1);
+*v8 = 150;
+`vector constructor iterator`(v8 + 1, 0x10u, 150, (void *(__thiscall *)(void *))TEdgeBox::TEdgeBox);
+}
+else
+{
+v9 = 0;
+}
+*((_DWORD *)v6 + 8) = v9;
+return v6;
+}
+
+//----- (01017441) --------------------------------------------------------
+TEdgeManager *__thiscall TEdgeManager::`scalar deleting destructor`(TEdgeManager *this, char a2)
+{
+TEdgeManager *v2; // esi
+
+v2 = this;
+TEdgeManager::~TEdgeManager(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
diff --git a/Classes/TEdgeManager/TEdgeManager.h b/Classes/TEdgeManager/TEdgeManager.h
new file mode 100644
index 0000000..93ed24a
--- /dev/null
+++ b/Classes/TEdgeManager/TEdgeManager.h
@@ -0,0 +1,8 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_TEDGEMANAGER_H
+#define PINBALL_TEDGEMANAGER_H
+
+#endif //PINBALL_TEDGEMANAGER_H
diff --git a/Classes/TEdgeSegment/TEdgeSegment.cpp b/Classes/TEdgeSegment/TEdgeSegment.cpp
new file mode 100644
index 0000000..c2170fa
--- /dev/null
+++ b/Classes/TEdgeSegment/TEdgeSegment.cpp
@@ -0,0 +1,16 @@
+#include "../../pinball.h"
+
+//----- (01015866) --------------------------------------------------------
+TEdgeSegment *__thiscall TEdgeSegment::TEdgeSegment(TEdgeSegment *this, struct TCollisionComponent *a2, char *a3, unsigned int a4)
+{
+TEdgeSegment *result; // eax
+
+result = this;
+*((_DWORD *)this + 1) = a2;
+*((_DWORD *)this + 2) = a3;
+*(_DWORD *)this = &TEdgeSegment::`vftable';
+*(_DWORD *)((char *)this + 17) = a4;
+*((_BYTE *)this + 12) = 0;
+return result;
+}
+// 1002444: using guessed type void *TEdgeSegment::`vftable';
diff --git a/Classes/TFlagSpinner/TFlagSpinner.cpp b/Classes/TFlagSpinner/TFlagSpinner.cpp
new file mode 100644
index 0000000..c75f9f1
--- /dev/null
+++ b/Classes/TFlagSpinner/TFlagSpinner.cpp
@@ -0,0 +1,194 @@
+#include "../../pinball.h"
+
+//----- (01015F34) --------------------------------------------------------
+void __stdcall TFlagSpinner::SpinTimer(int a1, void *a2)
+{
+*(_DWORD *)((char *)a2 + 102) = 0;
+TFlagSpinner::NextFrame((TFlagSpinner *)a2);
+}
+
+//----- (01015F4E) --------------------------------------------------------
+void __thiscall TFlagSpinner::NextFrame(TFlagSpinner *this)
+{
+TFlagSpinner *v1; // esi
+int v2; // eax
+int v3; // edx
+int v4; // ecx
+int v5; // edi
+double v6; // st7
+int v7; // et1
+char v9; // c0
+float v10; // ST0C_4
+
+v1 = this;
+*(_DWORD *)((char *)v1 + 98) += *(_DWORD *)((char *)this + 94);
+v2 = *(_DWORD *)((char *)this + 34);
+v3 = *(_DWORD *)((char *)this + 98);
+v4 = *(_DWORD *)(*(_DWORD *)(v2 + 4) + 4);
+if ( v3 < v4 )
+{
+if ( v3 < 0 )
+*(_DWORD *)((char *)v1 + 98) = v4 - 1;
+}
+else
+{
+*(_DWORD *)((char *)v1 + 98) = 0;
+}
+v5 = *(_DWORD *)(*(_DWORD *)(v2 + 4) + 4 * *(_DWORD *)((char *)v1 + 98) + 8);
+if ( !*(_DWORD *)(*(_DWORD *)((char *)v1 + 30) + 370) )
+{
+control_handler(63, v1);
+if ( *(_DWORD *)((char *)v1 + 70) )
+loader_play_sound(*(_DWORD *)((char *)v1 + 70));
+if ( !*(_DWORD *)((char *)v1 + 98) )
+control_handler(62, v1);
+}
+render_sprite_set(
+*(_DWORD **)((char *)v1 + 26),
+v5,
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v1 + 38) + 4) + 4 * *(_DWORD *)((char *)v1 + 98) + 8),
+*(_DWORD *)(v5 + 29) - *(_DWORD *)(*(_DWORD *)((char *)v1 + 30) + 234),
+*(_DWORD *)(v5 + 33) - *(_DWORD *)(*(_DWORD *)((char *)v1 + 30) + 238));
+v6 = *(float *)((char *)v1 + 90) * *(float *)((char *)v1 + 78);
+v7 = *(_DWORD *)((char *)v1 + 86);
+*(float *)((char *)v1 + 78) = v6;
+if ( !v9 )
+{
+v10 = 1.0 / v6;
+timer_set(v10, (int)v1, (int)TFlagSpinner::SpinTimer);
+}
+}
+
+//----- (01016014) --------------------------------------------------------
+int __thiscall TFlagSpinner::Message(TFlagSpinner *this, int a2, float a3)
+{
+TFlagSpinner *v3; // esi
+int v4; // eax
+
+v3 = this;
+if ( a2 == 1024 )
+{
+if ( *(_DWORD *)((char *)this + 102) )
+{
+timer_kill(*(_DWORD *)((char *)this + 102));
+*(_DWORD *)((char *)v3 + 102) = 0;
+}
+*(_DWORD *)((char *)v3 + 98) = 0;
+v4 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 34) + 4) + 8);
+render_sprite_set(
+*(_DWORD **)((char *)v3 + 26),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 34) + 4) + 8),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 38) + 4) + 8),
+*(_DWORD *)(v4 + 29) - *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 234),
+*(_DWORD *)(v4 + 33) - *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 238));
+}
+return 0;
+}
+
+//----- (01016078) --------------------------------------------------------
+int __thiscall TFlagSpinner::get_scoring(TFlagSpinner *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 2 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 110);
+return result;
+}
+
+//----- (01016096) --------------------------------------------------------
+void __thiscall TFlagSpinner::put_scoring(TFlagSpinner *this, int a2, int a3)
+{
+if ( a2 < 2 )
+*(_DWORD *)((char *)this + 4 * a2 + 110) = a3;
+}
+
+//----- (01018150) --------------------------------------------------------
+void __thiscall TFlagSpinner::Collision(TFlagSpinner *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+int v6; // eax
+TFlagSpinner *v7; // edi
+
+*(float *)((char *)a2 + 42) = *(float *)a3;
+v6 = *((_DWORD *)a3 + 1);
+v7 = this;
+*(float *)((char *)a2 + 70) = *(float *)((char *)a2 + 70) - a5;
+*(_DWORD *)((char *)a2 + 46) = v6;
+TBall::not_again(a2, a6);
+*(_DWORD *)((char *)v7 + 94) = 2 * (*(_DWORD *)((char *)v7 + 106) != (_DWORD)a6) - 1;
+if ( *(float *)((char *)a2 + 66) == 0.0 )
+*(_DWORD *)((char *)v7 + 78) = *(_DWORD *)((char *)v7 + 86);
+else
+*(float *)((char *)v7 + 78) = *(float *)((char *)a2 + 66) * 20.0;
+if ( *(float *)((char *)v7 + 78) < (double)*(float *)((char *)v7 + 86) )
+*(_DWORD *)((char *)v7 + 78) = *(_DWORD *)((char *)v7 + 86);
+if ( *(float *)((char *)v7 + 78) > (double)*(float *)((char *)v7 + 82) )
+*(_DWORD *)((char *)v7 + 78) = *(_DWORD *)((char *)v7 + 82);
+TFlagSpinner::NextFrame(v7);
+}
+
+//----- (010194B0) --------------------------------------------------------
+TFlagSpinner *__thiscall TFlagSpinner::TFlagSpinner(TFlagSpinner *this, struct TPinballTable *a2, int a3)
+{
+TFlagSpinner *v3; // esi
+TLine *v4; // eax
+TLine *v5; // edi
+TLine *v6; // eax
+TLine *v7; // eax
+_DWORD *v8; // eax
+_DWORD *v9; // eax
+_DWORD *v10; // eax
+char v12; // [esp+Ch] [ebp-60h]
+int *v13; // [esp+18h] [ebp-54h]
+unsigned int v14; // [esp+40h] [ebp-2Ch]
+int v15; // [esp+54h] [ebp-18h]
+int v16; // [esp+58h] [ebp-14h]
+int v17; // [esp+60h] [ebp-Ch]
+int v18; // [esp+64h] [ebp-8h]
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 0);
+*(_DWORD *)v3 = &TFlagSpinner::`vftable';
+*(_DWORD *)((char *)v3 + 102) = 0;
+loader_query_visual(a3, 0, &v12);
+v15 = *v13;
+v16 = v13[1];
+v17 = v13[2];
+v18 = v13[3];
+v4 = (TLine *)operator new(0x55u);
+if ( v4 )
+v5 = TLine::TLine(v4, v3, (char *)v3 + 5, v14, (struct vector_type *)&v17, (struct vector_type *)&v15);
+else
+v5 = 0;
+if ( v5 )
+{
+(*(void (__thiscall **)(TLine *))(*(_DWORD *)v5 + 8))(v5);
+objlist_class::Add((TFlagSpinner *)((char *)v3 + 42), (void *)v5);
+}
+v6 = (TLine *)operator new(0x55u);
+if ( v6 )
+v7 = TLine::TLine(v6, v3, (char *)v3 + 5, v14, (struct vector_type *)&v15, (struct vector_type *)&v17);
+else
+v7 = 0;
+*(_DWORD *)((char *)v3 + 106) = v7;
+if ( v7 )
+{
+(*(void (__thiscall **)(TLine *))(*(_DWORD *)v7 + 8))(v7);
+objlist_class::Add((TFlagSpinner *)((char *)v3 + 42), *(void **)((char *)v3 + 106));
+}
+*(_DWORD *)((char *)v3 + 90) = 1059481190;
+*(_DWORD *)((char *)v3 + 82) = 1195593728;
+*(_DWORD *)((char *)v3 + 86) = 1084227584;
+v8 = (_DWORD *)loader_query_float_attribute(a3, 0, 1202);
+if ( v8 )
+*(_DWORD *)((char *)v3 + 90) = *v8;
+v9 = (_DWORD *)loader_query_float_attribute(a3, 0, 1200);
+if ( v9 )
+*(_DWORD *)((char *)v3 + 82) = *v9;
+v10 = (_DWORD *)loader_query_float_attribute(a3, 0, 1201);
+if ( v10 )
+*(_DWORD *)((char *)v3 + 86) = *v10;
+return v3;
+}
+// 1002588: using guessed type void *TFlagSpinner::`vftable';
diff --git a/Classes/TFlipper/TFlipper.cpp b/Classes/TFlipper/TFlipper.cpp
new file mode 100644
index 0000000..f937744
--- /dev/null
+++ b/Classes/TFlipper/TFlipper.cpp
@@ -0,0 +1,261 @@
+#include "../../pinball.h"
+
+
+//----- (0101C047) --------------------------------------------------------
+TZmapList *__thiscall TFlipper::~TFlipper(TFlipper *this)
+{
+TCollisionComponent *v1; // esi
+void *v2; // ST00_4
+
+v1 = this;
+v2 = *(void **)((char *)this + 82);
+*(_DWORD *)this = &TFlipper::`vftable';
+operator delete(v2);
+return TCollisionComponent::~TCollisionComponent(v1);
+}
+// 1002838: using guessed type void *TFlipper::`vftable';
+
+//----- (0101C070) --------------------------------------------------------
+void __stdcall TFlipper::TimerExpired(int a1, void *a2)
+{
+char *v2; // esi
+double v3; // st7
+int v4; // edi
+signed __int64 v5; // rax
+int v6; // ebx
+int v7; // ecx
+int v8; // eax
+int v9; // ecx
+int v10; // edx
+int v11; // ecx
+int v12; // eax
+signed int v13; // [esp+14h] [ebp-4h]
+float v14; // [esp+24h] [ebp+Ch]
+
+v2 = (char *)a2;
+v13 = 0;
+v3 = _floor((time_now - *(float *)((char *)a2 + 102)) / *(float *)((char *)a2 + 98) + 0.5);
+v4 = *(_DWORD *)((char *)a2 + 34);
+v14 = (double)*(signed int *)(*(_DWORD *)(v4 + 4) + 4);
+if ( v3 > v14 )
+v3 = v14;
+if ( v3 < 0.0 )
+v3 = 0.0;
+v5 = (signed __int64)v3;
+if ( !(unsigned int)(signed __int64)v3 )
+LODWORD(v5) = 1;
+v6 = *(_DWORD *)(v2 + 6);
+if ( v6 == 1 )
+{
+*(_DWORD *)(v2 + 78) += v5;
+v7 = *(_DWORD *)(*(_DWORD *)(v4 + 4) + 4) - 1;
+if ( *(_DWORD *)(v2 + 78) >= v7 )
+{
+*(_DWORD *)(v2 + 78) = v7;
+v13 = 1;
+}
+}
+if ( v6 == 2 )
+{
+*(_DWORD *)(v2 + 78) -= v5;
+v8 = 0;
+if ( *(_DWORD *)(v2 + 78) <= 0 )
+{
+*(_DWORD *)(v2 + 78) = 0;
+v13 = 1;
+}
+}
+else
+{
+v8 = 0;
+}
+if ( v13 )
+*(_DWORD *)(v2 + 6) = 0;
+else
+v8 = timer_set(*(float *)(v2 + 98), (int)v2, (int)TFlipper::TimerExpired);
+v9 = *(_DWORD *)(v2 + 78);
+v10 = *(_DWORD *)(v2 + 30);
+*(_DWORD *)(v2 + 86) = v8;
+v11 = 4 * v9 + 8;
+v12 = *(_DWORD *)(v11 + *(_DWORD *)(*(_DWORD *)(v2 + 34) + 4));
+render_sprite_set(
+*(_DWORD **)(v2 + 26),
+*(_DWORD *)(v11 + *(_DWORD *)(*(_DWORD *)(v2 + 34) + 4)),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(v2 + 38) + 4) + v11),
+*(_DWORD *)(v12 + 29) - *(_DWORD *)(v10 + 234),
+*(_DWORD *)(v12 + 33) - *(_DWORD *)(v10 + 238));
+}
+// 1025630: using guessed type float time_now;
+
+//----- (0101C178) --------------------------------------------------------
+int __thiscall TFlipper::Message(TFlipper *this, int a2, float a3)
+{
+signed int v3; // ebx
+TFlipper *v4; // esi
+int v5; // ST04_4
+int v6; // eax
+double v7; // st7
+double v8; // ST14_8
+float v9; // ST00_4
+
+v3 = a2;
+v4 = this;
+if ( a2 == 1 )
+{
+control_handler(1, this);
+*(_DWORD *)((char *)v4 + 98) = *(_DWORD *)((char *)v4 + 90);
+v6 = *(_DWORD *)((char *)v4 + 74);
+LABEL_15:
+if ( v6 )
+loader_play_sound(v6);
+goto LABEL_17;
+}
+if ( a2 == 2 )
+{
+*(_DWORD *)((char *)this + 98) = *(_DWORD *)((char *)this + 94);
+v6 = *(_DWORD *)((char *)this + 70);
+goto LABEL_15;
+}
+if ( a2 <= 1008 )
+return 0;
+if ( a2 <= 1011 )
+{
+LABEL_12:
+v3 = 2;
+*(_DWORD *)((char *)this + 98) = *(_DWORD *)((char *)this + 94);
+LABEL_17:
+if ( *(_DWORD *)((char *)v4 + 86) )
+{
+timer_kill(*(_DWORD *)((char *)v4 + 86));
+*(_DWORD *)((char *)v4 + 86) = 0;
+}
+if ( *(_DWORD *)((char *)v4 + 6) )
+{
+v8 = a3 - *(float *)(*(_DWORD *)((char *)v4 + 82) + 201);
+v7 = v8 - _floor(v8 / *(float *)((char *)v4 + 98)) * *(float *)((char *)v4 + 98);
+if ( v7 < 0.0 )
+v7 = 0.0;
+}
+else
+{
+v7 = *(float *)((char *)v4 + 98);
+}
+v9 = v7;
+*(_DWORD *)((char *)v4 + 6) = v3;
+*(float *)((char *)v4 + 102) = a3;
+*(_DWORD *)((char *)v4 + 86) = timer_set(v9, (int)v4, (int)TFlipper::TimerExpired);
+goto LABEL_24;
+}
+if ( a2 != 1020 )
+{
+if ( a2 != 1022 )
+{
+if ( a2 != 1024 )
+return 0;
+goto LABEL_8;
+}
+goto LABEL_12;
+}
+LABEL_8:
+if ( *(_DWORD *)((char *)this + 6) )
+{
+if ( *(_DWORD *)((char *)this + 86) )
+timer_kill(*(_DWORD *)((char *)this + 86));
+*(_DWORD *)((char *)v4 + 78) = -1;
+v5 = *(_DWORD *)((char *)v4 + 86);
+*(_DWORD *)((char *)v4 + 6) = 2;
+TFlipper::TimerExpired(v5, (void *)v4);
+LABEL_24:
+TFlipperEdge::SetMotion(*(TFlipperEdge **)((char *)v4 + 82), v3, a3);
+}
+return 0;
+}
+
+//----- (0101C2AD) --------------------------------------------------------
+void __thiscall TFlipper::port_draw(TFlipper *this)
+{
+(*(void (**)(void))(**(_DWORD **)((char *)this + 82) + 4))();
+}
+
+//----- (0101C59D) --------------------------------------------------------
+TFlipper *__thiscall TFlipper::TFlipper(TFlipper *this, struct TPinballTable *a2, int a3)
+{
+int v3; // ebx
+TFlipper *v4; // esi
+int v5; // eax
+float *v6; // eax
+float v7; // ST2C_4
+float v8; // ST28_4
+float v9; // ST24_4
+float v10; // ST20_4
+float v11; // ST1C_4
+struct vector_type *v12; // ST18_4
+struct vector_type *v13; // ST14_4
+struct vector_type *v14; // eax
+TFlipperEdge *v15; // eax
+int v16; // ecx
+int v18; // [esp+20h] [ebp-50h]
+int v19; // [esp+24h] [ebp-4Ch]
+unsigned int v20; // [esp+54h] [ebp-1Ch]
+int v21; // [esp+58h] [ebp-18h]
+int v22; // [esp+5Ch] [ebp-14h]
+TFlipperEdge *v23; // [esp+68h] [ebp-8h]
+float *v24; // [esp+6Ch] [ebp-4h]
+float *v25; // [esp+7Ch] [ebp+Ch]
+
+v3 = a3;
+v4 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 0);
+*(_DWORD *)v4 = &TFlipper::`vftable';
+loader_query_visual(a3, 0, &v18);
+*(_DWORD *)((char *)v4 + 74) = v21;
+*(_DWORD *)((char *)v4 + 70) = v22;
+*(_DWORD *)((char *)v4 + 54) = v19;
+v5 = v18;
+*(_DWORD *)((char *)v4 + 86) = 0;
+*(_DWORD *)((char *)v4 + 58) = v5;
+v23 = (TFlipperEdge *)operator new(0xE9u);
+if ( v23 )
+{
+v25 = (float *)loader_query_float_attribute(a3, 0, 803);
+v24 = (float *)loader_query_float_attribute(v3, 0, 805);
+v6 = (float *)loader_query_float_attribute(v3, 0, 804);
+v7 = *(float *)((char *)v4 + 58);
+v8 = *(float *)((char *)v4 + 54);
+v9 = *v25;
+v10 = *v24;
+v11 = *v6;
+v12 = (struct vector_type *)loader_query_float_attribute(v3, 0, 802);
+v13 = (struct vector_type *)loader_query_float_attribute(v3, 0, 801);
+v14 = (struct vector_type *)loader_query_float_attribute(v3, 0, 800);
+v15 = TFlipperEdge::TFlipperEdge(v23, v4, (char *)v4 + 5, v20, a2, v14, v13, v12, v11, v10, v9, v8, v7);
+}
+else
+{
+v15 = 0;
+}
+*(_DWORD *)((char *)v4 + 82) = v15;
+if ( v15 )
+{
+v16 = *(_DWORD *)((char *)v4 + 34);
+*(float *)((char *)v4 + 90) = *(float *)((char *)v15 + 213) / (double)(*(_DWORD *)(*(_DWORD *)(v16 + 4) + 4) - 1);
+*(float *)((char *)v4 + 94) = *(float *)((char *)v15 + 217) / (double)(*(_DWORD *)(*(_DWORD *)(v16 + 4) + 4) - 1);
+}
+*(_DWORD *)((char *)v4 + 78) = 0;
+*(float *)((char *)v4 + 102) = 0.0;
+return v4;
+}
+// 1002838: using guessed type void *TFlipper::`vftable';
+
+//----- (0101C6D7) --------------------------------------------------------
+TFlipper *__thiscall TFlipper::`vector deleting destructor`(TFlipper *this, char a2)
+{
+TFlipper *v2; // esi
+
+v2 = this;
+TFlipper::~TFlipper(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
+
diff --git a/Classes/TFlipperEdge/TFlipperEdge.cpp b/Classes/TFlipperEdge/TFlipperEdge.cpp
new file mode 100644
index 0000000..5cc0673
--- /dev/null
+++ b/Classes/TFlipperEdge/TFlipperEdge.cpp
@@ -0,0 +1,860 @@
+#include "../../pinball.h"
+
+//----- (0101B0D4) --------------------------------------------------------
+void __thiscall TFlipperEdge::place_in_grid(TFlipperEdge *this)
+{
+double v1; // st7
+double v2; // st6
+double v3; // st6
+double v4; // st6
+double v5; // st6
+float v6; // ST18_4
+double v7; // st6
+double v8; // st6
+double v9; // st6
+double v10; // st6
+float v11; // ST18_4
+float v12; // ST08_4
+float v13; // [esp+1Ch] [ebp-Ch]
+float v14; // [esp+20h] [ebp-8h]
+float v15; // [esp+24h] [ebp-4h]
+
+v14 = *(float *)((char *)this + 33) - *(float *)((char *)this + 45);
+v13 = *(float *)((char *)this + 37) - *(float *)((char *)this + 45);
+v15 = *(float *)((char *)this + 45) + *(float *)((char *)this + 33);
+v1 = *(float *)((char *)this + 37) + *(float *)((char *)this + 45);
+v2 = *(float *)((char *)this + 153) - *(float *)((char *)this + 49);
+if ( v2 < v14 )
+v14 = v2;
+v3 = *(float *)((char *)this + 157) - *(float *)((char *)this + 49);
+if ( v3 < v13 )
+v13 = v3;
+v4 = *(float *)((char *)this + 49) + *(float *)((char *)this + 153);
+if ( v4 > v15 )
+v15 = v4;
+v5 = *(float *)((char *)this + 157) + *(float *)((char *)this + 49);
+if ( v5 > v1 )
+{
+v6 = v5;
+v1 = v6;
+}
+v7 = *(float *)((char *)this + 165) - *(float *)((char *)this + 49);
+if ( v7 < v14 )
+v14 = v7;
+v8 = *(float *)((char *)this + 169) - *(float *)((char *)this + 49);
+if ( v8 < v13 )
+v13 = v8;
+v9 = *(float *)((char *)this + 165) + *(float *)((char *)this + 49);
+if ( v9 > v15 )
+v15 = v9;
+v10 = *(float *)((char *)this + 49) + *(float *)((char *)this + 169);
+if ( v10 > v1 )
+{
+v11 = v10;
+v1 = v11;
+}
+v12 = v1;
+edges_insert_square(v13, v14, v12, v15, this, 0);
+}
+
+//----- (0101B1F7) --------------------------------------------------------
+double __thiscall TFlipperEdge::flipper_angle(TFlipperEdge *this, float a2)
+{
+int v2; // edx
+double v4; // st7
+double v5; // st7
+
+v2 = *(_DWORD *)((char *)this + 21);
+if ( !v2 )
+return *(float *)((char *)this + 77);
+v4 = (*(float *)((char *)this + 77) - *(float *)((char *)this + 73))
+/ *(float *)((char *)this + 69)
+* *(float *)((char *)this + 209);
+if ( v4 < 0.0 )
+v4 = -v4;
+if ( v4 >= 0.0000001 )
+v5 = (a2 - *(float *)((char *)this + 201)) / v4;
+else
+v5 = 1.0;
+if ( v5 < 0.0 )
+v5 = 0.0;
+if ( v5 > 1.0 )
+v5 = 1.0;
+if ( v2 == 2 )
+v5 = 1.0 - v5;
+return v5 * *(float *)((char *)this + 69);
+}
+
+//----- (0101B281) --------------------------------------------------------
+void __thiscall TFlipperEdge::build_edges_in_motion(TFlipperEdge *this)
+{
+TFlipperEdge *v1; // esi
+
+v1 = this;
+line_init((int)&lineA, A1, flt_1025718, A2, flt_10256B8);
+line_init((int)&lineB, B1, flt_10256F4, B2, flt_1025700);
+dword_102566C = *(_DWORD *)((char *)v1 + 53);
+circlebase = *(_DWORD *)((char *)v1 + 33);
+dword_1025664 = *(_DWORD *)((char *)v1 + 37);
+dword_102567C = *(_DWORD *)((char *)v1 + 57);
+circleT1 = T1;
+dword_1025674 = dword_102570C;
+}
+// 1025664: using guessed type int dword_1025664;
+// 102566C: using guessed type int dword_102566C;
+// 1025674: using guessed type int dword_1025674;
+// 102567C: using guessed type int dword_102567C;
+// 10256B8: using guessed type float flt_10256B8;
+// 10256F4: using guessed type float flt_10256F4;
+// 1025700: using guessed type float flt_1025700;
+// 102570C: using guessed type int dword_102570C;
+// 1025718: using guessed type float flt_1025718;
+
+//----- (0101B327) --------------------------------------------------------
+void __thiscall TFlipperEdge::set_control_points(TFlipperEdge *this, float a2)
+{
+TFlipperEdge *v2; // ebx
+float v3; // ST04_4
+double v4; // st7
+float v5; // ST08_4
+
+v2 = this;
+v3 = TFlipperEdge::flipper_angle(this, a2);
+SinCos(v3, &flipper_sin_angle, &flipper_cos_angle);
+v4 = flipper_cos_angle;
+A1 = *(_DWORD *)((char *)v2 + 101);
+*((_DWORD *)&A1 + 1) = *(_DWORD *)((char *)v2 + 105);
+*((_DWORD *)&A1 + 2) = *(_DWORD *)((char *)v2 + 109);
+A2 = *(_DWORD *)((char *)v2 + 113);
+*((_DWORD *)&A2 + 1) = *(_DWORD *)((char *)v2 + 117);
+*((_DWORD *)&A2 + 2) = *(_DWORD *)((char *)v2 + 121);
+B1 = *(_DWORD *)((char *)v2 + 125);
+*((_DWORD *)&B1 + 1) = *(_DWORD *)((char *)v2 + 129);
+*((_DWORD *)&B1 + 2) = *(_DWORD *)((char *)v2 + 133);
+B2 = *(_DWORD *)((char *)v2 + 137);
+*((_DWORD *)&B2 + 1) = *(_DWORD *)((char *)v2 + 141);
+*((_DWORD *)&B2 + 2) = *(_DWORD *)((char *)v2 + 145);
+T1 = *(_DWORD *)((char *)v2 + 153);
+*((_DWORD *)&T1 + 1) = *(_DWORD *)((char *)v2 + 157);
+*((_DWORD *)&T1 + 2) = *(_DWORD *)((char *)v2 + 161);
+v5 = v4;
+RotatePt((struct vector_type *)&A1, flipper_sin_angle, v5, (TFlipperEdge *)((char *)v2 + 33));
+RotatePt((struct vector_type *)&A2, flipper_sin_angle, flipper_cos_angle, (TFlipperEdge *)((char *)v2 + 33));
+RotatePt((struct vector_type *)&T1, flipper_sin_angle, flipper_cos_angle, (TFlipperEdge *)((char *)v2 + 33));
+RotatePt((struct vector_type *)&B1, flipper_sin_angle, flipper_cos_angle, (TFlipperEdge *)((char *)v2 + 33));
+RotatePt((struct vector_type *)&B2, flipper_sin_angle, flipper_cos_angle, (TFlipperEdge *)((char *)v2 + 33));
+}
+
+//----- (0101B5A8) --------------------------------------------------------
+int __thiscall TFlipperEdge::is_ball_inside(TFlipperEdge *this, float a2, float a3)
+{
+float v3; // ST08_4
+float v4; // ST04_4
+double v5; // st6
+double v7; // st5
+char v8; // c0
+double v9; // st4
+double v10; // st3
+int v11; // eax
+int v12; // eax
+double v13; // st6
+double v14; // st6
+double v15; // st5
+double v16; // st4
+double v17; // st5
+int v19; // eax
+double v20; // st6
+double v21; // st6
+double v22; // st5
+double v23; // st4
+bool v24; // c0
+double v25; // st4
+
+v5 = flt_10256F4;
+v7 = B1;
+if ( !v8
+&& (v7 - A2) * (a3 - flt_10256B8) - (v5 - flt_10256B8) * (a2 - A2) >= 0.0
+&& (B2 - v7) * (a3 - v5) - (flt_1025700 - v5) * (a2 - v7) >= 0.0
+&& (A1 - B2) * (a3 - flt_1025700) - (flt_1025718 - flt_1025700) * (a2 - B2) >= 0.0
+|| (v9 = *(float *)((char *)this + 33) - a2,
+v10 = *(float *)((char *)this + 37) - a3,
+v10 * v10 + v9 * v9 <= *(float *)((char *)this + 53))
+|| (*(float *)&dword_102570C - a3) * (*(float *)&dword_102570C - a3) + (T1 - a2) * (T1 - a2) < *(float *)((char *)this + 57) )
+{
+v11 = *(_DWORD *)((char *)this + 21);
+if ( *(float *)((char *)this + 69) < 0.0 )
+{
+v19 = v11 - 1;
+if ( v19 )
+{
+v20 = *(float *)((char *)this + 33);
+if ( v19 == 1 )
+{
+v21 = (v20 - A2) * (a3 - flt_10256B8);
+v22 = *(float *)((char *)this + 37) - flt_10256B8;
+v23 = a2 - A2;
+}
+else
+{
+v21 = (v20 - T1) * (a3 - *(float *)&dword_102570C);
+v22 = *(float *)((char *)this + 37) - *(float *)&dword_102570C;
+v23 = a2 - T1;
+}
+v24 = v21 - v22 * v23 < 0.0;
+}
+else
+{
+v25 = (*(float *)((char *)this + 33) - v7) * (a3 - v5) - (*(float *)((char *)this + 37) - v5) * (a2 - v7);
+}
+if ( v24 )
+return 5;
+return 4;
+}
+v12 = v11 - 1;
+v13 = *(float *)((char *)this + 33);
+if ( v12 )
+{
+if ( v12 == 1 )
+{
+v3 = a3 - flt_1025718;
+v14 = (v13 - A1) * v3;
+v4 = a2 - A1;
+v17 = (*(float *)((char *)this + 37) - flt_1025718) * v4;
+LABEL_12:
+if ( v14 - v17 >= 0.0 )
+return 5;
+return 4;
+}
+v14 = (v13 - T1) * (a3 - *(float *)&dword_102570C);
+v15 = *(float *)((char *)this + 37) - *(float *)&dword_102570C;
+v16 = a2 - T1;
+}
+else
+{
+v14 = (v13 - B2) * (a3 - flt_1025700);
+v15 = *(float *)((char *)this + 37) - flt_1025700;
+v16 = a2 - B2;
+}
+v17 = v15 * v16;
+goto LABEL_12;
+}
+return 0;
+}
+// 10256B8: using guessed type float flt_10256B8;
+// 10256F4: using guessed type float flt_10256F4;
+// 1025700: using guessed type float flt_1025700;
+// 102570C: using guessed type int dword_102570C;
+// 1025718: using guessed type float flt_1025718;
+
+//----- (0101B825) --------------------------------------------------------
+double __thiscall TFlipperEdge::FindCollisionDistance(TFlipperEdge *this, struct ray_type *a2)
+{
+struct ray_type *v2; // esi
+TFlipperEdge *v3; // ebx
+_DWORD *v4; // eax
+double result; // st7
+int v6; // eax
+int v7; // ecx
+float *v8; // esi
+double v9; // st7
+float *v10; // eax
+_DWORD *v11; // edi
+char *v12; // esi
+float v13; // eax
+char *v14; // esi
+_DWORD *v15; // edi
+_DWORD *v16; // edi
+_DWORD *v17; // esi
+double v18; // st7
+float v19; // eax
+double v20; // st7
+int v21; // eax
+int v22; // esi
+int v23; // eax
+int v24; // edx
+_DWORD *v25; // esi
+double v26; // st7
+_DWORD *v27; // esi
+double v28; // st7
+_DWORD *v29; // edi
+_DWORD *v30; // esi
+double v31; // st7
+double v32; // st7
+float v33; // eax
+double v34; // st7
+double v35; // st6
+double v36; // st5
+double v37; // st4
+__int16 v38; // fps
+double v39; // st6
+char v40; // ah
+bool v41; // c0
+bool v42; // c3
+signed int v43; // eax
+char v44; // [esp+14h] [ebp-70h]
+int v45; // [esp+18h] [ebp-6Ch]
+int v46; // [esp+1Ch] [ebp-68h]
+char v47; // [esp+20h] [ebp-64h]
+int v48; // [esp+24h] [ebp-60h]
+int v49; // [esp+28h] [ebp-5Ch]
+float v50; // [esp+40h] [ebp-44h]
+float v51; // [esp+44h] [ebp-40h]
+int v52; // [esp+48h] [ebp-3Ch]
+float v53; // [esp+4Ch] [ebp-38h]
+float v54; // [esp+50h] [ebp-34h]
+int v55; // [esp+54h] [ebp-30h]
+float v56; // [esp+58h] [ebp-2Ch]
+int v57; // [esp+5Ch] [ebp-28h]
+float v58; // [esp+6Ch] [ebp-18h]
+float v59; // [esp+70h] [ebp-14h]
+float v60; // [esp+74h] [ebp-10h]
+float v61; // [esp+78h] [ebp-Ch]
+float v62; // [esp+7Ch] [ebp-8h]
+float v63; // [esp+80h] [ebp-4h]
+
+v2 = a2;
+v3 = this;
+if ( *((float *)a2 + 8) > (double)*(float *)((char *)this + 205) )
+*(_DWORD *)((char *)this + 21) = 0;
+v4 = (_DWORD *)((char *)this + 197);
+if ( *(_DWORD *)((char *)this + 197) )
+{
+*v4 = 0;
+return 1000000000.0;
+}
+if ( *(_DWORD *)((char *)this + 21) )
+{
+v18 = *(float *)((char *)this + 181) * *((float *)a2 + 6);
+v63 = *(float *)a2;
+v62 = *((float *)a2 + 1);
+v19 = *((float *)a2 + 8);
+v60 = v18;
+v20 = *(float *)((char *)this + 181);
+v61 = v19;
+v59 = v20 * *((float *)a2 + 3);
+v58 = *((float *)a2 + 4) * *(float *)((char *)this + 181);
+if ( *((float *)a2 + 9) + *((float *)a2 + 8) <= v19 )
+return 1000000000.0;
+while ( 1 )
+{
+TFlipperEdge::set_control_points(v3, v61);
+TFlipperEdge::build_edges_in_motion(v3);
+v21 = TFlipperEdge::is_ball_inside(v3, v63, v62);
+if ( v21 )
+break;
+v22 = (int)v2 + 12;
+v53 = *(float *)v22;
+v22 += 4;
+v54 = *(float *)v22;
+v55 = *(_DWORD *)(v22 + 4);
+v23 = *((_DWORD *)a2 + 7);
+v50 = *(float *)a2;
+v51 = *((float *)a2 + 1);
+v52 = *((_DWORD *)a2 + 2);
+v57 = v23;
+v56 = v60;
+result = distance_to_flipper((struct ray_type *)&v50, (struct ray_type *)&v44);
+if ( result < 1000000000.0 )
+{
+*(_DWORD *)((char *)v3 + 221) = *(_DWORD *)&v44;
+*(_DWORD *)((char *)v3 + 225) = v45;
+*(_DWORD *)((char *)v3 + 229) = v46;
+v35 = *(float *)((char *)v3 + 221) - v53 * 0.00001;
+*(float *)((char *)v3 + 221) = v35;
+v36 = *(float *)((char *)v3 + 225) - v54 * 0.00001;
+*(float *)((char *)v3 + 225) = v36;
+v37 = (*(float *)((char *)v3 + 33) - T1) * (v36 - *(float *)&dword_102570C)
+- (*(float *)((char *)v3 + 37) - *(float *)&dword_102570C) * (v35 - T1);
+v39 = *(float *)((char *)v3 + 69);
+v40 = HIBYTE(v38);
+v41 = v39 < 0.0;
+v42 = v39 == 0.0;
+if ( v40 & 1 )
+{
+if ( v41 || v42 )
+goto LABEL_49;
+LABEL_47:
+v43 = 1;
+}
+else
+{
+if ( v41 || v42 )
+goto LABEL_47;
+LABEL_49:
+v43 = 0;
+}
+v15 = (_DWORD *)((char *)v3 + 89);
+if ( *(_DWORD *)((char *)v3 + 21) == 2 )
+{
+v14 = (char *)&lineB;
+*(_DWORD *)((char *)v3 + 81) = v43 == 0;
+}
+else
+{
+*(_DWORD *)((char *)v3 + 81) = v43;
+v14 = (char *)&lineA;
+}
+goto LABEL_25;
+}
+v61 = v61 + *(float *)((char *)v3 + 181);
+v63 = v63 + v59;
+v62 = v62 + v58;
+if ( *((float *)a2 + 9) + *((float *)a2 + 8) <= v61 )
+return 1000000000.0;
+v2 = a2;
+}
+v24 = *(_DWORD *)((char *)v3 + 21);
+if ( v24 != 1 || v21 == 5 )
+{
+if ( v24 != 2 || v21 == 4 )
+{
+v31 = *(float *)((char *)v3 + 33) - v63;
+*(_DWORD *)((char *)v3 + 81) = 0;
+*(_DWORD *)((char *)v3 + 85) = 1;
+v53 = v31;
+v54 = *(float *)((char *)v3 + 37) - v62;
+normalize_2d(&v53);
+v50 = v63 - v53 * 5.0;
+v51 = v62 - v54 * 5.0;
+v56 = *((float *)v2 + 6) + 10.0;
+if ( distance_to_flipper((struct ray_type *)&v50, (struct ray_type *)&v44) < 1000000000.0 )
+goto LABEL_20;
+v32 = -v53;
+*(float *)((char *)v3 + 221) = v63;
+v33 = v62;
+*(float *)((char *)v3 + 185) = v32;
+v34 = v54;
+*(float *)((char *)v3 + 225) = v33;
+*(float *)((char *)v3 + 189) = -v34;
+return 0.0;
+}
+v25 = &lineB;
+v53 = -lineB;
+v26 = flt_10256C4;
+}
+else
+{
+v25 = &lineA;
+v53 = -lineA;
+v26 = flt_1025684;
+}
+v54 = -v26;
+*(_DWORD *)((char *)v3 + 89) = *v25;
+v27 = v25 + 1;
+*(_DWORD *)((char *)v3 + 93) = *v27;
+*(_DWORD *)((char *)v3 + 97) = v27[1];
+*(_DWORD *)((char *)v3 + 85) = 0;
+*(_DWORD *)((char *)v3 + 81) = 1;
+v57 = 990057071;
+v50 = *(float *)a2 - v53 * 5.0;
+v51 = *((float *)a2 + 1) - v54 * 5.0;
+v56 = *((float *)a2 + 6) + 10.0;
+v28 = distance_to_flipper((struct ray_type *)&v50, (struct ray_type *)&v44);
+*(_DWORD *)((char *)v3 + 185) = *(_DWORD *)&v47;
+*(_DWORD *)((char *)v3 + 189) = v48;
+*(_DWORD *)((char *)v3 + 193) = v49;
+if ( v28 >= 1000000000.0 )
+return 1000000000.0;
+v10 = (float *)((char *)v3 + 221);
+v12 = &v44;
+v11 = (_DWORD *)((char *)v3 + 221);
+LABEL_41:
+*v11 = *(_DWORD *)v12;
+v30 = v12 + 4;
+v29 = v11 + 1;
+*v29 = *v30;
+v29[1] = v30[1];
+*v10 = *v10 - v53 * 0.00001;
+*(float *)((char *)v3 + 225) = *(float *)((char *)v3 + 225) - v54 * 0.00001;
+return 0.0;
+}
+*v4 = 0;
+*(_DWORD *)((char *)this + 81) = 0;
+*(_DWORD *)((char *)this + 85) = 0;
+TFlipperEdge::set_control_points(this, *((float *)a2 + 8));
+TFlipperEdge::build_edges_in_motion(v3);
+*(float *)&v6 = COERCE_FLOAT(TFlipperEdge::is_ball_inside(v3, *(float *)a2, *((float *)a2 + 1)));
+v7 = *((_DWORD *)a2 + 7);
+v61 = *(float *)&v6;
+v57 = v7;
+if ( *(float *)&v6 != 0.0 )
+{
+if ( Distance_Squared(
+*(float *)a2,
+*((float *)a2 + 1),
+*((_DWORD *)a2 + 2),
+*(float *)((char *)v3 + 33),
+*(float *)((char *)v3 + 37),
+*(_DWORD *)((char *)v3 + 41)) >= *(float *)((char *)v3 + 61) )
+{
+if ( Distance_Squared(
+*(float *)a2,
+*((float *)a2 + 1),
+*((_DWORD *)a2 + 2),
+T1,
+*((float *)&T1 + 1),
+*((_DWORD *)&T1 + 2)) >= *(float *)((char *)v3 + 65) )
+{
+if ( LODWORD(v61) == 4 )
+{
+v53 = -lineA;
+v9 = flt_1025684;
+}
+else
+{
+v53 = -lineB;
+v9 = flt_10256C4;
+}
+v54 = -v9;
+}
+else
+{
+v53 = T1 - *(float *)a2;
+v54 = *(float *)&dword_102570C - *((float *)a2 + 1);
+normalize_2d(&v53);
+}
+v8 = (float *)a2;
+}
+else
+{
+v8 = (float *)a2;
+v53 = *(float *)((char *)v3 + 33) - *(float *)a2;
+v54 = *(float *)((char *)v3 + 37) - *((float *)a2 + 1);
+normalize_2d(&v53);
+}
+v50 = *v8 - v53 * 5.0;
+v51 = v8[1] - v54 * 5.0;
+v56 = v8[6] + 10.0;
+if ( distance_to_flipper((struct ray_type *)&v50, (struct ray_type *)&v44) >= 1000000000.0 )
+{
+v53 = *(float *)((char *)v3 + 33) - *v8;
+v54 = *(float *)((char *)v3 + 37) - v8[1];
+normalize_2d(&v53);
+v50 = *v8 - v53 * 5.0;
+v51 = v8[1] - v54 * 5.0;
+if ( distance_to_flipper((struct ray_type *)&v50, (struct ray_type *)&v44) >= 1000000000.0 )
+return 1000000000.0;
+}
+LABEL_20:
+v10 = (float *)((char *)v3 + 221);
+*(_DWORD *)((char *)v3 + 221) = *(_DWORD *)&v44;
+*(_DWORD *)((char *)v3 + 225) = v45;
+*(_DWORD *)((char *)v3 + 229) = v46;
+v11 = (_DWORD *)((char *)v3 + 185);
+v12 = &v47;
+goto LABEL_41;
+}
+v53 = *((float *)a2 + 3);
+v54 = *((float *)a2 + 4);
+v55 = *((_DWORD *)a2 + 5);
+v13 = *((float *)a2 + 6);
+v50 = *(float *)a2;
+v51 = *((float *)a2 + 1);
+v52 = *((_DWORD *)a2 + 2);
+v56 = v13;
+result = distance_to_flipper((struct ray_type *)&v50, (struct ray_type *)&v44);
+v14 = &v44;
+if ( result == 0.0 )
+{
+*(_DWORD *)((char *)v3 + 221) = *(_DWORD *)&v44;
+*(_DWORD *)((char *)v3 + 225) = v45;
+*(_DWORD *)((char *)v3 + 229) = v46;
+*(float *)((char *)v3 + 221) = *(float *)((char *)v3 + 221) - v53 * 0.00001;
+*(float *)((char *)v3 + 225) = *(float *)((char *)v3 + 225) - v54 * 0.00001;
+}
+else
+{
+v15 = (_DWORD *)((char *)v3 + 221);
+LABEL_25:
+*v15 = *(_DWORD *)v14;
+v17 = v14 + 4;
+v16 = v15 + 1;
+*v16 = *v17;
+v16[1] = v17[1];
+}
+*(_DWORD *)((char *)v3 + 185) = *(_DWORD *)&v47;
+*(_DWORD *)((char *)v3 + 189) = v48;
+*(_DWORD *)((char *)v3 + 193) = v49;
+return result;
+}
+// 1025684: using guessed type float flt_1025684;
+// 10256C4: using guessed type float flt_10256C4;
+// 102570C: using guessed type int dword_102570C;
+
+//----- (0101BE06) --------------------------------------------------------
+void __thiscall TFlipperEdge::EdgeCollision(TFlipperEdge *this, struct TBall *a2, float a3)
+{
+TFlipperEdge *v3; // esi
+int v4; // eax
+double v5; // st7
+double v6; // st6
+double v7; // st7
+double v8; // st7
+double v9; // st6
+double v10; // st7
+double v11; // st7
+struct vector_type *v12; // ecx
+double v13; // st7
+double v14; // st6
+double v15; // st7
+long double v16; // st7
+float v17; // ST0C_4
+float v18; // ST18_4
+float v19; // ST14_4
+float v20; // [esp+14h] [ebp-4h]
+
+v3 = this;
+v4 = *(_DWORD *)((char *)this + 21);
+*(_DWORD *)((char *)this + 197) = 1;
+if ( !v4 )
+goto LABEL_4;
+if ( *(_DWORD *)((char *)this + 81) )
+{
+v5 = *(float *)((char *)this + 221) - *(float *)((char *)this + 33);
+v6 = *(float *)((char *)this + 225) - *(float *)((char *)this + 37);
+v7 = v6 * v6 + v5 * v5;
+if ( *(float *)&dword_102566C * 1.01 < v7 )
+{
+v20 = sqrt(v7 / *(float *)((char *)this + 177))
+* (fabs(*(float *)((char *)this + 69))
+/ *(float *)((char *)this + 209));
+v10 = DotProduct((TFlipperEdge *)((char *)this + 89), (TFlipperEdge *)((char *)this + 185));
+if ( v10 >= 0.0 )
+v11 = v10 * v20;
+else
+v11 = 0.0;
+v8 = v11 * *(float *)((char *)v3 + 149);
+goto LABEL_5;
+}
+LABEL_4:
+v8 = 0.0;
+LABEL_5:
+if ( v8 <= 0.0 )
+v9 = 1000000000.0;
+else
+v9 = -1.0;
+v18 = v8;
+v19 = v9;
+basic_collision(
+a2,
+(TFlipperEdge *)((char *)v3 + 221),
+(TFlipperEdge *)((char *)v3 + 185),
+*(float *)((char *)v3 + 25),
+*(float *)((char *)v3 + 29),
+v19,
+v18);
+return;
+}
+if ( !v4 || !*(_DWORD *)((char *)this + 85) )
+goto LABEL_4;
+v12 = (TFlipperEdge *)((char *)this + 221);
+v13 = *(float *)((char *)v3 + 221) - *(float *)((char *)v3 + 33);
+v14 = *(float *)((char *)v3 + 225) - *(float *)((char *)v3 + 37);
+v15 = v14 * v14 + v13 * v13;
+if ( *(float *)&dword_102566C * 1.01 < v15 )
+v16 = (1.0 - sqrt(v15 / *(float *)((char *)v3 + 177))) * *(float *)((char *)v3 + 25);
+else
+v16 = *(float *)((char *)v3 + 25);
+v17 = v16;
+basic_collision(a2, v12, (TFlipperEdge *)((char *)v3 + 185), v17, *(float *)((char *)v3 + 29), 1000000000.0, 0.0);
+}
+// 102566C: using guessed type int dword_102566C;
+
+//----- (0101BF98) --------------------------------------------------------
+void __thiscall TFlipperEdge::SetMotion(TFlipperEdge *this, int a2, float a3)
+{
+double v3; // st7
+int v4; // eax
+double v5; // st7
+int v6; // eax
+double v7; // st7
+
+switch ( a2 )
+{
+case 1:
+v5 = TFlipperEdge::flipper_angle(this, a3);
+v6 = *(_DWORD *)((char *)this + 69);
+*(float *)((char *)this + 73) = v5;
+*(_DWORD *)((char *)this + 77) = v6;
+v4 = *(_DWORD *)((char *)this + 213);
+goto LABEL_7;
+case 2:
+v3 = TFlipperEdge::flipper_angle(this, a3);
+v4 = *(_DWORD *)((char *)this + 217);
+*(float *)((char *)this + 73) = v3;
+*(float *)((char *)this + 77) = 0.0;
+LABEL_7:
+*(_DWORD *)((char *)this + 209) = v4;
+break;
+case 1024:
+*(_DWORD *)((char *)this + 21) = 0;
+*(float *)((char *)this + 77) = 0.0;
+return;
+}
+if ( !*(_DWORD *)((char *)this + 21) )
+*(float *)((char *)this + 201) = a3;
+v7 = *(float *)((char *)this + 209);
+*(_DWORD *)((char *)this + 21) = a2;
+*(float *)((char *)this + 205) = v7 + *(float *)((char *)this + 201);
+}
+
+//----- (0101C026) --------------------------------------------------------
+void __thiscall TFlipperEdge::port_draw(TFlipperEdge *this)
+{
+TFlipperEdge *v1; // esi
+
+v1 = this;
+TFlipperEdge::set_control_points(this, *(float *)((char *)this + 201));
+TFlipperEdge::build_edges_in_motion(v1);
+}
+
+//----- (0101C2BA) --------------------------------------------------------
+TFlipperEdge *__thiscall TFlipperEdge::TFlipperEdge(TFlipperEdge *this, struct TCollisionComponent *a2, char *a3, unsigned int a4, struct TPinballTable *a5, struct vector_type *a6, struct vector_type *a7, struct vector_type *a8, float a9, float a10, float a11, float a12, float a13)
+{
+TFlipperEdge *v13; // ebx
+double v14; // st7
+double v15; // st7
+float v16; // eax
+double v17; // st7
+float v18; // eax
+double v19; // st7
+double v20; // st7
+double v21; // st7
+double v22; // st7
+double v23; // st6
+double v24; // st7
+double v25; // st6
+struct vector_type *v26; // ecx
+double v27; // st7
+double v28; // st6
+long double v29; // st5
+double v30; // st7
+long double v31; // st7
+TFlipperEdge *result; // eax
+float v33; // [esp+Ch] [ebp-54h]
+float v34; // [esp+10h] [ebp-50h]
+float v35; // [esp+14h] [ebp-4Ch]
+float v36; // [esp+18h] [ebp-48h]
+float v37; // [esp+1Ch] [ebp-44h]
+float v38; // [esp+20h] [ebp-40h]
+float v39; // [esp+24h] [ebp-3Ch]
+double v40; // [esp+28h] [ebp-38h]
+float v41; // [esp+30h] [ebp-30h]
+float v42; // [esp+34h] [ebp-2Ch]
+float v43; // [esp+38h] [ebp-28h]
+float v44; // [esp+3Ch] [ebp-24h]
+float v45; // [esp+40h] [ebp-20h]
+float v46; // [esp+48h] [ebp-18h]
+float v47; // [esp+4Ch] [ebp-14h]
+float v48; // [esp+50h] [ebp-10h]
+float v49; // [esp+54h] [ebp-Ch]
+double v50; // [esp+58h] [ebp-8h]
+float v51; // [esp+6Ch] [ebp+Ch]
+float v52; // [esp+70h] [ebp+10h]
+float v53; // [esp+70h] [ebp+10h]
+float v54; // [esp+70h] [ebp+10h]
+
+v13 = this;
+TEdgeSegment::TEdgeSegment(this, a2, a3, a4);
+*(float *)((char *)v13 + 25) = a12;
+*(float *)((char *)v13 + 29) = a13;
+*(_DWORD *)v13 = &TFlipperEdge::`vftable';
+v46 = *(float *)a6;
+v47 = *((float *)a6 + 1);
+v48 = *((float *)a6 + 2);
+v49 = *(float *)a7;
+v50 = *(double *)((char *)a7 + 4);
+v14 = *((float *)&v50 + 1);
+v36 = *(float *)a8;
+v37 = *((float *)a8 + 1);
+v38 = *((float *)a8 + 2);
+*(float *)((char *)v13 + 213) = a9;
+*(float *)((char *)v13 + 217) = a10;
+*(float *)((char *)v13 + 149) = a11;
+*(float *)((char *)v13 + 49) = v14 + *(float *)((char *)a5 + 282);
+v15 = v48 + *(float *)((char *)a5 + 282);
+v16 = v46;
+*(float *)((char *)v13 + 153) = v49;
+v52 = v15;
+*(_DWORD *)((char *)v13 + 157) = LODWORD(v50);
+*(float *)((char *)v13 + 45) = v15;
+v17 = *(float *)((char *)v13 + 49) * 1.01;
+*(_DWORD *)((char *)v13 + 161) = HIDWORD(v50);
+*(float *)((char *)v13 + 65) = v17 * v17;
+*(float *)((char *)v13 + 165) = v36;
+*(float *)((char *)v13 + 169) = v37;
+*(float *)((char *)v13 + 61) = v52 * 1.01 * (v52 * 1.01);
+*(float *)((char *)v13 + 33) = v16;
+v18 = v47;
+v19 = *(float *)((char *)v13 + 49);
+*(float *)((char *)v13 + 173) = v38;
+*(float *)((char *)v13 + 37) = v18;
+*(float *)((char *)v13 + 57) = v19 * v19;
+*(float *)((char *)v13 + 53) = *(float *)((char *)v13 + 45) * *(float *)((char *)v13 + 45);
+v20 = v49 - v46;
+v53 = v20;
+v39 = v20;
+v21 = *(float *)&v50 - v47;
+v51 = v21;
+*(float *)&v40 = v21;
+normalize_2d(&v39);
+v41 = v36 - v46;
+v42 = v37 - v47;
+normalize_2d(&v41);
+v43 = 0.0;
+*((float *)&v40 + 1) = 0.0;
+*(float *)((char *)v13 + 69) = acos(DotProduct((const struct vector_type *)&v39, (const struct vector_type *)&v41));
+cross(&v39, &v41, &v33);
+if ( v35 < 0.0 )
+*(float *)((char *)v13 + 69) = -*(float *)((char *)v13 + 69);
+*(_DWORD *)((char *)v13 + 21) = 0;
+*(float *)((char *)v13 + 77) = 0.0;
+v44 = v53;
+v45 = v51;
+normalize_2d(&v44);
+v22 = v44;
+v23 = -v45;
+*(float *)((char *)v13 + 113) = v23 * *(float *)((char *)v13 + 45) + v46;
+*(float *)((char *)v13 + 117) = v22 * *(float *)((char *)v13 + 45) + v47;
+*(float *)((char *)v13 + 101) = v23 * *(float *)((char *)v13 + 49) + v49;
+*(float *)((char *)v13 + 105) = v22 * *(float *)((char *)v13 + 49) + *(float *)&v50;
+v54 = v23;
+v24 = -v22;
+v25 = -v54;
+v44 = v25;
+v45 = v24;
+*(float *)((char *)v13 + 125) = v25 * *(float *)((char *)v13 + 45) + v46;
+*(float *)((char *)v13 + 129) = v24 * *(float *)((char *)v13 + 45) + v47;
+*(float *)((char *)v13 + 137) = v25 * *(float *)((char *)v13 + 49) + v49;
+*(float *)((char *)v13 + 141) = v24 * *(float *)((char *)v13 + 49) + *(float *)&v50;
+if ( *(float *)((char *)v13 + 69) < 0.0 )
+{
+vswap((TFlipperEdge *)((char *)v13 + 101), (TFlipperEdge *)((char *)v13 + 125));
+vswap(v26, (TFlipperEdge *)((char *)v13 + 137));
+}
+v27 = v49 - *(float *)((char *)v13 + 33);
+v28 = *(float *)&v50 - *(float *)((char *)v13 + 37);
+v39 = v49;
+v40 = v50;
+v33 = v36;
+v34 = v37;
+v35 = v38;
+v29 = sqrt(v28 * v28 + v27 * v27) + *(float *)((char *)a5 + 282) + *((float *)&v50 + 1);
+*(float *)((char *)v13 + 177) = v29 * v29;
+if ( *(float *)((char *)v13 + 213) >= (double)*(float *)((char *)v13 + 217) )
+v30 = *(float *)((char *)v13 + 217);
+else
+v30 = *(float *)((char *)v13 + 213);
+v50 = v30;
+v31 = Distance((struct vector_type *)&v39, (struct vector_type *)&v33);
+*(float *)((char *)v13 + 181) = v50 / (v31 / *(float *)((char *)v13 + 49) + v31 / *(float *)((char *)v13 + 49));
+TFlipperEdge::place_in_grid(v13);
+*(_DWORD *)((char *)v13 + 197) = 0;
+*(float *)((char *)v13 + 201) = 0.0;
+*(_DWORD *)((char *)v13 + 81) = 0;
+*(float *)((char *)v13 + 205) = 0.0;
+result = v13;
+*(float *)((char *)v13 + 209) = 0.0;
+return result;
+}
+// 1002854: using guessed type void *TFlipperEdge::`vftable';
diff --git a/Classes/TGate/TGate.cpp b/Classes/TGate/TGate.cpp
new file mode 100644
index 0000000..3e9d034
--- /dev/null
+++ b/Classes/TGate/TGate.cpp
@@ -0,0 +1,54 @@
+#include "../../pinball.h"
+
+//----- (010163DB) --------------------------------------------------------
+int __thiscall TGate::Message(TGate *this, int a2, float a3)
+{
+TGate *v3; // esi
+int v4; // eax
+_DWORD *v5; // ST00_4
+
+v3 = this;
+if ( a2 != 1020 )
+{
+if ( a2 == 53 )
+{
+v5 = *(_DWORD **)((char *)this + 26);
+*((_BYTE *)this + 5) = 0;
+render_sprite_set_bitmap(v5, 0);
+loader_play_sound(*(_DWORD *)((char *)v3 + 82));
+}
+else if ( a2 == 54 || a2 == 1024 )
+{
+v4 = *(_DWORD *)((char *)this + 34);
+*((_BYTE *)this + 5) = 1;
+render_sprite_set_bitmap(*(_DWORD **)((char *)this + 26), *(_DWORD *)(*(_DWORD *)(v4 + 4) + 8));
+if ( a2 == 54 )
+loader_play_sound(*(_DWORD *)((char *)v3 + 78));
+}
+control_handler(a2, v3);
+}
+return 0;
+}
+
+//----- (010196E5) --------------------------------------------------------
+TGate *__thiscall TGate::TGate(TGate *this, struct TPinballTable *a2, int a3)
+{
+TGate *v3; // esi
+int v4; // eax
+char v6; // [esp+4h] [ebp-48h]
+int v7; // [esp+3Ch] [ebp-10h]
+int v8; // [esp+40h] [ebp-Ch]
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+*(_DWORD *)v3 = &TGate::`vftable';
+loader_query_visual(a3, 0, &v6);
+*(_DWORD *)((char *)v3 + 78) = v7;
+*(_DWORD *)((char *)v3 + 82) = v8;
+v4 = *(_DWORD *)((char *)v3 + 34);
+*((_BYTE *)v3 + 5) = 1;
+render_sprite_set_bitmap(*(_DWORD **)((char *)v3 + 26), *(_DWORD *)(*(_DWORD *)(v4 + 4) + 8));
+control_handler(1024, v3);
+return v3;
+}
+// 10025F8: using guessed type void *TGate::`vftable';
diff --git a/Classes/THole/THole.cpp b/Classes/THole/THole.cpp
new file mode 100644
index 0000000..2db3b39
--- /dev/null
+++ b/Classes/THole/THole.cpp
@@ -0,0 +1,196 @@
+#include "../../pinball.h"
+
+//----- (010169A4) --------------------------------------------------------
+void __stdcall THole::TimerExpired(int a1, void *a2)
+{
+*(_DWORD *)((char *)a2 + 86) = 0;
+*(_DWORD *)((char *)a2 + 82) = 1;
+}
+
+//----- (010169C0) --------------------------------------------------------
+int __thiscall THole::FieldEffect(THole *this, struct TBall *a2, struct vector_type *a3)
+{
+THole *v3; // esi
+double v4; // st7
+double v5; // st7
+int v6; // eax
+int v7; // eax
+int result; // eax
+double v9; // st7
+double v10; // st6
+float v11; // [esp+4h] [ebp-Ch]
+float v12; // [esp+8h] [ebp-8h]
+
+v3 = this;
+if ( *(_DWORD *)((char *)this + 78) )
+{
+if ( *(_DWORD *)((char *)this + 82) )
+{
+v4 = *(float *)((char *)a2 + 62)
+- *(float *)(*(_DWORD *)((char *)this + 30) + 270)
+* *(float *)((char *)a2 + 74)
+* *(float *)((char *)this + 98);
+*(float *)((char *)a2 + 62) = v4;
+v5 = v4 + *(float *)((char *)a2 + 50);
+*(float *)((char *)a2 + 50) = v5;
+if ( v5 <= *(float *)((char *)this + 102) )
+{
+v6 = *(_DWORD *)((char *)this + 102);
+*(_DWORD *)((char *)this + 78) = 0;
+*(_DWORD *)((char *)this + 82) = 0;
+*(_DWORD *)((char *)a2 + 50) = v6;
+v7 = *(_DWORD *)((char *)this + 106);
+*(float *)((char *)a2 + 62) = 0.0;
+*(_DWORD *)((char *)a2 + 110) = v7;
+*(float *)((char *)a2 + 58) = 0.0;
+*(_DWORD *)((char *)a2 + 106) = 0;
+*(float *)((char *)a2 + 54) = 0.0;
+*(float *)((char *)a2 + 66) = 0.0;
+loader_play_sound(*(_DWORD *)((char *)this + 70));
+control_handler(58, v3);
+}
+}
+result = 0;
+}
+else
+{
+v9 = *(float *)((char *)this + 114) - *(float *)((char *)a2 + 42);
+v11 = v9;
+v10 = *(float *)((char *)this + 118) - *(float *)((char *)a2 + 46);
+v12 = v10;
+if ( v10 * v10 + v9 * v9 <= *(float *)((char *)this + 126) )
+{
+normalize_2d(&v11);
+*(float *)a3 = v11 * *(float *)((char *)v3 + 110) - *(float *)((char *)a2 + 54) * *(float *)((char *)a2 + 66);
+*((float *)a3 + 1) = v12 * *(float *)((char *)v3 + 110)
+- *(float *)((char *)a2 + 58) * *(float *)((char *)a2 + 66);
+result = 1;
+}
+else
+{
+result = 0;
+}
+}
+return result;
+}
+
+//----- (01016AB1) --------------------------------------------------------
+int __thiscall THole::Message(THole *this, int a2, float a3)
+{
+THole *v3; // esi
+
+v3 = this;
+if ( a2 == 1024 && *(_DWORD *)((char *)this + 78) )
+{
+if ( *(_DWORD *)((char *)this + 86) )
+timer_kill(*(_DWORD *)((char *)this + 86));
+*(_DWORD *)((char *)v3 + 86) = 0;
+*(_DWORD *)((char *)v3 + 82) = 1;
+}
+return 0;
+}
+
+//----- (01018476) --------------------------------------------------------
+void __thiscall THole::Collision(THole *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+THole *v6; // esi
+int v7; // ecx
+
+v6 = this;
+if ( !*(_DWORD *)((char *)this + 78) )
+{
+*(_DWORD *)((char *)this + 82) = 0;
+*(_DWORD *)((char *)this + 66) = 1315859240;
+*(_DWORD *)((char *)this + 78) = 1;
+*(_DWORD *)((char *)a2 + 106) = this;
+*(_DWORD *)((char *)a2 + 42) = *(_DWORD *)((char *)this + 114);
+v7 = *(_DWORD *)((char *)this + 118);
+*(float *)((char *)a2 + 62) = 0.0;
+*(_DWORD *)((char *)a2 + 46) = v7;
+*(_DWORD *)((char *)v6 + 86) = timer_set(0.5, (int)v6, (int)THole::TimerExpired);
+if ( !*(_DWORD *)(*(_DWORD *)((char *)v6 + 30) + 370) )
+{
+loader_play_sound(*(_DWORD *)((char *)v6 + 74));
+control_handler(57, v6);
+}
+}
+}
+
+//----- (01019A1C) --------------------------------------------------------
+THole *__thiscall THole::THole(THole *this, struct TPinballTable *a2, int a3)
+{
+THole *v3; // ebx
+_DWORD *v4; // eax
+_DWORD *v5; // eax
+int v6; // eax
+float *v7; // edi
+double v8; // st7
+TCircle *v9; // eax
+float *v10; // eax
+unsigned int v11; // ecx
+char v13; // [esp+14h] [ebp-5Ch]
+_DWORD *v14; // [esp+20h] [ebp-50h]
+unsigned int v15; // [esp+48h] [ebp-28h]
+int v16; // [esp+5Ch] [ebp-14h]
+int v17; // [esp+60h] [ebp-10h]
+int v18; // [esp+64h] [ebp-Ch]
+int v19; // [esp+68h] [ebp-8h]
+struct vector_type *v20; // [esp+6Ch] [ebp-4h]
+float v21; // [esp+78h] [ebp+8h]
+TCircle *v22; // [esp+78h] [ebp+8h]
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 0);
+*(_DWORD *)v3 = &THole::`vftable';
+*(_DWORD *)((char *)v3 + 94) = 1028443341;
+*(_DWORD *)((char *)v3 + 6) = 0;
+*(_DWORD *)((char *)v3 + 86) = 0;
+*(_DWORD *)((char *)v3 + 78) = 0;
+v4 = (_DWORD *)loader_query_float_attribute(a3, 0, 407);
+if ( v4 )
+*(_DWORD *)((char *)v3 + 90) = *v4;
+else
+*(_DWORD *)((char *)v3 + 90) = 1048576000;
+v5 = (_DWORD *)loader_query_float_attribute(a3, 0, 701);
+if ( v5 )
+*(_DWORD *)((char *)v3 + 98) = *v5;
+else
+*(_DWORD *)((char *)v3 + 98) = 1056964608;
+v21 = *(float *)loader_query_float_attribute(a3, 0, 306);
+*(_DWORD *)((char *)v3 + 110) = *(_DWORD *)loader_query_float_attribute(a3, 0, 305);
+loader_query_visual(a3, 0, &v13);
+v6 = (int)v14;
+*(_DWORD *)((char *)v3 + 114) = *v14;
+v7 = (float *)(v6 + 8);
+*(_DWORD *)((char *)v3 + 118) = *(_DWORD *)(v6 + 4);
+v8 = v21 * *(float *)(v6 + 8);
+v20 = (struct vector_type *)v6;
+*(float *)((char *)v3 + 126) = v8;
+if ( 0.0 == v8 )
+*(_DWORD *)((char *)v3 + 126) = 981668463;
+v9 = (TCircle *)operator new(0x25u);
+if ( v9 )
+v22 = TCircle::TCircle(v9, v3, (char *)v3 + 5, v15, v20, *(float *)((char *)v3 + 126));
+else
+v22 = 0;
+if ( v22 )
+{
+(*(void (**)(void))(*(_DWORD *)v22 + 8))();
+objlist_class::Add((THole *)((char *)v3 + 42), (void *)v22);
+}
+*(float *)((char *)v3 + 126) = *v7 * *v7;
+*(_DWORD *)((char *)v3 + 102) = *(_DWORD *)(loader_query_float_attribute(a3, 0, 408) + 8);
+v10 = (float *)loader_query_float_attribute(a3, 0, 1304);
+*(_DWORD *)((char *)v3 + 106) = (signed __int64)_floor(*v10);
+v19 = *(_DWORD *)((char *)v3 + 126);
+v16 = *(_DWORD *)((char *)v3 + 114);
+v17 = *(_DWORD *)((char *)v3 + 118);
+*(_DWORD *)((char *)v3 + 130) = (char *)v3 + 5;
+v11 = v15;
+v18 = *(_DWORD *)((char *)v3 + 122);
+*(_DWORD *)((char *)v3 + 138) = v3;
+*(_DWORD *)((char *)v3 + 134) = v11;
+edges_insert_circle((struct circle_type *)&v16, 0, (THole *)((char *)v3 + 130));
+return v3;
+}
+// 10026AC: using guessed type void *THole::`vftable';
diff --git a/Classes/TKickback/TKickback.cpp b/Classes/TKickback/TKickback.cpp
new file mode 100644
index 0000000..2bdd83f
--- /dev/null
+++ b/Classes/TKickback/TKickback.cpp
@@ -0,0 +1,108 @@
+#include "../../pinball.h"
+
+//----- (0101663F) --------------------------------------------------------
+void __stdcall TKickback::TimerExpired(int a1, struct TPinballComponent *a2)
+{
+int v2; // eax
+int v3; // ST10_4
+int v4; // eax
+int v5; // eax
+
+if ( *(_DWORD *)((char *)a2 + 90) )
+{
+*(float *)((char *)a2 + 66) = 0.0;
+v2 = timer_set(*(float *)((char *)a2 + 82), (int)a2, (int)TKickback::TimerExpired);
+v3 = *(_DWORD *)((char *)a2 + 74);
+*(_DWORD *)((char *)a2 + 86) = v2;
+loader_play_sound(v3);
+v4 = *(_DWORD *)((char *)a2 + 34);
+if ( v4 )
+render_sprite_set(
+*(_DWORD **)((char *)a2 + 26),
+*(_DWORD *)(*(_DWORD *)(v4 + 4) + 12),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)a2 + 38) + 4) + 12),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(v4 + 4) + 12) + 29) - *(_DWORD *)(*(_DWORD *)((char *)a2 + 30) + 234),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(v4 + 4) + 12) + 33) - *(_DWORD *)(*(_DWORD *)((char *)a2 + 30) + 238));
+}
+else
+{
+v5 = *(_DWORD *)((char *)a2 + 34);
+if ( v5 )
+render_sprite_set(
+*(_DWORD **)((char *)a2 + 26),
+*(_DWORD *)(*(_DWORD *)(v5 + 4) + 8),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)a2 + 38) + 4) + 8),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(v5 + 4) + 8) + 29) - *(_DWORD *)(*(_DWORD *)((char *)a2 + 30) + 234),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(v5 + 4) + 8) + 33) - *(_DWORD *)(*(_DWORD *)((char *)a2 + 30) + 238));
+*(_DWORD *)((char *)a2 + 86) = 0;
+control_handler(60, a2);
+}
+}
+
+//----- (010166F6) --------------------------------------------------------
+int __thiscall TKickback::Message(TKickback *this, int a2, float a3)
+{
+TKickback *v3; // esi
+
+v3 = this;
+if ( (a2 == 1011 || a2 == 1024) && *(_DWORD *)((char *)this + 86) )
+{
+timer_kill(*(_DWORD *)((char *)this + 86));
+if ( *(_DWORD *)((char *)v3 + 34) )
+render_sprite_set_bitmap(*(_DWORD **)((char *)v3 + 26), 0);
+*(_DWORD *)((char *)v3 + 86) = 0;
+*(_DWORD *)((char *)v3 + 90) = 0;
+*(_DWORD *)((char *)v3 + 66) = 1315859240;
+}
+return 0;
+}
+
+//----- (010183E8) --------------------------------------------------------
+void __thiscall TKickback::Collision(TKickback *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TKickback *v6; // esi
+float v7; // ST10_4
+
+v6 = this;
+if ( *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 370) )
+{
+basic_collision(
+a2,
+a3,
+a4,
+*(float *)((char *)this + 54),
+*(float *)((char *)this + 58),
+0.0,
+*(float *)((char *)this + 62));
+}
+else
+{
+if ( !*(_DWORD *)((char *)this + 90) )
+{
+v7 = *(float *)((char *)this + 78);
+*(_DWORD *)((char *)this + 66) = 1315859240;
+*(_DWORD *)((char *)this + 90) = 1;
+*(_DWORD *)((char *)this + 86) = timer_set(v7, (int)this, (int)TKickback::TimerExpired);
+}
+if ( TCollisionComponent::DefaultCollision(v6, a2, a3, a4) )
+*(_DWORD *)((char *)v6 + 90) = 0;
+}
+}
+
+//----- (0101983D) --------------------------------------------------------
+TKickback *__thiscall TKickback::TKickback(TKickback *this, struct TPinballTable *a2, int a3)
+{
+TKickback *v3; // esi
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+*(_DWORD *)((char *)v3 + 6) = 0;
+*(_DWORD *)((char *)v3 + 86) = 0;
+*(_DWORD *)((char *)v3 + 90) = 0;
+*(_DWORD *)v3 = &TKickback::`vftable';
+*(_DWORD *)((char *)v3 + 78) = 1060320051;
+*(_DWORD *)((char *)v3 + 82) = 1036831949;
+*(_DWORD *)((char *)v3 + 66) = 1315859240;
+return v3;
+}
+// 1002668: using guessed type void *TKickback::`vftable';
diff --git a/Classes/TKickout/TKickout.cpp b/Classes/TKickout/TKickout.cpp
new file mode 100644
index 0000000..566333c
--- /dev/null
+++ b/Classes/TKickout/TKickout.cpp
@@ -0,0 +1,240 @@
+#include "../../pinball.h"
+
+//----- (01016745) --------------------------------------------------------
+void __thiscall TKickout::Collision(TKickout *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+struct TPinballComponent *v6; // esi
+
+v6 = this;
+if ( !*(_DWORD *)((char *)this + 78) )
+{
+*(_DWORD *)((char *)this + 102) = a2;
+*(_DWORD *)((char *)this + 66) = 1315859240;
+*(_DWORD *)((char *)this + 78) = 1;
+*(_DWORD *)((char *)a2 + 106) = this;
+*(_DWORD *)((char *)a2 + 42) = *(_DWORD *)((char *)this + 110);
+*(_DWORD *)((char *)a2 + 46) = *(_DWORD *)((char *)this + 114);
+*(_DWORD *)((char *)this + 126) = *(_DWORD *)((char *)a2 + 50);
+*(_DWORD *)((char *)a2 + 50) = *(_DWORD *)((char *)this + 98);
+if ( *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 370) )
+{
+(**(void (__thiscall ***)(TKickout *, signed int, _DWORD))this)(this, 55, 0.1);
+}
+else
+{
+loader_play_sound(*(_DWORD *)((char *)this + 70));
+control_handler(63, v6);
+}
+}
+}
+
+//----- (010167BE) --------------------------------------------------------
+void __stdcall TKickout::ResetTimerExpired(int a1, void *a2)
+{
+if ( !*(_DWORD *)((char *)a2 + 82) )
+*((_BYTE *)a2 + 5) = 1;
+*(_DWORD *)((char *)a2 + 86) = 0;
+}
+
+//----- (010167DD) --------------------------------------------------------
+void __stdcall TKickout::TimerExpired(int a1, void *a2)
+{
+double v2; // st7
+float v3; // ST08_4
+int v4; // eax
+int v5; // ecx
+int v6; // ST10_4
+
+if ( *(_DWORD *)((char *)a2 + 78) )
+{
+v2 = *(float *)((char *)a2 + 94);
+*(_DWORD *)((char *)a2 + 78) = 0;
+v3 = v2;
+*(_DWORD *)((char *)a2 + 86) = timer_set(v3, (int)a2, (int)TKickout::ResetTimerExpired);
+v4 = *(_DWORD *)((char *)a2 + 102);
+if ( v4 )
+{
+v5 = *(_DWORD *)((char *)a2 + 126);
+*(_DWORD *)((char *)a2 + 102) = 0;
+*(_DWORD *)(v4 + 50) = v5;
+throw_ball(
+(struct TBall *)v4,
+(struct vector_type *)((char *)a2 + 130),
+*(float *)((char *)a2 + 142),
+*(float *)((char *)a2 + 146),
+*(float *)((char *)a2 + 150));
+v6 = *(_DWORD *)((char *)a2 + 74);
+*((_BYTE *)a2 + 5) = 0;
+loader_play_sound(v6);
+}
+}
+}
+
+//----- (0101685B) --------------------------------------------------------
+int __thiscall TKickout::FieldEffect(TKickout *this, struct TBall *a2, struct vector_type *a3)
+{
+TKickout *v3; // edi
+double v5; // st7
+double v6; // st6
+float v7; // [esp+4h] [ebp-Ch]
+float v8; // [esp+8h] [ebp-8h]
+
+v3 = this;
+if ( *(_DWORD *)((char *)this + 78) )
+return 0;
+v5 = *(float *)((char *)this + 110) - *(float *)((char *)a2 + 42);
+v7 = v5;
+v6 = *(float *)((char *)this + 114) - *(float *)((char *)a2 + 46);
+v8 = v6;
+if ( v6 * v6 + v5 * v5 > *(float *)((char *)this + 122) )
+return 0;
+normalize_2d(&v7);
+*(float *)a3 = v7 * *(float *)((char *)v3 + 106) - *(float *)((char *)a2 + 54) * *(float *)((char *)a2 + 66);
+*((float *)a3 + 1) = v8 * *(float *)((char *)v3 + 106) - *(float *)((char *)a2 + 58) * *(float *)((char *)a2 + 66);
+return 1;
+}
+
+//----- (010168E3) --------------------------------------------------------
+int __thiscall TKickout::Message(TKickout *this, int a2, float a3)
+{
+TKickout *v3; // esi
+
+v3 = this;
+if ( a2 == 55 )
+{
+if ( *(_DWORD *)((char *)this + 78) )
+{
+if ( a3 < 0.0 )
+a3 = *(float *)((char *)this + 90);
+*(_DWORD *)((char *)this + 86) = timer_set(a3, (int)this, (int)TKickout::TimerExpired);
+}
+}
+else
+{
+if ( a2 != 1011 )
+{
+if ( a2 != 1024 )
+return 0;
+if ( *(_DWORD *)((char *)this + 78) )
+{
+if ( *(_DWORD *)((char *)this + 86) )
+timer_kill(*(_DWORD *)((char *)this + 86));
+TKickout::TimerExpired(0, (void *)v3);
+}
+}
+if ( *(_DWORD *)((char *)v3 + 82) )
+*((_BYTE *)v3 + 5) = 0;
+}
+return 0;
+}
+
+//----- (01016963) --------------------------------------------------------
+int __thiscall TKickout::get_scoring(TKickout *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 5 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 166);
+return result;
+}
+
+//----- (01016984) --------------------------------------------------------
+void __thiscall TKickout::put_scoring(TKickout *this, int a2, int a3)
+{
+if ( a2 < 5 )
+*(_DWORD *)((char *)this + 4 * a2 + 166) = a3;
+}
+
+//----- (01019884) --------------------------------------------------------
+TKickout *__thiscall TKickout::TKickout(TKickout *this, struct TPinballTable *a2, int a3, struct vector_type *a4)
+{
+TKickout *v4; // ebx
+float *v5; // eax
+float *v6; // esi
+double v7; // st7
+TCircle *v8; // eax
+int v9; // eax
+double v10; // st7
+int v11; // eax
+int v12; // eax
+unsigned int v13; // ecx
+char v15; // [esp+10h] [ebp-58h]
+float *v16; // [esp+1Ch] [ebp-4Ch]
+int v17; // [esp+20h] [ebp-48h]
+int v18; // [esp+28h] [ebp-40h]
+float v19; // [esp+2Ch] [ebp-3Ch]
+int v20; // [esp+30h] [ebp-38h]
+int v21; // [esp+34h] [ebp-34h]
+int v22; // [esp+38h] [ebp-30h]
+int v23; // [esp+3Ch] [ebp-2Ch]
+int v24; // [esp+40h] [ebp-28h]
+unsigned int v25; // [esp+44h] [ebp-24h]
+int v26; // [esp+58h] [ebp-10h]
+int v27; // [esp+5Ch] [ebp-Ch]
+int v28; // [esp+60h] [ebp-8h]
+int v29; // [esp+64h] [ebp-4h]
+float v30; // [esp+70h] [ebp+8h]
+TCircle *v31; // [esp+70h] [ebp+8h]
+struct vector_type *v32; // [esp+78h] [ebp+10h]
+
+v4 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 0);
+*(_DWORD *)v4 = &TKickout::`vftable';
+*(_DWORD *)((char *)v4 + 82) = a4 == 0;
+if ( !a4 )
+*((_BYTE *)v4 + 5) = 0;
+*(_DWORD *)((char *)v4 + 90) = 1069547520;
+*(_DWORD *)((char *)v4 + 94) = 1028443341;
+*(_DWORD *)((char *)v4 + 6) = 0;
+*(_DWORD *)((char *)v4 + 86) = 0;
+*(_DWORD *)((char *)v4 + 78) = 0;
+v30 = *(float *)loader_query_float_attribute(a3, 0, 306);
+*(_DWORD *)((char *)v4 + 106) = *(_DWORD *)loader_query_float_attribute(a3, 0, 305);
+loader_query_visual(a3, 0, &v15);
+*(_DWORD *)((char *)v4 + 70) = v17;
+*(_DWORD *)((char *)v4 + 74) = v24;
+v5 = v16;
+*(float *)((char *)v4 + 110) = *v16;
+v6 = v5 + 2;
+*(float *)((char *)v4 + 114) = v5[1];
+v7 = v30 * v5[2];
+v32 = (struct vector_type *)v5;
+*(float *)((char *)v4 + 122) = v7;
+if ( 0.0 == v7 )
+*(_DWORD *)((char *)v4 + 122) = 981668463;
+v8 = (TCircle *)operator new(0x25u);
+if ( v8 )
+v31 = TCircle::TCircle(v8, v4, (char *)v4 + 5, v25, v32, *(float *)((char *)v4 + 122));
+else
+v31 = 0;
+if ( v31 )
+{
+(*(void (**)(void))(*(_DWORD *)v31 + 8))();
+objlist_class::Add((TKickout *)((char *)v4 + 42), (void *)v31);
+}
+*(float *)((char *)v4 + 122) = *v6 * *v6;
+v9 = loader_query_float_attribute(a3, 0, 408);
+v10 = v19 * 0.01;
+*(_DWORD *)((char *)v4 + 98) = *(_DWORD *)(v9 + 8);
+v11 = v23;
+*(float *)((char *)v4 + 150) = v10;
+*(_DWORD *)((char *)v4 + 130) = v20;
+*(_DWORD *)((char *)v4 + 134) = v21;
+*(_DWORD *)((char *)v4 + 142) = v11;
+v12 = v18;
+*(_DWORD *)((char *)v4 + 138) = v22;
+*(_DWORD *)((char *)v4 + 146) = v12;
+v29 = *(_DWORD *)((char *)v4 + 122);
+v26 = *(_DWORD *)((char *)v4 + 110);
+v27 = *(_DWORD *)((char *)v4 + 114);
+*(_DWORD *)((char *)v4 + 154) = (char *)v4 + 5;
+v13 = v25;
+v28 = *(_DWORD *)((char *)v4 + 118);
+*(_DWORD *)((char *)v4 + 162) = v4;
+*(_DWORD *)((char *)v4 + 158) = v13;
+edges_insert_circle((struct circle_type *)&v26, 0, (TKickout *)((char *)v4 + 154));
+return v4;
+}
+// 1002690: using guessed type void *TKickout::`vftable';
diff --git a/Classes/TLight/TLight.cpp b/Classes/TLight/TLight.cpp
new file mode 100644
index 0000000..279a589
--- /dev/null
+++ b/Classes/TLight/TLight.cpp
@@ -0,0 +1,368 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "TLight.h"
+
+//----- (010099A8) --------------------------------------------------------
+void __thiscall TLight::Reset(TLight *this)
+{
+ TLight *v1; // esi
+ _DWORD *v2; // ST00_4
+ int v3; // eax
+
+ v1 = this;
+ if ( *(_DWORD *)((char *)this + 110) )
+ timer_kill(*(_DWORD *)((char *)this + 110));
+ if ( *(_DWORD *)((char *)v1 + 114) )
+ timer_kill(*(_DWORD *)((char *)v1 + 114));
+ if ( *(_DWORD *)((char *)v1 + 82) )
+ flasher_stop((TLight *)((char *)v1 + 42), -1);
+ v2 = *(_DWORD **)((char *)v1 + 26);
+ *(float *)((char *)v1 + 122) = 1.0;
+ *(_DWORD *)((char *)v1 + 110) = 0;
+ *(_DWORD *)((char *)v1 + 114) = 0;
+ *(_DWORD *)((char *)v1 + 78) = 0;
+ *(_DWORD *)((char *)v1 + 98) = 0;
+ *(_DWORD *)((char *)v1 + 86) = 0;
+ *(_DWORD *)((char *)v1 + 90) = 0;
+ *(_DWORD *)((char *)v1 + 82) = 0;
+ *(_DWORD *)((char *)v1 + 94) = 0;
+ render_sprite_set_bitmap(v2, 0);
+ *(_DWORD *)((char *)v1 + 42) = *(_DWORD *)((char *)v1 + 26);
+ v3 = *(_DWORD *)((char *)v1 + 34);
+ *(_DWORD *)((char *)v1 + 46) = 0;
+ if ( v3 )
+ *(_DWORD *)((char *)v1 + 50) = *(_DWORD *)(*(_DWORD *)(v3 + 4) + 8);
+ *(_DWORD *)((char *)v1 + 58) = 0;
+ *(_DWORD *)((char *)v1 + 54) = 0;
+ *(_DWORD *)((char *)v1 + 6) = 0;
+}
+
+//----- (01009A2A) --------------------------------------------------------
+void __stdcall TLight::TimerExpired(int a1, void *a2)
+{
+ bool v2; // zf
+ void (__thiscall **v3)(void *, signed int, _DWORD); // eax
+
+ if ( *(_DWORD *)((char *)a2 + 82) )
+ flasher_stop((struct flasher_type *)((char *)a2 + 42), -1);
+ render_sprite_set_bitmap(
+ *(_DWORD **)((char *)a2 + 26),
+ *(_DWORD *)((char *)a2 + 4 * *(_DWORD *)((char *)a2 + 78) + 46));
+ v2 = *(_DWORD *)((char *)a2 + 94) == 0;
+ *(_DWORD *)((char *)a2 + 86) = 0;
+ *(_DWORD *)((char *)a2 + 90) = 0;
+ *(_DWORD *)((char *)a2 + 82) = 0;
+ *(_DWORD *)((char *)a2 + 110) = 0;
+ if ( !v2 )
+ {
+ v3 = *(void (__thiscall ***)(void *, signed int, _DWORD))a2;
+ *(_DWORD *)((char *)a2 + 94) = 0;
+ (*v3)(a2, 20, 0.0);
+ }
+ if ( *(_DWORD *)((char *)a2 + 18) )
+ control_handler(60, (struct TPinballComponent *)a2);
+}
+
+//----- (01009A8F) --------------------------------------------------------
+void __thiscall TLight::schedule_timeout(TLight *this, float a2)
+{
+TLight *v2; // esi
+
+v2 = this;
+*(_DWORD *)((char *)this + 62) = *(_DWORD *)((char *)this + 102);
+*(_DWORD *)((char *)this + 66) = *(_DWORD *)((char *)this + 106);
+if ( *(_DWORD *)((char *)this + 110) )
+timer_kill(*(_DWORD *)((char *)this + 110));
+*(_DWORD *)((char *)v2 + 110) = 0;
+if ( a2 > 0.0 )
+*(_DWORD *)((char *)v2 + 110) = timer_set(a2, (int)v2, (int)TLight::TimerExpired);
+}
+
+//----- (01009AE3) --------------------------------------------------------
+int __thiscall TLight::Message(TLight *this, int a2, float a3)
+{
+TLight *v3; // esi
+bool v4; // zf
+int v5; // ST04_4
+float v6; // ST04_4
+signed __int64 v7; // rax
+int v8; // ecx
+signed int v9; // edx
+signed int v10; // edi
+int v11; // eax
+int v12; // eax
+int v13; // eax
+float v15; // ST04_4
+float v16; // ST04_4
+signed __int64 v17; // rax
+char *v18; // eax
+char *v19; // eax
+float v20; // ST04_4
+int v21; // ecx
+_DWORD *v22; // eax
+int v23; // [esp+1Ch] [ebp+Ch]
+
+v3 = this;
+if ( a2 > 1020 )
+{
+if ( a2 == 1024 )
+{
+(*(void (__thiscall **)(TLight *))(*(_DWORD *)this + 20))(this);
+v21 = 0;
+if ( *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 214) > 0 )
+{
+v22 = (_DWORD *)((char *)v3 + 146);
+do
+{
+*(v22 - 3) = *(_DWORD *)((char *)v3 + 82);
+*v22 = *(_DWORD *)((char *)v3 + 98);
+*(v22 - 4) = *(_DWORD *)((char *)v3 + 78);
+*(v22 - 5) = *(_DWORD *)((char *)v3 + 6);
+++v21;
+v22 += 6;
+}
+while ( v21 < *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 214) );
+}
+}
+}
+else if ( a2 == 1020 )
+{
+v18 = (char *)this + 24 * *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 218);
+*(_DWORD *)(v18 + 134) = *(_DWORD *)((char *)this + 82);
+*(_DWORD *)(v18 + 146) = *(_DWORD *)((char *)this + 98);
+*(_DWORD *)(v18 + 130) = *(_DWORD *)((char *)this + 78);
+*(_DWORD *)(v18 + 126) = *(_DWORD *)((char *)this + 6);
+(*(void (__thiscall **)(TLight *))(*(_DWORD *)this + 20))(this);
+v19 = (char *)v3 + 24 * (unsigned __int64)(signed __int64)_floor(a3);
+*(_DWORD *)((char *)v3 + 82) = *(_DWORD *)(v19 + 134);
+*(_DWORD *)((char *)v3 + 98) = *(_DWORD *)(v19 + 146);
+*(_DWORD *)((char *)v3 + 78) = *(_DWORD *)(v19 + 130);
+*(_DWORD *)((char *)v3 + 6) = *(_DWORD *)(v19 + 126);
+if ( *(_DWORD *)((char *)v3 + 98) )
+{
+v20 = (double)*(signed int *)((char *)v3 + 98);
+TLight::Message(v3, 11, v20);
+}
+if ( *(_DWORD *)((char *)v3 + 78) )
+TLight::Message(v3, 1, 0.0);
+if ( *(_DWORD *)((char *)v3 + 82) )
+TLight::Message(v3, 4, 0.0);
+}
+else
+{
+switch ( a2 )
+{
+case 0:
+v4 = *(_DWORD *)((char *)this + 82) == 0;
+*(_DWORD *)((char *)this + 78) = 0;
+if ( v4 && !*(_DWORD *)((char *)this + 86) && !*(_DWORD *)((char *)this + 90) )
+render_sprite_set_bitmap(*(_DWORD **)((char *)this + 26), *(_DWORD *)((char *)this + 46));
+return 0;
+case 1:
+v4 = *(_DWORD *)((char *)this + 82) == 0;
+*(_DWORD *)((char *)this + 78) = 1;
+if ( v4 && !*(_DWORD *)((char *)this + 86) && !*(_DWORD *)((char *)this + 90) )
+render_sprite_set_bitmap(*(_DWORD **)((char *)this + 26), *(_DWORD *)((char *)this + 50));
+return 0;
+case 2:
+return *(_DWORD *)((char *)v3 + 78);
+case 3:
+return *(_DWORD *)((char *)this + 82);
+case 4:
+TLight::schedule_timeout(this, 0.0);
+if ( !*(_DWORD *)((char *)v3 + 82) || !*(_DWORD *)((char *)v3 + 70) )
+{
+v5 = *(_DWORD *)((char *)v3 + 78);
+*(_DWORD *)((char *)v3 + 82) = 1;
+*(_DWORD *)((char *)v3 + 90) = 0;
+*(_DWORD *)((char *)v3 + 86) = 0;
+*(_DWORD *)((char *)v3 + 94) = 0;
+flasher_start((TLight *)((char *)v3 + 42), v5);
+}
+return 0;
+case 5:
+*(float *)((char *)this + 62) = a3 * *(float *)((char *)this + 102);
+*(float *)((char *)this + 66) = a3 * *(float *)((char *)this + 106);
+return 0;
+case 6:
+*(_DWORD *)((char *)this + 62) = *(_DWORD *)((char *)this + 102);
+*(_DWORD *)((char *)this + 66) = *(_DWORD *)((char *)this + 106);
+return 0;
+case 7:
+if ( !*(_DWORD *)((char *)this + 82) )
+flasher_start((TLight *)((char *)this + 42), *(_DWORD *)((char *)this + 78));
+*(_DWORD *)((char *)v3 + 82) = 1;
+*(_DWORD *)((char *)v3 + 90) = 0;
+*(_DWORD *)((char *)v3 + 94) = 0;
+goto LABEL_28;
+case 8:
+if ( !*(_DWORD *)((char *)this + 86) )
+{
+if ( *(_DWORD *)((char *)this + 82) )
+{
+flasher_stop((TLight *)((char *)this + 42), 0);
+*(_DWORD *)((char *)v3 + 82) = 0;
+}
+else
+{
+render_sprite_set_bitmap(*(_DWORD **)((char *)this + 26), *(_DWORD *)((char *)this + 46));
+}
+*(_DWORD *)((char *)v3 + 86) = 1;
+*(_DWORD *)((char *)v3 + 90) = 0;
+}
+goto LABEL_29;
+case 9:
+if ( !*(_DWORD *)((char *)this + 90) )
+{
+if ( *(_DWORD *)((char *)this + 82) )
+{
+flasher_stop((TLight *)((char *)this + 42), 1);
+*(_DWORD *)((char *)v3 + 82) = 0;
+}
+else
+{
+render_sprite_set_bitmap(*(_DWORD **)((char *)this + 26), *(_DWORD *)((char *)this + 50));
+}
+*(_DWORD *)((char *)v3 + 90) = 1;
+LABEL_28:
+*(_DWORD *)((char *)v3 + 86) = 0;
+}
+LABEL_29:
+ TLight::schedule_timeout(v3, a3);
+return 0;
+case 11:
+v7 = (signed __int64)_floor(a3);
+v8 = *(_DWORD *)((char *)v3 + 34);
+*(_DWORD *)((char *)v3 + 98) = v7;
+v9 = *(_DWORD *)(*(_DWORD *)(v8 + 4) + 4);
+if ( (signed int)v7 > v9 )
+*(_DWORD *)((char *)v3 + 98) = v9;
+v10 = 0;
+if ( *(_DWORD *)((char *)v3 + 98) < 0 )
+*(_DWORD *)((char *)v3 + 98) = 0;
+v4 = *(_DWORD *)((char *)v3 + 82) == 0;
+v11 = *(_DWORD *)((char *)v3 + 98);
+*(_DWORD *)((char *)v3 + 46) = 0;
+*(_DWORD *)((char *)v3 + 50) = *(_DWORD *)(*(_DWORD *)(v8 + 4) + 4 * v11 + 8);
+if ( v4 )
+{
+if ( !*(_DWORD *)((char *)v3 + 86) )
+{
+if ( *(_DWORD *)((char *)v3 + 90) )
+v10 = 1;
+else
+v10 = *(_DWORD *)((char *)v3 + 78);
+}
+}
+else
+{
+v10 = *(_DWORD *)((char *)v3 + 74);
+}
+render_sprite_set_bitmap(*(_DWORD **)((char *)v3 + 26), *(_DWORD *)((char *)v3 + 4 * v10 + 46));
+return 0;
+case 12:
+v23 = *(_DWORD *)((char *)this + 98) + 1;
+if ( v23 > *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)this + 34) + 4) + 4) )
+v23 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)this + 34) + 4) + 4);
+goto LABEL_32;
+case 13:
+v23 = *(_DWORD *)((char *)this + 98) - 1;
+if ( v23 < 0 )
+v23 = 0;
+LABEL_32:
+ v6 = (double)v23;
+TLight::Message(this, 11, v6);
+return 0;
+case 14:
+if ( *(_DWORD *)((char *)this + 110) )
+timer_kill(*(_DWORD *)((char *)this + 110));
+v4 = *(_DWORD *)((char *)v3 + 82) == 0;
+*(_DWORD *)((char *)v3 + 110) = 0;
+if ( !v4 )
+flasher_stop((TLight *)((char *)v3 + 42), -1);
+v12 = *(_DWORD *)((char *)v3 + 78);
+*(_DWORD *)((char *)v3 + 82) = 0;
+*(_DWORD *)((char *)v3 + 86) = 0;
+*(_DWORD *)((char *)v3 + 90) = 0;
+render_sprite_set_bitmap(*(_DWORD **)((char *)v3 + 26), *(_DWORD *)((char *)v3 + 4 * v12 + 46));
+return 0;
+case 15:
+v13 = *(_DWORD *)((char *)this + 114);
+*(_DWORD *)((char *)this + 94) = 0;
+if ( v13 )
+timer_kill(v13);
+*(_DWORD *)((char *)v3 + 114) = 0;
+TLight::Message(v3, 1, 0.0);
+TLight::Message(v3, 7, a3);
+return 0;
+case 16:
+if ( *(_DWORD *)((char *)this + 114) )
+timer_kill(*(_DWORD *)((char *)this + 114));
+*(_DWORD *)((char *)v3 + 114) = 0;
+TLight::Message(v3, 7, a3);
+*(_DWORD *)((char *)v3 + 94) = 1;
+return 0;
+case 17:
+v17 = (signed __int64)_floor(a3);
+TLight::Message(v3, v17 != 0, 0.0);
+return *(_DWORD *)((char *)v3 + 78);
+case 18:
+TLight::Message(this, 17, a3);
+TLight::Message(v3, 14, 0.0);
+return *(_DWORD *)((char *)v3 + 78);
+case 19:
+TLight::Message(this, 1, 0.0);
+goto LABEL_62;
+case 20:
+TLight::Message(this, 0, 0.0);
+LABEL_62:
+ TLight::Message(v3, 14, 0.0);
+return 0;
+case 21:
+v15 = (double)(*(_DWORD *)((char *)this + 78) == 0);
+TLight::Message(this, 17, v15);
+return *(_DWORD *)((char *)v3 + 78);
+case 22:
+v16 = (double)(*(_DWORD *)((char *)this + 78) == 0);
+TLight::Message(this, 18, v16);
+return *(_DWORD *)((char *)v3 + 78);
+case 23:
+*(_DWORD *)((char *)this + 6) = (signed __int64)_floor(a3);
+break;
+default:
+return 0;
+}
+}
+return 0;
+}
+
+//----- (0100AD21) --------------------------------------------------------
+TLight *__thiscall TLight::TLight(TLight *this, struct TPinballTable *a2, int a3)
+{
+TLight *v3; // esi
+float *v4; // eax
+double v5; // st7
+float *v6; // eax
+double v7; // st7
+
+v3 = this;
+TPinballComponent::TPinballComponent(this, a2, a3, 1);
+*(_DWORD *)v3 = &TLight::`vftable';
+*(_DWORD *)((char *)v3 + 110) = 0;
+*(_DWORD *)((char *)v3 + 82) = 0;
+*(_DWORD *)((char *)v3 + 114) = 0;
+*(_DWORD *)((char *)v3 + 70) = 0;
+TLight::Reset(v3);
+v4 = (float *)loader_query_float_attribute(a3, 0, 900);
+v5 = *v4;
+*(float *)((char *)v3 + 62) = *v4;
+*(float *)((char *)v3 + 102) = v5;
+v6 = (float *)loader_query_float_attribute(a3, 0, 901);
+v7 = *v6;
+*(float *)((char *)v3 + 66) = *v6;
+*(float *)((char *)v3 + 106) = v7;
+return v3;
+}
+// 1001A48: using guessed type void *TLight::`vftable';
diff --git a/Classes/TLight/TLight.h b/Classes/TLight/TLight.h
new file mode 100644
index 0000000..5fc27c0
--- /dev/null
+++ b/Classes/TLight/TLight.h
@@ -0,0 +1,8 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_TLIGHT_H
+#define PINBALL_TLIGHT_H
+
+#endif //PINBALL_TLIGHT_H
diff --git a/Classes/TLightBargraph/TLightBargraph.cpp b/Classes/TLightBargraph/TLightBargraph.cpp
new file mode 100644
index 0000000..907a028
--- /dev/null
+++ b/Classes/TLightBargraph/TLightBargraph.cpp
@@ -0,0 +1,195 @@
+//
+// Created by neo on 2019-08-15.
+
+#include "TLightBargraph.h"
+
+//----- (0100AA81) --------------------------------------------------------
+TZmapList *__thiscall TLightBargraph::~TLightBargraph(TLightBargraph *this)
+{
+ TLightGroup *v1; // esi
+ int v2; // eax
+
+ v1 = this;
+ v2 = *(_DWORD *)((char *)this + 138);
+ *(_DWORD *)this = &TLightBargraph::`vftable';
+ if ( v2 )
+ memoryfree(v2);
+ return TLightGroup::~TLightGroup(v1);
+}
+// 1001A30: using guessed type void *TLightBargraph::`vftable';
+
+//----- (0100AAA9) --------------------------------------------------------
+void __thiscall TLightBargraph::Reset(TLightBargraph *this)
+{
+ TLightBargraph *v1; // edi
+ _DWORD *v2; // esi
+
+ v1 = this;
+ v2 = (_DWORD *)((char *)this + 142);
+ if ( *(_DWORD *)((char *)this + 142) )
+ {
+ timer_kill(*(_DWORD *)((char *)this + 142));
+ *v2 = 0;
+ }
+ *(_DWORD *)((char *)v1 + 146) = 0;
+ TLightGroup::Reset(v1);
+}
+
+//----- (0100AAD9) --------------------------------------------------------
+void __stdcall TLightBargraph::BargraphTimerExpired(int a1, void *a2)
+{
+ int v2; // eax
+ float v3; // ST04_4
+
+ v2 = *(_DWORD *)((char *)a2 + 146);
+ *(_DWORD *)((char *)a2 + 142) = 0;
+ if ( v2 )
+ {
+ v3 = (double)(v2 - 1);
+ (**(void (__thiscall ***)(void *, signed int, _DWORD))a2)(a2, 45, LODWORD(v3));
+ control_handler(60, (struct TPinballComponent *)a2);
+ }
+ else
+ {
+ (**(void (__thiscall ***)(void *, signed int, _DWORD))a2)(a2, 20, 0.0);
+ control_handler(47, (struct TPinballComponent *)a2);
+ }
+}
+
+//----- (0100AB28) --------------------------------------------------------
+int __thiscall TLightBargraph::Message(TLightBargraph *this, int a2, float a3)
+{
+TLightBargraph *v3; // esi
+int v4; // ecx
+_DWORD *v5; // eax
+_DWORD *v6; // edi
+float v7; // ST0C_4
+int v8; // ebx
+int v9; // eax
+float v10; // ST08_4
+int v11; // eax
+signed int v13; // [esp+20h] [ebp+Ch]
+
+v3 = this;
+switch ( a2 )
+{
+case 37:
+return *(_DWORD *)((char *)this + 146);
+case 45:
+if ( *(_DWORD *)((char *)this + 142) )
+{
+timer_kill(*(_DWORD *)((char *)this + 142));
+*(_DWORD *)((char *)v3 + 142) = 0;
+}
+v8 = (signed __int64)_floor(a3);
+v9 = 2 * *(_DWORD *)(*(_DWORD *)((char *)v3 + 46) + 4);
+if ( v8 >= v9 )
+v8 = v9 - 1;
+if ( v8 >= 0 )
+{
+v10 = (double)(v8 / 2);
+TLightGroup::Message(v3, 45, v10);
+if ( !(v8 & 1) )
+TLightGroup::Message(v3, 46, 0.0);
+v11 = *(_DWORD *)((char *)v3 + 138);
+if ( v11 )
+*(_DWORD *)((char *)v3 + 142) = timer_set(
+*(float *)(v11 + 4 * v8),
+(int)v3,
+(int)TLightBargraph::BargraphTimerExpired);
+*(_DWORD *)((char *)v3 + 146) = v8;
+}
+else
+{
+TLightGroup::Message(v3, 20, 0.0);
+*(_DWORD *)((char *)v3 + 146) = 0;
+}
+break;
+case 1011:
+(*(void (**)(void))(*(_DWORD *)this + 20))();
+break;
+case 1020:
+v6 = (_DWORD *)((char *)this + 142);
+if ( *(_DWORD *)((char *)this + 142) )
+{
+timer_kill(*(_DWORD *)((char *)this + 142));
+*v6 = 0;
+}
+*(_DWORD *)((char *)v3 + 4 * *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 218) + 150) = *(_DWORD *)((char *)v3 + 146);
+(*(void (__thiscall **)(TLightBargraph *))(*(_DWORD *)v3 + 20))(v3);
+v13 = *(_DWORD *)((char *)v3 + 4 * (unsigned __int64)(signed __int64)_floor(a3) + 150);
+*(_DWORD *)((char *)v3 + 146) = v13;
+if ( v13 )
+{
+v7 = (double)v13;
+TLightBargraph::Message(v3, 45, v7);
+}
+break;
+case 1024:
+(*(void (**)(void))(*(_DWORD *)this + 20))();
+v4 = 0;
+if ( *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 214) > 0 )
+{
+v5 = (_DWORD *)((char *)v3 + 150);
+do
+{
+*v5 = *(_DWORD *)((char *)v3 + 146);
+++v4;
+++v5;
+}
+while ( v4 < *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 214) );
+}
+TLightGroup::Message(v3, 1024, a3);
+break;
+default:
+TLightGroup::Message(this, a2, a3);
+break;
+}
+return 0;
+}
+
+//----- (0100AE72) --------------------------------------------------------
+TLightBargraph *__thiscall TLightBargraph::TLightBargraph(TLightBargraph *this, struct TPinballTable *a2, int a3)
+{
+TLightBargraph *v3; // esi
+float *v4; // ebx
+int v5; // edi
+int v6; // eax
+int i; // eax
+
+v3 = this;
+TLightGroup::TLightGroup(this, a2, a3);
+*(_DWORD *)v3 = &TLightBargraph::`vftable';
+*(_DWORD *)((char *)v3 + 138) = 0;
+TLightBargraph::Reset(v3);
+if ( a3 > 0 )
+{
+v4 = (float *)loader_query_float_attribute(a3, 0, 904);
+if ( v4 )
+{
+v5 = 2 * *(_DWORD *)(*(_DWORD *)((char *)v3 + 46) + 4);
+v6 = memoryallocate(8 * *(_DWORD *)(*(_DWORD *)((char *)v3 + 46) + 4));
+*(_DWORD *)((char *)v3 + 138) = v6;
+if ( v6 )
+{
+for ( i = 0; i < v5; ++v4 )
+*(float *)(*(_DWORD *)((char *)v3 + 138) + 4 * i++) = *v4;
+}
+}
+}
+return v3;
+}
+// 1001A30: using guessed type void *TLightBargraph::`vftable';
+
+//----- (0100AEF9) --------------------------------------------------------
+TLightBargraph *__thiscall TLightBargraph::`vector deleting destructor'(TLightBargraph *this, char a2)
+{
+TLightBargraph *v2; // esi
+
+v2 = this;
+TLightBargraph::~TLightBargraph(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
+
diff --git a/Classes/TLightBargraph/TLightBargraph.h b/Classes/TLightBargraph/TLightBargraph.h
new file mode 100644
index 0000000..6d3a5a3
--- /dev/null
+++ b/Classes/TLightBargraph/TLightBargraph.h
@@ -0,0 +1,8 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_TLIGHTBARGRAPH_H
+#define PINBALL_TLIGHTBARGRAPH_H
+
+#endif //PINBALL_TLIGHTBARGRAPH_H
diff --git a/Classes/TLightRollover/TLightRollover.cpp b/Classes/TLightRollover/TLightRollover.cpp
new file mode 100644
index 0000000..b2a5b93
--- /dev/null
+++ b/Classes/TLightRollover/TLightRollover.cpp
@@ -0,0 +1,92 @@
+#include "../../pinball.h"
+
+//----- (010164D1) --------------------------------------------------------
+void __stdcall TLightRollover::delay_expired(int a1, void *a2)
+{
+render_sprite_set_bitmap(*(_DWORD **)((char *)a2 + 26), 0);
+*(_DWORD *)((char *)a2 + 91) = 0;
+}
+
+//----- (010164F2) --------------------------------------------------------
+void __thiscall TLightRollover::Collision(TLightRollover *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TLightRollover *v6; // esi
+double v7; // st7
+bool v8; // zf
+bool v9; // al
+int v10; // eax
+
+v6 = this;
+*(float *)((char *)a2 + 42) = *(float *)a3;
+v7 = *(float *)((char *)a2 + 70);
+*(_DWORD *)((char *)a2 + 46) = *((_DWORD *)a3 + 1);
+*(float *)((char *)a2 + 70) = v7 - a5;
+TBall::not_again(a2, a6);
+if ( !*(_DWORD *)(*(_DWORD *)((char *)v6 + 30) + 370) )
+{
+if ( *((_BYTE *)v6 + 78) )
+{
+timer_set(0.1, (int)v6, (int)TRollover::TimerExpired);
+v8 = *((_BYTE *)v6 + 78) == 0;
+*((_BYTE *)v6 + 5) = 0;
+v9 = v8;
+v8 = *(_DWORD *)((char *)v6 + 91) == 0;
+*((_BYTE *)v6 + 78) = v9;
+if ( v8 )
+*(_DWORD *)((char *)v6 + 91) = timer_set(
+*(float *)((char *)v6 + 87),
+(int)v6,
+(int)TLightRollover::delay_expired);
+}
+else
+{
+loader_play_sound(*(_DWORD *)((char *)v6 + 70));
+control_handler(63, v6);
+*((_BYTE *)v6 + 78) = *((_BYTE *)v6 + 78) == 0;
+v10 = *(_DWORD *)((char *)v6 + 34);
+if ( v10 )
+render_sprite_set_bitmap(*(_DWORD **)((char *)v6 + 26), *(_DWORD *)(*(_DWORD *)(v10 + 4) + 8));
+}
+}
+}
+
+//----- (010165A7) --------------------------------------------------------
+int __thiscall TLightRollover::Message(TLightRollover *this, int a2, float a3)
+{
+TLightRollover *v3; // esi
+int v4; // eax
+
+v3 = this;
+if ( a2 == 1024 )
+{
+v4 = *(_DWORD *)((char *)this + 91);
+*((_BYTE *)this + 5) = 1;
+*((_BYTE *)this + 78) = 0;
+if ( v4 )
+timer_kill(v4);
+*(_DWORD *)((char *)v3 + 91) = 0;
+if ( *(_DWORD *)((char *)v3 + 34) )
+render_sprite_set_bitmap(*(_DWORD **)((char *)v3 + 26), 0);
+}
+return 0;
+}
+
+//----- (010197BB) --------------------------------------------------------
+TLightRollover *__thiscall TLightRollover::TLightRollover(TLightRollover *this, struct TPinballTable *a2, int a3)
+{
+TLightRollover *v3; // esi
+bool v4; // zf
+
+v3 = this;
+TRollover::TRollover(this, a2, a3, 0);
+v4 = *(_DWORD *)((char *)v3 + 34) == 0;
+*(_DWORD *)v3 = &TLightRollover::`vftable';
+*((_BYTE *)v3 + 78) = 0;
+*(_DWORD *)((char *)v3 + 91) = 0;
+if ( !v4 )
+render_sprite_set_bitmap(*(_DWORD **)((char *)v3 + 26), 0);
+TRollover::build_walls(v3, a3);
+*(_DWORD *)((char *)v3 + 87) = *(_DWORD *)loader_query_float_attribute(a3, 0, 407);
+return v3;
+}
+// 1002630: using guessed type void *TLightRollover::`vftable';
diff --git a/Classes/TLine/TLine.cpp b/Classes/TLine/TLine.cpp
new file mode 100644
index 0000000..a40170e
--- /dev/null
+++ b/Classes/TLine/TLine.cpp
@@ -0,0 +1,272 @@
+#include "../../pinball.h"
+
+//----- (0101C6FD) --------------------------------------------------------
+TLine *__thiscall TLine::TLine(TLine *this, struct TCollisionComponent *a2, char *a3, unsigned int a4, float a5, float a6, float a7, float a8)
+{
+TLine *v8; // esi
+
+v8 = this;
+TEdgeSegment::TEdgeSegment(this, a2, a3, a4);
+*(float *)((char *)v8 + 69) = a5;
+*(float *)((char *)v8 + 73) = a6;
+*(float *)((char *)v8 + 77) = a7;
+*(float *)((char *)v8 + 81) = a8;
+*(_DWORD *)v8 = &TLine::`vftable';
+line_init((int)v8 + 21, a5, a6, a7, a8);
+return v8;
+}
+// 1002864: using guessed type void *TLine::`vftable';
+
+//----- (0101C764) --------------------------------------------------------
+double __thiscall TLine::FindCollisionDistance(TLine *this, struct ray_type *a2)
+{
+return ray_intersect_line((float *)a2, (float *)((char *)this + 21));
+}
+
+//----- (0101C77E) --------------------------------------------------------
+TLine *__thiscall TLine::TLine(TLine *this, struct TCollisionComponent *a2, char *a3, unsigned int a4, struct vector_type *a5, struct vector_type *a6)
+{
+TLine *v6; // esi
+double v7; // st7
+float v8; // ST10_4
+
+v6 = this;
+TEdgeSegment::TEdgeSegment(this, a2, a3, a4);
+*(_DWORD *)v6 = &TLine::`vftable';
+*(_DWORD *)((char *)v6 + 69) = *(_DWORD *)a5;
+*(_DWORD *)((char *)v6 + 73) = *((_DWORD *)a5 + 1);
+*(_DWORD *)((char *)v6 + 77) = *(_DWORD *)a6;
+v7 = *((float *)a6 + 1);
+*(float *)((char *)v6 + 81) = *((float *)a6 + 1);
+v8 = v7;
+line_init((int)v6 + 21, *(float *)((char *)v6 + 69), *(float *)((char *)v6 + 73), *(float *)((char *)v6 + 77), v8);
+return v6;
+}
+// 1002864: using guessed type void *TLine::`vftable';
+
+//----- (0101C7E6) --------------------------------------------------------
+void __thiscall TLine::EdgeCollision(TLine *this, struct TBall *a2, float a3)
+{
+(*(void (__stdcall **)(struct TBall *, char *, char *, _DWORD, TLine *))(**((_DWORD **)this + 1) + 20))(
+a2,
+(char *)this + 57,
+(char *)this + 21,
+LODWORD(a3),
+this);
+}
+
+//----- (0101C813) --------------------------------------------------------
+void __thiscall TLine::Offset(TLine *this, float a2)
+{
+double v2; // st7
+double v3; // st6
+float v4; // ST14_4
+float v5; // ST18_4
+double v6; // st6
+float v7; // ST10_4
+float v8; // [esp+20h] [ebp+8h]
+
+v2 = a2 * *(float *)((char *)this + 21);
+v3 = a2 * *(float *)((char *)this + 25);
+v4 = v2 + *(float *)((char *)this + 69);
+*(float *)((char *)this + 69) = v4;
+v5 = v3 + *(float *)((char *)this + 73);
+*(float *)((char *)this + 73) = v5;
+v8 = v2 + *(float *)((char *)this + 77);
+*(float *)((char *)this + 77) = v8;
+v6 = v3 + *(float *)((char *)this + 81);
+*(float *)((char *)this + 81) = v6;
+v7 = v6;
+line_init((int)this + 21, v4, v5, v8, v7);
+}
+
+//----- (0101C87B) --------------------------------------------------------
+void __thiscall TLine::place_in_grid(TLine *this)
+{
+TLine *v1; // esi
+int v2; // edi
+int v3; // ebx
+int v4; // ecx
+double v5; // st7
+int v6; // edi
+int v7; // edi
+double v8; // st7
+double v9; // st6
+int v10; // edi
+double v11; // st7
+double v12; // st6
+int v13; // edi
+double v14; // st7
+double v15; // st6
+double v16; // st7
+double v17; // st6
+float v18; // [esp+10h] [ebp-20h]
+float v19; // [esp+14h] [ebp-1Ch]
+signed int v20; // [esp+18h] [ebp-18h]
+int v21; // [esp+18h] [ebp-18h]
+signed int v22; // [esp+18h] [ebp-18h]
+int v23; // [esp+18h] [ebp-18h]
+signed int v24; // [esp+1Ch] [ebp-14h]
+signed int v25; // [esp+1Ch] [ebp-14h]
+int v26; // [esp+20h] [ebp-10h]
+int v27; // [esp+24h] [ebp-Ch]
+signed int v28; // [esp+28h] [ebp-8h]
+signed int v29; // [esp+2Ch] [ebp-4h]
+
+v1 = this;
+v2 = TEdgeManager::box_x(edge_manager, *(float *)((char *)this + 69));
+v3 = TEdgeManager::box_y(edge_manager, *(float *)((char *)v1 + 73));
+v27 = TEdgeManager::box_x(edge_manager, *(float *)((char *)v1 + 77));
+v4 = TEdgeManager::box_y(edge_manager, *(float *)((char *)v1 + 81));
+v26 = v4;
+if ( *(float *)((char *)v1 + 69) >= (double)*(float *)((char *)v1 + 77) )
+v24 = -1;
+else
+v24 = 1;
+if ( *(float *)((char *)v1 + 73) >= (double)*(float *)((char *)v1 + 81) )
+v20 = -1;
+else
+v20 = 1;
+if ( v3 == v4 )
+{
+if ( v24 == 1 )
+{
+while ( v2 <= v27 )
+TEdgeManager::add_edge_to_box(edge_manager, v2++, v3, v1);
+}
+else
+{
+while ( v2 >= v27 )
+TEdgeManager::add_edge_to_box(edge_manager, v2--, v3, v1);
+}
+}
+else if ( v2 == v27 )
+{
+if ( v20 == 1 )
+{
+if ( v3 <= v4 )
+{
+do
+TEdgeManager::add_edge_to_box(edge_manager, v2, v3++, v1);
+while ( v3 <= v26 );
+}
+}
+else if ( v3 >= v4 )
+{
+do
+TEdgeManager::add_edge_to_box(edge_manager, v2, v3--, v1);
+while ( v3 >= v26 );
+}
+}
+else
+{
+v28 = v2;
+v5 = (*(float *)((char *)v1 + 73) - *(float *)((char *)v1 + 81))
+/ (*(float *)((char *)v1 + 69) - *(float *)((char *)v1 + 77));
+v29 = v3;
+v19 = v5;
+v18 = *(float *)((char *)v1 + 73) - v5 * *(float *)((char *)v1 + 69);
+TEdgeManager::add_edge_to_box(edge_manager, v2, v3, v1);
+if ( v24 == 1 )
+{
+v6 = v2 + 1;
+if ( v20 == 1 )
+{
+v25 = v6;
+v7 = v28;
+v21 = v3 + 1;
+do
+{
+v8 = (double)v21 * *((float *)edge_manager + 1) + *((float *)edge_manager + 7);
+v9 = ((double)v25 * *(float *)edge_manager + *((float *)edge_manager + 6)) * v19 + v18;
+if ( v9 >= v8 )
+{
+if ( v9 == v8 )
+{
+++v7;
+++v25;
+}
+++v3;
+++v21;
+}
+else
+{
+++v7;
+++v25;
+}
+TEdgeManager::add_edge_to_box(edge_manager, v7, v3, v1);
+}
+while ( v7 != v27 || v3 != v26 );
+}
+else
+{
+v22 = v6;
+v10 = v28;
+do
+{
+v11 = (double)v29 * *((float *)edge_manager + 1) + *((float *)edge_manager + 7);
+v12 = ((double)v22 * *(float *)edge_manager + *((float *)edge_manager + 6)) * v19 + v18;
+if ( v12 <= v11 )
+{
+if ( v12 == v11 )
+{
+++v10;
+++v22;
+}
+--v29;
+}
+else
+{
+++v10;
+++v22;
+}
+TEdgeManager::add_edge_to_box(edge_manager, v10, v29, v1);
+}
+while ( v10 != v27 || v29 != v26 );
+}
+}
+else if ( v20 == 1 )
+{
+v13 = v3;
+v23 = v3 + 1;
+do
+{
+v14 = (double)v23 * *((float *)edge_manager + 1) + *((float *)edge_manager + 7);
+v15 = ((double)v28 * *(float *)edge_manager + *((float *)edge_manager + 6)) * v19 + v18;
+if ( v15 >= v14 )
+{
+if ( v15 == v14 )
+--v28;
+++v13;
+++v23;
+}
+else
+{
+--v28;
+}
+TEdgeManager::add_edge_to_box(edge_manager, v28, v13, v1);
+}
+while ( v28 != v27 || v13 != v26 );
+}
+else
+{
+do
+{
+v16 = (double)v29 * *((float *)edge_manager + 1) + *((float *)edge_manager + 7);
+v17 = ((double)v28 * *(float *)edge_manager + *((float *)edge_manager + 6)) * v19 + v18;
+if ( v17 <= v16 )
+{
+if ( v17 == v16 )
+--v28;
+--v29;
+}
+else
+{
+--v28;
+}
+TEdgeManager::add_edge_to_box(edge_manager, v28, v29, v1);
+}
+while ( v28 != v27 || v29 != v26 );
+}
+}
+}
diff --git a/Classes/TOneWay/TOneWay.cpp b/Classes/TOneWay/TOneWay.cpp
new file mode 100644
index 0000000..5bd38a5
--- /dev/null
+++ b/Classes/TOneWay/TOneWay.cpp
@@ -0,0 +1,132 @@
+
+#include "../../pinball.h"
+
+//----- (01015B61) --------------------------------------------------------
+int __thiscall TOneway::get_scoring(TOneway *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 6 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 86);
+return result;
+}
+
+//----- (01015B7F) --------------------------------------------------------
+void __thiscall TOneway::put_scoring(TOneway *this, int a2, int a3)
+{
+if ( a2 < 6 )
+*(_DWORD *)((char *)this + 4 * a2 + 86) = a3;
+}
+
+//----- (01018032) --------------------------------------------------------
+void __thiscall TOneway::Collision(TOneway *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TOneway *v6; // edi
+int v7; // edi
+double v8; // st7
+int v9; // eax
+
+v6 = this;
+if ( a6 == *(struct TEdgeSegment **)((char *)this + 82) )
+{
+TBall::not_again(a2, a6);
+v8 = *(float *)((char *)a2 + 70) - a5;
+*(_DWORD *)((char *)a2 + 42) = *(_DWORD *)a3;
+v9 = *((_DWORD *)a3 + 1);
+*(float *)((char *)a2 + 70) = v8;
+*(_DWORD *)((char *)a2 + 46) = v9;
+if ( !*(_DWORD *)(*(_DWORD *)((char *)v6 + 30) + 370) )
+{
+if ( *(_DWORD *)((char *)v6 + 74) )
+loader_play_sound(*(_DWORD *)((char *)v6 + 74));
+control_handler(63, v6);
+}
+}
+else if ( *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 370) )
+{
+basic_collision(a2, a3, a4, *(float *)((char *)this + 54), *(float *)((char *)this + 58), 1000000000.0, 0.0);
+}
+else if ( basic_collision(
+a2,
+a3,
+a4,
+*(float *)((char *)this + 54),
+*(float *)((char *)this + 58),
+*(float *)((char *)this + 66),
+*(float *)((char *)this + 62)) > 0.2 )
+{
+v7 = *(_DWORD *)((char *)v6 + 70);
+if ( v7 )
+loader_play_sound(v7);
+}
+}
+
+//----- (01019204) --------------------------------------------------------
+TOneway *__thiscall TOneway::TOneway(TOneway *this, struct TPinballTable *a2, int a3)
+{
+TLine *v3; // edi
+TOneway *v4; // esi
+TLine *v5; // eax
+TLine *v6; // eax
+TLine *v7; // eax
+float v8; // ST10_4
+char v10; // [esp+10h] [ebp-60h]
+int v11; // [esp+18h] [ebp-58h]
+int *v12; // [esp+1Ch] [ebp-54h]
+unsigned int v13; // [esp+44h] [ebp-2Ch]
+int v14; // [esp+58h] [ebp-18h]
+int v15; // [esp+5Ch] [ebp-14h]
+int v16; // [esp+64h] [ebp-Ch]
+int v17; // [esp+68h] [ebp-8h]
+
+v3 = 0;
+v4 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 0);
+*(_DWORD *)v4 = &TOneway::`vftable';
+loader_query_visual(a3, 0, &v10);
+if ( v11 == 2 )
+{
+v16 = *v12;
+v17 = v12[1];
+v14 = v12[2];
+v15 = v12[3];
+v5 = (TLine *)operator new(0x55u);
+if ( v5 )
+v3 = TLine::TLine(v5, v4, (char *)v4 + 5, v13, (struct vector_type *)&v16, (struct vector_type *)&v14);
+if ( v3 )
+{
+TLine::Offset(v3, *(float *)((char *)a2 + 282));
+(*(void (__thiscall **)(TLine *))(*(_DWORD *)v3 + 8))(v3);
+objlist_class::Add((TOneway *)((char *)v4 + 42), (void *)v3);
+}
+v6 = (TLine *)operator new(0x55u);
+if ( v6 )
+v7 = TLine::TLine(v6, v4, (char *)v4 + 5, v13, (struct vector_type *)&v14, (struct vector_type *)&v16);
+else
+v7 = 0;
+*(_DWORD *)((char *)v4 + 82) = v7;
+if ( v7 )
+{
+v8 = -(*(float *)((char *)a2 + 282) * 0.8);
+TLine::Offset(v7, v8);
+(*(void (**)(void))(**(_DWORD **)((char *)v4 + 82) + 8))();
+objlist_class::Add((TOneway *)((char *)v4 + 42), *(void **)((char *)v4 + 82));
+}
+}
+return v4;
+}
+// 1002530: using guessed type void *TOneway::`vftable';
+
+//----- (0101AAA7) --------------------------------------------------------
+TOneway *__thiscall TOneway::`scalar deleting destructor`(TOneway *this, char a2)
+{
+TOneway *v2; // esi
+
+v2 = this;
+TCollisionComponent::~TCollisionComponent(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
diff --git a/Classes/TPinballComponent/TPinballComponent.cpp b/Classes/TPinballComponent/TPinballComponent.cpp
new file mode 100644
index 0000000..d252406
--- /dev/null
+++ b/Classes/TPinballComponent/TPinballComponent.cpp
@@ -0,0 +1,231 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "TPinballComponent.h"
+
+//----- (010145F5) --------------------------------------------------------
+void *__stdcall TPinballComponent::operator new(size_t SizeOfElements)
+{
+return _calloc(1u, SizeOfElements);
+}
+
+//----- (010159A9) --------------------------------------------------------
+int __thiscall TPinballComponent::Message(TPinballComponent *this, int a2, float a3)
+{
+*(_DWORD *)((char *)this + 6) = a2;
+if ( a2 == 1024 )
+*(_DWORD *)((char *)this + 6) = 0;
+return 0;
+}
+
+//----- (010159CA) --------------------------------------------------------
+int __stdcall TPinballComponent::get_scoring(int a2)
+{
+return 0;
+}
+
+//----- (01017C6D) --------------------------------------------------------
+TPinballComponent *__thiscall TPinballComponent::TPinballComponent(TPinballComponent *this, struct TPinballTable *a2, int a3, int a4)
+{
+TPinballComponent *v4; // esi
+struct TPinballTable *v5; // edi
+TZmapList *v6; // eax
+TZmapList *v7; // eax
+objlist_class *v8; // ecx
+TZmapList *v9; // eax
+TZmapList *v10; // eax
+objlist_class *v11; // ecx
+int v12; // eax
+int v13; // ecx
+_DWORD *v14; // eax
+signed int v15; // ebx
+_DWORD *v16; // eax
+int v17; // eax
+char v19; // [esp+Ch] [ebp-6Ch]
+void *v20; // [esp+4Ch] [ebp-2Ch]
+void *v21; // [esp+50h] [ebp-28h]
+int v22; // [esp+54h] [ebp-24h]
+int v23; // [esp+58h] [ebp-20h]
+int v24; // [esp+5Ch] [ebp-1Ch]
+int v25; // [esp+60h] [ebp-18h]
+int v26; // [esp+64h] [ebp-14h]
+int v27; // [esp+68h] [ebp-10h]
+int v28; // [esp+6Ch] [ebp-Ch]
+int v29; // [esp+70h] [ebp-8h]
+int v30; // [esp+74h] [ebp-4h]
+struct TPinballTable *v31; // [esp+80h] [ebp+8h]
+struct TPinballTable *v32; // [esp+80h] [ebp+8h]
+signed int v33; // [esp+88h] [ebp+10h]
+
+v4 = this;
+v5 = a2;
+*(_DWORD *)this = &TPinballComponent::`vftable';
+*(_DWORD *)((char *)this + 6) = 0;
+*((_BYTE *)this + 4) = 0;
+*((_BYTE *)this + 5) = 0;
+*(_DWORD *)((char *)this + 30) = a2;
+*(_DWORD *)((char *)this + 26) = 0;
+if ( a2 )
+objlist_class::Add((struct TPinballTable *)((char *)a2 + 250), (void *)this);
+if ( a3 >= 0 )
+*(_DWORD *)((char *)v4 + 10) = loader_query_name(a3);
+if ( a4 && a3 >= 0 )
+{
+v33 = loader_query_visual_states(a3);
+v31 = 0;
+if ( v33 > 0 )
+{
+do
+{
+loader_query_visual(a3, (signed int)v31, &v19);
+if ( v20 )
+{
+if ( !*(_DWORD *)((char *)v4 + 34) )
+{
+v6 = (TZmapList *)operator new(8u);
+if ( v6 )
+v7 = TZmapList::TZmapList(v6, v33, 4);
+else
+v7 = 0;
+*(_DWORD *)((char *)v4 + 34) = v7;
+}
+v8 = *(objlist_class **)((char *)v4 + 34);
+if ( v8 )
+objlist_class::Add(v8, v20);
+}
+if ( v21 )
+{
+if ( !*(_DWORD *)((char *)v4 + 38) )
+{
+v9 = (TZmapList *)operator new(8u);
+if ( v9 )
+v10 = TZmapList::TZmapList(v9, v33, 4);
+else
+v10 = 0;
+*(_DWORD *)((char *)v4 + 38) = v10;
+}
+v11 = *(objlist_class **)((char *)v4 + 38);
+if ( v11 )
+objlist_class::Add(v11, v21);
+}
+v31 = (struct TPinballTable *)((char *)v31 + 1);
+}
+while ( (signed int)v31 < v33 );
+}
+v12 = *(_DWORD *)((char *)v4 + 38);
+if ( v12 )
+v30 = *(_DWORD *)(*(_DWORD *)(v12 + 4) + 8);
+v13 = *(_DWORD *)((char *)v4 + 34);
+if ( v13 )
+{
+v14 = *(_DWORD **)(*(_DWORD *)(v13 + 4) + 8);
+v26 = *(_DWORD *)((char *)v14 + 29) - *(_DWORD *)((char *)v5 + 234);
+v15 = 1;
+v27 = *(_DWORD *)((char *)v14 + 33) - *(_DWORD *)((char *)v5 + 238);
+v28 = v14[3];
+v29 = v14[4];
+if ( *(_DWORD *)(*(_DWORD *)(v13 + 4) + 4) > 1 )
+{
+v32 = (struct TPinballTable *)12;
+do
+{
+v16 = *(_DWORD **)((char *)v32 + *(_DWORD *)(*(_DWORD *)((char *)v4 + 34) + 4));
+v22 = *(_DWORD *)((char *)v16 + 29) - *(_DWORD *)((char *)v5 + 234);
+v23 = *(_DWORD *)((char *)v16 + 33) - *(_DWORD *)((char *)v5 + 238);
+v24 = v16[3];
+v25 = v16[4];
+enclosing_box(&v26, &v22, &v26);
+v32 = (struct TPinballTable *)((char *)v32 + 4);
+++v15;
+}
+while ( v15 < *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v4 + 34) + 4) + 4) );
+}
+v17 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v4 + 34) + 4) + 8);
+*(_DWORD *)((char *)v4 + 26) = render_create_sprite(
+v33 > 0,
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v4 + 34) + 4) + 8),
+v30,
+*(_DWORD *)(v17 + 29) - *(_DWORD *)((char *)v5 + 234),
+*(_DWORD *)(v17 + 33) - *(_DWORD *)((char *)v5 + 238),
+&v26);
+}
+}
+*(_DWORD *)((char *)v4 + 22) = a3;
+return v4;
+}
+// 10024A8: using guessed type void *TPinballComponent::`vftable';
+
+//----- (01018FBC) --------------------------------------------------------
+TZmapList *__thiscall TPinballComponent::~TPinballComponent(TPinballComponent *this)
+{
+TPinballComponent *v1; // esi
+TZmapList *result; // eax
+TZmapList *v3; // ecx
+TZmapList *v4; // ecx
+
+v1 = this;
+result = *(TZmapList **)((char *)this + 30);
+*(_DWORD *)this = &TPinballComponent::`vftable';
+if ( result )
+result = (TZmapList *)objlist_delete_object(*(_DWORD *)((char *)result + 254), (int)this);
+v3 = *(TZmapList **)((char *)v1 + 34);
+if ( v3 )
+result = TZmapList::`scalar deleting destructor`(v3, 1);
+v4 = *(TZmapList **)((char *)v1 + 38);
+if ( v4 )
+result = TZmapList::`scalar deleting destructor`(v4, 1);
+return result;
+}
+// 10024A8: using guessed type void *TPinballComponent::`vftable';
+
+//----- (01018FFD) --------------------------------------------------------
+TComponentGroup *__thiscall TComponentGroup::TComponentGroup(TComponentGroup *this, struct TPinballTable *a2, int a3)
+{
+TComponentGroup *v3; // esi
+int v4; // eax
+signed __int16 *i; // edi
+struct TPinballComponent *v6; // eax
+int v8; // [esp+Ch] [ebp-4h]
+int v9; // [esp+1Ch] [ebp+Ch]
+
+v3 = this;
+TPinballComponent::TPinballComponent(this, a2, a3, 0);
+*(_DWORD *)v3 = &TComponentGroup::`vftable';
+objlist_class::objlist_class((TComponentGroup *)((char *)v3 + 42), 4, 4);
+*(_DWORD *)((char *)v3 + 50) = 0;
+if ( a3 > 0 )
+{
+v4 = loader_query_iattribute(a3, 1027, &v8);
+v9 = 0;
+for ( i = (signed __int16 *)v4; v9 < v8; ++i )
+{
+v6 = TPinballTable::find_component(a2, *i);
+if ( v6 )
+objlist_class::Add((TComponentGroup *)((char *)v3 + 42), (void *)v6);
+++v9;
+}
+}
+return v3;
+}
+// 10024D8: using guessed type void *TComponentGroup::`vftable';
+
+//----- (01019082) --------------------------------------------------------
+TZmapList *__thiscall TComponentGroup::~TComponentGroup(TComponentGroup *this)
+{
+TComponentGroup *v1; // esi
+int v2; // eax
+
+v1 = this;
+v2 = *(_DWORD *)((char *)this + 50);
+*(_DWORD *)this = &TComponentGroup::`vftable';
+if ( v2 )
+{
+timer_kill(v2);
+*(_DWORD *)((char *)v1 + 50) = 0;
+}
+objlist_destroy(*(_DWORD *)((char *)v1 + 46));
+return TPinballComponent::~TPinballComponent(v1);
+}
+// 10024D8: using guessed type void *TComponentGroup::`vftable';
+
diff --git a/Classes/TPinballComponent/TPinballComponent.h b/Classes/TPinballComponent/TPinballComponent.h
new file mode 100644
index 0000000..de99b14
--- /dev/null
+++ b/Classes/TPinballComponent/TPinballComponent.h
@@ -0,0 +1,8 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_TPINBALLCOMPONENT_H
+#define PINBALL_TPINBALLCOMPONENT_H
+
+#endif //PINBALL_TPINBALLCOMPONENT_H
diff --git a/Classes/TPinballTable/TPinballTable.cpp b/Classes/TPinballTable/TPinballTable.cpp
new file mode 100644
index 0000000..4543e54
--- /dev/null
+++ b/Classes/TPinballTable/TPinballTable.cpp
@@ -0,0 +1,995 @@
+#include "../../pinball.h"
+
+//----- (01017467) --------------------------------------------------------
+void __stdcall TPinballTable::LightShow_timeout(int a1, void *a2)
+{
+void (__stdcall **v2)(signed int, _DWORD); // eax
+
+v2 = *(void (__stdcall ***)(signed int, _DWORD))a2;
+*(_DWORD *)((char *)a2 + 90) = 0;
+(*v2)(1013, 0.0);
+}
+
+//----- (0101748B) --------------------------------------------------------
+void __stdcall TPinballTable::EndGame_timeout(int a1, void *a2)
+{
+char *v2; // esi
+int v3; // eax
+int v4; // edi
+void (__thiscall ***v5)(_DWORD, signed int, _DWORD); // esi
+char *v6; // eax
+char *v7; // [esp+28h] [ebp+Ch]
+
+v2 = (char *)a2;
+*(_DWORD *)((char *)a2 + 94) = 0;
+pb_end_game();
+v3 = *(_DWORD *)(*(_DWORD *)((char *)a2 + 254) + 4) - 1;
+if ( v3 >= 0 )
+{
+v4 = 4 * v3 + 8;
+v7 = *(char **)(*(_DWORD *)((char *)a2 + 254) + 4);
+do
+{
+(***(void (__stdcall ****)(signed int, _DWORD))(v4 + *(_DWORD *)(v2 + 254)))(1022, 0.0);
+v4 -= 4;
+--v7;
+}
+while ( v7 );
+}
+v5 = *(void (__thiscall ****)(_DWORD, signed int, _DWORD))(v2 + 230);
+if ( v5 )
+(**v5)(v5, 1022, 0.0);
+control_handler(67, MissTextBox);
+v6 = get_rc_string(24, 0);
+TTextBox::Display(InfoTextBox, 1022, v6, -1.0);
+}
+
+//----- (01017526) --------------------------------------------------------
+int __thiscall TPinballTable::AddScore(TPinballTable *this, int a2)
+{
+_DWORD *v2; // eax
+_DWORD *v3; // eax
+int v4; // esi
+int *v5; // eax
+signed int v6; // edx
+
+if ( *(_DWORD *)((char *)this + 318) )
+{
+v2 = (_DWORD *)((char *)this + 314);
+*v2 += a2;
+if ( *(_DWORD *)((char *)this + 314) > 5000000 )
+*v2 = 5000000;
+}
+if ( *(_DWORD *)((char *)this + 310) )
+{
+v3 = (_DWORD *)((char *)this + 306);
+*v3 += a2;
+if ( *(_DWORD *)((char *)this + 306) > 5000000 )
+*v3 = 5000000;
+}
+v4 = *(_DWORD *)((char *)this + 298) + a2 * dword_1024758[*(_DWORD *)((char *)this + 294)];
+v5 = (int *)((char *)this + 82);
+*v5 += v4;
+v6 = *(_DWORD *)((char *)this + 82);
+if ( v6 > 1000000000 )
+{
+++*(_DWORD *)((char *)this + 86);
+*v5 = v6 - 1000000000;
+}
+score_set(*(_DWORD **)((char *)this + 50), *v5);
+return v4;
+}
+
+//----- (010175AA) --------------------------------------------------------
+void __userpurge TPinballTable::ChangeBallCount(TPinballTable *this@, int a2@, int a3)
+{
+TPinballTable *v3; // esi
+
+v3 = this;
+*(_DWORD *)((char *)this + 326) = a3;
+if ( a3 <= 0 )
+{
+score_erase(a2, *(_DWORD **)((char *)this + 54), 1);
+}
+else
+{
+score_set(*(_DWORD **)((char *)this + 54), *(_DWORD *)((char *)this + 330) - a3 + 1);
+score_update(a2, *(int **)((char *)v3 + 54));
+}
+}
+
+//----- (010175EF) --------------------------------------------------------
+void __stdcall TPinballTable::replay_timer_callback(int a1, void *a2)
+{
+*(_DWORD *)((char *)a2 + 354) = 0;
+*(_DWORD *)((char *)a2 + 358) = 0;
+}
+
+//----- (0101760E) --------------------------------------------------------
+void __thiscall TPinballTable::port_draw(TPinballTable *this)
+{
+TPinballTable *v1; // edi
+int v2; // eax
+int v3; // esi
+int v4; // ebx
+
+v1 = this;
+v2 = *(_DWORD *)(*(_DWORD *)((char *)this + 254) + 4) - 1;
+if ( v2 >= 0 )
+{
+v3 = 4 * v2 + 8;
+v4 = *(_DWORD *)(*(_DWORD *)((char *)this + 254) + 4);
+do
+{
+(*(void (**)(void))(**(_DWORD **)(v3 + *(_DWORD *)((char *)v1 + 254)) + 4))();
+v3 -= 4;
+--v4;
+}
+while ( v4 );
+}
+}
+
+//----- (01017648) --------------------------------------------------------
+struct TPinballComponent *__thiscall TPinballTable::find_component(TPinballTable *this, char *lpString2)
+{
+TPinballTable *v2; // edi
+signed int v3; // ebx
+int v4; // esi
+const CHAR *v5; // eax
+struct TPinballComponent *result; // eax
+int v7; // [esp+Ch] [ebp-8h]
+int v8; // [esp+10h] [ebp-4h]
+
+v8 = 0;
+v2 = this;
+v7 = *(_DWORD *)(*(_DWORD *)((char *)this + 254) + 4);
+if ( *(_DWORD *)(*(_DWORD *)((char *)this + 254) + 4) <= 0 )
+{
+LABEL_6:
+MessageBoxA(0, "Table cant find:", lpString2, 0x2000u);
+result = 0;
+}
+else
+{
+v3 = 8;
+while ( 1 )
+{
+v4 = *(_DWORD *)(v3 + *(_DWORD *)((char *)v2 + 254));
+v5 = *(const CHAR **)(v4 + 10);
+if ( v5 )
+{
+if ( !lstrcmpA(v5, lpString2) )
+break;
+}
+++v8;
+v3 += 4;
+if ( v8 >= v7 )
+goto LABEL_6;
+}
+result = (struct TPinballComponent *)v4;
+}
+return result;
+}
+
+//----- (010176BE) --------------------------------------------------------
+struct TPinballComponent *__thiscall TPinballTable::find_component(TPinballTable *this, int Val)
+{
+int v2; // eax
+int v3; // ecx
+int v4; // esi
+int v5; // edx
+struct TPinballComponent *result; // eax
+char DstBuf; // [esp+8h] [ebp-CCh]
+
+v2 = *(_DWORD *)((char *)this + 254);
+v3 = *(_DWORD *)(v2 + 4);
+v4 = 0;
+if ( v3 <= 0 )
+{
+LABEL_5:
+__itoa(Val, &DstBuf, 10);
+MessageBoxA(0, "Table cant find (lh):", &DstBuf, 0x2000u);
+result = 0;
+}
+else
+{
+v5 = v2 + 8;
+while ( 1 )
+{
+result = *(struct TPinballComponent **)v5;
+if ( Val == *(_DWORD *)(*(_DWORD *)v5 + 22) )
+break;
+++v4;
+v5 += 4;
+if ( v4 >= v3 )
+goto LABEL_5;
+}
+}
+return result;
+}
+
+//----- (01017738) --------------------------------------------------------
+void __stdcall TPinballTable::tilt_timeout(int a1, void *a2)
+{
+int v2; // eax
+_DWORD *v3; // edi
+int v4; // ebx
+char v5; // [esp+14h] [ebp-Ch]
+
+*(_DWORD *)((char *)a2 + 98) = 0;
+if ( *(_DWORD *)((char *)a2 + 370) )
+{
+v2 = *(_DWORD *)((char *)a2 + 262);
+v3 = (_DWORD *)(v2 + 8);
+if ( *(_DWORD *)(v2 + 4) > 0 )
+{
+v4 = *(_DWORD *)(v2 + 4);
+do
+{
+(*(void (__stdcall **)(_DWORD, char *, char *, _DWORD, _DWORD))(**(_DWORD **)((char *)a2 + 226) + 20))(
+*v3,
+&v5,
+&v5,
+0.0,
+0);
+++v3;
+--v4;
+}
+while ( v4 );
+}
+}
+}
+
+//----- (01017791) --------------------------------------------------------
+void __userpurge TPinballTable::tilt(TPinballTable *this@, int a2@, float a3)
+{
+TPinballTable *v3; // esi
+int v4; // ST14_4
+char *v5; // eax
+int v6; // ebx
+signed int v7; // ebx
+int v8; // [esp+20h] [ebp-4h]
+
+v3 = this;
+if ( !*(_DWORD *)((char *)this + 370) && !*(_DWORD *)((char *)this + 78) )
+{
+v4 = a2;
+TTextBox::Clear(InfoTextBox, a2);
+TTextBox::Clear(MissTextBox, a2);
+v5 = get_rc_string(35, 0);
+TTextBox::Display(InfoTextBox, a2, v5, -1.0);
+loader_play_sound(*(_DWORD *)((char *)v3 + 74));
+*(_DWORD *)((char *)v3 + 98) = timer_set(30.0, (int)v3, (int)TPinballTable::tilt_timeout);
+v6 = *(_DWORD *)(*(_DWORD *)((char *)v3 + 254) + 4);
+v8 = *(_DWORD *)(*(_DWORD *)((char *)v3 + 254) + 4);
+(**(void (__thiscall ***)(TPinballTable *, signed int, _DWORD, int))v3)(v3, 1011, -1.0, v4);
+if ( v6 > 0 )
+{
+v7 = 8;
+do
+{
+(***(void (__stdcall ****)(signed int, _DWORD))(v7 + *(_DWORD *)((char *)v3 + 254)))(1011, LODWORD(a3));
+v7 += 4;
+--v8;
+}
+while ( v8 );
+}
+(***(void (__stdcall ****)(signed int))((char *)v3 + 266))(8);
+*(_DWORD *)((char *)v3 + 370) = 1;
+table_control_handler(1011);
+}
+}
+
+//----- (010187D6) --------------------------------------------------------
+int __userpurge TPinballTable::Message@(TPinballTable *this@, int a2@, int a3, float a4)
+{
+TPinballTable *v4; // esi
+int v5; // eax
+int v6; // edi
+int v7; // ebx
+int v8; // eax
+int v9; // eax
+signed __int64 v10; // rax
+_DWORD *v11; // ST14_4
+bool v12; // zf
+bool v13; // sf
+unsigned __int8 v14; // of
+_DWORD *v15; // edi
+signed int v16; // eax
+int v17; // edi
+float v18; // ST10_4
+char *v19; // eax
+void (__thiscall ***v20)(_DWORD, signed int, _DWORD); // esi
+float v21; // ST10_4
+signed int v22; // ebx
+int v23; // ecx
+int v24; // eax
+int v25; // ST18_4
+_DWORD *v26; // ST14_4
+int v27; // edi
+float v28; // ST28_4
+char *v29; // eax
+char *v30; // eax
+void (__thiscall ***v31)(_DWORD, signed int, _DWORD); // esi
+void (__thiscall ***v32)(_DWORD, signed int, _DWORD); // esi
+int v33; // eax
+int v34; // edi
+int v35; // ebx
+char *v36; // eax
+float v38; // [esp+18h] [ebp-18h]
+int v39; // [esp+2Ch] [ebp-4h]
+signed int v40; // [esp+3Ch] [ebp+Ch]
+_DWORD **v41; // [esp+3Ch] [ebp+Ch]
+signed int v42; // [esp+3Ch] [ebp+Ch]
+
+v4 = this;
+switch ( a3 )
+{
+case 1000:
+if ( !*(_DWORD *)((char *)this + 370) )
+{
+v32 = *(void (__thiscall ****)(_DWORD, signed int, _DWORD))((char *)this + 42);
+goto LABEL_73;
+}
+goto LABEL_81;
+case 1001:
+if ( !*(_DWORD *)((char *)this + 370) )
+{
+v31 = *(void (__thiscall ****)(_DWORD, signed int, _DWORD))((char *)this + 42);
+goto LABEL_70;
+}
+goto LABEL_81;
+case 1002:
+if ( !*(_DWORD *)((char *)this + 370) )
+{
+v32 = *(void (__thiscall ****)(_DWORD, signed int, _DWORD))((char *)this + 46);
+LABEL_73:
+(**v32)(v32, 1, LODWORD(a4));
+}
+goto LABEL_81;
+case 1003:
+if ( !*(_DWORD *)((char *)this + 370) )
+{
+v31 = *(void (__thiscall ****)(_DWORD, signed int, _DWORD))((char *)this + 46);
+LABEL_70:
+(**v31)(v31, 2, LODWORD(a4));
+}
+goto LABEL_81;
+case 1004:
+case 1005:
+(***(void (__thiscall ****)(_DWORD, int, _DWORD))((char *)this + 222))(
+*(_DWORD *)((char *)this + 222),
+a3,
+LODWORD(a4));
+goto LABEL_81;
+case 1008:
+case 1009:
+case 1010:
+v33 = *(_DWORD *)(*(_DWORD *)((char *)this + 254) + 4) - 1;
+if ( v33 >= 0 )
+{
+v34 = 4 * v33 + 8;
+v35 = *(_DWORD *)(*(_DWORD *)((char *)this + 254) + 4);
+do
+{
+(***(void (__stdcall ****)(int, _DWORD))(v34 + *(_DWORD *)((char *)v4 + 254)))(a3, LODWORD(a4));
+v34 -= 4;
+--v35;
+}
+while ( v35 );
+}
+goto LABEL_81;
+case 1012:
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)this + 266))(14, 0.0);
+if ( *(_DWORD *)((char *)v4 + 370) )
+{
+*(_DWORD *)((char *)v4 + 370) = 0;
+if ( *(_DWORD *)((char *)v4 + 98) )
+timer_kill(*(_DWORD *)((char *)v4 + 98));
+*(_DWORD *)((char *)v4 + 98) = 0;
+}
+goto LABEL_81;
+case 1013:
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)this + 266))(34, 0.0);
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)v4 + 266))(20, 0.0);
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)v4 + 222))(1016, 0.0);
+if ( *(_BYTE *)(*(_DWORD *)((char *)v4 + 230) + 5) )
+v19 = get_rc_string(30, 0);
+else
+v19 = get_rc_string(26, 0);
+TTextBox::Display(InfoTextBox, 0, v19, -1.0);
+v20 = *(void (__thiscall ****)(_DWORD, signed int, _DWORD))((char *)v4 + 230);
+if ( v20 )
+(**v20)(v20, 1014, 0.0);
+goto LABEL_81;
+case 1014:
+if ( *(_DWORD *)((char *)this + 94) )
+{
+timer_kill(*(_DWORD *)((char *)this + 94));
+TPinballTable::EndGame_timeout(0, (void *)v4);
+pb_mode_change(1);
+}
+if ( *(_DWORD *)((char *)v4 + 90) )
+{
+timer_kill(*(_DWORD *)((char *)v4 + 90));
+*(_DWORD *)((char *)v4 + 90) = 0;
+TPinballTable::Message(v4, 1013, 0.0);
+}
+else
+{
+*(_DWORD *)((char *)v4 + 62) = 0;
+TPinballTable::Message(v4, 1024, 0.0);
+v9 = *(_DWORD *)(*(_DWORD *)((char *)v4 + 262) + 8);
+*(float *)(v9 + 46) = 0.0;
+*(float *)(v9 + 42) = 0.0;
+*(_DWORD *)(v9 + 50) = -1085485875;
+v10 = (signed __int64)_floor(a4);
+*(_DWORD *)((char *)v4 + 214) = v10;
+if ( (signed int)v10 >= 1 )
+{
+if ( (signed int)v10 > 4 )
+*(_DWORD *)((char *)v4 + 214) = 4;
+}
+else
+{
+*(_DWORD *)((char *)v4 + 214) = 1;
+}
+v11 = *(_DWORD **)((char *)v4 + 102);
+*(_DWORD *)((char *)v4 + 218) = 0;
+*(_DWORD *)((char *)v4 + 50) = v11;
+*(_DWORD *)((char *)v4 + 82) = 0;
+score_set(v11, 0);
+v14 = __OFSUB__(*(_DWORD *)((char *)v4 + 214), 1);
+v12 = *(_DWORD *)((char *)v4 + 214) == 1;
+v13 = *(_DWORD *)((char *)v4 + 214) - 1 < 0;
+*(_DWORD *)((char *)v4 + 294) = 0;
+v40 = 1;
+if ( !((unsigned __int8)(v13 ^ v14) | v12) )
+{
+v15 = (_DWORD *)((char *)v4 + 134);
+do
+{
+score_set((_DWORD *)*(v15 - 1), 0);
+++v40;
+*v15 = 0;
+v15[1] = 0;
+v15[3] = *(_DWORD *)((char *)v4 + 330);
+v15[4] = *(_DWORD *)((char *)v4 + 334);
+v15[5] = *(_DWORD *)((char *)v4 + 342);
+v15[2] = *(_DWORD *)((char *)v4 + 314);
+v15 += 7;
+}
+while ( v40 < *(_DWORD *)((char *)v4 + 214) );
+}
+*(_DWORD *)((char *)v4 + 326) = *(_DWORD *)((char *)v4 + 330);
+Sound_Idle();
+TPinballTable::ChangeBallCount(v4, 0, *(_DWORD *)((char *)v4 + 326));
+score_set(*(_DWORD **)((char *)v4 + 58), *(_DWORD *)((char *)v4 + 218) + 1);
+score_update(0, *(int **)((char *)v4 + 58));
+Sound_Idle();
+v16 = *(_DWORD *)((char *)v4 + 214);
+if ( v16 < 4 )
+{
+v41 = (_DWORD **)((char *)v4 + 28 * v16 + 102);
+v17 = 4 - v16;
+do
+{
+score_set(*v41, -1);
+v41 += 7;
+--v17;
+}
+while ( v17 );
+}
+Sound_Idle();
+*(_DWORD *)((char *)v4 + 318) = 0;
+*(_DWORD *)((char *)v4 + 310) = 0;
+*(_DWORD *)((char *)v4 + 322) = 0;
+TTextBox::Clear(InfoTextBox, 0);
+Sound_Idle();
+TTextBox::Clear(MissTextBox, 0);
+Sound_Idle();
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)v4 + 266))(28, 0.2);
+v18 = loader_play_sound(*(_DWORD *)((char *)v4 + 66));
+*(_DWORD *)((char *)v4 + 90) = timer_set(v18, (int)v4, (int)TPinballTable::LightShow_timeout);
+}
+goto LABEL_81;
+case 1018:
+if ( *(_DWORD *)((char *)this + 358) )
+timer_kill(*(_DWORD *)((char *)this + 358));
+v21 = _floor(a4);
+*(_DWORD *)((char *)v4 + 358) = timer_set(v21, (int)v4, (int)TPinballTable::replay_timer_callback);
+*(_DWORD *)((char *)v4 + 354) = 1;
+goto LABEL_81;
+case 1021:
+v22 = *(_DWORD *)((char *)this + 214);
+if ( v22 > 1 )
+{
+v23 = *(_DWORD *)((char *)this + 218);
+v39 = (v23 + 1) % v22;
+v24 = (int)v4 + 28 * v39;
+if ( *(_DWORD *)(v24 + 118) <= 0 )
+goto LABEL_81;
+*(_DWORD *)((char *)v4 + 28 * v23 + 106) = *(_DWORD *)((char *)v4 + 82);
+*(_DWORD *)((char *)v4 + 28 * *(_DWORD *)((char *)v4 + 218) + 110) = *(_DWORD *)((char *)v4 + 86);
+*(_DWORD *)((char *)v4 + 28 * *(_DWORD *)((char *)v4 + 218) + 118) = *(_DWORD *)((char *)v4 + 326);
+*(_DWORD *)((char *)v4 + 28 * *(_DWORD *)((char *)v4 + 218) + 122) = *(_DWORD *)((char *)v4 + 334);
+*(_DWORD *)((char *)v4 + 28 * *(_DWORD *)((char *)v4 + 218) + 126) = *(_DWORD *)((char *)v4 + 342);
+*(_DWORD *)((char *)v4 + 28 * *(_DWORD *)((char *)v4 + 218) + 114) = *(_DWORD *)((char *)v4 + 314);
+*(_DWORD *)((char *)v4 + 82) = *(_DWORD *)(v24 + 106);
+v25 = *(_DWORD *)((char *)v4 + 82);
+*(_DWORD *)((char *)v4 + 86) = *(_DWORD *)(v24 + 110);
+*(_DWORD *)((char *)v4 + 326) = *(_DWORD *)(v24 + 118);
+*(_DWORD *)((char *)v4 + 334) = *(_DWORD *)(v24 + 122);
+*(_DWORD *)((char *)v4 + 342) = *(_DWORD *)(v24 + 126);
+*(_DWORD *)((char *)v4 + 314) = *(_DWORD *)(v24 + 114);
+v26 = *(_DWORD **)(v24 + 102);
+*(_DWORD *)((char *)v4 + 50) = v26;
+score_set(v26, v25);
+*(_DWORD *)(*(_DWORD *)((char *)v4 + 50) + 4) = 1;
+TPinballTable::ChangeBallCount(v4, 0, *(_DWORD *)((char *)v4 + 326));
+score_set(*(_DWORD **)((char *)v4 + 58), v39 + 1);
+score_update(0, *(int **)((char *)v4 + 58));
+v27 = 0;
+if ( *(_DWORD *)(*(_DWORD *)((char *)v4 + 254) + 4) > 0 )
+{
+v42 = 8;
+do
+{
+v28 = (double)v39;
+(***(void (__stdcall ****)(signed int, _DWORD))(v42 + *(_DWORD *)((char *)v4 + 254)))(1020, LODWORD(v28));
+v42 += 4;
+++v27;
+}
+while ( v27 < *(_DWORD *)(*(_DWORD *)((char *)v4 + 254) + 4) );
+}
+if ( v39 )
+{
+switch ( v39 )
+{
+case 1:
+v38 = -1.0;
+if ( *(_BYTE *)(*(_DWORD *)((char *)v4 + 230) + 5) )
+v29 = get_rc_string(31, 0);
+else
+v29 = get_rc_string(27, 0);
+break;
+case 2:
+v38 = -1.0;
+if ( *(_BYTE *)(*(_DWORD *)((char *)v4 + 230) + 5) )
+v29 = get_rc_string(32, 0);
+else
+v29 = get_rc_string(28, 0);
+break;
+case 3:
+v38 = -1.0;
+if ( *(_BYTE *)(*(_DWORD *)((char *)v4 + 230) + 5) )
+v29 = get_rc_string(33, 0);
+else
+v29 = get_rc_string(29, 0);
+break;
+default:
+LABEL_59:
+*(_DWORD *)((char *)v4 + 318) = 0;
+*(_DWORD *)((char *)v4 + 310) = 0;
+*(_DWORD *)((char *)v4 + 322) = 0;
+*(_DWORD *)((char *)v4 + 218) = v39;
+goto LABEL_81;
+}
+}
+else
+{
+v38 = -1.0;
+if ( *(_BYTE *)(*(_DWORD *)((char *)v4 + 230) + 5) )
+v29 = get_rc_string(30, 0);
+else
+v29 = get_rc_string(26, 0);
+}
+TTextBox::Display(InfoTextBox, 0, v29, v38);
+goto LABEL_59;
+}
+if ( *(_BYTE *)(*(_DWORD *)((char *)this + 230) + 5) )
+v30 = get_rc_string(30, 0);
+else
+v30 = get_rc_string(26, 0);
+TTextBox::Display(InfoTextBox, 0, v30, -1.0);
+LABEL_81:
+table_control_handler(a3);
+return 0;
+case 1022:
+loader_play_sound(*(_DWORD *)((char *)this + 70));
+TTextBox::Clear(MissTextBox, a2);
+v36 = get_rc_string(34, 0);
+TTextBox::Display(InfoTextBox, a2, v36, -1.0);
+*(_DWORD *)((char *)v4 + 94) = timer_set(3.0, (int)v4, (int)TPinballTable::EndGame_timeout);
+goto LABEL_81;
+case 1024:
+v5 = *(_DWORD *)(*(_DWORD *)((char *)this + 254) + 4) - 1;
+if ( v5 >= 0 )
+{
+v6 = 4 * v5 + 8;
+v7 = *(_DWORD *)(*(_DWORD *)((char *)this + 254) + 4);
+do
+{
+(***(void (__stdcall ****)(signed int, _DWORD))(v6 + *(_DWORD *)((char *)v4 + 254)))(1024, 0.0);
+v6 -= 4;
+--v7;
+}
+while ( v7 );
+}
+if ( *(_DWORD *)((char *)v4 + 358) )
+timer_kill(*(_DWORD *)((char *)v4 + 358));
+v8 = *(_DWORD *)((char *)v4 + 90);
+*(_DWORD *)((char *)v4 + 358) = 0;
+if ( v8 )
+{
+timer_kill(v8);
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)v4 + 266))(34, 0.0);
+}
+*(_DWORD *)((char *)v4 + 90) = 0;
+*(_DWORD *)((char *)v4 + 294) = 0;
+*(_DWORD *)((char *)v4 + 298) = 0;
+*(_DWORD *)((char *)v4 + 302) = 0;
+*(_DWORD *)((char *)v4 + 306) = 10000;
+*(_DWORD *)((char *)v4 + 310) = 0;
+*(_DWORD *)((char *)v4 + 314) = 20000;
+*(_DWORD *)((char *)v4 + 318) = 0;
+*(_DWORD *)((char *)v4 + 322) = 0;
+*(_DWORD *)((char *)v4 + 334) = 0;
+*(_DWORD *)((char *)v4 + 338) = 0;
+*(_DWORD *)((char *)v4 + 342) = 0;
+*(_DWORD *)((char *)v4 + 346) = 0;
+*(_DWORD *)((char *)v4 + 350) = 0;
+*(_DWORD *)((char *)v4 + 354) = 0;
+*(_DWORD *)((char *)v4 + 358) = 0;
+*(_DWORD *)((char *)v4 + 370) = 0;
+goto LABEL_81;
+default:
+goto LABEL_81;
+}
+}
+
+//----- (0101A951) --------------------------------------------------------
+TZmapList *__thiscall TPinballTable::~TPinballTable(TPinballTable *this)
+{
+TPinballTable *v1; // esi
+int *v2; // edi
+int i; // ecx
+signed int v5; // [esp+Ch] [ebp-4h]
+
+v1 = this;
+*(_DWORD *)this = &TPinballTable::`vftable';
+v2 = (int *)((char *)this + 102);
+v5 = 4;
+do
+{
+if ( *v2 )
+{
+objlist_destroy(*v2);
+*v2 = 0;
+}
+v2 += 7;
+--v5;
+}
+while ( v5 );
+if ( *(_DWORD *)((char *)v1 + 58) )
+{
+objlist_destroy(*(_DWORD *)((char *)v1 + 58));
+*(_DWORD *)((char *)v1 + 58) = 0;
+}
+if ( *(_DWORD *)((char *)v1 + 54) )
+{
+objlist_destroy(*(_DWORD *)((char *)v1 + 54));
+*(_DWORD *)((char *)v1 + 54) = 0;
+}
+for ( i = *(_DWORD *)((char *)v1 + 266); ; i = *(_DWORD *)(*(_DWORD *)((char *)v1 + 254) + 8) )
+{
+if ( i )
+(*(void (__stdcall **)(signed int))(*(_DWORD *)i + 16))(1);
+if ( !*(_DWORD *)(*(_DWORD *)((char *)v1 + 254) + 4) )
+break;
+}
+objlist_destroy(*(_DWORD *)((char *)v1 + 262));
+objlist_destroy(*(_DWORD *)((char *)v1 + 254));
+return TPinballComponent::~TPinballComponent(v1);
+}
+// 1002790: using guessed type void *TPinballTable::`vftable';
+
+//----- (0101A9F2) --------------------------------------------------------
+TPinballTable *__thiscall TPinballTable::`vector deleting destructor`(TPinballTable *this, char a2)
+{
+TPinballTable *v2; // esi
+
+v2 = this;
+TPinballTable::~TPinballTable(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
+
+//----- (0101AAF3) --------------------------------------------------------
+TPinballTable *__thiscall TPinballTable::TPinballTable(TPinballTable *this)
+{
+TBall *v1; // ebx
+TPinballTable *v2; // esi
+TBall *v3; // eax
+TTableLayer *v4; // eax
+TLightGroup *v5; // eax
+TLightGroup *v6; // eax
+_DWORD *v7; // eax
+int v8; // ebx
+void **v9; // edi
+int v10; // eax
+__int16 *v11; // ebx
+__int16 v12; // ax
+signed __int16 *v13; // ebx
+int v14; // edi
+TWall *v15; // eax
+TOneway *v16; // eax
+TPlunger *v17; // eax
+TPlunger *v18; // eax
+TLight *v19; // eax
+TLight *v20; // eax
+TLightGroup *v21; // eax
+TComponentGroup *v22; // eax
+TFlipper *v23; // eax
+TFlipper *v24; // eax
+TFlipper *v25; // eax
+TFlipper *v26; // eax
+TBumper *v27; // eax
+TPopupTarget *v28; // eax
+TSoloTarget *v29; // eax
+TBlocker *v30; // eax
+TGate *v31; // eax
+TSink *v32; // eax
+TKickback *v33; // eax
+TTripwire *v34; // eax
+TRollover *v35; // eax
+TLightRollover *v36; // eax
+TDrain *v37; // eax
+TDrain *v38; // eax
+TFlagSpinner *v39; // eax
+TKickout *v40; // eax
+TKickout *v41; // eax
+TRamp *v42; // eax
+THole *v43; // eax
+TDemo *v44; // eax
+TLightBargraph *v45; // eax
+TSound *v46; // eax
+TTimer *v47; // eax
+TTextBox *v48; // eax
+int v50; // [esp+Ch] [ebp-8h]
+int i; // [esp+10h] [ebp-4h]
+
+v1 = 0;
+v2 = this;
+TPinballComponent::TPinballComponent(this, 0, -1, 0);
+*(_DWORD *)v2 = &TPinballTable::`vftable';
+objlist_class::objlist_class((TPinballTable *)((char *)v2 + 250), 32, 16);
+objlist_class::objlist_class((TPinballTable *)((char *)v2 + 258), 3, 1);
+*(_DWORD *)((char *)v2 + 50) = 0;
+*(_DWORD *)((char *)v2 + 54) = 0;
+*(_DWORD *)((char *)v2 + 58) = 0;
+*(_DWORD *)((char *)v2 + 78) = 0;
+*((_BYTE *)v2 + 5) = 1;
+*(_DWORD *)((char *)v2 + 370) = 0;
+*(_DWORD *)((char *)v2 + 94) = 0;
+*(_DWORD *)((char *)v2 + 90) = 0;
+*(_DWORD *)((char *)v2 + 358) = 0;
+*(_DWORD *)((char *)v2 + 98) = 0;
+*(_DWORD *)((char *)v2 + 346) = 0;
+v3 = (TBall *)TPinballComponent::operator new(0x16Au);
+if ( v3 )
+v1 = TBall::TBall(v3, v2);
+objlist_class::Add((TPinballTable *)((char *)v2 + 258), (void *)v1);
+if ( v1 )
+*((_BYTE *)v1 + 5) = 0;
+v4 = (TTableLayer *)TPinballComponent::operator new(0x7Eu);
+if ( v4 )
+TTableLayer::TTableLayer(v4, v2);
+v5 = (TLightGroup *)TPinballComponent::operator new(0x8Au);
+if ( v5 )
+v6 = TLightGroup::TLightGroup(v5, v2, 0);
+else
+v6 = 0;
+*(_DWORD *)((char *)v2 + 266) = v6;
+v7 = score_create("score1", render_background_bitmap);
+*(_DWORD *)((char *)v2 + 50) = v7;
+*(_DWORD *)((char *)v2 + 102) = v7;
+v8 = 1;
+v9 = (void **)((char *)v2 + 130);
+do
+{
+*v9 = score_dup(*(const void **)((char *)v2 + 50), v8++);
+v9 += 7;
+}
+while ( v8 < 4 );
+*(_DWORD *)((char *)v2 + 218) = 0;
+*(_DWORD *)((char *)v2 + 330) = 3;
+*(_DWORD *)((char *)v2 + 54) = score_create("ballcount1", render_background_bitmap);
+*(_DWORD *)((char *)v2 + 58) = score_create("player_number1", render_background_bitmap);
+v10 = loader_query_handle("table_objects");
+v11 = (__int16 *)loader_query_iattribute(v10, 1025, &v50);
+if ( v50 > 0 )
+{
+for ( i = 0; i < v50 / 2; ++i )
+{
+v12 = *v11;
+v13 = v11 + 1;
+v14 = *v13;
+v11 = v13 + 1;
+switch ( v12 )
+{
+case 1000:
+case 1010:
+v15 = (TWall *)TPinballComponent::operator new(0x5Au);
+if ( v15 )
+TWall::TWall(v15, v2, v14);
+break;
+case 1001:
+v17 = (TPlunger *)TPinballComponent::operator new(0x6Au);
+if ( v17 )
+v18 = TPlunger::TPlunger(v17, v2, v14);
+else
+v18 = 0;
+*(_DWORD *)((char *)v2 + 222) = v18;
+break;
+case 1002:
+v19 = (TLight *)TPinballComponent::operator new(0xDEu);
+if ( v19 )
+v20 = TLight::TLight(v19, v2, v14);
+else
+v20 = 0;
+objlist_class::Add((objlist_class *)(*(_DWORD *)((char *)v2 + 266) + 42), (void *)v20);
+break;
+case 1003:
+v23 = (TFlipper *)TPinballComponent::operator new(0x6Au);
+if ( v23 )
+v24 = TFlipper::TFlipper(v23, v2, v14);
+else
+v24 = 0;
+*(_DWORD *)((char *)v2 + 42) = v24;
+break;
+case 1004:
+v25 = (TFlipper *)TPinballComponent::operator new(0x6Au);
+if ( v25 )
+v26 = TFlipper::TFlipper(v25, v2, v14);
+else
+v26 = 0;
+*(_DWORD *)((char *)v2 + 46) = v26;
+break;
+case 1005:
+v27 = (TBumper *)TPinballComponent::operator new(0x96u);
+if ( v27 )
+TBumper::TBumper(v27, v2, v14);
+break;
+case 1006:
+v28 = (TPopupTarget *)TPinballComponent::operator new(0x72u);
+if ( v28 )
+TPopupTarget::TPopupTarget(v28, v2, v14);
+break;
+case 1007:
+v37 = (TDrain *)TPinballComponent::operator new(0x5Au);
+if ( v37 )
+v38 = TDrain::TDrain(v37, v2, v14);
+else
+v38 = 0;
+*(_DWORD *)((char *)v2 + 226) = v38;
+break;
+case 1011:
+v30 = (TBlocker *)TPinballComponent::operator new(0x72u);
+if ( v30 )
+TBlocker::TBlocker(v30, v2, v14);
+break;
+case 1012:
+v40 = (TKickout *)TPinballComponent::operator new(0xEAu);
+if ( v40 )
+TKickout::TKickout(v40, v2, v14, (struct vector_type *)1);
+break;
+case 1013:
+v31 = (TGate *)TPinballComponent::operator new(0x66u);
+if ( v31 )
+TGate::TGate(v31, v2, v14);
+break;
+case 1014:
+v33 = (TKickback *)TPinballComponent::operator new(0x5Eu);
+if ( v33 )
+TKickback::TKickback(v33, v2, v14);
+break;
+case 1015:
+v35 = (TRollover *)TPinballComponent::operator new(0x57u);
+if ( v35 )
+TRollover::TRollover(v35, v2, v14);
+break;
+case 1016:
+v16 = (TOneway *)TPinballComponent::operator new(0x6Eu);
+if ( v16 )
+TOneway::TOneway(v16, v2, v14);
+break;
+case 1017:
+v32 = (TSink *)TPinballComponent::operator new(0x9Eu);
+if ( v32 )
+TSink::TSink(v32, v2, v14);
+break;
+case 1018:
+v39 = (TFlagSpinner *)TPinballComponent::operator new(0x76u);
+if ( v39 )
+TFlagSpinner::TFlagSpinner(v39, v2, v14);
+break;
+case 1019:
+v29 = (TSoloTarget *)TPinballComponent::operator new(0x62u);
+if ( v29 )
+TSoloTarget::TSoloTarget(v29, v2, v14);
+break;
+case 1020:
+v36 = (TLightRollover *)TPinballComponent::operator new(0x5Fu);
+if ( v36 )
+TLightRollover::TLightRollover(v36, v2, v14);
+break;
+case 1021:
+v42 = (TRamp *)TPinballComponent::operator new(0x9Au);
+if ( v42 )
+TRamp::TRamp(v42, v2, (void *)v14);
+break;
+case 1022:
+v43 = (THole *)TPinballComponent::operator new(0x8Eu);
+if ( v43 )
+THole::THole(v43, v2, v14);
+break;
+case 1023:
+v44 = (TDemo *)TPinballComponent::operator new(0x82u);
+if ( v44 )
+TDemo::TDemo(v44, v2, v14);
+break;
+case 1024:
+v34 = (TTripwire *)TPinballComponent::operator new(0x57u);
+if ( v34 )
+TTripwire::TTripwire(v34, v2, v14);
+break;
+case 1026:
+v21 = (TLightGroup *)TPinballComponent::operator new(0x8Au);
+if ( v21 )
+TLightGroup::TLightGroup(v21, v2, v14);
+break;
+case 1028:
+v22 = (TComponentGroup *)TPinballComponent::operator new(0x36u);
+if ( v22 )
+TComponentGroup::TComponentGroup(v22, v2, v14);
+break;
+case 1029:
+v41 = (TKickout *)TPinballComponent::operator new(0xEAu);
+if ( v41 )
+TKickout::TKickout(v41, v2, v14, 0);
+break;
+case 1030:
+v45 = (TLightBargraph *)TPinballComponent::operator new(0xA6u);
+if ( v45 )
+TLightBargraph::TLightBargraph(v45, v2, v14);
+break;
+case 1031:
+v46 = (TSound *)TPinballComponent::operator new(0x2Eu);
+if ( v46 )
+TSound::TSound(v46, v2, v14);
+break;
+case 1032:
+v47 = (TTimer *)TPinballComponent::operator new(0x2Eu);
+if ( v47 )
+TTimer::TTimer(v47, v2, v14);
+break;
+case 1033:
+v48 = (TTextBox *)TPinballComponent::operator new(0x4Eu);
+if ( v48 )
+TTextBox::TTextBox(v48, v2, v14);
+break;
+default:
+continue;
+}
+}
+}
+build_occlude_list();
+InfoTextBox = TPinballTable::find_component(v2, "info_text_box");
+MissTextBox = TPinballTable::find_component(v2, "mission_text_box");
+control_make_links(v2);
+return v2;
+}
+// 1002790: using guessed type void *TPinballTable::`vftable';
+
diff --git a/Classes/TPlunger/TPlunger.cpp b/Classes/TPlunger/TPlunger.cpp
new file mode 100644
index 0000000..5aca65d
--- /dev/null
+++ b/Classes/TPlunger/TPlunger.cpp
@@ -0,0 +1,195 @@
+#include "../../pinball.h"
+
+
+//----- (010172F0) --------------------------------------------------------
+void __stdcall TPlunger::BallFeedTimer(int a1, void *a2)
+{
+void (__stdcall **v2)(signed int, _DWORD); // eax
+
+v2 = *(void (__stdcall ***)(signed int, _DWORD))a2;
+*(_DWORD *)((char *)a2 + 78) = 0;
+(*v2)(1015, 0.0);
+}
+
+//----- (01017314) --------------------------------------------------------
+void __stdcall TPlunger::PullbackTimer(int a1, void *a2)
+{
+char *v2; // esi
+double v3; // st7
+int v4; // ecx
+int v5; // eax
+float v6; // [esp+20h] [ebp+Ch]
+
+v2 = (char *)a2;
+v3 = (double)*(signed int *)((char *)a2 + 90) + *(float *)((char *)a2 + 62);
+*(float *)((char *)a2 + 62) = v3;
+v6 = (double)*(signed int *)((char *)a2 + 86);
+if ( v3 <= v6 )
+{
+*(_DWORD *)(v2 + 78) = timer_set(*(float *)(v2 + 94), (int)v2, (int)TPlunger::PullbackTimer);
+}
+else
+{
+*(_DWORD *)(v2 + 78) = 0;
+*(float *)(v2 + 62) = v6;
+}
+v4 = 4
+* (unsigned __int64)(signed __int64)_floor(
+(double)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(v2 + 34) + 4) + 4) - 1)
+* (*(float *)(v2 + 62)
+/ (double)*(signed int *)(v2 + 86)))
++ 8;
+v5 = *(_DWORD *)(v4 + *(_DWORD *)(*(_DWORD *)(v2 + 34) + 4));
+render_sprite_set(
+*(_DWORD **)(v2 + 26),
+*(_DWORD *)(v4 + *(_DWORD *)(*(_DWORD *)(v2 + 34) + 4)),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(v2 + 38) + 4) + v4),
+*(_DWORD *)(v5 + 29) - *(_DWORD *)(*(_DWORD *)(v2 + 30) + 234),
+*(_DWORD *)(v5 + 33) - *(_DWORD *)(*(_DWORD *)(v2 + 30) + 238));
+}
+
+//----- (010173C8) --------------------------------------------------------
+void __stdcall TPlunger::PlungerReleasedTimer(int a1, void *a2)
+{
+*(float *)((char *)a2 + 66) = 1000000000.0;
+*(float *)((char *)a2 + 62) = 0.0;
+}
+
+//----- (010185AD) --------------------------------------------------------
+int __thiscall TPlunger::Message(TPlunger *this, int a2, float a3)
+{
+TPlunger *v3; // esi
+int v4; // eax
+int v5; // ST10_4
+int v6; // edi
+int v7; // ST10_4
+double v8; // st7
+int v9; // eax
+int v10; // eax
+float v11; // ST08_4
+
+v3 = this;
+switch ( a2 )
+{
+case 1004:
+if ( !*(_DWORD *)((char *)this + 78) )
+{
+v7 = *(_DWORD *)((char *)this + 74);
+*(float *)((char *)this + 62) = 0.0;
+*(_DWORD *)((char *)this + 66) = 1315859240;
+loader_play_sound(v7);
+TPlunger::PullbackTimer(0, (void *)v3);
+}
+return 0;
+case 1005:
+case 1009:
+case 1010:
+goto LABEL_12;
+case 1015:
+v6 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)this + 30) + 254) + 8);
+(**(void (__thiscall ***)(_DWORD, signed int, _DWORD))v6)(
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)this + 30) + 254) + 8),
+1024,
+0.0);
+*(_DWORD *)(v6 + 42) = *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 286);
+*(_DWORD *)(v6 + 46) = *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 290);
+*(_BYTE *)(v6 + 5) = 1;
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 78) = 0;
+pb_tilt_no_more(a2);
+control_handler(a2, v3);
+return 0;
+case 1016:
+if ( *(_DWORD *)((char *)this + 82) )
+timer_kill(*(_DWORD *)((char *)this + 82));
+v4 = timer_set(0.95999998, (int)v3, (int)TPlunger::BallFeedTimer);
+v5 = *(_DWORD *)((char *)v3 + 98);
+*(_DWORD *)((char *)v3 + 82) = v4;
+loader_play_sound(v5);
+control_handler(a2, v3);
+return 0;
+case 1017:
+*(float *)((char *)this + 66) = 0.0;
+*(float *)((char *)this + 62) = (double)*(signed int *)((char *)this + 86);
+v8 = 0.2;
+goto LABEL_17;
+case 1024:
+if ( *(_DWORD *)((char *)this + 82) )
+timer_kill(*(_DWORD *)((char *)this + 82));
+*(_DWORD *)((char *)v3 + 82) = 0;
+LABEL_12:
+v9 = *(_DWORD *)((char *)v3 + 78);
+*(float *)((char *)v3 + 66) = 0.0;
+if ( v9 )
+timer_kill(v9);
+*(_DWORD *)((char *)v3 + 78) = 0;
+if ( a2 == 1005 )
+loader_play_sound(*(_DWORD *)((char *)v3 + 102));
+v10 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 34) + 4) + 8);
+render_sprite_set(
+*(_DWORD **)((char *)v3 + 26),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 34) + 4) + 8),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 38) + 4) + 8),
+*(_DWORD *)(v10 + 29) - *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 234),
+*(_DWORD *)(v10 + 33) - *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 238));
+v8 = *(float *)((char *)v3 + 94);
+LABEL_17:
+v11 = v8;
+timer_set(v11, (int)v3, (int)TPlunger::PlungerReleasedTimer);
+break;
+default:
+return 0;
+}
+return 0;
+}
+
+//----- (0101875F) --------------------------------------------------------
+void __thiscall TPlunger::Collision(TPlunger *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TPlunger *v6; // esi
+float v7; // ST18_4
+
+v6 = this;
+if ( *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 370) )
+(**(void (__stdcall ***)(signed int, _DWORD))this)(1017, 0.0);
+v7 = (double)_rand() * 0.00003051850947599719 * *(float *)((char *)v6 + 62) * 0.1 + *(float *)((char *)v6 + 62);
+basic_collision(a2, a3, a4, *(float *)((char *)v6 + 54), *(float *)((char *)v6 + 58), *(float *)((char *)v6 + 66), v7);
+}
+
+//----- (0101A4F3) --------------------------------------------------------
+TPlunger *__thiscall TPlunger::TPlunger(TPlunger *this, struct TPinballTable *a2, int a3)
+{
+TPlunger *v3; // esi
+int v4; // eax
+int v5; // eax
+signed __int64 v6; // rax
+_DWORD *v7; // eax
+char v9; // [esp+8h] [ebp-48h]
+int v10; // [esp+38h] [ebp-18h]
+int v11; // [esp+40h] [ebp-10h]
+int v12; // [esp+44h] [ebp-Ch]
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+*(_DWORD *)v3 = &TPlunger::`vftable';
+loader_query_visual(a3, 0, &v9);
+v4 = v11;
+*(float *)((char *)v3 + 62) = 0.0;
+*(_DWORD *)((char *)v3 + 82) = 0;
+*(_DWORD *)((char *)v3 + 78) = 0;
+*(_DWORD *)((char *)v3 + 98) = v4;
+*(_DWORD *)((char *)v3 + 102) = v12;
+*(_DWORD *)((char *)v3 + 74) = v10;
+v5 = *(_DWORD *)((char *)v3 + 34);
+*(_DWORD *)((char *)v3 + 66) = 1315859240;
+*(_DWORD *)((char *)v3 + 86) = 100;
+v6 = (signed __int64)(100.0 / ((double)*(signed int *)(*(_DWORD *)(v5 + 4) + 4) * 8.0));
+*(float *)((char *)v3 + 54) = 0.5;
+*(float *)((char *)v3 + 58) = 0.5;
+*(_DWORD *)((char *)v3 + 90) = v6;
+*(_DWORD *)((char *)v3 + 94) = 1020054733;
+v7 = (_DWORD *)loader_query_float_attribute(a3, 0, 601);
+*(_DWORD *)((char *)a2 + 286) = *v7;
+*(_DWORD *)((char *)a2 + 290) = v7[1];
+return v3;
+}
+// 1002750: using guessed type void *TPlunger::`vftable';
diff --git a/Classes/TPopupTarget/TPopupTarget.cpp b/Classes/TPopupTarget/TPopupTarget.cpp
new file mode 100644
index 0000000..8cc64f1
--- /dev/null
+++ b/Classes/TPopupTarget/TPopupTarget.cpp
@@ -0,0 +1,133 @@
+#include "../../pinball.h"
+
+//----- (010160B3) --------------------------------------------------------
+void __stdcall TPopupTarget::TimerExpired(int a1, void *a2)
+{
+int v2; // eax
+int v3; // esi
+
+*(_DWORD *)((char *)a2 + 78) = 0;
+v2 = *(_DWORD *)((char *)a2 + 34);
+*((_BYTE *)a2 + 5) = 1;
+render_sprite_set_bitmap(*(_DWORD **)((char *)a2 + 26), *(_DWORD *)(*(_DWORD *)(v2 + 4) + 8));
+if ( a1 )
+{
+v3 = *(_DWORD *)((char *)a2 + 70);
+if ( v3 )
+loader_play_sound(v3);
+}
+}
+
+//----- (010160F4) --------------------------------------------------------
+int __thiscall TPopupTarget::Message(TPopupTarget *this, int a2, float a3)
+{
+TPopupTarget *v3; // esi
+int v4; // eax
+int v5; // ecx
+_DWORD *v6; // eax
+int v7; // eax
+__int64 v8; // ST04_8
+
+v3 = this;
+switch ( a2 )
+{
+case 49:
+v8 = *(unsigned int *)((char *)this + 26);
+*((_BYTE *)this + 5) = 0;
+render_sprite_set_bitmap((_DWORD *)v8, SHIDWORD(v8));
+break;
+case 50:
+*(_DWORD *)((char *)this + 78) = timer_set(
+*(float *)((char *)this + 82),
+(int)this,
+(int)TPopupTarget::TimerExpired);
+break;
+case 1020:
+*(_DWORD *)((char *)this + 4 * *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 218) + 98) = *(_DWORD *)((char *)this + 6);
+v7 = *(_DWORD *)((char *)this + 4 * (unsigned __int64)(signed __int64)_floor(a3) + 98);
+*(_DWORD *)((char *)v3 + 6) = v7;
+TPopupTarget::Message(v3, 50 - (v7 != 0), 0.0);
+break;
+case 1024:
+v4 = *(_DWORD *)((char *)this + 30);
+*(_DWORD *)((char *)this + 6) = 0;
+v5 = 0;
+if ( *(_DWORD *)(v4 + 214) > 0 )
+{
+v6 = (_DWORD *)((char *)v3 + 98);
+do
+{
+*v6 = 0;
+++v5;
+++v6;
+}
+while ( v5 < *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 214) );
+}
+if ( *(_DWORD *)((char *)v3 + 78) )
+timer_kill(*(_DWORD *)((char *)v3 + 78));
+TPopupTarget::TimerExpired(0, (void *)v3);
+break;
+}
+return 0;
+}
+
+//----- (010161D0) --------------------------------------------------------
+int __thiscall TPopupTarget::get_scoring(TPopupTarget *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 3 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 86);
+return result;
+}
+
+//----- (010161EE) --------------------------------------------------------
+void __thiscall TPopupTarget::put_scoring(TPopupTarget *this, int a2, int a3)
+{
+if ( a2 < 3 )
+*(_DWORD *)((char *)this + 4 * a2 + 86) = a3;
+}
+
+//----- (010181ED) --------------------------------------------------------
+void __thiscall TPopupTarget::Collision(TPopupTarget *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TPopupTarget *v6; // esi
+
+v6 = this;
+if ( *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 370) )
+{
+basic_collision(a2, a3, a4, *(float *)((char *)this + 54), *(float *)((char *)this + 58), 1000000000.0, 0.0);
+}
+else if ( basic_collision(
+a2,
+a3,
+a4,
+*(float *)((char *)this + 54),
+*(float *)((char *)this + 58),
+*(float *)((char *)this + 66),
+*(float *)((char *)this + 62)) > *(float *)((char *)this + 66) )
+{
+if ( *(_DWORD *)((char *)v6 + 74) )
+loader_play_sound(*(_DWORD *)((char *)v6 + 74));
+(**(void (__thiscall ***)(TPopupTarget *, signed int, _DWORD))v6)(v6, 49, 0.0);
+control_handler(63, v6);
+}
+}
+
+//----- (010195E0) --------------------------------------------------------
+TPopupTarget *__thiscall TPopupTarget::TPopupTarget(TPopupTarget *this, struct TPinballTable *a2, int a3)
+{
+TPopupTarget *v3; // esi
+int v4; // eax
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+*(_DWORD *)v3 = &TPopupTarget::`vftable';
+v4 = *(_DWORD *)loader_query_float_attribute(a3, 0, 407);
+*(_DWORD *)((char *)v3 + 78) = 0;
+*(_DWORD *)((char *)v3 + 82) = v4;
+return v3;
+}
+// 10025A4: using guessed type void *TPopupTarget::`vftable';
diff --git a/Classes/TRamp/TRamp.cpp b/Classes/TRamp/TRamp.cpp
new file mode 100644
index 0000000..7a3fff9
--- /dev/null
+++ b/Classes/TRamp/TRamp.cpp
@@ -0,0 +1,593 @@
+#include "../../pinball.h"
+
+//----- (01016AEC) --------------------------------------------------------
+int __thiscall TRamp::get_scoring(TRamp *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 4 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 78);
+return result;
+}
+
+//----- (01016B0A) --------------------------------------------------------
+void __thiscall TRamp::put_scoring(TRamp *this, int a2, int a3)
+{
+if ( a2 < 4 )
+*(_DWORD *)((char *)this + 4 * a2 + 78) = a3;
+}
+
+//----- (01016C24) --------------------------------------------------------
+void __thiscall TRamp::Collision(TRamp *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TRamp *v6; // edi
+double v7; // st7
+int v8; // eax
+_DWORD *v9; // eax
+double v10; // st7
+double v11; // st6
+double v12; // st6
+double v13; // st7
+
+v6 = this;
+TBall::not_again(a2, a6);
+v7 = *(float *)((char *)a2 + 70) - a5;
+*(_DWORD *)((char *)a2 + 42) = *(_DWORD *)a3;
+v8 = *((_DWORD *)a3 + 1);
+*(float *)((char *)a2 + 70) = v7;
+*(_DWORD *)((char *)a2 + 46) = v8;
+v9 = *(_DWORD **)((char *)a6 + 13);
+if ( v9 )
+{
+*(_DWORD *)((char *)a2 + 150) = 1;
+*(_DWORD *)((char *)a2 + 138) = *v9;
+v10 = *(float *)((char *)a2 + 138) * *(float *)((char *)a2 + 42);
+v11 = *(float *)((char *)a2 + 46);
+*(_DWORD *)((char *)a2 + 142) = v9[1];
+v12 = v11 * *(float *)((char *)a2 + 142);
+*(_DWORD *)((char *)a2 + 146) = v9[2];
+*(_DWORD *)((char *)a2 + 94) = v9[11];
+*(_DWORD *)((char *)a2 + 98) = v9[12];
+*(float *)((char *)a2 + 50) = v10 + v12 + *(float *)((char *)a2 + 154) + *(float *)((char *)a2 + 146);
+*(_DWORD *)((char *)a2 + 110) = *(_DWORD *)((char *)v6 + 106);
+return;
+}
+if ( a6 == *(struct TEdgeSegment **)((char *)v6 + 134) )
+{
+if ( !*(_DWORD *)(*(_DWORD *)((char *)v6 + 30) + 370) )
+{
+loader_play_sound(*(_DWORD *)((char *)v6 + 70));
+control_handler(63, v6);
+}
+}
+else
+{
+*(_DWORD *)((char *)a2 + 150) = 0;
+if ( a6 == *(struct TEdgeSegment **)((char *)v6 + 126) )
+{
+*(_DWORD *)((char *)a2 + 110) = *(_DWORD *)((char *)v6 + 138);
+if ( !*(_DWORD *)((char *)v6 + 110) )
+return;
+v13 = *(float *)((char *)a2 + 154) + *(float *)((char *)v6 + 146);
+}
+else
+{
+*(_DWORD *)((char *)a2 + 110) = *(_DWORD *)((char *)v6 + 142);
+if ( !*(_DWORD *)((char *)v6 + 110) )
+return;
+v13 = *(float *)((char *)a2 + 154) + *(float *)((char *)v6 + 150);
+}
+*(float *)((char *)a2 + 50) = v13;
+}
+}
+
+//----- (01016D2E) --------------------------------------------------------
+int __thiscall TRamp::FieldEffect(TRamp *this, struct TBall *a2, struct vector_type *a3)
+{
+int result; // eax
+
+*(float *)a3 = *(float *)((char *)a2 + 94)
+- *(float *)((char *)a2 + 54) * *(float *)((char *)a2 + 66) * *(float *)((char *)this + 118);
+result = 1;
+*((float *)a3 + 1) = *(float *)((char *)a2 + 98)
+- *(float *)((char *)a2 + 58) * *(float *)((char *)a2 + 66) * *(float *)((char *)this + 118);
+return result;
+}
+
+//----- (01019BB8) --------------------------------------------------------
+TRamp *__thiscall TRamp::TRamp(TRamp *this, struct TPinballTable *a2, void *a3)
+{
+void *v3; // ebx
+TRamp *v4; // esi
+_DWORD *v5; // eax
+float *v6; // eax
+float *v7; // edi
+signed __int64 v8; // rax
+void *v9; // ST0C_4
+int v10; // edi
+double v11; // st7
+TLine *v12; // eax
+TLine *v13; // edi
+int v14; // eax
+int v15; // edi
+double v16; // st7
+int v17; // ecx
+TLine *v18; // eax
+TLine *v19; // edi
+int v20; // eax
+int v21; // edi
+double v22; // st7
+int v23; // ecx
+TLine *v24; // eax
+TLine *v25; // edi
+int v26; // eax
+bool v27; // zf
+bool v28; // sf
+int v29; // ecx
+int v30; // eax
+int v31; // ebx
+int v32; // edi
+int v33; // ecx
+double v34; // st7
+double v35; // st7
+double v36; // st7
+double v37; // st7
+float v38; // eax
+double v39; // st7
+double v40; // st7
+float v41; // eax
+double v42; // st7
+double v43; // st7
+double v44; // st7
+double v45; // st7
+float v46; // eax
+double v47; // st7
+double v48; // st7
+double v49; // st7
+double v50; // st7
+float v51; // eax
+double v52; // st7
+void *v53; // eax
+TLine *v54; // eax
+void *v55; // ecx
+void *v56; // eax
+TLine *v57; // eax
+void *v58; // ecx
+void *v59; // eax
+TLine *v60; // eax
+TLine *v61; // edi
+int v62; // ecx
+float *v63; // eax
+int v64; // ecx
+long double v65; // st7
+float v66; // ST0C_4
+double v67; // st7
+int v68; // ecx
+float v69; // ST08_4
+double v70; // st7
+float v71; // ST04_4
+char v73; // [esp+24h] [ebp-84h]
+void *v74; // [esp+58h] [ebp-50h]
+int v75; // [esp+6Ch] [ebp-3Ch]
+int v76; // [esp+70h] [ebp-38h]
+int v77; // [esp+78h] [ebp-30h]
+int v78; // [esp+7Ch] [ebp-2Ch]
+struct vector_type *v79; // [esp+80h] [ebp-28h]
+struct vector_type *v80; // [esp+84h] [ebp-24h]
+struct vector_type *v81; // [esp+88h] [ebp-20h]
+int v82; // [esp+8Ch] [ebp-1Ch]
+int v83; // [esp+90h] [ebp-18h]
+struct vector_type *v84; // [esp+94h] [ebp-14h]
+float v85; // [esp+98h] [ebp-10h]
+float v86; // [esp+9Ch] [ebp-Ch]
+float v87; // [esp+A0h] [ebp-8h]
+float v88; // [esp+A4h] [ebp-4h]
+
+v3 = a3;
+v4 = this;
+TCollisionComponent::TCollisionComponent(this, a2, (int)a3, 0);
+*(_DWORD *)v4 = &TRamp::`vftable';
+*(_DWORD *)((char *)v4 + 6) = 0;
+*((_BYTE *)v4 + 4) = 1;
+loader_query_visual((int)v3, 0, &v73);
+*(_DWORD *)((char *)v4 + 106) = v74;
+v5 = (_DWORD *)loader_query_float_attribute((int)v3, 0, 701);
+if ( v5 )
+*(_DWORD *)((char *)v4 + 118) = *v5;
+else
+*(_DWORD *)((char *)v4 + 118) = 1045220557;
+v6 = (float *)loader_query_float_attribute((int)v3, 0, 1305);
+if ( v6 )
+*(_DWORD *)((char *)v4 + 110) = (signed __int64)_floor(*v6);
+else
+*(_DWORD *)((char *)v4 + 110) = 0;
+v7 = (float *)loader_query_float_attribute((int)a3, 0, 1300);
+v8 = (signed __int64)_floor(*v7);
+v9 = a3;
+*(_DWORD *)((char *)v4 + 114) = v8;
+*(_DWORD *)((char *)v4 + 122) = v7 + 1;
+v10 = loader_query_float_attribute((int)v9, 0, 1303);
+v11 = _floor(*(float *)v10);
+v75 = *(_DWORD *)(v10 + 8);
+v76 = *(_DWORD *)(v10 + 12);
+v86 = *(float *)(v10 + 16);
+v87 = *(float *)(v10 + 20);
+v12 = (TLine *)operator new(0x55u);
+if ( v12 )
+v13 = TLine::TLine(
+v12,
+v4,
+(char *)v4 + 5,
+1 << (signed __int64)v11,
+(struct vector_type *)&v86,
+(struct vector_type *)&v75);
+else
+v13 = 0;
+*(_DWORD *)((char *)v4 + 134) = v13;
+objlist_class::Add((TRamp *)((char *)v4 + 42), (void *)v13);
+if ( v13 )
+{
+v14 = *(_DWORD *)v13;
+*(_DWORD *)((char *)v13 + 13) = 0;
+(*(void (__thiscall **)(TLine *))(v14 + 8))(v13);
+}
+v15 = loader_query_float_attribute((int)a3, 0, 1301);
+*(_DWORD *)((char *)v4 + 138) = (signed __int64)_floor(*(float *)v15);
+v16 = _floor(*(float *)(v15 + 4));
+v17 = *(_DWORD *)((char *)v4 + 138);
+v78 = (signed __int64)v16;
+v15 += 12;
+*(_DWORD *)((char *)v4 + 138) = 1 << v17;
+*(_DWORD *)((char *)v4 + 146) = *(_DWORD *)(v15 + 16);
+find_closest_edge(
+*(struct ramp_plane_type **)((char *)v4 + 122),
+*(_DWORD *)((char *)v4 + 114),
+(struct wall_point_type *)v15,
+&a2,
+&v80);
+v18 = (TLine *)operator new(0x55u);
+if ( v18 )
+v19 = TLine::TLine(v18, v4, (char *)v4 + 5, *(_DWORD *)((char *)v4 + 106), v80, a2);
+else
+v19 = 0;
+*(_DWORD *)((char *)v4 + 126) = v19;
+objlist_class::Add((TRamp *)((char *)v4 + 42), (void *)v19);
+if ( v19 )
+{
+v20 = *(_DWORD *)v19;
+*(_DWORD *)((char *)v19 + 13) = 0;
+(*(void (__thiscall **)(TLine *))(v20 + 8))(v19);
+}
+v21 = loader_query_float_attribute((int)a3, 0, 1302);
+*(_DWORD *)((char *)v4 + 142) = (signed __int64)_floor(*(float *)v21);
+v22 = _floor(*(float *)(v21 + 4));
+v23 = *(_DWORD *)((char *)v4 + 142);
+v77 = (signed __int64)v22;
+v21 += 12;
+*(_DWORD *)((char *)v4 + 142) = 1 << v23;
+*(_DWORD *)((char *)v4 + 150) = *(_DWORD *)(v21 + 16);
+find_closest_edge(
+*(struct ramp_plane_type **)((char *)v4 + 122),
+*(_DWORD *)((char *)v4 + 114),
+(struct wall_point_type *)v21,
+&v81,
+&v84);
+v24 = (TLine *)operator new(0x55u);
+if ( v24 )
+v25 = TLine::TLine(v24, v4, (char *)v4 + 5, *(_DWORD *)((char *)v4 + 106), v84, v81);
+else
+v25 = 0;
+*(_DWORD *)((char *)v4 + 130) = v25;
+objlist_class::Add((TRamp *)((char *)v4 + 42), (void *)v25);
+if ( v25 )
+{
+v26 = *(_DWORD *)v25;
+*(_DWORD *)((char *)v25 + 13) = 0;
+(*(void (__thiscall **)(TLine *))(v26 + 8))(v25);
+}
+v27 = *(_DWORD *)((char *)v4 + 114) == 0;
+v28 = *(_DWORD *)((char *)v4 + 114) < 0;
+v86 = 1000000000.0;
+v82 = 0;
+v85 = 1000000000.0;
+v88 = -1000000000.0;
+v87 = -1000000000.0;
+if ( !v28 && !v27 )
+{
+do
+{
+v29 = *(_DWORD *)((char *)v4 + 122);
+v83 = 52 * v82;
+v30 = v29 + 52 * v82;
+v31 = v30 + 28;
+v32 = v30 + 12;
+v33 = v30 + 20;
+v34 = *(float *)(v30 + 28);
+v79 = (struct vector_type *)(v30 + 20);
+if ( v34 >= *(float *)(v30 + 12) )
+v35 = *(float *)v32;
+else
+v35 = *(float *)v31;
+if ( v35 <= *(float *)v33 )
+{
+if ( *(float *)v31 >= (double)*(float *)v32 )
+v36 = *(float *)v32;
+else
+v36 = *(float *)v31;
+}
+else
+{
+v36 = *(float *)v33;
+}
+if ( v85 >= v36 )
+{
+if ( *(float *)v31 >= (double)*(float *)v32 )
+v37 = *(float *)v32;
+else
+v37 = *(float *)v31;
+if ( v37 <= *(float *)v33 )
+{
+if ( *(float *)v31 >= (double)*(float *)v32 )
+v38 = *(float *)v32;
+else
+v38 = *(float *)v31;
+}
+else
+{
+v38 = *(float *)v33;
+}
+v85 = v38;
+}
+if ( *(float *)(v31 + 4) >= (double)*(float *)(v32 + 4) )
+v39 = *(float *)(v32 + 4);
+else
+v39 = *(float *)(v31 + 4);
+if ( v39 <= *(float *)(v33 + 4) )
+{
+if ( *(float *)(v31 + 4) >= (double)*(float *)(v32 + 4) )
+v40 = *(float *)(v32 + 4);
+else
+v40 = *(float *)(v31 + 4);
+}
+else
+{
+v40 = *(float *)(v33 + 4);
+}
+if ( v85 >= v40 )
+{
+if ( *(float *)(v31 + 4) >= (double)*(float *)(v32 + 4) )
+v42 = *(float *)(v32 + 4);
+else
+v42 = *(float *)(v31 + 4);
+if ( v42 <= *(float *)(v33 + 4) )
+{
+if ( *(float *)(v31 + 4) >= (double)*(float *)(v32 + 4) )
+v41 = *(float *)(v32 + 4);
+else
+v41 = *(float *)(v31 + 4);
+}
+else
+{
+v41 = *(float *)(v33 + 4);
+}
+}
+else
+{
+v41 = v85;
+}
+v43 = *(float *)v31;
+v86 = v41;
+if ( v43 <= *(float *)v32 )
+v44 = *(float *)v32;
+else
+v44 = *(float *)v31;
+if ( v44 >= *(float *)v33 )
+{
+if ( *(float *)v31 <= (double)*(float *)v32 )
+v45 = *(float *)v32;
+else
+v45 = *(float *)v31;
+}
+else
+{
+v45 = *(float *)v33;
+}
+if ( v85 <= v45 )
+{
+if ( *(float *)v31 <= (double)*(float *)v32 )
+v47 = *(float *)v32;
+else
+v47 = *(float *)v31;
+if ( v47 >= *(float *)v33 )
+{
+if ( *(float *)v31 <= (double)*(float *)v32 )
+v46 = *(float *)v32;
+else
+v46 = *(float *)v31;
+}
+else
+{
+v46 = *(float *)v33;
+}
+}
+else
+{
+v46 = v85;
+}
+v48 = *(float *)(v31 + 4);
+v87 = v46;
+if ( v48 <= *(float *)(v32 + 4) )
+v49 = *(float *)(v32 + 4);
+else
+v49 = *(float *)(v31 + 4);
+if ( v49 >= *(float *)(v33 + 4) )
+{
+if ( *(float *)(v31 + 4) <= (double)*(float *)(v32 + 4) )
+v50 = *(float *)(v32 + 4);
+else
+v50 = *(float *)(v31 + 4);
+}
+else
+{
+v50 = *(float *)(v33 + 4);
+}
+if ( v85 <= v50 )
+{
+if ( *(float *)(v31 + 4) <= (double)*(float *)(v32 + 4) )
+v52 = *(float *)(v32 + 4);
+else
+v52 = *(float *)(v31 + 4);
+if ( v52 >= *(float *)(v33 + 4) )
+{
+if ( *(float *)(v31 + 4) <= (double)*(float *)(v32 + 4) )
+v51 = *(float *)(v32 + 4);
+else
+v51 = *(float *)(v31 + 4);
+}
+else
+{
+v51 = *(float *)(v33 + 4);
+}
+}
+else
+{
+v51 = v85;
+}
+v88 = v51;
+if ( (struct TPinballTable *)v32 != a2 || (struct vector_type *)v33 != v80 )
+{
+if ( (struct vector_type *)v32 != v81 || (struct vector_type *)v33 != v84 )
+{
+v53 = v74;
+goto LABEL_105;
+}
+if ( v77 )
+{
+v53 = *(void **)((char *)v4 + 142);
+goto LABEL_105;
+}
+}
+else if ( v78 )
+{
+v53 = *(void **)((char *)v4 + 138);
+LABEL_105:
+a3 = v53;
+goto LABEL_106;
+}
+a3 = 0;
+LABEL_106:
+if ( a3 )
+{
+v54 = (TLine *)operator new(0x55u);
+a3 = (void *)(v54 ? TLine::TLine(v54, v4, (char *)v4 + 5, (unsigned int)a3, (struct vector_type *)v32, v79) : 0);
+objlist_class::Add((TRamp *)((char *)v4 + 42), a3);
+if ( a3 )
+{
+v55 = a3;
+*(_DWORD *)((char *)a3 + 13) = v83 + *(_DWORD *)((char *)v4 + 122);
+(*(void (**)(void))(*(_DWORD *)v55 + 8))();
+}
+}
+if ( v79 != a2 || (struct vector_type *)v31 != v80 )
+{
+if ( v79 != v81 || (struct vector_type *)v31 != v84 )
+{
+v56 = v74;
+goto LABEL_122;
+}
+if ( v77 )
+{
+v56 = *(void **)((char *)v4 + 142);
+goto LABEL_122;
+}
+}
+else if ( v78 )
+{
+v56 = *(void **)((char *)v4 + 138);
+LABEL_122:
+a3 = v56;
+goto LABEL_123;
+}
+a3 = 0;
+LABEL_123:
+if ( a3 )
+{
+v57 = (TLine *)operator new(0x55u);
+a3 = (void *)(v57 ? TLine::TLine(v57, v4, (char *)v4 + 5, (unsigned int)a3, v79, (struct vector_type *)v31) : 0);
+objlist_class::Add((TRamp *)((char *)v4 + 42), a3);
+if ( a3 )
+{
+v58 = a3;
+*(_DWORD *)((char *)a3 + 13) = v83 + *(_DWORD *)((char *)v4 + 122);
+(*(void (**)(void))(*(_DWORD *)v58 + 8))();
+}
+}
+if ( (struct TPinballTable *)v31 != a2 || (struct vector_type *)v32 != v80 )
+{
+if ( (struct vector_type *)v31 != v81 || (struct vector_type *)v32 != v84 )
+{
+v59 = v74;
+goto LABEL_139;
+}
+if ( v77 )
+{
+v59 = *(void **)((char *)v4 + 142);
+goto LABEL_139;
+}
+}
+else if ( v78 )
+{
+v59 = *(void **)((char *)v4 + 138);
+LABEL_139:
+a3 = v59;
+goto LABEL_140;
+}
+a3 = 0;
+LABEL_140:
+if ( a3 )
+{
+v60 = (TLine *)operator new(0x55u);
+if ( v60 )
+v61 = TLine::TLine(
+v60,
+v4,
+(char *)v4 + 5,
+(unsigned int)a3,
+(struct vector_type *)v31,
+(struct vector_type *)v32);
+else
+v61 = 0;
+objlist_class::Add((TRamp *)((char *)v4 + 42), (void *)v61);
+if ( v61 )
+{
+*(_DWORD *)((char *)v61 + 13) = v83 + *(_DWORD *)((char *)v4 + 122);
+(*(void (__thiscall **)(TLine *))(*(_DWORD *)v61 + 8))(v61);
+}
+}
+v62 = v83;
+*(float *)(v83 + *(_DWORD *)((char *)v4 + 122) + 44) = cos(*(float *)(v83 + *(_DWORD *)((char *)v4 + 122) + 40))
+* sin(*(float *)(v83 + *(_DWORD *)((char *)v4 + 122) + 36))
+* *(float *)(*(_DWORD *)((char *)v4 + 30) + 270);
+v63 = (float *)(v62 + *(_DWORD *)((char *)v4 + 122));
+v64 = *(_DWORD *)((char *)v4 + 30);
+v65 = sin(v63[10]);
+++v82;
+v63[12] = v65 * sin(v63[9]) * *(float *)(v64 + 270);
+}
+while ( v82 < *(_DWORD *)((char *)v4 + 114) );
+}
+v66 = v87;
+v67 = v88;
+*(_DWORD *)((char *)v4 + 94) = (char *)v4 + 5;
+v68 = (int)v74;
+v69 = v67;
+v70 = v85;
+*(_DWORD *)((char *)v4 + 102) = v4;
+v71 = v70;
+*(_DWORD *)((char *)v4 + 98) = v68;
+edges_insert_square(v86, v71, v69, v66, 0, (TRamp *)((char *)v4 + 94));
+return v4;
+}
+// 10026CC: using guessed type void *TRamp::`vftable';
diff --git a/Classes/TRollover/TRollover.cpp b/Classes/TRollover/TRollover.cpp
new file mode 100644
index 0000000..6298f80
--- /dev/null
+++ b/Classes/TRollover/TRollover.cpp
@@ -0,0 +1,133 @@
+#include "../../pinball.h"
+
+//----- (0101644B) --------------------------------------------------------
+void __stdcall TRollover::TimerExpired(int a1, void *a2)
+{
+*((_BYTE *)a2 + 5) = 1;
+}
+
+//----- (01016460) --------------------------------------------------------
+int __thiscall TRollover::Message(TRollover *this, int a2, float a3)
+{
+int v3; // eax
+
+if ( a2 == 1024 )
+{
+v3 = *(_DWORD *)((char *)this + 34);
+*((_BYTE *)this + 5) = 1;
+*((_BYTE *)this + 78) = 0;
+if ( v3 )
+render_sprite_set_bitmap(*(_DWORD **)((char *)this + 26), *(_DWORD *)(*(_DWORD *)(v3 + 4) + 8));
+}
+return 0;
+}
+
+//----- (01016496) --------------------------------------------------------
+int __thiscall TRollover::get_scoring(TRollover *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 2 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 79);
+return result;
+}
+
+//----- (010164B4) --------------------------------------------------------
+void __thiscall TRollover::put_scoring(TRollover *this, int a2, int a3)
+{
+if ( a2 < 2 )
+*(_DWORD *)((char *)this + 4 * a2 + 79) = a3;
+}
+
+//----- (010182E4) --------------------------------------------------------
+void __thiscall TRollover::build_walls(TRollover *this, int a2)
+{
+char *v2; // esi
+unsigned int v3; // ST14_4
+float *v4; // eax
+unsigned int v5; // ST14_4
+float *v6; // eax
+char v7; // [esp+Ch] [ebp-48h]
+unsigned int v8; // [esp+40h] [ebp-14h]
+
+v2 = (char *)this;
+loader_query_visual(a2, 0, &v7);
+v3 = v8;
+v4 = (float *)loader_query_float_attribute(a2, 0, 600);
+install_wall(v4, (struct TCollisionComponent *)v2, v2 + 5, v3, 0.0, (void *)0x258);
+v5 = v8;
+v6 = (float *)loader_query_float_attribute(a2, 0, 603);
+install_wall(v6, (struct TCollisionComponent *)v2, v2 + 78, v5, 0.0, (void *)0x25B);
+}
+
+//----- (01018351) --------------------------------------------------------
+void __thiscall TRollover::Collision(TRollover *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TRollover *v6; // esi
+double v7; // st7
+int v8; // ebx
+int v9; // eax
+bool v10; // cl
+
+v6 = this;
+*(float *)((char *)a2 + 42) = *(float *)a3;
+v7 = *(float *)((char *)a2 + 70);
+*(_DWORD *)((char *)a2 + 46) = *((_DWORD *)a3 + 1);
+*(float *)((char *)a2 + 70) = v7 - a5;
+TBall::not_again(a2, a6);
+v8 = 0;
+if ( !*(_DWORD *)(*(_DWORD *)((char *)v6 + 30) + 370) )
+{
+if ( *((_BYTE *)v6 + 78) )
+{
+timer_set(0.1, (int)v6, (int)TRollover::TimerExpired);
+*((_BYTE *)v6 + 5) = 0;
+}
+else
+{
+loader_play_sound(*(_DWORD *)((char *)v6 + 70));
+control_handler(63, v6);
+}
+v9 = *(_DWORD *)((char *)v6 + 34);
+v10 = *((_BYTE *)v6 + 78) == 0;
+*((_BYTE *)v6 + 78) = v10;
+if ( v9 )
+{
+if ( !v10 )
+v8 = *(_DWORD *)(*(_DWORD *)(v9 + 4) + 8);
+render_sprite_set_bitmap(*(_DWORD **)((char *)v6 + 26), v8);
+}
+}
+}
+
+//----- (01019749) --------------------------------------------------------
+TRollover *__thiscall TRollover::TRollover(TRollover *this, struct TPinballTable *a2, int a3, int a4)
+{
+TRollover *v4; // esi
+
+v4 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, a4);
+*(_DWORD *)v4 = &TRollover::`vftable';
+return v4;
+}
+// 1002614: using guessed type void *TRollover::`vftable';
+
+//----- (01019771) --------------------------------------------------------
+TRollover *__thiscall TRollover::TRollover(TRollover *this, struct TPinballTable *a2, int a3)
+{
+TRollover *v3; // esi
+int v4; // eax
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 0);
+v4 = *(_DWORD *)((char *)v3 + 34);
+*(_DWORD *)v3 = &TRollover::`vftable';
+*((_BYTE *)v3 + 78) = 0;
+if ( v4 )
+render_sprite_set_bitmap(*(_DWORD **)((char *)v3 + 26), *(_DWORD *)(*(_DWORD *)(v4 + 4) + 8));
+TRollover::build_walls(v3, a3);
+return v3;
+}
+// 1002614: using guessed type void *TRollover::`vftable';
diff --git a/Classes/TSink/TSink.cpp b/Classes/TSink/TSink.cpp
new file mode 100644
index 0000000..89df5c0
--- /dev/null
+++ b/Classes/TSink/TSink.cpp
@@ -0,0 +1,151 @@
+#include "../../pinball.h"
+
+//----- (01017130) --------------------------------------------------------
+void __stdcall TSink::TimerExpired(int a1, void *a2)
+{
+int v2; // eax
+
+v2 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)a2 + 30) + 262) + 8);
+*(_DWORD *)(v2 + 106) = 0;
+*(_BYTE *)(v2 + 5) = 1;
+*(_DWORD *)(v2 + 42) = *(_DWORD *)((char *)a2 + 86);
+*(_DWORD *)(v2 + 46) = *(_DWORD *)((char *)a2 + 90);
+throw_ball(
+(struct TBall *)v2,
+(struct vector_type *)((char *)a2 + 98),
+*(float *)((char *)a2 + 110),
+*(float *)((char *)a2 + 114),
+*(float *)((char *)a2 + 118));
+if ( *(_DWORD *)((char *)a2 + 126) )
+loader_play_sound(*(_DWORD *)((char *)a2 + 126));
+*(_DWORD *)((char *)a2 + 78) = 0;
+}
+
+//----- (01017197) --------------------------------------------------------
+int __thiscall TSink::Message(TSink *this, int a2, float a3)
+{
+TSink *v3; // esi
+int v4; // eax
+int v5; // ecx
+_DWORD *v6; // eax
+
+v3 = this;
+switch ( a2 )
+{
+case 56:
+if ( a3 < 0.0 )
+a3 = *(float *)((char *)this + 82);
+*(_DWORD *)((char *)this + 78) = timer_set(a3, (int)this, (int)TSink::TimerExpired);
+break;
+case 1020:
+*(_DWORD *)((char *)this + 4 * *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 218) + 142) = *(_DWORD *)((char *)this + 6);
+*(_DWORD *)((char *)this + 6) = *(_DWORD *)((char *)this + 4 * (unsigned __int64)(signed __int64)_floor(a3) + 142);
+break;
+case 1024:
+if ( *(_DWORD *)((char *)this + 78) )
+timer_kill(*(_DWORD *)((char *)this + 78));
+v4 = *(_DWORD *)((char *)v3 + 30);
+*(_DWORD *)((char *)v3 + 78) = 0;
+*(_DWORD *)((char *)v3 + 6) = 0;
+v5 = 0;
+if ( *(_DWORD *)(v4 + 214) > 0 )
+{
+v6 = (_DWORD *)((char *)v3 + 142);
+do
+{
+*v6 = 0;
+++v5;
+++v6;
+}
+while ( v5 < *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 214) );
+}
+break;
+}
+return 0;
+}
+
+//----- (01017262) --------------------------------------------------------
+int __thiscall TSink::get_scoring(TSink *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 3 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 130);
+return result;
+}
+
+//----- (01017283) --------------------------------------------------------
+void __thiscall TSink::put_scoring(TSink *this, int a2, int a3)
+{
+if ( a2 < 3 )
+*(_DWORD *)((char *)this + 4 * a2 + 130) = a3;
+}
+
+//----- (010184ED) --------------------------------------------------------
+void __thiscall TSink::Collision(TSink *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TSink *v6; // esi
+int v7; // eax
+_DWORD *v8; // ST14_4
+
+v6 = this;
+v7 = *(_DWORD *)((char *)this + 30);
+*(_DWORD *)((char *)this + 78) = 0;
+if ( *(_DWORD *)(v7 + 370) )
+{
+basic_collision(a2, a3, a4, *(float *)((char *)this + 54), *(float *)((char *)this + 58), 1000000000.0, 0.0);
+}
+else
+{
+v8 = *(_DWORD **)((char *)a2 + 26);
+*((_BYTE *)a2 + 5) = 0;
+render_sprite_set_bitmap(v8, 0);
+loader_play_sound(*(_DWORD *)((char *)v6 + 122));
+control_handler(63, v6);
+}
+}
+
+//----- (0101A416) --------------------------------------------------------
+TSink *__thiscall TSink::TSink(TSink *this, struct TPinballTable *a2, int a3)
+{
+TSink *v3; // ebx
+int v4; // eax
+int v5; // eax
+int v6; // eax
+_DWORD *v7; // eax
+char v9; // [esp+Ch] [ebp-48h]
+int v10; // [esp+24h] [ebp-30h]
+float v11; // [esp+28h] [ebp-2Ch]
+int v12; // [esp+2Ch] [ebp-28h]
+int v13; // [esp+30h] [ebp-24h]
+int v14; // [esp+34h] [ebp-20h]
+int v15; // [esp+38h] [ebp-1Ch]
+int v16; // [esp+44h] [ebp-10h]
+int v17; // [esp+48h] [ebp-Ch]
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+*(_DWORD *)v3 = &TSink::`vftable';
+*(_DWORD *)((char *)v3 + 6) = 0;
+*(_DWORD *)((char *)v3 + 78) = 0;
+loader_query_visual(a3, 0, &v9);
+v4 = v15;
+*(float *)((char *)v3 + 118) = v11 * 0.01;
+*(_DWORD *)((char *)v3 + 98) = v12;
+*(_DWORD *)((char *)v3 + 110) = v4;
+*(_DWORD *)((char *)v3 + 114) = v10;
+v5 = v16;
+*(_DWORD *)((char *)v3 + 102) = v13;
+*(_DWORD *)((char *)v3 + 122) = v5;
+v6 = v17;
+*(_DWORD *)((char *)v3 + 106) = v14;
+*(_DWORD *)((char *)v3 + 126) = v6;
+v7 = (_DWORD *)loader_query_float_attribute(a3, 0, 601);
+*(_DWORD *)((char *)v3 + 86) = *v7;
+*(_DWORD *)((char *)v3 + 90) = v7[1];
+*(_DWORD *)((char *)v3 + 82) = *(_DWORD *)loader_query_float_attribute(a3, 0, 407);
+return v3;
+}
+// 1002704: using guessed type void *TSink::`vftable';
diff --git a/Classes/TSoloTarget/TSoloTarget.cpp b/Classes/TSoloTarget/TSoloTarget.cpp
new file mode 100644
index 0000000..453d384
--- /dev/null
+++ b/Classes/TSoloTarget/TSoloTarget.cpp
@@ -0,0 +1,97 @@
+#include "../../pinball.h"
+
+//----- (01016230) --------------------------------------------------------
+int __thiscall TSoloTarget::Message(TSoloTarget *this, int a2, float a3)
+{
+TSoloTarget *v3; // esi
+bool v4; // zf
+int v5; // ecx
+int v6; // eax
+
+v3 = this;
+if ( a2 >= 49 )
+{
+v4 = a2 == 50;
+if ( a2 > 50 )
+{
+if ( a2 != 1024 )
+return 0;
+if ( *(_DWORD *)((char *)this + 82) )
+timer_kill(*(_DWORD *)((char *)this + 82));
+*(_DWORD *)((char *)v3 + 82) = 0;
+v4 = a2 == 50;
+}
+*((_BYTE *)v3 + 5) = v4 || a2 == 1024;
+v5 = *(_DWORD *)((char *)v3 + 34);
+if ( v5 )
+{
+v6 = 4 * (3 - *((char *)v3 + 5));
+render_sprite_set(
+*(_DWORD **)((char *)v3 + 26),
+*(_DWORD *)(v6 + *(_DWORD *)(v5 + 4)),
+*(_DWORD *)(*(_DWORD *)(*(_DWORD *)((char *)v3 + 38) + 4) + v6),
+*(_DWORD *)(*(_DWORD *)(v6 + *(_DWORD *)(v5 + 4)) + 29) - *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 234),
+*(_DWORD *)(*(_DWORD *)(v6 + *(_DWORD *)(v5 + 4)) + 33) - *(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 238));
+}
+}
+return 0;
+}
+
+//----- (010162C4) --------------------------------------------------------
+int __thiscall TSoloTarget::get_scoring(TSoloTarget *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 1 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 94);
+return result;
+}
+
+//----- (010162E2) --------------------------------------------------------
+void __thiscall TSoloTarget::put_scoring(TSoloTarget *this, int a2, int a3)
+{
+if ( a2 < 1 )
+*(_DWORD *)((char *)this + 4 * a2 + 94) = a3;
+}
+
+//----- (0101620B) --------------------------------------------------------
+void __stdcall TSoloTarget::TimerExpired(int a1, void *a2)
+{
+(**(void (__thiscall ***)(void *, signed int, _DWORD))a2)(a2, 50, 0.0);
+*(_DWORD *)((char *)a2 + 82) = 0;
+}
+
+//----- (01018295) --------------------------------------------------------
+void __thiscall TSoloTarget::Collision(TSoloTarget *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TSoloTarget *v6; // esi
+
+v6 = this;
+if ( TCollisionComponent::DefaultCollision(this, a2, a3, a4) )
+{
+(**(void (__thiscall ***)(TSoloTarget *, signed int, _DWORD))v6)(v6, 49, 0.0);
+*(_DWORD *)((char *)v6 + 82) = timer_set(*(float *)((char *)v6 + 86), (int)v6, (int)TSoloTarget::TimerExpired);
+control_handler(63, v6);
+}
+}
+
+//----- (0101961F) --------------------------------------------------------
+TSoloTarget *__thiscall TSoloTarget::TSoloTarget(TSoloTarget *this, struct TPinballTable *a2, int a3)
+{
+TSoloTarget *v3; // esi
+char v5; // [esp+8h] [ebp-48h]
+int v6; // [esp+40h] [ebp-10h]
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+*(_DWORD *)((char *)v3 + 82) = 0;
+*(_DWORD *)v3 = &TSoloTarget::`vftable';
+*(_DWORD *)((char *)v3 + 86) = 1036831949;
+loader_query_visual(a3, 0, &v5);
+*(_DWORD *)((char *)v3 + 90) = v6;
+TSoloTarget::Message(v3, 50, 0.0);
+return v3;
+}
+// 10025C0: using guessed type void *TSoloTarget::`vftable';
diff --git a/Classes/TSound/TSound.cpp b/Classes/TSound/TSound.cpp
new file mode 100644
index 0000000..0e5cf16
--- /dev/null
+++ b/Classes/TSound/TSound.cpp
@@ -0,0 +1,40 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "TSound.h"
+
+//----- (0100AD8B) --------------------------------------------------------
+TSound *__thiscall TSound::`vector deleting destructor`(TSound *this, char a2)
+{
+TSound *v2; // esi
+
+v2 = this;
+TPinballComponent::~TPinballComponent(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
+
+//----- (0101797E) --------------------------------------------------------
+double __thiscall TSound::Play(TSound *this)
+{
+return loader_play_sound(*(_DWORD *)((char *)this + 42));
+}
+
+//----- (0101AA18) --------------------------------------------------------
+TSound *__thiscall TSound::TSound(TSound *this, struct TPinballTable *a2, int a3)
+{
+TSound *v3; // esi
+char v5; // [esp+4h] [ebp-48h]
+int v6; // [esp+3Ch] [ebp-10h]
+
+v3 = this;
+TPinballComponent::TPinballComponent(this, a2, a3, 1);
+*(_DWORD *)v3 = &TSound::`vftable';
+loader_query_visual(a3, 0, &v5);
+*(_DWORD *)((char *)v3 + 42) = v6;
+return v3;
+}
+// 10027A4: using guessed type void *TSound::`vftable';
+
diff --git a/Classes/TSound/TSound.h b/Classes/TSound/TSound.h
new file mode 100644
index 0000000..18bacbe
--- /dev/null
+++ b/Classes/TSound/TSound.h
@@ -0,0 +1,8 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_TSOUND_H
+#define PINBALL_TSOUND_H
+
+#endif //PINBALL_TSOUND_H
diff --git a/Classes/TTableLayer/TTableLayer.cpp b/Classes/TTableLayer/TTableLayer.cpp
new file mode 100644
index 0000000..1db1e7e
--- /dev/null
+++ b/Classes/TTableLayer/TTableLayer.cpp
@@ -0,0 +1,258 @@
+#include "../../pinball.h"
+
+//----- (010173E7) --------------------------------------------------------
+int __thiscall TTableLayer::FieldEffect(TTableLayer *this, struct TBall *a2, struct vector_type *a3)
+{
+TTableLayer *v3; // esi
+struct TBall *v4; // edi
+double v5; // ST08_8
+
+v3 = this;
+v4 = a2;
+v5 = *(float *)((char *)this + 98);
+*(float *)a3 = v5
+- (0.5 - (double)_rand() * 0.00003051850947599719 + *(float *)((char *)v4 + 54))
+* *(float *)((char *)v4 + 66)
+* *(float *)((char *)this + 110);
+*((float *)a3 + 1) = *(float *)((char *)v3 + 102)
+- *(float *)((char *)v4 + 58) * *(float *)((char *)v4 + 66) * *(float *)((char *)v3 + 110);
+return 1;
+}
+
+//----- (0101A5AB) --------------------------------------------------------
+TTableLayer *__thiscall TTableLayer::TTableLayer(TTableLayer *this, struct TPinballTable *a2)
+{
+struct TPinballTable *v2; // edi
+TTableLayer *v3; // esi
+float *v4; // eax
+int v5; // eax
+_DWORD *v6; // eax
+int v7; // eax
+_DWORD *v8; // eax
+_DWORD *v9; // eax
+float *v10; // ecx
+float *v11; // edi
+double v12; // st7
+double v13; // st7
+double v14; // st7
+double v15; // st7
+double v16; // st7
+double v17; // st7
+double v18; // st7
+double v19; // st7
+TEdgeManager *v20; // eax
+float v21; // ST18_4
+float v22; // ST14_4
+TLine *v23; // eax
+TLine *v24; // edi
+double v25; // st7
+float v26; // ST10_4
+double v27; // st7
+float v28; // ST0C_4
+char v30; // [esp+24h] [ebp-5Ch]
+int v31; // [esp+2Ch] [ebp-54h]
+float *v32; // [esp+30h] [ebp-50h]
+int v33; // [esp+38h] [ebp-48h]
+int v34; // [esp+54h] [ebp-2Ch]
+unsigned int v35; // [esp+58h] [ebp-28h]
+int v36; // [esp+5Ch] [ebp-24h]
+int v37; // [esp+60h] [ebp-20h]
+_DWORD *v38; // [esp+64h] [ebp-1Ch]
+struct zmap_header_type *v39; // [esp+68h] [ebp-18h]
+int v40; // [esp+6Ch] [ebp-14h]
+int v41; // [esp+70h] [ebp-10h]
+int v42; // [esp+74h] [ebp-Ch]
+int v43; // [esp+78h] [ebp-8h]
+int v44; // [esp+7Ch] [ebp-4h]
+struct TPinballTable *v45; // [esp+88h] [ebp+8h]
+struct TPinballTable *v46; // [esp+88h] [ebp+8h]
+
+v2 = a2;
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, -1, 0);
+*(_DWORD *)v3 = &TTableLayer::`vftable';
+v45 = (struct TPinballTable *)loader_query_handle("table");
+loader_query_visual((int)v45, 0, &v30);
+v4 = (float *)loader_query_float_attribute((int)v45, 0, 700);
+proj_recenter(COERCE_INT(*v4), COERCE_INT(v4[1]));
+render_set_background_zmap(v39, 0, 0);
+v5 = (int)v38;
+*(_DWORD *)((char *)v3 + 78) = v38;
+v40 = 0;
+v41 = 0;
+v42 = *(_DWORD *)(v5 + 12);
+v43 = *(_DWORD *)(v5 + 16);
+render_create_sprite(0, v5, (int)v39, 0, 0, &v40);
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 66) = v36;
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 70) = v37;
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 74) = v34;
+v6 = (_DWORD *)loader_query_float_attribute((int)v45, 0, 305);
+if ( v6 )
+{
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 270) = *v6;
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 274) = v6[1];
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 278) = v6[2];
+}
+else
+{
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 270) = 1103626240;
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 274) = 1056964608;
+*(_DWORD *)(*(_DWORD *)((char *)v3 + 30) + 278) = 1070141400;
+}
+v7 = *(_DWORD *)((char *)v3 + 30);
+*(float *)((char *)v3 + 98) = cos(*(float *)(v7 + 278)) * sin(*(float *)(v7 + 274)) * *(float *)(v7 + 270);
+*(float *)((char *)v3 + 102) = sin(*(float *)(v7 + 278)) * sin(*(float *)(v7 + 274)) * *(float *)(v7 + 270);
+v8 = (_DWORD *)loader_query_float_attribute((int)v45, 0, 701);
+if ( v8 )
+*(_DWORD *)((char *)v3 + 110) = *v8;
+else
+*(_DWORD *)((char *)v3 + 110) = 1045220557;
+v9 = v38;
+*(_DWORD *)((char *)v2 + 234) = *(_DWORD *)((char *)v38 + 29);
+*(_DWORD *)((char *)v2 + 238) = *(_DWORD *)((char *)v9 + 33);
+*(_DWORD *)((char *)v2 + 242) = v9[3];
+v10 = v32;
+*(_DWORD *)((char *)v2 + 246) = v9[4];
+v44 = v31;
+*(_DWORD *)((char *)v3 + 66) = v33;
+*(_DWORD *)((char *)v3 + 62) = 1097859072;
+v11 = v10;
+v46 = (struct TPinballTable *)v10;
+if ( v10[2] >= (double)v10[4] )
+v12 = v10[4];
+else
+v12 = v10[2];
+if ( v12 >= *v10 )
+{
+v13 = *v10;
+}
+else if ( v10[2] >= (double)v10[4] )
+{
+v13 = v10[4];
+}
+else
+{
+v13 = v10[2];
+}
+*(float *)((char *)v3 + 82) = v13;
+if ( v10[2] <= (double)v10[4] )
+v14 = v10[4];
+else
+v14 = v10[2];
+if ( v14 <= *v10 )
+{
+v15 = *v10;
+}
+else if ( v10[2] <= (double)v10[4] )
+{
+v15 = v10[4];
+}
+else
+{
+v15 = v10[2];
+}
+*(float *)((char *)v3 + 90) = v15;
+if ( v10[3] >= (double)v10[5] )
+v16 = v10[5];
+else
+v16 = v10[3];
+if ( v16 >= v10[1] )
+{
+v17 = v10[1];
+}
+else if ( v10[3] >= (double)v10[5] )
+{
+v17 = v10[5];
+}
+else
+{
+v17 = v10[3];
+}
+*(float *)((char *)v3 + 86) = v17;
+if ( v10[3] <= (double)v10[5] )
+v18 = v10[5];
+else
+v18 = v10[3];
+if ( v18 <= v10[1] )
+{
+v19 = v10[1];
+}
+else if ( v10[3] <= (double)v10[5] )
+{
+v19 = v10[5];
+}
+else
+{
+v19 = v10[3];
+}
+*(float *)((char *)v3 + 94) = v19;
+v20 = (TEdgeManager *)operator new(0xFC4u);
+if ( v20 )
+{
+v21 = *(float *)((char *)v3 + 94) - *(float *)((char *)v3 + 86);
+v22 = *(float *)((char *)v3 + 90) - *(float *)((char *)v3 + 82);
+edge_manager = TEdgeManager::TEdgeManager(v20, *(float *)((char *)v3 + 82), *(float *)((char *)v3 + 86), v22, v21);
+}
+else
+{
+edge_manager = 0;
+}
+if ( v44 > 0 )
+{
+while ( 1 )
+{
+v23 = (TLine *)operator new(0x55u);
+v24 = v23 ? TLine::TLine(v23, v3, (char *)v3 + 5, v35, v11[2], v11[3], *v11, v11[1]) : 0;
+if ( v24 )
+{
+(*(void (__thiscall **)(TLine *))(*(_DWORD *)v24 + 8))(v24);
+objlist_class::Add((TTableLayer *)((char *)v3 + 42), (void *)v24);
+}
+v46 = (struct TPinballTable *)((char *)v46 + 8);
+if ( !--v44 )
+break;
+v11 = (float *)v46;
+}
+}
+v25 = *(float *)((char *)v3 + 90);
+*(_DWORD *)((char *)v3 + 118) = -1;
+v26 = v25;
+v27 = *(float *)((char *)v3 + 94);
+*(_DWORD *)((char *)v3 + 114) = (char *)v3 + 5;
+v28 = v27;
+*(_DWORD *)((char *)v3 + 122) = v3;
+edges_insert_square(
+*(float *)((char *)v3 + 86),
+*(float *)((char *)v3 + 82),
+v28,
+v26,
+0,
+(TTableLayer *)((char *)v3 + 114));
+return v3;
+}
+// 100276C: using guessed type void *TTableLayer::`vftable';
+
+//----- (0101A928) --------------------------------------------------------
+TZmapList *__thiscall TTableLayer::~TTableLayer(TTableLayer *this)
+{
+TCollisionComponent *v1; // esi
+
+v1 = this;
+*(_DWORD *)this = &TTableLayer::`vftable';
+if ( edge_manager )
+TEdgeManager::`scalar deleting destructor`(edge_manager, 1);
+return TCollisionComponent::~TCollisionComponent(v1);
+}
+// 100276C: using guessed type void *TTableLayer::`vftable';
+
+//----- (0101AACD) --------------------------------------------------------
+TTableLayer *__thiscall TTableLayer::`scalar deleting destructor`(TTableLayer *this, char a2)
+{
+TTableLayer *v2; // esi
+
+v2 = this;
+TTableLayer::~TTableLayer(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
diff --git a/Classes/TTextBox/TTextBox.cpp b/Classes/TTextBox/TTextBox.cpp
new file mode 100644
index 0000000..fd5652d
--- /dev/null
+++ b/Classes/TTextBox/TTextBox.cpp
@@ -0,0 +1,399 @@
+#include "../../pinball.h"
+
+//----- (01014092) --------------------------------------------------------
+TTextBox *__thiscall TTextBox::TTextBox(TTextBox *this, struct TPinballTable *a2, int a3)
+{
+TTextBox *v3; // esi
+bool v4; // zf
+bool v5; // sf
+signed __int16 *v6; // eax
+int v7; // ecx
+int v8; // ecx
+
+v3 = this;
+TPinballComponent::TPinballComponent(this, a2, a3, 1);
+v4 = a3 == 0;
+v5 = a3 < 0;
+*(_DWORD *)v3 = &TTextBox::`vftable';
+*(_DWORD *)((char *)v3 + 42) = 0;
+*(_DWORD *)((char *)v3 + 46) = 0;
+*(_DWORD *)((char *)v3 + 50) = 0;
+*(_DWORD *)((char *)v3 + 54) = 0;
+*(_DWORD *)((char *)v3 + 62) = render_background_bitmap;
+*(_DWORD *)((char *)v3 + 66) = score_msg_fontp;
+*(_DWORD *)((char *)v3 + 70) = 0;
+*(_DWORD *)((char *)v3 + 74) = 0;
+*(_DWORD *)((char *)v3 + 58) = 0;
+if ( !v5 && !v4 )
+{
+v6 = (signed __int16 *)loader_query_iattribute(a3, 1500, &a2);
+v7 = *v6;
+++v6;
+*(_DWORD *)((char *)v3 + 42) = v7;
+v8 = *v6;
+++v6;
+*(_DWORD *)((char *)v3 + 46) = v8;
+*(_DWORD *)((char *)v3 + 50) = *v6;
+*(_DWORD *)((char *)v3 + 54) = v6[1];
+}
+return v3;
+}
+// 10023B4: using guessed type void *TTextBox::`vftable';
+// 10253C4: using guessed type struct score_msg_font_type *score_msg_fontp;
+
+//----- (01014143) --------------------------------------------------------
+void __usercall TTextBox::Clear(TTextBox *this@, int a2@)
+{
+TTextBox *v2; // esi
+_DWORD *v3; // edx
+int v4; // eax
+TTextBoxMessage *v5; // ecx
+int v6; // edi
+
+v2 = this;
+v3 = *(_DWORD **)((char *)this + 62);
+if ( v3 )
+gdrv_copy_bitmap(
+&vscreen,
+*(_DWORD *)((char *)this + 50),
+*(_DWORD *)((char *)this + 54),
+*(_DWORD *)((char *)this + 42),
+*(_DWORD *)((char *)this + 46),
+v3,
+*(_DWORD *)((char *)this + 42),
+*(_DWORD *)((char *)this + 46));
+else
+gdrv_fill_bitmap(
+a2,
+&vscreen,
+*(_DWORD *)((char *)this + 50),
+*(_DWORD *)((char *)this + 54),
+*(_DWORD *)((char *)this + 42),
+*(_DWORD *)((char *)this + 46),
+0);
+gdrv_blit(
+(int)&vscreen,
+*(_DWORD *)((char *)v2 + 42),
+*(_DWORD *)((char *)v2 + 46),
+*(_DWORD *)((char *)v2 + 42) + xDest,
+*(_DWORD *)((char *)v2 + 46) + yDest,
+*(_DWORD *)((char *)v2 + 50),
+*(_DWORD *)((char *)v2 + 54));
+v4 = *(_DWORD *)((char *)v2 + 58);
+if ( v4 )
+{
+if ( v4 != -1 )
+timer_kill(*(_DWORD *)((char *)v2 + 58));
+*(_DWORD *)((char *)v2 + 58) = 0;
+}
+while ( *(_DWORD *)((char *)v2 + 70) )
+{
+v5 = *(TTextBoxMessage **)((char *)v2 + 70);
+v6 = *(_DWORD *)v5;
+if ( v5 )
+TTextBoxMessage::`scalar deleting destructor`(v5, 1);
+*(_DWORD *)((char *)v2 + 70) = v6;
+}
+}
+
+//----- (010141E1) --------------------------------------------------------
+void __userpurge TTextBox::TimerExpired(int a1@, int a2, TTextBox *a3)
+{
+TTextBoxMessage *v3; // ecx
+int v4; // edi
+
+v3 = *(TTextBoxMessage **)((char *)a3 + 70);
+*(_DWORD *)((char *)a3 + 58) = 0;
+if ( v3 )
+{
+v4 = *(_DWORD *)v3;
+TTextBoxMessage::`scalar deleting destructor`(v3, 1);
+*(_DWORD *)((char *)a3 + 70) = v4;
+TTextBox::Draw(a3, a1);
+control_handler(60, a3);
+}
+}
+
+//----- (0101421C) --------------------------------------------------------
+TZmapList *__thiscall TTextBox::~TTextBox(TTextBox *this)
+{
+TTextBox *v1; // esi
+int v2; // eax
+TTextBoxMessage *v3; // ecx
+int v4; // edi
+
+v1 = this;
+v2 = *(_DWORD *)((char *)this + 58);
+*(_DWORD *)this = &TTextBox::`vftable';
+if ( v2 )
+{
+if ( v2 != -1 )
+timer_kill(v2);
+*(_DWORD *)((char *)v1 + 58) = 0;
+}
+if ( *(_DWORD *)((char *)v1 + 70) )
+{
+do
+{
+v3 = *(TTextBoxMessage **)((char *)v1 + 70);
+v4 = *(_DWORD *)v3;
+if ( v3 )
+TTextBoxMessage::`scalar deleting destructor`(v3, 1);
+*(_DWORD *)((char *)v1 + 70) = v4;
+}
+while ( v4 );
+}
+return TPinballComponent::~TPinballComponent(v1);
+}
+// 10023B4: using guessed type void *TTextBox::`vftable';
+
+//----- (01014269) --------------------------------------------------------
+void __usercall TTextBox::Draw(TTextBox *this@, int a2@)
+{
+TTextBox *v2; // esi
+_DWORD *v3; // edx
+float *v4; // edi
+int v5; // ebx
+double v6; // st7
+int v7; // eax
+float v8; // ST14_4
+_DWORD *v9; // ecx
+_BYTE *v10; // ebx
+int v11; // edi
+int v12; // eax
+int v13; // eax
+char *v14; // edx
+char v15; // al
+int v16; // eax
+_DWORD *v17; // edi
+int v18; // [esp-10h] [ebp-34h]
+int v19; // [esp-Ch] [ebp-30h]
+_BYTE *v20; // [esp+18h] [ebp-Ch]
+int v21; // [esp+18h] [ebp-Ch]
+int i; // [esp+1Ch] [ebp-8h]
+_BYTE *v23; // [esp+20h] [ebp-4h]
+
+v2 = this;
+v3 = *(_DWORD **)((char *)this + 62);
+if ( v3 )
+gdrv_copy_bitmap(
+&vscreen,
+*(_DWORD *)((char *)this + 50),
+*(_DWORD *)((char *)this + 54),
+*(_DWORD *)((char *)this + 42),
+*(_DWORD *)((char *)this + 46),
+v3,
+*(_DWORD *)((char *)this + 42),
+*(_DWORD *)((char *)this + 46));
+else
+gdrv_fill_bitmap(
+a2,
+&vscreen,
+*(_DWORD *)((char *)this + 50),
+*(_DWORD *)((char *)this + 54),
+*(_DWORD *)((char *)this + 42),
+*(_DWORD *)((char *)this + 46),
+0);
+while ( *(_DWORD *)((char *)v2 + 70) )
+{
+v4 = *(float **)((char *)v2 + 70);
+if ( v4[2] == -1.0 )
+{
+v5 = *(_DWORD *)v4;
+if ( !*(_DWORD *)v4 )
+{
+*(_DWORD *)((char *)v2 + 58) = -1;
+LABEL_18:
+v9 = *(_DWORD **)((char *)v2 + 66);
+if ( !v9 )
+{
+gdrv_blit(
+(int)&vscreen,
+*(_DWORD *)((char *)v2 + 42),
+*(_DWORD *)((char *)v2 + 46),
+*(_DWORD *)((char *)v2 + 42) + xDest,
+*(_DWORD *)((char *)v2 + 46) + yDest,
+*(_DWORD *)((char *)v2 + 50),
+*(_DWORD *)((char *)v2 + 54));
+grtext_draw_ttext_in_box(
+*(LPCSTR *)(*(_DWORD *)((char *)v2 + 70) + 4),
+xDest + *(_DWORD *)((char *)v2 + 42),
+yDest + *(_DWORD *)((char *)v2 + 46),
+*(_DWORD *)((char *)v2 + 50),
+*(_DWORD *)((char *)v2 + 54),
+255);
+return;
+}
+v10 = *(_BYTE **)(*(_DWORD *)((char *)v2 + 70) + 4);
+for ( i = *(_DWORD *)((char *)v2 + 46); ; i += v9[1] )
+{
+v15 = *v10;
+if ( !*v10 || i + v9[1] > *(_DWORD *)((char *)v2 + 46) + *(_DWORD *)((char *)v2 + 54) )
+break;
+v11 = 0;
+v20 = 0;
+v23 = v10;
+while ( 1 )
+{
+v16 = v15 & 0x7F;
+if ( !v16 || v16 == 10 )
+break;
+v12 = v9[v16 + 2];
+if ( v12 )
+{
+v13 = *(_DWORD *)(v12 + 12) + *v9 + v11;
+if ( v13 > *(_DWORD *)((char *)v2 + 50) )
+{
+if ( v20 )
+v23 = v20;
+break;
+}
+if ( *v23 == 32 )
+v20 = v23;
+v14 = v23 + 1;
+v11 = v13;
+++v23;
+}
+else
+{
+v14 = v23;
+}
+v15 = *v14;
+}
+v21 = *(_DWORD *)((char *)v2 + 42);
+while ( v10 < v23 )
+{
+v17 = (_DWORD *)v9[(*v10++ & 0x7F) + 2];
+if ( v17 )
+{
+v19 = v17[4];
+v18 = v17[3];
+if ( render_background_bitmap )
+gdrv_copy_bitmap_w_transparency(&vscreen, v18, v19, v21, i, v17, 0, 0);
+else
+gdrv_copy_bitmap(&vscreen, v18, v19, v21, i, v17, 0, 0);
+v9 = *(_DWORD **)((char *)v2 + 66);
+v21 += v17[3] + *v9;
+}
+}
+while ( (*v10 & 0x7F) == 32 )
+++v10;
+if ( (*v10 & 0x7F) == 10 )
+++v10;
+v9 = *(_DWORD **)((char *)v2 + 66);
+}
+break;
+}
+}
+else
+{
+v6 = TTextBoxMessage::TimeLeft((TTextBoxMessage *)*(_DWORD *)((char *)v2 + 70));
+if ( v6 >= -2.0 )
+{
+if ( v6 >= 0.25 )
+{
+v8 = v6;
+v7 = timer_set(v8, (int)v2, (int)TTextBox::TimerExpired);
+}
+else
+{
+v7 = timer_set(0.25, (int)v2, (int)TTextBox::TimerExpired);
+}
+*(_DWORD *)((char *)v2 + 58) = v7;
+goto LABEL_18;
+}
+v5 = *(_DWORD *)v4;
+}
+if ( v4 )
+TTextBoxMessage::`scalar deleting destructor`((TTextBoxMessage *)v4, 1);
+*(_DWORD *)((char *)v2 + 70) = v5;
+}
+gdrv_blit(
+(int)&vscreen,
+*(_DWORD *)((char *)v2 + 42),
+*(_DWORD *)((char *)v2 + 46),
+*(_DWORD *)((char *)v2 + 42) + xDest,
+*(_DWORD *)((char *)v2 + 46) + yDest,
+*(_DWORD *)((char *)v2 + 50),
+*(_DWORD *)((char *)v2 + 54));
+}
+
+//----- (010144B7) --------------------------------------------------------
+void __userpurge TTextBox::Display(TTextBox *this@, int a2@, char *a3, float a4)
+{
+TTextBox *v4; // esi
+const char **v5; // ecx
+int v6; // ST08_4
+int v7; // eax
+int v8; // eax
+TTextBoxMessage *v9; // eax
+TTextBoxMessage *v10; // eax
+bool v11; // zf
+
+v4 = this;
+if ( a3 )
+{
+if ( !*(_DWORD *)((char *)this + 70)
+|| (v5 = *(const char ***)((char *)this + 74), v6 = a2, v7 = strcmp(a3, v5[1]), a2 = v6, v7) )
+{
+if ( *(_DWORD *)((char *)v4 + 58) == -1 )
+TTextBox::Clear(v4, a2);
+v9 = (TTextBoxMessage *)operator new(0x10u);
+if ( v9 )
+v10 = TTextBoxMessage::TTextBoxMessage(v9, a3, a4);
+else
+v10 = 0;
+if ( v10 )
+{
+if ( *((_DWORD *)v10 + 1) )
+{
+if ( *(_DWORD *)((char *)v4 + 70) )
+**(_DWORD **)((char *)v4 + 74) = v10;
+else
+*(_DWORD *)((char *)v4 + 70) = v10;
+v11 = *(_DWORD *)((char *)v4 + 58) == 0;
+*(_DWORD *)((char *)v4 + 74) = v10;
+if ( v11 )
+TTextBox::Draw(v4, a2);
+}
+else
+{
+TTextBoxMessage::`scalar deleting destructor`(v10, 1);
+}
+}
+}
+else
+{
+TTextBoxMessage::Refresh((TTextBoxMessage *)v5, a4);
+if ( *(_DWORD *)((char *)v4 + 74) == *(_DWORD *)((char *)v4 + 70) )
+{
+v8 = *(_DWORD *)((char *)v4 + 58);
+if ( v8 && v8 != -1 )
+timer_kill(*(_DWORD *)((char *)v4 + 58));
+if ( a4 == -1.0 )
+*(_DWORD *)((char *)v4 + 58) = -1;
+else
+*(_DWORD *)((char *)v4 + 58) = timer_set(a4, (int)v4, (int)TTextBox::TimerExpired);
+}
+}
+}
+}
+
+//----- (010145CF) --------------------------------------------------------
+TTextBox *__thiscall TTextBox::`scalar deleting destructor`(TTextBox *this, char a2)
+{
+TTextBox *v2; // esi
+
+v2 = this;
+TTextBox::~TTextBox(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
+
+//----- (01019168) --------------------------------------------------------
+int __stdcall TTextBox::Message(int a2, float a3)
+{
+return 0;
+}
+
diff --git a/Classes/TTextBoxMessage/TTextBoxMessage.cpp b/Classes/TTextBoxMessage/TTextBoxMessage.cpp
new file mode 100644
index 0000000..002877a
--- /dev/null
+++ b/Classes/TTextBoxMessage/TTextBoxMessage.cpp
@@ -0,0 +1,50 @@
+#include "../../pinball.h"
+
+//----- (01013AF1) --------------------------------------------------------
+TTextBoxMessage *__thiscall TTextBoxMessage::TTextBoxMessage(TTextBoxMessage *this, char *a2, float a3)
+{
+TTextBoxMessage *v3; // esi
+char *v4; // edx
+
+v3 = this;
+*(_DWORD *)this = 0;
+*((float *)this + 2) = a3;
+*((_DWORD *)this + 3) = time_ticks - (unsigned __int64)(signed __int64)(a3 * -1000.0);
+if ( a2 )
+*((_DWORD *)this + 1) = memoryallocate(strlen(a2) + 1);
+else
+*((_DWORD *)this + 1) = 0;
+v4 = (char *)*((_DWORD *)v3 + 1);
+if ( v4 )
+strcpy(v4, a2);
+return v3;
+}
+// 1024F84: using guessed type int time_ticks;
+
+//----- (01013B60) --------------------------------------------------------
+double __thiscall TTextBoxMessage::TimeLeft(TTextBoxMessage *this)
+{
+return (double)(*((_DWORD *)this + 3) - time_ticks) * 0.001;
+}
+// 1024F84: using guessed type int time_ticks;
+
+//----- (01013B82) --------------------------------------------------------
+void __thiscall TTextBoxMessage::Refresh(TTextBoxMessage *this, float a2)
+{
+*((float *)this + 2) = a2;
+*((_DWORD *)this + 3) = time_ticks - (unsigned __int64)(signed __int64)(a2 * -1000.0);
+}
+// 1024F84: using guessed type int time_ticks;
+
+//----- (01014115) --------------------------------------------------------
+TTextBoxMessage *__thiscall TTextBoxMessage::`scalar deleting destructor`(TTextBoxMessage *this, char a2)
+{
+TTextBoxMessage *v2; // esi
+
+v2 = this;
+if ( *((_DWORD *)this + 1) )
+memoryfree(*((_DWORD *)this + 1));
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
diff --git a/Classes/TTimer/TTimer.cpp b/Classes/TTimer/TTimer.cpp
new file mode 100644
index 0000000..9082c13
--- /dev/null
+++ b/Classes/TTimer/TTimer.cpp
@@ -0,0 +1,44 @@
+#include "../../pinball.h"
+
+//----- (0101798C) --------------------------------------------------------
+void __stdcall TTimer::TimerExpired(int a1, struct TPinballComponent *a2)
+{
+*(_DWORD *)((char *)a2 + 42) = 0;
+control_handler(60, a2);
+}
+
+//----- (01018F5B) --------------------------------------------------------
+int __thiscall TTimer::Message(TTimer *this, int a2, float a3)
+{
+TTimer *v3; // esi
+
+v3 = this;
+if ( a2 == 59 )
+{
+if ( *(_DWORD *)((char *)this + 42) )
+timer_kill(*(_DWORD *)((char *)this + 42));
+*(_DWORD *)((char *)v3 + 42) = timer_set(a3, (int)v3, (int)TTimer::TimerExpired);
+}
+else if ( a2 == 1011 || a2 == 1022 || a2 == 1024 )
+{
+if ( *(_DWORD *)((char *)this + 42) )
+{
+timer_kill(*(_DWORD *)((char *)this + 42));
+*(_DWORD *)((char *)v3 + 42) = 0;
+}
+}
+return 0;
+}
+
+//----- (0101AA56) --------------------------------------------------------
+TTimer *__thiscall TTimer::TTimer(TTimer *this, struct TPinballTable *a2, int a3)
+{
+TTimer *v3; // esi
+
+v3 = this;
+TPinballComponent::TPinballComponent(this, a2, a3, 1);
+*(_DWORD *)((char *)v3 + 42) = 0;
+*(_DWORD *)v3 = &TTimer::`vftable';
+return v3;
+}
+// 10027BC: using guessed type void *TTimer::`vftable';
diff --git a/Classes/TTripwire/TTripwire.cpp b/Classes/TTripwire/TTripwire.cpp
new file mode 100644
index 0000000..ce147d0
--- /dev/null
+++ b/Classes/TTripwire/TTripwire.cpp
@@ -0,0 +1,32 @@
+#include "../../pinball.h"
+
+//----- (010165ED) --------------------------------------------------------
+void __thiscall TTripwire::Collision(TTripwire *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TTripwire *v6; // esi
+double v7; // st7
+
+v6 = this;
+*(float *)((char *)a2 + 42) = *(float *)a3;
+v7 = *(float *)((char *)a2 + 70);
+*(_DWORD *)((char *)a2 + 46) = *((_DWORD *)a3 + 1);
+*(float *)((char *)a2 + 70) = v7 - a5;
+TBall::not_again(a2, a6);
+if ( !*(_DWORD *)(*(_DWORD *)((char *)v6 + 30) + 370) )
+{
+loader_play_sound(*(_DWORD *)((char *)v6 + 70));
+control_handler(63, v6);
+}
+}
+
+//----- (01019816) --------------------------------------------------------
+TTripwire *__thiscall TTripwire::TTripwire(TTripwire *this, struct TPinballTable *a2, int a3)
+{
+TTripwire *v3; // esi
+
+v3 = this;
+TRollover::TRollover(this, a2, a3, 1);
+*(_DWORD *)v3 = &TTripwire::`vftable';
+return v3;
+}
+// 100264C: using guessed type void *TTripwire::`vftable';
diff --git a/Classes/TWall/TWall.cpp b/Classes/TWall/TWall.cpp
new file mode 100644
index 0000000..daac599
--- /dev/null
+++ b/Classes/TWall/TWall.cpp
@@ -0,0 +1,81 @@
+#include "../../pinball.h"
+
+//----- (01015ACE) --------------------------------------------------------
+void __stdcall TWall::TimerExpired(int a1, void *a2)
+{
+render_sprite_set_bitmap(*(_DWORD **)((char *)a2 + 26), 0);
+*(_DWORD *)((char *)a2 + 78) = 0;
+*(_DWORD *)((char *)a2 + 6) = 0;
+}
+
+//----- (01015AF3) --------------------------------------------------------
+int __thiscall TWall::Message(TWall *this, int a2, float a3)
+{
+TWall *v3; // esi
+
+v3 = this;
+if ( a2 == 1024 && *(_DWORD *)((char *)this + 78) )
+{
+timer_kill(*(_DWORD *)((char *)this + 78));
+TWall::TimerExpired(*(_DWORD *)((char *)v3 + 78), (void *)v3);
+}
+return 0;
+}
+
+//----- (01015B26) --------------------------------------------------------
+int __thiscall TWall::get_scoring(TWall *this, int a2)
+{
+int result; // eax
+
+if ( a2 >= 1 )
+result = 0;
+else
+result = *(_DWORD *)((char *)this + 4 * a2 + 86);
+return result;
+}
+
+//----- (01015B44) --------------------------------------------------------
+void __thiscall TWall::put_scoring(TWall *this, int a2, int a3)
+{
+if ( a2 < 1 )
+*(_DWORD *)((char *)this + 4 * a2 + 86) = a3;
+}
+
+//----- (01017FDE) --------------------------------------------------------
+void __thiscall TWall::Collision(TWall *this, struct TBall *a2, struct vector_type *a3, struct vector_type *a4, float a5, struct TEdgeSegment *a6)
+{
+TWall *v6; // esi
+
+v6 = this;
+if ( TCollisionComponent::DefaultCollision(this, a2, a3, a4) )
+{
+if ( *(_DWORD *)((char *)v6 + 82) )
+{
+render_sprite_set_bitmap(*(_DWORD **)((char *)v6 + 26), *(_DWORD *)((char *)v6 + 82));
+*(_DWORD *)((char *)v6 + 78) = timer_set(0.1, (int)v6, (int)TWall::TimerExpired);
+}
+control_handler(63, v6);
+}
+}
+
+//----- (010191BA) --------------------------------------------------------
+TWall *__thiscall TWall::TWall(TWall *this, struct TPinballTable *a2, int a3)
+{
+TWall *v3; // esi
+_DWORD *v4; // eax
+int v5; // eax
+
+v3 = this;
+TCollisionComponent::TCollisionComponent(this, a2, a3, 1);
+v4 = *(_DWORD **)((char *)v3 + 26);
+*(_DWORD *)v3 = &TWall::`vftable';
+if ( v4 )
+render_sprite_set_bitmap(v4, 0);
+v5 = *(_DWORD *)((char *)v3 + 34);
+if ( v5 )
+*(_DWORD *)((char *)v3 + 82) = *(_DWORD *)(*(_DWORD *)(v5 + 4) + 8);
+*(_DWORD *)((char *)v3 + 78) = 0;
+return v3;
+}
+// 1002508: using guessed type void *TWall::`vftable';
+
diff --git a/Classes/TZmapList/TZmapList.cpp b/Classes/TZmapList/TZmapList.cpp
new file mode 100644
index 0000000..ecb6dd1
--- /dev/null
+++ b/Classes/TZmapList/TZmapList.cpp
@@ -0,0 +1,22 @@
+#include "../../pinball.h"
+
+//----- (010158F0) --------------------------------------------------------
+TZmapList *__thiscall TZmapList::TZmapList(TZmapList *this, int a2, int a3)
+{
+TZmapList *v3; // esi
+
+v3 = this;
+objlist_class::objlist_class(this, a2, a3);
+return v3;
+}
+//----- (01017E5C) --------------------------------------------------------
+TZmapList *__thiscall TZmapList::`scalar deleting destructor`(TZmapList *this, char a2)
+{
+TZmapList *v2; // esi
+
+v2 = this;
+objlist_destroy(*((_DWORD *)this + 1));
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
diff --git a/Classes/TlightGroup/TLightGroup.cpp b/Classes/TlightGroup/TLightGroup.cpp
new file mode 100644
index 0000000..22cab9b
--- /dev/null
+++ b/Classes/TlightGroup/TLightGroup.cpp
@@ -0,0 +1,802 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "TLightGroup.h"
+
+//----- (01009FD1) --------------------------------------------------------
+TZmapList *__thiscall TLightGroup::~TLightGroup(TLightGroup *this)
+{
+ TLightGroup *v1; // esi
+
+ v1 = this;
+ objlist_destroy(*(_DWORD *)((char *)this + 46));
+ return TPinballComponent::~TPinballComponent(v1);
+}
+
+//----- (01009FEB) --------------------------------------------------------
+void __thiscall TLightGroup::Reset(TLightGroup *this)
+{
+ TLightGroup *v1; // esi
+ int v2; // eax
+ int v3; // eax
+
+ v1 = this;
+ if ( *(_DWORD *)((char *)this + 70) )
+ timer_kill(*(_DWORD *)((char *)this + 70));
+ v2 = *(_DWORD *)((char *)v1 + 66);
+ *(_DWORD *)((char *)v1 + 70) = 0;
+ if ( v2 )
+ timer_kill(v2);
+ v3 = *(_DWORD *)((char *)v1 + 54);
+ *(_DWORD *)((char *)v1 + 66) = 0;
+ *(_DWORD *)((char *)v1 + 58) = 0;
+ *(_DWORD *)((char *)v1 + 62) = 0;
+ *(_DWORD *)((char *)v1 + 50) = v3;
+}
+
+//----- (0100A027) --------------------------------------------------------
+void __stdcall TLightGroup::TimerExpired(int a1, void *a2)
+{
+ double v2; // st7
+ void (__stdcall **v3)(_DWORD, _DWORD); // eax
+ float v4; // ST04_4
+
+ v2 = *(float *)((char *)a2 + 50);
+ v3 = *(void (__stdcall ***)(_DWORD, _DWORD))a2;
+ *(_DWORD *)((char *)a2 + 70) = 0;
+ v4 = v2;
+ (*v3)(*(_DWORD *)((char *)a2 + 58), LODWORD(v4));
+}
+
+//----- (0100A04A) --------------------------------------------------------
+void __thiscall TLightGroup::reschedule_animation(TLightGroup *this, float a2)
+{
+TLightGroup *v2; // esi
+
+v2 = this;
+if ( *(_DWORD *)((char *)this + 70) )
+timer_kill(*(_DWORD *)((char *)this + 70));
+*(_DWORD *)((char *)v2 + 70) = 0;
+if ( a2 > 0.0 )
+{
+*(float *)((char *)v2 + 50) = a2;
+LABEL_7:
+*(_DWORD *)((char *)v2 + 70) = timer_set(*(float *)((char *)v2 + 50), (int)v2, (int)TLightGroup::TimerExpired);
+return;
+}
+if ( a2 < 0.0 )
+{
+*(_DWORD *)((char *)v2 + 50) = *(_DWORD *)((char *)v2 + 54);
+goto LABEL_7;
+}
+*(_DWORD *)((char *)v2 + 58) = 0;
+*(_DWORD *)((char *)v2 + 62) = 0;
+}
+
+//----- (0100A0B4) --------------------------------------------------------
+int __thiscall TLightGroup::next_light_up(TLightGroup *this)
+{
+ int v1; // ecx
+ int v2; // edx
+ int result; // eax
+ int v4; // ecx
+
+ v1 = *(_DWORD *)((char *)this + 46);
+ v2 = *(_DWORD *)(v1 + 4);
+ result = 0;
+ if ( v2 <= 0 )
+ return -1;
+ v4 = v1 + 8;
+ while ( *(_DWORD *)(*(_DWORD *)v4 + 78) )
+ {
+ ++result;
+ v4 += 4;
+ if ( result >= v2 )
+ return -1;
+ }
+ return result;
+}
+
+//----- (0100A0DE) --------------------------------------------------------
+int __thiscall TLightGroup::next_light_down(TLightGroup *this)
+{
+ int v1; // ecx
+ int result; // eax
+ int v3; // ecx
+
+ v1 = *(_DWORD *)((char *)this + 46);
+ result = *(_DWORD *)(v1 + 4) - 1;
+ if ( result < 0 )
+ return -1;
+ v3 = v1 + 4 * result + 8;
+ while ( !*(_DWORD *)(*(_DWORD *)v3 + 78) )
+ {
+ --result;
+ v3 -= 4;
+ if ( result < 0 )
+ return -1;
+ }
+ return result;
+}
+
+//----- (0100A104) --------------------------------------------------------
+void __thiscall TLightGroup::start_animation(TLightGroup *this)
+{
+ TLightGroup *v1; // edi
+ int v2; // eax
+ int v3; // esi
+ int v4; // ebx
+ int v5; // ecx
+ void (__stdcall **v6)(signed int, float); // eax
+ float v7; // [esp+0h] [ebp-10h]
+
+ v1 = this;
+ v2 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4) - 1;
+ if ( v2 >= 0 )
+ {
+ v3 = 4 * v2 + 8;
+ v4 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4);
+ do
+ {
+ v5 = *(_DWORD *)(v3 + *(_DWORD *)((char *)v1 + 46));
+ v6 = *(void (__stdcall ***)(signed int, float))v5;
+ v7 = 0.0;
+ if ( *(_DWORD *)(v5 + 78) )
+ (*v6)(9, COERCE_FLOAT(LODWORD(v7)));
+ else
+ (*v6)(8, COERCE_FLOAT(LODWORD(v7)));
+ v3 -= 4;
+ --v4;
+ }
+ while ( v4 );
+ }
+}
+
+//----- (0100A149) --------------------------------------------------------
+void __stdcall TLightGroup::NotifyTimerExpired(int a1, void *a2)
+{
+ *(_DWORD *)((char *)a2 + 66) = 0;
+ control_handler(61, (struct TPinballComponent *)a2);
+}
+
+//----- (0100A166) --------------------------------------------------------
+int __thiscall TLightGroup::Message(TLightGroup *this, int a2, float a3)
+{
+int v3; // ebx
+TLightGroup *v4; // esi
+int v5; // esi
+int result; // eax
+int v7; // ecx
+int v8; // edx
+int v9; // ecx
+int v10; // eax
+int v11; // ecx
+int v12; // eax
+int v13; // eax
+int v14; // ebx
+int v15; // ST28_4
+int v16; // ebx
+int v17; // eax
+int v18; // ecx
+int v19; // edx
+int v20; // eax
+int v21; // eax
+int v22; // eax
+int v23; // ebx
+int v24; // ST24_4
+bool v25; // zf
+int v26; // eax
+int v27; // ecx
+int j; // ebx
+double v29; // st7
+int v30; // eax
+void (__stdcall ***v31)(int, _DWORD); // ecx
+int v32; // eax
+int v33; // ecx
+signed int v34; // ebx
+float v35; // ST10_4
+int v36; // eax
+int v37; // eax
+void (__thiscall ***v38)(_DWORD, signed int, _DWORD); // edi
+void (__thiscall **v39)(_DWORD, signed int, _DWORD); // ST24_4
+float v40; // ST10_4
+int v41; // eax
+int v42; // eax
+void (__thiscall ***v43)(_DWORD, signed int, _DWORD); // edi
+void (__thiscall **v44)(_DWORD, signed int, _DWORD); // ebx
+float v45; // ST10_4
+int v46; // ecx
+int v47; // ebx
+int v48; // eax
+int v49; // ecx
+int v50; // eax
+int v51; // eax
+int v52; // ecx
+signed __int64 v53; // rax
+int v54; // ebx
+int v55; // ecx
+int v56; // ebx
+int v57; // eax
+int v58; // ecx
+int v59; // eax
+int v60; // eax
+int v61; // ecx
+signed __int64 v62; // rax
+int v63; // ebx
+int v64; // eax
+int v65; // ebx
+int v66; // eax
+int v67; // ebx
+int v68; // eax
+int v69; // eax
+int v70; // ebx
+int v71; // ecx
+signed __int64 v72; // rax
+signed int v73; // ecx
+int v74; // ebx
+int v75; // edi
+int v76; // ebx
+int v77; // eax
+int v78; // eax
+int v79; // edi
+int v80; // ecx
+_DWORD *v81; // eax
+char *v82; // eax
+char *v83; // eax
+int v84; // [esp+20h] [ebp-14h]
+int v85; // [esp+28h] [ebp-Ch]
+int v86; // [esp+28h] [ebp-Ch]
+int v87; // [esp+28h] [ebp-Ch]
+int v88; // [esp+28h] [ebp-Ch]
+int v89; // [esp+2Ch] [ebp-8h]
+int v90; // [esp+30h] [ebp-4h]
+int i; // [esp+30h] [ebp-4h]
+int v92; // [esp+30h] [ebp-4h]
+signed int v93; // [esp+30h] [ebp-4h]
+int v94; // [esp+30h] [ebp-4h]
+int v95; // [esp+3Ch] [ebp+8h]
+int v96; // [esp+3Ch] [ebp+8h]
+int v97; // [esp+3Ch] [ebp+8h]
+int v98; // [esp+3Ch] [ebp+8h]
+int v99; // [esp+3Ch] [ebp+8h]
+int v100; // [esp+3Ch] [ebp+8h]
+int v101; // [esp+3Ch] [ebp+8h]
+int v102; // [esp+3Ch] [ebp+8h]
+int v103; // [esp+40h] [ebp+Ch]
+int v104; // [esp+40h] [ebp+Ch]
+int v105; // [esp+40h] [ebp+Ch]
+
+v3 = a2;
+v4 = this;
+if ( a2 > 1009 )
+{
+if ( a2 != 1011 )
+{
+if ( a2 == 1020 )
+{
+v82 = (char *)this + 16 * *(_DWORD *)(*(_DWORD *)((char *)this + 30) + 218);
+*(_DWORD *)(v82 + 74) = *(_DWORD *)((char *)this + 6);
+*(_DWORD *)(v82 + 78) = *(_DWORD *)((char *)this + 58);
+*(_DWORD *)(v82 + 82) = *(_DWORD *)((char *)this + 50);
+(*(void (**)(void))(*(_DWORD *)this + 20))();
+v83 = (char *)v4 + 16 * (unsigned __int64)(signed __int64)_floor(a3);
+*(_DWORD *)((char *)v4 + 6) = *(_DWORD *)(v83 + 74);
+*(_DWORD *)((char *)v4 + 58) = *(_DWORD *)(v83 + 78);
+v25 = *(_DWORD *)((char *)v4 + 6) == 0;
+*(_DWORD *)((char *)v4 + 50) = *(_DWORD *)(v83 + 82);
+if ( !v25 )
+TLightGroup::TimerExpired(0, (void *)v4);
+}
+else if ( a2 != 1022 )
+{
+if ( a2 == 1024 )
+{
+(*(void (**)(void))(*(_DWORD *)this + 20))();
+v80 = 0;
+if ( *(_DWORD *)(*(_DWORD *)((char *)v4 + 30) + 214) > 0 )
+{
+v81 = (_DWORD *)((char *)v4 + 78);
+do
+{
+*(v81 - 1) = *(_DWORD *)((char *)v4 + 6);
+*v81 = *(_DWORD *)((char *)v4 + 58);
+v81[1] = *(_DWORD *)((char *)v4 + 50);
+++v80;
+v81 += 4;
+}
+while ( v80 < *(_DWORD *)(*(_DWORD *)((char *)v4 + 30) + 214) );
+}
+}
+else
+{
+LABEL_145:
+ v78 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4) - 1;
+if ( v78 >= 0 )
+{
+v79 = 4 * v78 + 8;
+v102 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4);
+do
+{
+(***(void (__stdcall ****)(int, _DWORD))(v79 + *(_DWORD *)((char *)v4 + 46)))(v3, LODWORD(a3));
+v79 -= 4;
+--v102;
+}
+while ( v102 );
+}
+}
+}
+}
+}
+else if ( a2 < 1008 )
+{
+switch ( a2 )
+{
+case 24:
+v10 = *(_DWORD *)((char *)this + 46);
+v11 = *(_DWORD *)(v10 + 4);
+v12 = *(_DWORD *)(v10 + 4 * v11 + 4);
+v90 = v11;
+v95 = v12;
+if ( *(_DWORD *)(v12 + 82) || *(_DWORD *)(v12 + 90) || *(_DWORD *)(v12 + 86) )
+return 0;
+if ( *(_DWORD *)((char *)v4 + 58) )
+{
+TLightGroup::Message(v4, 34, 0.0);
+v12 = v95;
+v11 = v90;
+}
+*(_DWORD *)((char *)v4 + 62) = 1;
+*(_DWORD *)((char *)v4 + 58) = v3;
+v89 = *(_DWORD *)(v12 + 6);
+v96 = *(_DWORD *)(v12 + 78);
+for ( i = v11 - 1; i > 0; *(_DWORD *)(v14 + 6) = *(_DWORD *)(v15 + 6) )
+{
+v13 = *(_DWORD *)((char *)v4 + 46);
+v14 = *(_DWORD *)(4 * i + v13 + 8);
+v15 = *(_DWORD *)(4 * i + v13 + 4);
+(**(void (__thiscall ***)(int, bool, _DWORD))v14)(v14, *(_DWORD *)(v15 + 78) != 0, 0.0);
+--i;
+}
+v16 = *(_DWORD *)(*(_DWORD *)((char *)v4 + 46) + 8);
+goto LABEL_19;
+case 25:
+v17 = *(_DWORD *)((char *)this + 46);
+v18 = *(_DWORD *)(v17 + 4);
+v19 = 4 * *(_DWORD *)(v17 + 4);
+v20 = *(_DWORD *)(v19 + v17 + 4);
+v92 = v18;
+v84 = v19;
+if ( *(_DWORD *)(v20 + 82) || *(_DWORD *)(v20 + 90) || *(_DWORD *)(v20 + 86) )
+return 0;
+if ( *(_DWORD *)((char *)v4 + 58) )
+{
+TLightGroup::Message(v4, 34, 0.0);
+v18 = v92;
+}
+v21 = *(_DWORD *)(*(_DWORD *)((char *)v4 + 46) + 8);
+*(_DWORD *)((char *)v4 + 62) = 1;
+*(_DWORD *)((char *)v4 + 58) = a2;
+v89 = *(_DWORD *)(v21 + 6);
+v96 = *(_DWORD *)(v21 + 78);
+if ( v18 - 1 > 0 )
+{
+v93 = 12;
+v85 = v18 - 1;
+do
+{
+v22 = *(_DWORD *)((char *)v4 + 46);
+v23 = *(_DWORD *)(v93 + v22 - 4);
+v24 = *(_DWORD *)(v93 + v22);
+(**(void (__thiscall ***)(int, bool, _DWORD))v23)(v23, *(_DWORD *)(v24 + 78) != 0, 0.0);
+v93 += 4;
+v25 = v85-- == 1;
+*(_DWORD *)(v23 + 6) = *(_DWORD *)(v24 + 6);
+}
+while ( !v25 );
+}
+v16 = *(_DWORD *)(v84 + *(_DWORD *)((char *)v4 + 46) + 4);
+LABEL_19:
+ (**(void (__thiscall ***)(int, bool, _DWORD))v16)(v16, v96 != 0, 0.0);
+*(_DWORD *)(v16 + 6) = v89;
+goto LABEL_20;
+case 26:
+if ( *(_DWORD *)((char *)this + 62) || !*(_DWORD *)((char *)this + 58) )
+TLightGroup::start_animation(this);
+v26 = *(_DWORD *)((char *)v4 + 46);
+*(_DWORD *)((char *)v4 + 58) = a2;
+*(_DWORD *)((char *)v4 + 62) = 0;
+v27 = *(_DWORD *)(v26 + 4);
+v97 = *(_DWORD *)(*(_DWORD *)(v26 + 4 * v27 + 4) + 90);
+for ( j = v27 - 1; ; --j )
+{
+v29 = 0.0;
+v30 = *(_DWORD *)((char *)v4 + 46);
+if ( j <= 0 )
+break;
+(***(void (__thiscall ****)(_DWORD, int, _DWORD))(v30 + 4 * j + 8))(
+*(_DWORD *)(v30 + 4 * j + 8),
+(*(_DWORD *)(*(_DWORD *)(v30 + 4 * j + 4) + 90) != 0) + 8,
+0.0);
+}
+v31 = *(void (__stdcall ****)(int, _DWORD))(v30 + 8);
+goto LABEL_44;
+case 27:
+if ( *(_DWORD *)((char *)this + 62) || !*(_DWORD *)((char *)this + 58) )
+TLightGroup::start_animation(this);
+v32 = *(_DWORD *)((char *)v4 + 46);
+*(_DWORD *)((char *)v4 + 58) = a2;
+*(_DWORD *)((char *)v4 + 62) = 0;
+v33 = *(_DWORD *)(v32 + 4);
+v97 = *(_DWORD *)(*(_DWORD *)(v32 + 8) + 90);
+v94 = *(_DWORD *)(v32 + 4);
+if ( v33 - 1 > 0 )
+{
+v34 = 12;
+v86 = v33 - 1;
+do
+{
+(***(void (__thiscall ****)(_DWORD, int, _DWORD))(v34 + *(_DWORD *)((char *)v4 + 46) - 4))(
+*(_DWORD *)(v34 + *(_DWORD *)((char *)v4 + 46) - 4),
+(*(_DWORD *)(*(_DWORD *)(v34 + *(_DWORD *)((char *)v4 + 46)) + 90) != 0) + 8,
+0.0);
+v34 += 4;
+--v86;
+}
+while ( v86 );
+}
+v29 = 0.0;
+v31 = *(void (__stdcall ****)(int, _DWORD))(*(_DWORD *)((char *)v4 + 46) + 4 * v94 + 4);
+LABEL_44:
+ v35 = v29;
+(**v31)((v97 != 0) + 8, LODWORD(v35));
+goto LABEL_20;
+case 28:
+if ( *(_DWORD *)((char *)this + 62) || !*(_DWORD *)((char *)this + 58) )
+TLightGroup::start_animation(this);
+v36 = *(_DWORD *)((char *)v4 + 46);
+*(_DWORD *)((char *)v4 + 58) = a2;
+*(_DWORD *)((char *)v4 + 62) = 0;
+v37 = *(_DWORD *)(v36 + 4) - 1;
+if ( v37 > 0 )
+{
+v98 = 8;
+v87 = v37;
+do
+{
+if ( _rand() % 100 > 70 )
+{
+v38 = *(void (__thiscall ****)(_DWORD, signed int, _DWORD))(v98 + *(_DWORD *)((char *)v4 + 46));
+v39 = *v38;
+v40 = (double)_rand() * 0.00003051850947599719 * a3 * 3.0 + 0.1;
+(*v39)(v38, 9, LODWORD(v40));
+}
+v98 += 4;
+--v87;
+}
+while ( v87 );
+}
+goto LABEL_20;
+case 29:
+if ( *(_DWORD *)((char *)this + 62) || !*(_DWORD *)((char *)this + 58) )
+TLightGroup::start_animation(this);
+v41 = *(_DWORD *)((char *)v4 + 46);
+*(_DWORD *)((char *)v4 + 58) = a2;
+*(_DWORD *)((char *)v4 + 62) = 0;
+v42 = *(_DWORD *)(v41 + 4) - 1;
+if ( v42 > 0 )
+{
+v99 = 8;
+v88 = v42;
+do
+{
+v43 = *(void (__thiscall ****)(_DWORD, signed int, _DWORD))(v99 + *(_DWORD *)((char *)v4 + 46));
+v44 = *v43;
+v45 = (double)(_rand() % 100 > 70);
+(*v44)(v43, 18, LODWORD(v45));
+v99 += 4;
+--v88;
+}
+while ( v88 );
+}
+LABEL_20:
+ TLightGroup::reschedule_animation(v4, a3);
+return 0;
+case 30:
+v46 = *(_DWORD *)((char *)this + 46);
+v47 = 0;
+v48 = *(_DWORD *)(v46 + 4) - 1;
+if ( v48 < 0 )
+return 0;
+v49 = v46 + 4 * v48 + 8;
+v50 = v48 + 1;
+do
+{
+if ( !*(_DWORD *)(*(_DWORD *)v49 + 78) )
+++v47;
+v49 -= 4;
+--v50;
+}
+while ( v50 );
+if ( !v47 )
+return 0;
+v51 = _rand();
+v52 = *(_DWORD *)((char *)v4 + 46);
+HIDWORD(v53) = v51 % v47;
+LODWORD(v53) = *(_DWORD *)(v52 + 4) - 1;
+if ( (signed int)v53 < 0 )
+goto LABEL_74;
+v103 = v52 + 4 * v53 + 8;
+while ( 1 )
+{
+if ( !*(_DWORD *)(*(_DWORD *)v103 + 78) )
+{
+v54 = HIDWORD(v53)--;
+if ( !v54 )
+break;
+}
+v103 -= 4;
+LODWORD(v53) = v53 - 1;
+if ( (signed int)v53 < 0 )
+goto LABEL_74;
+}
+LABEL_73:
+ (***(void (__fastcall ****)(_DWORD, _DWORD, signed int, _DWORD))(v52 + 4 * v53 + 8))(
+*(_DWORD *)(v52 + 4 * v53 + 8),
+HIDWORD(v53),
+1,
+0.0);
+goto LABEL_74;
+case 31:
+v55 = *(_DWORD *)((char *)this + 46);
+v56 = 0;
+v57 = *(_DWORD *)(v55 + 4) - 1;
+if ( v57 < 0 )
+return 0;
+v58 = v55 + 4 * v57 + 8;
+v59 = v57 + 1;
+do
+{
+if ( *(_DWORD *)(*(_DWORD *)v58 + 78) )
+++v56;
+v58 -= 4;
+--v59;
+}
+while ( v59 );
+if ( !v56 )
+return 0;
+v60 = _rand();
+v61 = *(_DWORD *)((char *)v4 + 46);
+HIDWORD(v62) = v60 % v56;
+LODWORD(v62) = *(_DWORD *)(v61 + 4) - 1;
+if ( (signed int)v62 < 0 )
+goto LABEL_74;
+v104 = v61 + 4 * v62 + 8;
+break;
+case 32:
+v64 = TLightGroup::next_light_up(this);
+if ( v64 < 0 )
+return 0;
+(***(void (__stdcall ****)(signed int, _DWORD))(*(_DWORD *)((char *)v4 + 46) + 4 * v64 + 8))(1, 0.0);
+goto LABEL_90;
+case 33:
+v66 = TLightGroup::next_light_down(this);
+if ( v66 < 0 )
+return 0;
+(***(void (__stdcall ****)(_DWORD, _DWORD))(*(_DWORD *)((char *)v4 + 46) + 4 * v66 + 8))(0, 0.0);
+LABEL_90:
+if ( *(_DWORD *)((char *)v4 + 58) )
+TLightGroup::start_animation(v4);
+return 1;
+case 34:
+if ( *(_DWORD *)((char *)this + 70) )
+timer_kill(*(_DWORD *)((char *)this + 70));
+v68 = *(_DWORD *)((char *)v4 + 58);
+*(_DWORD *)((char *)v4 + 70) = 0;
+if ( v68 == 26 || v68 == 27 || v68 == 28 )
+TLightGroup::Message(v4, 14, 0.0);
+*(_DWORD *)((char *)v4 + 58) = 0;
+*(_DWORD *)((char *)v4 + 62) = 0;
+return 0;
+case 35:
+v53 = (signed __int64)_floor(a3);
+v52 = *(_DWORD *)((char *)v4 + 46);
+if ( (signed int)v53 < *(_DWORD *)(v52 + 4) && (signed int)v53 >= 0 )
+goto LABEL_73;
+return 0;
+case 36:
+v62 = (signed __int64)_floor(a3);
+v61 = *(_DWORD *)((char *)v4 + 46);
+if ( (signed int)v62 < *(_DWORD *)(v61 + 4) && (signed int)v62 >= 0 )
+goto LABEL_117;
+return 0;
+case 37:
+v5 = *(_DWORD *)((char *)this + 46);
+result = 0;
+v7 = *(_DWORD *)(v5 + 4) - 1;
+if ( v7 >= 0 )
+{
+v8 = v5 + 4 * v7 + 8;
+v9 = *(_DWORD *)(v5 + 4);
+do
+{
+if ( *(_DWORD *)(*(_DWORD *)v8 + 78) )
+++result;
+v8 -= 4;
+--v9;
+}
+while ( v9 );
+}
+return result;
+case 38:
+return *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4);
+case 39:
+return *(_DWORD *)((char *)this + 58);
+case 40:
+return *(_DWORD *)((char *)this + 62);
+case 41:
+v65 = TLightGroup::next_light_up(this);
+if ( v65 < 0 )
+return 0;
+if ( *(_DWORD *)((char *)v4 + 58) || *(_DWORD *)((char *)v4 + 62) )
+TLightGroup::Message(v4, 34, 0.0);
+(***(void (__stdcall ****)(signed int, _DWORD))(*(_DWORD *)((char *)v4 + 46) + 4 * v65 + 8))(15, LODWORD(a3));
+return 1;
+case 42:
+v67 = TLightGroup::next_light_down(this);
+if ( v67 < 0 )
+return 0;
+if ( *(_DWORD *)((char *)v4 + 58) || *(_DWORD *)((char *)v4 + 62) )
+TLightGroup::Message(v4, 34, 0.0);
+(***(void (__stdcall ****)(signed int, _DWORD))(*(_DWORD *)((char *)v4 + 46) + 4 * v67 + 8))(16, LODWORD(a3));
+return 1;
+case 43:
+if ( *(_DWORD *)((char *)this + 66) )
+timer_kill(*(_DWORD *)((char *)this + 66));
+*(_DWORD *)((char *)v4 + 66) = 0;
+if ( a3 > 0.0 )
+*(_DWORD *)((char *)v4 + 66) = timer_set(a3, (int)v4, (int)TLightGroup::NotifyTimerExpired);
+return 0;
+case 44:
+v69 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4) - 1;
+if ( v69 >= 0 )
+{
+v70 = 4 * v69 + 8;
+v100 = *(_DWORD *)(*(_DWORD *)((char *)this + 46) + 4);
+do
+{
+v71 = *(_DWORD *)(v70 + *(_DWORD *)((char *)v4 + 46));
+if ( *(_DWORD *)(v71 + 78) )
+{
+(**(void (__stdcall ***)(_DWORD, _DWORD))v71)(0, 0.0);
+(***(void (__stdcall ****)(signed int, _DWORD))(v70 + *(_DWORD *)((char *)v4 + 46)))(16, LODWORD(a3));
+}
+v70 -= 4;
+--v100;
+}
+while ( v100 );
+}
+return 0;
+case 45:
+control_handler(a2, this);
+v72 = (signed __int64)_floor(a3);
+if ( (signed int)v72 >= 0 )
+{
+v73 = *(_DWORD *)(*(_DWORD *)((char *)v4 + 46) + 4);
+if ( (signed int)v72 <= v73 )
+{
+v74 = v73 - 1;
+if ( v73 - 1 > (signed int)v72 )
+{
+v105 = 4 * v74 + 8;
+v101 = v74 - v72;
+v74 = v72;
+do
+{
+(***(void (__fastcall ****)(_DWORD, _DWORD, signed int, _DWORD))(v105 + *(_DWORD *)((char *)v4 + 46)))(
+*(_DWORD *)(v105 + *(_DWORD *)((char *)v4 + 46)),
+HIDWORD(v72),
+20,
+0.0);
+v105 -= 4;
+--v101;
+}
+while ( v101 );
+}
+if ( v74 >= 0 )
+{
+v75 = 4 * v74 + 8;
+v76 = v74 + 1;
+do
+{
+(***(void (__fastcall ****)(_DWORD, _DWORD, signed int, _DWORD))(v75 + *(_DWORD *)((char *)v4 + 46)))(
+*(_DWORD *)(v75 + *(_DWORD *)((char *)v4 + 46)),
+HIDWORD(v72),
+19,
+0.0);
+v75 -= 4;
+--v76;
+}
+while ( v76 );
+}
+}
+}
+return 0;
+case 46:
+v77 = TLightGroup::next_light_down(this);
+if ( v77 >= 0 )
+(***(void (__stdcall ****)(signed int, _DWORD))(*(_DWORD *)((char *)v4 + 46) + 4 * v77 + 8))(4, 0.0);
+return 0;
+default:
+goto LABEL_145;
+}
+while ( 1 )
+{
+if ( *(_DWORD *)(*(_DWORD *)v104 + 78) )
+{
+v63 = HIDWORD(v62)--;
+if ( !v63 )
+break;
+}
+v104 -= 4;
+LODWORD(v62) = v62 - 1;
+if ( (signed int)v62 < 0 )
+goto LABEL_74;
+}
+LABEL_117:
+ (***(void (__fastcall ****)(_DWORD, _DWORD, _DWORD, _DWORD))(v61 + 4 * v62 + 8))(
+*(_DWORD *)(v61 + 4 * v62 + 8),
+HIDWORD(v62),
+0,
+0.0);
+LABEL_74:
+if ( *(_DWORD *)((char *)v4 + 58) )
+TLightGroup::start_animation(v4);
+}
+return 0;
+}
+
+//----- (0100ADB1) --------------------------------------------------------
+TLightGroup *__thiscall TLightGroup::TLightGroup(TLightGroup *this, struct TPinballTable *a2, int a3)
+{
+TLightGroup *v3; // esi
+signed __int16 *v4; // ebx
+struct TPinballComponent *v5; // eax
+int v7; // [esp+Ch] [ebp-4h]
+int i; // [esp+1Ch] [ebp+Ch]
+
+v3 = this;
+TPinballComponent::TPinballComponent(this, a2, a3, 0);
+*(_DWORD *)v3 = &TLightGroup::`vftable';
+objlist_class::objlist_class((TLightGroup *)((char *)v3 + 42), 4, 4);
+*(_DWORD *)((char *)v3 + 70) = 0;
+*(_DWORD *)((char *)v3 + 66) = 0;
+TLightGroup::Reset(v3);
+if ( a3 > 0 )
+{
+*(_DWORD *)((char *)v3 + 54) = *(_DWORD *)loader_query_float_attribute(a3, 0, 903);
+v4 = (signed __int16 *)loader_query_iattribute(a3, 1027, &v7);
+for ( i = 0; i < v7; ++v4 )
+{
+v5 = TPinballTable::find_component(a2, *v4);
+if ( v5 )
+objlist_class::Add((TLightGroup *)((char *)v3 + 42), (void *)v5);
+++i;
+}
+}
+return v3;
+}
+// 1001A60: using guessed type void *TLightGroup::`vftable';
+
+//----- (0100AE4C) --------------------------------------------------------
+TLightGroup *__thiscall TLightGroup::`vector deleting destructor'(TLightGroup *this, char a2)
+{
+TLightGroup *v2; // esi
+
+v2 = this;
+TLightGroup::~TLightGroup(this);
+if ( a2 & 1 )
+operator delete((void *)v2);
+return v2;
+}
+
diff --git a/Classes/TlightGroup/TLightGroup.h b/Classes/TlightGroup/TLightGroup.h
new file mode 100644
index 0000000..1380363
--- /dev/null
+++ b/Classes/TlightGroup/TLightGroup.h
@@ -0,0 +1,8 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_TLIGHTGROUP_H
+#define PINBALL_TLIGHTGROUP_H
+
+#endif //PINBALL_TLIGHTGROUP_H
diff --git a/about.cpp b/about.cpp
new file mode 100644
index 0000000..08b73e6
--- /dev/null
+++ b/about.cpp
@@ -0,0 +1,21 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+//----- (0100789A) --------------------------------------------------------
+INT __stdcall a_dialog(HINSTANCE hInstance, HWND hWnd, int a3)
+{
+ CHAR *v3; // eax
+ CHAR *v4; // eax
+ HICON v5; // eax
+ CHAR String1; // [esp+Ch] [ebp-194h]
+ CHAR szOtherStuff; // [esp+D4h] [ebp-CCh]
+
+ v3 = get_rc_string(38, 0);
+ lstrcpyA(&String1, v3);
+ v4 = get_rc_string(102, 0);
+ lstrcpyA(&szOtherStuff, v4);
+ v5 = LoadIconA(hInstance, "ICON_1");
+ return ShellAboutA(hWnd, &String1, &szOtherStuff, v5);
+}
+
diff --git a/control.cpp b/control.cpp
new file mode 100644
index 0000000..49b3e6e
--- /dev/null
+++ b/control.cpp
@@ -0,0 +1,2562 @@
+
+#include "pinball.h"
+
+//----- (0100C01D) --------------------------------------------------------
+void __stdcall control_make_links(struct TPinballTable *a1)
+{
+_DWORD *v1; // esi
+struct TPinballComponent *v2; // edi
+int v3; // ebx
+unsigned int v4; // esi
+struct TPinballTable *v5; // [esp+Ch] [ebp+8h]
+
+dword_1025040 = a1;
+v1 = &unk_1023EF8;
+v5 = (struct TPinballTable *)88;
+do
+{
+v2 = make_component_link((struct component_tag *)*(v1 - 2));
+v3 = 0;
+if ( v2 )
+{
+*(_DWORD *)((char *)v2 + 18) = v1 - 1;
+if ( *v1 > 0 )
+{
+do
+{
+(*(void (__thiscall **)(struct TPinballComponent *, int, _DWORD))(*(_DWORD *)v2 + 12))(
+v2,
+v3,
+*(_DWORD *)(v1[1] + 4 * v3));
+++v3;
+}
+while ( v3 < *v1 );
+}
+}
+v1 += 4;
+v5 = (struct TPinballTable *)((char *)v5 - 1);
+}
+while ( v5 );
+v4 = 0;
+do
+{
+make_component_link((struct component_tag *)off_1024470[v4]);
+++v4;
+}
+while ( v4 < 142 );
+}
+// 1024470: using guessed type char **off_1024470[142];
+
+//----- (0100C0BE) --------------------------------------------------------
+void __stdcall table_control_handler(int a1)
+{
+void (__stdcall **v1)(signed int, _DWORD); // eax
+
+if ( a1 == 1011 )
+{
+v1 = *(void (__stdcall ***)(signed int, _DWORD))dword_1023CEC;
+dword_1025044 = 0;
+(*v1)(7, 0.0);
+}
+}
+// 1023CEC: using guessed type int dword_1023CEC;
+// 1025044: using guessed type int dword_1025044;
+
+//----- (0100C397) --------------------------------------------------------
+void __stdcall AdvanceWormHoleDestination(int a1)
+{
+int v1; // eax
+int v2; // esi
+int v3; // esi
+float v4; // ST18_4
+float v5; // ST18_4
+int v6; // [esp+28h] [ebp+8h]
+
+v1 = *(_DWORD *)(dword_1023BBC + 6);
+if ( v1 != 16 && v1 != 22 && v1 != 23 )
+{
+v2 = *(_DWORD *)(dword_1023A24 + 6);
+if ( a1 || v2 )
+{
+v3 = v2 + 1;
+v6 = v3;
+if ( v3 == 4 )
+{
+v3 = 1;
+v6 = 1;
+}
+v4 = (double)v6;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A3C)(23, LODWORD(v4));
+v5 = (double)(3 - v3);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A3C)(11, LODWORD(v5));
+if ( !light_on((struct component_tag *)&off_1023A20) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A1C)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A3C)(19, 0.0);
+}
+}
+}
+}
+// 1023A1C: using guessed type int dword_1023A1C;
+// 1023A20: using guessed type char *off_1023A20;
+// 1023A24: using guessed type int dword_1023A24;
+// 1023A3C: using guessed type int dword_1023A3C;
+// 1023BBC: using guessed type int dword_1023BBC;
+
+//----- (0100C44B) --------------------------------------------------------
+void __stdcall FlipperRebounderControl1(int a1, struct TPinballComponent *a2)
+{
+int v2; // eax
+
+if ( a1 == 63 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10237D4)(9, 0.1);
+v2 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a2 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v2);
+}
+}
+// 10237D4: using guessed type int dword_10237D4;
+
+//----- (0100C48B) --------------------------------------------------------
+void __stdcall FlipperRebounderControl2(int a1, struct TPinballComponent *a2)
+{
+int v2; // eax
+
+if ( a1 == 63 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10237DC)(9, 0.1);
+v2 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a2 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v2);
+}
+}
+// 10237DC: using guessed type int dword_10237DC;
+
+//----- (0100C4CB) --------------------------------------------------------
+void __stdcall RebounderControl(int a1, struct TPinballComponent *a2)
+{
+int v2; // eax
+
+if ( a1 == 63 )
+{
+v2 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a2 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v2);
+}
+}
+
+//----- (0100C4F5) --------------------------------------------------------
+void __stdcall BumperControl(int a1, struct TPinballComponent *a2)
+{
+int v2; // eax
+
+if ( a1 == 63 )
+{
+v2 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a2 + 8))(*(_DWORD *)((char *)a2 + 78));
+TPinballTable::AddScore(dword_1025040, v2);
+}
+}
+
+//----- (0100C520) --------------------------------------------------------
+void __stdcall LeftKickerControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 60 )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023808)(54, 0.0);
+}
+// 1023808: using guessed type int dword_1023808;
+
+//----- (0100C546) --------------------------------------------------------
+void __stdcall RightKickerControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 60 )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023810)(54, 0.0);
+}
+// 1023810: using guessed type int dword_1023810;
+
+//----- (0100C56C) --------------------------------------------------------
+void __stdcall LeftKickerGateControl(int a1, struct TPinballComponent *a2)
+{
+float vars0; // [esp+Ch] [ebp+0h]
+
+if ( a1 == 53 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD, _DWORD))dword_1023818)(15, 5.0, LODWORD(vars0));
+vars0 = 5.0;
+(**(void (__stdcall ***)(signed int))dword_1023828)(7);
+}
+else if ( a1 == 54 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD, _DWORD))dword_1023818)(20, 0.0, LODWORD(vars0));
+vars0 = 0.0;
+(**(void (__stdcall ***)(signed int))dword_1023828)(20);
+}
+}
+// 1023818: using guessed type int dword_1023818;
+// 1023828: using guessed type int dword_1023828;
+
+//----- (0100C5D3) --------------------------------------------------------
+void __stdcall RightKickerGateControl(int a1, struct TPinballComponent *a2)
+{
+float vars0; // [esp+Ch] [ebp+0h]
+
+if ( a1 == 53 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD, _DWORD))dword_1023820)(15, 5.0, LODWORD(vars0));
+vars0 = 5.0;
+(**(void (__stdcall ***)(signed int))dword_1023830)(7);
+}
+else if ( a1 == 54 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD, _DWORD))dword_1023820)(20, 0.0, LODWORD(vars0));
+vars0 = 0.0;
+(**(void (__stdcall ***)(signed int))dword_1023830)(20);
+}
+}
+// 1023820: using guessed type int dword_1023820;
+// 1023830: using guessed type int dword_1023830;
+
+//----- (0100C63A) --------------------------------------------------------
+void __userpurge DeploymentChuteToEscapeChuteOneWayControl(int a1@, int a2@, int a3, struct TPinballComponent *a4)
+{
+int v4; // esi
+int v5; // eax
+int v6; // ST30_4
+CHAR *v7; // eax
+void (__thiscall ***v8)(_DWORD, signed int, _DWORD); // esi
+void (__thiscall ***v9)(_DWORD, signed int, _DWORD); // esi
+int v10; // [esp+30h] [ebp-4Ch]
+char Dest; // [esp+38h] [ebp-44h]
+
+if ( a3 == 63 )
+{
+v10 = a2;
+v4 = (**(int (__stdcall ***)(signed int, _DWORD))dword_1023CE4)(37, 0.0);
+if ( v4 )
+{
+(*(void (__stdcall **)(int))(*(_DWORD *)dword_1023DFC + 20))(v10);
+v5 = (*(int (__thiscall **)(struct TPinballComponent *, int))(*(_DWORD *)a4 + 8))(a4, v4 - 1);
+v6 = TPinballTable::AddScore(dword_1025040, v5);
+v7 = get_rc_string(21, 0);
+_sprintf(&Dest, v7, v6);
+TTextBox::Display(dword_1023E1C, a1, &Dest, 2.0);
+if ( !light_on((struct component_tag *)&off_1023884) )
+{
+v8 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A8C;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A8C)(34, 0.0);
+(**v8)(v8, 20, 0.0);
+v9 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A94;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A94)(34, 0.0);
+(**v9)(v9, 20, 0.0);
+}
+(**(void (__stdcall ***)(signed int))dword_1023CE4)(44);
+}
+}
+}
+// 100C63A: could not find valid save-restore pair for esi
+// 1023884: using guessed type char *off_1023884;
+// 1023A8C: using guessed type int dword_1023A8C;
+// 1023A94: using guessed type int dword_1023A94;
+// 1023CE4: using guessed type int dword_1023CE4;
+// 1023DFC: using guessed type int dword_1023DFC;
+
+//----- (0100C73E) --------------------------------------------------------
+void __stdcall DeploymentChuteToTableOneWayControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 63 )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CE4)(20, 0.0);
+}
+// 1023CE4: using guessed type int dword_1023CE4;
+
+//----- (0100C764) --------------------------------------------------------
+void __stdcall DrainBallBlockerControl(int a1, struct TPinballComponent *a2)
+{
+void (__thiscall **v2)(struct TPinballComponent *, signed int, _DWORD); // eax
+double v3; // st7
+float v4; // ST08_4
+void (__thiscall ***v5)(_DWORD, signed int, float); // ecx
+void (__thiscall **v6)(struct TPinballComponent *, signed int, _DWORD); // eax
+float v7; // ST08_4
+signed int v8; // [esp+4h] [ebp-Ch]
+float v9; // [esp+8h] [ebp-8h]
+
+if ( a1 == 52 )
+{
+v6 = *(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a2;
+v7 = (double)*(signed int *)((char *)a2 + 78);
+*(_DWORD *)((char *)a2 + 6) = 1;
+(*v6)(a2, 52, LODWORD(v7));
+v5 = (void (__thiscall ***)(_DWORD, signed int, float))dword_1023868;
+v9 = (double)*(signed int *)((char *)a2 + 78);
+v8 = 9;
+}
+else
+{
+if ( a1 != 60 )
+return;
+v2 = *(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a2;
+if ( *(_DWORD *)((char *)a2 + 6) != 1 )
+{
+*(_DWORD *)((char *)a2 + 6) = 0;
+(*v2)(a2, 51, 0.0);
+return;
+}
+v3 = (double)*(signed int *)((char *)a2 + 82);
+*(_DWORD *)((char *)a2 + 6) = 2;
+v4 = v3;
+(*v2)(a2, 59, LODWORD(v4));
+v5 = (void (__thiscall ***)(_DWORD, signed int, float))dword_1023868;
+v9 = (double)*(signed int *)((char *)a2 + 82);
+v8 = 7;
+}
+(**v5)(v5, v8, COERCE_FLOAT(LODWORD(v9)));
+}
+// 1023868: using guessed type int dword_1023868;
+
+//----- (0100C7E9) --------------------------------------------------------
+void __userpurge LaunchRampControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+signed int v3; // esi
+int v4; // ST08_4
+CHAR *v5; // eax
+int v6; // eax
+int v7; // ecx
+char Dest; // [esp+Ch] [ebp-44h]
+
+if ( a2 == 63 )
+{
+v3 = 0;
+if ( light_on((struct component_tag *)&off_1023874) )
+{
+v3 = 1;
+v4 = SpecialAddScore(*(_DWORD *)((char *)dword_1025040 + 302));
+v5 = get_rc_string(10, 0);
+_sprintf(&Dest, v5, v4);
+TTextBox::Display(dword_1023E1C, a1, &Dest, 2.0);
+}
+if ( light_on((struct component_tag *)&off_102387C) )
+v3 |= 2u;
+if ( light_on((struct component_tag *)&off_1023884) )
+v3 |= 4u;
+if ( v3 )
+{
+if ( v3 == 1 )
+{
+v7 = dword_1023D24;
+}
+else if ( v3 <= 1 || v3 > 3 )
+{
+v7 = dword_1023D34;
+}
+else
+{
+v7 = dword_1023D2C;
+}
+}
+else
+{
+v6 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a3 + 8))(a3, 0);
+TPinballTable::AddScore(dword_1025040, v6);
+v7 = dword_1023D3C;
+}
+(*(void (**)(void))(*(_DWORD *)v7 + 20))();
+}
+}
+// 1023874: using guessed type char *off_1023874;
+// 102387C: using guessed type char *off_102387C;
+// 1023884: using guessed type char *off_1023884;
+// 1023D24: using guessed type int dword_1023D24;
+// 1023D2C: using guessed type int dword_1023D2C;
+// 1023D34: using guessed type int dword_1023D34;
+// 1023D3C: using guessed type int dword_1023D3C;
+
+//----- (0100C8D7) --------------------------------------------------------
+void __stdcall LaunchRampHoleControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 58 )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023878)(7, 5.0);
+}
+// 1023878: using guessed type int dword_1023878;
+
+//----- (0100C901) --------------------------------------------------------
+void __stdcall SpaceWarpRolloverControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 63 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238D0)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238D8)(19, 0.0);
+}
+}
+// 10238D0: using guessed type int dword_10238D0;
+// 10238D8: using guessed type int dword_10238D8;
+
+//----- (0100C939) --------------------------------------------------------
+void __userpurge ReentryLanesRolloverControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5)
+{
+void (__thiscall ***v5)(_DWORD, signed int, _DWORD); // esi
+void (__thiscall ***v6)(_DWORD, signed int, _DWORD); // esi
+struct TPinballComponent *v7; // esi
+int v8; // ecx
+void (__stdcall **v9)(signed int, _DWORD); // eax
+int v10; // ST58_4
+void (__thiscall ***v11)(_DWORD, signed int, _DWORD, int, int); // esi
+int v12; // ebx
+bool v13; // zf
+int v14; // ebx
+char *v15; // eax
+int v16; // eax
+int v17; // [esp+60h] [ebp-4h]
+
+if ( a4 == 63 )
+{
+v17 = a3;
+v5 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A8C;
+if ( !light_on((struct component_tag *)&off_1023884)
+&& ((int (__thiscall *)(_DWORD, signed int, _DWORD))**v5)(v5, 39, 0.0) )
+{
+(**v5)(v5, 34, 0.0);
+(**v5)(v5, 20, 0.0);
+v6 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A94;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A94)(34, 0.0);
+(**v6)(v6, 20, 0.0);
+}
+v7 = a5;
+if ( (struct TPinballComponent *)dword_102372C == a5 )
+{
+v8 = dword_102370C;
+}
+else
+{
+v8 = dword_1023714;
+if ( (struct TPinballComponent *)dword_1023734 != a5 )
+v8 = dword_102371C;
+}
+if ( !*(_DWORD *)(v8 + 82) )
+{
+v9 = *(void (__stdcall ***)(signed int, _DWORD))v8;
+if ( *(_DWORD *)(v8 + 78) )
+{
+(*v9)(20, 0.0);
+}
+else
+{
+v10 = a1;
+(*v9)(19, 0.0);
+v11 = (void (__thiscall ***)(_DWORD, signed int, _DWORD, int, int))dword_1023724;
+v12 = (**(int (__thiscall ***)(int, signed int, _DWORD))dword_1023724)(dword_1023724, 37, 0.0);
+v13 = v12 == (**(int (__stdcall ***)(signed int, _DWORD))dword_1023724)(38, 0.0);
+v14 = v10;
+if ( v13 )
+{
+(**v11)(v11, 7, 5.0, a2, v17);
+((void (__thiscall *)(void (__thiscall ***)(_DWORD, signed int, _DWORD, int, int), _DWORD, _DWORD))**v11)(
+v11,
+0,
+0.0);
+if ( *(_DWORD *)(dword_10236E4 + 78) < 3 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023704)(12, 0.0);
+v15 = get_rc_string(5, 0);
+TTextBox::Display(dword_1023E1C, v14, v15, 2.0);
+}
+(**(void (__cdecl ***)(signed int, _DWORD))dword_1023704)(48, 60.0);
+}
+v7 = a5;
+}
+}
+v16 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)v7 + 8))(v7, 0);
+TPinballTable::AddScore(dword_1025040, v16);
+}
+}
+// 100C939: could not find valid save-restore pair for ebx
+// 100C939: could not find valid save-restore pair for edi
+// 100C939: could not find valid save-restore pair for esi
+// 10236E4: using guessed type int dword_10236E4;
+// 1023704: using guessed type int dword_1023704;
+// 102370C: using guessed type int dword_102370C;
+// 1023714: using guessed type int dword_1023714;
+// 102371C: using guessed type int dword_102371C;
+// 1023724: using guessed type int dword_1023724;
+// 102372C: using guessed type int dword_102372C;
+// 1023734: using guessed type int dword_1023734;
+// 1023884: using guessed type char *off_1023884;
+// 1023A8C: using guessed type int dword_1023A8C;
+// 1023A94: using guessed type int dword_1023A94;
+
+//----- (0100CABF) --------------------------------------------------------
+void __stdcall BumperGroupControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 61 )
+{
+if ( *(_DWORD *)((char *)a2 + 78) )
+{
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a2)(a2, 48, 60.0);
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a2)(a2, 13, 0.0);
+}
+}
+}
+
+//----- (0100CAFE) --------------------------------------------------------
+void __userpurge LaunchLanesRolloverControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5)
+{
+struct TPinballComponent *v5; // esi
+int v6; // ecx
+void (__stdcall **v7)(signed int, _DWORD); // eax
+int v8; // ST30_4
+void (__thiscall ***v9)(_DWORD, signed int, _DWORD, int, int); // esi
+int v10; // ebx
+bool v11; // zf
+int v12; // ebx
+char *v13; // eax
+int v14; // eax
+int v15; // [esp+38h] [ebp-4h]
+
+if ( a4 == 63 )
+{
+v15 = a3;
+v5 = a5;
+if ( (struct TPinballComponent *)dword_1023798 == a5 )
+{
+v6 = dword_1023778;
+}
+else
+{
+v6 = dword_1023780;
+if ( (struct TPinballComponent *)dword_10237A0 != a5 )
+v6 = dword_1023788;
+}
+if ( !*(_DWORD *)(v6 + 82) )
+{
+v7 = *(void (__stdcall ***)(signed int, _DWORD))v6;
+if ( *(_DWORD *)(v6 + 78) )
+{
+(*v7)(20, 0.0);
+}
+else
+{
+v8 = a1;
+(*v7)(19, 0.0);
+v9 = (void (__thiscall ***)(_DWORD, signed int, _DWORD, int, int))dword_1023790;
+v10 = (**(int (__thiscall ***)(int, signed int, _DWORD))dword_1023790)(dword_1023790, 37, 0.0);
+v11 = v10 == (**(int (__stdcall ***)(signed int, _DWORD))dword_1023790)(38, 0.0);
+v12 = v8;
+if ( v11 )
+{
+(**v9)(v9, 7, 5.0, a2, v15);
+((void (__thiscall *)(void (__thiscall ***)(_DWORD, signed int, _DWORD, int, int), _DWORD, _DWORD))**v9)(
+v9,
+0,
+0.0);
+if ( *(_DWORD *)(dword_1023758 + 78) < 3 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023770)(12, 0.0);
+v13 = get_rc_string(6, 0);
+TTextBox::Display(dword_1023E1C, v12, v13, 2.0);
+}
+(**(void (__cdecl ***)(signed int, _DWORD))dword_1023770)(48, 60.0);
+}
+v5 = a5;
+}
+}
+v14 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)v5 + 8))(v5, 0);
+TPinballTable::AddScore(dword_1025040, v14);
+}
+}
+// 100CAFE: could not find valid save-restore pair for ebx
+// 100CAFE: could not find valid save-restore pair for edi
+// 100CAFE: could not find valid save-restore pair for esi
+// 1023758: using guessed type int dword_1023758;
+// 1023770: using guessed type int dword_1023770;
+// 1023778: using guessed type int dword_1023778;
+// 1023780: using guessed type int dword_1023780;
+// 1023788: using guessed type int dword_1023788;
+// 1023790: using guessed type int dword_1023790;
+// 1023798: using guessed type int dword_1023798;
+// 10237A0: using guessed type int dword_10237A0;
+
+//----- (0100CC20) --------------------------------------------------------
+void __userpurge OutLaneRolloverControl(int a1@, int a2@, int a3, struct TPinballComponent *a4)
+{
+void (__stdcall ***v4)(signed int); // ecx
+int v5; // eax
+
+if ( a3 == 63 )
+{
+if ( light_on((struct component_tag *)&off_10238A8) || light_on((struct component_tag *)&off_10238B0) )
+{
+table_add_extra_ball(a1, 2.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238AC)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238B4)(20, 0.0);
+}
+else
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023E04 + 20))();
+}
+if ( (struct TPinballComponent *)dword_102389C == a4 )
+{
+if ( light_on((struct component_tag *)&off_1023814) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD, int))dword_1023818)(4, 0.0, a2);
+v4 = (void (__stdcall ***)(signed int))dword_1023828;
+LABEL_11:
+(**v4)(4);
+goto LABEL_12;
+}
+}
+else if ( light_on((struct component_tag *)&off_102381C) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD, int))dword_1023820)(4, 0.0, a2);
+v4 = (void (__stdcall ***)(signed int))dword_1023830;
+goto LABEL_11;
+}
+LABEL_12:
+v5 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a4 + 8))(a4, 0);
+TPinballTable::AddScore(dword_1025040, v5);
+}
+}
+// 100CC20: could not find valid save-restore pair for esi
+// 1023814: using guessed type char *off_1023814;
+// 1023818: using guessed type int dword_1023818;
+// 102381C: using guessed type char *off_102381C;
+// 1023820: using guessed type int dword_1023820;
+// 1023828: using guessed type int dword_1023828;
+// 1023830: using guessed type int dword_1023830;
+// 102389C: using guessed type int dword_102389C;
+// 10238A8: using guessed type char *off_10238A8;
+// 10238AC: using guessed type int dword_10238AC;
+// 10238B0: using guessed type char *off_10238B0;
+// 10238B4: using guessed type int dword_10238B4;
+// 1023E04: using guessed type int dword_1023E04;
+
+//----- (0100CD12) --------------------------------------------------------
+void __stdcall ExtraBallLightControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 19 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238AC)(9, 55.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238B4)(9, 55.0);
+dword_102504C = 1;
+}
+else if ( a1 == 60 )
+{
+if ( dword_102504C )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238AC)(7, 5.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238B4)(7, 5.0);
+dword_102504C = 0;
+}
+}
+}
+// 10238AC: using guessed type int dword_10238AC;
+// 10238B4: using guessed type int dword_10238B4;
+// 102504C: using guessed type int dword_102504C;
+
+//----- (0100CDA0) --------------------------------------------------------
+void __userpurge ReturnLaneRolloverControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+void (__stdcall ***v3)(signed int); // ecx
+int v4; // eax
+
+if ( a2 == 63 )
+{
+if ( (struct TPinballComponent *)dword_10238C0 == a3 )
+{
+if ( light_on((struct component_tag *)&off_10238CC) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD, int))dword_1023AC4)(20, 0.0, a1);
+v3 = (void (__stdcall ***)(signed int))dword_10238D0;
+LABEL_8:
+(**v3)(20);
+v4 = (*(int (__thiscall **)(struct TPinballComponent *, signed int))(*(_DWORD *)a3 + 8))(a3, 1);
+LABEL_10:
+TPinballTable::AddScore(dword_1025040, v4);
+return;
+}
+}
+else
+{
+if ( (struct TPinballComponent *)dword_10238C8 != a3 )
+return;
+if ( light_on((struct component_tag *)&off_10238D4) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD, int))dword_1023AC4)(20, 0.0, a1);
+v3 = (void (__stdcall ***)(signed int))dword_10238D8;
+goto LABEL_8;
+}
+}
+v4 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a3 + 8))(a3, 0);
+goto LABEL_10;
+}
+}
+// 100CDA0: could not find valid save-restore pair for esi
+// 10238C0: using guessed type int dword_10238C0;
+// 10238C8: using guessed type int dword_10238C8;
+// 10238CC: using guessed type char *off_10238CC;
+// 10238D0: using guessed type int dword_10238D0;
+// 10238D4: using guessed type char *off_10238D4;
+// 10238D8: using guessed type int dword_10238D8;
+// 1023AC4: using guessed type int dword_1023AC4;
+
+//----- (0100CE40) --------------------------------------------------------
+void __userpurge BonusLaneRolloverControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST08_4
+CHAR *v4; // eax
+int v5; // eax
+char *v6; // eax
+char Dest; // [esp+Ch] [ebp-44h]
+
+if ( a2 == 63 )
+{
+if ( light_on((struct component_tag *)&off_10238EC) )
+{
+v3 = SpecialAddScore(*(_DWORD *)((char *)dword_1025040 + 306));
+v4 = get_rc_string(3, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E1C, a1, &Dest, 2.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238F0)(20, 0.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D4C + 20))();
+}
+else
+{
+v5 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a3 + 8))(a3, 0);
+TPinballTable::AddScore(dword_1025040, v5);
+(*(void (**)(void))(*(_DWORD *)dword_1023D54 + 20))();
+v6 = get_rc_string(44, 0);
+TTextBox::Display(dword_1023E1C, a1, v6, 2.0);
+}
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(45, 11.0);
+}
+}
+// 10238EC: using guessed type char *off_10238EC;
+// 10238F0: using guessed type int dword_10238F0;
+// 1023978: using guessed type int dword_1023978;
+// 1023D4C: using guessed type int dword_1023D4C;
+// 1023D54: using guessed type int dword_1023D54;
+
+//----- (0100CF36) --------------------------------------------------------
+void __userpurge FuelRollover1Control(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+int v4; // eax
+
+if ( a2 == 63 )
+{
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023978)(37, 0.0) > 1 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023948)(8, 0.050000001);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(45, 1.0);
+v3 = get_rc_string(44, 0);
+TTextBox::Display(dword_1023E1C, a1, v3, 2.0);
+}
+v4 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a3 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v4);
+}
+}
+// 1023948: using guessed type int dword_1023948;
+// 1023978: using guessed type int dword_1023978;
+
+//----- (0100CFC0) --------------------------------------------------------
+void __userpurge FuelRollover2Control(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+int v4; // eax
+
+if ( a2 == 63 )
+{
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023978)(37, 0.0) > 3 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023950)(8, 0.050000001);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(45, 3.0);
+v3 = get_rc_string(44, 0);
+TTextBox::Display(dword_1023E1C, a1, v3, 2.0);
+}
+v4 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a3 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v4);
+}
+}
+// 1023950: using guessed type int dword_1023950;
+// 1023978: using guessed type int dword_1023978;
+
+//----- (0100D04E) --------------------------------------------------------
+void __userpurge FuelRollover3Control(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+int v4; // eax
+
+if ( a2 == 63 )
+{
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023978)(37, 0.0) > 5 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023958)(8, 0.050000001);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(45, 5.0);
+v3 = get_rc_string(44, 0);
+TTextBox::Display(dword_1023E1C, a1, v3, 2.0);
+}
+v4 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a3 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v4);
+}
+}
+// 1023958: using guessed type int dword_1023958;
+// 1023978: using guessed type int dword_1023978;
+
+//----- (0100D0DC) --------------------------------------------------------
+void __userpurge FuelRollover4Control(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+int v4; // eax
+
+if ( a2 == 63 )
+{
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023978)(37, 0.0) > 7 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023960)(8, 0.050000001);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(45, 7.0);
+v3 = get_rc_string(44, 0);
+TTextBox::Display(dword_1023E1C, a1, v3, 2.0);
+}
+v4 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a3 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v4);
+}
+}
+// 1023960: using guessed type int dword_1023960;
+// 1023978: using guessed type int dword_1023978;
+
+//----- (0100D16A) --------------------------------------------------------
+void __userpurge FuelRollover5Control(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+int v4; // eax
+
+if ( a2 == 63 )
+{
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023978)(37, 0.0) > 9 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023968)(8, 0.050000001);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(45, 9.0);
+v3 = get_rc_string(44, 0);
+TTextBox::Display(dword_1023E1C, a1, v3, 2.0);
+}
+v4 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a3 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v4);
+}
+}
+// 1023968: using guessed type int dword_1023968;
+// 1023978: using guessed type int dword_1023978;
+
+//----- (0100D1F8) --------------------------------------------------------
+void __userpurge FuelRollover6Control(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+int v4; // eax
+
+if ( a2 == 63 )
+{
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023978)(37, 0.0) > 11 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023970)(8, 0.050000001);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(45, 11.0);
+v3 = get_rc_string(44, 0);
+TTextBox::Display(dword_1023E1C, a1, v3, 2.0);
+}
+v4 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a3 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v4);
+}
+}
+// 1023970: using guessed type int dword_1023970;
+// 1023978: using guessed type int dword_1023978;
+
+//----- (0100D286) --------------------------------------------------------
+void __stdcall HyperspaceLightGroupControl(int a1, struct TPinballComponent *a2)
+{
+struct TPinballComponent *v2; // esi
+
+if ( a1 )
+{
+if ( a1 == 41 )
+{
+v2 = a2;
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a2)(a2, 41, 2.0);
+LABEL_7:
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))v2)(v2, 43, 60.0);
+return;
+}
+if ( a1 == 61 )
+{
+v2 = a2;
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a2)(a2, 33, 0.0);
+if ( (**(int (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))v2)(v2, 37, 0.0) )
+goto LABEL_7;
+}
+}
+else
+{
+(**(void (__thiscall ***)(struct TPinballComponent *, _DWORD, _DWORD))a2)(a2, 0, 0.0);
+}
+}
+
+//----- (0100D303) --------------------------------------------------------
+void __userpurge WormHoleControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5)
+{
+int v5; // ebx
+int v6; // edi
+int v7; // ebx
+int v8; // eax
+int v9; // ebx
+int v10; // edi
+char *v11; // eax
+int v12; // eax
+int v13; // ebx
+float v14; // ST3C_4
+int v15; // eax
+char *v16; // eax
+int v17; // [esp+40h] [ebp-Ch]
+int v18; // [esp+48h] [ebp-4h]
+
+if ( a4 == 63 )
+{
+v18 = a1;
+v5 = 0;
+if ( (struct TPinballComponent *)dword_10239EC != a5 )
+{
+LOBYTE(v5) = dword_10239F4 != (_DWORD)a5;
+++v5;
+}
+v17 = a2;
+v6 = *(_DWORD *)(dword_1023A24 + 6);
+v7 = v5 + 1;
+if ( v6 )
+{
+*(_DWORD *)(dword_1023A24 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A1C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A3C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C44)(20, 0.0);
+if ( v6 == v7 )
+{
+if ( *(_DWORD *)((char *)dword_1025040 + 346) )
+{
+table_bump_ball_sink_lock(v7);
+TPinballTable::AddScore(dword_1025040, 10000);
+}
+else
+{
+v11 = get_rc_string(49, 0);
+TTextBox::Display(dword_1023E1C, v7, v11, 2.0);
+table_set_replay(v7, 4.0);
+v12 = (*(int (__thiscall **)(struct TPinballComponent *, signed int))(*(_DWORD *)a5 + 8))(a5, 1);
+TPinballTable::AddScore(dword_1025040, v12);
+v13 = v7 - 1;
+(**(void (__stdcall ***)(signed int, _DWORD))off_1023A4C[v13][1])(16, *(float *)((char *)a5 + 82));
+v14 = (double)(2 - v13);
+(**(void (__stdcall ***)(signed int, _DWORD))off_1023A58[v13][1])(11, LODWORD(v14));
+(**(void (__stdcall ***)(signed int, _DWORD))off_1023A58[v13][1])(16, *(float *)((char *)a5 + 82));
+(**(void (__stdcall ***)(signed int, _DWORD))off_1023A40[v13][1])(56, *(float *)((char *)a5 + 82));
+}
+return;
+}
+v15 = (*(int (__thiscall **)(struct TPinballComponent *, signed int, int, int, int))(*(_DWORD *)a5 + 8))(
+a5,
+2,
+v17,
+a3,
+v18);
+TPinballTable::AddScore(dword_1025040, v15);
+v9 = v6 - 1;
+v10 = v6 - 1;
+(**(void (__stdcall ***)(signed int, _DWORD))off_1023A4C[v10][1])(16, *(float *)((char *)a5 + 82));
+}
+else
+{
+v8 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD, int, int, int))(*(_DWORD *)a5 + 8))(
+a5,
+0,
+v17,
+a3,
+v18);
+TPinballTable::AddScore(dword_1025040, v8);
+v9 = v7 - 1;
+v10 = v9;
+(**(void (__stdcall ***)(signed int, _DWORD))off_1023A4C[v9][1])(16, *(float *)((char *)a5 + 82));
+}
+(**(void (__stdcall ***)(signed int))off_1023A58[v10][1])(11);
+(**(void (__cdecl ***)(signed int, _DWORD))off_1023A58[v10][1])(16, *(float *)((char *)a5 + 82));
+(**(void (__stdcall ***)(signed int, _DWORD))off_1023A40[v10][1])(56, *(float *)((char *)a5 + 82));
+v16 = get_rc_string(49, 0);
+TTextBox::Display(dword_1023E1C, v9, v16, 2.0);
+}
+}
+// 100D303: could not find valid save-restore pair for ebx
+// 100D303: could not find valid save-restore pair for edi
+// 100D303: could not find valid save-restore pair for esi
+// 10239EC: using guessed type int dword_10239EC;
+// 10239F4: using guessed type int dword_10239F4;
+// 1023A1C: using guessed type int dword_1023A1C;
+// 1023A24: using guessed type int dword_1023A24;
+// 1023A3C: using guessed type int dword_1023A3C;
+// 1023A40: using guessed type char **off_1023A40[9];
+// 1023A4C: using guessed type char **off_1023A4C[6];
+// 1023A58: using guessed type char **off_1023A58[3];
+// 1023C44: using guessed type int dword_1023C44;
+
+//----- (0100D53A) --------------------------------------------------------
+void __stdcall LeftFlipperControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 1 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023724)(24, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023790)(24, 0.0);
+}
+}
+// 1023724: using guessed type int dword_1023724;
+// 1023790: using guessed type int dword_1023790;
+
+//----- (0100D572) --------------------------------------------------------
+void __stdcall RightFlipperControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 1 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023724)(25, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023790)(25, 0.0);
+}
+}
+// 1023724: using guessed type int dword_1023724;
+// 1023790: using guessed type int dword_1023790;
+
+//----- (0100D5AA) --------------------------------------------------------
+void __stdcall JackpotLightControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 60 )
+*(_DWORD *)((char *)dword_1025040 + 318) = 0;
+}
+
+//----- (0100D5CA) --------------------------------------------------------
+void __stdcall BonusLightControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 60 )
+*(_DWORD *)((char *)dword_1025040 + 310) = 0;
+}
+
+//----- (0100D5EA) --------------------------------------------------------
+void __stdcall BoosterTargetControl(int a1, struct TPinballComponent *a2)
+{
+int v2; // eax
+int v3; // ecx
+int v4; // eax
+int v5; // eax
+
+if ( a1 == 63 && !*(_DWORD *)((char *)a2 + 6) )
+{
+*(_DWORD *)((char *)a2 + 6) = 1;
+if ( *(_DWORD *)(dword_1023A9C + 6) + *(_DWORD *)(dword_1023AA4 + 6) + *(_DWORD *)(dword_1023AAC + 6) != 3 )
+{
+v5 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a2 + 8))(a2, 0);
+goto LABEL_19;
+}
+if ( light_on((struct component_tag *)&off_1023AB0) )
+{
+if ( light_on((struct component_tag *)&off_1023AB8) )
+{
+if ( light_on((struct component_tag *)&off_1023AC0) )
+{
+if ( light_on((struct component_tag *)&off_1023AC8) )
+{
+v4 = (*(int (__thiscall **)(struct TPinballComponent *, signed int))(*(_DWORD *)a2 + 8))(a2, 1);
+TPinballTable::AddScore(dword_1025040, v4);
+}
+else
+{
+table_set_bonus_hold(0);
+}
+v3 = dword_1023DCC;
+}
+else
+{
+table_set_bonus(0);
+v3 = dword_1023DBC;
+}
+}
+else
+{
+table_set_jackpot(0);
+v3 = dword_1023DB4;
+}
+}
+else
+{
+v2 = *(_DWORD *)(dword_1023BBC + 6);
+if ( v2 == 15 || v2 == 29 )
+goto LABEL_17;
+table_set_flag_lights(0);
+v3 = dword_1023DC4;
+}
+(*(void (**)(void))(*(_DWORD *)v3 + 20))();
+LABEL_17:
+*(_DWORD *)(dword_1023A9C + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A9C)(50, 0.0);
+*(_DWORD *)(dword_1023AA4 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AA4)(50, 0.0);
+*(_DWORD *)(dword_1023AAC + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AAC)(50, 0.0);
+v5 = (*(int (__thiscall **)(struct TPinballComponent *, signed int))(*(_DWORD *)a2 + 8))(a2, 1);
+LABEL_19:
+TPinballTable::AddScore(dword_1025040, v5);
+}
+}
+// 1023A9C: using guessed type int dword_1023A9C;
+// 1023AA4: using guessed type int dword_1023AA4;
+// 1023AAC: using guessed type int dword_1023AAC;
+// 1023AB0: using guessed type char *off_1023AB0;
+// 1023AB8: using guessed type char *off_1023AB8;
+// 1023AC0: using guessed type char *off_1023AC0;
+// 1023AC8: using guessed type char *off_1023AC8;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023DB4: using guessed type int dword_1023DB4;
+// 1023DBC: using guessed type int dword_1023DBC;
+// 1023DC4: using guessed type int dword_1023DC4;
+// 1023DCC: using guessed type int dword_1023DCC;
+
+//----- (0100D73E) --------------------------------------------------------
+void __stdcall MedalLightGroupControl(int a1, struct TPinballComponent *a2)
+{
+struct TPinballComponent *v2; // esi
+
+if ( a1 )
+{
+if ( a1 == 41 )
+{
+v2 = a2;
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a2)(a2, 41, 2.0);
+LABEL_7:
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))v2)(v2, 43, 30.0);
+return;
+}
+if ( a1 == 61 )
+{
+v2 = a2;
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a2)(a2, 33, 0.0);
+if ( (**(int (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))v2)(v2, 37, 0.0) )
+goto LABEL_7;
+}
+}
+else
+{
+(**(void (__thiscall ***)(struct TPinballComponent *, _DWORD, _DWORD))a2)(a2, 0, 0.0);
+}
+}
+
+//----- (0100D7BB) --------------------------------------------------------
+void __userpurge MultiplierLightGroupControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+struct TPinballComponent *v3; // esi
+double v4; // st7
+char *v5; // eax
+int v6; // ecx
+float v7; // ST10_4
+
+if ( a2 )
+{
+if ( a2 == 41 )
+{
+v3 = a3;
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a3)(a3, 41, 2.0);
+goto LABEL_13;
+}
+if ( a2 != 61 )
+{
+if ( a2 == 64 )
+{
+*(_DWORD *)((char *)dword_1025040 + 294) = 4;
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a3)(a3, 19, 0.0);
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a3)(a3, 43, 30.0);
+v5 = get_rc_string(59, 0);
+TTextBox::Display(dword_1023E1C, a1, v5, 2.0);
+return;
+}
+if ( a2 != 65 )
+return;
+v3 = a3;
+*(_DWORD *)((char *)dword_1025040 + 294) = 0;
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a3)(a3, 20, 0.0);
+v4 = -1.0;
+goto LABEL_14;
+}
+v6 = *(_DWORD *)((char *)dword_1025040 + 294);
+if ( v6 )
+*(_DWORD *)((char *)dword_1025040 + 294) = v6 - 1;
+v3 = a3;
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a3)(a3, 33, 0.0);
+if ( (**(int (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))v3)(v3, 37, 0.0) )
+{
+LABEL_13:
+v4 = 30.0;
+LABEL_14:
+v7 = v4;
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))v3)(v3, 43, LODWORD(v7));
+return;
+}
+}
+else
+{
+(**(void (__thiscall ***)(struct TPinballComponent *, _DWORD, _DWORD))a3)(a3, 0, 0.0);
+}
+}
+
+//----- (0100D8DE) --------------------------------------------------------
+void __userpurge FuelSpotTargetControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+void (__stdcall ***v3)(signed int, _DWORD); // ecx
+int v4; // eax
+char *v5; // eax
+
+if ( a2 == 63 )
+{
+if ( (struct TPinballComponent *)dword_1023B48 == a3 )
+{
+v3 = (void (__stdcall ***)(signed int, _DWORD))dword_1023B60;
+}
+else
+{
+v3 = (void (__stdcall ***)(signed int, _DWORD))dword_1023B68;
+if ( (struct TPinballComponent *)dword_1023B50 != a3 )
+v3 = (void (__stdcall ***)(signed int, _DWORD))dword_1023B70;
+}
+(**v3)(15, 2.0);
+v4 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a3 + 8))(a3, 0);
+TPinballTable::AddScore(dword_1025040, v4);
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023B78)(37, 0.0) == 3 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B78)(16, 2.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(45, 11.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D54 + 20))();
+v5 = get_rc_string(44, 0);
+TTextBox::Display(dword_1023E1C, a1, v5, 2.0);
+}
+else
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023E0C + 20))();
+}
+}
+}
+// 1023978: using guessed type int dword_1023978;
+// 1023B48: using guessed type int dword_1023B48;
+// 1023B50: using guessed type int dword_1023B50;
+// 1023B60: using guessed type int dword_1023B60;
+// 1023B68: using guessed type int dword_1023B68;
+// 1023B70: using guessed type int dword_1023B70;
+// 1023B78: using guessed type int dword_1023B78;
+// 1023D54: using guessed type int dword_1023D54;
+// 1023E0C: using guessed type int dword_1023E0C;
+
+//----- (0100D9C2) --------------------------------------------------------
+void __userpurge MissionSpotTargetControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+void (__stdcall ***v3)(signed int, _DWORD, int); // ecx
+int v4; // ecx
+int v5; // eax
+
+if ( a2 == 63 )
+{
+if ( (struct TPinballComponent *)dword_1023B84 == a3 )
+{
+*(_DWORD *)(dword_1023B9C + 6) |= 1u;
+v3 = (void (__stdcall ***)(signed int, _DWORD, int))dword_1023B9C;
+}
+else if ( (struct TPinballComponent *)dword_1023B8C == a3 )
+{
+*(_DWORD *)(dword_1023B9C + 6) |= 2u;
+v3 = (void (__stdcall ***)(signed int, _DWORD, int))dword_1023BA4;
+}
+else
+{
+*(_DWORD *)(dword_1023B9C + 6) |= 4u;
+v3 = (void (__stdcall ***)(signed int, _DWORD, int))dword_1023BAC;
+}
+(**v3)(15, 2.0, a1);
+if ( !light_on((struct component_tag *)&off_1023BB8) || (v4 = dword_1023E0C, *(_DWORD *)(dword_1023BBC + 82)) )
+v4 = dword_1023DD4;
+(*(void (**)(void))(*(_DWORD *)v4 + 20))();
+v5 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a3 + 8))(a3, 0);
+TPinballTable::AddScore(dword_1025040, v5);
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023BB4)(37, 0.0) == 3 )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023BB4)(16, 2.0);
+}
+}
+// 100D9C2: could not find valid save-restore pair for esi
+// 1023B84: using guessed type int dword_1023B84;
+// 1023B8C: using guessed type int dword_1023B8C;
+// 1023B9C: using guessed type int dword_1023B9C;
+// 1023BA4: using guessed type int dword_1023BA4;
+// 1023BAC: using guessed type int dword_1023BAC;
+// 1023BB4: using guessed type int dword_1023BB4;
+// 1023BB8: using guessed type char *off_1023BB8;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023DD4: using guessed type int dword_1023DD4;
+// 1023E0C: using guessed type int dword_1023E0C;
+
+//----- (0100DA94) --------------------------------------------------------
+void __stdcall LeftHazardSpotTargetControl(int a1, struct TPinballComponent *a2)
+{
+void (__stdcall ***v2)(signed int, _DWORD); // ecx
+int v3; // eax
+
+if ( a1 == 63 )
+{
+if ( (struct TPinballComponent *)dword_1023BC8 == a2 )
+{
+*(_DWORD *)(dword_1023BF8 + 6) |= 1u;
+v2 = (void (__stdcall ***)(signed int, _DWORD))dword_1023BF8;
+}
+else if ( (struct TPinballComponent *)dword_1023BD0 == a2 )
+{
+*(_DWORD *)(dword_1023BF8 + 6) |= 2u;
+v2 = (void (__stdcall ***)(signed int, _DWORD))dword_1023C00;
+}
+else
+{
+*(_DWORD *)(dword_1023BF8 + 6) |= 4u;
+v2 = (void (__stdcall ***)(signed int, _DWORD))dword_1023C08;
+}
+(**v2)(15, 2.0);
+v3 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a2 + 8))(a2, 0);
+TPinballTable::AddScore(dword_1025040, v3);
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023C28)(37, 0.0) == 3 )
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023DDC + 20))();
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023808)(53, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C28)(16, 2.0);
+}
+else
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023E0C + 20))();
+}
+}
+}
+// 1023808: using guessed type int dword_1023808;
+// 1023BC8: using guessed type int dword_1023BC8;
+// 1023BD0: using guessed type int dword_1023BD0;
+// 1023BF8: using guessed type int dword_1023BF8;
+// 1023C00: using guessed type int dword_1023C00;
+// 1023C08: using guessed type int dword_1023C08;
+// 1023C28: using guessed type int dword_1023C28;
+// 1023DDC: using guessed type int dword_1023DDC;
+// 1023E0C: using guessed type int dword_1023E0C;
+
+//----- (0100DB68) --------------------------------------------------------
+void __stdcall RightHazardSpotTargetControl(int a1, struct TPinballComponent *a2)
+{
+void (__stdcall ***v2)(signed int, _DWORD); // ecx
+int v3; // eax
+
+if ( a1 == 63 )
+{
+if ( (struct TPinballComponent *)dword_1023BE0 == a2 )
+{
+*(_DWORD *)(dword_1023C10 + 6) |= 1u;
+v2 = (void (__stdcall ***)(signed int, _DWORD))dword_1023C10;
+}
+else if ( (struct TPinballComponent *)dword_1023BE8 == a2 )
+{
+*(_DWORD *)(dword_1023C10 + 6) |= 2u;
+v2 = (void (__stdcall ***)(signed int, _DWORD))dword_1023C18;
+}
+else
+{
+*(_DWORD *)(dword_1023C10 + 6) |= 4u;
+v2 = (void (__stdcall ***)(signed int, _DWORD))dword_1023C20;
+}
+(**v2)(15, 2.0);
+v3 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a2 + 8))(a2, 0);
+TPinballTable::AddScore(dword_1025040, v3);
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023C30)(37, 0.0) == 3 )
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023DDC + 20))();
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023810)(53, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C30)(16, 2.0);
+}
+else
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023E0C + 20))();
+}
+}
+}
+// 1023810: using guessed type int dword_1023810;
+// 1023BE0: using guessed type int dword_1023BE0;
+// 1023BE8: using guessed type int dword_1023BE8;
+// 1023C10: using guessed type int dword_1023C10;
+// 1023C18: using guessed type int dword_1023C18;
+// 1023C20: using guessed type int dword_1023C20;
+// 1023C30: using guessed type int dword_1023C30;
+// 1023DDC: using guessed type int dword_1023DDC;
+// 1023E0C: using guessed type int dword_1023E0C;
+
+//----- (0100DC3C) --------------------------------------------------------
+void __userpurge WormHoleDestinationControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+int v4; // eax
+
+if ( a2 == 63 )
+{
+if ( !light_on((struct component_tag *)&off_1023C40) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C44)(15, 3.0);
+v3 = get_rc_string(93, 0);
+TTextBox::Display(dword_1023E1C, a1, v3, 2.0);
+}
+v4 = (*(int (__stdcall **)(_DWORD))(*(_DWORD *)a3 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v4);
+AdvanceWormHoleDestination(1);
+}
+}
+// 1023C40: using guessed type char *off_1023C40;
+// 1023C44: using guessed type int dword_1023C44;
+
+//----- (0100DCB0) --------------------------------------------------------
+void __userpurge BlackHoleKickoutControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // eax
+int v4; // ST08_4
+CHAR *v5; // eax
+char Dest; // [esp+Ch] [ebp-44h]
+
+if ( a2 == 63 )
+{
+v3 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a3 + 8))(a3, 0);
+v4 = TPinballTable::AddScore(dword_1025040, v3);
+v5 = get_rc_string(80, 0);
+_sprintf(&Dest, v5, v4);
+TTextBox::Display(dword_1023E1C, a1, &Dest, 2.0);
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a3)(a3, 55, -1.0);
+}
+}
+
+//----- (0100DD33) --------------------------------------------------------
+void __stdcall FlagControl(int a1, struct TPinballComponent *a2)
+{
+int v2; // edi
+BOOL v3; // eax
+int v4; // eax
+
+if ( a1 == 62 )
+{
+AdvanceWormHoleDestination(0);
+}
+else if ( a1 == 63 )
+{
+v2 = *(_DWORD *)a2;
+v3 = light_on((struct component_tag *)&off_102393C);
+v4 = (*(int (__thiscall **)(struct TPinballComponent *, BOOL))(v2 + 8))(a2, v3);
+TPinballTable::AddScore(dword_1025040, v4);
+}
+}
+// 102393C: using guessed type char *off_102393C;
+
+//----- (0100DD7A) --------------------------------------------------------
+void __userpurge GravityWellKickoutControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+CHAR *v3; // eax
+CHAR *v4; // eax
+int v5; // eax
+int v6; // ST0C_4
+CHAR *v7; // eax
+void (__thiscall **v8)(struct TPinballComponent *, signed int, _DWORD); // edi
+char Dest; // [esp+18h] [ebp-44h]
+
+switch ( a2 )
+{
+case 63:
+v5 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a3 + 8))(a3, 0);
+v6 = TPinballTable::AddScore(dword_1025040, v5);
+v7 = get_rc_string(81, 0);
+_sprintf(&Dest, v7, v6);
+TTextBox::Display(dword_1023E1C, a1, &Dest, 2.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C70)(20, 0.0);
+v8 = *(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a3;
+*((_BYTE *)a3 + 5) = 0;
+(*(void (**)(void))(*(_DWORD *)dword_1023E14 + 20))();
+(*v8)(a3, 55, 0.0);
+break;
+case 64:
+if ( a3 )
+{
+v4 = get_rc_string(82, 0);
+_sprintf(&Dest, v4, a3);
+}
+else
+{
+v3 = get_rc_string(45, 0);
+_sprintf(&Dest, v3);
+}
+TTextBox::Display(dword_1023E1C, a1, &Dest, 2.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C70)(4, 0.0);
+*(_BYTE *)(dword_1023C68 + 5) = 1;
+break;
+case 1024:
+*(_BYTE *)(dword_1023C68 + 5) = 0;
+break;
+}
+}
+// 1023C68: using guessed type int dword_1023C68;
+// 1023C70: using guessed type int dword_1023C70;
+// 1023E14: using guessed type int dword_1023E14;
+
+//----- (0100DEA5) --------------------------------------------------------
+void __stdcall SkillShotGate1Control(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 63 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023D04)(9, 5.0);
+if ( light_on((struct component_tag *)&off_1023CB0) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CE4)(34, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CE4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CB4)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023878)(7, 5.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239B0)(7, 5.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(45, 11.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023DF4 + 20))();
+}
+}
+}
+// 1023878: using guessed type int dword_1023878;
+// 1023978: using guessed type int dword_1023978;
+// 10239B0: using guessed type int dword_10239B0;
+// 1023CB0: using guessed type char *off_1023CB0;
+// 1023CB4: using guessed type int dword_1023CB4;
+// 1023CE4: using guessed type int dword_1023CE4;
+// 1023D04: using guessed type int dword_1023D04;
+// 1023DF4: using guessed type int dword_1023DF4;
+
+//----- (0100DF6A) --------------------------------------------------------
+void __stdcall SkillShotGate2Control(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 63 )
+{
+if ( light_on((struct component_tag *)&off_1023CB0) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CBC)(19, 0.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023DF4 + 20))();
+}
+}
+}
+// 1023CB0: using guessed type char *off_1023CB0;
+// 1023CBC: using guessed type int dword_1023CBC;
+// 1023DF4: using guessed type int dword_1023DF4;
+
+//----- (0100DFAB) --------------------------------------------------------
+void __stdcall SkillShotGate3Control(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 63 )
+{
+if ( light_on((struct component_tag *)&off_1023CB0) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CC4)(19, 0.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023DF4 + 20))();
+}
+}
+}
+// 1023CB0: using guessed type char *off_1023CB0;
+// 1023CC4: using guessed type int dword_1023CC4;
+// 1023DF4: using guessed type int dword_1023DF4;
+
+//----- (0100DFEC) --------------------------------------------------------
+void __stdcall SkillShotGate4Control(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 63 )
+{
+if ( light_on((struct component_tag *)&off_1023CB0) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CCC)(19, 0.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023DF4 + 20))();
+}
+}
+}
+// 1023CB0: using guessed type char *off_1023CB0;
+// 1023CCC: using guessed type int dword_1023CCC;
+// 1023DF4: using guessed type int dword_1023DF4;
+
+//----- (0100E02D) --------------------------------------------------------
+void __stdcall SkillShotGate5Control(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 63 )
+{
+if ( light_on((struct component_tag *)&off_1023CB0) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CD4)(19, 0.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023DF4 + 20))();
+}
+}
+}
+// 1023CB0: using guessed type char *off_1023CB0;
+// 1023CD4: using guessed type int dword_1023CD4;
+// 1023DF4: using guessed type int dword_1023DF4;
+
+//----- (0100E06E) --------------------------------------------------------
+void __stdcall SkillShotGate6Control(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 63 )
+{
+if ( light_on((struct component_tag *)&off_1023CB0) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CDC)(19, 0.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023DF4 + 20))();
+}
+}
+}
+// 1023CB0: using guessed type char *off_1023CB0;
+// 1023CDC: using guessed type int dword_1023CDC;
+// 1023DF4: using guessed type int dword_1023DF4;
+
+//----- (0100E0AF) --------------------------------------------------------
+void __stdcall ShootAgainLightControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 60 )
+{
+if ( *(_DWORD *)((char *)a2 + 6) )
+{
+*(_DWORD *)((char *)a2 + 6) = 0;
+}
+else
+{
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, _DWORD))a2)(a2, 16, 5.0);
+*(_DWORD *)((char *)a2 + 6) = 1;
+}
+}
+}
+
+//----- (0100E0ED) --------------------------------------------------------
+void __stdcall EscapeChuteSinkControl(int a1, struct TPinballComponent *a2)
+{
+if ( a1 == 63 )
+(**(void (__stdcall ***)(signed int, _DWORD))a2)(56, *(float *)((char *)a2 + 82));
+}
+
+//----- (0100E111) --------------------------------------------------------
+int __usercall cheat_bump_rank@(int a1@)
+{
+void (__thiscall ***v1)(_DWORD, signed int, _DWORD); // esi
+int result; // eax
+int v3; // edi
+CHAR *v4; // ST10_4
+CHAR *v5; // eax
+char Dest; // [esp+1Ch] [ebp-44h]
+
+v1 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023CF4;
+result = (**(int (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(37, 0.0);
+v3 = result;
+if ( result < 9 )
+{
+(**v1)(v1, 41, 2.0);
+v4 = get_rc_string(word_10246EC[2 * v3], 1);
+v5 = get_rc_string(83, 0);
+_sprintf(&Dest, v5, v4);
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+result = (*(int (**)(void))(*(_DWORD *)dword_1023D1C + 20))();
+}
+return result;
+}
+// 1023CF4: using guessed type int dword_1023CF4;
+// 1023D1C: using guessed type int dword_1023D1C;
+// 10246EC: using guessed type __int16 word_10246EC[];
+
+//----- (0100E1B0) --------------------------------------------------------
+void __userpurge pbctrl_bdoor_controller(int a1@, int a2)
+{
+signed int v2; // eax
+int v3; // eax
+bool v4; // zf
+
+if ( !*(_DWORD *)(dword_1023BBC + 6) )
+{
+if ( a2 <= 77 )
+{
+if ( a2 == 77 )
+{
+v3 = dword_1025050;
+if ( dword_1025050 == 4 || dword_1025050 == 61 || dword_1025050 == 81 || dword_1025050 == 101 )
+goto LABEL_87;
+v4 = dword_1025050 == 121;
+}
+else
+{
+if ( a2 <= 68 )
+{
+if ( a2 != 68 )
+{
+if ( a2 == 32 )
+{
+if ( dword_1025050 == 26 )
+{
+dword_1025050 = 27;
+return;
+}
+goto LABEL_77;
+}
+if ( a2 != 49 )
+{
+if ( a2 != 65 )
+{
+if ( a2 != 66 )
+{
+if ( a2 == 67 )
+{
+if ( !dword_1025050 )
+{
+dword_1025050 = 1;
+return;
+}
+if ( dword_1025050 == 11 )
+{
+dword_1025050 = 12;
+return;
+}
+}
+goto LABEL_77;
+}
+v2 = dword_1025050 != 0 ? 0 : 81;
+goto LABEL_88;
+}
+v3 = dword_1025050;
+if ( dword_1025050 == 5 || dword_1025050 == 62 || dword_1025050 == 82 || dword_1025050 == 102 )
+goto LABEL_87;
+v4 = dword_1025050 == 122;
+goto LABEL_86;
+}
+v2 = dword_1025050 != 0 ? 0 : 61;
+LABEL_88:
+dword_1025050 = v2;
+return;
+}
+if ( dword_1025050 != 22 && dword_1025050 != 23 )
+goto LABEL_77;
+LABEL_58:
+++dword_1025050;
+return;
+}
+if ( a2 != 69 )
+{
+switch ( a2 )
+{
+case 71:
+v2 = dword_1025050 != 0 ? 0 : 101;
+break;
+case 72:
+v2 = dword_1025050 != 0 ? 0 : 21;
+break;
+case 73:
+v3 = dword_1025050;
+if ( dword_1025050 == 1 || dword_1025050 == 10 )
+goto LABEL_87;
+v4 = dword_1025050 == 21;
+goto LABEL_86;
+default:
+goto LABEL_77;
+}
+goto LABEL_88;
+}
+v3 = dword_1025050;
+if ( dword_1025050 == 3 || dword_1025050 == 24 || dword_1025050 == 28 )
+goto LABEL_87;
+v4 = dword_1025050 == 44;
+}
+goto LABEL_86;
+}
+if ( a2 <= 83 )
+{
+if ( a2 == 83 )
+{
+v3 = dword_1025050;
+if ( dword_1025050 == 12 || dword_1025050 == 29 )
+goto LABEL_87;
+v4 = dword_1025050 == 45;
+}
+else
+{
+if ( a2 != 78 )
+{
+if ( a2 != 79 )
+{
+if ( a2 != 81 )
+{
+if ( a2 == 82 )
+{
+if ( !dword_1025050 )
+{
+dword_1025050 = 121;
+return;
+}
+if ( dword_1025050 == 7 )
+{
+dword_1025050 = 8;
+return;
+}
+}
+goto LABEL_77;
+}
+v2 = dword_1025050 != 0 ? 0 : 41;
+goto LABEL_88;
+}
+if ( dword_1025050 != 8 && dword_1025050 != 42 )
+goto LABEL_77;
+goto LABEL_58;
+}
+v3 = dword_1025050;
+if ( dword_1025050 == 2 || dword_1025050 == 9 )
+goto LABEL_87;
+v4 = dword_1025050 == 25;
+}
+LABEL_86:
+if ( v4 )
+{
+LABEL_87:
+v2 = v3 + 1;
+goto LABEL_88;
+}
+LABEL_77:
+dword_1025050 = 0;
+return;
+}
+switch ( a2 )
+{
+case 84:
+v3 = dword_1025050;
+if ( dword_1025050 != 30 )
+{
+if ( dword_1025050 == 27 || dword_1025050 == 6 )
+goto LABEL_87;
+v4 = dword_1025050 == 43;
+goto LABEL_86;
+}
+cheat_mode = 1;
+break;
+case 85:
+if ( dword_1025050 == 41 )
+{
+dword_1025050 = 42;
+return;
+}
+goto LABEL_77;
+case 88:
+if ( dword_1025050 == 63 )
+{
+table_add_extra_ball(a1, 2.0);
+goto LABEL_76;
+}
+if ( dword_1025050 != 83 )
+{
+if ( dword_1025050 == 103 )
+{
+GravityWellKickoutControl(a1, 64, 0);
+}
+else
+{
+if ( dword_1025050 != 123 )
+goto LABEL_77;
+cheat_bump_rank(a1);
+}
+LABEL_76:
+*(_DWORD *)((char *)dword_1025040 + 62) = 1;
+goto LABEL_77;
+}
+dword_1025044 = 1;
+break;
+default:
+goto LABEL_77;
+}
+*(_DWORD *)((char *)dword_1025040 + 62) = 1;
+goto LABEL_77;
+}
+}
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1024FF8: using guessed type int cheat_mode;
+// 1025044: using guessed type int dword_1025044;
+// 1025050: using guessed type int dword_1025050;
+
+
+//----- (01011EC9) --------------------------------------------------------
+void __stdcall control_handler(int a1, struct TPinballComponent *a2)
+{
+int v2; // esi
+int v3; // edi
+
+v2 = *(_DWORD *)((char *)a2 + 18);
+v3 = 0;
+if ( v2 )
+{
+if ( a1 == 1019 && *(_DWORD *)(v2 + 4) > 0 )
+{
+do
+{
+(*(void (__thiscall **)(struct TPinballComponent *, int, _DWORD))(*(_DWORD *)a2 + 12))(
+a2,
+v3,
+*(_DWORD *)(*(_DWORD *)(v2 + 8) + 4 * v3));
+++v3;
+}
+while ( v3 < *(_DWORD *)(v2 + 4) );
+}
+(*(void (__stdcall **)(int, struct TPinballComponent *))v2)(a1, a2);
+}
+MissionControl(a1, a2);
+}
+
+//----- (01011F1A) --------------------------------------------------------
+void __stdcall HyperspaceKickOutControl(int a1, struct TPinballComponent *a2)
+{
+double v2; // st7
+int v3; // eax
+struct TPinballComponent *v4; // eax
+int v5; // eax
+CHAR *v6; // eax
+int v7; // eax
+int v8; // ST30_4
+CHAR *v9; // eax
+int v10; // eax
+int v11; // ST30_4
+CHAR *v12; // eax
+TPinballTable *v13; // eax
+_DWORD *v14; // eax
+int v15; // ecx
+int v16; // [esp+30h] [ebp-5Ch]
+int v17; // [esp+40h] [ebp-4Ch]
+signed int v18; // [esp+44h] [ebp-48h]
+float v19; // [esp+44h] [ebp-48h]
+char Dest; // [esp+48h] [ebp-44h]
+
+v18 = 0;
+if ( a1 == 63 )
+{
+v2 = 0.0;
+v17 = (**(int (__stdcall ***)(signed int, _DWORD))dword_10239A8)(37, 0.0);
+HyperspaceLightGroupControl(41, dword_10239A8);
+if ( v17 )
+{
+if ( v17 == 1 )
+{
+v8 = SpecialAddScore(*(_DWORD *)((char *)dword_1025040 + 314));
+v9 = get_rc_string(14, 0);
+_sprintf(&Dest, v9, v8);
+v2 = 2.0;
+TTextBox::Display(dword_1023E1C, (int)a2, &Dest, 2.0);
+*(_DWORD *)((char *)dword_1025040 + 314) = 20000;
+goto LABEL_13;
+}
+if ( v17 == 2 )
+{
+DrainBallBlockerControl(52, dword_1023860);
+v7 = (*(int (__thiscall **)(struct TPinballComponent *, signed int))(*(_DWORD *)a2 + 8))(a2, 2);
+v16 = TPinballTable::AddScore(dword_1025040, v7);
+v6 = get_rc_string(2, 0);
+}
+else
+{
+if ( v17 != 3 )
+{
+if ( v17 == 4 )
+{
+v2 = 0.0;
+(**(void (__stdcall ***)(_DWORD, _DWORD))dword_10239A8)(0, 0.0);
+v3 = (*(int (__thiscall **)(struct TPinballComponent *, signed int))(*(_DWORD *)a2 + 8))(a2, 4);
+v4 = (struct TPinballComponent *)TPinballTable::AddScore(dword_1025040, v3);
+GravityWellKickoutControl((int)a2, 64, v4);
+}
+LABEL_13:
+if ( light_on((struct component_tag *)&off_10239AC) )
+{
+v18 = 1;
+v11 = SpecialAddScore(*(_DWORD *)((char *)dword_1025040 + 302));
+v12 = get_rc_string(10, 0);
+_sprintf(&Dest, v12, v11);
+v2 = 2.0;
+TTextBox::Display(dword_1023E1C, (int)a2, &Dest, 2.0);
+}
+if ( light_on((struct component_tag *)&off_10239B4) )
+v18 |= 2u;
+if ( light_on((struct component_tag *)&off_10239BC) )
+{
+v18 |= 4u;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239C0)(20, 0.0);
+MultiplierLightGroupControl((int)a2, 64, dword_1023B38);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B0C)(19, 0.0);
+table_set_jackpot((int)a2);
+table_set_bonus((int)a2);
+table_set_flag_lights((int)a2);
+table_set_bonus_hold((int)a2);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238D0)(19, 0.0);
+v2 = 0.0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238D8)(19, 0.0);
+ExtraBallLightControl(19, 0);
+DrainBallBlockerControl(52, dword_1023860);
+v13 = dword_1025040;
+if ( *(_DWORD *)((char *)dword_1025040 + 346) )
+{
+table_set_multiball((int)a2);
+v13 = dword_1025040;
+}
+if ( *(_DWORD *)((char *)v13 + 314) < 100000 )
+*(_DWORD *)((char *)v13 + 314) = 100000;
+v14 = (_DWORD *)((char *)v13 + 306);
+if ( *v14 < 100000 )
+*v14 = 100000;
+GravityWellKickoutControl((int)a2, 64, 0);
+}
+if ( v18 )
+{
+if ( v18 == 1 )
+{
+v15 = dword_1023D24;
+}
+else
+{
+if ( v18 <= 1 || v18 > 3 )
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023D6C + 20))();
+v19 = v2;
+(*(void (**)(void))(*(_DWORD *)dword_1023D74 + 20))();
+(*(void (**)(void))(*(_DWORD *)dword_1023D7C + 20))();
+LABEL_42:
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239B0)(7, 5.0);
+(**(void (__thiscall ***)(struct TPinballComponent *, signed int, float))a2)(
+a2,
+55,
+COERCE_FLOAT(LODWORD(v19)));
+return;
+}
+v15 = dword_1023D64;
+}
+}
+else
+{
+switch ( v17 )
+{
+case 1:
+v15 = dword_1023D8C;
+break;
+case 2:
+v15 = dword_1023D94;
+break;
+case 3:
+v15 = dword_1023D9C;
+break;
+case 4:
+v15 = dword_1023DA4;
+break;
+default:
+v15 = dword_1023D84;
+break;
+}
+}
+(*(void (**)(void))(*(_DWORD *)v15 + 20))();
+v19 = v2;
+goto LABEL_42;
+}
+ExtraBallLightControl(19, 0);
+v5 = (*(int (__thiscall **)(struct TPinballComponent *, signed int))(*(_DWORD *)a2 + 8))(a2, 3);
+v16 = TPinballTable::AddScore(dword_1025040, v5);
+v6 = get_rc_string(8, 0);
+}
+}
+else
+{
+v10 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a2 + 8))(a2, 0);
+v16 = TPinballTable::AddScore(dword_1025040, v10);
+v6 = get_rc_string(12, 0);
+}
+_sprintf(&Dest, v6, v16);
+v2 = 2.0;
+TTextBox::Display(dword_1023E1C, (int)a2, &Dest, 2.0);
+goto LABEL_13;
+}
+}
+// 10238D0: using guessed type int dword_10238D0;
+// 10238D8: using guessed type int dword_10238D8;
+// 10239AC: using guessed type char *off_10239AC;
+// 10239B0: using guessed type int dword_10239B0;
+// 10239B4: using guessed type char *off_10239B4;
+// 10239BC: using guessed type char *off_10239BC;
+// 10239C0: using guessed type int dword_10239C0;
+// 1023D24: using guessed type int dword_1023D24;
+// 1023D64: using guessed type int dword_1023D64;
+// 1023D6C: using guessed type int dword_1023D6C;
+// 1023D74: using guessed type int dword_1023D74;
+// 1023D7C: using guessed type int dword_1023D7C;
+// 1023D84: using guessed type int dword_1023D84;
+// 1023D8C: using guessed type int dword_1023D8C;
+// 1023D94: using guessed type int dword_1023D94;
+// 1023D9C: using guessed type int dword_1023D9C;
+// 1023DA4: using guessed type int dword_1023DA4;
+
+//----- (01012285) --------------------------------------------------------
+void __userpurge PlungerControl(int a1@, int a2, struct TPinballComponent *a3)
+{
+int (__stdcall **v3)(signed int, _DWORD); // eax
+void (__thiscall ***v4)(_DWORD, signed int, _DWORD); // esi
+void (__thiscall ***v5)(_DWORD, signed int, _DWORD); // esi
+
+if ( a2 == 1015 )
+{
+MissionControl(67, 0);
+}
+else if ( a2 == 1016 )
+{
+v3 = *(int (__stdcall ***)(signed int, _DWORD))dword_1023CF4;
+dword_1025044 = 0;
+if ( !(*v3)(37, 0.0) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(32, 0.0);
+if ( !light_on((struct component_tag *)&off_1023D00) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CE4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CB4)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CE4)(26, 0.25);
+v4 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A8C;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A8C)(20, 0.0);
+(**v4)(v4, 32, 0.2);
+(**v4)(v4, 26, 0.2);
+v5 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A94;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A94)(20, 0.0);
+(**v5)(v5, 32, 0.2);
+(**v5)(v5, 26, 0.2);
+*(_DWORD *)((char *)dword_1025040 + 302) = 25000;
+MultiplierLightGroupControl(a1, 65, dword_1023B38);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023D04)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023808)(53, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023810)(53, 0.0);
+}
+*(_DWORD *)(dword_1023D04 + 6) = 0;
+}
+}
+// 1023808: using guessed type int dword_1023808;
+// 1023810: using guessed type int dword_1023810;
+// 1023978: using guessed type int dword_1023978;
+// 1023A8C: using guessed type int dword_1023A8C;
+// 1023A94: using guessed type int dword_1023A94;
+// 1023CB4: using guessed type int dword_1023CB4;
+// 1023CE4: using guessed type int dword_1023CE4;
+// 1023CF4: using guessed type int dword_1023CF4;
+// 1023D00: using guessed type char *off_1023D00;
+// 1023D04: using guessed type int dword_1023D04;
+// 1025044: using guessed type int dword_1025044;
+
+//----- (0101240D) --------------------------------------------------------
+void __userpurge MedalTargetControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5)
+{
+int v5; // eax
+char *v6; // eax
+int v7; // eax
+char *v8; // eax
+int v9; // eax
+int v10; // eax
+float v11; // [esp+24h] [ebp-4h]
+
+if ( a4 == 63 && !*(_DWORD *)((char *)a5 + 6) )
+{
+*(_DWORD *)((char *)a5 + 6) = 1;
+if ( *(_DWORD *)(dword_1023ADC + 6) + *(_DWORD *)(dword_1023AE4 + 6) + *(_DWORD *)(dword_1023AEC + 6) == 3 )
+{
+MedalLightGroupControl(41, dword_1023B0C);
+v5 = (**(int (__stdcall ***)(signed int, _DWORD, int, int))dword_1023B0C)(37, 0.0, a2, a3) - 1;
+if ( v5 )
+{
+if ( v5 != 1 )
+{
+v6 = get_rc_string(55, 0);
+TTextBox::Display(dword_1023E1C, a1, v6, 2.0);
+table_add_extra_ball(a1, 4.0);
+LABEL_10:
+*(_DWORD *)(dword_1023ADC + 6) = 0;
+(**(void (__cdecl ***)(signed int, _DWORD))dword_1023ADC)(50, 0.0);
+*(_DWORD *)(dword_1023AE4 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AE4)(50, 0.0);
+*(_DWORD *)(dword_1023AEC + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AEC)(50, 0.0);
+return;
+}
+v7 = (*(int (__thiscall **)(struct TPinballComponent *, signed int))(*(_DWORD *)a5 + 8))(a5, 2);
+TPinballTable::AddScore(dword_1025040, v7);
+v11 = 2.0;
+v8 = get_rc_string(54, 0);
+}
+else
+{
+v9 = (*(int (__thiscall **)(struct TPinballComponent *, signed int))(*(_DWORD *)a5 + 8))(a5, 1);
+TPinballTable::AddScore(dword_1025040, v9);
+v11 = 2.0;
+v8 = get_rc_string(53, 0);
+}
+TTextBox::Display(dword_1023E1C, a1, v8, v11);
+goto LABEL_10;
+}
+v10 = (*(int (__thiscall **)(struct TPinballComponent *, _DWORD))(*(_DWORD *)a5 + 8))(a5, 0);
+TPinballTable::AddScore(dword_1025040, v10);
+}
+}
+// 101240D: could not find valid save-restore pair for edi
+// 101240D: could not find valid save-restore pair for esi
+// 1023ADC: using guessed type int dword_1023ADC;
+// 1023AE4: using guessed type int dword_1023AE4;
+// 1023AEC: using guessed type int dword_1023AEC;
+
+//----- (01012570) --------------------------------------------------------
+void __userpurge MultiplierTargetControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5)
+{
+int v5; // eax
+int v6; // eax
+int (__stdcall **v7)(signed int, _DWORD); // eax
+int v8; // eax
+int v9; // eax
+char *v10; // eax
+void (__stdcall **v11)(signed int); // eax
+int v12; // eax
+float vars0; // [esp+28h] [ebp+0h]
+
+if ( a4 == 63 && !*(_DWORD *)((char *)a5 + 6) )
+{
+*(_DWORD *)((char *)a5 + 6) = 1;
+v5 = *(_DWORD *)a5;
+if ( *(_DWORD *)(dword_1023B20 + 6) + *(_DWORD *)(dword_1023B28 + 6) + *(_DWORD *)(dword_1023B30 + 6) == 3 )
+{
+v6 = (*(int (__stdcall **)(signed int, int, int, _DWORD))(v5 + 8))(1, a3, a2, LODWORD(vars0));
+TPinballTable::AddScore(dword_1025040, v6);
+MultiplierLightGroupControl(a1, 41, dword_1023B38);
+v7 = *(int (__stdcall ***)(signed int, _DWORD))dword_1023B38;
+vars0 = 0.0;
+v8 = (*v7)(37, 0.0) - 1;
+vars0 = 2.0;
+if ( v8 )
+{
+v9 = v8 - 1;
+if ( v9 )
+{
+if ( v9 == 1 )
+{
+*(_DWORD *)((char *)dword_1025040 + 294) = 3;
+v10 = get_rc_string(58, 0);
+}
+else
+{
+*(_DWORD *)((char *)dword_1025040 + 294) = 4;
+v10 = get_rc_string(59, 0);
+}
+}
+else
+{
+*(_DWORD *)((char *)dword_1025040 + 294) = 2;
+v10 = get_rc_string(57, 0);
+}
+}
+else
+{
+*(_DWORD *)((char *)dword_1025040 + 294) = 1;
+v10 = get_rc_string(56, 0);
+}
+TTextBox::Display(dword_1023E1C, a1, v10, vars0);
+*(_DWORD *)(dword_1023B20 + 6) = 0;
+v11 = *(void (__stdcall ***)(signed int))dword_1023B20;
+vars0 = 0.0;
+(*v11)(50);
+*(_DWORD *)(dword_1023B28 + 6) = 0;
+(**(void (__cdecl ***)(signed int, _DWORD))dword_1023B28)(50, 0.0);
+*(_DWORD *)(dword_1023B30 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B30)(50, 0.0);
+}
+else
+{
+v12 = (*(int (__stdcall **)(_DWORD))(v5 + 8))(0);
+TPinballTable::AddScore(dword_1025040, v12);
+}
+}
+}
+// 1012570: could not find valid save-restore pair for edi
+// 1012570: could not find valid save-restore pair for esi
+// 1023B20: using guessed type int dword_1023B20;
+// 1023B28: using guessed type int dword_1023B28;
+// 1023B30: using guessed type int dword_1023B30;
+
+//----- (010126BA) --------------------------------------------------------
+void __stdcall BallDrainControl(int a1, struct TPinballComponent *a2)
+{
+TPinballTable *v2; // esi
+char *v3; // eax
+char *v4; // eax
+int v5; // ST1E8_4
+CHAR *v6; // eax
+int v7; // ecx
+int v8; // eax
+int v9; // eax
+char *v10; // eax
+char *v11; // eax
+int v12; // [esp+1ECh] [ebp-50h]
+int v13; // [esp+1F0h] [ebp-4Ch]
+char Dest; // [esp+1F8h] [ebp-44h]
+
+if ( a1 == 60 )
+{
+if ( *(_DWORD *)(dword_1023D0C + 6) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1025040)(1022, 0.0);
+if ( pb_chk_highscore() )
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023DFC + 20))();
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)dword_1025040 + 266))(16, 3.0);
+v11 = get_rc_string(177, 0);
+TTextBox::Display(dword_1023E24, 0, v11, -1.0);
+}
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A84)(1016, 0.0);
+}
+}
+else if ( a1 == 63 )
+{
+if ( dword_1025044 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C7C)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239FC)(56, 0.0);
+}
+else
+{
+v2 = dword_1025040;
+if ( *(_DWORD *)((char *)dword_1025040 + 370) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023D04)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023D0C)(20, 0.0);
+v2 = dword_1025040;
+}
+if ( light_on((struct component_tag *)&off_1023D00) )
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023DEC + 20))();
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023D04)(19, 0.0);
+v3 = get_rc_string(96, 0);
+TTextBox::Display(dword_1023E1C, 0, v3, -1.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023DE4 + 20))();
+}
+else if ( light_on((struct component_tag *)&off_1023D08) )
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023DEC + 20))();
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023D0C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023D04)(19, 0.0);
+v4 = get_rc_string(95, 0);
+TTextBox::Display(dword_1023E1C, 0, v4, 2.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023DE4 + 20))();
+--*(_DWORD *)((char *)dword_1025040 + 350);
+}
+else if ( *(_DWORD *)((char *)v2 + 338) )
+{
+(*(void (**)(void))(*(_DWORD *)dword_1023DEC + 20))();
+--*(_DWORD *)((char *)dword_1025040 + 338);
+}
+else
+{
+if ( !*(_DWORD *)((char *)v2 + 370) )
+{
+v5 = SpecialAddScore(*(_DWORD *)((char *)v2 + 306));
+v6 = get_rc_string(94, 0);
+_sprintf(&Dest, v6, v5);
+TTextBox::Display(dword_1023E1C, 0, &Dest, 2.0);
+v2 = dword_1025040;
+}
+v7 = *(_DWORD *)((char *)v2 + 334);
+if ( v7 )
+{
+*(_DWORD *)((char *)v2 + 334) = v7 - 1;
+(*(void (**)(void))(*(_DWORD *)dword_1023DE4 + 20))();
+v8 = *(_DWORD *)((char *)dword_1025040 + 218);
+if ( v8 )
+{
+v9 = v8 - 1;
+if ( v9 )
+{
+if ( v9 == 1 )
+v10 = get_rc_string(99, 0);
+else
+v10 = get_rc_string(100, 0);
+}
+else
+{
+v10 = get_rc_string(98, 0);
+}
+}
+else
+{
+v10 = get_rc_string(97, 0);
+}
+TTextBox::Display(dword_1023E1C, 0, v10, -1.0);
+}
+else
+{
+TPinballTable::ChangeBallCount(v2, 0, *(_DWORD *)((char *)v2 + 326) - 1);
+if ( *(_DWORD *)((char *)dword_1025040 + 218) + 1 != *(_DWORD *)((char *)dword_1025040 + 214)
+|| *(_DWORD *)((char *)dword_1025040 + 326) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1025040)(1021, 0.0);
+*(_DWORD *)(dword_1023D0C + 6) = 0;
+}
+else
+{
+*(_DWORD *)(dword_1023D0C + 6) = 1;
+}
+(*(void (**)(void))(*(_DWORD *)dword_1023DEC + 20))();
+}
+(**(void (__stdcall ***)(signed int, _DWORD, int, int))dword_1023724)(20, 0.0, v12, v13);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023790)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023818)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023820)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023868)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023878)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023880)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023888)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238AC)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238B4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238D0)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238D8)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238F0)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023940)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239A8)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239B0)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239B8)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239C0)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239D0)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A1C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A3C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A8C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A94)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ABC)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AC4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AB4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B0C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B38)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B78)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023BB4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C28)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C30)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C44)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CE4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CEC)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023BBC)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023828)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023830)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023978)(1024, 0.0);
+GravityWellKickoutControl(0, 1024, 0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C70)(20, 0.0);
+*(_DWORD *)(dword_1023A24 + 6) = 0;
+*(_DWORD *)(dword_1023B9C + 6) = 0;
+*(_DWORD *)(dword_1023BA4 + 6) = 0;
+*(_DWORD *)(dword_1023BAC + 6) = 0;
+*(_DWORD *)(dword_1023BB4 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CFC)(34, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(34, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023704)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023770)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023808)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023810)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023860)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A9C)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AA4)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AAC)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ADC)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AE4)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AEC)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B20)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B28)(1024, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B30)(1024, 0.0);
+if ( *(_DWORD *)(dword_1023D0C + 6) )
+*(_DWORD *)(dword_1023BBC + 6) = 32;
+else
+*(_DWORD *)(dword_1023BBC + 6) = 0;
+MissionControl(66, 0);
+(**(void (__cdecl ***)(signed int, _DWORD))dword_1025040)(1012, 0.0);
+if ( light_on((struct component_tag *)&off_1023AC8) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ACC)(20, 0.0);
+else
+*(_DWORD *)((char *)dword_1025040 + 306) = 25000;
+}
+}
+}
+}
+// 1023704: using guessed type int dword_1023704;
+// 1023724: using guessed type int dword_1023724;
+// 1023770: using guessed type int dword_1023770;
+// 1023790: using guessed type int dword_1023790;
+// 1023808: using guessed type int dword_1023808;
+// 1023810: using guessed type int dword_1023810;
+// 1023818: using guessed type int dword_1023818;
+// 1023820: using guessed type int dword_1023820;
+// 1023828: using guessed type int dword_1023828;
+// 1023830: using guessed type int dword_1023830;
+// 1023868: using guessed type int dword_1023868;
+// 1023878: using guessed type int dword_1023878;
+// 1023880: using guessed type int dword_1023880;
+// 1023888: using guessed type int dword_1023888;
+// 10238AC: using guessed type int dword_10238AC;
+// 10238B4: using guessed type int dword_10238B4;
+// 10238D0: using guessed type int dword_10238D0;
+// 10238D8: using guessed type int dword_10238D8;
+// 10238F0: using guessed type int dword_10238F0;
+// 1023940: using guessed type int dword_1023940;
+// 1023978: using guessed type int dword_1023978;
+// 10239B0: using guessed type int dword_10239B0;
+// 10239B8: using guessed type int dword_10239B8;
+// 10239C0: using guessed type int dword_10239C0;
+// 10239D0: using guessed type int dword_10239D0;
+// 10239FC: using guessed type int dword_10239FC;
+// 1023A1C: using guessed type int dword_1023A1C;
+// 1023A24: using guessed type int dword_1023A24;
+// 1023A3C: using guessed type int dword_1023A3C;
+// 1023A84: using guessed type int dword_1023A84;
+// 1023A8C: using guessed type int dword_1023A8C;
+// 1023A94: using guessed type int dword_1023A94;
+// 1023A9C: using guessed type int dword_1023A9C;
+// 1023AA4: using guessed type int dword_1023AA4;
+// 1023AAC: using guessed type int dword_1023AAC;
+// 1023AB4: using guessed type int dword_1023AB4;
+// 1023ABC: using guessed type int dword_1023ABC;
+// 1023AC4: using guessed type int dword_1023AC4;
+// 1023AC8: using guessed type char *off_1023AC8;
+// 1023ACC: using guessed type int dword_1023ACC;
+// 1023ADC: using guessed type int dword_1023ADC;
+// 1023AE4: using guessed type int dword_1023AE4;
+// 1023AEC: using guessed type int dword_1023AEC;
+// 1023B20: using guessed type int dword_1023B20;
+// 1023B28: using guessed type int dword_1023B28;
+// 1023B30: using guessed type int dword_1023B30;
+// 1023B78: using guessed type int dword_1023B78;
+// 1023B9C: using guessed type int dword_1023B9C;
+// 1023BA4: using guessed type int dword_1023BA4;
+// 1023BAC: using guessed type int dword_1023BAC;
+// 1023BB4: using guessed type int dword_1023BB4;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023C28: using guessed type int dword_1023C28;
+// 1023C30: using guessed type int dword_1023C30;
+// 1023C44: using guessed type int dword_1023C44;
+// 1023C70: using guessed type int dword_1023C70;
+// 1023C7C: using guessed type int dword_1023C7C;
+// 1023CE4: using guessed type int dword_1023CE4;
+// 1023CEC: using guessed type int dword_1023CEC;
+// 1023CF4: using guessed type int dword_1023CF4;
+// 1023CFC: using guessed type int dword_1023CFC;
+// 1023D00: using guessed type char *off_1023D00;
+// 1023D04: using guessed type int dword_1023D04;
+// 1023D08: using guessed type char *off_1023D08;
+// 1023D0C: using guessed type int dword_1023D0C;
+// 1023DE4: using guessed type int dword_1023DE4;
+// 1023DEC: using guessed type int dword_1023DEC;
+// 1023DFC: using guessed type int dword_1023DFC;
+// 1025044: using guessed type int dword_1025044;
diff --git a/exceptionhandling.cpp b/exceptionhandling.cpp
new file mode 100644
index 0000000..bd687bd
--- /dev/null
+++ b/exceptionhandling.cpp
@@ -0,0 +1,92 @@
+#include "pinball.h"
+
+//----- (0101CD2B) --------------------------------------------------------
+int __security_init_cookie()
+{
+signed int v0; // eax
+DWORD v1; // esi
+DWORD v2; // esi
+DWORD v3; // esi
+int result; // eax
+LARGE_INTEGER PerformanceCount; // [esp+0h] [ebp-10h]
+struct _FILETIME SystemTimeAsFileTime; // [esp+8h] [ebp-8h]
+
+v0 = __security_cookie;
+if ( !__security_cookie || __security_cookie == 47936 )
+{
+GetSystemTimeAsFileTime(&SystemTimeAsFileTime);
+v1 = SystemTimeAsFileTime.dwLowDateTime ^ SystemTimeAsFileTime.dwHighDateTime;
+v2 = GetCurrentProcessId() ^ v1;
+v3 = GetCurrentThreadId() ^ v2;
+LOWORD(v3) = GetTickCount() ^ v3;
+QueryPerformanceCounter(&PerformanceCount);
+v0 = (unsigned __int16)(v3 ^ LOWORD(PerformanceCount.LowPart) ^ WORD2(PerformanceCount.QuadPart));
+if ( !((unsigned __int16)v3 ^ (unsigned __int16)(LOWORD(PerformanceCount.LowPart) ^ WORD2(PerformanceCount.QuadPart))) )
+v0 = 47936;
+__security_cookie = v0;
+}
+result = ~v0;
+__security_cookie_complement = result;
+return result;
+}
+// 1024774: using guessed type int __security_cookie_complement;
+
+//----- (0101CDB9) --------------------------------------------------------
+BOOL __usercall __noreturn __report_gsfailure@(int a1@, int a2@, int a3@, int a4@, int a5@, int a6@)
+{
+unsigned int v6; // et0
+HANDLE v7; // eax
+int v9; // [esp+4h] [ebp-330h]
+int v10; // [esp+10h] [ebp-324h]
+int v11; // [esp+58h] [ebp-2DCh]
+int v12; // [esp+5Ch] [ebp-2D8h]
+__int16 v13; // [esp+E8h] [ebp-24Ch]
+__int16 v14; // [esp+ECh] [ebp-248h]
+__int16 v15; // [esp+F0h] [ebp-244h]
+__int16 v16; // [esp+F4h] [ebp-240h]
+int v17; // [esp+F8h] [ebp-23Ch]
+int v18; // [esp+FCh] [ebp-238h]
+int v19; // [esp+100h] [ebp-234h]
+int v20; // [esp+104h] [ebp-230h]
+int v21; // [esp+108h] [ebp-22Ch]
+int v22; // [esp+10Ch] [ebp-228h]
+int v23; // [esp+110h] [ebp-224h]
+int v24; // [esp+114h] [ebp-220h]
+__int16 v25; // [esp+118h] [ebp-21Ch]
+unsigned int v26; // [esp+11Ch] [ebp-218h]
+int *v27; // [esp+120h] [ebp-214h]
+__int16 v28; // [esp+124h] [ebp-210h]
+struct _EXCEPTION_POINTERS ExceptionInfo; // [esp+32Ch] [ebp-8h]
+int savedregs; // [esp+334h] [ebp+0h]
+int retaddr; // [esp+338h] [ebp+4h]
+
+v22 = a1;
+v21 = a3;
+v20 = a2;
+v19 = a4;
+v18 = a6;
+v17 = a5;
+v28 = __SS__;
+v25 = __CS__;
+v16 = __DS__;
+v15 = __ES__;
+v14 = __FS__;
+v13 = __GS__;
+v6 = __readeflags();
+v26 = v6;
+v12 = 65537;
+v24 = retaddr;
+v27 = &retaddr;
+v23 = savedregs;
+memset(&v9, 0, 0x50u);
+v9 = -1073740791;
+v10 = retaddr;
+ExceptionInfo.ExceptionRecord = (PEXCEPTION_RECORD)&v9;
+ExceptionInfo.ContextRecord = (PCONTEXT)&v12;
+v11 = __security_cookie_complement;
+SetUnhandledExceptionFilter(0);
+UnhandledExceptionFilter(&ExceptionInfo);
+v7 = GetCurrentProcess();
+return TerminateProcess(v7, 0x502u);
+}
+// 1024774: using guessed type int __security_cookie_complement;
diff --git a/geometry/edges.cpp b/geometry/edges.cpp
new file mode 100644
index 0000000..d07c401
--- /dev/null
+++ b/geometry/edges.cpp
@@ -0,0 +1,336 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+//----- (0100B9C7) --------------------------------------------------------
+void __stdcall edges_insert_circle(struct circle_type *a1, struct TEdgeSegment *a2, struct field_effect_type *a3)
+{
+ struct circle_type *v3; // ebx
+ long double v4; // st7
+ int v5; // esi
+ int v6; // edi
+ float *v7; // esi
+ int v8; // eax
+ int v9; // eax
+ double v10; // st7
+ double v11; // st7
+ float v12; // ST0C_4
+ double v13; // st7
+ float v14; // ST0C_4
+ double v15; // st7
+ float v16; // ST0C_4
+ double v17; // st7
+ double v18; // st7
+ float v19; // [esp+10h] [ebp-70h]
+ float v20; // [esp+14h] [ebp-6Ch]
+ int v21; // [esp+18h] [ebp-68h]
+ float v22; // [esp+1Ch] [ebp-64h]
+ float v23; // [esp+20h] [ebp-60h]
+ int v24; // [esp+28h] [ebp-58h]
+ float v25; // [esp+3Ch] [ebp-44h]
+ float v26; // [esp+40h] [ebp-40h]
+ int v27; // [esp+44h] [ebp-3Ch]
+ float v28; // [esp+48h] [ebp-38h]
+ float v29; // [esp+4Ch] [ebp-34h]
+ int v30; // [esp+50h] [ebp-30h]
+ float v31; // [esp+54h] [ebp-2Ch]
+ float v32; // [esp+58h] [ebp-28h]
+ float v33; // [esp+5Ch] [ebp-24h]
+ float v34; // [esp+60h] [ebp-20h]
+ float v35; // [esp+64h] [ebp-1Ch]
+ float v36; // [esp+68h] [ebp-18h]
+ struct circle_type *v37; // [esp+6Ch] [ebp-14h]
+ int v38; // [esp+70h] [ebp-10h]
+ int v39; // [esp+74h] [ebp-Ch]
+ float v40; // [esp+78h] [ebp-8h]
+ int v41; // [esp+7Ch] [ebp-4h]
+ struct circle_type *v42; // [esp+88h] [ebp+8h]
+ struct circle_type *v43; // [esp+88h] [ebp+8h]
+
+ v3 = a1;
+ v4 = sqrt(*((float *)a1 + 3)) + *(float *)edge_manager * 0.001;
+ v40 = v4 * v4;
+ v35 = *(float *)a1 - v4;
+ v33 = *((float *)a1 + 1) - v4;
+ v36 = v4 + *(float *)a1;
+ v34 = v4 + *((float *)a1 + 1);
+ v5 = TEdgeManager::box_x(edge_manager, v35);
+ v6 = TEdgeManager::box_y(edge_manager, v33);
+ v38 = TEdgeManager::box_x(edge_manager, v36);
+ v39 = TEdgeManager::box_y(edge_manager, v34);
+ if ( v5 - 1 <= 0 )
+ v42 = 0;
+ else
+ v42 = (struct circle_type *)(v5 - 1);
+ if ( v6 - 1 <= 0 )
+ v37 = 0;
+ else
+ v37 = (struct circle_type *)(v6 - 1);
+ v7 = (float *)edge_manager;
+ v38 = TEdgeManager::increment_box_x(edge_manager, v38);
+ v39 = TEdgeManager::increment_box_y((TEdgeManager *)v7, v39);
+ v28 = (double)(signed int)v42 * *v7 + v7[6];
+ v29 = (double)(signed int)v37 * v7[1] + v7[7];
+ v31 = v29;
+ v8 = (int)v42;
+ v41 = (int)v42;
+ LABEL_38:
+ if ( v8 <= v38 )
+ {
+ v9 = (int)v37;
+ v43 = v37;
+ while ( 1 )
+ {
+ if ( v9 > v39 )
+ {
+ v18 = v28 + *v7;
+ ++v41;
+ v29 = v31;
+ v8 = v41;
+ v28 = v18;
+ goto LABEL_38;
+ }
+ if ( v36 >= (double)v28 )
+ {
+ v32 = v28 + *v7;
+ if ( v35 <= (double)v32 && v34 >= (double)v29 )
+ {
+ v10 = v29 + v7[1];
+ if ( v33 <= v10 )
+ {
+ if ( *(float *)v3 > (double)v32
+ || *(float *)v3 < (double)v28
+ || v10 < *((float *)v3 + 1)
+ || *((float *)v3 + 1) < (double)v29 )
+ {
+ v25 = v28;
+ v26 = v29;
+ v27 = v30;
+ v11 = Distance_Squared(v28, v29, v30, *(float *)v3, *((float *)v3 + 1), *((_DWORD *)v3 + 2));
+ if ( v11 > v40 )
+ {
+ v12 = *(float *)v3;
+ v25 = v25 + *(float *)edge_manager;
+ v13 = Distance_Squared(v25, v26, v27, v12, *((float *)v3 + 1), *((_DWORD *)v3 + 2));
+ if ( v13 > v40 )
+ {
+ v14 = *(float *)v3;
+ v26 = v26 + *((float *)edge_manager + 1);
+ v15 = Distance_Squared(v25, v26, v27, v14, *((float *)v3 + 1), *((_DWORD *)v3 + 2));
+ if ( v15 > v40 )
+ {
+ v16 = *(float *)v3;
+ v25 = v25 - *(float *)edge_manager;
+ v17 = Distance_Squared(v25, v26, v27, v16, *((float *)v3 + 1), *((_DWORD *)v3 + 2));
+ if ( v17 > v40 )
+ {
+ v19 = v28;
+ v20 = v29;
+ v21 = v30;
+ v22 = 1.0;
+ v23 = 0.0;
+ v24 = *(_DWORD *)edge_manager;
+ if ( ray_intersect_circle(&v19, (float *)v3) >= 1000000000.0 )
+ {
+ v22 = -1.0;
+ v19 = v19 + *(float *)edge_manager;
+ if ( ray_intersect_circle(&v19, (float *)v3) >= 1000000000.0 )
+ {
+ v22 = 0.0;
+ v23 = 1.0;
+ v24 = *((_DWORD *)edge_manager + 1);
+ if ( ray_intersect_circle(&v19, (float *)v3) >= 1000000000.0 )
+ {
+ v23 = -1.0;
+ v20 = v20 + *((float *)edge_manager + 1);
+ if ( ray_intersect_circle(&v19, (float *)v3) >= 1000000000.0 )
+ {
+ v23 = 0.0;
+ v22 = -1.0;
+ v24 = *(_DWORD *)edge_manager;
+ if ( ray_intersect_circle(&v19, (float *)v3) >= 1000000000.0 )
+ {
+ v22 = 1.0;
+ v19 = v19 - *(float *)edge_manager;
+ if ( ray_intersect_circle(&v19, (float *)v3) >= 1000000000.0 )
+ {
+ v22 = 0.0;
+ v23 = -1.0;
+ v24 = *((_DWORD *)edge_manager + 1);
+ if ( ray_intersect_circle(&v19, (float *)v3) >= 1000000000.0 )
+ {
+ v23 = 1.0;
+ v20 = v20 - *((float *)edge_manager + 1);
+ if ( ray_intersect_circle(&v19, (float *)v3) >= 1000000000.0 )
+ goto LABEL_34;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ v7 = (float *)edge_manager;
+ }
+ if ( a2 )
+ {
+ TEdgeManager::add_edge_to_box((TEdgeManager *)v7, v41, (int)v43, a2);
+ v7 = (float *)edge_manager;
+ }
+ if ( a3 )
+ {
+ TEdgeManager::add_field_to_box((TEdgeManager *)v7, v41, (int)v43, a3);
+ LABEL_34:
+ v7 = (float *)edge_manager;
+ goto LABEL_35;
+ }
+ }
+ }
+ }
+ LABEL_35:
+ v43 = (struct circle_type *)((char *)v43 + 1);
+ v9 = (int)v43;
+ v29 = v29 + v7[1];
+ }
+ }
+}
+
+//----- (0100BE21) --------------------------------------------------------
+void __stdcall edges_insert_square(float a1, float a2, float a3, float a4, struct TEdgeSegment *a5, struct field_effect_type *a6)
+{
+ double v6; // st7
+ double v7; // st7
+ int v8; // eax
+ int v9; // edi
+ signed int v10; // ST28_4
+ int v11; // ebx
+ int v12; // eax
+ float *v13; // ecx
+ int v14; // esi
+ float v15; // [esp+10h] [ebp-18h]
+ float v16; // [esp+14h] [ebp-14h]
+ int v17; // [esp+1Ch] [ebp-Ch]
+ float v18; // [esp+20h] [ebp-8h]
+ int v19; // [esp+24h] [ebp-4h]
+ float v20; // [esp+30h] [ebp+8h]
+ float v21; // [esp+34h] [ebp+Ch]
+ float v22; // [esp+38h] [ebp+10h]
+ float v23; // [esp+3Ch] [ebp+14h]
+
+ v6 = (double)(signed int)(signed __int64)(*(float *)edge_manager * 0.001);
+ v21 = a2 - v6;
+ v23 = v6 + a4;
+ v7 = (double)(signed int)(signed __int64)(*((float *)edge_manager + 1) * 0.001);
+ v20 = a1 - v7;
+ v22 = v7 + a3;
+ v8 = TEdgeManager::box_x(edge_manager, v21);
+ v9 = v8;
+ v10 = v8;
+ v19 = TEdgeManager::box_y(edge_manager, v20);
+ v11 = TEdgeManager::box_x(edge_manager, v23);
+ v12 = TEdgeManager::box_y(edge_manager, v22);
+ v13 = (float *)edge_manager;
+ v17 = v12;
+ v15 = (double)v10 * *(float *)edge_manager + *((float *)edge_manager + 6);
+ v16 = (double)v19 * *((float *)edge_manager + 1) + *((float *)edge_manager + 7);
+ v18 = v16;
+ while ( v9 <= v11 )
+ {
+ v14 = v19;
+ if ( v19 <= v12 )
+ {
+ do
+ {
+ if ( v23 >= (double)v15 && v15 + *v13 >= v21 && v22 >= (double)v16 && v16 + v13[1] >= v20 )
+ {
+ if ( a5 )
+ {
+ TEdgeManager::add_edge_to_box((TEdgeManager *)v13, v9, v14, a5);
+ v13 = (float *)edge_manager;
+ }
+ if ( a6 )
+ {
+ TEdgeManager::add_field_to_box((TEdgeManager *)v13, v9, v14, a6);
+ v13 = (float *)edge_manager;
+ }
+ }
+ v12 = v17;
+ ++v14;
+ v16 = v16 + v13[1];
+ }
+ while ( v14 <= v17 );
+ }
+ ++v9;
+ v16 = v18;
+ v15 = v15 + *v13;
+ }
+}
+
+//----- (01016B27) --------------------------------------------------------
+void __stdcall find_closest_edge(struct ramp_plane_type *a1, int a2, struct wall_point_type *a3, struct vector_type **a4, struct vector_type **a5)
+{
+int v5; // ecx
+char *v6; // esi
+struct vector_type *v7; // ebx
+long double v8; // st7
+struct vector_type *v9; // edi
+long double v10; // st7
+long double v11; // st7
+int v12; // [esp+0h] [ebp-1Ch]
+int v13; // [esp+4h] [ebp-18h]
+int v14; // [esp+Ch] [ebp-10h]
+int v15; // [esp+10h] [ebp-Ch]
+float v16; // [esp+18h] [ebp-4h]
+float v17; // [esp+28h] [ebp+Ch]
+float v18; // [esp+28h] [ebp+Ch]
+float v19; // [esp+28h] [ebp+Ch]
+struct wall_point_type *v20; // [esp+2Ch] [ebp+10h]
+
+v14 = *(_DWORD *)a3;
+v15 = *((_DWORD *)a3 + 1);
+v5 = *((_DWORD *)a3 + 2);
+v13 = *((_DWORD *)a3 + 3);
+v16 = 1000000000.0;
+v12 = v5;
+if ( a2 > 0 )
+{
+v6 = (char *)a1 + 20;
+v20 = (struct wall_point_type *)a2;
+do
+{
+v7 = (struct vector_type *)(v6 - 8);
+v17 = Distance((struct vector_type *)&v14, (struct vector_type *)(v6 - 8));
+v8 = Distance((struct vector_type *)&v12, (struct vector_type *)v6) + v17;
+if ( v8 < v16 )
+{
+v16 = v8;
+*a4 = v7;
+*a5 = (struct vector_type *)v6;
+}
+v9 = (struct vector_type *)(v6 + 8);
+v18 = Distance((struct vector_type *)&v12, (struct vector_type *)(v6 + 8));
+v10 = Distance((struct vector_type *)&v14, (struct vector_type *)v6) + v18;
+if ( v10 < v16 )
+{
+v16 = v10;
+*a4 = (struct vector_type *)v6;
+*a5 = v9;
+}
+v19 = Distance((struct vector_type *)&v14, (struct vector_type *)(v6 + 8));
+v11 = Distance((struct vector_type *)&v12, (struct vector_type *)(v6 - 8)) + v19;
+if ( v11 < v16 )
+{
+v16 = v11;
+*a4 = v9;
+*a5 = v7;
+}
+v6 += 52;
+v20 = (struct wall_point_type *)((char *)v20 - 1);
+}
+while ( v20 );
+}
+}
diff --git a/geometry/geometry.cpp b/geometry/geometry.cpp
new file mode 100644
index 0000000..fa31012
--- /dev/null
+++ b/geometry/geometry.cpp
@@ -0,0 +1,622 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "../pinball.h"
+
+//----- (0100400B) --------------------------------------------------------
+signed int __stdcall rectangle_clip(int *a1, int *a2, _DWORD *a3)
+{
+ int v3; // edi
+ int v4; // edx
+ int v5; // esi
+ int v6; // ebx
+ int v7; // edx
+ int v9; // [esp+Ch] [ebp-8h]
+ int v10; // [esp+10h] [ebp-4h]
+ int v11; // [esp+1Ch] [ebp+8h]
+
+ v3 = *a1;
+ v9 = a1[1];
+ v10 = a1[3];
+ v4 = *a2 + a2[2];
+ v11 = a1[2];
+ v5 = a2[1] + a2[3];
+ if ( v3 + v11 < *a2 )
+ return 0;
+ if ( v3 >= v4 )
+ return 0;
+ v6 = v9;
+ if ( v9 + v10 < a2[1] || v9 >= v5 )
+ return 0;
+ if ( v3 < *a2 )
+ {
+ v11 += v3 - *a2;
+ v3 = *a2;
+ }
+ if ( v3 + v11 > v4 )
+ v11 = v4 - v3;
+ v7 = v10;
+ if ( v9 < a2[1] )
+ {
+ v7 = v9 - a2[1] + v10;
+ v6 = a2[1];
+ }
+ if ( v7 + v6 > v5 )
+ v7 = v5 - v6;
+ if ( !v11 || !v7 )
+ return 0;
+ if ( a3 )
+ {
+ *a3 = v3;
+ a3[1] = v6;
+ a3[2] = v11;
+ a3[3] = v7;
+ }
+ return 1;
+}
+
+//----- (010040C2) --------------------------------------------------------
+int __stdcall enclosing_box(_DWORD *a1, _DWORD *a2, _DWORD *a3)
+{
+ int v3; // esi
+ int v4; // edi
+ int v5; // eax
+ bool v6; // sf
+ unsigned __int8 v7; // of
+ int v8; // edx
+ int v9; // ecx
+ int v10; // eax
+ int result; // eax
+ int v12; // [esp+8h] [ebp-8h]
+ int v13; // [esp+Ch] [ebp-4h]
+ int v14; // [esp+18h] [ebp+8h]
+ int v15; // [esp+1Ch] [ebp+Ch]
+
+ v3 = *a1;
+ v4 = a1[1];
+ v13 = a1[2];
+ v12 = a1[3];
+ v5 = *a2;
+ v7 = __OFSUB__(*a2, *a1);
+ v6 = *a2 - *a1 < 0;
+ v14 = a2[1];
+ v8 = a2[2];
+ v9 = a2[3];
+ v15 = *a2;
+ if ( v6 ^ v7 )
+ {
+ v13 += v3 - v5;
+ v3 = v5;
+ }
+ if ( v14 < v4 )
+ {
+ v12 += v4 - v14;
+ v4 = v14;
+ }
+ if ( v8 + v5 > v3 + v13 )
+ v13 = v15 + v8 - v3;
+ v10 = v12;
+ if ( v9 + v14 > v12 + v4 )
+ v10 = v14 + v9 - v4;
+ a3[1] = v4;
+ a3[3] = v10;
+ result = v13;
+ *a3 = v3;
+ a3[2] = v13;
+ return result;
+}
+
+//----- (010077C4) --------------------------------------------------------
+BOOL __stdcall center_in(HWND hWnd, HWND a2)
+{
+ HWND v2; // eax
+ LONG v3; // ebx
+ int v4; // edi
+ int v5; // ecx
+ int v6; // eax
+ struct tagRECT v8; // [esp+Ch] [ebp-30h]
+ struct tagRECT Rect; // [esp+1Ch] [ebp-20h]
+ struct tagRECT v10; // [esp+2Ch] [ebp-10h]
+
+ GetWindowRect(hWnd, &Rect);
+ GetWindowRect(a2, &v8);
+ v2 = GetDesktopWindow();
+ GetWindowRect(v2, &v10);
+ if ( fullscrn_display_changed )
+ {
+ v10.bottom = 480;
+ v10.left = 0;
+ v10.top = 0;
+ v3 = 640;
+ v10.right = 640;
+ Rect.left = 0;
+ Rect.top = 0;
+ Rect.right = 640;
+ Rect.bottom = 480;
+ }
+ else
+ {
+ v3 = v10.right;
+ }
+ v4 = v8.bottom - v8.top;
+ v5 = Rect.left + (Rect.right + v8.left - v8.right - Rect.left) / 2;
+ v6 = Rect.top + (Rect.bottom + v8.top - v8.bottom - Rect.top) / 2;
+ if ( v8.right - v8.left + v5 > v3 )
+ v5 = v3 - (v8.right - v8.left);
+ if ( v4 + v6 > v10.bottom )
+ v6 = v10.bottom - v4;
+ if ( v5 < v10.left )
+ v5 = v10.left;
+ if ( v6 < v10.top )
+ v6 = v10.top;
+ return MoveWindow(a2, v5, v6, v8.right - v8.left, v8.bottom - v8.top, 0);
+}
+// 1024EF4: using guessed type int fullscrn_display_changed;
+
+//----- (01008AE9) --------------------------------------------------------
+double __stdcall normalize_2d(float *a1)
+{
+ double result; // st7
+
+ result = sqrt(*a1 * *a1 + a1[1] * a1[1]);
+ if ( 0.0 != result )
+ {
+ *a1 = 1.0 / result * *a1;
+ a1[1] = 1.0 / result * a1[1];
+ }
+ return result;
+}
+
+//----- (01008B34) --------------------------------------------------------
+double __stdcall ray_intersect_circle(float *a1, float *a2)
+{
+ double v2; // st7
+ double v3; // st7
+ double v4; // st6
+ double result; // st7
+ long double v6; // st5
+ float v7; // [esp+0h] [ebp-Ch]
+ float v8; // [esp+4h] [ebp-8h]
+
+ v7 = *a2 - *a1;
+ v2 = a2[1] - a1[1];
+ v8 = v2;
+ v3 = v2 * a1[4] + v7 * a1[3];
+ if ( v3 < 0.0 )
+ return 1000000000.0;
+ v4 = v8 * v8 + v7 * v7;
+ if ( v4 < a2[3] )
+ return v3 - sqrt(a2[3] - v4 + v3 * v3);
+ v6 = a2[3] - v4 + v3 * v3;
+ if ( v6 < 0.0 )
+ return 1000000000.0;
+ result = v3 - sqrt(v6);
+ if ( result < 0.0 || result > a1[6] )
+ return 1000000000.0;
+ return result;
+}
+
+//----- (01008BEB) --------------------------------------------------------
+int __stdcall line_init(int a1, float a2, float a3, float a4, float a5)
+{
+ float *v5; // esi
+ int v6; // edx
+ double v7; // st7
+ double v8; // st6
+ double v9; // st7
+ bool v10; // pf
+ int result; // eax
+
+ v5 = (float *)(a1 + 12);
+ *(float *)(a1 + 12) = a4 - a2;
+ *(float *)(a1 + 16) = a5 - a3;
+ normalize_2d((float *)(a1 + 12));
+ v7 = *(float *)(v6 + 16);
+ *(float *)v6 = *(float *)(v6 + 16);
+ v8 = -*(float *)(a1 + 12);
+ *(float *)(v6 + 4) = v8;
+ *(float *)(v6 + 24) = -(v7 * a2) - v8 * a3;
+ if ( *(float *)(a1 + 12) >= 0.000000001 || *v5 <= -0.000000001 )
+ {
+ v9 = a4;
+ v10 = a2 >= (double)a4;
+ result = LODWORD(a2);
+ }
+ else
+ {
+ *v5 = 0.0;
+ v9 = a5;
+ v10 = a3 >= (double)a5;
+ result = LODWORD(a3);
+ }
+ if ( v10 )
+ {
+ *(float *)(v6 + 28) = v9;
+ *(_DWORD *)(v6 + 32) = result;
+ }
+ else
+ {
+ *(float *)(v6 + 32) = v9;
+ *(_DWORD *)(v6 + 28) = result;
+ }
+ return result;
+}
+
+//----- (01008C8F) --------------------------------------------------------
+double __stdcall ray_intersect_line(float *a1, float *a2)
+{
+ double v2; // st7
+ double result; // st7
+ double v4; // st6
+ bool v5; // c0
+ bool v6; // c3
+ double v7; // st6
+
+ v2 = a2[1] * a1[4] + a1[3] * *a2;
+ if ( v2 < 0.0 )
+ {
+ result = -((*a1 * *a2 + a1[1] * a2[1] + a2[6]) / v2);
+ if ( result >= -a1[7] && result <= a1[6] )
+ {
+ a2[9] = result * a1[3] + *a1;
+ v4 = result * a1[4] + a1[1];
+ a2[10] = v4;
+ if ( 0.0 == a2[3] )
+ {
+ if ( v4 >= a2[7] )
+ {
+ v5 = v4 < a2[8];
+ v6 = v4 == a2[8];
+ goto LABEL_9;
+ }
+ }
+ else if ( a2[7] <= (double)a2[9] )
+ {
+ v7 = a2[9];
+ v5 = v7 < a2[8];
+ v6 = v7 == a2[8];
+ LABEL_9:
+ if ( v5 || v6 )
+ return result;
+ return 1000000000.0;
+ }
+ }
+ }
+ return 1000000000.0;
+}
+
+//----- (01008D4E) --------------------------------------------------------
+float *__stdcall proj_matrix_vector_multiply(float *a1, float *a2, float *a3)
+{
+ double v3; // st7
+ double v4; // st6
+ double v5; // st5
+ float *result; // eax
+
+ v3 = *a2;
+ v4 = a2[1];
+ v5 = a2[2];
+ result = a1;
+ *a3 = v5 * a1[2] + v4 * a1[1] + v3 * *a1 + a1[3];
+ a3[1] = v5 * result[6] + v4 * result[5] + v3 * result[4] + result[7];
+ a3[2] = v5 * result[10] + v4 * result[9] + v3 * result[8] + result[11];
+ return result;
+}
+
+//----- (01008DB8) --------------------------------------------------------
+float *__stdcall cross(float *a1, float *a2, float *a3)
+{
+ float *v3; // ecx
+ float *result; // eax
+
+ v3 = a2;
+ result = a1;
+ *a3 = a2[2] * a1[1] - a2[1] * a1[2];
+ a3[1] = -(*result * v3[2] - *v3 * result[2]);
+ a3[2] = *result * v3[1] - *v3 * result[1];
+ return result;
+}
+
+//----- (01008DFF) --------------------------------------------------------
+double __stdcall magnitude(float *a1)
+{
+ long double v1; // st7
+ double result; // st7
+
+ v1 = *a1 * *a1 + a1[1] * a1[1] + a1[2] * a1[2];
+ if ( v1 == 0.0 )
+ result = 0.0;
+ else
+ result = sqrt(v1);
+ return result;
+}
+
+//----- (01008E4B) --------------------------------------------------------
+int __stdcall proj_init(int a1, int a2, int a3, int a4)
+{
+ float *v4; // edx
+ float *v5; // eax
+ signed int v6; // esi
+ int result; // eax
+
+ v4 = (float *)&proj_matrix;
+ do
+ {
+ v5 = v4;
+ v6 = 4;
+ do
+ {
+ *v5 = *(float *)((char *)v5 + a1 - (_DWORD)&proj_matrix);
+ v5 += 4;
+ --v6;
+ }
+ while ( v6 );
+ ++v4;
+ }
+ while ( (signed int)v4 < (signed int)&unk_1028170 );
+ flt_1028198 = 0.0;
+ proj_d = a2;
+ flt_1028194 = 0.0;
+ proj_centerx = a3;
+ result = a4;
+ proj_centery = a4;
+ flt_1028190 = 0.0;
+ flt_102819C = 1.0;
+ return result;
+}
+// 1028138: using guessed type int proj_centery;
+// 102813C: using guessed type int proj_centerx;
+// 1028140: using guessed type int proj_d;
+// 1028190: using guessed type float flt_1028190;
+// 1028194: using guessed type float flt_1028194;
+// 1028198: using guessed type float flt_1028198;
+// 102819C: using guessed type float flt_102819C;
+
+//----- (01008EBA) --------------------------------------------------------
+int __stdcall proj_recenter(int a1, int a2)
+{
+ int result; // eax
+
+ proj_centerx = a1;
+ result = a2;
+ proj_centery = a2;
+ return result;
+}
+// 1028138: using guessed type int proj_centery;
+// 102813C: using guessed type int proj_centerx;
+
+//----- (01008ED8) --------------------------------------------------------
+void __stdcall proj_z_distance(float *a1)
+{
+ char v1; // [esp+0h] [ebp-Ch]
+
+ proj_matrix_vector_multiply((float *)&proj_matrix, a1, (float *)&v1);
+ magnitude((float *)&v1);
+}
+
+//----- (01008F03) --------------------------------------------------------
+double __stdcall proj_xform_to_2d(float *a1, _DWORD *a2)
+{
+ double v2; // st7
+ double v3; // st6
+ double result; // st7
+ float v5; // [esp+0h] [ebp-Ch]
+ float v6; // [esp+4h] [ebp-8h]
+ float v7; // [esp+8h] [ebp-4h]
+
+ proj_matrix_vector_multiply((float *)&proj_matrix, a1, &v5);
+ if ( 0.0 == v7 )
+ v2 = 999999.88;
+ else
+ v2 = *(float *)&proj_d / v7;
+ v3 = v6 * v2;
+ *a2 = (signed __int64)(v5 * v2 + *(float *)&proj_centerx);
+ result = 1.0;
+ a2[1] = (signed __int64)(v3 + *(float *)&proj_centery);
+ return result;
+}
+// 1028138: using guessed type int proj_centery;
+// 102813C: using guessed type int proj_centerx;
+// 1028140: using guessed type int proj_d;
+
+
+//----- (01013340) --------------------------------------------------------
+BOOL __stdcall overlapping_box(struct rectangle_type *a1, struct rectangle_type *a2, struct rectangle_type *a3)
+{
+int v3; // esi
+int v4; // edi
+int v5; // esi
+int v6; // esi
+int v7; // edi
+
+if ( *(_DWORD *)a1 >= *(_DWORD *)a2 )
+{
+*(_DWORD *)a3 = *(_DWORD *)a2;
+v3 = *((_DWORD *)a1 + 2) - *(_DWORD *)a2;
+v4 = *(_DWORD *)a1;
+}
+else
+{
+*(_DWORD *)a3 = *(_DWORD *)a1;
+v3 = *((_DWORD *)a2 + 2) - *(_DWORD *)a1;
+v4 = *(_DWORD *)a2;
+}
+*((_DWORD *)a3 + 2) = v3 + v4 + 1;
+v5 = *((_DWORD *)a1 + 1);
+if ( v5 >= *((_DWORD *)a2 + 1) )
+{
+*((_DWORD *)a3 + 1) = *((_DWORD *)a2 + 1);
+v6 = *((_DWORD *)a1 + 3) - *((_DWORD *)a2 + 1);
+v7 = *((_DWORD *)a1 + 1);
+}
+else
+{
+*((_DWORD *)a3 + 1) = v5;
+v6 = *((_DWORD *)a2 + 3) - *((_DWORD *)a1 + 1);
+v7 = *((_DWORD *)a2 + 1);
+}
+*((_DWORD *)a3 + 3) = v6 + v7 + 1;
+return *((_DWORD *)a3 + 2) <= *((_DWORD *)a2 + 2) + *((_DWORD *)a1 + 2)
+&& *((_DWORD *)a3 + 3) <= *((_DWORD *)a2 + 3) + *((_DWORD *)a1 + 3);
+}
+
+//----- (01015935) --------------------------------------------------------
+void __stdcall throw_ball(struct TBall *a1, struct vector_type *a2, float a3, float a4, float a5)
+{
+struct TBall *v5; // ebx
+int v6; // eax
+float v7; // ST04_4
+struct TBall *v8; // [esp+18h] [ebp+8h]
+
+v5 = a1;
+*(_DWORD *)((char *)a1 + 106) = 0;
+*(_DWORD *)((char *)a1 + 54) = *(_DWORD *)a2;
+*(_DWORD *)((char *)a1 + 58) = *((_DWORD *)a2 + 1);
+*(_DWORD *)((char *)a1 + 62) = *((_DWORD *)a2 + 2);
+v6 = _rand();
+v7 = (1.0 - ((double)v6 * 0.00003051850947599719 + (double)v6 * 0.00003051850947599719)) * a3;
+RotateVector((struct TBall *)((char *)a1 + 54), v7);
+v8 = (struct TBall *)_rand();
+*(float *)((char *)v5 + 66) = (1.0
+- ((double)(signed int)v8 * 0.00003051850947599719
++ (double)(signed int)v8 * 0.00003051850947599719))
+* (a4
+* a5)
++ a4;
+}
+
+//----- (0101B43A) --------------------------------------------------------
+double __stdcall distance_to_flipper(struct ray_type *a1, struct ray_type *a2)
+{
+signed int v2; // edi
+double v3; // st7
+double v4; // st7
+double v5; // st7
+double v6; // st7
+float *v7; // eax
+double v8; // st7
+_DWORD *v10; // esi
+_DWORD *v11; // esi
+float v12; // [esp+8h] [ebp-4h]
+
+v12 = 1000000000.0;
+v2 = -1;
+v3 = ray_intersect_line((float *)a1, (float *)&lineA);
+if ( v3 < 1000000000.0 )
+{
+v12 = v3;
+v2 = 0;
+}
+v4 = ray_intersect_circle((float *)a1, (float *)&circlebase);
+if ( v4 < v12 )
+{
+v12 = v4;
+v2 = 2;
+}
+v5 = ray_intersect_circle((float *)a1, (float *)&circleT1);
+if ( v5 < v12 )
+{
+v12 = v5;
+v2 = 3;
+}
+v6 = ray_intersect_line((float *)a1, (float *)&lineB);
+if ( v6 < v12 )
+{
+v12 = v6;
+v2 = 1;
+}
+if ( !a2 || v12 >= 1000000000.0 )
+return v12;
+if ( v2 != -1 )
+{
+if ( v2 )
+{
+if ( v2 != 1 )
+{
+if ( v2 == 2 )
+{
+v7 = (float *)((char *)a2 + 12);
+*(float *)a2 = v12 * *((float *)a1 + 3) + *(float *)a1;
+*((float *)a2 + 1) = v12 * *((float *)a1 + 4) + *((float *)a1 + 1);
+*((float *)a2 + 3) = *(float *)a2 - circlebase;
+v8 = *((float *)a2 + 1) - *(float *)&dword_1025664;
+}
+else
+{
+if ( v2 != 3 )
+return v12;
+v7 = (float *)((char *)a2 + 12);
+*(float *)a2 = v12 * *((float *)a1 + 3) + *(float *)a1;
+*((float *)a2 + 1) = v12 * *((float *)a1 + 4) + *((float *)a1 + 1);
+*((float *)a2 + 3) = *(float *)a2 - circleT1;
+v8 = *((float *)a2 + 1) - *(float *)&dword_1025674;
+}
+*((float *)a2 + 4) = v8;
+normalize_2d(v7);
+return v12;
+}
+*((_DWORD *)a2 + 3) = lineB;
+*((_DWORD *)a2 + 4) = *((_DWORD *)&lineB + 1);
+*((_DWORD *)a2 + 5) = *((_DWORD *)&lineB + 2);
+v10 = &unk_10256E4;
+}
+else
+{
+*((_DWORD *)a2 + 3) = lineA;
+*((_DWORD *)a2 + 4) = *((_DWORD *)&lineA + 1);
+*((_DWORD *)a2 + 5) = *((_DWORD *)&lineA + 2);
+v10 = &unk_10256A4;
+}
+*(_DWORD *)a2 = *v10;
+v11 = v10 + 1;
+*((_DWORD *)a2 + 1) = *v11;
+*((_DWORD *)a2 + 2) = v11[1];
+return v12;
+}
+return 1000000000.0;
+}
+// 1025664: using guessed type int dword_1025664;
+// 1025674: using guessed type int dword_1025674;
+
+//----- (0101CBB1) --------------------------------------------------------
+void __stdcall RotatePt(struct vector_type *a1, float a2, float a3, struct vector_type *a4)
+{
+double v4; // st7
+double v5; // st6
+
+v4 = *(float *)a1 - *(float *)a4;
+v5 = *((float *)a1 + 1) - *((float *)a4 + 1);
+*(float *)a1 = v4 * a3 - v5 * a2 + *(float *)a4;
+*((float *)a1 + 1) = v4 * a2 + v5 * a3 + *((float *)a4 + 1);
+}
+
+//----- (0101CBF5) --------------------------------------------------------
+long double __stdcall Distance(struct vector_type *a1, struct vector_type *a2)
+{
+double v2; // st7
+double v3; // st6
+
+v2 = *(float *)a1 - *(float *)a2;
+v3 = *((float *)a1 + 1) - *((float *)a2 + 1);
+return sqrt(v3 * v3 + v2 * v2);
+}
+
+//----- (0101CC23) --------------------------------------------------------
+double __stdcall Distance_Squared(float a1, float a2, int a3, float a4, float a5, int a6)
+{
+return (a2 - a5) * (a2 - a5) + (a1 - a4) * (a1 - a4);
+}
+
+//----- (0101CC4B) --------------------------------------------------------
+double __stdcall DotProduct(const struct vector_type *a1, const struct vector_type *a2)
+{
+return *((float *)a1 + 1) * *((float *)a2 + 1) + *(float *)a1 * *(float *)a2;
+}
+
+//----- (0101CC6B) --------------------------------------------------------
+void __stdcall SinCos(float a1, float *a2, float *a3)
+{
+*a2 = sin(a1);
+*a3 = cos(a1);
+}
diff --git a/graphics/flasher.cpp b/graphics/flasher.cpp
new file mode 100644
index 0000000..e406ca6
--- /dev/null
+++ b/graphics/flasher.cpp
@@ -0,0 +1,34 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+//----- (01009910) --------------------------------------------------------
+void __stdcall flasher_callback(int a1, void *a2)
+{
+ int v2; // eax
+
+ v2 = 1 - *((_DWORD *)a2 + 8);
+ *((_DWORD *)a2 + 8) = v2;
+ render_sprite_set_bitmap(*(_DWORD **)a2, *((_DWORD *)a2 + v2 + 1));
+ *((_DWORD *)a2 + 7) = timer_set(*((float *)a2 + *((_DWORD *)a2 + 8) + 5), (int)a2, (int)flasher_callback);
+}
+
+//----- (01009950) --------------------------------------------------------
+void __stdcall flasher_start(struct flasher_type *a1, int a2)
+{
+ *((_DWORD *)a1 + 8) = a2;
+ flasher_callback(0, (void *)a1);
+}
+
+//----- (0100996F) --------------------------------------------------------
+void __stdcall flasher_stop(struct flasher_type *a1, int a2)
+{
+ if ( *((_DWORD *)a1 + 7) )
+ timer_kill(*((_DWORD *)a1 + 7));
+ *((_DWORD *)a1 + 7) = 0;
+ if ( a2 >= 0 )
+ {
+ *((_DWORD *)a1 + 8) = a2;
+ render_sprite_set_bitmap(*(_DWORD **)a1, *((_DWORD *)a1 + a2 + 1));
+ }
+}
\ No newline at end of file
diff --git a/graphics/fullscreen.cpp b/graphics/fullscreen.cpp
new file mode 100644
index 0000000..76d5d9d
--- /dev/null
+++ b/graphics/fullscreen.cpp
@@ -0,0 +1,348 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "../pinball.h"
+
+//----- (010038F8) --------------------------------------------------------
+int sub_10038F8()
+{
+ int result; // eax
+ HWND v1; // eax
+ struct tagRECT Rect; // [esp+4h] [ebp-10h]
+
+ if ( fullscrn_screen_mode )
+ {
+ v1 = GetDesktopWindow();
+ GetWindowRect(v1, &Rect);
+ xDest = (Rect.right - dword_1025094 - Rect.left) / 2;
+ result = (Rect.bottom - dword_1025098 - Rect.top) / 2;
+ }
+ else
+ {
+ xDest = 0;
+ result = GetSystemMetrics(15);
+ }
+ yDest = result;
+ if ( dword_1024EE8 )
+ {
+ result = GetSystemMetrics(15);
+ yDest -= result;
+ }
+ return result;
+}
+// 1024EE4: using guessed type int fullscrn_screen_mode;
+// 1024EE8: using guessed type int dword_1024EE8;
+// 1025094: using guessed type int dword_1025094;
+// 1025098: using guessed type int dword_1025098;
+
+//----- (01003975) --------------------------------------------------------
+LONG sub_1003975()
+{
+ LONG v0; // eax
+
+ v0 = GetWindowLongA(hWnd, -16);
+ return SetWindowLongA(hWnd, -16, v0 | 0xC00000);
+}
+
+//----- (0100399D) --------------------------------------------------------
+LONG sub_100399D()
+{
+ LONG v0; // eax
+
+ v0 = GetWindowLongA(hWnd, -16);
+ return SetWindowLongA(hWnd, -16, v0 & 0xFF3FFFFF);
+}
+
+//----- (010039C5) --------------------------------------------------------
+BOOL __stdcall fullscrn_set_menu_mode(int a1)
+{
+ BOOL result; // eax
+
+ dword_1024EE8 = a1;
+ sub_10038F8();
+ if ( dword_1024EE8 )
+ {
+ dword_1024EEC |= 2u;
+ InvalidateRect(hWnd, 0, 1);
+ result = SetMenu(hWnd, (HMENU)dword_1024EC0);
+ }
+ else
+ {
+ dword_1024EEC |= 1u;
+ InvalidateRect(hWnd, 0, 1);
+ result = SetMenu(hWnd, 0);
+ }
+ return result;
+}
+// 1024EC0: using guessed type int dword_1024EC0;
+// 1024EE8: using guessed type int dword_1024EE8;
+// 1024EEC: using guessed type int dword_1024EEC;
+
+//----- (01003A23) --------------------------------------------------------
+signed int sub_1003A23()
+{
+ HWND v0; // eax
+ LONG v1; // eax
+ HWND v3; // eax
+ struct tagRECT Rect; // [esp+Ch] [ebp-B0h]
+ DEVMODEA DevMode; // [esp+1Ch] [ebp-A0h]
+
+ if ( dword_1024EF8 && !fullscrn_display_changed )
+ {
+ DevMode.dmSize = 156;
+ DevMode.dmFields = 1835008;
+ DevMode.dmPelsWidth = 640;
+ DevMode.dmPelsHeight = 480;
+ DevMode.dmBitsPerPel = 8;
+ sub_100399D();
+ if ( trick )
+ {
+ v0 = GetDesktopWindow();
+ GetWindowRect(v0, &Rect);
+ SetWindowPos(hWnd, HWND_MESSAGE|0x2, 0, 0, Rect.right - Rect.left + 1, Rect.bottom - Rect.top + 1, 8u);
+ }
+ dword_1024EF0 = 1;
+ v1 = ChangeDisplaySettingsA(&DevMode, 4u);
+ if ( v1 == 1 )
+ {
+ BYTE2(DevMode.dmFields) &= 0xFBu;
+ dword_1024EF0 = 1;
+ v1 = ChangeDisplaySettingsA(&DevMode, 4u);
+ }
+ fullscrn_display_changed = v1 == 0;
+ if ( v1 == 0 )
+ return 1;
+ }
+ v3 = GetDesktopWindow();
+ GetWindowRect(v3, &Rect);
+ sub_100399D();
+ SetWindowPos(hWnd, (HWND)0xFFFFFFFE, 0, 0, Rect.right - Rect.left + 1, Rect.bottom - Rect.top + 1, 8u);
+ return 0;
+}
+// 1023054: using guessed type int trick;
+// 1024EF0: using guessed type int dword_1024EF0;
+// 1024EF4: using guessed type int fullscrn_display_changed;
+// 1024EF8: using guessed type int dword_1024EF8;
+
+//----- (01003B66) --------------------------------------------------------
+int sub_1003B66()
+{
+ if ( fullscrn_display_changed )
+ {
+ fullscrn_display_changed = 0;
+ dword_1024EF0 = 1;
+ ChangeDisplaySettingsA(0, 4u);
+ if ( trick )
+ SetWindowPos(hWnd, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x13u);
+ }
+ sub_1003975();
+ SetWindowPos(hWnd, 0, X.left, X.top, X.right - X.left, X.bottom - X.top, 0x14u);
+ return 0;
+}
+// 1023054: using guessed type int trick;
+// 1024EF0: using guessed type int dword_1024EF0;
+// 1024EF4: using guessed type int fullscrn_display_changed;
+
+//----- (01003BE4) --------------------------------------------------------
+LONG __stdcall fullscrn_set_screen_mode(int a1)
+{
+ LONG result; // eax
+
+ result = a1;
+ if ( a1 != fullscrn_screen_mode )
+ {
+ fullscrn_screen_mode = a1;
+ if ( a1 )
+ {
+ if ( IsWindowVisible(hWnd) )
+ GetWindowRect(hWnd, &X);
+ sub_1003A23();
+ BYTE1(dword_1024EEC) |= 0x80u;
+ InvalidateRect(hWnd, 0, 1);
+ fullscrn_set_menu_mode(0);
+ result = sub_100399D();
+ }
+ else
+ {
+ sub_1003B66();
+ BYTE1(dword_1024EEC) |= 0x80u;
+ InvalidateRect(hWnd, 0, 1);
+ fullscrn_set_menu_mode(1);
+ result = RedrawWindow(0, 0, 0, 0x185u);
+ }
+ }
+ return result;
+}
+// 1024EE4: using guessed type int fullscrn_screen_mode;
+// 1024EEC: using guessed type int dword_1024EEC;
+
+//----- (01003C87) --------------------------------------------------------
+void __stdcall fullscrn_force_redraw()
+{
+ BYTE1(dword_1024EEC) |= 0x80u;
+}
+// 1024EEC: using guessed type int dword_1024EEC;
+
+//----- (01003C94) --------------------------------------------------------
+signed int __stdcall fullscrn_displaychange()
+{
+ signed int v0; // esi
+ signed int result; // eax
+ HWND v2; // ST18_4
+ HWND v3; // eax
+
+ v0 = 0;
+ if ( dword_1024EF0 )
+ {
+ dword_1024EF0 = 0;
+ result = 0;
+ }
+ else
+ {
+ if ( fullscrn_screen_mode && fullscrn_display_changed )
+ {
+ fullscrn_display_changed = 0;
+ fullscrn_screen_mode = 0;
+ sub_1003975();
+ BYTE1(dword_1024EEC) |= 0x80u;
+ InvalidateRect(hWnd, 0, 1);
+ fullscrn_set_menu_mode(1);
+ SetWindowPos(hWnd, 0, X.left, X.top, X.right - X.left, X.bottom - X.top, 0x1Cu);
+ v0 = 1;
+ }
+ else
+ {
+ SetWindowPos(hWnd, 0, X.left, X.top, X.right - X.left, X.bottom - X.top, 0x14u);
+ }
+ v2 = hWnd;
+ v3 = GetDesktopWindow();
+ center_in(v3, v2);
+ result = v0;
+ }
+ return result;
+}
+// 1024EE4: using guessed type int fullscrn_screen_mode;
+// 1024EEC: using guessed type int dword_1024EEC;
+// 1024EF0: using guessed type int dword_1024EF0;
+// 1024EF4: using guessed type int fullscrn_display_changed;
+
+//----- (01003D65) --------------------------------------------------------
+BOOL __stdcall fullscrn_init(int a1, int a2, int a3, HWND a4, int a5, int a6)
+{
+ HWND v6; // eax
+ int v7; // ebx
+ int v8; // edi
+ int v9; // eax
+ int v10; // kr00_4
+ BOOL result; // eax
+ int v12; // [esp+18h] [ebp+Ch]
+
+ dword_1024ED4 = 0;
+ dword_1024ED8 = 0;
+ dword_1024EF8 = a6;
+ hWnd = a4;
+ dword_1024EC0 = a5;
+ dword_1024EDC = a1;
+ dword_1024EE0 = a2;
+ v6 = GetDesktopWindow();
+ GetWindowRect(v6, &Rect);
+ v7 = a1 + 2 * GetSystemMetrics(5);
+ v12 = a2 + 2 * GetSystemMetrics(6);
+ v8 = GetSystemMetrics(15);
+ v9 = GetSystemMetrics(4);
+ v10 = Rect.bottom - Rect.top - v12;
+ X.bottom = v10 / 2 - 2 + v12 + 4;
+ X.right = (Rect.right - Rect.left - v7) / 2 - 2 + v7 + 4;
+ X.left = (Rect.right - Rect.left - v7) / 2 - 2;
+ X.top = v10 / 2 - (v9 + v8) - 2;
+ result = MoveWindow(hWnd, (Rect.right - Rect.left - v7) / 2 - 2, X.top, v7 + 4, X.bottom - X.top, 0);
+ dword_1024EEC = 0;
+ return result;
+}
+// 1024EC0: using guessed type int dword_1024EC0;
+// 1024ED4: using guessed type int dword_1024ED4;
+// 1024ED8: using guessed type int dword_1024ED8;
+// 1024EDC: using guessed type int dword_1024EDC;
+// 1024EE0: using guessed type int dword_1024EE0;
+// 1024EEC: using guessed type int dword_1024EEC;
+// 1024EF8: using guessed type int dword_1024EF8;
+
+//----- (01003E53) --------------------------------------------------------
+LONG __stdcall fullscrn_shutdown()
+{
+ LONG result; // eax
+
+ if ( fullscrn_display_changed )
+ result = fullscrn_set_screen_mode(0);
+ return result;
+}
+// 1024EF4: using guessed type int fullscrn_display_changed;
+
+//----- (01003E69) --------------------------------------------------------
+BOOL __stdcall fullscrn_activate(int a1)
+{
+ BOOL result; // eax
+
+ if ( fullscrn_screen_mode )
+ {
+ if ( !a1 )
+ {
+ fullscrn_set_screen_mode(0);
+ result = SetWindowPos(hWnd, (HWND)1, 0, 0, 0, 0, 0x13u);
+ }
+ }
+ return result;
+}
+// 1024EE4: using guessed type int fullscrn_screen_mode;
+
+//----- (01003EA2) --------------------------------------------------------
+int __stdcall fullscrn_convert_mouse_pos(int a1)
+{
+ return (unsigned __int16)(a1 - xDest) | ((unsigned __int16)(HIWORD(a1) - yDest) << 16);
+}
+
+//----- (01003ECF) --------------------------------------------------------
+_DWORD *__stdcall fullscrn_getminmaxinfo(_DWORD *a1)
+{
+ _DWORD *result; // eax
+
+ result = a1;
+ a1[2] = X.right - X.left;
+ a1[3] = X.bottom - X.top;
+ a1[4] = X.left;
+ a1[5] = X.top;
+ return result;
+}
+
+//----- (01003F98) --------------------------------------------------------
+void __stdcall fullscrn_paint()
+{
+ int v0; // ST04_4
+ int v1; // eax
+
+ if ( fullscrn_screen_mode )
+ {
+ if ( (dword_1024EEC & 0x8000) == 0 && dword_1024EEC )
+ {
+ if ( dword_1024EEC & 1 )
+ {
+ v0 = GetSystemMetrics(15);
+ sub_1003F10(0, 0, Rect.right - 1, v0);
+ }
+ }
+ else
+ {
+ if ( dword_1024EE8 )
+ v1 = GetSystemMetrics(15);
+ else
+ v1 = 0;
+ sub_1003F10(0, -v1, Rect.right, v1 + Rect.bottom);
+ }
+ }
+ render_paint();
+ dword_1024EEC = 0;
+}
+// 1024EE4: using guessed type int fullscrn_screen_mode;
+// 1024EE8: using guessed type int dword_1024EE8;
+// 1024EEC: using guessed type int dword_1024EEC;
diff --git a/graphics/graphics.cpp b/graphics/graphics.cpp
new file mode 100644
index 0000000..361f6b2
--- /dev/null
+++ b/graphics/graphics.cpp
@@ -0,0 +1,853 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "../pinball.h"
+
+//----- (01003803) --------------------------------------------------------
+int __stdcall grtext_draw_ttext_in_box(LPCSTR lpString, int mode, int a3, COLORREF color, int a5, int a6)
+{
+ HDC v6; // ebx
+ CHAR *v7; // eax
+ unsigned __int16 v8; // ax
+ int v9; // eax
+ struct tagRECT rc; // [esp+Ch] [ebp-10h]
+ int modea; // [esp+28h] [ebp+Ch]
+ COLORREF colora; // [esp+30h] [ebp+14h]
+
+ v6 = _GetDC(gdrv_hwnd);
+ rc.left = mode;
+ rc.right = color + mode;
+ rc.top = a3;
+ rc.bottom = a5 + a3;
+ if ( grtext_red < 0 )
+ {
+ grtext_blue = 255;
+ grtext_green = 255;
+ grtext_red = 255;
+ v7 = get_rc_string(189, 0);
+ if ( v7 )
+ _sscanf(v7, "%d %d %d", &grtext_red, &grtext_green, &grtext_blue);
+ }
+ modea = SetBkMode(v6, 1);
+ HIBYTE(v8) = grtext_blue;
+ LOBYTE(v8) = grtext_green;
+ colora = SetTextColor(v6, (unsigned __int8)grtext_red | (v8 << 8));
+ v9 = lstrlenA(lpString);
+ DrawTextA(v6, lpString, v9, &rc, 0x810u);
+ SetBkMode(v6, modea);
+ SetTextColor(v6, colora);
+ return ReleaseDC(gdrv_hwnd, v6);
+}
+// 1023050: using guessed type int grtext_red;
+// 1028290: using guessed type int grtext_blue;
+// 1028294: using guessed type int grtext_green;
+
+
+
+//----- (01004154) --------------------------------------------------------
+int __stdcall DibSetUsage(int a1, HPALETTE hpal, int a3)
+{
+ signed int v4; // edi
+ unsigned __int16 v5; // cx
+ char *v6; // esi
+ signed int i; // eax
+ _BYTE *v8; // eax
+ BYTE v9; // bl
+ struct tagPALETTEENTRY pPalEntries[256]; // [esp+4h] [ebp-400h]
+ HPALETTE hpala; // [esp+410h] [ebp+Ch]
+
+ if ( !hpal )
+ hpal = (HPALETTE)GetStockObject(15);
+ if ( !a1 )
+ return 0;
+ v4 = *(_DWORD *)(a1 + 32);
+ if ( !v4 )
+ {
+ v5 = *(_WORD *)(a1 + 14);
+ if ( v5 <= 8u )
+ v4 = 1 << v5;
+ }
+ if ( v4 == 3 )
+ {
+ if ( *(_DWORD *)(a1 + 16) != 3 )
+ {
+ LABEL_12:
+ v6 = (char *)(a1 + *(_DWORD *)a1);
+ if ( (unsigned int)a3 <= 0 || (unsigned int)a3 > 2 )
+ {
+ if ( v4 >= 256 )
+ v4 = 256;
+ GetPaletteEntries(hpal, 0, v4, pPalEntries);
+ hpala = 0;
+ if ( v4 > 0 )
+ {
+ v8 = v6 + 1;
+ do
+ {
+ v9 = pPalEntries[(_DWORD)hpala].peRed;
+ hpala = (HPALETTE)((char *)hpala + 1);
+ v8[1] = v9;
+ *v8 = v8[(char *)pPalEntries - v6];
+ *(v8 - 1) = v8[&pPalEntries[0].peGreen - (BYTE *)v6];
+ v8[2] = 0;
+ v8 += 4;
+ }
+ while ( (signed int)hpala < v4 );
+ }
+ }
+ else
+ {
+ for ( i = 0; i < v4; v6 += 2 )
+ *(_WORD *)v6 = i++;
+ }
+ return 1;
+ }
+ v4 = 0;
+ }
+ if ( v4 > 0 )
+ goto LABEL_12;
+ return 1;
+}
+// 1004154: using guessed type struct tagPALETTEENTRY pPalEntries[256];
+
+//----- (0100423A) --------------------------------------------------------
+_DWORD *__stdcall DibCreate(int a1, int a2, int a3)
+{
+ unsigned int v3; // edi
+ HGLOBAL v4; // eax
+ _DWORD *v5; // esi
+ _DWORD *result; // eax
+ _DWORD *i; // ecx
+ _DWORD *v8; // ecx
+ int v9; // [esp+18h] [ebp+Ch]
+
+ v3 = a3 * ((a2 * a1 / 8 + 3) & 0xFFFFFFFC);
+ v4 = GlobalAlloc(0x42u, v3 + 1064);
+ v5 = GlobalLock(v4);
+ result = 0;
+ if ( v5 )
+ {
+ v5[5] = v3;
+ v5[1] = a2;
+ *v5 = 40;
+ v5[2] = a3;
+ *((_WORD *)v5 + 6) = 1;
+ *((_WORD *)v5 + 7) = a1;
+ v5[4] = 0;
+ v5[6] = 0;
+ v5[7] = 0;
+ v5[8] = 0;
+ v5[9] = 0;
+ if ( a1 == 4 )
+ {
+ v5[8] = 16;
+ }
+ else if ( a1 == 8 )
+ {
+ v5[8] = 256;
+ }
+ v9 = 0;
+ for ( i = v5 + 10; v9 < v5[8] / 16; ++v9 )
+ {
+ *i = 0;
+ v8 = i + 1;
+ *v8 = 0x800000;
+ ++v8;
+ *v8 = 0x8000;
+ ++v8;
+ *v8 = 8421376;
+ ++v8;
+ *v8 = 128;
+ ++v8;
+ *v8 = 8388736;
+ ++v8;
+ *v8 = 32896;
+ ++v8;
+ *v8 = 12632256;
+ ++v8;
+ *v8 = 8421504;
+ ++v8;
+ *v8 = 16711680;
+ ++v8;
+ *v8 = 65280;
+ ++v8;
+ *v8 = 16776960;
+ ++v8;
+ *v8 = 255;
+ ++v8;
+ *v8 = 16711935;
+ ++v8;
+ *v8 = 0xFFFF;
+ ++v8;
+ *v8 = 0xFFFFFF;
+ i = v8 + 1;
+ }
+ result = v5;
+ }
+ return result;
+}
+
+//----- (01004380) --------------------------------------------------------
+int __stdcall gdrv_init(int a1, HWND a2)
+{
+ gdrv_hinst = a1;
+ gdrv_hwnd = a2;
+ if ( !gdrv_palette_handle )
+ gdrv_palette_handle = CreatePalette(¤t_palette);
+ return 0;
+}
+// 1028284: using guessed type int gdrv_hinst;
+
+//----- (010043B9) --------------------------------------------------------
+int __stdcall gdrv_display_palette(int a1)
+{
+ HWND v1; // eax
+ HDC v2; // eax
+ HDC v3; // ebx
+ HPALETTE v4; // edi
+ BYTE *v5; // eax
+ int v6; // ecx
+ BYTE *v7; // eax
+ HWND v8; // eax
+ HDC v10; // [esp+0h] [ebp-14h]
+ signed int v11; // [esp+4h] [ebp-10h]
+ char *v12; // [esp+1Ch] [ebp+8h]
+
+ if ( gdrv_palette_handle )
+ DeleteObject(gdrv_palette_handle);
+ gdrv_palette_handle = CreatePalette(¤t_palette);
+ v1 = GetDesktopWindow();
+ v2 = _GetDC(v1);
+ v3 = v2;
+ v10 = v2;
+ SetSystemPaletteUse(v2, 2u);
+ SetSystemPaletteUse(v3, 1u);
+ v4 = SelectPalette(v3, (HPALETTE)gdrv_palette_handle, 0);
+ RealizePalette(v3);
+ SelectPalette(v3, v4, 0);
+ GetSystemPaletteEntries(v3, 0, 0x100u, &pPalEntries);
+ v5 = &pPalEntries.peFlags;
+ do
+ {
+ *v5 = 0;
+ v5 += 4;
+ }
+ while ( (signed int)v5 < (signed int)&unk_102345F );
+ v6 = a1;
+ v12 = (char *)&unk_102305B - a1;
+ v7 = (BYTE *)(v6 + 41);
+ v11 = 236;
+ do
+ {
+ if ( v6 )
+ {
+ v7[(_DWORD)v12] = v7[1];
+ v7[(_DWORD)&pPalEntries - v6] = *v7;
+ v7[(_DWORD)((char *)&pPalEntries - v6 + 1)] = *(v7 - 1);
+ v3 = v10;
+ }
+ v7[(_DWORD)((char *)&pPalEntries - v6 + 2)] = 4;
+ v7 += 4;
+ --v11;
+ }
+ while ( v11 );
+ if ( !(GetDeviceCaps(v3, 38) & 0x100) )
+ {
+ byte_102345A = -1;
+ byte_1023459 = -1;
+ byte_1023458 = -1;
+ }
+ ResizePalette((HPALETTE)gdrv_palette_handle, 0x100u);
+ SetPaletteEntries((HPALETTE)gdrv_palette_handle, 0, 0x100u, &pPalEntries);
+ v8 = GetDesktopWindow();
+ ReleaseDC(v8, v3);
+ return 0;
+}
+// 1023458: using guessed type char byte_1023458;
+// 1023459: using guessed type char byte_1023459;
+// 102345A: using guessed type char byte_102345A;
+
+//----- (01004508) --------------------------------------------------------
+int __stdcall gdrv_uninit()
+{
+ if ( gdrv_palette_handle )
+ DeleteObject(gdrv_palette_handle);
+ return 0;
+}
+
+//----- (01004520) --------------------------------------------------------
+int __stdcall gdrv_create_bitmap_dib(int a1, int a2, int a3)
+{
+ int v3; // edi
+ _DWORD *v4; // eax
+ _DWORD *v5; // eax
+ int v6; // ecx
+
+ v3 = a2;
+ v4 = DibCreate(8, a2, a3);
+ *(_DWORD *)a1 = v4;
+ DibSetUsage((int)v4, (HPALETTE)gdrv_palette_handle, 1);
+ *(_DWORD *)(a1 + 12) = a2;
+ *(_DWORD *)(a1 + 20) = a2;
+ if ( a2 % 4 )
+ v3 = 4 - a2 % 4 + a2;
+ v5 = *(_DWORD **)a1;
+ *(_DWORD *)(a1 + 20) = v3;
+ *(_DWORD *)(a1 + 16) = a3;
+ *(_BYTE *)(a1 + 24) = 2;
+ if ( v5[4] == 3 )
+ v6 = (int)v5 + *v5 + 12;
+ else
+ v6 = (int)&v5[v5[8]] + *v5;
+ *(_DWORD *)(a1 + 8) = v6;
+ *(_DWORD *)(a1 + 4) = v6;
+ return 0;
+}
+
+//----- (0100459A) --------------------------------------------------------
+int __stdcall gdrv_create_bitmap(int a1, int a2, int a3)
+{
+ return gdrv_create_bitmap_dib(a1, a2, a3);
+}
+
+//----- (010045AA) --------------------------------------------------------
+signed int __stdcall gdrv_create_raw_bitmap(int a1, int a2, int a3, int a4)
+{
+ unsigned int v4; // ST04_4
+ int v5; // eax
+
+ *(_DWORD *)a1 = 0;
+ *(_DWORD *)(a1 + 12) = a2;
+ *(_DWORD *)(a1 + 20) = a2;
+ if ( a4 && a2 % 4 )
+ *(_DWORD *)(a1 + 20) = a2 - a2 % 4 + 4;
+ v4 = a3 * *(_DWORD *)(a1 + 20);
+ *(_DWORD *)(a1 + 16) = a3;
+ *(_BYTE *)(a1 + 24) = 1;
+ v5 = memoryallocate(v4);
+ *(_DWORD *)(a1 + 8) = v5;
+ if ( !v5 )
+ return -1;
+ *(_DWORD *)(a1 + 4) = v5;
+ return 0;
+}
+
+//----- (0100460C) --------------------------------------------------------
+signed int __stdcall gdrv_destroy_bitmap(int a1)
+{
+ HGLOBAL v2; // eax
+ HGLOBAL v3; // eax
+
+ if ( !a1 )
+ return -1;
+ if ( *(_BYTE *)(a1 + 24) == 1 )
+ {
+ memoryfree(*(_DWORD *)(a1 + 8));
+ }
+ else if ( *(_BYTE *)(a1 + 24) == 2 )
+ {
+ v2 = GlobalHandle(*(LPCVOID *)a1);
+ GlobalUnlock(v2);
+ v3 = GlobalHandle(*(LPCVOID *)a1);
+ GlobalFree(v3);
+ }
+ memset((void *)a1, 0, 0x24u);
+ *(_BYTE *)(a1 + 36) = 0;
+ return 0;
+}
+
+//----- (01004664) --------------------------------------------------------
+UINT __stdcall gdrv_start_blit_sequence()
+{
+ HDC v0; // eax
+
+ v0 = _GetDC(gdrv_hwnd);
+ gdrv_sequence_handle = 0;
+ gdrv_sequence_hdc = v0;
+ SelectPalette(v0, (HPALETTE)gdrv_palette_handle, 0);
+ return RealizePalette(gdrv_sequence_hdc);
+}
+// 102828C: using guessed type int gdrv_sequence_handle;
+
+//----- (0100469C) --------------------------------------------------------
+int __stdcall gdrv_blit_sequence(int a1, int xSrc, int a3, int xDest, int yDest, int DestWidth, int DestHeight)
+{
+ int result; // eax
+
+ if ( !gdrv_use_wing )
+ result = StretchDIBits(
+ gdrv_sequence_hdc,
+ xDest,
+ yDest,
+ DestWidth,
+ DestHeight,
+ xSrc,
+ *(_DWORD *)(a1 + 16) - a3 - DestHeight,
+ DestWidth,
+ DestHeight,
+ *(const void **)(a1 + 8),
+ *(const BITMAPINFO **)a1,
+ 1u,
+ 0xCC0020u);
+ return result;
+}
+// 1024EFC: using guessed type int gdrv_use_wing;
+
+//----- (010046ED) --------------------------------------------------------
+int __stdcall gdrv_end_blit_sequence()
+{
+ return ReleaseDC(gdrv_hwnd, gdrv_sequence_hdc);
+}
+
+//----- (01004705) --------------------------------------------------------
+HDC __stdcall gdrv_blit(int a1, int xSrc, int a3, int xDest, int yDest, int DestWidth, int DestHeight)
+{
+ HDC result; // eax
+ HDC v8; // esi
+
+ result = _GetDC(gdrv_hwnd);
+ v8 = result;
+ if ( result )
+ {
+ SelectPalette(result, (HPALETTE)gdrv_palette_handle, 0);
+ RealizePalette(v8);
+ if ( !gdrv_use_wing )
+ StretchDIBits(
+ v8,
+ xDest,
+ yDest,
+ DestWidth,
+ DestHeight,
+ xSrc,
+ *(_DWORD *)(a1 + 16) - a3 - DestHeight,
+ DestWidth,
+ DestHeight,
+ *(const void **)(a1 + 8),
+ *(const BITMAPINFO **)a1,
+ 1u,
+ 0xCC0020u);
+ result = (HDC)ReleaseDC(gdrv_hwnd, v8);
+ }
+ return result;
+}
+// 1024EFC: using guessed type int gdrv_use_wing;
+
+//----- (01004787) --------------------------------------------------------
+int __stdcall gdrv_blat(int a1, int xDest, int yDest)
+{
+ HDC v3; // edi
+
+ v3 = _GetDC(gdrv_hwnd);
+ SelectPalette(v3, (HPALETTE)gdrv_palette_handle, 0);
+ RealizePalette(v3);
+ if ( !gdrv_use_wing )
+ StretchDIBits(
+ v3,
+ xDest,
+ yDest,
+ *(_DWORD *)(a1 + 12),
+ *(_DWORD *)(a1 + 16),
+ 0,
+ 0,
+ *(_DWORD *)(a1 + 12),
+ *(_DWORD *)(a1 + 16),
+ *(const void **)(a1 + 8),
+ *(const BITMAPINFO **)a1,
+ 1u,
+ 0xCC0020u);
+ return ReleaseDC(gdrv_hwnd, v3);
+}
+// 1024EFC: using guessed type int gdrv_use_wing;
+
+//----- (010047FA) --------------------------------------------------------
+int __userpurge gdrv_fill_bitmap@(int a1@, _DWORD *a2, unsigned int a3, int a4, int a5, int a6, char a7)
+{
+_DWORD *v7; // esi
+int v8; // eax
+int result; // eax
+unsigned int v10; // ecx
+char v11; // dl
+unsigned int v12; // ecx
+int v13; // eax
+char *v14; // [esp+Ch] [ebp+8h]
+
+v7 = a2;
+v8 = a2[4];
+if ( v8 < 0 )
+v8 = -v8;
+result = a5 + a2[2] + a2[3] * (v8 - a4 - a6);
+v14 = (char *)result;
+if ( a4 > 0 )
+{
+v10 = a3;
+do
+{
+if ( (signed int)v10 > 0 )
+{
+LOBYTE(a1) = a7;
+BYTE1(a1) = a7;
+v11 = v10;
+v12 = v10 >> 2;
+v13 = a1 << 16;
+LOWORD(v13) = a1;
+memset32(v14, v13, v12);
+memset(&v14[4 * v12], a7, v11 & 3);
+v10 = a3;
+v14 += a3;
+}
+result = v7[5] - v10;
+v14 += result;
+--a4;
+}
+while ( a4 );
+}
+return result;
+}
+
+//----- (01004870) --------------------------------------------------------
+char *__stdcall gdrv_copy_bitmap(_DWORD *a1, int a2, int a3, int a4, int a5, _DWORD *a6, int a7, int a8)
+{
+ _DWORD *v8; // edx
+ int v9; // ecx
+ _DWORD *v10; // esi
+ int v11; // eax
+ char *result; // eax
+ _BYTE *v13; // ecx
+ char v14; // bl
+ int v15; // [esp+10h] [ebp+8h]
+ int v16; // [esp+24h] [ebp+1Ch]
+
+ v8 = a1;
+ v9 = a1[4];
+ v10 = a6;
+ v11 = a6[4];
+ if ( v11 < 0 )
+ v11 = -v11;
+ if ( v9 < 0 )
+ v9 = -v9;
+ result = (char *)(a7 + a6[2] + a6[5] * (v11 - a3 - a8));
+ v13 = (_BYTE *)(a4 + a1[2] + a1[5] * (v9 - a3 - a5));
+ if ( a3 > 0 )
+ {
+ v16 = a3;
+ do
+ {
+ if ( a2 > 0 )
+ {
+ v15 = a2;
+ do
+ {
+ v14 = *result++;
+ *v13++ = v14;
+ --v15;
+ }
+ while ( v15 );
+ }
+ result += v10[5] - a2;
+ v13 += v8[5] - a2;
+ --v16;
+ }
+ while ( v16 );
+ }
+ return result;
+}
+
+//----- (010048EC) --------------------------------------------------------
+_BYTE *__stdcall gdrv_copy_bitmap_w_transparency(_DWORD *a1, int a2, int a3, int a4, int a5, _DWORD *a6, int a7, int a8)
+{
+ _DWORD *v8; // edx
+ int v9; // ecx
+ _DWORD *v10; // esi
+ int v11; // eax
+ _BYTE *result; // eax
+ _BYTE *v13; // ecx
+ int v14; // [esp+10h] [ebp+8h]
+ int v15; // [esp+24h] [ebp+1Ch]
+
+ v8 = a1;
+ v9 = a1[4];
+ v10 = a6;
+ v11 = a6[4];
+ if ( v11 < 0 )
+ v11 = -v11;
+ if ( v9 < 0 )
+ v9 = -v9;
+ result = (_BYTE *)(a7 + a6[2] + a6[5] * (v11 - a3 - a8));
+ v13 = (_BYTE *)(a4 + a1[2] + a1[5] * (v9 - a3 - a5));
+ if ( a3 > 0 )
+ {
+ v15 = a3;
+ do
+ {
+ if ( a2 > 0 )
+ {
+ v14 = a2;
+ do
+ {
+ if ( *result )
+ *v13 = *result;
+ ++result;
+ ++v13;
+ --v14;
+ }
+ while ( v14 );
+ }
+ result += v10[5] - a2;
+ v13 += v8[5] - a2;
+ --v15;
+ }
+ while ( v15 );
+ }
+ return result;
+}
+
+
+//----- (01003F10) --------------------------------------------------------
+HBRUSH __userpurge sub_1003F10@(LONG a1@, LONG a2@, int a3, int a4)
+{
+HBRUSH result; // eax
+HDC v5; // esi
+RECT rc; // [esp+0h] [ebp-18h]
+HGDIOBJ v7; // [esp+10h] [ebp-8h]
+HGDIOBJ h; // [esp+14h] [ebp-4h]
+
+result = CreateSolidBrush(0);
+h = result;
+if ( result )
+{
+v5 = _GetDC(hWnd);
+v7 = SelectObject(v5, h);
+if ( v5 )
+{
+rc.right = a3 + a1 + 1;
+rc.bottom = a4 + a2 + 1;
+rc.left = a1;
+rc.top = a2;
+FillRect(v5, &rc, (HBRUSH)h);
+ReleaseDC(hWnd, v5);
+}
+SelectObject(v5, v7);
+result = (HBRUSH)DeleteObject(h);
+}
+return result;
+}
+
+//----- (0100496C) --------------------------------------------------------
+int __stdcall zdrv_pad(int a1)
+{
+ int result; // eax
+
+ result = a1;
+ if ( a1 & 3 )
+ result = a1 - (a1 & 3) + 4;
+ return result;
+}
+
+//----- (01004989) --------------------------------------------------------
+signed int __stdcall zdrv_create_zmap(int a1, int a2, int a3)
+{
+ __int16 v3; // ax
+ int v4; // eax
+
+ v3 = zdrv_pad(a2);
+ *(_WORD *)(a1 + 4) = v3;
+ v4 = memoryallocate(2 * a3 * v3);
+ *(_DWORD *)(a1 + 6) = v4;
+ if ( !v4 )
+ return -1;
+ *(_DWORD *)(a1 + 10) = v4;
+ *(_WORD *)a1 = a2;
+ *(_WORD *)(a1 + 2) = a3;
+ return 0;
+}
+
+//----- (010049D6) --------------------------------------------------------
+signed int __stdcall zdrv_destroy_zmap(_DWORD *a1)
+{
+ int v2; // edi
+
+ if ( !a1 )
+ return -1;
+ if ( *(_DWORD *)((char *)a1 + 6) )
+ memoryfree(*(_DWORD *)((char *)a1 + 6));
+ *a1 = 0;
+ a1[1] = 0;
+ v2 = (int)(a1 + 2);
+ *(_DWORD *)v2 = 0;
+ *(_WORD *)(v2 + 4) = 0;
+ return 0;
+}
+
+//----- (01004A08) --------------------------------------------------------
+int __userpurge zdrv_fill@(int a1@, int a2, unsigned int a3, int a4, int a5, int a6, __int16 a7)
+{
+int result; // eax
+int v8; // esi
+char *v9; // edx
+unsigned int v10; // ecx
+unsigned __int8 v11; // cf
+unsigned int v12; // ecx
+char *v13; // edi
+int i; // ecx
+bool v15; // zf
+int v16; // [esp+Ch] [ebp+8h]
+
+result = a4;
+v8 = a2;
+v9 = (char *)(*(_DWORD *)(a2 + 6) + 2 * (a5 + *(signed __int16 *)(a2 + 4) * (*(signed __int16 *)(a2 + 2) - a4 - a6)));
+if ( a4 > 0 )
+{
+v10 = a3;
+v16 = a4;
+do
+{
+if ( (signed int)v10 > 0 )
+{
+LOWORD(a1) = a7;
+a1 <<= 16;
+LOWORD(a1) = a7;
+v11 = v10 & 1;
+v12 = v10 >> 1;
+memset32(v9, a1, v12);
+v13 = &v9[4 * v12];
+for ( i = v11; i; --i )
+{
+*(_WORD *)v13 = a7;
+v13 += 2;
+}
+v10 = a3;
+v9 += 2 * a3;
+}
+result = *(signed __int16 *)(v8 + 4) - v10;
+v15 = v16-- == 1;
+v9 += 2 * result;
+}
+while ( !v15 );
+}
+return result;
+}
+
+//----- (01004A76) --------------------------------------------------------
+_WORD *__stdcall zdrv_paint(int a1, int a2, _DWORD *a3, int a4, int a5, int a6, int a7, int a8, _DWORD *a9, int a10, int a11, int a12, int a13, int a14)
+{
+ int v14; // ecx
+ _DWORD *v15; // ebx
+ int v16; // eax
+ _WORD *v17; // edi
+ _WORD *result; // eax
+ bool v19; // zf
+ int v20; // [esp+18h] [ebp+Ch]
+ int v21; // [esp+24h] [ebp+18h]
+ _BYTE *v22; // [esp+38h] [ebp+2Ch]
+ _BYTE *v23; // [esp+3Ch] [ebp+30h]
+
+ v14 = a3[4];
+ v15 = a9;
+ v16 = a9[4];
+ if ( v16 < 0 )
+ v16 = -v16;
+ if ( v14 < 0 )
+ v14 = -v14;
+ v23 = (_BYTE *)(a10 + a9[2] + a9[5] * (v16 - a2 - a11));
+ v22 = (_BYTE *)(a4 + a3[2] + a3[5] * (v14 - a2 - a5));
+ v17 = (_WORD *)(*(_DWORD *)(a12 + 6)
+ + 2 * (a13 + *(signed __int16 *)(a12 + 4) * (*(signed __int16 *)(a12 + 2) - a2 - a14)));
+ result = (_WORD *)(*(_DWORD *)(a6 + 6)
+ + 2 * (a7 + *(signed __int16 *)(a6 + 4) * (*(signed __int16 *)(a6 + 2) - a2 - a8)));
+ if ( a2 )
+ {
+ v21 = a2;
+ while ( 1 )
+ {
+ if ( a1 )
+ {
+ v20 = a1;
+ do
+ {
+ if ( *result >= *v17 )
+ {
+ *v22 = *v23;
+ v15 = a9;
+ *result = *v17;
+ }
+ ++v23;
+ ++v22;
+ ++v17;
+ ++result;
+ --v20;
+ }
+ while ( v20 );
+ }
+ v23 += v15[5] - a1;
+ v22 += a3[5] - a1;
+ v17 += *(signed __int16 *)(a12 + 4) - a1;
+ v19 = v21-- == 1;
+ result += *(signed __int16 *)(a6 + 4) - a1;
+ if ( v19 )
+ break;
+ v15 = a9;
+ }
+ }
+ return result;
+}
+
+//----- (01004B75) --------------------------------------------------------
+unsigned __int16 *__stdcall zdrv_paint_flat(int a1, int a2, _DWORD *a3, int a4, int a5, int a6, int a7, int a8, _DWORD *a9, int a10, int a11, unsigned __int16 a12)
+{
+ _DWORD *v12; // esi
+ int v13; // ecx
+ _DWORD *v14; // edi
+ int v15; // eax
+ int v16; // ecx
+ unsigned __int16 *result; // eax
+ bool v18; // zf
+ int v19; // [esp+18h] [ebp+Ch]
+ _BYTE *v20; // [esp+1Ch] [ebp+10h]
+ _BYTE *v21; // [esp+34h] [ebp+28h]
+ int v22; // [esp+3Ch] [ebp+30h]
+
+ v12 = a3;
+ v13 = a3[4];
+ v14 = a9;
+ v15 = a9[4];
+ if ( v15 < 0 )
+ v15 = -v15;
+ if ( v13 < 0 )
+ v13 = -v13;
+ v16 = a3[2] + a3[5] * (v13 - a2 - a5);
+ v20 = (_BYTE *)(a10 + a9[2] + a9[5] * (v15 - a2 - a11));
+ v21 = (_BYTE *)(a4 + v16);
+ result = (unsigned __int16 *)(*(_DWORD *)(a6 + 6)
+ + 2 * (a7 + *(signed __int16 *)(a6 + 4) * (*(signed __int16 *)(a6 + 2) - a2 - a8)));
+ if ( a2 > 0 )
+ {
+ v22 = a2;
+ do
+ {
+ if ( a1 > 0 )
+ {
+ v19 = a1;
+ do
+ {
+ if ( *v20 )
+ {
+ if ( *result > a12 )
+ *v21 = *v20;
+ }
+ ++v20;
+ ++v21;
+ ++result;
+ --v19;
+ }
+ while ( v19 );
+ }
+ v20 += v14[5] - a1;
+ v21 += v12[5] - a1;
+ v18 = v22-- == 1;
+ result += *(signed __int16 *)(a6 + 4) - a1;
+ }
+ while ( !v18 );
+ }
+ return result;
+}
diff --git a/graphics/render.cpp b/graphics/render.cpp
new file mode 100644
index 0000000..dce8d4f
--- /dev/null
+++ b/graphics/render.cpp
@@ -0,0 +1,677 @@
+#include "pinball.h"
+
+//----- (0101304D) --------------------------------------------------------
+void __stdcall render_repaint(struct render_sprite_type_struct *a1)
+{
+int *v1; // edi
+bool v2; // zf
+bool v3; // sf
+int v4; // esi
+int v5; // [esp+8h] [ebp-10h]
+int v6; // [esp+Ch] [ebp-Ch]
+int v7; // [esp+10h] [ebp-8h]
+int v8; // [esp+14h] [ebp-4h]
+struct render_sprite_type_struct *v9; // [esp+20h] [ebp+8h]
+
+v1 = (int *)a1;
+if ( *((_DWORD *)a1 + 17) )
+{
+v2 = *((_DWORD *)a1 + 18) == 0;
+v3 = *((_DWORD *)a1 + 18) < 0;
+v9 = 0;
+if ( !v3 && !v2 )
+{
+do
+{
+v4 = *(_DWORD *)(v1[17] + 4 * (_DWORD)v9);
+if ( !*(_BYTE *)(v4 + 24) && *(_DWORD *)(v4 + 16) )
+{
+if ( rectangle_clip((int *)v4, v1 + 13, &v5) )
+zdrv_paint(
+v7,
+v8,
+&vscreen,
+v5,
+v6,
+(int)&zscreen,
+v5,
+v6,
+*(_DWORD **)(v4 + 16),
+v5 - *(_DWORD *)v4,
+v6 - *(_DWORD *)(v4 + 4),
+*(_DWORD *)(v4 + 20),
+v5 + *(_DWORD *)(v4 + 44) - *(_DWORD *)v4,
+v6 + *(_DWORD *)(v4 + 48) - *(_DWORD *)(v4 + 4));
+}
+v9 = (struct render_sprite_type_struct *)((char *)v9 + 1);
+}
+while ( (signed int)v9 < v1[18] );
+}
+}
+}
+
+//----- (010130F3) --------------------------------------------------------
+void __stdcall render_paint_balls()
+{
+int v0; // ecx
+int v1; // edi
+int i; // esi
+struct render_sprite_type_struct *v3; // edx
+struct render_sprite_type_struct **v4; // eax
+struct render_sprite_type_struct *v5; // ecx
+struct render_sprite_type_struct *v6; // edi
+int *v7; // esi
+int v8; // ebx
+int v9; // ST48_4
+int v10; // [esp+Ch] [ebp-10h]
+struct render_sprite_type_struct **v11; // [esp+10h] [ebp-Ch]
+_DWORD *v12; // [esp+14h] [ebp-8h]
+
+v0 = render_many_balls;
+if ( render_many_balls > 1 )
+{
+v1 = 0;
+if ( render_many_balls > 0 )
+{
+do
+{
+for ( i = v1; i < v0 / 2; ++i )
+{
+v3 = render_ball_list[i];
+v4 = &render_ball_list[v1];
+if ( *((_WORD *)*v4 + 13) > *((_WORD *)v3 + 13) )
+{
+v5 = *v4;
+*v4 = v3;
+render_ball_list[i] = v5;
+v0 = render_many_balls;
+}
+}
+++v1;
+}
+while ( v1 < v0 );
+}
+}
+v10 = 0;
+v11 = render_ball_list;
+if ( v0 > 0 )
+{
+v12 = &ball_bitmap;
+do
+{
+v6 = *v11;
+v7 = (int *)((char *)*v11 + 52);
+if ( *((_DWORD *)*v11 + 4) && rectangle_clip((int *)v6, (int *)&vscreen_rect, (_DWORD *)*v11 + 13) )
+{
+v8 = *v7;
+v9 = v7[1];
+gdrv_copy_bitmap(v12, v7[2], v7[3], 0, 0, &vscreen, *v7, v9);
+zdrv_paint_flat(
+v7[2],
+v7[3],
+&vscreen,
+v8,
+v9,
+(int)&zscreen,
+v8,
+v9,
+*((_DWORD **)v6 + 4),
+v8 - *(_DWORD *)v6,
+v9 - *((_DWORD *)v6 + 1),
+*((_WORD *)v6 + 13));
+}
+else
+{
+v7[2] = -1;
+}
+++v10;
+v12 = (_DWORD *)((char *)v12 + 37);
+++v11;
+}
+while ( v10 < render_many_balls );
+}
+}
+// 102506C: using guessed type struct render_sprite_type_struct **render_ball_list;
+// 1025070: using guessed type int render_many_balls;
+
+//----- (0101320D) --------------------------------------------------------
+void __stdcall render_unpaint_balls()
+{
+_DWORD *v0; // ebx
+struct render_sprite_type_struct *v1; // edi
+_DWORD *v2; // esi
+int v3; // eax
+_DWORD *v4; // edi
+_DWORD *v5; // esi
+bool v6; // zf
+int v7; // [esp+0h] [ebp-8h]
+struct render_sprite_type_struct **v8; // [esp+4h] [ebp-4h]
+
+v8 = &render_ball_list[render_many_balls - 1];
+if ( render_many_balls - 1 >= 0 )
+{
+v0 = (_DWORD *)((char *)&ball_bitmap + 37 * (render_many_balls - 1));
+v7 = render_many_balls;
+do
+{
+v1 = *v8;
+v2 = (_DWORD *)((char *)*v8 + 52);
+v3 = *((_DWORD *)*v8 + 15);
+if ( v3 > 0 )
+gdrv_copy_bitmap(&vscreen, v3, *((_DWORD *)*v8 + 16), *((_DWORD *)*v8 + 13), *((_DWORD *)*v8 + 14), v0, 0, 0);
+--v8;
+v4 = (_DWORD *)((char *)v1 + 28);
+*v4 = *v2;
+v5 = v2 + 1;
+++v4;
+*v4 = *v5;
+++v5;
+++v4;
+*v4 = *v5;
+v0 = (_DWORD *)((char *)v0 - 37);
+v6 = v7-- == 1;
+v4[1] = v5[1];
+}
+while ( !v6 );
+}
+}
+// 102506C: using guessed type struct render_sprite_type_struct **render_ball_list;
+// 1025070: using guessed type int render_many_balls;
+
+//----- (01013283) --------------------------------------------------------
+int __stdcall render_remove_sprite(struct render_sprite_type_struct *a1)
+{
+int v1; // eax
+int v2; // ecx
+
+v1 = render_many_sprites;
+v2 = 0;
+if ( render_many_sprites <= 0 )
+return 0;
+while ( render_sprite_list[v2] != a1 )
+{
+if ( ++v2 >= render_many_sprites )
+return 0;
+}
+while ( v2 < v1 )
+{
+render_sprite_list[v2] = render_sprite_list[v2 + 1];
+v1 = render_many_sprites;
+++v2;
+}
+render_many_sprites = v1 - 1;
+if ( *((_DWORD *)a1 + 17) )
+memoryfree(*((_DWORD *)a1 + 17));
+memoryfree((int)a1);
+return 1;
+}
+// 1025084: using guessed type struct render_sprite_type_struct **render_sprite_list;
+// 10250B4: using guessed type int render_many_sprites;
+
+//----- (010132E8) --------------------------------------------------------
+int __stdcall render_remove_ball(struct render_sprite_type_struct *a1)
+{
+int v1; // eax
+int v2; // ecx
+
+v1 = render_many_balls;
+v2 = 0;
+if ( render_many_balls <= 0 )
+return 0;
+while ( render_ball_list[v2] != a1 )
+{
+if ( ++v2 >= render_many_balls )
+return 0;
+}
+while ( v2 < v1 )
+{
+render_ball_list[v2] = render_ball_list[v2 + 1];
+v1 = render_many_balls;
+++v2;
+}
+render_many_balls = v1 - 1;
+memoryfree((int)a1);
+return 1;
+}
+// 102506C: using guessed type struct render_sprite_type_struct **render_ball_list;
+// 1025070: using guessed type int render_many_balls;
+
+//----- (010133C7) --------------------------------------------------------
+void __stdcall render_update()
+{
+int i; // eax
+int *v1; // esi
+int *v2; // edi
+struct render_sprite_type_struct **v3; // esi
+int v4; // edi
+struct render_sprite_type_struct *v5; // eax
+struct render_sprite_type_struct *v6; // edi
+int *v7; // esi
+int v8; // edx
+struct render_sprite_type_struct *v9; // eax
+int *v10; // edi
+bool v11; // zf
+int *v12; // esi
+int *v13; // edi
+int *v14; // esi
+int v15; // eax
+unsigned int v16; // ecx
+int v17; // edi
+int v18; // esi
+int v19; // edx
+int v20; // edx
+int xSrc; // [esp+Ch] [ebp-24h]
+int v22; // [esp+10h] [ebp-20h]
+int v23; // [esp+14h] [ebp-1Ch]
+int v24; // [esp+18h] [ebp-18h]
+struct render_sprite_type_struct *v25; // [esp+1Ch] [ebp-14h]
+int v26; // [esp+20h] [ebp-10h]
+int v27; // [esp+24h] [ebp-Ch]
+int v28; // [esp+28h] [ebp-8h]
+struct render_sprite_type_struct **j; // [esp+2Ch] [ebp-4h]
+
+v28 = 0;
+j = render_dirty_list;
+for ( i = render_many_dirty; v28 < render_many_dirty; ++j )
+{
+v1 = (int *)*j;
+if ( *((_BYTE *)*j + 25) )
+{
+if ( *((_BYTE *)*j + 25) == 1 )
+{
+if ( v1[9] > 0 )
+enclosing_box(v1 + 7, v1, v1 + 13);
+v2 = v1 + 13;
+if ( rectangle_clip(v1 + 13, (int *)&vscreen_rect, v1 + 13) )
+{
+LABEL_29:
+v15 = v1[14];
+v16 = v1[15];
+v17 = *v2;
+v18 = v1[16];
+v27 = v15;
+v26 = v16;
+zdrv_fill((int)&vscreen, (int)&zscreen, v16, v18, v17, v15, 0xFFFF);
+if ( render_background_bitmap )
+gdrv_copy_bitmap(&vscreen, v26, v18, v17, v27, (_DWORD *)render_background_bitmap, v17, v27);
+else
+gdrv_fill_bitmap((int)&vscreen, &vscreen, v26, v18, v17, v27, 0);
+goto LABEL_8;
+}
+LABEL_7:
+v1[15] = -1;
+goto LABEL_8;
+}
+}
+else
+{
+v2 = v1 + 13;
+if ( !rectangle_clip(v1, (int *)&vscreen_rect, v1 + 13) )
+goto LABEL_7;
+if ( !v1[4] )
+goto LABEL_29;
+}
+LABEL_8:
+++v28;
+i = render_many_dirty;
+}
+v3 = render_dirty_list;
+v4 = 0;
+if ( i > 0 )
+{
+do
+{
+v5 = *v3;
+if ( *((_DWORD *)*v3 + 15) > 0 && (!*((_BYTE *)v5 + 25) || *((_BYTE *)v5 + 25) == 1) )
+render_repaint(*v3);
+++v4;
+++v3;
+}
+while ( v4 < render_many_dirty );
+}
+render_paint_balls();
+if ( render_blit )
+{
+gdrv_start_blit_sequence();
+v27 = xDest + render_offset_x;
+v26 = yDest + render_offset_y;
+v28 = 0;
+for ( j = render_dirty_list; v28 < render_many_dirty; ++j )
+{
+v6 = *j;
+v7 = (int *)((char *)*j + 52);
+v8 = *((_DWORD *)*j + 15);
+v25 = *j;
+if ( v8 > 0 )
+gdrv_blit_sequence((int)&vscreen, *v7, v7[1], *v7 + v27, v7[1] + v26, v8, v7[3]);
+v9 = v25;
+v10 = (int *)((char *)v6 + 28);
+v11 = *((_BYTE *)v25 + 24) == 0;
+*v10 = *v7;
+v12 = v7 + 1;
+++v10;
+*v10 = *v12;
+++v12;
+++v10;
+*v10 = *v12;
+v10[1] = v12[1];
+if ( !v11 )
+render_remove_sprite(v9);
+++v28;
+}
+v28 = 0;
+for ( j = render_ball_list; v28 < render_many_balls; ++j )
+{
+v13 = (int *)((char *)*j + 28);
+v14 = (int *)((char *)*j + 52);
+if ( overlapping_box((struct rectangle_type *)v14, (struct rectangle_type *)v13, (struct rectangle_type *)&xSrc)
+&& *((_DWORD *)*j + 15) > 0 )
+{
+if ( v23 > 0 )
+gdrv_blit_sequence((int)&vscreen, xSrc, v22, xSrc + v27, v22 + v26, v23, v24);
+}
+else
+{
+v19 = v14[2];
+if ( v19 > 0 )
+gdrv_blit_sequence((int)&vscreen, *v14, v14[1], *v14 + v27, v14[1] + v26, v19, v14[3]);
+v20 = v13[2];
+if ( v20 > 0 )
+gdrv_blit_sequence((int)&vscreen, *v13, v13[1], *v13 + v27, v13[1] + v26, v20, v13[3]);
+}
+++v28;
+}
+gdrv_end_blit_sequence();
+}
+render_many_dirty = 0;
+render_unpaint_balls();
+}
+// 1024754: using guessed type int render_blit;
+// 1025068: using guessed type struct render_sprite_type_struct **render_dirty_list;
+// 102506C: using guessed type struct render_sprite_type_struct **render_ball_list;
+// 1025070: using guessed type int render_many_balls;
+// 10250C0: using guessed type int render_many_dirty;
+// 10253AC: using guessed type int render_offset_x;
+// 10253B0: using guessed type int render_offset_y;
+
+//----- (01013670) --------------------------------------------------------
+void __stdcall render_uninit()
+{
+int i; // esi
+int j; // esi
+
+gdrv_destroy_bitmap((int)&vscreen);
+zdrv_destroy_zmap(&zscreen);
+for ( i = 0; i < render_many_sprites; ++i )
+render_remove_sprite(render_sprite_list[i]);
+for ( j = 0; j < render_many_balls; ++j )
+render_remove_ball(render_ball_list[j]);
+memoryfree((int)render_ball_list);
+memoryfree((int)render_dirty_list);
+memoryfree((int)render_sprite_list);
+render_many_sprites = 0;
+render_many_dirty = 0;
+render_many_balls = 0;
+}
+// 1025068: using guessed type struct render_sprite_type_struct **render_dirty_list;
+// 102506C: using guessed type struct render_sprite_type_struct **render_ball_list;
+// 1025070: using guessed type int render_many_balls;
+// 1025084: using guessed type struct render_sprite_type_struct **render_sprite_list;
+// 10250B4: using guessed type int render_many_sprites;
+// 10250C0: using guessed type int render_many_dirty;
+
+//----- (01013705) --------------------------------------------------------
+char *__stdcall render_init(_DWORD *a1, float a2, float a3, int a4, int a5)
+{
+int v5; // edi
+char *result; // eax
+char *v7; // [esp+18h] [ebp+18h]
+
+++memory_critical_allocation;
+render_zscaler = a3;
+render_zmin = a2;
+render_zmax = 4294967300.0 / a3 + a2;
+render_sprite_list = (struct render_sprite_type_struct **)memoryallocate(0xFA0u);
+render_dirty_list = (struct render_sprite_type_struct **)memoryallocate(0xFA0u);
+render_ball_list = (struct render_sprite_type_struct **)memoryallocate(0x50u);
+gdrv_create_bitmap((int)&vscreen, a4, a5);
+zdrv_create_zmap((int)&zscreen, a4, a5);
+zdrv_fill((int)&vscreen, (int)&zscreen, zscreen, word_102505A, 0, 0, 0xFFFF);
+v5 = a5;
+dword_1025078 = 0;
+vscreen_rect = 0;
+dword_102507C = a4;
+dword_1025080 = a5;
+yDest = 0;
+xDest = 0;
+v7 = (char *)&ball_bitmap;
+do
+{
+gdrv_create_raw_bitmap((int)v7, 64, 64, 1);
+v7 += 37;
+}
+while ( (signed int)v7 < (signed int)&render_offset_x );
+render_background_bitmap = (int)a1;
+if ( a1 )
+result = gdrv_copy_bitmap(&vscreen, a4, v5, 0, 0, a1, 0, 0);
+else
+result = (char *)gdrv_fill_bitmap((int)&vscreen, &vscreen, dword_1025094, dword_1025098, 0, 0, 0);
+--memory_critical_allocation;
+return result;
+}
+// 1024F04: using guessed type int memory_critical_allocation;
+// 102505A: using guessed type __int16 word_102505A;
+// 1025068: using guessed type struct render_sprite_type_struct **render_dirty_list;
+// 102506C: using guessed type struct render_sprite_type_struct **render_ball_list;
+// 1025078: using guessed type int dword_1025078;
+// 102507C: using guessed type int dword_102507C;
+// 1025080: using guessed type int dword_1025080;
+// 1025084: using guessed type struct render_sprite_type_struct **render_sprite_list;
+// 1025094: using guessed type int dword_1025094;
+// 1025098: using guessed type int dword_1025098;
+// 10250B0: using guessed type float render_zscaler;
+// 10250B8: using guessed type float render_zmax;
+// 10250BC: using guessed type float render_zmin;
+// 10253AC: using guessed type int render_offset_x;
+
+//----- (0101382A) --------------------------------------------------------
+int __stdcall render_sprite_modified(int a1)
+{
+int result; // eax
+
+if ( *(_BYTE *)(a1 + 25) != 2 )
+{
+result = render_many_dirty;
+if ( render_many_dirty < 999 )
+render_dirty_list[render_many_dirty++] = (struct render_sprite_type_struct *)a1;
+}
+return result;
+}
+// 1025068: using guessed type struct render_sprite_type_struct **render_dirty_list;
+// 10250C0: using guessed type int render_many_dirty;
+
+//----- (0101385C) --------------------------------------------------------
+int __stdcall render_create_sprite(int a1, int a2, int a3, int a4, int a5, _DWORD *a6)
+{
+int v6; // ebx
+int result; // eax
+
+v6 = memoryallocate(0x5Cu);
+result = 0;
+if ( v6 )
+{
+*(_DWORD *)(v6 + 4) = a5;
+*(_DWORD *)(v6 + 16) = a2;
+*(_DWORD *)v6 = a4;
+*(_BYTE *)(v6 + 25) = a1;
+*(_BYTE *)(v6 + 24) = 0;
+*(_DWORD *)(v6 + 68) = 0;
+*(_DWORD *)(v6 + 72) = 0;
+if ( a6 )
+{
+*(_DWORD *)(v6 + 76) = *a6;
+*(_DWORD *)(v6 + 80) = a6[1];
+*(_DWORD *)(v6 + 84) = a6[2];
+*(_DWORD *)(v6 + 88) = a6[3];
+}
+else
+{
+*(_DWORD *)(v6 + 84) = -1;
+*(_DWORD *)(v6 + 88) = -1;
+*(_DWORD *)(v6 + 76) = 0;
+*(_DWORD *)(v6 + 80) = 0;
+}
+if ( a2 )
+{
+*(_DWORD *)(v6 + 8) = *(_DWORD *)(a2 + 12);
+*(_DWORD *)(v6 + 12) = *(_DWORD *)(a2 + 16);
+}
+else
+{
+*(_DWORD *)(v6 + 8) = 0;
+*(_DWORD *)(v6 + 12) = 0;
+}
+*(_DWORD *)(v6 + 20) = a3;
+*(_DWORD *)(v6 + 48) = 0;
+*(_DWORD *)(v6 + 44) = 0;
+if ( !a3 && a1 != 2 )
+{
+*(_DWORD *)(v6 + 20) = render_background_zmap;
+*(_DWORD *)(v6 + 44) = a4 - render_zmap_offset;
+*(_DWORD *)(v6 + 48) = a5 - dword_10253C0;
+}
+*(_DWORD *)(v6 + 28) = *(_DWORD *)v6;
+*(_DWORD *)(v6 + 32) = *(_DWORD *)(v6 + 4);
+*(_DWORD *)(v6 + 36) = *(_DWORD *)(v6 + 8);
+*(_DWORD *)(v6 + 40) = *(_DWORD *)(v6 + 12);
+if ( a1 == 2 )
+{
+render_ball_list[render_many_balls++] = (struct render_sprite_type_struct *)v6;
+}
+else
+{
+render_sprite_list[render_many_sprites++] = (struct render_sprite_type_struct *)v6;
+render_sprite_modified(v6);
+}
+result = v6;
+}
+return result;
+}
+// 102506C: using guessed type struct render_sprite_type_struct **render_ball_list;
+// 1025070: using guessed type int render_many_balls;
+// 1025084: using guessed type struct render_sprite_type_struct **render_sprite_list;
+// 10250B4: using guessed type int render_many_sprites;
+// 10253B8: using guessed type struct zmap_header_type *render_background_zmap;
+// 10253C0: using guessed type int dword_10253C0;
+
+//----- (0101394E) --------------------------------------------------------
+int __stdcall render_set_background_zmap(struct zmap_header_type *a1, int a2, int a3)
+{
+int result; // eax
+
+render_background_zmap = a1;
+render_zmap_offset = a2;
+result = a3;
+dword_10253C0 = a3;
+return result;
+}
+// 10253B8: using guessed type struct zmap_header_type *render_background_zmap;
+// 10253C0: using guessed type int dword_10253C0;
+
+//----- (01013974) --------------------------------------------------------
+int __stdcall render_sprite_set(_DWORD *a1, int a2, int a3, int a4, int a5)
+{
+int result; // eax
+
+result = (int)a1;
+if ( a1 )
+{
+*a1 = a4;
+a1[1] = a5;
+a1[4] = a2;
+if ( a2 )
+{
+a1[2] = *(_DWORD *)(a2 + 12);
+a1[3] = *(_DWORD *)(a2 + 16);
+}
+a1[5] = a3;
+result = render_sprite_modified((int)a1);
+}
+return result;
+}
+
+//----- (010139B6) --------------------------------------------------------
+void __stdcall render_sprite_set_bitmap(_DWORD *a1, int a2)
+{
+if ( a1 && a1[4] != a2 )
+{
+a1[4] = a2;
+if ( a2 )
+{
+a1[2] = *(_DWORD *)(a2 + 12);
+a1[3] = *(_DWORD *)(a2 + 16);
+}
+render_sprite_modified((int)a1);
+}
+}
+
+//----- (010139EC) --------------------------------------------------------
+void __stdcall render_ball_set(int a1, int a2, float a3, int a4, int a5)
+{
+double v5; // st7
+
+if ( a1 )
+{
+*(_DWORD *)(a1 + 16) = a2;
+if ( a2 )
+{
+*(_DWORD *)a1 = a4;
+*(_DWORD *)(a1 + 4) = a5;
+*(_DWORD *)(a1 + 8) = *(_DWORD *)(a2 + 12);
+*(_DWORD *)(a1 + 12) = *(_DWORD *)(a2 + 16);
+}
+if ( a3 >= (double)render_zmin )
+{
+v5 = (a3 - render_zmin) * render_zscaler;
+if ( v5 <= render_zmax )
+*(_WORD *)(a1 + 26) = (signed __int64)v5;
+else
+*(_WORD *)(a1 + 26) = -1;
+}
+else
+{
+*(_WORD *)(a1 + 26) = 0;
+}
+}
+}
+// 10250B0: using guessed type float render_zscaler;
+// 10250B8: using guessed type float render_zmax;
+// 10250BC: using guessed type float render_zmin;
+
+//----- (01013A6A) --------------------------------------------------------
+void __stdcall render_paint()
+{
+render_paint_balls();
+gdrv_blat((int)&vscreen, xDest, yDest);
+render_unpaint_balls();
+}
+
+//----- (01013A8F) --------------------------------------------------------
+void __stdcall render_shift(int a1, int a2, int xSrc, int a4, int DestWidth, int DestHeight)
+{
+render_offset_x += a1;
+render_offset_y += a2;
+render_paint_balls();
+gdrv_blit(
+(int)&vscreen,
+xSrc,
+a4,
+xSrc + render_offset_x + xDest,
+a4 + render_offset_y + yDest,
+DestWidth,
+DestHeight);
+render_unpaint_balls();
+}
+// 10253AC: using guessed type int render_offset_x;
+// 10253B0: using guessed type int render_offset_y;
+
diff --git a/graphics/splash.cpp b/graphics/splash.cpp
new file mode 100644
index 0000000..12a4ea9
--- /dev/null
+++ b/graphics/splash.cpp
@@ -0,0 +1,373 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+//----- (01006D96) --------------------------------------------------------
+HPALETTE __stdcall splash_init_palette(LOGPALETTE *plpal)
+{
+ LOGPALETTE *v1; // edi
+ HWND v2; // eax
+ HDC v3; // ebx
+ HWND v4; // eax
+ HPALETTE result; // eax
+ HPALETTE hPal; // ST1C_4
+ HWND v7; // eax
+ BYTE *v8; // eax
+ signed int v9; // ecx
+ signed int v10; // ecx
+ BYTE *v11; // eax
+ HPALETTE plpala; // [esp+18h] [ebp+8h]
+
+ v1 = plpal;
+ plpal->palVersion = 768;
+ plpal->palNumEntries = 256;
+ plpala = CreatePalette(plpal);
+ v2 = GetDesktopWindow();
+ v3 = _GetDC(v2);
+ GetDeviceCaps(v3, 38);
+ if ( GetDeviceCaps(v3, 104) == 256 )
+ {
+ SetSystemPaletteUse(v3, 2u);
+ SetSystemPaletteUse(v3, 1u);
+ hPal = SelectPalette(v3, plpala, 0);
+ RealizePalette(v3);
+ SelectPalette(v3, hPal, 0);
+ RealizePalette(v3);
+ GetSystemPaletteEntries(v3, 0, 0x100u, v1->palPalEntry);
+ v7 = GetDesktopWindow();
+ ReleaseDC(v7, v3);
+ v8 = &v1->palPalEntry[0].peFlags;
+ v9 = 256;
+ do
+ {
+ *v8 = 0;
+ v8 += 4;
+ --v9;
+ }
+ while ( v9 );
+ v10 = 10;
+ v11 = &v1[5].palPalEntry[0].peGreen;
+ do
+ {
+ *(v11 - 1) = v10;
+ *v11 = v10;
+ v11[1] = v10;
+ v11[2] = 4;
+ ++v10;
+ v11 += 4;
+ }
+ while ( v10 < 246 );
+ ResizePalette(plpala, 0x100u);
+ SetPaletteEntries(plpala, 0, 0x100u, v1->palPalEntry);
+ result = plpala;
+ }
+ else
+ {
+ if ( plpala )
+ DeleteObject(plpala);
+ v4 = GetDesktopWindow();
+ ReleaseDC(v4, v3);
+ result = 0;
+ }
+ return result;
+}
+
+//----- (01006EB9) --------------------------------------------------------
+HBITMAP __stdcall load_title_bitmap(HMODULE hModule, HDC hdc, LPCSTR lpName, UINT iStart, int a5, int a6)
+{
+ HRSRC v6; // eax
+ HGLOBAL v7; // eax
+ const BITMAPINFO *v9; // eax
+ const BITMAPINFO *v10; // esi
+ signed int v11; // edi
+ bool v12; // cf
+ bool v13; // zf
+ BYTE *v14; // ecx
+ BYTE *v15; // edx
+ HBITMAP v16; // esi
+ LOGPALETTE plpal; // [esp+0h] [ebp-40Ch]
+ void *pjBits; // [esp+404h] [ebp-8h]
+ HGLOBAL hResData; // [esp+408h] [ebp-4h]
+ HMODULE hModulea; // [esp+414h] [ebp+8h]
+ HPALETTE lpNamea; // [esp+41Ch] [ebp+10h]
+
+ v6 = FindResourceA(hModule, lpName, (LPCSTR)2);
+ if ( !v6 )
+ return 0;
+ v7 = LoadResource(hModule, v6);
+ hResData = v7;
+ if ( !v7 )
+ return 0;
+ v9 = (const BITMAPINFO *)LockResource(v7);
+ v10 = v9;
+ v11 = v9->bmiHeader.biClrUsed;
+ if ( !v11 )
+ v11 = 1 << LOBYTE(v9->bmiHeader.biBitCount);
+ v12 = v9->bmiHeader.biBitCount < 4u;
+ v13 = v9->bmiHeader.biBitCount == 4;
+ pjBits = &v9->bmiColors[v11];
+ if ( !v12 && !v13 )
+ {
+ lpNamea = splash_init_palette(&plpal);
+ *(_DWORD *)a6 = lpNamea;
+ if ( lpNamea )
+ {
+ hModulea = 0;
+ if ( a5 > 0 )
+ {
+ v14 = &plpal.palPalEntry[iStart].peGreen;
+ v15 = &v10->bmiColors[0].rgbGreen;
+ do
+ {
+ if ( (signed int)hModulea >= v11 )
+ break;
+ hModulea = (HMODULE)((char *)hModulea + 1);
+ *(v14 - 1) = v15[1];
+ *v14 = *v15;
+ v14[1] = *(v15 - 1);
+ v14[2] = 4;
+ v15 += 4;
+ v14 += 4;
+ }
+ while ( (signed int)hModulea < a5 );
+ }
+ SetPaletteEntries(lpNamea, iStart, (UINT)hModulea, &plpal.palPalEntry[iStart]);
+ SelectPalette(hdc, *(HPALETTE *)a6, 0);
+ RealizePalette(hdc);
+ }
+ }
+ v16 = CreateDIBitmap(hdc, &v10->bmiHeader, 4u, pjBits, v10, 0);
+ FreeResource(hResData);
+ return v16;
+}
+
+//----- (01006FCB) --------------------------------------------------------
+int __stdcall splash_bitmap_setup(int a1)
+{
+ HWND v1; // eax
+ HDC v2; // eax
+ HDC v3; // edi
+ HBITMAP v4; // eax
+ HWND v5; // ST14_4
+ HDC v6; // eax
+ HBITMAP v7; // eax
+ int result; // eax
+ char pv; // [esp+8h] [ebp-1Ch]
+ int v10; // [esp+Ch] [ebp-18h]
+ int v11; // [esp+10h] [ebp-14h]
+ HGDIOBJ h; // [esp+20h] [ebp-4h]
+
+ h = 0;
+ v1 = GetDesktopWindow();
+ v2 = _GetDC(v1);
+ v3 = v2;
+ if ( v2 )
+ {
+ *(_DWORD *)(a1 + 12) = CreateCompatibleDC(v2);
+ v4 = CreateCompatibleBitmap(v3, 10, 10);
+ v5 = *(HWND *)a1;
+ h = v4;
+ ReleaseDC(v5, v3);
+ if ( h )
+ {
+ v6 = *(HDC *)(a1 + 12);
+ if ( v6 )
+ {
+ SelectObject(v6, h);
+ if ( GetDeviceCaps(*(HDC *)(a1 + 12), 38) & 0x100 || GetDeviceCaps(*(HDC *)(a1 + 12), 24) >= 256 )
+ v7 = load_title_bitmap(hInstance, *(HDC *)(a1 + 12), (LPCSTR)(a1 + 32), 0xAu, 236, a1 + 4);
+ else
+ v7 = LoadBitmapA(hInstance, (LPCSTR)(a1 + 232));
+ *(_DWORD *)(a1 + 8) = v7;
+ if ( v7 )
+ {
+ SelectObject(*(HDC *)(a1 + 12), v7);
+ DeleteObject(h);
+ GetObjectA(*(HANDLE *)(a1 + 8), 24, &pv);
+ *(_DWORD *)(a1 + 16) = v10;
+ result = v11;
+ *(_DWORD *)(a1 + 20) = v11;
+ return result;
+ }
+ }
+ }
+ else
+ {
+ GetLastError();
+ }
+ }
+ if ( *(_DWORD *)(a1 + 4) )
+ DeleteObject(*(HGDIOBJ *)(a1 + 4));
+ if ( *(_DWORD *)a1 )
+ DestroyWindow(*(HWND *)a1);
+ if ( h )
+ DeleteObject(h);
+ result = *(_DWORD *)(a1 + 12);
+ if ( result )
+ result = DeleteDC(*(HDC *)(a1 + 12));
+ *(_DWORD *)(a1 + 8) = 0;
+ return result;
+}
+
+//----- (01007103) --------------------------------------------------------
+void __stdcall splash_paint(int a1, HDC hdc)
+{
+ HWND v2; // eax
+ HPALETTE v3; // ST1C_4
+ struct tagRECT Rect; // [esp+4h] [ebp-10h]
+
+ if ( *(_DWORD *)(a1 + 8) )
+ {
+ v2 = GetDesktopWindow();
+ GetWindowRect(v2, &Rect);
+ v3 = *(HPALETTE *)(a1 + 4);
+ *(_DWORD *)(a1 + 24) = (Rect.right - Rect.left - *(_DWORD *)(a1 + 16)) / 2;
+ *(_DWORD *)(a1 + 28) = (Rect.bottom - Rect.top - *(_DWORD *)(a1 + 20)) / 2;
+ SelectPalette(hdc, v3, 0);
+ RealizePalette(hdc);
+ SelectPalette(*(HDC *)(a1 + 12), *(HPALETTE *)(a1 + 4), 0);
+ RealizePalette(*(HDC *)(a1 + 12));
+ BitBlt(
+ hdc,
+ *(_DWORD *)(a1 + 24),
+ *(_DWORD *)(a1 + 28),
+ *(_DWORD *)(a1 + 16),
+ *(_DWORD *)(a1 + 20),
+ *(HDC *)(a1 + 12),
+ 0,
+ 0,
+ 0xCC0020u);
+ }
+}
+
+//----- (010071A5) --------------------------------------------------------
+void __stdcall splash_hide(int a1)
+{
+ HDC v1; // edi
+
+ if ( a1 )
+ {
+ if ( *(_DWORD *)a1 )
+ {
+ v1 = _GetDC(*(HWND *)a1);
+ BitBlt(v1, 0, 0, *(_DWORD *)(a1 + 24), *(_DWORD *)(a1 + 28), v1, 0, 0, 0x42u);
+ ReleaseDC(*(HWND *)a1, v1);
+ }
+ }
+}
+
+//----- (010071ED) --------------------------------------------------------
+HINSTANCE __stdcall splash_destroy(int a1)
+{
+ void *v1; // eax
+ HDC v2; // eax
+ HINSTANCE result; // eax
+
+ if ( a1 )
+ {
+ if ( *(_DWORD *)a1 )
+ {
+ DestroyWindow(*(HWND *)a1);
+ v1 = *(void **)(a1 + 4);
+ *(_DWORD *)a1 = 0;
+ if ( v1 )
+ DeleteObject(v1);
+ v2 = *(HDC *)(a1 + 12);
+ *(_DWORD *)(a1 + 4) = 0;
+ if ( v2 )
+ DeleteDC(v2);
+ if ( *(_DWORD *)(a1 + 8) )
+ DeleteObject(*(HGDIOBJ *)(a1 + 8));
+ }
+ memoryfree(a1);
+ }
+ result = hInstance;
+ if ( hInstance )
+ {
+ result = (HINSTANCE)UnregisterClassA("3DPB_SPLASH_CLASS", hInstance);
+ hInstance = 0;
+ }
+ return result;
+}
+
+//----- (01007264) --------------------------------------------------------
+LRESULT __stdcall splash_message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ HDC v5; // eax
+ HDC v6; // esi
+ LONG v7; // [esp+4h] [ebp-48h]
+ struct tagPAINTSTRUCT Paint; // [esp+8h] [ebp-44h]
+
+ if ( Msg == 15 )
+ {
+ v7 = GetWindowLongA(hWnd, 0);
+ BeginPaint(hWnd, &Paint);
+ EndPaint(hWnd, &Paint);
+ v5 = _GetDC(hWnd);
+ v6 = v5;
+ if ( v5 )
+ {
+ if ( v7 )
+ {
+ BitBlt(v5, 0, 0, 10000, 10000, v5, 0, 0, 0x42u);
+ splash_paint(v7, v6);
+ }
+ }
+ ReleaseDC(hWnd, v6);
+ }
+ else if ( Msg != 20 )
+ {
+ return DefWindowProcA(hWnd, Msg, wParam, lParam);
+ }
+ return 0;
+}
+
+//----- (01007308) --------------------------------------------------------
+int __stdcall splash_screen(int a1, LPCSTR lpString2, LPCSTR a3)
+{
+ int v3; // esi
+ HINSTANCE v4; // ST28_4
+ HWND v5; // eax
+ HWND v7; // eax
+ WNDCLASSA WndClass; // [esp+8h] [ebp-38h]
+ struct tagRECT Rect; // [esp+30h] [ebp-10h]
+
+ v3 = memoryallocate(0x1B0u);
+ if ( !v3 )
+ return 0;
+ lstrcpyA((LPSTR)(v3 + 32), lpString2);
+ lstrcpyA((LPSTR)(v3 + 232), a3);
+ if ( !hInstance )
+ {
+ hInstance = (HINSTANCE)a1;
+ WndClass.style = 0;
+ WndClass.lpfnWndProc = splash_message_handler;
+ WndClass.cbClsExtra = 0;
+ WndClass.cbWndExtra = 4;
+ WndClass.hInstance = (HINSTANCE)a1;
+ WndClass.hIcon = 0;
+ WndClass.hCursor = LoadCursorA(0, (LPCSTR)0x7F00);
+ WndClass.hbrBackground = 0;
+ WndClass.lpszMenuName = WindowName;
+ WndClass.lpszClassName = "3DPB_SPLASH_CLASS";
+ RegisterClassA(&WndClass);
+ }
+ v4 = hInstance;
+ *(_DWORD *)(v3 + 8) = 0;
+ v5 = CreateWindowExA(0, "3DPB_SPLASH_CLASS", WindowName, 0x80000000, -10, -10, 1, 1, 0, 0, v4, 0);
+ *(_DWORD *)v3 = v5;
+ if ( !v5 )
+ {
+ memoryfree(v3);
+ return 0;
+ }
+ SetWindowLongA(v5, 0, v3);
+ v7 = GetDesktopWindow();
+ GetWindowRect(v7, &Rect);
+ splash_bitmap_setup(v3);
+ MoveWindow(*(HWND *)v3, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top, 0);
+ ShowWindow(*(HWND *)v3, 8);
+ SetFocus(*(HWND *)v3);
+ UpdateWindow(*(HWND *)v3);
+ return v3;
+}
\ No newline at end of file
diff --git a/graphics/timer.cpp b/graphics/timer.cpp
new file mode 100644
index 0000000..a0d5248
--- /dev/null
+++ b/graphics/timer.cpp
@@ -0,0 +1,224 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "../pinball.h"
+
+//----- (0100742F) --------------------------------------------------------
+signed int __stdcall timer_init(int a1)
+{
+ int v1; // eax
+ int v3; // edx
+ _DWORD *v4; // ecx
+
+ v1 = memoryallocate(20 * a1);
+ dword_1024F80 = v1;
+ if ( !v1 )
+ return 1;
+ dword_1024F78 = 0;
+ v3 = a1 - 1;
+ dword_1024F74 = a1;
+ dword_10235F4 = 1;
+ if ( a1 - 1 > 0 )
+ {
+ v4 = (_DWORD *)(v1 + 12);
+ do
+ {
+ *v4 = v4 + 2;
+ v4 += 5;
+ --v3;
+ }
+ while ( v3 );
+ }
+ *(_DWORD *)(20 * a1 + v1 - 8) = 0;
+ dword_1024F70 = 0;
+ dword_1024F7C = v1;
+ return 0;
+}
+// 10235F4: using guessed type int dword_10235F4;
+// 1024F70: using guessed type int dword_1024F70;
+// 1024F74: using guessed type int dword_1024F74;
+// 1024F78: using guessed type int dword_1024F78;
+// 1024F7C: using guessed type int dword_1024F7C;
+// 1024F80: using guessed type int dword_1024F80;
+
+//----- (0100749B) --------------------------------------------------------
+void __stdcall timer_uninit()
+{
+ if ( dword_1024F80 )
+ memoryfree(dword_1024F80);
+ dword_1024F80 = 0;
+}
+// 1024F80: using guessed type int dword_1024F80;
+
+//----- (010074B7) --------------------------------------------------------
+int __stdcall timer_set(float a1, int a2, int a3)
+{
+ signed __int64 v3; // rax
+ int v4; // esi
+ int v5; // ebx
+ _DWORD *v7; // ecx
+ _DWORD *v8; // eax
+ int v9; // edx
+ _DWORD *v10; // edi
+ int v11; // eax
+ int v12; // [esp+0h] [ebp-8h]
+ int v13; // [esp+4h] [ebp-4h]
+ int v14; // [esp+10h] [ebp+8h]
+
+ v3 = (signed __int64)(a1 * -1000.0);
+ v4 = dword_1024F78;
+ v5 = time_ticks - v3;
+ v12 = time_ticks - v3;
+ if ( dword_1024F78 >= dword_1024F74 )
+ return 0;
+ v14 = 0;
+ v7 = (_DWORD *)dword_1024F7C;
+ v8 = (_DWORD *)(dword_1024F7C + 12);
+ v9 = *(_DWORD *)(dword_1024F7C + 12);
+ *(_DWORD *)(dword_1024F7C + 12) = 0;
+ dword_1024F7C = v9;
+ v13 = dword_1024F70;
+ v10 = (_DWORD *)dword_1024F70;
+ if ( v4 > 0 )
+ {
+ while ( v5 >= *v10 )
+ {
+ ++v14;
+ v13 = (int)v10;
+ v10 = (_DWORD *)v10[3];
+ if ( v14 >= v4 )
+ break;
+ v5 = v12;
+ }
+ if ( v10 != (_DWORD *)v13 )
+ {
+ *v8 = *(_DWORD *)(v13 + 12);
+ *(_DWORD *)(v13 + 12) = v7;
+ v5 = v12;
+ goto LABEL_12;
+ }
+ v5 = v12;
+ }
+ *v8 = dword_1024F70;
+ dword_1024F70 = (int)v7;
+ LABEL_12:
+ v7[1] = a2;
+ v7[2] = a3;
+ v11 = dword_10235F4;
+ v7[4] = dword_10235F4;
+ dword_1024F78 = v4 + 1;
+ *v7 = v5;
+ dword_10235F4 = v11 + 1;
+ if ( v11 + 1 <= 0 )
+ dword_10235F4 = 1;
+ return v7[4];
+}
+// 10235F4: using guessed type int dword_10235F4;
+// 1024F70: using guessed type int dword_1024F70;
+// 1024F74: using guessed type int dword_1024F74;
+// 1024F78: using guessed type int dword_1024F78;
+// 1024F7C: using guessed type int dword_1024F7C;
+// 1024F84: using guessed type int time_ticks;
+
+//----- (0100758D) --------------------------------------------------------
+signed int __stdcall timer_check()
+{
+ _DWORD *v0; // eax
+ signed int v1; // ebx
+ _DWORD *v2; // ecx
+ int v3; // edx
+ bool v4; // zf
+ _DWORD *v5; // ecx
+ int v6; // edx
+ char v8; // [esp+4h] [ebp-14h]
+ int v9; // [esp+8h] [ebp-10h]
+ void (__stdcall *v10)(int, int); // [esp+Ch] [ebp-Ch]
+ int v11; // [esp+14h] [ebp-4h]
+
+ v0 = (_DWORD *)dword_1024F70;
+ v1 = 0;
+ if ( dword_1024F70 )
+ {
+ while ( time_ticks >= *v0 )
+ {
+ --dword_1024F78;
+ qmemcpy(&v8, v0, 0x14u);
+ v2 = v0 + 3;
+ v3 = (int)v0;
+ v0 = (_DWORD *)v0[3];
+ ++v1;
+ v4 = v10 == 0;
+ dword_1024F70 = (int)v0;
+ *v2 = dword_1024F7C;
+ dword_1024F7C = v3;
+ if ( !v4 )
+ {
+ v10(v11, v9);
+ v0 = (_DWORD *)dword_1024F70;
+ }
+ if ( v1 > 1 )
+ break;
+ if ( !v0 )
+ return v1;
+ }
+ while ( v0 && time_ticks >= *v0 + 100 )
+ {
+ --dword_1024F78;
+ qmemcpy(&v8, v0, 0x14u);
+ v4 = v10 == 0;
+ v5 = v0 + 3;
+ v6 = (int)v0;
+ v0 = (_DWORD *)v0[3];
+ dword_1024F70 = (int)v0;
+ *v5 = dword_1024F7C;
+ dword_1024F7C = v6;
+ if ( !v4 )
+ {
+ v10(v11, v9);
+ v0 = (_DWORD *)dword_1024F70;
+ }
+ ++v1;
+ }
+ }
+ return v1;
+}
+// 1024F70: using guessed type int dword_1024F70;
+// 1024F78: using guessed type int dword_1024F78;
+// 1024F7C: using guessed type int dword_1024F7C;
+// 1024F84: using guessed type int time_ticks;
+
+//----- (01007659) --------------------------------------------------------
+int __stdcall timer_kill(int a1)
+{
+ int v1; // ecx
+ int v2; // esi
+ int v3; // edx
+ int result; // eax
+
+ v1 = dword_1024F70;
+ v2 = 0;
+ v3 = 0;
+ if ( dword_1024F78 <= 0 )
+ return 0;
+ result = a1;
+ while ( a1 != *(_DWORD *)(v1 + 16) )
+ {
+ ++v2;
+ v3 = v1;
+ v1 = *(_DWORD *)(v1 + 12);
+ if ( v2 >= dword_1024F78 )
+ return 0;
+ }
+ if ( v3 )
+ *(_DWORD *)(v3 + 12) = *(_DWORD *)(v1 + 12);
+ else
+ dword_1024F70 = *(_DWORD *)(v1 + 12);
+ --dword_1024F78;
+ *(_DWORD *)(v1 + 12) = dword_1024F7C;
+ dword_1024F7C = v1;
+ return result;
+}
+// 1024F70: using guessed type int dword_1024F70;
+// 1024F78: using guessed type int dword_1024F78;
+// 1024F7C: using guessed type int dword_1024F7C;
diff --git a/help.cpp b/help.cpp
new file mode 100644
index 0000000..bcd03d7
--- /dev/null
+++ b/help.cpp
@@ -0,0 +1,63 @@
+#include "pinball.h"
+
+//----- (0100772D) --------------------------------------------------------
+void __stdcall help_introduction(int a1, int a2)
+{
+ CHAR *v2; // ebx
+ CHAR *v3; // eax
+ CHAR *v4; // eax
+ HWND v5; // eax
+ CHAR *lpString1; // [esp+8h] [ebp-4h]
+
+ v2 = (CHAR *)memoryallocate(0x1F4u);
+ if ( v2 )
+ {
+ lpString1 = (CHAR *)memoryallocate(0x1F4u);
+ if ( lpString1 )
+ {
+ v3 = get_rc_string(178, 0);
+ options_get_string(0, "HelpFile", v2, v3, 500);
+ v4 = get_rc_string(166, 0);
+ options_get_string((DWORD)v4, "HelpFile", v2, v2, 500);
+ lstrcpyA(lpString1, v2);
+ memoryfree((int)v2);
+ v5 = GetDesktopWindow();
+ HtmlHelpA(v5, lpString1, 0, 0);
+ memoryfree((int)lpString1);
+ }
+ else
+ {
+ memoryfree((int)v2);
+ }
+ }
+}
+
+//----- (0101CF1A) --------------------------------------------------------
+HWND __stdcall HtmlHelpA(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData)
+{
+HMODULE v4; // ecx
+FARPROC v5; // eax
+CHAR LibFileName; // [esp+Ch] [ebp-108h]
+
+v4 = hModule;
+if ( hModule || (HMODULE)dword_1025728 != hModule )
+goto LABEL_13;
+if ( sub_101CEB6((LPBYTE)&LibFileName) )
+hModule = LoadLibraryA(&LibFileName);
+v4 = hModule;
+if ( hModule || (v4 = LoadLibraryA("hhctrl.ocx"), (hModule = v4) != 0) )
+{
+LABEL_13:
+v5 = (FARPROC)pHtmlHelpA;
+if ( pHtmlHelpA )
+return (HWND)((int (__stdcall *)(HWND, LPCSTR, UINT, DWORD_PTR))v5)(hwndCaller, pszFile, uCommand, dwData);
+v5 = GetProcAddress(v4, (LPCSTR)0xE);
+pHtmlHelpA = (HWND (__stdcall *)(HWND, const char *, unsigned int, unsigned int))v5;
+if ( v5 )
+return (HWND)((int (__stdcall *)(HWND, LPCSTR, UINT, DWORD_PTR))v5)(hwndCaller, pszFile, uCommand, dwData);
+}
+dword_1025728 = 1;
+return 0;
+}
+// 1025720: using guessed type HWND (__stdcall *pHtmlHelpA)(HWND, const char *, unsigned int, unsigned int);
+// 1025728: using guessed type int dword_1025728;
diff --git a/highscore.cpp b/highscore.cpp
new file mode 100644
index 0000000..fd429b8
--- /dev/null
+++ b/highscore.cpp
@@ -0,0 +1,405 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "pinball.h"
+
+//----- (01004C3C) --------------------------------------------------------
+int __stdcall high_score_clear_table(int a1)
+{
+ int result; // eax
+ signed int v2; // ecx
+
+ result = a1;
+ v2 = 5;
+ do
+ {
+ *(_DWORD *)(result + 32) = -999;
+ *(_BYTE *)result = 0;
+ result += 36;
+ --v2;
+ }
+ while ( v2 );
+ return result;
+}
+
+//----- (01004C60) --------------------------------------------------------
+signed int __stdcall high_score_get_score_position(int a1, int a2)
+{
+ signed int result; // eax
+ _DWORD *v3; // ecx
+
+ if ( a2 <= 0 )
+ return -1;
+ result = 0;
+ v3 = (_DWORD *)(a1 + 32);
+ while ( a2 <= *v3 )
+ {
+ ++result;
+ v3 += 9;
+ if ( result >= 5 )
+ return -1;
+ }
+ return result;
+}
+
+//----- (01004C8D) --------------------------------------------------------
+int __stdcall high_score_place_new_score_into(int a1, int a2, LPCSTR lpString, int a4)
+{
+ char *v4; // edi
+ int v5; // eax
+ int v6; // esi
+
+ if ( a4 >= 0 )
+ {
+ if ( a4 <= 4 )
+ {
+ v4 = (char *)(a1 + 144);
+ v5 = 5 - a4;
+ do
+ {
+ --v5;
+ qmemcpy(v4, v4 - 36, 0x24u);
+ v4 -= 36;
+ }
+ while ( v5 );
+ }
+ v6 = a1 + 36 * a4;
+ *(_DWORD *)(v6 + 32) = a2;
+ if ( lstrlenA(lpString) >= 31 )
+ *((_BYTE *)lpString + 31) = 0;
+ lstrcpyA((LPSTR)v6, lpString);
+ *(_BYTE *)(v6 + 31) = 0;
+ }
+ return a4;
+}
+
+//----- (01004CF9) --------------------------------------------------------
+char *__stdcall scramble_number_string(int Val, char *DstBuf)
+{
+ return __ltoa(Val, DstBuf, 10);
+}
+
+//----- (01004D18) --------------------------------------------------------
+signed int __stdcall high_score_read(int a1, int a2)
+{
+ int i; // eax
+ CHAR *dwDisposition; // [esp+10h] [ebp-30h]
+ CHAR *v5; // [esp+14h] [ebp-2Ch]
+ signed int Val; // [esp+18h] [ebp-28h]
+ int v7; // [esp+1Ch] [ebp-24h]
+ LPSTR lpString1; // [esp+20h] [ebp-20h]
+ CHAR *lpString2; // [esp+24h] [ebp-1Ch]
+ char DstBuf; // [esp+28h] [ebp-18h]
+
+ v7 = 0;
+ high_score_clear_table(a1);
+ lpString2 = (CHAR *)memoryallocate(0x12Cu);
+ if ( !lpString2 )
+ return 1;
+ v5 = (CHAR *)memoryallocate(0x12Cu);
+ Val = 0;
+ lpString1 = (LPSTR)a1;
+ dwDisposition = get_rc_string(166, 0);
+ do
+ {
+ __itoa(Val, &DstBuf, 10);
+ lstrcatA(&DstBuf, ".Name");
+ options_get_string((DWORD)dwDisposition, &DstBuf, lpString2, WindowName, 32);
+ lpString2[32] = 0;
+ lstrcpyA(lpString1, lpString2);
+ __itoa(Val, &DstBuf, 10);
+ lstrcatA(&DstBuf, ".Score");
+ options_get_string((DWORD)dwDisposition, &DstBuf, lpString2, WindowName, 300);
+ *((_DWORD *)lpString1 + 8) = _atol(lpString2);
+ for ( i = lstrlenA(lpString1); --i >= 0; v7 += lpString1[i] )
+ ;
+ v7 += *((_DWORD *)lpString1 + 8);
+ ++Val;
+ lpString1 += 36;
+ }
+ while ( Val < 5 );
+ scramble_number_string(v7, lpString2);
+ options_get_string((DWORD)dwDisposition, "Verification", v5, WindowName, 300);
+ if ( lstrcmpA(lpString2, v5) )
+ high_score_clear_table(a1);
+ memoryfree((int)lpString2);
+ memoryfree((int)v5);
+ return 0;
+}
+
+//----- (01004E87) --------------------------------------------------------
+int __stdcall high_score_write(LPCSTR lpString, int a2)
+{
+ LPCSTR v2; // ebx
+ int i; // eax
+ HKEY phkResult; // [esp+8h] [ebp-28h]
+ signed int Val; // [esp+Ch] [ebp-24h]
+ int v7; // [esp+10h] [ebp-20h]
+ char *v8; // [esp+14h] [ebp-1Ch]
+ char DstBuf; // [esp+18h] [ebp-18h]
+
+ v2 = lpString;
+ v7 = 0;
+ v8 = (char *)memoryallocate(0x12Cu);
+ if ( !v8 )
+ return 1;
+ Val = 0;
+ phkResult = (HKEY)get_rc_string(166, 0);
+ do
+ {
+ __itoa(Val, &DstBuf, 10);
+ lstrcatA(&DstBuf, ".Name");
+ options_set_string(phkResult, &DstBuf, v2);
+ __itoa(Val, &DstBuf, 10);
+ lstrcatA(&DstBuf, ".Score");
+ __ltoa(*((_DWORD *)v2 + 8), v8, 10);
+ options_set_string(phkResult, &DstBuf, v8);
+ for ( i = lstrlenA(v2); --i >= 0; v7 += v2[i] )
+ ;
+ v7 += *((_DWORD *)v2 + 8);
+ ++Val;
+ v2 += 36;
+ }
+ while ( Val < 5 );
+ scramble_number_string(v7, v8);
+ options_set_string(phkResult, "Verification", v8);
+ memoryfree((int)v8);
+ return 0;
+}
+
+//----- (01004F99) --------------------------------------------------------
+char *__stdcall score_string_format(int a1, char *a2)
+{
+ char *result; // eax
+ DWORD dwDisposition; // [esp+4h] [ebp-20h]
+ DWORD cbData; // [esp+8h] [ebp-1Ch]
+ char *Dest; // [esp+Ch] [ebp-18h]
+ HKEY phkResult; // [esp+10h] [ebp-14h]
+ CHAR String1; // [esp+14h] [ebp-10h]
+
+ result = a2;
+ Dest = a2;
+ if ( a1 == -999 )
+ {
+ *a2 = 0;
+ }
+ else
+ {
+ lstrcpyA(&String1, ",");
+ if ( !RegCreateKeyExA(
+ HKEY_CURRENT_USER,
+ "Control Panel\\International",
+ 0,
+ 0,
+ 0,
+ 0xF003Fu,
+ 0,
+ &phkResult,
+ &dwDisposition) )
+ {
+ cbData = 10;
+ RegQueryValueExA(phkResult, "sThousand", 0, 0, (LPBYTE)&String1, &cbData);
+ RegCloseKey(phkResult);
+ }
+ phkResult = (HKEY)(a1 % 1000000000 / 1000000);
+ if ( a1 / 1000000000 <= 0 )
+ {
+ if ( (signed int)phkResult <= 0 )
+ {
+ if ( a1 % 1000000 / 1000 <= 0 )
+ _sprintf(Dest, "%ld", a1);
+ else
+ _sprintf(Dest, "%ld%s%03ld", a1 % 1000000 / 1000, &String1, a1 % 1000);
+ }
+ else
+ {
+ _sprintf(Dest, "%ld%s%03ld%s%03ld", phkResult, &String1, a1 % 1000000 / 1000, &String1, a1 % 1000);
+ }
+ }
+ else
+ {
+ _sprintf(
+ Dest,
+ "%ld%s%03ld%s%03ld%s%03ld",
+ a1 / 1000000000,
+ &String1,
+ phkResult,
+ &String1,
+ a1 % 1000000 / 1000,
+ &String1,
+ a1 % 1000);
+ }
+ result = Dest;
+ }
+ return result;
+}
+
+//----- (010050E2) --------------------------------------------------------
+void __stdcall hsdlg_show_score(HWND hDlg, LPCSTR lpString, int a3, int a4)
+{
+ HWND v4; // eax
+ HWND v5; // eax
+ CHAR String; // [esp+10h] [ebp-28h]
+
+ if ( a4 < 5 )
+ {
+ score_string_format(a3, &String);
+ if ( String )
+ {
+ v4 = GetDlgItem(hDlg, a4 + 401);
+ SetWindowTextA(v4, lpString);
+ v5 = GetDlgItem(hDlg, a4 + 501);
+ SetWindowTextA(v5, &String);
+ }
+ }
+}
+
+//----- (01005159) --------------------------------------------------------
+void __stdcall show_high_scores(HWND hDlg, LPCSTR lpString)
+{
+ LPCSTR v2; // edi
+ signed int v3; // ebx
+ int v4; // esi
+
+ v2 = lpString;
+ v3 = 0;
+ v4 = 0;
+ do
+ {
+ if ( high_score_dlg_enter_name == 1 && high_score_position == v4 )
+ {
+ hsdlg_show_score(hDlg, " ", high_score_dlg_score, v4);
+ v3 = 1;
+ }
+ hsdlg_show_score(hDlg, v2, *((_DWORD *)v2 + 8), v4++ + v3);
+ v2 += 36;
+ }
+ while ( v4 < 5 );
+}
+// 1028270: using guessed type int high_score_dlg_enter_name;
+
+//----- (010051B5) --------------------------------------------------------
+BOOL __stdcall HighScore(HWND hWnd, UINT a2, WPARAM a3, LPARAM a4)
+{
+ CHAR *v4; // eax
+ CHAR *v5; // eax
+ HWND v7; // eax
+ HWND v8; // edi
+ HWND v9; // eax
+ signed int nIDDlgItem; // [esp+Ch] [ebp-1D4h]
+ CHAR String1; // [esp+14h] [ebp-1CCh]
+ CHAR String; // [esp+DCh] [ebp-104h]
+ char v13; // [esp+FBh] [ebp-E5h]
+
+ switch ( a2 )
+ {
+ case 0x10u:
+ SendMessageA(hWnd, 0x111u, 2u, 0);
+ break;
+ case 0x53u:
+ WinHelpA(*(HWND *)(a4 + 12), "pinball.hlp", 0xCu, (ULONG_PTR)&unk_1023460);
+ break;
+ case 0x7Bu:
+ WinHelpA((HWND)a3, "pinball.hlp", 0xAu, (ULONG_PTR)&unk_1023460);
+ break;
+ case 0x110u:
+ show_high_scores(hWnd, high_score_dlg_hst);
+ nIDDlgItem = 601;
+ do
+ {
+ v7 = GetDlgItem(hWnd, nIDDlgItem);
+ ShowWindow(v7, 0);
+ ++nIDDlgItem;
+ }
+ while ( nIDDlgItem < 611 );
+ if ( high_score_dlg_enter_name == 1 )
+ {
+ if ( high_score_position == -1 )
+ {
+ high_score_dlg_enter_name = 0;
+ return 1;
+ }
+ v8 = GetDlgItem(hWnd, high_score_position + 601);
+ ShowWindow(v8, 5);
+ EnableWindow(v8, 1);
+ SetFocus(v8);
+ if ( high_score_default_name )
+ {
+ SetWindowTextA(v8, high_score_default_name);
+ SendMessageA(v8, 0xB1u, 0, -1);
+ }
+ SendMessageA(v8, 0xC5u, 0x1Fu, 0);
+ }
+ else
+ {
+ SetFocus(hWnd);
+ }
+ v9 = GetParent(hWnd);
+ if ( v9 )
+ center_in(v9, hWnd);
+ return 0;
+ case 0x111u:
+ if ( a3 == 1 )
+ {
+ if ( high_score_dlg_enter_name != 1 )
+ goto LABEL_15;
+ GetDlgItemTextA(hWnd, high_score_position + 601, &String, 32);
+ v13 = 0;
+ high_score_place_new_score_into((int)high_score_dlg_hst, high_score_dlg_score, &String, high_score_position);
+ }
+ else if ( a3 != 2 )
+ {
+ if ( a3 == 112 )
+ {
+ v4 = get_rc_string(41, 0);
+ lstrcpyA(&String1, v4);
+ v5 = get_rc_string(40, 0);
+ if ( MessageBoxA(hWnd, v5, &String1, 0x101u) == 1 )
+ {
+ high_score_clear_table((int)high_score_dlg_hst);
+ if ( high_score_dlg_enter_name )
+ EndDialog(hWnd, 1);
+ else
+ EndDialog(hWnd, 0);
+ }
+ }
+ return 0;
+ }
+ high_score_dlg_enter_name = 0;
+ LABEL_15:
+ EndDialog(hWnd, 0);
+ return 1;
+ }
+ return 0;
+}
+// 1028270: using guessed type int high_score_dlg_enter_name;
+
+//----- (01005412) --------------------------------------------------------
+INT_PTR __stdcall show_high_score_dialog(const CHAR *a1)
+{
+ high_score_dlg_enter_name = 0;
+ high_score_dlg_score = 0;
+ high_score_dlg_hst = a1;
+ return DialogBoxParamA(hinst, "dlg_highscores", hwnd_frame, HighScore, 0);
+}
+// 1028270: using guessed type int high_score_dlg_enter_name;
+
+//----- (01005452) --------------------------------------------------------
+INT_PTR __stdcall show_and_set_high_score_dialog(const CHAR *a1, int a2, int a3, const CHAR *a4)
+{
+ INT_PTR result; // eax
+
+ high_score_position = a3;
+ high_score_dlg_score = a2;
+ high_score_dlg_hst = a1;
+ high_score_dlg_enter_name = 1;
+ high_score_default_name = a4;
+ do
+ result = DialogBoxParamA(hinst, "dlg_highscores", hwnd_frame, HighScore, 0);
+ while ( result );
+ return result;
+}
+// 1028270: using guessed type int high_score_dlg_enter_name;
+
+
diff --git a/lights.cpp b/lights.cpp
new file mode 100644
index 0000000..cf5c3c8
--- /dev/null
+++ b/lights.cpp
@@ -0,0 +1,11 @@
+#include "pinball.h"
+
+//----- (0100C092) --------------------------------------------------------
+BOOL __stdcall light_on(struct component_tag *a1)
+{
+int v1; // eax
+
+v1 = *((_DWORD *)a1 + 1);
+return *(_DWORD *)(v1 + 78) || *(_DWORD *)(v1 + 90) || *(_DWORD *)(v1 + 82);
+}
+
diff --git a/memory.cpp b/memory.cpp
new file mode 100644
index 0000000..635ac3c
--- /dev/null
+++ b/memory.cpp
@@ -0,0 +1,98 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "pinball.h"
+
+//----- (010054AC) --------------------------------------------------------
+int __stdcall memory_init(int a1)
+{
+ int result; // eax
+
+ result = a1;
+ memory_critical_callback = (int (*)(void))a1;
+ return result;
+}
+// 1024F08: using guessed type int (*memory_critical_callback)(void);
+
+//----- (010054C2) --------------------------------------------------------
+int __stdcall memoryallocate(unsigned int a1)
+{
+ _DWORD *v1; // eax
+
+ v1 = _malloc(a1 + 4);
+ if ( a1 >= 0xFFDC )
+ {
+ if ( v1 )
+ {
+ *v1 = a1 << 8;
+ memory_use_total += a1 + 4;
+ *(_BYTE *)v1 = -91;
+ return (int)(v1 + 1);
+ }
+ }
+ else if ( v1 )
+ {
+ *v1 = a1 << 8;
+ memory_use_total += a1 + 4;
+ *(_BYTE *)v1 = 90;
+ return (int)(v1 + 1);
+ }
+ if ( memory_critical_allocation )
+ {
+ if ( memory_critical_callback )
+ memory_critical_callback();
+ }
+ return 0;
+}
+// 1024F08: invalid function type has been ignored
+// 1024F00: using guessed type int memory_use_total;
+// 1024F04: using guessed type int memory_critical_allocation;
+// 1024F08: using guessed type int (*memory_critical_callback)(void);
+
+//----- (01005541) --------------------------------------------------------
+void __stdcall memoryfree(int a1)
+{
+ char v1; // cl
+
+ memory_use_total += -4 - (*(_DWORD *)(a1 - 4) >> 8);
+ v1 = *(_BYTE *)(a1 - 4);
+ if ( v1 == 90 || v1 == -91 )
+ _free((void *)(a1 - 4));
+}
+// 1024F00: using guessed type int memory_use_total;
+
+//----- (01005579) --------------------------------------------------------
+int __stdcall memoryrealloc(int a1, unsigned int a2)
+{
+ int result; // eax
+ char *v3; // eax
+ char v4; // cl
+
+ if ( !a1 )
+ return memoryallocate(a2);
+ v3 = (char *)(a1 - 4);
+ memory_use_total -= *(_DWORD *)(a1 - 4) >> 8;
+ if ( *(_BYTE *)(a1 - 4) != 90 && *(_BYTE *)(a1 - 4) != -91 || (v3 = (char *)_realloc(v3, a2 + 4)) != 0 )
+ {
+ v4 = *v3;
+ *(_DWORD *)v3 = a2 << 8;
+ memory_use_total += a2;
+ *v3 = v4;
+ result = (int)(v3 + 4);
+ }
+ else
+ {
+ if ( memory_critical_allocation )
+ {
+ if ( memory_critical_callback )
+ memory_critical_callback();
+ }
+ result = 0;
+ }
+ return result;
+}
+// 1024F00: using guessed type int memory_use_total;
+// 1024F04: using guessed type int memory_critical_allocation;
+// 1024F08: using guessed type int (*memory_critical_callback)(void);
+
diff --git a/missions.cpp b/missions.cpp
new file mode 100644
index 0000000..7d8a102
--- /dev/null
+++ b/missions.cpp
@@ -0,0 +1,2544 @@
+//----- (0100E657) --------------------------------------------------------
+void __userpurge WaitingDeploymentController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+
+switch ( a2 )
+{
+case 63:
+if ( (struct TPinballComponent *)dword_1023838 == a3 || (struct TPinballComponent *)dword_1023840 == a3 )
+{
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+}
+break;
+case 66:
+TTextBox::Clear(dword_1023E24, a1);
+dword_1025048 = 0;
+break;
+case 67:
+v3 = get_rc_string(50, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+break;
+}
+}
+// 1023838: using guessed type int dword_1023838;
+// 1023840: using guessed type int dword_1023840;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1025048: using guessed type int dword_1025048;
+
+//----- (0100E6D2) --------------------------------------------------------
+void __stdcall SelectMissionController(int a1, struct TPinballComponent *a2)
+{
+signed int v2; // esi
+void (__thiscall ***v3)(_DWORD, signed int, _DWORD); // edi
+void (__thiscall ***v4)(_DWORD, signed int, _DWORD); // edi
+char *v5; // eax
+void (__stdcall ***v6)(signed int, _DWORD); // ecx
+char *v7; // eax
+CHAR *v8; // ST58_4
+CHAR *v9; // eax
+int v10; // esi
+int v11; // ST58_4
+CHAR *v12; // eax
+signed int v13; // [esp+58h] [ebp-54h]
+char Dest; // [esp+68h] [ebp-44h]
+
+v2 = 0;
+if ( a1 == 45 || a1 == 47 )
+{
+if ( (struct TPinballComponent *)dword_1023978 == a2 )
+LABEL_83:
+MissionControl(67, a2);
+}
+else if ( a1 == 63 )
+{
+if ( (struct TPinballComponent *)dword_1023B84 == a2 )
+v2 = 1;
+if ( (struct TPinballComponent *)dword_1023B8C == a2 )
+v2 = 2;
+if ( (struct TPinballComponent *)dword_1023B94 == a2 )
+v2 = 3;
+if ( v2 )
+{
+if ( *(_DWORD *)(dword_1023B9C + 6) == 7 )
+{
+*(_DWORD *)(dword_1023B9C + 6) = 0;
+v2 = 4;
+}
+switch ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(37, 0.0) )
+{
+case 1:
+switch ( v2 )
+{
+case 1:
+v13 = 3;
+break;
+case 2:
+v13 = 4;
+break;
+case 3:
+v13 = 2;
+break;
+default:
+v13 = 5;
+break;
+}
+goto LABEL_71;
+case 2:
+case 3:
+switch ( v2 )
+{
+case 1:
+v13 = 9;
+break;
+case 2:
+v13 = 11;
+break;
+case 3:
+v13 = 10;
+break;
+default:
+LABEL_69:
+v13 = 16;
+break;
+}
+goto LABEL_71;
+case 4:
+case 5:
+switch ( v2 )
+{
+case 1:
+v13 = 6;
+break;
+case 2:
+v13 = 8;
+break;
+case 3:
+v13 = 7;
+break;
+default:
+LABEL_70:
+v13 = 15;
+break;
+}
+goto LABEL_71;
+case 6:
+case 7:
+switch ( v2 )
+{
+case 1:
+v13 = 12;
+break;
+case 2:
+v13 = 13;
+break;
+case 3:
+v13 = 14;
+break;
+default:
+LABEL_68:
+v13 = 17;
+break;
+}
+goto LABEL_71;
+case 8:
+case 9:
+switch ( v2 )
+{
+case 1:
+goto LABEL_70;
+case 2:
+goto LABEL_69;
+case 3:
+goto LABEL_68;
+}
+v13 = 18;
+LABEL_71:
+*(_DWORD *)(dword_1023888 + 6) = v13;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023888)(15, 2.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023BBC)(4, 0.0);
+goto LABEL_83;
+default:
+return;
+}
+}
+else if ( (struct TPinballComponent *)dword_1023870 == a2
+&& light_on((struct component_tag *)&off_1023884)
+&& (**(int (__stdcall ***)(signed int, _DWORD))dword_1023978)(37, 0.0) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023888)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023BBC)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CFC)(26, -1.0);
+if ( light_on((struct component_tag *)&off_1023EB8) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EBC)(20, 0.0);
+if ( light_on((struct component_tag *)&off_1023EC0) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EC4)(20, 0.0);
+if ( light_on((struct component_tag *)&off_1023EC8) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ECC)(20, 0.0);
+v10 = *(_DWORD *)(dword_1023888 + 6);
+*(_DWORD *)(dword_1023BBC + 6) = v10;
+MissionControl(66, 0);
+v11 = SpecialAddScore(*(&off_10246A0 + v10));
+v12 = get_rc_string(77, 0);
+_sprintf(&Dest, v12, v11);
+TTextBox::Display(dword_1023E24, 0, &Dest, 4.0);
+}
+}
+else
+{
+if ( a1 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023BBC)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CFC)(34, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023BB4)(20, 0.0);
+*(_DWORD *)(dword_1023888 + 6) = 0;
+*(_DWORD *)(dword_1023B9C + 6) = 0;
+v3 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A8C;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A8C)(34, 0.0);
+(**v3)(v3, 20, 0.0);
+v4 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A94;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A94)(34, 0.0);
+(**v4)(v4, 20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EEC)(20, 0.0);
+}
+else if ( a1 != 67 )
+{
+return;
+}
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023978)(37, 0.0) )
+{
+if ( light_on((struct component_tag *)&off_1023884) )
+{
+v8 = get_rc_string(word_1024708[2 * *(_DWORD *)(dword_1023888 + 6)], 1);
+v9 = get_rc_string(106, 0);
+_sprintf(&Dest, v9, v8);
+TTextBox::Display(dword_1023E24, 0, &Dest, -1.0);
+if ( light_on((struct component_tag *)&off_1023EC0) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EC4)(20, 0.0);
+if ( light_on((struct component_tag *)&off_1023EC8) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ECC)(20, 0.0);
+if ( !light_on((struct component_tag *)&off_1023EB8) )
+{
+v6 = (void (__stdcall ***)(signed int, _DWORD))dword_1023EBC;
+goto LABEL_28;
+}
+}
+else
+{
+v7 = get_rc_string(104, 0);
+TTextBox::Display(dword_1023E24, 0, v7, -1.0);
+if ( light_on((struct component_tag *)&off_1023EB8) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EBC)(20, 0.0);
+if ( light_on((struct component_tag *)&off_1023EC0) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EC4)(20, 0.0);
+if ( !light_on((struct component_tag *)&off_1023EC8) )
+{
+v6 = (void (__stdcall ***)(signed int, _DWORD))dword_1023ECC;
+goto LABEL_28;
+}
+}
+}
+else
+{
+v5 = get_rc_string(105, 0);
+TTextBox::Display(dword_1023E24, 0, v5, -1.0);
+if ( light_on((struct component_tag *)&off_1023EB8) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EBC)(20, 0.0);
+if ( light_on((struct component_tag *)&off_1023EC8) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ECC)(20, 0.0);
+if ( !light_on((struct component_tag *)&off_1023EC0) )
+{
+v6 = (void (__stdcall ***)(signed int, _DWORD))dword_1023EC4;
+LABEL_28:
+(**v6)(7, 0.0);
+return;
+}
+}
+}
+}
+// 1023870: using guessed type int dword_1023870;
+// 1023884: using guessed type char *off_1023884;
+// 1023888: using guessed type int dword_1023888;
+// 1023978: using guessed type int dword_1023978;
+// 1023A8C: using guessed type int dword_1023A8C;
+// 1023A94: using guessed type int dword_1023A94;
+// 1023B84: using guessed type int dword_1023B84;
+// 1023B8C: using guessed type int dword_1023B8C;
+// 1023B94: using guessed type int dword_1023B94;
+// 1023B9C: using guessed type int dword_1023B9C;
+// 1023BB4: using guessed type int dword_1023BB4;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023CF4: using guessed type int dword_1023CF4;
+// 1023CFC: using guessed type int dword_1023CFC;
+// 1023EB8: using guessed type char *off_1023EB8;
+// 1023EBC: using guessed type int dword_1023EBC;
+// 1023EC0: using guessed type char *off_1023EC0;
+// 1023EC4: using guessed type int dword_1023EC4;
+// 1023EC8: using guessed type char *off_1023EC8;
+// 1023ECC: using guessed type int dword_1023ECC;
+// 1023EEC: using guessed type int dword_1023EEC;
+// 1024708: using guessed type __int16 word_1024708[];
+
+//----- (0100EBF3) --------------------------------------------------------
+void __userpurge PracticeMissionController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST10_4
+CHAR *v4; // eax
+int v5; // ecx
+char *v6; // eax
+int v7; // ST10_4
+CHAR *v8; // eax
+char Dest; // [esp+14h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E74)(
+dword_1023E74,
+a3,
+7,
+0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E8C)(7, 0.0);
+*(_DWORD *)(dword_1023888 + 6) = 8;
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(107, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_10236E4 == a3
+|| (struct TPinballComponent *)dword_10236EC == a3
+|| (struct TPinballComponent *)dword_10236F4 == a3
+|| (struct TPinballComponent *)dword_10236FC == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E74)(
+dword_1023E74,
+a3,
+20,
+0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E8C)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v6 = get_rc_string(108, 0);
+TTextBox::Display(dword_1023E24, a1, v6, 4.0);
+v7 = SpecialAddScore(500000);
+v8 = get_rc_string(78, 0);
+_sprintf(&Dest, v8, v7);
+if ( !AddRankProgress(6) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+}
+// 10236E4: using guessed type int dword_10236E4;
+// 10236EC: using guessed type int dword_10236EC;
+// 10236F4: using guessed type int dword_10236F4;
+// 10236FC: using guessed type int dword_10236FC;
+// 1023888: using guessed type int dword_1023888;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E74: using guessed type int dword_1023E74;
+// 1023E8C: using guessed type int dword_1023E8C;
+
+//----- (0100ED83) --------------------------------------------------------
+void __userpurge LaunchTrainingController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST08_4
+CHAR *v4; // eax
+int v5; // ecx
+char *v6; // eax
+int v7; // ST08_4
+CHAR *v8; // eax
+char Dest; // [esp+Ch] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023EBC)(
+dword_1023EBC,
+a3,
+7,
+0.0);
+*(_DWORD *)(dword_1023888 + 6) = 3;
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(110, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023870 == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023EBC)(
+dword_1023EBC,
+a3,
+20,
+0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v6 = get_rc_string(111, 0);
+TTextBox::Display(dword_1023E24, a1, v6, 4.0);
+v7 = SpecialAddScore(500000);
+v8 = get_rc_string(78, 0);
+_sprintf(&Dest, v8, v7);
+if ( !AddRankProgress(6) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+}
+// 1023870: using guessed type int dword_1023870;
+// 1023888: using guessed type int dword_1023888;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023EBC: using guessed type int dword_1023EBC;
+
+//----- (0100EED7) --------------------------------------------------------
+void __userpurge ReentryTrainingController(int a1@, int a2, struct TPinballComponent *a3)
+{
+void (__thiscall ***v3)(_DWORD, signed int, _DWORD); // esi
+void (__thiscall ***v4)(_DWORD, signed int, _DWORD); // esi
+int v5; // ST38_4
+CHAR *v6; // eax
+int v7; // ecx
+char *v8; // eax
+int v9; // ST38_4
+CHAR *v10; // eax
+char Dest; // [esp+40h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 3;
+v3 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A8C;
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023A8C)(
+dword_1023A8C,
+a3,
+20,
+0.0);
+(**v3)(v3, 32, 0.2);
+(**v3)(v3, 26, 0.2);
+v4 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A94;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A94)(20, 0.0);
+(**v4)(v4, 32, 0.2);
+(**v4)(v4, 26, 0.2);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E6C)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v5 = *(_DWORD *)(dword_1023888 + 6);
+v6 = get_rc_string(112, 0);
+_sprintf(&Dest, v6, v5);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_102372C == a3
+|| (struct TPinballComponent *)dword_1023734 == a3
+|| (struct TPinballComponent *)dword_102373C == a3 )
+{
+v7 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v7;
+if ( v7 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E6C)(
+dword_1023E6C,
+a3,
+20,
+0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v8 = get_rc_string(113, 0);
+TTextBox::Display(dword_1023E24, a1, v8, 4.0);
+v9 = SpecialAddScore(500000);
+v10 = get_rc_string(78, 0);
+_sprintf(&Dest, v10, v9);
+if ( !AddRankProgress(6) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+}
+// 102372C: using guessed type int dword_102372C;
+// 1023734: using guessed type int dword_1023734;
+// 102373C: using guessed type int dword_102373C;
+// 1023888: using guessed type int dword_1023888;
+// 1023A8C: using guessed type int dword_1023A8C;
+// 1023A94: using guessed type int dword_1023A94;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E6C: using guessed type int dword_1023E6C;
+
+//----- (0100F0B3) --------------------------------------------------------
+void __userpurge ScienceMissionController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST60_4
+CHAR *v4; // eax
+int v5; // edx
+char *v6; // eax
+int v7; // ST60_4
+CHAR *v8; // eax
+char Dest; // [esp+68h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 9;
+*(_DWORD *)(dword_1023A9C + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A9C)(50, 0.0);
+*(_DWORD *)(dword_1023AA4 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AA4)(50, 0.0);
+*(_DWORD *)(dword_1023AAC + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AAC)(50, 0.0);
+*(_DWORD *)(dword_1023ADC + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ADC)(50, 0.0);
+*(_DWORD *)(dword_1023AE4 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AE4)(50, 0.0);
+*(_DWORD *)(dword_1023AEC + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AEC)(50, 0.0);
+*(_DWORD *)(dword_1023B20 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B20)(50, 0.0);
+*(_DWORD *)(dword_1023B28 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B28)(50, 0.0);
+*(_DWORD *)(dword_1023B30 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B30)(50, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E4C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E7C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EAC)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(114, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023A9C == a3
+|| (struct TPinballComponent *)dword_1023AA4 == a3
+|| (struct TPinballComponent *)dword_1023AAC == a3
+|| (struct TPinballComponent *)dword_1023ADC == a3
+|| (struct TPinballComponent *)dword_1023AE4 == a3
+|| (struct TPinballComponent *)dword_1023AEC == a3
+|| (struct TPinballComponent *)dword_1023B20 == a3
+|| (struct TPinballComponent *)dword_1023B28 == a3
+|| (struct TPinballComponent *)dword_1023B30 == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E4C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E7C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EAC)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v6 = get_rc_string(115, 0);
+TTextBox::Display(dword_1023E24, a1, v6, 4.0);
+v7 = SpecialAddScore(750000);
+v8 = get_rc_string(78, 0);
+_sprintf(&Dest, v8, v7);
+if ( !AddRankProgress(9) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+}
+// 1023888: using guessed type int dword_1023888;
+// 1023A9C: using guessed type int dword_1023A9C;
+// 1023AA4: using guessed type int dword_1023AA4;
+// 1023AAC: using guessed type int dword_1023AAC;
+// 1023ADC: using guessed type int dword_1023ADC;
+// 1023AE4: using guessed type int dword_1023AE4;
+// 1023AEC: using guessed type int dword_1023AEC;
+// 1023B20: using guessed type int dword_1023B20;
+// 1023B28: using guessed type int dword_1023B28;
+// 1023B30: using guessed type int dword_1023B30;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E4C: using guessed type int dword_1023E4C;
+// 1023E7C: using guessed type int dword_1023E7C;
+// 1023EAC: using guessed type int dword_1023EAC;
+
+//----- (0100F381) --------------------------------------------------------
+void __userpurge StrayCometController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+char *v4; // eax
+int v5; // ST10_4
+CHAR *v6; // eax
+char Dest; // [esp+18h] [ebp-44h]
+
+if ( a2 == 63 )
+{
+if ( (struct TPinballComponent *)dword_1023BE0 == a3
+|| (struct TPinballComponent *)dword_1023BE8 == a3
+|| (struct TPinballComponent *)dword_1023BF0 == a3 )
+{
+if ( *(_DWORD *)(dword_1023C10 + 6) == 7 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E64)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E54)(7, 0.0);
+*(_DWORD *)(dword_1023C10 + 6) = 15;
+MissionControl(67, a3);
+}
+}
+else if ( (struct TPinballComponent *)dword_1023980 == a3 && *(_DWORD *)(dword_1023C10 + 6) == 15 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E54)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v4 = get_rc_string(119, 0);
+TTextBox::Display(dword_1023E24, a1, v4, 4.0);
+v5 = SpecialAddScore(1000000);
+v6 = get_rc_string(78, 0);
+_sprintf(&Dest, v6, v5);
+if ( !AddRankProgress(8) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+else
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C30)(20, 0.0);
+*(_DWORD *)(dword_1023C10 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E64)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+if ( *(_DWORD *)(dword_1023C10 + 6) == 15 )
+v3 = get_rc_string(118, 0);
+else
+v3 = get_rc_string(117, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+}
+}
+// 1023980: using guessed type int dword_1023980;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023BE0: using guessed type int dword_1023BE0;
+// 1023BE8: using guessed type int dword_1023BE8;
+// 1023BF0: using guessed type int dword_1023BF0;
+// 1023C10: using guessed type int dword_1023C10;
+// 1023C30: using guessed type int dword_1023C30;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E54: using guessed type int dword_1023E54;
+// 1023E64: using guessed type int dword_1023E64;
+
+//----- (0100F539) --------------------------------------------------------
+void __userpurge SpaceRadiationController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+char *v4; // eax
+int v5; // ST10_4
+CHAR *v6; // eax
+char Dest; // [esp+18h] [ebp-44h]
+
+if ( a2 == 63 )
+{
+if ( (struct TPinballComponent *)dword_1023BC8 == a3
+|| (struct TPinballComponent *)dword_1023BD0 == a3
+|| (struct TPinballComponent *)dword_1023BD8 == a3 )
+{
+if ( *(_DWORD *)(dword_1023BF8 + 6) == 7 )
+{
+*(_DWORD *)(dword_1023BF8 + 6) = 15;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A3C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E9C)(20, 0.0);
+MissionControl(67, a3);
+AdvanceWormHoleDestination(1);
+}
+}
+else if ( ((struct TPinballComponent *)dword_10239EC == a3
+|| (struct TPinballComponent *)dword_10239F4 == a3
+|| (struct TPinballComponent *)dword_10239FC == a3)
+&& *(_DWORD *)(dword_1023BF8 + 6) == 15 )
+{
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v4 = get_rc_string(121, 0);
+TTextBox::Display(dword_1023E24, a1, v4, 4.0);
+v5 = SpecialAddScore(1000000);
+v6 = get_rc_string(78, 0);
+_sprintf(&Dest, v6, v5);
+if ( !AddRankProgress(8) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+else
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C28)(20, 0.0);
+*(_DWORD *)(dword_1023BF8 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E9C)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+if ( *(_DWORD *)(dword_1023BF8 + 6) == 15 )
+v3 = get_rc_string(120, 0);
+else
+v3 = get_rc_string(176, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+}
+}
+// 10239EC: using guessed type int dword_10239EC;
+// 10239F4: using guessed type int dword_10239F4;
+// 10239FC: using guessed type int dword_10239FC;
+// 1023A3C: using guessed type int dword_1023A3C;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023BC8: using guessed type int dword_1023BC8;
+// 1023BD0: using guessed type int dword_1023BD0;
+// 1023BD8: using guessed type int dword_1023BD8;
+// 1023BF8: using guessed type int dword_1023BF8;
+// 1023C28: using guessed type int dword_1023C28;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E9C: using guessed type int dword_1023E9C;
+
+//----- (0100F6F4) --------------------------------------------------------
+void __userpurge BlackHoleThreatController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+void (__stdcall ***v4)(signed int, _DWORD); // ecx
+char *v5; // eax
+char *v6; // eax
+int v7; // ST10_4
+CHAR *v8; // eax
+float v9; // [esp+10h] [ebp-4Ch]
+char Dest; // [esp+18h] [ebp-44h]
+
+if ( a2 == 11 )
+{
+if ( (struct TPinballComponent *)dword_1023758 == a3 )
+MissionControl(67, a3);
+}
+else if ( a2 == 63 )
+{
+if ( (struct TPinballComponent *)dword_1023C5C == a3 && *(_DWORD *)(dword_1023758 + 78) )
+{
+if ( light_on((struct component_tag *)&off_1023EB0) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EB4)(20, 0.0);
+if ( light_on((struct component_tag *)&off_1023EA0) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EA4)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v6 = get_rc_string(124, 0);
+TTextBox::Display(dword_1023E24, a1, v6, 4.0);
+v7 = SpecialAddScore(1000000);
+v8 = get_rc_string(78, 0);
+_sprintf(&Dest, v8, v7);
+if ( !AddRankProgress(8) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+else
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023770)(11, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v9 = -1.0;
+if ( *(_DWORD *)(dword_1023758 + 78) )
+{
+v5 = get_rc_string(123, 0);
+TTextBox::Display(dword_1023E24, a1, v5, v9);
+if ( light_on((struct component_tag *)&off_1023EB0) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EB4)(20, 0.0);
+if ( !light_on((struct component_tag *)&off_1023EA0) )
+{
+v4 = (void (__stdcall ***)(signed int, _DWORD))dword_1023EA4;
+goto LABEL_12;
+}
+}
+else
+{
+v3 = get_rc_string(122, 0);
+TTextBox::Display(dword_1023E24, a1, v3, v9);
+if ( light_on((struct component_tag *)&off_1023EA0) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EA4)(20, 0.0);
+if ( !light_on((struct component_tag *)&off_1023EB0) )
+{
+v4 = (void (__stdcall ***)(signed int, _DWORD))dword_1023EB4;
+LABEL_12:
+(**v4)(7, 0.0);
+return;
+}
+}
+}
+}
+// 1023758: using guessed type int dword_1023758;
+// 1023770: using guessed type int dword_1023770;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023C5C: using guessed type int dword_1023C5C;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023EA0: using guessed type char *off_1023EA0;
+// 1023EA4: using guessed type int dword_1023EA4;
+// 1023EB0: using guessed type char *off_1023EB0;
+// 1023EB4: using guessed type int dword_1023EB4;
+
+//----- (0100F900) --------------------------------------------------------
+void __userpurge BugHuntController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST90_4
+CHAR *v4; // eax
+int v5; // edx
+char *v6; // eax
+int v7; // ST90_4
+CHAR *v8; // eax
+char Dest; // [esp+9Ch] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 15;
+*(_DWORD *)(dword_1023A9C + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A9C)(50, 0.0);
+*(_DWORD *)(dword_1023AA4 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AA4)(50, 0.0);
+*(_DWORD *)(dword_1023AAC + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AAC)(50, 0.0);
+*(_DWORD *)(dword_1023ADC + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ADC)(50, 0.0);
+*(_DWORD *)(dword_1023AE4 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AE4)(50, 0.0);
+*(_DWORD *)(dword_1023AEC + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AEC)(50, 0.0);
+*(_DWORD *)(dword_1023B20 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B20)(50, 0.0);
+*(_DWORD *)(dword_1023B28 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B28)(50, 0.0);
+*(_DWORD *)(dword_1023B30 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B30)(50, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023B78)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023BB4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C28)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C30)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E64)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E74)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E84)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E9C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ECC)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(125, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023A9C == a3
+|| (struct TPinballComponent *)dword_1023AA4 == a3
+|| (struct TPinballComponent *)dword_1023AAC == a3
+|| (struct TPinballComponent *)dword_1023ADC == a3
+|| (struct TPinballComponent *)dword_1023AE4 == a3
+|| (struct TPinballComponent *)dword_1023AEC == a3
+|| (struct TPinballComponent *)dword_1023B20 == a3
+|| (struct TPinballComponent *)dword_1023B28 == a3
+|| (struct TPinballComponent *)dword_1023B30 == a3
+|| (struct TPinballComponent *)dword_1023B48 == a3
+|| (struct TPinballComponent *)dword_1023B50 == a3
+|| (struct TPinballComponent *)dword_1023B58 == a3
+|| (struct TPinballComponent *)dword_1023B84 == a3
+|| (struct TPinballComponent *)dword_1023B8C == a3
+|| (struct TPinballComponent *)dword_1023B94 == a3
+|| (struct TPinballComponent *)dword_1023BC8 == a3
+|| (struct TPinballComponent *)dword_1023BD0 == a3
+|| (struct TPinballComponent *)dword_1023BD8 == a3
+|| (struct TPinballComponent *)dword_1023BE0 == a3
+|| (struct TPinballComponent *)dword_1023BE8 == a3
+|| (struct TPinballComponent *)dword_1023BF0 == a3
+|| (struct TPinballComponent *)dword_1023C3C == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E64)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E74)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E84)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E9C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ECC)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v6 = get_rc_string(126, 0);
+TTextBox::Display(dword_1023E24, a1, v6, 4.0);
+v7 = SpecialAddScore(750000);
+v8 = get_rc_string(78, 0);
+_sprintf(&Dest, v8, v7);
+if ( !AddRankProgress(7) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+}
+// 1023888: using guessed type int dword_1023888;
+// 1023A9C: using guessed type int dword_1023A9C;
+// 1023AA4: using guessed type int dword_1023AA4;
+// 1023AAC: using guessed type int dword_1023AAC;
+// 1023ADC: using guessed type int dword_1023ADC;
+// 1023AE4: using guessed type int dword_1023AE4;
+// 1023AEC: using guessed type int dword_1023AEC;
+// 1023B20: using guessed type int dword_1023B20;
+// 1023B28: using guessed type int dword_1023B28;
+// 1023B30: using guessed type int dword_1023B30;
+// 1023B48: using guessed type int dword_1023B48;
+// 1023B50: using guessed type int dword_1023B50;
+// 1023B58: using guessed type int dword_1023B58;
+// 1023B78: using guessed type int dword_1023B78;
+// 1023B84: using guessed type int dword_1023B84;
+// 1023B8C: using guessed type int dword_1023B8C;
+// 1023B94: using guessed type int dword_1023B94;
+// 1023BB4: using guessed type int dword_1023BB4;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023BC8: using guessed type int dword_1023BC8;
+// 1023BD0: using guessed type int dword_1023BD0;
+// 1023BD8: using guessed type int dword_1023BD8;
+// 1023BE0: using guessed type int dword_1023BE0;
+// 1023BE8: using guessed type int dword_1023BE8;
+// 1023BF0: using guessed type int dword_1023BF0;
+// 1023C28: using guessed type int dword_1023C28;
+// 1023C30: using guessed type int dword_1023C30;
+// 1023C3C: using guessed type int dword_1023C3C;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E64: using guessed type int dword_1023E64;
+// 1023E74: using guessed type int dword_1023E74;
+// 1023E84: using guessed type int dword_1023E84;
+// 1023E9C: using guessed type int dword_1023E9C;
+// 1023ECC: using guessed type int dword_1023ECC;
+
+//----- (0100FCD9) --------------------------------------------------------
+void __userpurge RescueMissionController(int a1@, int a2, struct TPinballComponent *a3)
+{
+BOOL v3; // eax
+char *v4; // eax
+void (__stdcall ***v5)(signed int, _DWORD); // ecx
+char *v6; // eax
+int v7; // ecx
+char *v8; // eax
+int v9; // ST18_4
+CHAR *v10; // eax
+float v11; // [esp+18h] [ebp-4Ch]
+char Dest; // [esp+20h] [ebp-44h]
+
+if ( a2 == 63 )
+{
+if ( (struct TPinballComponent *)dword_1023A9C == a3
+|| (struct TPinballComponent *)dword_1023AA4 == a3
+|| (struct TPinballComponent *)dword_1023AAC == a3 )
+{
+goto LABEL_31;
+}
+if ( (struct TPinballComponent *)dword_1023980 != a3 || !light_on((struct component_tag *)&off_102393C) )
+return;
+v7 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v7;
+if ( v7 )
+{
+LABEL_31:
+MissionControl(67, a3);
+return;
+}
+if ( light_on((struct component_tag *)&off_1023E48) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E4C)(20, 0.0);
+if ( light_on((struct component_tag *)&off_1023E50) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E54)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v8 = get_rc_string(129, 0);
+TTextBox::Display(dword_1023E24, a1, v8, 4.0);
+v9 = SpecialAddScore(750000);
+v10 = get_rc_string(78, 0);
+_sprintf(&Dest, v10, v9);
+if ( !AddRankProgress(7) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+else
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023940)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239D0)(20, 0.0);
+*(_DWORD *)(dword_1023888 + 6) = 1;
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = light_on((struct component_tag *)&off_102393C);
+v11 = -1.0;
+if ( v3 )
+{
+v6 = get_rc_string(128, 0);
+TTextBox::Display(dword_1023E24, a1, v6, v11);
+if ( light_on((struct component_tag *)&off_1023E48) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E4C)(20, 0.0);
+if ( !light_on((struct component_tag *)&off_1023E50) )
+{
+v5 = (void (__stdcall ***)(signed int, _DWORD))dword_1023E54;
+goto LABEL_11;
+}
+}
+else
+{
+v4 = get_rc_string(127, 0);
+TTextBox::Display(dword_1023E24, a1, v4, v11);
+if ( light_on((struct component_tag *)&off_1023E50) )
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E54)(20, 0.0);
+if ( !light_on((struct component_tag *)&off_1023E48) )
+{
+v5 = (void (__stdcall ***)(signed int, _DWORD))dword_1023E4C;
+LABEL_11:
+(**v5)(7, 0.0);
+return;
+}
+}
+}
+}
+// 1023888: using guessed type int dword_1023888;
+// 102393C: using guessed type char *off_102393C;
+// 1023940: using guessed type int dword_1023940;
+// 1023980: using guessed type int dword_1023980;
+// 10239D0: using guessed type int dword_10239D0;
+// 1023A9C: using guessed type int dword_1023A9C;
+// 1023AA4: using guessed type int dword_1023AA4;
+// 1023AAC: using guessed type int dword_1023AAC;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E48: using guessed type char *off_1023E48;
+// 1023E4C: using guessed type int dword_1023E4C;
+// 1023E50: using guessed type char *off_1023E50;
+// 1023E54: using guessed type int dword_1023E54;
+
+//----- (0100FF35) --------------------------------------------------------
+void __userpurge AlienMenaceController(int a1@, int a2, struct TPinballComponent *a3)
+{
+void (__thiscall ***v3)(_DWORD, signed int, _DWORD); // esi
+void (__thiscall ***v4)(_DWORD, signed int, _DWORD); // esi
+char *v5; // eax
+
+if ( a2 != 11 )
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023704)(11, 0.0);
+v3 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A8C;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A8C)(20, 0.0);
+(**v3)(v3, 32, 0.2);
+(**v3)(v3, 26, 0.2);
+v4 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A94;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A94)(20, 0.0);
+(**v4)(v4, 32, 0.2);
+(**v4)(v4, 26, 0.2);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E6C)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v5 = get_rc_string(175, 0);
+TTextBox::Display(dword_1023E24, a1, v5, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_10236E4 == a3 )
+{
+if ( *(_DWORD *)(dword_10236E4 + 78) )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E6C)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 20;
+MissionControl(66, 0);
+}
+}
+}
+// 10236E4: using guessed type int dword_10236E4;
+// 1023704: using guessed type int dword_1023704;
+// 1023A8C: using guessed type int dword_1023A8C;
+// 1023A94: using guessed type int dword_1023A94;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023E6C: using guessed type int dword_1023E6C;
+
+//----- (01010051) --------------------------------------------------------
+void __userpurge AlienMenacePartTwoController(int a1@, int a2, struct TPinballComponent *a3)
+{
+void (__thiscall ***v3)(_DWORD, signed int, _DWORD); // esi
+void (__thiscall ***v4)(_DWORD, signed int, _DWORD); // esi
+int v5; // ST30_4
+CHAR *v6; // eax
+int v7; // ecx
+char *v8; // eax
+int v9; // ST30_4
+CHAR *v10; // eax
+char Dest; // [esp+38h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 8;
+v3 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A8C;
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023A8C)(
+dword_1023A8C,
+a3,
+34,
+0.0);
+(**v3)(v3, 20, 0.0);
+v4 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A94;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A94)(34, 0.0);
+(**v4)(v4, 20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E74)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E8C)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v5 = *(_DWORD *)(dword_1023888 + 6);
+v6 = get_rc_string(107, 0);
+_sprintf(&Dest, v6, v5);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_10236E4 == a3
+|| (struct TPinballComponent *)dword_10236EC == a3
+|| (struct TPinballComponent *)dword_10236F4 == a3
+|| (struct TPinballComponent *)dword_10236FC == a3 )
+{
+v7 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v7;
+if ( v7 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E74)(
+dword_1023E74,
+a3,
+20,
+0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E8C)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v8 = get_rc_string(130, 0);
+TTextBox::Display(dword_1023E24, a1, v8, 4.0);
+v9 = SpecialAddScore(750000);
+v10 = get_rc_string(78, 0);
+_sprintf(&Dest, v10, v9);
+if ( !AddRankProgress(7) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+}
+// 10236E4: using guessed type int dword_10236E4;
+// 10236EC: using guessed type int dword_10236EC;
+// 10236F4: using guessed type int dword_10236F4;
+// 10236FC: using guessed type int dword_10236FC;
+// 1023888: using guessed type int dword_1023888;
+// 1023A8C: using guessed type int dword_1023A8C;
+// 1023A94: using guessed type int dword_1023A94;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E74: using guessed type int dword_1023E74;
+// 1023E8C: using guessed type int dword_1023E8C;
+
+//----- (0101022D) --------------------------------------------------------
+void __userpurge SatelliteController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST08_4
+CHAR *v4; // eax
+int v5; // ecx
+char *v6; // eax
+int v7; // ST08_4
+CHAR *v8; // eax
+char Dest; // [esp+Ch] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 3;
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E74)(
+dword_1023E74,
+a3,
+7,
+0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(132, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_10236FC == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E74)(
+dword_1023E74,
+a3,
+20,
+0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v6 = get_rc_string(133, 0);
+TTextBox::Display(dword_1023E24, a1, v6, 4.0);
+v7 = SpecialAddScore(1250000);
+v8 = get_rc_string(78, 0);
+_sprintf(&Dest, v8, v7);
+if ( !AddRankProgress(9) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+}
+// 10236FC: using guessed type int dword_10236FC;
+// 1023888: using guessed type int dword_1023888;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E74: using guessed type int dword_1023E74;
+
+//----- (01010385) --------------------------------------------------------
+void __userpurge ReconnaissanceController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST30_4
+CHAR *v4; // eax
+int v5; // ecx
+char *v6; // eax
+int v7; // ST30_4
+CHAR *v8; // eax
+char Dest; // [esp+38h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 15;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E3C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E44)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E6C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EB4)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ED4)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EDC)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(134, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_102372C == a3
+|| (struct TPinballComponent *)dword_1023734 == a3
+|| (struct TPinballComponent *)dword_102373C == a3
+|| (struct TPinballComponent *)dword_1023798 == a3
+|| (struct TPinballComponent *)dword_10237A0 == a3
+|| (struct TPinballComponent *)dword_10237A8 == a3
+|| (struct TPinballComponent *)dword_102389C == a3
+|| (struct TPinballComponent *)dword_10238A4 == a3
+|| (struct TPinballComponent *)dword_10238C0 == a3
+|| (struct TPinballComponent *)dword_10238C8 == a3
+|| (struct TPinballComponent *)dword_10238E8 == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, 0);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E3C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E44)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E6C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EB4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ED4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EDC)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v6 = get_rc_string(136, 0);
+TTextBox::Display(dword_1023E24, a1, v6, 4.0);
+v7 = SpecialAddScore(1250000);
+v8 = get_rc_string(78, 0);
+_sprintf(&Dest, v8, v7);
+if ( !AddRankProgress(9) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+}
+// 102372C: using guessed type int dword_102372C;
+// 1023734: using guessed type int dword_1023734;
+// 102373C: using guessed type int dword_102373C;
+// 1023798: using guessed type int dword_1023798;
+// 10237A0: using guessed type int dword_10237A0;
+// 10237A8: using guessed type int dword_10237A8;
+// 1023888: using guessed type int dword_1023888;
+// 102389C: using guessed type int dword_102389C;
+// 10238A4: using guessed type int dword_10238A4;
+// 10238C0: using guessed type int dword_10238C0;
+// 10238C8: using guessed type int dword_10238C8;
+// 10238E8: using guessed type int dword_10238E8;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E3C: using guessed type int dword_1023E3C;
+// 1023E44: using guessed type int dword_1023E44;
+// 1023E6C: using guessed type int dword_1023E6C;
+// 1023EB4: using guessed type int dword_1023EB4;
+// 1023ED4: using guessed type int dword_1023ED4;
+// 1023EDC: using guessed type int dword_1023EDC;
+
+//----- (010105E3) --------------------------------------------------------
+void __userpurge DoomsdayMachineController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST10_4
+CHAR *v4; // eax
+int v5; // ecx
+char *v6; // eax
+int v7; // ST10_4
+CHAR *v8; // eax
+char Dest; // [esp+14h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 3;
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E3C)(
+dword_1023E3C,
+a3,
+7,
+0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ED4)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(137, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_102389C == a3 || (struct TPinballComponent *)dword_10238A4 == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E3C)(
+dword_1023E3C,
+a3,
+20,
+0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ED4)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v6 = get_rc_string(138, 0);
+TTextBox::Display(dword_1023E24, a1, v6, 4.0);
+v7 = SpecialAddScore(1250000);
+v8 = get_rc_string(78, 0);
+_sprintf(&Dest, v8, v7);
+if ( !AddRankProgress(9) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+}
+// 1023888: using guessed type int dword_1023888;
+// 102389C: using guessed type int dword_102389C;
+// 10238A4: using guessed type int dword_10238A4;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E3C: using guessed type int dword_1023E3C;
+// 1023ED4: using guessed type int dword_1023ED4;
+
+//----- (01010767) --------------------------------------------------------
+void __userpurge CosmicPlagueController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST20_4
+CHAR *v4; // eax
+int v5; // ecx
+char Dest; // [esp+24h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 75;
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023940)(
+dword_1023940,
+a3,
+19,
+0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239D0)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E5C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E94)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(139, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023930 == a3 || (struct TPinballComponent *)dword_10239C8 == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E5C)(
+dword_1023E5C,
+a3,
+20,
+0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E94)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 21;
+MissionControl(66, 0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023940)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239D0)(20, 0.0);
+}
+}
+}
+// 1023888: using guessed type int dword_1023888;
+// 1023930: using guessed type int dword_1023930;
+// 1023940: using guessed type int dword_1023940;
+// 10239C8: using guessed type int dword_10239C8;
+// 10239D0: using guessed type int dword_10239D0;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023E5C: using guessed type int dword_1023E5C;
+// 1023E94: using guessed type int dword_1023E94;
+
+//----- (010108BC) --------------------------------------------------------
+void __userpurge CosmicPlaguePartTwoController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+char *v4; // eax
+int v5; // ST08_4
+CHAR *v6; // eax
+char Dest; // [esp+Ch] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E84)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(140, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023C50 == a3 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E84)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v4 = get_rc_string(141, 0);
+TTextBox::Display(dword_1023E24, a1, v4, 4.0);
+v5 = SpecialAddScore(1750000);
+v6 = get_rc_string(78, 0);
+_sprintf(&Dest, v6, v5);
+if ( !AddRankProgress(11) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023C50: using guessed type int dword_1023C50;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E84: using guessed type int dword_1023E84;
+
+//----- (010109D5) --------------------------------------------------------
+void __userpurge SecretMissionYellowController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A1C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A3C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A3C)(23, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023C44)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A14)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A34)(11, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A34)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A34)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(142, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_10239FC == a3 )
+{
+*(_DWORD *)(dword_1023BBC + 6) = 22;
+MissionControl(66, 0);
+}
+}
+// 10239FC: using guessed type int dword_10239FC;
+// 1023A14: using guessed type int dword_1023A14;
+// 1023A1C: using guessed type int dword_1023A1C;
+// 1023A34: using guessed type int dword_1023A34;
+// 1023A3C: using guessed type int dword_1023A3C;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023C44: using guessed type int dword_1023C44;
+
+//----- (01010AD3) --------------------------------------------------------
+void __userpurge SecretMissionRedController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A04)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A24)(11, 2.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A24)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A24)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(143, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_10239EC == a3 )
+{
+*(_DWORD *)(dword_1023BBC + 6) = 23;
+MissionControl(66, 0);
+}
+}
+// 10239EC: using guessed type int dword_10239EC;
+// 1023A04: using guessed type int dword_1023A04;
+// 1023A24: using guessed type int dword_1023A24;
+// 1023BBC: using guessed type int dword_1023BBC;
+
+//----- (01010B85) --------------------------------------------------------
+void __userpurge SecretMissionGreenController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+char *v4; // eax
+int v5; // ST20_4
+CHAR *v6; // eax
+char Dest; // [esp+24h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A0C)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A2C)(11, 1.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A2C)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A2C)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(144, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_10239F4 == a3 )
+{
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v4 = get_rc_string(145, 0);
+TTextBox::Display(dword_1023E24, a1, v4, 4.0);
+v5 = SpecialAddScore(1500000);
+v6 = get_rc_string(78, 0);
+_sprintf(&Dest, v6, v5);
+if ( !AddRankProgress(10) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+// 10239F4: using guessed type int dword_10239F4;
+// 1023A0C: using guessed type int dword_1023A0C;
+// 1023A2C: using guessed type int dword_1023A2C;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+
+//----- (01010CC2) --------------------------------------------------------
+void __userpurge TimeWarpController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST10_4
+CHAR *v4; // eax
+int v5; // ecx
+char Dest; // [esp+14h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 25;
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E34)(
+dword_1023E34,
+a3,
+7,
+0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EE4)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(146, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_10237C4 == a3
+|| (struct TPinballComponent *)dword_10237CC == a3
+|| (struct TPinballComponent *)dword_10237E8 == a3
+|| (struct TPinballComponent *)dword_10237F0 == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__fastcall ***)(int, struct TPinballComponent *, signed int, _DWORD))dword_1023E34)(
+dword_1023E34,
+a3,
+20,
+0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EE4)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 24;
+MissionControl(66, 0);
+}
+}
+}
+// 10237C4: using guessed type int dword_10237C4;
+// 10237CC: using guessed type int dword_10237CC;
+// 10237E8: using guessed type int dword_10237E8;
+// 10237F0: using guessed type int dword_10237F0;
+// 1023888: using guessed type int dword_1023888;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023E34: using guessed type int dword_1023E34;
+// 1023EE4: using guessed type int dword_1023EE4;
+
+//----- (01010DD3) --------------------------------------------------------
+void __userpurge TimeWarpPartTwoController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+char *v4; // eax
+int v5; // eax
+CHAR *v6; // ST30_4
+CHAR *v7; // eax
+char *v8; // eax
+int v9; // esi
+CHAR *v10; // ST30_4
+CHAR *v11; // eax
+char Dest; // [esp+38h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023880)(7, -1.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239B8)(7, -1.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E54)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EBC)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(147, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023980 == a3 )
+{
+v4 = get_rc_string(47, 0);
+TTextBox::Display(dword_1023E24, a1, v4, 4.0);
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(37, 0.0) > 1 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(33, 5.0);
+v5 = (**(int (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(37, 0.0);
+v6 = get_rc_string(word_10246EC[2 * (v5 - 1)], 1);
+v7 = get_rc_string(174, 0);
+_sprintf(&Dest, v7, v6);
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+}
+}
+else
+{
+if ( (struct TPinballComponent *)dword_1023870 != a3 )
+return;
+v8 = get_rc_string(46, 0);
+TTextBox::Display(dword_1023E24, a1, v8, 4.0);
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(37, 0.0) < 9 )
+{
+v9 = (**(int (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(37, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(41, 5.0);
+v10 = get_rc_string(word_10246EC[2 * v9], 1);
+v11 = get_rc_string(173, 0);
+_sprintf(&Dest, v11, v10);
+}
+if ( !AddRankProgress(12) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D1C + 20))();
+}
+}
+SpecialAddScore(2000000);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023880)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239B8)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E54)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EBC)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+}
+// 1023870: using guessed type int dword_1023870;
+// 1023880: using guessed type int dword_1023880;
+// 1023980: using guessed type int dword_1023980;
+// 10239B8: using guessed type int dword_10239B8;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023CF4: using guessed type int dword_1023CF4;
+// 1023D1C: using guessed type int dword_1023D1C;
+// 1023E54: using guessed type int dword_1023E54;
+// 1023EBC: using guessed type int dword_1023EBC;
+// 10246EC: using guessed type __int16 word_10246EC[];
+
+//----- (0101106F) --------------------------------------------------------
+void __userpurge MaelstromController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST18_4
+CHAR *v4; // eax
+int v5; // edx
+char Dest; // [esp+1Ch] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 3;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E4C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E7C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EAC)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(148, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023A9C == a3
+|| (struct TPinballComponent *)dword_1023AA4 == a3
+|| (struct TPinballComponent *)dword_1023AAC == a3
+|| (struct TPinballComponent *)dword_1023ADC == a3
+|| (struct TPinballComponent *)dword_1023AE4 == a3
+|| (struct TPinballComponent *)dword_1023AEC == a3
+|| (struct TPinballComponent *)dword_1023B20 == a3
+|| (struct TPinballComponent *)dword_1023B28 == a3
+|| (struct TPinballComponent *)dword_1023B30 == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E4C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E7C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EAC)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 25;
+MissionControl(66, 0);
+}
+}
+}
+// 1023888: using guessed type int dword_1023888;
+// 1023A9C: using guessed type int dword_1023A9C;
+// 1023AA4: using guessed type int dword_1023AA4;
+// 1023AAC: using guessed type int dword_1023AAC;
+// 1023ADC: using guessed type int dword_1023ADC;
+// 1023AE4: using guessed type int dword_1023AE4;
+// 1023AEC: using guessed type int dword_1023AEC;
+// 1023B20: using guessed type int dword_1023B20;
+// 1023B28: using guessed type int dword_1023B28;
+// 1023B30: using guessed type int dword_1023B30;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023E4C: using guessed type int dword_1023E4C;
+// 1023E7C: using guessed type int dword_1023E7C;
+// 1023EAC: using guessed type int dword_1023EAC;
+
+//----- (010111D3) --------------------------------------------------------
+void __userpurge MaelstromPartTwoController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST28_4
+CHAR *v4; // eax
+int v5; // edx
+char Dest; // [esp+30h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 3;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E64)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E74)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E84)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E9C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ECC)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(149, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023B48 == a3
+|| (struct TPinballComponent *)dword_1023B50 == a3
+|| (struct TPinballComponent *)dword_1023B58 == a3
+|| (struct TPinballComponent *)dword_1023B84 == a3
+|| (struct TPinballComponent *)dword_1023B8C == a3
+|| (struct TPinballComponent *)dword_1023B94 == a3
+|| (struct TPinballComponent *)dword_1023BC8 == a3
+|| (struct TPinballComponent *)dword_1023BD0 == a3
+|| (struct TPinballComponent *)dword_1023BD8 == a3
+|| (struct TPinballComponent *)dword_1023BE0 == a3
+|| (struct TPinballComponent *)dword_1023BE8 == a3
+|| (struct TPinballComponent *)dword_1023BF0 == a3
+|| (struct TPinballComponent *)dword_1023C3C == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E64)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E74)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E84)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E9C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ECC)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 26;
+MissionControl(66, 0);
+}
+}
+}
+// 1023888: using guessed type int dword_1023888;
+// 1023B48: using guessed type int dword_1023B48;
+// 1023B50: using guessed type int dword_1023B50;
+// 1023B58: using guessed type int dword_1023B58;
+// 1023B84: using guessed type int dword_1023B84;
+// 1023B8C: using guessed type int dword_1023B8C;
+// 1023B94: using guessed type int dword_1023B94;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023BC8: using guessed type int dword_1023BC8;
+// 1023BD0: using guessed type int dword_1023BD0;
+// 1023BD8: using guessed type int dword_1023BD8;
+// 1023BE0: using guessed type int dword_1023BE0;
+// 1023BE8: using guessed type int dword_1023BE8;
+// 1023BF0: using guessed type int dword_1023BF0;
+// 1023C3C: using guessed type int dword_1023C3C;
+// 1023E64: using guessed type int dword_1023E64;
+// 1023E74: using guessed type int dword_1023E74;
+// 1023E84: using guessed type int dword_1023E84;
+// 1023E9C: using guessed type int dword_1023E9C;
+// 1023ECC: using guessed type int dword_1023ECC;
+
+//----- (010113A1) --------------------------------------------------------
+void __userpurge MaelstromPartThreeController(int a1@, int a2, struct TPinballComponent *a3)
+{
+int v3; // ST30_4
+CHAR *v4; // eax
+int v5; // edx
+char Dest; // [esp+38h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 5;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E3C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E44)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E6C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EB4)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ED4)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EDC)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = *(_DWORD *)(dword_1023888 + 6);
+v4 = get_rc_string(150, 0);
+_sprintf(&Dest, v4, v3);
+TTextBox::Display(dword_1023E24, a1, &Dest, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_102372C == a3
+|| (struct TPinballComponent *)dword_1023734 == a3
+|| (struct TPinballComponent *)dword_102373C == a3
+|| (struct TPinballComponent *)dword_1023798 == a3
+|| (struct TPinballComponent *)dword_10237A0 == a3
+|| (struct TPinballComponent *)dword_10237A8 == a3
+|| (struct TPinballComponent *)dword_102389C == a3
+|| (struct TPinballComponent *)dword_10238A4 == a3
+|| (struct TPinballComponent *)dword_10238C0 == a3
+|| (struct TPinballComponent *)dword_10238C8 == a3
+|| (struct TPinballComponent *)dword_10238E8 == a3 )
+{
+v5 = *(_DWORD *)(dword_1023888 + 6) - 1;
+*(_DWORD *)(dword_1023888 + 6) = v5;
+if ( v5 )
+{
+MissionControl(67, a3);
+}
+else
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E3C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E44)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E6C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EB4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ED4)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EDC)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 27;
+MissionControl(66, 0);
+}
+}
+}
+// 102372C: using guessed type int dword_102372C;
+// 1023734: using guessed type int dword_1023734;
+// 102373C: using guessed type int dword_102373C;
+// 1023798: using guessed type int dword_1023798;
+// 10237A0: using guessed type int dword_10237A0;
+// 10237A8: using guessed type int dword_10237A8;
+// 1023888: using guessed type int dword_1023888;
+// 102389C: using guessed type int dword_102389C;
+// 10238A4: using guessed type int dword_10238A4;
+// 10238C0: using guessed type int dword_10238C0;
+// 10238C8: using guessed type int dword_10238C8;
+// 10238E8: using guessed type int dword_10238E8;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023E3C: using guessed type int dword_1023E3C;
+// 1023E44: using guessed type int dword_1023E44;
+// 1023E6C: using guessed type int dword_1023E6C;
+// 1023EB4: using guessed type int dword_1023EB4;
+// 1023ED4: using guessed type int dword_1023ED4;
+// 1023EDC: using guessed type int dword_1023EDC;
+
+//----- (01011582) --------------------------------------------------------
+void __userpurge MaelstromPartFourController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+*(_DWORD *)(dword_1023888 + 6) = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EC4)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(151, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023924 == a3 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EC4)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 28;
+MissionControl(66, 0);
+}
+}
+// 1023888: using guessed type int dword_1023888;
+// 1023924: using guessed type int dword_1023924;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023EC4: using guessed type int dword_1023EC4;
+
+//----- (01011612) --------------------------------------------------------
+void __userpurge MaelstromPartFiveController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EBC)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(152, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023870 == a3 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EBC)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 29;
+MissionControl(66, 0);
+}
+}
+// 1023870: using guessed type int dword_1023870;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023EBC: using guessed type int dword_1023EBC;
+
+//----- (01011699) --------------------------------------------------------
+void __userpurge MaelstromPartSixController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023940)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239D0)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E5C)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E94)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(153, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023930 == a3 || (struct TPinballComponent *)dword_10239C8 == a3 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E5C)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E94)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 30;
+MissionControl(66, 0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023940)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239D0)(20, 0.0);
+}
+}
+// 1023930: using guessed type int dword_1023930;
+// 1023940: using guessed type int dword_1023940;
+// 10239C8: using guessed type int dword_10239C8;
+// 10239D0: using guessed type int dword_10239D0;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023E5C: using guessed type int dword_1023E5C;
+// 1023E94: using guessed type int dword_1023E94;
+
+//----- (01011798) --------------------------------------------------------
+void __userpurge MaelstromPartSevenController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+AdvanceWormHoleDestination(1);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239EC)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239F4)(7, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239FC)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(154, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_10239EC == a3
+|| (struct TPinballComponent *)dword_10239F4 == a3
+|| (struct TPinballComponent *)dword_10239FC == a3 )
+{
+*(_DWORD *)(dword_1023BBC + 6) = 31;
+MissionControl(66, 0);
+}
+}
+// 10239EC: using guessed type int dword_10239EC;
+// 10239F4: using guessed type int dword_10239F4;
+// 10239FC: using guessed type int dword_10239FC;
+// 1023BBC: using guessed type int dword_1023BBC;
+
+//----- (0101184C) --------------------------------------------------------
+void __userpurge MaelstromPartEightController(int a1@, int a2, struct TPinballComponent *a3)
+{
+char *v3; // eax
+int v4; // ST10_4
+CHAR *v5; // eax
+char *v6; // eax
+char Dest; // [esp+14h] [ebp-44h]
+
+if ( a2 != 63 )
+{
+if ( a2 == 66 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239C0)(19, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E54)(7, 0.0);
+}
+else if ( a2 != 67 )
+{
+return;
+}
+v3 = get_rc_string(155, 0);
+TTextBox::Display(dword_1023E24, a1, v3, -1.0);
+return;
+}
+if ( (struct TPinballComponent *)dword_1023980 == a3 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023E54)(20, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239C0)(20, 0.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v4 = SpecialAddScore(5000000);
+v5 = get_rc_string(78, 0);
+_sprintf(&Dest, v5, v4);
+v6 = get_rc_string(48, 0);
+TTextBox::Display(dword_1023E1C, a1, v6, 4.0);
+if ( !AddRankProgress(18) )
+{
+TTextBox::Display(dword_1023E24, a1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D14 + 20))();
+}
+}
+}
+// 1023980: using guessed type int dword_1023980;
+// 10239C0: using guessed type int dword_10239C0;
+// 1023BBC: using guessed type int dword_1023BBC;
+// 1023D14: using guessed type int dword_1023D14;
+// 1023E54: using guessed type int dword_1023E54;
+
+//----- (01011985) --------------------------------------------------------
+void __stdcall GameoverController(int a1, struct TPinballComponent *a2)
+{
+TTextBox *v2; // eax
+int v3; // esi
+int v4; // esi
+int v5; // ecx
+CHAR *v6; // eax
+int v7; // esi
+int v8; // esi
+int v9; // ecx
+int v10; // esi
+CHAR *v11; // eax
+char *v12; // eax
+int v13; // [esp+10h] [ebp-94h]
+int v14; // [esp+10h] [ebp-94h]
+char Dest; // [esp+20h] [ebp-84h]
+
+if ( a1 != 66 )
+{
+if ( a1 != 67 )
+return;
+v2 = dword_1023E24;
+v3 = *(_DWORD *)((char *)dword_1023E24 + 6);
+if ( !(v3 & 0x100) )
+{
+if ( !(v3 & 0x200) )
+goto LABEL_33;
+goto LABEL_18;
+}
+v4 = *(_DWORD *)((_BYTE *)dword_1023E24 + 6) & 0xF;
+v5 = **(_DWORD **)((char *)dword_1025040 + 28 * v4 + 102);
+v3 = v4 + 1;
+if ( v5 >= 0 )
+{
+switch ( v3 )
+{
+case 1:
+v13 = v5;
+v6 = get_rc_string(180, 0);
+break;
+case 2:
+v13 = v5;
+v6 = get_rc_string(181, 0);
+break;
+case 3:
+v13 = v5;
+v6 = get_rc_string(182, 0);
+break;
+case 4:
+v13 = v5;
+v6 = get_rc_string(183, 0);
+break;
+default:
+goto LABEL_9;
+}
+_sprintf(&Dest, v6, v13);
+TTextBox::Display(dword_1023E24, 256, &Dest, 3.0);
+if ( v3 == *(_DWORD *)((char *)dword_1025040 + 214) )
+v7 = 512;
+else
+v7 = v3 | 0x100;
+goto LABEL_32;
+}
+LABEL_9:
+*(_DWORD *)((char *)dword_1023E24 + 6) = 512;
+v2 = dword_1023E24;
+LABEL_18:
+v8 = v3 & 0xF;
+v9 = dword_1025598[9 * v8];
+v10 = v8 + 1;
+if ( v9 > 0 )
+{
+switch ( v10 )
+{
+case 1:
+v14 = v9;
+v11 = get_rc_string(184, 0);
+break;
+case 2:
+v14 = v9;
+v11 = get_rc_string(185, 0);
+break;
+case 3:
+v14 = v9;
+v11 = get_rc_string(186, 0);
+break;
+case 4:
+v14 = v9;
+v11 = get_rc_string(187, 0);
+break;
+case 5:
+v14 = v9;
+v11 = get_rc_string(188, 0);
+break;
+default:
+goto LABEL_33;
+}
+_sprintf(&Dest, v11, v14);
+TTextBox::Display(dword_1023E24, 256, &Dest, 3.0);
+if ( v10 == 5 )
+v7 = 0;
+else
+v7 = v10 | 0x200;
+LABEL_32:
+*(_DWORD *)((char *)dword_1023E24 + 6) = v7;
+return;
+}
+LABEL_33:
+*(_DWORD *)((char *)v2 + 6) = 256;
+v12 = get_rc_string(172, 0);
+TTextBox::Display(dword_1023E24, 256, v12, 10.0);
+return;
+}
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023EEC)(20, 0.0);
+pb_mode_change(2);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A74)(1022, 0.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A7C)(1022, 0.0);
+*(_DWORD *)((char *)dword_1023E24 + 6) = 0;
+}
+// 1023A74: using guessed type int dword_1023A74;
+// 1023A7C: using guessed type int dword_1023A7C;
+// 1023EEC: using guessed type int dword_1023EEC;
+
+//----- (01011B98) --------------------------------------------------------
+void __stdcall UnselectMissionController(int a1, struct TPinballComponent *a2)
+{
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+}
+// 1023BBC: using guessed type int dword_1023BBC;
+
+//----- (01011BB5) --------------------------------------------------------
+void __stdcall MissionControl(int a1, struct TPinballComponent *a2)
+{
+int v2; // ebx
+signed int v3; // edi
+void (__thiscall ***v4)(_DWORD, signed int, _DWORD); // ebx
+void (__thiscall ***v5)(_DWORD, signed int, _DWORD); // ebx
+char *v6; // eax
+char *v7; // eax
+int v8; // [esp+30h] [ebp-4h]
+
+if ( dword_1023BBC )
+{
+v2 = *(_DWORD *)(dword_1023BBC + 6);
+v3 = a1;
+v8 = *(_DWORD *)(dword_1023BBC + 6);
+switch ( a1 )
+{
+case 47:
+if ( (struct TPinballComponent *)dword_1023978 == a2 && v2 > 1 )
+{
+v4 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A8C;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A8C)(34, 0.0);
+(**v4)(v4, 20, 0.0);
+v5 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023A94;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023A94)(34, 0.0);
+(**v5)(v5, 20, 0.0);
+v6 = get_rc_string(109, 0);
+TTextBox::Display(dword_1023E24, (int)v5, v6, 4.0);
+*(_DWORD *)(dword_1023BBC + 6) = 1;
+MissionControl(66, 0);
+v2 = v8;
+}
+break;
+case 60:
+if ( (struct TPinballComponent *)dword_1023978 == a2 && v2 )
+{
+if ( (**(int (__stdcall ***)(signed int, _DWORD))dword_1023978)(37, 0.0) == 1 )
+{
+v7 = get_rc_string(116, 0);
+TTextBox::Display(dword_1023E24, v2, v7, 4.0);
+}
+break;
+}
+if ( dword_1023E24 == a2 )
+goto LABEL_14;
+break;
+case 1009:
+LABEL_14:
+v3 = 67;
+break;
+}
+switch ( v2 )
+{
+case 0:
+WaitingDeploymentController(v2, v3, a2);
+break;
+case 1:
+SelectMissionController(v3, a2);
+break;
+case 2:
+PracticeMissionController(v2, v3, a2);
+break;
+case 3:
+LaunchTrainingController(v2, v3, a2);
+break;
+case 4:
+ReentryTrainingController(v2, v3, a2);
+break;
+case 5:
+ScienceMissionController(v2, v3, a2);
+break;
+case 6:
+StrayCometController(v2, v3, a2);
+break;
+case 7:
+BlackHoleThreatController(v2, v3, a2);
+break;
+case 8:
+SpaceRadiationController(v2, v3, a2);
+break;
+case 9:
+BugHuntController(v2, v3, a2);
+break;
+case 10:
+AlienMenaceController(v2, v3, a2);
+break;
+case 11:
+RescueMissionController(v2, v3, a2);
+break;
+case 12:
+SatelliteController(v2, v3, a2);
+break;
+case 13:
+ReconnaissanceController(v2, v3, a2);
+break;
+case 14:
+DoomsdayMachineController(v2, v3, a2);
+break;
+case 15:
+CosmicPlagueController(v2, v3, a2);
+break;
+case 16:
+SecretMissionYellowController(v2, v3, a2);
+break;
+case 17:
+TimeWarpController(v2, v3, a2);
+break;
+case 18:
+MaelstromController(v2, v3, a2);
+break;
+case 20:
+AlienMenacePartTwoController(v2, v3, a2);
+break;
+case 21:
+CosmicPlaguePartTwoController(v2, v3, a2);
+break;
+case 22:
+SecretMissionRedController(v2, v3, a2);
+break;
+case 23:
+SecretMissionGreenController(v2, v3, a2);
+break;
+case 24:
+TimeWarpPartTwoController(v2, v3, a2);
+break;
+case 25:
+MaelstromPartTwoController(v2, v3, a2);
+break;
+case 26:
+MaelstromPartThreeController(v2, v3, a2);
+break;
+case 27:
+MaelstromPartFourController(v2, v3, a2);
+break;
+case 28:
+MaelstromPartFiveController(v2, v3, a2);
+break;
+case 29:
+MaelstromPartSixController(v2, v3, a2);
+break;
+case 30:
+MaelstromPartSevenController(v2, v3, a2);
+break;
+case 31:
+MaelstromPartEightController(v2, v3, a2);
+break;
+case 32:
+GameoverController(v3, a2);
+break;
+default:
+UnselectMissionController(v3, a2);
+break;
+}
+}
+}
+// 1023978: using guessed type int dword_1023978;
+// 1023A8C: using guessed type int dword_1023A8C;
+// 1023A94: using guessed type int dword_1023A94;
+// 1023BBC: using guessed type int dword_1023BBC;
diff --git a/objlist.cpp b/objlist.cpp
new file mode 100644
index 0000000..d6b5d36
--- /dev/null
+++ b/objlist.cpp
@@ -0,0 +1,82 @@
+#include "pinball.h"
+
+//----- (01012E51) --------------------------------------------------------
+int __stdcall objlist_add_object(_DWORD *a1, int a2)
+{
+int v2; // ecx
+
+v2 = a1[1];
+if ( v2 >= *a1 )
+return 0;
+a1[v2 + 2] = a2;
+return ++a1[1];
+}
+
+//----- (01012E7A) --------------------------------------------------------
+signed int __stdcall objlist_delete_object(int a1, int a2)
+{
+int v2; // edx
+int v3; // ecx
+_DWORD *v4; // esi
+
+v2 = *(_DWORD *)(a1 + 4);
+v3 = v2 - 1;
+if ( v2 - 1 < 0 )
+return 0;
+v4 = (_DWORD *)(a1 + 4 * v3 + 8);
+while ( *v4 != a2 )
+{
+--v3;
+--v4;
+if ( v3 < 0 )
+return 0;
+}
+*(_DWORD *)(a1 + 4 * v3 + 8) = *(_DWORD *)(a1 + 4 * v2 + 4);
+--*(_DWORD *)(a1 + 4);
+return 1;
+}
+
+//----- (01012EBE) --------------------------------------------------------
+_DWORD *__stdcall objlist_new(int a1)
+{
+_DWORD *result; // eax
+
+result = (_DWORD *)memoryallocate(4 * a1 + 12);
+if ( result )
+{
+result[1] = 0;
+*result = a1;
+}
+return result;
+}
+
+//----- (01012EE8) --------------------------------------------------------
+int *__stdcall objlist_grow(int *a1, int a2)
+{
+int *v2; // esi
+int v3; // eax
+int *v4; // eax
+
+v2 = a1;
+if ( a1 )
+{
+v3 = a2 + a1[1];
+if ( v3 > *a1 )
+{
+v4 = (int *)memoryrealloc((int)a1, 4 * v3 + 12);
+if ( v4 )
+{
+v2 = v4;
+*v4 = a2 + v4[1];
+}
+}
+}
+return v2;
+}
+
+//----- (01013C6F) --------------------------------------------------------
+void __stdcall objlist_destroy(int a1)
+{
+if ( a1 )
+memoryfree(a1);
+}
diff --git a/options.cpp b/options.cpp
new file mode 100644
index 0000000..73fda2c
--- /dev/null
+++ b/options.cpp
@@ -0,0 +1,587 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "pinball.h"
+
+//----- (010034B6) --------------------------------------------------------
+CHAR *__stdcall options_path_init(LPCSTR lpString)
+{
+ int v1; // eax
+ CHAR *result; // eax
+
+ v1 = lstrlenA(lpString);
+ result = (CHAR *)memoryallocate(v1 + 1);
+ lpString2 = result;
+ if ( result )
+ result = lstrcpyA(result, lpString);
+ return result;
+}
+
+//----- (010034E7) --------------------------------------------------------
+void __stdcall options_path_uninit()
+{
+ if ( lpString2 )
+ memoryfree((int)lpString2);
+ lpString2 = 0;
+}
+
+//----- (01003503) --------------------------------------------------------
+LPCSTR __stdcall options_path(LPCSTR lpString2)
+{
+ CHAR *v1; // eax
+
+ v1 = lpString1;
+ if ( !lpString1 )
+ {
+ v1 = (CHAR *)memoryallocate(0x7D0u);
+ lpString1 = v1;
+ if ( !v1 )
+ return ::lpString2;
+ }
+ lstrcpyA(v1, ::lpString2);
+ if ( lpString2 )
+ {
+ lstrcatA(lpString1, "\\");
+ lstrcatA(lpString1, lpString2);
+ }
+ return lpString1;
+}
+
+//----- (0100356C) --------------------------------------------------------
+void __stdcall options_path_free()
+{
+ if ( lpString1 )
+ memoryfree((int)lpString1);
+ lpString1 = 0;
+}
+
+//----- (01003588) --------------------------------------------------------
+HKEY __stdcall options_get_int(DWORD cbData, LPCSTR lpValueName, HKEY phkResult)
+{
+ HKEY result; // eax
+ const CHAR *v4; // eax
+ DWORD dwDisposition; // [esp+4h] [ebp-8h]
+ BYTE Data[4]; // [esp+8h] [ebp-4h]
+
+ result = phkResult;
+ *(_DWORD *)Data = phkResult;
+ if ( lpString2 )
+ {
+ v4 = options_path((LPCSTR)cbData);
+ if ( !RegCreateKeyExA(HKEY_CURRENT_USER, v4, 0, 0, 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
+ {
+ cbData = 4;
+ RegQueryValueExA(phkResult, lpValueName, 0, 0, Data, &cbData);
+ RegCloseKey(phkResult);
+ }
+ options_path_free();
+ result = *(HKEY *)Data;
+ }
+ return result;
+}
+
+//----- (01003601) --------------------------------------------------------
+void __stdcall options_get_string(DWORD dwDisposition, LPCSTR lpValueName, LPSTR lpString1, LPCSTR lpString2, int iMaxLength)
+{
+ const CHAR *v5; // edi
+ const CHAR *v6; // eax
+
+ v5 = (const CHAR *)iMaxLength;
+ lstrcpynA(lpString1, lpString2, iMaxLength);
+ if ( ::lpString2 )
+ {
+ v6 = options_path((LPCSTR)dwDisposition);
+ if ( !RegCreateKeyExA(HKEY_CURRENT_USER, v6, 0, 0, 0, 0xF003Fu, 0, (PHKEY)&iMaxLength, &dwDisposition) )
+ {
+ lpString2 = v5;
+ RegQueryValueExA((HKEY)iMaxLength, lpValueName, 0, 0, (LPBYTE)lpString1, (LPDWORD)&lpString2);
+ RegCloseKey((HKEY)iMaxLength);
+ }
+ options_path_free();
+ }
+}
+
+//----- (0100367C) --------------------------------------------------------
+void __stdcall options_set_int(HKEY phkResult, LPCSTR lpValueName, BYTE Data)
+{
+ const CHAR *v3; // eax
+ DWORD dwDisposition; // [esp+4h] [ebp-4h]
+
+ if ( lpString2 )
+ {
+ v3 = options_path((LPCSTR)phkResult);
+ if ( !RegCreateKeyExA(HKEY_CURRENT_USER, v3, 0, 0, 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
+ {
+ RegSetValueExA(phkResult, lpValueName, 0, 4u, &Data, 4u);
+ RegCloseKey(phkResult);
+ }
+ options_path_free();
+ }
+}
+
+//----- (010036E3) --------------------------------------------------------
+void __stdcall options_set_string(HKEY phkResult, LPCSTR lpValueName, LPCSTR lpString)
+{
+ const CHAR *v3; // eax
+ int v4; // eax
+ DWORD dwDisposition; // [esp+4h] [ebp-4h]
+
+ if ( lpString2 )
+ {
+ v3 = options_path((LPCSTR)phkResult);
+ if ( !RegCreateKeyExA(HKEY_CURRENT_USER, v3, 0, 0, 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
+ {
+ v4 = lstrlenA(lpString);
+ RegSetValueExA(phkResult, lpValueName, 0, 1u, (const BYTE *)lpString, v4 + 1);
+ RegCloseKey(phkResult);
+ }
+ options_path_free();
+ }
+}
+
+//----- (010055F3) --------------------------------------------------------
+void __stdcall options_uninit()
+{
+ options_set_int(0, "Sounds", (BYTE)options);
+ options_set_int(0, "Music", (BYTE)phkResult);
+ options_set_int(0, "FullScreen", (BYTE)dword_102822C);
+ options_set_int(0, "Players", (BYTE)dword_1028234);
+ options_set_int(0, "Left Flippper key", (BYTE)dword_1028238);
+ options_set_int(0, "Right Flipper key", (BYTE)dword_102823C);
+ options_set_int(0, "Plunger key", (BYTE)dword_1028240);
+ options_set_int(0, "Left Table Bump key", (BYTE)dword_1028244);
+ options_set_int(0, "Right Table Bump key", (BYTE)dword_1028248);
+ options_set_int(0, "Bottom Table Bump key", (BYTE)dword_102824C);
+}
+
+//----- (010056A9) --------------------------------------------------------
+HMENU __stdcall options_menu_set(UINT uIDEnableItem, int a2)
+{
+ HMENU result; // eax
+
+ result = hMenu;
+ if ( hMenu )
+ result = (HMENU)EnableMenuItem(hMenu, uIDEnableItem, a2 == 0);
+ return result;
+}
+
+//----- (010056D3) --------------------------------------------------------
+HMENU __stdcall options_menu_check(UINT uIDCheckItem, int a2)
+{
+ HMENU result; // eax
+
+ result = hMenu;
+ if ( hMenu )
+ result = (HMENU)CheckMenuItem(hMenu, uIDCheckItem, a2 != 0 ? 8 : 0);
+ return result;
+}
+
+//----- (010056FF) --------------------------------------------------------
+HMENU __stdcall options_toggle(UINT uIDCheckItem)
+{
+ HMENU result; // eax
+ int v2; // ST08_4
+ int v3; // esi
+ bool v4; // zf
+ int v5; // ST08_4
+
+ switch ( uIDCheckItem )
+ {
+ case 0xC9u:
+ v3 = options == 0;
+ v5 = options == 0;
+ options = (HKEY)(options == 0);
+ Sound_Enable(0, 7, v5);
+ return options_menu_check(uIDCheckItem, v3);
+ case 0xCAu:
+ v3 = phkResult == 0;
+ v4 = phkResult != 0;
+ phkResult = (HKEY)(phkResult == 0);
+ if ( v4 )
+ midi_music_stop();
+ else
+ midi_play_pb_theme(0);
+ return options_menu_check(uIDCheckItem, v3);
+ case 0x193u:
+ v2 = dword_102822C == 0;
+ dword_102822C = (HKEY)(dword_102822C == 0);
+ v3 = v2;
+ fullscrn_set_screen_mode(v2);
+ return options_menu_check(uIDCheckItem, v3);
+ }
+ if ( (signed int)uIDCheckItem > 407 && (signed int)uIDCheckItem <= 411 )
+ {
+ dword_1028234 = (HKEY)(uIDCheckItem - 407);
+ options_menu_check(0x198u, uIDCheckItem == 408);
+ options_menu_check(0x199u, dword_1028234 == (HKEY)2);
+ options_menu_check(0x19Au, dword_1028234 == (HKEY)3);
+ result = options_menu_check(0x19Bu, dword_1028234 == (HKEY)4);
+ }
+ return result;
+}
+
+//----- (0100580C) --------------------------------------------------------
+unsigned int __stdcall get_vk_key_name(__int16 a1, LPSTR lpString)
+{
+ LONG v2; // eax
+
+ v2 = MapVirtualKeyA((unsigned __int16)a1, 0) << 16;
+ if ( (unsigned __int16)a1 >= 0x21u && (unsigned __int16)a1 <= 0x2Eu )
+ v2 |= 0x1000000u;
+ return GetKeyNameTextA(v2, lpString, 19) != 0 ? (unsigned int)lpString : 0;
+}
+
+//----- (01005850) --------------------------------------------------------
+BOOL __stdcall KeyMapDlgProc(HWND a1, UINT a2, WPARAM a3, LPARAM a4)
+{
+ unsigned int v5; // eax
+ LRESULT v6; // eax
+ unsigned int v7; // eax
+ LRESULT v8; // eax
+ unsigned int v9; // eax
+ LRESULT v10; // eax
+ unsigned int v11; // eax
+ LRESULT v12; // eax
+ unsigned int v13; // eax
+ LRESULT v14; // eax
+ unsigned int v15; // eax
+ LRESULT v16; // eax
+ unsigned __int16 v17; // ax
+ unsigned __int16 v18; // ax
+ unsigned __int16 v19; // ax
+ unsigned __int16 v20; // ax
+ unsigned __int16 v21; // ax
+ unsigned __int16 v22; // ax
+ HKEY v23; // ebx
+ __int16 *v24; // edi
+ HKEY *v25; // esi
+ CHAR *v26; // eax
+ CHAR *v27; // eax
+ __int16 v28; // cx
+ __int16 v29; // dx
+ INT_PTR v30; // eax
+ __int16 v31; // [esp+Ch] [ebp-B0h]
+ HKEY v32; // [esp+10h] [ebp-ACh]
+ HKEY v33; // [esp+14h] [ebp-A8h]
+ HKEY v34; // [esp+18h] [ebp-A4h]
+ HKEY v35; // [esp+1Ch] [ebp-A0h]
+ HKEY v36; // [esp+20h] [ebp-9Ch]
+ HKEY v37; // [esp+24h] [ebp-98h]
+ INT_PTR nResult; // [esp+28h] [ebp-94h]
+ WPARAM v39; // [esp+2Ch] [ebp-90h]
+ __int16 *i; // [esp+30h] [ebp-8Ch]
+ LPARAM v41; // [esp+34h] [ebp-88h]
+ WPARAM wParam; // [esp+38h] [ebp-84h]
+ HWND hDlg; // [esp+3Ch] [ebp-80h]
+ CHAR String1; // [esp+40h] [ebp-7Ch]
+ CHAR lParam[20]; // [esp+A4h] [ebp-18h]
+
+ hDlg = a1;
+ switch ( a2 )
+ {
+ case 0x53u:
+ WinHelpA(*(HWND *)(a4 + 12), "pinball.hlp", 0xCu, (ULONG_PTR)&unk_1023540);
+ return 1;
+ case 0x7Bu:
+ WinHelpA((HWND)a3, "pinball.hlp", 0xAu, (ULONG_PTR)&unk_1023540);
+ return 1;
+ case 0x110u:
+ i = &vk_list;
+ if ( vk_list == -1 )
+ return 1;
+ while ( 1 )
+ {
+ v28 = *i;
+ v29 = *i & 0x4000;
+ v30 = (unsigned __int8)*i;
+ v39 = (unsigned __int8)*i;
+ v31 = v29;
+ if ( v29 )
+ {
+ wParam = 128;
+ nResult = (unsigned __int16)v30;
+ do
+ {
+ if ( nResult == MapVirtualKeyA((unsigned __int16)wParam, 2u) )
+ break;
+ ++wParam;
+ }
+ while ( (unsigned __int16)wParam < 0x100u );
+ LOWORD(v30) = wParam;
+ if ( (_WORD)wParam != 256 )
+ {
+ *(_WORD *)lParam = (unsigned __int8)v39;
+ v39 = wParam;
+ nResult = wParam;
+ LABEL_32:
+ v41 = (unsigned __int16)v30;
+ while ( 1 )
+ {
+ if ( v31 || get_vk_key_name(v30, lParam) )
+ {
+ wParam = (unsigned __int16)SendDlgItemMessageA(hDlg, 401, 0x14Au, 0xFFFFFFFF, (LPARAM)lParam);
+ SendDlgItemMessageA(hDlg, 401, 0x151u, wParam, v41);
+ if ( (HKEY)v41 == dword_1028238 )
+ SendDlgItemMessageA(hDlg, 401, 0x14Eu, wParam, 0);
+ wParam = (unsigned __int16)SendDlgItemMessageA(hDlg, 402, 0x14Au, 0xFFFFFFFF, (LPARAM)lParam);
+ SendDlgItemMessageA(hDlg, 402, 0x151u, wParam, v41);
+ if ( (HKEY)v41 == dword_102823C )
+ SendDlgItemMessageA(hDlg, 402, 0x14Eu, wParam, 0);
+ wParam = (unsigned __int16)SendDlgItemMessageA(hDlg, 403, 0x14Au, 0xFFFFFFFF, (LPARAM)lParam);
+ SendDlgItemMessageA(hDlg, 403, 0x151u, wParam, v41);
+ if ( (HKEY)v41 == dword_1028240 )
+ SendDlgItemMessageA(hDlg, 403, 0x14Eu, wParam, 0);
+ wParam = (unsigned __int16)SendDlgItemMessageA(hDlg, 404, 0x14Au, 0xFFFFFFFF, (LPARAM)lParam);
+ SendDlgItemMessageA(hDlg, 404, 0x151u, wParam, v41);
+ if ( (HKEY)v41 == dword_1028244 )
+ SendDlgItemMessageA(hDlg, 404, 0x14Eu, wParam, 0);
+ wParam = (unsigned __int16)SendDlgItemMessageA(hDlg, 405, 0x14Au, 0xFFFFFFFF, (LPARAM)lParam);
+ SendDlgItemMessageA(hDlg, 405, 0x151u, wParam, v41);
+ if ( (HKEY)v41 == dword_1028248 )
+ SendDlgItemMessageA(hDlg, 405, 0x14Eu, wParam, 0);
+ wParam = (unsigned __int16)SendDlgItemMessageA(hDlg, 406, 0x14Au, 0xFFFFFFFF, (LPARAM)lParam);
+ SendDlgItemMessageA(hDlg, 406, 0x151u, wParam, v41);
+ if ( (HKEY)v41 == dword_102824C )
+ SendDlgItemMessageA(hDlg, 406, 0x14Eu, wParam, 0);
+ }
+ ++v39;
+ ++v41;
+ if ( (unsigned __int16)v39 > (unsigned __int16)nResult )
+ break;
+ LOWORD(v30) = v39;
+ }
+ goto LABEL_49;
+ }
+ }
+ else
+ {
+ if ( v28 >= 0 )
+ {
+ nResult = v30;
+ }
+ else
+ {
+ ++i;
+ LOWORD(nResult) = *i;
+ }
+ if ( (unsigned __int16)v30 <= (unsigned __int16)nResult )
+ goto LABEL_32;
+ }
+ LABEL_49:
+ ++i;
+ if ( *i == -1 )
+ return 1;
+ }
+ }
+ if ( a2 != 273 )
+ return 0;
+ nResult = (unsigned __int16)a3;
+ switch ( (unsigned __int16)a3 )
+ {
+ case 1u:
+ v39 = 0;
+ v17 = SendDlgItemMessageA(a1, 401, 0x147u, 0, 0);
+ v32 = (HKEY)SendDlgItemMessageA(hDlg, 401, 0x150u, v17, 0);
+ v18 = SendDlgItemMessageA(hDlg, 402, 0x147u, 0, 0);
+ v33 = (HKEY)SendDlgItemMessageA(hDlg, 402, 0x150u, v18, 0);
+ v19 = SendDlgItemMessageA(hDlg, 403, 0x147u, 0, 0);
+ v34 = (HKEY)SendDlgItemMessageA(hDlg, 403, 0x150u, v19, 0);
+ v20 = SendDlgItemMessageA(hDlg, 404, 0x147u, 0, 0);
+ v35 = (HKEY)SendDlgItemMessageA(hDlg, 404, 0x150u, v20, 0);
+ v21 = SendDlgItemMessageA(hDlg, 405, 0x147u, 0, 0);
+ v36 = (HKEY)SendDlgItemMessageA(hDlg, 405, 0x150u, v21, 0);
+ v22 = SendDlgItemMessageA(hDlg, 406, 0x147u, 0, 0);
+ v23 = (HKEY)SendDlgItemMessageA(hDlg, 406, 0x150u, v22, 0);
+ v37 = v23;
+ v24 = (__int16 *)1;
+ v25 = &v32;
+ while ( !v39 )
+ {
+ for ( i = v24; (signed int)i < 6; i = (__int16 *)((char *)i + 1) )
+ {
+ if ( v39 )
+ break;
+ if ( *v25 == *(&v32 + (_DWORD)i) )
+ {
+ v26 = get_rc_string(43, 0);
+ lstrcpyA(&String1, v26);
+ v27 = get_rc_string(39, 0);
+ MessageBoxA(hDlg, v27, &String1, 0x2000u);
+ v39 = 1;
+ }
+ }
+ v24 = (__int16 *)((char *)v24 + 1);
+ ++v25;
+ if ( (signed int)v24 - 1 >= 5 )
+ {
+ if ( v39 )
+ return 1;
+ dword_1028238 = v32;
+ dword_102823C = v33;
+ dword_1028240 = v34;
+ dword_1028244 = v35;
+ dword_1028248 = v36;
+ dword_102824C = v23;
+ goto LABEL_20;
+ }
+ }
+ break;
+ case 2u:
+ LABEL_20:
+ EndDialog(hDlg, nResult);
+ break;
+ case 0x1F5u:
+ v5 = get_vk_key_name(dword_1028250, lParam);
+ v6 = SendDlgItemMessageA(hDlg, 401, 0x158u, 0, v5);
+ SendDlgItemMessageA(hDlg, 401, 0x14Eu, v6, 0);
+ v7 = get_vk_key_name(dword_1028254, lParam);
+ v8 = SendDlgItemMessageA(hDlg, 402, 0x158u, 0, v7);
+ SendDlgItemMessageA(hDlg, 402, 0x14Eu, v8, 0);
+ v9 = get_vk_key_name(dword_1028258, lParam);
+ v10 = SendDlgItemMessageA(hDlg, 403, 0x158u, 0, v9);
+ SendDlgItemMessageA(hDlg, 403, 0x14Eu, v10, 0);
+ v11 = get_vk_key_name(dword_102825C, lParam);
+ v12 = SendDlgItemMessageA(hDlg, 404, 0x158u, 0, v11);
+ SendDlgItemMessageA(hDlg, 404, 0x14Eu, v12, 0);
+ v13 = get_vk_key_name(dword_1028260, lParam);
+ v14 = SendDlgItemMessageA(hDlg, 405, 0x158u, 0, v13);
+ SendDlgItemMessageA(hDlg, 405, 0x14Eu, v14, 0);
+ v15 = get_vk_key_name(dword_1028264, lParam);
+ v16 = SendDlgItemMessageA(hDlg, 406, 0x158u, 0, v15);
+ SendDlgItemMessageA(hDlg, 406, 0x14Eu, v16, 0);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+// 1023508: using guessed type __int16 vk_list;
+
+//----- (01005F45) --------------------------------------------------------
+INT_PTR __stdcall options_keyboard()
+{
+ return DialogBoxParamA(hinst, "KEYMAPPER", hwnd_frame, KeyMapDlgProc, 0);
+}
+
+//----- (01005F69) --------------------------------------------------------
+void __stdcall options_init(HMENU a1)
+{
+ CHAR *v1; // eax
+ CHAR *v2; // edi
+
+ hMenu = a1;
+ options = (HKEY)1;
+ phkResult = 0;
+ dword_102822C = 0;
+ dword_1028228 = (HKEY)5;
+ dword_1028230 = (HKEY)2;
+ *(_DWORD *)&dword_1028250 = 90;
+ *(_DWORD *)&dword_1028254 = 191;
+ *(_DWORD *)&dword_1028258 = 32;
+ *(_DWORD *)&dword_102825C = 88;
+ *(_DWORD *)&dword_1028260 = 190;
+ *(_DWORD *)&dword_1028264 = 38;
+ get_rc_int(159, (int *)&dword_1028250);
+ get_rc_int(160, (int *)&dword_1028254);
+ get_rc_int(161, (int *)&dword_1028258);
+ get_rc_int(162, (int *)&dword_102825C);
+ get_rc_int(163, (int *)&dword_1028260);
+ get_rc_int(164, (int *)&dword_1028264);
+ dword_1028238 = *(HKEY *)&dword_1028250;
+ dword_102823C = *(HKEY *)&dword_1028254;
+ dword_1028240 = *(HKEY *)&dword_1028258;
+ dword_1028244 = *(HKEY *)&dword_102825C;
+ dword_1028248 = *(HKEY *)&dword_1028260;
+ dword_1028234 = (HKEY)1;
+ dword_102824C = *(HKEY *)&dword_1028264;
+ options = options_get_int(0, "Sounds", options);
+ phkResult = options_get_int(0, "Music", phkResult);
+ dword_1028228 = options_get_int(0, "Average", dword_1028228);
+ dword_102822C = options_get_int(0, "FullScreen", dword_102822C);
+ dword_1028230 = options_get_int(0, "Priority_Adjustment", dword_1028230);
+ dword_1028234 = options_get_int(0, "Players", dword_1028234);
+ dword_1028238 = options_get_int(0, "Left Flippper key", dword_1028238);
+ dword_102823C = options_get_int(0, "Right Flipper key", dword_102823C);
+ dword_1028240 = options_get_int(0, "Plunger key", dword_1028240);
+ dword_1028244 = options_get_int(0, "Left Table Bump key", dword_1028244);
+ dword_1028248 = options_get_int(0, "Right Table Bump key", dword_1028248);
+ dword_102824C = options_get_int(0, "Bottom Table Bump key", dword_102824C);
+ options_menu_check(0xC9u, (int)options);
+ Sound_Enable(0, 7, (int)options);
+ options_menu_check(0xCAu, (int)phkResult);
+ options_menu_check(0x193u, (int)dword_102822C);
+ options_menu_check(0x198u, dword_1028234 == (HKEY)1);
+ options_menu_check(0x199u, dword_1028234 == (HKEY)2);
+ options_menu_check(0x19Au, dword_1028234 == (HKEY)3);
+ options_menu_check(0x19Bu, dword_1028234 == (HKEY)4);
+ v1 = (CHAR *)memoryallocate(0x1F4u);
+ v2 = v1;
+ if ( v1 )
+ {
+ options_get_string(0, "Shell Exe", v1, WindowName, 500);
+ if ( !*v2 )
+ {
+ if ( hMenu )
+ {
+ DeleteMenu(hMenu, 0x195u, 0);
+ DrawMenuBar(hwnd_frame);
+ }
+ }
+ }
+}
+
+//----- (010067F3) --------------------------------------------------------
+int __stdcall FindShiftKeys()
+{
+ signed int v0; // esi
+ int v1; // eax
+ int result; // eax
+ CHAR String; // [esp+Ch] [ebp-18h]
+
+ RightShift = -1;
+ LeftShift = -1;
+ v0 = 0;
+ do
+ {
+ if ( MapVirtualKeyA(v0, 1u) == 16 )
+ {
+ LeftShift = v0;
+ break;
+ }
+ ++v0;
+ }
+ while ( v0 < 256 );
+ while ( ++v0 < 256 )
+ {
+ if ( MapVirtualKeyA(v0, 1u) == 16 )
+ {
+ RightShift = v0;
+ break;
+ }
+ }
+ if ( !GetKeyNameTextA(LeftShift << 16, &String, 19) || !__strnicmp(&String, "right", 5u) )
+ {
+ v1 = RightShift;
+ }
+ else
+ {
+ v1 = LeftShift;
+ LeftShift = RightShift;
+ RightShift = v1;
+ }
+ result = GetKeyNameTextA(v1 << 16, &String, 19);
+ if ( result )
+ {
+ result = __strnicmp(&String, "left", 4u);
+ if ( result )
+ {
+ result = LeftShift;
+ LeftShift = RightShift;
+ RightShift = result;
+ }
+ }
+ return result;
+}
+// 10235EC: using guessed type int LeftShift;
+// 10235F0: using guessed type int RightShift;
diff --git a/partman/loader.cpp b/partman/loader.cpp
new file mode 100644
index 0000000..fcc4c98
--- /dev/null
+++ b/partman/loader.cpp
@@ -0,0 +1,644 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "../pinball.h"
+
+//----- (01008F7A) --------------------------------------------------------
+signed int __stdcall loader_error(int a1, int a2)
+{
+ int v2; // eax
+ const CHAR *v3; // esi
+ const CHAR *v4; // edi
+ int v5; // edx
+ int v6; // ecx
+
+ v2 = loader_errors[0];
+ v3 = 0;
+ v4 = 0;
+ v5 = 0;
+ if ( loader_errors[0] < 0 )
+ goto LABEL_13;
+ v6 = 0;
+ do
+ {
+ if ( a1 == v2 )
+ v3 = off_10235FC[v6];
+ if ( a2 == v2 )
+ v4 = off_10235FC[v6];
+ v6 = 2 * ++v5;
+ v2 = loader_errors[2 * v5];
+ }
+ while ( v2 >= 0 );
+ if ( !v3 )
+ LABEL_13:
+ v3 = off_10235FC[2 * v5];
+ MessageBoxA(0, v3, v4, 0x2000u);
+ return -1;
+}
+// 10235F8: using guessed type int loader_errors[];
+
+//----- (01008FE0) --------------------------------------------------------
+_DWORD *__stdcall loader_default_vsi(_DWORD *a1)
+{
+ _DWORD *result; // eax
+
+ result = a1;
+ a1[13] = 0;
+ a1[5] = 1369940824;
+ a1[12] = 0;
+ *a1 = 1064514355;
+ a1[1] = 1058642330;
+ a1[2] = 0;
+ a1[4] = 0;
+ a1[16] = 0;
+ a1[17] = 0;
+ a1[15] = 0;
+ a1[14] = 0;
+ return result;
+}
+
+//----- (0100901F) --------------------------------------------------------
+signed int __stdcall loader_get_sound_id(int a1)
+{
+ signed __int16 v1; // dx
+ signed int v2; // eax
+ signed int result; // eax
+ signed int v4; // edi
+ int v5; // esi
+ int v6; // eax
+ _WORD *v7; // eax
+ const CHAR *lpName; // ST18_4
+ HFILE hFile; // ST1C_4
+ int v10; // [esp+10h] [ebp+8h]
+
+ v1 = 1;
+ if ( sound_count <= 1 )
+ {
+ LABEL_5:
+ loader_error(25, 26);
+ result = -1;
+ }
+ else
+ {
+ v2 = 1;
+ while ( dword_1027C24[5 * v2] != a1 )
+ {
+ v2 = ++v1;
+ if ( v1 >= sound_count )
+ goto LABEL_5;
+ }
+ v4 = v1;
+ v5 = 5 * v1;
+ if ( !dword_1027C28[v5] && !sound_list[v5] )
+ {
+ v6 = dword_1027C24[v5];
+ *(float *)&algn_1027C2C[20 * v1] = 0.0;
+ v10 = v6;
+ if ( v6 > 0 && !dword_102556C )
+ {
+ v7 = (_WORD *)partman_field(loader_table, v6, 0);
+ if ( v7 )
+ {
+ if ( *v7 == 202 )
+ {
+ lpName = (const CHAR *)partman_field(loader_table, v10, 9);
+ hFile = _lopen(lpName, 0);
+ *(float *)(v5 * 4 + 16940076) = (double)_llseek(hFile, 0, 2) * 0.0000909090909090909;
+ _lclose(hFile);
+ sound_list[v5] = (int)Sound_LoadWaveFile(lpName);
+ }
+ }
+ }
+ }
+ ++dword_1027C28[v5];
+ result = v4;
+ }
+ return result;
+}
+// 10236D8: using guessed type int sound_count;
+// 102556C: using guessed type int dword_102556C;
+// 1027C20: using guessed type int sound_list[];
+// 1027C24: using guessed type int dword_1027C24[];
+// 1027C28: using guessed type int dword_1027C28[];
+
+//----- (0100911D) --------------------------------------------------------
+void __stdcall loader_unload()
+{
+ signed int v0; // esi
+ LPCVOID *v1; // edi
+
+ v0 = 1;
+ if ( sound_count > 1 )
+ {
+ v1 = (LPCVOID *)&unk_1027C34;
+ do
+ {
+ Sound_FreeSound(*v1);
+ ++v0;
+ v1 += 5;
+ }
+ while ( v0 < sound_count );
+ }
+ if ( dword_1027C30[5 * v0] )
+ memoryfree(dword_1027C30[5 * v0]);
+ sound_count = 1;
+}
+// 10236D8: using guessed type int sound_count;
+// 1027C30: using guessed type int dword_1027C30[];
+
+//----- (0100916A) --------------------------------------------------------
+int __stdcall loader_loadfrom(_WORD *a1)
+{
+ _WORD *v1; // edx
+ __int16 v2; // di
+ _WORD *v3; // eax
+ int result; // eax
+ int v5; // ecx
+
+ v1 = a1;
+ v2 = 0;
+ loader_table = (int)a1;
+ if ( *a1 <= 0 )
+ {
+ result = sound_count;
+ }
+ else
+ {
+ do
+ {
+ v3 = (_WORD *)partman_field((int)v1, v2, 0);
+ v1 = (_WORD *)loader_table;
+ if ( v3 && *v3 == 202 )
+ {
+ result = sound_count;
+ sound_record_table = loader_table;
+ if ( sound_count < 65 )
+ {
+ v5 = 5 * sound_count;
+ sound_list[v5] = 0;
+ ++result;
+ dword_1027C24[v5] = v2;
+ sound_count = result;
+ }
+ }
+ else
+ {
+ result = sound_count;
+ }
+ ++v2;
+ }
+ while ( v2 < *v1 );
+ }
+ loader_sound_count = result;
+ return result;
+}
+// 10236D8: using guessed type int sound_count;
+// 1027C10: using guessed type int sound_record_table;
+// 1027C20: using guessed type int sound_list[];
+// 1027C24: using guessed type int dword_1027C24[];
+// 1028134: using guessed type int loader_sound_count;
+
+//----- (010091EB) --------------------------------------------------------
+int __stdcall loader_query_handle(LPCSTR lpString)
+{
+ return partman_record_labeled(loader_table, lpString);
+}
+
+//----- (01009207) --------------------------------------------------------
+signed int __stdcall loader_query_visual_states(int a1)
+{
+ signed int result; // eax
+ _WORD *v2; // eax
+
+ if ( a1 < 0 )
+ return loader_error(0, 17);
+ v2 = (_WORD *)partman_field(loader_table, a1, 10);
+ if ( v2 && *v2 == 100 )
+ result = (signed __int16)v2[1];
+ else
+ result = 1;
+ return result;
+}
+
+//----- (01009249) --------------------------------------------------------
+signed int __stdcall loader_material(int a1, _DWORD *a2)
+{
+ int v2; // edi
+ _WORD *v4; // eax
+ float *v5; // esi
+ unsigned int v6; // ebx
+ double v7; // st7
+ _DWORD *v8; // esi
+ double v9; // st7
+ signed __int64 v10; // rax
+ int v11; // [esp+1Ch] [ebp+8h]
+ int v12; // [esp+1Ch] [ebp+8h]
+
+ v2 = a1;
+ if ( a1 < 0 )
+ return loader_error(0, 21);
+ v4 = (_WORD *)partman_field(loader_table, a1, 0);
+ if ( !v4 )
+ return loader_error(1, 21);
+ if ( *v4 == 300 )
+ {
+ v5 = (float *)partman_field(loader_table, a1, 11);
+ if ( !v5 )
+ return loader_error(11, 21);
+ v11 = 0;
+ v6 = (unsigned int)partman_field_size(loader_table, v2, 11) >> 2;
+ if ( (signed __int16)v6 <= 0 )
+ return 0;
+ while ( 1 )
+ {
+ v7 = *v5;
+ v8 = v5 + 1;
+ v12 = v11 + 1;
+ v9 = _floor(v7);
+ switch ( (signed __int16)(signed __int64)v9 )
+ {
+ case 301:
+ *a2 = *v8;
+ break;
+ case 302:
+ a2[1] = *v8;
+ break;
+ case 304:
+ v10 = (signed __int64)_floor(*(float *)v8);
+ a2[4] = loader_get_sound_id((signed __int16)v10);
+ break;
+ default:
+ return loader_error(9, 21);
+ }
+ v5 = (float *)(v8 + 1);
+ v11 = v12 + 1;
+ if ( (signed __int16)v11 >= (signed __int16)v6 )
+ return 0;
+ }
+ }
+ return loader_error(3, 21);
+}
+
+//----- (01009349) --------------------------------------------------------
+signed int __stdcall loader_kicker(int a1, _DWORD *a2)
+{
+ _WORD *v3; // eax
+ float *v4; // esi
+ double v5; // st7
+ _DWORD *v6; // esi
+ double v7; // st7
+ signed __int64 v8; // rax
+ int v9; // eax
+ _DWORD *v10; // esi
+ int v11; // eax
+ int v12; // eax
+ unsigned int v13; // [esp+14h] [ebp-4h]
+ int v14; // [esp+20h] [ebp+8h]
+ int v15; // [esp+20h] [ebp+8h]
+
+ if ( a1 < 0 )
+ return loader_error(0, 20);
+ v3 = (_WORD *)partman_field(loader_table, a1, 0);
+ if ( !v3 )
+ return loader_error(1, 20);
+ if ( *v3 != 400 )
+ return loader_error(4, 20);
+ v4 = (float *)partman_field(loader_table, a1, 11);
+ if ( !v4 )
+ return loader_error(11, 20);
+ v13 = (unsigned int)partman_field_size(loader_table, a1, 11) >> 2;
+ v14 = 0;
+ if ( (signed __int16)v13 <= 0 )
+ return 0;
+ while ( 1 )
+ {
+ v5 = *v4;
+ v6 = v4 + 1;
+ v15 = v14 + 1;
+ v7 = _floor(v5);
+ switch ( (signed __int16)(signed __int64)v7 )
+ {
+ case 401:
+ *a2 = *v6;
+ goto LABEL_24;
+ case 402:
+ a2[1] = *v6;
+ goto LABEL_24;
+ case 403:
+ a2[2] = *v6;
+ goto LABEL_24;
+ }
+ if ( (signed __int16)(signed __int64)v7 != 404 )
+ break;
+ v9 = *v6;
+ v10 = v6 + 1;
+ a2[3] = v9;
+ v11 = *v10;
+ ++v10;
+ a2[4] = v11;
+ v12 = *v10;
+ v4 = (float *)(v10 + 1);
+ v14 = v15 + 3;
+ a2[5] = v12;
+ LABEL_25:
+ if ( (signed __int16)v14 >= (signed __int16)v13 )
+ return 0;
+ }
+ if ( (signed __int16)(signed __int64)v7 == 405 )
+ {
+ a2[6] = *v6;
+ goto LABEL_24;
+ }
+ if ( (signed __int16)(signed __int64)v7 == 406 )
+ {
+ v8 = (signed __int64)_floor(*(float *)v6);
+ a2[7] = loader_get_sound_id((signed __int16)v8);
+ LABEL_24:
+ v4 = (float *)(v6 + 1);
+ v14 = v15 + 1;
+ goto LABEL_25;
+ }
+ return loader_error(10, 20);
+}
+
+//----- (01009486) --------------------------------------------------------
+signed int __stdcall loader_state_id(int a1, signed int a2)
+{
+ int v2; // esi
+ __int16 v3; // di
+ _WORD *v5; // eax
+ _WORD *v6; // eax
+
+ v2 = a1;
+ v3 = loader_query_visual_states(a1);
+ if ( v3 <= 0 )
+ return loader_error(12, 24);
+ v5 = (_WORD *)partman_field(loader_table, a1, 0);
+ if ( !v5 )
+ return loader_error(1, 24);
+ if ( *v5 != 200 )
+ return loader_error(5, 24);
+ if ( a2 > v3 )
+ return loader_error(12, 24);
+ if ( !a2 )
+ return v2;
+ v2 = a2 + a1;
+ v6 = (_WORD *)partman_field(loader_table, a2 + a1, 0);
+ if ( !v6 )
+ return loader_error(1, 24);
+ if ( *v6 == 201 )
+ return v2;
+ return loader_error(6, 24);
+}
+
+//----- (0100950A) --------------------------------------------------------
+signed int __stdcall loader_query_visual(int a1, signed int a2, _DWORD *a3)
+{
+ _DWORD *v3; // edi
+ int v5; // eax
+ int v6; // ebx
+ int v7; // eax
+ signed __int16 *v8; // esi
+ unsigned int v9; // eax
+ int v10; // ebx
+ signed int v11; // ecx
+ _BYTE *v12; // esi
+ int v13; // ebx
+ int v14; // ecx
+ int v15; // ecx
+ int v16; // ecx
+ int v17; // ecx
+ int v18; // ecx
+ int v19; // ecx
+ float *v20; // eax
+ float *v21; // esi
+ signed __int64 v22; // rax
+ int v23; // esi
+ int v24; // [esp+1Ch] [ebp+8h]
+ unsigned int v25; // [esp+24h] [ebp+10h]
+
+ v3 = a3;
+ loader_default_vsi(a3);
+ if ( a1 < 0 )
+ return loader_error(0, 18);
+ v5 = loader_state_id(a1, a2);
+ v6 = v5;
+ v24 = v5;
+ if ( v5 < 0 )
+ return loader_error(16, 18);
+ a3[16] = partman_field(loader_table, v5, 1);
+ v7 = partman_field(loader_table, v6, 12);
+ a3[17] = v7;
+ if ( v7 )
+ {
+ *(_DWORD *)(v7 + 6) = v7 + 14;
+ *(_DWORD *)(a3[17] + 10) = *(_DWORD *)(a3[17] + 6);
+ }
+ v8 = (signed __int16 *)partman_field(loader_table, v6, 10);
+ if ( v8 )
+ {
+ v9 = partman_field_size(loader_table, v6, 10);
+ v10 = 0;
+ v25 = v9 >> 1;
+ if ( (signed __int16)(v9 >> 1) > 0 )
+ {
+ while ( 1 )
+ {
+ v11 = *v8;
+ v12 = v8 + 1;
+ v13 = v10 + 1;
+ if ( v11 <= 406 )
+ {
+ if ( v11 == 406 )
+ {
+ v3[12] = loader_get_sound_id(*(signed __int16 *)v12);
+ }
+ else
+ {
+ v14 = v11 - 100;
+ if ( v14 )
+ {
+ v15 = v14 - 200;
+ if ( v15 )
+ {
+ v16 = v15 - 4;
+ if ( v16 )
+ {
+ if ( v16 != 96 )
+ return loader_error(9, 18);
+ if ( loader_kicker(*(signed __int16 *)v12, v3 + 5) )
+ return loader_error(14, 18);
+ }
+ else
+ {
+ v3[4] = loader_get_sound_id(*(signed __int16 *)v12);
+ }
+ }
+ else if ( loader_material(*(signed __int16 *)v12, v3) )
+ {
+ return loader_error(15, 18);
+ }
+ }
+ else if ( a2 )
+ {
+ return loader_error(7, 18);
+ }
+ }
+ goto LABEL_32;
+ }
+ v17 = v11 - 602;
+ if ( !v17 )
+ {
+ v3[13] |= 1 << *v12;
+ goto LABEL_32;
+ }
+ v18 = v17 - 498;
+ if ( !v18 )
+ break;
+ v19 = v18 - 1;
+ if ( !v19 )
+ {
+ v3[15] = loader_get_sound_id(*(signed __int16 *)v12);
+ LABEL_32:
+ v8 = (signed __int16 *)(v12 + 2);
+ v10 = v13 + 1;
+ goto LABEL_33;
+ }
+ if ( v19 != 399 )
+ return loader_error(9, 18);
+ v8 = (signed __int16 *)(v12 + 16);
+ v10 = v13 + 8;
+ LABEL_33:
+ if ( (signed __int16)v10 >= (signed __int16)v25 )
+ goto LABEL_34;
+ }
+ v3[14] = loader_get_sound_id(*(signed __int16 *)v12);
+ goto LABEL_32;
+ }
+ }
+ LABEL_34:
+ if ( !v3[13] )
+ v3[13] = 1;
+ v20 = (float *)partman_field(loader_table, v24, 11);
+ if ( !v20 )
+ return 0;
+ v21 = v20 + 1;
+ if ( *v20 != 600.0 )
+ return 0;
+ v3[2] = (signed __int16)((unsigned int)partman_field_size(loader_table, v24, 11) >> 2) / 2 - 2;
+ v22 = (signed __int64)(_floor(*v21) - 1.0);
+ v23 = (int)(v21 + 1);
+ if ( !(_WORD)v22 )
+ {
+ v3[2] = 1;
+ LABEL_40:
+ v3[3] = v23;
+ return 0;
+ }
+ if ( (_WORD)v22 == 1 )
+ {
+ v3[2] = 2;
+ goto LABEL_40;
+ }
+ if ( (signed __int16)v22 == v3[2] )
+ goto LABEL_40;
+ return loader_error(8, 18);
+}
+
+//----- (0100975D) --------------------------------------------------------
+int __stdcall loader_query_name(int a1)
+{
+ if ( a1 >= 0 )
+ return partman_field(loader_table, a1, 3);
+ loader_error(0, 19);
+ return 0;
+}
+
+//----- (0100978E) --------------------------------------------------------
+int __stdcall loader_query_float_attribute(int a1, signed int a2, int a3)
+{
+ __int16 v3; // bx
+ int result; // eax
+ int v5; // edi
+ float *v6; // eax
+ float *v7; // esi
+
+ v3 = 0;
+ if ( a1 >= 0 )
+ {
+ v5 = loader_state_id(a1, a2);
+ if ( v5 >= 0 )
+ {
+ while ( 1 )
+ {
+ v6 = (float *)partman_field_nth(loader_table, v5, 11, v3);
+ v7 = v6;
+ if ( !v6 )
+ break;
+ if ( (signed __int16)(signed __int64)_floor(*v6) == a3 )
+ return (int)(v7 + 1);
+ ++v3;
+ }
+ loader_error(13, 22);
+ result = 0;
+ }
+ else
+ {
+ loader_error(16, 22);
+ result = 0;
+ }
+ }
+ else
+ {
+ loader_error(0, 22);
+ result = 0;
+ }
+ return result;
+}
+
+//----- (0100981A) --------------------------------------------------------
+int __stdcall loader_query_iattribute(int a1, int a2, _DWORD *a3)
+{
+ __int16 v3; // di
+ int result; // eax
+ signed __int16 *v5; // eax
+ signed __int16 *v6; // esi
+
+ v3 = 0;
+ if ( a1 >= 0 )
+ {
+ while ( 1 )
+ {
+ v5 = (signed __int16 *)partman_field_nth(loader_table, a1, 10, v3);
+ v6 = v5;
+ if ( !v5 )
+ break;
+ if ( *v5 == a2 )
+ {
+ *a3 = partman_field_size(loader_table, a1, 10) / 2 - 1;
+ return (int)(v6 + 1);
+ }
+ ++v3;
+ }
+ loader_error(2, 23);
+ *a3 = 0;
+ result = 0;
+ }
+ else
+ {
+ loader_error(0, 22);
+ result = 0;
+ }
+ return result;
+}
+
+//----- (01009895) --------------------------------------------------------
+double __stdcall loader_play_sound(int a1)
+{
+ if ( a1 <= 0 )
+ return 0.0;
+ Sound_PlaySound(sound_list[5 * a1], 0, 7, 5u, 0);
+ return *(float *)&algn_1027C2C[20 * a1];
+}
+// 1027C20: using guessed type int sound_list[];
diff --git a/partman/partman.cpp b/partman/partman.cpp
new file mode 100644
index 0000000..997b606
--- /dev/null
+++ b/partman/partman.cpp
@@ -0,0 +1,388 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "../pinball.h"
+
+//----- (01006270) --------------------------------------------------------
+int __stdcall partman_field(int a1, int a2, int a3)
+{
+ signed __int16 *v3; // eax
+ int v4; // edx
+ int v5; // esi
+ signed __int16 *v6; // eax
+ int v7; // ecx
+
+ v3 = *(signed __int16 **)(*(_DWORD *)(a1 + 6) + 4 * a2);
+ v4 = *v3;
+ v5 = 0;
+ if ( v4 <= 0 )
+ return 0;
+ v6 = v3 + 1;
+ while ( 1 )
+ {
+ v7 = *v6;
+ if ( v7 == a3 )
+ break;
+ if ( v7 <= a3 )
+ {
+ ++v5;
+ v6 += 5;
+ if ( v5 < v4 )
+ continue;
+ }
+ return 0;
+ }
+ return *(_DWORD *)(v6 + 3);
+}
+
+//----- (010062B1) --------------------------------------------------------
+int __stdcall partman_field_size_nth(int a1, int a2, int a3, int a4)
+{
+ signed __int16 *v4; // eax
+ int v5; // edx
+ int v6; // esi
+ int v7; // edi
+ signed __int16 *v8; // eax
+ int v9; // ecx
+
+ v4 = *(signed __int16 **)(*(_DWORD *)(a1 + 6) + 4 * a2);
+ v5 = *v4;
+ v6 = 0;
+ v7 = 0;
+ if ( v5 <= 0 )
+ return 0;
+ v8 = v4 + 1;
+ while ( 1 )
+ {
+ v9 = *v8;
+ if ( v9 != a3 )
+ {
+ if ( v9 > a3 )
+ return 0;
+ goto LABEL_7;
+ }
+ if ( v7 == a4 )
+ return *(_DWORD *)(v8 + 1);
+ ++v7;
+ LABEL_7:
+ ++v6;
+ v8 += 5;
+ if ( v6 >= v5 )
+ return 0;
+ }
+}
+
+//----- (010062FE) --------------------------------------------------------
+int __stdcall partman_field_size(int a1, int a2, int a3)
+{
+ return partman_field_size_nth(a1, a2, a3, 0);
+}
+
+//----- (0100631C) --------------------------------------------------------
+int __stdcall partman_field_nth(int a1, int a2, int a3, int a4)
+{
+ signed __int16 *v4; // eax
+ int v5; // edx
+ int v6; // esi
+ int v7; // edi
+ signed __int16 *v8; // eax
+ int v9; // ecx
+
+ v4 = *(signed __int16 **)(*(_DWORD *)(a1 + 6) + 4 * a2);
+ v5 = *v4;
+ v6 = 0;
+ v7 = 0;
+ if ( v5 <= 0 )
+ return 0;
+ v8 = v4 + 1;
+ while ( 1 )
+ {
+ v9 = *v8;
+ if ( v9 != a3 )
+ {
+ if ( v9 > a3 )
+ return 0;
+ goto LABEL_7;
+ }
+ if ( a4 == v7 )
+ return *(_DWORD *)(v8 + 3);
+ ++v7;
+ LABEL_7:
+ ++v6;
+ v8 += 5;
+ if ( v6 >= v5 )
+ return 0;
+ }
+}
+
+//----- (01006369) --------------------------------------------------------
+int __stdcall partman_record_labeled(int a1, LPCSTR lpString)
+{
+ int v2; // esi
+ int v3; // eax
+ int v4; // ecx
+ bool v5; // zf
+ LPCSTR v6; // edx
+ int v8; // [esp+Ch] [ebp-4h]
+
+ v8 = lstrlenA(lpString);
+ v2 = *(signed __int16 *)a1;
+ while ( 1 )
+ {
+ if ( --v2 < 0 )
+ return -1;
+ v3 = partman_field(a1, v2, 3);
+ v4 = 0;
+ if ( v3 )
+ {
+ v5 = v8 == 0;
+ if ( v8 > 0 )
+ {
+ v6 = lpString;
+ do
+ {
+ if ( *v6 != v6[v3 - (_DWORD)lpString] )
+ break;
+ ++v4;
+ ++v6;
+ }
+ while ( v4 < v8 );
+ v5 = v4 == v8;
+ }
+ if ( v5 && !lpString[v4] && !*(_BYTE *)(v4 + v3) )
+ break;
+ }
+ }
+ return v2;
+}
+
+//----- (010063DB) --------------------------------------------------------
+int __stdcall partman_field_labeled(int a1, LPCSTR lpString, int a3)
+{
+ int v3; // eax
+ int result; // eax
+
+ v3 = partman_record_labeled(a1, lpString);
+ if ( v3 < 0 )
+ result = 0;
+ else
+ result = partman_field(a1, v3, a3);
+ return result;
+}
+
+//----- (01006408) --------------------------------------------------------
+void __stdcall partman_unload_records(_WORD *a1)
+{
+ signed __int16 *i; // edi
+ _WORD *v2; // esi
+ int *v3; // ebx
+ signed int v4; // [esp+4h] [ebp-4h]
+ signed int v5; // [esp+10h] [ebp+8h]
+
+ v4 = 0;
+ for ( i = a1; v4 < *i; ++v4 )
+ {
+ v2 = *(_WORD **)(*(_DWORD *)(i + 3) + 4 * v4);
+ if ( v2 )
+ {
+ v5 = 0;
+ if ( *v2 > 0 )
+ {
+ v3 = (int *)(v2 + 4);
+ do
+ {
+ if ( *v3 )
+ {
+ if ( *((_WORD *)v3 - 3) == 1 )
+ gdrv_destroy_bitmap(*v3);
+ memoryfree(*v3);
+ }
+ ++v5;
+ v3 = (int *)((char *)v3 + 10);
+ }
+ while ( v5 < (signed __int16)*v2 );
+ }
+ memoryfree((int)v2);
+ }
+ }
+ if ( *(_DWORD *)(i + 1) )
+ memoryfree(*(_DWORD *)(i + 1));
+ memoryfree(*(_DWORD *)(i + 3));
+ memoryfree((int)i);
+}
+
+//----- (010064E2) --------------------------------------------------------
+signed __int16 *__stdcall partman_load_records(LPCSTR lpFileName)
+{
+ HFILE v1; // ebx
+ signed __int16 *v3; // edi
+ int v4; // eax
+ CHAR *v5; // eax
+ UINT v6; // esi
+ void *v7; // eax
+ int v8; // ebx
+ int v9; // eax
+ char v10; // al
+ char v11; // bl
+ int v12; // eax
+ int v13; // esi
+ _WORD *v14; // eax
+ int v15; // esi
+ int v16; // eax
+ int v17; // ebx
+ int v18; // eax
+ int v19; // eax
+ void *v20; // eax
+ signed __int16 v21; // ax
+ int v22; // [esp+4h] [ebp-168h]
+ int v23; // [esp+8h] [ebp-164h]
+ char v24; // [esp+Ch] [ebp-160h]
+ __int16 v25; // [esp+Dh] [ebp-15Fh]
+ __int16 v26; // [esp+Fh] [ebp-15Dh]
+ __int16 v27; // [esp+11h] [ebp-15Bh]
+ __int16 v28; // [esp+13h] [ebp-159h]
+ int lBytes; // [esp+15h] [ebp-157h]
+ char v30; // [esp+19h] [ebp-153h]
+ int v31; // [esp+1Ch] [ebp-150h]
+ int v32; // [esp+20h] [ebp-14Ch]
+ HFILE hFile; // [esp+24h] [ebp-148h]
+ struct _OFSTRUCT ReOpenBuff; // [esp+28h] [ebp-144h]
+ char Buffer; // [esp+B0h] [ebp-BCh]
+ CHAR String; // [esp+F7h] [ebp-75h]
+ unsigned __int16 v37; // [esp+15Fh] [ebp-Dh]
+ unsigned __int16 v38; // [esp+165h] [ebp-7h]
+
+ v1 = OpenFile(lpFileName, &ReOpenBuff, 0);
+ hFile = v1;
+ if ( v1 == -1 )
+ return 0;
+ _lread(v1, &Buffer, 0xB7u);
+ if ( lstrcmpA("PARTOUT(4.0)RESOURCE", &Buffer) )
+ {
+ _lclose(v1);
+ return 0;
+ }
+ v3 = (signed __int16 *)memoryallocate(0xAu);
+ if ( !v3 )
+ {
+ _lclose(v1);
+ return 0;
+ }
+ if ( lstrlenA(&String) <= 0 )
+ {
+ *(_DWORD *)(v3 + 1) = 0;
+ }
+ else
+ {
+ v4 = lstrlenA(&String);
+ v5 = (CHAR *)memoryallocate(v4 + 1);
+ *(_DWORD *)(v3 + 1) = v5;
+ if ( !v5 )
+ {
+ _lclose(v1);
+ LABEL_10:
+ memoryfree((int)v3);
+ return 0;
+ }
+ lstrcpyA(v5, &String);
+ }
+ v6 = v38;
+ if ( v38 )
+ {
+ v7 = (void *)memoryallocate(v38);
+ v8 = (int)v7;
+ if ( !v7 )
+ {
+ _lclose(hFile);
+ goto LABEL_19;
+ }
+ _lread(hFile, v7, v6);
+ memoryfree(v8);
+ }
+ v9 = memoryallocate(4 * v37);
+ *(_DWORD *)(v3 + 3) = v9;
+ if ( !v9 )
+ {
+ LABEL_19:
+ if ( *(_DWORD *)(v3 + 1) )
+ memoryfree(*(_DWORD *)(v3 + 1));
+ goto LABEL_10;
+ }
+ v32 = 0;
+ if ( v37 )
+ {
+ do
+ {
+ v10 = _lread_char(hFile);
+ v11 = v10;
+ if ( v10 <= 0 )
+ v12 = 0;
+ else
+ v12 = v10 - 1;
+ v13 = 4 * v32;
+ *(_DWORD *)(v13 + *(_DWORD *)(v3 + 3)) = memoryallocate(10 * v12 + 12);
+ v14 = *(_WORD **)(v13 + *(_DWORD *)(v3 + 3));
+ if ( !v14 )
+ break;
+ v31 = 0;
+ *v14 = v11;
+ v22 = v11;
+ if ( v11 > 0 )
+ {
+ v15 = (int)(v14 + 4);
+ do
+ {
+ LOBYTE(v16) = _lread_char(hFile);
+ *(_WORD *)(v15 - 6) = (unsigned __int8)v16;
+ v16 = (unsigned __int8)v16;
+ v17 = field_size[(unsigned __int8)v16];
+ v23 = (unsigned __int8)v16;
+ if ( v17 < 0 )
+ {
+ v17 = _lread_long(hFile);
+ v16 = v23;
+ }
+ if ( v16 == 1 )
+ {
+ _hread(hFile, &v24, 14);
+ v18 = memoryallocate(0x25u);
+ *(_DWORD *)v15 = v18;
+ if ( !v18 )
+ goto LABEL_41;
+ v19 = v30 & 2 ? gdrv_create_bitmap(v18, v25, v26) : gdrv_create_raw_bitmap(v18, v25, v26, v30 & 1);
+ if ( v19 )
+ goto LABEL_41;
+ _hread(hFile, *(LPVOID *)(*(_DWORD *)v15 + 8), lBytes);
+ *(_DWORD *)(*(_DWORD *)v15 + 29) = v27;
+ *(_DWORD *)(*(_DWORD *)v15 + 33) = v28;
+ }
+ else
+ {
+ v20 = (void *)memoryallocate(v17);
+ *(_DWORD *)v15 = v20;
+ if ( !v20 )
+ goto LABEL_41;
+ _hread(hFile, v20, v17);
+ }
+ v21 = v32 + 1;
+ ++v31;
+ *(_DWORD *)(v15 - 4) = v17;
+ *v3 = v21;
+ v15 += 10;
+ }
+ while ( v31 < v22 );
+ }
+ ++v32;
+ }
+ while ( v32 < v37 );
+ }
+ LABEL_41:
+ _lclose(hFile);
+ if ( *v3 != v37 )
+ {
+ partman_unload_records(v3);
+ return 0;
+ }
+ return v3;
+}
diff --git a/pinball.cpp b/pinball.cpp
new file mode 100644
index 0000000..9089789
--- /dev/null
+++ b/pinball.cpp
@@ -0,0 +1,1020 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include
+#include
+#include
+#include "pinball.h"
+
+//----- (0101461A) --------------------------------------------------------
+signed int __stdcall pb_mode_change(int a1)
+{
+int v1; // eax
+int v2; // eax
+
+switch ( a1 )
+{
+case 1:
+if ( dword_1025570 )
+{
+options_menu_set(0x191u, 0);
+options_menu_set(0x67u, 0);
+options_menu_check(0x194u, 1);
+if ( MainTable )
+{
+v2 = *(_DWORD *)((char *)MainTable + 230);
+if ( v2 )
+*(_BYTE *)(v2 + 5) = 1;
+}
+}
+else
+{
+options_menu_set(0x67u, 1);
+options_menu_set(0x191u, 1);
+options_menu_check(0x194u, 0);
+if ( MainTable )
+{
+v1 = *(_DWORD *)((char *)MainTable + 230);
+if ( v1 )
+*(_BYTE *)(v1 + 5) = 0;
+}
+}
+break;
+case 2:
+options_menu_set(0x191u, 0);
+if ( !dword_1025570 )
+{
+options_menu_set(0x67u, 1);
+options_menu_check(0x194u, 0);
+}
+if ( MainTable && *(_DWORD *)((char *)MainTable + 266) )
+(***(void (__thiscall ****)(_DWORD, signed int, _DWORD))((char *)MainTable + 266))(
+*(_DWORD *)((char *)MainTable + 266),
+29,
+1.4);
+break;
+case 3:
+case 4:
+options_menu_set(0x191u, 0);
+options_menu_set(0x67u, 0);
+dword_1025574 = 5000;
+break;
+}
+dword_1025568 = a1;
+return 1;
+}
+// 1025568: using guessed type int dword_1025568;
+// 1025570: using guessed type int dword_1025570;
+// 1025574: using guessed type int dword_1025574;
+
+//----- (01014743) --------------------------------------------------------
+signed int __stdcall pb_mode_countdown(int a1)
+{
+if ( !dword_1025568 || dword_1025568 <= 0 )
+return 1;
+if ( dword_1025568 > 2 )
+{
+if ( dword_1025568 == 3 )
+{
+dword_1025574 -= a1;
+if ( dword_1025574 < 0 || a1 < 0 )
+pb_mode_change(4);
+}
+else if ( dword_1025568 == 4 )
+{
+dword_1025574 -= a1;
+if ( dword_1025574 < 0 || a1 < 0 )
+pb_mode_change(1);
+}
+return 1;
+}
+return 0;
+}
+// 1025568: using guessed type int dword_1025568;
+// 1025574: using guessed type int dword_1025574;
+
+//----- (0101479B) --------------------------------------------------------
+int __stdcall pb_end_game()
+{
+struct TPinballTable *v0; // edx
+int v1; // esi
+int v2; // eax
+int **v3; // ecx
+int v4; // eax
+int *v5; // esi
+int v6; // eax
+int *v7; // ecx
+int v8; // edi
+int *v9; // ecx
+int *v10; // eax
+int v11; // edx
+int result; // eax
+int v13; // edi
+int v14; // ebx
+CHAR *v15; // eax
+int v16[4]; // [esp+Ch] [ebp-F8h]
+int v17[4]; // [esp+1Ch] [ebp-E8h]
+int v18; // [esp+2Ch] [ebp-D8h]
+int v19; // [esp+30h] [ebp-D4h]
+int i; // [esp+34h] [ebp-D0h]
+CHAR String1; // [esp+38h] [ebp-CCh]
+
+pb_mode_change(2);
+v0 = MainTable;
+v2 = 0;
+v18 = *(_DWORD *)((char *)MainTable + 214);
+v1 = v18;
+if ( v18 > 0 )
+{
+v3 = (int **)((char *)MainTable + 102);
+do
+{
+v16[v2] = **v3;
+v17[v2] = v2;
+++v2;
+v3 += 7;
+}
+while ( v2 < v1 );
+}
+v4 = 0;
+for ( i = 0; i < v1; ++i )
+{
+v19 = v4;
+if ( v4 < v1 )
+{
+v5 = &v16[v4];
+do
+{
+v6 = v19;
+v7 = &v16[v19];
+v8 = *v7;
+if ( *v7 > (unsigned int)*v5 )
+{
+*v7 = *v5;
+v9 = &v17[i];
+v10 = &v17[v6];
+v11 = *v10;
+*v5 = v8;
+*v10 = *v9;
+*v9 = v11;
+v0 = MainTable;
+}
+++v19;
+}
+while ( v19 < v18 );
+v1 = v18;
+}
+v4 = i + 1;
+}
+result = 0;
+if ( !dword_1025570 && !*(_DWORD *)((char *)v0 + 62) )
+{
+i = 0;
+if ( v1 > 0 )
+{
+do
+{
+v13 = v16[i];
+v14 = high_score_get_score_position((int)byte_1025578, v16[i]);
+if ( v14 >= 0 )
+{
+v15 = get_rc_string(LOWORD(v17[i]) + 26, 0);
+lstrcpyA(&String1, v15);
+show_and_set_high_score_dialog(byte_1025578, v13, v14, &String1);
+}
+result = ++i;
+}
+while ( i < v18 );
+}
+}
+return result;
+}
+// 1025570: using guessed type int dword_1025570;
+// 101479B: using guessed type int var_F8[4];
+// 101479B: using guessed type int var_E8[4];
+
+//----- (01014908) --------------------------------------------------------
+signed int __stdcall pb_chk_highscore()
+{
+int v0; // esi
+int v1; // edi
+
+if ( dword_1025570 )
+return 0;
+v0 = *(_DWORD *)((char *)MainTable + 214) - 1;
+if ( v0 < 0 )
+return 0;
+v1 = 28 * v0;
+while ( high_score_get_score_position((int)byte_1025578, **(_DWORD **)((char *)MainTable + v1 + 102)) < 0 )
+{
+--v0;
+v1 -= 28;
+if ( v0 < 0 )
+return 0;
+}
+return 1;
+}
+// 1025570: using guessed type int dword_1025570;
+
+//----- (01014956) --------------------------------------------------------
+long double __stdcall pb_collide(struct TEdgeSegment *a1, float a2, struct TBall *a3)
+{
+struct TBall *v3; // ebx
+double v4; // st7
+float v5; // eax
+double v6; // st6
+double v7; // st5
+int v8; // eax
+double v9; // st7
+double v11; // st7
+struct vector_type *v12; // ST0C_4
+int v13; // [esp+8h] [ebp-40h]
+int v14; // [esp+Ch] [ebp-3Ch]
+int v15; // [esp+10h] [ebp-38h]
+int v16; // [esp+14h] [ebp-34h]
+int v17; // [esp+18h] [ebp-30h]
+int v18; // [esp+1Ch] [ebp-2Ch]
+float v19; // [esp+20h] [ebp-28h]
+int v20; // [esp+24h] [ebp-24h]
+float v21; // [esp+28h] [ebp-20h]
+float v22; // [esp+2Ch] [ebp-1Ch]
+int v23; // [esp+30h] [ebp-18h]
+float v24; // [esp+34h] [ebp-14h]
+float v25; // [esp+38h] [ebp-10h]
+float v26; // [esp+3Ch] [ebp-Ch]
+struct vector_type *v27; // [esp+40h] [ebp-8h]
+float v28; // [esp+44h] [ebp-4h]
+
+v3 = a3;
+if ( *((_BYTE *)a3 + 5) && !*(_DWORD *)((char *)a3 + 106) )
+{
+if ( ball_speed_limit < (double)*(float *)((char *)a3 + 66) )
+*(float *)((char *)a3 + 66) = ball_speed_limit;
+v4 = a2;
+v5 = *(float *)((char *)v3 + 66);
+*(float *)((char *)v3 + 74) = a2;
+v6 = v4 * *(float *)((char *)v3 + 66);
+v27 = (struct TBall *)((char *)v3 + 42);
+v13 = *(_DWORD *)((char *)v3 + 42);
+*(float *)((char *)v3 + 70) = v6;
+v7 = *(float *)&a1;
+v14 = *(_DWORD *)((char *)v3 + 46);
+*(float *)((char *)v3 + 78) = *(float *)&a1;
+v15 = *(_DWORD *)((char *)v3 + 50);
+v16 = *(_DWORD *)((char *)v3 + 54);
+v17 = *(_DWORD *)((char *)v3 + 58);
+v28 = v5;
+v8 = *(_DWORD *)((char *)v3 + 110);
+v18 = *(_DWORD *)((char *)v3 + 62);
+v19 = v6;
+v23 = v8;
+v21 = v7;
+v22 = v4;
+v20 = 990057071;
+v9 = TEdgeManager::FindCollisionDistance(edge_manager, (struct ray_type *)&v13, v3, &a1);
+*(_DWORD *)((char *)v3 + 134) = 0;
+*(float *)&a3 = v9;
+if ( *(float *)&a3 >= 1000000000.0 )
+{
+v11 = a2 * *(float *)((char *)v3 + 66);
+v12 = v27;
+*(float *)((char *)v3 + 70) = v11;
+v24 = v11 * *(float *)((char *)v3 + 54);
+v25 = v11 * *(float *)((char *)v3 + 58);
+v26 = 0.0;
+vector_add(v12, (struct vector_type *)&v24);
+}
+else
+{
+(**(void (__stdcall ***)(struct TBall *, struct TBall *))a1)(v3, a3);
+if ( v28 > 0.000000001 )
+return fabs(*(float *)&a3 / v28);
+}
+}
+return a2;
+}
+// 10253D0: using guessed type float ball_speed_limit;
+
+//----- (01014A68) --------------------------------------------------------
+void __stdcall pb_timed_frame(float a1, float a2, int a3)
+{
+int v3; // eax
+int v4; // edi
+int v5; // ebx
+int v6; // esi
+bool v7; // zf
+int v8; // ecx
+double v9; // st7
+double v10; // st7
+double v11; // st7
+long double v12; // st7
+int v13; // esi
+char v14; // [esp+18h] [ebp-2Ch]
+float v15; // [esp+24h] [ebp-20h]
+float v16; // [esp+28h] [ebp-1Ch]
+float v17; // [esp+2Ch] [ebp-18h]
+int v18; // [esp+30h] [ebp-14h]
+int v19; // [esp+34h] [ebp-10h]
+int v20; // [esp+38h] [ebp-Ch]
+float v21; // [esp+3Ch] [ebp-8h]
+float v22; // [esp+40h] [ebp-4h]
+
+v3 = *(_DWORD *)((char *)MainTable + 262);
+v18 = *(_DWORD *)(v3 + 4);
+v4 = v18;
+v5 = v3 + 8;
+if ( v18 > 0 )
+{
+v19 = v18;
+do
+{
+v6 = *(_DWORD *)v5;
+v7 = *(_BYTE *)(*(_DWORD *)v5 + 5) == 0;
+v22 = a2;
+if ( !v7 )
+{
+v8 = *(_DWORD *)(v6 + 106);
+if ( v8 )
+{
+*(float *)(v6 + 74) = a2;
+(*(void (__stdcall **)(int, char *))(*(_DWORD *)v8 + 24))(v6, &v14);
+}
+else
+{
+if ( *((_BYTE *)MainTable + 5) )
+{
+v15 = 0.0;
+v16 = 0.0;
+v17 = 0.0;
+TEdgeManager::FieldEffects(edge_manager, (struct TBall *)v6, (struct vector_type *)&v15);
+v15 = v15 * a2;
+v16 = v16 * a2;
+*(float *)(v6 + 54) = *(float *)(v6 + 66) * *(float *)(v6 + 54);
+*(float *)(v6 + 58) = *(float *)(v6 + 66) * *(float *)(v6 + 58);
+vector_add((struct vector_type *)(v6 + 54), (struct vector_type *)&v15);
+*(float *)(v6 + 66) = normalize_2d((float *)(v6 + 54));
+if ( 0.0 == *(float *)(v6 + 54) )
+v9 = 1000000000.0;
+else
+v9 = 1.0 / *(float *)(v6 + 54);
+*(float *)(v6 + 82) = v9;
+if ( 0.0 == *(float *)(v6 + 58) )
+v10 = 1000000000.0;
+else
+v10 = 1.0 / *(float *)(v6 + 58);
+v4 = v18;
+*(float *)(v6 + 86) = v10;
+}
+v11 = a2;
+v21 = a1;
+v20 = 10;
+while ( v11 > 0.000001 && v20 )
+{
+v12 = pb_collide((struct TEdgeSegment *)LODWORD(v21), v22, (struct TBall *)v6);
+--v20;
+v22 = v22 - v12;
+v21 = v12 + v21;
+v11 = v22;
+}
+}
+}
+v5 += 4;
+--v19;
+}
+while ( v19 );
+}
+if ( a3 )
+{
+v13 = *(_DWORD *)((char *)MainTable + 262) + 8;
+if ( v4 > 0 )
+{
+do
+{
+if ( *(_BYTE *)(*(_DWORD *)v13 + 5) )
+(*(void (**)(void))(**(_DWORD **)v13 + 20))();
+v13 += 4;
+--v4;
+}
+while ( v4 );
+}
+}
+}
+
+//----- (01014BF9) --------------------------------------------------------
+signed int __userpurge pb_frame@(int a1@, int a2)
+{
+double v2; // st7
+char *v3; // eax
+float v5; // [esp+10h] [ebp-4h]
+
+if ( a2 > 100 )
+a2 = 100;
+v5 = (double)a2 * 0.001;
+if ( !pb_mode_countdown(a2) )
+{
+time_next = time_now + v5;
+pb_timed_frame(time_now, v5, 1);
+time_now = time_next;
+time_ticks += a2;
+if ( nudged_left || nudged_right || nudged_up )
+{
+nudge_count = v5 * 4.0 + nudge_count;
+}
+else
+{
+v2 = nudge_count - v5;
+if ( v2 <= 0.0 )
+v2 = 0.0;
+nudge_count = v2;
+}
+timer_check();
+render_update();
+score_update(a1, *(int **)((char *)MainTable + 50));
+if ( !*(_DWORD *)((char *)MainTable + 370) )
+{
+if ( nudge_count > 0.5 )
+{
+v3 = get_rc_string(25, 0);
+TTextBox::Display(InfoTextBox, a1, v3, 2.0);
+}
+if ( nudge_count > 1.0 )
+TPinballTable::tilt(MainTable, a1, time_now);
+}
+}
+return 1;
+}
+// 1024F84: using guessed type int time_ticks;
+// 1025630: using guessed type float time_now;
+// 1025634: using guessed type float time_next;
+// 102563C: using guessed type int nudged_left;
+// 1025640: using guessed type int nudged_right;
+// 1025644: using guessed type int nudged_up;
+// 102564C: using guessed type float nudge_count;
+
+//----- (01014D3D) --------------------------------------------------------
+void __stdcall pb_firsttime_setup()
+{
+render_blit = 0;
+render_update();
+render_blit = 1;
+}
+// 1024754: using guessed type int render_blit;
+
+//----- (01014D59) --------------------------------------------------------
+struct TPinballTable *__usercall pb_tilt_no_more@(int a1@)
+{
+struct TPinballTable *result; // eax
+
+if ( *(_DWORD *)((char *)MainTable + 370) )
+TTextBox::Clear(InfoTextBox, a1);
+result = MainTable;
+*(_DWORD *)((char *)MainTable + 370) = 0;
+nudge_count = -2.0;
+return result;
+}
+// 102564C: using guessed type float nudge_count;
+
+//----- (01014D8E) --------------------------------------------------------
+void __stdcall pb_ballset(signed int a1, signed int a2)
+{
+int v2; // esi
+
+v2 = *(_DWORD *)(*(_DWORD *)((char *)MainTable + 262) + 8);
+*(float *)(v2 + 54) = (double)a1 * 30.0;
+*(float *)(v2 + 58) = (double)a2 * 30.0;
+*(float *)(v2 + 66) = normalize_2d((float *)(v2 + 54));
+}
+
+//----- (01014DCF) --------------------------------------------------------
+void __stdcall nudge(float a1, float a2)
+{
+struct TPinballTable *v2; // eax
+int v3; // ecx
+int v4; // edx
+int v5; // ebx
+int v6; // esi
+double v7; // st7
+double v8; // st7
+int v9; // ST18_4
+int v10; // ST14_4
+int v11; // ST08_4
+double v12; // st7
+float v13; // [esp+20h] [ebp-10h]
+float v14; // [esp+24h] [ebp-Ch]
+int v15; // [esp+2Ch] [ebp-4h]
+
+v2 = MainTable;
+v3 = *(_DWORD *)((char *)MainTable + 262);
+v4 = *(_DWORD *)(v3 + 4);
+v13 = a1 * 0.5;
+v5 = v3 + 8;
+v14 = a2 * 0.5;
+if ( v4 > 0 )
+{
+v15 = v4;
+do
+{
+v6 = *(_DWORD *)v5;
+if ( *(_BYTE *)(*(_DWORD *)v5 + 5) && !*(_DWORD *)(v6 + 106) )
+{
+*(float *)(v6 + 54) = *(float *)(v6 + 54) * *(float *)(v6 + 66);
+*(float *)(v6 + 58) = *(float *)(v6 + 58) * *(float *)(v6 + 66);
+vector_add((struct vector_type *)(v6 + 54), (struct vector_type *)&v13);
+*(float *)(v6 + 66) = normalize_2d((float *)(v6 + 54));
+if ( 0.0 == *(float *)(v6 + 54) )
+v7 = 1000000000.0;
+else
+v7 = 1.0 / *(float *)(v6 + 54);
+*(float *)(v6 + 82) = v7;
+if ( 0.0 == *(float *)(v6 + 58) )
+v8 = 1000000000.0;
+else
+v8 = 1.0 / *(float *)(v6 + 58);
+*(float *)(v6 + 86) = v8;
+v2 = MainTable;
+}
+v5 += 4;
+--v15;
+}
+while ( v15 );
+}
+v9 = *(_DWORD *)((char *)v2 + 246);
+v10 = *(_DWORD *)((char *)v2 + 242);
+v11 = (signed __int64)_floor(0.5 - a2);
+v12 = _floor(a1 + 0.5);
+render_shift((signed __int64)v12, v11, 0, 0, v10, v9);
+}
+
+//----- (01014EEE) --------------------------------------------------------
+void __stdcall un_nudge_left(int a1, void *a2)
+{
+if ( nudged_left )
+nudge(2.0, -1.0);
+nudged_left = 0;
+}
+// 102563C: using guessed type int nudged_left;
+
+//----- (01014F20) --------------------------------------------------------
+void __stdcall un_nudge_right(int a1, void *a2)
+{
+if ( nudged_right )
+nudge(-2.0, -1.0);
+nudged_right = 0;
+}
+// 1025640: using guessed type int nudged_right;
+
+//----- (01014F52) --------------------------------------------------------
+void __stdcall nudge_left()
+{
+nudge(-2.0, 1.0);
+if ( nudge_timer )
+timer_kill(nudge_timer);
+nudge_timer = timer_set(0.40000001, 0, (int)un_nudge_left);
+nudged_left = 1;
+}
+// 102563C: using guessed type int nudged_left;
+// 1025648: using guessed type int nudge_timer;
+
+//----- (01014FA4) --------------------------------------------------------
+void __stdcall nudge_right()
+{
+nudge(2.0, 1.0);
+if ( nudge_timer )
+timer_kill(nudge_timer);
+nudge_timer = timer_set(0.40000001, 0, (int)un_nudge_right);
+nudged_right = 1;
+}
+// 1025640: using guessed type int nudged_right;
+// 1025648: using guessed type int nudge_timer;
+
+//----- (01014FF6) --------------------------------------------------------
+void __stdcall un_nudge_up(int a1, void *a2)
+{
+if ( nudged_up )
+nudge(0.0, -1.0);
+nudged_up = 0;
+}
+// 1025644: using guessed type int nudged_up;
+
+//----- (01015024) --------------------------------------------------------
+void __stdcall nudge_up()
+{
+nudge(0.0, 1.0);
+if ( nudge_timer )
+timer_kill(nudge_timer);
+nudge_timer = timer_set(0.40000001, 0, (int)un_nudge_up);
+nudged_up = 1;
+}
+// 1025644: using guessed type int nudged_up;
+// 1025648: using guessed type int nudge_timer;
+
+//----- (01015072) --------------------------------------------------------
+void __stdcall pb_keydown(HKEY a1)
+{
+CHAR *v1; // eax
+int v2; // eax
+int v3; // edx
+int v4; // esi
+int v5; // ecx
+TBall *v6; // eax
+TBall *v7; // eax
+int v8; // ecx
+CHAR String1; // [esp+Ch] [ebp-E0h]
+char Dest; // [esp+D4h] [ebp-18h]
+
+if ( single_step || dword_1025570 )
+return;
+if ( dword_1025568 != 1 )
+{
+pb_mode_countdown(-1);
+return;
+}
+pbctrl_bdoor_controller(0, (int)a1);
+if ( a1 == dword_1028238 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))MainTable)(1000, LODWORD(time_now));
+return;
+}
+if ( a1 == dword_102823C )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))MainTable)(1002, LODWORD(time_now));
+}
+else
+{
+if ( a1 == dword_1028240 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))MainTable)(1004, LODWORD(time_now));
+return;
+}
+if ( a1 == dword_1028244 )
+{
+if ( !*(_DWORD *)((char *)MainTable + 370) )
+nudge_right();
+return;
+}
+if ( a1 == dword_1028248 )
+{
+if ( !*(_DWORD *)((char *)MainTable + 370) )
+nudge_left();
+return;
+}
+if ( a1 == dword_102824C )
+{
+if ( !*(_DWORD *)((char *)MainTable + 370) )
+nudge_up();
+return;
+}
+}
+if ( cheat_mode )
+{
+if ( a1 == (HKEY)66 )
+{
+v2 = *(_DWORD *)((char *)MainTable + 262);
+v3 = *(_DWORD *)(v2 + 4);
+v4 = 0;
+v5 = v2 + 8;
+if ( v3 <= 0 )
+{
+LABEL_36:
+v7 = (TBall *)TPinballComponent::operator new(0x16Au);
+if ( v7 )
+v6 = TBall::TBall(v7, MainTable);
+else
+v6 = 0;
+}
+else
+{
+while ( 1 )
+{
+v6 = *(TBall **)v5;
+if ( !*(_BYTE *)(*(_DWORD *)v5 + 5) )
+break;
+++v4;
+v5 += 4;
+if ( v4 >= v3 )
+goto LABEL_36;
+}
+}
+v8 = *(_DWORD *)((char *)v6 + 154);
+*(float *)((char *)v6 + 42) = 1.0;
+*((_BYTE *)v6 + 5) = 1;
+*(_DWORD *)((char *)v6 + 50) = v8;
+*(float *)((char *)v6 + 46) = 1.0;
+*(float *)((char *)v6 + 62) = 0.0;
+*(float *)((char *)v6 + 58) = 0.0;
+*(float *)((char *)v6 + 54) = 0.0;
+}
+else if ( a1 == (HKEY)72 )
+{
+v1 = get_rc_string(26, 0);
+lstrcpyA(&String1, v1);
+show_and_set_high_score_dialog(byte_1025578, 1000000000, 1, &String1);
+}
+else if ( a1 == (HKEY)77 )
+{
+_sprintf(&Dest, "%ld", memory_use_total);
+MessageBoxA(hwnd_frame, &Dest, "Mem:", 0x2000u);
+}
+else if ( a1 == (HKEY)82 )
+{
+cheat_bump_rank(0);
+}
+else if ( a1 == (HKEY)122 )
+{
+gdrv_get_focus();
+}
+else if ( (HKEY)((char *)a1 - 122) == (HKEY)1 )
+{
+(*(void (**)(void))(*(_DWORD *)MainTable + 4))();
+}
+}
+}
+// 1024F00: using guessed type int memory_use_total;
+// 1024FD8: using guessed type int single_step;
+// 1024FF8: using guessed type int cheat_mode;
+// 1025568: using guessed type int dword_1025568;
+// 1025570: using guessed type int dword_1025570;
+// 1025630: using guessed type float time_now;
+
+//----- (010152E4) --------------------------------------------------------
+void __stdcall pb_keyup(HKEY a1)
+{
+if ( dword_1025568 == 1 && !single_step && !dword_1025570 )
+{
+if ( a1 == dword_1028238 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))MainTable)(1001, LODWORD(time_now));
+}
+else if ( a1 == dword_102823C )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))MainTable)(1003, LODWORD(time_now));
+}
+else if ( a1 == dword_1028240 )
+{
+(**(void (__stdcall ***)(signed int, _DWORD))MainTable)(1005, LODWORD(time_now));
+}
+else if ( a1 == dword_1028244 )
+{
+un_nudge_right(0, 0);
+}
+else if ( a1 == dword_1028248 )
+{
+un_nudge_left(0, 0);
+}
+else if ( a1 == dword_102824C )
+{
+un_nudge_up(0, 0);
+}
+}
+}
+// 1024FD8: using guessed type int single_step;
+// 1025568: using guessed type int dword_1025568;
+// 1025570: using guessed type int dword_1025570;
+// 1025630: using guessed type float time_now;
+
+//----- (010153AE) --------------------------------------------------------
+int __stdcall pb_replay_level(int a1)
+{
+float v1; // ST04_4
+
+dword_1025570 = a1;
+pb_mode_change(1);
+if ( phkResult )
+midi_play_pb_theme(0);
+v1 = (double)(signed int)dword_1028234;
+return (**(int (__stdcall ***)(signed int, _DWORD))MainTable)(1014, LODWORD(v1));
+}
+// 1025570: using guessed type int dword_1025570;
+
+//----- (010153F4) --------------------------------------------------------
+INT_PTR __stdcall pb_high_scores()
+{
+return show_high_score_dialog(byte_1025578);
+}
+
+//----- (01015404) --------------------------------------------------------
+_DWORD *__stdcall pb_window_size(_DWORD *a1, _DWORD *a2)
+{
+_DWORD *result; // eax
+
+*a1 = 600;
+result = a2;
+*a2 = 416;
+return result;
+}
+
+//----- (01015424) --------------------------------------------------------
+int __stdcall pb_init()
+{
+int result; // eax
+int v1; // eax
+signed __int16 *v2; // ebx
+_DWORD *v3; // edi
+_DWORD *v4; // esi
+char *v5; // eax
+signed int v6; // ecx
+double v7; // st7
+double v8; // st5
+int v9; // ST1C_4
+int v10; // ST18_4
+int v11; // ST14_4
+int *v12; // esi
+TPinballTable *v13; // eax
+double v14; // st7
+char v15; // [esp+1Ch] [ebp-294h]
+float v16; // [esp+4Ch] [ebp-264h]
+float v17; // [esp+50h] [ebp-260h]
+CHAR String1; // [esp+54h] [ebp-25Ch]
+CHAR Filename; // [esp+180h] [ebp-130h]
+
+++memory_critical_allocation;
+lstrcpyA(&String1, byte_102543C);
+make_path_name(&Filename, &String1, 0x12Cu);
+v17 = 0.0;
+pb_record_table = (int)partman_load_records(&Filename);
+get_rc_int(158, (int *)&v17);
+if ( v17 != 0.0 )
+score_load_msg_font("pbmsg_ft");
+if ( !pb_record_table )
+return pb_record_table + 1;
+v1 = partman_field_labeled(pb_record_table, "background", 5);
+gdrv_display_palette(v1);
+v2 = (signed __int16 *)partman_field_labeled(pb_record_table, "table_size", 10);
+v3 = (_DWORD *)partman_field_labeled(pb_record_table, "background", 1);
+v4 = (_DWORD *)partman_field_labeled(pb_record_table, "camera_info", 11);
+if ( v4 )
+{
+v5 = &v15;
+LODWORD(v17) = 3;
+do
+{
+v6 = 4;
+do
+{
+*(_DWORD *)v5 = *v4;
+++v4;
+v5 += 4;
+--v6;
+}
+while ( v6 );
+--LODWORD(v17);
+}
+while ( v17 != 0.0 );
+v7 = *(float *)v4;
+LODWORD(v17) = v2[1];
+v8 = (double)SLODWORD(v17);
+LODWORD(v17) = *v2;
+*(float *)&v9 = v8 * 0.5;
+*(float *)&v10 = 0.5 * (double)SLODWORD(v17);
+*(float *)&v11 = v7;
+proj_init((int)&v15, v11, v10, v9);
+v12 = v4 + 1;
+v16 = *(float *)v12;
+v17 = *((float *)v12 + 1);
+}
+render_init(0, v16, v17, *v2, v2[1]);
+gdrv_copy_bitmap(&vscreen, v3[3], v3[4], *(_DWORD *)((char *)v3 + 29), *(_DWORD *)((char *)v3 + 33), v3, 0, 0);
+gdrv_destroy_bitmap((int)v3);
+loader_loadfrom((_WORD *)pb_record_table);
+if ( dword_102556C )
+pb_mode_change(1);
+else
+pb_mode_change(3);
+time_ticks = 0;
+timer_init(150);
+score_init();
+v13 = (TPinballTable *)TPinballComponent::operator new(0x176u);
+if ( v13 )
+MainTable = TPinballTable::TPinballTable(v13);
+else
+MainTable = 0;
+high_score_read((int)byte_1025578, (int)&pb_state);
+v14 = *(float *)(*(_DWORD *)(*(_DWORD *)((char *)MainTable + 262) + 8) + 154);
+--memory_critical_allocation;
+result = 0;
+ball_speed_limit = v14 * 200.0;
+return result;
+}
+// 1024F04: using guessed type int memory_critical_allocation;
+// 1024F84: using guessed type int time_ticks;
+// 10253D0: using guessed type float ball_speed_limit;
+// 102556C: using guessed type int dword_102556C;
+
+//----- (0101566E) --------------------------------------------------------
+int __stdcall pb_uninit()
+{
+score_unload_msg_font();
+loader_unload();
+partman_unload_records((_WORD *)pb_record_table);
+high_score_write(byte_1025578, (int)&pb_state);
+if ( MainTable )
+(*(void (__stdcall **)(signed int))(*(_DWORD *)MainTable + 16))(1);
+MainTable = 0;
+gdrv_get_focus();
+timer_uninit();
+render_uninit();
+return 0;
+}
+
+//----- (010156C1) --------------------------------------------------------
+int __stdcall pb_loose_focus()
+{
+int result; // eax
+
+if ( MainTable )
+result = (**(int (__stdcall ***)(signed int, _DWORD))MainTable)(1010, LODWORD(time_now));
+return result;
+}
+// 1025630: using guessed type float time_now;
+
+//----- (010156E4) --------------------------------------------------------
+void __usercall pb_pause_continue(int a1@)
+{
+char *v1; // eax
+char *v2; // eax
+float v3; // [esp+8h] [ebp-8h]
+
+single_step = single_step == 0;
+TTextBox::Clear(InfoTextBox, a1);
+TTextBox::Clear(MissTextBox, a1);
+if ( single_step )
+{
+if ( MainTable )
+(**(void (__stdcall ***)(signed int, _DWORD))MainTable)(1008, LODWORD(time_now));
+v1 = get_rc_string(22, 0);
+TTextBox::Display(InfoTextBox, a1, v1, -1.0);
+midi_music_stop();
+}
+else
+{
+if ( MainTable )
+(**(void (__stdcall ***)(signed int, _DWORD))MainTable)(1009, 0.0);
+if ( !dword_1025570 )
+{
+if ( dword_1025568 == 2 )
+{
+v3 = -1.0;
+v2 = get_rc_string(24, 0);
+}
+else
+{
+v3 = 5.0;
+v2 = get_rc_string(23, 0);
+}
+TTextBox::Display(InfoTextBox, a1, v2, v3);
+}
+if ( phkResult && !single_step )
+midi_play_pb_theme(0);
+}
+}
+// 1024FD8: using guessed type int single_step;
+// 1025568: using guessed type int dword_1025568;
+// 1025570: using guessed type int dword_1025570;
+// 1025630: using guessed type float time_now;
+
+//----- (010157C3) --------------------------------------------------------
+int __stdcall pb_launch_ball()
+{
+return (***(int (__stdcall ****)(signed int, _DWORD))((char *)MainTable + 222))(1017, 0.0);
+}
+
+//----- (010157E3) --------------------------------------------------------
+int __stdcall pb_reset_table()
+{
+int result; // eax
+
+if ( MainTable )
+result = (**(int (__stdcall ***)(signed int, _DWORD))MainTable)(1024, 0.0);
+return result;
+}
+
+//----- (01015802) --------------------------------------------------------
+void __usercall pb_toggle_demo(int a1@)
+{
+char *v1; // eax
+
+if ( dword_1025570 )
+{
+dword_1025570 = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))MainTable)(1024, 0.0);
+pb_mode_change(2);
+TTextBox::Clear(MissTextBox, a1);
+v1 = get_rc_string(24, 0);
+TTextBox::Display(InfoTextBox, a1, v1, -1.0);
+}
+else
+{
+pb_replay_level(1);
+}
+}
+// 1025570: using guessed type int dword_1025570;
+
+//----- (010211D0) --------------------------------------------------------
+int __stdcall check_expiration_date()
+{
+return 0;
+}
+
+// ALL OK, 648 function(s) have been successfully decompiled
+
diff --git a/pinball.h b/pinball.h
new file mode 100644
index 0000000..f975f67
--- /dev/null
+++ b/pinball.h
@@ -0,0 +1,2762 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#ifndef PINBALL_PINBALL_H
+#define PINBALL_PINBALL_H
+
+/*
+ This file has been generated by IDA.
+ It contains local type definitions from
+ the type library 'pinball'
+*/
+
+#define __int8 char
+#define __int16 short
+#define __int32 int
+#define __int64 long long
+
+struct _GUID;
+struct _devicemodeA;
+struct tagLOGPALETTE;
+struct tagWNDCLASSA;
+struct HWND__;
+struct HINSTANCE__;
+struct HICON__;
+struct HBRUSH__;
+struct HDC__;
+struct tagMSG;
+struct tagINITCOMMONCONTROLSEX;
+union _LARGE_INTEGER;
+struct _EXCEPTION_RECORD;
+struct _CONTEXT;
+struct tWAVEFORMATEX;
+struct HTASK__;
+struct HMMIO__;
+
+/* 1 */
+typedef _GUID GUID;
+
+/* 2 */
+struct _GUID
+{
+ unsigned int Data1;
+ unsigned __int16 Data2;
+ unsigned __int16 Data3;
+ unsigned __int8 Data4[8];
+};
+
+/* 3 */
+struct _SCOPETABLE_ENTRY
+{
+ int EnclosingLevel;
+ void *FilterFunc;
+ void *HandlerFunc;
+};
+
+/* 4 */
+typedef struct _SCOPETABLE_ENTRY *PSCOPETABLE_ENTRY;
+
+/* 64 */
+typedef void *PVOID;
+
+/* 15 */
+typedef unsigned int DWORD;
+
+/* 5 */
+struct _EH3_EXCEPTION_REGISTRATION
+{
+ struct _EH3_EXCEPTION_REGISTRATION *Next;
+ PVOID ExceptionHandler;
+ PSCOPETABLE_ENTRY ScopeTable;
+ DWORD TryLevel;
+};
+
+/* 6 */
+typedef struct _EH3_EXCEPTION_REGISTRATION EH3_EXCEPTION_REGISTRATION;
+
+/* 7 */
+typedef struct _EH3_EXCEPTION_REGISTRATION *PEH3_EXCEPTION_REGISTRATION;
+
+/* 8 */
+struct CPPEH_RECORD
+{
+ DWORD old_esp;
+ EXCEPTION_POINTERS *exc_ptr;
+ struct _EH3_EXCEPTION_REGISTRATION registration;
+};
+
+/* 10 */
+typedef int LONG;
+
+/* 9 */
+struct tagRECT
+{
+ LONG left;
+ LONG top;
+ LONG right;
+ LONG bottom;
+};
+
+/* 11 */
+typedef _devicemodeA DEVMODEA;
+
+/* 13 */
+typedef unsigned __int8 BYTE;
+
+/* 14 */
+typedef unsigned __int16 WORD;
+
+/* 17 */
+struct _devicemodeA::$1DE029518E5B112A14BB6E76DECCA4C4::$5ACE225D4D14CE0550A9F5A217E306C5
+{
+ __int16 dmOrientation;
+ __int16 dmPaperSize;
+ __int16 dmPaperLength;
+ __int16 dmPaperWidth;
+};
+
+/* 19 */
+struct _POINTL
+{
+ LONG x;
+ LONG y;
+};
+
+/* 18 */
+typedef _POINTL POINTL;
+
+/* 16 */
+union _devicemodeA::$1DE029518E5B112A14BB6E76DECCA4C4
+{
+ struct
+ {
+ __int16 dmOrientation;
+ __int16 dmPaperSize;
+ __int16 dmPaperLength;
+ __int16 dmPaperWidth;
+ };
+ POINTL dmPosition;
+};
+
+/* 12 */
+struct _devicemodeA
+{
+ BYTE dmDeviceName[32];
+ WORD dmSpecVersion;
+ WORD dmDriverVersion;
+ WORD dmSize;
+ WORD dmDriverExtra;
+ DWORD dmFields;
+ union
+ {
+ struct
+ {
+ __int16 dmOrientation;
+ __int16 dmPaperSize;
+ __int16 dmPaperLength;
+ __int16 dmPaperWidth;
+ };
+ POINTL dmPosition;
+ };
+ __int16 dmScale;
+ __int16 dmCopies;
+ __int16 dmDefaultSource;
+ __int16 dmPrintQuality;
+ __int16 dmColor;
+ __int16 dmDuplex;
+ __int16 dmYResolution;
+ __int16 dmTTOption;
+ __int16 dmCollate;
+ BYTE dmFormName[32];
+ WORD dmLogPixels;
+ DWORD dmBitsPerPel;
+ DWORD dmPelsWidth;
+ DWORD dmPelsHeight;
+ DWORD dmDisplayFlags;
+ DWORD dmDisplayFrequency;
+ DWORD dmICMMethod;
+ DWORD dmICMIntent;
+ DWORD dmMediaType;
+ DWORD dmDitherType;
+ DWORD dmReserved1;
+ DWORD dmReserved2;
+ DWORD dmPanningWidth;
+ DWORD dmPanningHeight;
+};
+
+/* 20 */
+typedef tagRECT RECT;
+
+/* 21 */
+struct tagPALETTEENTRY
+{
+ BYTE peRed;
+ BYTE peGreen;
+ BYTE peBlue;
+ BYTE peFlags;
+};
+
+/* 22 */
+typedef tagLOGPALETTE LOGPALETTE;
+
+/* 24 */
+typedef tagPALETTEENTRY PALETTEENTRY;
+
+/* 23 */
+struct tagLOGPALETTE
+{
+ WORD palVersion;
+ WORD palNumEntries;
+ PALETTEENTRY palPalEntry[1];
+};
+
+/* 26 */
+typedef char CHAR;
+
+/* 25 */
+struct _OFSTRUCT
+{
+ BYTE cBytes;
+ BYTE fFixedDisk;
+ WORD nErrCode;
+ WORD Reserved1;
+ WORD Reserved2;
+ CHAR szPathName[128];
+};
+
+/* 27 */
+typedef tagWNDCLASSA WNDCLASSA;
+
+/* 29 */
+typedef unsigned int UINT;
+
+/* 35 */
+typedef LONG LRESULT;
+
+/* 31 */
+typedef HWND__ *HWND;
+
+/* 33 */
+typedef UINT WPARAM;
+
+/* 34 */
+typedef LONG LPARAM;
+
+/* 30 */
+typedef LRESULT (__stdcall *WNDPROC)(HWND, UINT, WPARAM, LPARAM);
+
+/* 36 */
+typedef HINSTANCE__ *HINSTANCE;
+
+/* 38 */
+typedef HICON__ *HICON;
+
+/* 40 */
+typedef HICON HCURSOR;
+
+/* 41 */
+typedef HBRUSH__ *HBRUSH;
+
+/* 43 */
+typedef const CHAR *LPCSTR;
+
+/* 28 */
+struct tagWNDCLASSA
+{
+ UINT style;
+ WNDPROC lpfnWndProc;
+ int cbClsExtra;
+ int cbWndExtra;
+ HINSTANCE hInstance;
+ HICON hIcon;
+ HCURSOR hCursor;
+ HBRUSH hbrBackground;
+ LPCSTR lpszMenuName;
+ LPCSTR lpszClassName;
+};
+
+/* 32 */
+struct HWND__
+{
+ int unused;
+};
+
+/* 37 */
+struct HINSTANCE__
+{
+ int unused;
+};
+
+/* 39 */
+struct HICON__
+{
+ int unused;
+};
+
+/* 42 */
+struct HBRUSH__
+{
+ int unused;
+};
+
+/* 45 */
+typedef HDC__ *HDC;
+
+/* 47 */
+typedef int BOOL;
+
+/* 44 */
+struct tagPAINTSTRUCT
+{
+ HDC hdc;
+ BOOL fErase;
+ RECT rcPaint;
+ BOOL fRestore;
+ BOOL fIncUpdate;
+ BYTE rgbReserved[32];
+};
+
+/* 46 */
+struct HDC__
+{
+ int unused;
+};
+
+/* 48 */
+typedef tagPAINTSTRUCT PAINTSTRUCT;
+
+/* 49 */
+typedef tagMSG MSG;
+
+/* 52 */
+struct tagPOINT
+{
+ LONG x;
+ LONG y;
+};
+
+/* 51 */
+typedef tagPOINT POINT;
+
+/* 50 */
+struct tagMSG
+{
+ HWND hwnd;
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+ DWORD time;
+ POINT pt;
+};
+
+/* 53 */
+typedef tagINITCOMMONCONTROLSEX INITCOMMONCONTROLSEX;
+
+/* 54 */
+#pragma pack(push, 1)
+struct tagINITCOMMONCONTROLSEX
+{
+ DWORD dwSize;
+ DWORD dwICC;
+};
+#pragma pack(pop)
+
+/* 55 */
+struct _FILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+};
+
+/* 56 */
+typedef _LARGE_INTEGER LARGE_INTEGER;
+
+/* 58 */
+struct _LARGE_INTEGER::$837407842DC9087486FDFA5FEB63B74E
+{
+ DWORD LowPart;
+ LONG HighPart;
+};
+
+/* 59 */
+typedef __int64 LONGLONG;
+
+/* 57 */
+union _LARGE_INTEGER
+{
+ struct
+ {
+ DWORD LowPart;
+ LONG HighPart;
+ };
+ _LARGE_INTEGER::$837407842DC9087486FDFA5FEB63B74E u;
+ LONGLONG QuadPart;
+};
+
+/* 62 */
+typedef _EXCEPTION_RECORD EXCEPTION_RECORD;
+
+/* 61 */
+typedef EXCEPTION_RECORD *PEXCEPTION_RECORD;
+
+/* 67 */
+typedef _CONTEXT CONTEXT;
+
+/* 66 */
+typedef CONTEXT *PCONTEXT;
+
+/* 60 */
+struct _EXCEPTION_POINTERS
+{
+ PEXCEPTION_RECORD ExceptionRecord;
+ PCONTEXT ContextRecord;
+};
+
+/* 65 */
+typedef unsigned int UINT_PTR;
+
+/* 63 */
+struct _EXCEPTION_RECORD
+{
+ DWORD ExceptionCode;
+ DWORD ExceptionFlags;
+ _EXCEPTION_RECORD *ExceptionRecord;
+ PVOID ExceptionAddress;
+ DWORD NumberParameters;
+ UINT_PTR ExceptionInformation[15];
+};
+
+/* 70 */
+struct _FLOATING_SAVE_AREA
+{
+ DWORD ControlWord;
+ DWORD StatusWord;
+ DWORD TagWord;
+ DWORD ErrorOffset;
+ DWORD ErrorSelector;
+ DWORD DataOffset;
+ DWORD DataSelector;
+ BYTE RegisterArea[80];
+ DWORD Cr0NpxState;
+};
+
+/* 69 */
+typedef _FLOATING_SAVE_AREA FLOATING_SAVE_AREA;
+
+/* 68 */
+struct _CONTEXT
+{
+ DWORD ContextFlags;
+ DWORD Dr0;
+ DWORD Dr1;
+ DWORD Dr2;
+ DWORD Dr3;
+ DWORD Dr6;
+ DWORD Dr7;
+ FLOATING_SAVE_AREA FloatSave;
+ DWORD SegGs;
+ DWORD SegFs;
+ DWORD SegEs;
+ DWORD SegDs;
+ DWORD Edi;
+ DWORD Esi;
+ DWORD Ebx;
+ DWORD Edx;
+ DWORD Ecx;
+ DWORD Eax;
+ DWORD Ebp;
+ DWORD Eip;
+ DWORD SegCs;
+ DWORD EFlags;
+ DWORD Esp;
+ DWORD SegSs;
+ BYTE ExtendedRegisters[512];
+};
+
+/* 72 */
+typedef UINT MMVERSION;
+
+/* 71 */
+#pragma pack(push, 1)
+struct tagWAVEOUTCAPSA
+{
+ WORD wMid;
+ WORD wPid;
+ MMVERSION vDriverVersion;
+ CHAR szPname[32];
+ DWORD dwFormats;
+ WORD wChannels;
+ WORD wReserved1;
+ DWORD dwSupport;
+};
+#pragma pack(pop)
+
+/* 75 */
+#pragma pack(push, 1)
+struct mmtime_tag::$532DCF0E9B9A2B0A020BD11490F25514::$2498AB4F57B5A5935D3AAA9956C218FB
+{
+ BYTE hour;
+ BYTE min;
+ BYTE sec;
+ BYTE frame;
+ BYTE fps;
+ BYTE dummy;
+ BYTE pad[2];
+};
+#pragma pack(pop)
+
+/* 76 */
+#pragma pack(push, 1)
+struct mmtime_tag::$532DCF0E9B9A2B0A020BD11490F25514::$B7A2B1CE967584EBB3840978181CF21D
+{
+ DWORD songptrpos;
+};
+#pragma pack(pop)
+
+/* 74 */
+#pragma pack(push, 1)
+union mmtime_tag::$532DCF0E9B9A2B0A020BD11490F25514
+{
+ DWORD ms;
+ DWORD sample;
+ DWORD cb;
+ DWORD ticks;
+ mmtime_tag::$532DCF0E9B9A2B0A020BD11490F25514::$2498AB4F57B5A5935D3AAA9956C218FB smpte;
+ mmtime_tag::$532DCF0E9B9A2B0A020BD11490F25514::$B7A2B1CE967584EBB3840978181CF21D midi;
+};
+#pragma pack(pop)
+
+/* 73 */
+#pragma pack(push, 1)
+struct mmtime_tag
+{
+ UINT wType;
+ mmtime_tag::$532DCF0E9B9A2B0A020BD11490F25514 u;
+};
+#pragma pack(pop)
+
+/* 77 */
+typedef tWAVEFORMATEX WAVEFORMATEX;
+
+/* 78 */
+#pragma pack(push, 1)
+struct tWAVEFORMATEX
+{
+ WORD wFormatTag;
+ WORD nChannels;
+ DWORD nSamplesPerSec;
+ DWORD nAvgBytesPerSec;
+ WORD nBlockAlign;
+ WORD wBitsPerSample;
+ WORD cbSize;
+};
+#pragma pack(pop)
+
+/* 80 */
+typedef DWORD FOURCC;
+
+/* 83 */
+typedef CHAR *LPSTR;
+
+/* 82 */
+typedef LRESULT __stdcall MMIOPROC(LPSTR lpmmioinfo, UINT uMsg, LPARAM lParam1, LPARAM lParam2);
+
+/* 81 */
+typedef MMIOPROC *LPMMIOPROC;
+
+/* 84 */
+typedef HTASK__ *HTASK;
+
+/* 86 */
+typedef char *HPSTR;
+
+/* 87 */
+typedef HMMIO__ *HMMIO;
+
+/* 79 */
+#pragma pack(push, 1)
+struct _MMIOINFO
+{
+ DWORD dwFlags;
+ FOURCC fccIOProc;
+ LPMMIOPROC pIOProc;
+ UINT wErrorRet;
+ HTASK htask;
+ LONG cchBuffer;
+ HPSTR pchBuffer;
+ HPSTR pchNext;
+ HPSTR pchEndRead;
+ HPSTR pchEndWrite;
+ LONG lBufOffset;
+ LONG lDiskOffset;
+ DWORD adwInfo[3];
+ DWORD dwReserved1;
+ DWORD dwReserved2;
+ HMMIO hmmio;
+};
+#pragma pack(pop)
+
+/* 85 */
+struct HTASK__
+{
+ int unused;
+};
+
+/* 88 */
+#pragma pack(push, 1)
+struct HMMIO__
+{
+ int unused;
+};
+#pragma pack(pop)
+
+/* 89 */
+#pragma pack(push, 1)
+struct _MMCKINFO
+{
+ FOURCC ckid;
+ DWORD cksize;
+ FOURCC fccType;
+ DWORD dwDataOffset;
+ DWORD dwFlags;
+};
+#pragma pack(pop)
+
+/* 91 */
+typedef BYTE *LPBYTE;
+
+/* 92 */
+typedef void *HANDLE;
+
+/* 90 */
+struct _STARTUPINFOA
+{
+ DWORD cb;
+ LPSTR lpReserved;
+ LPSTR lpDesktop;
+ LPSTR lpTitle;
+ DWORD dwX;
+ DWORD dwY;
+ DWORD dwXSize;
+ DWORD dwYSize;
+ DWORD dwXCountChars;
+ DWORD dwYCountChars;
+ DWORD dwFillAttribute;
+ DWORD dwFlags;
+ WORD wShowWindow;
+ WORD cbReserved2;
+ LPBYTE lpReserved2;
+ HANDLE hStdInput;
+ HANDLE hStdOutput;
+ HANDLE hStdError;
+};
+
+/* 93 */
+struct TLightGroup;
+
+/* 94 */
+struct TLightBargraph;
+
+/* 95 */
+struct TBall;
+
+/* 96 */
+struct TEdgeManager;
+
+/* 97 */
+struct TTextBoxMessage;
+
+/* 98 */
+struct TEdgeSegment;
+
+/* 99 */
+struct TCircle;
+
+/* 100 */
+struct TPinballComponent;
+
+/* 101 */
+struct TCollisionComponent;
+
+/* 102 */
+struct TWall;
+
+/* 103 */
+struct TOneway;
+
+/* 104 */
+struct TBumper;
+
+/* 105 */
+struct TFlagSpinner;
+
+/* 106 */
+struct TPopupTarget;
+
+/* 107 */
+struct TSoloTarget;
+
+/* 108 */
+struct TRollover;
+
+/* 109 */
+struct TLightRollover;
+
+/* 110 */
+struct TKickback;
+
+/* 111 */
+struct TKickout;
+
+/* 112 */
+struct THole;
+
+/* 113 */
+struct TRamp;
+
+/* 114 */
+struct TSink;
+
+/* 115 */
+struct TDrain;
+
+/* 116 */
+struct TTableLayer;
+
+/* 117 */
+struct TPinballTable;
+
+/* 118 */
+struct TPlunger;
+
+/* 119 */
+struct TTextBox;
+
+/* 120 */
+struct TFlipperEdge;
+
+/* 121 */
+struct TFlipper;
+
+/* 122 */
+struct TLine;
+
+/* 123 */
+struct objlist_class;
+
+/* 124 */
+struct TLight;
+
+/* 125 */
+struct TEdgeBox;
+
+/* 126 */
+struct TZmapList;
+
+/* 127 */
+struct TComponentGroup;
+
+/* 128 */
+struct TDemo;
+
+/* 129 */
+struct TTimer;
+
+/* 130 */
+struct TBlocker;
+
+/* 131 */
+struct TTripwire;
+
+/* 132 */
+struct TSound;
+
+/* 133 */
+struct TGate;
+
+
+//-------------------------------------------------------------------------
+// Function declarations
+
+#define __thiscall __cdecl // Test compile in C mode
+
+// LSTATUS __stdcall RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult);
+// LSTATUS __stdcall RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
+// LSTATUS __stdcall RegCloseKey(HKEY hKey);
+// LSTATUS __stdcall RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
+// LSTATUS __stdcall RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, REGSAM samDesired, const LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition);
+// LSTATUS __stdcall RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE *lpData, DWORD cbData);
+// LSTATUS __stdcall RegQueryValueA(HKEY hKey, LPCSTR lpSubKey, LPSTR lpData, PLONG lpcbData);
+// BOOL __stdcall InitCommonControlsEx(const INITCOMMONCONTROLSEX *picce);
+// UINT __stdcall RealizePalette(HDC hdc);
+// HPALETTE __stdcall SelectPalette(HDC hdc, HPALETTE hPal, BOOL bForceBkgd);
+// HDC __stdcall CreateCompatibleDC(HDC hdc);
+// int __stdcall GetObjectA(HANDLE h, int c, LPVOID pv);
+// HGDIOBJ __stdcall GetStockObject(int i);
+// HBITMAP __stdcall CreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *pbmih, DWORD flInit, const void *pjBits, const BITMAPINFO *pbmi, UINT iUsage);
+// UINT __stdcall GetPaletteEntries(HPALETTE hpal, UINT iStart, UINT cEntries, LPPALETTEENTRY pPalEntries);
+// BOOL __stdcall DeleteDC(HDC hdc);
+// UINT __stdcall SetPaletteEntries(HPALETTE hpal, UINT iStart, UINT cEntries, const PALETTEENTRY *pPalEntries);
+// BOOL __stdcall ResizePalette(HPALETTE hpal, UINT n);
+// UINT __stdcall GetSystemPaletteEntries(HDC hdc, UINT iStart, UINT cEntries, LPPALETTEENTRY pPalEntries);
+// UINT __stdcall SetSystemPaletteUse(HDC hdc, UINT use);
+// int __stdcall GetDeviceCaps(HDC hdc, int index);
+// HBITMAP __stdcall CreateCompatibleBitmap(HDC hdc, int cx, int cy);
+// BOOL __stdcall BitBlt(HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, DWORD rop);
+// HPALETTE __stdcall CreatePalette(const LOGPALETTE *plpal);
+// HBRUSH __stdcall CreateSolidBrush(COLORREF color);
+// HGDIOBJ __stdcall SelectObject(HDC hdc, HGDIOBJ h);
+// BOOL __stdcall DeleteObject(HGDIOBJ ho);
+// int __stdcall SetBkMode(HDC hdc, int mode);
+// COLORREF __stdcall SetTextColor(HDC hdc, COLORREF color);
+// DWORD __stdcall GetLayout(HDC hdc);
+// int __stdcall StretchDIBits(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc, int SrcWidth, int SrcHeight, const void *lpBits, const BITMAPINFO *lpbmi, UINT iUsage, DWORD rop);
+// DWORD __stdcall SetLayout(HDC hdc, DWORD l);
+// BOOL __stdcall TerminateProcess(HANDLE hProcess, UINT uExitCode);
+// void __stdcall GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo);
+// UINT __stdcall GetPrivateProfileIntA(LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault, LPCSTR lpFileName);
+// BOOL __stdcall WritePrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpString, LPCSTR lpFileName);
+// DWORD __stdcall SizeofResource(HMODULE hModule, HRSRC hResInfo);
+// DWORD __stdcall GetVersion();
+// HMODULE __stdcall LoadLibraryA(LPCSTR lpLibFileName);
+// FARPROC __stdcall GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
+// LPTOP_LEVEL_EXCEPTION_FILTER __stdcall SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
+// LONG __stdcall UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo);
+// HANDLE __stdcall GetCurrentProcess();
+// BOOL __stdcall FreeResource(HGLOBAL hResData);
+// void __stdcall GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime);
+// DWORD __stdcall GetCurrentProcessId();
+// DWORD __stdcall GetCurrentThreadId();
+// DWORD __stdcall GetTickCount();
+// BOOL __stdcall QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);
+// HFILE __stdcall _lopen(LPCSTR lpPathName, int iReadWrite);
+// void __stdcall Sleep(DWORD dwMilliseconds);
+// UINT __stdcall WinExec(LPCSTR lpCmdLine, UINT uCmdShow);
+// HANDLE __stdcall GetCurrentThread();
+// BOOL __stdcall SetThreadPriority(HANDLE hThread, int nPriority);
+// DWORD __stdcall GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
+// DWORD __stdcall GetLastError();
+// int __stdcall lstrcmpA(LPCSTR lpString1, LPCSTR lpString2);
+// HMODULE __stdcall GetModuleHandleA(LPCSTR lpModuleName);
+// HRSRC __stdcall FindResourceA(HMODULE hModule, LPCSTR lpName, LPCSTR lpType);
+// HGLOBAL __stdcall LoadResource(HMODULE hModule, HRSRC hResInfo);
+// LPVOID __stdcall LockResource(HGLOBAL hResData);
+// int __stdcall _hread(HFILE hFile, LPVOID lpBuffer, int lBytes);
+// HGLOBAL __stdcall GlobalHandle(LPCVOID pMem);
+// BOOL __stdcall GlobalUnlock(HGLOBAL hMem);
+// HGLOBAL __stdcall GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags);
+// HGLOBAL __stdcall GlobalFree(HGLOBAL hMem);
+// LONG __stdcall _llseek(HFILE hFile, LONG lOffset, int iOrigin);
+// UINT __stdcall _lread(HFILE hFile, LPVOID lpBuffer, UINT uBytes);
+// HGLOBAL __stdcall GlobalAlloc(UINT uFlags, SIZE_T dwBytes);
+// LPVOID __stdcall GlobalLock(HGLOBAL hMem);
+// HLOCAL __stdcall LocalAlloc(UINT uFlags, SIZE_T uBytes);
+// HLOCAL __stdcall LocalFree(HLOCAL hMem);
+// HFILE __stdcall OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle);
+// HFILE __stdcall _lclose(HFILE hFile);
+// LPSTR __stdcall lstrcpynA(LPSTR lpString1, LPCSTR lpString2, int iMaxLength);
+// LPSTR __stdcall lstrcatA(LPSTR lpString1, LPCSTR lpString2);
+// int __stdcall lstrlenA(LPCSTR lpString);
+// LPSTR __stdcall lstrcpyA(LPSTR lpString1, LPCSTR lpString2);
+// INT __stdcall ShellAboutA(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon);
+// UINT __stdcall RegisterWindowMessageA(LPCSTR lpString);
+// HWND __stdcall FindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName);
+// BOOL __stdcall GetCursorPos(LPPOINT lpPoint);
+// BOOL __stdcall SetCursorPos(int X, int Y);
+// BOOL __stdcall PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg);
+// BOOL __stdcall TranslateMessage(const MSG *lpMsg);
+// LRESULT __stdcall DispatchMessageA(const MSG *lpMsg);
+// BOOL __stdcall GetMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
+// BOOL __stdcall IsIconic(HWND hWnd);
+// BOOL __stdcall SetForegroundWindow(HWND hWnd);
+// HMENU __stdcall GetMenu(HWND hWnd);
+// void __stdcall PostQuitMessage(int nExitCode);
+// BOOL __stdcall PostMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+// BOOL __stdcall ReleaseCapture();
+// HWND __stdcall SetCapture(HWND hWnd);
+// HICON __stdcall LoadIconA(HINSTANCE hInstance, LPCSTR lpIconName);
+// BOOL __stdcall EndPaint(HWND hWnd, const PAINTSTRUCT *lpPaint);
+// BOOL __stdcall UnregisterClassA(LPCSTR lpClassName, HINSTANCE hInstance);
+// HBITMAP __stdcall LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName);
+// BOOL __stdcall DestroyWindow(HWND hWnd);
+// ATOM __stdcall RegisterClassA(const WNDCLASSA *lpWndClass);
+// HWND __stdcall CreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
+// LONG __stdcall GetWindowLongA(HWND hWnd, int nIndex);
+// LRESULT __stdcall DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+// BOOL __stdcall UpdateWindow(HWND hWnd);
+// HCURSOR __stdcall LoadCursorA(HINSTANCE hInstance, LPCSTR lpCursorName);
+// HCURSOR __stdcall SetCursor(HCURSOR hCursor);
+// BOOL __stdcall DeleteMenu(HMENU hMenu, UINT uPosition, UINT uFlags);
+// BOOL __stdcall DrawMenuBar(HWND hWnd);
+// LRESULT __stdcall SendDlgItemMessageA(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam);
+// UINT __stdcall MapVirtualKeyA(UINT uCode, UINT uMapType);
+// int __stdcall GetKeyNameTextA(LONG lParam, LPSTR lpString, int cchSize);
+// DWORD __stdcall CheckMenuItem(HMENU hMenu, UINT uIDCheckItem, UINT uCheck);
+// BOOL __stdcall EnableMenuItem(HMENU hMenu, UINT uIDEnableItem, UINT uEnable);
+// INT_PTR __stdcall DialogBoxParamA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
+// int __stdcall MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
+// BOOL __stdcall EndDialog(HWND hDlg, INT_PTR nResult);
+// UINT __stdcall GetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPSTR lpString, int cchMax);
+// BOOL __stdcall ShowWindow(HWND hWnd, int nCmdShow);
+// BOOL __stdcall EnableWindow(HWND hWnd, BOOL bEnable);
+// HWND __stdcall SetFocus(HWND hWnd);
+// LRESULT __stdcall SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+// HWND __stdcall GetParent(HWND hWnd);
+// BOOL __stdcall WinHelpA(HWND hWndMain, LPCSTR lpszHelp, UINT uCommand, ULONG_PTR dwData);
+// HWND __stdcall GetDlgItem(HWND hDlg, int nIDDlgItem);
+// BOOL __stdcall SetWindowTextA(HWND hWnd, LPCSTR lpString);
+// LONG __stdcall SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong);
+// int __stdcall GetSystemMetrics(int nIndex);
+// HDC __stdcall GetDC(HWND hWnd);
+// HDC __stdcall BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
+// BOOL __stdcall InvalidateRect(HWND hWnd, const RECT *lpRect, BOOL bErase);
+// LONG __stdcall ChangeDisplaySettingsA(DEVMODEA *lpDevMode, DWORD dwFlags);
+// BOOL __stdcall SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
+// BOOL __stdcall RedrawWindow(HWND hWnd, const RECT *lprcUpdate, HRGN hrgnUpdate, UINT flags);
+// BOOL __stdcall IsWindowVisible(HWND hWnd);
+// BOOL __stdcall MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);
+// int __stdcall FillRect(HDC hDC, const RECT *lprc, HBRUSH hbr);
+// INT_PTR __stdcall DialogBoxIndirectParamA(HINSTANCE hInstance, LPCDLGTEMPLATEA hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
+// int __stdcall GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount);
+// BOOL __stdcall MessageBeep(UINT uType);
+// HWND __stdcall GetDesktopWindow();
+// BOOL __stdcall GetWindowRect(HWND hWnd, LPRECT lpRect);
+// int __stdcall DrawTextA(HDC hdc, LPCSTR lpchText, int cchText, LPRECT lprc, UINT format);
+// int __stdcall ReleaseDC(HWND hWnd, HDC hDC);
+// int __stdcall LoadStringA(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int cchBufferMax);
+// int _wsprintfA(LPSTR, LPCSTR, ...);
+// BOOL __stdcall SetMenu(HWND hWnd, HMENU hMenu);
+// DWORD __stdcall timeGetTime();
+// BOOL __stdcall sndPlaySoundA(LPCSTR pszSound, UINT fuSound);
+// HMMIO __stdcall mmioOpenA(LPSTR pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen);
+// MMRESULT __stdcall mmioClose(HMMIO hmmio, UINT fuClose);
+// MMRESULT __stdcall mmioDescend(HMMIO hmmio, LPMMCKINFO pmmcki, const MMCKINFO *pmmckiParent, UINT fuDescend);
+// LONG __stdcall mmioRead(HMMIO hmmio, HPSTR pch, LONG cch);
+// MMRESULT __stdcall mmioAscend(HMMIO hmmio, LPMMCKINFO pmmcki, UINT fuAscend);
+// MMRESULT __stdcall waveOutPause(HWAVEOUT hwo);
+// MMRESULT __stdcall waveOutRestart(HWAVEOUT hwo);
+// MMRESULT __stdcall waveOutWrite(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
+// MMRESULT __stdcall waveOutOpen(LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
+// MMRESULT __stdcall waveOutClose(HWAVEOUT hwo);
+// MMRESULT __stdcall waveOutPrepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
+// MMRESULT __stdcall waveOutUnprepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
+// MMRESULT __stdcall waveOutReset(HWAVEOUT hwo);
+// MMRESULT __stdcall waveOutGetPosition(HWAVEOUT hwo, LPMMTIME pmmt, UINT cbmmt);
+// UINT __stdcall waveOutGetNumDevs();
+// MMRESULT __stdcall waveOutGetDevCapsA(UINT_PTR uDeviceID, LPWAVEOUTCAPSA pwoc, UINT cbwoc);
+// MCIERROR __stdcall mciSendCommandA(MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
+// void __cdecl __cexit();
+// int __cdecl ___getmainargs(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); weak
+// int __cdecl ___setusermatherr(_DWORD); weak
+// void __cdecl __noreturn __exit(int Code);
+// int ___p__fmode(void); weak
+// int __cdecl ___set_app_type(_DWORD); weak
+// int __cdecl _atoi(const char *Str);
+// void __cdecl __c_exit();
+// wchar_t *__cdecl _wcscpy(wchar_t *Dest, const wchar_t *Source);
+// size_t __cdecl _wcslen(const wchar_t *Str);
+// int __cdecl _isdigit(int C);
+// int __cdecl _isalnum(int C);
+// int __cdecl _isspace(int C);
+// void *__cdecl _calloc(size_t NumOfElements, size_t SizeOfElements);
+// int __cdecl _rand();
+// double __cdecl _floor(double);
+// char *__cdecl _strstr(const char *Str, const char *SubStr);
+// void __cdecl __noreturn _exit(int Code);
+// FILE *__cdecl _fopen(const char *Filename, const char *Mode);
+// int __cdecl _fclose(FILE *File);
+// int __cdecl __strnicmp(const char *Str1, const char *Str, size_t MaxCount);
+// void *__cdecl _realloc(void *Memory, size_t NewSize);
+// void __cdecl _free(void *Memory);
+// void *__cdecl _malloc(size_t Size);
+// int _sprintf(char *Dest, const char *Format, ...);
+// char *__cdecl __itoa(int Val, char *DstBuf, int Radix);
+// int _sscanf(const char *Src, const char *Format, ...);
+// char *__cdecl __ltoa(int Val, char *DstBuf, int Radix);
+// int ___p__commode(void); weak
+// void *__cdecl _memmove(void *Dst, const void *Src, size_t Size);
+// int __cdecl _atol(const char *Str);
+HDC __stdcall _GetDC(HWND hWnd);
+HDC __stdcall _BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
+CHAR *__stdcall options_path_init(LPCSTR lpString);
+void __stdcall options_path_uninit();
+LPCSTR __stdcall options_path(LPCSTR lpString2);
+void __stdcall options_path_free();
+HKEY __stdcall options_get_int(DWORD cbData, LPCSTR lpValueName, HKEY phkResult);
+void __stdcall options_get_string(DWORD dwDisposition, LPCSTR lpValueName, LPSTR lpString1, LPCSTR lpString2, int iMaxLength);
+void __stdcall options_set_int(HKEY phkResult, LPCSTR lpValueName, BYTE Data);
+void __stdcall options_set_string(HKEY phkResult, LPCSTR lpValueName, LPCSTR lpString);
+CHAR *__stdcall get_rc_string(__int16 a1, int a2);
+int __stdcall get_rc_int(__int16 a1, int *a2);
+int __stdcall grtext_draw_ttext_in_box(LPCSTR lpString, int mode, int, COLORREF color, int, int); // idb
+int sub_10038F8();
+LONG sub_1003975();
+LONG sub_100399D();
+BOOL __stdcall fullscrn_set_menu_mode(int a1);
+signed int sub_1003A23();
+int sub_1003B66();
+LONG __stdcall fullscrn_set_screen_mode(int a1);
+void __stdcall fullscrn_force_redraw();
+signed int __stdcall fullscrn_displaychange();
+BOOL __stdcall fullscrn_init(int a1, int a2, int a3, HWND a4, int a5, int a6);
+LONG __stdcall fullscrn_shutdown();
+BOOL __stdcall fullscrn_activate(int a1);
+int __stdcall fullscrn_convert_mouse_pos(int a1);
+_DWORD *__stdcall fullscrn_getminmaxinfo(_DWORD *a1);
+// HBRUSH __userpurge sub_1003F10@(LONG a1@, LONG a2@, int a3, int a4);
+void __stdcall fullscrn_paint();
+signed int __stdcall rectangle_clip(int *a1, int *a2, _DWORD *a3);
+int __stdcall enclosing_box(_DWORD *a1, _DWORD *a2, _DWORD *a3);
+int __stdcall DibSetUsage(int, HPALETTE hpal, int); // idb
+_DWORD *__stdcall DibCreate(int a1, int a2, int a3);
+int __stdcall gdrv_init(int a1, HWND a2);
+int __stdcall gdrv_display_palette(int a1);
+int __stdcall gdrv_uninit();
+int __stdcall gdrv_create_bitmap_dib(int a1, int a2, int a3);
+int __stdcall gdrv_create_bitmap(int a1, int a2, int a3);
+signed int __stdcall gdrv_create_raw_bitmap(int a1, int a2, int a3, int a4);
+signed int __stdcall gdrv_destroy_bitmap(int a1);
+UINT __stdcall gdrv_start_blit_sequence();
+int __stdcall gdrv_blit_sequence(int, int xSrc, int, int xDest, int yDest, int DestWidth, int DestHeight); // idb
+int __stdcall gdrv_end_blit_sequence();
+HDC __stdcall gdrv_blit(int a1, int xSrc, int a3, int xDest, int yDest, int DestWidth, int DestHeight);
+int __stdcall gdrv_blat(int, int xDest, int yDest); // idb
+// int __userpurge gdrv_fill_bitmap@(int a1@, _DWORD *a2, unsigned int a3, int a4, int a5, int a6, char a7);
+char *__stdcall gdrv_copy_bitmap(_DWORD *a1, int a2, int a3, int a4, int a5, _DWORD *a6, int a7, int a8);
+_BYTE *__stdcall gdrv_copy_bitmap_w_transparency(_DWORD *a1, int a2, int a3, int a4, int a5, _DWORD *a6, int a7, int a8);
+int __stdcall zdrv_pad(int a1);
+signed int __stdcall zdrv_create_zmap(int a1, int a2, int a3);
+signed int __stdcall zdrv_destroy_zmap(_DWORD *a1);
+// int __userpurge zdrv_fill@(int a1@, int a2, unsigned int a3, int a4, int a5, int a6, __int16 a7);
+_WORD *__stdcall zdrv_paint(int a1, int a2, _DWORD *a3, int a4, int a5, int a6, int a7, int a8, _DWORD *a9, int a10, int a11, int a12, int a13, int a14);
+unsigned __int16 *__stdcall zdrv_paint_flat(int a1, int a2, _DWORD *a3, int a4, int a5, int a6, int a7, int a8, _DWORD *a9, int a10, int a11, unsigned __int16 a12);
+int __stdcall high_score_clear_table(int a1);
+signed int __stdcall high_score_get_score_position(int a1, int a2);
+int __stdcall high_score_place_new_score_into(int, int, LPCSTR lpString, int); // idb
+char *__stdcall scramble_number_string(int Val, char *DstBuf);
+signed int __stdcall high_score_read(int a1, int a2);
+int __stdcall high_score_write(LPCSTR lpString, int); // idb
+char *__stdcall score_string_format(int a1, char *a2);
+void __stdcall hsdlg_show_score(HWND hDlg, LPCSTR lpString, int a3, int a4);
+void __stdcall show_high_scores(HWND hDlg, LPCSTR lpString);
+BOOL __stdcall HighScore(HWND, UINT, WPARAM, LPARAM); // idb
+INT_PTR __stdcall show_high_score_dialog(const CHAR *a1);
+INT_PTR __stdcall show_and_set_high_score_dialog(const CHAR *a1, int a2, int a3, const CHAR *a4);
+int __stdcall memory_init(int a1);
+int __stdcall memoryallocate(unsigned int a1);
+void __stdcall memoryfree(int a1);
+int __stdcall memoryrealloc(int a1, unsigned int a2);
+void __stdcall options_uninit();
+HMENU __stdcall options_menu_set(UINT uIDEnableItem, int a2);
+HMENU __stdcall options_menu_check(UINT uIDCheckItem, int a2);
+HMENU __stdcall options_toggle(UINT uIDCheckItem);
+unsigned int __stdcall get_vk_key_name(__int16 a1, LPSTR lpString);
+BOOL __stdcall KeyMapDlgProc(HWND, UINT, WPARAM, LPARAM); // idb
+INT_PTR __stdcall options_keyboard();
+void __stdcall options_init(HMENU a1);
+int __stdcall partman_field(int a1, int a2, int a3);
+int __stdcall partman_field_size_nth(int a1, int a2, int a3, int a4);
+int __stdcall partman_field_size(int a1, int a2, int a3);
+int __stdcall partman_field_nth(int a1, int a2, int a3, int a4);
+int __stdcall partman_record_labeled(int, LPCSTR lpString); // idb
+int __stdcall partman_field_labeled(int, LPCSTR lpString, int); // idb
+void __stdcall partman_unload_records(_WORD *a1);
+char __stdcall _lread_char(HFILE hFile);
+int __stdcall _lread_long(HFILE hFile); // idb
+signed __int16 *__stdcall partman_load_records(LPCSTR lpFileName);
+int __stdcall FindShiftKeys();
+int __stdcall nullsub_1(int, int, int); // weak
+LRESULT __stdcall SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+int __stdcall Sound_Init(HINSTANCE hInstance, int, int); // idb
+HLOCAL __stdcall Sound_Close();
+CHAR *__stdcall Sound_LoadWaveFile(LPCSTR lpName);
+LPCVOID __stdcall Sound_FreeSound(LPCVOID pMem);
+LPCVOID __stdcall Sound_Deactivate();
+LPCVOID __stdcall Sound_Activate();
+int __stdcall Sound_Idle();
+signed int __stdcall Sound_Flush(signed int a1, int a2);
+void __stdcall Sound_PlaySound(int a1, int a2, int a3, unsigned __int16 a4, __int16 a5);
+void __stdcall Sound_Enable(signed int a1, int a2, int a3);
+HPALETTE __stdcall splash_init_palette(LOGPALETTE *plpal);
+HBITMAP __stdcall load_title_bitmap(HMODULE hModule, HDC hdc, LPCSTR lpName, UINT iStart, int a5, int a6);
+int __stdcall splash_bitmap_setup(int a1);
+void __stdcall splash_paint(int a1, HDC hdc);
+void __stdcall splash_hide(int a1);
+HINSTANCE __stdcall splash_destroy(int a1);
+LRESULT __stdcall splash_message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+int __stdcall splash_screen(int, LPCSTR lpString2, LPCSTR); // idb
+signed int __stdcall timer_init(int a1);
+void __stdcall timer_uninit();
+int __stdcall timer_set(float, int, int); // idb
+signed int __stdcall timer_check();
+int __stdcall timer_kill(int a1);
+int __stdcall make_path_name(LPSTR lpFilename, LPCSTR lpString2, DWORD nSize); // idb
+void __stdcall help_introduction(int a1, int a2);
+BOOL __stdcall center_in(HWND hWnd, HWND a2);
+INT __stdcall a_dialog(HINSTANCE hInstance, HWND hWnd, int a3);
+// void __usercall winmain_pause(int a1@);
+// void __usercall winmain_end_pause(int a1@);
+// HCURSOR __usercall winmain_new_game@(int a1@);
+void __stdcall __noreturn winmain_memalloc_failure(); // idb
+HANDLE __stdcall adjust_priority(int a1);
+LRESULT __stdcall message_handler(HWND hWnd, UINT Msg, WPARAM wParam, int a4);
+signed int sub_10082A9();
+int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
+double __stdcall normalize_2d(float *a1);
+double __stdcall ray_intersect_circle(float *a1, float *a2);
+int __stdcall line_init(int, float, float, float, float); // idb
+double __stdcall ray_intersect_line(float *a1, float *a2);
+float *__stdcall proj_matrix_vector_multiply(float *a1, float *a2, float *a3);
+float *__stdcall cross(float *a1, float *a2, float *a3);
+double __stdcall magnitude(float *a1);
+int __stdcall proj_init(int a1, int a2, int a3, int a4);
+int __stdcall proj_recenter(int a1, int a2);
+double __stdcall proj_z_distance(_DWORD); // weak
+double __stdcall proj_xform_to_2d(float *a1, _DWORD *a2);
+signed int __stdcall loader_error(int a1, int a2);
+_DWORD *__stdcall loader_default_vsi(_DWORD *a1);
+signed int __stdcall loader_get_sound_id(int a1);
+void __stdcall loader_unload();
+int __stdcall loader_loadfrom(_WORD *a1);
+int __stdcall loader_query_handle(LPCSTR lpString); // idb
+signed int __stdcall loader_query_visual_states(int a1);
+signed int __stdcall loader_material(int a1, _DWORD *a2);
+signed int __stdcall loader_kicker(int a1, _DWORD *a2);
+signed int __stdcall loader_state_id(int a1, signed int a2);
+signed int __stdcall loader_query_visual(int a1, signed int a2, _DWORD *a3);
+int __stdcall loader_query_name(int a1);
+int __stdcall loader_query_float_attribute(int a1, signed int a2, int a3);
+int __stdcall loader_query_iattribute(int a1, int a2, _DWORD *a3);
+double __stdcall loader_play_sound(int a1);
+objlist_class *__thiscall objlist_class::objlist_class(objlist_class *this, int a2, int a3);
+void __thiscall objlist_class::Grow(objlist_class *__hidden this); // idb
+void __stdcall flasher_callback(int, void *); // idb
+void __stdcall flasher_start(struct flasher_type *, int); // idb
+void __stdcall flasher_stop(struct flasher_type *, int); // idb
+void __thiscall TLight::Reset(TLight *__hidden this); // idb
+void __stdcall TLight::TimerExpired(int, void *); // idb
+void __thiscall TLight::schedule_timeout(TLight *this, float); // idb
+int __thiscall TLight::Message(TLight *this, int, float); // idb
+TZmapList *__thiscall TLightGroup::~TLightGroup(TLightGroup *this);
+void __thiscall TLightGroup::Reset(TLightGroup *__hidden this); // idb
+void __stdcall TLightGroup::TimerExpired(int, void *); // idb
+void __thiscall TLightGroup::reschedule_animation(TLightGroup *this, float); // idb
+int __thiscall TLightGroup::next_light_up(TLightGroup *__hidden this); // idb
+int __thiscall TLightGroup::next_light_down(TLightGroup *__hidden this); // idb
+void __thiscall TLightGroup::start_animation(TLightGroup *__hidden this); // idb
+void __stdcall TLightGroup::NotifyTimerExpired(int, void *); // idb
+int __thiscall TLightGroup::Message(TLightGroup *this, int, float); // idb
+TZmapList *__thiscall TLightBargraph::~TLightBargraph(TLightBargraph *this);
+void __thiscall TLightBargraph::Reset(TLightBargraph *this); // idb
+void __stdcall TLightBargraph::BargraphTimerExpired(int, void *); // idb
+int __thiscall TLightBargraph::Message(TLightBargraph *this, int, float); // idb
+void __thiscall objlist_class::Add(objlist_class *this, void *); // idb
+TLight *__thiscall TLight::TLight(TLight *this, struct TPinballTable *a2, int a3);
+TSound *__thiscall TSound::`vector deleting destructor'(TSound *this, char a2);
+TLightGroup *__thiscall TLightGroup::TLightGroup(TLightGroup *this, struct TPinballTable *a2, int a3);
+TLightGroup *__thiscall TLightGroup::`vector deleting destructor'(TLightGroup *this, char a2);
+TLightBargraph *__thiscall TLightBargraph::TLightBargraph(TLightBargraph *this, struct TPinballTable *a2, int a3);
+TLightBargraph *__thiscall TLightBargraph::`vector deleting destructor'(TLightBargraph *this, char a2);
+int __stdcall midi_music_init(HWND a1);
+MCIERROR __stdcall midi_music_shutdown();
+MCIERROR __stdcall midi_music_stop();
+MCIERROR __stdcall midi_play_pb_theme(int a1);
+HWND __stdcall restart_midi_seq(int a1);
+bool __thiscall TBall::already_hit(TBall *this, struct TEdgeSegment *a2);
+TEdgeBox *__thiscall TEdgeBox::TEdgeBox(TEdgeBox *this);
+signed __int64 __thiscall TEdgeManager::box_x(TEdgeManager *this, float a2);
+signed __int64 __thiscall TEdgeManager::box_y(TEdgeManager *this, float a2);
+int __thiscall TEdgeManager::increment_box_x(TEdgeManager *this, int); // idb
+int __thiscall TEdgeManager::increment_box_y(TEdgeManager *this, int); // idb
+void __stdcall `vector constructor iterator'(void *, unsigned int, int, void *(__thiscall *)(void *)); // idb
+void __thiscall TEdgeBox::~TEdgeBox(TEdgeBox *this);
+void __stdcall `vector destructor iterator'(void *, unsigned int, int, void (__thiscall *)(void *)); // idb
+void __thiscall TEdgeManager::FieldEffects(TEdgeManager *this, struct TBall *, struct vector_type *); // idb
+// int __userpurge TEdgeManager::TestGridBox@(TEdgeManager *this@, double a2@, int a3, int a4, float *a5, struct TEdgeSegment **a6, struct ray_type *a7, struct TBall *a8, int a9);
+double __thiscall TEdgeManager::FindCollisionDistance(TEdgeManager *this, struct ray_type *a2, struct TBall *a3, struct TEdgeSegment **a4);
+TEdgeManager *__thiscall TEdgeManager::TEdgeManager(TEdgeManager *this, float a2, float a3, float a4, float a5);
+TEdgeBox *__thiscall TEdgeBox::`vector deleting destructor'(TEdgeBox *this, char a2);
+void __thiscall TEdgeManager::add_edge_to_box(TEdgeManager *this, int, int, struct TEdgeSegment *); // idb
+void __thiscall TEdgeManager::add_field_to_box(TEdgeManager *this, int, int, struct field_effect_type *); // idb
+TEdgeBox *__thiscall TEdgeManager::~TEdgeManager(TEdgeManager *this);
+void __stdcall edges_insert_circle(struct circle_type *, struct TEdgeSegment *, struct field_effect_type *); // idb
+void __stdcall edges_insert_square(float, float, float, float, struct TEdgeSegment *, struct field_effect_type *); // idb
+struct TPinballComponent *__stdcall make_component_link(struct component_tag *); // idb
+void __stdcall control_make_links(struct TPinballTable *); // idb
+BOOL __stdcall light_on(struct component_tag *a1);
+void __stdcall table_control_handler(int); // idb
+// void __userpurge table_set_replay(int a1@, float a2);
+// void __usercall table_set_multiball(int a1@);
+// void __usercall table_set_jackpot(int a1@);
+// void __usercall table_set_bonus(int a1@);
+// void __usercall table_set_flag_lights(int a1@);
+// void __usercall table_set_bonus_hold(int a1@);
+// void __usercall table_bump_ball_sink_lock(int a1@);
+// void __userpurge table_add_extra_ball(int a1@, float a2);
+int __stdcall SpecialAddScore(int); // idb
+void __stdcall AdvanceWormHoleDestination(int); // idb
+void __stdcall FlipperRebounderControl1(int, struct TPinballComponent *); // idb
+void __stdcall FlipperRebounderControl2(int, struct TPinballComponent *); // idb
+void __stdcall RebounderControl(int, struct TPinballComponent *); // idb
+void __stdcall BumperControl(int, struct TPinballComponent *); // idb
+void __stdcall LeftKickerControl(int, struct TPinballComponent *); // idb
+void __stdcall RightKickerControl(int, struct TPinballComponent *); // idb
+void __stdcall LeftKickerGateControl(int, struct TPinballComponent *); // idb
+void __stdcall RightKickerGateControl(int, struct TPinballComponent *); // idb
+// void __userpurge DeploymentChuteToEscapeChuteOneWayControl(int a1@, int a2@, int a3, struct TPinballComponent *a4);
+void __stdcall DeploymentChuteToTableOneWayControl(int, struct TPinballComponent *); // idb
+void __stdcall DrainBallBlockerControl(int, struct TPinballComponent *); // idb
+// void __userpurge LaunchRampControl(int a1@, int a2, struct TPinballComponent *a3);
+void __stdcall LaunchRampHoleControl(int, struct TPinballComponent *); // idb
+void __stdcall SpaceWarpRolloverControl(int, struct TPinballComponent *); // idb
+// void __userpurge ReentryLanesRolloverControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5);
+void __stdcall BumperGroupControl(int, struct TPinballComponent *); // idb
+// void __userpurge LaunchLanesRolloverControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5);
+// void __userpurge OutLaneRolloverControl(int a1@, int a2@, int a3, struct TPinballComponent *a4);
+void __stdcall ExtraBallLightControl(int, struct TPinballComponent *); // idb
+// void __userpurge ReturnLaneRolloverControl(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge BonusLaneRolloverControl(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge FuelRollover1Control(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge FuelRollover2Control(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge FuelRollover3Control(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge FuelRollover4Control(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge FuelRollover5Control(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge FuelRollover6Control(int a1@, int a2, struct TPinballComponent *a3);
+void __stdcall HyperspaceLightGroupControl(int, struct TPinballComponent *); // idb
+// void __userpurge WormHoleControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5);
+void __stdcall LeftFlipperControl(int, struct TPinballComponent *); // idb
+void __stdcall RightFlipperControl(int, struct TPinballComponent *); // idb
+void __stdcall JackpotLightControl(int, struct TPinballComponent *); // idb
+void __stdcall BonusLightControl(int, struct TPinballComponent *); // idb
+void __stdcall BoosterTargetControl(int, struct TPinballComponent *); // idb
+void __stdcall MedalLightGroupControl(int, struct TPinballComponent *); // idb
+// void __userpurge MultiplierLightGroupControl(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge FuelSpotTargetControl(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MissionSpotTargetControl(int a1@, int a2, struct TPinballComponent *a3);
+void __stdcall LeftHazardSpotTargetControl(int, struct TPinballComponent *); // idb
+void __stdcall RightHazardSpotTargetControl(int, struct TPinballComponent *); // idb
+// void __userpurge WormHoleDestinationControl(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge BlackHoleKickoutControl(int a1@, int a2, struct TPinballComponent *a3);
+void __stdcall FlagControl(int, struct TPinballComponent *); // idb
+// void __userpurge GravityWellKickoutControl(int a1@, int a2, struct TPinballComponent *a3);
+void __stdcall SkillShotGate1Control(int, struct TPinballComponent *); // idb
+void __stdcall SkillShotGate2Control(int, struct TPinballComponent *); // idb
+void __stdcall SkillShotGate3Control(int, struct TPinballComponent *); // idb
+void __stdcall SkillShotGate4Control(int, struct TPinballComponent *); // idb
+void __stdcall SkillShotGate5Control(int, struct TPinballComponent *); // idb
+void __stdcall SkillShotGate6Control(int, struct TPinballComponent *); // idb
+void __stdcall ShootAgainLightControl(int, struct TPinballComponent *); // idb
+void __stdcall EscapeChuteSinkControl(int, struct TPinballComponent *); // idb
+// int __usercall cheat_bump_rank@(int a1@);
+// void __userpurge pbctrl_bdoor_controller(int a1@, int a2);
+int __stdcall AddRankProgress(int); // idb
+// void __userpurge WaitingDeploymentController(int a1@, int a2, struct TPinballComponent *a3);
+void __stdcall SelectMissionController(int, struct TPinballComponent *); // idb
+// void __userpurge PracticeMissionController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge LaunchTrainingController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge ReentryTrainingController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge ScienceMissionController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge StrayCometController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge SpaceRadiationController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge BlackHoleThreatController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge BugHuntController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge RescueMissionController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge AlienMenaceController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge AlienMenacePartTwoController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge SatelliteController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge ReconnaissanceController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge DoomsdayMachineController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge CosmicPlagueController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge CosmicPlaguePartTwoController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge SecretMissionYellowController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge SecretMissionRedController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge SecretMissionGreenController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge TimeWarpController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge TimeWarpPartTwoController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MaelstromController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MaelstromPartTwoController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MaelstromPartThreeController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MaelstromPartFourController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MaelstromPartFiveController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MaelstromPartSixController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MaelstromPartSevenController(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MaelstromPartEightController(int a1@, int a2, struct TPinballComponent *a3);
+void __stdcall GameoverController(int, struct TPinballComponent *); // idb
+void __stdcall UnselectMissionController(int, struct TPinballComponent *); // idb
+void __stdcall MissionControl(int, struct TPinballComponent *); // idb
+void __stdcall control_handler(int, struct TPinballComponent *); // idb
+void __stdcall HyperspaceKickOutControl(int, struct TPinballComponent *); // idb
+// void __userpurge PlungerControl(int a1@, int a2, struct TPinballComponent *a3);
+// void __userpurge MedalTargetControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5);
+// void __userpurge MultiplierTargetControl(int a1@, int a2@, int a3@, int a4, struct TPinballComponent *a5);
+void __stdcall BallDrainControl(int, struct TPinballComponent *); // idb
+int __stdcall objlist_add_object(_DWORD *a1, int a2);
+signed int __stdcall objlist_delete_object(int a1, int a2);
+_DWORD *__stdcall objlist_new(int a1);
+int *__stdcall objlist_grow(int *a1, int a2);
+void __stdcall build_occlude_list();
+void __stdcall render_repaint(struct render_sprite_type_struct *); // idb
+void __stdcall render_paint_balls(); // idb
+void __stdcall render_unpaint_balls(); // idb
+int __stdcall render_remove_sprite(struct render_sprite_type_struct *); // idb
+int __stdcall render_remove_ball(struct render_sprite_type_struct *); // idb
+BOOL __stdcall overlapping_box(struct rectangle_type *a1, struct rectangle_type *a2, struct rectangle_type *a3);
+void __stdcall render_update();
+void __stdcall render_uninit();
+char *__stdcall render_init(_DWORD *a1, float a2, float a3, int a4, int a5);
+int __stdcall render_sprite_modified(int a1);
+int __stdcall render_create_sprite(int a1, int a2, int a3, int a4, int a5, _DWORD *a6);
+int __stdcall render_set_background_zmap(struct zmap_header_type *a1, int a2, int a3);
+int __stdcall render_sprite_set(_DWORD *a1, int a2, int a3, int a4, int a5);
+void __stdcall render_sprite_set_bitmap(_DWORD *a1, int a2);
+void __stdcall render_ball_set(int a1, int a2, float a3, int a4, int a5);
+void __stdcall render_paint();
+void __stdcall render_shift(int a1, int a2, int xSrc, int a4, int DestWidth, int DestHeight);
+TTextBoxMessage *__thiscall TTextBoxMessage::TTextBoxMessage(TTextBoxMessage *this, char *a2, float a3);
+double __thiscall TTextBoxMessage::TimeLeft(TTextBoxMessage *this);
+void __thiscall TTextBoxMessage::Refresh(TTextBoxMessage *this, float); // idb
+_DWORD *__stdcall score_create(LPCSTR lpString, int a2);
+void *__stdcall score_dup(const void *a1, int a2);
+void __stdcall objlist_destroy(int a1);
+_DWORD *__stdcall score_set(_DWORD *a1, int a2);
+// void *__userpurge score_erase@(int a1@, _DWORD *a2, int a3);
+// HDC __userpurge score_update@(int a1@, int *a2);
+signed int __stdcall score_init();
+void __stdcall score_unload_msg_font();
+HRSRC __stdcall score_load_msg_font(LPCSTR lpName);
+TTextBox *__thiscall TTextBox::TTextBox(TTextBox *this, struct TPinballTable *a2, int a3);
+TTextBoxMessage *__thiscall TTextBoxMessage::`scalar deleting destructor'(TTextBoxMessage *this, char a2);
+// void __usercall TTextBox::Clear(TTextBox *this@, int a2@);
+// void __userpurge TTextBox::TimerExpired(int a1@, int a2, TTextBox *a3);
+TZmapList *__thiscall TTextBox::~TTextBox(TTextBox *this);
+// void __usercall TTextBox::Draw(TTextBox *this@, int a2@);
+// void __userpurge TTextBox::Display(TTextBox *this@, int a2@, char *a3, float a4);
+TTextBox *__thiscall TTextBox::`scalar deleting destructor'(TTextBox *this, char a2);
+void *__stdcall TPinballComponent::operator new(size_t SizeOfElements); // idb
+_DWORD __stdcall pb_paint(); // idb
+signed int __stdcall pb_mode_change(int a1);
+signed int __stdcall pb_mode_countdown(int a1);
+int __stdcall pb_end_game();
+signed int __stdcall pb_chk_highscore();
+long double __stdcall pb_collide(struct TEdgeSegment *a1, float a2, struct TBall *a3);
+void __stdcall pb_timed_frame(float, float, int); // idb
+// signed int __userpurge pb_frame@(int a1@, int a2);
+void __stdcall pb_firsttime_setup();
+// struct TPinballTable *__usercall pb_tilt_no_more@(int a1@);
+void __stdcall pb_ballset(signed int a1, signed int a2);
+void __stdcall nudge(float, float); // idb
+void __stdcall un_nudge_left(int, void *); // idb
+void __stdcall un_nudge_right(int, void *); // idb
+void __stdcall nudge_left(); // idb
+void __stdcall nudge_right(); // idb
+void __stdcall un_nudge_up(int, void *); // idb
+void __stdcall nudge_up(); // idb
+void __stdcall pb_keydown(HKEY a1);
+void __stdcall pb_keyup(HKEY a1);
+int __stdcall pb_replay_level(int a1);
+INT_PTR __stdcall pb_high_scores();
+_DWORD *__stdcall pb_window_size(_DWORD *a1, _DWORD *a2);
+int __stdcall pb_init();
+int __stdcall pb_uninit();
+int __stdcall pb_loose_focus();
+// void __usercall pb_pause_continue(int a1@);
+int __stdcall pb_launch_ball();
+int __stdcall pb_reset_table();
+// void __usercall pb_toggle_demo(int a1@);
+TEdgeSegment *__thiscall TEdgeSegment::TEdgeSegment(TEdgeSegment *this, struct TCollisionComponent *a2, char *a3, unsigned int a4);
+_DWORD __stdcall gdrv_get_focus(); // idb
+TCircle *__thiscall TCircle::TCircle(TCircle *this, struct TCollisionComponent *a2, char *a3, unsigned int a4, struct vector_type *a5, float a6);
+double __thiscall TCircle::FindCollisionDistance(TCircle *this, struct ray_type *a2);
+TZmapList *__thiscall TZmapList::TZmapList(TZmapList *this, int a2, int a3);
+void __thiscall TBall::not_again(TBall *this, struct TEdgeSegment *); // idb
+void __stdcall throw_ball(struct TBall *, struct vector_type *, float, float, float); // idb
+int __thiscall TPinballComponent::Message(TPinballComponent *this, int, float); // idb
+int __stdcall TPinballComponent::get_scoring(int a2);
+void __stdcall TComponentGroup::NotifyTimerExpired(int, struct TPinballComponent *); // idb
+int __thiscall TComponentGroup::Message(TComponentGroup *this, int, float); // idb
+void __thiscall TCollisionComponent::port_draw(TCollisionComponent *__hidden this); // idb
+void __stdcall TWall::TimerExpired(int, void *); // idb
+int __thiscall TWall::Message(TWall *this, int, float); // idb
+int __thiscall TWall::get_scoring(TWall *this, int); // idb
+void __thiscall TWall::put_scoring(TWall *this, int, int); // idb
+int __thiscall TOneway::get_scoring(TOneway *this, int); // idb
+void __thiscall TOneway::put_scoring(TOneway *this, int, int); // idb
+int __thiscall TBall::Message(TBall *this, int, float); // idb
+void __thiscall TBall::Repaint(TBall *__hidden this); // idb
+void __stdcall TBumper::TimerExpired(int, void *); // idb
+void __thiscall TBumper::Fire(TBumper *this); // idb
+int __thiscall TBumper::Message(TBumper *this, int, float); // idb
+int __thiscall TBumper::get_scoring(TBumper *this, int); // idb
+void __thiscall TBumper::put_scoring(TBumper *this, int, int); // idb
+void __stdcall TFlagSpinner::SpinTimer(int, void *); // idb
+void __thiscall TFlagSpinner::NextFrame(TFlagSpinner *this); // idb
+int __thiscall TFlagSpinner::Message(TFlagSpinner *this, int, float); // idb
+int __thiscall TFlagSpinner::get_scoring(TFlagSpinner *this, int); // idb
+void __thiscall TFlagSpinner::put_scoring(TFlagSpinner *this, int, int); // idb
+void __stdcall TPopupTarget::TimerExpired(int, void *); // idb
+int __thiscall TPopupTarget::Message(TPopupTarget *this, int, float); // idb
+int __thiscall TPopupTarget::get_scoring(TPopupTarget *this, int); // idb
+void __thiscall TPopupTarget::put_scoring(TPopupTarget *this, int, int); // idb
+void __stdcall TSoloTarget::TimerExpired(int, void *); // idb
+int __thiscall TSoloTarget::Message(TSoloTarget *this, int, float); // idb
+int __thiscall TSoloTarget::get_scoring(TSoloTarget *this, int); // idb
+void __thiscall TSoloTarget::put_scoring(TSoloTarget *this, int, int); // idb
+void __stdcall TBlocker::TimerExpired(int, struct TPinballComponent *); // idb
+int __thiscall TBlocker::Message(TBlocker *this, int, float); // idb
+int __thiscall TGate::Message(TGate *this, int, float); // idb
+void __stdcall TRollover::TimerExpired(int, void *); // idb
+int __thiscall TRollover::Message(TRollover *this, int, float); // idb
+int __thiscall TRollover::get_scoring(TRollover *this, int); // idb
+void __thiscall TRollover::put_scoring(TRollover *this, int, int); // idb
+void __stdcall TLightRollover::delay_expired(int, void *); // idb
+void __thiscall TLightRollover::Collision(TLightRollover *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+int __thiscall TLightRollover::Message(TLightRollover *this, int, float); // idb
+void __thiscall TTripwire::Collision(TTripwire *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __stdcall TKickback::TimerExpired(int, struct TPinballComponent *); // idb
+int __thiscall TKickback::Message(TKickback *this, int, float); // idb
+void __thiscall TKickout::Collision(TKickout *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __stdcall TKickout::ResetTimerExpired(int, void *); // idb
+void __stdcall TKickout::TimerExpired(int, void *); // idb
+int __thiscall TKickout::FieldEffect(TKickout *this, struct TBall *, struct vector_type *); // idb
+int __thiscall TKickout::Message(TKickout *this, int, float); // idb
+int __thiscall TKickout::get_scoring(TKickout *this, int); // idb
+void __thiscall TKickout::put_scoring(TKickout *this, int, int); // idb
+void __stdcall THole::TimerExpired(int, void *); // idb
+int __thiscall THole::FieldEffect(THole *this, struct TBall *, struct vector_type *); // idb
+int __thiscall THole::Message(THole *this, int, float); // idb
+int __thiscall TRamp::get_scoring(TRamp *this, int); // idb
+void __thiscall TRamp::put_scoring(TRamp *this, int, int); // idb
+void __stdcall find_closest_edge(struct ramp_plane_type *, int, struct wall_point_type *, struct vector_type **, struct vector_type **); // idb
+void __thiscall TRamp::Collision(TRamp *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+int __thiscall TRamp::FieldEffect(TRamp *this, struct TBall *, struct vector_type *); // idb
+void __stdcall TDemo::PlungerRelease(int, void *); // idb
+void __stdcall TDemo::UnFlipRight(int, void *); // idb
+void __stdcall TDemo::UnFlipLeft(int, void *); // idb
+void __stdcall TDemo::FlipRight(int, void *); // idb
+void __stdcall TDemo::FlipLeft(int, void *); // idb
+void __stdcall TDemo::NewGameRestartTimer(int, void *); // idb
+void __thiscall TDemo::Collision(TDemo *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+int __thiscall TDemo::Message(TDemo *this, int, float); // idb
+void __stdcall TSink::TimerExpired(int, void *); // idb
+int __thiscall TSink::Message(TSink *this, int, float); // idb
+int __thiscall TSink::get_scoring(TSink *this, int); // idb
+void __thiscall TSink::put_scoring(TSink *this, int, int); // idb
+int __thiscall TDrain::Message(TDrain *this, int, float); // idb
+void __stdcall TDrain::TimerCallback(int, struct TPinballComponent *); // idb
+void __stdcall TPlunger::BallFeedTimer(int, void *); // idb
+void __stdcall TPlunger::PullbackTimer(int, void *); // idb
+void __stdcall TPlunger::PlungerReleasedTimer(int, void *); // idb
+int __thiscall TTableLayer::FieldEffect(TTableLayer *this, struct TBall *, struct vector_type *); // idb
+TEdgeManager *__thiscall TEdgeManager::`scalar deleting destructor'(TEdgeManager *this, char a2);
+void __stdcall TPinballTable::LightShow_timeout(int, void *); // idb
+void __stdcall TPinballTable::EndGame_timeout(int, void *); // idb
+int __thiscall TPinballTable::AddScore(TPinballTable *this, int); // idb
+// void __userpurge TPinballTable::ChangeBallCount(TPinballTable *this@, int a2@, int a3);
+void __stdcall TPinballTable::replay_timer_callback(int, void *); // idb
+void __thiscall TPinballTable::port_draw(TPinballTable *__hidden this); // idb
+struct TPinballComponent *__thiscall TPinballTable::find_component(TPinballTable *this, char *); // idb
+struct TPinballComponent *__thiscall TPinballTable::find_component(TPinballTable *this, int); // idb
+void __stdcall TPinballTable::tilt_timeout(int, void *); // idb
+// void __userpurge TPinballTable::tilt(TPinballTable *this@, int a2@, float a3);
+double __stdcall basic_collision(struct TBall *a1, struct vector_type *a2, struct vector_type *a3, float a4, float a5, float a6, float a7);
+double __thiscall TSound::Play(TSound *this);
+void __stdcall TTimer::TimerExpired(int, struct TPinballComponent *); // idb
+struct TEdgeSegment *__stdcall install_wall(float *, struct TCollisionComponent *, char *, unsigned int, float, void *); // idb
+TPinballComponent *__thiscall TPinballComponent::TPinballComponent(TPinballComponent *this, struct TPinballTable *a2, int a3, int a4);
+TZmapList *__thiscall TZmapList::`scalar deleting destructor'(TZmapList *this, char a2);
+void __thiscall TCollisionComponent::Collision(TCollisionComponent *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+int __thiscall TCollisionComponent::DefaultCollision(TCollisionComponent *this, struct TBall *, struct vector_type *, struct vector_type *); // idb
+void __thiscall TWall::Collision(TWall *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall TOneway::Collision(TOneway *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall TBumper::Collision(TBumper *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall TFlagSpinner::Collision(TFlagSpinner *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall TPopupTarget::Collision(TPopupTarget *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall TSoloTarget::Collision(TSoloTarget *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall TRollover::build_walls(TRollover *this, int); // idb
+void __thiscall TRollover::Collision(TRollover *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall TKickback::Collision(TKickback *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall THole::Collision(THole *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall TSink::Collision(TSink *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+void __thiscall TDrain::Collision(TDrain *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+int __thiscall TPlunger::Message(TPlunger *this, int, float); // idb
+void __thiscall TPlunger::Collision(TPlunger *this, struct TBall *, struct vector_type *, struct vector_type *, float, struct TEdgeSegment *); // idb
+// int __userpurge TPinballTable::Message@(TPinballTable *this@, int a2@, int a3, float a4);
+int __thiscall TTimer::Message(TTimer *this, int, float); // idb
+TZmapList *__thiscall TPinballComponent::~TPinballComponent(TPinballComponent *this);
+TComponentGroup *__thiscall TComponentGroup::TComponentGroup(TComponentGroup *this, struct TPinballTable *a2, int a3);
+TZmapList *__thiscall TComponentGroup::~TComponentGroup(TComponentGroup *this);
+TCollisionComponent *__thiscall TCollisionComponent::TCollisionComponent(TCollisionComponent *this, struct TPinballTable *a2, int a3, int a4);
+int __stdcall TTextBox::Message(int a2, float a3);
+TZmapList *__thiscall TCollisionComponent::~TCollisionComponent(TCollisionComponent *this);
+TWall *__thiscall TWall::TWall(TWall *this, struct TPinballTable *a2, int a3);
+TOneway *__thiscall TOneway::TOneway(TOneway *this, struct TPinballTable *a2, int a3);
+TBall *__thiscall TBall::TBall(TBall *this, struct TPinballTable *a2);
+TBumper *__thiscall TBumper::TBumper(TBumper *this, struct TPinballTable *a2, int a3);
+TFlagSpinner *__thiscall TFlagSpinner::TFlagSpinner(TFlagSpinner *this, struct TPinballTable *a2, int a3);
+TPopupTarget *__thiscall TPopupTarget::TPopupTarget(TPopupTarget *this, struct TPinballTable *a2, int a3);
+TSoloTarget *__thiscall TSoloTarget::TSoloTarget(TSoloTarget *this, struct TPinballTable *a2, int a3);
+TBlocker *__thiscall TBlocker::TBlocker(TBlocker *this, struct TPinballTable *a2, int a3);
+TGate *__thiscall TGate::TGate(TGate *this, struct TPinballTable *a2, int a3);
+TRollover *__thiscall TRollover::TRollover(TRollover *this, struct TPinballTable *a2, int a3, int a4);
+TRollover *__thiscall TRollover::TRollover(TRollover *this, struct TPinballTable *a2, int a3);
+TLightRollover *__thiscall TLightRollover::TLightRollover(TLightRollover *this, struct TPinballTable *a2, int a3);
+TTripwire *__thiscall TTripwire::TTripwire(TTripwire *this, struct TPinballTable *a2, int a3);
+TKickback *__thiscall TKickback::TKickback(TKickback *this, struct TPinballTable *a2, int a3);
+TKickout *__thiscall TKickout::TKickout(TKickout *this, struct TPinballTable *a2, int a3, struct vector_type *a4);
+THole *__thiscall THole::THole(THole *this, struct TPinballTable *a2, int a3);
+TRamp *__thiscall TRamp::TRamp(TRamp *this, struct TPinballTable *a2, void *a3);
+TDemo *__thiscall TDemo::TDemo(TDemo *this, struct TPinballTable *a2, int a3);
+TSink *__thiscall TSink::TSink(TSink *this, struct TPinballTable *a2, int a3);
+TDrain *__thiscall TDrain::TDrain(TDrain *this, struct TPinballTable *a2, int a3);
+TPlunger *__thiscall TPlunger::TPlunger(TPlunger *this, struct TPinballTable *a2, int a3);
+TTableLayer *__thiscall TTableLayer::TTableLayer(TTableLayer *this, struct TPinballTable *a2);
+TZmapList *__thiscall TTableLayer::~TTableLayer(TTableLayer *this);
+TZmapList *__thiscall TPinballTable::~TPinballTable(TPinballTable *this);
+TPinballTable *__thiscall TPinballTable::`vector deleting destructor'(TPinballTable *this, char a2);
+TSound *__thiscall TSound::TSound(TSound *this, struct TPinballTable *a2, int a3);
+TTimer *__thiscall TTimer::TTimer(TTimer *this, struct TPinballTable *a2, int a3);
+TComponentGroup *__thiscall TComponentGroup::`scalar deleting destructor'(TComponentGroup *this, char a2);
+TOneway *__thiscall TOneway::`scalar deleting destructor'(TOneway *this, char a2);
+TTableLayer *__thiscall TTableLayer::`scalar deleting destructor'(TTableLayer *this, char a2);
+TPinballTable *__thiscall TPinballTable::TPinballTable(TPinballTable *this);
+void __stdcall vswap(struct vector_type *, struct vector_type *); // idb
+void __thiscall TFlipperEdge::place_in_grid(TFlipperEdge *this); // idb
+double __thiscall TFlipperEdge::flipper_angle(TFlipperEdge *this, float a2);
+void __thiscall TFlipperEdge::build_edges_in_motion(TFlipperEdge *__hidden this); // idb
+void __thiscall TFlipperEdge::set_control_points(TFlipperEdge *this, float); // idb
+double __stdcall distance_to_flipper(struct ray_type *a1, struct ray_type *a2);
+int __thiscall TFlipperEdge::is_ball_inside(TFlipperEdge *this, float, float); // idb
+double __thiscall TFlipperEdge::FindCollisionDistance(TFlipperEdge *this, struct ray_type *a2);
+void __thiscall TFlipperEdge::EdgeCollision(TFlipperEdge *this, struct TBall *, float); // idb
+void __thiscall TFlipperEdge::SetMotion(TFlipperEdge *this, int, float); // idb
+void __thiscall TFlipperEdge::port_draw(TFlipperEdge *this); // idb
+TZmapList *__thiscall TFlipper::~TFlipper(TFlipper *this);
+void __stdcall TFlipper::TimerExpired(int, void *); // idb
+int __thiscall TFlipper::Message(TFlipper *this, int, float); // idb
+void __thiscall TFlipper::port_draw(TFlipper *__hidden this); // idb
+TFlipperEdge *__thiscall TFlipperEdge::TFlipperEdge(TFlipperEdge *this, struct TCollisionComponent *a2, char *a3, unsigned int a4, struct TPinballTable *a5, struct vector_type *a6, struct vector_type *a7, struct vector_type *a8, float a9, float a10, float a11, float a12, float a13);
+TFlipper *__thiscall TFlipper::TFlipper(TFlipper *this, struct TPinballTable *a2, int a3);
+TFlipper *__thiscall TFlipper::`vector deleting destructor'(TFlipper *this, char a2);
+TLine *__thiscall TLine::TLine(TLine *this, struct TCollisionComponent *a2, char *a3, unsigned int a4, float a5, float a6, float a7, float a8);
+double __thiscall TLine::FindCollisionDistance(TLine *this, struct ray_type *a2);
+TLine *__thiscall TLine::TLine(TLine *this, struct TCollisionComponent *a2, char *a3, unsigned int a4, struct vector_type *a5, struct vector_type *a6);
+void __thiscall TLine::EdgeCollision(TLine *this, struct TBall *, float); // idb
+void __thiscall TLine::Offset(TLine *this, float); // idb
+void __thiscall TLine::place_in_grid(TLine *this); // idb
+void __thiscall TCircle::place_in_grid(TCircle *this); // idb
+void __stdcall vector_add(struct vector_type *, struct vector_type *); // idb
+void __stdcall RotatePt(struct vector_type *, float, float, struct vector_type *); // idb
+long double __stdcall Distance(struct vector_type *a1, struct vector_type *a2);
+double __stdcall Distance_Squared(float a1, float a2, int a3, float a4, float a5, int a6);
+double __stdcall DotProduct(const struct vector_type *a1, const struct vector_type *a2);
+void __stdcall SinCos(float, float *, float *); // idb
+void __thiscall TCircle::EdgeCollision(TCircle *this, struct TBall *, float); // idb
+void __stdcall RotateVector(struct vector_type *, float); // idb
+int __security_init_cookie();
+// BOOL __usercall __noreturn __report_gsfailure@(int a1@, int a2@, int a3@, int a4@, int a5@, int a6@);
+int __stdcall sub_101CEB6(LPBYTE lpData); // idb
+HWND __stdcall HtmlHelpA(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData);
+_WORD *__stdcall SessionToGlobalDataPtr(_WORD *a1);
+BOOL __stdcall IsValidLPMIXWAVE(int a1);
+bool __stdcall HasCurrentOutputFormat(const void *a1);
+int __stdcall DefaultPauseBlocks(int a1);
+unsigned int __stdcall DefaultGoodWavePos(UINT_PTR uDeviceID);
+DWORD __stdcall MyWaveOutGetPosition(HWAVEOUT hwo, int a2);
+int __stdcall AddFactor(int a1, int a2);
+int __stdcall SubFactor(int a1, int a2);
+unsigned int __stdcall SetWaveOutPosition(unsigned int a1);
+unsigned int __stdcall MyWaveOutReset(HWAVEOUT hwo);
+__int16 __stdcall cmixit(_BYTE *a1, char *a2, char *a3, int a4, unsigned __int16 a5);
+_DWORD *__stdcall InitChannelNodes();
+int __stdcall GetChannelNode();
+_DWORD *__stdcall FreeChannelNode(_DWORD *a1);
+struct wavehdr_tag *__stdcall FreeWaveBlocks(HWAVEOUT hwo, int a2);
+int __stdcall AllocWaveBlocks(HWAVEOUT hwo, int); // idb
+_DWORD *__stdcall SwapWaveBlocks();
+_DWORD *__stdcall GetWaveBlock();
+struct wavehdr_tag *__stdcall RemoveFromPlayingQueue(struct wavehdr_tag *a1);
+LPWAVEHDR __stdcall DestroyPlayQueue();
+int __stdcall ReleaseWaveDevice(int a1);
+signed int __stdcall GetWaveDevice();
+signed int __stdcall WaveMixOpenChannel(_WORD *a1, signed int a2, unsigned int a3);
+LPWAVEHDR __stdcall AddToPlayingQueue(struct wavehdr_tag *a1);
+int __stdcall MixerPlay(LPWAVEHDR pwh, int); // idb
+DWORD __stdcall FreePlayedBlocks();
+int __stdcall WaveMixPump();
+LRESULT __stdcall WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+signed int __stdcall NoResetRemix(int a1, int a2);
+signed int __stdcall ResetRemix(int a1, int a2);
+void __stdcall ResetWavePosIfNoChannelData();
+signed int __stdcall WaveMixPlay(int a1);
+signed int __stdcall WaveMixFlushChannel(_WORD *a1, signed int a2, char a3);
+signed int __stdcall WaveMixCloseChannel(_WORD *a1, signed int a2, char a3);
+int __stdcall WaveMixFreeWave(int, LPCVOID pMem); // idb
+// _WORD *__userpurge BitsPerSampleAlign@(int a1@, LPCVOID pMem, int a3, __int16 a4, int a5);
+_BYTE *__stdcall ChannelAlign(LPCVOID pMem, __int16 a2, __int16 a3, __int16 a4, int a5);
+void __stdcall AvgSample(_WORD *a1, unsigned __int8 *a2, int a3, int a4, int a5);
+int __stdcall RepSample(_BYTE *a1, unsigned __int8 *a2, signed int a3, int a4, int a5);
+LPCVOID __stdcall SamplesPerSecAlign(LPCVOID pMem, int a2, int a3, __int16 a4, __int16 a5, int a6);
+LPCVOID __stdcall WaveFormatConvert(int a1, int a2, LPCVOID pMem, int a4);
+CHAR *__stdcall WaveMixOpenWave(LPCVOID pMem, LPCSTR lpName, HMODULE hModule, LONG cch);
+unsigned int __stdcall FigureOutDMABufferSize(unsigned int a1, int a2);
+int __stdcall RemoveInvalidIniNameCharacters(LPCSTR lpString); // idb
+UINT __stdcall ShowWaveOutDevices();
+const char *__stdcall GetOperatingSystemPrefix();
+int __stdcall ReadRegistryToGetMachineSpecificInfSection(int, LPSTR lpString1, int); // idb
+int __stdcall ReadRegistryInt(HKEY hKey, LPCSTR lpSubKey, int); // idb
+signed int __stdcall ReadRegistryForAppSpecificConfigs(int a1);
+int __stdcall ShowCurrentSettings();
+int __stdcall Settings_OnInitDialog(HWND hWnd, int, int); // idb
+int __stdcall Settings_OnCommand(HWND hWnd, int, int, int); // idb
+BOOL __stdcall SettingsDlgProc(HWND, UINT, WPARAM, LPARAM); // idb
+_DWORD *__stdcall MakeDlgTemplate(int a1, int a2, __int16 a3, __int16 a4, __int16 a5, __int16 a6, wchar_t *Str);
+_WORD *__stdcall AddDlgControl(int a1, LPCVOID pMem, __int16 a3, int a4, __int16 a5, __int16 a6, __int16 a7, __int16 a8, __int16 a9, wchar_t *Str);
+_WORD *__stdcall MakeSettingsDlgTemplate();
+void __stdcall DestroySettingsDlgTemplate(LPCVOID pMem);
+signed int __stdcall WaveMixGetConfig(_WORD *a1, int a2);
+BOOL __stdcall SaveConfigSettings(__int16 a1);
+DWORD __stdcall SetIniFileName(HMODULE hModule);
+int __stdcall InitVolumeTable();
+int __stdcall WaveMixStartup(HMODULE hModule); // idb
+signed int __stdcall WaveMixActivate(_WORD *a1, int a2);
+MMRESULT __stdcall WaveMixConfigure(int a1, HWND hWndParent, int a3, int a4, int a5);
+signed int __stdcall ReadConfigSettings(int a1);
+int __stdcall WaveMixConfigureInit(_WORD *a1);
+int __stdcall WaveMixInit();
+HLOCAL __stdcall WaveMixCloseSession(HLOCAL hMem);
+int WinMainCRTStartup();
+// void __cdecl operator delete(void *); idb
+// void *__cdecl operator new(unsigned int); idb
+// int __cdecl _initterm(_DWORD, _DWORD); weak
+unsigned int _setdefaultprecision();
+int __stdcall check_expiration_date();
+// unsigned int __cdecl _controlfp(unsigned int NewValue, unsigned int Mask);
+
+//-------------------------------------------------------------------------
+// Data declarations
+
+// extern _UNKNOWN __acmdln; weak
+// extern _UNKNOWN __adjust_fdiv; weak
+CHAR WindowName[2] = { '\0', '\0' }; // idb
+void *TLightBargraph::`vftable' = &TLightBargraph::Message; // weak
+void *TLight::`vftable' = &TLight::Message; // weak
+void *TLightGroup::`vftable' = &TLightGroup::Message; // weak
+void *TTextBox::`vftable' = &TTextBox::Message; // weak
+void *TEdgeSegment::`vftable' = &_purecall; // weak
+void *TCircle::`vftable' = &TCircle::EdgeCollision; // weak
+void *TPinballComponent::`vftable' = &TPinballComponent::Message; // weak
+void *TComponentGroup::`vftable' = &TComponentGroup::Message; // weak
+void *TCollisionComponent::`vftable' = &TPinballComponent::Message; // weak
+void *TWall::`vftable' = &TWall::Message; // weak
+void *TOneway::`vftable' = &TPinballComponent::Message; // weak
+void *TBall::`vftable' = &TBall::Message; // weak
+void *TBumper::`vftable' = &TBumper::Message; // weak
+void *TFlagSpinner::`vftable' = &TFlagSpinner::Message; // weak
+void *TPopupTarget::`vftable' = &TPopupTarget::Message; // weak
+void *TSoloTarget::`vftable' = &TSoloTarget::Message; // weak
+void *TBlocker::`vftable' = &TBlocker::Message; // weak
+void *TGate::`vftable' = &TGate::Message; // weak
+void *TRollover::`vftable' = &TRollover::Message; // weak
+void *TLightRollover::`vftable' = &TLightRollover::Message; // weak
+void *TTripwire::`vftable' = &TRollover::Message; // weak
+void *TKickback::`vftable' = &TKickback::Message; // weak
+void *TKickout::`vftable' = &TKickout::Message; // weak
+void *THole::`vftable' = &THole::Message; // weak
+void *TRamp::`vftable' = &TPinballComponent::Message; // weak
+void *TDemo::`vftable' = &TDemo::Message; // weak
+void *TSink::`vftable' = &TSink::Message; // weak
+void *TDrain::`vftable' = &TDrain::Message; // weak
+void *TPlunger::`vftable' = &TPlunger::Message; // weak
+void *TTableLayer::`vftable' = &TPinballComponent::Message; // weak
+void *TPinballTable::`vftable' = &TPinballTable::Message; // weak
+void *TSound::`vftable' = &TPinballComponent::Message; // weak
+void *TTimer::`vftable' = &TTimer::Message; // weak
+void *TFlipper::`vftable' = &TFlipper::Message; // weak
+void *TFlipperEdge::`vftable' = &TFlipperEdge::EdgeCollision; // weak
+void *TLine::`vftable' = &TLine::EdgeCollision; // weak
+int gpFormat[4] = { 65537, 11025, 11025, 524289 }; // weak
+_UNKNOWN __xc_a; // weak
+_UNKNOWN __xc_z; // weak
+_UNKNOWN __xi_a; // weak
+_UNKNOWN __xi_z; // weak
+int grtext_red = 4294967295; // weak
+int trick = 1; // weak
+LOGPALETTE current_palette = { 768u, 256u, { { 0u, 0u, 0u, 0u } } }; // idb
+_UNKNOWN unk_102305B; // weak
+PALETTEENTRY pPalEntries = { 0u, 0u, 0u, 0u }; // idb
+char byte_1023458 = '\0'; // weak
+char byte_1023459 = '\0'; // weak
+char byte_102345A = '\0'; // weak
+_UNKNOWN unk_102345F; // weak
+_UNKNOWN unk_1023460; // weak
+__int16 vk_list = 32833; // weak
+_UNKNOWN unk_1023540; // weak
+__int16 field_size[14] =
+ {
+ 2,
+ 65535,
+ 2,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 65535,
+ 0
+ }; // idb
+int LeftShift = 4294967295; // weak
+int RightShift = 4294967295; // weak
+int dword_10235F4 = 1; // weak
+int loader_errors[] = { 0 }; // weak
+char *off_10235FC[54] =
+ {
+ "Bad Handle",
+ (char *)1,
+ "No Type Field",
+ (char *)2,
+ "No Attributes Field",
+ (char *)0xB,
+ "No float Attributes Field",
+ (char *)3,
+ "Wrong Type: MATERIAL Expected",
+ (char *)4,
+ "Wrong Type: KICKER Expected",
+ (char *)5,
+ "Wrong Type: AN_OBJECT Expected",
+ (char *)6,
+ "Wrong Type: A_STATE Expected",
+ (char *)7,
+ "STATES (re)defined in a state",
+ (char *)9,
+ "Unrecognized Attribute",
+ (char *)0xA,
+ "Unrecognized float Attribute",
+ (char *)0xD,
+ "float Attribute not found",
+ (char *)0xC,
+ "state_index out of range",
+ (char *)0xF,
+ "loader_material() reports failure",
+ (char *)0xE,
+ "loader_kicker() reports failure",
+ (char *)0x10,
+ "loader_state_id() reports failure",
+ (char *)8,
+ "# walls doesn't match data size",
+ (char *)0x11,
+ "loader_query_visual_states()",
+ (char *)0x12,
+ "loader_query_visual()",
+ (char *)0x15,
+ "loader_material()",
+ (char *)0x14,
+ "loader_kicker()",
+ (char *)0x16,
+ "loader_query_attribute()",
+ (char *)0x17,
+ "loader_query_iattribute()",
+ (char *)0x13,
+ "loader_query_name()",
+ (char *)0x18,
+ "loader_state_id()",
+ (char *)0x19,
+ "loader_get_sound_id()",
+ (char *)0x1A,
+ "sound reference is not A_SOUND record",
+ (char *)0xFFFFFFFF
+ }; // idb
+int sound_count = 1; // weak
+int dword_10236E4 = 0; // weak
+int dword_10236EC = 0; // weak
+int dword_10236F4 = 0; // weak
+int dword_10236FC = 0; // weak
+int dword_1023704 = 0; // weak
+int dword_102370C = 0; // weak
+int dword_1023714 = 0; // weak
+int dword_102371C = 0; // weak
+int dword_1023724 = 0; // weak
+int dword_102372C = 0; // weak
+int dword_1023734 = 0; // weak
+int dword_102373C = 0; // weak
+int dword_1023758 = 0; // weak
+int dword_1023770 = 0; // weak
+int dword_1023778 = 0; // weak
+int dword_1023780 = 0; // weak
+int dword_1023788 = 0; // weak
+int dword_1023790 = 0; // weak
+int dword_1023798 = 0; // weak
+int dword_10237A0 = 0; // weak
+int dword_10237A8 = 0; // weak
+int dword_10237C4 = 0; // weak
+int dword_10237CC = 0; // weak
+int dword_10237D4 = 0; // weak
+int dword_10237DC = 0; // weak
+int dword_10237E8 = 0; // weak
+int dword_10237F0 = 0; // weak
+int dword_1023808 = 0; // weak
+int dword_1023810 = 0; // weak
+char *off_1023814 = "lite30"; // weak
+int dword_1023818 = 0; // weak
+char *off_102381C = "lite29"; // weak
+int dword_1023820 = 0; // weak
+int dword_1023828 = 0; // weak
+int dword_1023830 = 0; // weak
+int dword_1023838 = 0; // weak
+int dword_1023840 = 0; // weak
+struct TPinballComponent *dword_1023860 = NULL; // idb
+int dword_1023868 = 0; // weak
+int dword_1023870 = 0; // weak
+char *off_1023874 = "lite54"; // weak
+int dword_1023878 = 0; // weak
+char *off_102387C = "lite55"; // weak
+int dword_1023880 = 0; // weak
+char *off_1023884 = "lite56"; // weak
+int dword_1023888 = 0; // weak
+int dword_102389C = 0; // weak
+int dword_10238A4 = 0; // weak
+char *off_10238A8 = "lite17"; // weak
+int dword_10238AC = 0; // weak
+char *off_10238B0 = "lite18"; // weak
+int dword_10238B4 = 0; // weak
+int dword_10238C0 = 0; // weak
+int dword_10238C8 = 0; // weak
+char *off_10238CC = "lite27"; // weak
+int dword_10238D0 = 0; // weak
+char *off_10238D4 = "lite28"; // weak
+int dword_10238D8 = 0; // weak
+int dword_10238E8 = 0; // weak
+char *off_10238EC = "lite16"; // weak
+int dword_10238F0 = 0; // weak
+int dword_1023924 = 0; // weak
+int dword_1023930 = 0; // weak
+char *off_102393C = "lite20"; // weak
+int dword_1023940 = 0; // weak
+int dword_1023948 = 0; // weak
+int dword_1023950 = 0; // weak
+int dword_1023958 = 0; // weak
+int dword_1023960 = 0; // weak
+int dword_1023968 = 0; // weak
+int dword_1023970 = 0; // weak
+int dword_1023978 = 0; // weak
+int dword_1023980 = 0; // weak
+struct TPinballComponent *dword_10239A8 = NULL; // idb
+char *off_10239AC = "lite25"; // weak
+int dword_10239B0 = 0; // weak
+char *off_10239B4 = "lite26"; // weak
+int dword_10239B8 = 0; // weak
+char *off_10239BC = "lite130"; // weak
+int dword_10239C0 = 0; // weak
+int dword_10239C8 = 0; // weak
+int dword_10239D0 = 0; // weak
+int dword_10239EC = 0; // weak
+int dword_10239F4 = 0; // weak
+int dword_10239FC = 0; // weak
+int dword_1023A04 = 0; // weak
+int dword_1023A0C = 0; // weak
+int dword_1023A14 = 0; // weak
+int dword_1023A1C = 0; // weak
+char *off_1023A20 = "lite4"; // weak
+int dword_1023A24 = 0; // weak
+int dword_1023A2C = 0; // weak
+int dword_1023A34 = 0; // weak
+int dword_1023A3C = 0; // weak
+char **off_1023A40[9] =
+ {
+ &off_10239E8,
+ &off_10239F0,
+ &off_10239F8,
+ &off_1023A00,
+ &off_1023A08,
+ &off_1023A10,
+ &off_1023A20,
+ &off_1023A28,
+ &off_1023A30
+ }; // weak
+char **off_1023A4C[6] =
+ {
+ &off_1023A00,
+ &off_1023A08,
+ &off_1023A10,
+ &off_1023A20,
+ &off_1023A28,
+ &off_1023A30
+ }; // weak
+char **off_1023A58[3] = { &off_1023A20, &off_1023A28, &off_1023A30 }; // weak
+int dword_1023A74 = 0; // weak
+int dword_1023A7C = 0; // weak
+int dword_1023A84 = 0; // weak
+int dword_1023A8C = 0; // weak
+int dword_1023A94 = 0; // weak
+int dword_1023A9C = 0; // weak
+int dword_1023AA4 = 0; // weak
+int dword_1023AAC = 0; // weak
+char *off_1023AB0 = "lite61"; // weak
+int dword_1023AB4 = 0; // weak
+char *off_1023AB8 = "lite60"; // weak
+int dword_1023ABC = 0; // weak
+char *off_1023AC0 = "lite59"; // weak
+int dword_1023AC4 = 0; // weak
+char *off_1023AC8 = "lite58"; // weak
+int dword_1023ACC = 0; // weak
+int dword_1023ADC = 0; // weak
+int dword_1023AE4 = 0; // weak
+int dword_1023AEC = 0; // weak
+struct TPinballComponent *dword_1023B0C = NULL; // idb
+int dword_1023B20 = 0; // weak
+int dword_1023B28 = 0; // weak
+int dword_1023B30 = 0; // weak
+struct TPinballComponent *dword_1023B38 = NULL; // idb
+int dword_1023B48 = 0; // weak
+int dword_1023B50 = 0; // weak
+int dword_1023B58 = 0; // weak
+int dword_1023B60 = 0; // weak
+int dword_1023B68 = 0; // weak
+int dword_1023B70 = 0; // weak
+int dword_1023B78 = 0; // weak
+int dword_1023B84 = 0; // weak
+int dword_1023B8C = 0; // weak
+int dword_1023B94 = 0; // weak
+int dword_1023B9C = 0; // weak
+int dword_1023BA4 = 0; // weak
+int dword_1023BAC = 0; // weak
+int dword_1023BB4 = 0; // weak
+char *off_1023BB8 = "lite198"; // weak
+int dword_1023BBC = 0; // weak
+int dword_1023BC8 = 0; // weak
+int dword_1023BD0 = 0; // weak
+int dword_1023BD8 = 0; // weak
+int dword_1023BE0 = 0; // weak
+int dword_1023BE8 = 0; // weak
+int dword_1023BF0 = 0; // weak
+int dword_1023BF8 = 0; // weak
+int dword_1023C00 = 0; // weak
+int dword_1023C08 = 0; // weak
+int dword_1023C10 = 0; // weak
+int dword_1023C18 = 0; // weak
+int dword_1023C20 = 0; // weak
+int dword_1023C28 = 0; // weak
+int dword_1023C30 = 0; // weak
+int dword_1023C3C = 0; // weak
+char *off_1023C40 = "lite110"; // weak
+int dword_1023C44 = 0; // weak
+int dword_1023C50 = 0; // weak
+int dword_1023C5C = 0; // weak
+int dword_1023C68 = 0; // weak
+int dword_1023C70 = 0; // weak
+int dword_1023C7C = 0; // weak
+char *off_1023CB0 = "lite67"; // weak
+int dword_1023CB4 = 0; // weak
+int dword_1023CBC = 0; // weak
+int dword_1023CC4 = 0; // weak
+int dword_1023CCC = 0; // weak
+int dword_1023CD4 = 0; // weak
+int dword_1023CDC = 0; // weak
+int dword_1023CE4 = 0; // weak
+int dword_1023CEC = 0; // weak
+int dword_1023CF4 = 0; // weak
+int dword_1023CFC = 0; // weak
+char *off_1023D00 = "lite200"; // weak
+int dword_1023D04 = 0; // weak
+char *off_1023D08 = "lite199"; // weak
+int dword_1023D0C = 0; // weak
+int dword_1023D14 = 0; // weak
+int dword_1023D1C = 0; // weak
+int dword_1023D24 = 0; // weak
+int dword_1023D2C = 0; // weak
+int dword_1023D34 = 0; // weak
+int dword_1023D3C = 0; // weak
+int dword_1023D44 = 0; // weak
+int dword_1023D4C = 0; // weak
+int dword_1023D54 = 0; // weak
+int dword_1023D64 = 0; // weak
+int dword_1023D6C = 0; // weak
+int dword_1023D74 = 0; // weak
+int dword_1023D7C = 0; // weak
+int dword_1023D84 = 0; // weak
+int dword_1023D8C = 0; // weak
+int dword_1023D94 = 0; // weak
+int dword_1023D9C = 0; // weak
+int dword_1023DA4 = 0; // weak
+int dword_1023DAC = 0; // weak
+int dword_1023DB4 = 0; // weak
+int dword_1023DBC = 0; // weak
+int dword_1023DC4 = 0; // weak
+int dword_1023DCC = 0; // weak
+int dword_1023DD4 = 0; // weak
+int dword_1023DDC = 0; // weak
+int dword_1023DE4 = 0; // weak
+int dword_1023DEC = 0; // weak
+int dword_1023DF4 = 0; // weak
+int dword_1023DFC = 0; // weak
+int dword_1023E04 = 0; // weak
+int dword_1023E0C = 0; // weak
+int dword_1023E14 = 0; // weak
+TTextBox *dword_1023E1C = NULL; // idb
+TTextBox *dword_1023E24 = NULL; // idb
+int dword_1023E34 = 0; // weak
+int dword_1023E3C = 0; // weak
+int dword_1023E44 = 0; // weak
+char *off_1023E48 = "lite303"; // weak
+int dword_1023E4C = 0; // weak
+char *off_1023E50 = "lite304"; // weak
+int dword_1023E54 = 0; // weak
+int dword_1023E5C = 0; // weak
+int dword_1023E64 = 0; // weak
+int dword_1023E6C = 0; // weak
+int dword_1023E74 = 0; // weak
+int dword_1023E7C = 0; // weak
+int dword_1023E84 = 0; // weak
+int dword_1023E8C = 0; // weak
+int dword_1023E94 = 0; // weak
+int dword_1023E9C = 0; // weak
+char *off_1023EA0 = "lite314"; // weak
+int dword_1023EA4 = 0; // weak
+int dword_1023EAC = 0; // weak
+char *off_1023EB0 = "lite316"; // weak
+int dword_1023EB4 = 0; // weak
+char *off_1023EB8 = "lite317"; // weak
+int dword_1023EBC = 0; // weak
+char *off_1023EC0 = "lite318"; // weak
+int dword_1023EC4 = 0; // weak
+char *off_1023EC8 = "lite319"; // weak
+int dword_1023ECC = 0; // weak
+int dword_1023ED4 = 0; // weak
+int dword_1023EDC = 0; // weak
+int dword_1023EE4 = 0; // weak
+int dword_1023EEC = 0; // weak
+_UNKNOWN unk_1023EF8; // weak
+char **off_1024470[142] =
+ {
+ &off_1023708,
+ &off_1023710,
+ &off_1023718,
+ &off_1023720,
+ &off_1023774,
+ &off_102377C,
+ &off_1023784,
+ &off_102378C,
+ &off_1023814,
+ &off_102381C,
+ &off_1023864,
+ &off_1023874,
+ &off_102387C,
+ &off_1023884,
+ &off_10238B0,
+ &off_10238CC,
+ &off_10238D4,
+ &off_10238EC,
+ &off_1023984,
+ &off_102398C,
+ &off_1023994,
+ &off_102399C,
+ &off_10239AC,
+ &off_10239B4,
+ &off_10239BC,
+ &off_1023A00,
+ &off_1023A08,
+ &off_1023A10,
+ &off_1023A18,
+ &off_1023A20,
+ &off_1023A28,
+ &off_1023A30,
+ &off_1023A38,
+ &off_1023A88,
+ &off_1023A90,
+ &off_1023944,
+ &off_102394C,
+ &off_1023954,
+ &off_102395C,
+ &off_1023964,
+ &off_102396C,
+ &off_1023974,
+ &off_102393C,
+ &off_10239CC,
+ &off_1023AB0,
+ &off_1023AC8,
+ &off_1023AF0,
+ &off_1023AF8,
+ &off_1023B00,
+ &off_1023B5C,
+ &off_1023B64,
+ &off_1023B6C,
+ &off_1023B74,
+ &off_1023B98,
+ &off_1023BA0,
+ &off_1023BA8,
+ &off_1023BB0,
+ &off_1023BF4,
+ &off_1023BFC,
+ &off_1023C04,
+ &off_1023C0C,
+ &off_1023C14,
+ &off_1023C1C,
+ &off_1023C24,
+ &off_1023C2C,
+ &off_1023C40,
+ &off_1023C6C,
+ &off_1023CB0,
+ &off_1023CB8,
+ &off_1023CC0,
+ &off_1023CC8,
+ &off_1023CD0,
+ &off_1023CD8,
+ &off_1023CE0,
+ &off_1023CE8,
+ &off_1023BB8,
+ &off_1023CF0,
+ &off_1023CF8,
+ &off_1023D10,
+ &off_1023D18,
+ &off_1023D20,
+ &off_1023D28,
+ &off_1023D30,
+ &off_1023D38,
+ &off_1023D40,
+ &off_1023D48,
+ &off_1023D58,
+ &off_1023D60,
+ &off_1023D68,
+ &off_1023D70,
+ &off_1023D78,
+ &off_1023D80,
+ &off_1023D88,
+ &off_1023D90,
+ &off_1023D98,
+ &off_1023DA0,
+ &off_1023DA8,
+ &off_1023DB0,
+ &off_1023DB8,
+ &off_1023DC0,
+ &off_1023DC8,
+ &off_1023DD0,
+ &off_1023DD8,
+ &off_1023DE0,
+ &off_1023D08,
+ &off_1023824,
+ &off_102382C,
+ &off_1023E18,
+ &off_1023E20,
+ &off_1023DE8,
+ &off_10237D0,
+ &off_10237D8,
+ &off_1023DF0,
+ &off_1023DF8,
+ &off_1023E00,
+ &off_1023E08,
+ &off_1023E30,
+ &off_1023E38,
+ &off_1023E40,
+ &off_1023E48,
+ &off_1023E50,
+ &off_1023E58,
+ &off_1023E60,
+ &off_1023E68,
+ &off_1023E70,
+ &off_1023E78,
+ &off_1023E80,
+ &off_1023E88,
+ &off_1023E90,
+ &off_1023E98,
+ &off_1023EA0,
+ &off_1023EA8,
+ &off_1023EB0,
+ &off_1023EB8,
+ &off_1023EC0,
+ &off_1023EC8,
+ &off_1023ED0,
+ &off_1023ED8,
+ &off_1023EE0,
+ &off_1023EE8,
+ &off_1023D50,
+ &off_1023E10
+ }; // weak
+int off_10246A0 = 16923984; // idb
+__int16 word_10246EC[] = { 84 }; // weak
+__int16 word_1024708[] = { 91 }; // weak
+int render_blit = 1; // weak
+int dword_1024758[5] = { 1, 2, 3, 5, 10 }; // idb
+int __security_cookie_complement = 4294919359; // weak
+int __security_cookie = 47936; // weak
+CHAR aWavemixV23ByAn[] = "WaveMix V 2.3 by Angel M. Diaz, Jr. (c) Microsoft 1993-1995"; // idb
+int __defaultmatherr = 1; // weak
+LPCSTR lpString2 = NULL; // idb
+LPSTR lpString1 = NULL; // idb
+CHAR byte_10248A8[1536] =
+ {
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+ '\0',
+
+ }; // idb
+int rc_string_slot; // weak
+struct tagRECT Rect; // idb
+HWND hWnd; // idb
+int dword_1024EC0; // weak
+struct tagRECT X; // idb
+int dword_1024ED4; // weak
+int dword_1024ED8; // weak
+int dword_1024EDC; // weak
+int dword_1024EE0; // weak
+int fullscrn_screen_mode; // weak
+int dword_1024EE8; // weak
+int dword_1024EEC; // weak
+int dword_1024EF0; // weak
+int fullscrn_display_changed; // weak
+int dword_1024EF8; // weak
+int gdrv_use_wing; // weak
+int memory_use_total; // weak
+int memory_critical_allocation; // weak
+int (*memory_critical_callback)(void); // weak
+HMENU hMenu; // idb
+__int16 word_1024F18; // weak
+int dword_1024F1C[8]; // idb
+int dword_1024F3C[8]; // idb
+LPCVOID pMem; // idb
+HMODULE dword_1024F60; // idb
+HWND dword_1024F64; // idb
+int (__stdcall *dword_1024F68)(_DWORD, _DWORD, _DWORD); // weak
+HINSTANCE hInstance; // idb
+int dword_1024F70; // weak
+int dword_1024F74; // weak
+int dword_1024F78; // weak
+int dword_1024F7C; // weak
+int dword_1024F80; // weak
+int time_ticks; // weak
+char Dest[80]; // idb
+int single_step; // weak
+int bQuit; // weak
+int DispFrameRate; // weak
+int DispGRhistory; // weak
+int mouse_down; // weak
+int has_focus; // weak
+int activated; // weak
+int no_time_loss; // weak
+int cheat_mode; // weak
+int midi_seq1_open; // weak
+int midi_seq1_playing; // weak
+HWND midi_notify_hwnd; // weak
+_UNKNOWN mci_open_info; // weak
+MCIDEVICEID mciId; // idb
+int dword_1025014; // weak
+int dword_1025018; // weak
+CHAR byte_1025020[28]; // idb
+TEdgeManager *edge_manager; // idb
+TPinballTable *dword_1025040; // idb
+int dword_1025044; // weak
+int dword_1025048; // weak
+int dword_102504C; // weak
+int dword_1025050; // weak
+_UNKNOWN zscreen; // weak
+__int16 word_102505A; // weak
+struct render_sprite_type_struct **render_dirty_list; // weak
+struct render_sprite_type_struct **render_ball_list; // weak
+int render_many_balls; // weak
+_UNKNOWN vscreen_rect; // weak
+int dword_1025078; // weak
+int dword_102507C; // weak
+int dword_1025080; // weak
+struct render_sprite_type_struct **render_sprite_list; // weak
+_UNKNOWN vscreen; // weak
+int dword_1025094; // weak
+int dword_1025098; // weak
+int xDest; // idb
+int yDest; // idb
+float render_zscaler; // weak
+int render_many_sprites; // weak
+float render_zmax; // weak
+float render_zmin; // weak
+int render_many_dirty; // weak
+_UNKNOWN ball_bitmap; // weak
+int render_offset_x; // weak
+int render_offset_y; // weak
+int render_background_bitmap; // idb
+struct zmap_header_type *render_background_zmap; // weak
+_UNKNOWN render_zmap_offset; // weak
+int dword_10253C0; // weak
+struct score_msg_font_type *score_msg_fontp; // weak
+float ball_speed_limit; // weak
+_UNKNOWN pb_state; // weak
+CHAR byte_102543C[300]; // idb
+int dword_1025568; // weak
+int dword_102556C; // weak
+int dword_1025570; // weak
+int dword_1025574; // weak
+CHAR byte_1025578[32]; // idb
+int dword_1025598[36]; // idb
+float time_now; // weak
+float time_next; // weak
+int pb_record_table; // idb
+int nudged_left; // weak
+int nudged_right; // weak
+int nudged_up; // weak
+int nudge_timer; // weak
+float nudge_count; // weak
+TTextBox *InfoTextBox; // idb
+TTextBox *MissTextBox; // idb
+struct TPinballTable *MainTable; // idb
+float flipper_sin_angle; // idb
+_UNKNOWN circlebase; // weak
+int dword_1025664; // weak
+int dword_102566C; // weak
+_UNKNOWN circleT1; // weak
+int dword_1025674; // weak
+int dword_102567C; // weak
+_UNKNOWN lineA; // weak
+float flt_1025684; // weak
+_UNKNOWN unk_10256A4; // weak
+float flipper_cos_angle; // idb
+_UNKNOWN A2; // weak
+float flt_10256B8; // weak
+_UNKNOWN lineB; // weak
+float flt_10256C4; // weak
+_UNKNOWN unk_10256E4; // weak
+_UNKNOWN B1; // weak
+float flt_10256F4; // weak
+_UNKNOWN B2; // weak
+float flt_1025700; // weak
+_UNKNOWN T1; // weak
+int dword_102570C; // weak
+_UNKNOWN A1; // weak
+float flt_1025718; // weak
+HWND (__stdcall *pHtmlHelpA)(HWND, const char *, unsigned int, unsigned int); // weak
+int dword_1025728; // weak
+HMODULE hModule; // idb
+int dword_1025730[16]; // idb
+_UNKNOWN unk_1025770; // weak
+int dword_1025798; // weak
+int dword_10257A0[16]; // idb
+HINSTANCE dword_10257E0; // idb
+_UNKNOWN unk_10257E4; // weak
+__int16 word_1025810[]; // weak
+__int16 word_1025812[30]; // idb
+CHAR FileName[276]; // idb
+int dword_1025964; // weak
+int dword_1025968; // weak
+char byte_1025970[128]; // idb
+_UNKNOWN unk_10259F0; // weak
+_UNKNOWN unk_10263F0; // weak
+_UNKNOWN unk_1026470; // weak
+_UNKNOWN unk_1027B68; // weak
+int dword_1027BA4; // weak
+LPARAM hMem; // idb
+int dword_1027BE4; // weak
+int dword_1027BE8; // weak
+LPWAVEHDR pwh; // idb
+int dword_1027BF0; // weak
+int dword_1027BF4; // weak
+int dword_1027BF8; // weak
+int _dowildcard; // weak
+int _newmode; // weak
+int _commode; // weak
+int _fmode;
+int loader_table; // idb
+int sound_record_table; // weak
+int sound_list[]; // weak
+int dword_1027C24[]; // weak
+int dword_1027C28[]; // weak
+char algn_1027C2C[4]; // weak
+int dword_1027C30[]; // weak
+_UNKNOWN unk_1027C34; // weak
+int loader_sound_count; // weak
+int proj_centery; // weak
+int proj_centerx; // weak
+int proj_d; // weak
+_UNKNOWN proj_matrix; // weak
+_UNKNOWN unk_1028170; // weak
+float flt_1028190; // weak
+float flt_1028194; // weak
+float flt_1028198; // weak
+float flt_102819C; // weak
+int then; // weak
+_UNKNOWN gfr_display; // weak
+int dword_10281C8; // weak
+UINT iFrostUniqueMsg; // idb
+int last_mouse_y; // idb
+int now; // weak
+HCURSOR mouse_hsave; // idb
+int last_mouse_x; // idb
+HWND hwnd_frame; // idb
+int return_value; // weak
+HINSTANCE hinst; // idb
+int num_channels; // weak
+HKEY options; // idb
+HKEY phkResult; // idb
+HKEY dword_1028228; // idb
+HKEY dword_102822C; // idb
+HKEY dword_1028230; // idb
+HKEY dword_1028234; // idb
+HKEY dword_1028238; // idb
+HKEY dword_102823C; // idb
+HKEY dword_1028240; // idb
+HKEY dword_1028244; // idb
+HKEY dword_1028248; // idb
+HKEY dword_102824C; // idb
+__int16 dword_1028250; // idb
+__int16 dword_1028254; // idb
+__int16 dword_1028258; // idb
+__int16 dword_102825C; // idb
+__int16 dword_1028260; // idb
+__int16 dword_1028264; // idb
+int high_score_dlg_score; // idb
+LPCSTR high_score_dlg_hst; // idb
+int high_score_dlg_enter_name; // weak
+int high_score_position; // idb
+LPCSTR high_score_default_name; // idb
+HGDIOBJ gdrv_palette_handle; // idb
+HDC gdrv_sequence_hdc; // idb
+int gdrv_hinst; // weak
+HWND gdrv_hwnd; // idb
+int gdrv_sequence_handle; // weak
+int grtext_blue; // weak
+int grtext_green; // weak
+int __onexitend; // weak
+int __onexitbegin; // weak
+int _adjust_fdiv; // weak
+
+#endif //PINBALL_PINBALL_H
diff --git a/score.cpp b/score.cpp
new file mode 100644
index 0000000..2a728f5
--- /dev/null
+++ b/score.cpp
@@ -0,0 +1,382 @@
+#include "pinball.h"
+
+//----- (0100C335) --------------------------------------------------------
+int __stdcall SpecialAddScore(int a1)
+{
+TPinballTable *v1; // ecx
+int v2; // esi
+int v3; // edi
+int v4; // ebx
+int result; // eax
+TPinballTable *v6; // ecx
+
+v1 = dword_1025040;
+v2 = *(_DWORD *)((char *)dword_1025040 + 318);
+*(_DWORD *)((char *)dword_1025040 + 318) = 0;
+v3 = *(_DWORD *)((char *)v1 + 310);
+*(_DWORD *)((char *)v1 + 310) = 0;
+v4 = *(_DWORD *)((char *)v1 + 294);
+*(_DWORD *)((char *)v1 + 294) = 0;
+result = TPinballTable::AddScore(v1, a1);
+v6 = dword_1025040;
+*(_DWORD *)((char *)dword_1025040 + 310) = v3;
+*(_DWORD *)((char *)v6 + 294) = v4;
+*(_DWORD *)((char *)v6 + 318) = v2;
+return result;
+}
+
+//----- (0100E50B) --------------------------------------------------------
+int __stdcall AddRankProgress(int a1)
+{
+signed int v1; // ebx
+int v2; // edi
+void (__thiscall ***v3)(_DWORD, signed int, _DWORD); // esi
+signed int v4; // edi
+int v5; // eax
+int (__thiscall ***v6)(_DWORD, signed int, _DWORD); // esi
+int v7; // edi
+CHAR *v8; // ST40_4
+CHAR *v9; // eax
+__int64 v10; // rax
+int v11; // edx
+signed __int64 v12; // rt2
+char Dest; // [esp+50h] [ebp-44h]
+
+v1 = 0;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10238F0)(19, 0.0);
+v2 = a1;
+v3 = (void (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023CFC;
+if ( a1 > 0 )
+{
+do
+{
+(**v3)(v3, 41, 2.0);
+--v2;
+}
+while ( v2 );
+}
+v4 = ((int (__thiscall *)(_DWORD, signed int, _DWORD))**v3)(v3, 37, 0.0);
+v5 = ((int (__thiscall *)(_DWORD, signed int, _DWORD))**v3)(v3, 38, 0.0);
+if ( v4 == v5 )
+{
+v1 = 1;
+(**v3)(v3, 16, 5.0);
+v6 = (int (__thiscall ***)(_DWORD, signed int, _DWORD))dword_1023CF4;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023CF4)(34, 0.0);
+v7 = (**v6)(v6, 37, 0.0);
+if ( v7 < 9 )
+{
+(**v6)(v6, 41, 5.0);
+v8 = get_rc_string(word_10246EC[2 * v7], 1);
+v9 = get_rc_string(83, 0);
+_sprintf(&Dest, v9, v8);
+TTextBox::Display(dword_1023E24, 1, &Dest, 8.0);
+(*(void (**)(void))(*(_DWORD *)dword_1023D1C + 20))();
+}
+}
+else
+{
+v10 = 3 * v5;
+v12 = v10 % 4;
+LODWORD(v10) = v10 / 4;
+v11 = v12;
+if ( v4 >= (signed int)v10 )
+(**(void (__fastcall ***)(int, int, signed int, _DWORD))dword_1023CF4)(dword_1023CF4, v11, 27, -1.0);
+}
+return v1;
+}
+// 10238F0: using guessed type int dword_10238F0;
+// 1023CF4: using guessed type int dword_1023CF4;
+// 1023CFC: using guessed type int dword_1023CFC;
+// 1023D1C: using guessed type int dword_1023D1C;
+// 10246EC: using guessed type __int16 word_10246EC[];
+
+
+//----- (01013BB3) --------------------------------------------------------
+_DWORD *__stdcall score_create(LPCSTR lpString, int a2)
+{
+_DWORD *v2; // esi
+__int16 *v3; // eax
+__int16 v5; // cx
+signed __int16 *v6; // eax
+int v7; // edx
+int v8; // edx
+int v9; // ebx
+int *v10; // edi
+int v11; // [esp+10h] [ebp+Ch]
+
+v2 = (_DWORD *)memoryallocate(0x44u);
+if ( !v2 )
+return 0;
+*v2 = -9999;
+v2[2] = a2;
+v3 = (__int16 *)partman_field_labeled(loader_table, lpString, 10);
+if ( !v3 )
+{
+memoryfree((int)v2);
+return 0;
+}
+v5 = *v3;
+v6 = v3 + 1;
+v7 = *v6;
+++v6;
+v2[3] = v7;
+v8 = *v6;
+++v6;
+v2[4] = v8;
+v2[5] = *v6;
+v2[6] = v6[1];
+v9 = v5;
+v10 = v2 + 7;
+v11 = 10;
+do
+{
+*v10 = partman_field(loader_table, v9, 1);
+++v10;
+++v9;
+--v11;
+}
+while ( v11 );
+return v2;
+}
+
+//----- (01013C48) --------------------------------------------------------
+void *__stdcall score_dup(const void *a1, int a2)
+{
+void *result; // eax
+
+result = (void *)memoryallocate(0x44u);
+if ( result )
+qmemcpy(result, a1, 0x44u);
+return result;
+}
+
+
+//----- (01013C89) --------------------------------------------------------
+_DWORD *__stdcall score_set(_DWORD *a1, int a2)
+{
+_DWORD *result; // eax
+
+result = a1;
+if ( a1 )
+{
+*a1 = a2;
+a1[1] = 1;
+}
+return result;
+}
+
+//----- (01013CAA) --------------------------------------------------------
+void *__userpurge score_erase@(int a1@, _DWORD *a2, int a3)
+{
+_DWORD *v3; // edx
+void *result; // eax
+
+if ( a2 )
+{
+v3 = (_DWORD *)a2[2];
+if ( v3 )
+result = gdrv_copy_bitmap(&vscreen, a2[5], a2[6], a2[3], a2[4], v3, a2[3], a2[4]);
+else
+result = (void *)gdrv_fill_bitmap(a1, &vscreen, a2[5], a2[6], a2[3], a2[4], 0);
+if ( a3 )
+result = gdrv_blit((int)&vscreen, a2[3], a2[4], a2[3] + xDest, a2[4] + yDest, a2[5], a2[6]);
+}
+return result;
+}
+
+//----- (01013D2D) --------------------------------------------------------
+HDC __userpurge score_update@(int a1@, int *a2)
+{
+HDC result; // eax
+int v3; // ecx
+int v4; // edi
+unsigned int v5; // kr00_4
+int v6; // eax
+char *v7; // eax
+int v8; // [esp-24h] [ebp-40h]
+int v9; // [esp-20h] [ebp-3Ch]
+_DWORD *v10; // [esp-14h] [ebp-30h]
+int v11; // [esp+4h] [ebp-18h]
+int v12; // [esp+8h] [ebp-14h]
+char DstBuf[12]; // [esp+Ch] [ebp-10h]
+
+result = 0;
+if ( a2 && a2[1] && *a2 <= 1000000000 )
+{
+v3 = a2[4];
+v4 = a2[5] + a2[3];
+a2[1] = 0;
+v11 = v3;
+score_erase(a1, a2, 0);
+if ( *a2 >= 0 )
+{
+__ltoa(*a2, DstBuf, 10);
+v5 = strlen(DstBuf);
+v6 = v5 - 1;
+v12 = v5 - 1;
+if ( (signed int)(v5 - 1) >= 0 )
+{
+while ( 1 )
+{
+v7 = &DstBuf[v6];
+*v7 -= 48;
+v10 = (_DWORD *)a2[*v7 + 7];
+v4 -= v10[3];
+v9 = v10[4];
+v8 = v10[3];
+if ( render_background_bitmap )
+gdrv_copy_bitmap_w_transparency(&vscreen, v8, v9, v4, v11, v10, 0, 0);
+else
+gdrv_copy_bitmap(&vscreen, v8, v9, v4, v11, v10, 0, 0);
+if ( --v12 < 0 )
+break;
+v6 = v12;
+}
+}
+}
+result = gdrv_blit((int)&vscreen, a2[3], a2[4], a2[3] + xDest, a2[4] + yDest, a2[5], a2[6]);
+}
+return result;
+}
+// 1013D2D: using guessed type char DstBuf[12];
+
+//----- (01013E25) --------------------------------------------------------
+signed int __stdcall score_init()
+{
+return 1;
+}
+
+//----- (01013E2E) --------------------------------------------------------
+void __stdcall score_unload_msg_font()
+{
+signed int v0; // esi
+
+if ( score_msg_fontp )
+{
+v0 = 8;
+do
+{
+if ( *(_DWORD *)((char *)score_msg_fontp + v0) )
+{
+gdrv_destroy_bitmap(*(_DWORD *)((char *)score_msg_fontp + v0));
+memoryfree(*(_DWORD *)((char *)score_msg_fontp + v0));
+}
+v0 += 4;
+}
+while ( v0 < 520 );
+score_msg_fontp = 0;
+}
+}
+// 10253C4: using guessed type struct score_msg_font_type *score_msg_fontp;
+
+//----- (01013E73) --------------------------------------------------------
+HRSRC __stdcall score_load_msg_font(LPCSTR lpName)
+{
+HRSRC result; // eax
+HRSRC v2; // esi
+signed __int16 *v3; // ebx
+int v4; // edx
+signed int v5; // esi
+signed int v6; // ecx
+char *v7; // eax
+_BYTE *v8; // esi
+int v9; // eax
+unsigned int v10; // eax
+const void *v11; // esi
+_DWORD *v12; // eax
+int v13; // edx
+char *v14; // eax
+int v15; // esi
+HRSRC hResData; // [esp+0h] [ebp-20h]
+unsigned int v17; // [esp+4h] [ebp-1Ch]
+char *i; // [esp+8h] [ebp-18h]
+int v19; // [esp+Ch] [ebp-14h]
+signed int v20; // [esp+10h] [ebp-10h]
+char *v21; // [esp+14h] [ebp-Ch]
+int v22; // [esp+18h] [ebp-8h]
+int v23; // [esp+1Ch] [ebp-4h]
+LPCSTR lpNamea; // [esp+28h] [ebp+8h]
+
+result = FindResourceA(hinst, lpName, (LPCSTR)0xA);
+if ( !result )
+return result;
+result = (HRSRC)LoadResource(hinst, result);
+v2 = result;
+hResData = result;
+if ( !result )
+return result;
+v3 = (signed __int16 *)LockResource(result);
+v22 = (int)(v3 + 67);
+v4 = memoryallocate(0x208u);
+score_msg_fontp = (struct score_msg_font_type *)v4;
+if ( !v4 )
+return (HRSRC)FreeResource(v2);
+v5 = 128;
+memset((void *)(v4 + 8), 0, 0x200u);
+v6 = 0;
+v7 = (char *)(v3 + 3);
+do
+{
+if ( *v7 > v6 )
+v6 = *v7;
+++v7;
+--v5;
+}
+while ( v5 );
+v19 = memoryallocate(v6 * v3[2] + 4);
+if ( !v19 )
+{
+memoryfree((int)score_msg_fontp);
+score_msg_fontp = 0;
+return (HRSRC)FreeResource(hResData);
+}
+v23 = 0;
+*(_DWORD *)score_msg_fontp = *v3;
+*((_DWORD *)score_msg_fontp + 1) = v3[2];
+lpNamea = (LPCSTR)8;
+while ( 1 )
+{
+v8 = (char *)v3 + v23 + 6;
+if ( *v8 )
+break;
+LABEL_16:
+lpNamea += 4;
+++v23;
+if ( (signed int)lpNamea >= 520 )
+goto LABEL_19;
+}
+*(_DWORD *)((char *)score_msg_fontp + (_DWORD)lpNamea) = memoryallocate(0x25u);
+v9 = *(_DWORD *)((char *)score_msg_fontp + (_DWORD)lpNamea);
+if ( !v9 )
+goto LABEL_19;
+if ( !gdrv_create_raw_bitmap(v9, (char)*v8, v3[2], 0) )
+{
+v10 = v3[2] * (char)*v8;
+v11 = (const void *)v22;
+v22 += ++v10;
+qmemcpy((void *)(v19 + 3), v11, v10);
+v20 = 0;
+v17 = *((char *)v3 + v23 + 6);
+v21 = (char *)(v19 + 4);
+v12 = *(_DWORD **)((char *)score_msg_fontp + (_DWORD)lpNamea);
+v13 = -v12[5];
+v14 = (char *)(v12[2] - v13 * (v12[4] - 1));
+for ( i = v14; v20 < v3[2]; i += v13 )
+{
+qmemcpy(v14, v21, v17);
+++v20;
+v21 += v17;
+v14 = &i[v13];
+}
+goto LABEL_16;
+}
+v15 = 4 * v23 + 8;
+memoryfree(*(_DWORD *)((char *)score_msg_fontp + v15));
+*(_DWORD *)((char *)score_msg_fontp + v15) = 0;
+LABEL_19:
+if ( v23 != 128 )
+score_unload_msg_font();
+return (HRSRC)FreeResource(hResData);
+}
+// 10253C4: using guessed type struct score_msg_font_type *score_msg_fontp;
diff --git a/sound/midi.cpp b/sound/midi.cpp
new file mode 100644
index 0000000..7c8ec0b
--- /dev/null
+++ b/sound/midi.cpp
@@ -0,0 +1,88 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "../pinball.h"
+
+//----- (0100AF1F) --------------------------------------------------------
+int __stdcall midi_music_init(HWND a1)
+{
+ CHAR *v1; // eax
+
+ mciId = 0;
+ midi_notify_hwnd = a1;
+ v1 = get_rc_string(156, 0);
+ lstrcpyA(byte_1025020, v1);
+ dword_1025018 = 0;
+ dword_1025014 = (int)byte_1025020;
+ if ( !mciSendCommandA(0, 0x803u, 0x2002u, (DWORD_PTR)&mci_open_info) )
+ midi_seq1_open = 1;
+ return midi_seq1_open;
+}
+// 1025000: using guessed type int midi_seq1_open;
+// 1025008: using guessed type HWND midi_notify_hwnd;
+// 1025014: using guessed type int dword_1025014;
+// 1025018: using guessed type int dword_1025018;
+
+//----- (0100AF8E) --------------------------------------------------------
+MCIERROR __stdcall midi_music_shutdown()
+{
+ MCIERROR result; // eax
+
+ if ( midi_seq1_open )
+ result = mciSendCommandA(mciId, 0x804u, 0, 0);
+ midi_seq1_open = 0;
+ return result;
+}
+// 1025000: using guessed type int midi_seq1_open;
+
+//----- (0100AFB9) --------------------------------------------------------
+MCIERROR __stdcall midi_music_stop()
+{
+ MCIERROR result; // eax
+
+ result = 0;
+ if ( midi_seq1_playing )
+ result = mciSendCommandA(mciId, 0x808u, 0, 0);
+ return result;
+}
+// 1025004: using guessed type int midi_seq1_playing;
+
+//----- (0100AFDC) --------------------------------------------------------
+MCIERROR __stdcall midi_play_pb_theme(int a1)
+{
+ MCIERROR v1; // esi
+ DWORD_PTR dwParam2; // [esp+4h] [ebp-Ch]
+ int v4; // [esp+8h] [ebp-8h]
+
+ v1 = 0;
+ midi_music_stop();
+ v4 = 0;
+ dwParam2 = (DWORD_PTR)midi_notify_hwnd;
+ if ( !a1 && midi_seq1_open )
+ {
+ v1 = mciSendCommandA(mciId, 0x806u, 5u, (DWORD_PTR)&dwParam2);
+ midi_seq1_playing = v1 == 0;
+ }
+ return v1;
+}
+// 1025000: using guessed type int midi_seq1_open;
+// 1025004: using guessed type int midi_seq1_playing;
+// 1025008: using guessed type HWND midi_notify_hwnd;
+
+//----- (0100B035) --------------------------------------------------------
+HWND __stdcall restart_midi_seq(int a1)
+{
+ HWND result; // eax
+ DWORD_PTR dwParam2; // [esp+0h] [ebp-Ch]
+ int v3; // [esp+4h] [ebp-8h]
+
+ v3 = 0;
+ result = midi_notify_hwnd;
+ dwParam2 = (DWORD_PTR)midi_notify_hwnd;
+ if ( midi_seq1_playing )
+ result = (HWND)mciSendCommandA(mciId, 0x806u, 5u, (DWORD_PTR)&dwParam2);
+ return result;
+}
+// 1025004: using guessed type int midi_seq1_playing;
+// 1025008: using guessed type HWND midi_notify_hwnd;
diff --git a/sound/sound.cpp b/sound/sound.cpp
new file mode 100644
index 0000000..971651e
--- /dev/null
+++ b/sound/sound.cpp
@@ -0,0 +1,317 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "../pinball.h"
+
+//----- (010068F7) --------------------------------------------------------
+LRESULT __stdcall SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ signed int v5; // eax
+ int v6; // esi
+ int v7; // edi
+
+ if ( Msg != 957 )
+ return DefWindowProcA(hWnd, Msg, wParam, lParam);
+ v5 = -1;
+ v6 = 0;
+ if ( num_channels > 0 )
+ {
+ v7 = 0;
+ do
+ {
+ if ( dword_1024F1C[v7 + 8] == lParam && (v5 < 0 || dword_1024F1C[v7] < (unsigned int)dword_1024F1C[v5]) )
+ v5 = v6;
+ ++v6;
+ ++v7;
+ }
+ while ( v6 < num_channels );
+ if ( v5 >= 0 )
+ {
+ dword_1024F1C[v5] = 0;
+ dword_1024F3C[v5] = 0;
+ }
+ }
+ dword_1024F68(2, lParam, v5);
+ return 0;
+}
+// 1024F68: using guessed type int (__stdcall *dword_1024F68)(_DWORD, _DWORD, _DWORD);
+// 1028208: using guessed type int num_channels;
+
+
+//----- (01006973) --------------------------------------------------------
+int __stdcall Sound_Init(HINSTANCE hInstance, int a2, int a3)
+{
+ int v3; // ecx
+ int i; // eax
+ FILE *v5; // eax
+ CHAR *v6; // eax
+ _WORD *v7; // eax
+ WNDCLASSA WndClass; // [esp+8h] [ebp-158h]
+ char Filename; // [esp+30h] [ebp-130h]
+
+ v3 = a2;
+ if ( a2 > 8 )
+ v3 = 8;
+ num_channels = v3;
+ if ( dword_1024F64 || pMem )
+ return 0;
+ word_1024F18 = -1;
+ for ( i = 0; i < v3; ++i )
+ {
+ dword_1024F1C[i] = 0;
+ dword_1024F3C[i] = 0;
+ }
+ dword_1024F68 = (int (__stdcall *)(_DWORD, _DWORD, _DWORD))a3;
+ if ( !a3 )
+ dword_1024F68 = nullsub_1;
+ make_path_name(&Filename, "wavemix.inf", 0x12Cu);
+ v5 = _fopen(&Filename, "r");
+ if ( v5 )
+ {
+ _fclose(v5);
+ }
+ else
+ {
+ v6 = get_rc_string(42, 0);
+ MessageBoxA(hwnd_frame, v6, WindowName, 0x2000u);
+ }
+ WndClass.style = 0;
+ WndClass.lpfnWndProc = SoundCallBackWndProc;
+ WndClass.cbClsExtra = 0;
+ WndClass.cbWndExtra = 0;
+ WndClass.hInstance = hInstance;
+ WndClass.hIcon = 0;
+ WndClass.hCursor = 0;
+ WndClass.hbrBackground = 0;
+ WndClass.lpszMenuName = 0;
+ WndClass.lpszClassName = "WaveMixSoundGuy";
+ RegisterClassA(&WndClass);
+ dword_1024F64 = CreateWindowExA(0, "WaveMixSoundGuy", 0, 0x80000000, 2147483648, 0, 2147483648, 0, 0, 0, hInstance, 0);
+ if ( !dword_1024F64 )
+ return 0;
+ dword_1024F60 = hInstance;
+ v7 = (_WORD *)WaveMixInit();
+ pMem = v7;
+ if ( !v7 )
+ return 0;
+ WaveMixOpenChannel(v7, num_channels, 2u);
+ return 1;
+}
+// 10068EF: using guessed type int __stdcall nullsub_1(int, int, int);
+// 1024F18: using guessed type __int16 word_1024F18;
+// 1024F68: using guessed type int (__stdcall *dword_1024F68)(_DWORD, _DWORD, _DWORD);
+// 1028208: using guessed type int num_channels;
+
+//----- (01006AF6) --------------------------------------------------------
+HLOCAL __stdcall Sound_Close()
+{
+ HLOCAL result; // eax
+
+ if ( dword_1024F64 )
+ {
+ DestroyWindow(dword_1024F64);
+ dword_1024F64 = 0;
+ }
+ result = (HLOCAL)pMem;
+ if ( pMem )
+ {
+ WaveMixCloseChannel(pMem, 0, 1);
+ result = WaveMixCloseSession((HLOCAL)pMem);
+ pMem = 0;
+ }
+ return result;
+}
+
+//----- (01006B38) --------------------------------------------------------
+CHAR *__stdcall Sound_LoadWaveFile(LPCSTR lpName)
+{
+ CHAR *result; // eax
+
+ if ( pMem )
+ result = WaveMixOpenWave(pMem, lpName, dword_1024F60, 1);
+ else
+ result = 0;
+ return result;
+}
+
+//----- (01006B64) --------------------------------------------------------
+LPCVOID __stdcall Sound_FreeSound(LPCVOID pMem)
+{
+ LPCVOID result; // eax
+
+ if ( pMem )
+ {
+ result = ::pMem;
+ if ( ::pMem )
+ result = (LPCVOID)WaveMixFreeWave((int)::pMem, pMem);
+ }
+ return result;
+}
+
+//----- (01006B8A) --------------------------------------------------------
+LPCVOID __stdcall Sound_Deactivate()
+{
+ LPCVOID result; // eax
+
+ result = pMem;
+ if ( pMem )
+ result = (LPCVOID)WaveMixActivate(pMem, 0);
+ return result;
+}
+
+//----- (01006BA1) --------------------------------------------------------
+LPCVOID __stdcall Sound_Activate()
+{
+ LPCVOID result; // eax
+
+ result = pMem;
+ if ( pMem )
+ result = (LPCVOID)WaveMixActivate(pMem, 1);
+ return result;
+}
+
+//----- (01006BB8) --------------------------------------------------------
+int __stdcall Sound_Idle()
+{
+ int result; // eax
+
+ if ( pMem )
+ result = WaveMixPump();
+ return result;
+}
+
+//----- (01006BCC) --------------------------------------------------------
+signed int __stdcall Sound_Flush(signed int a1, int a2)
+{
+ signed int result; // eax
+ int v3; // edi
+ signed int v4; // esi
+
+ if ( pMem )
+ {
+ result = num_channels;
+ v3 = a2;
+ if ( a2 >= num_channels )
+ v3 = num_channels - 1;
+ v4 = a1;
+ if ( a1 >= 0 && v3 < num_channels )
+ {
+ while ( v4 <= v3 )
+ {
+ result = WaveMixFlushChannel(pMem, v4, 0);
+ dword_1024F1C[v4] = 0;
+ dword_1024F3C[v4++] = 0;
+ }
+ }
+ }
+ return result;
+}
+// 1028208: using guessed type int num_channels;
+
+//----- (01006C26) --------------------------------------------------------
+void __stdcall Sound_PlaySound(int a1, int a2, int a3, unsigned __int16 a4, __int16 a5)
+{
+ int v5; // ecx
+ int v6; // edx
+ int v7; // esi
+ int v8; // edx
+ int v9; // esi
+ __int16 v10; // [esp+4h] [ebp-1Ch]
+ LPCVOID v11; // [esp+6h] [ebp-1Ah]
+ int v12; // [esp+Ah] [ebp-16h]
+ int v13; // [esp+Eh] [ebp-12h]
+ HWND v14; // [esp+12h] [ebp-Eh]
+ int v15; // [esp+16h] [ebp-Ah]
+ __int16 v16; // [esp+1Ah] [ebp-6h]
+
+ v5 = a2;
+ v6 = 0;
+ v7 = a2;
+ if ( pMem )
+ {
+ if ( a3 >= num_channels )
+ a3 = num_channels - 1;
+ if ( a1 && a2 >= 0 && a3 < num_channels )
+ {
+ if ( (a4 & 0x8000u) == 0 || num_channels <= 0 )
+ {
+ LABEL_11:
+ if ( a2 < a3 )
+ {
+ v8 = a2;
+ do
+ {
+ if ( (1 << ++v5) & (unsigned __int16)word_1024F18 && dword_1024F1C[v5] < (unsigned int)dword_1024F1C[v8] )
+ {
+ v7 = v5;
+ v8 = v5;
+ }
+ }
+ while ( v5 < a3 );
+ }
+ if ( (1 << v7) & (unsigned __int16)word_1024F18 )
+ {
+ v11 = pMem;
+ v14 = dword_1024F64;
+ v15 = a4;
+ v10 = 28;
+ v16 = a5;
+ v12 = v7;
+ v13 = a1;
+ dword_1024F68(1, a1, v7);
+ v9 = v7;
+ dword_1024F1C[v9] = timeGetTime();
+ dword_1024F3C[v9] = a1;
+ WaveMixPlay((int)&v10);
+ }
+ }
+ else
+ {
+ while ( dword_1024F3C[v6] != a1 )
+ {
+ if ( ++v6 >= num_channels )
+ goto LABEL_11;
+ }
+ }
+ }
+ }
+}
+// 1024F18: using guessed type __int16 word_1024F18;
+// 1024F68: using guessed type int (__stdcall *dword_1024F68)(_DWORD, _DWORD, _DWORD);
+// 1028208: using guessed type int num_channels;
+
+//----- (01006D34) --------------------------------------------------------
+void __stdcall Sound_Enable(signed int a1, int a2, int a3)
+{
+ int v3; // edi
+ signed int v4; // esi
+ signed int v5; // eax
+
+ if ( pMem )
+ {
+ v3 = a2;
+ if ( a2 >= num_channels )
+ v3 = num_channels - 1;
+ v4 = a1;
+ if ( a1 >= 0 && v3 < num_channels )
+ {
+ while ( v4 <= v3 )
+ {
+ v5 = 1 << v4;
+ if ( a3 )
+ {
+ word_1024F18 |= v5;
+ }
+ else
+ {
+ word_1024F18 &= ~(_WORD)v5;
+ Sound_Flush(v4, v4);
+ }
+ ++v4;
+ }
+ }
+ }
+}
+// 1024F18: using guessed type __int16 word_1024F18;
+// 1028208: using guessed type int num_channels;
diff --git a/table.cpp b/table.cpp
new file mode 100644
index 0000000..a8ff144
--- /dev/null
+++ b/table.cpp
@@ -0,0 +1,107 @@
+#include "pinball.h"
+
+
+//----- (0100C0EE) --------------------------------------------------------
+void __userpurge table_set_replay(int a1@, float a2)
+{
+char *v2; // eax
+
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023D0C)(19, 0.0);
+v2 = get_rc_string(0, 0);
+TTextBox::Display(dword_1023E1C, a1, v2, a2);
+}
+// 1023D0C: using guessed type int dword_1023D0C;
+
+//----- (0100C12A) --------------------------------------------------------
+void __usercall table_set_multiball(int a1@)
+{
+char *v1; // eax
+
+v1 = get_rc_string(16, 0);
+TTextBox::Display(dword_1023E1C, a1, v1, 2.0);
+}
+
+//----- (0100C14F) --------------------------------------------------------
+void __usercall table_set_jackpot(int a1@)
+{
+char *v1; // eax
+
+*(_DWORD *)((char *)dword_1025040 + 318) = 1;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ABC)(9, 60.0);
+v1 = get_rc_string(15, 0);
+TTextBox::Display(dword_1023E1C, a1, v1, 2.0);
+}
+// 1023ABC: using guessed type int dword_1023ABC;
+
+//----- (0100C199) --------------------------------------------------------
+void __usercall table_set_bonus(int a1@)
+{
+char *v1; // eax
+
+*(_DWORD *)((char *)dword_1025040 + 310) = 1;
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AC4)(9, 60.0);
+v1 = get_rc_string(4, 0);
+TTextBox::Display(dword_1023E1C, a1, v1, 2.0);
+}
+// 1023AC4: using guessed type int dword_1023AC4;
+
+//----- (0100C1E3) --------------------------------------------------------
+void __usercall table_set_flag_lights(int a1@)
+{
+char *v1; // eax
+
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023940)(9, 60.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_10239D0)(9, 60.0);
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023AB4)(9, 60.0);
+v1 = get_rc_string(51, 0);
+TTextBox::Display(dword_1023E1C, a1, v1, 2.0);
+}
+// 1023940: using guessed type int dword_1023940;
+// 10239D0: using guessed type int dword_10239D0;
+// 1023AB4: using guessed type int dword_1023AB4;
+
+//----- (0100C24A) --------------------------------------------------------
+void __usercall table_set_bonus_hold(int a1@)
+{
+char *v1; // eax
+
+(**(void (__stdcall ***)(signed int, _DWORD))dword_1023ACC)(19, 0.0);
+v1 = get_rc_string(52, 0);
+TTextBox::Display(dword_1023E1C, a1, v1, 2.0);
+}
+// 1023ACC: using guessed type int dword_1023ACC;
+
+//----- (0100C281) --------------------------------------------------------
+void __usercall table_bump_ball_sink_lock(int a1@)
+{
+int v1; // ecx
+char *v2; // eax
+
+v1 = *(_DWORD *)((char *)dword_1025040 + 342);
+if ( v1 == 2 )
+{
+table_set_multiball(a1);
+*(_DWORD *)((char *)dword_1025040 + 342) = 0;
+}
+else
+{
+*(_DWORD *)((char *)dword_1025040 + 342) = v1 + 1;
+(*(void (**)(void))(*(_DWORD *)dword_1023DAC + 20))();
+v2 = get_rc_string(1, 0);
+TTextBox::Display(dword_1023E1C, a1, v2, 2.0);
+(***(void (__stdcall ****)(signed int, _DWORD))((char *)dword_1025040 + 222))(1016, 0.0);
+}
+}
+// 1023DAC: using guessed type int dword_1023DAC;
+
+//----- (0100C2F3) --------------------------------------------------------
+void __userpurge table_add_extra_ball(int a1@, float a2)
+{
+char *v2; // eax
+
+++*(_DWORD *)((char *)dword_1025040 + 334);
+(*(void (**)(void))(*(_DWORD *)dword_1023D44 + 20))();
+v2 = get_rc_string(9, 0);
+TTextBox::Display(dword_1023E1C, a1, v2, a2);
+}
+// 1023D44: using guessed type int dword_1023D44;
\ No newline at end of file
diff --git a/underscore.cpp b/underscore.cpp
new file mode 100644
index 0000000..22ce619
--- /dev/null
+++ b/underscore.cpp
@@ -0,0 +1,154 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "pinball.h"
+
+//----- (01003445) --------------------------------------------------------
+HDC __stdcall _GetDC(HWND hWnd)
+{
+ HDC v1; // eax
+ HDC v2; // esi
+
+ v1 = GetDC(hWnd);
+ v2 = v1;
+ if ( hWnd && GetLayout(v1) & 1 )
+ SetLayout(v2, 0);
+ return v2;
+}
+
+//----- (0100347C) --------------------------------------------------------
+HDC __stdcall _BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint)
+{
+ HDC v2; // eax
+ HDC v3; // esi
+
+ v2 = BeginPaint(hWnd, lpPaint);
+ v3 = v2;
+ if ( hWnd && GetLayout(v2) & 1 )
+ SetLayout(v3, 0);
+ return v3;
+}
+
+//----- (01006498) --------------------------------------------------------
+char __stdcall _lread_char(HFILE hFile)
+{
+ char Buffer; // [esp+1h] [ebp-1h]
+
+ Buffer = 0;
+ _lread(hFile, &Buffer, 1u);
+ return Buffer;
+}
+
+//----- (010064BD) --------------------------------------------------------
+int __stdcall _lread_long(HFILE hFile)
+{
+ int Buffer; // [esp+0h] [ebp-4h]
+
+ Buffer = 0;
+ _lread(hFile, &Buffer, 4u);
+ return Buffer;
+}
+
+
+//----- (01003752) --------------------------------------------------------
+CHAR *__stdcall get_rc_string(__int16 a1, int a2)
+{
+ CHAR *v2; // esi
+
+ v2 = &byte_10248A8[256 * rc_string_slot];
+ if ( !LoadStringA(hinst, a1, &byte_10248A8[256 * rc_string_slot], 255) )
+ *v2 = 0;
+ if ( ++rc_string_slot >= 6 )
+ rc_string_slot = 0;
+ return v2;
+}
+// 1024EA8: using guessed type int rc_string_slot;
+
+//----- (010037A6) --------------------------------------------------------
+int __stdcall get_rc_int(__int16 a1, int *a2)
+{
+ int result; // eax
+ CHAR Buffer; // [esp+4h] [ebp-104h]
+
+ result = LoadStringA(hinst, a1, &Buffer, 255);
+ if ( result )
+ {
+ *a2 = _atoi(&Buffer);
+ result = 1;
+ }
+ return result;
+}
+
+//----- (01012F2A) --------------------------------------------------------
+void __stdcall build_occlude_list()
+{
+struct render_sprite_type_struct *v0; // esi
+signed int v1; // edi
+struct render_sprite_type_struct *v2; // ebx
+int v3; // [esp+4h] [ebp-14h]
+struct render_sprite_type_struct **v4; // [esp+8h] [ebp-10h]
+int i; // [esp+Ch] [ebp-Ch]
+struct render_sprite_type_struct **v6; // [esp+10h] [ebp-8h]
+int v7; // [esp+14h] [ebp-4h]
+
+++memory_critical_allocation;
+v7 = 0;
+v4 = render_sprite_list;
+v3 = 0;
+if ( render_many_sprites > 0 )
+{
+do
+{
+v0 = *v4;
+if ( *((_DWORD *)*v4 + 17) )
+{
+memoryfree(*((_DWORD *)*v4 + 17));
+*((_DWORD *)v0 + 17) = 0;
+*((_DWORD *)v0 + 18) = 0;
+}
+if ( !*((_BYTE *)v0 + 24) && *((_DWORD *)v0 + 21) != -1 )
+{
+if ( !v7 )
+v7 = memoryallocate(0xFA0u);
+v1 = 0;
+v6 = render_sprite_list;
+for ( i = 0; i < render_many_sprites; ++v6 )
+{
+v2 = *v6;
+if ( !*((_BYTE *)*v6 + 24)
+&& *((_DWORD *)v2 + 21) != -1
+&& rectangle_clip((int *)v0 + 19, (int *)v2 + 19, 0)
+&& v7 )
+{
+*(_DWORD *)(v7 + 4 * v1++) = v2;
+}
+++i;
+}
+if ( !*((_BYTE *)v0 + 24) && *((_DWORD *)v0 + 4) && v1 < 2 )
+v1 = 0;
+if ( v1 )
+{
+*((_DWORD *)v0 + 17) = memoryrealloc(v7, 4 * v1);
+*((_DWORD *)v0 + 18) = v1;
+v7 = 0;
+}
+}
+++v3;
+++v4;
+}
+while ( v3 < render_many_sprites );
+if ( v7 )
+memoryfree(v7);
+}
+--memory_critical_allocation;
+}
+// 1024F04: using guessed type int memory_critical_allocation;
+// 1025084: using guessed type struct render_sprite_type_struct **render_sprite_list;
+// 10250B4: using guessed type int render_many_sprites;
+
+//----- (010211B9) --------------------------------------------------------
+unsigned int _setdefaultprecision()
+{
+return _controlfp(0x10000u, 0x30000u);
+}
diff --git a/vectors.cpp b/vectors.cpp
new file mode 100644
index 0000000..c2f817d
--- /dev/null
+++ b/vectors.cpp
@@ -0,0 +1,40 @@
+//----- (0101CB8E) --------------------------------------------------------
+void __stdcall vector_add(struct vector_type *a1, struct vector_type *a2)
+{
+*(float *)a1 = *(float *)a1 + *(float *)a2;
+*((float *)a1 + 1) = *((float *)a2 + 1) + *((float *)a1 + 1);
+}
+
+//----- (0101CCF3) --------------------------------------------------------
+void __stdcall RotateVector(struct vector_type *a1, float a2)
+{
+long double v2; // st7
+long double v3; // st6
+long double v4; // st5
+
+v2 = sin(a2);
+v3 = cos(a2);
+v4 = v3 * *(float *)a1 - v2 * *((float *)a1 + 1);
+*(float *)a1 = v4;
+*((float *)a1 + 1) = v4 * v2 + v3 * *((float *)a1 + 1);
+}
+
+//----- (0101B0A4) --------------------------------------------------------
+void __stdcall vswap(struct vector_type *a1, struct vector_type *a2)
+{
+int v2; // ST08_4
+int v3; // ST0C_4
+int v4; // ST10_4
+_DWORD *v5; // edi
+
+v2 = *(_DWORD *)a1;
+v3 = *((_DWORD *)a1 + 1);
+v4 = *((_DWORD *)a1 + 2);
+*(_DWORD *)a1 = *(_DWORD *)a2;
+v5 = (_DWORD *)((char *)a1 + 4);
+*v5 = *((_DWORD *)a2 + 1);
+v5[1] = *((_DWORD *)a2 + 2);
+*(_DWORD *)a2 = v2;
+*((_DWORD *)a2 + 1) = v3;
+*((_DWORD *)a2 + 2) = v4;
+}
diff --git a/wavemix.cpp b/wavemix.cpp
new file mode 100644
index 0000000..daac4b8
--- /dev/null
+++ b/wavemix.cpp
@@ -0,0 +1,3655 @@
+#include "pinball.h"
+
+//----- (0101CFD0) --------------------------------------------------------
+_WORD *__stdcall SessionToGlobalDataPtr(_WORD *a1)
+{
+if ( a1 && *a1 == 21554 && a1[222] == 21554 )
+return a1;
+MessageBeep(0xFFFFFFFF);
+_wsprintfA(aWavemixV23ByAn, "Invalid session handle 0x%04X passed to WaveMix API", a1);
+MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x30u);
+return 0;
+}
+
+//----- (0101D02C) --------------------------------------------------------
+BOOL __stdcall IsValidLPMIXWAVE(int a1)
+{
+BOOL result; // eax
+
+result = a1;
+if ( a1 )
+result = *(_WORD *)(a1 + 64) == 21554;
+return result;
+}
+
+//----- (0101D04E) --------------------------------------------------------
+bool __stdcall HasCurrentOutputFormat(const void *a1)
+{
+return memcmp(a1, (const void *)(hMem + 380), 0x10u) == 0;
+}
+
+//----- (0101D079) --------------------------------------------------------
+int __stdcall DefaultPauseBlocks(int a1)
+{
+int result; // eax
+
+if ( GetVersion() < 0x80000000 || (unsigned __int8)GetVersion() < 4u )
+result = a1;
+else
+result = 0;
+return result;
+}
+
+//----- (0101D0A5) --------------------------------------------------------
+unsigned int __stdcall DefaultGoodWavePos(UINT_PTR uDeviceID)
+{
+signed int v1; // eax
+unsigned int result; // eax
+struct tagWAVEOUTCAPSA pwoc; // [esp+0h] [ebp-38h]
+
+v1 = waveOutGetNumDevs();
+if ( (signed int)uDeviceID > v1 || (uDeviceID & 0x80000000) != 0 || !v1 || waveOutGetDevCapsA(uDeviceID, &pwoc, 0x34u) )
+result = 0;
+else
+result = ((unsigned int)LOBYTE(pwoc.dwSupport) >> 5) & 1;
+return result;
+}
+
+//----- (0101D0FC) --------------------------------------------------------
+DWORD __stdcall MyWaveOutGetPosition(HWAVEOUT hwo, int a2)
+{
+struct mmtime_tag pmmt; // [esp+0h] [ebp-10h]
+
+if ( !a2 )
+return (timeGetTime() - *(_DWORD *)(hMem + 416)) * *(_DWORD *)(hMem + 388) / 0x3E8 & 0xFFFFFFF8;
+pmmt.wType = 4;
+waveOutGetPosition(hwo, &pmmt, 0xCu);
+return (*(int (__stdcall **)(DWORD, _DWORD))(hMem + 436))(pmmt.u.ms, *(_DWORD *)(hMem + 424));
+}
+
+//----- (0101D178) --------------------------------------------------------
+int __stdcall AddFactor(int a1, int a2)
+{
+return a1 + a2;
+}
+
+//----- (0101D18E) --------------------------------------------------------
+int __stdcall SubFactor(int a1, int a2)
+{
+return a1 - a2;
+}
+
+//----- (0101D1A2) --------------------------------------------------------
+unsigned int __stdcall SetWaveOutPosition(unsigned int a1)
+{
+LPARAM v1; // eax
+HWAVEOUT v2; // ecx
+DWORD v3; // ecx
+DWORD v4; // eax
+LPARAM v5; // ecx
+DWORD v6; // edi
+unsigned int result; // eax
+struct mmtime_tag pmmt; // [esp+0h] [ebp-10h]
+
+v1 = hMem;
+v2 = *(HWAVEOUT *)(hMem + 12);
+pmmt.wType = 4;
+if ( v2 )
+{
+waveOutGetPosition(v2, &pmmt, 0xCu);
+v3 = pmmt.u.ms;
+v1 = hMem;
+}
+else
+{
+v3 = 0;
+pmmt.u.ms = 0;
+}
+if ( v3 < a1 )
+{
+*(_DWORD *)(v1 + 424) = a1 - v3;
+*(_DWORD *)(v1 + 436) = AddFactor;
+}
+else
+{
+*(_DWORD *)(v1 + 424) = v3 - a1;
+*(_DWORD *)(v1 + 436) = SubFactor;
+}
+v4 = timeGetTime();
+v5 = hMem;
+v6 = v4;
+result = 1000 * a1 / *(_DWORD *)(hMem + 388);
+*(_DWORD *)(hMem + 412) = a1;
+*(_DWORD *)(v5 + 416) = v6 - result;
+return result;
+}
+
+//----- (0101D251) --------------------------------------------------------
+unsigned int __stdcall MyWaveOutReset(HWAVEOUT hwo)
+{
+unsigned int v1; // esi
+
+v1 = MyWaveOutGetPosition(hwo, *(_DWORD *)(hMem + 420));
+waveOutReset(hwo);
+return SetWaveOutPosition(v1);
+}
+
+//----- (0101D285) --------------------------------------------------------
+__int16 __stdcall cmixit(_BYTE *a1, char *a2, char *a3, int a4, unsigned __int16 a5)
+{
+int v5; // eax
+unsigned __int8 *v6; // esi
+_BYTE *v7; // edi
+int v8; // ecx
+int v9; // edx
+_BYTE *v10; // edi
+unsigned __int8 *v11; // esi
+int v12; // edx
+int v13; // ebx
+unsigned __int16 *v14; // eax
+int v15; // ecx
+unsigned __int8 *v16; // ecx
+int v17; // ecx
+bool v18; // zf
+unsigned __int8 *v19; // esi
+int v20; // edi
+_BYTE *v21; // ecx
+int v22; // ebx
+unsigned __int16 *v23; // ecx
+int v24; // eax
+int v26; // [esp+10h] [ebp-8h]
+int v27; // [esp+10h] [ebp-8h]
+unsigned __int16 v28; // [esp+14h] [ebp-4h]
+unsigned __int16 v29; // [esp+14h] [ebp-4h]
+int v30; // [esp+30h] [ebp+18h]
+int v31; // [esp+30h] [ebp+18h]
+
+LOWORD(v5) = hMem;
+if ( *(_WORD *)(hMem + 382) == 2 )
+{
+if ( a4 == 1 )
+{
+v6 = *(unsigned __int8 **)a2;
+LOWORD(v5) = (_WORD)a3;
+if ( a5 )
+{
+v7 = a1;
+v5 = *(unsigned __int16 *)a3 << 8;
+v8 = *((unsigned __int16 *)a3 + 1) << 8;
+v9 = (unsigned __int16)(((unsigned __int16)(a5 - 1) >> 1) + 1);
+do
+{
+*v7 = byte_1025970[*v6 + v5];
+v10 = v7 + 1;
+v11 = v6 + 1;
+*v10 = byte_1025970[*v11 + v8];
+v7 = v10 + 1;
+v6 = v11 + 1;
+--v9;
+}
+while ( v9 );
+}
+}
+else
+{
+v28 = 0;
+LOWORD(v5) = a5;
+if ( a5 )
+{
+v26 = (unsigned __int16)(((unsigned __int16)(a5 - 1) >> 1) + 1);
+do
+{
+v12 = 128;
+v13 = 128;
+if ( a4 > 0 )
+{
+v14 = (unsigned __int16 *)a3;
+v15 = a2 - a3;
+v30 = a4;
+while ( 1 )
+{
+v16 = (unsigned __int8 *)(*(_DWORD *)((char *)v14 + v15) + v28);
+v13 = v13 + (unsigned __int8)byte_1025970[256 * *v14 + *v16] - 128;
+v17 = (unsigned __int8)byte_1025970[256 * v14[1] + v16[1]];
+v14 += 2;
+v18 = v30-- == 1;
+v12 = v12 + v17 - 128;
+if ( v18 )
+break;
+v15 = a2 - a3;
+}
+if ( v13 >= 0 )
+{
+if ( v13 > 255 )
+LOBYTE(v13) = -1;
+}
+else
+{
+LOBYTE(v13) = 0;
+}
+if ( v12 >= 0 )
+{
+if ( v12 > 255 )
+LOBYTE(v12) = -1;
+}
+else
+{
+LOBYTE(v12) = 0;
+}
+}
+v28 += 2;
+*a1 = v13;
+a1[1] = v12;
+LOWORD(v5) = (_WORD)a1 + 2;
+v18 = v26-- == 1;
+a1 += 2;
+}
+while ( !v18 );
+}
+}
+}
+else if ( a4 == 1 )
+{
+v19 = *(unsigned __int8 **)a2;
+v5 = (*(unsigned __int16 *)a3 + *((unsigned __int16 *)a3 + 1)) / 2;
+if ( a5 )
+{
+v20 = a5;
+v21 = a1;
+v5 = (unsigned __int16)v5 << 8;
+do
+{
+*v21++ = byte_1025970[*v19++ + v5];
+--v20;
+}
+while ( v20 );
+}
+}
+else
+{
+v29 = 0;
+if ( a5 )
+{
+v27 = a5;
+do
+{
+v22 = 128;
+if ( a4 > 0 )
+{
+v23 = (unsigned __int16 *)a3;
+v31 = a4;
+do
+{
+v24 = (unsigned __int8)byte_1025970[256 * (unsigned __int16)((*v23 + v23[1]) / 2)
++ *(unsigned __int8 *)(*(_DWORD *)((char *)v23 + a2 - a3) + v29)];
+v23 += 2;
+v18 = v31-- == 1;
+v22 = v22 + v24 - 128;
+}
+while ( !v18 );
+if ( v22 >= 0 )
+{
+if ( v22 > 255 )
+LOBYTE(v22) = -1;
+}
+else
+{
+LOBYTE(v22) = 0;
+}
+}
+v5 = (int)a1++;
+++v29;
+v18 = v27-- == 1;
+*(_BYTE *)v5 = v22;
+}
+while ( !v18 );
+}
+}
+return v5;
+}
+
+//----- (0101D491) --------------------------------------------------------
+_DWORD *__stdcall InitChannelNodes()
+{
+_DWORD *result; // eax
+
+result = &unk_1026470;
+do
+{
+*result = result + 15;
+result += 15;
+}
+while ( (signed int)result < (signed int)&unk_1027B68 );
+dword_1027BA4 = 0;
+dword_1025964 = (int)&unk_1026470;
+return result;
+}
+// 1025964: using guessed type int dword_1025964;
+// 1027BA4: using guessed type int dword_1027BA4;
+
+//----- (0101D4B9) --------------------------------------------------------
+int __stdcall GetChannelNode()
+{
+int result; // eax
+int v1; // ecx
+
+result = dword_1025964;
+if ( dword_1025964 )
+{
+v1 = *(_DWORD *)dword_1025964;
+*(_DWORD *)dword_1025964 = 0;
+dword_1025964 = v1;
+}
+return result;
+}
+// 1025964: using guessed type int dword_1025964;
+
+//----- (0101D4D4) --------------------------------------------------------
+_DWORD *__stdcall FreeChannelNode(_DWORD *a1)
+{
+_DWORD *result; // eax
+
+result = a1;
+if ( a1 )
+{
+*a1 = dword_1025964;
+dword_1025964 = (int)a1;
+}
+return result;
+}
+// 1025964: using guessed type int dword_1025964;
+
+//----- (0101D4F6) --------------------------------------------------------
+struct wavehdr_tag *__stdcall FreeWaveBlocks(HWAVEOUT hwo, int a2)
+{
+signed int v2; // ebx
+LPCVOID *v3; // esi
+struct wavehdr_tag *result; // eax
+HGLOBAL v5; // eax
+HGLOBAL v6; // eax
+
+v2 = 0;
+do
+{
+v3 = (LPCVOID *)(a2 + 4 * v2);
+result = (struct wavehdr_tag *)*v3;
+if ( *v3 )
+{
+waveOutUnprepareHeader(hwo, result, 0x20u);
+v5 = GlobalHandle(*v3);
+GlobalUnlock(v5);
+v6 = GlobalHandle(*v3);
+result = (struct wavehdr_tag *)GlobalFree(v6);
+*v3 = 0;
+}
+++v2;
+}
+while ( v2 < 10 );
+return result;
+}
+
+//----- (0101D549) --------------------------------------------------------
+int __stdcall AllocWaveBlocks(HWAVEOUT hwo, int a2)
+{
+signed int v2; // edi
+HGLOBAL v3; // eax
+_DWORD *v4; // eax
+int v5; // ecx
+signed int v6; // edi
+int i; // edi
+HGLOBAL v9; // eax
+HGLOBAL v10; // eax
+
+v2 = 0;
+do
+{
+v3 = GlobalAlloc(0x2000u, 0x2B41u);
+v4 = GlobalLock(v3);
+v5 = a2 + 4 * v2;
+*(_DWORD *)v5 = v4;
+if ( !v4 )
+{
+if ( dword_1027BE4 )
+MessageBoxA(
+0,
+"Unable to allocate memory for waveform data. Try making more memory available by closing other applications.",
+"WavMix32",
+0x30u);
+for ( i = v2 - 1; i >= 0; --i )
+{
+v9 = GlobalHandle(*(LPCVOID *)(a2 + 4 * i));
+GlobalUnlock(v9);
+v10 = GlobalHandle(*(LPCVOID *)(a2 + 4 * i));
+GlobalFree(v10);
+*(_DWORD *)(a2 + 4 * i) = 0;
+}
+return 0;
+}
+*v4 = v4 + 12;
+*(_DWORD *)(*(_DWORD *)v5 + 4) = *(_DWORD *)(hMem + 396);
+*(_DWORD *)(*(_DWORD *)v5 + 16) = 0;
+*(_DWORD *)(*(_DWORD *)v5 + 20) = 0;
+*(_DWORD *)(*(_DWORD *)v5 + 32) = 1;
+++v2;
+*(_DWORD *)(*(_DWORD *)v5 + 36) = 0;
+}
+while ( v2 < 10 );
+v6 = 0;
+while ( !waveOutPrepareHeader(hwo, *(LPWAVEHDR *)(a2 + 4 * v6), 0x20u) )
+{
+*(_DWORD *)(*(_DWORD *)(a2 + 4 * v6++) + 16) |= 1u;
+if ( v6 >= 10 )
+return 1;
+}
+if ( dword_1027BE4 )
+MessageBoxA(0, "Unable to prepare wave header.", "WavMix32", 0x30u);
+FreeWaveBlocks(hwo, a2);
+return 0;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (0101D649) --------------------------------------------------------
+_DWORD *__stdcall SwapWaveBlocks()
+{
+_DWORD *result; // eax
+
+result = (_DWORD *)(hMem + 408);
+if ( *(_UNKNOWN **)(hMem + 408) == &unk_10257E4 )
+*result = &unk_1025770;
+else
+*result = &unk_10257E4;
+return result;
+}
+
+//----- (0101D66B) --------------------------------------------------------
+_DWORD *__stdcall GetWaveBlock()
+{
+int v0; // edx
+int v1; // eax
+int v2; // esi
+_DWORD *result; // eax
+int v4; // ecx
+
+v0 = *(_DWORD *)(hMem + 400);
+v1 = 0;
+if ( v0 > 0 )
+{
+v2 = *(_DWORD *)(hMem + 408);
+do
+{
+if ( *(_DWORD *)(*(_DWORD *)v2 + 32) )
+break;
+++v1;
+v2 += 4;
+}
+while ( v1 < v0 );
+}
+if ( v1 >= v0 )
+return 0;
+v4 = *(_DWORD *)(hMem + 396);
+result = *(_DWORD **)(*(_DWORD *)(hMem + 408) + 4 * v1);
+result[8] = 0;
+result[1] = v4;
+*result = result + 12;
+result[10] = dword_1025798;
+return result;
+}
+// 1025798: using guessed type int dword_1025798;
+
+//----- (0101D6C8) --------------------------------------------------------
+struct wavehdr_tag *__stdcall RemoveFromPlayingQueue(struct wavehdr_tag *a1)
+{
+struct wavehdr_tag *result; // eax
+LPWAVEHDR v2; // edx
+DWORD v3; // ecx
+bool v4; // zf
+
+if ( !pwh )
+return 0;
+result = a1;
+if ( a1 != pwh )
+{
+v2 = pwh;
+v3 = pwh[1].dwUser;
+if ( v3 )
+{
+do
+{
+if ( (struct wavehdr_tag *)v3 == a1 )
+break;
+v2 = (LPWAVEHDR)v3;
+v3 = *(_DWORD *)(v3 + 44);
+}
+while ( v3 );
+if ( v3 )
+{
+v4 = v3 == dword_1027BF0;
+v2[1].dwUser = *(_DWORD *)(v3 + 44);
+if ( v4 )
+dword_1027BF0 = (int)v2;
+goto LABEL_12;
+}
+}
+return 0;
+}
+pwh = (LPWAVEHDR)a1[1].dwUser;
+if ( !pwh )
+dword_1027BF0 = 0;
+LABEL_12:
+a1[1].dwUser = 0;
+return result;
+}
+// 1027BF0: using guessed type int dword_1027BF0;
+
+//----- (0101D734) --------------------------------------------------------
+LPWAVEHDR __stdcall DestroyPlayQueue()
+{
+struct wavehdr_tag *v0; // ST00_4
+LPWAVEHDR result; // eax
+
+while ( 1 )
+{
+result = pwh;
+if ( !pwh )
+break;
+v0 = pwh;
+pwh[1].lpData = (LPSTR)1;
+RemoveFromPlayingQueue(v0);
+}
+return result;
+}
+
+//----- (0101D752) --------------------------------------------------------
+int __stdcall ReleaseWaveDevice(int a1)
+{
+int result; // eax
+HWND v2; // ST04_4
+
+if ( *(_DWORD *)(a1 + 16) )
+{
+result = *(_DWORD *)(a1 + 12);
+if ( result )
+{
+MyWaveOutReset(*(HWAVEOUT *)(a1 + 12));
+DestroyPlayQueue();
+FreeWaveBlocks(*(HWAVEOUT *)(a1 + 12), (int)&unk_10257E4);
+FreeWaveBlocks(*(HWAVEOUT *)(a1 + 12), (int)&unk_1025770);
+waveOutClose(*(HWAVEOUT *)(a1 + 12));
+v2 = *(HWND *)(a1 + 4);
+*(_DWORD *)(a1 + 12) = 0;
+result = DestroyWindow(v2);
+*(_DWORD *)(a1 + 4) = 0;
+}
+}
+return result;
+}
+
+//----- (0101D7B1) --------------------------------------------------------
+signed int __stdcall GetWaveDevice()
+{
+HWND v0; // eax
+LPARAM v1; // ecx
+MMRESULT v2; // edi
+HWND v4; // ST2C_4
+WAVEFORMATEX pwfx; // [esp+Ch] [ebp-14h]
+
+if ( *(_DWORD *)(hMem + 12) )
+return 0;
+v0 = CreateWindowExA(0, "WavMix32", WindowName, 0x8000000u, 0, 0, 0, 0, 0, 0, dword_10257E0, 0);
+v1 = hMem;
+*(_DWORD *)(hMem + 4) = v0;
+if ( !v0 )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "Failed to create callback window.", "WavMix32", 0x30u);
+return 1;
+}
+pwfx.wFormatTag = *(_WORD *)(v1 + 380);
+pwfx.nChannels = *(_WORD *)(v1 + 382);
+pwfx.nSamplesPerSec = *(_DWORD *)(v1 + 384);
+pwfx.nAvgBytesPerSec = *(_DWORD *)(v1 + 388);
+pwfx.nBlockAlign = *(_WORD *)(v1 + 392);
+pwfx.wBitsPerSample = *(_WORD *)(v1 + 394);
+pwfx.cbSize = 0;
+v2 = waveOutOpen((LPHWAVEOUT)(v1 + 12), 0xFFFFFFFF, &pwfx, *(_DWORD *)(v1 + 4), 0, 0x10000u);
+if ( v2 )
+{
+DestroyWindow(*(HWND *)(hMem + 4));
+*(_DWORD *)(hMem + 4) = 0;
+return v2;
+}
+if ( AllocWaveBlocks(*(HWAVEOUT *)(hMem + 12), (int)&unk_10257E4)
+&& AllocWaveBlocks(*(HWAVEOUT *)(hMem + 12), (int)&unk_1025770) )
+{
+*(_DWORD *)(hMem + 408) = &unk_10257E4;
+return 0;
+}
+FreeWaveBlocks(*(HWAVEOUT *)(hMem + 12), (int)&unk_10257E4);
+FreeWaveBlocks(*(HWAVEOUT *)(hMem + 12), (int)&unk_1025770);
+waveOutClose(*(HWAVEOUT *)(hMem + 12));
+v4 = *(HWND *)(hMem + 4);
+*(_DWORD *)(hMem + 12) = 0;
+DestroyWindow(v4);
+return 1;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (0101D918) --------------------------------------------------------
+signed int __stdcall WaveMixOpenChannel(_WORD *a1, signed int a2, unsigned int a3)
+{
+_WORD *v3; // eax
+signed int v4; // ecx
+int v6; // ecx
+_DWORD *v7; // edx
+int v8; // ecx
+_DWORD *v9; // edx
+
+v3 = SessionToGlobalDataPtr(a1);
+hMem = (LPARAM)v3;
+if ( !v3 )
+return 5;
+if ( a3 > 2 )
+return 10;
+v4 = a2;
+if ( a3 )
+{
+if ( a3 == 2 && (a2 > 16 || a2 < 1) )
+return 11;
+}
+else if ( a2 >= 16 )
+{
+return 11;
+}
+if ( a3 )
+{
+if ( a3 == 1 )
+{
+v4 = 16;
+}
+else if ( a3 != 2 )
+{
+return 10;
+}
+v6 = v4 - 1;
+if ( v6 >= 0 )
+{
+v7 = &v3[2 * v6 + 122];
+v8 = v6 + 1;
+do
+{
+if ( *v7 == -1 )
+{
+*v7 = 0;
+*((_WORD *)v7 - 32) = v3[88];
+*((_WORD *)v7 - 31) = v3[89];
+++*((_DWORD *)v3 + 77);
+}
+--v7;
+--v8;
+}
+while ( v8 );
+}
+}
+else
+{
+v9 = &v3[2 * a2 + 122];
+if ( *v9 != -1 )
+return 4;
+*v9 = 0;
+v3[2 * a2 + 90] = v3[88];
+v3[2 * a2 + 91] = v3[89];
+++*((_DWORD *)v3 + 77);
+}
+return 0;
+}
+
+//----- (0101D9E7) --------------------------------------------------------
+LPWAVEHDR __stdcall AddToPlayingQueue(struct wavehdr_tag *a1)
+{
+LPWAVEHDR result; // eax
+
+result = pwh;
+a1[1].dwUser = 0;
+if ( result )
+{
+*(_DWORD *)(dword_1027BF0 + 44) = a1;
+}
+else
+{
+result = a1;
+pwh = a1;
+}
+dword_1027BF0 = (int)a1;
+return result;
+}
+// 1027BF0: using guessed type int dword_1027BF0;
+
+//----- (0101DA1D) --------------------------------------------------------
+int __stdcall MixerPlay(LPWAVEHDR pwh, int a2)
+{
+LPWAVEHDR v2; // edi
+LPARAM v4; // esi
+_DWORD *v5; // ecx
+signed int v6; // ebx
+_DWORD *v7; // eax
+int v8; // edx
+unsigned int v9; // ebx
+int v10; // eax
+unsigned int v11; // ecx
+int v12; // edi
+unsigned int v13; // eax
+unsigned int v14; // edx
+unsigned int v15; // ebx
+int v16; // eax
+unsigned int v17; // eax
+int v18; // eax
+int v19; // edx
+int v20; // edi
+unsigned int v21; // edx
+int *v22; // eax
+int v23; // ecx
+bool v24; // zf
+unsigned int v25; // [esp+4h] [ebp-1Ch]
+unsigned int v26; // [esp+8h] [ebp-18h]
+int v27; // [esp+Ch] [ebp-14h]
+LPSTR v28; // [esp+10h] [ebp-10h]
+int v29; // [esp+14h] [ebp-Ch]
+unsigned int v30; // [esp+18h] [ebp-8h]
+unsigned int v31; // [esp+1Ch] [ebp-4h]
+
+v2 = pwh;
+if ( !pwh )
+return 0;
+v30 = -1;
+v31 = 0;
+v4 = hMem;
+v5 = (_DWORD *)(hMem + 244);
+v6 = 16;
+do
+{
+v7 = (_DWORD *)*v5;
+if ( *v5 != -1 && v7 )
+{
+do
+{
+if ( v7[11] > *(_DWORD *)(v4 + 412) )
+break;
+v7 = (_DWORD *)*v7;
+}
+while ( v7 );
+if ( v7 )
+{
+if ( v7[10] < v30 )
+v30 = v7[10];
+v8 = v31++;
+dword_1025730[v8] = (int)v7;
+}
+}
+++v5;
+--v6;
+}
+while ( v6 );
+if ( !v31 )
+{
+if ( a2 )
+pwh[1].lpData = (LPSTR)1;
+return 0;
+}
+v9 = *(_DWORD *)(v4 + 412);
+v28 = pwh->lpData;
+LOWORD(v10) = *(_WORD *)(v4 + 396);
+v25 = *(_DWORD *)(v4 + 412);
+v27 = *(unsigned __int16 *)(v4 + 396);
+while ( (_WORD)v10 )
+{
+if ( v9 >= v30 )
+{
+v26 = 0;
+v29 = 0;
+v11 = v9 + (unsigned __int16)v10;
+if ( !v31 )
+goto LABEL_47;
+do
+{
+v12 = dword_1025730[v26];
+v13 = *(_DWORD *)(v12 + 40);
+if ( v13 <= v9 )
+{
+if ( *(_DWORD *)(v12 + 44) < v11 )
+v11 = *(_DWORD *)(v12 + 44);
+v14 = v9 - v13;
+if ( *(_WORD *)(v12 + 26) )
+{
+v15 = *(_DWORD *)(v12 + 36);
+v14 %= v15;
+v16 = v15 - v14;
+v9 = v25;
+v17 = v25 + v16;
+if ( v17 < v11 )
+v11 = v17;
+}
+v18 = v14 + *(_DWORD *)(v12 + 48);
+v19 = v29++;
+dword_10257A0[v19] = v18;
+word_1025810[2 * v19] = *(_WORD *)(v12 + 56);
+word_1025812[2 * v19] = *(_WORD *)(v12 + 58);
+}
+else if ( v13 < v11 )
+{
+v11 = *(_DWORD *)(v12 + 40);
+}
+++v26;
+}
+while ( v26 < v31 );
+if ( v29 )
+{
+v20 = v11 - v9;
+(*(void (__stdcall **)(LPSTR, int *, __int16 *, int, unsigned int))(v4 + 428))(
+v28,
+dword_10257A0,
+word_1025810,
+v29,
+v11 - v9);
+v28 += v20;
+v27 -= v20;
+v30 = -1;
+v9 += v20;
+v25 = v9;
+v21 = 0;
+v22 = dword_1025730;
+do
+{
+if ( !*v22 )
+goto LABEL_57;
+do
+{
+if ( *(_DWORD *)(*v22 + 44) > v9 )
+break;
+v23 = *(_DWORD *)*v22;
+*v22 = v23;
+}
+while ( v23 );
+if ( *v22 )
+{
+if ( *(_DWORD *)(*v22 + 40) < v30 )
+v30 = *(_DWORD *)(*v22 + 40);
+++v21;
+++v22;
+}
+else
+{
+LABEL_57:
+v24 = v31-- == 1;
+*v22 = dword_1025730[v31];
+if ( v24 )
+break;
+}
+}
+while ( v21 < v31 );
+v4 = hMem;
+}
+}
+else
+{
+v10 = (unsigned __int16)v10;
+if ( (unsigned __int16)v10 + v9 >= v30 )
+v10 = v30 - v9;
+memset(v28, 0x80u, (unsigned __int16)v10);
+v28 += v10;
+v9 += v10;
+v27 -= v10;
+v25 = v9;
+}
+v2 = pwh;
+LABEL_47:
+LOWORD(v10) = v27;
+}
+v2[1].dwBufferLength = *(_DWORD *)(v4 + 412);
+*(_DWORD *)(v4 + 412) += *(_DWORD *)(v4 + 396);
+if ( a2 )
+{
+AddToPlayingQueue(v2);
+if ( waveOutWrite(*(HWAVEOUT *)(v4 + 12), v2, 0x20u) )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "Failed to write block to device", "WavMix32", 0x30u);
+v2[1].lpData = (LPSTR)1;
+RemoveFromPlayingQueue(v2);
+}
+}
+return 1;
+}
+// 1025810: using guessed type __int16 word_1025810[];
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (0101DC8C) --------------------------------------------------------
+DWORD __stdcall FreePlayedBlocks()
+{
+DWORD result; // eax
+LPARAM v1; // esi
+signed int v2; // ebx
+_DWORD *v3; // edi
+HWND v4; // eax
+signed int v5; // edi
+DWORD v6; // [esp+Ch] [ebp-8h]
+WPARAM wParam; // [esp+10h] [ebp-4h]
+
+result = MyWaveOutGetPosition(*(HWAVEOUT *)(hMem + 12), *(_DWORD *)(hMem + 420));
+wParam = 0;
+v1 = hMem;
+v6 = result;
+v2 = 244;
+do
+{
+v3 = *(_DWORD **)(v2 + v1);
+if ( v3 && v3 != (_DWORD *)-1 )
+{
+do
+{
+result = v6;
+if ( v6 < v3[11] )
+break;
+*(_DWORD *)(v2 + v1) = *v3;
+v4 = *(HWND *)((char *)v3 + 18);
+if ( v4 )
+{
+PostMessageA(v4, 0x3BDu, wParam, v3[8]);
+v1 = hMem;
+}
+result = (DWORD)FreeChannelNode(v3);
+v3 = *(_DWORD **)(v2 + v1);
+}
+while ( v3 );
+}
+++wParam;
+v2 += 4;
+}
+while ( v2 < 308 );
+if ( !*(_DWORD *)(v1 + 420) && !pwh )
+{
+v5 = 244;
+do
+{
+result = *(_DWORD *)(v5 + v1);
+if ( result )
+{
+if ( result != -1 )
+{
+result = PostMessageA(*(HWND *)(v1 + 4), 0x400u, 0, v1);
+v1 = hMem;
+}
+}
+v5 += 4;
+}
+while ( v5 < 308 );
+}
+return result;
+}
+
+//----- (0101DD5D) --------------------------------------------------------
+int __stdcall WaveMixPump()
+{
+int result; // eax
+LPWAVEHDR i; // esi
+struct wavehdr_tag *v2; // eax
+
+result = dword_1025798;
+hMem = dword_1025798;
+if ( dword_1025798 )
+{
+LABEL_5:
+for ( i = pwh; i; i = (LPWAVEHDR)i[1].dwUser )
+{
+if ( i->dwFlags & 1 )
+{
+RemoveFromPlayingQueue(i);
+i[1].lpData = (LPSTR)1;
+goto LABEL_5;
+}
+}
+FreePlayedBlocks();
+do
+{
+v2 = (struct wavehdr_tag *)GetWaveBlock();
+result = MixerPlay(v2, 1);
+}
+while ( result );
+}
+return result;
+}
+// 1025798: using guessed type int dword_1025798;
+
+//----- (0101DDAD) --------------------------------------------------------
+LRESULT __stdcall WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+if ( Msg != 957 && Msg != 1024 )
+return DefWindowProcA(hWnd, Msg, wParam, lParam);
+WaveMixPump();
+return 0;
+}
+
+//----- (0101DDD8) --------------------------------------------------------
+signed int __stdcall NoResetRemix(int a1, int a2)
+{
+WaveMixPump();
+return 1;
+}
+
+//----- (0101DDE8) --------------------------------------------------------
+signed int __stdcall ResetRemix(int a1, int a2)
+{
+struct wavehdr_tag *v2; // eax
+struct wavehdr_tag *v3; // esi
+int v4; // esi
+LPARAM v5; // eax
+bool v6; // zf
+bool v7; // sf
+LPWAVEHDR i; // esi
+signed int v10; // [esp+Ch] [ebp-8h]
+int v11; // [esp+10h] [ebp-4h]
+
+v10 = 0;
+v11 = 0;
+*(_DWORD *)(hMem + 412) = a1;
+DestroyPlayQueue();
+SwapWaveBlocks();
+while ( 1 )
+{
+v2 = (struct wavehdr_tag *)GetWaveBlock();
+v3 = v2;
+if ( !v2 )
+break;
+if ( !MixerPlay(v2, 0) )
+{
+v3[1].lpData = (LPSTR)1;
+break;
+}
+AddToPlayingQueue(v3);
+}
+v4 = *(_DWORD *)(hMem + 412);
+MyWaveOutReset(*(HWAVEOUT *)(hMem + 12));
+v5 = hMem;
+v6 = *(_DWORD *)(hMem + 404) == 0;
+v7 = *(_DWORD *)(hMem + 404) < 0;
+*(_DWORD *)(hMem + 412) = v4;
+if ( !v7 && !v6 )
+{
+waveOutPause(*(HWAVEOUT *)(v5 + 12));
+v5 = hMem;
+v10 = 1;
+v11 = 0;
+}
+for ( i = pwh; i; i = (LPWAVEHDR)i[1].dwUser )
+{
+if ( waveOutWrite(*(HWAVEOUT *)(v5 + 12), i, 0x20u) )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "Failed to write block to device", "WavMix32", 0x30u);
+i[1].lpData = (LPSTR)1;
+RemoveFromPlayingQueue(i);
+}
+v5 = hMem;
+if ( v10 )
+{
+if ( ++v11 >= *(_DWORD *)(hMem + 404) )
+{
+waveOutRestart(*(HWAVEOUT *)(hMem + 12));
+v5 = hMem;
+v10 = 0;
+}
+}
+}
+if ( v10 )
+waveOutRestart(*(HWAVEOUT *)(v5 + 12));
+return 1;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (0101DF07) --------------------------------------------------------
+void __stdcall ResetWavePosIfNoChannelData()
+{
+signed int v0; // edx
+_DWORD *v1; // eax
+
+if ( !pwh )
+{
+v0 = 0;
+v1 = (_DWORD *)(hMem + 244);
+while ( !*v1 || *v1 == -1 )
+{
+++v0;
+++v1;
+if ( v0 >= 16 )
+{
+SetWaveOutPosition(0);
+return;
+}
+}
+}
+}
+
+//----- (0101DF3D) --------------------------------------------------------
+signed int __stdcall WaveMixPlay(int a1)
+{
+_WORD *v1; // ebx
+const void *v2; // edi
+int v3; // eax
+signed int v4; // edx
+signed int v5; // ecx
+_DWORD *v6; // eax
+bool v7; // zf
+int v8; // eax
+int v9; // edx
+int v10; // ecx
+int v11; // ecx
+int v12; // esi
+_DWORD **v13; // ebx
+LPARAM v14; // esi
+DWORD v15; // eax
+_DWORD *v16; // eax
+_DWORD *v17; // edi
+int v18; // ecx
+int v19; // eax
+__int16 v20; // bx
+_DWORD **v21; // ebx
+_DWORD *i; // eax
+_DWORD *v23; // ST24_4
+DWORD v24; // eax
+_DWORD *v25; // ecx
+_DWORD *v26; // eax
+DWORD v27; // eax
+unsigned __int16 v28; // ax
+int v29; // ebx
+signed int v30; // edi
+struct wavehdr_tag *v31; // eax
+int j; // eax
+struct wavehdr_tag *v33; // eax
+const CHAR *v35; // [esp-14h] [ebp-24h]
+signed int v36; // [esp+8h] [ebp-8h]
+signed int v37; // [esp+Ch] [ebp-4h]
+DWORD v38; // [esp+18h] [ebp+8h]
+
+++dword_1027BF8;
+v37 = 12;
+v36 = 0;
+if ( dword_1027BF8 > 1 )
+goto LABEL_97;
+if ( !a1 )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "NULL parameters pointer passed to WaveMixPlay!", "WavMix32", 0x30u);
+v37 = 5;
+goto LABEL_97;
+}
+v1 = SessionToGlobalDataPtr(*(_WORD **)(a1 + 2));
+hMem = (LPARAM)v1;
+if ( !v1 )
+{
+if ( !dword_1027BE4 )
+{
+LABEL_10:
+v37 = 5;
+goto LABEL_97;
+}
+v35 = "Invalid session handle passed to WaveMixPlay";
+LABEL_9:
+MessageBoxA(0, v35, "WavMix32", 0x30u);
+goto LABEL_10;
+}
+v2 = *(const void **)(a1 + 10);
+if ( !IsValidLPMIXWAVE(*(_DWORD *)(a1 + 10)) )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "Invalid or NULL wave pointer passed to WaveMixPlay!", "WavMix32", 0x30u);
+goto LABEL_10;
+}
+LOBYTE(v3) = HasCurrentOutputFormat(v2);
+if ( !v3 )
+{
+_wsprintfA(
+aWavemixV23ByAn,
+"The LPMIXWAVE 0x%lx is not in the current output format, close the wave and reopen it.",
+v2);
+if ( dword_1027BE4 )
+MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x30u);
+v37 = 8;
+goto LABEL_97;
+}
+if ( *((_DWORD *)v1 + 4) )
+{
+if ( !*((_DWORD *)v1 + 77) )
+{
+if ( !dword_1027BE4 )
+goto LABEL_10;
+v35 = "You must open a channel before you can play a wave!";
+goto LABEL_9;
+}
+if ( *(_BYTE *)(a1 + 18) & 2 )
+{
+v4 = 0;
+v5 = 0;
+v6 = v1 + 156;
+do
+{
+if ( *(v6 - 17) != -1 )
+{
+if ( !*(_DWORD *)&v1[2 * v4 + 122] )
+break;
+if ( v5 != v4 && *v6 < *(_DWORD *)&v1[2 * v4 + 156] )
+v4 = v5;
+}
+++v5;
+++v6;
+}
+while ( v5 < 16 );
+*(_DWORD *)(a1 + 6) = v4;
+}
+else
+{
+v4 = *(_DWORD *)(a1 + 6);
+}
+++*((_DWORD *)v1 + 94);
+v7 = *(_DWORD *)&v1[2 * v4 + 122] == -1;
+*(_DWORD *)&v1[2 * v4 + 156] = *((_DWORD *)v1 + 94);
+if ( v7 )
+goto LABEL_10;
+v8 = GetChannelNode();
+if ( !v8 )
+goto LABEL_97;
+qmemcpy((void *)(v8 + 4), (const void *)a1, 0x1Cu);
+v10 = *(_DWORD *)(v8 + 14);
+*(_DWORD *)(v8 + 32) = v10;
+*(_DWORD *)(v8 + 36) = *(_DWORD *)(v10 + 20);
+v11 = *(_DWORD *)(v10 + 16);
+*(_DWORD *)(v8 + 48) = v11;
+v12 = (unsigned __int16)v1[196];
+v13 = (_DWORD **)(v1 + 220);
+*(_DWORD *)(v8 + 52) = *(_DWORD *)(v8 + 36) + v11 - v12;
+*(_DWORD *)(v8 + 10) = v9;
+if ( *v13 )
+{
+*(_DWORD *)v8 = **v13;
+**v13 = v8;
+*v13 = (_DWORD *)v8;
+}
+else
+{
+*v13 = (_DWORD *)v8;
+*(_DWORD *)v8 = v8;
+}
+if ( !(*(_BYTE *)(v8 + 22) & 8) )
+{
+ResetWavePosIfNoChannelData();
+v14 = hMem;
+if ( *(signed int (__stdcall **)(int, int))(hMem + 432) == ResetRemix )
+{
+v15 = MyWaveOutGetPosition(*(HWAVEOUT *)(hMem + 12), *(_DWORD *)(hMem + 420));
+v14 = hMem;
+}
+else
+{
+v15 = *(_DWORD *)(hMem + 412);
+}
+v38 = v15;
+if ( !*(_DWORD *)(v14 + 440) )
+goto LABEL_84;
+do
+{
+v16 = *(_DWORD **)(v14 + 440);
+v17 = (_DWORD *)*v16;
+if ( (_DWORD *)*v16 == v16 )
+*(_DWORD *)(v14 + 440) = 0;
+else
+*v16 = *v17;
+v18 = *(_DWORD *)((char *)v17 + 22);
+v19 = *(_DWORD *)((char *)v17 + 10);
+*v17 = 0;
+if ( v18 & 0x10 )
+{
+*((_WORD *)v17 + 28) = *((_WORD *)v17 + 14);
+v20 = *((_WORD *)v17 + 15);
+}
+else
+{
+*((_WORD *)v17 + 28) = *(_WORD *)(v14 + 4 * v19 + 180);
+v20 = *(_WORD *)(v14 + 4 * v19 + 182);
+}
+*((_WORD *)v17 + 29) = v20;
+if ( *((_WORD *)v17 + 28) > 0xAu )
+*((_WORD *)v17 + 28) = 10;
+if ( *((_WORD *)v17 + 29) > 0xAu )
+*((_WORD *)v17 + 29) = 10;
+if ( v18 & 1 )
+{
+v21 = (_DWORD **)(v14 + 4 * v19 + 244);
+for ( i = *v21; i; i = v23 )
+{
+v23 = (_DWORD *)*i;
+FreeChannelNode(i);
+}
+v7 = pwh == 0;
+*v21 = v17;
+if ( !v7 )
+v36 = 1;
+if ( *((_BYTE *)v17 + 22) & 4 )
+v24 = v38;
+else
+v24 = *(_DWORD *)(v14 + 412);
+v17[10] = v24;
+}
+else
+{
+v25 = (_DWORD *)(v14 + 4 * v19 + 244);
+v26 = (_DWORD *)*v25;
+if ( *v25 )
+{
+while ( *v26 )
+v26 = (_DWORD *)*v26;
+*v26 = v17;
+v27 = v26[11];
+if ( *((_BYTE *)v17 + 22) & 4 )
+{
+if ( v27 <= v38 )
+v27 = v38;
+}
+else if ( *(_DWORD *)(v14 + 412) > v27 )
+{
+v27 = *(_DWORD *)(v14 + 412);
+}
+}
+else
+{
+v27 = v38;
+*v25 = v17;
+if ( !(*((_BYTE *)v17 + 22) & 4) )
+v27 = *(_DWORD *)(v14 + 412);
+}
+v17[10] = v27;
+if ( *(_DWORD *)(v14 + 412) > v17[10] )
+v36 = 1;
+}
+v28 = *((_WORD *)v17 + 13);
+if ( v28 == -1 )
+v17[11] = -1;
+else
+v17[11] = v17[10] + v17[9] * (v28 + 1) - *(unsigned __int16 *)(v14 + 392);
+}
+while ( *(_DWORD *)(v14 + 440) );
+if ( !v36 )
+goto LABEL_84;
+if ( !(*(int (__stdcall **)(DWORD, _DWORD))(v14 + 432))(v38, 0) )
+{
+v14 = hMem;
+LABEL_84:
+v29 = 0;
+if ( pwh || *(_DWORD *)(v14 + 404) <= 0 )
+{
+v30 = 0;
+}
+else
+{
+waveOutPause(*(HWAVEOUT *)(v14 + 12));
+v30 = 1;
+}
+v31 = (struct wavehdr_tag *)GetWaveBlock();
+for ( j = MixerPlay(v31, 1); j; j = MixerPlay(v33, 1) )
+{
+if ( v30 )
+{
+if ( ++v29 >= *(_DWORD *)(hMem + 404) )
+{
+waveOutRestart(*(HWAVEOUT *)(hMem + 12));
+v30 = 0;
+}
+}
+v33 = (struct wavehdr_tag *)GetWaveBlock();
+}
+if ( v30 )
+waveOutRestart(*(HWAVEOUT *)(hMem + 12));
+goto LABEL_96;
+}
+}
+LABEL_96:
+v37 = 0;
+goto LABEL_97;
+}
+if ( dword_1027BE4 )
+MessageBoxA(0, "Wave device not allocated, call WaveMixActivate(hMixSession,TRUE)", "WavMix32", 0x30u);
+v37 = 4;
+LABEL_97:
+--dword_1027BF8;
+return v37;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+// 1027BF8: using guessed type int dword_1027BF8;
+
+//----- (0101E373) --------------------------------------------------------
+signed int __stdcall WaveMixFlushChannel(_WORD *a1, signed int a2, char a3)
+{
+_DWORD *v3; // ebx
+_WORD *v4; // eax
+_WORD *v5; // esi
+signed int v6; // ecx
+int v7; // eax
+_DWORD **v8; // edi
+_DWORD *v9; // eax
+DWORD v10; // eax
+signed int v13; // [esp+8h] [ebp-4h]
+int v14; // [esp+14h] [ebp+8h]
+
+v3 = 0;
+v13 = 0;
+v4 = SessionToGlobalDataPtr(a1);
+v5 = v4;
+hMem = (LPARAM)v4;
+if ( v4 )
+{
+if ( a3 & 1 )
+{
+v6 = 0;
+v7 = 16;
+goto LABEL_9;
+}
+v6 = a2;
+if ( a2 < 0 || a2 >= 16 )
+return 11;
+if ( *(_DWORD *)&v4[2 * a2 + 122] != -1 )
+{
+v7 = a2 + 1;
+if ( !(__OFSUB__(a2, a2 + 1) ^ 1) )
+return 0;
+LABEL_9:
+v8 = (_DWORD **)&v5[2 * v6 + 122];
+v14 = v7 - v6;
+do
+{
+v9 = *v8;
+if ( *v8 != (_DWORD *)-1 )
+{
+*v8 = v3;
+if ( v9 != v3 )
+{
+v13 = 1;
+do
+{
+v3 = (_DWORD *)*v9;
+FreeChannelNode(v9);
+v9 = v3;
+}
+while ( v3 );
+}
+}
+++v8;
+--v14;
+}
+while ( v14 );
+if ( (_DWORD *)v13 != v3 && !(a3 & 2) && *((_DWORD **)v5 + 4) != v3 )
+{
+v10 = MyWaveOutGetPosition(*((HWAVEOUT *)v5 + 3), *((_DWORD *)v5 + 105));
+(*((void (__stdcall **)(DWORD, _DWORD *))v5 + 108))(v10, v3);
+}
+return 0;
+}
+}
+return 5;
+}
+
+//----- (0101E434) --------------------------------------------------------
+signed int __stdcall WaveMixCloseChannel(_WORD *a1, signed int a2, char a3)
+{
+signed int result; // eax
+signed int v4; // esi
+int v5; // ecx
+LPARAM v6; // eax
+_DWORD *v7; // edx
+int v8; // ecx
+
+hMem = (LPARAM)SessionToGlobalDataPtr(a1);
+if ( !hMem )
+return 5;
+v4 = a2;
+result = WaveMixFlushChannel(a1, a2, a3 | 2);
+if ( !result )
+{
+if ( a3 & 1 )
+{
+v4 = 0;
+v5 = 16;
+}
+else
+{
+v5 = a2 + 1;
+if ( !(__OFSUB__(a2, a2 + 1) ^ 1) )
+return 0;
+}
+v6 = hMem;
+v7 = (_DWORD *)(hMem + 4 * v4 + 244);
+v8 = v5 - v4;
+do
+{
+if ( *v7 != -1 )
+{
+*v7 = -1;
+--*(_DWORD *)(v6 + 308);
+}
+++v7;
+--v8;
+}
+while ( v8 );
+return 0;
+}
+return result;
+}
+
+//----- (0101E4A9) --------------------------------------------------------
+int __stdcall WaveMixFreeWave(int a1, LPCVOID pMem)
+{
+_WORD *v2; // ebx
+LPCVOID *v4; // edi
+_DWORD **v5; // ebx
+_DWORD *v6; // esi
+HGLOBAL v7; // eax
+HGLOBAL v8; // eax
+HGLOBAL v9; // eax
+HGLOBAL v10; // eax
+_DWORD *v11; // [esp+Ch] [ebp+8h]
+char *pMema; // [esp+10h] [ebp+Ch]
+
+v2 = SessionToGlobalDataPtr((_WORD *)a1);
+if ( !v2 )
+return 5;
+v4 = (LPCVOID *)pMem;
+if ( !IsValidLPMIXWAVE((int)pMem) )
+return 5;
+v5 = (_DWORD **)(v2 + 122);
+pMema = (char *)16;
+do
+{
+v6 = *v5;
+if ( *v5 != (_DWORD *)-1 )
+{
+v11 = 0;
+while ( v6 )
+{
+if ( (LPCVOID *)v6[8] == v4 )
+{
+if ( v11 )
+{
+*v11 = *v6;
+FreeChannelNode(v6);
+v6 = (_DWORD *)*v11;
+}
+else
+{
+v6 = (_DWORD *)*v6;
+FreeChannelNode(*v5);
+*v5 = v6;
+}
+}
+else
+{
+v11 = v6;
+v6 = (_DWORD *)*v6;
+}
+}
+}
+++v5;
+--pMema;
+}
+while ( pMema );
+if ( v4[4] )
+{
+v7 = GlobalHandle(v4[4]);
+GlobalUnlock(v7);
+v8 = GlobalHandle(v4[4]);
+GlobalFree(v8);
+}
+*((_WORD *)v4 + 32) = 0;
+v9 = GlobalHandle(v4);
+GlobalUnlock(v9);
+v10 = GlobalHandle(v4);
+GlobalFree(v10);
+return 0;
+}
+
+//----- (0101E579) --------------------------------------------------------
+_WORD *__userpurge BitsPerSampleAlign@(int a1@, LPCVOID pMem, int a3, __int16 a4, int a5)
+{
+_WORD *v6; // edi
+int v7; // edi
+unsigned int v8; // esi
+SIZE_T v9; // eax
+HGLOBAL v10; // eax
+_WORD *v11; // eax
+_WORD *v12; // ecx
+_WORD *v13; // ebx
+_BYTE *v14; // edi
+char *i; // edx
+HGLOBAL v16; // eax
+HGLOBAL v17; // eax
+int v18; // [esp+Ch] [ebp+Ch]
+
+if ( (_WORD)a3 == a4 )
+return pMem;
+if ( ((_WORD)a3 == 8 || (_WORD)a3 == 16) && (a4 == 8 || a4 == 16) )
+{
+LOWORD(a1) = (unsigned __int16)a3 >> 3;
+v7 = a1;
+v8 = *(_DWORD *)a5 / (unsigned int)((unsigned __int16)a3 >> 3);
+v9 = v8 * ((unsigned __int16)a4 >> 3);
+*(_DWORD *)a5 = v9;
+v10 = GlobalAlloc(0x2002u, v9);
+v11 = GlobalLock(v10);
+v12 = v11;
+if ( v11 )
+{
+if ( (unsigned __int16)v7 <= (unsigned __int16)((unsigned __int16)a4 >> 3) )
+{
+for ( i = (char *)pMem; v8; --v8 )
+{
+LOWORD(v7) = *i;
+v7 = (v7 - 128) << 8;
+*v11 = v7;
+++v11;
+++i;
+}
+}
+else
+{
+v13 = pMem;
+v14 = v11;
+if ( v8 )
+{
+v18 = v8;
+do
+{
+*v14++ = *v13 / 256 + -128;
+++v13;
+--v18;
+}
+while ( v18 );
+}
+}
+v6 = v12;
+}
+else
+{
+if ( dword_1027BE4 )
+MessageBoxA(
+0,
+"Unable to allocate memory for waveform data. Try making more memory available by closing other applications.",
+"WavMix32",
+0x40u);
+v6 = 0;
+}
+}
+else
+{
+v6 = 0;
+}
+v16 = GlobalHandle(pMem);
+GlobalUnlock(v16);
+v17 = GlobalHandle(pMem);
+GlobalFree(v17);
+return v6;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (0101E686) --------------------------------------------------------
+_BYTE *__stdcall ChannelAlign(LPCVOID pMem, __int16 a2, __int16 a3, __int16 a4, int a5)
+{
+unsigned int v6; // edi
+SIZE_T v7; // eax
+HGLOBAL v8; // eax
+_BYTE *v9; // eax
+_BYTE *v10; // ebx
+unsigned __int8 *v11; // ecx
+_BYTE *v12; // eax
+_WORD *v13; // eax
+_WORD *v14; // esi
+HGLOBAL v15; // eax
+HGLOBAL v16; // eax
+
+if ( a2 == a3 )
+return pMem;
+v6 = *(_DWORD *)a5 / (unsigned int)(unsigned __int16)a4 / (unsigned __int16)a2;
+v7 = v6 * (unsigned __int16)a4 * (unsigned __int16)a3;
+*(_DWORD *)a5 = v7;
+v8 = GlobalAlloc(0x2002u, v7);
+v9 = GlobalLock(v8);
+v10 = v9;
+if ( v9 )
+{
+v11 = (unsigned __int8 *)pMem;
+if ( (unsigned __int16)a2 >= (unsigned __int16)a3 )
+{
+v14 = v9;
+if ( a4 == 1 )
+{
+for ( ; v6; --v6 )
+{
+*(_BYTE *)v14 = (*v11 + v11[1]) / 2;
+v14 = (_WORD *)((char *)v14 + 1);
+v11 += 2;
+}
+}
+else
+{
+for ( ; v6; --v6 )
+{
+*v14 = (*(signed __int16 *)v11 + *((signed __int16 *)v11 + 1)) / 2;
+++v14;
+v11 += 4;
+}
+}
+}
+else if ( a4 == 1 )
+{
+for ( ; v6; --v6 )
+{
+*v9 = *v11;
+v12 = v9 + 1;
+*v12 = *v11;
+v9 = v12 + 1;
+++v11;
+}
+}
+else
+{
+for ( ; v6; --v6 )
+{
+*(_WORD *)v9 = *(_WORD *)v11;
+v13 = v9 + 2;
+*v13 = *(_WORD *)v11;
+v9 = v13 + 1;
+v11 += 2;
+}
+}
+}
+else
+{
+if ( dword_1027BE4 )
+MessageBoxA(
+0,
+"Unable to allocate memory for waveform data. Try making more memory available by closing other applications.",
+"WavMix32",
+0x40u);
+v10 = 0;
+}
+v15 = GlobalHandle(pMem);
+GlobalUnlock(v15);
+v16 = GlobalHandle(pMem);
+GlobalFree(v16);
+return v10;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (0101E7B0) --------------------------------------------------------
+void __stdcall AvgSample(_WORD *a1, unsigned __int8 *a2, int a3, int a4, int a5)
+{
+int v5; // edi
+_BYTE *v6; // esi
+unsigned __int8 *v7; // ecx
+int v8; // eax
+int v9; // edx
+int v10; // ebx
+int v11; // edx
+signed __int16 *v12; // edi
+signed __int16 *v13; // ecx
+int v14; // eax
+int v15; // esi
+int v16; // edx
+bool v17; // zf
+int v18; // [esp+18h] [ebp+Ch]
+
+if ( a4 == 1 )
+{
+v5 = a5;
+if ( a5 > 0 )
+{
+v6 = a1;
+do
+{
+v7 = a2++;
+v8 = 0;
+if ( a3 > 0 )
+{
+v9 = a3;
+do
+{
+v10 = *v7;
+v7 += a5;
+--v9;
+v8 = v8 + v10 - 128;
+}
+while ( v9 );
+}
+*v6++ = (unsigned int)(v8 / a3) + -128;
+--v5;
+}
+while ( v5 );
+}
+}
+else
+{
+v11 = a5;
+v12 = (signed __int16 *)a2;
+if ( a5 > 0 )
+{
+v18 = a5;
+while ( 1 )
+{
+v13 = v12;
+v14 = 0;
+++v12;
+if ( a3 > 0 )
+{
+v15 = a3;
+v16 = 2 * v11;
+do
+{
+v14 += *v13;
+v13 = (signed __int16 *)((char *)v13 + v16);
+--v15;
+}
+while ( v15 );
+}
+v17 = v18-- == 1;
+*a1 = v14 / a3;
+if ( v17 )
+break;
+v11 = a5;
+}
+}
+}
+}
+
+//----- (0101E83A) --------------------------------------------------------
+int __stdcall RepSample(_BYTE *a1, unsigned __int8 *a2, signed int a3, int a4, int a5)
+{
+int v5; // ebx
+int result; // eax
+unsigned __int8 *v7; // edi
+char v8; // cl
+_BYTE *v9; // esi
+_BYTE *v10; // esi
+int v11; // edx
+int v12; // ebx
+_WORD *v13; // esi
+_WORD *v14; // edi
+int v15; // ecx
+int v16; // edx
+int v17; // [esp+14h] [ebp+8h]
+_WORD *v18; // [esp+18h] [ebp+Ch]
+unsigned __int8 *v19; // [esp+20h] [ebp+14h]
+
+if ( a4 == 1 )
+{
+v5 = a5;
+result = (int)a1;
+if ( a5 > 0 )
+{
+v7 = a2;
+do
+{
+v8 = *v7;
+v9 = a1++;
+result = (v7[v5] - *v7) / a3;
+*v9 = *v7;
+v10 = &v9[v5];
+if ( a3 > 1 )
+{
+v11 = a3 - 1;
+do
+{
+v8 += result;
+*v10 = v8;
+v10 += v5;
+--v11;
+}
+while ( v11 );
+}
+++v7;
+--a5;
+}
+while ( a5 );
+}
+}
+else
+{
+v19 = a2;
+v18 = a1;
+result = a5;
+if ( a5 > 0 )
+{
+v12 = a5;
+v17 = a5;
+do
+{
+v13 = v18;
+LOWORD(v15) = *(_WORD *)v19;
+++v18;
+v14 = &v13[v12];
+result = ((signed __int16)v13[v12] - *(signed __int16 *)v19) / a3;
+*v13 = *(_WORD *)v19;
+v15 = (signed __int16)v15;
+if ( a3 > 1 )
+{
+v16 = a3 - 1;
+do
+{
+v15 += result;
+*v14 = v15;
+v14 = (_WORD *)((char *)v14 + v12 * 2);
+--v16;
+}
+while ( v16 );
+}
+v19 += 2;
+--v17;
+}
+while ( v17 );
+}
+}
+return result;
+}
+
+//----- (0101E8F5) --------------------------------------------------------
+LPCVOID __stdcall SamplesPerSecAlign(LPCVOID pMem, int a2, int a3, __int16 a4, __int16 a5, int a6)
+{
+LPCVOID result; // eax
+_DWORD *v7; // ecx
+int v8; // edi
+unsigned int v9; // eax
+int v10; // esi
+unsigned int v11; // eax
+HGLOBAL v12; // eax
+_BYTE *v13; // ebx
+HGLOBAL v14; // eax
+HGLOBAL v15; // eax
+int v16; // ecx
+_BYTE *v17; // eax
+int v18; // esi
+_BYTE *v19; // eax
+HGLOBAL v20; // eax
+HGLOBAL v21; // eax
+int v22; // [esp+8h] [ebp-8h]
+LPCVOID v23; // [esp+Ch] [ebp-4h]
+int v24; // [esp+1Ch] [ebp+Ch]
+int v25; // [esp+1Ch] [ebp+Ch]
+int v26; // [esp+20h] [ebp+10h]
+int v27; // [esp+20h] [ebp+10h]
+unsigned int v28; // [esp+2Ch] [ebp+1Ch]
+
+if ( a2 == a3 )
+return pMem;
+v7 = (_DWORD *)a6;
+v8 = (unsigned __int16)a4 * (unsigned __int16)a5;
+v28 = *(_DWORD *)a6 / (unsigned int)v8;
+if ( a3 <= (unsigned int)a2 )
+{
+v11 = a2 / (unsigned int)a3;
+v24 = 0;
+v26 = v11;
+v10 = v28 / v11;
+}
+else
+{
+v9 = a3 / (unsigned int)a2;
+v26 = 0;
+v24 = v9;
+v10 = v28 * v9;
+}
+*v7 = v8 * v10;
+v12 = GlobalAlloc(0x2002u, v8 * v10);
+v13 = GlobalLock(v12);
+if ( v13 )
+{
+v23 = pMem;
+v22 = (int)v13;
+if ( v24 <= 0 )
+{
+if ( v10 != 1 )
+{
+v25 = v10 - 1;
+do
+{
+AvgSample(v13, (unsigned __int8 *)pMem, v26, (unsigned __int16)a4, (unsigned __int16)a5);
+pMem = (char *)pMem + v8 * v26;
+v13 += v8;
+--v25;
+}
+while ( v25 );
+}
+if ( v8 > 0 )
+{
+v19 = pMem;
+do
+{
+*v13++ = *v19++;
+--v8;
+}
+while ( v8 );
+}
+}
+else
+{
+if ( v28 != 1 )
+{
+v27 = v28 - 1;
+do
+{
+RepSample(v13, (unsigned __int8 *)pMem, v24, (unsigned __int16)a4, (unsigned __int16)a5);
+pMem = (char *)pMem + v8;
+v13 += v8 * v24;
+--v27;
+}
+while ( v27 );
+}
+v16 = v24;
+if ( v24 > 0 )
+{
+do
+{
+v17 = pMem;
+if ( v8 > 0 )
+{
+v18 = (unsigned __int16)a4 * (unsigned __int16)a5;
+do
+{
+*v13++ = *v17++;
+--v18;
+}
+while ( v18 );
+}
+--v16;
+}
+while ( v16 );
+}
+}
+v20 = GlobalHandle(v23);
+GlobalUnlock(v20);
+v21 = GlobalHandle(v23);
+GlobalFree(v21);
+result = (LPCVOID)v22;
+}
+else
+{
+if ( dword_1027BE4 )
+MessageBoxA(
+0,
+"Unable to allocate memory for waveform data. Try making more memory available by closing other applications.",
+"WavMix32",
+0x40u);
+v14 = GlobalHandle(pMem);
+GlobalUnlock(v14);
+v15 = GlobalHandle(pMem);
+GlobalFree(v15);
+result = 0;
+}
+return result;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (0101EA82) --------------------------------------------------------
+LPCVOID __stdcall WaveFormatConvert(int a1, int a2, LPCVOID pMem, int a4)
+{
+LPCVOID result; // eax
+_WORD *v5; // eax
+_BYTE *v6; // eax
+
+if ( *(_WORD *)(a2 + 2) == *(_WORD *)(a1 + 2)
+&& *(_DWORD *)(a2 + 4) == *(_DWORD *)(a1 + 4)
+&& *(_WORD *)(a2 + 14) == *(_WORD *)(a1 + 14) )
+{
+return pMem;
+}
+v5 = BitsPerSampleAlign(*(unsigned __int16 *)(a2 + 14), pMem, *(unsigned __int16 *)(a2 + 14), *(_WORD *)(a1 + 14), a4);
+if ( v5 && (v6 = ChannelAlign(v5, *(_WORD *)(a2 + 2), *(_WORD *)(a1 + 2), *(_WORD *)(a1 + 14) >> 3, a4)) != 0 )
+result = SamplesPerSecAlign(
+v6,
+*(_DWORD *)(a2 + 4),
+*(_DWORD *)(a1 + 4),
+*(_WORD *)(a1 + 14) >> 3,
+*(_WORD *)(a1 + 2),
+a4);
+else
+result = 0;
+return result;
+}
+
+//----- (0101EB23) --------------------------------------------------------
+CHAR *__stdcall WaveMixOpenWave(LPCVOID pMem, LPCSTR lpName, HMODULE hModule, LONG cch)
+{
+_WORD *v4; // eax
+WORD v5; // cx
+HGLOBAL v7; // eax
+CHAR *v8; // edi
+HRSRC v9; // eax
+HRSRC v10; // esi
+HGLOBAL v11; // eax
+HGLOBAL v12; // eax
+HGLOBAL v13; // eax
+HGLOBAL v14; // eax
+HGLOBAL v15; // eax
+void *v16; // eax
+const void *v17; // esi
+LONG v18; // eax
+LPCVOID v19; // esi
+const void *v20; // ST08_4
+int v21; // eax
+int v22; // eax
+const CHAR *v23; // [esp-10h] [ebp-A4h]
+UINT v24; // [esp-Ch] [ebp-A0h]
+struct _MMIOINFO pmmioinfo; // [esp+4h] [ebp-90h]
+struct _MMCKINFO pmmcki; // [esp+4Ch] [ebp-48h]
+HWAVEOUT phwo; // [esp+60h] [ebp-34h]
+struct _MMCKINFO v28; // [esp+64h] [ebp-30h]
+WAVEFORMATEX pwfx; // [esp+78h] [ebp-1Ch]
+LPCVOID v30; // [esp+8Ch] [ebp-8h]
+HGLOBAL hResData; // [esp+90h] [ebp-4h]
+HMMIO hModulea; // [esp+A4h] [ebp+10h]
+
+hResData = 0;
+v30 = 0;
+v4 = SessionToGlobalDataPtr(pMem);
+pwfx.wFormatTag = v4[190];
+pwfx.nChannels = v4[191];
+pwfx.nSamplesPerSec = *((_DWORD *)v4 + 96);
+pwfx.nAvgBytesPerSec = *((_DWORD *)v4 + 97);
+v5 = v4[196];
+hMem = (LPARAM)v4;
+pwfx.nBlockAlign = v5;
+pwfx.wBitsPerSample = v4[197];
+pwfx.cbSize = 0;
+if ( waveOutOpen(&phwo, 0xFFFFFFFF, &pwfx, 0, 0, 1u) )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "The waveform device can't play this format.", "WavMix32", 0x30u);
+return 0;
+}
+v7 = GlobalAlloc(0x2040u, 0x42u);
+v8 = (CHAR *)GlobalLock(v7);
+if ( !v8 )
+{
+if ( dword_1027BE4 )
+MessageBoxA(
+0,
+"Unable to allocate memory for waveform data. Try making more memory available by closing other applications.",
+"WavMix32",
+0x40u);
+return 0;
+}
+if ( cch & 2 )
+{
+v9 = FindResourceA(hModule, lpName, "WAVE");
+v10 = v9;
+if ( !v9 || (hResData = LoadResource(hModule, v9)) == 0 )
+{
+if ( HIWORD(lpName) )
+_wsprintfA(aWavemixV23ByAn, "Failed to open 'WAVE' resource '%s'.", lpName);
+else
+_wsprintfA(aWavemixV23ByAn, "Failed to open 'WAVE' resource %u.", (unsigned __int16)lpName);
+if ( dword_1027BE4 )
+MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x30u);
+goto LABEL_31;
+}
+memset(&pmmioinfo, 0, sizeof(pmmioinfo));
+pmmioinfo.pchBuffer = (HPSTR)LockResource(hResData);
+if ( !pmmioinfo.pchBuffer )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "Failed to lock 'WAVE' resource", "WavMix32", 0x30u);
+FreeResource(hResData);
+hResData = 0;
+LABEL_31:
+v11 = GlobalHandle(v8);
+GlobalUnlock(v11);
+v12 = GlobalHandle(v8);
+GlobalFree(v12);
+if ( v30 )
+{
+v13 = GlobalHandle(v30);
+GlobalUnlock(v13);
+v14 = GlobalHandle(v30);
+GlobalFree(v14);
+}
+if ( hResData )
+FreeResource(hResData);
+return 0;
+}
+pmmioinfo.cchBuffer = SizeofResource(hModule, v10);
+pmmioinfo.fccIOProc = 541934925;
+pmmioinfo.adwInfo[0] = 0;
+hModulea = mmioOpenA(0, &pmmioinfo, 0);
+if ( !hModulea )
+{
+if ( !dword_1027BE4 )
+goto LABEL_29;
+v24 = pmmioinfo.wErrorRet;
+v23 = "Failed to open resource, mmioOpen error=%u.\nMay need to make sure resource is marked read-write";
+goto LABEL_28;
+}
+}
+else if ( cch & 4 )
+{
+qmemcpy(&pmmioinfo, lpName, sizeof(pmmioinfo));
+hModulea = mmioOpenA(0, &pmmioinfo, 0);
+if ( !hModulea )
+{
+if ( !dword_1027BE4 )
+goto LABEL_29;
+v24 = pmmioinfo.wErrorRet;
+v23 = "Failed to open memory file, mmioOpen error=%u.\nMay need to make sure memory is read-write";
+LABEL_28:
+_wsprintfA(aWavemixV23ByAn, v23, v24);
+MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x30u);
+LABEL_29:
+if ( hModulea )
+mmioClose(hModulea, 0);
+goto LABEL_31;
+}
+}
+else
+{
+hModulea = mmioOpenA((LPSTR)lpName, 0, 0x10000u);
+if ( !hModulea )
+{
+if ( dword_1027BE4 )
+{
+_wsprintfA(aWavemixV23ByAn, "Failed to open wave file %s.", lpName);
+MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x30u);
+}
+goto LABEL_29;
+}
+}
+pmmcki.fccType = 1163280727;
+if ( mmioDescend(hModulea, &pmmcki, 0, 0x20u) )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "This is not a WAVE file.", "WavMix32", 0x30u);
+goto LABEL_29;
+}
+v28.ckid = 544501094;
+if ( mmioDescend(hModulea, &v28, &pmmcki, 0x10u) )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "WAVE file is corrupted.", "WavMix32", 0x30u);
+goto LABEL_29;
+}
+if ( mmioRead(hModulea, v8, 16) != 16 )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "Failed to read format chunk.", "WavMix32", 0x30u);
+goto LABEL_29;
+}
+if ( *(_WORD *)v8 != 1 )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "The file is not a PCM file.", "WavMix32", 0x30u);
+goto LABEL_29;
+}
+mmioAscend(hModulea, &v28, 0);
+v28.ckid = 1635017060;
+if ( mmioDescend(hModulea, &v28, &pmmcki, 0x10u) )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "WAVE file has no data chunk.", "WavMix32", 0x30u);
+goto LABEL_29;
+}
+cch = v28.cksize;
+if ( !v28.cksize )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "The data chunk has no data.", "WavMix32", 0x30u);
+goto LABEL_29;
+}
+v15 = GlobalAlloc(0x2002u, v28.cksize);
+v16 = GlobalLock(v15);
+v17 = v16;
+v30 = v16;
+if ( !v16 )
+{
+if ( dword_1027BE4 )
+MessageBoxA(
+0,
+"Unable to allocate memory for waveform data. Try making more memory available by closing other applications.",
+"WavMix32",
+0x40u);
+goto LABEL_29;
+}
+v18 = mmioRead(hModulea, (HPSTR)v16, cch);
+if ( v18 != cch )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "Failed to read data chunk.", "WavMix32", 0x30u);
+goto LABEL_29;
+}
+v19 = WaveFormatConvert(hMem + 380, (int)v8, v17, (int)&cch);
+v30 = v19;
+if ( !v19 )
+{
+if ( dword_1027BE4 )
+MessageBoxA(0, "Failed to convert wave format.", "WavMix32", 0x30u);
+goto LABEL_29;
+}
+mmioClose(hModulea, 0);
+if ( hResData )
+FreeResource(hResData);
+*((_DWORD *)v8 + 5) = cch;
+v20 = (const void *)(hMem + 380);
+*((_DWORD *)v8 + 4) = v19;
+*((_DWORD *)v8 + 8) = 0;
+*((_DWORD *)v8 + 9) = 0;
+*((_DWORD *)v8 + 7) = 0;
+*((_WORD *)v8 + 32) = 21554;
+_memmove(v8, v20, 0x10u);
+if ( HIWORD(lpName) )
+{
+v21 = lstrlenA(lpName);
+if ( v21 > 15 )
+v22 = v21 - 15;
+else
+v22 = 0;
+lstrcpyA(v8 + 48, &lpName[v22]);
+}
+else
+{
+_wsprintfA(v8 + 48, "res#%u", (unsigned __int16)lpName);
+}
+return v8;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (0101F093) --------------------------------------------------------
+unsigned int __stdcall FigureOutDMABufferSize(unsigned int a1, int a2)
+{
+unsigned int result; // eax
+signed int v3; // ecx
+
+result = a1;
+if ( !a1 )
+result = *(_DWORD *)(a2 + 4) * *(unsigned __int16 *)(a2 + 2) * ((unsigned int)*(unsigned __int16 *)(a2 + 14) >> 3) >> 4;
+v3 = 344;
+if ( result < 0x158 || (v3 = 11025, result > 0x2B11) )
+result = v3;
+return result;
+}
+
+//----- (0101F0D4) --------------------------------------------------------
+int __stdcall RemoveInvalidIniNameCharacters(LPCSTR lpString)
+{
+CHAR *v1; // esi
+
+v1 = (CHAR *)lpString;
+if ( !lpString || !*lpString )
+return 0;
+do
+{
+if ( !_isalnum(*v1) && !_isspace(*v1) )
+break;
+++v1;
+}
+while ( *v1 );
+do
+*v1-- = 0;
+while ( v1 >= lpString && _isspace(*v1) );
+return lstrlenA(lpString);
+}
+
+//----- (0101F13D) --------------------------------------------------------
+UINT __stdcall ShowWaveOutDevices()
+{
+UINT result; // eax
+signed int v1; // [esp+0h] [ebp-40h]
+signed int uDeviceID; // [esp+4h] [ebp-3Ch]
+struct tagWAVEOUTCAPSA pwoc; // [esp+8h] [ebp-38h]
+
+result = waveOutGetNumDevs();
+v1 = result;
+if ( result )
+{
+_wsprintfA(aWavemixV23ByAn, "%d waveOut Devices have been detected on your system.", result);
+result = MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x40u);
+for ( uDeviceID = 0; uDeviceID < v1; result = uDeviceID )
+{
+if ( !waveOutGetDevCapsA(uDeviceID, &pwoc, 0x34u) && RemoveInvalidIniNameCharacters(pwoc.szPname) )
+_wsprintfA(
+aWavemixV23ByAn,
+"Device %i: %s\n\tVersion %u.%u",
+uDeviceID,
+pwoc.szPname,
+BYTE1(pwoc.vDriverVersion),
+LOBYTE(pwoc.vDriverVersion));
+else
+_wsprintfA(aWavemixV23ByAn, "waveOutGetDevCaps failed (err %u) for device %d", 1, uDeviceID);
+MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x40u);
+++uDeviceID;
+}
+}
+return result;
+}
+
+//----- (0101F20F) --------------------------------------------------------
+const char *__stdcall GetOperatingSystemPrefix()
+{
+const char *result; // eax
+bool v1; // cf
+
+if ( GetVersion() < 0x80000000 )
+return "WinNT:";
+if ( GetVersion() >= 0x80000000 && (unsigned __int8)GetVersion() >= 4u )
+return "Win95:";
+if ( GetVersion() < 0x80000000 || (v1 = (unsigned __int8)GetVersion() < 4u, result = "Win31:", !v1) )
+result = "OS_X:";
+return result;
+}
+
+//----- (0101F25C) --------------------------------------------------------
+int __stdcall ReadRegistryToGetMachineSpecificInfSection(int a1, LPSTR lpString1, int a3)
+{
+const char *v3; // eax
+int v4; // esi
+const char *v6; // eax
+LONG cbData; // [esp+Ch] [ebp-44h]
+int v8; // [esp+10h] [ebp-40h]
+HKEY phkResult; // [esp+14h] [ebp-3Ch]
+CHAR SubKey; // [esp+18h] [ebp-38h]
+
+v8 = 0;
+v3 = GetOperatingSystemPrefix();
+v4 = lstrlenA(v3);
+if ( a3 < v4 + 10 )
+return 0;
+_wsprintfA(&SubKey, "Device%u", a1);
+if ( RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\WaveMix", &phkResult) )
+return 0;
+v6 = GetOperatingSystemPrefix();
+lstrcpyA(lpString1, v6);
+cbData = a3 - v4;
+if ( !RegQueryValueA(phkResult, &SubKey, &lpString1[v4], &cbData) && cbData > 0 )
+v8 = 1;
+RegCloseKey(phkResult);
+return v8;
+}
+
+//----- (0101F315) --------------------------------------------------------
+int __stdcall ReadRegistryInt(HKEY hKey, LPCSTR lpSubKey, int a3)
+{
+int result; // eax
+LONG cbData; // [esp+0h] [ebp-14h]
+CHAR Data; // [esp+4h] [ebp-10h]
+
+if ( !hKey || (cbData = 10, RegQueryValueA(hKey, lpSubKey, &Data, &cbData)) )
+result = a3;
+else
+result = _atol(&Data);
+return result;
+}
+
+//----- (0101F36B) --------------------------------------------------------
+signed int __stdcall ReadRegistryForAppSpecificConfigs(int a1)
+{
+int v1; // ebx
+int v3; // eax
+int v4; // eax
+struct tagWAVEOUTCAPSA *v5; // ST04_4
+UINT_PTR v6; // ST00_4
+HKEY phkResult; // [esp+8h] [ebp-3Ch]
+CHAR SubKey; // [esp+Ch] [ebp-38h]
+
+v1 = *(_DWORD *)(a1 + 2);
+if ( !(v1 & 0x400) || !*(_DWORD *)(a1 + 26) )
+return 0;
+if ( (v1 & 0x80u) == 0 )
+{
+*(_WORD *)(a1 + 20) = *(_WORD *)(hMem + 24);
+}
+else if ( *(unsigned __int16 *)(a1 + 20) >= waveOutGetNumDevs() )
+{
+*(_WORD *)(a1 + 20) = 0;
+}
+_wsprintfA(&SubKey, "WaveMix\\Device%u", *(unsigned __int16 *)(a1 + 20));
+if ( RegOpenKeyA(*(HKEY *)(a1 + 26), &SubKey, &phkResult) )
+return 0;
+if ( !(v1 & 1) )
+*(_WORD *)(a1 + 6) = ReadRegistryInt(phkResult, "Channels", 1);
+if ( !(v1 & 2) )
+*(_WORD *)(a1 + 8) = ReadRegistryInt(phkResult, "SamplesPerSec", 11);
+if ( !(v1 & 4) )
+*(_WORD *)(a1 + 10) = ReadRegistryInt(phkResult, "WaveBlocks", 3);
+if ( !(v1 & 8) )
+*(_WORD *)(a1 + 12) = ReadRegistryInt(phkResult, "WaveBlockLen", 0);
+*(_WORD *)(a1 + 14) = 1;
+if ( !(v1 & 0x20) )
+*(_WORD *)(a1 + 16) = (unsigned __int16)ReadRegistryInt(phkResult, "Remix", 1) != 2;
+if ( !(v1 & 0x40) )
+{
+v3 = DefaultGoodWavePos(*(unsigned __int16 *)(a1 + 20));
+*(_WORD *)(a1 + 18) = (unsigned __int16)ReadRegistryInt(phkResult, "GoodWavePos", v3) != 0;
+}
+if ( !(v1 & 0x100) )
+*(_WORD *)(a1 + 24) = ReadRegistryInt(phkResult, "ShowDebugDialogs", 0);
+if ( !(v1 & 0x200) )
+{
+v4 = DefaultPauseBlocks(*(unsigned __int16 *)(a1 + 10));
+*(_WORD *)(a1 + 22) = ReadRegistryInt(phkResult, "PauseBlocks", v4);
+}
+v5 = (struct tagWAVEOUTCAPSA *)(hMem + 124);
+v6 = *(unsigned __int16 *)(a1 + 20);
+*(_DWORD *)(a1 + 2) = 1023;
+waveOutGetDevCapsA(v6, v5, 0x34u);
+RegCloseKey(phkResult);
+return 1;
+}
+
+//----- (0101F50B) --------------------------------------------------------
+int __stdcall ShowCurrentSettings()
+{
+const char *v0; // esi
+const char *v1; // edx
+const char *v2; // ecx
+struct tagWAVEOUTCAPSA pwoc; // [esp+0h] [ebp-38h]
+
+if ( waveOutGetDevCapsA(*(_DWORD *)(hMem + 24), &pwoc, 0x34u) || !RemoveInvalidIniNameCharacters(pwoc.szPname) )
+lstrcpyA(pwoc.szPname, "Unknown Device");
+v0 = "cmixit";
+if ( *(__int16 (__stdcall **)(_BYTE *, char *, char *, int, unsigned __int16))(hMem + 428) != cmixit )
+v0 = "386 mixit";
+v1 = "TRUE";
+if ( !*(_DWORD *)(hMem + 420) )
+v1 = "FALSE";
+v2 = "Reset";
+if ( *(signed int (__stdcall **)(int, int))(hMem + 432) != ResetRemix )
+v2 = "NoReset";
+_wsprintfA(
+aWavemixV23ByAn,
+"Using:\t%s.\n"
+"\tRemix = %s\n"
+"\tGoodGetPos=%s\n"
+"\t%d ping pong wave blocks\n"
+"\tWave block len = %lu bytes\n"
+"\tpfnMixit=%s\n"
+"\tSamplesPerSec=%lu,\n"
+"\tChannels=%d\n"
+"\tPauseBlocks=%d",
+pwoc.szPname,
+v2,
+v1,
+*(_DWORD *)(hMem + 400),
+*(_DWORD *)(hMem + 396),
+v0,
+*(_DWORD *)(hMem + 384),
+*(unsigned __int16 *)(hMem + 382),
+*(_DWORD *)(hMem + 404));
+return MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x40u);
+}
+
+//----- (0101F5F1) --------------------------------------------------------
+int __stdcall Settings_OnInitDialog(HWND hWnd, int a2, int a3)
+{
+BOOL v3; // ST0C_4
+HWND v4; // eax
+BOOL v5; // ST0C_4
+HWND v6; // eax
+BOOL v7; // ST0C_4
+HWND v8; // eax
+BOOL v9; // ST0C_4
+HWND v10; // eax
+BOOL v11; // ST0C_4
+HWND v12; // eax
+HWND v13; // eax
+HWND v14; // eax
+HWND v15; // eax
+HWND v16; // eax
+HWND v17; // eax
+HWND v18; // eax
+HWND v19; // eax
+HWND v20; // eax
+HWND v21; // eax
+HWND v22; // eax
+HWND v23; // eax
+HWND v24; // eax
+HWND v25; // eax
+HWND v26; // eax
+HWND v27; // eax
+HWND v28; // eax
+HWND v29; // eax
+MMRESULT v30; // eax
+HWND v31; // eax
+WPARAM v32; // ST0C_4
+HWND v33; // eax
+signed int v35; // [esp+Ch] [ebp-148h]
+signed int uDeviceID; // [esp+10h] [ebp-144h]
+struct tagWAVEOUTCAPSA pwoc; // [esp+1Ch] [ebp-138h]
+CHAR String; // [esp+50h] [ebp-104h]
+
+GetWindowTextA(hWnd, &String, 256);
+_wsprintfA(aWavemixV23ByAn, &String, 2, 81);
+SetWindowTextA(hWnd, aWavemixV23ByAn);
+SetWindowLongA(hWnd, -21, a3);
+v3 = *(_WORD *)(a3 + 6) > 1u;
+v4 = GetDlgItem(hWnd, 1000);
+SendMessageA(v4, 0xF1u, v3, 0);
+v5 = *(_WORD *)(a3 + 16) != 0;
+v6 = GetDlgItem(hWnd, 1001);
+SendMessageA(v6, 0xF1u, v5, 0);
+v7 = *(_WORD *)(a3 + 18) != 0;
+v8 = GetDlgItem(hWnd, 1004);
+SendMessageA(v8, 0xF1u, v7, 0);
+v9 = *(_WORD *)(a3 + 14) != 0;
+v10 = GetDlgItem(hWnd, 1005);
+SendMessageA(v10, 0xF1u, v9, 0);
+v11 = *(_WORD *)(a3 + 24) != 0;
+v12 = GetDlgItem(hWnd, 1010);
+SendMessageA(v12, 0xF1u, v11, 0);
+v13 = GetDlgItem(hWnd, 1005);
+EnableWindow(v13, 0);
+v14 = GetDlgItem(hWnd, 1003);
+SendMessageA(v14, 0xC5u, 2u, 0);
+v15 = GetDlgItem(hWnd, 1007);
+SendMessageA(v15, 0xC5u, 4u, 0);
+v16 = GetDlgItem(hWnd, 1008);
+SendMessageA(v16, 0xC5u, 2u, 0);
+v17 = GetDlgItem(hWnd, 1011);
+SendMessageA(v17, 0xC5u, 2u, 0);
+v18 = GetDlgItem(hWnd, 1012);
+GetWindowTextA(v18, &String, 100);
+_wsprintfA(aWavemixV23ByAn, &String, 2, 10);
+v19 = GetDlgItem(hWnd, 1012);
+SetWindowTextA(v19, aWavemixV23ByAn);
+v20 = GetDlgItem(hWnd, 1013);
+GetWindowTextA(v20, &String, 100);
+_wsprintfA(aWavemixV23ByAn, &String, 344, 11025);
+v21 = GetDlgItem(hWnd, 1013);
+SetWindowTextA(v21, aWavemixV23ByAn);
+v22 = GetDlgItem(hWnd, 1014);
+GetWindowTextA(v22, &String, 100);
+_wsprintfA(aWavemixV23ByAn, &String, 0, 10);
+v23 = GetDlgItem(hWnd, 1014);
+SetWindowTextA(v23, aWavemixV23ByAn);
+v24 = GetDlgItem(hWnd, 1015);
+GetWindowTextA(v24, &String, 100);
+_wsprintfA(aWavemixV23ByAn, &String, 16);
+v25 = GetDlgItem(hWnd, 1015);
+SetWindowTextA(v25, aWavemixV23ByAn);
+_wsprintfA(aWavemixV23ByAn, "%d", *(unsigned __int16 *)(a3 + 10));
+v26 = GetDlgItem(hWnd, 1003);
+SetWindowTextA(v26, aWavemixV23ByAn);
+_wsprintfA(aWavemixV23ByAn, "%d", *(unsigned __int16 *)(a3 + 12));
+v27 = GetDlgItem(hWnd, 1007);
+SetWindowTextA(v27, aWavemixV23ByAn);
+_wsprintfA(aWavemixV23ByAn, "%d", *(unsigned __int16 *)(a3 + 8));
+v28 = GetDlgItem(hWnd, 1008);
+SetWindowTextA(v28, aWavemixV23ByAn);
+_wsprintfA(aWavemixV23ByAn, "%d", *(unsigned __int16 *)(a3 + 22));
+v29 = GetDlgItem(hWnd, 1011);
+SetWindowTextA(v29, aWavemixV23ByAn);
+uDeviceID = 0;
+v35 = waveOutGetNumDevs();
+if ( v35 > 0 )
+{
+do
+{
+v30 = waveOutGetDevCapsA(uDeviceID, &pwoc, 0x34u);
+if ( v30 )
+{
+_wsprintfA(aWavemixV23ByAn, "waveOutGetDevCaps failed (err %u) for device %d", v30, uDeviceID);
+MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x40u);
+}
+else
+{
+_wsprintfA(aWavemixV23ByAn, "%d: %s", uDeviceID, pwoc.szPname);
+v31 = GetDlgItem(hWnd, 1009);
+SendMessageA(v31, 0x143u, 0, (LPARAM)aWavemixV23ByAn);
+}
+++uDeviceID;
+}
+while ( uDeviceID < v35 );
+}
+v32 = *(unsigned __int16 *)(a3 + 20);
+v33 = GetDlgItem(hWnd, 1009);
+SendMessageA(v33, 0x14Eu, v32, 0);
+return 1;
+}
+
+//----- (0101FA63) --------------------------------------------------------
+int __stdcall Settings_OnCommand(HWND hWnd, int a2, int a3, int a4)
+{
+_WORD *v4; // ebx
+HWND v6; // eax
+HWND v7; // eax
+HWND v8; // eax
+HWND v9; // eax
+HWND v10; // eax
+HWND v11; // eax
+HWND v12; // eax
+HWND v13; // eax
+HWND v14; // eax
+HWND v15; // eax
+__int16 v16; // ax
+
+v4 = (_WORD *)GetWindowLongA(hWnd, -21);
+if ( a2 == 1 )
+{
+if ( v4 )
+{
+v6 = GetDlgItem(hWnd, 1000);
+v4[3] = (SendMessageA(v6, 0xF0u, 0, 0) != 0) + 1;
+v7 = GetDlgItem(hWnd, 1001);
+v4[8] = SendMessageA(v7, 0xF0u, 0, 0) != 0;
+v8 = GetDlgItem(hWnd, 1004);
+v4[9] = SendMessageA(v8, 0xF0u, 0, 0) != 0;
+v9 = GetDlgItem(hWnd, 1010);
+v4[12] = SendMessageA(v9, 0xF0u, 0, 0) != 0;
+v10 = GetDlgItem(hWnd, 1005);
+v4[7] = SendMessageA(v10, 0xF0u, 0, 0) != 0;
+v11 = GetDlgItem(hWnd, 1003);
+GetWindowTextA(v11, aWavemixV23ByAn, 10);
+v4[5] = _atoi(aWavemixV23ByAn);
+v12 = GetDlgItem(hWnd, 1007);
+GetWindowTextA(v12, aWavemixV23ByAn, 10);
+v4[6] = _atoi(aWavemixV23ByAn);
+v13 = GetDlgItem(hWnd, 1008);
+GetWindowTextA(v13, aWavemixV23ByAn, 10);
+v4[4] = _atoi(aWavemixV23ByAn);
+v14 = GetDlgItem(hWnd, 1011);
+GetWindowTextA(v14, aWavemixV23ByAn, 10);
+v4[11] = _atoi(aWavemixV23ByAn);
+v15 = GetDlgItem(hWnd, 1009);
+GetWindowTextA(v15, aWavemixV23ByAn, 10);
+if ( _isdigit(aWavemixV23ByAn[0]) )
+v16 = _atoi(aWavemixV23ByAn);
+else
+v16 = 0;
+v4[10] = v16;
+EndDialog(hWnd, 1);
+}
+}
+else
+{
+if ( a2 != 2 )
+return 0;
+EndDialog(hWnd, 0);
+}
+return 1;
+}
+
+//----- (0101FC24) --------------------------------------------------------
+BOOL __stdcall SettingsDlgProc(HWND hWnd, UINT a2, WPARAM a3, LPARAM a4)
+{
+if ( a2 == 272 )
+return Settings_OnInitDialog(hWnd, a3, a4);
+if ( a2 != 273 )
+return 0;
+Settings_OnCommand(hWnd, (unsigned __int16)a3, a4, a3 >> 16);
+return 1;
+}
+
+//----- (0101FC6D) --------------------------------------------------------
+_DWORD *__stdcall MakeDlgTemplate(int a1, int a2, __int16 a3, __int16 a4, __int16 a5, __int16 a6, wchar_t *Str)
+{
+size_t v7; // eax
+HGLOBAL v8; // eax
+_DWORD *v9; // ebx
+
+v7 = 2 * _wcslen(Str) + 24;
+*(_DWORD *)a1 = v7;
+if ( v7 & 3 )
+*(_DWORD *)a1 = v7 - (v7 & 3) + 4;
+v8 = GlobalAlloc(0x42u, *(_DWORD *)a1);
+v9 = GlobalLock(v8);
+if ( v9 )
+{
+v9[1] = 0;
+*((_WORD *)v9 + 4) = 0;
+*v9 = a2 | 0x10000000;
+*((_WORD *)v9 + 5) = a3;
+*((_WORD *)v9 + 6) = a4;
+*((_WORD *)v9 + 7) = a5;
+*((_WORD *)v9 + 8) = a6;
+qmemcpy((char *)v9 + 22, Str, 2 * _wcslen(Str) + 2);
+}
+return v9;
+}
+
+//----- (0101FD0E) --------------------------------------------------------
+_WORD *__stdcall AddDlgControl(int a1, LPCVOID pMem, __int16 a3, int a4, __int16 a5, __int16 a6, __int16 a7, __int16 a8, __int16 a9, wchar_t *Str)
+{
+const void *v10; // edi
+HGLOBAL v11; // eax
+SIZE_T v12; // ST04_4
+HGLOBAL v13; // eax
+HGLOBAL v14; // eax
+int v15; // eax
+char *pMema; // [esp+10h] [ebp+Ch]
+
+v10 = pMem;
+if ( pMem )
+{
+pMema = *(char **)a1;
+*(_DWORD *)a1 += 2 * _wcslen(Str) + 25;
+if ( *(_DWORD *)a1 & 3 )
+*(_DWORD *)a1 = *(_DWORD *)a1 - (*(_DWORD *)a1 & 3) + 4;
+v11 = GlobalHandle(v10);
+GlobalUnlock(v11);
+v12 = *(_DWORD *)a1;
+v13 = GlobalHandle(v10);
+v14 = GlobalReAlloc(v13, v12, 0x42u);
+v10 = GlobalLock(v14);
+if ( v10 )
+{
+v15 = (int)&pMema[(_DWORD)v10];
+*(_DWORD *)(v15 + 4) = 0;
+*(_DWORD *)v15 = a4 | 0x50000000;
+*(_WORD *)(v15 + 8) = a6;
+*(_WORD *)(v15 + 10) = a7;
+*(_WORD *)(v15 + 12) = a8;
+*(_WORD *)(v15 + 14) = a9;
+*(_WORD *)(v15 + 16) = a5;
+*(_DWORD *)(v15 + 18) = ((unsigned __int16)a3 << 16) | 0xFFFF;
+_wcscpy((wchar_t *)&pMema[(_DWORD)v10 + 22], Str);
+++*((_WORD *)v10 + 4);
+}
+}
+return v10;
+}
+
+//----- (0101FDE1) --------------------------------------------------------
+_WORD *__stdcall MakeSettingsDlgTemplate()
+{
+_DWORD *v0; // eax
+_WORD *v1; // eax
+_WORD *v2; // eax
+_WORD *v3; // eax
+_WORD *v4; // eax
+_WORD *v5; // eax
+_WORD *v6; // eax
+_WORD *v7; // eax
+_WORD *v8; // eax
+_WORD *v9; // eax
+_WORD *v10; // eax
+_WORD *v11; // eax
+_WORD *v12; // eax
+_WORD *v13; // eax
+_WORD *v14; // eax
+_WORD *v15; // eax
+_WORD *v16; // eax
+_WORD *v17; // eax
+int v19; // [esp+Ch] [ebp-4h]
+
+v19 = 0;
+v0 = MakeDlgTemplate((int)&v19, -2134376320, 0, 0, 212, 132, L"WavMix32 Settings (Ver %X.%X Static)");
+v1 = AddDlgControl((int)&v19, v0, 128, 65537, 1, 155, 5, 50, 14, L"&Ok");
+v2 = AddDlgControl((int)&v19, v1, 128, 0x10000, 2, 155, 25, 50, 14, L"&Cancel");
+v3 = AddDlgControl((int)&v19, v2, 130, 0, 1012, 5, 5, 115, 8, L"Number of WaveBlocks (%d-%d):");
+v4 = AddDlgControl((int)&v19, v3, 130, 0, 1013, 5, 20, 115, 8, L"Size of WaveBlocks (%d-%d):");
+v5 = AddDlgControl((int)&v19, v4, 130, 0, 0xFFFF, 5, 35, 102, 8, L"Playback Frequency (11,22,44):");
+v6 = AddDlgControl((int)&v19, v5, 130, 0, 0xFFFF, 5, 80, 57, 8, L"Playback Device:");
+v7 = AddDlgControl((int)&v19, v6, 130, 0, 1014, 5, 50, 115, 8, L"Number of Pause Blocks (%d-%d):");
+v8 = AddDlgControl((int)&v19, v7, 130, 0, 1015, 5, 65, 63, 8, L"Max Channels = %d");
+v9 = AddDlgControl((int)&v19, v8, 129, 8454272, 1003, 125, 5, 25, 12, L"-1");
+v10 = AddDlgControl((int)&v19, v9, 129, 8454272, 1007, 125, 20, 25, 12, L"-1");
+v11 = AddDlgControl((int)&v19, v10, 129, 8454272, 1008, 125, 35, 25, 12, L"-1");
+v12 = AddDlgControl((int)&v19, v11, 129, 8454272, 1011, 125, 50, 25, 12, L"-1");
+v13 = AddDlgControl((int)&v19, v12, 133, 2162946, 1009, 65, 80, 140, 60, L"No Devices");
+v14 = AddDlgControl((int)&v19, v13, 128, 65539, 1000, 5, 101, 40, 10, L"Stereo");
+v15 = AddDlgControl((int)&v19, v14, 128, 65539, 1001, 55, 101, 60, 10, L"Reset Remix");
+v16 = AddDlgControl((int)&v19, v15, 128, 65539, 1010, 125, 101, 78, 10, L"Show Debug Dialogs");
+v17 = AddDlgControl((int)&v19, v16, 128, 65539, 1005, 5, 117, 40, 10, L"CMixit");
+return AddDlgControl((int)&v19, v17, 128, 65539, 1004, 55, 117, 75, 10, L"Good Get Position");
+}
+
+//----- (01020059) --------------------------------------------------------
+void __stdcall DestroySettingsDlgTemplate(LPCVOID pMem)
+{
+HGLOBAL v1; // eax
+HGLOBAL v2; // eax
+
+if ( pMem )
+{
+v1 = GlobalHandle(pMem);
+GlobalUnlock(v1);
+v2 = GlobalHandle(pMem);
+GlobalFree(v2);
+}
+}
+
+//----- (0102008D) --------------------------------------------------------
+signed int __stdcall WaveMixGetConfig(_WORD *a1, int a2)
+{
+_WORD *v2; // eax
+int v4; // ebx
+
+v2 = SessionToGlobalDataPtr(a1);
+hMem = (LPARAM)v2;
+if ( !v2 )
+return 5;
+if ( !a2 )
+return 11;
+v4 = *(_DWORD *)(a2 + 2);
+if ( v4 & 1 )
+*(_WORD *)(a2 + 6) = v2[191];
+if ( v4 & 2 )
+*(_WORD *)(a2 + 8) = 11 * (*((_DWORD *)v2 + 96) / 0x2B11u);
+if ( v4 & 4 )
+*(_WORD *)(a2 + 10) = v2[200];
+if ( v4 & 8 )
+*(_WORD *)(a2 + 12) = v2[198];
+if ( v4 & 0x10 )
+*(_WORD *)(a2 + 14) = *((_DWORD *)v2 + 107) == (_DWORD)cmixit;
+if ( v4 & 0x20 )
+*(_WORD *)(a2 + 16) = *((_DWORD *)v2 + 108) == (_DWORD)ResetRemix;
+if ( v4 & 0x40 )
+*(_WORD *)(a2 + 18) = v2[210];
+if ( (v4 & 0x80u) != 0 )
+*(_WORD *)(a2 + 20) = v2[12];
+if ( v4 & 0x100 )
+*(_WORD *)(a2 + 24) = dword_1027BE4 != 0;
+if ( v4 & 0x200 )
+*(_WORD *)(a2 + 22) = v2[202];
+return 0;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (0102018C) --------------------------------------------------------
+BOOL __stdcall SaveConfigSettings(__int16 a1)
+{
+BOOL result; // eax
+
+if ( (a1 & 0x80u) != 0 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", *(_DWORD *)(hMem + 24));
+result = WritePrivateProfileStringA("general", "WaveOutDevice", aWavemixV23ByAn, FileName);
+}
+if ( a1 & 1 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", *(unsigned __int16 *)(hMem + 382));
+result = WritePrivateProfileStringA((LPCSTR)(hMem + 28), "Channels", aWavemixV23ByAn, FileName);
+}
+if ( a1 & 2 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", (unsigned __int16)(11 * (*(_DWORD *)(hMem + 384) / 0x2B11u)));
+result = WritePrivateProfileStringA((LPCSTR)(hMem + 28), "SamplesPerSec", aWavemixV23ByAn, FileName);
+}
+if ( a1 & 4 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", *(_DWORD *)(hMem + 400));
+result = WritePrivateProfileStringA((LPCSTR)(hMem + 28), "WaveBlocks", aWavemixV23ByAn, FileName);
+}
+if ( a1 & 8 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", *(unsigned __int16 *)(hMem + 396));
+result = WritePrivateProfileStringA((LPCSTR)(hMem + 28), "WaveBlockLen", aWavemixV23ByAn, FileName);
+}
+if ( a1 & 0x10 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", *(_DWORD *)(hMem + 428) == (_DWORD)cmixit);
+result = WritePrivateProfileStringA((LPCSTR)(hMem + 28), "CMixit", aWavemixV23ByAn, FileName);
+}
+if ( a1 & 0x20 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", (*(_DWORD *)(hMem + 432) != (_DWORD)ResetRemix) + 1);
+result = WritePrivateProfileStringA((LPCSTR)(hMem + 28), "Remix", aWavemixV23ByAn, FileName);
+}
+if ( a1 & 0x40 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", *(_DWORD *)(hMem + 420) == 0);
+result = WritePrivateProfileStringA((LPCSTR)(hMem + 28), "GoodWavePos", aWavemixV23ByAn, FileName);
+}
+if ( a1 & 0x100 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", dword_1027BE4 != 0);
+result = WritePrivateProfileStringA("general", "ShowDebugDialogs", aWavemixV23ByAn, FileName);
+}
+if ( a1 & 0x200 )
+{
+_wsprintfA(aWavemixV23ByAn, "%d", *(_DWORD *)(hMem + 404));
+result = WritePrivateProfileStringA((LPCSTR)(hMem + 28), "PauseBlocks", aWavemixV23ByAn, FileName);
+}
+return result;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (010203CD) --------------------------------------------------------
+DWORD __stdcall SetIniFileName(HMODULE hModule)
+{
+DWORD result; // eax
+CHAR *i; // eax
+
+result = GetModuleFileNameA(hModule, FileName, 0x104u);
+if ( result )
+{
+for ( i = &FileName[result]; *i != 92; --i )
+;
+*i = 0;
+lstrcpyA(i, "\\WAVEMIX.INF");
+result = 1;
+}
+return result;
+}
+
+//----- (01020412) --------------------------------------------------------
+int __stdcall InitVolumeTable()
+{
+char *v0; // edi
+signed int v1; // esi
+int result; // eax
+int v3; // [esp+Ch] [ebp-Ch]
+int v4; // [esp+10h] [ebp-8h]
+int v5; // [esp+14h] [ebp-4h]
+
+v4 = 0;
+v3 = 0;
+v0 = (char *)&unk_10259F0;
+do
+{
+v1 = -128;
+v5 = v3;
+do
+{
+v0[v1] = v5 / 10 + -128;
+result = v4;
+v5 += v4;
+++v1;
+}
+while ( v1 < 128 );
+++v4;
+v3 -= 128;
+v0 += 256;
+}
+while ( (signed int)v0 <= (signed int)&unk_10263F0 );
+return result;
+}
+
+//----- (0102046F) --------------------------------------------------------
+int __stdcall WaveMixStartup(HMODULE hModule)
+{
+WNDCLASSA WndClass; // [esp+4h] [ebp-28h]
+
+if ( dword_1027BF4 )
+return 1;
+if ( !SetIniFileName(hModule) )
+return 0;
+InitVolumeTable();
+dword_1027BE8 = GetPrivateProfileIntA("general", "debug", 0, FileName);
+dword_1025968 = (int)cmixit;
+dword_10257E0 = hModule;
+WndClass.hCursor = LoadCursorA(0, (LPCSTR)0x7F00);
+WndClass.hIcon = 0;
+WndClass.lpszMenuName = 0;
+WndClass.lpszClassName = "WavMix32";
+WndClass.hbrBackground = (HBRUSH)GetStockObject(1);
+WndClass.hInstance = dword_10257E0;
+WndClass.style = 0;
+WndClass.lpfnWndProc = WndProc;
+WndClass.cbWndExtra = 0;
+WndClass.cbClsExtra = 0;
+if ( !RegisterClassA(&WndClass) )
+return 0;
+InitChannelNodes();
+dword_1027BF4 = 1;
+return 1;
+}
+// 1025968: using guessed type int dword_1025968;
+// 1027BE8: using guessed type int dword_1027BE8;
+// 1027BF4: using guessed type int dword_1027BF4;
+
+//----- (0102053B) --------------------------------------------------------
+signed int __stdcall WaveMixActivate(_WORD *a1, int a2)
+{
+_WORD *v2; // eax
+int v3; // ecx
+signed int result; // eax
+unsigned int v5; // ST04_4
+struct wavehdr_tag *v6; // eax
+DWORD v7; // eax
+bool v8; // zf
+
+v2 = SessionToGlobalDataPtr(a1);
+v3 = (int)v2;
+hMem = (LPARAM)v2;
+if ( !v2 )
+return 5;
+if ( a2 )
+{
+if ( dword_1025798 )
+return dword_1025798 != (_DWORD)v2 ? 4 : 0;
+if ( *((_DWORD *)v2 + 5) )
+return 12;
+dword_1025798 = (int)v2;
+sndPlaySoundA(0, 0);
+result = GetWaveDevice();
+if ( result )
+{
+dword_1025798 = 0;
+return result;
+}
+v5 = *(_DWORD *)(hMem + 412);
+*(_DWORD *)(hMem + 16) = 1;
+SetWaveOutPosition(v5);
+do
+v6 = (struct wavehdr_tag *)GetWaveBlock();
+while ( MixerPlay(v6, 1) );
+}
+else
+{
+if ( *((_DWORD *)v2 + 4) )
+{
+v7 = MyWaveOutGetPosition(*((HWAVEOUT *)v2 + 3), *((_DWORD *)v2 + 105));
+v3 = hMem;
+*(_DWORD *)(hMem + 412) = v7;
+}
+ReleaseWaveDevice(v3);
+v8 = hMem == dword_1025798;
+*(_DWORD *)(hMem + 16) = 0;
+if ( v8 )
+dword_1025798 = 0;
+}
+return 0;
+}
+// 1025798: using guessed type int dword_1025798;
+
+//----- (01020615) --------------------------------------------------------
+MMRESULT __stdcall WaveMixConfigure(int a1, HWND hWndParent, int a3, int a4, int a5)
+{
+_WORD *v5; // esi
+_WORD *v6; // eax
+const DLGTEMPLATE *v7; // esi
+INT_PTR v8; // edi
+LPARAM v9; // eax
+MMRESULT result; // eax
+_WORD *v11; // esi
+LPARAM *v12; // edi
+UINT_PTR v13; // eax
+LPARAM v14; // eax
+bool v15; // zf
+int v16; // ecx
+const char *v17; // eax
+int v18; // eax
+int v19; // eax
+int v20; // eax
+_DWORD *v21; // eax
+int v22; // eax
+signed int v23; // eax
+signed int v24; // ecx
+_DWORD *v25; // eax
+int v26; // ecx
+int v27; // edx
+unsigned __int16 v28; // ax
+unsigned int v29; // edx
+signed int v30; // ecx
+__int16 v31; // cx
+signed int (__stdcall *v32)(int, int); // eax
+int v33; // ecx
+_DWORD *v34; // eax
+int v35; // esi
+LPARAM dwInitParam; // [esp+Ch] [ebp-6Ch]
+unsigned __int16 v38; // [esp+18h] [ebp-60h]
+_DWORD *v39; // [esp+2Ch] [ebp-4Ch]
+_WORD *v40; // [esp+30h] [ebp-48h]
+int v41; // [esp+34h] [ebp-44h]
+LPARAM *v42; // [esp+38h] [ebp-40h]
+int v43; // [esp+3Ch] [ebp-3Ch]
+struct tagWAVEOUTCAPSA pwoc; // [esp+40h] [ebp-38h]
+
+v5 = (_WORD *)a1;
+v42 = (LPARAM *)a3;
+v40 = (_WORD *)a1;
+v39 = (_DWORD *)a4;
+v43 = 0;
+v6 = SessionToGlobalDataPtr((_WORD *)a1);
+hMem = (LPARAM)v6;
+if ( !v6 )
+return 5;
+if ( *((_DWORD *)v6 + 4) )
+return 4;
+if ( *((_DWORD *)v6 + 5) )
+return 12;
+WaveMixFlushChannel((_WORD *)a1, -1, 1);
+if ( !v42 )
+{
+LOWORD(dwInitParam) = 30;
+*(LPARAM *)((char *)&dwInitParam + 2) = 1023;
+WaveMixGetConfig((_WORD *)a1, (int)&dwInitParam);
+v7 = (const DLGTEMPLATE *)MakeSettingsDlgTemplate();
+if ( !v7 )
+return 1;
+*(_DWORD *)(hMem + 20) = 1;
+v8 = DialogBoxIndirectParamA(dword_10257E0, v7, hWndParent, SettingsDlgProc, (LPARAM)&dwInitParam);
+DestroySettingsDlgTemplate(v7);
+v9 = hMem;
+*(_DWORD *)(hMem + 20) = 0;
+if ( v8 != 1 )
+return 1;
+if ( *(_DWORD *)(v9 + 396) == v38 )
+*(LPARAM *)((char *)&dwInitParam + 2) &= 0xFFFFFFF7;
+v5 = v40;
+v42 = &dwInitParam;
+}
+if ( !*(LPARAM *)((char *)v42 + 2) )
+return 1;
+v11 = SessionToGlobalDataPtr(v5);
+hMem = (LPARAM)v11;
+if ( !v11 )
+return 5;
+v12 = v42;
+v41 = *(LPARAM *)((char *)v42 + 2);
+if ( v41 & 0x100 )
+dword_1027BE4 = *((_WORD *)v42 + 12) != 0;
+if ( (v41 & 0x80u) != 0 )
+{
+v13 = *((unsigned __int16 *)v42 + 10);
+if ( v13 != *((_DWORD *)v11 + 6) )
+{
+result = waveOutGetDevCapsA(v13, &pwoc, 0x34u);
+if ( result )
+return result;
+v14 = hMem;
+qmemcpy((void *)(hMem + 124), &pwoc, 0x34u);
+v15 = *(_WORD *)(v14 + 168) == 1;
+*(_DWORD *)(v14 + 24) = *((unsigned __int16 *)v42 + 10);
+if ( v15 && *(_WORD *)(v14 + 382) == 2 )
+{
+*(_WORD *)(v14 + 382) = 1;
+v16 = *(_DWORD *)(v14 + 384);
+v43 = 1;
+*(_WORD *)(v14 + 392) = 1;
+*(_DWORD *)(v14 + 388) = v16;
+}
+lstrcpyA((LPSTR)(v14 + 28), pwoc.szPname);
+if ( !RemoveInvalidIniNameCharacters((LPCSTR)(hMem + 28)) )
+lstrcpyA((LPSTR)(hMem + 28), "Unkown Device");
+if ( !ReadRegistryToGetMachineSpecificInfSection(*(_DWORD *)(hMem + 24), (LPSTR)(hMem + 28), 96) )
+{
+v17 = GetOperatingSystemPrefix();
+lstrcpyA((LPSTR)(hMem + 28), v17);
+lstrcatA((LPSTR)(hMem + 28), (LPCSTR)(hMem + 132));
+}
+v11 = (_WORD *)hMem;
+v12 = v42;
+}
+}
+if ( v41 & 1 )
+{
+if ( *((_WORD *)v12 + 3) <= 1u )
+{
+if ( v11[191] == 2 )
+v43 = 1;
+v11[191] = 1;
+v19 = *((_DWORD *)v11 + 96);
+v11[196] = 1;
+goto LABEL_39;
+}
+if ( v11[84] > 1u )
+{
+if ( v11[191] == 1 )
+v43 = 1;
+v11[191] = 2;
+v18 = *((_DWORD *)v11 + 96);
+v11[196] = 2;
+v19 = 2 * v18;
+LABEL_39:
+*((_DWORD *)v11 + 97) = v19;
+goto LABEL_40;
+}
+}
+LABEL_40:
+if ( v41 & 2 )
+{
+v20 = *((unsigned __int16 *)v12 + 4);
+if ( v20 == 22 )
+{
+if ( *((_DWORD *)v11 + 96) != 22050 )
+v43 = 1;
+*((_DWORD *)v11 + 96) = 22050;
+v22 = 22050 * (unsigned __int16)v11[191];
+}
+else
+{
+v15 = v20 == 44;
+v21 = v11 + 192;
+if ( v15 )
+{
+if ( *v21 != 44100 )
+v43 = 1;
+*v21 = 44100;
+v22 = 44100 * (unsigned __int16)v11[191];
+}
+else
+{
+if ( *v21 != 11025 )
+v43 = 1;
+*v21 = 11025;
+v22 = 11025 * (unsigned __int16)v11[191];
+}
+}
+*((_DWORD *)v11 + 97) = v22;
+}
+if ( v41 & 4 )
+{
+v23 = *((unsigned __int16 *)v12 + 5);
+v24 = 2;
+*((_DWORD *)v11 + 100) = v23;
+if ( v23 < 2 || (v24 = 10, v23 > 10) )
+*((_DWORD *)v11 + 100) = v24;
+v25 = v11 + 202;
+v26 = *((_DWORD *)v11 + 101);
+if ( v26 >= 0 )
+{
+v27 = *((_DWORD *)v11 + 100);
+if ( v26 > v27 )
+*v25 = v27;
+}
+else
+{
+*v25 = 0;
+}
+}
+if ( v43 )
+*((_DWORD *)v11 + 99) = FigureOutDMABufferSize(0, (int)(v11 + 190));
+if ( v41 & 8 )
+{
+v28 = *((_WORD *)v12 + 6);
+if ( v28 )
+*((_DWORD *)v11 + 99) = v28;
+}
+v29 = *((_DWORD *)v11 + 99);
+v30 = 344;
+if ( v29 < 0x158 || (v30 = 11025, v29 > 0x2B11) )
+*((_DWORD *)v11 + 99) = v30;
+v31 = v41;
+if ( v41 & 0x10 )
+*((_DWORD *)v11 + 107) = cmixit;
+if ( v31 & 0x20 )
+{
+v32 = ResetRemix;
+if ( !*((_WORD *)v12 + 8) )
+v32 = NoResetRemix;
+*((_DWORD *)v11 + 108) = v32;
+}
+if ( v31 & 0x40 )
+*((_DWORD *)v11 + 105) = *((_WORD *)v12 + 9) != 0;
+if ( v31 & 0x200 )
+{
+v33 = *((unsigned __int16 *)v12 + 11);
+v34 = v11 + 202;
+*((_DWORD *)v11 + 101) = v33;
+if ( v33 >= 0 )
+{
+v35 = *((_DWORD *)v11 + 100);
+if ( v33 > v35 )
+*v34 = v35;
+}
+else
+{
+*v34 = 0;
+}
+}
+WaveMixGetConfig(v40, (int)v12);
+if ( v39 )
+*v39 = v43;
+if ( a5 )
+SaveConfigSettings(v41);
+if ( dword_1027BE4 )
+ShowCurrentSettings();
+return 0;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (01020A36) --------------------------------------------------------
+signed int __stdcall ReadConfigSettings(int a1)
+{
+UINT v2; // eax
+UINT_PTR *v3; // ebx
+const char *v4; // eax
+unsigned int v5; // eax
+UINT v6; // eax
+signed int (__stdcall *v7)(int, int); // ecx
+LPARAM v8; // eax
+UINT v9; // ecx
+LPARAM v10; // eax
+signed int v11; // eax
+LPARAM v12; // ecx
+signed int v13; // edx
+int v14; // eax
+signed int v15; // eax
+LPARAM v16; // ecx
+signed int v17; // edx
+unsigned __int16 v18; // ax
+LPARAM v19; // ecx
+int v20; // eax
+int v21; // eax
+unsigned int v22; // eax
+int v23; // esi
+const CHAR *v24; // [esp-10h] [ebp-24h]
+int v25; // [esp-Ch] [ebp-20h]
+UINT v26; // [esp+4h] [ebp-10h]
+UINT v27; // [esp+8h] [ebp-Ch]
+UINT v28; // [esp+Ch] [ebp-8h]
+unsigned int nDefault; // [esp+10h] [ebp-4h]
+UINT nDefaulta; // [esp+10h] [ebp-4h]
+INT nDefaultb; // [esp+10h] [ebp-4h]
+
+nDefault = waveOutGetNumDevs();
+if ( !nDefault )
+return 0;
+if ( *(_BYTE *)(a1 + 3) & 4 && ReadRegistryForAppSpecificConfigs(a1) )
+{
+WaveMixConfigure(hMem, 0, a1, 0, 0);
+return 1;
+}
+if ( *(_BYTE *)(a1 + 2) >= 0 )
+{
+v3 = (UINT_PTR *)(hMem + 24);
+v2 = GetPrivateProfileIntA("general", "WaveOutDevice", 0, FileName);
+}
+else
+{
+v2 = *(unsigned __int16 *)(a1 + 20);
+v3 = (UINT_PTR *)(hMem + 24);
+}
+*v3 = v2;
+if ( *v3 >= nDefault )
+*v3 = 0;
+if ( waveOutGetDevCapsA(*v3, (LPWAVEOUTCAPSA)(hMem + 124), 0x34u)
+|| !RemoveInvalidIniNameCharacters((LPCSTR)(hMem + 132)) )
+{
+lstrcpyA((LPSTR)(hMem + 132), "Unkown Device");
+}
+if ( !ReadRegistryToGetMachineSpecificInfSection(*(_DWORD *)(hMem + 24), (LPSTR)(hMem + 28), 96) )
+{
+v4 = GetOperatingSystemPrefix();
+lstrcpyA((LPSTR)(hMem + 28), v4);
+lstrcatA((LPSTR)(hMem + 28), (LPCSTR)(hMem + 132));
+}
+nDefaulta = GetPrivateProfileIntA("default", "Remix", 1, FileName);
+v5 = DefaultGoodWavePos(*(_DWORD *)(hMem + 24));
+v28 = GetPrivateProfileIntA("default", "GoodWavePos", v5, FileName);
+v27 = GetPrivateProfileIntA("default", "WaveBlocks", 3, FileName);
+v26 = GetPrivateProfileIntA("default", "SamplesPerSec", 11, FileName);
+if ( *(_BYTE *)(hMem + 172) & 0x10 )
+{
+if ( !dword_1027BE4 )
+return 0;
+v25 = hMem + 132;
+v24 = "%s is a syncronous (blocking) wave output device. This will not permit audio to play while other applications are running.";
+LABEL_19:
+_wsprintfA(aWavemixV23ByAn, v24, v25);
+MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x40u);
+return 0;
+}
+if ( GetPrivateProfileIntA("not compatible", (LPCSTR)(hMem + 28), 0, FileName) )
+{
+if ( !dword_1027BE4 )
+return 0;
+v25 = hMem + 28;
+v24 = "%s is not compatible with the realtime wavemixer.";
+goto LABEL_19;
+}
+v6 = GetPrivateProfileIntA((LPCSTR)(hMem + 28), "Remix", nDefaulta, FileName);
+v7 = NoResetRemix;
+if ( v6 != 2 )
+v7 = ResetRemix;
+v8 = hMem;
+*(_DWORD *)(hMem + 432) = v7;
+v9 = GetPrivateProfileIntA((LPCSTR)(v8 + 28), "GoodWavePos", v28, FileName);
+v10 = hMem;
+*(_DWORD *)(hMem + 420) = v9 != 0;
+v11 = GetPrivateProfileIntA((LPCSTR)(v10 + 28), "WaveBlocks", v27, FileName);
+v12 = hMem;
+v13 = 2;
+*(_DWORD *)(hMem + 400) = v11;
+if ( v11 < 2 || (v13 = 10, v11 > 10) )
+*(_DWORD *)(v12 + 400) = v13;
+v14 = DefaultPauseBlocks(*(_DWORD *)(v12 + 400));
+v15 = GetPrivateProfileIntA((LPCSTR)(hMem + 28), "PauseBlocks", v14, FileName);
+v16 = hMem;
+*(_DWORD *)(hMem + 404) = v15;
+if ( v15 >= 0 )
+{
+v17 = *(_DWORD *)(v16 + 400);
+if ( v15 > v17 )
+*(_DWORD *)(v16 + 404) = v17;
+}
+else
+{
+*(_DWORD *)(v16 + 404) = 0;
+}
+nDefaultb = GetPrivateProfileIntA((LPCSTR)(v16 + 28), "SamplesPerSec", v26, FileName);
+v18 = GetPrivateProfileIntA((LPCSTR)(hMem + 28), "Channels", 1, FileName);
+v19 = hMem;
+*(_WORD *)(hMem + 382) = v18;
+if ( v18 >= 1u )
+{
+if ( v18 > 2u )
+*(_WORD *)(v19 + 382) = 2;
+}
+else
+{
+*(_WORD *)(v19 + 382) = 1;
+}
+v20 = *(unsigned __int16 *)(v19 + 382);
+if ( nDefaultb == 22 )
+{
+*(_DWORD *)(v19 + 384) = 22050;
+v21 = 22050 * v20;
+}
+else if ( nDefaultb == 44 )
+{
+*(_DWORD *)(v19 + 384) = 44100;
+v21 = 44100 * v20;
+}
+else
+{
+v21 = 11025 * v20;
+}
+*(_DWORD *)(v19 + 388) = v21;
+v22 = GetPrivateProfileIntA("default", "WaveBlockLen", 0, FileName);
+v23 = hMem;
+*(_DWORD *)(v23 + 396) = FigureOutDMABufferSize(v22, hMem + 380);
+WaveMixConfigure(v23, 0, a1, 0, 0);
+return 1;
+}
+// 1027BE4: using guessed type int dword_1027BE4;
+
+//----- (01020D99) --------------------------------------------------------
+int __stdcall WaveMixConfigureInit(_WORD *a1)
+{
+unsigned int v1; // ecx
+HMODULE v2; // eax
+int result; // eax
+BOOL v4; // eax
+_DWORD *v5; // eax
+_WORD *v6; // eax
+void *v7; // ST0C_4
+__int16 v8; // [esp+8h] [ebp-20h]
+char v9; // [esp+Bh] [ebp-1Dh]
+__int16 v10; // [esp+20h] [ebp-8h]
+__int16 v11; // [esp+24h] [ebp-4h]
+
+memset(&v8, 0, 0x1Cu);
+v1 = 30;
+v11 = 0;
+v8 = 30;
+if ( a1 )
+{
+if ( *a1 < 0x1Eu )
+v1 = (unsigned __int16)*a1;
+qmemcpy(&v8, a1, v1);
+}
+if ( dword_1027BF4 || (v2 = GetModuleHandleA(0), (result = WaveMixStartup(v2)) != 0) )
+{
+if ( v9 & 1 )
+v4 = v10 != 0;
+else
+v4 = GetPrivateProfileIntA("general", "ShowDebugDialogs", 0, FileName) != 0;
+dword_1027BE4 = v4;
+if ( !waveOutGetNumDevs() )
+{
+if ( dword_1027BE4 )
+{
+_wsprintfA(aWavemixV23ByAn, "This system does not have a valid wave output device.");
+MessageBoxA(0, aWavemixV23ByAn, "WavMix32", 0x40u);
+}
+return 0;
+}
+if ( GetPrivateProfileIntA("general", "ShowDevices", 0, FileName) )
+ShowWaveOutDevices();
+v5 = LocalAlloc(0x40u, 0x1C0u);
+hMem = (LPARAM)v5;
+if ( !v5 )
+return 0;
+v5[107] = dword_1025968;
+*((_WORD *)v5 + 222) = 21554;
+*(_WORD *)v5 = 21554;
+v5[102] = 0;
+v5[5] = 0;
+*((_WORD *)v5 + 88) = 10;
+*((_WORD *)v5 + 89) = 10;
+memset(v5 + 61, 0xFFu, 0x40u);
+_memmove(v5 + 95, gpFormat, 0x10u);
+if ( !ReadConfigSettings((int)&v8) )
+{
+v6 = (_WORD *)hMem;
+v7 = (void *)hMem;
+*(_WORD *)(hMem + 444) = 0;
+*v6 = 0;
+LocalFree(v7);
+hMem = 0;
+}
+result = hMem;
+}
+return result;
+}
+// 10028C0: using guessed type int gpFormat[4];
+// 1025968: using guessed type int dword_1025968;
+// 1027BE4: using guessed type int dword_1027BE4;
+// 1027BF4: using guessed type int dword_1027BF4;
+
+//----- (01020F2D) --------------------------------------------------------
+int __stdcall WaveMixInit()
+{
+return WaveMixConfigureInit(0);
+}
+
+//----- (01020F3A) --------------------------------------------------------
+HLOCAL __stdcall WaveMixCloseSession(HLOCAL hMem)
+{
+void *v1; // edi
+HLOCAL result; // eax
+
+::hMem = (LPARAM)SessionToGlobalDataPtr(hMem);
+if ( !::hMem
+|| (WaveMixActivate(hMem, 0),
+WaveMixCloseChannel(hMem, 0, 1),
+v1 = (void *)::hMem,
+::hMem = 0,
+memset(v1, 0, 0x1C0u),
+!hMem)
+|| (result = LocalFree(hMem)) != 0 )
+{
+result = (HLOCAL)5;
+}
+return result;
+}
diff --git a/windows.cpp b/windows.cpp
new file mode 100644
index 0000000..f3ab557
--- /dev/null
+++ b/windows.cpp
@@ -0,0 +1,1062 @@
+//
+// Created by neo on 2019-08-15.
+//
+
+#include "pinball.h"
+
+//----- (0100833A) --------------------------------------------------------
+int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
+{
+ CHAR *v4; // eax
+ CHAR *v5; // eax
+ int v6; // eax
+ CHAR *v7; // ST24_4
+ CHAR *v8; // eax
+ signed int v9; // edi
+ CHAR *v10; // eax
+ CHAR *v11; // eax
+ CHAR *v12; // ST2C_4
+ CHAR *v13; // eax
+ CHAR *v14; // eax
+ CHAR *v15; // eax
+ CHAR *v16; // eax
+ HINSTANCE v17; // edi
+ CHAR *v18; // ST28_4
+ CHAR *v19; // eax
+ CHAR *v20; // eax
+ HWND v21; // eax
+ CHAR *v22; // eax
+ CHAR *v23; // eax
+ HWND v24; // eax
+ HMENU v26; // eax
+ DWORD (__stdcall *v27)(); // edi
+ DWORD v28; // eax
+ HINSTANCE v29; // eax
+ char *v30; // esi
+ signed int v31; // edx
+ signed int v32; // edi
+ _BYTE *v33; // eax
+ char v34; // cl
+ char v35; // cl
+ DWORD v36; // eax
+ int v37; // eax
+ HINSTANCE v38; // ST2C_4
+ CHAR *v39; // eax
+ WNDCLASSA WndClass; // [esp+14h] [ebp-13Ch]
+ INITCOMMONCONTROLSEX picce; // [esp+3Ch] [ebp-114h]
+ HINSTANCE v42; // [esp+44h] [ebp-10Ch]
+ LPCSTR lpString1; // [esp+48h] [ebp-108h]
+ int v44; // [esp+4Ch] [ebp-104h]
+ HINSTANCE v45; // [esp+50h] [ebp-100h]
+ char *Str; // [esp+54h] [ebp-FCh]
+ int v47; // [esp+58h] [ebp-F8h]
+ struct tagPOINT Point; // [esp+5Ch] [ebp-F4h]
+ CHAR String1; // [esp+64h] [ebp-ECh]
+ struct tagMSG Dest; // [esp+12Ch] [ebp-24h]
+
+ v42 = hInstance;
+ Str = lpCmdLine;
+ v47 = 300;
+ v45 = 0;
+ memory_init((int)winmain_memalloc_failure);
+ ++memory_critical_allocation;
+ v4 = get_rc_string(165, 0);
+ options_path_init(v4);
+ v5 = get_rc_string(166, 0);
+ if ( (signed int)options_get_int((DWORD)v5, "Table Version", (HKEY)1) <= 1 )
+ {
+ Point.y = memoryallocate(0x1F4u);
+ if ( !Point.y )
+ {
+ LABEL_3:
+ options_path_uninit();
+ return 0;
+ }
+ v10 = get_rc_string(166, 0);
+ options_set_int((HKEY)v10, "Table Version", 1u);
+ GetModuleFileNameA(hinst, (LPSTR)Point.y, 0x1F4u);
+ v11 = get_rc_string(166, 0);
+ options_set_string((HKEY)v11, "Table Exe", (LPCSTR)Point.y);
+ v12 = get_rc_string(169, 0);
+ v13 = get_rc_string(166, 0);
+ options_set_string((HKEY)v13, "Table Name", v12);
+ v14 = get_rc_string(166, 0);
+ options_set_string(0, "Last Table Played", v14);
+ memoryfree(Point.y);
+ Point.y = memoryallocate(0x1F4u);
+ if ( Point.y )
+ {
+ lpString1 = (LPCSTR)memoryallocate(0x1F4u);
+ if ( lpString1 )
+ {
+ v44 = 0;
+ do
+ {
+ _sprintf((char *)&Dest, "Table%d", v44);
+ options_get_string(0, (LPCSTR)&Dest, (LPSTR)Point.y, WindowName, 500);
+ if ( !*(_BYTE *)Point.y )
+ break;
+ options_get_string(Point.y, "Table Name", (LPSTR)lpString1, WindowName, 500);
+ v15 = get_rc_string(169, 0);
+ if ( !lstrcmpA(lpString1, v15) )
+ goto LABEL_15;
+ if ( !*lpString1 )
+ break;
+ ++v44;
+ }
+ while ( v44 < 32700 );
+ v16 = get_rc_string(166, 0);
+ options_set_string(0, (LPCSTR)&Dest, v16);
+ LABEL_15:
+ memoryfree((int)lpString1);
+ }
+ memoryfree(Point.y);
+ }
+ }
+ else
+ {
+ v6 = memoryallocate(0x1F4u);
+ Point.y = v6;
+ if ( !v6 )
+ goto LABEL_3;
+ v7 = (CHAR *)v6;
+ v8 = get_rc_string(166, 0);
+ options_get_string((DWORD)v8, "Shell Exe", v7, WindowName, 500);
+ v9 = WinExec((LPCSTR)Point.y, 5u);
+ memoryfree(Point.y);
+ if ( v9 >= 32 )
+ goto LABEL_3;
+ }
+ --memory_critical_allocation;
+ v17 = v42;
+ dword_102556C = _strstr(Str, "-quick") != 0;
+ hinst = v42;
+ v18 = get_rc_string(168, 0);
+ v19 = get_rc_string(166, 0);
+ options_get_string((DWORD)v19, "Pinball Data", byte_102543C, v18, 300);
+ iFrostUniqueMsg = RegisterWindowMessageA("PinballThemeSwitcherUniqueMsgString");
+ v20 = get_rc_string(167, 0);
+ v21 = FindWindowA(v20, 0);
+ if ( v21 )
+ {
+ SendMessageA(v21, iFrostUniqueMsg, 0, 0);
+ return 0;
+ }
+ if ( check_expiration_date() )
+ return 0;
+ picce.dwSize = 8;
+ picce.dwICC = 5885;
+ InitCommonControlsEx(&picce);
+ WndClass.style = 4104;
+ WndClass.lpfnWndProc = message_handler;
+ WndClass.cbClsExtra = 0;
+ WndClass.cbWndExtra = 0;
+ WndClass.hInstance = v17;
+ WndClass.hIcon = LoadIconA(v17, "ICON_1");
+ WndClass.hCursor = LoadCursorA(0, (LPCSTR)0x7F00);
+ WndClass.hbrBackground = (HBRUSH)16;
+ WndClass.lpszMenuName = "MENU_1";
+ WndClass.lpszClassName = get_rc_string(167, 0);
+ Point.y = splash_screen((int)v17, "splash_bitmap", "splash_bitmap");
+ RegisterClassA(&WndClass);
+ FindShiftKeys();
+ v22 = get_rc_string(38, 0);
+ lstrcpyA(&String1, v22);
+ v23 = get_rc_string(167, 0);
+ v24 = CreateWindowExA(0, v23, &String1, 0x3CA0000u, 0, 0, 640, 480, 0, 0, v17, 0);
+ hwnd_frame = v24;
+ if ( !v24 )
+ {
+ PostQuitMessage(0);
+ return 0;
+ }
+ v26 = GetMenu(v24);
+ options_init(v26);
+ pb_reset_table();
+ pb_firsttime_setup();
+ if ( _strstr(Str, "-fullscreen") )
+ {
+ dword_102822C = (HKEY)1;
+ options_menu_check(0x193u, 1);
+ }
+ ShowWindow(hwnd_frame, nShowCmd);
+ fullscrn_set_screen_mode((int)dword_102822C);
+ UpdateWindow(hwnd_frame);
+ if ( Point.y )
+ {
+ splash_hide(Point.y);
+ splash_destroy(Point.y);
+ }
+ adjust_priority((int)dword_1028230);
+ v27 = timeGetTime;
+ Point.y = timeGetTime();
+ while ( timeGetTime() >= Point.y && timeGetTime() - Point.y < 0x7D0 )
+ PeekMessageA(&Dest, hwnd_frame, 0, 0, 1u);
+ if ( _strstr(Str, "-demo") )
+ pb_toggle_demo(0);
+ else
+ pb_replay_level(0);
+ v28 = timeGetTime();
+ LABEL_35:
+ then = v28;
+ while ( 1 )
+ {
+ if ( !v47 )
+ {
+ v47 = 300;
+ if ( DispFrameRate )
+ {
+ v29 = (HINSTANCE)v27();
+ v42 = v29;
+ if ( v45 )
+ {
+ Str = (char *)((char *)v29 - (char *)v45);
+ _sprintf(::Dest, "Frames/sec = %02.02f", 300.0 / ((double)(unsigned int)((char *)v29 - (char *)v45) * 0.001));
+ SetWindowTextA(hwnd_frame, ::Dest);
+ if ( DispGRhistory )
+ {
+ if ( !dword_10281C8 )
+ {
+ v30 = (char *)_malloc(0x400u);
+ v31 = 0;
+ v32 = 0;
+ v33 = v30 + 41;
+ do
+ {
+ if ( v31 + 10 >= 256 )
+ break;
+ v34 = v32;
+ if ( v32 > 255 )
+ v34 = -1;
+ v33[1] = v34;
+ v35 = v32;
+ if ( v32 > 255 )
+ v35 = v31;
+ *v33 = v35;
+ *(v33 - 1) = v35;
+ v32 += 8;
+ v33 += 4;
+ ++v31;
+ }
+ while ( v31 < 256 );
+ gdrv_display_palette((int)v30);
+ _free(v30);
+ gdrv_create_bitmap((int)&gfr_display, 400, 15);
+ v27 = timeGetTime;
+ }
+ gdrv_blit((int)&gfr_display, 0, 0, 0, 0, 300, 10);
+ gdrv_fill_bitmap(0, &gfr_display, 0x12Cu, 10, 0, 0, 0);
+ }
+ }
+ v45 = v42;
+ }
+ else
+ {
+ v45 = 0;
+ }
+ }
+ Sound_Idle();
+ if ( !sub_10082A9() || bQuit )
+ break;
+ if ( has_focus )
+ {
+ if ( mouse_down )
+ {
+ now = v27();
+ if ( now - then >= 2 )
+ {
+ GetCursorPos(&Point);
+ pb_ballset(last_mouse_x - Point.x, Point.y - last_mouse_y);
+ SetCursorPos(last_mouse_x, last_mouse_y);
+ }
+ }
+ if ( !single_step )
+ {
+ v36 = v27();
+ now = v36;
+ if ( no_time_loss )
+ {
+ then = v36;
+ no_time_loss = 0;
+ }
+ if ( v36 == then )
+ {
+ Sleep(8u);
+ }
+ else if ( pb_frame(0, v36 - then) )
+ {
+ if ( dword_10281C8 )
+ {
+ v37 = now - then + 10;
+ if ( v37 > 236 )
+ LOBYTE(v37) = -7;
+ gdrv_fill_bitmap(0, &gfr_display, 1u, 10, 299 - v47, 0, v37);
+ }
+ --v47;
+ v28 = now;
+ goto LABEL_35;
+ }
+ }
+ }
+ }
+ gdrv_destroy_bitmap((int)&gfr_display);
+ options_uninit();
+ midi_music_shutdown();
+ pb_uninit();
+ Sound_Close();
+ gdrv_uninit();
+ DestroyWindow(hwnd_frame);
+ options_path_uninit();
+ v38 = hinst;
+ v39 = get_rc_string(167, 0);
+ UnregisterClassA(v39, v38);
+ return return_value;
+}
+// 1024F04: using guessed type int memory_critical_allocation;
+// 1024FD8: using guessed type int single_step;
+// 1024FDC: using guessed type int bQuit;
+// 1024FE0: using guessed type int DispFrameRate;
+// 1024FE4: using guessed type int DispGRhistory;
+// 1024FE8: using guessed type int mouse_down;
+// 1024FEC: using guessed type int has_focus;
+// 1024FF4: using guessed type int no_time_loss;
+// 102556C: using guessed type int dword_102556C;
+// 10281A0: using guessed type int then;
+// 10281C8: using guessed type int dword_10281C8;
+// 10281F0: using guessed type int now;
+// 1028200: using guessed type int return_value;
+
+//----- (010076BF) --------------------------------------------------------
+int __stdcall make_path_name(LPSTR lpFilename, LPCSTR lpString2, DWORD nSize)
+{
+ DWORD v3; // eax
+ CHAR *i; // ecx
+
+ v3 = GetModuleFileNameA(hinst, lpFilename, nSize);
+ if ( v3 && v3 != nSize )
+ {
+ for ( i = &lpFilename[v3]; i > lpFilename; --i )
+ {
+ if ( *i == 92 || *i == 58 )
+ {
+ i[1] = 0;
+ break;
+ }
+ --v3;
+ }
+ if ( (signed int)(v3 + 13) < (signed int)nSize )
+ {
+ lstrcatA(lpFilename, lpString2);
+ return 0;
+ }
+ lstrcatA(lpFilename, "?");
+ }
+ return 1;
+}
+
+//----- (01007918) --------------------------------------------------------
+void __usercall winmain_pause(int a1) {
+if ( fullscrn_screen_mode )
+{
+if ( single_step )
+fullscrn_set_menu_mode(0);
+else
+fullscrn_set_menu_mode(1);
+}
+pb_pause_continue(a1);
+no_time_loss = 1;
+}
+// 1024EE4: using guessed type int fullscrn_screen_mode;
+// 1024FD8: using guessed type int single_step;
+// 1024FF4: using guessed type int no_time_loss;
+
+//----- (01007949) --------------------------------------------------------
+void __usercall winmain_end_pause(int a1)
+{
+if ( single_step )
+{
+if ( fullscrn_screen_mode )
+fullscrn_set_menu_mode(0);
+pb_pause_continue(a1);
+no_time_loss = 1;
+}
+}
+// 1024EE4: using guessed type int fullscrn_screen_mode;
+// 1024FD8: using guessed type int single_step;
+// 1024FF4: using guessed type int no_time_loss;
+
+//----- (01007976) --------------------------------------------------------
+HCURSOR __usercall winmain_new_game(int a1)
+{
+HCURSOR v1; // eax
+HCURSOR v2; // edi
+
+winmain_end_pause(a1);
+v1 = LoadCursorA(0, (LPCSTR)0x7F02);
+v2 = SetCursor(v1);
+pb_replay_level(0);
+return SetCursor(v2);
+}
+
+//----- (010079A9) --------------------------------------------------------
+void __stdcall __noreturn winmain_memalloc_failure()
+{
+ CHAR *v0; // ST08_4
+ CHAR *v1; // eax
+
+ midi_music_stop();
+ Sound_Close();
+ gdrv_uninit();
+ v0 = get_rc_string(170, 0);
+ v1 = get_rc_string(179, 0);
+ MessageBoxA(0, v1, v0, 0x2030u);
+ _exit(1);
+}
+
+//----- (010079ED) --------------------------------------------------------
+HANDLE __stdcall adjust_priority(int a1)
+{
+ HANDLE result; // eax
+
+ result = GetCurrentThread();
+ switch ( a1 )
+ {
+ case -2:
+ return (HANDLE)SetThreadPriority(result, -2);
+ case -1:
+ return (HANDLE)SetThreadPriority(result, -1);
+ case 0:
+ return (HANDLE)SetThreadPriority(result, 0);
+ case 1:
+ return (HANDLE)SetThreadPriority(result, 1);
+ case 2:
+ return (HANDLE)SetThreadPriority(result, 2);
+ case 3:
+ result = (HANDLE)SetThreadPriority(result, 15);
+ break;
+ }
+ return result;
+}
+
+//----- (01007A3E) --------------------------------------------------------
+LRESULT __stdcall message_handler(HWND hWnd, UINT Msg, WPARAM wParam, int a4)
+{
+ WPARAM v5; // ebx
+ HWND v6; // eax
+ HCURSOR v7; // eax
+ HCURSOR v8; // ebx
+ HKEY v9; // eax
+ HKEY v10; // ST18_4
+ HMENU v11; // eax
+ HANDLE v12; // eax
+ bool v13; // zf
+ char *v14; // ebx
+ CHAR *v15; // ST14_4
+ CHAR *v16; // eax
+ struct tagRECT Rect; // [esp+8h] [ebp-64h]
+ int v18; // [esp+18h] [ebp-54h]
+ LPARAM lParam; // [esp+1Ch] [ebp-50h]
+ LPSTR lpString1; // [esp+20h] [ebp-4Ch]
+ HWND v21; // [esp+24h] [ebp-48h]
+ PAINTSTRUCT Paint; // [esp+28h] [ebp-44h]
+
+ v21 = hWnd;
+ lParam = a4;
+ if ( Msg != iFrostUniqueMsg )
+ {
+ v5 = wParam;
+ if ( Msg <= 0x1C )
+ {
+ if ( Msg == 28 )
+ {
+ if ( wParam )
+ {
+ activated = 1;
+ Sound_Activate();
+ if ( phkResult && !single_step )
+ midi_play_pb_theme(0);
+ no_time_loss = 1;
+ adjust_priority((int)dword_1028230);
+ }
+ else
+ {
+ activated = 0;
+ fullscrn_activate(0);
+ options_menu_check(0x193u, 0);
+ dword_102822C = 0;
+ v12 = GetCurrentThread();
+ SetThreadPriority(v12, 0);
+ Sound_Deactivate();
+ midi_music_stop();
+ }
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ if ( Msg <= 8 )
+ {
+ if ( Msg != 8 )
+ {
+ if ( Msg == 1 )
+ {
+ ++memory_critical_allocation;
+ v6 = GetDesktopWindow();
+ GetWindowRect(v6, &Rect);
+ v18 = Rect.right - Rect.left;
+ lpString1 = (LPSTR)(Rect.bottom - Rect.top);
+ pb_window_size(&v18, &lpString1);
+ v7 = LoadCursorA(0, (LPCSTR)0x7F02);
+ v8 = SetCursor(v7);
+ gdrv_init((int)hinst, v21);
+ v9 = options_get_int(0, "Voices", (HKEY)8);
+ if ( !Sound_Init(hinst, (int)v9, 0) )
+ options_menu_set(0xC9u, 0);
+ Sound_Activate();
+ if ( !dword_102556C && !midi_music_init(v21) )
+ options_menu_set(0xCAu, 0);
+ if ( pb_init() )
+ _exit(0);
+ SetCursor(v8);
+ v10 = options_get_int(0, "Change Display", (HKEY)1);
+ v11 = GetMenu(v21);
+ fullscrn_init(v18, (int)lpString1, (int)dword_102822C, v21, (int)v11, (int)v10);
+ --memory_critical_allocation;
+ v5 = wParam;
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ if ( Msg != 2 )
+ {
+ if ( Msg != 3 )
+ {
+ if ( Msg == 7 )
+ {
+ has_focus = 1;
+ no_time_loss = 1;
+ gdrv_get_focus();
+ fullscrn_force_redraw();
+ pb_paint();
+ }
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ goto LABEL_70;
+ }
+ goto LABEL_28;
+ }
+ has_focus = 0;
+ gdrv_get_focus();
+ pb_loose_focus();
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ switch ( Msg )
+ {
+ case 0xFu:
+ _BeginPaint(hWnd, &Paint);
+ fullscrn_paint();
+ EndPaint(hWnd, &Paint);
+ break;
+ case 0x10u:
+ case 0x12u:
+ LABEL_28:
+ winmain_end_pause(wParam);
+ bQuit = 1;
+ PostQuitMessage(0);
+ fullscrn_shutdown();
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x14u:
+ break;
+ default:
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ return 0;
+ }
+ if ( Msg <= 0x11F )
+ {
+ if ( Msg == 287 )
+ {
+ if ( a4 )
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ if ( fullscrn_screen_mode )
+ fullscrn_set_menu_mode(0);
+ return 0;
+ }
+ if ( Msg <= 0x104 )
+ {
+ switch ( Msg )
+ {
+ case 0x104u:
+ no_time_loss = 1;
+ if ( fullscrn_screen_mode )
+ fullscrn_set_menu_mode(1);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x24u:
+ fullscrn_getminmaxinfo((_DWORD *)a4);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x7Eu:
+ if ( fullscrn_displaychange() )
+ {
+ dword_102822C = 0;
+ options_menu_check(0x193u, 0);
+ }
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ if ( Msg != 256 )
+ {
+ if ( Msg == 257 )
+ pb_keyup((HKEY)wParam);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ if ( !(a4 & 0x40000000) )
+ pb_keydown((HKEY)wParam);
+ switch ( wParam )
+ {
+ case 0x1Bu:
+ if ( dword_102822C )
+ options_toggle(0x193u);
+ SendMessageA(hwnd_frame, 0x112u, 0xF020u, 0);
+ break;
+ case 0x70u:
+ help_introduction((int)hinst, (int)v21);
+ break;
+ case 0x71u:
+ winmain_new_game(113);
+ break;
+ case 0x72u:
+ winmain_pause(114);
+ break;
+ case 0x73u:
+ options_toggle(0x193u);
+ break;
+ case 0x77u:
+ if ( !single_step )
+ winmain_pause(wParam);
+ options_keyboard();
+ break;
+ }
+ if ( !cheat_mode )
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ switch ( wParam )
+ {
+ case 0x48u:
+ DispGRhistory = 1;
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x59u:
+ SetWindowTextA(v21, "Pinball");
+ DispFrameRate = DispFrameRate == 0;
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x70u:
+ pb_frame(112, 10);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ if ( wParam != 126 )
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ single_step = single_step == 0;
+ v13 = single_step == 0;
+ goto LABEL_69;
+ }
+ if ( Msg != 273 )
+ {
+ if ( Msg == 274 )
+ {
+ if ( (wParam & 0xFFF0) == 61456 )
+ {
+ if ( fullscrn_screen_mode )
+ return 0;
+ }
+ else
+ {
+ if ( (wParam & 0xFFF0) == 61472 )
+ {
+ if ( !single_step )
+ winmain_pause(wParam);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ if ( (wParam & 0xFFF0) != 61728 )
+ {
+ if ( (wParam & 0xFFF0) == 61760 )
+ fullscrn_activate(0);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ }
+ winmain_end_pause(wParam);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ v13 = Msg == 278;
+ LABEL_69:
+ if ( v13 )
+ {
+ LABEL_70:
+ no_time_loss = 1;
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ no_time_loss = 1;
+ if ( wParam > 0x12D )
+ {
+ switch ( wParam )
+ {
+ case 0x191u:
+ winmain_end_pause(wParam);
+ pb_launch_ball();
+ break;
+ case 0x192u:
+ winmain_pause(wParam);
+ break;
+ case 0x193u:
+ goto LABEL_130;
+ case 0x194u:
+ winmain_end_pause(wParam);
+ pb_toggle_demo(wParam);
+ break;
+ case 0x195u:
+ if ( !single_step )
+ winmain_pause(wParam);
+ lpString1 = (LPSTR)memoryallocate(0x1F4u);
+ if ( lpString1 )
+ {
+ v14 = (char *)memoryallocate(0x1F4u);
+ if ( v14 )
+ {
+ options_get_string(0, "Shell Exe", lpString1, WindowName, 500);
+ _sprintf(
+ v14,
+ "%s %s%lX %s%lX",
+ lpString1,
+ "select=",
+ hwnd_frame,
+ "confirm=",
+ (_DWORD)hwnd_frame
+ * (_DWORD)hwnd_frame
+ * (_DWORD)hwnd_frame
+ * (_DWORD)hwnd_frame
+ * (_DWORD)hwnd_frame
+ * (_DWORD)hwnd_frame
+ * (_DWORD)hwnd_frame);
+ if ( (signed int)WinExec(v14, 5u) < 32 )
+ {
+ v15 = get_rc_string(170, 0);
+ v16 = get_rc_string(171, 0);
+ MessageBoxA(hwnd_frame, v16, v15, 0x2010u);
+ }
+ memoryfree((int)lpString1);
+ memoryfree((int)v14);
+ }
+ else
+ {
+ memoryfree((int)lpString1);
+ }
+ v5 = wParam;
+ }
+ break;
+ case 0x196u:
+ goto LABEL_110;
+ case 0x198u:
+ case 0x199u:
+ case 0x19Au:
+ case 0x19Bu:
+ options_toggle(wParam);
+ winmain_new_game(wParam);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ if ( wParam == 301 )
+ {
+ if ( !single_step )
+ winmain_pause(301);
+ help_introduction((int)hinst, (int)hWnd);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ if ( wParam > 0x69 )
+ {
+ if ( wParam == 106 )
+ {
+ pb_end_game();
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ if ( wParam > 0xC8 )
+ {
+ if ( wParam <= 0xCA )
+ {
+ LABEL_130:
+ if ( !single_step )
+ winmain_pause(wParam);
+ options_toggle(wParam);
+ }
+ else if ( wParam == 204 )
+ {
+ LABEL_110:
+ if ( !single_step )
+ winmain_pause(wParam);
+ options_keyboard();
+ }
+ }
+ }
+ else
+ {
+ switch ( wParam )
+ {
+ case 0x69u:
+ PostMessageA(v21, 0x12u, 0, 0);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x65u:
+ winmain_new_game(101);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x66u:
+ if ( !single_step )
+ winmain_pause(102);
+ a_dialog(hinst, hWnd, (int)"DIALOG_1");
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x67u:
+ if ( !single_step )
+ winmain_pause(wParam);
+ pb_high_scores();
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ }
+ }
+ LABEL_144:
+ if ( v5 == 1 )
+ restart_midi_seq(lParam);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ switch ( Msg )
+ {
+ case 0x201u:
+ if ( dword_1025568 )
+ {
+ if ( cheat_mode )
+ {
+ mouse_down = 1;
+ mouse_hsave = SetCursor(0);
+ lParam = fullscrn_convert_mouse_pos(a4);
+ last_mouse_x = (unsigned __int16)lParam;
+ last_mouse_y = (unsigned int)lParam >> 16;
+ SetCapture(v21);
+ }
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ break;
+ case 0x202u:
+ if ( mouse_down )
+ {
+ mouse_down = 0;
+ SetCursor(mouse_hsave);
+ ReleaseCapture();
+ }
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x204u:
+ case 0x207u:
+ if ( dword_1025568 )
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ break;
+ case 0x218u:
+ if ( wParam == 4 && dword_102822C )
+ {
+ dword_102822C = 0;
+ options_menu_check(0x193u, 0);
+ fullscrn_set_screen_mode((int)dword_102822C);
+ }
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x311u:
+ InvalidateRect(v21, 0, 0);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ case 0x3B9u:
+ goto LABEL_144;
+ default:
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ pb_mode_countdown(-1);
+ return DefWindowProcA(v21, Msg, v5, lParam);
+ }
+ if ( IsIconic(hWnd) )
+ ShowWindow(hWnd, 9);
+ SetForegroundWindow(hWnd);
+ return 0;
+}
+// 1024EE4: using guessed type int fullscrn_screen_mode;
+// 1024F04: using guessed type int memory_critical_allocation;
+// 1024FD8: using guessed type int single_step;
+// 1024FDC: using guessed type int bQuit;
+// 1024FE0: using guessed type int DispFrameRate;
+// 1024FE4: using guessed type int DispGRhistory;
+// 1024FE8: using guessed type int mouse_down;
+// 1024FEC: using guessed type int has_focus;
+// 1024FF0: using guessed type int activated;
+// 1024FF4: using guessed type int no_time_loss;
+// 1024FF8: using guessed type int cheat_mode;
+// 1025568: using guessed type int dword_1025568;
+// 102556C: using guessed type int dword_102556C;
+
+//----- (010082A9) --------------------------------------------------------
+signed int sub_10082A9()
+{
+ MSG Msg; // [esp+8h] [ebp-1Ch]
+
+ if ( has_focus && !single_step )
+ {
+ while ( PeekMessageA(&Msg, 0, 0, 0, 1u) )
+ {
+ TranslateMessage(&Msg);
+ DispatchMessageA(&Msg);
+ if ( Msg.message == 18 )
+ goto LABEL_9;
+ }
+ return 1;
+ }
+ GetMessageA(&Msg, hwnd_frame, 0, 0);
+ TranslateMessage(&Msg);
+ DispatchMessageA(&Msg);
+ if ( Msg.message != 18 )
+ return 1;
+ LABEL_9:
+ return_value = Msg.wParam;
+ return 0;
+}
+// 1024FD8: using guessed type int single_step;
+// 1024FEC: using guessed type int has_focus;
+// 1028200: using guessed type int return_value;
+
+
+
+//----- (0101CEB6) --------------------------------------------------------
+int __stdcall sub_101CEB6(LPBYTE lpData)
+{
+signed int v1; // esi
+DWORD cbData; // [esp+4h] [ebp-8h]
+HKEY phkResult; // [esp+8h] [ebp-4h]
+
+v1 = 0;
+if ( RegOpenKeyExA(
+HKEY_CLASSES_ROOT,
+"CLSID\\{ADB880A6-D8FF-11CF-9377-00AA003B7A11}\\InprocServer32",
+0,
+0x20019u,
+&phkResult) )
+{
+return 0;
+}
+cbData = 260;
+if ( !RegQueryValueExA(phkResult, WindowName, 0, 0, lpData, &cbData) )
+v1 = 1;
+RegCloseKey(phkResult);
+return v1;
+}
+
+//----- (01020F95) --------------------------------------------------------
+int WinMainCRTStartup()
+{
+HMODULE v0; // eax
+int v1; // ecx
+int v2; // eax
+int v3; // eax
+bool v4; // zf
+CHAR *v5; // esi
+signed int v6; // eax
+int v7; // ST20_4
+HMODULE v8; // eax
+int v9; // eax
+int v10; // esi
+struct _STARTUPINFOA StartupInfo; // [esp+Ch] [ebp-80h]
+int v13; // [esp+50h] [ebp-3Ch]
+int v14; // [esp+54h] [ebp-38h]
+char v15; // [esp+58h] [ebp-34h]
+char v16; // [esp+5Ch] [ebp-30h]
+char v17; // [esp+60h] [ebp-2Ch]
+int v18; // [esp+68h] [ebp-24h]
+CHAR *v19; // [esp+6Ch] [ebp-20h]
+int v20; // [esp+70h] [ebp-1Ch]
+CPPEH_RECORD ms_exc; // [esp+74h] [ebp-18h]
+
+v0 = GetModuleHandleA(0);
+if ( *(_WORD *)v0 != 23117 )
+goto LABEL_5;
+v1 = (int)v0 + *((_DWORD *)v0 + 15);
+if ( *(_DWORD *)v1 != 17744 )
+goto LABEL_5;
+v2 = *(unsigned __int16 *)(v1 + 24);
+if ( v2 == 267 )
+{
+if ( *(_DWORD *)(v1 + 116) > 0xEu )
+{
+v3 = 0;
+v4 = *(_DWORD *)(v1 + 232) == 0;
+goto LABEL_10;
+}
+LABEL_5:
+v20 = 0;
+goto LABEL_11;
+}
+if ( v2 != 523 || *(_DWORD *)(v1 + 132) <= 0xEu )
+goto LABEL_5;
+v3 = 0;
+v4 = *(_DWORD *)(v1 + 248) == 0;
+LABEL_10:
+LOBYTE(v3) = !v4;
+v20 = v3;
+LABEL_11:
+ms_exc.registration.TryLevel = 0;
+___set_app_type(2);
+__onexitend = -1;
+__onexitbegin = -1;
+*(_DWORD *)___p__fmode() = _fmode;
+*(_DWORD *)___p__commode() = _commode;
+_adjust_fdiv = __adjust_fdiv;
+check_expiration_date();
+if ( !__defaultmatherr )
+___setusermatherr(check_expiration_date);
+_setdefaultprecision();
+_initterm(&__xi_a, &__xi_z);
+v18 = _newmode;
+v14 = ___getmainargs(&v15, &v16, &v17, _dowildcard, &v18);
+_initterm(&__xc_a, &__xc_z);
+v5 = (CHAR *)__acmdln;
+v19 = (CHAR *)__acmdln;
+if ( *__acmdln != 34 )
+{
+while ( (unsigned __int8)*v5 > 0x20u )
+v19 = ++v5;
+goto LABEL_18;
+}
+do
+v19 = ++v5;
+while ( *v5 && *v5 != 34 );
+if ( *v5 != 34 )
+goto LABEL_18;
+do
+{
+v19 = ++v5;
+LABEL_18:
+;
+}
+while ( *v5 && (unsigned __int8)*v5 <= 0x20u );
+StartupInfo.dwFlags = 0;
+GetStartupInfoA(&StartupInfo);
+if ( StartupInfo.dwFlags & 1 )
+v6 = StartupInfo.wShowWindow;
+else
+v6 = 10;
+v7 = v6;
+v8 = GetModuleHandleA(0);
+v9 = WinMain(v8, 0, v5, v7);
+v10 = v9;
+v13 = v9;
+if ( !v20 )
+_exit(v9);
+__cexit();
+return v10;
+}
+// 10012BC: using guessed type int __cdecl ___getmainargs(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD);
+// 10012C4: using guessed type int __cdecl ___setusermatherr(_DWORD);
+// 10012D0: using guessed type int ___p__fmode(void);
+// 10012D4: using guessed type int __cdecl ___set_app_type(_DWORD);
+// 100134C: using guessed type int ___p__commode(void);
+// 10211AE: using guessed type int __cdecl _initterm(_DWORD, _DWORD);
+// 1024890: using guessed type int __defaultmatherr;
+// 1027BFC: using guessed type int _dowildcard;
+// 1027C00: using guessed type int _newmode;
+// 1027C04: using guessed type int _commode;
+// 1028298: using guessed type int __onexitend;
+// 102829C: using guessed type int __onexitbegin;
+// 10282A0: using guessed type int _adjust_fdiv;