mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-11-14 19:25:18 -05: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/gdrv.cpp
|
||||
SpaceCadetPinball/gdrv.h
|
||||
SpaceCadetPinball/GroupData.cpp
|
||||
SpaceCadetPinball/GroupData.h
|
||||
SpaceCadetPinball/high_score.cpp
|
||||
SpaceCadetPinball/high_score.h
|
||||
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 "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"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
|
@ -24,57 +15,6 @@ int main(int argc, char* argv[])
|
|||
winmain::WinMain(cmdLine.c_str());
|
||||
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
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "render.h"
|
||||
#include "TFlipperEdge.h"
|
||||
#include "timer.h"
|
||||
#include "TPinballTable.h"
|
||||
|
||||
TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "objlist_class.h"
|
||||
#include "pb.h"
|
||||
#include "pinball.h"
|
||||
#include "TBlocker.h"
|
||||
#include "TBumper.h"
|
||||
#include "TComponentGroup.h"
|
||||
|
@ -27,6 +28,7 @@
|
|||
#include "TRamp.h"
|
||||
#include "TPlunger.h"
|
||||
#include "TWall.h"
|
||||
#include "TTextBox.h"
|
||||
|
||||
int control::pbctrl_state;
|
||||
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#include "pch.h"
|
||||
#include "gdrv.h"
|
||||
|
||||
#include "GroupData.h"
|
||||
#include "memory.h"
|
||||
#include "partman.h"
|
||||
#include "pb.h"
|
||||
#include "score.h"
|
||||
#include "winmain.h"
|
||||
|
||||
SDL_Texture* gdrv::vScreenTex = nullptr;
|
||||
char* gdrv::vScreenPixels = nullptr;
|
||||
ColorRgba* gdrv::vScreenPixels = nullptr;
|
||||
int gdrv::vScreenWidth, gdrv::vScreenHeight;
|
||||
ColorRgba gdrv::current_palette[256]{};
|
||||
SDL_Rect gdrv::DestinationRect{};
|
||||
|
@ -20,7 +24,7 @@ int gdrv::init(int width, int height)
|
|||
SDL_TEXTUREACCESS_STREAMING,
|
||||
width, height
|
||||
);
|
||||
vScreenPixels = memory::allocate(width * height * 4);
|
||||
vScreenPixels = memory::allocate<ColorRgba>(width * height);
|
||||
vScreenWidth = width;
|
||||
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;
|
||||
bmp->Stride = width;
|
||||
if (width % 4)
|
||||
bmp->Stride = 4 - width % 4 + width;
|
||||
assertm(width >= 0 && height >= 0, "Negative bitmap8 dimensions");
|
||||
|
||||
bmp->Width = width;
|
||||
bmp->Height = height;
|
||||
bmp->Stride = width;
|
||||
bmp->BitmapType = BitmapTypes::DibBitmap;
|
||||
bmp->BmpBufPtr1 = memory::allocate(bmp->Height * bmp->Stride);
|
||||
return 0;
|
||||
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 -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;
|
||||
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;
|
||||
}
|
||||
assertm(header.Width >= 0 && header.Height >= 0, "Negative bitmap8 dimensions");
|
||||
|
||||
int gdrv::create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size)
|
||||
{
|
||||
bmp->Width = width;
|
||||
bmp->Stride = width;
|
||||
bmp->BitmapType = BitmapTypes::Spliced;
|
||||
bmp->Height = height;
|
||||
char* buf = memory::allocate(size);
|
||||
bmp->BmpBufPtr1 = buf;
|
||||
if (!buf)
|
||||
return -1;
|
||||
return 0;
|
||||
if (header.IsFlagSet(bmp8Flags::Spliced))
|
||||
bmp.BitmapType = BitmapTypes::Spliced;
|
||||
else if (header.IsFlagSet(bmp8Flags::DibBitmap))
|
||||
bmp.BitmapType = BitmapTypes::DibBitmap;
|
||||
else
|
||||
bmp.BitmapType = BitmapTypes::RawBitmap;
|
||||
|
||||
bmp.Width = header.Width;
|
||||
bmp.Stride = header.Width;
|
||||
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 -1;
|
||||
}
|
||||
|
||||
int gdrv::display_palette(ColorRgba* plt)
|
||||
{
|
||||
const uint32_t sysPaletteColors[]
|
||||
{
|
||||
0x00000000,
|
||||
0x00000000, // Color 0: transparent
|
||||
0x00000080,
|
||||
0x00008000,
|
||||
0x00008080,
|
||||
|
@ -122,6 +157,19 @@ int gdrv::display_palette(ColorRgba* plt)
|
|||
current_palette[255].rgba.peGreen = -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;
|
||||
}
|
||||
|
||||
|
@ -134,6 +182,10 @@ int gdrv::destroy_bitmap(gdrv_bitmap8* bmp)
|
|||
if (bmp->BitmapType != BitmapTypes::None)
|
||||
{
|
||||
memory::free(bmp->BmpBufPtr1);
|
||||
if (bmp->IndexedBmpPtr)
|
||||
memory::free(bmp->IndexedBmpPtr);
|
||||
if (bmp->Texture)
|
||||
SDL_DestroyTexture(bmp->Texture);
|
||||
}
|
||||
memset(bmp, 0, sizeof(gdrv_bitmap8));
|
||||
return 0;
|
||||
|
@ -151,7 +203,7 @@ void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrc, int xDest, int yDest, int
|
|||
{
|
||||
StretchDIBitsScaled(
|
||||
xSrc,
|
||||
ySrc ,
|
||||
ySrc,
|
||||
xDest,
|
||||
yDest,
|
||||
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;
|
||||
if (bmpHeight < 0)
|
||||
bmpHeight = -bmpHeight;
|
||||
char* bmpPtr = &bmp->BmpBufPtr1[bmp->Width * (bmpHeight - height - yOff) + xOff];
|
||||
auto color = current_palette[fillChar];
|
||||
auto bmpPtr = &bmp->BmpBufPtr1[bmp->Width * yOff + xOff];
|
||||
for (; height > 0; --height)
|
||||
{
|
||||
if (width > 0)
|
||||
memset(bmpPtr, fillChar, width);
|
||||
bmpPtr += bmp->Stride;
|
||||
for (int x = width; x > 0; --x)
|
||||
*bmpPtr++ = color;
|
||||
bmpPtr += bmp->Stride - width;
|
||||
}
|
||||
}
|
||||
|
||||
void gdrv::copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
|
||||
int srcXOff, int srcYOff)
|
||||
{
|
||||
int dstHeight = abs(dstBmp->Height);
|
||||
int srcHeight = abs(srcBmp->Height);
|
||||
char* srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeight - height - srcYOff) + srcXOff];
|
||||
char* dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeight - height - yOff) + xOff];
|
||||
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * srcYOff + srcXOff];
|
||||
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * yOff + xOff];
|
||||
|
||||
for (int y = height; y > 0; --y)
|
||||
{
|
||||
for (int x = width; x > 0; --x)
|
||||
*dstPtr++ = *srcPtr++;
|
||||
|
||||
srcPtr += srcBmp->Stride - width;
|
||||
dstPtr += dstBmp->Stride - width;
|
||||
std::memcpy(dstPtr, srcPtr, width * sizeof(ColorRgba));
|
||||
srcPtr += srcBmp->Stride;
|
||||
dstPtr += dstBmp->Stride;
|
||||
}
|
||||
}
|
||||
|
||||
void gdrv::copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
|
||||
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff)
|
||||
{
|
||||
int dstHeight = abs(dstBmp->Height);
|
||||
int srcHeight = abs(srcBmp->Height);
|
||||
char* srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeight - height - srcYOff) + srcXOff];
|
||||
char* dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeight - height - yOff) + xOff];
|
||||
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * srcYOff + srcXOff];
|
||||
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * yOff + xOff];
|
||||
|
||||
for (int y = height; y > 0; --y)
|
||||
{
|
||||
for (int x = width; x > 0; --x)
|
||||
{
|
||||
if (*srcPtr)
|
||||
if ((*srcPtr).Color)
|
||||
*dstPtr = *srcPtr;
|
||||
++srcPtr;
|
||||
++dstPtr;
|
||||
|
@ -230,19 +274,15 @@ void gdrv::copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int heigh
|
|||
|
||||
|
||||
void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6)
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
int gdrv::StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
|
||||
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
|
||||
if (xDst < 0)
|
||||
{
|
||||
{
|
||||
xSrc -= xDst;
|
||||
xDst = 0;
|
||||
}
|
||||
|
@ -258,27 +298,22 @@ int gdrv::StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
|
|||
if (xSrc + width > bmp->Width)
|
||||
width = bmp->Width - xSrc;
|
||||
if (ySrc + height > bmp->Height)
|
||||
height = bmp->Height - ySrc;
|
||||
height = bmp->Height - ySrc;
|
||||
|
||||
xDst = std::max(0, std::min(xDst, vScreenWidth));
|
||||
yDst = std::max(0, std::min(yDst, vScreenHeight));
|
||||
if (xDst + width > vScreenWidth)
|
||||
width = vScreenWidth - xDst;
|
||||
if (yDst + height > vScreenHeight)
|
||||
height = vScreenHeight - yDst;
|
||||
height = vScreenHeight - yDst;
|
||||
|
||||
auto srcPtr = reinterpret_cast<uint8_t*>(&bmp->BmpBufPtr1[bmp->Stride * ySrc + xSrc]);
|
||||
auto dstPtr = &reinterpret_cast<uint32_t*>(vScreenPixels)[vScreenWidth * yDst + xDst];
|
||||
auto srcPtr = &bmp->BmpBufPtr1[bmp->Stride * ySrc + xSrc];
|
||||
auto dstPtr = &vScreenPixels[vScreenWidth * yDst + xDst];
|
||||
for (int y = height; y > 0; --y)
|
||||
{
|
||||
for (int x = width; x > 0; --x)
|
||||
{
|
||||
|
||||
*dstPtr++ = current_palette[*srcPtr++].Color;
|
||||
}
|
||||
|
||||
srcPtr += bmp->Stride - width;
|
||||
dstPtr += vScreenWidth - width;
|
||||
std::memcpy(dstPtr, srcPtr, width * sizeof(ColorRgba));
|
||||
srcPtr += bmp->Stride;
|
||||
dstPtr += vScreenWidth;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -297,5 +332,41 @@ void gdrv::BlitScreen()
|
|||
);
|
||||
std::memcpy(lockedPixels, vScreenPixels, vScreenWidth * vScreenHeight * 4);
|
||||
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
|
||||
|
||||
enum class BitmapTypes : char
|
||||
enum class BitmapTypes : uint8_t
|
||||
{
|
||||
None = 0,
|
||||
RawBitmap = 1,
|
||||
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
|
||||
{
|
||||
|
@ -26,13 +16,43 @@ struct Rgba
|
|||
uint8_t peBlue;
|
||||
uint8_t peFlags;
|
||||
};
|
||||
|
||||
union ColorRgba
|
||||
{
|
||||
ColorRgba() = default;
|
||||
|
||||
explicit ColorRgba(uint32_t color)
|
||||
: Color(color)
|
||||
{
|
||||
}
|
||||
|
||||
explicit ColorRgba(Rgba rgba)
|
||||
: rgba(rgba)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t Color;
|
||||
Rgba rgba;
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -42,25 +62,26 @@ public:
|
|||
static int init(int width, int height);
|
||||
static int uninit();
|
||||
static void get_focus();
|
||||
static int create_bitmap(gdrv_bitmap8* bmp, int width, int height);
|
||||
static int create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag);
|
||||
static int create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size);
|
||||
static int create_bitmap(gdrv_bitmap8* bmp, int width, int height, int stride = -1, bool indexed = true);
|
||||
static int create_bitmap(gdrv_bitmap8& bmp, const struct dat8BitBmpHeader& header);
|
||||
static int destroy_bitmap(gdrv_bitmap8* bmp);
|
||||
static int display_palette(ColorRgba* plt);
|
||||
static void start_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 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,
|
||||
int srcXOff, int srcYOff);
|
||||
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
|
||||
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 BlitScreen();
|
||||
static void ApplyPalette(gdrv_bitmap8& bmp);
|
||||
static void CreatePreview(gdrv_bitmap8& bmp);
|
||||
private:
|
||||
static SDL_Texture* vScreenTex;
|
||||
static char* vScreenPixels;
|
||||
static ColorRgba* vScreenPixels;
|
||||
static int vScreenWidth, vScreenHeight;
|
||||
static ColorRgba current_palette[256];
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "memory.h"
|
||||
#include "options.h"
|
||||
#include "pinball.h"
|
||||
#include "score.h"
|
||||
|
||||
int high_score::dlg_enter_name;
|
||||
int high_score::dlg_score;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
#include "pinball.h"
|
||||
|
||||
struct high_score_struct
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "pch.h"
|
||||
#include "loader.h"
|
||||
#include "memory.h"
|
||||
#include "partman.h"
|
||||
#include "GroupData.h"
|
||||
#include "pb.h"
|
||||
#include "pinball.h"
|
||||
#include "Sound.h"
|
||||
|
@ -12,7 +12,7 @@ errorMsg loader::loader_errors[] =
|
|||
{
|
||||
errorMsg{0, "Bad Handle"},
|
||||
errorMsg{1, "No Type Field"},
|
||||
errorMsg{2, "No Attributes Field"},
|
||||
errorMsg{2, "No Attributes Field"},
|
||||
errorMsg{3, "Wrong Type: MATERIAL Expected"},
|
||||
errorMsg{4, "Wrong Type: KICKER Expected"},
|
||||
errorMsg{5, "Wrong Type: AN_OBJECT Expected"},
|
||||
|
@ -42,8 +42,8 @@ errorMsg loader::loader_errors[] =
|
|||
|
||||
int loader::sound_count = 1;
|
||||
int loader::loader_sound_count;
|
||||
datFileStruct* loader::loader_table;
|
||||
datFileStruct* loader::sound_record_table;
|
||||
DatFile* loader::loader_table;
|
||||
DatFile* loader::sound_record_table;
|
||||
soundListStruct loader::sound_list[65];
|
||||
|
||||
int loader::error(int errorCode, int captionCode)
|
||||
|
@ -82,14 +82,14 @@ void loader::default_vsi(visualStruct* visual)
|
|||
visual->SoundIndex4 = 0;
|
||||
}
|
||||
|
||||
void loader::loadfrom(datFileStruct* datFile)
|
||||
void loader::loadfrom(DatFile* datFile)
|
||||
{
|
||||
loader_table = datFile;
|
||||
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 (sound_count < 65)
|
||||
|
@ -136,26 +136,27 @@ int loader::get_sound_id(int groupIndex)
|
|||
if (!sound_list[soundIndex].Loaded && !sound_list[soundIndex].WavePtr)
|
||||
{
|
||||
WaveHeader wavHeader{};
|
||||
|
||||
|
||||
int soundGroupId = sound_list[soundIndex].GroupIndex;
|
||||
sound_list[soundIndex].Duration = 0.0;
|
||||
if (soundGroupId > 0 && !pinball::quickFlag)
|
||||
{
|
||||
auto value = reinterpret_cast<int16_t*>(partman::field(loader_table, soundGroupId,
|
||||
datFieldTypes::ShortValue));
|
||||
auto value = reinterpret_cast<int16_t*>(loader_table->field(soundGroupId,
|
||||
FieldTypes::ShortValue));
|
||||
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.
|
||||
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)
|
||||
{
|
||||
// FT sounds are in SOUND subfolder
|
||||
fileName.insert(0, 1, PathSeparator);
|
||||
fileName.insert(0, "SOUND");
|
||||
}
|
||||
|
||||
|
||||
auto filePath = pinball::make_path_name(fileName);
|
||||
auto file = fopen(filePath.c_str(), "rb");
|
||||
if (file)
|
||||
|
@ -163,7 +164,7 @@ int loader::get_sound_id(int groupIndex)
|
|||
fread(&wavHeader, 1, sizeof wavHeader, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
|
||||
auto sampleCount = wavHeader.data_size / (wavHeader.channels * (wavHeader.bits_per_sample / 8.0));
|
||||
sound_list[soundIndex].Duration = static_cast<float>(sampleCount / wavHeader.sample_rate);
|
||||
sound_list[soundIndex].WavePtr = Sound::LoadWaveFile(filePath);
|
||||
|
@ -178,7 +179,7 @@ int loader::get_sound_id(int groupIndex)
|
|||
|
||||
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)
|
||||
|
@ -186,7 +187,7 @@ short loader::query_visual_states(int groupIndex)
|
|||
short result;
|
||||
if (groupIndex < 0)
|
||||
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)
|
||||
result = shortArr[1];
|
||||
else
|
||||
|
@ -202,7 +203,7 @@ char* loader::query_name(int groupIndex)
|
|||
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)
|
||||
|
@ -215,13 +216,13 @@ int16_t* loader::query_iattribute(int groupIndex, int firstValue, int* arraySize
|
|||
|
||||
for (auto skipIndex = 0;; ++skipIndex)
|
||||
{
|
||||
auto shortArr = reinterpret_cast<int16_t*>(partman::field_nth(loader_table, groupIndex,
|
||||
datFieldTypes::ShortArray, skipIndex));
|
||||
auto shortArr = reinterpret_cast<int16_t*>(loader_table->field_nth(groupIndex,
|
||||
FieldTypes::ShortArray, skipIndex));
|
||||
if (!shortArr)
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -248,8 +249,8 @@ float* loader::query_float_attribute(int groupIndex, int groupIndexOffset, int f
|
|||
|
||||
for (auto skipIndex = 0;; ++skipIndex)
|
||||
{
|
||||
auto floatArr = reinterpret_cast<float*>(partman::field_nth(loader_table, stateId, datFieldTypes::FloatArray,
|
||||
skipIndex));
|
||||
auto floatArr = reinterpret_cast<float*>(loader_table->field_nth(stateId, FieldTypes::FloatArray,
|
||||
skipIndex));
|
||||
if (!floatArr)
|
||||
break;
|
||||
if (static_cast<int16_t>(floor(*floatArr)) == firstValue)
|
||||
|
@ -277,8 +278,8 @@ float loader::query_float_attribute(int groupIndex, int groupIndexOffset, int fi
|
|||
|
||||
for (auto skipIndex = 0;; ++skipIndex)
|
||||
{
|
||||
auto floatArr = reinterpret_cast<float*>(partman::field_nth(loader_table, stateId,
|
||||
datFieldTypes::FloatArray, skipIndex));
|
||||
auto floatArr = reinterpret_cast<float*>(loader_table->field_nth(stateId,
|
||||
FieldTypes::FloatArray, skipIndex));
|
||||
if (!floatArr)
|
||||
break;
|
||||
if (static_cast<int16_t>(floor(*floatArr)) == firstValue)
|
||||
|
@ -295,16 +296,16 @@ int loader::material(int groupIndex, visualStruct* visual)
|
|||
{
|
||||
if (groupIndex < 0)
|
||||
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)
|
||||
return error(1, 21);
|
||||
if (*shortArr != 300)
|
||||
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)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (visualState <= 0)
|
||||
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)
|
||||
return error(1, 24);
|
||||
if (*shortArr != 200)
|
||||
|
@ -350,7 +351,7 @@ int loader::state_id(int groupIndex, int groupIndexOffset)
|
|||
return groupIndex;
|
||||
|
||||
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)
|
||||
return error(1, 24);
|
||||
if (*shortArr != 201)
|
||||
|
@ -362,15 +363,15 @@ int loader::kicker(int groupIndex, visualKickerStruct* kicker)
|
|||
{
|
||||
if (groupIndex < 0)
|
||||
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)
|
||||
return error(1, 20);
|
||||
if (*shortArr != 400)
|
||||
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)
|
||||
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)
|
||||
return 0;
|
||||
|
||||
|
@ -421,19 +422,13 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vis
|
|||
if (stateId < 0)
|
||||
return error(16, 18);
|
||||
|
||||
visual->Bitmap = reinterpret_cast<gdrv_bitmap8*>(partman::field(loader_table, stateId, datFieldTypes::Bitmap8bit));
|
||||
visual->ZMap = reinterpret_cast<zmap_header_type*>(partman::field(loader_table, stateId, datFieldTypes::Bitmap16bit)
|
||||
);
|
||||
if (visual->ZMap)
|
||||
{
|
||||
visual->ZMap->ZPtr1 = visual->ZMap->ZBuffer;
|
||||
visual->ZMap->ZPtr2 = visual->ZMap->ZPtr1;
|
||||
}
|
||||
visual->Bitmap = loader_table->GetBitmap(stateId);
|
||||
visual->ZMap = loader_table->GetZMap(stateId);
|
||||
|
||||
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)
|
||||
{
|
||||
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;)
|
||||
{
|
||||
switch (shortArr[0])
|
||||
|
@ -479,13 +474,13 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vis
|
|||
|
||||
if (!visual->CollisionGroup)
|
||||
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)
|
||||
return 0;
|
||||
if (*floatArr != 600.0f)
|
||||
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);
|
||||
switch (floatVal)
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "zdrv.h"
|
||||
|
||||
|
||||
struct datFileStruct;
|
||||
struct DatFile;
|
||||
|
||||
struct errorMsg
|
||||
{
|
||||
|
@ -89,7 +89,7 @@ public:
|
|||
static void default_vsi(visualStruct* visual);
|
||||
static int get_sound_id(int groupIndex);
|
||||
static void unload();
|
||||
static void loadfrom(datFileStruct* datFile);
|
||||
static void loadfrom(DatFile* datFile);
|
||||
static int query_handle(LPCSTR lpString);
|
||||
static short query_visual_states(int groupIndex);
|
||||
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 int16_t* query_iattribute(int groupIndex, int firstValue, int* arraySize);
|
||||
static float play_sound(int soundIndex);
|
||||
static datFileStruct* loader_table;
|
||||
static DatFile* loader_table;
|
||||
private:
|
||||
static errorMsg loader_errors[];
|
||||
static datFileStruct* sound_record_table;
|
||||
static DatFile* sound_record_table;
|
||||
static int sound_count;
|
||||
static int loader_sound_count;
|
||||
static soundListStruct sound_list[65];
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "render.h"
|
||||
#include "TBall.h"
|
||||
#include "timer.h"
|
||||
#include "TPinballTable.h"
|
||||
|
||||
int nudge::nudged_left;
|
||||
int nudge::nudged_right;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "memory.h"
|
||||
#include "midi.h"
|
||||
#include "pb.h"
|
||||
#include "pinball.h"
|
||||
#include "resource.h"
|
||||
#include "Sound.h"
|
||||
#include "winmain.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
#include "pinball.h"
|
||||
#include <map>
|
||||
|
||||
struct optionsStruct
|
||||
{
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "pch.h"
|
||||
#include "partman.h"
|
||||
|
||||
#include "fullscrn.h"
|
||||
#include "gdrv.h"
|
||||
#include "GroupData.h"
|
||||
#include "memory.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
|
||||
};
|
||||
|
||||
datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool fullTiltMode)
|
||||
DatFile* partman::load_records(LPCSTR lpFileName, bool fullTiltMode)
|
||||
{
|
||||
datFileHeader header{};
|
||||
dat8BitBmpHeader bmpHeader{};
|
||||
|
@ -18,35 +21,23 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
|
|||
auto fileHandle = fopen(lpFileName, "rb");
|
||||
if (fileHandle == nullptr)
|
||||
return nullptr;
|
||||
|
||||
fread(&header, 1, sizeof header, fileHandle);
|
||||
if (strcmp("PARTOUT(4.0)RESOURCE", header.FileSignature) != 0)
|
||||
{
|
||||
fclose(fileHandle);
|
||||
return nullptr;
|
||||
}
|
||||
auto datFile = memory::allocate<datFileStruct>();
|
||||
|
||||
auto datFile = new DatFile();
|
||||
if (!datFile)
|
||||
{
|
||||
fclose(fileHandle);
|
||||
return nullptr;
|
||||
}
|
||||
if (strlen(header.Description) <= 0)
|
||||
{
|
||||
datFile->Description = nullptr;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
datFile->AppName = header.AppName;
|
||||
datFile->Description = header.Description;
|
||||
|
||||
if (header.Unknown)
|
||||
{
|
||||
|
@ -54,102 +45,75 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
|
|||
if (!unknownBuf)
|
||||
{
|
||||
fclose(fileHandle);
|
||||
if (datFile->Description)
|
||||
memory::free(datFile->Description);
|
||||
memory::free(datFile);
|
||||
delete datFile;
|
||||
return nullptr;
|
||||
}
|
||||
fread(unknownBuf, 1, header.Unknown, fileHandle);
|
||||
memory::free(unknownBuf);
|
||||
}
|
||||
|
||||
auto groupDataBuf = memory::allocate<datGroupData*>(header.NumberOfGroups);
|
||||
datFile->GroupData = groupDataBuf;
|
||||
if (!groupDataBuf)
|
||||
{
|
||||
if (datFile->Description)
|
||||
memory::free(datFile->Description);
|
||||
memory::free(datFile);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
datFile->Groups.reserve(header.NumberOfGroups);
|
||||
bool abort = false;
|
||||
for (auto groupIndex = 0; !abort && groupIndex < header.NumberOfGroups; ++groupIndex)
|
||||
{
|
||||
auto entryCount = _lread_char(fileHandle);
|
||||
auto groupDataSize = entryCount <= 0 ? 0 : entryCount - 1;
|
||||
auto groupData = memory::allocate<datGroupData>(1, sizeof(datEntryData) * groupDataSize);
|
||||
datFile->GroupData[groupIndex] = groupData;
|
||||
if (!groupData)
|
||||
break;
|
||||
auto groupData = new GroupData(groupIndex);
|
||||
groupData->ReserveEntries(entryCount);
|
||||
|
||||
groupData->EntryCount = 0;
|
||||
for (auto entryIndex = 0; entryIndex < entryCount; ++entryIndex)
|
||||
{
|
||||
auto entryData = &groupData->Entries[groupData->EntryCount];
|
||||
auto entryType = static_cast<datFieldTypes>(_lread_char(fileHandle));
|
||||
auto entryData = new EntryData();
|
||||
auto entryType = static_cast<FieldTypes>(_lread_char(fileHandle));
|
||||
entryData->EntryType = entryType;
|
||||
|
||||
int fieldSize = _field_size[static_cast<int>(entryType)];
|
||||
if (fieldSize < 0)
|
||||
fieldSize = _lread_long(fileHandle);
|
||||
entryData->FieldSize = fieldSize;
|
||||
|
||||
if (entryType == datFieldTypes::Bitmap8bit)
|
||||
if (entryType == FieldTypes::Bitmap8bit)
|
||||
{
|
||||
fread(&bmpHeader, 1, sizeof(dat8BitBmpHeader), fileHandle);
|
||||
if (bmpHeader.Resolution != resolution && bmpHeader.Resolution != -1)
|
||||
{
|
||||
fseek(fileHandle, bmpHeader.Size, SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
assertm(bmpHeader.Size + sizeof(dat8BitBmpHeader) == fieldSize, "partman: Wrong bitmap field size");
|
||||
assertm(bmpHeader.Resolution >= 0 && bmpHeader.Resolution <= 2,
|
||||
"partman: bitmap resolution out of bounds");
|
||||
|
||||
auto bmp = memory::allocate<gdrv_bitmap8>();
|
||||
entryData->Buffer = reinterpret_cast<char*>(bmp);
|
||||
if (!bmp)
|
||||
if (!bmp || gdrv::create_bitmap(*bmp, bmpHeader))
|
||||
{
|
||||
abort = true;
|
||||
break;
|
||||
}
|
||||
int bmpRez;
|
||||
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);
|
||||
bmp->XPosition = bmpHeader.XPosition;
|
||||
bmp->YPosition = bmpHeader.YPosition;
|
||||
fread(bmp->IndexedBmpPtr, 1, bmpHeader.Size, fileHandle);
|
||||
}
|
||||
else if (entryType == datFieldTypes::Bitmap16bit)
|
||||
else if (entryType == FieldTypes::Bitmap16bit)
|
||||
{
|
||||
/*Full tilt has extra byte(@0:resolution) in zMap*/
|
||||
char zMapResolution = 0;
|
||||
if (fullTiltMode)
|
||||
{
|
||||
char zMapResolution = _lread_char(fileHandle);
|
||||
zMapResolution = _lread_char(fileHandle);
|
||||
fieldSize--;
|
||||
if (zMapResolution != resolution && zMapResolution != -1)
|
||||
{
|
||||
fseek(fileHandle, fieldSize, SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
assertm(zMapResolution >= 0 && zMapResolution <= 2, "partman: zMap resolution out of bounds");
|
||||
}
|
||||
|
||||
fread(&zMapHeader, 1, sizeof(dat16BitBmpHeader), fileHandle);
|
||||
int length = fieldSize - sizeof(dat16BitBmpHeader);
|
||||
|
||||
auto zmap = memory::allocate<zmap_header_type>(1, length);
|
||||
zmap->Width = zMapHeader.Width;
|
||||
zmap->Height = zMapHeader.Height;
|
||||
zmap->Stride = zMapHeader.Stride;
|
||||
fread(zmap->ZBuffer, 1, length, fileHandle);
|
||||
entryData->Buffer = reinterpret_cast<char*>(zmap);
|
||||
auto zMap = memory::allocate<zmap_header_type>();
|
||||
zdrv::create_zmap(zMap, zMapHeader.Width, zMapHeader.Height, zMapHeader.Stride);
|
||||
zMap->Resolution = zMapResolution;
|
||||
if (zMapHeader.Stride * zMapHeader.Height * 2 == length)
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -163,122 +127,19 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
|
|||
fread(entryBuffer, 1, fieldSize, fileHandle);
|
||||
}
|
||||
|
||||
entryData->FieldSize = fieldSize;
|
||||
groupData->EntryCount++;
|
||||
groupData->AddEntry(entryData);
|
||||
}
|
||||
datFile->NumberOfGroups = groupIndex + 1;
|
||||
|
||||
datFile->Groups.push_back(groupData);
|
||||
}
|
||||
|
||||
fclose(fileHandle);
|
||||
if (datFile->NumberOfGroups == header.NumberOfGroups)
|
||||
if (datFile->Groups.size() == header.NumberOfGroups)
|
||||
return datFile;
|
||||
unload_records(datFile);
|
||||
delete datFile;
|
||||
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 Buffer = 0;
|
||||
|
|
|
@ -1,29 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
enum class datFieldTypes : int16_t
|
||||
{
|
||||
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 ? )
|
||||
};
|
||||
struct zmap_header_type;
|
||||
struct gdrv_bitmap8;
|
||||
|
||||
|
||||
enum class bmp8Flags : unsigned char
|
||||
{
|
||||
|
@ -33,8 +12,7 @@ enum class bmp8Flags : unsigned char
|
|||
};
|
||||
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
#pragma pack(push, 1)
|
||||
struct datFileHeader
|
||||
{
|
||||
char FileSignature[21];
|
||||
|
@ -45,34 +23,10 @@ struct datFileHeader
|
|||
int SizeOfBody;
|
||||
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
|
||||
{
|
||||
char Resolution;
|
||||
uint8_t Resolution;
|
||||
int16_t Width;
|
||||
int16_t Height;
|
||||
int16_t XPosition;
|
||||
|
@ -80,18 +34,12 @@ struct dat8BitBmpHeader
|
|||
int Size;
|
||||
bmp8Flags Flags;
|
||||
|
||||
bool IsFlagSet(bmp8Flags flag)
|
||||
bool IsFlagSet(bmp8Flags flag) const
|
||||
{
|
||||
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
|
||||
{
|
||||
int16_t Width;
|
||||
|
@ -101,22 +49,17 @@ struct dat16BitBmpHeader
|
|||
int16_t Unknown1_0;
|
||||
int16_t Unknown1_1;
|
||||
};
|
||||
|
||||
#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");
|
||||
|
||||
|
||||
class partman
|
||||
{
|
||||
public:
|
||||
static datFileStruct* load_records(LPCSTR lpFileName, int resolution, 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);
|
||||
static struct DatFile* load_records(LPCSTR lpFileName, bool fullTiltMode);
|
||||
private:
|
||||
static short _field_size[];
|
||||
static char _lread_char(FILE* file);
|
||||
|
|
|
@ -24,9 +24,14 @@
|
|||
#include "TLightGroup.h"
|
||||
#include "TPlunger.h"
|
||||
#include "TTableLayer.h"
|
||||
#include "GroupData.h"
|
||||
#include "partman.h"
|
||||
#include "score.h"
|
||||
#include "TPinballTable.h"
|
||||
#include "TTextBox.h"
|
||||
|
||||
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_;
|
||||
float pb::time_now, pb::time_next, pb::ball_speed_limit;
|
||||
high_score_struct pb::highscore_table[5];
|
||||
|
@ -39,7 +44,7 @@ int pb::init()
|
|||
|
||||
++memory::critical_allocation;
|
||||
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;
|
||||
pinball::get_rc_int(158, &useBmpFont);
|
||||
|
@ -49,12 +54,12 @@ int pb::init()
|
|||
if (!record_table)
|
||||
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);
|
||||
|
||||
auto backgroundBmp = (gdrv_bitmap8*)partman::field_labeled(record_table, "background", datFieldTypes::Bitmap8bit);
|
||||
auto cameraInfoId = partman::record_labeled(record_table, "camera_info") + fullscrn::GetResolution();
|
||||
auto cameraInfo = (float*)partman::field(record_table, cameraInfoId, datFieldTypes::FloatArray);
|
||||
auto backgroundBmp = record_table->GetBitmap(record_table->record_labeled("background"));
|
||||
auto cameraInfoId = record_table->record_labeled("camera_info") + fullscrn::GetResolution();
|
||||
auto cameraInfo = (float*)record_table->field(cameraInfoId, FieldTypes::FloatArray);
|
||||
|
||||
/*Full tilt: table size depends on resolution*/
|
||||
auto resInfo = &fullscrn::resolution_array[fullscrn::GetResolution()];
|
||||
|
@ -84,7 +89,6 @@ int pb::init()
|
|||
0,
|
||||
0);
|
||||
|
||||
gdrv::destroy_bitmap(backgroundBmp);
|
||||
loader::loadfrom(record_table);
|
||||
|
||||
if (pinball::quickFlag)
|
||||
|
@ -108,7 +112,7 @@ int pb::uninit()
|
|||
{
|
||||
score::unload_msg_font();
|
||||
loader::unload();
|
||||
partman::unload_records(record_table);
|
||||
delete record_table;
|
||||
high_score::write(highscore_table);
|
||||
if (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;
|
||||
maths::vector_add(&ball->Acceleration, &vec2);
|
||||
ball->Speed = maths::normalize_2d(&ball->Acceleration);
|
||||
ball->InvAcceleration.X = ball->Acceleration.X == 0.0f ? 1000000000.0f : 1.0f / ball->Acceleration.X;
|
||||
ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0f ? 1000000000.0f : 1.0f / ball->Acceleration.Y;
|
||||
ball->InvAcceleration.X = ball->Acceleration.X == 0.0f ? 1.0e9f : 1.0f / ball->Acceleration.X;
|
||||
ball->InvAcceleration.Y = ball->Acceleration.Y == 0.0f ? 1.0e9f : 1.0f / ball->Acceleration.Y;
|
||||
}
|
||||
|
||||
auto timeDelta2 = timeDelta;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
#include "high_score.h"
|
||||
#include "partman.h"
|
||||
#include "TPinballTable.h"
|
||||
|
||||
class TPinballTable;
|
||||
class DatFile;
|
||||
class TBall;
|
||||
|
||||
class pb
|
||||
|
@ -11,7 +11,7 @@ public:
|
|||
static int time_ticks;
|
||||
static float ball_speed_limit, time_now, time_next;
|
||||
static int cheat_mode, game_mode;
|
||||
static datFileStruct* record_table;
|
||||
static DatFile* record_table;
|
||||
static TPinballTable* MainTable;
|
||||
static high_score_struct highscore_table[5];
|
||||
static bool FullTiltMode;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "TTextBox.h"
|
||||
|
||||
class TTextBox;
|
||||
|
||||
class pinball
|
||||
{
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "pch.h"
|
||||
#include "render.h"
|
||||
|
||||
#include "GroupData.h"
|
||||
#include "memory.h"
|
||||
#include "pb.h"
|
||||
|
||||
int render::blit = 0;
|
||||
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);
|
||||
dirty_list = memory::allocate<render_sprite_type_struct*>(1000);
|
||||
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::fill(&zscreen, zscreen.Width, zscreen.Height, 0, 0, 0xFFFF);
|
||||
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;
|
||||
while (ballBmp < &ball_bitmap[20])
|
||||
{
|
||||
gdrv::create_raw_bitmap(ballBmp, 64, 64, 1);
|
||||
gdrv::create_bitmap(ballBmp, 64, 64, 64, false);
|
||||
++ballBmp;
|
||||
}
|
||||
background_bitmap = bmp;
|
||||
|
@ -473,7 +476,7 @@ void render::paint_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];
|
||||
if (curBall->DirtyRect.Width > 0)
|
||||
|
@ -554,3 +557,95 @@ void render::build_occlude_list()
|
|||
|
||||
--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 shift(int offsetX, int offsetY, int xSrc, int ySrc, int DestWidth, int DestHeight);
|
||||
static void build_occlude_list();
|
||||
static void SpriteViewer(bool* show);
|
||||
};
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
#include "fullscrn.h"
|
||||
#include "loader.h"
|
||||
#include "memory.h"
|
||||
#include "partman.h"
|
||||
#include "GroupData.h"
|
||||
#include "pb.h"
|
||||
#include "render.h"
|
||||
#include "TDrain.h"
|
||||
#include "winmain.h"
|
||||
|
||||
// Todo: load font from file
|
||||
const uint8_t PB_MSGFT_bin[]
|
||||
|
@ -32,9 +30,9 @@ scoreStruct* score::create(LPCSTR fieldName, gdrv_bitmap8* renderBgBmp)
|
|||
score->BackgroundBmp = renderBgBmp;
|
||||
|
||||
/*Full tilt: score box dimensions index is offset by resolution*/
|
||||
auto dimensionsId = partman::record_labeled(pb::record_table, fieldName) + fullscrn::GetResolution();
|
||||
auto dimensions = reinterpret_cast<int16_t*>(partman::field(loader::loader_table, dimensionsId,
|
||||
datFieldTypes::ShortArray));
|
||||
auto dimensionsId = pb::record_table->record_labeled(fieldName) + fullscrn::GetResolution();
|
||||
auto dimensions = reinterpret_cast<int16_t*>(loader::loader_table->field( dimensionsId,
|
||||
FieldTypes::ShortArray));
|
||||
if (!dimensions)
|
||||
{
|
||||
memory::free(score);
|
||||
|
@ -48,8 +46,7 @@ scoreStruct* score::create(LPCSTR fieldName, gdrv_bitmap8* renderBgBmp)
|
|||
|
||||
for (int index = 0; index < 10; index++)
|
||||
{
|
||||
score->CharBmp[index] = reinterpret_cast<gdrv_bitmap8*>(partman::field(
|
||||
loader::loader_table, groupIndex, datFieldTypes::Bitmap8bit));
|
||||
score->CharBmp[index] = loader::loader_table->GetBitmap(groupIndex);
|
||||
++groupIndex;
|
||||
}
|
||||
return score;
|
||||
|
@ -122,7 +119,7 @@ void score::load_msg_font_3DPB(LPCSTR lpName)
|
|||
break;
|
||||
}
|
||||
|
||||
if (gdrv::create_raw_bitmap(bmp, width, height, 0))
|
||||
if (gdrv::create_bitmap(bmp, width, height, width))
|
||||
{
|
||||
memory::free(bmp);
|
||||
msg_fontp->Chars[charInd] = nullptr;
|
||||
|
@ -133,12 +130,12 @@ void score::load_msg_font_3DPB(LPCSTR lpName)
|
|||
memcpy(tmpCharBur + 3, ptrToData, sizeInBytes);
|
||||
ptrToData += sizeInBytes;
|
||||
|
||||
auto srcptr = tmpCharBur + 4;
|
||||
auto dstPtr = &bmp->BmpBufPtr1[bmp->Stride * (bmp->Height - 1)];
|
||||
auto srcPtr = tmpCharBur + 4;
|
||||
auto dstPtr = &bmp->IndexedBmpPtr[bmp->Stride * (bmp->Height - 1)];
|
||||
for (auto y = 0; y < height; ++y)
|
||||
{
|
||||
memcpy(dstPtr, srcptr, width);
|
||||
srcptr += width;
|
||||
memcpy(dstPtr, srcPtr, width);
|
||||
srcPtr += width;
|
||||
dstPtr -= bmp->Stride;
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +149,7 @@ void score::load_msg_font_FT(LPCSTR lpName)
|
|||
{
|
||||
if (!pb::record_table)
|
||||
return;
|
||||
int groupIndex = partman::record_labeled(pb::record_table, lpName);
|
||||
int groupIndex = pb::record_table->record_labeled(lpName);
|
||||
if (groupIndex < 0)
|
||||
return;
|
||||
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;
|
||||
|
||||
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)
|
||||
msg_fontp->GapWidth = gapArray[fullscrn::GetResolution()];
|
||||
else
|
||||
msg_fontp->GapWidth = 0;
|
||||
for (auto charIndex = 32; charIndex < 128; charIndex++, ++groupIndex)
|
||||
{
|
||||
auto bmp = reinterpret_cast<gdrv_bitmap8*>(partman::field(pb::record_table, groupIndex,
|
||||
datFieldTypes::Bitmap8bit));
|
||||
auto bmp = pb::record_table->GetBitmap(groupIndex);
|
||||
if (!bmp)
|
||||
break;
|
||||
if (!msg_fontp->Height)
|
||||
|
@ -181,7 +177,7 @@ void score::unload_msg_font()
|
|||
{
|
||||
if (msg_fontp)
|
||||
{
|
||||
/*3DB creates bitmaps, FT just references them from partman*/
|
||||
/*3DBP creates bitmaps, FT just references them from partman*/
|
||||
if (!pb::FullTiltMode)
|
||||
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 update(scoreStruct* score);
|
||||
static void string_format(int score, char* str);
|
||||
static void ApplyPalette();
|
||||
private :
|
||||
static void load_msg_font_3DPB(LPCSTR lpName);
|
||||
static void load_msg_font_FT(LPCSTR lpName);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "pinball.h"
|
||||
#include "options.h"
|
||||
#include "pb.h"
|
||||
#include "render.h"
|
||||
#include "Sound.h"
|
||||
#include "resource.h"
|
||||
|
||||
|
@ -36,6 +37,7 @@ gdrv_bitmap8 winmain::gfr_display{};
|
|||
std::string winmain::DatFileName;
|
||||
bool winmain::ShowAboutDialog = false;
|
||||
bool winmain::ShowImGuiDemo = false;
|
||||
bool winmain::ShowSpriteViewer = false;
|
||||
bool winmain::LaunchBallEnabled = true;
|
||||
bool winmain::HighScoresEnabled = true;
|
||||
bool winmain::DemoActive = false;
|
||||
|
@ -137,7 +139,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
|||
if (pb::init())
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not load game data",
|
||||
"The .dat file is missing", window);
|
||||
"The .dat file is missing", window);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -180,7 +182,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
|||
char buf[60];
|
||||
auto elapsedSec = static_cast<float>(curTime - prevTime) * 0.001f;
|
||||
snprintf(buf, sizeof buf, "Updates/sec = %02.02f Frames/sec = %02.02f ",
|
||||
300.0f / elapsedSec, frameCounter / elapsedSec);
|
||||
300.0f / elapsedSec, frameCounter / elapsedSec);
|
||||
SDL_SetWindowTitle(window, buf);
|
||||
frameCounter = 0;
|
||||
|
||||
|
@ -199,15 +201,14 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
|||
redGreen = i1;
|
||||
}
|
||||
|
||||
auto clr = Rgba{redGreen, redGreen, blue, 0};
|
||||
*pltPtr++ = {*reinterpret_cast<uint32_t*>(&clr)};
|
||||
*pltPtr++ = ColorRgba{Rgba{redGreen, redGreen, blue, 0}};
|
||||
}
|
||||
gdrv::display_palette(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);
|
||||
}
|
||||
}
|
||||
|
@ -254,12 +255,12 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
|||
if (gfr_display.BmpBufPtr1)
|
||||
{
|
||||
auto deltaT = now - then + 10;
|
||||
auto fillChar = static_cast<char>(deltaT);
|
||||
auto fillChar = static_cast<uint8_t>(deltaT);
|
||||
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;
|
||||
then = now;
|
||||
|
@ -329,7 +330,7 @@ void winmain::RenderUi()
|
|||
// No demo window in release to save space
|
||||
#ifndef NDEBUG
|
||||
if (ShowImGuiDemo)
|
||||
ImGui::ShowDemoWindow();
|
||||
ImGui::ShowDemoWindow(&ShowImGuiDemo);
|
||||
#endif
|
||||
|
||||
if (ImGui::BeginMainMenuBar())
|
||||
|
@ -444,6 +445,12 @@ void winmain::RenderUi()
|
|||
ShowImGuiDemo ^= true;
|
||||
}
|
||||
#endif
|
||||
if (ImGui::MenuItem("Sprite Viewer", nullptr, ShowSpriteViewer))
|
||||
{
|
||||
if (!ShowSpriteViewer && !single_step)
|
||||
pause();
|
||||
ShowSpriteViewer ^= true;
|
||||
}
|
||||
if (ImGui::MenuItem("Help Topics", "F1"))
|
||||
{
|
||||
if (!single_step)
|
||||
|
@ -465,6 +472,8 @@ void winmain::RenderUi()
|
|||
|
||||
a_dialog();
|
||||
high_score::RenderHighScoreDialog();
|
||||
if (ShowSpriteViewer)
|
||||
render::SpriteViewer(&ShowSpriteViewer);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
case SDLK_h:
|
||||
case SDLK_g:
|
||||
DispGRhistory = 1;
|
||||
break;
|
||||
case SDLK_y:
|
||||
|
@ -627,7 +636,6 @@ int winmain::event_handler(const SDL_Event* event)
|
|||
{
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
case SDL_WINDOWEVENT_TAKE_FOCUS:
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
activated = 1;
|
||||
Sound::Activate();
|
||||
|
|
|
@ -11,7 +11,7 @@ public:
|
|||
static ImGuiIO* ImIO;
|
||||
static bool LaunchBallEnabled;
|
||||
static bool HighScoresEnabled;
|
||||
static bool DemoActive;
|
||||
static bool DemoActive;
|
||||
static char* BasePath;
|
||||
|
||||
static int WinMain(LPCSTR lpCmdLine);
|
||||
|
@ -32,6 +32,7 @@ private:
|
|||
static bool restart;
|
||||
static bool ShowAboutDialog;
|
||||
static bool ShowImGuiDemo;
|
||||
static bool ShowSpriteViewer;
|
||||
|
||||
static void RenderUi();
|
||||
};
|
||||
|
|
|
@ -2,20 +2,18 @@
|
|||
#include "zdrv.h"
|
||||
#include "memory.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->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)
|
||||
|
@ -32,20 +30,22 @@ int zdrv::destroy_zmap(zmap_header_type* zmap)
|
|||
return -1;
|
||||
if (zmap->ZPtr1)
|
||||
memory::free(zmap->ZPtr1);
|
||||
if (zmap->Texture)
|
||||
SDL_DestroyTexture(zmap->Texture);
|
||||
memset(zmap, 0, sizeof(zmap_header_type));
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 x = width; x > 0; --x)
|
||||
{
|
||||
*dstPtr++ = fillWord;
|
||||
}
|
||||
dstPtr += zmap->Stride - width;
|
||||
dstPtr += zmap->Stride - width;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
zmap_header_type* srcZMap, int srcZMapXOff, int srcZMapYOff)
|
||||
{
|
||||
if (srcBmp->BitmapType == BitmapTypes::Spliced)
|
||||
{
|
||||
/*Spliced bitmap is also a zMap, how convenient*/
|
||||
paint_spliced_bmp(srcBmp->XPosition, srcBmp->YPosition, dstBmp, dstZMap, srcBmp);
|
||||
return;
|
||||
}
|
||||
assertm(srcBmp->BitmapType != BitmapTypes::Spliced, "Wrong bmp type");
|
||||
|
||||
int dstHeightAbs = abs(dstBmp->Height);
|
||||
int srcHeightAbs = abs(srcBmp->Height);
|
||||
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeightAbs - height - srcBmpYOff) + srcBmpXOff];
|
||||
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeightAbs - height - dstBmpYOff) + dstBmpXOff];
|
||||
auto srcPtrZ = &srcZMap->ZPtr1[srcZMap->Stride * (srcZMap->Height - height - srcZMapYOff) + srcZMapXOff];
|
||||
auto dstPtrZ = &dstZMap->ZPtr1[dstZMap->Stride * (dstZMap->Height - height - dstZMapYOff) + dstZMapXOff];
|
||||
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * srcBmpYOff + srcBmpXOff];
|
||||
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * dstBmpYOff + dstBmpXOff];
|
||||
auto srcPtrZ = &srcZMap->ZPtr1[srcZMap->Stride * srcZMapYOff + srcZMapXOff];
|
||||
auto dstPtrZ = &dstZMap->ZPtr1[dstZMap->Stride * dstZMapYOff + dstZMapXOff];
|
||||
|
||||
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,
|
||||
int srcBmpYOff, uint16_t depth)
|
||||
{
|
||||
int dstHeightAbs = abs(dstBmp->Height);
|
||||
int srcHeightAbs = abs(srcBmp->Height);
|
||||
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeightAbs - height - dstBmpYOff) + dstBmpXOff];
|
||||
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeightAbs - height - srcBmpYOff) + srcBmpXOff];
|
||||
auto zPtr = &zMap->ZPtr1[zMap->Stride * (zMap->Height - height - dstZMapYOff) + dstZMapXOff];
|
||||
assertm(srcBmp->BitmapType != BitmapTypes::Spliced, "Wrong bmp type");
|
||||
|
||||
auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * dstBmpYOff + dstBmpXOff];
|
||||
auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * srcBmpYOff + srcBmpXOff];
|
||||
auto zPtr = &zMap->ZPtr1[zMap->Stride * dstZMapYOff + dstZMapXOff];
|
||||
|
||||
for (int y = height; y > 0; y--)
|
||||
{
|
||||
for (int x = width; x > 0; --x)
|
||||
{
|
||||
if (*srcPtr && *zPtr > depth)
|
||||
if ((*srcPtr).Color && *zPtr > depth)
|
||||
{
|
||||
*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");
|
||||
int xOffset = xPos - pb::MainTable->XOffset;
|
||||
int yOffset = dstBmp->Height - srcBmp->Height - (yPos - pb::MainTable->YOffset);
|
||||
if (yOffset < 0)
|
||||
if (zMap.Texture)
|
||||
return;
|
||||
|
||||
auto bmpDstPtr = &dstBmp->BmpBufPtr1[xOffset + yOffset * dstBmp->Stride];
|
||||
auto zMapDstPtr = &dstZmap->ZPtr2[xOffset + yOffset * dstZmap->Stride];
|
||||
auto bmpSrcPtr = reinterpret_cast<unsigned short*>(srcBmp->BmpBufPtr1);
|
||||
auto tmpBuff = new ColorRgba[zMap.Width * zMap.Height];
|
||||
|
||||
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++);
|
||||
if (stride < 0)
|
||||
break;
|
||||
|
||||
/*Stride is in terms of dst stride, hardcoded to match vScreen width in current resolution*/
|
||||
zMapDstPtr += stride;
|
||||
bmpDstPtr += stride;
|
||||
for (auto count = *bmpSrcPtr++; count; count--)
|
||||
for (auto x = 0; x < zMap.Width; x++)
|
||||
{
|
||||
auto depth = *bmpSrcPtr++;
|
||||
auto charPtr = reinterpret_cast<char**>(&bmpSrcPtr);
|
||||
if (*zMapDstPtr >= depth)
|
||||
{
|
||||
*bmpDstPtr = **charPtr;
|
||||
*zMapDstPtr = depth;
|
||||
}
|
||||
auto depth = static_cast<uint8_t>((0xffff - *src++) / 0xff);
|
||||
color.rgba.peRed = depth;
|
||||
color.rgba.peGreen = depth;
|
||||
color.rgba.peBlue = depth;
|
||||
|
||||
(*charPtr)++;
|
||||
++zMapDstPtr;
|
||||
++bmpDstPtr;
|
||||
/*auto depth = static_cast<float>(*src++) /0xffff;
|
||||
color.rgba.peRed = (1-depth) * 0xff;
|
||||
color.rgba.peBlue = (depth) * 0xff;*/
|
||||
*dst++ = color;
|
||||
}
|
||||
src += zMap.Stride - zMap.Width;
|
||||
}
|
||||
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
|
||||
auto texture = SDL_CreateTexture
|
||||
(
|
||||
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 Height;
|
||||
int Stride;
|
||||
unsigned Resolution;
|
||||
uint16_t* ZPtr1;
|
||||
uint16_t* ZPtr2;
|
||||
uint16_t ZBuffer[1];
|
||||
SDL_Texture* Texture;
|
||||
};
|
||||
|
||||
class zdrv
|
||||
{
|
||||
public:
|
||||
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 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,
|
||||
|
@ -24,6 +24,6 @@ public:
|
|||
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,
|
||||
int srcBmpXOff, int srcBmpYOff, uint16_t depth);
|
||||
static void paint_spliced_bmp(int xPos, int yPos, gdrv_bitmap8* dstBmp, zmap_header_type* dstZmap,
|
||||
gdrv_bitmap8* srcBmp);
|
||||
static void CreatePreview(zmap_header_type& zMap);
|
||||
static void FlipZMapHorizontally(const zmap_header_type& zMap);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue