home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1996 by Raphael Quinet. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby
- * granted, provided that the above copyright notice appear in all
- * copies and that both that copyright notice and this permission
- * notice appear in supporting documentation. If more than a few
- * lines of this code are used in a program which displays a copyright
- * notice or credit notice, the following acknowledgment must also be
- * displayed on the same screen: "This product includes software
- * developed by Raphael Quinet for use in the Quake Editing Utilities
- * project." THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR
- * IMPLIED WARRANTY.
- *
- * More information about the QEU project can be found on the WWW:
- * "http://www.montefiore.ulg.ac.be/~quinet/games/editing.html" or by
- * mail: Raphael Quinet, 9 rue des Martyrs, B-4550 Nandrin, Belgium.
- */
-
- /*
- * Q_FILES.C - Basic file loading and saving routines.
- *
- * This file was derived from D_WADS.C (Doom Editing Utilities 5.3),
- * written by the DEU Team: Raphael Quinet, Brandon Wyber, Ted
- * Vessenes and others.
- */
-
- #include "qeu.h"
- #include "q_misc.h"
- #ifdef QEU_UNIX
- #include <sys/types.h>
- #include <sys/stat.h>
- #else
- #include <dos.h>
- #endif
- #include "q_files.h"
-
-
- /*
- * Check if a file exists and is readable.
- */
- Bool Exists(char *filename)
- {
- FILE *test;
-
- if ((test = fopen(filename, "rb")) == NULL)
- return FALSE;
- fclose(test);
- return TRUE;
- }
-
-
- /*
- * Create the directories so that a file can be created with a full path name.
- * Ignore the errors in mkdir (errors will be detected when file is created).
- */
- void CreatePathToFile(char *filename)
- {
- char *cp;
- char *path;
-
- path = QStrDup(filename);
- for (cp = path; *cp; cp++)
- if (*cp == '/' || *cp == '\\')
- {
- *cp = '\0';
- #ifdef QEU_UNIX
- if (cp != path)
- mkdir(path, 0755);
- *cp = '/';
- #else
- if (cp != path)
- mkdir(path);
- *cp = '\\';
- #endif
- }
- QFree(path);
- }
-
-
- /*
- * Convert a full path name so that it contains "\" for directories
- * under DOS and "/" under other systems.
- * The conversion is done in the string itself.
- */
- char *ConvertFilePath(char *filename)
- {
- char *cp;
-
- if (filename == NULL)
- ProgError("BUG: cannot convert a NULL pathname");
- for (cp = filename; *cp; cp++)
- if (*cp == '/' || *cp == '\\')
- {
- #ifdef QEU_DOS
- *cp = '\\';
- #else
- *cp = '/';
- #endif
- }
- return filename;
- }
-
-
- /*
- * Convert a full path name so that it contains only "/" for directories.
- * The conversion is done in the string itself.
- */
- char *UNIXifyFilePath(char *filename)
- {
- char *cp;
-
- if (filename == NULL)
- ProgError("BUG: cannot convert a NULL pathname");
- for (cp = filename; *cp; cp++)
- if (*cp == '\\')
- *cp = '/';
- return filename;
- }
-
-
- /*
- * Return a pointer to the first character of the name of a file,
- * skipping all leading directories.
- */
- char *GetBaseName(char *filename)
- {
- char *p;
-
- if (filename == NULL)
- return NULL;
- for (p = filename; *p; p++)
- if (*p == '/' || *p == '\\')
- filename = p + 1;
- return filename;
- }
-
-
- /*
- * Return a pointer to the first character of the file extension, or NULL
- * if the file name contains no dot (or if there are more than three
- * characters after the dot).
- */
- char *GetFileExtension(char *filename)
- {
- char *extp;
- char *p;
-
- if (filename == NULL)
- return NULL;
- extp = NULL;
- for (p = filename; *p; p++)
- {
- if (*p == '.')
- extp = p + 1;
- #ifdef QEU_DOS
- else if (*p == '\\')
- extp = NULL;
- #else
- else if (*p == '/')
- extp = NULL;
- #endif
- if (extp != NULL && p == extp + 3)
- extp = NULL;
- }
- return extp;
- }
-
-
- /*
- * Return a newly allocated string containing the original file name with
- * a new extension. If oldext is not NULL, the old extension of the file
- * is compared against oldext. If they differ, this function returns NULL.
- * If oldext is NULL, no check is performed.
- */
- char *ChangeFileExtension(char *filename, char *oldext, char *newext)
- {
- char *extp;
- int len;
- char *newname;
-
- if (filename == NULL || newext == NULL)
- return NULL;
- extp = GetFileExtension(filename);
- if (oldext != NULL && (extp == NULL || stricmp(extp, oldext)))
- return NULL;
- if (extp != NULL)
- len = (int)(extp - filename);
- else
- len = strlen(filename) + 1;
- newname = (char *)QMalloc(len + strlen(newext) + 1);
- if (extp != NULL)
- strncpy(newname, filename, len);
- else
- {
- strcpy(newname, filename);
- strcat(newname, ".");
- }
- strcat(newname, newext);
- return newname;
- }
-
-
- /*
- * Return the size of a file, or -1 if an error occurs.
- * The current position is reset to the beginning of the file.
- */
- Int32 GetFileSize(FILE *file)
- {
- Int32 size;
-
- if (file == NULL)
- return 0L;
- if (fseek(file, 0L, SEEK_END) < 0)
- return -1;
- size = ftell(file);
- if (size < 0)
- return -1;
- if (fseek(file, 0L, SEEK_SET) < 0)
- return -1;
- return size;
- }
-
-
- /*
- * Read bytes from a file with error checking. Read 32K chunks so that
- * we don't have problems with old DOS.
- * Returns FALSE if some error occured.
- */
- Bool ReadBytes(FILE *file, void huge *addr, UInt32 size)
- {
- while (size > 0x8000)
- {
- if (fread(addr, 1, 0x8000, file) != 0x8000)
- return FALSE;
- addr = (char huge *)addr + 0x8000;
- size -= 0x8000;
- }
- if (fread(addr, 1, size, file) != size)
- return FALSE;
- return TRUE;
- }
-
-
- /*
- * Output bytes to a binary file with error checking. Write 32K chunks so
- * that we don't have problems with old DOS.
- * Returns FALSE if some error occured.
- */
- Bool WriteBytes(FILE *file, void huge *addr, UInt32 size)
- {
- while (size > 0x8000)
- {
- if (fwrite(addr, 1, 0x8000, file) != 0x8000)
- return FALSE;
- addr = (char huge *)addr + 0x8000;
- size -= 0x8000;
- }
- if (fwrite(addr, 1, size, file) != size)
- return FALSE;
- return TRUE;
- }
-
-
- /*
- * Copy bytes from a binary file to another with error checking.
- * Returns FALSE if some error occured.
- */
- Bool CopyBytes(FILE *dest, FILE *source, UInt32 size)
- {
- void huge *data;
-
- data = QMalloc(0x8000 + 2);
- while (size > 0x8000)
- {
- if (fread(data, 1, 0x8000, source) != 0x8000)
- return FALSE;
- if (fwrite(data, 1, 0x8000, dest) != 0x8000)
- return FALSE;
- size -= 0x8000;
- }
- if (fread(data, 1, size, source) != size)
- return FALSE;
- if (fwrite(data, 1, size, dest) != size)
- return FALSE;
- QFree(data);
- return TRUE;
- }
-
-
- /*
- * Get the type of a file from its magic number (first 4 bytes). The
- * file must be open and the current position is modified. Note that
- * some file formats have a magic number which is only 2 bytes, so it
- * will be necessary to go back in the stream if such a file is read
- * with this routine.
- */
- int ReadMagic(FILE *file)
- {
- UInt8 buf[4];
-
- if (ReadBytes(file, buf, 4) == FALSE)
- return FTYPE_ERROR;
- if (!strncmp(buf, "IWAD", 4))
- return FTYPE_IWAD;
- if (!strncmp(buf, "PWAD", 4))
- return FTYPE_PWAD;
- if (!strncmp(buf, "PACK", 4))
- return FTYPE_PACK;
- if (!strncmp(buf, "WAD2", 4))
- return FTYPE_WAD2;
- if (buf[0] == 0x17 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
- return FTYPE_BSP;
- if (!strncmp(buf, "IDPO", 4))
- return FTYPE_MODEL;
- if (!strncmp(buf, "IDSP", 4))
- return FTYPE_SPRITE;
- if (!strncmp(buf, "RIFF", 4))
- return FTYPE_WAV;
- if (!strncmp(buf, ".snd", 4))
- return FTYPE_AU;
- if (buf[0] == 'P')
- {
- if (buf[1] == '1')
- return FTYPE_PBM_ASC;
- if (buf[1] == '2')
- return FTYPE_PGM_ASC;
- if (buf[1] == '3')
- return FTYPE_PPM_ASC;
- if (buf[1] == '4')
- return FTYPE_PBM_RAW;
- if (buf[1] == '5')
- return FTYPE_PGM_RAW;
- if (buf[1] == '6')
- return FTYPE_PPM_RAW;
- }
- if (buf[0] == 'B' && buf[1] == 'M')
- return FTYPE_BMP;
- if (!strncmp(buf, "GIF8", 4))
- return FTYPE_GIF;
- if (buf[0] == 0x0a && buf[1] == 0x05 && buf[2] == 0x01 && buf[3] == 0x08)
- return FTYPE_PCX;
- return FTYPE_UNKNOWN;
- }
-
-
- /*
- * Open a file and get its type from the magic number (first 4 bytes).
- * The type of the file is returned in *ftype_r, see symbols in q_files.h.
- * Returns NULL if the file cannot be opened or read.
- */
- FILE *OpenFileReadMagic(char *filename, int *ftype_r)
- {
- FILE *f;
-
- *ftype_r = FTYPE_ERROR;
- if ((f = fopen(filename, "rb")) == NULL)
- return NULL;
- *ftype_r = ReadMagic(f);
- if (*ftype_r == FTYPE_ERROR)
- {
- fclose(f);
- return NULL;
- }
- return f;
- }
-
-
- /*
- * Read and write short and long integers with endianness conversion.
- */
- #ifdef FAT_ENDIAN
- Bool ReadInt16(FILE *file, UInt16 huge *x)
- {
- if (ReadBytes(file, x, 2L) == FALSE)
- return FALSE;
- *x = SwapInt16(*x);
- return TRUE;
- }
-
- Bool ReadInt32(FILE *file, UInt32 huge *x)
- {
- if (ReadBytes(file, x, 4L) == FALSE)
- return FALSE;
- *x = SwapInt32(*x);
- return TRUE;
- }
-
- Bool ReadFloat32(FILE *file, Float32 huge *x)
- {
- if (ReadBytes(file, x, 4L) == FALSE)
- return FALSE;
- *x = SwapFloat32(*x);
- return TRUE;
- }
-
- Bool WriteInt16(FILE *file, UInt16 huge *x)
- {
- UInt16 n;
-
- n = SwapInt16(*x);
- return WriteBytes(file, &n, 2L);
- }
-
- Bool WriteInt32(FILE *file, UInt32 huge *x)
- {
- UInt32 n;
-
- n = SwapInt32(*x);
- return WriteBytes(file, &n, 4L);
- }
-
- Bool WriteFloat32(FILE *file, Float32 huge *x)
- {
- Float32 n;
-
- n = SwapFloat32(*x);
- return WriteBytes(file, &n, 4L);
- }
- #endif /* FAT_ENDIAN */
-
- /* end of file */
-