mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-11-27 19:10:18 +01:00
gdrv: RGBA buffers, pre-applied palettes, SDL bitmap origin.
Refactored partman. Added sprite viewer.
This commit is contained in:
parent
8bae7a5b05
commit
c63c6701ac
28 changed files with 901 additions and 564 deletions
|
@ -32,6 +32,8 @@ set(SOURCE_FILES
|
||||||
SpaceCadetPinball/fullscrn.h
|
SpaceCadetPinball/fullscrn.h
|
||||||
SpaceCadetPinball/gdrv.cpp
|
SpaceCadetPinball/gdrv.cpp
|
||||||
SpaceCadetPinball/gdrv.h
|
SpaceCadetPinball/gdrv.h
|
||||||
|
SpaceCadetPinball/GroupData.cpp
|
||||||
|
SpaceCadetPinball/GroupData.h
|
||||||
SpaceCadetPinball/high_score.cpp
|
SpaceCadetPinball/high_score.cpp
|
||||||
SpaceCadetPinball/high_score.h
|
SpaceCadetPinball/high_score.h
|
||||||
SpaceCadetPinball/loader.cpp
|
SpaceCadetPinball/loader.cpp
|
||||||
|
|
268
SpaceCadetPinball/GroupData.cpp
Normal file
268
SpaceCadetPinball/GroupData.cpp
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "GroupData.h"
|
||||||
|
|
||||||
|
#include "fullscrn.h"
|
||||||
|
#include "gdrv.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "zdrv.h"
|
||||||
|
|
||||||
|
|
||||||
|
EntryData::~EntryData()
|
||||||
|
{
|
||||||
|
if (Buffer)
|
||||||
|
{
|
||||||
|
if (EntryType == FieldTypes::Bitmap8bit)
|
||||||
|
gdrv::destroy_bitmap(reinterpret_cast<gdrv_bitmap8*>(Buffer));
|
||||||
|
else if (EntryType == FieldTypes::Bitmap16bit)
|
||||||
|
zdrv::destroy_zmap(reinterpret_cast<zmap_header_type*>(Buffer));
|
||||||
|
memory::free(Buffer);
|
||||||
|
}
|
||||||
|
if (DerivedBmp)
|
||||||
|
{
|
||||||
|
gdrv::destroy_bitmap(DerivedBmp);
|
||||||
|
memory::free(DerivedBmp);
|
||||||
|
}
|
||||||
|
if (DerivedZMap)
|
||||||
|
{
|
||||||
|
zdrv::destroy_zmap(DerivedZMap);
|
||||||
|
memory::free(DerivedZMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GroupData::GroupData(int groupId)
|
||||||
|
{
|
||||||
|
GroupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::AddEntry(EntryData* entry)
|
||||||
|
{
|
||||||
|
Entries.push_back(entry);
|
||||||
|
|
||||||
|
switch (entry->EntryType)
|
||||||
|
{
|
||||||
|
case FieldTypes::GroupName:
|
||||||
|
GroupName = entry->Buffer;
|
||||||
|
break;
|
||||||
|
case FieldTypes::Bitmap8bit:
|
||||||
|
{
|
||||||
|
auto bmp = reinterpret_cast<gdrv_bitmap8*>(entry->Buffer);
|
||||||
|
if (bmp->BitmapType == BitmapTypes::Spliced)
|
||||||
|
{
|
||||||
|
// Get rid of spliced bitmap early on, to simplify render pipeline
|
||||||
|
auto splitBmp = memory::allocate<gdrv_bitmap8>();
|
||||||
|
auto splitZMap = memory::allocate<zmap_header_type>();
|
||||||
|
SplitSplicedBitmap(*bmp, *splitBmp, *splitZMap);
|
||||||
|
entry->DerivedBmp = splitBmp;
|
||||||
|
entry->DerivedZMap = splitZMap;
|
||||||
|
SetBitmap(splitBmp);
|
||||||
|
SetZMap(splitZMap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetBitmap(bmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FieldTypes::Bitmap16bit:
|
||||||
|
{
|
||||||
|
SetZMap(reinterpret_cast<zmap_header_type*>(entry->Buffer));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdrv_bitmap8* GroupData::GetBitmap(int resolution) const
|
||||||
|
{
|
||||||
|
return Bitmaps[resolution];
|
||||||
|
}
|
||||||
|
|
||||||
|
zmap_header_type* GroupData::GetZMap(int resolution) const
|
||||||
|
{
|
||||||
|
return ZMaps[resolution];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::SplitSplicedBitmap(const gdrv_bitmap8& srcBmp, gdrv_bitmap8& bmp, zmap_header_type& zMap)
|
||||||
|
{
|
||||||
|
assertm(srcBmp.BitmapType == BitmapTypes::Spliced, "GroupData: wrong bitmap type");
|
||||||
|
|
||||||
|
gdrv::create_bitmap(&bmp, srcBmp.Width, srcBmp.Height, srcBmp.Width);
|
||||||
|
std::memset(bmp.IndexedBmpPtr, 0xff, bmp.Stride * bmp.Height);
|
||||||
|
bmp.XPosition = srcBmp.XPosition;
|
||||||
|
bmp.YPosition = srcBmp.YPosition;
|
||||||
|
bmp.Resolution = srcBmp.Resolution;
|
||||||
|
|
||||||
|
zdrv::create_zmap(&zMap, srcBmp.Width, srcBmp.Height, srcBmp.Width);
|
||||||
|
zdrv::fill(&zMap, zMap.Width, zMap.Height, 0, 0, 0xFFFF);
|
||||||
|
zMap.Resolution = srcBmp.Resolution;
|
||||||
|
|
||||||
|
auto tableWidth = fullscrn::resolution_array[srcBmp.Resolution].TableWidth;
|
||||||
|
auto src = reinterpret_cast<uint16_t*>(srcBmp.IndexedBmpPtr);
|
||||||
|
auto srcChar = reinterpret_cast<char**>(&src);
|
||||||
|
for (int dstInd = 0;;)
|
||||||
|
{
|
||||||
|
auto stride = static_cast<int16_t>(*src++);
|
||||||
|
if (stride < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Stride is in terms of dst stride, hardcoded to match vScreen width in current resolution
|
||||||
|
if (stride > bmp.Width)
|
||||||
|
{
|
||||||
|
stride += bmp.Width - tableWidth;
|
||||||
|
assertm(stride >= 0, "Spliced bitmap: negative computed stride");
|
||||||
|
}
|
||||||
|
|
||||||
|
dstInd += stride;
|
||||||
|
for (auto count = *src++; count; count--)
|
||||||
|
{
|
||||||
|
auto depth = *src++;
|
||||||
|
bmp.IndexedBmpPtr[dstInd] = **srcChar;
|
||||||
|
zMap.ZPtr1[dstInd] = depth;
|
||||||
|
|
||||||
|
(*srcChar)++;
|
||||||
|
dstInd++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::SetBitmap(gdrv_bitmap8* bmp)
|
||||||
|
{
|
||||||
|
assertm(Bitmaps[bmp->Resolution] == nullptr, "GroupData: bitmap override");
|
||||||
|
Bitmaps[bmp->Resolution] = bmp;
|
||||||
|
|
||||||
|
auto zMap = ZMaps[bmp->Resolution];
|
||||||
|
if (zMap)
|
||||||
|
{
|
||||||
|
assertm(bmp->Width == zMap->Width && bmp->Height == zMap->Height,
|
||||||
|
"GroupData: mismatched bitmap/zMap dimensions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupData::SetZMap(zmap_header_type* zMap)
|
||||||
|
{
|
||||||
|
// Flip zMap to match with flipped non-indexed bitmaps
|
||||||
|
zdrv::FlipZMapHorizontally(*zMap);
|
||||||
|
|
||||||
|
assertm(ZMaps[zMap->Resolution] == nullptr, "GroupData: zMap override");
|
||||||
|
ZMaps[zMap->Resolution] = zMap;
|
||||||
|
|
||||||
|
auto bmp = Bitmaps[zMap->Resolution];
|
||||||
|
if (bmp)
|
||||||
|
{
|
||||||
|
assertm(bmp->Width == zMap->Width && bmp->Height == zMap->Height,
|
||||||
|
"GroupData: mismatched bitmap/zMap dimensions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DatFile::~DatFile()
|
||||||
|
{
|
||||||
|
for (auto group : Groups)
|
||||||
|
{
|
||||||
|
if (!group)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const auto entry : group->GetEntries())
|
||||||
|
{
|
||||||
|
delete entry;
|
||||||
|
}
|
||||||
|
delete group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* DatFile::field(int groupIndex, FieldTypes targetEntryType)
|
||||||
|
{
|
||||||
|
assertm(targetEntryType != FieldTypes::Bitmap8bit && targetEntryType != FieldTypes::Bitmap16bit,
|
||||||
|
"partman: Use specific get for bitmaps");
|
||||||
|
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
for (const auto entry : group->GetEntries())
|
||||||
|
{
|
||||||
|
if (entry->EntryType == targetEntryType)
|
||||||
|
{
|
||||||
|
return entry->Buffer;
|
||||||
|
}
|
||||||
|
if (entry->EntryType > targetEntryType)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* DatFile::field_nth(int groupIndex, FieldTypes targetEntryType, int skipFirstN)
|
||||||
|
{
|
||||||
|
assertm(targetEntryType != FieldTypes::Bitmap8bit && targetEntryType != FieldTypes::Bitmap16bit,
|
||||||
|
"partman: Use specific get for bitmaps");
|
||||||
|
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
auto skipCount = 0;
|
||||||
|
for (const auto entry : group->GetEntries())
|
||||||
|
{
|
||||||
|
if (entry->EntryType > targetEntryType)
|
||||||
|
break;
|
||||||
|
if (entry->EntryType == targetEntryType)
|
||||||
|
if (skipCount++ == skipFirstN)
|
||||||
|
return entry->Buffer;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DatFile::field_size_nth(int groupIndex, FieldTypes targetEntryType, int skipFirstN)
|
||||||
|
{
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
auto skipCount = 0;
|
||||||
|
for (const auto entry : group->GetEntries())
|
||||||
|
{
|
||||||
|
if (entry->EntryType > targetEntryType)
|
||||||
|
return 0;
|
||||||
|
if (entry->EntryType == targetEntryType)
|
||||||
|
if (skipCount++ == skipFirstN)
|
||||||
|
return entry->FieldSize;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DatFile::field_size(int groupIndex, FieldTypes targetEntryType)
|
||||||
|
{
|
||||||
|
return field_size_nth(groupIndex, targetEntryType, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DatFile::record_labeled(LPCSTR targetGroupName)
|
||||||
|
{
|
||||||
|
auto targetLength = strlen(targetGroupName);
|
||||||
|
for (int groupIndex = Groups.size() - 1; groupIndex >= 0; --groupIndex)
|
||||||
|
{
|
||||||
|
auto groupName = field(groupIndex, FieldTypes::GroupName);
|
||||||
|
if (!groupName)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
for (index = 0; index < targetLength; index++)
|
||||||
|
if (targetGroupName[index] != groupName[index])
|
||||||
|
break;
|
||||||
|
if (index == targetLength && !targetGroupName[index] && !groupName[index])
|
||||||
|
return groupIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* DatFile::field_labeled(LPCSTR lpString, FieldTypes fieldType)
|
||||||
|
{
|
||||||
|
auto groupIndex = record_labeled(lpString);
|
||||||
|
return groupIndex < 0 ? nullptr : field(groupIndex, fieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdrv_bitmap8* DatFile::GetBitmap(int groupIndex)
|
||||||
|
{
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
return group->GetBitmap(fullscrn::GetResolution());
|
||||||
|
}
|
||||||
|
|
||||||
|
zmap_header_type* DatFile::GetZMap(int groupIndex)
|
||||||
|
{
|
||||||
|
auto group = Groups[groupIndex];
|
||||||
|
return group->GetZMap(fullscrn::GetResolution());
|
||||||
|
}
|
97
SpaceCadetPinball/GroupData.h
Normal file
97
SpaceCadetPinball/GroupData.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct zmap_header_type;
|
||||||
|
struct gdrv_bitmap8;
|
||||||
|
|
||||||
|
|
||||||
|
enum class FieldTypes : int16_t
|
||||||
|
{
|
||||||
|
// One 16 bit signed integer
|
||||||
|
ShortValue = 0,
|
||||||
|
|
||||||
|
// Sprite bitmap, 8bpp, indexed color
|
||||||
|
Bitmap8bit = 1,
|
||||||
|
|
||||||
|
Unknown2 = 2,
|
||||||
|
|
||||||
|
// Group name, char[]. Not all groups have names.
|
||||||
|
GroupName = 3,
|
||||||
|
|
||||||
|
Unknown4 = 4,
|
||||||
|
|
||||||
|
// Palette, contains 256 RBGA 4-byte colors.
|
||||||
|
Palette = 5,
|
||||||
|
|
||||||
|
Unknown6 = 6,
|
||||||
|
|
||||||
|
Unknown7 = 7,
|
||||||
|
|
||||||
|
Unknown8 = 8,
|
||||||
|
|
||||||
|
// String, char[]
|
||||||
|
String = 9,
|
||||||
|
|
||||||
|
// Array of 16 bit signed integers
|
||||||
|
ShortArray = 10,
|
||||||
|
|
||||||
|
// Array of 32 bit floats
|
||||||
|
FloatArray = 11,
|
||||||
|
|
||||||
|
// Sprite depth map, 16bpp, unsigned
|
||||||
|
Bitmap16bit = 12,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntryData
|
||||||
|
{
|
||||||
|
~EntryData();
|
||||||
|
FieldTypes EntryType{};
|
||||||
|
int FieldSize{};
|
||||||
|
char* Buffer{};
|
||||||
|
gdrv_bitmap8* DerivedBmp{};
|
||||||
|
zmap_header_type* DerivedZMap{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class GroupData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int GroupId;
|
||||||
|
std::string GroupName;
|
||||||
|
|
||||||
|
GroupData(int groupId);
|
||||||
|
void AddEntry(EntryData* entry);
|
||||||
|
const std::vector<EntryData*>& GetEntries() const { return Entries; }
|
||||||
|
const EntryData* GetEntry(size_t index) const { return Entries[index]; }
|
||||||
|
size_t EntryCount() const { return Entries.size(); }
|
||||||
|
void ReserveEntries(size_t count) { Entries.reserve(count); }
|
||||||
|
gdrv_bitmap8* GetBitmap(int resolution) const;
|
||||||
|
zmap_header_type* GetZMap(int resolution) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<EntryData*> Entries;
|
||||||
|
gdrv_bitmap8* Bitmaps[3]{};
|
||||||
|
zmap_header_type* ZMaps[3]{};
|
||||||
|
|
||||||
|
static void SplitSplicedBitmap(const gdrv_bitmap8& srcBmp, gdrv_bitmap8& bmp, zmap_header_type& zMap);
|
||||||
|
|
||||||
|
void SetBitmap(gdrv_bitmap8* bmp);
|
||||||
|
void SetZMap(zmap_header_type* zMap);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DatFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string AppName;
|
||||||
|
std::string Description;
|
||||||
|
std::vector<GroupData*> Groups;
|
||||||
|
|
||||||
|
~DatFile();
|
||||||
|
char* field_nth(int groupIndex, FieldTypes targetEntryType, int skipFirstN);
|
||||||
|
char* field(int groupIndex, FieldTypes entryType);
|
||||||
|
int field_size_nth(int groupIndex, FieldTypes targetEntryType, int skipFirstN);
|
||||||
|
int field_size(int groupIndex, FieldTypes targetEntryType);
|
||||||
|
int record_labeled(LPCSTR targetGroupName);
|
||||||
|
char* field_labeled(LPCSTR lpString, FieldTypes fieldType);
|
||||||
|
gdrv_bitmap8* GetBitmap(int groupIndex);
|
||||||
|
zmap_header_type* GetZMap(int groupIndex);
|
||||||
|
};
|
|
@ -3,15 +3,6 @@
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
#include "objlist_class.h"
|
|
||||||
#include "partman.h"
|
|
||||||
#include "gdrv.h"
|
|
||||||
#include "loader.h"
|
|
||||||
#include "pb.h"
|
|
||||||
#include "pinball.h"
|
|
||||||
#include "score.h"
|
|
||||||
#include "TPinballTable.h"
|
|
||||||
#include "TTextBox.h"
|
|
||||||
#include "winmain.h"
|
#include "winmain.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
|
@ -24,57 +15,6 @@ int main(int argc, char* argv[])
|
||||||
winmain::WinMain(cmdLine.c_str());
|
winmain::WinMain(cmdLine.c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Hello World!\n";
|
|
||||||
gdrv::init(0,0);
|
|
||||||
|
|
||||||
auto d = objlist_class<void>(2, 4);
|
|
||||||
for (size_t i = 0; i < 100; i++)
|
|
||||||
{
|
|
||||||
d.Add((void*)i);
|
|
||||||
}
|
|
||||||
d.Delete((void*)3);
|
|
||||||
|
|
||||||
auto xx = sizeof(datFileHeader);
|
|
||||||
|
|
||||||
winmain::DatFileName = "PINBALL.DAT";
|
|
||||||
pb::init();
|
|
||||||
auto datFile = pb::record_table;
|
|
||||||
|
|
||||||
assert(partman::field_size_nth(datFile, 0, datFieldTypes::String, 0) == 43);
|
|
||||||
assert(partman::field_size_nth(datFile, 2, datFieldTypes::Palette, 0) == 1024);
|
|
||||||
assert(partman::field_size_nth(datFile, 101, datFieldTypes::FloatArray, 4) == 32);
|
|
||||||
|
|
||||||
assert(strcmp(partman::field(datFile, 0, datFieldTypes::String), "3D-Pinball: Copyright 1994, Cinematronics") == 0);
|
|
||||||
assert(strcmp(partman::field(datFile, 540, datFieldTypes::GroupName), "table_objects") == 0);
|
|
||||||
|
|
||||||
assert(partman::record_labeled(datFile, "background") == 2);
|
|
||||||
assert(partman::record_labeled(datFile, "a_bump1") == 372);
|
|
||||||
|
|
||||||
assert(memcmp(partman::field_labeled(datFile, "table_size", datFieldTypes::ShortArray), new short[2]{ 600, 416 }, 2 * 2) == 0);
|
|
||||||
|
|
||||||
//loader::error(25, 26);
|
|
||||||
loader::get_sound_id(18);
|
|
||||||
visualStruct visual1{};
|
|
||||||
loader::material(96, &visual1);
|
|
||||||
loader::query_visual(283, 0, &visual1);
|
|
||||||
visualKickerStruct kicker1{};
|
|
||||||
loader::kicker(509, &kicker1);
|
|
||||||
|
|
||||||
auto score1 = score::create("score1", nullptr);
|
|
||||||
|
|
||||||
auto pinballTable = pb::MainTable;
|
|
||||||
//pinballTable->find_component(1);
|
|
||||||
|
|
||||||
for (int i = 0; i < 190; i++)
|
|
||||||
{
|
|
||||||
auto rsc = pinball::get_rc_string(i, 0);
|
|
||||||
if (rsc)
|
|
||||||
printf("%d:\t%s\n", i, rsc);
|
|
||||||
}
|
|
||||||
|
|
||||||
//DatParser::Parse(dataFileName);
|
|
||||||
std::cout << "Goodby World!\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
|
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TFlipperEdge.h"
|
#include "TFlipperEdge.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "TPinballTable.h"
|
||||||
|
|
||||||
TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
|
TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "objlist_class.h"
|
#include "objlist_class.h"
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
|
#include "pinball.h"
|
||||||
#include "TBlocker.h"
|
#include "TBlocker.h"
|
||||||
#include "TBumper.h"
|
#include "TBumper.h"
|
||||||
#include "TComponentGroup.h"
|
#include "TComponentGroup.h"
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
#include "TRamp.h"
|
#include "TRamp.h"
|
||||||
#include "TPlunger.h"
|
#include "TPlunger.h"
|
||||||
#include "TWall.h"
|
#include "TWall.h"
|
||||||
|
#include "TTextBox.h"
|
||||||
|
|
||||||
int control::pbctrl_state;
|
int control::pbctrl_state;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "gdrv.h"
|
#include "gdrv.h"
|
||||||
|
|
||||||
|
#include "GroupData.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "partman.h"
|
||||||
|
#include "pb.h"
|
||||||
|
#include "score.h"
|
||||||
#include "winmain.h"
|
#include "winmain.h"
|
||||||
|
|
||||||
SDL_Texture* gdrv::vScreenTex = nullptr;
|
SDL_Texture* gdrv::vScreenTex = nullptr;
|
||||||
char* gdrv::vScreenPixels = nullptr;
|
ColorRgba* gdrv::vScreenPixels = nullptr;
|
||||||
int gdrv::vScreenWidth, gdrv::vScreenHeight;
|
int gdrv::vScreenWidth, gdrv::vScreenHeight;
|
||||||
ColorRgba gdrv::current_palette[256]{};
|
ColorRgba gdrv::current_palette[256]{};
|
||||||
SDL_Rect gdrv::DestinationRect{};
|
SDL_Rect gdrv::DestinationRect{};
|
||||||
|
@ -20,7 +24,7 @@ int gdrv::init(int width, int height)
|
||||||
SDL_TEXTUREACCESS_STREAMING,
|
SDL_TEXTUREACCESS_STREAMING,
|
||||||
width, height
|
width, height
|
||||||
);
|
);
|
||||||
vScreenPixels = memory::allocate(width * height * 4);
|
vScreenPixels = memory::allocate<ColorRgba>(width * height);
|
||||||
vScreenWidth = width;
|
vScreenWidth = width;
|
||||||
vScreenHeight = height;
|
vScreenHeight = height;
|
||||||
|
|
||||||
|
@ -38,53 +42,84 @@ void gdrv::get_focus()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int gdrv::create_bitmap(gdrv_bitmap8* bmp, int width, int height)
|
int gdrv::create_bitmap(gdrv_bitmap8* bmp, int width, int height, int stride, bool indexed)
|
||||||
{
|
{
|
||||||
bmp->Width = width;
|
assertm(width >= 0 && height >= 0, "Negative bitmap8 dimensions");
|
||||||
bmp->Stride = width;
|
|
||||||
if (width % 4)
|
|
||||||
bmp->Stride = 4 - width % 4 + width;
|
|
||||||
|
|
||||||
|
bmp->Width = width;
|
||||||
bmp->Height = height;
|
bmp->Height = height;
|
||||||
|
bmp->Stride = width;
|
||||||
bmp->BitmapType = BitmapTypes::DibBitmap;
|
bmp->BitmapType = BitmapTypes::DibBitmap;
|
||||||
bmp->BmpBufPtr1 = memory::allocate(bmp->Height * bmp->Stride);
|
bmp->Texture = nullptr;
|
||||||
|
|
||||||
|
if (stride >= 0)
|
||||||
|
bmp->IndexedStride = stride;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bmp->IndexedStride = width;
|
||||||
|
if (width % 4)
|
||||||
|
bmp->IndexedStride = width - width % 4 + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexed)
|
||||||
|
bmp->IndexedBmpPtr = memory::allocate(bmp->Height * bmp->IndexedStride);
|
||||||
|
bmp->BmpBufPtr1 = memory::allocate<ColorRgba>(bmp->Height * bmp->Stride);
|
||||||
|
if (bmp->BmpBufPtr1)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gdrv::create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag)
|
int gdrv::create_bitmap(gdrv_bitmap8& bmp, const dat8BitBmpHeader& header)
|
||||||
{
|
{
|
||||||
bmp->Width = width;
|
assertm(header.Width >= 0 && header.Height >= 0, "Negative bitmap8 dimensions");
|
||||||
bmp->Stride = width;
|
|
||||||
if (flag && width % 4)
|
|
||||||
bmp->Stride = width - width % 4 + 4;
|
|
||||||
unsigned int sizeInBytes = height * bmp->Stride;
|
|
||||||
bmp->Height = height;
|
|
||||||
bmp->BitmapType = BitmapTypes::RawBitmap;
|
|
||||||
char* buf = memory::allocate(sizeInBytes);
|
|
||||||
bmp->BmpBufPtr1 = buf;
|
|
||||||
if (!buf)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gdrv::create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size)
|
if (header.IsFlagSet(bmp8Flags::Spliced))
|
||||||
{
|
bmp.BitmapType = BitmapTypes::Spliced;
|
||||||
bmp->Width = width;
|
else if (header.IsFlagSet(bmp8Flags::DibBitmap))
|
||||||
bmp->Stride = width;
|
bmp.BitmapType = BitmapTypes::DibBitmap;
|
||||||
bmp->BitmapType = BitmapTypes::Spliced;
|
else
|
||||||
bmp->Height = height;
|
bmp.BitmapType = BitmapTypes::RawBitmap;
|
||||||
char* buf = memory::allocate(size);
|
|
||||||
bmp->BmpBufPtr1 = buf;
|
bmp.Width = header.Width;
|
||||||
if (!buf)
|
bmp.Stride = header.Width;
|
||||||
return -1;
|
bmp.IndexedStride = header.Width;
|
||||||
|
bmp.Height = header.Height;
|
||||||
|
bmp.XPosition = header.XPosition;
|
||||||
|
bmp.YPosition = header.YPosition;
|
||||||
|
bmp.Resolution = header.Resolution;
|
||||||
|
bmp.Texture = nullptr;
|
||||||
|
|
||||||
|
int sizeInBytes;
|
||||||
|
if (bmp.BitmapType == BitmapTypes::Spliced)
|
||||||
|
{
|
||||||
|
sizeInBytes = header.Size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bmp.BitmapType == BitmapTypes::RawBitmap)
|
||||||
|
assertm(bmp.Width % 4 == 0 || header.IsFlagSet(bmp8Flags::RawBmpUnaligned), "Wrong raw bitmap align flag");
|
||||||
|
if (bmp.Width % 4)
|
||||||
|
bmp.IndexedStride = bmp.Width - bmp.Width % 4 + 4;
|
||||||
|
sizeInBytes = bmp.Height * bmp.IndexedStride;
|
||||||
|
assertm(sizeInBytes == header.Size, "Wrong bitmap8 size");
|
||||||
|
}
|
||||||
|
|
||||||
|
bmp.IndexedBmpPtr = memory::allocate(sizeInBytes);
|
||||||
|
bmp.BmpBufPtr1 = memory::allocate<ColorRgba>(bmp.Stride * bmp.Height);
|
||||||
|
if (bmp.BmpBufPtr1)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gdrv::display_palette(ColorRgba* plt)
|
int gdrv::display_palette(ColorRgba* plt)
|
||||||
{
|
{
|
||||||
const uint32_t sysPaletteColors[]
|
const uint32_t sysPaletteColors[]
|
||||||
{
|
{
|
||||||
0x00000000,
|
0x00000000, // Color 0: transparent
|
||||||
0x00000080,
|
0x00000080,
|
||||||
0x00008000,
|
0x00008000,
|
||||||
0x00008080,
|
0x00008080,
|
||||||
|
@ -122,6 +157,19 @@ int gdrv::display_palette(ColorRgba* plt)
|
||||||
current_palette[255].rgba.peGreen = -1;
|
current_palette[255].rgba.peGreen = -1;
|
||||||
current_palette[255].rgba.peRed = -1;
|
current_palette[255].rgba.peRed = -1;
|
||||||
|
|
||||||
|
score::ApplyPalette();
|
||||||
|
for (const auto group : pb::record_table->Groups)
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= 2; i++)
|
||||||
|
{
|
||||||
|
auto bmp = group->GetBitmap(i);
|
||||||
|
if (bmp)
|
||||||
|
{
|
||||||
|
ApplyPalette(*bmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +182,10 @@ int gdrv::destroy_bitmap(gdrv_bitmap8* bmp)
|
||||||
if (bmp->BitmapType != BitmapTypes::None)
|
if (bmp->BitmapType != BitmapTypes::None)
|
||||||
{
|
{
|
||||||
memory::free(bmp->BmpBufPtr1);
|
memory::free(bmp->BmpBufPtr1);
|
||||||
|
if (bmp->IndexedBmpPtr)
|
||||||
|
memory::free(bmp->IndexedBmpPtr);
|
||||||
|
if (bmp->Texture)
|
||||||
|
SDL_DestroyTexture(bmp->Texture);
|
||||||
}
|
}
|
||||||
memset(bmp, 0, sizeof(gdrv_bitmap8));
|
memset(bmp, 0, sizeof(gdrv_bitmap8));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -151,7 +203,7 @@ void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrc, int xDest, int yDest, int
|
||||||
{
|
{
|
||||||
StretchDIBitsScaled(
|
StretchDIBitsScaled(
|
||||||
xSrc,
|
xSrc,
|
||||||
ySrc ,
|
ySrc,
|
||||||
xDest,
|
xDest,
|
||||||
yDest,
|
yDest,
|
||||||
width,
|
width,
|
||||||
|
@ -173,51 +225,43 @@ void gdrv::blat(gdrv_bitmap8* bmp, int xDest, int yDest)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, char fillChar)
|
void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar)
|
||||||
{
|
{
|
||||||
int bmpHeight = bmp->Height;
|
auto color = current_palette[fillChar];
|
||||||
if (bmpHeight < 0)
|
auto bmpPtr = &bmp->BmpBufPtr1[bmp->Width * yOff + xOff];
|
||||||
bmpHeight = -bmpHeight;
|
|
||||||
char* bmpPtr = &bmp->BmpBufPtr1[bmp->Width * (bmpHeight - height - yOff) + xOff];
|
|
||||||
for (; height > 0; --height)
|
for (; height > 0; --height)
|
||||||
{
|
{
|
||||||
if (width > 0)
|
for (int x = width; x > 0; --x)
|
||||||
memset(bmpPtr, fillChar, width);
|
*bmpPtr++ = color;
|
||||||
bmpPtr += bmp->Stride;
|
bmpPtr += bmp->Stride - width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdrv::copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
|
void gdrv::copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
|
||||||
int srcXOff, int srcYOff)
|
int srcXOff, int srcYOff)
|
||||||
{
|
{
|
||||||
int dstHeight = abs(dstBmp->Height);
|
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * srcYOff + srcXOff];
|
||||||
int srcHeight = abs(srcBmp->Height);
|
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * yOff + xOff];
|
||||||
char* srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeight - height - srcYOff) + srcXOff];
|
|
||||||
char* dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeight - height - yOff) + xOff];
|
|
||||||
|
|
||||||
for (int y = height; y > 0; --y)
|
for (int y = height; y > 0; --y)
|
||||||
{
|
{
|
||||||
for (int x = width; x > 0; --x)
|
std::memcpy(dstPtr, srcPtr, width * sizeof(ColorRgba));
|
||||||
*dstPtr++ = *srcPtr++;
|
srcPtr += srcBmp->Stride;
|
||||||
|
dstPtr += dstBmp->Stride;
|
||||||
srcPtr += srcBmp->Stride - width;
|
|
||||||
dstPtr += dstBmp->Stride - width;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdrv::copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
|
void gdrv::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)
|
||||||
{
|
{
|
||||||
int dstHeight = abs(dstBmp->Height);
|
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * srcYOff + srcXOff];
|
||||||
int srcHeight = abs(srcBmp->Height);
|
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * yOff + xOff];
|
||||||
char* srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeight - height - srcYOff) + srcXOff];
|
|
||||||
char* dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeight - height - yOff) + xOff];
|
|
||||||
|
|
||||||
for (int y = height; y > 0; --y)
|
for (int y = height; y > 0; --y)
|
||||||
{
|
{
|
||||||
for (int x = width; x > 0; --x)
|
for (int x = width; x > 0; --x)
|
||||||
{
|
{
|
||||||
if (*srcPtr)
|
if ((*srcPtr).Color)
|
||||||
*dstPtr = *srcPtr;
|
*dstPtr = *srcPtr;
|
||||||
++srcPtr;
|
++srcPtr;
|
||||||
++dstPtr;
|
++dstPtr;
|
||||||
|
@ -236,10 +280,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 gdrv::StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
|
||||||
int width, int height, gdrv_bitmap8* bmp)
|
int width, int height, gdrv_bitmap8* bmp)
|
||||||
{
|
{
|
||||||
// Y is inverted, X normal left to right
|
|
||||||
ySrc = std::max(0, std::min(bmp->Height - height, bmp->Height)) - ySrc;
|
|
||||||
yDst = std::max(0, std::min(vScreenHeight - height, vScreenHeight)) - yDst;
|
|
||||||
|
|
||||||
// Negative dst == positive src offset
|
// Negative dst == positive src offset
|
||||||
if (xDst < 0)
|
if (xDst < 0)
|
||||||
{
|
{
|
||||||
|
@ -267,18 +307,13 @@ int gdrv::StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
|
||||||
if (yDst + height > vScreenHeight)
|
if (yDst + height > vScreenHeight)
|
||||||
height = vScreenHeight - yDst;
|
height = vScreenHeight - yDst;
|
||||||
|
|
||||||
auto srcPtr = reinterpret_cast<uint8_t*>(&bmp->BmpBufPtr1[bmp->Stride * ySrc + xSrc]);
|
auto srcPtr = &bmp->BmpBufPtr1[bmp->Stride * ySrc + xSrc];
|
||||||
auto dstPtr = &reinterpret_cast<uint32_t*>(vScreenPixels)[vScreenWidth * yDst + xDst];
|
auto dstPtr = &vScreenPixels[vScreenWidth * yDst + xDst];
|
||||||
for (int y = height; y > 0; --y)
|
for (int y = height; y > 0; --y)
|
||||||
{
|
{
|
||||||
for (int x = width; x > 0; --x)
|
std::memcpy(dstPtr, srcPtr, width * sizeof(ColorRgba));
|
||||||
{
|
srcPtr += bmp->Stride;
|
||||||
|
dstPtr += vScreenWidth;
|
||||||
*dstPtr++ = current_palette[*srcPtr++].Color;
|
|
||||||
}
|
|
||||||
|
|
||||||
srcPtr += bmp->Stride - width;
|
|
||||||
dstPtr += vScreenWidth - width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -297,5 +332,41 @@ void gdrv::BlitScreen()
|
||||||
);
|
);
|
||||||
std::memcpy(lockedPixels, vScreenPixels, vScreenWidth * vScreenHeight * 4);
|
std::memcpy(lockedPixels, vScreenPixels, vScreenWidth * vScreenHeight * 4);
|
||||||
SDL_UnlockTexture(vScreenTex);
|
SDL_UnlockTexture(vScreenTex);
|
||||||
SDL_RenderCopyEx(winmain::Renderer, vScreenTex, nullptr, &DestinationRect, 0, nullptr, SDL_FLIP_VERTICAL);
|
SDL_RenderCopyEx(winmain::Renderer, vScreenTex, nullptr, &DestinationRect, 0, nullptr, SDL_FLIP_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdrv::ApplyPalette(gdrv_bitmap8& bmp)
|
||||||
|
{
|
||||||
|
if (bmp.BitmapType == BitmapTypes::None)
|
||||||
|
return;
|
||||||
|
assertm(bmp.BitmapType != BitmapTypes::Spliced, "gdrv: wrong bitmap type");
|
||||||
|
assertm(bmp.IndexedBmpPtr != nullptr, "gdrv: non-indexed bitmap");
|
||||||
|
|
||||||
|
// Apply palette, flip horizontally
|
||||||
|
auto dst = bmp.BmpBufPtr1;
|
||||||
|
for (auto y = bmp.Height - 1; y >= 0; y--)
|
||||||
|
{
|
||||||
|
auto src = reinterpret_cast<uint8_t*>(bmp.IndexedBmpPtr) + bmp.IndexedStride * y;
|
||||||
|
for (auto x = 0; x < bmp.Width; x++)
|
||||||
|
{
|
||||||
|
*dst++ = current_palette[*src++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdrv::CreatePreview(gdrv_bitmap8& bmp)
|
||||||
|
{
|
||||||
|
if (bmp.Texture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
|
||||||
|
auto texture = SDL_CreateTexture
|
||||||
|
(
|
||||||
|
winmain::Renderer,
|
||||||
|
SDL_PIXELFORMAT_ARGB8888,
|
||||||
|
SDL_TEXTUREACCESS_STATIC,
|
||||||
|
bmp.Width, bmp.Height
|
||||||
|
);
|
||||||
|
SDL_UpdateTexture(texture, nullptr, bmp.BmpBufPtr1, bmp.Width * 4);
|
||||||
|
bmp.Texture = texture;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum class BitmapTypes : char
|
enum class BitmapTypes : uint8_t
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
RawBitmap = 1,
|
RawBitmap = 1,
|
||||||
DibBitmap = 2,
|
DibBitmap = 2,
|
||||||
Spliced = 4,
|
Spliced = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gdrv_bitmap8
|
|
||||||
{
|
|
||||||
char* BmpBufPtr1;
|
|
||||||
int Width;
|
|
||||||
int Height;
|
|
||||||
int Stride;
|
|
||||||
BitmapTypes BitmapType;
|
|
||||||
int XPosition;
|
|
||||||
int YPosition;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Rgba
|
struct Rgba
|
||||||
{
|
{
|
||||||
|
@ -26,13 +16,43 @@ struct Rgba
|
||||||
uint8_t peBlue;
|
uint8_t peBlue;
|
||||||
uint8_t peFlags;
|
uint8_t peFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
union ColorRgba
|
union ColorRgba
|
||||||
{
|
{
|
||||||
|
ColorRgba() = default;
|
||||||
|
|
||||||
|
explicit ColorRgba(uint32_t color)
|
||||||
|
: Color(color)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit ColorRgba(Rgba rgba)
|
||||||
|
: rgba(rgba)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Color;
|
uint32_t Color;
|
||||||
Rgba rgba;
|
Rgba rgba;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(ColorRgba) == 4, "Wrong size of RGBA color");
|
static_assert(sizeof(ColorRgba) == 4, "Wrong size of RGBA color");
|
||||||
|
|
||||||
|
struct gdrv_bitmap8
|
||||||
|
{
|
||||||
|
ColorRgba* BmpBufPtr1;
|
||||||
|
char* IndexedBmpPtr;
|
||||||
|
int Width;
|
||||||
|
int Height;
|
||||||
|
int Stride;
|
||||||
|
int IndexedStride;
|
||||||
|
BitmapTypes BitmapType;
|
||||||
|
int XPosition;
|
||||||
|
int YPosition;
|
||||||
|
unsigned Resolution;
|
||||||
|
//ColorRgba* RgbaBuffer;
|
||||||
|
SDL_Texture* Texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class gdrv
|
class gdrv
|
||||||
{
|
{
|
||||||
|
@ -42,25 +62,26 @@ public:
|
||||||
static int init(int width, int height);
|
static int init(int width, int height);
|
||||||
static int uninit();
|
static int uninit();
|
||||||
static void get_focus();
|
static void get_focus();
|
||||||
static int create_bitmap(gdrv_bitmap8* bmp, int width, int height);
|
static int create_bitmap(gdrv_bitmap8* bmp, int width, int height, int stride = -1, bool indexed = true);
|
||||||
static int create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag);
|
static int create_bitmap(gdrv_bitmap8& bmp, const struct dat8BitBmpHeader& header);
|
||||||
static int create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size);
|
|
||||||
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 start_blit_sequence();
|
static void start_blit_sequence();
|
||||||
static void end_blit_sequence();
|
static void end_blit_sequence();
|
||||||
static void blit(gdrv_bitmap8* bmp, int xSrc, int ySrc, int xDest, int yDest, int width, int height);
|
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 blat(gdrv_bitmap8* bmp, int xDest, int yDest);
|
||||||
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, char 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 BlitScreen();
|
||||||
|
static void ApplyPalette(gdrv_bitmap8& bmp);
|
||||||
|
static void CreatePreview(gdrv_bitmap8& bmp);
|
||||||
private:
|
private:
|
||||||
static SDL_Texture* vScreenTex;
|
static SDL_Texture* vScreenTex;
|
||||||
static char* vScreenPixels;
|
static ColorRgba* vScreenPixels;
|
||||||
static int vScreenWidth, vScreenHeight;
|
static int vScreenWidth, vScreenHeight;
|
||||||
static ColorRgba current_palette[256];
|
static ColorRgba current_palette[256];
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "pinball.h"
|
||||||
|
#include "score.h"
|
||||||
|
|
||||||
int high_score::dlg_enter_name;
|
int high_score::dlg_enter_name;
|
||||||
int high_score::dlg_score;
|
int high_score::dlg_score;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "pinball.h"
|
|
||||||
|
|
||||||
struct high_score_struct
|
struct high_score_struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "partman.h"
|
#include "GroupData.h"
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "pinball.h"
|
#include "pinball.h"
|
||||||
#include "Sound.h"
|
#include "Sound.h"
|
||||||
|
@ -42,8 +42,8 @@ errorMsg loader::loader_errors[] =
|
||||||
|
|
||||||
int loader::sound_count = 1;
|
int loader::sound_count = 1;
|
||||||
int loader::loader_sound_count;
|
int loader::loader_sound_count;
|
||||||
datFileStruct* loader::loader_table;
|
DatFile* loader::loader_table;
|
||||||
datFileStruct* loader::sound_record_table;
|
DatFile* loader::sound_record_table;
|
||||||
soundListStruct loader::sound_list[65];
|
soundListStruct loader::sound_list[65];
|
||||||
|
|
||||||
int loader::error(int errorCode, int captionCode)
|
int loader::error(int errorCode, int captionCode)
|
||||||
|
@ -82,14 +82,14 @@ void loader::default_vsi(visualStruct* visual)
|
||||||
visual->SoundIndex4 = 0;
|
visual->SoundIndex4 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loader::loadfrom(datFileStruct* datFile)
|
void loader::loadfrom(DatFile* datFile)
|
||||||
{
|
{
|
||||||
loader_table = datFile;
|
loader_table = datFile;
|
||||||
sound_record_table = loader_table;
|
sound_record_table = loader_table;
|
||||||
|
|
||||||
for (auto groupIndex = 0; groupIndex < datFile->NumberOfGroups; ++groupIndex)
|
for (auto groupIndex = 0; groupIndex < datFile->Groups.size(); ++groupIndex)
|
||||||
{
|
{
|
||||||
auto value = reinterpret_cast<int16_t*>(partman::field(datFile, groupIndex, datFieldTypes::ShortValue));
|
auto value = reinterpret_cast<int16_t*>(datFile->field(groupIndex, FieldTypes::ShortValue));
|
||||||
if (value && *value == 202)
|
if (value && *value == 202)
|
||||||
{
|
{
|
||||||
if (sound_count < 65)
|
if (sound_count < 65)
|
||||||
|
@ -141,14 +141,15 @@ int loader::get_sound_id(int groupIndex)
|
||||||
sound_list[soundIndex].Duration = 0.0;
|
sound_list[soundIndex].Duration = 0.0;
|
||||||
if (soundGroupId > 0 && !pinball::quickFlag)
|
if (soundGroupId > 0 && !pinball::quickFlag)
|
||||||
{
|
{
|
||||||
auto value = reinterpret_cast<int16_t*>(partman::field(loader_table, soundGroupId,
|
auto value = reinterpret_cast<int16_t*>(loader_table->field(soundGroupId,
|
||||||
datFieldTypes::ShortValue));
|
FieldTypes::ShortValue));
|
||||||
if (value && *value == 202)
|
if (value && *value == 202)
|
||||||
{
|
{
|
||||||
std::string fileName = partman::field(loader_table, soundGroupId, datFieldTypes::String);
|
std::string fileName = loader_table->field(soundGroupId, FieldTypes::String);
|
||||||
|
|
||||||
// File name is in lower case, while game data is in upper case.
|
// File name is in lower case, while game data is in upper case.
|
||||||
std::transform(fileName.begin(), fileName.end(), fileName.begin(), [](unsigned char c) { return std::toupper(c); });
|
std::transform(fileName.begin(), fileName.end(), fileName.begin(),
|
||||||
|
[](unsigned char c) { return std::toupper(c); });
|
||||||
if (pb::FullTiltMode)
|
if (pb::FullTiltMode)
|
||||||
{
|
{
|
||||||
// FT sounds are in SOUND subfolder
|
// FT sounds are in SOUND subfolder
|
||||||
|
@ -178,7 +179,7 @@ int loader::get_sound_id(int groupIndex)
|
||||||
|
|
||||||
int loader::query_handle(LPCSTR lpString)
|
int loader::query_handle(LPCSTR lpString)
|
||||||
{
|
{
|
||||||
return partman::record_labeled(loader_table, lpString);
|
return loader_table->record_labeled(lpString);
|
||||||
}
|
}
|
||||||
|
|
||||||
short loader::query_visual_states(int groupIndex)
|
short loader::query_visual_states(int groupIndex)
|
||||||
|
@ -186,7 +187,7 @@ short loader::query_visual_states(int groupIndex)
|
||||||
short result;
|
short result;
|
||||||
if (groupIndex < 0)
|
if (groupIndex < 0)
|
||||||
return error(0, 17);
|
return error(0, 17);
|
||||||
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortArray));
|
auto shortArr = reinterpret_cast<int16_t*>(loader_table->field(groupIndex, FieldTypes::ShortArray));
|
||||||
if (shortArr && *shortArr == 100)
|
if (shortArr && *shortArr == 100)
|
||||||
result = shortArr[1];
|
result = shortArr[1];
|
||||||
else
|
else
|
||||||
|
@ -202,7 +203,7 @@ char* loader::query_name(int groupIndex)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return partman::field(loader_table, groupIndex, datFieldTypes::GroupName);
|
return loader_table->field(groupIndex, FieldTypes::GroupName);
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t* loader::query_iattribute(int groupIndex, int firstValue, int* arraySize)
|
int16_t* loader::query_iattribute(int groupIndex, int firstValue, int* arraySize)
|
||||||
|
@ -215,13 +216,13 @@ int16_t* loader::query_iattribute(int groupIndex, int firstValue, int* arraySize
|
||||||
|
|
||||||
for (auto skipIndex = 0;; ++skipIndex)
|
for (auto skipIndex = 0;; ++skipIndex)
|
||||||
{
|
{
|
||||||
auto shortArr = reinterpret_cast<int16_t*>(partman::field_nth(loader_table, groupIndex,
|
auto shortArr = reinterpret_cast<int16_t*>(loader_table->field_nth(groupIndex,
|
||||||
datFieldTypes::ShortArray, skipIndex));
|
FieldTypes::ShortArray, skipIndex));
|
||||||
if (!shortArr)
|
if (!shortArr)
|
||||||
break;
|
break;
|
||||||
if (*shortArr == firstValue)
|
if (*shortArr == firstValue)
|
||||||
{
|
{
|
||||||
*arraySize = partman::field_size(loader_table, groupIndex, datFieldTypes::ShortArray) / 2 - 1;
|
*arraySize = loader_table->field_size(groupIndex, FieldTypes::ShortArray) / 2 - 1;
|
||||||
return shortArr + 1;
|
return shortArr + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +249,7 @@ float* loader::query_float_attribute(int groupIndex, int groupIndexOffset, int f
|
||||||
|
|
||||||
for (auto skipIndex = 0;; ++skipIndex)
|
for (auto skipIndex = 0;; ++skipIndex)
|
||||||
{
|
{
|
||||||
auto floatArr = reinterpret_cast<float*>(partman::field_nth(loader_table, stateId, datFieldTypes::FloatArray,
|
auto floatArr = reinterpret_cast<float*>(loader_table->field_nth(stateId, FieldTypes::FloatArray,
|
||||||
skipIndex));
|
skipIndex));
|
||||||
if (!floatArr)
|
if (!floatArr)
|
||||||
break;
|
break;
|
||||||
|
@ -277,8 +278,8 @@ float loader::query_float_attribute(int groupIndex, int groupIndexOffset, int fi
|
||||||
|
|
||||||
for (auto skipIndex = 0;; ++skipIndex)
|
for (auto skipIndex = 0;; ++skipIndex)
|
||||||
{
|
{
|
||||||
auto floatArr = reinterpret_cast<float*>(partman::field_nth(loader_table, stateId,
|
auto floatArr = reinterpret_cast<float*>(loader_table->field_nth(stateId,
|
||||||
datFieldTypes::FloatArray, skipIndex));
|
FieldTypes::FloatArray, skipIndex));
|
||||||
if (!floatArr)
|
if (!floatArr)
|
||||||
break;
|
break;
|
||||||
if (static_cast<int16_t>(floor(*floatArr)) == firstValue)
|
if (static_cast<int16_t>(floor(*floatArr)) == firstValue)
|
||||||
|
@ -295,16 +296,16 @@ int loader::material(int groupIndex, visualStruct* visual)
|
||||||
{
|
{
|
||||||
if (groupIndex < 0)
|
if (groupIndex < 0)
|
||||||
return error(0, 21);
|
return error(0, 21);
|
||||||
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
|
auto shortArr = reinterpret_cast<int16_t*>(loader_table->field(groupIndex, FieldTypes::ShortValue));
|
||||||
if (!shortArr)
|
if (!shortArr)
|
||||||
return error(1, 21);
|
return error(1, 21);
|
||||||
if (*shortArr != 300)
|
if (*shortArr != 300)
|
||||||
return error(3, 21);
|
return error(3, 21);
|
||||||
auto floatArr = reinterpret_cast<float*>(partman::field(loader_table, groupIndex, datFieldTypes::FloatArray));
|
auto floatArr = reinterpret_cast<float*>(loader_table->field(groupIndex, FieldTypes::FloatArray));
|
||||||
if (!floatArr)
|
if (!floatArr)
|
||||||
return error(11, 21);
|
return error(11, 21);
|
||||||
|
|
||||||
int floatArrLength = partman::field_size(loader_table, groupIndex, datFieldTypes::FloatArray) / 4;
|
int floatArrLength = loader_table->field_size(groupIndex, FieldTypes::FloatArray) / 4;
|
||||||
for (auto index = 0; index < floatArrLength; index += 2)
|
for (auto index = 0; index < floatArrLength; index += 2)
|
||||||
{
|
{
|
||||||
switch (static_cast<int>(floor(floatArr[index])))
|
switch (static_cast<int>(floor(floatArr[index])))
|
||||||
|
@ -339,7 +340,7 @@ int loader::state_id(int groupIndex, int groupIndexOffset)
|
||||||
auto visualState = query_visual_states(groupIndex);
|
auto visualState = query_visual_states(groupIndex);
|
||||||
if (visualState <= 0)
|
if (visualState <= 0)
|
||||||
return error(12, 24);
|
return error(12, 24);
|
||||||
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
|
auto shortArr = reinterpret_cast<int16_t*>(loader_table->field(groupIndex, FieldTypes::ShortValue));
|
||||||
if (!shortArr)
|
if (!shortArr)
|
||||||
return error(1, 24);
|
return error(1, 24);
|
||||||
if (*shortArr != 200)
|
if (*shortArr != 200)
|
||||||
|
@ -350,7 +351,7 @@ int loader::state_id(int groupIndex, int groupIndexOffset)
|
||||||
return groupIndex;
|
return groupIndex;
|
||||||
|
|
||||||
groupIndex += groupIndexOffset;
|
groupIndex += groupIndexOffset;
|
||||||
shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
|
shortArr = reinterpret_cast<int16_t*>(loader_table->field(groupIndex, FieldTypes::ShortValue));
|
||||||
if (!shortArr)
|
if (!shortArr)
|
||||||
return error(1, 24);
|
return error(1, 24);
|
||||||
if (*shortArr != 201)
|
if (*shortArr != 201)
|
||||||
|
@ -362,15 +363,15 @@ int loader::kicker(int groupIndex, visualKickerStruct* kicker)
|
||||||
{
|
{
|
||||||
if (groupIndex < 0)
|
if (groupIndex < 0)
|
||||||
return error(0, 20);
|
return error(0, 20);
|
||||||
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, groupIndex, datFieldTypes::ShortValue));
|
auto shortArr = reinterpret_cast<int16_t*>(loader_table->field(groupIndex, FieldTypes::ShortValue));
|
||||||
if (!shortArr)
|
if (!shortArr)
|
||||||
return error(1, 20);
|
return error(1, 20);
|
||||||
if (*shortArr != 400)
|
if (*shortArr != 400)
|
||||||
return error(4, 20);
|
return error(4, 20);
|
||||||
auto floatArr = reinterpret_cast<float*>(partman::field(loader_table, groupIndex, datFieldTypes::FloatArray));
|
auto floatArr = reinterpret_cast<float*>(loader_table->field(groupIndex, FieldTypes::FloatArray));
|
||||||
if (!floatArr)
|
if (!floatArr)
|
||||||
return error(11, 20);
|
return error(11, 20);
|
||||||
int floatArrLength = partman::field_size(loader_table, groupIndex, datFieldTypes::FloatArray) / 4;
|
int floatArrLength = loader_table->field_size(groupIndex, FieldTypes::FloatArray) / 4;
|
||||||
if (floatArrLength <= 0)
|
if (floatArrLength <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -421,19 +422,13 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vis
|
||||||
if (stateId < 0)
|
if (stateId < 0)
|
||||||
return error(16, 18);
|
return error(16, 18);
|
||||||
|
|
||||||
visual->Bitmap = reinterpret_cast<gdrv_bitmap8*>(partman::field(loader_table, stateId, datFieldTypes::Bitmap8bit));
|
visual->Bitmap = loader_table->GetBitmap(stateId);
|
||||||
visual->ZMap = reinterpret_cast<zmap_header_type*>(partman::field(loader_table, stateId, datFieldTypes::Bitmap16bit)
|
visual->ZMap = loader_table->GetZMap(stateId);
|
||||||
);
|
|
||||||
if (visual->ZMap)
|
|
||||||
{
|
|
||||||
visual->ZMap->ZPtr1 = visual->ZMap->ZBuffer;
|
|
||||||
visual->ZMap->ZPtr2 = visual->ZMap->ZPtr1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto shortArr = reinterpret_cast<int16_t*>(partman::field(loader_table, stateId, datFieldTypes::ShortArray));
|
auto shortArr = reinterpret_cast<int16_t*>(loader_table->field(stateId, FieldTypes::ShortArray));
|
||||||
if (shortArr)
|
if (shortArr)
|
||||||
{
|
{
|
||||||
unsigned int shortArrSize = partman::field_size(loader_table, stateId, datFieldTypes::ShortArray);
|
unsigned int shortArrSize = loader_table->field_size(stateId, FieldTypes::ShortArray);
|
||||||
for (auto index = 0u; index < shortArrSize / 2;)
|
for (auto index = 0u; index < shortArrSize / 2;)
|
||||||
{
|
{
|
||||||
switch (shortArr[0])
|
switch (shortArr[0])
|
||||||
|
@ -479,13 +474,13 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vis
|
||||||
|
|
||||||
if (!visual->CollisionGroup)
|
if (!visual->CollisionGroup)
|
||||||
visual->CollisionGroup = 1;
|
visual->CollisionGroup = 1;
|
||||||
auto floatArr = reinterpret_cast<float*>(partman::field(loader_table, stateId, datFieldTypes::FloatArray));
|
auto floatArr = reinterpret_cast<float*>(loader_table->field(stateId, FieldTypes::FloatArray));
|
||||||
if (!floatArr)
|
if (!floatArr)
|
||||||
return 0;
|
return 0;
|
||||||
if (*floatArr != 600.0f)
|
if (*floatArr != 600.0f)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
visual->FloatArrCount = partman::field_size(loader_table, stateId, datFieldTypes::FloatArray) / 4 / 2 - 2;
|
visual->FloatArrCount = loader_table->field_size(stateId, FieldTypes::FloatArray) / 4 / 2 - 2;
|
||||||
auto floatVal = static_cast<int>(floor(floatArr[1]) - 1.0f);
|
auto floatVal = static_cast<int>(floor(floatArr[1]) - 1.0f);
|
||||||
switch (floatVal)
|
switch (floatVal)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "zdrv.h"
|
#include "zdrv.h"
|
||||||
|
|
||||||
|
|
||||||
struct datFileStruct;
|
struct DatFile;
|
||||||
|
|
||||||
struct errorMsg
|
struct errorMsg
|
||||||
{
|
{
|
||||||
|
@ -89,7 +89,7 @@ public:
|
||||||
static void default_vsi(visualStruct* visual);
|
static void default_vsi(visualStruct* visual);
|
||||||
static int get_sound_id(int groupIndex);
|
static int get_sound_id(int groupIndex);
|
||||||
static void unload();
|
static void unload();
|
||||||
static void loadfrom(datFileStruct* datFile);
|
static void loadfrom(DatFile* datFile);
|
||||||
static int query_handle(LPCSTR lpString);
|
static int query_handle(LPCSTR lpString);
|
||||||
static short query_visual_states(int groupIndex);
|
static short query_visual_states(int groupIndex);
|
||||||
static int material(int groupIndex, visualStruct* visual);
|
static int material(int groupIndex, visualStruct* visual);
|
||||||
|
@ -101,10 +101,10 @@ public:
|
||||||
static float query_float_attribute(int groupIndex, int groupIndexOffset, int firstValue, float defVal);
|
static float query_float_attribute(int groupIndex, int groupIndexOffset, int firstValue, float defVal);
|
||||||
static int16_t* query_iattribute(int groupIndex, int firstValue, int* arraySize);
|
static int16_t* query_iattribute(int groupIndex, int firstValue, int* arraySize);
|
||||||
static float play_sound(int soundIndex);
|
static float play_sound(int soundIndex);
|
||||||
static datFileStruct* loader_table;
|
static DatFile* loader_table;
|
||||||
private:
|
private:
|
||||||
static errorMsg loader_errors[];
|
static errorMsg loader_errors[];
|
||||||
static datFileStruct* sound_record_table;
|
static DatFile* sound_record_table;
|
||||||
static int sound_count;
|
static int sound_count;
|
||||||
static int loader_sound_count;
|
static int loader_sound_count;
|
||||||
static soundListStruct sound_list[65];
|
static soundListStruct sound_list[65];
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TBall.h"
|
#include "TBall.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "TPinballTable.h"
|
||||||
|
|
||||||
int nudge::nudged_left;
|
int nudge::nudged_left;
|
||||||
int nudge::nudged_right;
|
int nudge::nudged_right;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "midi.h"
|
#include "midi.h"
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
|
#include "pinball.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "Sound.h"
|
#include "Sound.h"
|
||||||
#include "winmain.h"
|
#include "winmain.h"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "pinball.h"
|
#include <map>
|
||||||
|
|
||||||
struct optionsStruct
|
struct optionsStruct
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "partman.h"
|
#include "partman.h"
|
||||||
|
|
||||||
|
#include "fullscrn.h"
|
||||||
#include "gdrv.h"
|
#include "gdrv.h"
|
||||||
|
#include "GroupData.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "zdrv.h"
|
#include "zdrv.h"
|
||||||
|
|
||||||
|
@ -9,7 +12,7 @@ short partman::_field_size[] =
|
||||||
2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0
|
2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool fullTiltMode)
|
DatFile* partman::load_records(LPCSTR lpFileName, bool fullTiltMode)
|
||||||
{
|
{
|
||||||
datFileHeader header{};
|
datFileHeader header{};
|
||||||
dat8BitBmpHeader bmpHeader{};
|
dat8BitBmpHeader bmpHeader{};
|
||||||
|
@ -18,35 +21,23 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
|
||||||
auto fileHandle = fopen(lpFileName, "rb");
|
auto fileHandle = fopen(lpFileName, "rb");
|
||||||
if (fileHandle == nullptr)
|
if (fileHandle == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
fread(&header, 1, sizeof header, fileHandle);
|
fread(&header, 1, sizeof header, fileHandle);
|
||||||
if (strcmp("PARTOUT(4.0)RESOURCE", header.FileSignature) != 0)
|
if (strcmp("PARTOUT(4.0)RESOURCE", header.FileSignature) != 0)
|
||||||
{
|
{
|
||||||
fclose(fileHandle);
|
fclose(fileHandle);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto datFile = memory::allocate<datFileStruct>();
|
|
||||||
|
auto datFile = new DatFile();
|
||||||
if (!datFile)
|
if (!datFile)
|
||||||
{
|
{
|
||||||
fclose(fileHandle);
|
fclose(fileHandle);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (strlen(header.Description) <= 0)
|
|
||||||
{
|
datFile->AppName = header.AppName;
|
||||||
datFile->Description = nullptr;
|
datFile->Description = header.Description;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto lenOfStr = strlen(header.Description);
|
|
||||||
auto descriptionBuf = memory::allocate(lenOfStr + 1);
|
|
||||||
datFile->Description = descriptionBuf;
|
|
||||||
if (!descriptionBuf)
|
|
||||||
{
|
|
||||||
fclose(fileHandle);
|
|
||||||
memory::free(datFile);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
strncpy(descriptionBuf, header.Description, lenOfStr + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (header.Unknown)
|
if (header.Unknown)
|
||||||
{
|
{
|
||||||
|
@ -54,102 +45,75 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
|
||||||
if (!unknownBuf)
|
if (!unknownBuf)
|
||||||
{
|
{
|
||||||
fclose(fileHandle);
|
fclose(fileHandle);
|
||||||
if (datFile->Description)
|
delete datFile;
|
||||||
memory::free(datFile->Description);
|
|
||||||
memory::free(datFile);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
fread(unknownBuf, 1, header.Unknown, fileHandle);
|
fread(unknownBuf, 1, header.Unknown, fileHandle);
|
||||||
memory::free(unknownBuf);
|
memory::free(unknownBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto groupDataBuf = memory::allocate<datGroupData*>(header.NumberOfGroups);
|
datFile->Groups.reserve(header.NumberOfGroups);
|
||||||
datFile->GroupData = groupDataBuf;
|
|
||||||
if (!groupDataBuf)
|
|
||||||
{
|
|
||||||
if (datFile->Description)
|
|
||||||
memory::free(datFile->Description);
|
|
||||||
memory::free(datFile);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool abort = false;
|
bool abort = false;
|
||||||
for (auto groupIndex = 0; !abort && groupIndex < header.NumberOfGroups; ++groupIndex)
|
for (auto groupIndex = 0; !abort && groupIndex < header.NumberOfGroups; ++groupIndex)
|
||||||
{
|
{
|
||||||
auto entryCount = _lread_char(fileHandle);
|
auto entryCount = _lread_char(fileHandle);
|
||||||
auto groupDataSize = entryCount <= 0 ? 0 : entryCount - 1;
|
auto groupData = new GroupData(groupIndex);
|
||||||
auto groupData = memory::allocate<datGroupData>(1, sizeof(datEntryData) * groupDataSize);
|
groupData->ReserveEntries(entryCount);
|
||||||
datFile->GroupData[groupIndex] = groupData;
|
|
||||||
if (!groupData)
|
|
||||||
break;
|
|
||||||
|
|
||||||
groupData->EntryCount = 0;
|
|
||||||
for (auto entryIndex = 0; entryIndex < entryCount; ++entryIndex)
|
for (auto entryIndex = 0; entryIndex < entryCount; ++entryIndex)
|
||||||
{
|
{
|
||||||
auto entryData = &groupData->Entries[groupData->EntryCount];
|
auto entryData = new EntryData();
|
||||||
auto entryType = static_cast<datFieldTypes>(_lread_char(fileHandle));
|
auto entryType = static_cast<FieldTypes>(_lread_char(fileHandle));
|
||||||
entryData->EntryType = entryType;
|
entryData->EntryType = entryType;
|
||||||
|
|
||||||
int fieldSize = _field_size[static_cast<int>(entryType)];
|
int fieldSize = _field_size[static_cast<int>(entryType)];
|
||||||
if (fieldSize < 0)
|
if (fieldSize < 0)
|
||||||
fieldSize = _lread_long(fileHandle);
|
fieldSize = _lread_long(fileHandle);
|
||||||
|
entryData->FieldSize = fieldSize;
|
||||||
|
|
||||||
if (entryType == datFieldTypes::Bitmap8bit)
|
if (entryType == FieldTypes::Bitmap8bit)
|
||||||
{
|
{
|
||||||
fread(&bmpHeader, 1, sizeof(dat8BitBmpHeader), fileHandle);
|
fread(&bmpHeader, 1, sizeof(dat8BitBmpHeader), fileHandle);
|
||||||
if (bmpHeader.Resolution != resolution && bmpHeader.Resolution != -1)
|
assertm(bmpHeader.Size + sizeof(dat8BitBmpHeader) == fieldSize, "partman: Wrong bitmap field size");
|
||||||
{
|
assertm(bmpHeader.Resolution >= 0 && bmpHeader.Resolution <= 2,
|
||||||
fseek(fileHandle, bmpHeader.Size, SEEK_CUR);
|
"partman: bitmap resolution out of bounds");
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bmp = memory::allocate<gdrv_bitmap8>();
|
auto bmp = memory::allocate<gdrv_bitmap8>();
|
||||||
entryData->Buffer = reinterpret_cast<char*>(bmp);
|
entryData->Buffer = reinterpret_cast<char*>(bmp);
|
||||||
if (!bmp)
|
if (!bmp || gdrv::create_bitmap(*bmp, bmpHeader))
|
||||||
{
|
{
|
||||||
abort = true;
|
abort = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int bmpRez;
|
fread(bmp->IndexedBmpPtr, 1, bmpHeader.Size, fileHandle);
|
||||||
if (bmpHeader.IsFlagSet(bmp8Flags::Spliced))
|
|
||||||
bmpRez = gdrv::create_spliced_bitmap(bmp, bmpHeader.Width, bmpHeader.Height, bmpHeader.Size);
|
|
||||||
else if (bmpHeader.IsFlagSet(bmp8Flags::DibBitmap))
|
|
||||||
bmpRez = gdrv::create_bitmap(bmp, bmpHeader.Width, bmpHeader.Height);
|
|
||||||
else
|
|
||||||
bmpRez = gdrv::create_raw_bitmap(bmp, bmpHeader.Width, bmpHeader.Height,
|
|
||||||
bmpHeader.IsFlagSet(bmp8Flags::RawBmpUnaligned));
|
|
||||||
if (bmpRez)
|
|
||||||
{
|
|
||||||
abort = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
fread(bmp->BmpBufPtr1, 1, bmpHeader.Size, fileHandle);
|
else if (entryType == FieldTypes::Bitmap16bit)
|
||||||
bmp->XPosition = bmpHeader.XPosition;
|
|
||||||
bmp->YPosition = bmpHeader.YPosition;
|
|
||||||
}
|
|
||||||
else if (entryType == datFieldTypes::Bitmap16bit)
|
|
||||||
{
|
{
|
||||||
/*Full tilt has extra byte(@0:resolution) in zMap*/
|
/*Full tilt has extra byte(@0:resolution) in zMap*/
|
||||||
|
char zMapResolution = 0;
|
||||||
if (fullTiltMode)
|
if (fullTiltMode)
|
||||||
{
|
{
|
||||||
char zMapResolution = _lread_char(fileHandle);
|
zMapResolution = _lread_char(fileHandle);
|
||||||
fieldSize--;
|
fieldSize--;
|
||||||
if (zMapResolution != resolution && zMapResolution != -1)
|
assertm(zMapResolution >= 0 && zMapResolution <= 2, "partman: zMap resolution out of bounds");
|
||||||
{
|
|
||||||
fseek(fileHandle, fieldSize, SEEK_CUR);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fread(&zMapHeader, 1, sizeof(dat16BitBmpHeader), fileHandle);
|
fread(&zMapHeader, 1, sizeof(dat16BitBmpHeader), fileHandle);
|
||||||
int length = fieldSize - sizeof(dat16BitBmpHeader);
|
int length = fieldSize - sizeof(dat16BitBmpHeader);
|
||||||
|
|
||||||
auto zmap = memory::allocate<zmap_header_type>(1, length);
|
auto zMap = memory::allocate<zmap_header_type>();
|
||||||
zmap->Width = zMapHeader.Width;
|
zdrv::create_zmap(zMap, zMapHeader.Width, zMapHeader.Height, zMapHeader.Stride);
|
||||||
zmap->Height = zMapHeader.Height;
|
zMap->Resolution = zMapResolution;
|
||||||
zmap->Stride = zMapHeader.Stride;
|
if (zMapHeader.Stride * zMapHeader.Height * 2 == length)
|
||||||
fread(zmap->ZBuffer, 1, length, fileHandle);
|
{
|
||||||
entryData->Buffer = reinterpret_cast<char*>(zmap);
|
fread(zMap->ZPtr1, 1, length, fileHandle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 3DPB .dat has zeroed zMap headers, in groups 497 and 498, skip them.
|
||||||
|
fseek(fileHandle, length, SEEK_CUR);
|
||||||
|
}
|
||||||
|
entryData->Buffer = reinterpret_cast<char*>(zMap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -163,122 +127,19 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
|
||||||
fread(entryBuffer, 1, fieldSize, fileHandle);
|
fread(entryBuffer, 1, fieldSize, fileHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
entryData->FieldSize = fieldSize;
|
groupData->AddEntry(entryData);
|
||||||
groupData->EntryCount++;
|
|
||||||
}
|
}
|
||||||
datFile->NumberOfGroups = groupIndex + 1;
|
|
||||||
|
datFile->Groups.push_back(groupData);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fileHandle);
|
fclose(fileHandle);
|
||||||
if (datFile->NumberOfGroups == header.NumberOfGroups)
|
if (datFile->Groups.size() == header.NumberOfGroups)
|
||||||
return datFile;
|
return datFile;
|
||||||
unload_records(datFile);
|
delete datFile;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void partman::unload_records(datFileStruct* datFile)
|
|
||||||
{
|
|
||||||
for (auto groupIndex = 0; groupIndex < datFile->NumberOfGroups; ++groupIndex)
|
|
||||||
{
|
|
||||||
auto group = datFile->GroupData[groupIndex];
|
|
||||||
if (!group)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (auto entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
|
|
||||||
{
|
|
||||||
auto entry = &group->Entries[entryIndex];
|
|
||||||
if (entry->Buffer)
|
|
||||||
{
|
|
||||||
if (entry->EntryType == datFieldTypes::Bitmap8bit)
|
|
||||||
gdrv::destroy_bitmap(reinterpret_cast<gdrv_bitmap8*>(entry->Buffer));
|
|
||||||
memory::free(entry->Buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memory::free(group);
|
|
||||||
}
|
|
||||||
if (datFile->Description)
|
|
||||||
memory::free(datFile->Description);
|
|
||||||
memory::free(datFile->GroupData);
|
|
||||||
memory::free(datFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* partman::field(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType)
|
|
||||||
{
|
|
||||||
auto group = datFile->GroupData[groupIndex];
|
|
||||||
for (auto entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
|
|
||||||
{
|
|
||||||
auto entry = &group->Entries[entryIndex];
|
|
||||||
if (entry->EntryType == targetEntryType)
|
|
||||||
return entry->Buffer;
|
|
||||||
if (entry->EntryType > targetEntryType)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char* partman::field_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN)
|
|
||||||
{
|
|
||||||
auto group = datFile->GroupData[groupIndex];
|
|
||||||
for (auto skipCount = 0, entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
|
|
||||||
{
|
|
||||||
auto entry = &group->Entries[entryIndex];
|
|
||||||
if (entry->EntryType > targetEntryType)
|
|
||||||
break;
|
|
||||||
if (entry->EntryType == targetEntryType)
|
|
||||||
if (skipCount++ == skipFirstN)
|
|
||||||
return entry->Buffer;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int partman::field_size_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN)
|
|
||||||
{
|
|
||||||
auto group = datFile->GroupData[groupIndex];
|
|
||||||
for (auto skipCount = 0, entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
|
|
||||||
{
|
|
||||||
auto entry = &group->Entries[entryIndex];
|
|
||||||
if (entry->EntryType > targetEntryType)
|
|
||||||
return 0;
|
|
||||||
if (entry->EntryType == targetEntryType)
|
|
||||||
if (skipCount++ == skipFirstN)
|
|
||||||
return entry->FieldSize;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int partman::field_size(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType)
|
|
||||||
{
|
|
||||||
return field_size_nth(datFile, groupIndex, targetEntryType, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int partman::record_labeled(datFileStruct* datFile, LPCSTR targetGroupName)
|
|
||||||
{
|
|
||||||
auto targetLength = strlen(targetGroupName);
|
|
||||||
for (int groupIndex = datFile->NumberOfGroups - 1; groupIndex >= 0; --groupIndex)
|
|
||||||
{
|
|
||||||
auto groupName = field(datFile, groupIndex, datFieldTypes::GroupName);
|
|
||||||
if (!groupName)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int index;
|
|
||||||
for (index = 0; index < targetLength; index++)
|
|
||||||
if (targetGroupName[index] != groupName[index])
|
|
||||||
break;
|
|
||||||
if (index == targetLength && !targetGroupName[index] && !groupName[index])
|
|
||||||
return groupIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* partman::field_labeled(datFileStruct* datFile, LPCSTR lpString, datFieldTypes fieldType)
|
|
||||||
{
|
|
||||||
auto groupIndex = record_labeled(datFile, lpString);
|
|
||||||
return groupIndex < 0 ? nullptr : field(datFile, groupIndex, fieldType);
|
|
||||||
}
|
|
||||||
|
|
||||||
char partman::_lread_char(FILE* file)
|
char partman::_lread_char(FILE* file)
|
||||||
{
|
{
|
||||||
char Buffer = 0;
|
char Buffer = 0;
|
||||||
|
|
|
@ -1,29 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum class datFieldTypes : int16_t
|
struct zmap_header_type;
|
||||||
{
|
struct gdrv_bitmap8;
|
||||||
ShortValue = 0,
|
|
||||||
//, does not have the 32bits size value, but a 16bits value(see above).
|
|
||||||
Bitmap8bit = 1,
|
|
||||||
// 8 bpp bitmap
|
|
||||||
Unknown2 = 2,
|
|
||||||
GroupName = 3,
|
|
||||||
// Group name
|
|
||||||
Unknown4 = 4,
|
|
||||||
Palette = 5,
|
|
||||||
// Palette(1 color is 1 DWORD, only present 1 time in PINBALL.DAT ,with a data size of 1024 bytes for 256 colors.Some colors are 0 ,because their indexes are reserved by Windows.)
|
|
||||||
Unknown6 = 6,
|
|
||||||
Unknown7 = 7,
|
|
||||||
Unknown8 = 8,
|
|
||||||
String = 9,
|
|
||||||
// String(content)
|
|
||||||
ShortArray = 10,
|
|
||||||
// Array of 16bits integer values
|
|
||||||
FloatArray = 11,
|
|
||||||
// Array of 32bits floating point values(collision box, ...)
|
|
||||||
Bitmap16bit = 12,
|
|
||||||
// 16 bpp bitmap(Heightmap ? )
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class bmp8Flags : unsigned char
|
enum class bmp8Flags : unsigned char
|
||||||
{
|
{
|
||||||
|
@ -33,8 +12,7 @@ enum class bmp8Flags : unsigned char
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push)
|
#pragma pack(push, 1)
|
||||||
#pragma pack(1)
|
|
||||||
struct datFileHeader
|
struct datFileHeader
|
||||||
{
|
{
|
||||||
char FileSignature[21];
|
char FileSignature[21];
|
||||||
|
@ -45,34 +23,10 @@ struct datFileHeader
|
||||||
int SizeOfBody;
|
int SizeOfBody;
|
||||||
unsigned short Unknown;
|
unsigned short Unknown;
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
|
||||||
static_assert(sizeof(datFileHeader) == 183, "Wrong size of datFileHeader");
|
|
||||||
|
|
||||||
struct datEntryData
|
|
||||||
{
|
|
||||||
datFieldTypes EntryType;
|
|
||||||
int FieldSize;
|
|
||||||
char* Buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct datGroupData
|
|
||||||
{
|
|
||||||
int16_t EntryCount;
|
|
||||||
datEntryData Entries[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct datFileStruct
|
|
||||||
{
|
|
||||||
unsigned short NumberOfGroups;
|
|
||||||
char* Description;
|
|
||||||
datGroupData** GroupData;
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
struct dat8BitBmpHeader
|
struct dat8BitBmpHeader
|
||||||
{
|
{
|
||||||
char Resolution;
|
uint8_t Resolution;
|
||||||
int16_t Width;
|
int16_t Width;
|
||||||
int16_t Height;
|
int16_t Height;
|
||||||
int16_t XPosition;
|
int16_t XPosition;
|
||||||
|
@ -80,18 +34,12 @@ struct dat8BitBmpHeader
|
||||||
int Size;
|
int Size;
|
||||||
bmp8Flags Flags;
|
bmp8Flags Flags;
|
||||||
|
|
||||||
bool IsFlagSet(bmp8Flags flag)
|
bool IsFlagSet(bmp8Flags flag) const
|
||||||
{
|
{
|
||||||
return static_cast<char>(Flags) & static_cast<char>(flag);
|
return static_cast<char>(Flags) & static_cast<char>(flag);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
static_assert(sizeof(dat8BitBmpHeader) == 14, "Wrong size of dat8BitBmpHeader");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct dat16BitBmpHeader
|
struct dat16BitBmpHeader
|
||||||
{
|
{
|
||||||
int16_t Width;
|
int16_t Width;
|
||||||
|
@ -101,22 +49,17 @@ struct dat16BitBmpHeader
|
||||||
int16_t Unknown1_0;
|
int16_t Unknown1_0;
|
||||||
int16_t Unknown1_1;
|
int16_t Unknown1_1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
static_assert(sizeof(dat8BitBmpHeader) == 14, "Wrong size of dat8BitBmpHeader");
|
||||||
|
static_assert(sizeof(datFileHeader) == 183, "Wrong size of datFileHeader");
|
||||||
static_assert(sizeof(dat16BitBmpHeader) == 14, "Wrong size of zmap_header_type");
|
static_assert(sizeof(dat16BitBmpHeader) == 14, "Wrong size of zmap_header_type");
|
||||||
|
|
||||||
|
|
||||||
class partman
|
class partman
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static datFileStruct* load_records(LPCSTR lpFileName, int resolution, bool fullTiltMode);
|
static struct DatFile* load_records(LPCSTR lpFileName, bool fullTiltMode);
|
||||||
static void unload_records(datFileStruct* datFile);
|
|
||||||
static char* field_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN);
|
|
||||||
static char* field(datFileStruct* datFile, int groupIndex, datFieldTypes entryType);
|
|
||||||
static int field_size_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN);
|
|
||||||
static int field_size(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType);
|
|
||||||
static int record_labeled(datFileStruct* datFile, LPCSTR targetGroupName);
|
|
||||||
static char* field_labeled(datFileStruct* datFile, LPCSTR lpString, datFieldTypes fieldType);
|
|
||||||
private:
|
private:
|
||||||
static short _field_size[];
|
static short _field_size[];
|
||||||
static char _lread_char(FILE* file);
|
static char _lread_char(FILE* file);
|
||||||
|
|
|
@ -24,9 +24,14 @@
|
||||||
#include "TLightGroup.h"
|
#include "TLightGroup.h"
|
||||||
#include "TPlunger.h"
|
#include "TPlunger.h"
|
||||||
#include "TTableLayer.h"
|
#include "TTableLayer.h"
|
||||||
|
#include "GroupData.h"
|
||||||
|
#include "partman.h"
|
||||||
|
#include "score.h"
|
||||||
|
#include "TPinballTable.h"
|
||||||
|
#include "TTextBox.h"
|
||||||
|
|
||||||
TPinballTable* pb::MainTable = nullptr;
|
TPinballTable* pb::MainTable = nullptr;
|
||||||
datFileStruct* pb::record_table = nullptr;
|
DatFile* pb::record_table = nullptr;
|
||||||
int pb::time_ticks = 0, pb::demo_mode = 0, pb::cheat_mode = 0, pb::game_mode = 2, pb::mode_countdown_;
|
int pb::time_ticks = 0, pb::demo_mode = 0, pb::cheat_mode = 0, pb::game_mode = 2, pb::mode_countdown_;
|
||||||
float pb::time_now, pb::time_next, pb::ball_speed_limit;
|
float pb::time_now, pb::time_next, pb::ball_speed_limit;
|
||||||
high_score_struct pb::highscore_table[5];
|
high_score_struct pb::highscore_table[5];
|
||||||
|
@ -39,7 +44,7 @@ int pb::init()
|
||||||
|
|
||||||
++memory::critical_allocation;
|
++memory::critical_allocation;
|
||||||
auto dataFilePath = pinball::make_path_name(winmain::DatFileName);
|
auto dataFilePath = pinball::make_path_name(winmain::DatFileName);
|
||||||
record_table = partman::load_records(dataFilePath.c_str(), fullscrn::GetResolution(), FullTiltMode);
|
record_table = partman::load_records(dataFilePath.c_str(), FullTiltMode);
|
||||||
|
|
||||||
auto useBmpFont = 0;
|
auto useBmpFont = 0;
|
||||||
pinball::get_rc_int(158, &useBmpFont);
|
pinball::get_rc_int(158, &useBmpFont);
|
||||||
|
@ -49,12 +54,12 @@ int pb::init()
|
||||||
if (!record_table)
|
if (!record_table)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
auto plt = (ColorRgba*)partman::field_labeled(record_table, "background", datFieldTypes::Palette);
|
auto plt = (ColorRgba*)record_table->field_labeled("background", FieldTypes::Palette);
|
||||||
gdrv::display_palette(plt);
|
gdrv::display_palette(plt);
|
||||||
|
|
||||||
auto backgroundBmp = (gdrv_bitmap8*)partman::field_labeled(record_table, "background", datFieldTypes::Bitmap8bit);
|
auto backgroundBmp = record_table->GetBitmap(record_table->record_labeled("background"));
|
||||||
auto cameraInfoId = partman::record_labeled(record_table, "camera_info") + fullscrn::GetResolution();
|
auto cameraInfoId = record_table->record_labeled("camera_info") + fullscrn::GetResolution();
|
||||||
auto cameraInfo = (float*)partman::field(record_table, cameraInfoId, datFieldTypes::FloatArray);
|
auto cameraInfo = (float*)record_table->field(cameraInfoId, FieldTypes::FloatArray);
|
||||||
|
|
||||||
/*Full tilt: table size depends on resolution*/
|
/*Full tilt: table size depends on resolution*/
|
||||||
auto resInfo = &fullscrn::resolution_array[fullscrn::GetResolution()];
|
auto resInfo = &fullscrn::resolution_array[fullscrn::GetResolution()];
|
||||||
|
@ -84,7 +89,6 @@ int pb::init()
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
gdrv::destroy_bitmap(backgroundBmp);
|
|
||||||
loader::loadfrom(record_table);
|
loader::loadfrom(record_table);
|
||||||
|
|
||||||
if (pinball::quickFlag)
|
if (pinball::quickFlag)
|
||||||
|
@ -108,7 +112,7 @@ int pb::uninit()
|
||||||
{
|
{
|
||||||
score::unload_msg_font();
|
score::unload_msg_font();
|
||||||
loader::unload();
|
loader::unload();
|
||||||
partman::unload_records(record_table);
|
delete record_table;
|
||||||
high_score::write(highscore_table);
|
high_score::write(highscore_table);
|
||||||
if (MainTable)
|
if (MainTable)
|
||||||
delete MainTable;
|
delete MainTable;
|
||||||
|
@ -287,8 +291,8 @@ void pb::timed_frame(float timeNow, float timeDelta, bool drawBalls)
|
||||||
ball->Acceleration.Y = ball->Speed * ball->Acceleration.Y;
|
ball->Acceleration.Y = ball->Speed * ball->Acceleration.Y;
|
||||||
maths::vector_add(&ball->Acceleration, &vec2);
|
maths::vector_add(&ball->Acceleration, &vec2);
|
||||||
ball->Speed = maths::normalize_2d(&ball->Acceleration);
|
ball->Speed = maths::normalize_2d(&ball->Acceleration);
|
||||||
ball->InvAcceleration.X = ball->Acceleration.X == 0.0f ? 1000000000.0f : 1.0f / ball->Acceleration.X;
|
ball->InvAcceleration.X = ball->Acceleration.X == 0.0f ? 1.0e9f : 1.0f / ball->Acceleration.X;
|
||||||
ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0f ? 1000000000.0f : 1.0f / ball->Acceleration.Y;
|
ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0f ? 1.0e9f : 1.0f / ball->Acceleration.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto timeDelta2 = timeDelta;
|
auto timeDelta2 = timeDelta;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "high_score.h"
|
#include "high_score.h"
|
||||||
#include "partman.h"
|
|
||||||
#include "TPinballTable.h"
|
|
||||||
|
|
||||||
|
class TPinballTable;
|
||||||
|
class DatFile;
|
||||||
class TBall;
|
class TBall;
|
||||||
|
|
||||||
class pb
|
class pb
|
||||||
|
@ -11,7 +11,7 @@ public:
|
||||||
static int time_ticks;
|
static int time_ticks;
|
||||||
static float ball_speed_limit, time_now, time_next;
|
static float ball_speed_limit, time_now, time_next;
|
||||||
static int cheat_mode, game_mode;
|
static int cheat_mode, game_mode;
|
||||||
static datFileStruct* record_table;
|
static DatFile* record_table;
|
||||||
static TPinballTable* MainTable;
|
static TPinballTable* MainTable;
|
||||||
static high_score_struct highscore_table[5];
|
static high_score_struct highscore_table[5];
|
||||||
static bool FullTiltMode;
|
static bool FullTiltMode;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "TTextBox.h"
|
|
||||||
|
class TTextBox;
|
||||||
|
|
||||||
class pinball
|
class pinball
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
#include "GroupData.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "pb.h"
|
||||||
|
|
||||||
int render::blit = 0;
|
int render::blit = 0;
|
||||||
int render::many_dirty, render::many_sprites, render::many_balls;
|
int render::many_dirty, render::many_sprites, render::many_balls;
|
||||||
|
@ -21,7 +24,7 @@ void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int h
|
||||||
sprite_list = memory::allocate<render_sprite_type_struct*>(1000);
|
sprite_list = memory::allocate<render_sprite_type_struct*>(1000);
|
||||||
dirty_list = memory::allocate<render_sprite_type_struct*>(1000);
|
dirty_list = memory::allocate<render_sprite_type_struct*>(1000);
|
||||||
ball_list = memory::allocate<render_sprite_type_struct*>(20);
|
ball_list = memory::allocate<render_sprite_type_struct*>(20);
|
||||||
gdrv::create_bitmap(&vscreen, width, height);
|
gdrv::create_bitmap(&vscreen, width, height, width, false);
|
||||||
zdrv::create_zmap(&zscreen, width, height);
|
zdrv::create_zmap(&zscreen, width, height);
|
||||||
zdrv::fill(&zscreen, zscreen.Width, zscreen.Height, 0, 0, 0xFFFF);
|
zdrv::fill(&zscreen, zscreen.Width, zscreen.Height, 0, 0, 0xFFFF);
|
||||||
vscreen_rect.YPosition = 0;
|
vscreen_rect.YPosition = 0;
|
||||||
|
@ -33,7 +36,7 @@ void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int h
|
||||||
gdrv_bitmap8* ballBmp = ball_bitmap;
|
gdrv_bitmap8* ballBmp = ball_bitmap;
|
||||||
while (ballBmp < &ball_bitmap[20])
|
while (ballBmp < &ball_bitmap[20])
|
||||||
{
|
{
|
||||||
gdrv::create_raw_bitmap(ballBmp, 64, 64, 1);
|
gdrv::create_bitmap(ballBmp, 64, 64, 64, false);
|
||||||
++ballBmp;
|
++ballBmp;
|
||||||
}
|
}
|
||||||
background_bitmap = bmp;
|
background_bitmap = bmp;
|
||||||
|
@ -473,7 +476,7 @@ void render::paint_balls()
|
||||||
|
|
||||||
void render::unpaint_balls()
|
void render::unpaint_balls()
|
||||||
{
|
{
|
||||||
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];
|
||||||
if (curBall->DirtyRect.Width > 0)
|
if (curBall->DirtyRect.Width > 0)
|
||||||
|
@ -554,3 +557,95 @@ void render::build_occlude_list()
|
||||||
|
|
||||||
--memory::critical_allocation;
|
--memory::critical_allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void render::SpriteViewer(bool* show)
|
||||||
|
{
|
||||||
|
static const char* BitmapTypes[] =
|
||||||
|
{
|
||||||
|
"None",
|
||||||
|
"RawBitmap",
|
||||||
|
"DibBitmap",
|
||||||
|
"Spliced",
|
||||||
|
};
|
||||||
|
static float scale = 1.0f;
|
||||||
|
auto uv_min = ImVec2(0.0f, 0.0f); // Top-left
|
||||||
|
auto uv_max = ImVec2(1.0f, 1.0f); // Lower-right
|
||||||
|
auto tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
|
||||||
|
auto border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); // 50% opaque white
|
||||||
|
|
||||||
|
if (ImGui::Begin("Sprite viewer", show, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_MenuBar))
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMenuBar())
|
||||||
|
{
|
||||||
|
ImGui::SliderFloat("Sprite scale", &scale, 0.1f, 10.0f, "scale = %.3f");
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto group : pb::record_table->Groups)
|
||||||
|
{
|
||||||
|
bool emptyGroup = true;
|
||||||
|
for (int i = 0; i <= 2; i++)
|
||||||
|
{
|
||||||
|
auto bmp = group->GetBitmap(i);
|
||||||
|
if (bmp)
|
||||||
|
{
|
||||||
|
emptyGroup = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (emptyGroup)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ImGui::Text("Group: %d, name:%s", group->GroupId, group->GroupName.c_str());
|
||||||
|
for (int i = 0; i <= 2; i++)
|
||||||
|
{
|
||||||
|
auto bmp = group->GetBitmap(i);
|
||||||
|
if (!bmp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto type = BitmapTypes[static_cast<char>(bmp->BitmapType)];
|
||||||
|
ImGui::Text("type:%s, size:%d, resolution: %dx%d, offset:%dx%d", type,
|
||||||
|
bmp->Resolution,
|
||||||
|
bmp->Width, bmp->Height, bmp->XPosition, bmp->YPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int same = 0, i = 0; i <= 2; i++)
|
||||||
|
{
|
||||||
|
auto bmp = group->GetBitmap(i);
|
||||||
|
if (!bmp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
gdrv::CreatePreview(*bmp);
|
||||||
|
if (bmp->Texture)
|
||||||
|
{
|
||||||
|
if (!same)
|
||||||
|
same = true;
|
||||||
|
else
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::Image(bmp->Texture, ImVec2(bmp->Width * scale, bmp->Height * scale),
|
||||||
|
uv_min, uv_max, tint_col, border_col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int same = 0, i = 0; i <= 2; i++)
|
||||||
|
{
|
||||||
|
auto zMap = group->GetZMap(i);
|
||||||
|
if (!zMap)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
zdrv::CreatePreview(*zMap);
|
||||||
|
if (zMap->Texture)
|
||||||
|
{
|
||||||
|
if (!same)
|
||||||
|
same = true;
|
||||||
|
else
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Image(zMap->Texture, ImVec2(zMap->Width * scale, zMap->Height * scale),
|
||||||
|
uv_min, uv_max, tint_col, border_col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
|
@ -61,4 +61,5 @@ public:
|
||||||
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 shift(int offsetX, int offsetY, int xSrc, int ySrc, int DestWidth, int DestHeight);
|
||||||
static void build_occlude_list();
|
static void build_occlude_list();
|
||||||
|
static void SpriteViewer(bool* show);
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
#include "fullscrn.h"
|
#include "fullscrn.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "partman.h"
|
#include "GroupData.h"
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "TDrain.h"
|
|
||||||
#include "winmain.h"
|
|
||||||
|
|
||||||
// Todo: load font from file
|
// Todo: load font from file
|
||||||
const uint8_t PB_MSGFT_bin[]
|
const uint8_t PB_MSGFT_bin[]
|
||||||
|
@ -32,9 +30,9 @@ scoreStruct* score::create(LPCSTR fieldName, gdrv_bitmap8* renderBgBmp)
|
||||||
score->BackgroundBmp = renderBgBmp;
|
score->BackgroundBmp = renderBgBmp;
|
||||||
|
|
||||||
/*Full tilt: score box dimensions index is offset by resolution*/
|
/*Full tilt: score box dimensions index is offset by resolution*/
|
||||||
auto dimensionsId = partman::record_labeled(pb::record_table, fieldName) + fullscrn::GetResolution();
|
auto dimensionsId = pb::record_table->record_labeled(fieldName) + fullscrn::GetResolution();
|
||||||
auto dimensions = reinterpret_cast<int16_t*>(partman::field(loader::loader_table, dimensionsId,
|
auto dimensions = reinterpret_cast<int16_t*>(loader::loader_table->field( dimensionsId,
|
||||||
datFieldTypes::ShortArray));
|
FieldTypes::ShortArray));
|
||||||
if (!dimensions)
|
if (!dimensions)
|
||||||
{
|
{
|
||||||
memory::free(score);
|
memory::free(score);
|
||||||
|
@ -48,8 +46,7 @@ scoreStruct* score::create(LPCSTR fieldName, gdrv_bitmap8* renderBgBmp)
|
||||||
|
|
||||||
for (int index = 0; index < 10; index++)
|
for (int index = 0; index < 10; index++)
|
||||||
{
|
{
|
||||||
score->CharBmp[index] = reinterpret_cast<gdrv_bitmap8*>(partman::field(
|
score->CharBmp[index] = loader::loader_table->GetBitmap(groupIndex);
|
||||||
loader::loader_table, groupIndex, datFieldTypes::Bitmap8bit));
|
|
||||||
++groupIndex;
|
++groupIndex;
|
||||||
}
|
}
|
||||||
return score;
|
return score;
|
||||||
|
@ -122,7 +119,7 @@ void score::load_msg_font_3DPB(LPCSTR lpName)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gdrv::create_raw_bitmap(bmp, width, height, 0))
|
if (gdrv::create_bitmap(bmp, width, height, width))
|
||||||
{
|
{
|
||||||
memory::free(bmp);
|
memory::free(bmp);
|
||||||
msg_fontp->Chars[charInd] = nullptr;
|
msg_fontp->Chars[charInd] = nullptr;
|
||||||
|
@ -133,12 +130,12 @@ void score::load_msg_font_3DPB(LPCSTR lpName)
|
||||||
memcpy(tmpCharBur + 3, ptrToData, sizeInBytes);
|
memcpy(tmpCharBur + 3, ptrToData, sizeInBytes);
|
||||||
ptrToData += sizeInBytes;
|
ptrToData += sizeInBytes;
|
||||||
|
|
||||||
auto srcptr = tmpCharBur + 4;
|
auto srcPtr = tmpCharBur + 4;
|
||||||
auto dstPtr = &bmp->BmpBufPtr1[bmp->Stride * (bmp->Height - 1)];
|
auto dstPtr = &bmp->IndexedBmpPtr[bmp->Stride * (bmp->Height - 1)];
|
||||||
for (auto y = 0; y < height; ++y)
|
for (auto y = 0; y < height; ++y)
|
||||||
{
|
{
|
||||||
memcpy(dstPtr, srcptr, width);
|
memcpy(dstPtr, srcPtr, width);
|
||||||
srcptr += width;
|
srcPtr += width;
|
||||||
dstPtr -= bmp->Stride;
|
dstPtr -= bmp->Stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +149,7 @@ void score::load_msg_font_FT(LPCSTR lpName)
|
||||||
{
|
{
|
||||||
if (!pb::record_table)
|
if (!pb::record_table)
|
||||||
return;
|
return;
|
||||||
int groupIndex = partman::record_labeled(pb::record_table, lpName);
|
int groupIndex = pb::record_table->record_labeled(lpName);
|
||||||
if (groupIndex < 0)
|
if (groupIndex < 0)
|
||||||
return;
|
return;
|
||||||
msg_fontp = reinterpret_cast<score_msg_font_type*>(memory::allocate(sizeof(score_msg_font_type)));
|
msg_fontp = reinterpret_cast<score_msg_font_type*>(memory::allocate(sizeof(score_msg_font_type)));
|
||||||
|
@ -160,15 +157,14 @@ void score::load_msg_font_FT(LPCSTR lpName)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(msg_fontp, 0, sizeof(score_msg_font_type));
|
memset(msg_fontp, 0, sizeof(score_msg_font_type));
|
||||||
auto gapArray = reinterpret_cast<int16_t*>(partman::field(pb::record_table, groupIndex, datFieldTypes::ShortArray));
|
auto gapArray = reinterpret_cast<int16_t*>(pb::record_table->field(groupIndex, FieldTypes::ShortArray));
|
||||||
if (gapArray)
|
if (gapArray)
|
||||||
msg_fontp->GapWidth = gapArray[fullscrn::GetResolution()];
|
msg_fontp->GapWidth = gapArray[fullscrn::GetResolution()];
|
||||||
else
|
else
|
||||||
msg_fontp->GapWidth = 0;
|
msg_fontp->GapWidth = 0;
|
||||||
for (auto charIndex = 32; charIndex < 128; charIndex++, ++groupIndex)
|
for (auto charIndex = 32; charIndex < 128; charIndex++, ++groupIndex)
|
||||||
{
|
{
|
||||||
auto bmp = reinterpret_cast<gdrv_bitmap8*>(partman::field(pb::record_table, groupIndex,
|
auto bmp = pb::record_table->GetBitmap(groupIndex);
|
||||||
datFieldTypes::Bitmap8bit));
|
|
||||||
if (!bmp)
|
if (!bmp)
|
||||||
break;
|
break;
|
||||||
if (!msg_fontp->Height)
|
if (!msg_fontp->Height)
|
||||||
|
@ -181,7 +177,7 @@ void score::unload_msg_font()
|
||||||
{
|
{
|
||||||
if (msg_fontp)
|
if (msg_fontp)
|
||||||
{
|
{
|
||||||
/*3DB creates bitmaps, FT just references them from partman*/
|
/*3DBP creates bitmaps, FT just references them from partman*/
|
||||||
if (!pb::FullTiltMode)
|
if (!pb::FullTiltMode)
|
||||||
for (int i = 0; i < 128; i++)
|
for (int i = 0; i < 128; i++)
|
||||||
{
|
{
|
||||||
|
@ -314,3 +310,18 @@ void score::string_format(int score, char* str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void score::ApplyPalette()
|
||||||
|
{
|
||||||
|
if (!msg_fontp || pb::FullTiltMode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Only 3DPB font needs this, because it is not loaded by partman
|
||||||
|
for (auto& Char : msg_fontp->Chars)
|
||||||
|
{
|
||||||
|
if (Char)
|
||||||
|
{
|
||||||
|
gdrv::ApplyPalette(*Char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
static void set(scoreStruct* score, int value);
|
static void set(scoreStruct* score, int value);
|
||||||
static void update(scoreStruct* score);
|
static void update(scoreStruct* score);
|
||||||
static void string_format(int score, char* str);
|
static void string_format(int score, char* str);
|
||||||
|
static void ApplyPalette();
|
||||||
private :
|
private :
|
||||||
static void load_msg_font_3DPB(LPCSTR lpName);
|
static void load_msg_font_3DPB(LPCSTR lpName);
|
||||||
static void load_msg_font_FT(LPCSTR lpName);
|
static void load_msg_font_FT(LPCSTR lpName);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "pinball.h"
|
#include "pinball.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
|
#include "render.h"
|
||||||
#include "Sound.h"
|
#include "Sound.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ gdrv_bitmap8 winmain::gfr_display{};
|
||||||
std::string winmain::DatFileName;
|
std::string winmain::DatFileName;
|
||||||
bool winmain::ShowAboutDialog = false;
|
bool winmain::ShowAboutDialog = false;
|
||||||
bool winmain::ShowImGuiDemo = false;
|
bool winmain::ShowImGuiDemo = false;
|
||||||
|
bool winmain::ShowSpriteViewer = false;
|
||||||
bool winmain::LaunchBallEnabled = true;
|
bool winmain::LaunchBallEnabled = true;
|
||||||
bool winmain::HighScoresEnabled = true;
|
bool winmain::HighScoresEnabled = true;
|
||||||
bool winmain::DemoActive = false;
|
bool winmain::DemoActive = false;
|
||||||
|
@ -199,15 +201,14 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
||||||
redGreen = i1;
|
redGreen = i1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto clr = Rgba{redGreen, redGreen, blue, 0};
|
*pltPtr++ = ColorRgba{Rgba{redGreen, redGreen, blue, 0}};
|
||||||
*pltPtr++ = {*reinterpret_cast<uint32_t*>(&clr)};
|
|
||||||
}
|
}
|
||||||
gdrv::display_palette(plt);
|
gdrv::display_palette(plt);
|
||||||
free(plt);
|
free(plt);
|
||||||
gdrv::create_bitmap(&gfr_display, 400, 15);
|
gdrv::create_bitmap(&gfr_display, 400, 15, 400, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
gdrv::blit(&gfr_display, 0, 0, 0, 0, 300, 10);
|
gdrv::blit(&gfr_display, 0, 0, 0, 30, 300, 10);
|
||||||
gdrv::fill_bitmap(&gfr_display, 300, 10, 0, 0, 0);
|
gdrv::fill_bitmap(&gfr_display, 300, 10, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,12 +255,12 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
||||||
if (gfr_display.BmpBufPtr1)
|
if (gfr_display.BmpBufPtr1)
|
||||||
{
|
{
|
||||||
auto deltaT = now - then + 10;
|
auto deltaT = now - then + 10;
|
||||||
auto fillChar = static_cast<char>(deltaT);
|
auto fillChar = static_cast<uint8_t>(deltaT);
|
||||||
if (deltaT > 236)
|
if (deltaT > 236)
|
||||||
{
|
{
|
||||||
fillChar = -7;
|
fillChar = 1;
|
||||||
}
|
}
|
||||||
gdrv::fill_bitmap(&gfr_display, 1, 10, 299 - updateCounter, 0, fillChar);
|
gdrv::fill_bitmap(&gfr_display, 1, 10, 300 - updateCounter, 0, fillChar);
|
||||||
}
|
}
|
||||||
--updateCounter;
|
--updateCounter;
|
||||||
then = now;
|
then = now;
|
||||||
|
@ -329,7 +330,7 @@ void winmain::RenderUi()
|
||||||
// No demo window in release to save space
|
// No demo window in release to save space
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (ShowImGuiDemo)
|
if (ShowImGuiDemo)
|
||||||
ImGui::ShowDemoWindow();
|
ImGui::ShowDemoWindow(&ShowImGuiDemo);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ImGui::BeginMainMenuBar())
|
if (ImGui::BeginMainMenuBar())
|
||||||
|
@ -444,6 +445,12 @@ void winmain::RenderUi()
|
||||||
ShowImGuiDemo ^= true;
|
ShowImGuiDemo ^= true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (ImGui::MenuItem("Sprite Viewer", nullptr, ShowSpriteViewer))
|
||||||
|
{
|
||||||
|
if (!ShowSpriteViewer && !single_step)
|
||||||
|
pause();
|
||||||
|
ShowSpriteViewer ^= true;
|
||||||
|
}
|
||||||
if (ImGui::MenuItem("Help Topics", "F1"))
|
if (ImGui::MenuItem("Help Topics", "F1"))
|
||||||
{
|
{
|
||||||
if (!single_step)
|
if (!single_step)
|
||||||
|
@ -465,6 +472,8 @@ void winmain::RenderUi()
|
||||||
|
|
||||||
a_dialog();
|
a_dialog();
|
||||||
high_score::RenderHighScoreDialog();
|
high_score::RenderHighScoreDialog();
|
||||||
|
if (ShowSpriteViewer)
|
||||||
|
render::SpriteViewer(&ShowSpriteViewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int winmain::event_handler(const SDL_Event* event)
|
int winmain::event_handler(const SDL_Event* event)
|
||||||
|
@ -553,7 +562,7 @@ int winmain::event_handler(const SDL_Event* event)
|
||||||
|
|
||||||
switch (event->key.keysym.sym)
|
switch (event->key.keysym.sym)
|
||||||
{
|
{
|
||||||
case SDLK_h:
|
case SDLK_g:
|
||||||
DispGRhistory = 1;
|
DispGRhistory = 1;
|
||||||
break;
|
break;
|
||||||
case SDLK_y:
|
case SDLK_y:
|
||||||
|
@ -627,7 +636,6 @@ int winmain::event_handler(const SDL_Event* event)
|
||||||
{
|
{
|
||||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||||
case SDL_WINDOWEVENT_TAKE_FOCUS:
|
case SDL_WINDOWEVENT_TAKE_FOCUS:
|
||||||
case SDL_WINDOWEVENT_EXPOSED:
|
|
||||||
case SDL_WINDOWEVENT_SHOWN:
|
case SDL_WINDOWEVENT_SHOWN:
|
||||||
activated = 1;
|
activated = 1;
|
||||||
Sound::Activate();
|
Sound::Activate();
|
||||||
|
|
|
@ -32,6 +32,7 @@ private:
|
||||||
static bool restart;
|
static bool restart;
|
||||||
static bool ShowAboutDialog;
|
static bool ShowAboutDialog;
|
||||||
static bool ShowImGuiDemo;
|
static bool ShowImGuiDemo;
|
||||||
|
static bool ShowSpriteViewer;
|
||||||
|
|
||||||
static void RenderUi();
|
static void RenderUi();
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,20 +2,18 @@
|
||||||
#include "zdrv.h"
|
#include "zdrv.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
|
#include "winmain.h"
|
||||||
|
|
||||||
|
|
||||||
int zdrv::create_zmap(zmap_header_type* zmap, int width, int height)
|
int zdrv::create_zmap(zmap_header_type* zmap, int width, int height, int stride)
|
||||||
{
|
{
|
||||||
int stride = pad(width);
|
|
||||||
zmap->Stride = stride;
|
|
||||||
auto bmpBuf = memory::allocate<unsigned short>(height * stride);
|
|
||||||
zmap->ZPtr1 = bmpBuf;
|
|
||||||
if (!bmpBuf)
|
|
||||||
return -1;
|
|
||||||
zmap->ZPtr2 = bmpBuf;
|
|
||||||
zmap->Width = width;
|
zmap->Width = width;
|
||||||
zmap->Height = height;
|
zmap->Height = height;
|
||||||
return 0;
|
zmap->Stride = stride >= 0 ? stride : pad(width);
|
||||||
|
zmap->Texture = nullptr;
|
||||||
|
|
||||||
|
zmap->ZPtr1 = memory::allocate<unsigned short>(zmap->Stride * zmap->Height);
|
||||||
|
return zmap->ZPtr1 ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int zdrv::pad(int width)
|
int zdrv::pad(int width)
|
||||||
|
@ -32,13 +30,15 @@ int zdrv::destroy_zmap(zmap_header_type* zmap)
|
||||||
return -1;
|
return -1;
|
||||||
if (zmap->ZPtr1)
|
if (zmap->ZPtr1)
|
||||||
memory::free(zmap->ZPtr1);
|
memory::free(zmap->ZPtr1);
|
||||||
|
if (zmap->Texture)
|
||||||
|
SDL_DestroyTexture(zmap->Texture);
|
||||||
memset(zmap, 0, sizeof(zmap_header_type));
|
memset(zmap, 0, sizeof(zmap_header_type));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zdrv::fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, uint16_t fillWord)
|
void zdrv::fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, uint16_t fillWord)
|
||||||
{
|
{
|
||||||
auto dstPtr = &zmap->ZPtr1[zmap->Stride * (zmap->Height - height - yOff) + xOff];
|
auto dstPtr = &zmap->ZPtr1[zmap->Stride * yOff + xOff];
|
||||||
for (int y = height; y > 0; --y)
|
for (int y = height; y > 0; --y)
|
||||||
{
|
{
|
||||||
for (int x = width; x > 0; --x)
|
for (int x = width; x > 0; --x)
|
||||||
|
@ -54,19 +54,12 @@ void zdrv::paint(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, in
|
||||||
int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff, int srcBmpYOff,
|
int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff, int srcBmpYOff,
|
||||||
zmap_header_type* srcZMap, int srcZMapXOff, int srcZMapYOff)
|
zmap_header_type* srcZMap, int srcZMapXOff, int srcZMapYOff)
|
||||||
{
|
{
|
||||||
if (srcBmp->BitmapType == BitmapTypes::Spliced)
|
assertm(srcBmp->BitmapType != BitmapTypes::Spliced, "Wrong bmp type");
|
||||||
{
|
|
||||||
/*Spliced bitmap is also a zMap, how convenient*/
|
|
||||||
paint_spliced_bmp(srcBmp->XPosition, srcBmp->YPosition, dstBmp, dstZMap, srcBmp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dstHeightAbs = abs(dstBmp->Height);
|
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * srcBmpYOff + srcBmpXOff];
|
||||||
int srcHeightAbs = abs(srcBmp->Height);
|
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * dstBmpYOff + dstBmpXOff];
|
||||||
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeightAbs - height - srcBmpYOff) + srcBmpXOff];
|
auto srcPtrZ = &srcZMap->ZPtr1[srcZMap->Stride * srcZMapYOff + srcZMapXOff];
|
||||||
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeightAbs - height - dstBmpYOff) + dstBmpXOff];
|
auto dstPtrZ = &dstZMap->ZPtr1[dstZMap->Stride * dstZMapYOff + dstZMapXOff];
|
||||||
auto srcPtrZ = &srcZMap->ZPtr1[srcZMap->Stride * (srcZMap->Height - height - srcZMapYOff) + srcZMapXOff];
|
|
||||||
auto dstPtrZ = &dstZMap->ZPtr1[dstZMap->Stride * (dstZMap->Height - height - dstZMapYOff) + dstZMapXOff];
|
|
||||||
|
|
||||||
for (int y = height; y > 0; y--)
|
for (int y = height; y > 0; y--)
|
||||||
{
|
{
|
||||||
|
@ -94,17 +87,17 @@ void zdrv::paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOf
|
||||||
zmap_header_type* zMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff,
|
zmap_header_type* zMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff,
|
||||||
int srcBmpYOff, uint16_t depth)
|
int srcBmpYOff, uint16_t depth)
|
||||||
{
|
{
|
||||||
int dstHeightAbs = abs(dstBmp->Height);
|
assertm(srcBmp->BitmapType != BitmapTypes::Spliced, "Wrong bmp type");
|
||||||
int srcHeightAbs = abs(srcBmp->Height);
|
|
||||||
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeightAbs - height - dstBmpYOff) + dstBmpXOff];
|
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * dstBmpYOff + dstBmpXOff];
|
||||||
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeightAbs - height - srcBmpYOff) + srcBmpXOff];
|
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * srcBmpYOff + srcBmpXOff];
|
||||||
auto zPtr = &zMap->ZPtr1[zMap->Stride * (zMap->Height - height - dstZMapYOff) + dstZMapXOff];
|
auto zPtr = &zMap->ZPtr1[zMap->Stride * dstZMapYOff + dstZMapXOff];
|
||||||
|
|
||||||
for (int y = height; y > 0; y--)
|
for (int y = height; y > 0; y--)
|
||||||
{
|
{
|
||||||
for (int x = width; x > 0; --x)
|
for (int x = width; x > 0; --x)
|
||||||
{
|
{
|
||||||
if (*srcPtr && *zPtr > depth)
|
if ((*srcPtr).Color && *zPtr > depth)
|
||||||
{
|
{
|
||||||
*dstPtr = *srcPtr;
|
*dstPtr = *srcPtr;
|
||||||
}
|
}
|
||||||
|
@ -119,40 +112,58 @@ void zdrv::paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void zdrv::paint_spliced_bmp(int xPos, int yPos, gdrv_bitmap8* dstBmp, zmap_header_type* dstZmap, gdrv_bitmap8* srcBmp)
|
void zdrv::CreatePreview(zmap_header_type& zMap)
|
||||||
{
|
{
|
||||||
assertm(srcBmp->BitmapType == BitmapTypes::Spliced, "Wrong bmp type");
|
if (zMap.Texture)
|
||||||
int xOffset = xPos - pb::MainTable->XOffset;
|
|
||||||
int yOffset = dstBmp->Height - srcBmp->Height - (yPos - pb::MainTable->YOffset);
|
|
||||||
if (yOffset < 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto bmpDstPtr = &dstBmp->BmpBufPtr1[xOffset + yOffset * dstBmp->Stride];
|
auto tmpBuff = new ColorRgba[zMap.Width * zMap.Height];
|
||||||
auto zMapDstPtr = &dstZmap->ZPtr2[xOffset + yOffset * dstZmap->Stride];
|
|
||||||
auto bmpSrcPtr = reinterpret_cast<unsigned short*>(srcBmp->BmpBufPtr1);
|
|
||||||
|
|
||||||
while (true)
|
ColorRgba color{};
|
||||||
|
auto dst = tmpBuff;
|
||||||
|
auto src = zMap.ZPtr1;
|
||||||
|
for (auto y = 0; y < zMap.Height; y++)
|
||||||
{
|
{
|
||||||
auto stride = static_cast<short>(*bmpSrcPtr++);
|
for (auto x = 0; x < zMap.Width; x++)
|
||||||
if (stride < 0)
|
{
|
||||||
break;
|
auto depth = static_cast<uint8_t>((0xffff - *src++) / 0xff);
|
||||||
|
color.rgba.peRed = depth;
|
||||||
|
color.rgba.peGreen = depth;
|
||||||
|
color.rgba.peBlue = depth;
|
||||||
|
|
||||||
/*Stride is in terms of dst stride, hardcoded to match vScreen width in current resolution*/
|
/*auto depth = static_cast<float>(*src++) /0xffff;
|
||||||
zMapDstPtr += stride;
|
color.rgba.peRed = (1-depth) * 0xff;
|
||||||
bmpDstPtr += stride;
|
color.rgba.peBlue = (depth) * 0xff;*/
|
||||||
for (auto count = *bmpSrcPtr++; count; count--)
|
*dst++ = color;
|
||||||
{
|
}
|
||||||
auto depth = *bmpSrcPtr++;
|
src += zMap.Stride - zMap.Width;
|
||||||
auto charPtr = reinterpret_cast<char**>(&bmpSrcPtr);
|
|
||||||
if (*zMapDstPtr >= depth)
|
|
||||||
{
|
|
||||||
*bmpDstPtr = **charPtr;
|
|
||||||
*zMapDstPtr = depth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(*charPtr)++;
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
|
||||||
++zMapDstPtr;
|
auto texture = SDL_CreateTexture
|
||||||
++bmpDstPtr;
|
(
|
||||||
|
winmain::Renderer,
|
||||||
|
SDL_PIXELFORMAT_ARGB8888,
|
||||||
|
SDL_TEXTUREACCESS_STATIC,
|
||||||
|
zMap.Width, zMap.Height
|
||||||
|
);
|
||||||
|
SDL_UpdateTexture(texture, nullptr, tmpBuff, zMap.Width * 4);
|
||||||
|
zMap.Texture = texture;
|
||||||
|
delete[] tmpBuff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdrv::FlipZMapHorizontally(const zmap_header_type& zMap)
|
||||||
|
{
|
||||||
|
// Flip in-place, iterate over Height/2 lines
|
||||||
|
auto dst = zMap.ZPtr1;
|
||||||
|
auto src = zMap.ZPtr1 + zMap.Stride * (zMap.Height - 1);
|
||||||
|
for (auto y = zMap.Height - 1; y >= zMap.Height / 2; y--)
|
||||||
|
{
|
||||||
|
for (auto x = 0; x < zMap.Width; x++)
|
||||||
|
{
|
||||||
|
std::swap(*dst++, *src++);
|
||||||
}
|
}
|
||||||
|
dst += zMap.Stride - zMap.Width;
|
||||||
|
src -= zMap.Stride + zMap.Width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,16 @@ struct zmap_header_type
|
||||||
int Width;
|
int Width;
|
||||||
int Height;
|
int Height;
|
||||||
int Stride;
|
int Stride;
|
||||||
|
unsigned Resolution;
|
||||||
uint16_t* ZPtr1;
|
uint16_t* ZPtr1;
|
||||||
uint16_t* ZPtr2;
|
SDL_Texture* Texture;
|
||||||
uint16_t ZBuffer[1];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class zdrv
|
class zdrv
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static int pad(int width);
|
static int pad(int width);
|
||||||
static int create_zmap(zmap_header_type* zmap, int width, int height);
|
static int create_zmap(zmap_header_type* zmap, int width, int height, int stride = -1);
|
||||||
static int destroy_zmap(zmap_header_type* zmap);
|
static int destroy_zmap(zmap_header_type* zmap);
|
||||||
static void fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, uint16_t fillWord);
|
static void fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, uint16_t fillWord);
|
||||||
static void paint(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff,
|
static void paint(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff,
|
||||||
|
@ -24,6 +24,6 @@ public:
|
||||||
static void paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff,
|
static void paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff,
|
||||||
zmap_header_type* zMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp,
|
zmap_header_type* zMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp,
|
||||||
int srcBmpXOff, int srcBmpYOff, uint16_t depth);
|
int srcBmpXOff, int srcBmpYOff, uint16_t depth);
|
||||||
static void paint_spliced_bmp(int xPos, int yPos, gdrv_bitmap8* dstBmp, zmap_header_type* dstZmap,
|
static void CreatePreview(zmap_header_type& zMap);
|
||||||
gdrv_bitmap8* srcBmp);
|
static void FlipZMapHorizontally(const zmap_header_type& zMap);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue