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"
|
2021-01-29 14:42:05 +01:00
|
|
|
#include "zdrv.h"
|
2020-11-05 16:44:34 +01:00
|
|
|
|
2021-01-29 14:42:05 +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)
|
|
|
|
{
|
|
|
|
_OFSTRUCT ReOpenBuff{};
|
2021-01-28 16:01:26 +01:00
|
|
|
datFileHeader header{};
|
2020-10-24 17:30:45 +02:00
|
|
|
dat8BitBmpHeader bmpHeader{};
|
2021-01-29 14:42:05 +01:00
|
|
|
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
|
|
|
}
|
2021-01-28 16:01:26 +01:00
|
|
|
auto datFile = (datFileStruct*)memory::allocate(sizeof(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);
|
2020-11-08 16:37:59 +01:00
|
|
|
auto descriptionBuf = static_cast<char*>(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
|
|
|
{
|
2021-01-28 16:01:26 +01:00
|
|
|
auto unknownBuf = static_cast<char*>(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
|
|
|
|
2021-01-28 16:01:26 +01:00
|
|
|
auto groupDataBuf = (datGroupData**)memory::allocate(sizeof(void*) * 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 = reinterpret_cast<datGroupData*>(memory::allocate(
|
|
|
|
sizeof(datEntryData) * groupDataSize + sizeof(datGroupData)));
|
|
|
|
datFile->GroupData[groupIndex] = groupData;
|
|
|
|
if (!groupData)
|
|
|
|
break;
|
|
|
|
|
|
|
|
groupData->EntryCount = entryCount;
|
|
|
|
datEntryData* entryData = groupData->Entries;
|
|
|
|
for (auto entryIndex = 0; entryIndex < entryCount; ++entryIndex)
|
2020-10-24 17:30:45 +02:00
|
|
|
{
|
2021-01-28 16:01:26 +01:00
|
|
|
auto entryType = static_cast<datFieldTypes>(_lread_char(fileHandle));
|
|
|
|
entryData->EntryType = entryType;
|
2021-01-29 14:42:05 +01:00
|
|
|
|
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-29 14:42:05 +01:00
|
|
|
|
2021-01-28 16:01:26 +01:00
|
|
|
if (entryType == datFieldTypes::Bitmap8bit)
|
|
|
|
{
|
|
|
|
_hread(fileHandle, &bmpHeader, sizeof(dat8BitBmpHeader));
|
|
|
|
auto bmp = reinterpret_cast<gdrv_bitmap8*>(memory::allocate(sizeof(gdrv_bitmap8)));
|
|
|
|
entryData->Buffer = reinterpret_cast<char*>(bmp);
|
|
|
|
if (!bmp)
|
|
|
|
{
|
|
|
|
abort = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (bmpHeader.IsFlagSet(bmp8Flags::DibBitmap)
|
|
|
|
? gdrv::create_bitmap(bmp, bmpHeader.Width, bmpHeader.Height)
|
|
|
|
: gdrv::create_raw_bitmap(bmp, bmpHeader.Width, bmpHeader.Height,
|
|
|
|
bmpHeader.IsFlagSet(bmp8Flags::RawBmpUnaligned)))
|
|
|
|
{
|
|
|
|
abort = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
_hread(fileHandle, bmp->BmpBufPtr1, bmpHeader.Size);
|
|
|
|
bmp->XPosition = bmpHeader.XPosition;
|
|
|
|
bmp->YPosition = bmpHeader.YPosition;
|
|
|
|
}
|
2021-01-29 14:42:05 +01:00
|
|
|
else if (entryType == datFieldTypes::Bitmap16bit)
|
|
|
|
{
|
|
|
|
_hread(fileHandle, &zMapHeader, sizeof(dat16BitBmpHeader));
|
|
|
|
int length = fieldSize - sizeof(dat16BitBmpHeader);
|
|
|
|
|
|
|
|
auto zmap = reinterpret_cast<zmap_header_type*>(memory::allocate(sizeof(zmap_header_type) + 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
|
|
|
|
{
|
2021-01-28 16:01:26 +01:00
|
|
|
char* entryBuffer = static_cast<char*>(memory::allocate(fieldSize));
|
|
|
|
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;
|
|
|
|
datFile->NumberOfGroups = groupIndex + 1;
|
|
|
|
++entryData;
|
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 (int groupIndex = 0; groupIndex < datFile->NumberOfGroups; ++groupIndex)
|
|
|
|
{
|
|
|
|
datGroupData* group = datFile->GroupData[groupIndex];
|
|
|
|
if (group)
|
|
|
|
{
|
|
|
|
int entryIndex = 0;
|
|
|
|
if (group->EntryCount > 0)
|
|
|
|
{
|
|
|
|
datEntryData* entry = group->Entries;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (entry->Buffer)
|
|
|
|
{
|
2020-11-29 16:50:49 +01:00
|
|
|
if (entry->EntryType == datFieldTypes::Bitmap8bit)
|
|
|
|
gdrv::destroy_bitmap((gdrv_bitmap8*)entry->Buffer);
|
2020-11-05 16:44:34 +01:00
|
|
|
memory::free(entry->Buffer);
|
2020-10-24 17:30:45 +02:00
|
|
|
}
|
|
|
|
++entryIndex;
|
|
|
|
++entry;
|
|
|
|
}
|
|
|
|
while (entryIndex < group->EntryCount);
|
|
|
|
}
|
2020-11-05 16:44:34 +01: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)
|
|
|
|
{
|
|
|
|
datGroupData* groupData = datFile->GroupData[groupIndex];
|
|
|
|
int entryCount = groupData->EntryCount;
|
|
|
|
int entryIndex = 0;
|
|
|
|
if (entryCount <= 0)
|
|
|
|
return nullptr;
|
|
|
|
datEntryData* entry = groupData->Entries;
|
|
|
|
while (true)
|
|
|
|
{
|
2020-11-08 16:37:59 +01:00
|
|
|
auto entryType = entry->EntryType;
|
2020-10-24 17:30:45 +02:00
|
|
|
if (entryType == targetEntryType)
|
|
|
|
break;
|
|
|
|
if (entryType > targetEntryType)
|
|
|
|
return nullptr;
|
|
|
|
++entryIndex;
|
|
|
|
++entry;
|
|
|
|
if (entryIndex < entryCount)
|
|
|
|
continue;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return entry->Buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char* partman::field_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN)
|
|
|
|
{
|
|
|
|
datGroupData* groupData = datFile->GroupData[groupIndex];
|
|
|
|
int entryCount = groupData->EntryCount, skipCount = 0, entryIndex = 0;
|
|
|
|
if (0 < entryCount)
|
|
|
|
{
|
|
|
|
datEntryData* entry = groupData->Entries;
|
|
|
|
do
|
|
|
|
{
|
2020-11-08 16:37:59 +01:00
|
|
|
auto entryType = entry->EntryType;
|
2020-10-24 17:30:45 +02:00
|
|
|
if (entryType == targetEntryType)
|
|
|
|
{
|
|
|
|
if (skipCount == skipFirstN)
|
|
|
|
{
|
|
|
|
return entry->Buffer;
|
|
|
|
}
|
|
|
|
skipCount++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (targetEntryType < entryType)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
entryIndex++;
|
|
|
|
entry++;
|
|
|
|
}
|
|
|
|
while (entryIndex < entryCount);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
int partman::field_size_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN)
|
|
|
|
{
|
|
|
|
datGroupData* groupData = datFile->GroupData[groupIndex];
|
|
|
|
int entryCount = groupData->EntryCount, skipCount = 0, entryIndex = 0;
|
|
|
|
if (0 < entryCount)
|
|
|
|
{
|
|
|
|
datEntryData* entry = groupData->Entries;
|
|
|
|
do
|
|
|
|
{
|
2020-11-08 16:37:59 +01:00
|
|
|
auto entryType = entry->EntryType;
|
2020-10-24 17:30:45 +02:00
|
|
|
if (entryType == targetEntryType)
|
|
|
|
{
|
|
|
|
if (skipCount == skipFirstN)
|
|
|
|
{
|
|
|
|
return entry->FieldSize;
|
|
|
|
}
|
|
|
|
skipCount++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (targetEntryType < entryType)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
entryIndex++;
|
|
|
|
entry++;
|
|
|
|
}
|
|
|
|
while (entryIndex < entryCount);
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
int trgGroupNameLen = lstrlenA(targetGroupName);
|
|
|
|
int groupIndex = datFile->NumberOfGroups;
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (--groupIndex < 0)
|
|
|
|
return -1;
|
2020-11-08 16:37:59 +01:00
|
|
|
char* groupName = field(datFile, groupIndex, datFieldTypes::GroupName);
|
2020-10-24 17:30:45 +02:00
|
|
|
if (groupName)
|
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
bool found = trgGroupNameLen == 0;
|
|
|
|
if (trgGroupNameLen > 0)
|
|
|
|
{
|
|
|
|
LPCSTR targetNamePtr = targetGroupName;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (*targetNamePtr != targetNamePtr[groupName - targetGroupName])
|
|
|
|
break;
|
|
|
|
++index;
|
|
|
|
++targetNamePtr;
|
|
|
|
}
|
|
|
|
while (index < trgGroupNameLen);
|
|
|
|
found = index == trgGroupNameLen;
|
|
|
|
}
|
|
|
|
if (found && !targetGroupName[index] && !groupName[index])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return groupIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* partman::field_labeled(datFileStruct* datFile, LPCSTR lpString, datFieldTypes fieldType)
|
|
|
|
{
|
|
|
|
char* result;
|
|
|
|
int groupIndex = record_labeled(datFile, lpString);
|
|
|
|
if (groupIndex < 0)
|
|
|
|
result = nullptr;
|
|
|
|
else
|
|
|
|
result = field(datFile, groupIndex, fieldType);
|
|
|
|
return result;
|
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;
|
|
|
|
}
|