Render tweaks part 1: refactored sprite struct.

Optimized sprite handling in render.
Fixed switch warning in control.
This commit is contained in:
Muzychenko Andrey 2022-09-21 16:43:04 +03:00
parent 1e43bdd5fa
commit 9f0ae0434e
23 changed files with 258 additions and 321 deletions

View File

@ -52,7 +52,7 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
auto zDepth = proj::z_distance(*visVec); auto zDepth = proj::z_distance(*visVec);
VisualZArray[index] = zDepth; VisualZArray[index] = zDepth;
} }
RenderSprite = render::create_sprite(VisualTypes::Ball, nullptr, nullptr, 0, 0, nullptr); RenderSprite = new render_sprite(VisualTypes::Ball, nullptr, nullptr, 0, 0, nullptr);
PinballTable->CollisionCompOffset = Offset; PinballTable->CollisionCompOffset = Offset;
Position.Z = Offset; Position.Z = Offset;
} }
@ -78,8 +78,7 @@ void TBall::Repaint()
} }
auto bmp = ListBitmap->at(index); auto bmp = ListBitmap->at(index);
render::ball_set( RenderSprite->ball_set(
RenderSprite,
bmp, bmp,
zDepth, zDepth,
pos2D.X - bmp->Width / 2, pos2D.X - bmp->Width / 2,
@ -110,7 +109,7 @@ int TBall::Message(MessageCode code, float value)
{ {
if (code == MessageCode::Reset) if (code == MessageCode::Reset)
{ {
render::ball_set(RenderSprite, nullptr, 0.0, 0, 0); RenderSprite->ball_set(nullptr, 0.0, 0, 0);
Position.X = 0.0; Position.X = 0.0;
CollisionComp = nullptr; CollisionComp = nullptr;
Position.Y = 0.0; Position.Y = 0.0;
@ -145,5 +144,5 @@ vector2 TBall::get_coordinates()
void TBall::Disable() void TBall::Disable()
{ {
ActiveFlag = false; ActiveFlag = false;
render::sprite_set_bitmap(RenderSprite, nullptr); RenderSprite->set_bitmap(nullptr);
} }

View File

@ -20,7 +20,7 @@ TBlocker::TBlocker(TPinballTable* table, int groupIndex) : TCollisionComponent(t
Timer = 0; Timer = 0;
MessageField = 0; MessageField = 0;
ActiveFlag = 0; ActiveFlag = 0;
render::sprite_set_bitmap(RenderSprite, nullptr); RenderSprite->set_bitmap(nullptr);
} }
int TBlocker::Message(MessageCode code, float value) int TBlocker::Message(MessageCode code, float value)
@ -38,14 +38,14 @@ int TBlocker::Message(MessageCode code, float value)
} }
MessageField = 0; MessageField = 0;
ActiveFlag = 0; ActiveFlag = 0;
render::sprite_set_bitmap(RenderSprite, nullptr); RenderSprite->set_bitmap(nullptr);
if (code == MessageCode::TBlockerDisable) if (code == MessageCode::TBlockerDisable)
loader::play_sound(SoundIndex3, this, "TBlocker1"); loader::play_sound(SoundIndex3, this, "TBlocker1");
break; break;
case MessageCode::TBlockerEnable: case MessageCode::TBlockerEnable:
ActiveFlag = 1; ActiveFlag = 1;
loader::play_sound(SoundIndex4, this, "TBlocker2"); loader::play_sound(SoundIndex4, this, "TBlocker2");
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0)); RenderSprite->set_bitmap(ListBitmap->at(0));
if (Timer) if (Timer)
timer::kill(Timer); timer::kill(Timer);
Timer = timer::set(std::max(value, 0.0f), this, TimerExpired); Timer = timer::set(std::max(value, 0.0f), this, TimerExpired);

View File

@ -113,8 +113,7 @@ void TBumper::TimerExpired(int timerId, void* caller)
auto bmp = bump->ListBitmap->at(bump->BmpIndex * 2); auto bmp = bump->ListBitmap->at(bump->BmpIndex * 2);
auto zMap = bump->ListZMap->at(bump->BmpIndex * 2); auto zMap = bump->ListZMap->at(bump->BmpIndex * 2);
bump->Timer = 0; bump->Timer = 0;
render::sprite_set( bump->RenderSprite->set(
bump->RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - bump->PinballTable->XOffset, bmp->XPosition - bump->PinballTable->XOffset,
@ -127,8 +126,7 @@ void TBumper::Fire()
int bmpIndex = 2 * BmpIndex + 1; int bmpIndex = 2 * BmpIndex + 1;
auto bmp = ListBitmap->at(bmpIndex); auto bmp = ListBitmap->at(bmpIndex);
auto zMap = ListZMap->at(bmpIndex); auto zMap = ListZMap->at(bmpIndex);
render::sprite_set( RenderSprite->set(
RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - PinballTable->XOffset, bmp->XPosition - PinballTable->XOffset,

View File

@ -62,8 +62,7 @@ int TFlagSpinner::Message(MessageCode code, float value)
BmpIndex = 0; BmpIndex = 0;
auto bmp = ListBitmap->at(0); auto bmp = ListBitmap->at(0);
auto zMap = ListZMap->at(0); auto zMap = ListZMap->at(0);
render::sprite_set( RenderSprite->set(
RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - PinballTable->XOffset, bmp->XPosition - PinballTable->XOffset,
@ -113,8 +112,7 @@ void TFlagSpinner::NextFrame()
auto bmp = ListBitmap->at(BmpIndex); auto bmp = ListBitmap->at(BmpIndex);
auto zMap = ListZMap->at(BmpIndex); auto zMap = ListZMap->at(BmpIndex);
render::sprite_set( RenderSprite->set(
RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - PinballTable->XOffset, bmp->XPosition - PinballTable->XOffset,

View File

@ -121,8 +121,7 @@ void TFlipper::UpdateSprite(float timeNow)
BmpIndex = newBmpIndex; BmpIndex = newBmpIndex;
auto bmp = ListBitmap->at(BmpIndex); auto bmp = ListBitmap->at(BmpIndex);
auto zMap = ListZMap->at(BmpIndex); auto zMap = ListZMap->at(BmpIndex);
render::sprite_set( RenderSprite->set(
RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - PinballTable->XOffset, bmp->XPosition - PinballTable->XOffset,

View File

@ -14,7 +14,7 @@ TGate::TGate(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
SoundIndex4 = visual.SoundIndex4; SoundIndex4 = visual.SoundIndex4;
SoundIndex3 = visual.SoundIndex3; SoundIndex3 = visual.SoundIndex3;
ActiveFlag = 1; ActiveFlag = 1;
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0)); RenderSprite->set_bitmap(ListBitmap->at(0));
control::handler(MessageCode::Reset, this); control::handler(MessageCode::Reset, this);
} }
@ -24,13 +24,13 @@ int TGate::Message(MessageCode code, float value)
{ {
case MessageCode::TGateDisable: case MessageCode::TGateDisable:
ActiveFlag = 0; ActiveFlag = 0;
render::sprite_set_bitmap(RenderSprite, nullptr); RenderSprite->set_bitmap(nullptr);
loader::play_sound(SoundIndex3, this, "TGate1"); loader::play_sound(SoundIndex3, this, "TGate1");
break; break;
case MessageCode::Reset: case MessageCode::Reset:
case MessageCode::TGateEnable: case MessageCode::TGateEnable:
ActiveFlag = 1; ActiveFlag = 1;
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0)); RenderSprite->set_bitmap(ListBitmap->at(0));
if (code == MessageCode::TGateEnable) if (code == MessageCode::TGateEnable)
loader::play_sound(SoundIndex4, this, "TGate2"); loader::play_sound(SoundIndex4, this, "TGate2");
break; break;

View File

@ -25,7 +25,7 @@ int TKickback::Message(MessageCode code, float value)
{ {
timer::kill(Timer); timer::kill(Timer);
if (ListBitmap) if (ListBitmap)
render::sprite_set_bitmap(RenderSprite, nullptr); RenderSprite->set_bitmap(nullptr);
Timer = 0; Timer = 0;
KickActiveFlag = 0; KickActiveFlag = 0;
Threshold = 1000000000.0; Threshold = 1000000000.0;
@ -67,8 +67,7 @@ void TKickback::TimerExpired(int timerId, void* caller)
{ {
auto bmp = kick->ListBitmap->at(1); auto bmp = kick->ListBitmap->at(1);
auto zMap = kick->ListZMap->at(1); auto zMap = kick->ListZMap->at(1);
render::sprite_set( kick->RenderSprite->set(
kick->RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - kick->PinballTable->XOffset, bmp->XPosition - kick->PinballTable->XOffset,
@ -81,8 +80,7 @@ void TKickback::TimerExpired(int timerId, void* caller)
{ {
auto bmp = kick->ListBitmap->at(0); auto bmp = kick->ListBitmap->at(0);
auto zMap = kick->ListZMap->at(0); auto zMap = kick->ListZMap->at(0);
render::sprite_set( kick->RenderSprite->set(
kick->RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - kick->PinballTable->XOffset, bmp->XPosition - kick->PinballTable->XOffset,

View File

@ -225,7 +225,8 @@ int TLight::Message(MessageCode code, float value)
case MessageCode::TLightFtTmpOverrideOn: case MessageCode::TLightFtTmpOverrideOn:
case MessageCode::TLightFtTmpOverrideOff: case MessageCode::TLightFtTmpOverrideOff:
// FT codes in negative to avoid overlap with 3DPB TLightGroup codes // FT codes in negative to avoid overlap with 3DPB TLightGroup codes
render::sprite_set_bitmap(RenderSprite, BmpArr[code == MessageCode::TLightFtTmpOverrideOn]); if (ListBitmap)
RenderSprite->set_bitmap(BmpArr[code == MessageCode::TLightFtTmpOverrideOn]);
if (UndoOverrideTimer) if (UndoOverrideTimer)
timer::kill(UndoOverrideTimer); timer::kill(UndoOverrideTimer);
UndoOverrideTimer = 0; UndoOverrideTimer = 0;
@ -240,7 +241,8 @@ int TLight::Message(MessageCode code, float value)
timer::kill(UndoOverrideTimer); timer::kill(UndoOverrideTimer);
UndoOverrideTimer = 0; UndoOverrideTimer = 0;
TemporaryOverrideFlag = false; TemporaryOverrideFlag = false;
render::sprite_set_bitmap(RenderSprite, PreviousBitmap); if (ListBitmap)
RenderSprite->set_bitmap(PreviousBitmap);
break; break;
default: default:
break; break;
@ -267,10 +269,12 @@ void TLight::Reset()
TemporaryOverrideFlag = false; TemporaryOverrideFlag = false;
TurnOffAfterFlashingFg = false; TurnOffAfterFlashingFg = false;
PreviousBitmap = nullptr; PreviousBitmap = nullptr;
render::sprite_set_bitmap(RenderSprite, nullptr);
BmpArr[0] = nullptr; BmpArr[0] = nullptr;
if (ListBitmap) if (ListBitmap)
{
BmpArr[1] = ListBitmap->at(0); BmpArr[1] = ListBitmap->at(0);
RenderSprite->set_bitmap(nullptr);
}
MessageField = 0; MessageField = 0;
} }
@ -326,8 +330,8 @@ void TLight::flasher_start(bool bmpIndex)
void TLight::SetSpriteBmp(gdrv_bitmap8* bmp) void TLight::SetSpriteBmp(gdrv_bitmap8* bmp)
{ {
PreviousBitmap = bmp; PreviousBitmap = bmp;
if (!TemporaryOverrideFlag) if (!TemporaryOverrideFlag && RenderSprite)
render::sprite_set_bitmap(RenderSprite, bmp); RenderSprite->set_bitmap(bmp);
} }
void TLight::flasher_callback(int timerId, void* caller) void TLight::flasher_callback(int timerId, void* caller)

View File

@ -14,7 +14,7 @@ TLightRollover::TLightRollover(TPinballTable* table, int groupIndex) : TRollover
RolloverFlag = 0; RolloverFlag = 0;
Timer = 0; Timer = 0;
if (ListBitmap != nullptr) if (ListBitmap != nullptr)
render::sprite_set_bitmap(RenderSprite, nullptr); RenderSprite->set_bitmap(nullptr);
build_walls(groupIndex); build_walls(groupIndex);
FloatArr = *loader::query_float_attribute(groupIndex, 0, 407); FloatArr = *loader::query_float_attribute(groupIndex, 0, 407);
} }
@ -29,7 +29,7 @@ int TLightRollover::Message(MessageCode code, float value)
timer::kill(Timer); timer::kill(Timer);
Timer = 0; Timer = 0;
if (ListBitmap) if (ListBitmap)
render::sprite_set_bitmap(RenderSprite, nullptr); RenderSprite->set_bitmap(nullptr);
} }
return 0; return 0;
} }
@ -57,7 +57,7 @@ void TLightRollover::Collision(TBall* ball, vector2* nextPosition, vector2* dire
control::handler(MessageCode::ControlCollision, this); control::handler(MessageCode::ControlCollision, this);
RolloverFlag = RolloverFlag == 0; RolloverFlag = RolloverFlag == 0;
if (ListBitmap) if (ListBitmap)
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0)); RenderSprite->set_bitmap(ListBitmap->at(0));
} }
} }
} }
@ -65,6 +65,6 @@ void TLightRollover::Collision(TBall* ball, vector2* nextPosition, vector2* dire
void TLightRollover::delay_expired(int timerId, void* caller) void TLightRollover::delay_expired(int timerId, void* caller)
{ {
auto roll = static_cast<TLightRollover*>(caller); auto roll = static_cast<TLightRollover*>(caller);
render::sprite_set_bitmap(roll->RenderSprite, nullptr); roll->RenderSprite->set_bitmap(nullptr);
roll->Timer = 0; roll->Timer = 0;
} }

View File

@ -23,10 +23,12 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
Control = nullptr; Control = nullptr;
VisualPosNormX= -1.0f; VisualPosNormX= -1.0f;
VisualPosNormY = -1.0f; VisualPosNormY = -1.0f;
GroupIndex = groupIndex;
if (table) if (table)
table->ComponentList.push_back(this); table->ComponentList.push_back(this);
if (groupIndex >= 0) if (groupIndex >= 0)
GroupName = loader::query_name(groupIndex); GroupName = loader::query_name(groupIndex);
if (loadVisuals && groupIndex >= 0) if (loadVisuals && groupIndex >= 0)
{ {
int visualCount = loader::query_visual_states(groupIndex); int visualCount = loader::query_visual_states(groupIndex);
@ -37,15 +39,13 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
{ {
if (!ListBitmap) if (!ListBitmap)
ListBitmap = new std::vector<gdrv_bitmap8*>(); ListBitmap = new std::vector<gdrv_bitmap8*>();
if (ListBitmap) ListBitmap->push_back(visual.Bitmap);
ListBitmap->push_back(visual.Bitmap);
} }
if (visual.ZMap) if (visual.ZMap)
{ {
if (!ListZMap) if (!ListZMap)
ListZMap = new std::vector<zmap_header_type*>(); ListZMap = new std::vector<zmap_header_type*>();
if (ListZMap) ListZMap->push_back(visual.ZMap);
ListZMap->push_back(visual.ZMap);
} }
} }
@ -68,8 +68,8 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
maths::enclosing_box(bmp1Rect, tmpRect, bmp1Rect); maths::enclosing_box(bmp1Rect, tmpRect, bmp1Rect);
} }
RenderSprite = render::create_sprite( RenderSprite = new render_sprite(
visualCount > 0 ? VisualTypes::Sprite : VisualTypes::None, VisualTypes::Sprite,
rootBmp, rootBmp,
zMap, zMap,
rootBmp->XPosition - table->XOffset, rootBmp->XPosition - table->XOffset,
@ -85,7 +85,6 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool
VisualPosNormY = posNorm.Y; VisualPosNormY = posNorm.Y;
} }
} }
GroupIndex = groupIndex;
} }

View File

@ -2,7 +2,7 @@
struct zmap_header_type; struct zmap_header_type;
struct gdrv_bitmap8; struct gdrv_bitmap8;
struct render_sprite_type_struct; struct render_sprite;
struct component_control; struct component_control;
struct vector2; struct vector2;
class TPinballTable; class TPinballTable;
@ -145,7 +145,7 @@ public:
char* GroupName; char* GroupName;
component_control* Control; component_control* Control;
int GroupIndex; int GroupIndex;
render_sprite_type_struct* RenderSprite; render_sprite* RenderSprite;
TPinballTable* PinballTable; TPinballTable* PinballTable;
std::vector<gdrv_bitmap8*>* ListBitmap; std::vector<gdrv_bitmap8*>* ListBitmap;
std::vector<zmap_header_type*>* ListZMap; std::vector<zmap_header_type*>* ListZMap;

View File

@ -133,8 +133,7 @@ int TPlunger::Message(MessageCode code, float value)
loader::play_sound(SoundIndexP2, this, "TPlunger3"); loader::play_sound(SoundIndexP2, this, "TPlunger3");
auto bmp = ListBitmap->at(0); auto bmp = ListBitmap->at(0);
auto zMap = ListZMap->at(0); auto zMap = ListZMap->at(0);
render::sprite_set( RenderSprite->set(
RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - PinballTable->XOffset, bmp->XPosition - PinballTable->XOffset,
@ -156,8 +155,7 @@ int TPlunger::Message(MessageCode code, float value)
auto bmp = ListBitmap->at(0); auto bmp = ListBitmap->at(0);
auto zMap = ListZMap->at(0); auto zMap = ListZMap->at(0);
render::sprite_set( RenderSprite->set(
RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - PinballTable->XOffset, bmp->XPosition - PinballTable->XOffset,
@ -204,8 +202,7 @@ void TPlunger::PullbackTimer(int timerId, void* caller)
(plunger->Boost / plunger->MaxPullback))); (plunger->Boost / plunger->MaxPullback)));
auto bmp = plunger->ListBitmap->at(index); auto bmp = plunger->ListBitmap->at(index);
auto zMap = plunger->ListZMap->at(index); auto zMap = plunger->ListZMap->at(index);
render::sprite_set( plunger->RenderSprite->set(
plunger->RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - plunger->PinballTable->XOffset, bmp->XPosition - plunger->PinballTable->XOffset,

View File

@ -20,7 +20,7 @@ int TPopupTarget::Message(MessageCode code, float value)
{ {
case MessageCode::TPopupTargetDisable: case MessageCode::TPopupTargetDisable:
ActiveFlag = 0; ActiveFlag = 0;
render::sprite_set_bitmap(RenderSprite, nullptr); RenderSprite->set_bitmap(nullptr);
break; break;
case MessageCode::TPopupTargetEnable: case MessageCode::TPopupTargetEnable:
Timer = timer::set(TimerTime, this, TimerExpired); Timer = timer::set(TimerTime, this, TimerExpired);
@ -79,7 +79,7 @@ void TPopupTarget::TimerExpired(int timerId, void* caller)
auto target = static_cast<TPopupTarget*>(caller); auto target = static_cast<TPopupTarget*>(caller);
target->Timer = 0; target->Timer = 0;
target->ActiveFlag = 1; target->ActiveFlag = 1;
render::sprite_set_bitmap(target->RenderSprite, target->ListBitmap->at(0)); target->RenderSprite->set_bitmap(target->ListBitmap->at(0));
if (timerId) if (timerId)
{ {
if (target->SoftHitSoundId) if (target->SoftHitSoundId)

View File

@ -20,7 +20,7 @@ TRollover::TRollover(TPinballTable* table, int groupIndex, bool createWall) : TC
TRollover::TRollover(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false) TRollover::TRollover(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
{ {
if (ListBitmap) if (ListBitmap)
render::sprite_set_bitmap(RenderSprite, ListBitmap->at(0)); RenderSprite->set_bitmap(ListBitmap->at(0));
build_walls(groupIndex); build_walls(groupIndex);
} }
@ -29,10 +29,10 @@ int TRollover::Message(MessageCode code, float value)
{ {
if (code == MessageCode::Reset) if (code == MessageCode::Reset)
{ {
this->ActiveFlag = 1; ActiveFlag = 1;
this->RolloverFlag = 0; RolloverFlag = 0;
if (this->ListBitmap) if (ListBitmap)
render::sprite_set_bitmap(this->RenderSprite, this->ListBitmap->at(0)); RenderSprite->set_bitmap(ListBitmap->at(0));
} }
return 0; return 0;
} }
@ -62,7 +62,7 @@ void TRollover::Collision(TBall* ball, vector2* nextPosition, vector2* direction
{ {
if (!RolloverFlag) if (!RolloverFlag)
bmp = ListBitmap->at(0); bmp = ListBitmap->at(0);
render::sprite_set_bitmap(RenderSprite, bmp); RenderSprite->set_bitmap(bmp);
} }
} }
} }

View File

@ -42,8 +42,7 @@ int TSoloTarget::Message(MessageCode code, float value)
auto index = 1 - ActiveFlag; auto index = 1 - ActiveFlag;
auto bmp = ListBitmap->at(index); auto bmp = ListBitmap->at(index);
auto zMap = ListZMap->at(index); auto zMap = ListZMap->at(index);
render::sprite_set( RenderSprite->set(
RenderSprite,
bmp, bmp,
zMap, zMap,
bmp->XPosition - PinballTable->XOffset, bmp->XPosition - PinballTable->XOffset,

View File

@ -32,7 +32,7 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f
rect.YPosition = 0; rect.YPosition = 0;
rect.Width = bmp->Width; rect.Width = bmp->Width;
rect.Height = bmp->Height; rect.Height = bmp->Height;
render::create_sprite(VisualTypes::None, bmp, visual.ZMap, 0, 0, &rect); new render_sprite(VisualTypes::Background, bmp, visual.ZMap, 0, 0, &rect);
PinballTable->SoundIndex1 = visual.SoundIndex4; PinballTable->SoundIndex1 = visual.SoundIndex4;
PinballTable->SoundIndex2 = visual.SoundIndex3; PinballTable->SoundIndex2 = visual.SoundIndex3;

View File

@ -9,7 +9,7 @@
TWall::TWall(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true) TWall::TWall(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, true)
{ {
if (RenderSprite) if (RenderSprite)
render::sprite_set_bitmap(RenderSprite, nullptr); RenderSprite->set_bitmap(nullptr);
if (ListBitmap) if (ListBitmap)
BmpPtr = ListBitmap->at(0); BmpPtr = ListBitmap->at(0);
} }
@ -30,7 +30,7 @@ void TWall::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
{ {
if (BmpPtr) if (BmpPtr)
{ {
render::sprite_set_bitmap(RenderSprite, BmpPtr); RenderSprite->set_bitmap(BmpPtr);
Timer = timer::set(0.1f, this, TimerExpired); Timer = timer::set(0.1f, this, TimerExpired);
} }
control::handler(MessageCode::ControlCollision, this); control::handler(MessageCode::ControlCollision, this);
@ -40,7 +40,7 @@ void TWall::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
void TWall::TimerExpired(int timerId, void* caller) void TWall::TimerExpired(int timerId, void* caller)
{ {
auto wall = static_cast<TWall*>(caller); auto wall = static_cast<TWall*>(caller);
render::sprite_set_bitmap(wall->RenderSprite, nullptr); wall->RenderSprite->set_bitmap(nullptr);
wall->Timer = 0; wall->Timer = 0;
wall->MessageField = 0; wall->MessageField = 0;
} }

View File

@ -2081,6 +2081,7 @@ void control::GravityWellKickoutControl(MessageCode code, TPinballComponent* cal
case MessageCode::Reset: case MessageCode::Reset:
kickout1->ActiveFlag = 0; kickout1->ActiveFlag = 0;
break; break;
default: break;
} }
} }

View File

@ -42,7 +42,7 @@ TTextBox *pb::InfoTextBox, *pb::MissTextBox;
int pb::init() int pb::init()
{ {
float projMat[12], zMin = 0, zScaler = 0; float projMat[12];
if (DatFileName.empty()) if (DatFileName.empty())
return 1; return 1;
@ -75,12 +75,12 @@ int pb::init()
auto projCenterX = resInfo->TableWidth * 0.5f; auto projCenterX = resInfo->TableWidth * 0.5f;
auto projCenterY = resInfo->TableHeight * 0.5f; auto projCenterY = resInfo->TableHeight * 0.5f;
auto projD = cameraInfo[0]; auto projD = cameraInfo[0];
proj::init(projMat, projD, projCenterX, projCenterY); auto zMin = cameraInfo[1];
zMin = cameraInfo[1]; auto zScaler = cameraInfo[2];
zScaler = cameraInfo[2]; proj::init(projMat, projD, projCenterX, projCenterY, zMin, zScaler);
} }
render::init(nullptr, zMin, zScaler, resInfo->TableWidth, resInfo->TableHeight); render::init(nullptr, resInfo->TableWidth, resInfo->TableHeight);
gdrv::copy_bitmap( gdrv::copy_bitmap(
render::vscreen, render::vscreen,
backgroundBmp->Width, backgroundBmp->Width,

View File

@ -3,17 +3,10 @@
mat4_row_major proj::matrix; mat4_row_major proj::matrix;
float proj::d_, proj::centerx, proj::centery; float proj::d_, proj::centerx, proj::centery;
float proj::zscaler, proj::zmin, proj::zmax;
void proj::init(float* mat4x3, float d, float centerX, float centerY) void proj::init(float* mat4x3, float d, float centerX, float centerY, float zMin, float zScaler)
{ {
/*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); memcpy(&matrix, mat4x3, sizeof(float) * 4 * 3);
matrix.Row3.X = 0.0; matrix.Row3.X = 0.0;
@ -24,6 +17,10 @@ void proj::init(float* mat4x3, float d, float centerX, float centerY)
d_ = d; d_ = d;
centerx = centerX; centerx = centerX;
centery = centerY; centery = centerY;
zscaler = zScaler;
zmin = zMin;
zmax = static_cast<float>(0xffFFffFF) / zScaler + zMin;
} }
vector3 proj::matrix_vector_multiply(const mat4_row_major& mat, const vector3& vec) vector3 proj::matrix_vector_multiply(const mat4_row_major& mat, const vector3& vec)
@ -103,3 +100,17 @@ void proj::recenter(float centerX, float centerY)
centerx = centerX; centerx = centerX;
centery = centerY; centery = centerY;
} }
uint16_t proj::NormalizeDepth(float depth)
{
uint16_t result = 0;
if (depth >= zmin)
{
auto depthScaled = (depth - zmin) * zscaler;
if (depthScaled <= zmax)
result = static_cast<uint16_t>(depthScaled);
else
result = 0xffFF;
}
return result;
}

View File

@ -21,14 +21,16 @@ struct mat4_row_major
class proj class proj
{ {
public: public:
static void init(float* mat4x3, float d, float centerX, float centerY); static void init(float* mat4x3, float d, float centerX, float centerY, float zMin, float zScaler);
static vector3 matrix_vector_multiply(const mat4_row_major& mat, const vector3& vec); static vector3 matrix_vector_multiply(const mat4_row_major& mat, const vector3& vec);
static float z_distance(const vector3& vec); static float z_distance(const vector3& vec);
static vector2i xform_to_2d(const vector3& vec); static vector2i xform_to_2d(const vector3& vec);
static vector2i xform_to_2d(const vector2& vec); static vector2i xform_to_2d(const vector2& vec);
static vector3 ReverseXForm(const vector2i& vec); static vector3 ReverseXForm(const vector2i& vec);
static void recenter(float centerX, float centerY); static void recenter(float centerX, float centerY);
static uint16_t NormalizeDepth(float depth);
private: private:
static mat4_row_major matrix; static mat4_row_major matrix;
static float d_, centerx, centery; static float d_, centerx, centery;
static float zscaler, zmin, zmax;
}; };

View File

@ -9,21 +9,95 @@
#include "TPinballTable.h" #include "TPinballTable.h"
#include "winmain.h" #include "winmain.h"
#include "DebugOverlay.h" #include "DebugOverlay.h"
#include "proj.h"
std::vector<render_sprite_type_struct*> render::dirty_list, render::sprite_list, render::ball_list; std::vector<render_sprite*> render::sprite_list, render::ball_list;
zmap_header_type* render::background_zmap; zmap_header_type* render::background_zmap;
int render::zmap_offset, render::zmap_offsetY, render::offset_x, render::offset_y; int render::zmap_offsetX, render::zmap_offsetY, render::offset_x, render::offset_y;
float render::zscaler, render::zmin, render::zmax;
rectangle_type render::vscreen_rect; rectangle_type render::vscreen_rect;
gdrv_bitmap8 *render::vscreen, *render::background_bitmap, *render::ball_bitmap[20]; gdrv_bitmap8 *render::vscreen, *render::background_bitmap, *render::ball_bitmap[20];
zmap_header_type* render::zscreen; zmap_header_type* render::zscreen;
SDL_Rect render::DestinationRect{}; SDL_Rect render::DestinationRect{};
void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height) render_sprite::render_sprite(VisualTypes visualType, gdrv_bitmap8* bmp, zmap_header_type* zMap,
int xPosition, int yPosition, rectangle_type* boundingRect)
{
Bmp = bmp;
ZMap = zMap;
VisualType = visualType;
DeleteFlag = false;
OccludedSprites = nullptr;
DirtyRect = rectangle_type{};
DirtyFlag = visualType != VisualTypes::Ball;
ZMapOffestX = 0;
ZMapOffestY = 0;
Depth = 0xffFF;
if (boundingRect)
{
BoundingRect = *boundingRect;
}
else
{
BoundingRect.Width = -1;
BoundingRect.Height = -1;
BoundingRect.XPosition = 0;
BoundingRect.YPosition = 0;
}
BmpRect.YPosition = yPosition;
BmpRect.XPosition = xPosition;
if (bmp)
{
BmpRect.Width = bmp->Width;
BmpRect.Height = bmp->Height;
}
else
{
BmpRect.Width = 0;
BmpRect.Height = 0;
}
DirtyRectPrev = BmpRect;
render::AddSprite(*this);
}
render_sprite::~render_sprite()
{
render::RemoveSprite(*this);
delete OccludedSprites;
}
void render_sprite::set(gdrv_bitmap8* bmp, zmap_header_type* zMap, int xPos, int yPos)
{
if (Bmp == bmp && ZMap == zMap && BmpRect.XPosition == xPos && BmpRect.YPosition == yPos)
return;
Bmp = bmp;
ZMap = zMap;
DirtyFlag = VisualType != VisualTypes::Ball;
BmpRect.XPosition = xPos;
BmpRect.YPosition = yPos;
if (bmp)
{
BmpRect.Width = bmp->Width;
BmpRect.Height = bmp->Height;
}
}
void render_sprite::set_bitmap(gdrv_bitmap8* bmp)
{
set(bmp, ZMap, BmpRect.XPosition, BmpRect.YPosition);
}
void render_sprite::ball_set(gdrv_bitmap8* bmp, float depth, int xPos, int yPos)
{
set(bmp, ZMap,xPos, yPos);
Depth = proj::NormalizeDepth(depth);
}
void render::init(gdrv_bitmap8* bmp, int width, int height)
{ {
zscaler = zScaler;
zmin = zMin;
zmax = 4294967300.0f / zScaler + zMin;
vscreen = new gdrv_bitmap8(width, height, false); vscreen = new gdrv_bitmap8(width, height, false);
zscreen = new zmap_header_type(width, height, width); zscreen = new zmap_header_type(width, height, width);
zdrv::fill(zscreen, zscreen->Width, zscreen->Height, 0, 0, 0xFFFF); zdrv::fill(zscreen, zscreen->Width, zscreen->Height, 0, 0, 0xFFFF);
@ -49,15 +123,12 @@ void render::uninit()
{ {
delete vscreen; delete vscreen;
delete zscreen; delete zscreen;
for (auto sprite : sprite_list)
remove_sprite(sprite, false); // Sprite destructor removes it from the list.
for (auto ball : ball_list) while (!sprite_list.empty())
remove_ball(ball, false); delete sprite_list[0];
for (auto& ballBmp : ball_bitmap) while (!ball_list.empty())
delete ballBmp; delete ball_list[0];
ball_list.clear();
dirty_list.clear();
sprite_list.clear();
DebugOverlay::UnInit(); DebugOverlay::UnInit();
} }
@ -70,36 +141,39 @@ void render::update()
{ {
unpaint_balls(); unpaint_balls();
// Clip dirty sprites with vScreen, clear clipping (dirty) rectangles // Clip dirty sprites with vScreen, clear clipping (dirty) rectangles
for (auto curSprite : dirty_list) for (const auto sprite : sprite_list)
{ {
if (!sprite->DirtyFlag)
continue;
bool clearSprite = false; bool clearSprite = false;
switch (curSprite->VisualType) switch (sprite->VisualType)
{ {
case VisualTypes::Sprite: case VisualTypes::Sprite:
if (curSprite->DirtyRectPrev.Width > 0) if (sprite->DirtyRectPrev.Width > 0)
maths::enclosing_box(curSprite->DirtyRectPrev, curSprite->BmpRect, curSprite->DirtyRect); maths::enclosing_box(sprite->DirtyRectPrev, sprite->BmpRect, sprite->DirtyRect);
if (maths::rectangle_clip(curSprite->DirtyRect, vscreen_rect, &curSprite->DirtyRect)) if (maths::rectangle_clip(sprite->DirtyRect, vscreen_rect, &sprite->DirtyRect))
clearSprite = true; clearSprite = true;
else else
curSprite->DirtyRect.Width = -1; sprite->DirtyRect.Width = -1;
break; break;
case VisualTypes::None: case VisualTypes::Background:
if (maths::rectangle_clip(curSprite->BmpRect, vscreen_rect, &curSprite->DirtyRect)) if (maths::rectangle_clip(sprite->BmpRect, vscreen_rect, &sprite->DirtyRect))
clearSprite = !curSprite->Bmp; clearSprite = !sprite->Bmp;
else else
curSprite->DirtyRect.Width = -1; sprite->DirtyRect.Width = -1;
break; break;
default: break; default: break;
} }
if (clearSprite) if (clearSprite)
{ {
auto yPos = curSprite->DirtyRect.YPosition; auto yPos = sprite->DirtyRect.YPosition;
auto width = curSprite->DirtyRect.Width; auto width = sprite->DirtyRect.Width;
auto xPos = curSprite->DirtyRect.XPosition; auto xPos = sprite->DirtyRect.XPosition;
auto height = curSprite->DirtyRect.Height; auto height = sprite->DirtyRect.Height;
zdrv::fill(zscreen, width, height, xPos, yPos, 0xFFFF); zdrv::fill(zscreen, width, height, xPos, yPos, 0xFFFF);
if (background_bitmap) if (background_bitmap)
gdrv::copy_bitmap(vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos); gdrv::copy_bitmap(vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos);
@ -109,191 +183,60 @@ void render::update()
} }
// Paint dirty rectangles of dirty sprites // Paint dirty rectangles of dirty sprites
for (auto sprite : dirty_list) for (auto sprite : sprite_list)
{ {
if (sprite->DirtyRect.Width > 0 && (sprite->VisualType == VisualTypes::None || sprite->VisualType == if (!sprite->DirtyFlag)
VisualTypes::Sprite)) continue;
repaint(sprite);
repaint(*sprite);
sprite->DirtyFlag = false;
sprite->DirtyRectPrev = sprite->DirtyRect;
if (sprite->DeleteFlag)
delete sprite;
} }
paint_balls(); paint_balls();
// In the original, this used to blit dirty sprites and balls
for (auto sprite : dirty_list)
{
sprite->DirtyRectPrev = sprite->DirtyRect;
if (sprite->UnknownFlag != 0)
remove_sprite(sprite, true);
}
dirty_list.clear();
} }
void render::sprite_modified(render_sprite_type_struct* sprite) void render::AddSprite(render_sprite& sprite)
{ {
if (sprite->VisualType != VisualTypes::Ball && dirty_list.size() < 999) if (!sprite.ZMap && sprite.VisualType != VisualTypes::Ball)
dirty_list.push_back(sprite); {
sprite.ZMap = background_zmap;
sprite.ZMapOffestY = sprite.BmpRect.XPosition - zmap_offsetX;
sprite.ZMapOffestX = sprite.BmpRect.YPosition - zmap_offsetY;
}
auto& list = sprite.VisualType == VisualTypes::Ball ? ball_list : sprite_list;
list.push_back(&sprite);
} }
render_sprite_type_struct* render::create_sprite(VisualTypes visualType, gdrv_bitmap8* bmp, zmap_header_type* zMap, void render::RemoveSprite(render_sprite& sprite)
int xPosition, int yPosition, rectangle_type* rect)
{ {
auto sprite = new render_sprite_type_struct(); auto& list = sprite.VisualType == VisualTypes::Ball ? ball_list : sprite_list;
if (!sprite) auto it = std::find(list.begin(), list.end(), &sprite);
return nullptr; if (it != list.end())
sprite->BmpRect.YPosition = yPosition; list.erase(it);
sprite->BmpRect.XPosition = xPosition;
sprite->Bmp = bmp;
sprite->VisualType = visualType;
sprite->UnknownFlag = 0;
sprite->SpriteArray = nullptr;
sprite->DirtyRect = rectangle_type{};
if (rect)
{
sprite->BoundingRect = *rect;
}
else
{
sprite->BoundingRect.Width = -1;
sprite->BoundingRect.Height = -1;
sprite->BoundingRect.XPosition = 0;
sprite->BoundingRect.YPosition = 0;
}
if (bmp)
{
sprite->BmpRect.Width = bmp->Width;
sprite->BmpRect.Height = bmp->Height;
}
else
{
sprite->BmpRect.Width = 0;
sprite->BmpRect.Height = 0;
}
sprite->ZMap = zMap;
sprite->ZMapOffestX = 0;
sprite->ZMapOffestY = 0;
if (!zMap && visualType != VisualTypes::Ball)
{
sprite->ZMap = background_zmap;
sprite->ZMapOffestY = xPosition - zmap_offset;
sprite->ZMapOffestX = yPosition - zmap_offsetY;
}
sprite->DirtyRectPrev = sprite->BmpRect;
if (visualType == VisualTypes::Ball)
{
ball_list.push_back(sprite);
}
else
{
sprite_list.push_back(sprite);
sprite_modified(sprite);
}
return sprite;
} }
void render::set_background_zmap(zmap_header_type* zMap, int offsetX, int offsetY)
void render::remove_sprite(render_sprite_type_struct* sprite, bool removeFromList)
{
if (removeFromList)
{
auto it = std::find(sprite_list.begin(), sprite_list.end(), sprite);
if (it != sprite_list.end())
sprite_list.erase(it);
}
delete sprite->SpriteArray;
delete sprite;
}
void render::remove_ball(render_sprite_type_struct* ball, bool removeFromList)
{
if (removeFromList)
{
auto it = std::find(ball_list.begin(), ball_list.end(), ball);
if (it != ball_list.end())
ball_list.erase(it);
}
delete ball->SpriteArray;
delete ball;
}
void render::sprite_set(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp, zmap_header_type* zMap, int xPos,
int yPos)
{
if (sprite)
{
sprite->BmpRect.XPosition = xPos;
sprite->BmpRect.YPosition = yPos;
sprite->Bmp = bmp;
if (bmp)
{
sprite->BmpRect.Width = bmp->Width;
sprite->BmpRect.Height = bmp->Height;
}
sprite->ZMap = zMap;
sprite_modified(sprite);
}
}
void render::sprite_set_bitmap(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp)
{
if (sprite && sprite->Bmp != bmp)
{
sprite->Bmp = bmp;
if (bmp)
{
sprite->BmpRect.Width = bmp->Width;
sprite->BmpRect.Height = bmp->Height;
}
sprite_modified(sprite);
}
}
void render::set_background_zmap(struct zmap_header_type* zMap, int offsetX, int offsetY)
{ {
background_zmap = zMap; background_zmap = zMap;
zmap_offset = offsetX; zmap_offsetX = offsetX;
zmap_offsetY = offsetY; zmap_offsetY = offsetY;
} }
void render::ball_set(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp, float depth, int xPos, int yPos) void render::repaint(const render_sprite& sprite)
{
if (sprite)
{
sprite->Bmp = bmp;
if (bmp)
{
sprite->BmpRect.XPosition = xPos;
sprite->BmpRect.YPosition = yPos;
sprite->BmpRect.Width = bmp->Width;
sprite->BmpRect.Height = bmp->Height;
}
if (depth >= zmin)
{
float depth2 = (depth - zmin) * zscaler;
if (depth2 <= zmax)
sprite->Depth = static_cast<short>(depth2);
else
sprite->Depth = -1;
}
else
{
sprite->Depth = 0;
}
}
}
void render::repaint(struct render_sprite_type_struct* sprite)
{ {
rectangle_type clipRect{}; rectangle_type clipRect{};
if (!sprite->SpriteArray) if (!sprite.OccludedSprites || sprite.VisualType == VisualTypes::Ball || sprite.DirtyRect.Width <= 0)
return; return;
for (auto refSprite : *sprite->SpriteArray)
for (auto refSprite : *sprite.OccludedSprites)
{ {
if (!refSprite->UnknownFlag && refSprite->Bmp) if (!refSprite->DeleteFlag && refSprite->Bmp)
{ {
if (maths::rectangle_clip(refSprite->BmpRect, sprite->DirtyRect, &clipRect)) if (maths::rectangle_clip(refSprite->BmpRect, sprite.DirtyRect, &clipRect))
zdrv::paint( zdrv::paint(
clipRect.Width, clipRect.Width,
clipRect.Height, clipRect.Height,
@ -316,20 +259,11 @@ void render::repaint(struct render_sprite_type_struct* sprite)
void render::paint_balls() void render::paint_balls()
{ {
// Sort ball sprites by depth // Sort ball sprites by ascending depth
for (auto i = 0u; i < ball_list.size(); i++) std::sort(ball_list.begin(), ball_list.end(), [](const render_sprite* lhs, const render_sprite* rhs)
{ {
for (auto j = i; j < ball_list.size() / 2; ++j) return lhs->Depth < rhs->Depth;
{ });
auto ballA = ball_list[j];
auto ballB = ball_list[i];
if (ballB->Depth > ballA->Depth)
{
ball_list[i] = ballA;
ball_list[j] = ballB;
}
}
}
// For balls that clip vScreen: save original vScreen contents and paint ball bitmap. // For balls that clip vScreen: save original vScreen contents and paint ball bitmap.
for (auto index = 0u; index < ball_list.size(); ++index) for (auto index = 0u; index < ball_list.size(); ++index)
@ -391,26 +325,25 @@ void render::shift(int offsetX, int offsetY)
void render::build_occlude_list() void render::build_occlude_list()
{ {
std::vector<render_sprite_type_struct*>* spriteArr = nullptr; std::vector<render_sprite*>* spriteArr = nullptr;
for (auto mainSprite : sprite_list) for (auto mainSprite : sprite_list)
{ {
if (mainSprite->SpriteArray) if (mainSprite->OccludedSprites)
{ {
delete mainSprite->SpriteArray; delete mainSprite->OccludedSprites;
mainSprite->SpriteArray = nullptr; mainSprite->OccludedSprites = nullptr;
} }
if (!mainSprite->UnknownFlag && mainSprite->BoundingRect.Width != -1) if (!mainSprite->DeleteFlag && mainSprite->BoundingRect.Width != -1)
{ {
if (!spriteArr) if (!spriteArr)
spriteArr = new std::vector<render_sprite_type_struct*>(); spriteArr = new std::vector<render_sprite*>();
for (auto refSprite : sprite_list) for (auto refSprite : sprite_list)
{ {
if (!refSprite->UnknownFlag if (!refSprite->DeleteFlag
&& refSprite->BoundingRect.Width != -1 && refSprite->BoundingRect.Width != -1
&& maths::rectangle_clip(mainSprite->BoundingRect, refSprite->BoundingRect, nullptr) && maths::rectangle_clip(mainSprite->BoundingRect, refSprite->BoundingRect, nullptr))
&& spriteArr)
{ {
spriteArr->push_back(refSprite); spriteArr->push_back(refSprite);
} }
@ -420,7 +353,7 @@ void render::build_occlude_list()
spriteArr->clear(); spriteArr->clear();
if (!spriteArr->empty()) if (!spriteArr->empty())
{ {
mainSprite->SpriteArray = spriteArr; mainSprite->OccludedSprites = spriteArr;
spriteArr = nullptr; spriteArr = nullptr;
} }
} }

View File

@ -5,25 +5,33 @@
enum class VisualTypes : char enum class VisualTypes : char
{ {
None = 0, Background = 0,
Sprite = 1, Sprite = 1,
Ball = 2 Ball = 2
}; };
struct render_sprite_type_struct struct render_sprite
{ {
rectangle_type BmpRect; rectangle_type BmpRect{};
gdrv_bitmap8* Bmp; gdrv_bitmap8* Bmp;
zmap_header_type* ZMap; zmap_header_type* ZMap;
char UnknownFlag; bool DeleteFlag;
VisualTypes VisualType; VisualTypes VisualType;
int16_t Depth; uint16_t Depth;
rectangle_type DirtyRectPrev; rectangle_type DirtyRectPrev{};
int ZMapOffestY; int ZMapOffestY;
int ZMapOffestX; int ZMapOffestX;
rectangle_type DirtyRect; rectangle_type DirtyRect{};
std::vector<render_sprite_type_struct*>* SpriteArray; std::vector<render_sprite*>* OccludedSprites;
rectangle_type BoundingRect; rectangle_type BoundingRect{};
bool DirtyFlag{};
render_sprite(VisualTypes visualType, gdrv_bitmap8* bmp, zmap_header_type* zMap,
int xPosition, int yPosition, rectangle_type* boundingRect);
~render_sprite();
void set(gdrv_bitmap8* bmp, zmap_header_type* zMap, int xPos, int yPos);
void set_bitmap(gdrv_bitmap8* bmp);
void ball_set(gdrv_bitmap8* bmp, float depth, int xPos, int yPos);
}; };
@ -33,35 +41,26 @@ public:
static gdrv_bitmap8 *vscreen, *background_bitmap; static gdrv_bitmap8 *vscreen, *background_bitmap;
static SDL_Rect DestinationRect; static SDL_Rect DestinationRect;
static void init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height); static void init(gdrv_bitmap8* bmp, int width, int height);
static void uninit(); static void uninit();
static void recreate_screen_texture(); static void recreate_screen_texture();
static void update(); static void update();
static void sprite_modified(render_sprite_type_struct* sprite); static void AddSprite(render_sprite& sprite);
static render_sprite_type_struct* create_sprite(VisualTypes visualType, gdrv_bitmap8* bmp, static void RemoveSprite(render_sprite& sprite);
zmap_header_type* zMap, static void set_background_zmap(zmap_header_type* zMap, int offsetX, int offsetY);
int xPosition, int yPosition, rectangle_type* rect);
static void remove_sprite(render_sprite_type_struct* sprite, bool removeFromList);
static void remove_ball(render_sprite_type_struct* ball, bool removeFromList);
static void sprite_set(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp, zmap_header_type* zMap, int xPos,
int yPos);
static void sprite_set_bitmap(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp);
static void set_background_zmap(struct zmap_header_type* zMap, int offsetX, int offsetY);
static void ball_set(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp, float depth, int xPos, int yPos);
static void shift(int offsetX, int offsetY); static void shift(int offsetX, int offsetY);
static void build_occlude_list(); static void build_occlude_list();
static void SpriteViewer(bool* show); static void SpriteViewer(bool* show);
static void PresentVScreen(); static void PresentVScreen();
private: private:
static std::vector<render_sprite_type_struct*> dirty_list, sprite_list, ball_list; static std::vector<render_sprite*> sprite_list, ball_list;
static zmap_header_type* background_zmap; static zmap_header_type* background_zmap;
static int zmap_offset, zmap_offsetY, offset_x, offset_y; static int zmap_offsetX, zmap_offsetY, offset_x, offset_y;
static float zscaler, zmin, zmax;
static rectangle_type vscreen_rect; static rectangle_type vscreen_rect;
static gdrv_bitmap8 *ball_bitmap[20]; static gdrv_bitmap8 *ball_bitmap[20];
static zmap_header_type* zscreen; static zmap_header_type* zscreen;
static void repaint(struct render_sprite_type_struct* sprite); static void repaint(const render_sprite& sprite);
static void paint_balls(); static void paint_balls();
static void unpaint_balls(); static void unpaint_balls();
}; };