Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
parent
2e338c00cb
commit
3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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() {
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Reference in a new issue