Partman v2, ready.

This commit is contained in:
oz 2020-10-24 18:30:45 +03:00
parent 375db278c4
commit 7d141d2931
5 changed files with 391 additions and 54 deletions

View File

@ -23,4 +23,28 @@
</ArrayItems> </ArrayItems>
</Expand> </Expand>
</Type> </Type>
<Type Name="datFileStruct">
<DisplayString>{{ NumberOfGroups={NumberOfGroups} }}</DisplayString>
<Expand>
<Item Name="[NumberOfGroups]" ExcludeView="simple">NumberOfGroups</Item>
<Item Name="[Description]" ExcludeView="simple">Description</Item>
<ArrayItems>
<Size>NumberOfGroups</Size>
<ValuePointer>GroupData</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="datGroupData">
<DisplayString>{{ EntryCount={EntryCount} }}</DisplayString>
<Expand>
<Item Name="[EntryCount]" ExcludeView="simple">EntryCount</Item>
<ArrayItems>
<Size>EntryCount</Size>
<ValuePointer>Entries</ValuePointer>
</ArrayItems>
</Expand>
</Type>
</AutoVisualizer> </AutoVisualizer>

View File

@ -2,6 +2,7 @@
// //
#include "pch.h" #include "pch.h"
#include <iostream> #include <iostream>
#include "objlist_class.h" #include "objlist_class.h"
#include "partman.h" #include "partman.h"
@ -23,6 +24,19 @@ int main()
char dataFileName[300]; char dataFileName[300];
partman::make_path_name(dataFileName, "PINBALL.DAT"); partman::make_path_name(dataFileName, "PINBALL.DAT");
auto datFile = partman::load_records(dataFileName); auto datFile = partman::load_records(dataFileName);
assert(datFile);
assert(partman::field_size_nth(datFile, 0, String, 0) == 43);
assert(partman::field_size_nth(datFile, 2, Palette, 0) == 1024);
assert(partman::field_size_nth(datFile, 101, FloatArray, 4) == 32);
assert(strcmp(partman::field(datFile, 0, String), "3D-Pinball: Copyright 1994, Cinematronics") == 0);
assert(strcmp(partman::field(datFile, 540, 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", ShortArray), new short[2]{ 600, 416 }, 2 * 2) == 0);
//DatParser::Parse(dataFileName); //DatParser::Parse(dataFileName);
} }

View File

@ -1,80 +1,324 @@
#include "pch.h" #include "pch.h"
#include "partman.h" #include "partman.h"
short partman::_field_size[] = { 2, 0x0FFFF, 2, 0x0FFFF, 0x0FFFF, 0x0FFFF, 0x0FFFF, 0x0FFFF,0x0FFFF, 0x0FFFF, 0x0FFFF, 0x0FFFF, 0x0FFFF, 0 }; short partman::_field_size[] = {
2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0
};
datFileStruct* partman::load_records(LPCSTR lpFileName) datFileStruct* partman::load_records(LPCSTR lpFileName)
{ {
_OFSTRUCT ReOpenBuff{}; _OFSTRUCT ReOpenBuff{};
datFileHeader Buffer; datFileHeader Buffer{};
dat8BitBmpHeader bmpHeader{};
datFileStruct* datFile; datFileStruct* datFile;
HFILE fileHandle, hFile; int groupIndex, groupDataSize;
int lenOfStr, groupIndex; datGroupData** groupDataBuf;
unsigned short unknown;
char* descriptionBuf, * unknownBuf, * unknownBuf2;
char** groupDataBuf;
fileHandle = OpenFile(lpFileName, &ReOpenBuff, 0); const HFILE fileHandle = OpenFile(lpFileName, &ReOpenBuff, 0);
hFile = fileHandle;
if (fileHandle == -1) if (fileHandle == -1)
return 0; return nullptr;
_lread(fileHandle, &Buffer, 183u); _lread(fileHandle, &Buffer, 183u);
if (lstrcmpA("PARTOUT(4.0)RESOURCE", Buffer.FileSignature)) if (lstrcmpA("PARTOUT(4.0)RESOURCE", Buffer.FileSignature))
{ {
_lclose(fileHandle); _lclose(fileHandle);
return 0; return nullptr;
} }
datFile = (datFileStruct*)memoryallocate(10); datFile = (datFileStruct*)memoryallocate(sizeof(datFileStruct));
if (!datFile) if (!datFile)
{ {
_lclose(fileHandle); _lclose(fileHandle);
return 0; return nullptr;
} }
if (lstrlenA(Buffer.Description) <= 0) if (lstrlenA(Buffer.Description) <= 0)
{ {
datFile->Description = 0; datFile->Description = nullptr;
} }
else else
{ {
lenOfStr = lstrlenA(Buffer.Description); int lenOfStr = lstrlenA(Buffer.Description);
descriptionBuf = (char*)memoryallocate(lenOfStr + 1); auto descriptionBuf = (char*)memoryallocate(lenOfStr + 1);
datFile->Description = descriptionBuf; datFile->Description = descriptionBuf;
if (!descriptionBuf) if (!descriptionBuf)
{ {
_lclose(fileHandle); _lclose(fileHandle);
LABEL_10:
memoryfree(datFile); memoryfree(datFile);
return 0; return nullptr;
} }
lstrcpyA(descriptionBuf, Buffer.Description); lstrcpyA(descriptionBuf, Buffer.Description);
} }
unknown = Buffer.Unknown;
if (Buffer.Unknown) if (Buffer.Unknown)
{ {
unknownBuf = (char*)memoryallocate(Buffer.Unknown); auto unknownBuf = (char*)memoryallocate(Buffer.Unknown);
unknownBuf2 = unknownBuf;
if (!unknownBuf) if (!unknownBuf)
{ {
_lclose(hFile); _lclose(fileHandle);
goto LABEL_19; if (datFile->Description)
memoryfree(datFile->Description);
memoryfree(datFile);
return nullptr;
} }
_lread(hFile, (void*)unknownBuf, unknown); _lread(fileHandle, static_cast<void*>(unknownBuf), Buffer.Unknown);
memoryfree(unknownBuf2); memoryfree(unknownBuf);
} }
groupDataBuf = (char**)memoryallocate(4 * Buffer.NumberOfGroups);
groupDataBuf = (datGroupData**)memoryallocate(sizeof(void*) * Buffer.NumberOfGroups);
datFile->GroupData = groupDataBuf; datFile->GroupData = groupDataBuf;
if (!groupDataBuf) if (!groupDataBuf)
{ {
LABEL_19:
if (datFile->Description) if (datFile->Description)
memoryfree(datFile->Description); memoryfree(datFile->Description);
goto LABEL_10; memoryfree(datFile);
return nullptr;
} }
groupIndex = 0; groupIndex = 0;
if (Buffer.NumberOfGroups)
{
do
{
char entryCount = _lread_char(fileHandle);
if (entryCount <= 0)
groupDataSize = 0;
else
groupDataSize = entryCount - 1;
datFile->GroupData[groupIndex] = (datGroupData*)memoryallocate(
sizeof(datEntryData) * groupDataSize + sizeof(datGroupData));
datGroupData* groupData = datFile->GroupData[groupIndex];
if (!groupData)
break;
int entryIndex = 0;
groupData->EntryCount = entryCount;
if (entryCount > 0)
{
datEntryData* entryData = groupData->Entries;
do
{
auto entryType = static_cast<datFieldTypes>(_lread_char(fileHandle));
entryData->EntryType = entryType;
int fieldSize = _field_size[entryType];
if (fieldSize < 0)
{
fieldSize = _lread_long(fileHandle);
}
if (entryType == Bitmap8bit)
{
_hread(fileHandle, &bmpHeader, 14);
char* bmpBuffer = (char*)memoryallocate(0x25u);
entryData->Buffer = bmpBuffer;
if (!bmpBuffer)
goto LABEL_41;
/*if (bmpHeader.Unknown2 & 2 ? gdrv_create_bitmap((int)bmpBuffer, bmpHeader.Width, bmpHeader.Height) : gdrv_create_raw_bitmap((int)bmpBuffer, bmpHeader.Width, bmpHeader.Height, bmpHeader.Unknown2 & 1))
goto LABEL_41;*/
//_hread(fileHandle, *(LPVOID*)(entryData->Buffer + 8), bmpHeader.Size);
char* tempBuff = (char*)memoryallocate(bmpHeader.Size);
_hread(fileHandle, tempBuff, bmpHeader.Size);
memoryfree(tempBuff);
*((int*)entryData->Buffer + 29) = bmpHeader.XPosition;
*((int*)entryData->Buffer + 33) = bmpHeader.YPosition;
}
else
{
char* entryBuffer = (char*)memoryallocate(fieldSize);
entryData->Buffer = entryBuffer;
if (!entryBuffer)
goto LABEL_41;
_hread(fileHandle, entryBuffer, fieldSize);
}
++entryIndex;
entryData->FieldSize = fieldSize;
datFile->NumberOfGroups = groupIndex + 1;
++entryData;
}
while (entryIndex < entryCount);
}
++groupIndex;
}
while (groupIndex < Buffer.NumberOfGroups);
}
LABEL_41:
_lclose(fileHandle);
if (datFile->NumberOfGroups == Buffer.NumberOfGroups)
return datFile;
unload_records(datFile);
return nullptr;
}
return datFile; 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)
{
//if (HIWORD(entry->EntryType) == 1)
//gdrv_destroy_bitmap(entry->Buffer);
memoryfree(entry->Buffer);
}
++entryIndex;
++entry;
}
while (entryIndex < group->EntryCount);
}
memoryfree(group);
}
}
if (datFile->Description)
memoryfree(datFile->Description);
memoryfree(datFile->GroupData);
memoryfree(datFile);
}
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)
{
int entryType = entry->EntryType;
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
{
int entryType = entry->EntryType;
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
{
int entryType = entry->EntryType;
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;
char* groupName = field(datFile, groupIndex, GroupName);
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;
} }
@ -99,4 +343,18 @@ int partman::make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize)
} }
lstrcatA(lpFilename, "?"); lstrcatA(lpFilename, "?");
return 1; return 1;
} }
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;
}

View File

@ -1,8 +1,33 @@
#pragma once #pragma once
enum datFieldTypes : __int16
{
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 ? )
};
#pragma pack(push) #pragma pack(push)
#pragma pack(1) #pragma pack(1)
struct datFileHeader struct datFileHeader
{ {
char FileSignature[21]; char FileSignature[21];
char AppName[50]; char AppName[50];
@ -15,44 +40,60 @@ struct datFileHeader
#pragma pack(pop) #pragma pack(pop)
static_assert(sizeof(datFileHeader) == 183, "Wrong size of datFileHeader"); static_assert(sizeof(datFileHeader) == 183, "Wrong size of datFileHeader");
struct datEntryData
{
datFieldTypes EntryType;
int FieldSize;
char* Buffer;
};
struct datGroupData
{
__int16 EntryCount;
datEntryData Entries[1];
};
struct datFileStruct struct datFileStruct
{ {
unsigned short NumberOfGroups; unsigned short NumberOfGroups;
char* Description; char* Description;
char** GroupData; datGroupData** GroupData;
}; };
#pragma pack(push)
#pragma pack(1)
enum datFieldTypes struct dat8BitBmpHeader
{ {
ShortValue = 0,//, does not have the 32bits size value, but a 16bits value(see above). char Unknown1;
Bitmap8bit = 1,// 8 bpp bitmap __int16 Width;
Unknown2 = 2, __int16 Height;
GroupName = 3,// Group name __int16 XPosition;
Unknown4 = 4, __int16 YPosition;
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.) int Size;
Unknown6 = 6, char Unknown2;
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 ? )
}; };
#pragma pack(pop)
static_assert(sizeof(dat8BitBmpHeader) == 14, "Wrong size of dat8BitBmpHeader");
//typedef const char* LPCSTR; //typedef const char* LPCSTR;
class partman class partman
{ {
public: public:
static datFileStruct* load_records(LPCSTR lpFileName); static datFileStruct* load_records(LPCSTR lpFileName);
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 int make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize = 0x12Cu); static int make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize = 0x12Cu);
private: private:
static short _field_size[]; static short _field_size[];
static char _lread_char(HFILE hFile);
static int _lread_long(HFILE hFile);
}; };

View File

@ -11,8 +11,8 @@
// TODO: add headers that you want to pre-compile here // TODO: add headers that you want to pre-compile here
#include <windows.h> #include <windows.h>
#include <cstdio> #include <cstdio>
#include <assert.h>
#define memoryallocate(x) malloc(x); #define memoryallocate(x) malloc(x);
#define memoryfree(x) free(x); #define memoryfree(x) free(x);