TBall, nudge v1, ready.

render occlude list.
This commit is contained in:
oz 2020-12-27 18:19:36 +03:00
parent 99fba56a34
commit a143b820af
30 changed files with 494 additions and 328 deletions

Binary file not shown.

View File

@ -1,150 +0,0 @@
#include "pch.h"
#include "DatParser.h"
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
FILE* ff; unsigned char* fdat; int fsiz;
char tbuf[256];
int ngrp;
void err(int n)
{
printf("Error %i\n", n);
exit(n);
}
void cerr(int c, int n)
{
if (c) err(n);
}
void safeprint(char* s, int n)
{
int i;
for (i = 0; i < n; i++)
{
if (!s[i]) break;
fputc(s[i], stdout);
}
}
void printhexbytestr(uchar* s, int n)
{
int i;
for (i = 0; i < n; i++)
printf("%02X", s[i]);
}
void printshortstr(short* s, int n)
{
int i;
for (i = 0; i < n; i++)
printf(" %i", s[i]);
}
void printfloatstr(float* s, int n)
{
int i;
for (i = 0; i < n; i++)
printf(" %f", s[i]);
}
int main2(int argc, const char* argv[])
{
int g, en, es, n, et; unsigned char* p;
printf("pbwdlist - 3D Pinball for Windows DAT file listing program\nby AdrienTD\n\n");
if (argc < 2) { printf("Usage: pbwdlist FILE.DAT\n"); return 1; }
FILE *ff;
fopen_s(&ff,argv[1], "rb");
//ff = fopen(argv[1], "rb");
cerr(!ff, -1);
printf("File: %s\n\n", argv[1]);
fseek(ff, 0, SEEK_END);
fsiz = ftell(ff);
fdat = (unsigned char*)malloc(fsiz);
cerr(!fdat, -2);
fseek(ff, 0, SEEK_SET);
fread(fdat, fsiz, 1, ff);
fclose(ff);
printf("-- Header --");
printf("\nFile signature:\t"); safeprint((char*)fdat, 21);
printf("\nApp name:\t"); safeprint((char*)fdat + 0x15, 50);
printf("\nDescription:\t"); safeprint((char*)fdat + 0x47, 100);
printf("\nFile size:\t%i", *((int*)(fdat + 0xAB)));
printf("\nNum. groups:\t%i", ngrp = *((short*)(fdat + 0xAF)));
printf("\nSize of body:\t%i", *((int*)(fdat + 0xB1)));
printf("\nUnknown value:\t%i", *((short*)(fdat + 0xB5)));
printf("\n\n-- Body --");
p = fdat + 0xB7;
for (g = 0; g < ngrp; g++)
{
n = *(p++);
printf("\nGroup %i:\tnum entries: %i, location: 0x%X\n", g, n, p - fdat - 1);
for (en = 0; en < n; en++)
{
et = *(p++);
if (et)
{
es = *((int*)p); p += 4;
printf("\t\t- type: %i, size: %i\n", et, es);
switch (et)
{
case 1: // Bitmap
printf("\t\t Bitmap, width: %i, height: %i\n", *(ushort*)(p + 1), *(ushort*)(p + 3));
break;
case 3: // Group name
printf("\t\t Group name: ");
safeprint((char*)p, es);
printf("\n"); break;
case 5: // Palette
printf("\t\t Palette\n"); break;
case 9: // String
printf("\t\t String: ");
safeprint((char*)p, es);
printf("\n"); break;
case 10:
//printf("\t\t Content: ");
//printhexbytestr(p, es);
printf("\t\t Shorts:");
printshortstr((short*)p, es / 2);
printf("\n"); break;
case 11:
printf("\t\t Floats:");
printfloatstr((float*)p, es / 4);
printf("\n"); break;
case 12:
printf("\t\t Special bitmap\n"); break;
default:
printf("\t\t Unknown!\n"); break;
}
p += es;
}
else
{
es = *((short*)p); p += 2;
printf("\t\t- type: %i, value: %i\n", et, es);
}
}
}
free(fdat);
return 0;
}
void DatParser::Parse(const char* file)
{
main2(2, new const char* [2] {0, file});
}

View File

@ -1,7 +0,0 @@
#pragma once
class DatParser
{
public:
static void Parse(const char * file);
};

View File

@ -6,7 +6,6 @@
#include <iostream>
#include "objlist_class.h"
#include "partman.h"
#include "DatParser.h"
#include "gdrv.h"
#include "loader.h"
#include "pb.h"

View File

@ -157,7 +157,6 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="control.h" />
<ClInclude Include="DatParser.h" />
<ClInclude Include="fullscrn.h" />
<ClInclude Include="gdrv.h" />
<ClInclude Include="high_score.h" />
@ -221,7 +220,6 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="control.cpp" />
<ClCompile Include="DatParser.cpp" />
<ClCompile Include="fullscrn.cpp" />
<ClCompile Include="gdrv.cpp" />
<ClCompile Include="high_score.cpp" />

View File

@ -42,9 +42,6 @@
<ClInclude Include="partman.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DatParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="loader.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -233,9 +230,6 @@
<ClCompile Include="partman.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DatParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="loader.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@ -1,2 +1,128 @@
#include "pch.h"
#include "TBall.h"
#include "loader.h"
#include "maths.h"
#include "objlist_class.h"
#include "proj.h"
#include "render.h"
#include "TPinballTable.h"
#include "TZmapList.h"
TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
{
visualStruct visual{};
Unknown9F = 0.0;
Unknown7F = 0.0;
UnknownBaseFlag2 = 1;
Unknown16 = 0;
EdgeCollisionCount = 0;
Unknown8F = 0.0;
Unknown17 = 1;
CollisionFlag = 0;
Speed = 0.0;
Acceleration.Y = 0.0;
Acceleration.X = 0.0;
InvAcceleration.Y = 1000000000.0;
InvAcceleration.X = 1000000000.0;
Position.X = 0.0;
Position.Y = 0.0;
ListBitmap = new TZmapList(0, 4);
auto groupIndex = loader::query_handle("ball");
Offset = *loader::query_float_attribute(groupIndex, 0, 500);
auto visualCount = loader::query_visual_states(groupIndex);
auto index = 0;
if (visualCount > 0)
{
auto visualZPtr = VisualZArray;
do
{
loader::query_visual(groupIndex, index, &visual);
if (ListBitmap)
ListBitmap->Add(visual.Bitmap);
auto visVec = reinterpret_cast<vector_type*>(loader::query_float_attribute(groupIndex, index, 501));
auto zDepth = proj::z_distance(visVec);
++index;
*visualZPtr = zDepth;
++visualZPtr;
}
while (index < visualCount);
}
RenderSprite = render::create_sprite(VisualType::Ball, nullptr, nullptr, 0, 0, nullptr);
PinballTable->CollisionCompOffset = Offset;
Position.Z = Offset;
}
void TBall::Repaint()
{
int pos2D[2];
if (CollisionFlag)
{
Position.Z =
CollisionOffset.X * Position.X +
CollisionOffset.Y * Position.Y +
Offset + CollisionOffset.Z;
}
proj::xform_to_2d(&Position, pos2D);
auto zDepth = proj::z_distance(&Position);
auto zArrPtr = VisualZArray;
int index;
for (index = 0; index < ListBitmap->Count() - 1; ++index, zArrPtr++)
{
if (*zArrPtr <= zDepth) break;
}
auto bmp = static_cast<gdrv_bitmap8*>(ListBitmap->Get(index));
render::ball_set(
RenderSprite,
bmp,
zDepth,
bmp->Width / 2 - pos2D[0],
bmp->Height / 2 - pos2D[1]);
}
void TBall::not_again(TEdgeSegment* edge)
{
if (EdgeCollisionCount < 5)
{
Collisions[EdgeCollisionCount] = edge;
++EdgeCollisionCount;
}
}
bool TBall::already_hit(TEdgeSegment* edge)
{
for (int i = 0; i < EdgeCollisionCount; i++)
{
if (Collisions[i] == edge)
return true;
}
return false;
}
int TBall::Message(int code, float value)
{
if (code == 1024)
{
render::ball_set(RenderSprite, nullptr, 0.0, 0, 0);
Position.X = 0.0;
Unknown16 = 0;
Position.Y = 0.0;
UnknownBaseFlag2 = 0;
CollisionFlag = 0;
Unknown17 = 1;
Acceleration.Y = 0.0;
Position.Z = Offset;
Acceleration.X = 0.0;
Speed = 0.0;
Unknown7F = 0.0;
}
return 0;
}

View File

@ -1,11 +1,35 @@
#pragma once
#include "maths.h"
#include "TPinballComponent.h"
class TBall :
public TPinballComponent
class TEdgeSegment;
class TBall : public TPinballComponent
{
public :
TBall(TPinballTable* table): TPinballComponent(table, -1, false)
{
}
TBall(TPinballTable* table);
void Repaint();
void not_again(TEdgeSegment* edge);
bool already_hit(TEdgeSegment* edge);
int Message(int code, float value) override;
vector_type Position;
vector_type Acceleration;
float Speed;
float Unknown7F;
float Unknown8F;
float Unknown9F;
vector_type InvAcceleration;
int Unknown13;
int Unknown14;
int Unknown15;
int Unknown16;
int Unknown17;
TEdgeSegment* Collisions[5];
int EdgeCollisionCount;
vector_type CollisionOffset;
int CollisionFlag;
float Offset;
int Unknown29;
float VisualZArray[50];
};

View File

@ -8,7 +8,7 @@
TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool loadVisuals)
{
visualStruct visual{}; // [esp+Ch] [ebp-6Ch]
visualStruct visual{};
MessageField = 0;
UnknownBaseFlag1 = 0;
@ -18,7 +18,7 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
ListBitmap = nullptr;
ListZMap = nullptr;
if (table)
table->ListP1->Add(this);
table->ComponentList->Add(this);
if (groupIndex >= 0)
GroupName = loader::query_name(groupIndex);
if (loadVisuals && groupIndex >= 0)
@ -80,7 +80,7 @@ TPinballComponent::~TPinballComponent()
{
TPinballTable* table = PinballTable;
if (table)
table->ListP1->Delete(this);
table->ComponentList->Delete(this);
delete ListBitmap;
delete ListZMap;

View File

@ -7,6 +7,7 @@ class TZmapList;
enum class message_code
{
Reset = 1024,
};
class TPinballComponent

View File

@ -47,8 +47,8 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
{
int shortArrLength;
ListP1 = new objlist_class(32, 16);
ListP2 = new objlist_class(3, 1);
ComponentList = new objlist_class(32, 16);
BallList = new objlist_class(3, 1);
CurScoreStruct = nullptr;
ScoreBallcount = nullptr;
ScorePlayerNumber1 = nullptr;
@ -62,7 +62,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
MultiballFlag = 0;
auto ballObj = new TBall(this);
ListP2->Add(ballObj);
BallList->Add(ballObj);
if (ballObj)
ballObj->UnknownBaseFlag2 = 0;
new TTableLayer(this);
@ -188,7 +188,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false)
}
}
//build_occlude_list();
render::build_occlude_list();
pinball::InfoTextBox = dynamic_cast<TTextBox*>(find_component("info_text_box"));
pinball::MissTextBox = dynamic_cast<TTextBox*>(find_component("mission_text_box"));
control::make_links(this);
@ -212,22 +212,22 @@ TPinballTable::~TPinballTable()
ScoreBallcount = nullptr;
}
delete LightGroup;
while (ListP1->Count() > 0)
while (ComponentList->Count() > 0)
{
delete static_cast<TPinballComponent*>(ListP1->Get(0));
delete static_cast<TPinballComponent*>(ComponentList->Get(0));
}
delete ListP2;
delete ListP1;
delete BallList;
delete ComponentList;
}
TPinballComponent* TPinballTable::find_component(LPCSTR componentName)
{
int objCount = ListP1->Count();
int objCount = ComponentList->Count();
if (objCount > 0)
{
for (int index = 0; index < objCount; ++index)
{
TPinballComponent* obj = static_cast<TPinballComponent*>(ListP1->Get(index));
TPinballComponent* obj = static_cast<TPinballComponent*>(ComponentList->Get(index));
const CHAR* groupName = obj->GroupName;
if (groupName && !lstrcmpA(groupName, componentName))
{
@ -242,12 +242,12 @@ TPinballComponent* TPinballTable::find_component(LPCSTR componentName)
TPinballComponent* TPinballTable::find_component(int groupIndex)
{
char Buffer[33];
int objCount = ListP1->Count();
int objCount = ComponentList->Count();
if (objCount > 0)
{
for (int index = 0; index < objCount; ++index)
{
TPinballComponent* obj = static_cast<TPinballComponent*>(ListP1->Get(index));
TPinballComponent* obj = static_cast<TPinballComponent*>(ComponentList->Get(index));
if (obj->GroupIndex == groupIndex)
return obj;
}
@ -305,11 +305,11 @@ void TPinballTable::tilt(float time)
pinball::MissTextBox->Clear();
pinball::InfoTextBox->Display(pinball::get_rc_string(35, 0), -1.0);
loader::play_sound(this2->SoundIndex3);
this2->TiltTimeoutTimer = timer::set(30.0, this2, TPinballTable::tilt_timeout);
this2->TiltTimeoutTimer = timer::set(30.0, this2, tilt_timeout);
for (int i = 0; i < ListP1->Count(); i++)
for (int i = 0; i < ComponentList->Count(); i++)
{
static_cast<TPinballComponent*>(ListP1->Get(i))->Message(1011, time);
static_cast<TPinballComponent*>(ComponentList->Get(i))->Message(1011, time);
}
this2->LightGroup->Message(8, 0);
this2->TiltLockFlag = 1;
@ -320,9 +320,9 @@ void TPinballTable::tilt(float time)
void TPinballTable::port_draw()
{
for (int index = ListP1->Count() - 1; index >= 0; index--)
for (int index = ComponentList->Count() - 1; index >= 0; index--)
{
static_cast<TPinballComponent*>(ListP1->Get(index))->port_draw();
static_cast<TPinballComponent*>(ComponentList->Get(index))->port_draw();
}
}
@ -362,9 +362,9 @@ int TPinballTable::Message(int code, float value)
case 1008:
case 1009:
case 1010:
for (int i = 0; i < ListP1->Count(); i++)
for (int i = 0; i < ComponentList->Count(); i++)
{
static_cast<TPinballComponent*>(ListP1->Get(i))->Message(code, value);
static_cast<TPinballComponent*>(ComponentList->Get(i))->Message(code, value);
}
break;
case 1012:
@ -406,10 +406,10 @@ int TPinballTable::Message(int code, float value)
{
UnknownP6 = 0;
Message(1024, 0.0);
/*v8 = (char*)this2->ListP2.ListPtr->Array[0];
*(float*)(v8 + 46) = 0.0;
*(float*)(v8 + 42) = 0.0;
*(_DWORD*)(v8 + 50) = -1085485875;*/
auto ball = static_cast<TBall*>(BallList->Get(0));
ball->Position.Y = 0.0;
ball->Position.X = 0.0;
ball->Position.Z = -0.8f;
auto playerCount = static_cast<int>(floor(value));
PlayerCount = playerCount;
@ -513,9 +513,9 @@ int TPinballTable::Message(int code, float value)
score::set(ScorePlayerNumber1, nextPlayer + 1);
score::update(ScorePlayerNumber1);
for (int i = 0; i < ListP1->Count(); i++)
for (int i = 0; i < ComponentList->Count(); i++)
{
static_cast<TPinballComponent*>(ListP1->Get(i))->Message(1020, static_cast<float>(nextPlayer));
static_cast<TPinballComponent*>(ComponentList->Get(i))->Message(1020, static_cast<float>(nextPlayer));
}
char* textboxText = nullptr;
@ -564,9 +564,9 @@ int TPinballTable::Message(int code, float value)
EndGameTimeoutTimer = timer::set(3.0, this, EndGame_timeout);
break;
case 1024:
for (int i = 0; i < ListP1->Count(); i++)
for (int i = 0; i < ComponentList->Count(); i++)
{
static_cast<TPinballComponent*>(ListP1->Get(i))->Message(1024, 0);
static_cast<TPinballComponent*>(ComponentList->Get(i))->Message(1024, 0);
}
if (ReplayTimer)
timer::kill(ReplayTimer);
@ -608,9 +608,9 @@ void TPinballTable::EndGame_timeout(int timerId, void* caller)
table->EndGameTimeoutTimer = 0;
pb::end_game();
for (int i = 0; i < table->ListP1->Count(); i++)
for (int i = 0; i < table->ComponentList->Count(); i++)
{
static_cast<TPinballComponent*>(table->ListP1->Get(i))->Message(1022, 0);
static_cast<TPinballComponent*>(table->ComponentList->Get(i))->Message(1022, 0);
}
if (table->Demo)
table->Demo->Message(1022, 0.0);
@ -635,12 +635,6 @@ void TPinballTable::replay_timer_callback(int timerId, void* caller)
void TPinballTable::tilt_timeout(int timerId, void* caller)
{
auto table = static_cast<TPinballTable*>(caller);
objlist_struct1* v2; // eax
void** v3; // edi
int v4; // ebx
char v5; // [esp+14h] [ebp-Ch]
table->TiltTimeoutTimer = 0;
if (table->TiltLockFlag)
{

View File

@ -65,8 +65,8 @@ public:
int YOffset;
int Width;
int Height;
objlist_class* ListP1;
objlist_class* ListP2;
objlist_class* ComponentList;
objlist_class* BallList;
TLightGroup* LightGroup;
float TableAngleMult;
float TableAngle1;

View File

@ -533,7 +533,7 @@ TPinballComponent* control::make_component_link(component_tag* tag)
if (tag->Component)
return tag->Component;
auto compList = TableG->ListP1;
auto compList = TableG->ComponentList;
for (int index = 0; index < compList->Count(); index++)
{
auto comp = static_cast<TPinballComponent*>(compList->Get(index));

View File

@ -40,9 +40,10 @@ void fullscrn::init(int width, int height, int isFullscreen, HWND winHandle, HME
hWnd,
(WindowRect1.right - WindowRect1.left - widht2) / 2 - 2,
WindowRect2.top,
widht2 + 4,
WindowRect2.bottom - WindowRect2.top,
widht2 + 4 + 10,
WindowRect2.bottom - WindowRect2.top + 10,
0);
// Todo: WH + 10 hack: original request 640x480 window but somehow receives 650x490, even thought spyxx says it is 640x480
fullscrn_flag1 = 0;
}
@ -94,8 +95,8 @@ int fullscrn::setWindowFlagsDisDlg()
int fullscrn::enableFullscreen()
{
tagRECT Rect{}; // [esp+Ch] [ebp-B0h]
DEVMODEA DevMode{}; // [esp+1Ch] [ebp-A0h]
tagRECT Rect{};
DEVMODEA DevMode{};
if (ChangeDisplay && !display_changed)
{
@ -153,7 +154,7 @@ int fullscrn::disableFullscreen()
bool fullscrn::set_menu_mode(int menuEnabled)
{
BOOL result; // eax
BOOL result;
MenuEnabled = menuEnabled;
GetWindowCenter();
@ -174,8 +175,8 @@ bool fullscrn::set_menu_mode(int menuEnabled)
void fullscrn::GetWindowCenter()
{
int yPos; // eax
tagRECT Rect{}; // [esp+4h] [ebp-10h]
int yPos;
tagRECT Rect{};
if (screen_mode)
{
@ -201,7 +202,7 @@ void fullscrn::force_redraw()
void fullscrn::center_in(HWND parent, HWND child)
{
LONG right; // ebx
LONG right;
tagRECT childRect{}, parentRect{}, desktopRect{};
GetWindowRect(parent, &parentRect);
@ -296,8 +297,8 @@ void fullscrn::activate(int flag)
void fullscrn::fillRect(int right, int bottom)
{
// Weird reg usage, should be zero
int v2 = 0; // ebx
int v3 = 0; // edi
int v2 = 0;
int v3 = 0;
RECT rc;
HGDIOBJ brush = CreateSolidBrush(0);

View File

@ -91,7 +91,7 @@ BITMAPINFO* gdrv::DibCreate(__int16 bpp, int width, int height)
void gdrv::DibSetUsage(BITMAPINFO* dib, HPALETTE hpal, int someFlag)
{
tagPALETTEENTRY pPalEntries[256]; // [esp+4h] [ebp-400h]
tagPALETTEENTRY pPalEntries[256];
if (!hpal)
hpal = static_cast<HPALETTE>(GetStockObject(DEFAULT_PALETTE));
@ -140,7 +140,7 @@ void gdrv::DibSetUsage(BITMAPINFO* dib, HPALETTE hpal, int someFlag)
int gdrv::create_bitmap_dib(gdrv_bitmap8* bmp, int width, int height)
{
char* bmpBufPtr; // ecx
char* bmpBufPtr;
auto dib = DibCreate(8, width, height);
DibSetUsage(dib, palette_handle, 1);
@ -210,7 +210,6 @@ int gdrv::display_palette(PALETTEENTRY* plt)
{
if (plt)
{
// Todo: verify RGB order
pltDst->peRed = pltSrc->peBlue;
pltDst->peGreen = pltSrc->peGreen;
pltDst->peBlue = pltSrc->peRed;

View File

@ -415,28 +415,28 @@ int loader::kicker(int groupIndex, visualKickerStruct* kicker)
int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* visual)
{
visualStruct* visual2; // edi
int groupIndexSum; // eax
int groupIndexSum2; // ebx
zmap_header_type* bitmap16; // eax
__int16* shortArr; // esi
unsigned int shortArrSize; // eax
int index; // ebx
int shortVal; // ecx
__int16* nextShortVal; // esi
int nextIndex; // ebx
int shortValSub100; // ecx
int shortValSub300; // ecx
int shortValSub304; // ecx
int shortValSub602; // ecx
int shortValSub1100; // ecx
int shortValSub1101; // ecx
float* floatArr; // eax
float* nextFloatVal; // esi
__int64 floatVal; // rax
float* floatArrPtr; // esi
int groupIndexSum3; // [esp+1Ch] [ebp+8h]
int shortArrLength; // [esp+24h] [ebp+10h]
visualStruct* visual2;
int groupIndexSum;
int groupIndexSum2;
zmap_header_type* bitmap16;
__int16* shortArr;
unsigned int shortArrSize;
int index;
int shortVal;
__int16* nextShortVal;
int nextIndex;
int shortValSub100;
int shortValSub300;
int shortValSub304;
int shortValSub602;
int shortValSub1100;
int shortValSub1101;
float* floatArr;
float* nextFloatVal;
__int64 floatVal;
float* floatArrPtr;
int groupIndexSum3;
int shortArrLength;
visual2 = visual;
default_vsi(visual);

View File

@ -81,10 +81,10 @@ int maths::rectangle_clip(rectangle_type* rect1, rectangle_type* rect2, rectangl
int maths::overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect)
{
int v3; // esi
int v4; // edi
int v6; // esi
int v7; // edi
int v3;
int v4;
int v6;
int v7;
if (rect1->XPosition >= rect2->XPosition)
{
@ -166,9 +166,9 @@ float maths::normalize_2d(vector_type* vec)
void maths::line_init(line_type* line, float x0, float y0, float x1, float y1)
{
float v9; // st7
bool lineDirection; // pf
float v11; // eax
float v9;
bool lineDirection;
float v11;
line->Direction.X = x1 - x0;
line->Direction.Y = y1 - y0;
@ -204,12 +204,12 @@ void maths::line_init(line_type* line, float x0, float y0, float x1, float y1)
float maths::ray_intersect_line(ray_type* ray, line_type* line)
{
// Similar to https://rootllama.wordpress.com/2014/06/20/ray-line-segment-intersection-test-in-2d/
float perpDot; // st7
float result; // st7
float v4; // st6
bool v5; // c0
bool v6; // c3
float v7; // st6
float perpDot;
float result;
float v4;
bool v5;
bool v6;
float v7;
perpDot = line->PerpendicularL.Y * ray->Direction.Y + ray->Direction.X * line->PerpendicularL.X;
if (perpDot < 0.0)
@ -263,3 +263,9 @@ float maths::magnitude(vector_type* vec)
result = sqrt(magSq);
return result;
}
void maths::vector_add(vector_type* vec1Dst, vector_type* vec2)
{
vec1Dst->X += vec2->X;
vec1Dst->Y += vec2->Y;
}

View File

@ -55,4 +55,5 @@ public:
static float ray_intersect_line(ray_type* ray, line_type* line);
static void cross(vector_type* vec1, vector_type* vec2, vector_type* dstVec);
static float magnitude(vector_type* vec);
static void vector_add(vector_type* vec1Dst, vector_type* vec2);
};

View File

@ -1,26 +1,99 @@
#include "pch.h"
#include "nudge.h"
void nudge::un_nudge_right(int x, int y)
#include "objlist_class.h"
#include "pb.h"
#include "render.h"
#include "TBall.h"
#include "timer.h"
int nudge::nudged_left;
int nudge::nudged_right;
int nudge::nudged_up;
int nudge::timer;
float nudge::nudge_count;
void nudge::un_nudge_right(int timerId, void* caller)
{
if (nudged_right)
_nudge(-2.0, -1.0);
nudged_right = 0;
}
void nudge::un_nudge_left(int x, int y)
void nudge::un_nudge_left(int timerId, void* caller)
{
if (nudged_left)
_nudge(2.0, -1.0);
nudged_left = 0;
}
void nudge::un_nudge_up(int x, int y)
void nudge::un_nudge_up(int timerId, void* caller)
{
if (nudged_up)
_nudge(0.0, -1.0);
nudged_up = 0;
}
void nudge::nudge_right()
{
_nudge(2.0, 1.0);
if (timer)
timer::kill(timer);
timer = timer::set(0.4f, nullptr, un_nudge_right);
nudged_right = 1;
}
void nudge::nudge_left()
{
_nudge(-2.0, 1.0);
if (timer)
timer::kill(timer);
timer = timer::set(0.4f, nullptr, un_nudge_left);
nudged_left = 1;
}
void nudge::nudge_up()
{
_nudge(0.0, 1.0);
if (timer)
timer::kill(timer);
timer = timer::set(0.4f, nullptr, un_nudge_up);
nudged_up = 1;
}
void nudge::_nudge(float xDiff, float yDiff)
{
vector_type accelMod;
float invAccelX, invAccelY;
auto table = pb::MainTable;
auto ballList = pb::MainTable->BallList;
accelMod.X = xDiff * 0.5f;
accelMod.Y = yDiff * 0.5f;
for (auto index = 0; index < ballList->Count(); index++)
{
auto ball = static_cast<TBall*>(ballList->Get(index));
if (ball->UnknownBaseFlag2 && !ball->Unknown16)
{
ball->Acceleration.X = ball->Acceleration.X * ball->Speed;
ball->Acceleration.Y = ball->Acceleration.Y * ball->Speed;
maths::vector_add(&ball->Acceleration, &accelMod);
ball->Speed = maths::normalize_2d(&ball->Acceleration);
if (0.0 == ball->Acceleration.X)
invAccelX = 1000000000.0;
else
invAccelX = 1.0f / ball->Acceleration.X;
ball->InvAcceleration.X = invAccelX;
if (0.0 == ball->Acceleration.Y)
invAccelY = 1000000000.0;
else
invAccelY = 1.0f / ball->Acceleration.Y;
ball->InvAcceleration.Y = invAccelY;
table = pb::MainTable;
}
}
render::shift(static_cast<int>(floor(xDiff + 0.5)), static_cast<int>(floor(0.5 - yDiff)), 0, 0, table->Width,
table->Height);
}

View File

@ -1,12 +1,19 @@
#pragma once
class nudge
{
public :
static void un_nudge_right(int x, int y);
static void un_nudge_left(int x, int y);
static void un_nudge_up(int x, int y);
public:
static void un_nudge_right(int timerId, void* caller);
static void un_nudge_left(int timerId, void* caller);
static void un_nudge_up(int timerId, void* caller);
static void nudge_right();
static void nudge_left();
static void nudge_up();
static int nudged_left;
static int nudged_right;
static int nudged_up;
static float nudge_count;
private:
static void _nudge(float x, float y);
static int timer;
};

View File

@ -88,7 +88,6 @@ int objlist_class::objlist_delete_object(objlist_struct1* ptrToStruct, void* val
if (--index < 0)
return 0;
}
//ptrToStruct->Array[index] = *(&ptrToStruct->Count + count);
ptrToStruct->Array[index] = ptrToStruct->Array[count - 1];
--ptrToStruct->Count;
return 1;

View File

@ -187,7 +187,7 @@ void options::path_free()
int options::get_int(LPCSTR optPath, LPCSTR lpValueName, int defaultValue)
{
DWORD dwDisposition; // [esp+4h] [ebp-8h]
DWORD dwDisposition;
HKEY result = (HKEY)defaultValue, Data = (HKEY)defaultValue;
if (!OptionsRegPath)
@ -205,7 +205,7 @@ int options::get_int(LPCSTR optPath, LPCSTR lpValueName, int defaultValue)
void options::set_int(LPCSTR optPath, LPCSTR lpValueName, int data)
{
DWORD dwDisposition; // [esp+4h] [ebp-4h]
DWORD dwDisposition;
if (OptionsRegPath)
{
@ -240,7 +240,7 @@ void options::get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR lpString1, LP
void options::set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value)
{
DWORD dwDisposition; // [esp+4h] [ebp-4h]
DWORD dwDisposition;
if (OptionsRegPath)
{

View File

@ -77,7 +77,6 @@ struct dat8BitBmpHeader
static_assert(sizeof(dat8BitBmpHeader) == 14, "Wrong size of dat8BitBmpHeader");
//typedef const char* LPCSTR;
class partman
{
public:

View File

@ -13,14 +13,15 @@
#include "timer.h"
#include "winmain.h"
#include "resource.h"
#include "TBall.h"
#include "TDemo.h"
#include "TLightGroup.h"
#include "TPlunger.h"
TPinballTable* pb::MainTable = nullptr;
datFileStruct* pb::record_table = nullptr;
int pb::time_ticks = 0, pb::demo_mode = 0, pb::cheat_mode = 0, pb::game_mode = 2, pb::mode_countdown_, pb::
ball_speed_limit, pb::state;
float pb::time_now, pb::time_next;
int pb::time_ticks = 0, pb::demo_mode = 0, pb::cheat_mode = 0, pb::game_mode = 2, pb::mode_countdown_, pb::state;
float pb::time_now, pb::time_next, pb::ball_speed_limit;
high_score_struct pb::highscore_table[5];
int pb::init()
@ -63,7 +64,6 @@ int pb::init()
}
render::init(nullptr, zMin, zScaler, tableSize[0], tableSize[1]);
gdrv::fill_bitmap(&render::vscreen, render::vscreen.Width, render::vscreen.Height, 0, 0, '\xFF'); // temp
gdrv::copy_bitmap(
&render::vscreen,
backgroundBmp->Width,
@ -89,9 +89,7 @@ int pb::init()
MainTable = new TPinballTable();
high_score::read(highscore_table, &state);
//v11 = *(float*)((char*)MainTable->ListP2.ListPtr->Array[0] + 154);
//ball_speed_limit = v11 * 200.0;
ball_speed_limit = static_cast<TBall*>(MainTable->BallList->Get(0))->Offset * 200.0f;
--memory::critical_allocation;
return 0;
}
@ -142,9 +140,8 @@ void pb::mode_change(int mode)
options::menu_check(Menu1_Demo, 1);
if (MainTable)
{
/*v2 = MainTable->UnknownP48;
if (v2)
*(_BYTE*)(v2 + 5) = 1;*/
if (MainTable->Demo)
MainTable->Demo->UnknownBaseFlag2 = 1;
}
}
else
@ -154,9 +151,8 @@ void pb::mode_change(int mode)
options::menu_check(Menu1_Demo, 0);
if (MainTable)
{
/*v1 = MainTable->UnknownP48;
if (v1)
*(_BYTE*)(v1 + 5) = 0;*/
if (MainTable->Demo)
MainTable->Demo->UnknownBaseFlag2 = 0;
}
}
break;
@ -208,6 +204,10 @@ void pb::replay_level(int demoMode)
void pb::ballset(int x, int y)
{
TBall* ball = static_cast<TBall*>(MainTable->BallList->Get(0));
ball->Acceleration.X = x * 30.0f;
ball->Acceleration.Y = y * 30.0f;
ball->Speed = maths::normalize_2d(&ball->Acceleration);
}
int pb::frame(int time)
@ -221,30 +221,29 @@ int pb::frame(int time)
//pb::timed_frame(time_now, timeMul, 1);
time_now = time_next;
time_ticks += time;
/*if (nudged_left || nudged_right || nudged_up)
if (nudge::nudged_left || nudge::nudged_right || nudge::nudged_up)
{
nudge_count = timeMul * 4.0 + nudge_count;
nudge::nudge_count = timeMul * 4.0f + nudge::nudge_count;
}
else
{
v2 = nudge_count - timeMul;
if (v2 <= 0.0)
v2 = 0.0;
nudge_count = v2;
}*/
auto nudgeDec = nudge::nudge_count - timeMul;
if (nudgeDec <= 0.0)
nudgeDec = 0.0;
nudge::nudge_count = nudgeDec;
}
timer::check();
render::update();
//score::update(MainTable->Score1);
/*if (!MainTable->UnknownP83)
score::update(MainTable->CurScoreStruct);
if (!MainTable->TiltLockFlag)
{
if (nudge_count > 0.5)
if (nudge::nudge_count > 0.5)
{
v3 = pinball:: get_rc_string(25, 0);
pinball::InfoTextBox->Display( v3, 2.0);
pinball::InfoTextBox->Display(pinball::get_rc_string(25, 0), 2.0);
}
if (nudge_count > 1.0)
TPinballTable::tilt(MainTable, v1, time_now);
}*/
if (nudge::nudge_count > 1.0)
MainTable->tilt(time_now);
}
}
return 1;
}
@ -316,15 +315,15 @@ void pb::keyup(int key)
}
else if (key == options::Options.LeftTableBumpKey)
{
nudge::un_nudge_right(0, 0);
nudge::un_nudge_right(0, nullptr);
}
else if (key == options::Options.RightTableBumpKey)
{
nudge::un_nudge_left(0, 0);
nudge::un_nudge_left(0, nullptr);
}
else if (key == options::Options.BottomTableBumpKey)
{
nudge::un_nudge_up(0, 0);
nudge::un_nudge_up(0, nullptr);
}
}
}
@ -379,12 +378,38 @@ void pb::keydown(int key)
switch (key)
{
case 'B':
/**/
TBall* ball;
if (MainTable->BallList->Count() <= 0)
{
ball = new TBall(MainTable);
}
else
{
for (auto index = 0; ;)
{
ball = static_cast<TBall*>(MainTable->BallList->Get(index));
if (!ball->UnknownBaseFlag2)
break;
++index;
if (index >= MainTable->BallList->Count())
{
ball = new TBall(MainTable);
break;
}
}
}
ball->Position.X = 1.0;
ball->UnknownBaseFlag2 = 1;
ball->Position.Z = ball->Offset;
ball->Position.Y = 1.0;
ball->Acceleration.Z = 0.0;
ball->Acceleration.Y = 0.0;
ball->Acceleration.X = 0.0;
break;
case 'H':
/*auto v1 = get_rc_string(26, 0);
lstrcpyA(&String1, v1);
show_and_set_high_score_dialog(highscore_table, 1000000000, 1, &String1);*/
char String1[200];
lstrcpyA(String1, pinball::get_rc_string(26, 0));
high_score::show_and_set_high_score_dialog(highscore_table, 1000000000, 1, String1);
break;
case 'M':
char buffer[20];
@ -450,3 +475,28 @@ void pb::high_scores()
{
high_score::show_high_score_dialog(highscore_table);
}
void pb::tilt_no_more()
{
if (MainTable->TiltLockFlag)
pinball::InfoTextBox->Clear();
MainTable->TiltLockFlag = 0;
nudge::nudge_count = -2.0;
}
bool pb::chk_highscore()
{
if (demo_mode)
return false;
int playerIndex = MainTable->PlayerCount - 1;
if (playerIndex < 0)
return false;
for (int i = playerIndex;
high_score::get_score_position(highscore_table, MainTable->PlayerScores[i].ScoreStruct->Score) < 0;
--i)
{
if (--playerIndex < 0)
return false;
}
return true;
}

View File

@ -7,7 +7,7 @@ class pb
{
public:
static int time_ticks;
static int ball_speed_limit;
static float ball_speed_limit;
static int cheat_mode, game_mode;
static datFileStruct* record_table;
static TPinballTable* MainTable;
@ -33,6 +33,8 @@ public:
static void launch_ball();
static int end_game();
static void high_scores();
static void tilt_no_more();
static bool chk_highscore();
private :
static int demo_mode, mode_countdown_;
static float time_now, time_next;

View File

@ -36,9 +36,9 @@ int pinball::get_rc_int(int uID, int* dst)
void pinball::FindShiftKeys()
{
signed int i; // esi
int rightShift; // eax
CHAR stringBuf[20]; // [esp+Ch] [ebp-18h]
signed int i;
int rightShift;
CHAR stringBuf[20];
RightShift = -1;
LeftShift = -1;

View File

@ -6,14 +6,14 @@ float proj::d_, proj::centerx, proj::centery;
void proj::init(float* mat4x3, float d, float centerX, float centerY)
{
//for (auto colIndex = 0; colIndex < 4; ++colIndex)
//{
// // Todo: out of bounds read from mat4x3?
// for (int rowIndex = colIndex, i = 4; i > 0; rowIndex += 4, --i)
// {
// ((float*)&matrix)[rowIndex] = mat4x3[rowIndex];
// }
//}
/*for (auto colIndex = 0; colIndex < 4; ++colIndex)
{
// Todo: out of bounds read from mat4x3?
for (int rowIndex = colIndex, i = 4; i > 0; rowIndex += 4, --i)
{
((float*)&matrix)[rowIndex] = mat4x3[rowIndex];
}
}*/
memcpy(&matrix, mat4x3, sizeof(float) * 4 * 3);
matrix.Row3.X = 0.0;

View File

@ -153,7 +153,7 @@ void render::update()
rect->Width = dirtyRect->Width;
rect->Height = dirtyRect->Height;
if (sprite->Unknown6_0 != 0)
if (sprite->UnknownFlag != 0)
remove_sprite(sprite);
}
@ -228,7 +228,7 @@ render_sprite_type_struct* render::create_sprite(VisualType visualType, gdrv_bit
sprite->BmpRect.XPosition = xPosition;
sprite->Bmp = bmp;
sprite->VisualType = visualType;
sprite->Unknown6_0 = 0;
sprite->UnknownFlag = 0;
sprite->SpriteArray = nullptr;
sprite->SpriteCount = 0;
if (rect)
@ -395,7 +395,7 @@ void render::repaint(struct render_sprite_type_struct* sprite)
for (int index = 0; index < sprite->SpriteCount; index++)
{
render_sprite_type_struct* curSprite = sprite->SpriteArray[index];
if (!curSprite->Unknown6_0 && curSprite->Bmp)
if (!curSprite->UnknownFlag && curSprite->Bmp)
{
if (maths::rectangle_clip(&curSprite->BmpRect, &sprite->DirtyRect, &clipRect))
zdrv::paint(
@ -523,3 +523,52 @@ void render::shift(int offsetX, int offsetY, int xSrc, int ySrc, int DestWidth,
DestHeight);
unpaint_balls();
}
void render::build_occlude_list()
{
++memory::critical_allocation;
render_sprite_type_struct** spriteArr = nullptr;
auto spritePtr1 = sprite_list;
for (int index = 0; index < many_sprites; ++index, ++spritePtr1)
{
auto curSprite = *spritePtr1;
if ((*spritePtr1)->SpriteArray)
{
memory::free((*spritePtr1)->SpriteArray);
curSprite->SpriteArray = nullptr;
curSprite->SpriteCount = 0;
}
if (!curSprite->UnknownFlag && curSprite->BoundingRect.Width != -1)
{
if (!spriteArr)
spriteArr = reinterpret_cast<render_sprite_type_struct**>(memory::allocate(0xFA0u));
int occludeCount = 0;
auto spritePtr2 = sprite_list;
for (int i = 0; i < many_sprites; ++i, ++spritePtr2)
{
auto sprite = *spritePtr2;
if (!sprite->UnknownFlag
&& sprite->BoundingRect.Width != -1
&& maths::rectangle_clip(&curSprite->BoundingRect, &sprite->BoundingRect, nullptr)
&& spriteArr)
{
spriteArr[occludeCount++] = sprite;
}
}
if (!curSprite->UnknownFlag && curSprite->Bmp && occludeCount < 2)
occludeCount = 0;
if (occludeCount)
{
curSprite->SpriteArray = reinterpret_cast<render_sprite_type_struct**>(memory::realloc(
spriteArr, 4 * occludeCount));
curSprite->SpriteCount = occludeCount;
spriteArr = nullptr;
}
}
}
if (spriteArr)
memory::free(spriteArr);
--memory::critical_allocation;
}

View File

@ -15,7 +15,7 @@ struct __declspec(align(4)) render_sprite_type_struct
rectangle_type BmpRect;
gdrv_bitmap8* Bmp;
zmap_header_type* ZMap;
char Unknown6_0;
char UnknownFlag;
VisualType VisualType;
__int16 Depth;
rectangle_type BmpRectCopy;
@ -62,4 +62,5 @@ public:
static void paint_balls();
static void unpaint_balls();
static void shift(int offsetX, int offsetY, int xSrc, int ySrc, int DestWidth, int DestHeight);
static void build_occlude_list();
};

View File

@ -370,7 +370,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
SetCursor(prevCursor);
auto changeDisplayFg = options::get_int(nullptr, "Change Display", 1);
auto menuHandle = GetMenu(hWnd);
fullscrn::init(width, static_cast<int>(height), options::Options.FullScreen, hWnd, menuHandle,
fullscrn::init(width, height, options::Options.FullScreen, hWnd, menuHandle,
changeDisplayFg);
--memory::critical_allocation;
@ -662,7 +662,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
int winmain::ProcessWindowMessages()
{
MSG Msg{}; // [esp+8h] [ebp-1Ch]
MSG Msg{};
if (has_focus && !single_step)
{