#include "pch.h" #include "partman.h" #include "gdrv.h" #include "GroupData.h" #include "zdrv.h" short partman::_field_size[] = { 2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 }; DatFile* partman::load_records(LPCSTR lpFileName, bool fullTiltMode) { datFileHeader header{}; dat8BitBmpHeader bmpHeader{}; dat16BitBmpHeader zMapHeader{}; auto fileHandle = fopenu(lpFileName, "rb"); if (fileHandle == nullptr) return nullptr; fread(&header, 1, sizeof header, fileHandle); if (strcmp("PARTOUT(4.0)RESOURCE", header.FileSignature) != 0) { fclose(fileHandle); return nullptr; } auto datFile = new DatFile(); if (!datFile) { fclose(fileHandle); return nullptr; } datFile->AppName = header.AppName; datFile->Description = header.Description; if (header.Unknown) { auto unknownBuf = new char[header.Unknown]; if (!unknownBuf) { fclose(fileHandle); delete datFile; return nullptr; } fread(unknownBuf, 1, header.Unknown, fileHandle); delete[] unknownBuf; } datFile->Groups.reserve(header.NumberOfGroups); bool abort = false; for (auto groupIndex = 0; !abort && groupIndex < header.NumberOfGroups; ++groupIndex) { auto entryCount = LRead(fileHandle); auto groupData = new GroupData(groupIndex); groupData->ReserveEntries(entryCount); for (auto entryIndex = 0; entryIndex < entryCount; ++entryIndex) { auto entryData = new EntryData(); auto entryType = static_cast(LRead(fileHandle)); entryData->EntryType = entryType; int fixedSize = _field_size[static_cast(entryType)]; size_t fieldSize = fixedSize >= 0 ? fixedSize : LRead(fileHandle); entryData->FieldSize = static_cast(fieldSize); if (entryType == FieldTypes::Bitmap8bit) { 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(bmp); fread(bmp->IndexedBmpPtr, 1, bmpHeader.Size, fileHandle); } else if (entryType == FieldTypes::Bitmap16bit) { /*Full tilt has extra byte(@0:resolution) in zMap*/ auto zMapResolution = 0u; if (fullTiltMode) { zMapResolution = LRead(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); zmap_header_type* zMap; if (zMapHeader.Stride * zMapHeader.Height * 2u == length) { 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(length), SEEK_CUR); zMap = new zmap_header_type(0, 0, 0); } entryData->Buffer = reinterpret_cast(zMap); } else { auto entryBuffer = new char[fieldSize]; entryData->Buffer = entryBuffer; if (!entryBuffer) { abort = true; break; } fread(entryBuffer, 1, fieldSize, fileHandle); } groupData->AddEntry(entryData); } datFile->Groups.push_back(groupData); } fclose(fileHandle); if (datFile->Groups.size() == header.NumberOfGroups) { datFile->Finalize(); return datFile; } delete datFile; return nullptr; }