251 lines
9.8 KiB
C++
251 lines
9.8 KiB
C++
![]() |
/*
|
||
|
** 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 - File Caching routines *
|
||
|
* *
|
||
|
* File Name : FILECACH.CPP *
|
||
|
* *
|
||
|
* Programmer : Scott K. Bowen *
|
||
|
* *
|
||
|
* Start Date : September 13, 1993 *
|
||
|
* *
|
||
|
* Last Update : April 18, 1994 [SKB] *
|
||
|
* *
|
||
|
*-------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* Make_File_Resident -- Makes a file resident even if not flaged so. *
|
||
|
* Flush_Unused_File_Cache -- Flushes the file cache of any non opened fi*
|
||
|
* Free_Resident_File -- Free the given file if it is resident. *
|
||
|
* Unfragment_File_Cache -- Does a garbage collection on the file heap. *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
#ifndef WWSTD_H
|
||
|
#include <wwstd.h>
|
||
|
#endif
|
||
|
|
||
|
#ifndef _FILE_H
|
||
|
#include "_file.h"
|
||
|
#endif
|
||
|
|
||
|
#ifndef WWMEM_H
|
||
|
#include <wwmem.h>
|
||
|
#endif
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
/* The following PRIVATE functions are in this file: */
|
||
|
/*=========================================================================*/
|
||
|
|
||
|
|
||
|
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
|
||
|
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* UNFRAGMENT_FILE_CACHE -- Does a garbage collection on the file heap. *
|
||
|
* *
|
||
|
* INPUT: NONE. *
|
||
|
* *
|
||
|
* OUTPUT: NONE. *
|
||
|
* *
|
||
|
* WARNINGS: Can be a lengthy process. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 04/18/1994 SKB : Created. *
|
||
|
*=========================================================================*/
|
||
|
VOID Unfragment_File_Cache(VOID)
|
||
|
{
|
||
|
FileDataType *filedata;
|
||
|
FileDataType *parent;
|
||
|
UWORD idx;
|
||
|
|
||
|
|
||
|
// Let the memory system clean up the file heap.
|
||
|
Mem_Cleanup(FileCacheHeap);
|
||
|
|
||
|
// Now get our pointers back.
|
||
|
// Start after the parent PAK files since we will need to check our pointers
|
||
|
// with them.
|
||
|
filedata = &FileDataPtr[NumPAKFiles];
|
||
|
for (idx = NumPAKFiles; idx < NumPAKFiles; idx++, filedata++) {
|
||
|
while (filedata->Name) {
|
||
|
|
||
|
// Only process files that are in the file cache.
|
||
|
if (filedata->Ptr) {
|
||
|
|
||
|
// Is a inner PAK file?
|
||
|
if (filedata->Flag & FILEF_PACKED) {
|
||
|
|
||
|
parent = &FileDataPtr[filedata->Disk];
|
||
|
|
||
|
// Is it just a copied pointer of the parent?
|
||
|
if (parent->Ptr == filedata->Ptr) {
|
||
|
filedata->Ptr = Mem_Find(FileCacheHeap, filedata->Disk);
|
||
|
}
|
||
|
else
|
||
|
filedata->Ptr = Mem_Find(FileCacheHeap, idx);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
filedata->Ptr = Mem_Find(FileCacheHeap, idx);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now that the children have been taken care of, let us do the parents.
|
||
|
for (filedata = FileDataPtr, idx = 0; idx < NumPAKFiles; idx++, filedata++) {
|
||
|
|
||
|
// Only process files that are in the file cache.
|
||
|
if (filedata->Ptr) {
|
||
|
filedata->Ptr = Mem_Find(FileCacheHeap, idx);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MAKE_FILE_RESIDENT -- Makes a file resident even if not flaged so. *
|
||
|
* *
|
||
|
* INPUT: BYTE *filename - name of file to be made resident. *
|
||
|
* *
|
||
|
* OUTPUT: BOOL if successful. could fail in not enouph RAM or not found. *
|
||
|
* *
|
||
|
* WARNINGS: File must be in FileData table. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 09/13/1993 SKB : Created. *
|
||
|
*=========================================================================*/
|
||
|
BOOL Make_File_Resident(BYTE const *filename)
|
||
|
{
|
||
|
FileDataType *filedata; // Pointer to the current FileData.
|
||
|
FileDataType hold; // Hold buffer for record (DO NOT ACCESS DIRECTLY)
|
||
|
WORD fileindex;
|
||
|
WORD oldflag;
|
||
|
WORD handle;
|
||
|
|
||
|
fileindex = Find_File_Index(filename);
|
||
|
|
||
|
// if the file is not in the table, we can't make it resident
|
||
|
if (fileindex == ERROR) return(FALSE);
|
||
|
|
||
|
// Get a pointer for quicker pointer action.
|
||
|
filedata = &FileDataPtr[fileindex];
|
||
|
|
||
|
// Change the flags for a moment.
|
||
|
oldflag = filedata->Flag;
|
||
|
filedata->Flag |= FILEF_RESIDENT;
|
||
|
filedata->Flag &= ~FILEF_FLUSH;
|
||
|
|
||
|
// Make the file resident.
|
||
|
handle = Open_File(filename, READ);
|
||
|
Close_File(handle);
|
||
|
|
||
|
// Set flags back to normal.
|
||
|
filedata->Flag = oldflag;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
* Flush_Unused_File_Cache -- Flushes the file cache of any non opened files. *
|
||
|
* *
|
||
|
* INPUT: WORD flush_keep - TRUE to flush even files marked FILEF_KEEP.*
|
||
|
* *
|
||
|
* OUTPUT: WORD Number of file flushed. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 02/23/1993 SB : Created. *
|
||
|
*=========================================================================*/
|
||
|
WORD Flush_Unused_File_Cache(WORD flush_keeps)
|
||
|
{
|
||
|
WORD index;
|
||
|
WORD freed = 0;
|
||
|
FileDataType *filedata = NULL;
|
||
|
FileDataType hold; // Hold buffer for record (DO NOT ACCESS DIRECTLY)
|
||
|
|
||
|
// Loop throuph the file table looking for files that could be freed.
|
||
|
index = 0;
|
||
|
filedata = &FileDataPtr[index];;
|
||
|
while (filedata->Name && strlen(filedata->Name)) {
|
||
|
|
||
|
if (filedata->Ptr && !filedata->OpenCount &&
|
||
|
(flush_keeps || !(filedata->Flag & FILEF_KEEP)) ) {
|
||
|
|
||
|
Mem_Free(FileCacheHeap, filedata->Ptr);
|
||
|
filedata->Ptr = NULL;
|
||
|
freed++;
|
||
|
}
|
||
|
index++;
|
||
|
filedata = &FileDataPtr[index];;
|
||
|
}
|
||
|
return (freed);
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
* FREE_RESIDENT_FILE -- Free the given file if it is resident. *
|
||
|
* *
|
||
|
* INPUT: BYTE *file to free *
|
||
|
* *
|
||
|
* OUTPUT: TRUE if file was free'd, FALSE otherwise *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/22/1992 CY : Created. *
|
||
|
*=========================================================================*/
|
||
|
BOOL cdecl Free_Resident_File(BYTE const *file)
|
||
|
{
|
||
|
WORD fileindex;
|
||
|
BOOL oldflag; // Previous file flag.
|
||
|
FileDataType *filedata; // Pointer to the current FileData.
|
||
|
FileDataType hold; // Hold buffer for record (DO NOT ACCESS DIRECTLY)
|
||
|
|
||
|
|
||
|
// if the file is not in the table, we can't free it
|
||
|
if ((fileindex = Find_File_Index(file)) == ERROR) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
// get a pointer for quicker calculations.
|
||
|
filedata = &FileDataPtr[fileindex];
|
||
|
|
||
|
// If it isn't resident, don't try to Free it
|
||
|
if (filedata->Ptr == NULL) {
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
// Change the flags for a moment.
|
||
|
oldflag = filedata->Flag;
|
||
|
filedata->Flag &= ~(FILEF_RESIDENT|FILEF_KEEP);
|
||
|
filedata->Flag |= FILEF_FLUSH;
|
||
|
|
||
|
// Get the file out of Memory if it was there.
|
||
|
Close_File(Open_File(file, READ));
|
||
|
|
||
|
// Set flags back to original.
|
||
|
filedata->Flag = oldflag;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|