mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-11-24 01:40:18 +01:00
gdrv: blit no more, present render:vScreen directly.
Improved split bitmap handling.
This commit is contained in:
parent
625a6e7498
commit
22ce8ac538
16 changed files with 290 additions and 467 deletions
|
@ -18,16 +18,6 @@ EntryData::~EntryData()
|
||||||
zdrv::destroy_zmap(reinterpret_cast<zmap_header_type*>(Buffer));
|
zdrv::destroy_zmap(reinterpret_cast<zmap_header_type*>(Buffer));
|
||||||
memory::free(Buffer);
|
memory::free(Buffer);
|
||||||
}
|
}
|
||||||
if (DerivedBmp)
|
|
||||||
{
|
|
||||||
gdrv::destroy_bitmap(DerivedBmp);
|
|
||||||
memory::free(DerivedBmp);
|
|
||||||
}
|
|
||||||
if (DerivedZMap)
|
|
||||||
{
|
|
||||||
zdrv::destroy_zmap(DerivedZMap);
|
|
||||||
memory::free(DerivedZMap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,8 +28,7 @@ GroupData::GroupData(int groupId)
|
||||||
|
|
||||||
void GroupData::AddEntry(EntryData* entry)
|
void GroupData::AddEntry(EntryData* entry)
|
||||||
{
|
{
|
||||||
Entries.push_back(entry);
|
auto addEntry = true;
|
||||||
|
|
||||||
switch (entry->EntryType)
|
switch (entry->EntryType)
|
||||||
{
|
{
|
||||||
case FieldTypes::GroupName:
|
case FieldTypes::GroupName:
|
||||||
|
@ -47,21 +36,23 @@ void GroupData::AddEntry(EntryData* entry)
|
||||||
break;
|
break;
|
||||||
case FieldTypes::Bitmap8bit:
|
case FieldTypes::Bitmap8bit:
|
||||||
{
|
{
|
||||||
auto bmp = reinterpret_cast<gdrv_bitmap8*>(entry->Buffer);
|
auto srcBmp = reinterpret_cast<gdrv_bitmap8*>(entry->Buffer);
|
||||||
if (bmp->BitmapType == BitmapTypes::Spliced)
|
if (srcBmp->BitmapType == BitmapTypes::Spliced)
|
||||||
{
|
{
|
||||||
// Get rid of spliced bitmap early on, to simplify render pipeline
|
// Get rid of spliced bitmap early on, to simplify render pipeline
|
||||||
auto splitBmp = memory::allocate<gdrv_bitmap8>();
|
auto bmp = memory::allocate<gdrv_bitmap8>();
|
||||||
auto splitZMap = memory::allocate<zmap_header_type>();
|
auto zMap = memory::allocate<zmap_header_type>();
|
||||||
SplitSplicedBitmap(*bmp, *splitBmp, *splitZMap);
|
SplitSplicedBitmap(*srcBmp, *bmp, *zMap);
|
||||||
entry->DerivedBmp = splitBmp;
|
|
||||||
entry->DerivedZMap = splitZMap;
|
NeedsSort = true;
|
||||||
SetBitmap(splitBmp);
|
addEntry = false;
|
||||||
SetZMap(splitZMap);
|
AddEntry(new EntryData(FieldTypes::Bitmap8bit, reinterpret_cast<char*>(bmp)));
|
||||||
|
AddEntry(new EntryData(FieldTypes::Bitmap16bit, reinterpret_cast<char*>(zMap)));
|
||||||
|
delete entry;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetBitmap(bmp);
|
SetBitmap(srcBmp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +63,24 @@ void GroupData::AddEntry(EntryData* entry)
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addEntry)
|
||||||
|
Entries.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::FinalizeGroup()
|
||||||
|
{
|
||||||
|
if (NeedsSort)
|
||||||
|
{
|
||||||
|
// Entries within a group are sorted by EntryType, in ascending order.
|
||||||
|
// Dat files follow this rule, zMaps inserted in the middle break it.
|
||||||
|
NeedsSort = false;
|
||||||
|
std::sort(Entries.begin(), Entries.end(), [](const EntryData* lhs, const EntryData* rhs)
|
||||||
|
{
|
||||||
|
return lhs->EntryType < rhs->EntryType;
|
||||||
|
});
|
||||||
|
Entries.shrink_to_fit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gdrv_bitmap8* GroupData::GetBitmap(int resolution) const
|
gdrv_bitmap8* GroupData::GetBitmap(int resolution) const
|
||||||
|
|
|
@ -43,12 +43,16 @@ enum class FieldTypes : int16_t
|
||||||
|
|
||||||
struct EntryData
|
struct EntryData
|
||||||
{
|
{
|
||||||
|
EntryData() = default;
|
||||||
|
|
||||||
|
EntryData(FieldTypes entryType, char* buffer): EntryType(entryType), FieldSize(-1), Buffer(buffer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~EntryData();
|
~EntryData();
|
||||||
FieldTypes EntryType{};
|
FieldTypes EntryType{};
|
||||||
int FieldSize{};
|
int FieldSize{};
|
||||||
char* Buffer{};
|
char* Buffer{};
|
||||||
gdrv_bitmap8* DerivedBmp{};
|
|
||||||
zmap_header_type* DerivedZMap{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GroupData
|
class GroupData
|
||||||
|
@ -59,6 +63,7 @@ public:
|
||||||
|
|
||||||
GroupData(int groupId);
|
GroupData(int groupId);
|
||||||
void AddEntry(EntryData* entry);
|
void AddEntry(EntryData* entry);
|
||||||
|
void FinalizeGroup();
|
||||||
const std::vector<EntryData*>& GetEntries() const { return Entries; }
|
const std::vector<EntryData*>& GetEntries() const { return Entries; }
|
||||||
const EntryData* GetEntry(size_t index) const { return Entries[index]; }
|
const EntryData* GetEntry(size_t index) const { return Entries[index]; }
|
||||||
size_t EntryCount() const { return Entries.size(); }
|
size_t EntryCount() const { return Entries.size(); }
|
||||||
|
@ -70,6 +75,7 @@ private:
|
||||||
std::vector<EntryData*> Entries;
|
std::vector<EntryData*> Entries;
|
||||||
gdrv_bitmap8* Bitmaps[3]{};
|
gdrv_bitmap8* Bitmaps[3]{};
|
||||||
zmap_header_type* ZMaps[3]{};
|
zmap_header_type* ZMaps[3]{};
|
||||||
|
bool NeedsSort = false;
|
||||||
|
|
||||||
static void SplitSplicedBitmap(const gdrv_bitmap8& srcBmp, gdrv_bitmap8& bmp, zmap_header_type& zMap);
|
static void SplitSplicedBitmap(const gdrv_bitmap8& srcBmp, gdrv_bitmap8& bmp, zmap_header_type& zMap);
|
||||||
|
|
||||||
|
|
|
@ -86,14 +86,6 @@ void TTextBox::Clear()
|
||||||
OffsetY);
|
OffsetY);
|
||||||
else
|
else
|
||||||
gdrv::fill_bitmap(&render::vscreen, Width, Height, OffsetX, OffsetY, 0);
|
gdrv::fill_bitmap(&render::vscreen, Width, Height, OffsetX, OffsetY, 0);
|
||||||
gdrv::blit(
|
|
||||||
&render::vscreen,
|
|
||||||
OffsetX,
|
|
||||||
OffsetY,
|
|
||||||
OffsetX + render::vscreen.XPosition,
|
|
||||||
OffsetY + render::vscreen.YPosition,
|
|
||||||
Width,
|
|
||||||
Height);
|
|
||||||
if (Timer)
|
if (Timer)
|
||||||
{
|
{
|
||||||
if (Timer != -1)
|
if (Timer != -1)
|
||||||
|
@ -198,14 +190,6 @@ void TTextBox::Draw()
|
||||||
auto font = Font;
|
auto font = Font;
|
||||||
if (!font)
|
if (!font)
|
||||||
{
|
{
|
||||||
gdrv::blit(
|
|
||||||
&render::vscreen,
|
|
||||||
OffsetX,
|
|
||||||
OffsetY,
|
|
||||||
OffsetX + render::vscreen.XPosition,
|
|
||||||
OffsetY + render::vscreen.YPosition,
|
|
||||||
Width,
|
|
||||||
Height);
|
|
||||||
gdrv::grtext_draw_ttext_in_box(
|
gdrv::grtext_draw_ttext_in_box(
|
||||||
Message1->Text,
|
Message1->Text,
|
||||||
render::vscreen.XPosition + OffsetX,
|
render::vscreen.XPosition + OffsetX,
|
||||||
|
@ -276,13 +260,4 @@ void TTextBox::Draw()
|
||||||
++text;
|
++text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gdrv::blit(
|
|
||||||
&render::vscreen,
|
|
||||||
OffsetX,
|
|
||||||
OffsetY,
|
|
||||||
OffsetX + render::vscreen.XPosition,
|
|
||||||
OffsetY + render::vscreen.YPosition,
|
|
||||||
Width,
|
|
||||||
Height);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ void fullscrn::window_size_changed()
|
||||||
OffsetY = static_cast<int>(floor((height - res->TableHeight * ScaleY) / 2));
|
OffsetY = static_cast<int>(floor((height - res->TableHeight * ScaleY) / 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
gdrv::DestinationRect = SDL_Rect
|
render::DestinationRect = SDL_Rect
|
||||||
{
|
{
|
||||||
OffsetX, OffsetY,
|
OffsetX, OffsetY,
|
||||||
width - OffsetX * 2, height - OffsetY * 2
|
width - OffsetX * 2, height - OffsetY * 2
|
||||||
|
|
|
@ -9,41 +9,7 @@
|
||||||
#include "score.h"
|
#include "score.h"
|
||||||
#include "winmain.h"
|
#include "winmain.h"
|
||||||
|
|
||||||
SDL_Texture* gdrv::vScreenTex = nullptr;
|
|
||||||
ColorRgba* gdrv::vScreenPixels = nullptr;
|
|
||||||
int gdrv::vScreenWidth, gdrv::vScreenHeight;
|
|
||||||
ColorRgba gdrv::current_palette[256]{};
|
ColorRgba gdrv::current_palette[256]{};
|
||||||
SDL_Rect gdrv::DestinationRect{};
|
|
||||||
|
|
||||||
int gdrv::init(int width, int height)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
UsingSdlHint hint{SDL_HINT_RENDER_SCALE_QUALITY, options::Options.LinearFiltering ? "linear" : "nearest"};
|
|
||||||
vScreenTex = SDL_CreateTexture
|
|
||||||
(
|
|
||||||
winmain::Renderer,
|
|
||||||
SDL_PIXELFORMAT_ARGB8888,
|
|
||||||
SDL_TEXTUREACCESS_STREAMING,
|
|
||||||
width, height
|
|
||||||
);
|
|
||||||
}
|
|
||||||
vScreenWidth = width;
|
|
||||||
vScreenHeight = height;
|
|
||||||
vScreenPixels = new ColorRgba[width * height];
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gdrv::uninit()
|
|
||||||
{
|
|
||||||
SDL_DestroyTexture(vScreenTex);
|
|
||||||
delete[] vScreenPixels;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdrv::get_focus()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int gdrv::create_bitmap(gdrv_bitmap8* bmp, int width, int height, int stride, bool indexed)
|
int gdrv::create_bitmap(gdrv_bitmap8* bmp, int width, int height, int stride, bool indexed)
|
||||||
{
|
{
|
||||||
|
@ -122,23 +88,23 @@ int gdrv::display_palette(ColorRgba* plt)
|
||||||
{
|
{
|
||||||
const uint32_t sysPaletteColors[]
|
const uint32_t sysPaletteColors[]
|
||||||
{
|
{
|
||||||
0x00000000, // Color 0: transparent
|
0xff000000, // Color 0: transparent
|
||||||
0x00000080,
|
0xff000080,
|
||||||
0x00008000,
|
0xff008000,
|
||||||
0x00008080,
|
0xff008080,
|
||||||
0x00800000,
|
0xff800000,
|
||||||
0x00800080,
|
0xff800080,
|
||||||
0x00808000,
|
0xff808000,
|
||||||
0x00C0C0C0,
|
0xffC0C0C0,
|
||||||
0x00C0DCC0,
|
0xffC0DCC0,
|
||||||
0x00F0CAA6
|
0xffF0CAA6
|
||||||
};
|
};
|
||||||
|
|
||||||
memcpy(current_palette, sysPaletteColors, sizeof sysPaletteColors);
|
memcpy(current_palette, sysPaletteColors, sizeof sysPaletteColors);
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
current_palette[i].rgba.peFlags = 0;
|
current_palette[i].rgba.Alpha = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pltSrc = &plt[10];
|
auto pltSrc = &plt[10];
|
||||||
|
@ -147,18 +113,16 @@ int gdrv::display_palette(ColorRgba* plt)
|
||||||
{
|
{
|
||||||
if (plt)
|
if (plt)
|
||||||
{
|
{
|
||||||
pltDst->rgba.peRed = pltSrc->rgba.peRed;
|
pltDst->rgba.Blue = pltSrc->rgba.Blue;
|
||||||
pltDst->rgba.peGreen = pltSrc->rgba.peGreen;
|
pltDst->rgba.Green = pltSrc->rgba.Green;
|
||||||
pltDst->rgba.peBlue = pltSrc->rgba.peBlue;
|
pltDst->rgba.Red = pltSrc->rgba.Red;
|
||||||
}
|
}
|
||||||
pltDst->rgba.peFlags = 4;
|
pltDst->rgba.Alpha = 0xFF;
|
||||||
pltSrc++;
|
pltSrc++;
|
||||||
pltDst++;
|
pltDst++;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_palette[255].rgba.peBlue = -1;
|
current_palette[255].Color = 0xffFFFFFF;
|
||||||
current_palette[255].rgba.peGreen = -1;
|
|
||||||
current_palette[255].rgba.peRed = -1;
|
|
||||||
|
|
||||||
score::ApplyPalette();
|
score::ApplyPalette();
|
||||||
for (const auto group : pb::record_table->Groups)
|
for (const auto group : pb::record_table->Groups)
|
||||||
|
@ -194,32 +158,6 @@ int gdrv::destroy_bitmap(gdrv_bitmap8* bmp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrc, int xDest, int yDest, int width, int height)
|
|
||||||
{
|
|
||||||
StretchDIBitsScaled(
|
|
||||||
xSrc,
|
|
||||||
ySrc,
|
|
||||||
xDest,
|
|
||||||
yDest,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
bmp
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdrv::blat(gdrv_bitmap8* bmp, int xDest, int yDest)
|
|
||||||
{
|
|
||||||
StretchDIBitsScaled(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
xDest,
|
|
||||||
yDest,
|
|
||||||
bmp->Width,
|
|
||||||
bmp->Height,
|
|
||||||
bmp
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar)
|
void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar)
|
||||||
{
|
{
|
||||||
auto color = current_palette[fillChar];
|
auto color = current_palette[fillChar];
|
||||||
|
@ -272,64 +210,6 @@ void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int gdrv::StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
|
|
||||||
int width, int height, gdrv_bitmap8* bmp)
|
|
||||||
{
|
|
||||||
// Negative dst == positive src offset
|
|
||||||
if (xDst < 0)
|
|
||||||
{
|
|
||||||
xSrc -= xDst;
|
|
||||||
xDst = 0;
|
|
||||||
}
|
|
||||||
if (yDst < 0)
|
|
||||||
{
|
|
||||||
ySrc -= yDst;
|
|
||||||
yDst = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clamp out of bounds rectangles
|
|
||||||
xSrc = std::max(0, std::min(xSrc, bmp->Width));
|
|
||||||
ySrc = std::max(0, std::min(ySrc, bmp->Height));
|
|
||||||
if (xSrc + width > bmp->Width)
|
|
||||||
width = bmp->Width - xSrc;
|
|
||||||
if (ySrc + height > bmp->Height)
|
|
||||||
height = bmp->Height - ySrc;
|
|
||||||
|
|
||||||
xDst = std::max(0, std::min(xDst, vScreenWidth));
|
|
||||||
yDst = std::max(0, std::min(yDst, vScreenHeight));
|
|
||||||
if (xDst + width > vScreenWidth)
|
|
||||||
width = vScreenWidth - xDst;
|
|
||||||
if (yDst + height > vScreenHeight)
|
|
||||||
height = vScreenHeight - yDst;
|
|
||||||
|
|
||||||
auto srcPtr = &bmp->BmpBufPtr1[bmp->Stride * ySrc + xSrc];
|
|
||||||
auto dstPtr = &vScreenPixels[vScreenWidth * yDst + xDst];
|
|
||||||
for (int y = height; y > 0; --y)
|
|
||||||
{
|
|
||||||
std::memcpy(dstPtr, srcPtr, width * sizeof(ColorRgba));
|
|
||||||
srcPtr += bmp->Stride;
|
|
||||||
dstPtr += vScreenWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdrv::BlitScreen()
|
|
||||||
{
|
|
||||||
int pitch = 0;
|
|
||||||
void* lockedPixels;
|
|
||||||
SDL_LockTexture
|
|
||||||
(
|
|
||||||
vScreenTex,
|
|
||||||
nullptr,
|
|
||||||
&lockedPixels,
|
|
||||||
&pitch
|
|
||||||
);
|
|
||||||
std::memcpy(lockedPixels, vScreenPixels, vScreenWidth * vScreenHeight * sizeof(ColorRgba));
|
|
||||||
SDL_UnlockTexture(vScreenTex);
|
|
||||||
SDL_RenderCopy(winmain::Renderer, vScreenTex, nullptr, &DestinationRect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdrv::ApplyPalette(gdrv_bitmap8& bmp)
|
void gdrv::ApplyPalette(gdrv_bitmap8& bmp)
|
||||||
{
|
{
|
||||||
if (bmp.BitmapType == BitmapTypes::None)
|
if (bmp.BitmapType == BitmapTypes::None)
|
||||||
|
|
|
@ -11,10 +11,10 @@ enum class BitmapTypes : uint8_t
|
||||||
|
|
||||||
struct Rgba
|
struct Rgba
|
||||||
{
|
{
|
||||||
uint8_t peRed;
|
uint8_t Blue;
|
||||||
uint8_t peGreen;
|
uint8_t Green;
|
||||||
uint8_t peBlue;
|
uint8_t Red;
|
||||||
uint8_t peFlags;
|
uint8_t Alpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
union ColorRgba
|
union ColorRgba
|
||||||
|
@ -57,32 +57,18 @@ struct gdrv_bitmap8
|
||||||
class gdrv
|
class gdrv
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static SDL_Rect DestinationRect;
|
|
||||||
|
|
||||||
static int init(int width, int height);
|
|
||||||
static int uninit();
|
|
||||||
static void get_focus();
|
|
||||||
static int create_bitmap(gdrv_bitmap8* bmp, int width, int height, int stride = -1, bool indexed = true);
|
static int create_bitmap(gdrv_bitmap8* bmp, int width, int height, int stride = -1, bool indexed = true);
|
||||||
static int create_bitmap(gdrv_bitmap8& bmp, const struct dat8BitBmpHeader& header);
|
static int create_bitmap(gdrv_bitmap8& bmp, const struct dat8BitBmpHeader& header);
|
||||||
static int destroy_bitmap(gdrv_bitmap8* bmp);
|
static int destroy_bitmap(gdrv_bitmap8* bmp);
|
||||||
static int display_palette(ColorRgba* plt);
|
static int display_palette(ColorRgba* plt);
|
||||||
static void blit(gdrv_bitmap8* bmp, int xSrc, int ySrc, int xDest, int yDest, int width, int height);
|
|
||||||
static void blat(gdrv_bitmap8* bmp, int xDest, int yDest);
|
|
||||||
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar);
|
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar);
|
||||||
static void copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
|
static void copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
|
||||||
int srcXOff, int srcYOff);
|
int srcXOff, int srcYOff);
|
||||||
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
|
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
|
||||||
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff);
|
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff);
|
||||||
static void grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6);
|
static void grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6);
|
||||||
static void BlitScreen();
|
|
||||||
static void ApplyPalette(gdrv_bitmap8& bmp);
|
static void ApplyPalette(gdrv_bitmap8& bmp);
|
||||||
static void CreatePreview(gdrv_bitmap8& bmp);
|
static void CreatePreview(gdrv_bitmap8& bmp);
|
||||||
private:
|
private:
|
||||||
static SDL_Texture* vScreenTex;
|
|
||||||
static ColorRgba* vScreenPixels;
|
|
||||||
static int vScreenWidth, vScreenHeight;
|
|
||||||
static ColorRgba current_palette[256];
|
static ColorRgba current_palette[256];
|
||||||
|
|
||||||
static int StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
|
|
||||||
int width, int height, gdrv_bitmap8* bmp);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -68,7 +68,6 @@ void nudge::_nudge(float xDiff, float yDiff)
|
||||||
vector_type accelMod;
|
vector_type accelMod;
|
||||||
float invAccelX, invAccelY;
|
float invAccelX, invAccelY;
|
||||||
|
|
||||||
auto table = pb::MainTable;
|
|
||||||
auto ballList = pb::MainTable->BallList;
|
auto ballList = pb::MainTable->BallList;
|
||||||
accelMod.X = xDiff * 0.5f;
|
accelMod.X = xDiff * 0.5f;
|
||||||
accelMod.Y = yDiff * 0.5f;
|
accelMod.Y = yDiff * 0.5f;
|
||||||
|
@ -91,10 +90,8 @@ void nudge::_nudge(float xDiff, float yDiff)
|
||||||
else
|
else
|
||||||
invAccelY = 1.0f / ball->Acceleration.Y;
|
invAccelY = 1.0f / ball->Acceleration.Y;
|
||||||
ball->InvAcceleration.Y = invAccelY;
|
ball->InvAcceleration.Y = invAccelY;
|
||||||
table = pb::MainTable;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render::shift(static_cast<int>(floor(xDiff + 0.5f)), static_cast<int>(floor(0.5f - yDiff)), 0, 0, table->Width,
|
render::shift(static_cast<int>(floor(xDiff + 0.5f)), static_cast<int>(floor(0.5f - yDiff)));
|
||||||
table->Height);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,7 +217,6 @@ void options::toggle(Menu1 uIDCheckItem)
|
||||||
case Menu1::WindowUniformScale:
|
case Menu1::WindowUniformScale:
|
||||||
Options.UniformScaling ^= true;
|
Options.UniformScaling ^= true;
|
||||||
fullscrn::window_size_changed();
|
fullscrn::window_size_changed();
|
||||||
pb::paint();
|
|
||||||
break;
|
break;
|
||||||
case Menu1::WindowLinearFilter:
|
case Menu1::WindowLinearFilter:
|
||||||
Options.LinearFiltering ^= true;
|
Options.LinearFiltering ^= true;
|
||||||
|
|
|
@ -130,6 +130,7 @@ DatFile* partman::load_records(LPCSTR lpFileName, bool fullTiltMode)
|
||||||
groupData->AddEntry(entryData);
|
groupData->AddEntry(entryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groupData->FinalizeGroup();
|
||||||
datFile->Groups.push_back(groupData);
|
datFile->Groups.push_back(groupData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,6 @@ int pb::init()
|
||||||
zScaler = cameraInfo[2];
|
zScaler = cameraInfo[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
gdrv::init(resInfo->TableWidth, resInfo->TableHeight);
|
|
||||||
render::init(nullptr, zMin, zScaler, resInfo->TableWidth, resInfo->TableHeight);
|
render::init(nullptr, zMin, zScaler, resInfo->TableWidth, resInfo->TableHeight);
|
||||||
gdrv::copy_bitmap(
|
gdrv::copy_bitmap(
|
||||||
&render::vscreen,
|
&render::vscreen,
|
||||||
|
@ -116,7 +115,6 @@ int pb::uninit()
|
||||||
if (MainTable)
|
if (MainTable)
|
||||||
delete MainTable;
|
delete MainTable;
|
||||||
MainTable = nullptr;
|
MainTable = nullptr;
|
||||||
gdrv::get_focus();
|
|
||||||
timer::uninit();
|
timer::uninit();
|
||||||
render::uninit();
|
render::uninit();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -131,14 +129,7 @@ void pb::reset_table()
|
||||||
|
|
||||||
void pb::firsttime_setup()
|
void pb::firsttime_setup()
|
||||||
{
|
{
|
||||||
render::blit = 0;
|
|
||||||
render::update();
|
render::update();
|
||||||
render::blit = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pb::paint()
|
|
||||||
{
|
|
||||||
render::paint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pb::mode_change(int mode)
|
void pb::mode_change(int mode)
|
||||||
|
@ -493,9 +484,6 @@ void pb::keydown(int key)
|
||||||
case 's':
|
case 's':
|
||||||
MainTable->AddScore(static_cast<int>(RandFloat() * 1000000.0f));
|
MainTable->AddScore(static_cast<int>(RandFloat() * 1000000.0f));
|
||||||
break;
|
break;
|
||||||
case SDLK_F11:
|
|
||||||
gdrv::get_focus();
|
|
||||||
break;
|
|
||||||
case SDLK_F12:
|
case SDLK_F12:
|
||||||
MainTable->port_draw();
|
MainTable->port_draw();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -44,7 +44,6 @@ public:
|
||||||
static int uninit();
|
static int uninit();
|
||||||
static void reset_table();
|
static void reset_table();
|
||||||
static void firsttime_setup();
|
static void firsttime_setup();
|
||||||
static void paint();
|
|
||||||
static void mode_change(int mode);
|
static void mode_change(int mode);
|
||||||
static void toggle_demo();
|
static void toggle_demo();
|
||||||
static void replay_level(int demoMode);
|
static void replay_level(int demoMode);
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
|
|
||||||
#include "GroupData.h"
|
#include "GroupData.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "options.h"
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
|
#include "TPinballTable.h"
|
||||||
|
#include "winmain.h"
|
||||||
|
|
||||||
int render::blit = 0;
|
|
||||||
int render::many_dirty, render::many_sprites, render::many_balls;
|
int render::many_dirty, render::many_sprites, render::many_balls;
|
||||||
render_sprite_type_struct **render::dirty_list, **render::sprite_list, **render::ball_list;
|
render_sprite_type_struct **render::dirty_list, **render::sprite_list, **render::ball_list;
|
||||||
zmap_header_type* render::background_zmap;
|
zmap_header_type* render::background_zmap;
|
||||||
|
@ -14,6 +16,8 @@ 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_Texture* render::vScreenTex = nullptr;
|
||||||
|
SDL_Rect render::DestinationRect{};
|
||||||
|
|
||||||
void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height)
|
void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height)
|
||||||
{
|
{
|
||||||
|
@ -41,6 +45,18 @@ void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int h
|
||||||
gdrv::copy_bitmap(&vscreen, width, height, 0, 0, bmp, 0, 0);
|
gdrv::copy_bitmap(&vscreen, width, height, 0, 0, bmp, 0, 0);
|
||||||
else
|
else
|
||||||
gdrv::fill_bitmap(&vscreen, vscreen.Width, vscreen.Height, 0, 0, 0);
|
gdrv::fill_bitmap(&vscreen, vscreen.Width, vscreen.Height, 0, 0, 0);
|
||||||
|
|
||||||
|
{
|
||||||
|
UsingSdlHint hint{SDL_HINT_RENDER_SCALE_QUALITY, options::Options.LinearFiltering ? "linear" : "nearest"};
|
||||||
|
vScreenTex = SDL_CreateTexture
|
||||||
|
(
|
||||||
|
winmain::Renderer,
|
||||||
|
SDL_PIXELFORMAT_ARGB8888,
|
||||||
|
SDL_TEXTUREACCESS_STREAMING,
|
||||||
|
width, height
|
||||||
|
);
|
||||||
|
SDL_SetTextureBlendMode(vScreenTex, SDL_BLENDMODE_NONE);
|
||||||
|
}
|
||||||
--memory::critical_allocation;
|
--memory::critical_allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,154 +76,73 @@ void render::uninit()
|
||||||
many_sprites = 0;
|
many_sprites = 0;
|
||||||
many_dirty = 0;
|
many_dirty = 0;
|
||||||
many_balls = 0;
|
many_balls = 0;
|
||||||
|
SDL_DestroyTexture(vScreenTex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void render::update()
|
void render::update()
|
||||||
{
|
{
|
||||||
rectangle_type overlapRect{};
|
unpaint_balls();
|
||||||
|
|
||||||
auto dirtyPtr = dirty_list;
|
// Clip dirty sprites with vScreen, clear clipping (dirty) rectangles
|
||||||
for (int index = 0; index < many_dirty; ++dirtyPtr, ++index)
|
|
||||||
{
|
|
||||||
auto curSprite = *dirtyPtr;
|
|
||||||
if ((*dirtyPtr)->VisualType != VisualTypes::None)
|
|
||||||
{
|
|
||||||
if ((*dirtyPtr)->VisualType == VisualTypes::Sprite)
|
|
||||||
{
|
|
||||||
if (curSprite->BmpRectCopy.Width > 0)
|
|
||||||
maths::enclosing_box(&curSprite->BmpRectCopy, &curSprite->BmpRect, &curSprite->DirtyRect);
|
|
||||||
|
|
||||||
if (!maths::rectangle_clip(&curSprite->DirtyRect, &vscreen_rect, &curSprite->DirtyRect))
|
|
||||||
{
|
|
||||||
curSprite->DirtyRect.Width = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto yPos = curSprite->DirtyRect.YPosition;
|
|
||||||
auto width = curSprite->DirtyRect.Width;
|
|
||||||
auto xPos = curSprite->DirtyRect.XPosition;
|
|
||||||
auto height = curSprite->DirtyRect.Height;
|
|
||||||
zdrv::fill(&zscreen, width, height, xPos, yPos, 0xFFFF);
|
|
||||||
if (background_bitmap)
|
|
||||||
gdrv::copy_bitmap(&vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos);
|
|
||||||
else
|
|
||||||
gdrv::fill_bitmap(&vscreen, width, height, xPos, yPos, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!maths::rectangle_clip(&curSprite->BmpRect, &vscreen_rect, &curSprite->DirtyRect))
|
|
||||||
{
|
|
||||||
curSprite->DirtyRect.Width = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!curSprite->Bmp)
|
|
||||||
{
|
|
||||||
auto yPos = curSprite->DirtyRect.YPosition;
|
|
||||||
auto width = curSprite->DirtyRect.Width;
|
|
||||||
auto xPos = curSprite->DirtyRect.XPosition;
|
|
||||||
auto height = curSprite->DirtyRect.Height;
|
|
||||||
zdrv::fill(&zscreen, width, height, xPos, yPos, 0xFFFF);
|
|
||||||
if (background_bitmap)
|
|
||||||
gdrv::copy_bitmap(&vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos);
|
|
||||||
else
|
|
||||||
gdrv::fill_bitmap(&vscreen, width, height, xPos, yPos, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyPtr = dirty_list;
|
|
||||||
for (int index = 0; index < many_dirty; ++index)
|
for (int index = 0; index < many_dirty; ++index)
|
||||||
{
|
{
|
||||||
auto sprite = *dirtyPtr;
|
bool clearSprite = false;
|
||||||
if ((*dirtyPtr)->DirtyRect.Width > 0 && (sprite->VisualType == VisualTypes::None || sprite->VisualType ==
|
auto curSprite = dirty_list[index];
|
||||||
|
switch (curSprite->VisualType)
|
||||||
|
{
|
||||||
|
case VisualTypes::Sprite:
|
||||||
|
if (curSprite->DirtyRectPrev.Width > 0)
|
||||||
|
maths::enclosing_box(&curSprite->DirtyRectPrev, &curSprite->BmpRect, &curSprite->DirtyRect);
|
||||||
|
|
||||||
|
if (maths::rectangle_clip(&curSprite->DirtyRect, &vscreen_rect, &curSprite->DirtyRect))
|
||||||
|
clearSprite = true;
|
||||||
|
else
|
||||||
|
curSprite->DirtyRect.Width = -1;
|
||||||
|
break;
|
||||||
|
case VisualTypes::None:
|
||||||
|
if (maths::rectangle_clip(&curSprite->BmpRect, &vscreen_rect, &curSprite->DirtyRect))
|
||||||
|
clearSprite = !curSprite->Bmp;
|
||||||
|
else
|
||||||
|
curSprite->DirtyRect.Width = -1;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clearSprite)
|
||||||
|
{
|
||||||
|
auto yPos = curSprite->DirtyRect.YPosition;
|
||||||
|
auto width = curSprite->DirtyRect.Width;
|
||||||
|
auto xPos = curSprite->DirtyRect.XPosition;
|
||||||
|
auto height = curSprite->DirtyRect.Height;
|
||||||
|
zdrv::fill(&zscreen, width, height, xPos, yPos, 0xFFFF);
|
||||||
|
if (background_bitmap)
|
||||||
|
gdrv::copy_bitmap(&vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos);
|
||||||
|
else
|
||||||
|
gdrv::fill_bitmap(&vscreen, width, height, xPos, yPos, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paint dirty rectangles of dirty sprites
|
||||||
|
for (int index = 0; index < many_dirty; ++index)
|
||||||
|
{
|
||||||
|
auto sprite = dirty_list[index];
|
||||||
|
if (sprite->DirtyRect.Width > 0 && (sprite->VisualType == VisualTypes::None || sprite->VisualType ==
|
||||||
VisualTypes::Sprite))
|
VisualTypes::Sprite))
|
||||||
repaint(*dirtyPtr);
|
repaint(sprite);
|
||||||
++dirtyPtr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
paint_balls();
|
paint_balls();
|
||||||
if (blit)
|
|
||||||
{
|
|
||||||
auto xPos = vscreen.XPosition + offset_x;
|
|
||||||
auto yPos = vscreen.YPosition + offset_y;
|
|
||||||
dirtyPtr = dirty_list;
|
|
||||||
for (int index = 0; index < many_dirty; ++dirtyPtr, ++index)
|
|
||||||
{
|
|
||||||
auto sprite = *dirtyPtr;
|
|
||||||
auto dirtyRect = &(*dirtyPtr)->DirtyRect;
|
|
||||||
auto width2 = (*dirtyPtr)->DirtyRect.Width;
|
|
||||||
if (width2 > 0)
|
|
||||||
gdrv::blit(
|
|
||||||
&vscreen,
|
|
||||||
dirtyRect->XPosition,
|
|
||||||
dirtyRect->YPosition,
|
|
||||||
dirtyRect->XPosition + xPos,
|
|
||||||
dirtyRect->YPosition + yPos,
|
|
||||||
width2,
|
|
||||||
dirtyRect->Height);
|
|
||||||
|
|
||||||
auto rect = &sprite->BmpRectCopy;
|
|
||||||
rect->XPosition = dirtyRect->XPosition;
|
|
||||||
rect->YPosition = dirtyRect->YPosition;
|
|
||||||
rect->Width = dirtyRect->Width;
|
|
||||||
rect->Height = dirtyRect->Height;
|
|
||||||
|
|
||||||
|
// In the original, this used to blit dirty sprites and balls
|
||||||
|
for (int index = 0; index < many_dirty; ++index)
|
||||||
|
{
|
||||||
|
auto sprite = dirty_list[index];
|
||||||
|
sprite->DirtyRectPrev = sprite->DirtyRect;
|
||||||
if (sprite->UnknownFlag != 0)
|
if (sprite->UnknownFlag != 0)
|
||||||
remove_sprite(sprite);
|
remove_sprite(sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
dirtyPtr = ball_list;
|
|
||||||
for (int index = 0; index < many_balls; ++dirtyPtr, ++index)
|
|
||||||
{
|
|
||||||
auto rectCopy = &(*dirtyPtr)->BmpRectCopy;
|
|
||||||
auto dirtyRect = &(*dirtyPtr)->DirtyRect;
|
|
||||||
if (maths::overlapping_box(dirtyRect, rectCopy, &overlapRect) && dirtyRect->Width > 0)
|
|
||||||
{
|
|
||||||
if (overlapRect.Width > 0)
|
|
||||||
gdrv::blit(
|
|
||||||
&vscreen,
|
|
||||||
overlapRect.XPosition,
|
|
||||||
overlapRect.YPosition,
|
|
||||||
overlapRect.XPosition + xPos,
|
|
||||||
overlapRect.YPosition + yPos,
|
|
||||||
overlapRect.Width,
|
|
||||||
overlapRect.Height);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dirtyRect->Width > 0)
|
|
||||||
gdrv::blit(
|
|
||||||
&vscreen,
|
|
||||||
dirtyRect->XPosition,
|
|
||||||
dirtyRect->YPosition,
|
|
||||||
dirtyRect->XPosition + xPos,
|
|
||||||
dirtyRect->YPosition + yPos,
|
|
||||||
dirtyRect->Width,
|
|
||||||
dirtyRect->Height);
|
|
||||||
if (rectCopy->Width > 0)
|
|
||||||
gdrv::blit(
|
|
||||||
&vscreen,
|
|
||||||
rectCopy->XPosition,
|
|
||||||
rectCopy->YPosition,
|
|
||||||
rectCopy->XPosition + xPos,
|
|
||||||
rectCopy->YPosition + yPos,
|
|
||||||
rectCopy->Width,
|
|
||||||
rectCopy->Height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
many_dirty = 0;
|
many_dirty = 0;
|
||||||
unpaint_balls();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void render::paint()
|
|
||||||
{
|
|
||||||
paint_balls();
|
|
||||||
gdrv::blat(&vscreen, vscreen.XPosition, vscreen.YPosition);
|
|
||||||
unpaint_balls();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void render::sprite_modified(render_sprite_type_struct* sprite)
|
void render::sprite_modified(render_sprite_type_struct* sprite)
|
||||||
|
@ -260,7 +195,7 @@ render_sprite_type_struct* render::create_sprite(VisualTypes visualType, gdrv_bi
|
||||||
sprite->ZMapOffestY = xPosition - zmap_offset;
|
sprite->ZMapOffestY = xPosition - zmap_offset;
|
||||||
sprite->ZMapOffestX = yPosition - zmap_offsetY;
|
sprite->ZMapOffestX = yPosition - zmap_offsetY;
|
||||||
}
|
}
|
||||||
sprite->BmpRectCopy = sprite->BmpRect;
|
sprite->DirtyRectPrev = sprite->BmpRect;
|
||||||
if (visualType == VisualTypes::Ball)
|
if (visualType == VisualTypes::Ball)
|
||||||
{
|
{
|
||||||
ball_list[many_balls++] = sprite;
|
ball_list[many_balls++] = sprite;
|
||||||
|
@ -389,10 +324,10 @@ void render::repaint(struct render_sprite_type_struct* sprite)
|
||||||
return;
|
return;
|
||||||
for (int index = 0; index < sprite->SpriteCount; index++)
|
for (int index = 0; index < sprite->SpriteCount; index++)
|
||||||
{
|
{
|
||||||
render_sprite_type_struct* curSprite = sprite->SpriteArray[index];
|
auto refSprite = sprite->SpriteArray[index];
|
||||||
if (!curSprite->UnknownFlag && curSprite->Bmp)
|
if (!refSprite->UnknownFlag && refSprite->Bmp)
|
||||||
{
|
{
|
||||||
if (maths::rectangle_clip(&curSprite->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,
|
||||||
|
@ -402,12 +337,12 @@ void render::repaint(struct render_sprite_type_struct* sprite)
|
||||||
&zscreen,
|
&zscreen,
|
||||||
clipRect.XPosition,
|
clipRect.XPosition,
|
||||||
clipRect.YPosition,
|
clipRect.YPosition,
|
||||||
curSprite->Bmp,
|
refSprite->Bmp,
|
||||||
clipRect.XPosition - curSprite->BmpRect.XPosition,
|
clipRect.XPosition - refSprite->BmpRect.XPosition,
|
||||||
clipRect.YPosition - curSprite->BmpRect.YPosition,
|
clipRect.YPosition - refSprite->BmpRect.YPosition,
|
||||||
curSprite->ZMap,
|
refSprite->ZMap,
|
||||||
clipRect.XPosition + curSprite->ZMapOffestY - curSprite->BmpRect.XPosition,
|
clipRect.XPosition + refSprite->ZMapOffestY - refSprite->BmpRect.XPosition,
|
||||||
clipRect.YPosition + curSprite->ZMapOffestX - curSprite->BmpRect.YPosition);
|
clipRect.YPosition + refSprite->ZMapOffestX - refSprite->BmpRect.YPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,62 +350,55 @@ void render::repaint(struct render_sprite_type_struct* sprite)
|
||||||
|
|
||||||
void render::paint_balls()
|
void render::paint_balls()
|
||||||
{
|
{
|
||||||
int ballCount = many_balls;
|
// Sort ball sprites by depth
|
||||||
if (many_balls > 1)
|
for (auto i = 0; i < many_balls; i++)
|
||||||
{
|
{
|
||||||
for (int index = 0; index < ballCount; index++)
|
for (auto j = i; j < many_balls / 2; ++j)
|
||||||
{
|
{
|
||||||
for (int i = index; i < ballCount / 2; ++i)
|
auto ballA = ball_list[j];
|
||||||
|
auto ballB = ball_list[i];
|
||||||
|
if (ballB->Depth > ballA->Depth)
|
||||||
{
|
{
|
||||||
auto curBall = ball_list[i];
|
ball_list[i] = ballA;
|
||||||
auto firstBallPtr = &ball_list[index];
|
ball_list[j] = ballB;
|
||||||
if ((*firstBallPtr)->Depth > curBall->Depth)
|
|
||||||
{
|
|
||||||
auto firstBall = *firstBallPtr;
|
|
||||||
*firstBallPtr = curBall;
|
|
||||||
ball_list[i] = firstBall;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ballPtr = ball_list;
|
// For balls that clip vScreen: save original vScreen contents and paint ball bitmap.
|
||||||
auto ballBmpPtr = ball_bitmap;
|
for (auto index = 0; index < many_balls; ++index)
|
||||||
for (int index2 = 0; index2 < many_balls; ++index2)
|
|
||||||
{
|
{
|
||||||
struct render_sprite_type_struct* sprite = *ballPtr;
|
auto ball = ball_list[index];
|
||||||
rectangle_type* rect2 = &(*ballPtr)->DirtyRect;
|
auto dirty = &ball->DirtyRect;
|
||||||
if ((*ballPtr)->Bmp && maths::rectangle_clip(&sprite->BmpRect, &vscreen_rect, &(*ballPtr)->DirtyRect))
|
if (ball->Bmp && maths::rectangle_clip(&ball->BmpRect, &vscreen_rect, &ball->DirtyRect))
|
||||||
{
|
{
|
||||||
int xPos = rect2->XPosition;
|
int xPos = dirty->XPosition;
|
||||||
int yPos = rect2->YPosition;
|
int yPos = dirty->YPosition;
|
||||||
gdrv::copy_bitmap(ballBmpPtr, rect2->Width, rect2->Height, 0, 0, &vscreen, xPos, yPos);
|
gdrv::copy_bitmap(&ball_bitmap[index], dirty->Width, dirty->Height, 0, 0, &vscreen, xPos, yPos);
|
||||||
zdrv::paint_flat(
|
zdrv::paint_flat(
|
||||||
rect2->Width,
|
dirty->Width,
|
||||||
rect2->Height,
|
dirty->Height,
|
||||||
&vscreen,
|
&vscreen,
|
||||||
xPos,
|
xPos,
|
||||||
yPos,
|
yPos,
|
||||||
&zscreen,
|
&zscreen,
|
||||||
xPos,
|
xPos,
|
||||||
yPos,
|
yPos,
|
||||||
sprite->Bmp,
|
ball->Bmp,
|
||||||
xPos - sprite->BmpRect.XPosition,
|
xPos - ball->BmpRect.XPosition,
|
||||||
yPos - sprite->BmpRect.YPosition,
|
yPos - ball->BmpRect.YPosition,
|
||||||
sprite->Depth);
|
ball->Depth);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rect2->Width = -1;
|
dirty->Width = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
++ballBmpPtr;
|
|
||||||
++ballPtr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void render::unpaint_balls()
|
void render::unpaint_balls()
|
||||||
{
|
{
|
||||||
|
// Restore portions of vScreen saved during previous paint_balls call.
|
||||||
for (int index = many_balls - 1; index >= 0; index--)
|
for (int index = many_balls - 1; index >= 0; index--)
|
||||||
{
|
{
|
||||||
auto curBall = ball_list[index];
|
auto curBall = ball_list[index];
|
||||||
|
@ -485,63 +413,54 @@ void render::unpaint_balls()
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
curBall->BmpRectCopy = curBall->DirtyRect;
|
curBall->DirtyRectPrev = curBall->DirtyRect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void render::shift(int offsetX, int offsetY, int xSrc, int ySrc, int DestWidth, int DestHeight)
|
void render::shift(int offsetX, int offsetY)
|
||||||
{
|
{
|
||||||
offset_x += offsetX;
|
offset_x += offsetX;
|
||||||
offset_y += offsetY;
|
offset_y += offsetY;
|
||||||
paint_balls();
|
|
||||||
gdrv::blit(
|
|
||||||
&vscreen,
|
|
||||||
xSrc,
|
|
||||||
ySrc,
|
|
||||||
xSrc + offset_x + vscreen.XPosition,
|
|
||||||
ySrc + offset_y + vscreen.YPosition,
|
|
||||||
DestWidth,
|
|
||||||
DestHeight);
|
|
||||||
unpaint_balls();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void render::build_occlude_list()
|
void render::build_occlude_list()
|
||||||
{
|
{
|
||||||
++memory::critical_allocation;
|
++memory::critical_allocation;
|
||||||
render_sprite_type_struct** spriteArr = nullptr;
|
render_sprite_type_struct** spriteArr = nullptr;
|
||||||
auto spritePtr1 = sprite_list;
|
for (int index = 0; index < many_sprites; ++index)
|
||||||
for (int index = 0; index < many_sprites; ++index, ++spritePtr1)
|
|
||||||
{
|
{
|
||||||
auto curSprite = *spritePtr1;
|
auto mainSprite = sprite_list[index];
|
||||||
if ((*spritePtr1)->SpriteArray)
|
if (mainSprite->SpriteArray)
|
||||||
{
|
{
|
||||||
memory::free((*spritePtr1)->SpriteArray);
|
memory::free(mainSprite->SpriteArray);
|
||||||
curSprite->SpriteArray = nullptr;
|
mainSprite->SpriteArray = nullptr;
|
||||||
curSprite->SpriteCount = 0;
|
mainSprite->SpriteCount = 0;
|
||||||
}
|
}
|
||||||
if (!curSprite->UnknownFlag && curSprite->BoundingRect.Width != -1)
|
|
||||||
|
if (!mainSprite->UnknownFlag && mainSprite->BoundingRect.Width != -1)
|
||||||
{
|
{
|
||||||
if (!spriteArr)
|
if (!spriteArr)
|
||||||
spriteArr = memory::allocate<render_sprite_type_struct*>(1000);
|
spriteArr = memory::allocate<render_sprite_type_struct*>(1000);
|
||||||
|
|
||||||
int occludeCount = 0;
|
int occludeCount = 0;
|
||||||
auto spritePtr2 = sprite_list;
|
for (int i = 0; i < many_sprites; ++i)
|
||||||
for (int i = 0; i < many_sprites; ++i, ++spritePtr2)
|
|
||||||
{
|
{
|
||||||
auto sprite = *spritePtr2;
|
auto refSprite = sprite_list[i];
|
||||||
if (!sprite->UnknownFlag
|
if (!refSprite->UnknownFlag
|
||||||
&& sprite->BoundingRect.Width != -1
|
&& refSprite->BoundingRect.Width != -1
|
||||||
&& maths::rectangle_clip(&curSprite->BoundingRect, &sprite->BoundingRect, nullptr)
|
&& maths::rectangle_clip(&mainSprite->BoundingRect, &refSprite->BoundingRect, nullptr)
|
||||||
&& spriteArr)
|
&& spriteArr)
|
||||||
{
|
{
|
||||||
spriteArr[occludeCount++] = sprite;
|
spriteArr[occludeCount++] = refSprite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!curSprite->UnknownFlag && curSprite->Bmp && occludeCount < 2)
|
|
||||||
|
if (!mainSprite->UnknownFlag && mainSprite->Bmp && occludeCount < 2)
|
||||||
occludeCount = 0;
|
occludeCount = 0;
|
||||||
if (occludeCount)
|
if (occludeCount)
|
||||||
{
|
{
|
||||||
curSprite->SpriteArray = memory::realloc(spriteArr, sizeof(void*) * occludeCount);
|
mainSprite->SpriteArray = memory::realloc(spriteArr, sizeof(void*) * occludeCount);
|
||||||
curSprite->SpriteCount = occludeCount;
|
mainSprite->SpriteCount = occludeCount;
|
||||||
spriteArr = nullptr;
|
spriteArr = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -644,3 +563,81 @@ void render::SpriteViewer(bool* show)
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void render::BlitVScreen()
|
||||||
|
{
|
||||||
|
int pitch = 0;
|
||||||
|
ColorRgba* lockedPixels;
|
||||||
|
SDL_LockTexture
|
||||||
|
(
|
||||||
|
vScreenTex,
|
||||||
|
nullptr,
|
||||||
|
reinterpret_cast<void**>(&lockedPixels),
|
||||||
|
&pitch
|
||||||
|
);
|
||||||
|
assertm(pitch == vscreen.Width * sizeof(ColorRgba), "Padding on vScreen texture");
|
||||||
|
|
||||||
|
if (offset_x == 0 && offset_y == 0)
|
||||||
|
{
|
||||||
|
// No offset - direct copy
|
||||||
|
std::memcpy(lockedPixels, vscreen.BmpBufPtr1, vscreen.Width * vscreen.Height * sizeof(ColorRgba));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Copy offset table and fixed side bar
|
||||||
|
auto tableWidth = pb::MainTable->Width;
|
||||||
|
auto scoreWidth = vscreen.Width - pb::MainTable->Width;
|
||||||
|
auto tableStride = tableWidth * sizeof(ColorRgba);
|
||||||
|
auto scoreStride = scoreWidth * sizeof(ColorRgba);
|
||||||
|
auto srcScorePtr = &vscreen.BmpBufPtr1[tableWidth];
|
||||||
|
|
||||||
|
auto xSrc = 0, ySrc = 0, xDst = offset_x, yDst = offset_y, height = vscreen.Height;
|
||||||
|
|
||||||
|
// Negative dst == positive src offset
|
||||||
|
if (xDst < 0)
|
||||||
|
{
|
||||||
|
xSrc -= xDst;
|
||||||
|
xDst = 0;
|
||||||
|
}
|
||||||
|
if (yDst < 0)
|
||||||
|
{
|
||||||
|
ySrc -= yDst;
|
||||||
|
yDst = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xSrc)
|
||||||
|
{
|
||||||
|
tableStride -= xSrc * sizeof(ColorRgba);
|
||||||
|
}
|
||||||
|
if (xDst)
|
||||||
|
{
|
||||||
|
tableStride -= xDst * sizeof(ColorRgba);
|
||||||
|
tableWidth -= xDst;
|
||||||
|
scoreWidth += xDst;
|
||||||
|
}
|
||||||
|
if (ySrc)
|
||||||
|
height -= ySrc;
|
||||||
|
|
||||||
|
auto srcBmpPtr = &vscreen.BmpBufPtr1[vscreen.Width * ySrc + xSrc];
|
||||||
|
auto dstPtr = &lockedPixels[vscreen.Width * yDst + xDst];
|
||||||
|
for (int y = height; y > 0; --y)
|
||||||
|
{
|
||||||
|
std::memcpy(dstPtr, srcBmpPtr, tableStride);
|
||||||
|
dstPtr += tableWidth;
|
||||||
|
std::memcpy(dstPtr, srcScorePtr, scoreStride);
|
||||||
|
dstPtr += scoreWidth;
|
||||||
|
|
||||||
|
srcBmpPtr += vscreen.Stride;
|
||||||
|
srcScorePtr += vscreen.Stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SDL_UnlockTexture(vScreenTex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void render::PresentVScreen()
|
||||||
|
{
|
||||||
|
BlitVScreen();
|
||||||
|
SDL_RenderCopy(winmain::Renderer, vScreenTex, nullptr, &DestinationRect);
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct render_sprite_type_struct
|
||||||
char UnknownFlag;
|
char UnknownFlag;
|
||||||
VisualTypes VisualType;
|
VisualTypes VisualType;
|
||||||
int16_t Depth;
|
int16_t Depth;
|
||||||
rectangle_type BmpRectCopy;
|
rectangle_type DirtyRectPrev;
|
||||||
int ZMapOffestY;
|
int ZMapOffestY;
|
||||||
int ZMapOffestX;
|
int ZMapOffestX;
|
||||||
rectangle_type DirtyRect;
|
rectangle_type DirtyRect;
|
||||||
|
@ -31,20 +31,12 @@ struct render_sprite_type_struct
|
||||||
class render
|
class render
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static int blit;
|
static gdrv_bitmap8 vscreen, *background_bitmap;
|
||||||
static int many_dirty, many_sprites, many_balls;
|
static SDL_Rect DestinationRect;
|
||||||
static render_sprite_type_struct **dirty_list, **sprite_list, **ball_list;
|
|
||||||
static zmap_header_type* background_zmap;
|
|
||||||
static int zmap_offset, zmap_offsetY, offset_x, offset_y;
|
|
||||||
static float zscaler, zmin, zmax;
|
|
||||||
static rectangle_type vscreen_rect;
|
|
||||||
static gdrv_bitmap8 vscreen, *background_bitmap, ball_bitmap[20];
|
|
||||||
static zmap_header_type zscreen;
|
|
||||||
|
|
||||||
static void init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height);
|
static void init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height);
|
||||||
static void uninit();
|
static void uninit();
|
||||||
static void update();
|
static void update();
|
||||||
static void paint();
|
|
||||||
static void sprite_modified(render_sprite_type_struct* sprite);
|
static void sprite_modified(render_sprite_type_struct* sprite);
|
||||||
static render_sprite_type_struct* create_sprite(VisualTypes visualType, gdrv_bitmap8* bmp,
|
static render_sprite_type_struct* create_sprite(VisualTypes visualType, gdrv_bitmap8* bmp,
|
||||||
zmap_header_type* zMap,
|
zmap_header_type* zMap,
|
||||||
|
@ -56,10 +48,23 @@ public:
|
||||||
static void sprite_set_bitmap(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp);
|
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 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 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 build_occlude_list();
|
||||||
|
static void SpriteViewer(bool* show);
|
||||||
|
static void PresentVScreen();
|
||||||
|
private:
|
||||||
|
static int many_dirty, many_sprites, many_balls;
|
||||||
|
static render_sprite_type_struct **dirty_list, **sprite_list, **ball_list;
|
||||||
|
static zmap_header_type* background_zmap;
|
||||||
|
static int zmap_offset, zmap_offsetY, offset_x, offset_y;
|
||||||
|
static float zscaler, zmin, zmax;
|
||||||
|
static rectangle_type vscreen_rect;
|
||||||
|
static gdrv_bitmap8 ball_bitmap[20];
|
||||||
|
static zmap_header_type zscreen;
|
||||||
|
static SDL_Texture* vScreenTex;
|
||||||
|
|
||||||
static void repaint(struct render_sprite_type_struct* sprite);
|
static void repaint(struct render_sprite_type_struct* sprite);
|
||||||
static void paint_balls();
|
static void paint_balls();
|
||||||
static void unpaint_balls();
|
static void unpaint_balls();
|
||||||
static void shift(int offsetX, int offsetY, int xSrc, int ySrc, int DestWidth, int DestHeight);
|
static void BlitVScreen();
|
||||||
static void build_occlude_list();
|
|
||||||
static void SpriteViewer(bool* show);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -208,15 +208,6 @@ void score::erase(scoreStruct* score, int blitFlag)
|
||||||
score->OffsetY);
|
score->OffsetY);
|
||||||
else
|
else
|
||||||
gdrv::fill_bitmap(&render::vscreen, score->Width, score->Height, score->OffsetX, score->OffsetY, 0);
|
gdrv::fill_bitmap(&render::vscreen, score->Width, score->Height, score->OffsetX, score->OffsetY, 0);
|
||||||
if (blitFlag)
|
|
||||||
gdrv::blit(
|
|
||||||
&render::vscreen,
|
|
||||||
score->OffsetX,
|
|
||||||
score->OffsetY,
|
|
||||||
score->OffsetX + render::vscreen.XPosition,
|
|
||||||
score->OffsetY + render::vscreen.YPosition,
|
|
||||||
score->Width,
|
|
||||||
score->Height);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,14 +247,6 @@ void score::update(scoreStruct* score)
|
||||||
gdrv::copy_bitmap(&render::vscreen, width, height, x, y, bmp, 0, 0);
|
gdrv::copy_bitmap(&render::vscreen, width, height, x, y, bmp, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gdrv::blit(
|
|
||||||
&render::vscreen,
|
|
||||||
score->OffsetX,
|
|
||||||
score->OffsetY,
|
|
||||||
score->OffsetX + render::vscreen.XPosition,
|
|
||||||
score->OffsetY + render::vscreen.YPosition,
|
|
||||||
score->Width,
|
|
||||||
score->Height);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
||||||
gdrv::create_bitmap(&gfr_display, 400, 15, 400, false);
|
gdrv::create_bitmap(&gfr_display, 400, 15, 400, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
gdrv::blit(&gfr_display, 0, 0, 0, 30, 300, 10);
|
gdrv::copy_bitmap(&render::vscreen, 300, 10, 0, 30, &gfr_display, 0, 0);
|
||||||
gdrv::fill_bitmap(&gfr_display, 300, 10, 0, 0, 0);
|
gdrv::fill_bitmap(&gfr_display, 300, 10, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,7 +284,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
||||||
RenderUi();
|
RenderUi();
|
||||||
|
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
gdrv::BlitScreen();
|
render::PresentVScreen();
|
||||||
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
ImGuiSDL::Render(ImGui::GetDrawData());
|
ImGuiSDL::Render(ImGui::GetDrawData());
|
||||||
|
@ -307,7 +307,6 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
||||||
midi::music_shutdown();
|
midi::music_shutdown();
|
||||||
pb::uninit();
|
pb::uninit();
|
||||||
Sound::Close();
|
Sound::Close();
|
||||||
gdrv::uninit();
|
|
||||||
ImGuiSDL::Deinitialize();
|
ImGuiSDL::Deinitialize();
|
||||||
ImGui_ImplSDL2_Shutdown();
|
ImGui_ImplSDL2_Shutdown();
|
||||||
SDL_DestroyRenderer(renderer);
|
SDL_DestroyRenderer(renderer);
|
||||||
|
@ -649,8 +648,6 @@ int winmain::event_handler(const SDL_Event* event)
|
||||||
midi::play_pb_theme(0);
|
midi::play_pb_theme(0);
|
||||||
no_time_loss = 1;
|
no_time_loss = 1;
|
||||||
has_focus = 1;
|
has_focus = 1;
|
||||||
gdrv::get_focus();
|
|
||||||
pb::paint();
|
|
||||||
break;
|
break;
|
||||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||||
case SDL_WINDOWEVENT_HIDDEN:
|
case SDL_WINDOWEVENT_HIDDEN:
|
||||||
|
@ -660,7 +657,6 @@ int winmain::event_handler(const SDL_Event* event)
|
||||||
Sound::Deactivate();
|
Sound::Deactivate();
|
||||||
midi::music_stop();
|
midi::music_stop();
|
||||||
has_focus = 0;
|
has_focus = 0;
|
||||||
gdrv::get_focus();
|
|
||||||
pb::loose_focus();
|
pb::loose_focus();
|
||||||
break;
|
break;
|
||||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||||
|
@ -698,7 +694,6 @@ void winmain::memalloc_failure()
|
||||||
{
|
{
|
||||||
midi::music_stop();
|
midi::music_stop();
|
||||||
Sound::Close();
|
Sound::Close();
|
||||||
gdrv::uninit();
|
|
||||||
char* caption = pinball::get_rc_string(170, 0);
|
char* caption = pinball::get_rc_string(170, 0);
|
||||||
char* text = pinball::get_rc_string(179, 0);
|
char* text = pinball::get_rc_string(179, 0);
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, caption, text, MainWindow);
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, caption, text, MainWindow);
|
||||||
|
@ -723,7 +718,10 @@ void winmain::a_dialog()
|
||||||
ImGui::TextUnformatted("Decompiled -> Ported to SDL");
|
ImGui::TextUnformatted("Decompiled -> Ported to SDL");
|
||||||
if (ImGui::SmallButton("Project home: https://github.com/k4zmu2a/SpaceCadetPinball"))
|
if (ImGui::SmallButton("Project home: https://github.com/k4zmu2a/SpaceCadetPinball"))
|
||||||
{
|
{
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||||
|
// Relatively new feature, skip with older SDL
|
||||||
SDL_OpenURL("https://github.com/k4zmu2a/SpaceCadetPinball");
|
SDL_OpenURL("https://github.com/k4zmu2a/SpaceCadetPinball");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
|
|
@ -127,9 +127,9 @@ void zdrv::CreatePreview(zmap_header_type& zMap)
|
||||||
for (auto x = 0; x < zMap.Width; x++)
|
for (auto x = 0; x < zMap.Width; x++)
|
||||||
{
|
{
|
||||||
auto depth = static_cast<uint8_t>((0xffff - *src++) / 0xff);
|
auto depth = static_cast<uint8_t>((0xffff - *src++) / 0xff);
|
||||||
color.rgba.peRed = depth;
|
color.rgba.Blue = depth;
|
||||||
color.rgba.peGreen = depth;
|
color.rgba.Green = depth;
|
||||||
color.rgba.peBlue = depth;
|
color.rgba.Red = depth;
|
||||||
*dst++ = color;
|
*dst++ = color;
|
||||||
}
|
}
|
||||||
src += zMap.Stride - zMap.Width;
|
src += zMap.Stride - zMap.Width;
|
||||||
|
|
Loading…
Reference in a new issue