static UNPKentry *wadLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount) { PHYSFS_uint32 directoryOffset; UNPKentry *entries = NULL; UNPKentry *entry = NULL; BAIL_IF_MACRO(!__PHYSFS_readAll(io, &directoryOffset, 4), ERRPASS, 0); directoryOffset = PHYSFS_swapULE32(directoryOffset); BAIL_IF_MACRO(!io->seek(io, directoryOffset), ERRPASS, 0); entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount); BAIL_IF_MACRO(!entries, PHYSFS_ERR_OUT_OF_MEMORY, NULL); for (entry = entries; fileCount > 0; fileCount--, entry++) { if (!__PHYSFS_readAll(io, &entry->startPos, 4)) goto failed; if (!__PHYSFS_readAll(io, &entry->size, 4)) goto failed; if (!__PHYSFS_readAll(io, &entry->name, 8)) goto failed; entry->name[8] = '\0'; /* name might not be null-terminated in file. */ entry->size = PHYSFS_swapULE32(entry->size); entry->startPos = PHYSFS_swapULE32(entry->startPos); } /* for */ return entries; failed: allocator.Free(entries); return NULL; } /* wadLoadEntries */
static void *QPAK_openArchive(PHYSFS_Io *io, const char *name, int forWriting) { UNPKentry *entries = NULL; PHYSFS_uint32 val = 0; PHYSFS_uint32 pos = 0; PHYSFS_uint32 count = 0; assert(io != NULL); /* shouldn't ever happen. */ BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL); BAIL_IF_MACRO(!__PHYSFS_readAll(io, &val, 4), ERRPASS, NULL); if (PHYSFS_swapULE32(val) != QPAK_SIG) BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL); BAIL_IF_MACRO(!__PHYSFS_readAll(io, &val, 4), ERRPASS, NULL); pos = PHYSFS_swapULE32(val); /* directory table offset. */ BAIL_IF_MACRO(!__PHYSFS_readAll(io, &val, 4), ERRPASS, NULL); count = PHYSFS_swapULE32(val); /* corrupted archive? */ BAIL_IF_MACRO((count % 64) != 0, PHYSFS_ERR_CORRUPT, NULL); count /= 64; BAIL_IF_MACRO(!io->seek(io, pos), ERRPASS, NULL); entries = qpakLoadEntries(io, count); BAIL_IF_MACRO(!entries, ERRPASS, NULL); return UNPK_openArchive(io, entries, count); } /* QPAK_openArchive */
static void *SLB_openArchive(PHYSFS_Io *io, const char *name, int forWriting) { PHYSFS_uint32 version; PHYSFS_uint32 count = 0; PHYSFS_uint32 tocPos = 0; UNPKentry *entries = NULL; assert(io != NULL); /* shouldn't ever happen. */ BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL); BAIL_IF_MACRO(!__PHYSFS_readAll(io, &version, sizeof(version)), ERRPASS, NULL); version = PHYSFS_swapULE32(version); BAIL_IF_MACRO(version != 0, ERRPASS, NULL); BAIL_IF_MACRO(!__PHYSFS_readAll(io, &count, sizeof(count)), ERRPASS, NULL); count = PHYSFS_swapULE32(count); /* offset of the table of contents */ BAIL_IF_MACRO(!__PHYSFS_readAll(io, &tocPos, sizeof(tocPos)), ERRPASS, NULL); tocPos = PHYSFS_swapULE32(tocPos); /* seek to the table of contents */ BAIL_IF_MACRO(!io->seek(io, tocPos), ERRPASS, NULL); entries = slbLoadEntries(io, count); BAIL_IF_MACRO(!entries, ERRPASS, NULL); return UNPK_openArchive(io, entries, count); } /* SLB_openArchive */
static UNPKentry *slbLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount) { UNPKentry *entries = NULL; UNPKentry *entry = NULL; entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount); BAIL_IF_MACRO(entries == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL); for (entry = entries; fileCount > 0; fileCount--, entry++) { char *ptr; /* don't include the '\' in the beginning */ char backslash; GOTO_IF_MACRO(!__PHYSFS_readAll(io, &backslash, 1), ERRPASS, failed); GOTO_IF_MACRO(backslash != '\\', ERRPASS, failed); /* read the rest of the buffer, 63 bytes */ GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->name, 63), ERRPASS, failed); entry->name[63] = '\0'; /* in case the name lacks the null terminator */ /* convert backslashes */ for (ptr = entry->name; *ptr; ptr++) { if (*ptr == '\\') *ptr = '/'; } /* for */ GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->startPos, 4), ERRPASS, failed); entry->startPos = PHYSFS_swapULE32(entry->startPos); GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->size, 4), ERRPASS, failed); entry->size = PHYSFS_swapULE32(entry->size); } /* for */ return entries; failed: allocator.Free(entries); return NULL; } /* slbLoadEntries */
static void *WAD_openArchive(PHYSFS_Io *io, const char *name, int forWriting) { PHYSFS_uint8 buf[4]; UNPKentry *entries = NULL; PHYSFS_uint32 count = 0; assert(io != NULL); /* shouldn't ever happen. */ BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL); BAIL_IF_MACRO(!__PHYSFS_readAll(io, buf, sizeof (buf)), ERRPASS, NULL); if ((memcmp(buf, "IWAD", 4) != 0) && (memcmp(buf, "PWAD", 4) != 0)) BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL); BAIL_IF_MACRO(!__PHYSFS_readAll(io, &count, sizeof (count)), ERRPASS, NULL); count = PHYSFS_swapULE32(count); entries = wadLoadEntries(io, count); BAIL_IF_MACRO(!entries, ERRPASS, NULL); return UNPK_openArchive(io, entries, count); } /* WAD_openArchive */
static UNPKentry *qpakLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount) { UNPKentry *entries = NULL; UNPKentry *entry = NULL; entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount); BAIL_IF_MACRO(entries == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL); for (entry = entries; fileCount > 0; fileCount--, entry++) { if (!__PHYSFS_readAll(io, &entry->name, 56)) goto failed; if (!__PHYSFS_readAll(io, &entry->startPos, 4)) goto failed; if (!__PHYSFS_readAll(io, &entry->size, 4)) goto failed; entry->size = PHYSFS_swapULE32(entry->size); entry->startPos = PHYSFS_swapULE32(entry->startPos); } /* for */ return entries; failed: allocator.Free(entries); return NULL; } /* qpakLoadEntries */