Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.

This commit is contained in:
LFeenanEA 2025-02-27 17:34:39 +00:00
parent 2e338c00cb
commit 3d0ee53a05
No known key found for this signature in database
GPG key ID: C6EBE8C2EA08F7E0
6072 changed files with 2283311 additions and 0 deletions

View file

@ -0,0 +1,165 @@
/*
** Command & Conquer Generals Zero Hour(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) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
////// Win32BIGFile.cpp /////////////////////////
// Bryan Cleveland, August 2002
/////////////////////////////////////////////////////
#include "Common/LocalFile.h"
#include "Common/LocalFileSystem.h"
#include "Common/RAMFile.h"
#include "Common/StreamingArchiveFile.h"
#include "Common/GameMemory.h"
#include "Common/PerfTimer.h"
#include "Win32Device/Common/Win32BIGFile.h"
//============================================================================
// Win32BIGFile::Win32BIGFile
//============================================================================
Win32BIGFile::Win32BIGFile()
{
}
//============================================================================
// Win32BIGFile::~Win32BIGFile
//============================================================================
Win32BIGFile::~Win32BIGFile()
{
}
//============================================================================
// Win32BIGFile::openFile
//============================================================================
File* Win32BIGFile::openFile( const Char *filename, Int access )
{
const ArchivedFileInfo *fileInfo = getArchivedFileInfo(AsciiString(filename));
if (fileInfo == NULL) {
return NULL;
}
RAMFile *ramFile = NULL;
if (BitTest(access, File::STREAMING))
ramFile = newInstance( StreamingArchiveFile );
else
ramFile = newInstance( RAMFile );
ramFile->deleteOnClose();
if (ramFile->openFromArchive(m_file, fileInfo->m_filename, fileInfo->m_offset, fileInfo->m_size) == FALSE) {
ramFile->close();
ramFile = NULL;
return NULL;
}
if ((access & File::WRITE) == 0) {
// requesting read only access. Just return the RAM file.
return ramFile;
}
// whoever is opening this file wants write access, so copy the file to the local disk
// and return that file pointer.
File *localFile = TheLocalFileSystem->openFile(filename, access);
if (localFile != NULL) {
ramFile->copyDataToFile(localFile);
}
ramFile->close();
ramFile = NULL;
return localFile;
}
//============================================================================
// Win32BIGFile::closeAllFiles
//============================================================================
void Win32BIGFile::closeAllFiles( void )
{
}
//============================================================================
// Win32BIGFile::getName
//============================================================================
AsciiString Win32BIGFile::getName( void )
{
return m_name;
}
//============================================================================
// Win32BIGFile::getPath
//============================================================================
AsciiString Win32BIGFile::getPath( void )
{
return m_path;
}
//============================================================================
// Win32BIGFile::setSearchPriority
//============================================================================
void Win32BIGFile::setSearchPriority( Int new_priority )
{
}
//============================================================================
// Win32BIGFile::close
//============================================================================
void Win32BIGFile::close( void )
{
}
//============================================================================
// Win32BIGFile::getFileInfo
//============================================================================
Bool Win32BIGFile::getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const
{
const ArchivedFileInfo *tempFileInfo = getArchivedFileInfo(filename);
if (tempFileInfo == NULL) {
return FALSE;
}
TheLocalFileSystem->getFileInfo(AsciiString(m_file->getName()), fileInfo);
// fill in the size info. Since the size can't be bigger than a JUNK file, the high Int will always be 0.
fileInfo->sizeHigh = 0;
fileInfo->sizeLow = tempFileInfo->m_size;
return TRUE;
}

View file

@ -0,0 +1,236 @@
/*
** Command & Conquer Generals Zero Hour(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) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//////// Win32BIGFileSystem.h ///////////////////////////
// Bryan Cleveland, August 2002
/////////////////////////////////////////////////////////////
#include <winsock2.h>
#include "Common/AudioAffect.h"
#include "Common/ArchiveFile.h"
#include "Common/ArchiveFileSystem.h"
#include "Common/File.h"
#include "Common/GameAudio.h"
#include "Common/GameMemory.h"
#include "Common/LocalFileSystem.h"
#include "Win32Device/Common/Win32BIGFile.h"
#include "Win32Device/Common/Win32BIGFileSystem.h"
#include "Common/registry.h"
#ifdef _INTERNAL
// for occasional debugging...
//#pragma optimize("", off)
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
#endif
static const char *BIGFileIdentifier = "BIGF";
Win32BIGFileSystem::Win32BIGFileSystem() : ArchiveFileSystem() {
}
Win32BIGFileSystem::~Win32BIGFileSystem() {
}
void Win32BIGFileSystem::init() {
DEBUG_ASSERTCRASH(TheLocalFileSystem != NULL, ("TheLocalFileSystem must be initialized before TheArchiveFileSystem."));
if (TheLocalFileSystem == NULL) {
return;
}
loadBigFilesFromDirectory("", "*.big");
// load original Generals assets
AsciiString installPath;
GetStringFromGeneralsRegistry("", "InstallPath", installPath );
//@todo this will need to be ramped up to a crash for release
#ifndef _INTERNAL
// had to make this non-internal only, otherwise we can't autobuild
// GeneralsZH...
DEBUG_ASSERTCRASH(installPath != "", ("Be 1337! Go install Generals!"));
#endif
if (installPath!="")
loadBigFilesFromDirectory(installPath, "*.big");
}
void Win32BIGFileSystem::reset() {
}
void Win32BIGFileSystem::update() {
}
void Win32BIGFileSystem::postProcessLoad() {
}
ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) {
File *fp = TheLocalFileSystem->openFile(filename, File::READ | File::BINARY);
AsciiString archiveFileName;
archiveFileName = filename;
archiveFileName.toLower();
Int archiveFileSize = 0;
Int numLittleFiles = 0;
ArchiveFile *archiveFile = NEW Win32BIGFile;
DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - opening BIG file %s\n", filename));
if (fp == NULL) {
DEBUG_CRASH(("Could not open archive file %s for parsing", filename));
return NULL;
}
AsciiString asciibuf;
char buffer[_MAX_PATH];
fp->read(buffer, 4); // read the "BIG" at the beginning of the file.
buffer[4] = 0;
if (strcmp(buffer, BIGFileIdentifier) != 0) {
DEBUG_CRASH(("Error reading BIG file identifier in file %s", filename));
fp->close();
fp = NULL;
return NULL;
}
// read in the file size.
fp->read(&archiveFileSize, 4);
DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - size of archive file is %d bytes\n", archiveFileSize));
// char t;
// read in the number of files contained in this BIG file.
// change the order of the bytes cause the file size is in reverse byte order for some reason.
fp->read(&numLittleFiles, 4);
numLittleFiles = ntohl(numLittleFiles);
DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - %d are contained in archive\n", numLittleFiles));
// for (Int i = 0; i < 2; ++i) {
// t = buffer[i];
// buffer[i] = buffer[(4-i)-1];
// buffer[(4-i)-1] = t;
// }
// seek to the beginning of the directory listing.
fp->seek(0x10, File::START);
// read in each directory listing.
ArchivedFileInfo *fileInfo = NEW ArchivedFileInfo;
for (Int i = 0; i < numLittleFiles; ++i) {
Int filesize = 0;
Int fileOffset = 0;
fp->read(&fileOffset, 4);
fp->read(&filesize, 4);
filesize = ntohl(filesize);
fileOffset = ntohl(fileOffset);
fileInfo->m_archiveFilename = archiveFileName;
fileInfo->m_offset = fileOffset;
fileInfo->m_size = filesize;
// read in the path name of the file.
Int pathIndex = -1;
do {
++pathIndex;
fp->read(buffer + pathIndex, 1);
} while (buffer[pathIndex] != 0);
Int filenameIndex = pathIndex;
while ((buffer[filenameIndex] != '\\') && (buffer[filenameIndex] != '/') && (filenameIndex >= 0)) {
--filenameIndex;
}
fileInfo->m_filename = (char *)(buffer + filenameIndex + 1);
fileInfo->m_filename.toLower();
buffer[filenameIndex + 1] = 0;
AsciiString path;
path = buffer;
AsciiString debugpath;
debugpath = path;
debugpath.concat(fileInfo->m_filename);
// DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - adding file %s to archive file %s, file number %d\n", debugpath.str(), fileInfo->m_archiveFilename.str(), i));
archiveFile->addFile(path, fileInfo);
}
archiveFile->attachFile(fp);
delete fileInfo;
fileInfo = NULL;
// leave fp open as the archive file will be using it.
return archiveFile;
}
void Win32BIGFileSystem::closeArchiveFile(const Char *filename) {
// Need to close the specified big file
ArchiveFileMap::iterator it = m_archiveFileMap.find(filename);
if (it == m_archiveFileMap.end()) {
return;
}
if (stricmp(filename, MUSIC_BIG) == 0) {
// Stop the current audio
TheAudio->stopAudio(AudioAffect_Music);
// No need to turn off other audio, as the lookups will just fail.
}
DEBUG_ASSERTCRASH(stricmp(filename, MUSIC_BIG) == 0, ("Attempting to close Archive file '%s', need to add code to handle its shutdown correctly.", filename));
// may need to do some other processing here first.
delete (it->second);
m_archiveFileMap.erase(it);
}
void Win32BIGFileSystem::closeAllArchiveFiles() {
}
void Win32BIGFileSystem::closeAllFiles() {
}
Bool Win32BIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite) {
FilenameList filenameList;
TheLocalFileSystem->getFileListInDirectory(dir, AsciiString(""), fileMask, filenameList, TRUE);
Bool actuallyAdded = FALSE;
FilenameListIter it = filenameList.begin();
while (it != filenameList.end()) {
ArchiveFile *archiveFile = openArchiveFile((*it).str());
if (archiveFile != NULL) {
DEBUG_LOG(("Win32BIGFileSystem::loadBigFilesFromDirectory - loading %s into the directory tree.\n", (*it).str()));
loadIntoDirectoryTree(archiveFile, *it, overwrite);
m_archiveFileMap[(*it)] = archiveFile;
DEBUG_LOG(("Win32BIGFileSystem::loadBigFilesFromDirectory - %s inserted into the archive file map.\n", (*it).str()));
actuallyAdded = TRUE;
}
it++;
}
return actuallyAdded;
}

View file

@ -0,0 +1,236 @@
/*
** Command & Conquer Generals Zero Hour(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) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: Generals
//
// Module: Game Engine Device Win32 Common
//
// File name: Win32CDManager.cpp
//
// Created: 11/26/01 TR
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------------
#include "windows.h"
#include "Common/GameMemory.h"
#include "Common/FileSystem.h"
#include "Win32DEvice/Common/Win32CDManager.h"
//----------------------------------------------------------------------------
// Externals
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Defines
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Private Types
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Private Data
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Public Data
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Private Prototypes
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Private Functions
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Public Functions
//----------------------------------------------------------------------------
CDManagerInterface* CreateCDManager( void )
{
return NEW Win32CDManager;
}
//============================================================================
// Win32CDDrive::Win32CDDrive
//============================================================================
Win32CDDrive::Win32CDDrive()
{
}
//============================================================================
// Win32CDDrive::~Win32CDDrive
//============================================================================
Win32CDDrive::~Win32CDDrive()
{
}
//============================================================================
// Win32CDDrive::refreshInfo
//============================================================================
void Win32CDDrive::refreshInfo( void )
{
Bool mayRequireUpdate = (m_disk != CD::NO_DISK);
Char volName[1024];
// read the volume info
if ( GetVolumeInformation( m_drivePath.str(), volName, sizeof(volName) -1, NULL, NULL, NULL, NULL, 0 ))
{
m_diskName = volName;
m_disk = CD::UNKNOWN_DISK;
}
else
{
m_diskName.clear();
m_disk = CD::NO_DISK;
if (mayRequireUpdate)
TheFileSystem->unloadMusicFilesFromCD();
}
// This is an override, not an extension of CDDrive
}
//============================================================================
// Win32CDManager::Win32CDManager
//============================================================================
Win32CDManager::Win32CDManager()
{
}
//============================================================================
// Win32CDManager::~Win32CDManager
//============================================================================
Win32CDManager::~Win32CDManager()
{
}
//============================================================================
// Win32CDManager::init
//============================================================================
void Win32CDManager::init( void )
{
CDManager::init(); // init base classes
destroyAllDrives();
// detect CD Drives
for ( Char driveLetter = 'a'; driveLetter <= 'z'; driveLetter++ )
{
AsciiString drivePath;
drivePath.format( "%c:\\", driveLetter );
if ( GetDriveType( drivePath.str() ) == DRIVE_CDROM )
{
newDrive( drivePath.str() );
}
}
refreshDrives();
}
//============================================================================
// Win32CDManager::update
//============================================================================
void Win32CDManager::update( void )
{
CDManager::update();
}
//============================================================================
// Win32CDManager::reset
//============================================================================
void Win32CDManager::reset( void )
{
CDManager::reset();
}
//============================================================================
// Win32CDManager::createDrive
//============================================================================
CDDriveInterface* Win32CDManager::createDrive( void )
{
return NEW Win32CDDrive;
}
//============================================================================
// Win32CDManager::refreshDrives
//============================================================================
void Win32CDManager::refreshDrives( void )
{
CDManager::refreshDrives();
}

View file

@ -0,0 +1,169 @@
/*
** Command & Conquer Generals Zero Hour(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) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: W3DGameEngine.cpp ////////////////////////////////////////////////////////////////////////
// Author: Colin Day, April 2001
// Description:
// Implementation of the Win32 game engine, this is the highest level of
// the game application, it creates all the devices we will use for the game
///////////////////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include "Win32Device/Common/Win32GameEngine.h"
#include "Common/PerfTimer.h"
#include "GameNetwork/LANAPICallbacks.h"
extern DWORD TheMessageTime;
//-------------------------------------------------------------------------------------------------
/** Constructor for Win32GameEngine */
//-------------------------------------------------------------------------------------------------
Win32GameEngine::Win32GameEngine()
{
// Stop blue screen
m_previousErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS );
}
//-------------------------------------------------------------------------------------------------
/** Destructor for Win32GameEngine */
//-------------------------------------------------------------------------------------------------
Win32GameEngine::~Win32GameEngine()
{
// restore it (this isn't really necessary, but feels good.)
SetErrorMode( m_previousErrorMode );
}
//-------------------------------------------------------------------------------------------------
/** Initialize the game engine */
//-------------------------------------------------------------------------------------------------
void Win32GameEngine::init( void )
{
// extending functionality
GameEngine::init();
} // end init
//-------------------------------------------------------------------------------------------------
/** Reset the system */
//-------------------------------------------------------------------------------------------------
void Win32GameEngine::reset( void )
{
// extending functionality
GameEngine::reset();
} // end reset
//-------------------------------------------------------------------------------------------------
/** Update the game engine by updating the GameClient and
* GameLogic singletons. */
//-------------------------------------------------------------------------------------------------
void Win32GameEngine::update( void )
{
// call the engine normal update
GameEngine::update();
extern HWND ApplicationHWnd;
if (ApplicationHWnd && ::IsIconic(ApplicationHWnd)) {
while (ApplicationHWnd && ::IsIconic(ApplicationHWnd)) {
// We are alt-tabbed out here. Sleep a bit, & process windows
// so that we can become un-alt-tabbed out.
Sleep(5);
serviceWindowsOS();
if (TheLAN != NULL) {
// BGC - need to update TheLAN so we can process and respond to other
// people's messages who may not be alt-tabbed out like we are.
TheLAN->setIsActive(isActive());
TheLAN->update();
}
// If we are running a multiplayer game, keep running the logic.
// There is code in the client to skip client redraw if we are
// iconic. jba.
if (TheGameEngine->getQuitting() || TheGameLogic->isInInternetGame() || TheGameLogic->isInLanGame()) {
break; // keep running.
}
}
// When we are alt-tabbed out... the MilesAudioManager seems to go into a coma sometimes
// and not regain focus properly when we come back. This seems to wake it up nicely.
AudioAffect aa = (AudioAffect)0x10;
TheAudio->setVolume(TheAudio->getVolume( aa ), aa );
}
// allow windows to perform regular windows maintenance stuff like msgs
serviceWindowsOS();
} // end update
//-------------------------------------------------------------------------------------------------
/** This function may be called from within this application to let
* Microsoft Windows do its message processing and dispatching. Presumeably
* we would call this at least once each time around the game loop to keep
* Windows services from backing up */
//-------------------------------------------------------------------------------------------------
void Win32GameEngine::serviceWindowsOS( void )
{
MSG msg;
Int returnValue;
//
// see if we have any messages to process, a NULL window handle tells the
// OS to look at the main window associated with the calling thread, us!
//
while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
// get the message
returnValue = GetMessage( &msg, NULL, 0, 0 );
// this is one possible way to check for quitting conditions as a message
// of WM_QUIT will cause GetMessage() to return 0
/*
if( returnValue == 0 )
{
setQuitting( true );
break;
}
*/
TheMessageTime = msg.time;
// translate and dispatch the message
TranslateMessage( &msg );
DispatchMessage( &msg );
TheMessageTime = 0;
} // end while
} // end ServiceWindowsOS

View file

@ -0,0 +1,35 @@
/*
** Command & Conquer Generals Zero Hour(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) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//////// Win32LocalFile.cpp ///////////////////////////
// Bryan Cleveland, August 2002
///////////////////////////////////////////////////////
#include "Win32Device/Common/Win32LocalFile.h"
Win32LocalFile::Win32LocalFile() : LocalFile() {
}
Win32LocalFile::~Win32LocalFile() {
}

View file

@ -0,0 +1,214 @@
/*
** Command & Conquer Generals Zero Hour(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) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
///////// Win32LocalFileSystem.cpp /////////////////////////
// Bryan Cleveland, August 2002
////////////////////////////////////////////////////////////
#include <windows.h>
#include "Common/AsciiString.h"
#include "Common/GameMemory.h"
#include "Common/PerfTimer.h"
#include "Win32Device/Common/Win32LocalFileSystem.h"
#include "Win32Device/Common/Win32LocalFile.h"
#include <io.h>
Win32LocalFileSystem::Win32LocalFileSystem() : LocalFileSystem()
{
}
Win32LocalFileSystem::~Win32LocalFileSystem() {
}
//DECLARE_PERF_TIMER(Win32LocalFileSystem_openFile)
File * Win32LocalFileSystem::openFile(const Char *filename, Int access /* = 0 */)
{
//USE_PERF_TIMER(Win32LocalFileSystem_openFile)
Win32LocalFile *file = newInstance( Win32LocalFile );
// sanity check
if (strlen(filename) <= 0) {
return NULL;
}
if (access & File::WRITE) {
// if opening the file for writing, we need to make sure the directory is there
// before we try to create the file.
AsciiString string;
string = filename;
AsciiString token;
AsciiString dirName;
string.nextToken(&token, "\\/");
dirName = token;
while ((token.find('.') == NULL) || (string.find('.') != NULL)) {
createDirectory(dirName);
string.nextToken(&token, "\\/");
dirName.concat('\\');
dirName.concat(token);
}
}
if (file->open(filename, access) == FALSE) {
file->close();
file->deleteInstance();
file = NULL;
} else {
file->deleteOnClose();
}
// this will also need to play nice with the STREAMING type that I added, if we ever enable this
// srj sez: this speeds up INI loading, but makes BIG files unusable.
// don't enable it without further tweaking.
//
// unless you like running really slowly.
// if (!(access&File::WRITE)) {
// // Return a ramfile.
// RAMFile *ramFile = newInstance( RAMFile );
// if (ramFile->open(file)) {
// file->close(); // is deleteonclose, so should delete.
// ramFile->deleteOnClose();
// return ramFile;
// } else {
// ramFile->close();
// ramFile->deleteInstance();
// }
// }
return file;
}
void Win32LocalFileSystem::update()
{
}
void Win32LocalFileSystem::init()
{
}
void Win32LocalFileSystem::reset()
{
}
//DECLARE_PERF_TIMER(Win32LocalFileSystem_doesFileExist)
Bool Win32LocalFileSystem::doesFileExist(const Char *filename) const
{
//USE_PERF_TIMER(Win32LocalFileSystem_doesFileExist)
if (_access(filename, 0) == 0) {
return TRUE;
}
return FALSE;
}
void Win32LocalFileSystem::getFileListInDirectory(const AsciiString& currentDirectory, const AsciiString& originalDirectory, const AsciiString& searchName, FilenameList & filenameList, Bool searchSubdirectories) const
{
HANDLE fileHandle = NULL;
WIN32_FIND_DATA findData;
char search[_MAX_PATH];
AsciiString asciisearch;
asciisearch = originalDirectory;
asciisearch.concat(currentDirectory);
asciisearch.concat(searchName);
strcpy(search, asciisearch.str());
Bool done = FALSE;
fileHandle = FindFirstFile(search, &findData);
done = (fileHandle == INVALID_HANDLE_VALUE);
while (!done) {
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(strcmp(findData.cFileName, ".") && strcmp(findData.cFileName, ".."))) {
// if we haven't already, add this filename to the list.
// a stl set should only allow one copy of each filename
AsciiString newFilename;
newFilename = originalDirectory;
newFilename.concat(currentDirectory);
newFilename.concat(findData.cFileName);
if (filenameList.find(newFilename) == filenameList.end()) {
filenameList.insert(newFilename);
}
}
done = (FindNextFile(fileHandle, &findData) == 0);
}
FindClose(fileHandle);
if (searchSubdirectories) {
AsciiString subdirsearch;
subdirsearch = originalDirectory;
subdirsearch.concat(currentDirectory);
subdirsearch.concat("*.");
fileHandle = FindFirstFile(subdirsearch.str(), &findData);
done = fileHandle == INVALID_HANDLE_VALUE;
while (!done) {
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(strcmp(findData.cFileName, ".") && strcmp(findData.cFileName, ".."))) {
AsciiString tempsearchstr;
tempsearchstr.concat(currentDirectory);
tempsearchstr.concat(findData.cFileName);
tempsearchstr.concat('\\');
// recursively add files in subdirectories if required.
getFileListInDirectory(tempsearchstr, originalDirectory, searchName, filenameList, searchSubdirectories);
}
done = (FindNextFile(fileHandle, &findData) == 0);
}
FindClose(fileHandle);
}
}
Bool Win32LocalFileSystem::getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const
{
WIN32_FIND_DATA findData;
HANDLE findHandle = NULL;
findHandle = FindFirstFile(filename.str(), &findData);
if (findHandle == INVALID_HANDLE_VALUE) {
return FALSE;
}
fileInfo->timestampHigh = findData.ftLastWriteTime.dwHighDateTime;
fileInfo->timestampLow = findData.ftLastWriteTime.dwLowDateTime;
fileInfo->sizeHigh = findData.nFileSizeHigh;
fileInfo->sizeLow = findData.nFileSizeLow;
FindClose(findHandle);
return TRUE;
}
Bool Win32LocalFileSystem::createDirectory(AsciiString directory)
{
if ((directory.getLength() > 0) && (directory.getLength() < _MAX_DIR)) {
return (CreateDirectory(directory.str(), NULL) != 0);
}
return FALSE;
}

View file

@ -0,0 +1,129 @@
/*
** Command & Conquer Generals Zero Hour(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) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// Win32OSDisplay.cpp //////////////////////////////////////
// John McDonald, December 2002
////////////////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "Common/OSDisplay.h"
#include "Common/SubsystemInterface.h"
#include "Common/STLTypeDefs.h"
#include "Common/AsciiString.h"
#include "Common/SystemInfo.h"
#include "Common/UnicodeString.h"
#include "GameClient/GameText.h"
#ifdef _INTERNAL
//#pragma optimize("", off)
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
#endif
extern HWND ApplicationHWnd;
//-------------------------------------------------------------------------------------------------
static void RTSFlagsToOSFlags(UnsignedInt buttonFlags, UnsignedInt otherFlags, UnsignedInt& outWindowsFlags)
{
outWindowsFlags = 0;
if (BitTest(buttonFlags, OSDBT_OK)) {
outWindowsFlags |= MB_OK;
}
if (BitTest(buttonFlags, OSDBT_CANCEL)) {
outWindowsFlags |= MB_OKCANCEL;
}
//-----------------------------------------------------------------------------------------------
if (BitTest(otherFlags, OSDOF_SYSTEMMODAL)) {
outWindowsFlags |= MB_SYSTEMMODAL;
}
if (BitTest(otherFlags, OSDOF_APPLICATIONMODAL)) {
outWindowsFlags |= MB_APPLMODAL;
}
if (BitTest(otherFlags, OSDOF_TASKMODAL)) {
outWindowsFlags |= MB_TASKMODAL;
}
if (BitTest(otherFlags, OSDOF_EXCLAMATIONICON)) {
outWindowsFlags |= MB_ICONEXCLAMATION;
}
if (BitTest(otherFlags, OSDOF_INFORMATIONICON)) {
outWindowsFlags |= MB_ICONINFORMATION;
}
if (BitTest(otherFlags, OSDOF_ERRORICON)) {
outWindowsFlags |= MB_ICONERROR;
}
if (BitTest(otherFlags, OSDOF_STOPICON)) {
outWindowsFlags |= MB_ICONSTOP;
}
}
//-------------------------------------------------------------------------------------------------
OSDisplayButtonType OSDisplayWarningBox(AsciiString p, AsciiString m, UnsignedInt buttonFlags, UnsignedInt otherFlags)
{
if (!TheGameText) {
return OSDBT_ERROR;
}
UnicodeString promptStr = TheGameText->fetch(p);
UnicodeString mesgStr = TheGameText->fetch(m);
UnsignedInt windowsOptionsFlags = 0;
RTSFlagsToOSFlags(buttonFlags, otherFlags, windowsOptionsFlags);
// @todo Make this return more than just ok/cancel - jkmcd
// (we need a function to translate back the other way.)
Int returnResult = 0;
if (TheSystemIsUnicode)
{
returnResult = ::MessageBoxW(NULL, mesgStr.str(), promptStr.str(), windowsOptionsFlags);
}
else
{
// However, if we're using the default version of the message box, we need to
// translate the string into an AsciiString
AsciiString promptA, mesgA;
promptA.translate(promptStr);
mesgA.translate(mesgStr);
//Make sure main window is not TOP_MOST
::SetWindowPos(ApplicationHWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
returnResult = ::MessageBoxA(NULL, mesgA.str(), promptA.str(), windowsOptionsFlags);
}
if (returnResult == IDOK) {
return OSDBT_OK;
}
return OSDBT_CANCEL;
}