CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

CDFILE.CPP (24573B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\cdfile.cpv   2.18   16 Oct 1995 16:48:10   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  ***             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               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Westwood Library                                             *
     22  *                                                                                             *
     23  *                    File Name : CDFILE.CPP                                                   *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : October 18, 1994                                             *
     28  *                                                                                             *
     29  *                  Last Update : October 18, 1994   [JLB]                                     *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   CDFileClass::Clear_Search_Drives -- Removes all record of a search path.                  *
     34  *   CDFileClass::Open -- Opens the file object -- with path search.                           *
     35  *   CDFileClass::Open -- Opens the file wherever it can be found.                             *
     36  *   CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename.          *
     37  *   CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access.            *
     38  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     39 
     40 #include	"function.h"
     41 //#include	"cdfile.h"
     42 
     43 /*
     44 **	Pointer to the first search path record.
     45 */
     46 CDFileClass::SearchDriveType * CDFileClass::First = 0;
     47 
     48 int  CDFileClass::CurrentCDDrive = 0;
     49 int  CDFileClass::LastCDDrive = 0;
     50 char CDFileClass::RawPath[512];
     51 
     52 
     53 
     54 int __cdecl Is_Disk_Inserted(int disk)
     55 {
     56 	return true;
     57 
     58 #if (0)	// ST - 12/17/2018 5:31PM
     59 	struct find_t fb;
     60 	char	scan[] = "?:\\*.*";
     61 
     62 	scan[0] = 'A' + disk;
     63 	return(_dos_findfirst(scan, _A_SUBDIR, &fb) == 0);
     64 #endif
     65 }
     66 
     67 
     68 CDFileClass::CDFileClass(char const *filename) :
     69 	IsDisabled(false)
     70 {
     71 	Set_Name(filename);
     72 	memset (RawPath, 0, sizeof(RawPath));
     73 }
     74 
     75 
     76 CDFileClass::CDFileClass(void) :
     77 	IsDisabled(false)
     78 {
     79 }
     80 
     81 
     82 /***********************************************************************************************
     83  * CDFileClass::Open -- Opens the file object -- with path search.                             *
     84  *                                                                                             *
     85  *    This will open the file object, but since the file object could have been constructed    *
     86  *    with a pathname, this routine will try to find the file first. For files opened for      *
     87  *    writing, then use the existing filename without performing a path search.                *
     88  *                                                                                             *
     89  * INPUT:   rights   -- The access rights to use when opening the file                         *
     90  *                                                                                             *
     91  * OUTPUT:  bool; Was the open successful?                                                     *
     92  *                                                                                             *
     93  * WARNINGS:   none                                                                            *
     94  *                                                                                             *
     95  * HISTORY:                                                                                    *
     96  *   10/18/1994 JLB : Created.                                                                 *
     97  *=============================================================================================*/
     98 int CDFileClass::Open(int rights)
     99 {
    100 	return(RawFileClass::Open(rights));
    101 }
    102 
    103 
    104 /***********************************************************************************************
    105  * CDFC::Refresh_Search_Drives -- Updates the search path when a CD changes or is added        *
    106  *                                                                                             *
    107  *                                                                                             *
    108  *                                                                                             *
    109  * INPUT:    Nothing                                                                           *
    110  *                                                                                             *
    111  * OUTPUT:   Nothing                                                                           *
    112  *                                                                                             *
    113  * WARNINGS: None                                                                              *
    114  *                                                                                             *
    115  * HISTORY:                                                                                    *
    116  *    5/22/96 9:01AM ST : Created                                                              *
    117  *=============================================================================================*/
    118 void CDFileClass::Refresh_Search_Drives (void)
    119 {
    120 	Clear_Search_Drives();
    121 	Set_Search_Drives(RawPath);
    122 }
    123 
    124 
    125 
    126 
    127 
    128 /***********************************************************************************************
    129  * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access.              *
    130  *                                                                                             *
    131  *    This routine sets up a list of search paths to use when accessing files. The path list   *
    132  *    is scanned if the file could not be found in the current directory. This is the primary  *
    133  *    method of supporting CD-ROM drives, but is also useful for scanning network and other    *
    134  *    directories. The pathlist as passed to this routine is of the same format as the path    *
    135  *    list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.*
    136  *                                                                                             *
    137  *    If a path entry begins with "?:" then the question mark will be replaced with the first  *
    138  *    CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path     *
    139  *    entry will be ignored. By using this feature, you can always pass the CD-ROM path        *
    140  *    specification to this routine and it will not break if the CD-ROM is not loaded (as in   *
    141  *    the case during development).                                                            *
    142  *                                                                                             *
    143  *    Here is an example path specification:                                                   *
    144  *                                                                                             *
    145  *       Set_Search_Drives("DATA;?:\DATA;F:\PROJECT\DATA");                                    *
    146  *                                                                                             *
    147  *    In this example, the current directory will be searched first, followed by a the         *
    148  *    subdirectory "DATA" located off of the current directory. If not found, then the CD-ROM  *
    149  *    will be searched in a directory called "\DATA". If not found or the CD-ROM is not        *
    150  *    present, then it will look to the hard coded path of "F:\PROJECTS\DATA" (maybe a         *
    151  *    network?). If all of these searches fail, the file system will default to the current    *
    152  *    directory and let the normal file error system take over.                                *
    153  *                                                                                             *
    154  * INPUT:   pathlist -- Pointer to string of path specifications (separated by semicolons)     *
    155  *                      that will be used to search for files.                                 *
    156  *                                                                                             *
    157  * OUTPUT:  none                                                                               *
    158  *                                                                                             *
    159  * WARNINGS:   none                                                                            *
    160  *                                                                                             *
    161  * HISTORY:                                                                                    *
    162  *   10/18/1994 JLB : Created.                                                                 *
    163  *   05/21/1996 ST  : Modified to recognise multiple CD drives                                 *
    164  *=============================================================================================*/
    165 int CDFileClass::Set_Search_Drives(char * pathlist)
    166 {
    167 	int found = FALSE;
    168 	int empty = FALSE;
    169 	/*
    170 	**	If there is no pathlist to add, then just return.
    171 	*/
    172 	if (!pathlist) return(0);
    173 
    174 	/*
    175 	** Save the path as it was passed in so we can parse it again later.
    176 	** Check for the case where RawPath was passed in.
    177 	*/
    178 	if (pathlist != RawPath){
    179 		strcat (RawPath, ";");
    180 		strcat (RawPath, pathlist);
    181 	}
    182 
    183 	char const * ptr = strtok(pathlist, ";");
    184 	while (ptr) {
    185 		if (strlen(ptr)){
    186 
    187 			char path[MAX_PATH];						// Working path buffer.
    188 
    189 			/*
    190 			**	Fixup the path to be legal. Legal is defined as all that is necessary to
    191 			**	create a pathname is to append the actual filename submitted to the
    192 			**	file system. This means that it must have either a trailing ':' or '\'
    193 			**	character.
    194 			*/
    195 			strcpy(path, ptr);
    196 			switch (path[strlen(path)-1]) {
    197 				case ':':
    198 				case '\\':
    199 					break;
    200 
    201 				default:
    202 					strcat(path, "\\");
    203 					break;
    204 			}
    205 
    206 			/*
    207 			**	If there is a drive letter specified, and this drive letter is '?', then it should
    208 			**	be substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then
    209 			**	merely ignore this path entry.
    210 			*/
    211 			if (strncmp(path, "?:", 2) == 0) {
    212 				if (CurrentCDDrive){
    213 					found = TRUE;
    214 					/*
    215 					** If the drive has a C&C CD in it then add it to the path
    216 					*/
    217 					if (Get_CD_Index(CurrentCDDrive, 2*60) >= 0){
    218 						path[0] = CurrentCDDrive + 'A';
    219 						Add_Search_Drive(path);
    220 					}
    221 				}
    222 				/*
    223 				**	Find the next path string and resubmit.
    224 				*/
    225 				ptr = strtok(NULL, ";");
    226 				continue;
    227 			}
    228 
    229 			found	= TRUE;
    230 			Add_Search_Drive(path);
    231 		}
    232 
    233 		/*
    234 		**	Find the next path string and resubmit.
    235 		*/
    236 		ptr = strtok(NULL, ";");
    237 	}
    238 	if (!found) return(1);
    239 	if (empty) return(2);
    240 	return(0);
    241 }
    242 
    243 
    244 
    245 /***********************************************************************************************
    246  * CDFC::Set_CD_Drive -- sets the current CD drive letter                                      *
    247  *                                                                                             *
    248  *                                                                                             *
    249  *                                                                                             *
    250  * INPUT:    Nothing                                                                           *
    251  *                                                                                             *
    252  * OUTPUT:   Nothing                                                                           *
    253  *                                                                                             *
    254  * WARNINGS: None                                                                              *
    255  *                                                                                             *
    256  * HISTORY:                                                                                    *
    257  *    5/22/96 9:39AM ST : Created                                                              *
    258  *=============================================================================================*/
    259 
    260 void CDFileClass::Set_CD_Drive (int drive)
    261 {
    262 	LastCDDrive = CurrentCDDrive;
    263 	CurrentCDDrive = drive;
    264 }
    265 
    266 
    267 
    268 /***********************************************************************************************
    269  * CDFC::Add_Search_Drive -- Add a new path to the search path list                            *
    270  *                                                                                             *
    271  *                                                                                             *
    272  *                                                                                             *
    273  * INPUT:    path                                                                              *
    274  *                                                                                             *
    275  * OUTPUT:   Nothing                                                                           *
    276  *                                                                                             *
    277  * WARNINGS: None                                                                              *
    278  *                                                                                             *
    279  * HISTORY:                                                                                    *
    280  *    5/22/96 10:12AM ST : Created                                                             *
    281  *=============================================================================================*/
    282 
    283 void CDFileClass::Add_Search_Drive(char *path)
    284 {
    285 	SearchDriveType *srch;					// Working pointer to path object.
    286 	/*
    287 	**	Allocate a record structure.
    288 	*/
    289 	srch	= new SearchDriveType;
    290 
    291 	/*
    292 	**	Attach the path to this structure.
    293 	*/
    294 	srch->Path = strdup(path);
    295 	srch->Next = NULL;
    296 
    297 	/*
    298 	**	Attach this path record to the end of the path chain.
    299 	*/
    300 	if (!First) {
    301 		First = srch;
    302 	} else {
    303 		SearchDriveType * chain = First;
    304 
    305 		while (chain->Next) {
    306 			chain = (SearchDriveType *)chain->Next;
    307 		}
    308 		chain->Next = srch;
    309 	}
    310 }
    311 
    312 
    313 
    314 
    315 /***********************************************************************************************
    316  * CDFileClass::Clear_Search_Drives -- Removes all record of a search path.                    *
    317  *                                                                                             *
    318  *    Use this routine to clear out any previous path(s) set with Set_Search_Drives()          *
    319  *    function.                                                                                *
    320  *                                                                                             *
    321  * INPUT:   none                                                                               *
    322  *                                                                                             *
    323  * OUTPUT:  none                                                                               *
    324  *                                                                                             *
    325  * WARNINGS:   none                                                                            *
    326  *                                                                                             *
    327  * HISTORY:                                                                                    *
    328  *   10/18/1994 JLB : Created.                                                                 *
    329  *=============================================================================================*/
    330 void CDFileClass::Clear_Search_Drives(void)
    331 {
    332 	SearchDriveType	* chain;			// Working pointer to path chain.
    333 
    334 	chain = First;
    335 	while (chain) {
    336 		SearchDriveType	*next;
    337 
    338 		next = (SearchDriveType *)chain->Next;
    339 		if (chain->Path) {
    340 			free((char *)chain->Path);
    341 		}
    342 		delete chain;
    343 
    344 		chain = next;
    345 	}
    346 	First = 0;
    347 }
    348 
    349 
    350 /***********************************************************************************************
    351  * CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename.            *
    352  *                                                                                             *
    353  *    This routine will scan all the directories specified in the path list and if the file    *
    354  *    was found in one of the directories, it will set the filename to a composite of the      *
    355  *    correct directory and the filename. It is used to allow path searching when searching    *
    356  *    for files. Typical use is to support CD-ROM drives. This routine examines the current    *
    357  *    directory first before scanning through the path list. If after scanning the entire      *
    358  *    path list, the file still could not be found, then the file object's name is set with    *
    359  *    just the raw filename as passed to this routine.                                         *
    360  *                                                                                             *
    361  * INPUT:   filename -- Pointer to the filename to set as the name of this file object.        *
    362  *                                                                                             *
    363  * OUTPUT:  Returns a pointer to the final and complete filename of this file object. This     *
    364  *          may have a path attached to the file.                                              *
    365  *                                                                                             *
    366  * WARNINGS:   none                                                                            *
    367  *                                                                                             *
    368  * HISTORY:                                                                                    *
    369  *   10/18/1994 JLB : Created.                                                                 *
    370  *=============================================================================================*/
    371 char const * CDFileClass::Set_Name(char const *filename)
    372 {
    373 	/*
    374 	**	Try to find the file in the current directory first. If it can be found, then
    375 	**	just return with the normal file name setting process. Do the same if there is
    376 	**	no multi-drive search path.
    377 	*/
    378 	RawFileClass::Set_Name(filename);
    379 	if (IsDisabled || !First || RawFileClass::Is_Available()) {
    380 		return(File_Name());
    381 	}
    382 
    383 	/*
    384 	**	Attempt to find the file first. Check the current directory. If not found there, then
    385 	**	search all the path specifications available. If it still can't be found, then just
    386 	**	fall into the normal raw file filename setting system.
    387 	*/
    388 	SearchDriveType * srch = First;
    389 
    390 	while (srch) {
    391 		char path[_MAX_PATH];
    392 
    393 		/*
    394 		**	Build a pathname to search for.
    395 		*/
    396 		strcpy(path, srch->Path);
    397 		strcat(path, filename);
    398 
    399 		/*
    400 		**	Check to see if the file could be found. The low level Is_Available logic will
    401 		**	prompt if necessary when the CD-ROM drive has been removed. In all other cases,
    402 		**	it will return false and the search process will continue.
    403 		*/
    404 		RawFileClass::Set_Name(path);
    405 		if (RawFileClass::Is_Available()) {
    406 			return(File_Name());
    407 		}
    408 
    409 		/*
    410 		**	It wasn't found, so try the next path entry.
    411 		*/
    412 		srch = (SearchDriveType *)srch->Next;
    413 	}
    414 
    415 	/*
    416 	**	At this point, all path searching has failed. Just set the file name to the
    417 	**	plain text passed to this routine and be done with it.
    418 	*/
    419 	RawFileClass::Set_Name(filename);
    420 	return(File_Name());
    421 }
    422 
    423 
    424 /***********************************************************************************************
    425  * CDFileClass::Open -- Opens the file wherever it can be found.                               *
    426  *                                                                                             *
    427  *    This routine is similar to the RawFileClass open except that if the file is being        *
    428  *    opened only for READ access, it will search all specified directories looking for the    *
    429  *    file. If after a complete search the file still couldn't be found, then it is opened     *
    430  *    using the normal RawFileClass system -- resulting in normal error procedures.            *
    431  *                                                                                             *
    432  * INPUT:   filename -- Pointer to the override filename to supply for this file object. It    *
    433  *                      would be the base filename (sans any directory specification).         *
    434  *                                                                                             *
    435  *          rights   -- The access rights to use when opening the file.                        *
    436  *                                                                                             *
    437  * OUTPUT:  bool; Was the file opened successfully? If so then the filename may be different   *
    438  *                than requested. The location of the file can be determined by examining the  *
    439  *                filename of this file object. The filename will contain the complete         *
    440  *                pathname used to open the file.                                              *
    441  *                                                                                             *
    442  * WARNINGS:   none                                                                            *
    443  *                                                                                             *
    444  * HISTORY:                                                                                    *
    445  *   10/18/1994 JLB : Created.                                                                 *
    446  *=============================================================================================*/
    447 int CDFileClass::Open(char const *filename, int rights)
    448 {
    449 	Close();
    450 
    451 	/*
    452 	**	Verify that there is a filename associated with this file object. If not, then this is a
    453 	**	big error condition.
    454 	*/
    455 	if (!filename) {
    456 		Error(ENOENT, false);
    457 	}
    458 
    459 	/*
    460 	**	If writing is requested, then multiple drive searching is not performed.
    461 	*/
    462 	if (IsDisabled || rights == WRITE) {
    463 		return(RawFileClass::Open(filename, rights));
    464 	}
    465 
    466 	/*
    467 	**	Perform normal multiple drive searching for the filename and open
    468 	**	using the normal procedure.
    469 	*/
    470 	Set_Name(filename);
    471 	return(RawFileClass::Open(rights));
    472 }
    473 
    474 
    475 #ifdef NEVER
    476 /* Get the drive letters if the CD's online */
    477 WORD __cdecl GetCDDrive(VOID)
    478 {
    479 	_ES = FP_SEG(&cdDrive[0]);
    480 	_BX = FP_OFF(&cdDrive[0]);
    481 	_AX = 0x150d;
    482 	geninterrupt(0x2F);
    483 	return((WORD)(*cdDrive));
    484 }
    485 #endif
    486 
    487 int Get_CD_Drive(void)
    488 {
    489 #ifdef NEVER
    490 	for (int index = 0; index < 26; index++) {
    491 		union REGS regs;
    492 
    493 		regs.w.ax = 0x150B;
    494 		regs.w.bx = 0;
    495 		regs.w.cx = index;
    496 		int386(0x2F, &regs, &regs);
    497 		if (regs.w.bx == 0xADAD) {
    498 			return(index);
    499 		}
    500 	}
    501 	return(0);
    502 #else
    503 
    504 //	GetCDClass temp;
    505 //	return(temp.GetCDDrive());
    506 	return (0);
    507 #endif
    508 
    509 }
    510 
    511 
    512 
    513 const char *CDFileClass::Get_Search_Path(int index)
    514 {
    515 	if (First == NULL) {
    516 		return NULL;
    517 	}
    518 
    519 	SearchDriveType *sd = First;
    520 
    521 	for (int i=0 ; i <= index ; i++) {		// We want to loop once, even if index==0
    522 		
    523 		if (i == index) {
    524 			return sd->Path;
    525 		}
    526 
    527 		sd = (SearchDriveType *) sd->Next;
    528 		if (sd == NULL) {
    529 			return NULL;
    530 		}
    531 	}
    532 
    533 	return NULL;
    534 }