/* ** 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 . */ /*************************************************************************** ** 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 #endif #ifndef _FILE_H #include "_file.h" #endif #ifndef WWMEM_H #include #endif #include /*=========================================================================*/ /* 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); }