1
0
Fork 0
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:
Muzychenko Andrey 2021-09-25 16:52:19 +03:00
parent 625a6e7498
commit 22ce8ac538
16 changed files with 290 additions and 467 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);
} }

View file

@ -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

View file

@ -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)

View file

@ -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);
}; };

View file

@ -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);
} }

View file

@ -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;

View file

@ -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);
} }

View file

@ -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;

View file

@ -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);

View file

@ -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) for (int index = 0; index < many_dirty; ++index)
{ {
auto curSprite = *dirtyPtr; bool clearSprite = false;
if ((*dirtyPtr)->VisualType != VisualTypes::None) auto curSprite = dirty_list[index];
switch (curSprite->VisualType)
{ {
if ((*dirtyPtr)->VisualType == VisualTypes::Sprite) case VisualTypes::Sprite:
{ if (curSprite->DirtyRectPrev.Width > 0)
if (curSprite->BmpRectCopy.Width > 0) maths::enclosing_box(&curSprite->DirtyRectPrev, &curSprite->BmpRect, &curSprite->DirtyRect);
maths::enclosing_box(&curSprite->BmpRectCopy, &curSprite->BmpRect, &curSprite->DirtyRect);
if (!maths::rectangle_clip(&curSprite->DirtyRect, &vscreen_rect, &curSprite->DirtyRect)) if (maths::rectangle_clip(&curSprite->DirtyRect, &vscreen_rect, &curSprite->DirtyRect))
{ clearSprite = true;
curSprite->DirtyRect.Width = -1; else
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; curSprite->DirtyRect.Width = -1;
continue; break;
} case VisualTypes::None:
if (!curSprite->Bmp) if (maths::rectangle_clip(&curSprite->BmpRect, &vscreen_rect, &curSprite->DirtyRect))
{ clearSprite = !curSprite->Bmp;
auto yPos = curSprite->DirtyRect.YPosition; else
auto width = curSprite->DirtyRect.Width; curSprite->DirtyRect.Width = -1;
auto xPos = curSprite->DirtyRect.XPosition; break;
auto height = curSprite->DirtyRect.Height; default: break;
zdrv::fill(&zscreen, width, height, xPos, yPos, 0xFFFF); }
if (background_bitmap)
gdrv::copy_bitmap(&vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos); if (clearSprite)
else {
gdrv::fill_bitmap(&vscreen, width, height, xPos, yPos, 0); 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; // Paint dirty rectangles of dirty sprites
for (int index = 0; index < many_dirty; ++index) for (int index = 0; index < many_dirty; ++index)
{ {
auto sprite = *dirtyPtr; auto sprite = dirty_list[index];
if ((*dirtyPtr)->DirtyRect.Width > 0 && (sprite->VisualType == VisualTypes::None || sprite->VisualType == 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)
// In the original, this used to blit dirty sprites and balls
for (int index = 0; index < many_dirty; ++index)
{ {
auto xPos = vscreen.XPosition + offset_x; auto sprite = dirty_list[index];
auto yPos = vscreen.YPosition + offset_y; sprite->DirtyRectPrev = sprite->DirtyRect;
dirtyPtr = dirty_list; if (sprite->UnknownFlag != 0)
for (int index = 0; index < many_dirty; ++dirtyPtr, ++index) remove_sprite(sprite);
{
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;
if (sprite->UnknownFlag != 0)
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);
}

View file

@ -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);
}; };

View file

@ -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);
} }
} }

View file

@ -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();

View file

@ -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;