SpaceCadetPinball/SpaceCadetPinball/partman.cpp

142 lines
3.7 KiB
C++
Raw Permalink 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"
#include "GroupData.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
DatFile* partman::load_records(LPCSTR lpFileName, bool fullTiltMode)
2020-10-18 17:08:41 +02:00
{
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
auto fileHandle = fopenu(lpFileName, "rb");
if (fileHandle == nullptr)
2020-10-24 17:30:45 +02:00
return nullptr;
fread(&header, 1, sizeof header, fileHandle);
if (strcmp("PARTOUT(4.0)RESOURCE", header.FileSignature) != 0)
2020-10-18 17:08:41 +02:00
{
fclose(fileHandle);
2020-10-24 17:30:45 +02:00
return nullptr;
2020-10-18 17:08:41 +02:00
}
auto datFile = new DatFile();
2020-10-18 17:08:41 +02:00
if (!datFile)
{
fclose(fileHandle);
2020-10-24 17:30:45 +02:00
return nullptr;
2020-10-18 17:08:41 +02:00
}
datFile->AppName = header.AppName;
datFile->Description = header.Description;
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 = new char[header.Unknown];
2020-10-18 17:08:41 +02:00
if (!unknownBuf)
{
fclose(fileHandle);
delete datFile;
2020-10-24 17:30:45 +02:00
return nullptr;
2020-10-18 17:08:41 +02:00
}
fread(unknownBuf, 1, header.Unknown, fileHandle);
delete[] unknownBuf;
2020-10-18 17:08:41 +02:00
}
2020-10-24 17:30:45 +02:00
datFile->Groups.reserve(header.NumberOfGroups);
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
{
auto entryCount = LRead<uint8_t>(fileHandle);
auto groupData = new GroupData(groupIndex);
groupData->ReserveEntries(entryCount);
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 = new EntryData();
auto entryType = static_cast<FieldTypes>(LRead<uint8_t>(fileHandle));
2021-01-28 16:01:26 +01:00
entryData->EntryType = entryType;
int fixedSize = _field_size[static_cast<int>(entryType)];
size_t fieldSize = fixedSize >= 0 ? fixedSize : LRead<uint32_t>(fileHandle);
entryData->FieldSize = static_cast<int>(fieldSize);
if (entryType == FieldTypes::Bitmap8bit)
2021-01-28 16:01:26 +01:00
{
fread(&bmpHeader, 1, sizeof(dat8BitBmpHeader), fileHandle);
assertm(bmpHeader.Size + sizeof(dat8BitBmpHeader) == fieldSize, "partman: Wrong bitmap field size");
assertm(bmpHeader.Resolution <= 2, "partman: bitmap resolution out of bounds");
auto bmp = new gdrv_bitmap8(bmpHeader);
entryData->Buffer = reinterpret_cast<char*>(bmp);
fread(bmp->IndexedBmpPtr, 1, bmpHeader.Size, fileHandle);
2021-01-28 16:01:26 +01:00
}
else if (entryType == FieldTypes::Bitmap16bit)
{
/*Full tilt has extra byte(@0:resolution) in zMap*/
auto zMapResolution = 0u;
if (fullTiltMode)
{
zMapResolution = LRead<uint8_t>(fileHandle);
fieldSize--;
// -1 means universal resolution, maybe. FT demo .006 is the only known user.
if (zMapResolution == 0xff)
zMapResolution = 0;
assertm(zMapResolution <= 2, "partman: zMap resolution out of bounds");
}
fread(&zMapHeader, 1, sizeof(dat16BitBmpHeader), fileHandle);
auto length = fieldSize - sizeof(dat16BitBmpHeader);
2021-11-23 13:23:11 +01:00
zmap_header_type* zMap;
if (zMapHeader.Stride * zMapHeader.Height * 2u == length)
{
2021-11-23 13:23:11 +01:00
zMap = new zmap_header_type(zMapHeader.Width, zMapHeader.Height, zMapHeader.Stride);
zMap->Resolution = zMapResolution;
fread(zMap->ZPtr1, 1, length, fileHandle);
}
else
{
// 3DPB .dat has zeroed zMap headers, in groups 497 and 498, skip them.
fseek(fileHandle, static_cast<int>(length), SEEK_CUR);
2021-11-23 13:23:11 +01:00
zMap = new zmap_header_type(0, 0, 0);
}
entryData->Buffer = reinterpret_cast<char*>(zMap);
}
2020-10-24 17:30:45 +02:00
else
{
auto entryBuffer = new char[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
}
fread(entryBuffer, 1, fieldSize, fileHandle);
2020-10-24 17:30:45 +02:00
}
2021-01-28 16:01:26 +01:00
groupData->AddEntry(entryData);
2020-10-24 17:30:45 +02:00
}
datFile->Groups.push_back(groupData);
2020-10-24 17:30:45 +02:00
}
fclose(fileHandle);
if (datFile->Groups.size() == header.NumberOfGroups)
{
datFile->Finalize();
2020-10-24 17:30:45 +02:00
return datFile;
}
delete datFile;
2020-10-24 17:30:45 +02:00
return nullptr;
}