Descent3/cfile/hogfile.cpp

306 lines
8.0 KiB
C++
Raw Normal View History

2024-04-16 03:43:29 +00:00
/*
* $Logfile: /DescentIII/Main/Cfile/hog.cpp $
* $Revision: 20 $
* $Date: 8/06/99 4:29p $
* $Author: Samir $
*
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
*
* $Log: /DescentIII/Main/Cfile/hog.cpp $
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 20 8/06/99 4:29p Samir
* added function to read record information for a hog file entry. needed
* from mn3edit.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 19 7/28/99 3:35p Kevin
* Mac!
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 18 5/10/99 10:25p Ardussi
* changes to compile on Mac
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 17 4/15/99 9:19p Jeff
* Changes for Linux version
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 16 2/16/99 2:08p Nate
* Made CreateNewHogFile() a bit friendlier
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 15 1/13/99 6:39a Jeff
* fixed some case-sensitive #includes
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 13 10/15/98 2:52p Nate
* Fixed FileCopy() by changing free() to mem_free()
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 12 10/08/98 4:23p Kevin
* Changed code to comply with memory library usage. Always use mem_malloc
* , mem_free and mem_strdup
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 11 8/16/98 4:23p Nate
* Added CreateNewHogFile()
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 10 8/14/98 4:38p Nate
* Fixed a few minor bugs and added better error reporting
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 9 8/14/98 1:01p Nate
* Added better error reporting for the HogEditor
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 8 7/27/98 9:48a Nate
* Fixed hog file header filling
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 7 7/24/98 6:39p Nate
* fixed hog bugs.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 6 7/20/98 3:34p Nate
* Fixed up Hog file stuff
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 5 7/13/98 6:20p Nate
* Fixed ReadHogEntry() and WriteHogEntry()
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 4 7/13/98 2:18p Nate
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 3 4/01/98 7:03p Samir
* modified some cfile stuff.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 2 3/31/98 6:13p Samir
* new hogfile format.
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
* 1 3/31/98 6:08p Samir
2024-04-16 18:56:40 +00:00
*
2024-04-16 03:43:29 +00:00
*
* $NoKeywords: $
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef MACINTOSH
2024-04-16 18:56:40 +00:00
#include <stat.h>
2024-04-16 03:43:29 +00:00
#else
2024-04-16 18:56:40 +00:00
#include <sys/stat.h>
2024-04-16 03:43:29 +00:00
#endif
#ifndef __LINUX__
2024-04-16 18:56:40 +00:00
// Non-Linux Builds
2024-04-16 03:43:29 +00:00
#include <io.h>
#else
2024-04-16 18:56:40 +00:00
// Linux Builds
2024-04-16 03:43:29 +00:00
#include "linux/linux_fix.h"
#endif
#include "byteswap.h"
#include "cfile/hogfile.h"
2024-04-16 03:43:29 +00:00
#include "pstypes.h"
#include "Macros.h"
#include "mem.h"
#include "ddio.h"
#include <algorithm>
2024-04-16 18:56:40 +00:00
/* HOG FILE FORMAT v2.0
HOG_TAG_STR [strlen()]
NFILES [int32]
HDRINFO [HOG_HDR_SIZE]
FILE_TABLE [sizeof(FILE_ENTRY) * NFILES]
FILE 0 [filelen(FILE 0)]
FILE 1 [filelen(FILE 1)]
.
.
.
FILE NFILES-1 [filelen(NFILES -1)]
2024-04-16 03:43:29 +00:00
*/
2024-04-16 18:56:40 +00:00
char hogerr_filename[PSPATHNAME_LEN]; // Used by NewHogFile() to return errors
2024-04-16 03:43:29 +00:00
////////////////////////////////////////////////////////////////////////
/* FileCopy
2024-04-16 18:56:40 +00:00
used to copy one file to another.
2024-04-16 03:43:29 +00:00
*/
2024-04-16 18:56:40 +00:00
bool FileCopy(FILE *ofp, FILE *ifp, int length) {
#define BUFFER_SIZE (1024 * 1024) // 1 meg
char *buffer;
buffer = (char *)mem_malloc(BUFFER_SIZE);
if (!buffer)
return false;
while (length) {
size_t n, read_len;
read_len = std::min(length, (int)BUFFER_SIZE);
2024-04-16 18:56:40 +00:00
n = fread(buffer, 1, read_len, ifp);
if (n != read_len) {
mem_free(buffer);
return false;
}
if (fwrite(buffer, 1, read_len, ofp) != read_len) {
mem_free(buffer);
return false;
}
length -= read_len;
}
mem_free(buffer);
return true;
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
bool ReadHogHeader(FILE *fp, tHogHeader *header) {
int res;
2024-04-16 18:56:40 +00:00
res = fread(&header->nfiles, sizeof(header->nfiles), 1, fp);
header->nfiles = INTEL_INT(header->nfiles);
res = fread(&header->file_data_offset, sizeof(header->file_data_offset), 1, fp);
header->file_data_offset = INTEL_INT(header->file_data_offset);
if (res)
return true;
else
return false;
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
bool ReadHogEntry(FILE *fp, tHogFileEntry *entry) {
int res;
res = fread(entry->name, sizeof(char), HOG_FILENAME_LEN, fp);
2024-04-16 18:56:40 +00:00
res = fread(&entry->flags, sizeof(entry->flags), 1, fp);
entry->flags = INTEL_INT(entry->flags);
res = fread(&entry->len, sizeof(entry->len), 1, fp);
entry->len = INTEL_INT(entry->len);
res = fread(&entry->timestamp, sizeof(entry->timestamp), 1, fp);
entry->timestamp = INTEL_INT(entry->timestamp);
if (res)
return true;
else
return false;
2024-04-16 03:43:29 +00:00
}
bool WriteHogEntry(FILE *fp, tHogFileEntry *entry) {
int res;
res = fwrite(entry->name, sizeof(char), HOG_FILENAME_LEN, fp);
2024-04-16 18:56:40 +00:00
res = fwrite(&entry->flags, sizeof(entry->flags), 1, fp);
res = fwrite(&entry->len, sizeof(entry->len), 1, fp);
res = fwrite(&entry->timestamp, sizeof(entry->timestamp), 1, fp);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
if (res)
return true;
else
return false;
2024-04-16 03:43:29 +00:00
}
// A modified version of NewHogFile()
2024-04-16 03:43:29 +00:00
// This one also takes a pointer to a function that will perform
// progress updates (for the user)
int NewHogFile(const char *hogname, int nfiles, const char **filenames, void (*UpdateFunction)(char *)) {
2024-04-16 18:56:40 +00:00
unsigned i;
int table_pos;
FILE *hog_fp;
tHogHeader header;
tHogFileEntry *table;
char ext[_MAX_EXT];
hogerr_filename[0] = '\0';
// allocate file table
2024-04-16 18:56:40 +00:00
if (nfiles <= 0)
return HOGMAKER_ERROR;
table = new tHogFileEntry[nfiles];
if (!table)
return HOGMAKER_MEMORY;
// create new file
hog_fp = fopen(hogname, "wb");
if (hog_fp == NULL) {
delete[] table;
strcpy(hogerr_filename, hogname);
return HOGMAKER_OPENOUTFILE;
}
// write the tag
if (!fwrite(HOG_TAG_STR, strlen(HOG_TAG_STR), 1, hog_fp)) {
delete[] table;
fclose(hog_fp);
strcpy(hogerr_filename, hogname);
return HOGMAKER_OUTFILE;
}
// write number of files
ubyte filler = 0xff;
header.nfiles = (unsigned)nfiles;
header.file_data_offset = strlen(HOG_TAG_STR) + HOG_HDR_SIZE + (sizeof(tHogFileEntry) * header.nfiles);
if (!fwrite(&header.nfiles, sizeof(header.nfiles), 1, hog_fp)) {
delete[] table;
fclose(hog_fp);
strcpy(hogerr_filename, hogname);
return HOGMAKER_OUTFILE;
}
if (!fwrite(&header.file_data_offset, sizeof(header.file_data_offset), 1, hog_fp)) {
delete[] table;
fclose(hog_fp);
strcpy(hogerr_filename, hogname);
return HOGMAKER_OUTFILE;
}
// write out filler
for (i = 0; i < HOG_HDR_SIZE - sizeof(tHogHeader); i++)
if (!fwrite(&filler, sizeof(ubyte), 1, hog_fp)) {
delete[] table;
fclose(hog_fp);
strcpy(hogerr_filename, hogname);
return HOGMAKER_OUTFILE;
}
// save file position of index table and write out dummy table
table_pos = strlen(HOG_TAG_STR) + HOG_HDR_SIZE;
memset(&table[0], 0, sizeof(table[0]));
for (i = 0; i < header.nfiles; i++) {
if (!WriteHogEntry(hog_fp, &table[0])) {
2024-04-16 18:56:40 +00:00
delete[] table;
fclose(hog_fp);
strcpy(hogerr_filename, hogname);
return HOGMAKER_OUTFILE;
}
}
// write files (& build index)
for (i = 0; i < header.nfiles; i++) {
FILE *ifp;
#if defined(__LINUX__) || defined(MACINTOSH)
struct stat mystat;
#else
struct _stat32 mystat;
#endif
ifp = fopen(filenames[i], "rb");
if (ifp == NULL) {
delete[] table;
fclose(hog_fp);
strcpy(hogerr_filename, filenames[i]);
return HOGMAKER_INFILE;
}
// using ddio_SplitPath since it is linux friendly
//_splitpath(filenames[i],NULL,NULL,table[i].name,ext);
ddio_SplitPath(filenames[i], NULL, table[i].name, ext);
_fstat32(fileno(ifp), &mystat);
strcat(table[i].name, ext);
table[i].flags = 0;
#ifdef MACINTOSH
table[i].len = mystat.st_size;
#else
table[i].len = _filelength(fileno(ifp));
#endif
table[i].timestamp = mystat.st_mtime;
if (!FileCopy(hog_fp, ifp, table[i].len)) {
delete[] table;
fclose(hog_fp);
strcpy(hogerr_filename, filenames[i]);
return HOGMAKER_COPY;
}
fclose(ifp);
if (UpdateFunction != nullptr) {
// Setup the update message and send it
char msg[256];
int ipct = int(100.0 * (double(i) / double(header.nfiles)));
sprintf(msg, "Creating Hog File... (%d%% done)", ipct);
2024-04-16 18:56:40 +00:00
UpdateFunction(msg);
}
2024-04-16 18:56:40 +00:00
}
// now write the real index
fseek(hog_fp, table_pos, SEEK_SET);
for (i = 0; i < header.nfiles; i++) {
if (!WriteHogEntry(hog_fp, &table[i])) {
2024-04-16 18:56:40 +00:00
delete[] table;
fclose(hog_fp);
strcpy(hogerr_filename, hogname);
return HOGMAKER_OUTFILE;
}
}
// cleanup
2024-04-16 18:56:40 +00:00
fclose(hog_fp);
delete[] table;
if (UpdateFunction != nullptr) {
// Setup the update message and send it
char msg[256];
sprintf(msg, "Done Creating Hog File.");
2024-04-16 18:56:40 +00:00
UpdateFunction(msg);
}
2024-04-16 18:56:40 +00:00
return HOGMAKER_OK;
2024-04-16 03:43:29 +00:00
}