diff --git a/SpaceCadetPinball/NatvisFile.natvis b/SpaceCadetPinball/NatvisFile.natvis
index cedec29..b8dac18 100644
--- a/SpaceCadetPinball/NatvisFile.natvis
+++ b/SpaceCadetPinball/NatvisFile.natvis
@@ -23,4 +23,28 @@
+
+
+ {{ NumberOfGroups={NumberOfGroups} }}
+
+ - NumberOfGroups
+ - Description
+
+ NumberOfGroups
+ GroupData
+
+
+
+
+ {{ EntryCount={EntryCount} }}
+
+ - EntryCount
+
+ EntryCount
+ Entries
+
+
+
+
+
\ No newline at end of file
diff --git a/SpaceCadetPinball/SpaceCadetPinball.cpp b/SpaceCadetPinball/SpaceCadetPinball.cpp
index eec39fd..2dcb374 100644
--- a/SpaceCadetPinball/SpaceCadetPinball.cpp
+++ b/SpaceCadetPinball/SpaceCadetPinball.cpp
@@ -2,6 +2,7 @@
//
#include "pch.h"
+
#include
#include "objlist_class.h"
#include "partman.h"
@@ -23,6 +24,19 @@ int main()
char dataFileName[300];
partman::make_path_name(dataFileName, "PINBALL.DAT");
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);
}
diff --git a/SpaceCadetPinball/partman.cpp b/SpaceCadetPinball/partman.cpp
index f9c3ae4..6200bd2 100644
--- a/SpaceCadetPinball/partman.cpp
+++ b/SpaceCadetPinball/partman.cpp
@@ -1,80 +1,324 @@
#include "pch.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)
{
_OFSTRUCT ReOpenBuff{};
- datFileHeader Buffer;
+ datFileHeader Buffer{};
+ dat8BitBmpHeader bmpHeader{};
datFileStruct* datFile;
- HFILE fileHandle, hFile;
- int lenOfStr, groupIndex;
- unsigned short unknown;
- char* descriptionBuf, * unknownBuf, * unknownBuf2;
- char** groupDataBuf;
+ int groupIndex, groupDataSize;
+ datGroupData** groupDataBuf;
- fileHandle = OpenFile(lpFileName, &ReOpenBuff, 0);
- hFile = fileHandle;
+ const HFILE fileHandle = OpenFile(lpFileName, &ReOpenBuff, 0);
if (fileHandle == -1)
- return 0;
+ return nullptr;
_lread(fileHandle, &Buffer, 183u);
if (lstrcmpA("PARTOUT(4.0)RESOURCE", Buffer.FileSignature))
{
_lclose(fileHandle);
- return 0;
+ return nullptr;
}
- datFile = (datFileStruct*)memoryallocate(10);
+ datFile = (datFileStruct*)memoryallocate(sizeof(datFileStruct));
if (!datFile)
{
_lclose(fileHandle);
- return 0;
+ return nullptr;
}
if (lstrlenA(Buffer.Description) <= 0)
{
- datFile->Description = 0;
+ datFile->Description = nullptr;
}
else
{
- lenOfStr = lstrlenA(Buffer.Description);
- descriptionBuf = (char*)memoryallocate(lenOfStr + 1);
+ int lenOfStr = lstrlenA(Buffer.Description);
+ auto descriptionBuf = (char*)memoryallocate(lenOfStr + 1);
datFile->Description = descriptionBuf;
if (!descriptionBuf)
{
_lclose(fileHandle);
- LABEL_10:
memoryfree(datFile);
- return 0;
+ return nullptr;
}
lstrcpyA(descriptionBuf, Buffer.Description);
}
- unknown = Buffer.Unknown;
+
if (Buffer.Unknown)
{
- unknownBuf = (char*)memoryallocate(Buffer.Unknown);
- unknownBuf2 = unknownBuf;
+ auto unknownBuf = (char*)memoryallocate(Buffer.Unknown);
if (!unknownBuf)
{
- _lclose(hFile);
- goto LABEL_19;
+ _lclose(fileHandle);
+ if (datFile->Description)
+ memoryfree(datFile->Description);
+ memoryfree(datFile);
+ return nullptr;
}
- _lread(hFile, (void*)unknownBuf, unknown);
- memoryfree(unknownBuf2);
+ _lread(fileHandle, static_cast(unknownBuf), Buffer.Unknown);
+ memoryfree(unknownBuf);
}
- groupDataBuf = (char**)memoryallocate(4 * Buffer.NumberOfGroups);
+
+ groupDataBuf = (datGroupData**)memoryallocate(sizeof(void*) * Buffer.NumberOfGroups);
datFile->GroupData = groupDataBuf;
if (!groupDataBuf)
{
- LABEL_19:
if (datFile->Description)
memoryfree(datFile->Description);
- goto LABEL_10;
+ memoryfree(datFile);
+ return nullptr;
}
+
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(_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, "?");
return 1;
-}
\ No newline at end of file
+}
+
+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;
+}
diff --git a/SpaceCadetPinball/partman.h b/SpaceCadetPinball/partman.h
index 01a5189..2b1decf 100644
--- a/SpaceCadetPinball/partman.h
+++ b/SpaceCadetPinball/partman.h
@@ -1,8 +1,33 @@
#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(1)
-struct datFileHeader
+struct datFileHeader
{
char FileSignature[21];
char AppName[50];
@@ -15,44 +40,60 @@ struct datFileHeader
#pragma pack(pop)
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
{
unsigned short NumberOfGroups;
char* Description;
- char** GroupData;
+ datGroupData** GroupData;
};
-
-
-enum datFieldTypes
+#pragma pack(push)
+#pragma pack(1)
+struct dat8BitBmpHeader
{
- 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 ? )
+ char Unknown1;
+ __int16 Width;
+ __int16 Height;
+ __int16 XPosition;
+ __int16 YPosition;
+ int Size;
+ char Unknown2;
};
+#pragma pack(pop)
+static_assert(sizeof(dat8BitBmpHeader) == 14, "Wrong size of dat8BitBmpHeader");
+
+
//typedef const char* LPCSTR;
class partman
{
public:
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);
-
+
private:
static short _field_size[];
+ static char _lread_char(HFILE hFile);
+ static int _lread_long(HFILE hFile);
};
-
-
-
-
diff --git a/SpaceCadetPinball/pch.h b/SpaceCadetPinball/pch.h
index baa7afc..40ca0eb 100644
--- a/SpaceCadetPinball/pch.h
+++ b/SpaceCadetPinball/pch.h
@@ -11,8 +11,8 @@
// TODO: add headers that you want to pre-compile here
#include
-
#include
+#include
#define memoryallocate(x) malloc(x);
#define memoryfree(x) free(x);