1
0
Fork 0
mirror of https://github.com/k4zmu2a/SpaceCadetPinball.git synced 2024-11-14 22:08:04 +01:00
SpaceCadetPinball/SpaceCadetPinball/partman.cpp

296 lines
7.9 KiB
C++
Raw Normal View History

2020-10-18 17:08:41 +02:00
#include "pch.h"
#include "partman.h"
2020-11-08 16:37:59 +01:00
#include "gdrv.h"
2020-11-05 16:44:34 +01:00
#include "memory.h"
#include "zdrv.h"
2020-11-05 16:44:34 +01:00
short partman::_field_size[] =
2021-01-28 16:01:26 +01:00
{
2020-10-24 17:30:45 +02:00
2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0
};
2020-10-18 17:08:41 +02:00
datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool fullTiltMode)
2020-10-18 17:08:41 +02:00
{
_OFSTRUCT ReOpenBuff{};
2021-01-28 16:01:26 +01:00
datFileHeader header{};
2020-10-24 17:30:45 +02:00
dat8BitBmpHeader bmpHeader{};
dat16BitBmpHeader zMapHeader{};
2020-10-24 17:30:45 +02:00
const HFILE fileHandle = OpenFile(lpFileName, &ReOpenBuff, 0);
2020-10-18 17:08:41 +02:00
if (fileHandle == -1)
2020-10-24 17:30:45 +02:00
return nullptr;
2021-01-28 16:01:26 +01:00
_lread(fileHandle, &header, 183u);
if (lstrcmpA("PARTOUT(4.0)RESOURCE", header.FileSignature))
2020-10-18 17:08:41 +02:00
{
_lclose(fileHandle);
2020-10-24 17:30:45 +02:00
return nullptr;
2020-10-18 17:08:41 +02:00
}
auto datFile = memory::allocate<datFileStruct>();
2020-10-18 17:08:41 +02:00
if (!datFile)
{
_lclose(fileHandle);
2020-10-24 17:30:45 +02:00
return nullptr;
2020-10-18 17:08:41 +02:00
}
2021-01-28 16:01:26 +01:00
if (lstrlenA(header.Description) <= 0)
2020-10-18 17:08:41 +02:00
{
2020-10-24 17:30:45 +02:00
datFile->Description = nullptr;
2020-10-18 17:08:41 +02:00
}
else
{
2021-01-28 16:01:26 +01:00
int lenOfStr = lstrlenA(header.Description);
auto descriptionBuf = memory::allocate(lenOfStr + 1);
2020-10-18 17:08:41 +02:00
datFile->Description = descriptionBuf;
if (!descriptionBuf)
{
_lclose(fileHandle);
2020-11-05 16:44:34 +01:00
memory::free(datFile);
2020-10-24 17:30:45 +02:00
return nullptr;
2020-10-18 17:08:41 +02:00
}
2021-01-28 16:01:26 +01:00
lstrcpyA(descriptionBuf, header.Description);
2020-10-18 17:08:41 +02:00
}
2020-10-24 17:30:45 +02:00
2021-01-28 16:01:26 +01:00
if (header.Unknown)
2020-10-18 17:08:41 +02:00
{
auto unknownBuf = memory::allocate(header.Unknown);
2020-10-18 17:08:41 +02:00
if (!unknownBuf)
{
2020-10-24 17:30:45 +02:00
_lclose(fileHandle);
if (datFile->Description)
2020-11-05 16:44:34 +01:00
memory::free(datFile->Description);
memory::free(datFile);
2020-10-24 17:30:45 +02:00
return nullptr;
2020-10-18 17:08:41 +02:00
}
2021-01-28 16:01:26 +01:00
_lread(fileHandle, static_cast<void*>(unknownBuf), header.Unknown);
2020-11-05 16:44:34 +01:00
memory::free(unknownBuf);
2020-10-18 17:08:41 +02:00
}
2020-10-24 17:30:45 +02:00
auto groupDataBuf = memory::allocate<datGroupData*>(header.NumberOfGroups);
2020-10-18 17:08:41 +02:00
datFile->GroupData = groupDataBuf;
if (!groupDataBuf)
{
if (datFile->Description)
2020-11-05 16:44:34 +01:00
memory::free(datFile->Description);
memory::free(datFile);
2020-10-24 17:30:45 +02:00
return nullptr;
2020-10-18 17:08:41 +02:00
}
2020-10-24 17:30:45 +02:00
2021-01-28 16:01:26 +01:00
bool abort = false;
for (auto groupIndex = 0; !abort && groupIndex < header.NumberOfGroups; ++groupIndex)
2020-10-24 17:30:45 +02:00
{
2021-01-28 16:01:26 +01:00
auto entryCount = _lread_char(fileHandle);
auto groupDataSize = entryCount <= 0 ? 0 : entryCount - 1;
auto groupData = memory::allocate<datGroupData>(1, sizeof(datEntryData) * groupDataSize);
2021-01-28 16:01:26 +01:00
datFile->GroupData[groupIndex] = groupData;
if (!groupData)
break;
groupData->EntryCount = 0;
2021-01-28 16:01:26 +01:00
for (auto entryIndex = 0; entryIndex < entryCount; ++entryIndex)
2020-10-24 17:30:45 +02:00
{
auto entryData = &groupData->Entries[groupData->EntryCount];
2021-01-28 16:01:26 +01:00
auto entryType = static_cast<datFieldTypes>(_lread_char(fileHandle));
entryData->EntryType = entryType;
2021-01-28 16:01:26 +01:00
int fieldSize = _field_size[static_cast<int>(entryType)];
if (fieldSize < 0)
fieldSize = _lread_long(fileHandle);
2021-01-28 16:01:26 +01:00
if (entryType == datFieldTypes::Bitmap8bit)
{
_hread(fileHandle, &bmpHeader, sizeof(dat8BitBmpHeader));
if (bmpHeader.Resolution != resolution && bmpHeader.Resolution != -1)
{
_llseek(fileHandle, bmpHeader.Size, 1);
continue;
}
auto bmp = memory::allocate<gdrv_bitmap8>();
2021-01-28 16:01:26 +01:00
entryData->Buffer = reinterpret_cast<char*>(bmp);
if (!bmp)
{
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)
2021-01-28 16:01:26 +01:00
{
abort = true;
break;
}
_hread(fileHandle, bmp->BmpBufPtr1, bmpHeader.Size);
bmp->XPosition = bmpHeader.XPosition;
bmp->YPosition = bmpHeader.YPosition;
}
else if (entryType == datFieldTypes::Bitmap16bit)
{
/*Full tilt has extra byte(@0:resolution) in zMap*/
if (fullTiltMode)
{
char zMapResolution = _lread_char(fileHandle);
fieldSize--;
if (zMapResolution != resolution && zMapResolution != -1)
{
_llseek(fileHandle, fieldSize, 1);
continue;
}
}
_hread(fileHandle, &zMapHeader, sizeof(dat16BitBmpHeader));
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;
_hread(fileHandle, zmap->ZBuffer, length);
entryData->Buffer = reinterpret_cast<char*>(zmap);
}
2020-10-24 17:30:45 +02:00
else
{
char* entryBuffer = memory::allocate(fieldSize);
2021-01-28 16:01:26 +01:00
entryData->Buffer = entryBuffer;
if (!entryBuffer)
2020-10-24 17:30:45 +02:00
{
2021-01-28 16:01:26 +01:00
abort = true;
break;
2020-10-24 17:30:45 +02:00
}
2021-01-28 16:01:26 +01:00
_hread(fileHandle, entryBuffer, fieldSize);
2020-10-24 17:30:45 +02:00
}
2021-01-28 16:01:26 +01:00
entryData->FieldSize = fieldSize;
groupData->EntryCount++;
2020-10-24 17:30:45 +02:00
}
datFile->NumberOfGroups = groupIndex + 1;
2020-10-24 17:30:45 +02:00
}
_lclose(fileHandle);
2021-01-28 16:01:26 +01:00
if (datFile->NumberOfGroups == header.NumberOfGroups)
2020-10-24 17:30:45 +02:00
return datFile;
unload_records(datFile);
return nullptr;
}
2020-10-18 17:08:41 +02:00
2020-10-24 17:30:45 +02:00
void partman::unload_records(datFileStruct* datFile)
{
for (auto groupIndex = 0; groupIndex < datFile->NumberOfGroups; ++groupIndex)
2020-10-24 17:30:45 +02:00
{
auto group = datFile->GroupData[groupIndex];
if (!group)
continue;
for (auto entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
2020-10-24 17:30:45 +02:00
{
auto entry = &group->Entries[entryIndex];
if (entry->Buffer)
2020-10-24 17:30:45 +02:00
{
if (entry->EntryType == datFieldTypes::Bitmap8bit)
gdrv::destroy_bitmap(reinterpret_cast<gdrv_bitmap8*>(entry->Buffer));
memory::free(entry->Buffer);
2020-10-24 17:30:45 +02:00
}
}
memory::free(group);
2020-10-24 17:30:45 +02:00
}
if (datFile->Description)
2020-11-05 16:44:34 +01:00
memory::free(datFile->Description);
memory::free(datFile->GroupData);
memory::free(datFile);
2020-10-24 17:30:45 +02:00
}
char* partman::field(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType)
{
auto group = datFile->GroupData[groupIndex];
for (auto entryIndex = 0; entryIndex < group->EntryCount; ++entryIndex)
2020-10-24 17:30:45 +02:00
{
auto entry = &group->Entries[entryIndex];
if (entry->EntryType == targetEntryType)
return entry->Buffer;
if (entry->EntryType > targetEntryType)
2020-10-24 17:30:45 +02:00
break;
}
return nullptr;
2020-10-24 17:30:45 +02:00
}
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)
2020-10-24 17:30:45 +02:00
{
auto entry = &group->Entries[entryIndex];
if (entry->EntryType > targetEntryType)
break;
if (entry->EntryType == targetEntryType)
if (skipCount++ == skipFirstN)
return entry->Buffer;
2020-10-24 17:30:45 +02:00
}
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)
2020-10-24 17:30:45 +02:00
{
auto entry = &group->Entries[entryIndex];
if (entry->EntryType > targetEntryType)
return 0;
if (entry->EntryType == targetEntryType)
if (skipCount++ == skipFirstN)
return entry->FieldSize;
2020-10-24 17:30:45 +02:00
}
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 = lstrlenA(targetGroupName);
for (int groupIndex = datFile->NumberOfGroups - 1; groupIndex >= 0; --groupIndex)
2020-10-24 17:30:45 +02:00
{
auto groupName = field(datFile, groupIndex, datFieldTypes::GroupName);
if (!groupName)
continue;
int index;
for (index = 0; index < targetLength; index++)
if (targetGroupName[index] != groupName[index])
2020-10-24 17:30:45 +02:00
break;
if (index == targetLength && !targetGroupName[index] && !groupName[index])
return groupIndex;
2020-10-24 17:30:45 +02:00
}
return -1;
2020-10-24 17:30:45 +02:00
}
char* partman::field_labeled(datFileStruct* datFile, LPCSTR lpString, datFieldTypes fieldType)
{
auto groupIndex = record_labeled(datFile, lpString);
return groupIndex < 0 ? nullptr : field(datFile, groupIndex, fieldType);
2020-10-18 17:08:41 +02:00
}
2020-10-24 17:30:45 +02:00
char partman::_lread_char(HFILE hFile)
{
char Buffer = 0;
_lread(hFile, &Buffer, 1u);
return Buffer;
}
int partman::_lread_long(HFILE hFile)
{
int Buffer = 0;
_lread(hFile, &Buffer, 4u);
return Buffer;
}