123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code 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.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /* $Header: F:\projects\c&c\vcs\code\cdfile.cpv 2.18 16 Oct 1995 16:48:10 JOE_BOSTIC $ */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Westwood Library *
- * *
- * File Name : CDFILE.CPP *
- * *
- * Programmer : Joe L. Bostic *
- * *
- * Start Date : October 18, 1994 *
- * *
- * Last Update : October 18, 1994 [JLB] *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * CDFileClass::Clear_Search_Drives -- Removes all record of a search path. *
- * CDFileClass::Open -- Opens the file object -- with path search. *
- * CDFileClass::Open -- Opens the file wherever it can be found. *
- * CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename. *
- * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- //#include "cdfile.h"
- /*
- ** Pointer to the first search path record.
- */
- CDFileClass::SearchDriveType * CDFileClass::First = 0;
- int CDFileClass::CurrentCDDrive = 0;
- int CDFileClass::LastCDDrive = 0;
- char CDFileClass::RawPath[512];
- int __cdecl Is_Disk_Inserted(int disk)
- {
- return true;
- #if (0) // ST - 12/17/2018 5:31PM
- struct find_t fb;
- char scan[] = "?:\\*.*";
- scan[0] = 'A' + disk;
- return(_dos_findfirst(scan, _A_SUBDIR, &fb) == 0);
- #endif
- }
- CDFileClass::CDFileClass(char const *filename) :
- IsDisabled(false)
- {
- Set_Name(filename);
- memset (RawPath, 0, sizeof(RawPath));
- }
- CDFileClass::CDFileClass(void) :
- IsDisabled(false)
- {
- }
- /***********************************************************************************************
- * CDFileClass::Open -- Opens the file object -- with path search. *
- * *
- * This will open the file object, but since the file object could have been constructed *
- * with a pathname, this routine will try to find the file first. For files opened for *
- * writing, then use the existing filename without performing a path search. *
- * *
- * INPUT: rights -- The access rights to use when opening the file *
- * *
- * OUTPUT: bool; Was the open successful? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/18/1994 JLB : Created. *
- *=============================================================================================*/
- int CDFileClass::Open(int rights)
- {
- return(RawFileClass::Open(rights));
- }
- /***********************************************************************************************
- * CDFC::Refresh_Search_Drives -- Updates the search path when a CD changes or is added *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 5/22/96 9:01AM ST : Created *
- *=============================================================================================*/
- void CDFileClass::Refresh_Search_Drives (void)
- {
- Clear_Search_Drives();
- Set_Search_Drives(RawPath);
- }
- /***********************************************************************************************
- * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access. *
- * *
- * This routine sets up a list of search paths to use when accessing files. The path list *
- * is scanned if the file could not be found in the current directory. This is the primary *
- * method of supporting CD-ROM drives, but is also useful for scanning network and other *
- * directories. The pathlist as passed to this routine is of the same format as the path *
- * list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.*
- * *
- * If a path entry begins with "?:" then the question mark will be replaced with the first *
- * CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path *
- * entry will be ignored. By using this feature, you can always pass the CD-ROM path *
- * specification to this routine and it will not break if the CD-ROM is not loaded (as in *
- * the case during development). *
- * *
- * Here is an example path specification: *
- * *
- * Set_Search_Drives("DATA;?:\DATA;F:\PROJECT\DATA"); *
- * *
- * In this example, the current directory will be searched first, followed by a the *
- * subdirectory "DATA" located off of the current directory. If not found, then the CD-ROM *
- * will be searched in a directory called "\DATA". If not found or the CD-ROM is not *
- * present, then it will look to the hard coded path of "F:\PROJECTS\DATA" (maybe a *
- * network?). If all of these searches fail, the file system will default to the current *
- * directory and let the normal file error system take over. *
- * *
- * INPUT: pathlist -- Pointer to string of path specifications (separated by semicolons) *
- * that will be used to search for files. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/18/1994 JLB : Created. *
- * 05/21/1996 ST : Modified to recognise multiple CD drives *
- *=============================================================================================*/
- int CDFileClass::Set_Search_Drives(char * pathlist)
- {
- int found = FALSE;
- int empty = FALSE;
- /*
- ** If there is no pathlist to add, then just return.
- */
- if (!pathlist) return(0);
- /*
- ** Save the path as it was passed in so we can parse it again later.
- ** Check for the case where RawPath was passed in.
- */
- if (pathlist != RawPath){
- strcat (RawPath, ";");
- strcat (RawPath, pathlist);
- }
- char const * ptr = strtok(pathlist, ";");
- while (ptr) {
- if (strlen(ptr)){
- char path[MAX_PATH]; // Working path buffer.
- /*
- ** Fixup the path to be legal. Legal is defined as all that is necessary to
- ** create a pathname is to append the actual filename submitted to the
- ** file system. This means that it must have either a trailing ':' or '\'
- ** character.
- */
- strcpy(path, ptr);
- switch (path[strlen(path)-1]) {
- case ':':
- case '\\':
- break;
- default:
- strcat(path, "\\");
- break;
- }
- /*
- ** If there is a drive letter specified, and this drive letter is '?', then it should
- ** be substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then
- ** merely ignore this path entry.
- */
- if (strncmp(path, "?:", 2) == 0) {
- if (CurrentCDDrive){
- found = TRUE;
- /*
- ** If the drive has a C&C CD in it then add it to the path
- */
- if (Get_CD_Index(CurrentCDDrive, 2*60) >= 0){
- path[0] = CurrentCDDrive + 'A';
- Add_Search_Drive(path);
- }
- }
- /*
- ** Find the next path string and resubmit.
- */
- ptr = strtok(NULL, ";");
- continue;
- }
- found = TRUE;
- Add_Search_Drive(path);
- }
- /*
- ** Find the next path string and resubmit.
- */
- ptr = strtok(NULL, ";");
- }
- if (!found) return(1);
- if (empty) return(2);
- return(0);
- }
- /***********************************************************************************************
- * CDFC::Set_CD_Drive -- sets the current CD drive letter *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 5/22/96 9:39AM ST : Created *
- *=============================================================================================*/
- void CDFileClass::Set_CD_Drive (int drive)
- {
- LastCDDrive = CurrentCDDrive;
- CurrentCDDrive = drive;
- }
- /***********************************************************************************************
- * CDFC::Add_Search_Drive -- Add a new path to the search path list *
- * *
- * *
- * *
- * INPUT: path *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 5/22/96 10:12AM ST : Created *
- *=============================================================================================*/
- void CDFileClass::Add_Search_Drive(char *path)
- {
- SearchDriveType *srch; // Working pointer to path object.
- /*
- ** Allocate a record structure.
- */
- srch = new SearchDriveType;
- /*
- ** Attach the path to this structure.
- */
- srch->Path = strdup(path);
- srch->Next = NULL;
- /*
- ** Attach this path record to the end of the path chain.
- */
- if (!First) {
- First = srch;
- } else {
- SearchDriveType * chain = First;
- while (chain->Next) {
- chain = (SearchDriveType *)chain->Next;
- }
- chain->Next = srch;
- }
- }
- /***********************************************************************************************
- * CDFileClass::Clear_Search_Drives -- Removes all record of a search path. *
- * *
- * Use this routine to clear out any previous path(s) set with Set_Search_Drives() *
- * function. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/18/1994 JLB : Created. *
- *=============================================================================================*/
- void CDFileClass::Clear_Search_Drives(void)
- {
- SearchDriveType * chain; // Working pointer to path chain.
- chain = First;
- while (chain) {
- SearchDriveType *next;
- next = (SearchDriveType *)chain->Next;
- if (chain->Path) {
- free((char *)chain->Path);
- }
- delete chain;
- chain = next;
- }
- First = 0;
- }
- /***********************************************************************************************
- * CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename. *
- * *
- * This routine will scan all the directories specified in the path list and if the file *
- * was found in one of the directories, it will set the filename to a composite of the *
- * correct directory and the filename. It is used to allow path searching when searching *
- * for files. Typical use is to support CD-ROM drives. This routine examines the current *
- * directory first before scanning through the path list. If after scanning the entire *
- * path list, the file still could not be found, then the file object's name is set with *
- * just the raw filename as passed to this routine. *
- * *
- * INPUT: filename -- Pointer to the filename to set as the name of this file object. *
- * *
- * OUTPUT: Returns a pointer to the final and complete filename of this file object. This *
- * may have a path attached to the file. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/18/1994 JLB : Created. *
- *=============================================================================================*/
- char const * CDFileClass::Set_Name(char const *filename)
- {
- /*
- ** Try to find the file in the current directory first. If it can be found, then
- ** just return with the normal file name setting process. Do the same if there is
- ** no multi-drive search path.
- */
- RawFileClass::Set_Name(filename);
- if (IsDisabled || !First || RawFileClass::Is_Available()) {
- return(File_Name());
- }
- /*
- ** Attempt to find the file first. Check the current directory. If not found there, then
- ** search all the path specifications available. If it still can't be found, then just
- ** fall into the normal raw file filename setting system.
- */
- SearchDriveType * srch = First;
- while (srch) {
- char path[_MAX_PATH];
- /*
- ** Build a pathname to search for.
- */
- strcpy(path, srch->Path);
- strcat(path, filename);
- /*
- ** Check to see if the file could be found. The low level Is_Available logic will
- ** prompt if necessary when the CD-ROM drive has been removed. In all other cases,
- ** it will return false and the search process will continue.
- */
- RawFileClass::Set_Name(path);
- if (RawFileClass::Is_Available()) {
- return(File_Name());
- }
- /*
- ** It wasn't found, so try the next path entry.
- */
- srch = (SearchDriveType *)srch->Next;
- }
- /*
- ** At this point, all path searching has failed. Just set the file name to the
- ** plain text passed to this routine and be done with it.
- */
- RawFileClass::Set_Name(filename);
- return(File_Name());
- }
- /***********************************************************************************************
- * CDFileClass::Open -- Opens the file wherever it can be found. *
- * *
- * This routine is similar to the RawFileClass open except that if the file is being *
- * opened only for READ access, it will search all specified directories looking for the *
- * file. If after a complete search the file still couldn't be found, then it is opened *
- * using the normal RawFileClass system -- resulting in normal error procedures. *
- * *
- * INPUT: filename -- Pointer to the override filename to supply for this file object. It *
- * would be the base filename (sans any directory specification). *
- * *
- * rights -- The access rights to use when opening the file. *
- * *
- * OUTPUT: bool; Was the file opened successfully? If so then the filename may be different *
- * than requested. The location of the file can be determined by examining the *
- * filename of this file object. The filename will contain the complete *
- * pathname used to open the file. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/18/1994 JLB : Created. *
- *=============================================================================================*/
- int CDFileClass::Open(char const *filename, int rights)
- {
- Close();
- /*
- ** Verify that there is a filename associated with this file object. If not, then this is a
- ** big error condition.
- */
- if (!filename) {
- Error(ENOENT, false);
- }
- /*
- ** If writing is requested, then multiple drive searching is not performed.
- */
- if (IsDisabled || rights == WRITE) {
- return(RawFileClass::Open(filename, rights));
- }
- /*
- ** Perform normal multiple drive searching for the filename and open
- ** using the normal procedure.
- */
- Set_Name(filename);
- return(RawFileClass::Open(rights));
- }
- #ifdef NEVER
- /* Get the drive letters if the CD's online */
- WORD __cdecl GetCDDrive(VOID)
- {
- _ES = FP_SEG(&cdDrive[0]);
- _BX = FP_OFF(&cdDrive[0]);
- _AX = 0x150d;
- geninterrupt(0x2F);
- return((WORD)(*cdDrive));
- }
- #endif
- int Get_CD_Drive(void)
- {
- #ifdef NEVER
- for (int index = 0; index < 26; index++) {
- union REGS regs;
- regs.w.ax = 0x150B;
- regs.w.bx = 0;
- regs.w.cx = index;
- int386(0x2F, ®s, ®s);
- if (regs.w.bx == 0xADAD) {
- return(index);
- }
- }
- return(0);
- #else
- // GetCDClass temp;
- // return(temp.GetCDDrive());
- return (0);
- #endif
- }
- const char *CDFileClass::Get_Search_Path(int index)
- {
- if (First == NULL) {
- return NULL;
- }
- SearchDriveType *sd = First;
- for (int i=0 ; i <= index ; i++) { // We want to loop once, even if index==0
-
- if (i == index) {
- return sd->Path;
- }
- sd = (SearchDriveType *) sd->Next;
- if (sd == NULL) {
- return NULL;
- }
- }
- return NULL;
- }
|