mirror of
https://github.com/electronicarts/CnC_Red_Alert.git
synced 2025-12-16 07:31:39 -05:00
Initial commit of Command & Conquer Red Alert source code.
This commit is contained in:
511
WIN32LIB/SRCDEBUG/FILEINIT.CPP
Normal file
511
WIN32LIB/SRCDEBUG/FILEINIT.CPP
Normal file
@@ -0,0 +1,511 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : Library - Fileio init routines. *
|
||||
* *
|
||||
* File Name : FILEINIT.C *
|
||||
* *
|
||||
* Programmer : Scott K. Bowen *
|
||||
* *
|
||||
* Start Date : September 13, 1993 *
|
||||
* *
|
||||
* Last Update : April 19, 1994 [SKB] *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* WWDOS_Init -- Initialize the fileio WWS fileio system. *
|
||||
* WWDOS_Shutdown -- Clean up any things that needs to be to exit game. *
|
||||
* Init_FileData_Table -- Initializes or reads in FileData Table. *
|
||||
* Sort_FileData_Table -- Sorts the FileData table that is in memory. *
|
||||
* Preload_Files -- Loads files marked with FILEF_PRELOAD into cache. *
|
||||
* Init_File_Cache -- Initializes and allocs the file cache heap. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
#ifndef WWSTD_H
|
||||
#include "wwstd.h"
|
||||
#endif
|
||||
|
||||
#ifndef _FILE_H
|
||||
#include "_file.h"
|
||||
#endif
|
||||
|
||||
#ifndef WWMEM_H
|
||||
#include <wwmem.h>
|
||||
#endif
|
||||
|
||||
#ifndef MISC_H
|
||||
#include <misc.h>
|
||||
#endif
|
||||
|
||||
#include <direct.h>
|
||||
#include <search.h>
|
||||
#include <string.h>
|
||||
|
||||
/*=========================================================================*/
|
||||
/* The following PRIVATE functions are in this file: */
|
||||
/*=========================================================================*/
|
||||
|
||||
PRIVATE FileInitErrorType cdecl Init_File_Cache(ULONG cachesize);
|
||||
PRIVATE FileInitErrorType cdecl Init_FileData_Table(BYTE const *filename);
|
||||
PRIVATE FileInitErrorType cdecl Set_Search_Drives( BYTE *cdpath );
|
||||
PRIVATE FileInitErrorType cdecl Preload_Files(VOID);
|
||||
PRIVATE int QSort_Comp_Func(const void *p1, const void *p2);
|
||||
PRIVATE VOID Sort_FileData_Table(VOID);
|
||||
|
||||
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* WWDOS_INIT -- Initialize the fileio WWS fileio system. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: ULONG cachesize - size wanted for the cache. *
|
||||
* BYTE *filedat - NULL or name of filedata table file. *
|
||||
* BYTE *cdpath - NULL or secondary search path on a CD. *
|
||||
* *
|
||||
* OUTPUT: Returns all errors encountered or'd together. *
|
||||
* *
|
||||
* WARNINGS: User should call the WWDOS_Init function for all file *
|
||||
* initialization. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1994 SKB : Created. *
|
||||
*=========================================================================*/
|
||||
FileInitErrorType cdecl WWDOS_Init(ULONG cachesize, BYTE *filedata, BYTE *cdpath)
|
||||
{
|
||||
// FileInitErrorType errors;
|
||||
unsigned errors ;
|
||||
|
||||
// This has not been completed yet, when it is, uncomment it and add errors.
|
||||
Install_Hard_Error_Handler () ;
|
||||
Get_Devices();
|
||||
|
||||
if (cachesize) {
|
||||
errors = Init_File_Cache(cachesize);
|
||||
} else {
|
||||
errors = FI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
errors = errors | Init_FileData_Table(filedata);
|
||||
|
||||
errors = errors | Set_Search_Drives(cdpath);
|
||||
|
||||
errors = errors | Preload_Files();
|
||||
|
||||
|
||||
return ( FileInitErrorType ) errors ;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* WWDOS_SHUTDOWN -- Clean up any things that needs to be in file syste to *
|
||||
* exit game. *
|
||||
* One could shut down the file system and open it back *
|
||||
* up with a different size cache or filetable. *
|
||||
* *
|
||||
* INPUT: NONE. *
|
||||
* *
|
||||
* OUTPUT: NONE. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1994 SKB : Created. *
|
||||
*=========================================================================*/
|
||||
VOID cdecl WWDOS_Shutdown(VOID)
|
||||
{
|
||||
FileDataType *filedata; // Pointer to the current FileData.
|
||||
WORD file_handle;
|
||||
FileHandleType *filehandletable; // Pointer to the current file handle.
|
||||
|
||||
// Close all open files.
|
||||
filehandletable = FileHandleTable;
|
||||
for (file_handle = 0; file_handle < TABLE_MAX; file_handle++, filehandletable++) {
|
||||
if (!filehandletable->Empty) {
|
||||
Close_File(file_handle);
|
||||
}
|
||||
}
|
||||
|
||||
// Free the file cache heap.
|
||||
if (FileCacheHeap) {
|
||||
|
||||
// Get a pointer to the current filedata.
|
||||
if (FileDataPtr) {
|
||||
filedata = FileDataPtr;
|
||||
} else {
|
||||
filedata = FileData;
|
||||
}
|
||||
|
||||
while(filedata->Name && filedata->Name[0]) {
|
||||
filedata->Ptr = NULL;
|
||||
filedata++;
|
||||
}
|
||||
|
||||
Free(FileCacheHeap);
|
||||
FileCacheHeap = NULL;
|
||||
}
|
||||
|
||||
// Free up the file data.
|
||||
if (FileDataPtr != FileData) {
|
||||
Free(FileDataPtr);
|
||||
}
|
||||
FileDataPtr = NULL;
|
||||
|
||||
chdir(StartPath);
|
||||
ibm_setdisk(*StartPath - 'A');
|
||||
|
||||
// This has not been completed yet, when it is, uncomment it and add errors.
|
||||
Remove_Hard_Error_Handler();
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* INIT_FILE_CACHE -- Initializes and allocs the file cache heap. *
|
||||
* *
|
||||
* INPUT: ULONG cachesize - size of heap cache.. *
|
||||
* *
|
||||
* OUTPUT: FileInitErrorType error code. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1994 SKB : Created. *
|
||||
*=========================================================================*/
|
||||
PRIVATE FileInitErrorType cdecl Init_File_Cache(ULONG cachesize)
|
||||
{
|
||||
// Allocate and initialize the file cache heap.
|
||||
if (FileCacheHeap) {
|
||||
return (FI_CACHE_ALREADY_INIT);
|
||||
}
|
||||
|
||||
if ((Ram_Free(MEM_NORMAL) >= cachesize)) {
|
||||
FileCacheHeap = Alloc(cachesize, MEM_NORMAL);
|
||||
Mem_Init(FileCacheHeap, cachesize);
|
||||
}
|
||||
|
||||
if (!FileCacheHeap) {
|
||||
return (FI_CACHE_TOO_BIG);
|
||||
}
|
||||
|
||||
return (FI_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* INIT_FILEDATA_TABLE -- Initializes or reads in FileData Table. *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: FileInitErrorType error code. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/13/1993 SKB : Created. *
|
||||
*=========================================================================*/
|
||||
PRIVATE FileInitErrorType cdecl Init_FileData_Table(BYTE const *filename)
|
||||
{
|
||||
WORD fd;
|
||||
ULONG fsize;
|
||||
FileDataType *ptr;
|
||||
WORD index;
|
||||
BYTE fname[13];
|
||||
|
||||
/*
|
||||
** Inialize the file handle table to reflect no files open.
|
||||
*/
|
||||
for (index = 0; index < TABLE_MAX; index++) {
|
||||
FileHandleTable[index].Empty = TRUE;
|
||||
}
|
||||
|
||||
// Set up our FileData ptr to be the initial FileData table.
|
||||
FileDataPtr = FileData;
|
||||
|
||||
// Sort the filedata table.
|
||||
// This needs to be done even if we load it off disk since the initial file data
|
||||
// table might contain a filename.
|
||||
Sort_FileData_Table();
|
||||
|
||||
// If there is a file name, then the filedata table will be loaded from disk.
|
||||
if (filename) {
|
||||
if (!Find_File(filename)) {
|
||||
return (FI_FILEDATA_FILE_NOT_FOUND);
|
||||
}
|
||||
fd = Open_File(filename, READ);
|
||||
|
||||
fsize = File_Size(fd);
|
||||
|
||||
if ((Ram_Free(MEM_NORMAL) < fsize)) {
|
||||
Close_File(fd);
|
||||
return (FI_FILEDATA_TOO_BIG);
|
||||
}
|
||||
|
||||
// Allocate some system memory.
|
||||
// Setup the new FileDataPtr and this time.
|
||||
FileDataPtr = ptr = (FileDataType *) Alloc(fsize, MEM_NORMAL);
|
||||
|
||||
// Load the file up into memory.
|
||||
Read_File(fd, FileDataPtr, fsize);
|
||||
Close_File(fd);
|
||||
|
||||
// Process the filetable. The filenames need their pointers adjusted.
|
||||
// At this time we will also count the number of files and number of PAK files.
|
||||
NumPAKFiles = NumFiles = 0;
|
||||
|
||||
// Make sure that the file name will have a NUL at the end.
|
||||
fname[12] = 0;
|
||||
while(TRUE) {
|
||||
// Have we reached the end of the list?
|
||||
if (!ptr->Name) break;
|
||||
|
||||
// Adjust the name pointer to point the the correct area.
|
||||
ptr->Name = (BYTE *)FileDataPtr + (LONG) ptr->Name;
|
||||
|
||||
// Count up weather it is a PAK file or a normal file.
|
||||
if (!NumFiles && strstr((char *) ptr->Name, (char *) ".PAK")) {
|
||||
NumPAKFiles++;
|
||||
|
||||
// Mark that it has been processed so that Open_File() will not do it.
|
||||
ptr->Flag |= FILEF_PROCESSED;
|
||||
|
||||
} else {
|
||||
NumFiles++;
|
||||
}
|
||||
|
||||
// Next record.
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
return (FI_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Set_Search_Drives -- Sets up the CDRom and HardDrive paths. *
|
||||
* *
|
||||
* INPUT: BYTE *cdpath - path of data files on a CD. *
|
||||
* Should pass in NULL for non CD products. *
|
||||
* *
|
||||
* OUTPUT: FileInitErrorType error code. *
|
||||
* Varibable defined: *
|
||||
* ExecPath = Full path of EXE file. *
|
||||
* StartPath = Directory user started in. *
|
||||
* DataPath = secondary search path (typically CD-ROM). *
|
||||
* Note: format of paths is "C:\PATH" *
|
||||
* *
|
||||
* WARNINGS: The cdpath may be overiden by a "-CD<path>" command line *
|
||||
* arguement that specifies another drive (HARD or CD) and path *
|
||||
* where the data resides. Whenever a file is opened, it checks *
|
||||
* the startup drive first, then the CD search path if the first *
|
||||
* search was unsuccessful. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 01/14/1993 SB : Created. *
|
||||
* 04/19/1994 SKB : Mods for 32 bit library. *
|
||||
*=========================================================================*/
|
||||
PRIVATE FileInitErrorType cdecl Set_Search_Drives( BYTE *cdpath )
|
||||
{
|
||||
BYTE *ptr;
|
||||
|
||||
|
||||
#if LIB_EXTERNS_RESOLVED
|
||||
// NOTE: THIS IS WRONG, THIS IS NOT THE WAY TO GET THE EXE's PATH.
|
||||
// Locate the executable.
|
||||
strcpy(ExecPath, _argv[0]);
|
||||
|
||||
// Find the very last '\' on the path.
|
||||
ptr = strrchr((char *) ExecPath, (int) '\\');
|
||||
#else
|
||||
ptr = NULL;
|
||||
#endif
|
||||
|
||||
// Remove the exe name to just have the path.
|
||||
if (ptr == NULL) {
|
||||
*ExecPath = 0;
|
||||
}
|
||||
else {
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
// Did the user specify a second path?
|
||||
ptr = Find_Argv("-CD");
|
||||
|
||||
// If so, set the data path to that.
|
||||
if (ptr) {
|
||||
strcpy(DataPath, ptr + 3);
|
||||
}
|
||||
// Otherwise check to see if there is a CD-Rom drive.
|
||||
else {
|
||||
if (cdpath && *cdpath) {
|
||||
|
||||
#if LIB_EXTERNS_RESOLVED
|
||||
UseCD = GetCDDrive();
|
||||
#else
|
||||
UseCD = FALSE;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
UseCD = FALSE;
|
||||
}
|
||||
|
||||
// If so, set the Drive to it and find out if any directories.
|
||||
if ( UseCD ) {
|
||||
strcpy( DataPath, "A:" );
|
||||
strcat( DataPath, cdpath);
|
||||
*DataPath = 'A'+UseCD;
|
||||
}
|
||||
// If not, set the Data path to the execacutable path.
|
||||
else {
|
||||
strcpy(DataPath, ExecPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Finnally, set the starting path.
|
||||
getcwd(StartPath, XMAXPATH);
|
||||
|
||||
// Make sure they are all uppercase.
|
||||
strupr(StartPath);
|
||||
strupr(DataPath);
|
||||
strupr(ExecPath);
|
||||
|
||||
// Change directories to the secondary search path (DataPath).
|
||||
if (*DataPath && chdir(DataPath)) {
|
||||
return (FI_SEARCH_PATH_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Lastley, Make sure we are in the startup directory. This will overide
|
||||
// the secondary data path if they are on the same drive.
|
||||
if (chdir(StartPath)) {
|
||||
return (FI_STARTUP_PATH_NOT_FOUND);
|
||||
}
|
||||
|
||||
return (FI_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* PRELOAD_FILES -- Loads files marked with FILEF_PRELOAD into cache. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: none. *
|
||||
* *
|
||||
* OUTPUT: FileInitErrorType error code. *
|
||||
* *
|
||||
* WARNINGS: The FileData must be initialized and the file heap initialized*
|
||||
* in order for this to work. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1994 SKB : Created. *
|
||||
*=========================================================================*/
|
||||
PRIVATE FileInitErrorType cdecl Preload_Files(VOID)
|
||||
{
|
||||
FileDataType *filedata; // Working file data table pointer.
|
||||
BOOL oldflag; // Previous file flag.
|
||||
|
||||
if (!FileDataPtr) {
|
||||
return (FI_FILETABLE_NOT_INIT);
|
||||
}
|
||||
|
||||
if (!FileCacheHeap) {
|
||||
return (FI_NO_CACHE_FOR_PRELOAD);
|
||||
}
|
||||
|
||||
/*
|
||||
** Make all files flagged to be made resident at startup, resident.
|
||||
*/
|
||||
filedata = FileDataPtr;
|
||||
|
||||
while (filedata->Name && strlen(filedata->Name)) {
|
||||
if (filedata->Flag & FILEF_PRELOAD) {
|
||||
|
||||
oldflag = filedata->Flag;
|
||||
filedata->Flag |= FILEF_RESIDENT; // Make it resident.
|
||||
filedata->Flag &= ~FILEF_FLUSH; // Don't purge on Close_File.
|
||||
|
||||
Close_File(Open_File(filedata->Name, READ));
|
||||
|
||||
filedata->Flag &= ~(FILEF_RESIDENT|FILEF_FLUSH); // Clear bits.
|
||||
filedata->Flag |= oldflag & (FILEF_RESIDENT|FILEF_FLUSH); // Restore bits.
|
||||
|
||||
}
|
||||
filedata++;
|
||||
}
|
||||
return (FI_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* SORT_FILEDATA_TABLE -- Sorts the FileData table that is in memory. *
|
||||
* *
|
||||
* INPUT: NONE *
|
||||
* *
|
||||
* OUTPUT: NONE. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/13/1993 SKB : Created. *
|
||||
*=========================================================================*/
|
||||
|
||||
PRIVATE int QSort_Comp_Func(const void *p1, const void *p2)
|
||||
{
|
||||
return(strcmp(((FileDataType*)p1)->Name, ((FileDataType*)p2)->Name));
|
||||
}
|
||||
PRIVATE VOID Sort_FileData_Table(VOID)
|
||||
{
|
||||
/*
|
||||
** Sort the filetable it but keep the pack file indexes correct.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The number of pak files in the file table.
|
||||
*/
|
||||
NumPAKFiles = 0;
|
||||
strupr(FileData[NumPAKFiles].Name);
|
||||
while (strstr((char *) FileData[NumPAKFiles].Name, (char *) ".PAK")) {
|
||||
strupr(FileData[NumPAKFiles].Name);
|
||||
NumPAKFiles++;
|
||||
}
|
||||
|
||||
/*
|
||||
** Count the remaining files within the file table.
|
||||
*/
|
||||
NumFiles = 0;
|
||||
while(FileData[NumFiles+NumPAKFiles].Name && FileData[NumFiles+NumPAKFiles].Name[0]) {
|
||||
strupr(FileData[NumFiles+NumPAKFiles].Name);
|
||||
NumFiles++;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sort the file entries (past the pak files).
|
||||
*/
|
||||
if (NumFiles) {
|
||||
qsort(&FileData[NumPAKFiles], NumFiles, sizeof(FileDataType), QSort_Comp_Func);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user