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
6072 changed files with 2283311 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
/*
** Command & Conquer Generals(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/>.
*/
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef BSEARCH_H
#define BSEARCH_H
/*
** Binary searching template. It can be faster than the built in C library
** version since the comparison function can be inlined. If the comparison
** process is significantly more time consuming than the overhead of
** a function call, then using the C library version would be appropriate.
*/
template<class T>
T * Binary_Search(T * A, int n, T const & target)
{
const T * pointer = A;
int stride = n;
/*
** Keep binary searching until a match has been found
** or the search has resulted in no match.
*/
while (0 < stride) {
int const pivot = stride / 2;
T const * const tryptr = pointer + pivot;
/*
** Binary stride forward or backward depending on if the candidate
** element is smaller or larger than the target element. If
** smaller, then merely adjusting the stride is required. If larger,
** then the base pointer must be adjusted and the stride must be
** moved backward.
*/
if (target < *tryptr) {
stride = pivot;
} else {
/*
** An exact match results in the pointer being found
** and returned to the caller. This check is performed
** here since 50% of the time, the first compare will
** be true and thus the equality comparison would be
** called less often -- should be faster as a result.
*/
if (*tryptr == target) {
return ((T *) tryptr);
}
pointer = tryptr + 1;
stride -= pivot + 1;
}
}
return (NULL);
}
#endif

View File

@@ -0,0 +1,95 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/BUFF.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:59a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef CCBUFF_H
#define CCBUFF_H
/*
** The "bool" integral type was defined by the C++ committee in
** November of '94. Until the compiler supports this, use the following
** definition.
*/
#include "bool.h"
/*
** A general purpose buffer pointer handler object. It holds not only the pointer to the
** buffer, but its size as well. By using this class instead of separate pointer and size
** values, function interfaces and algorithms become simpler to manage and understand.
*/
class Buffer {
public:
Buffer(char * ptr, long size=0);
Buffer(void * ptr=0, long size=0);
Buffer(void const * ptr, long size=0);
Buffer(long size);
Buffer(Buffer const & buffer);
~Buffer(void);
Buffer & operator = (Buffer const & buffer);
operator void * (void) const {return(BufferPtr);}
operator char * (void) const {return((char *)BufferPtr);}
void Reset(void);
void * Get_Buffer(void) const {return(BufferPtr);}
long Get_Size(void) const {return(Size);}
bool Is_Valid(void) const {return(BufferPtr != 0);}
protected:
/*
** Pointer to the buffer memory.
*/
void * BufferPtr;
/*
** The size of the buffer memory.
*/
long Size;
/*
** Was the buffer allocated by this class? If so, then this class
** will be responsible for freeing the buffer.
*/
bool IsAllocated;
};
#endif

View File

@@ -0,0 +1,134 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/crc.h $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 10/04/99 10:25a $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef CRC_H
#define CRC_H
#include <stdlib.h>
#ifdef _UNIX
#include "osdep.h"
#endif
/*
** This is a CRC engine class. It will process submitted data and generate a CRC from it.
** Well, actually, the value returned is not a true CRC. However, it shares the same strength
** characteristic and is faster to generate than the traditional CRC. This object is treated like
** a method class. If it is called as a function (using the function operator), it will return
** the CRC value. There are other function operators to submit data for processing.
*/
class CRCEngine {
public:
// Constructor for CRC engine (it can have an override initial CRC value).
CRCEngine(long initial=0) : CRC(initial), Index(0) {
StagingBuffer.Composite = 0;
};
// Fetches CRC value.
long operator() (void) const {return(Value());};
// Submits one byte sized datum to the CRC accumulator.
void operator() (char datum);
// Submits an arbitrary buffer to the CRC accumulator.
long operator() (void const * buffer, int length);
// Implicit conversion operator so this object appears like a 'long integer'.
operator long(void) const {return(Value());};
protected:
bool Buffer_Needs_Data(void) const {
return(Index != 0);
};
long Value(void) const {
if (Buffer_Needs_Data()) {
return(_lrotl(CRC, 1) + StagingBuffer.Composite);
}
return(CRC);
};
/*
** Current accumulator of the CRC value. This value doesn't take into
** consideration any pending data in the staging buffer.
*/
long CRC;
/*
** This is the sub index into the staging buffer used to keep track of
** partial data blocks as they are submitted to the CRC engine.
*/
int Index;
/*
** This is the buffer that holds the incoming partial data. When the buffer
** is filled, the value is transformed into the CRC and the buffer is flushed
** in preparation for additional data.
*/
union {
long Composite;
char Buffer[sizeof(long)];
} StagingBuffer;
};
// the CRC class defines a few static functions for dealing with CRCs a little differently than
// the CRCEngine. This class uses a algorithm that produces CRC values that have a high probability
// of being unique under most circumstances.
// Note: this code was provided by Byon Garrabrant
//
// 12/09/97 EHC - converted from c to c++ static class and added to crc.h and crc.cpp
//
#define CRC32(c,crc) (CRC::_Table[((unsigned long)(crc) ^ (c)) & 0xFFL] ^ (((crc) >> 8) & 0x00FFFFFFL))
class CRC {
// CRC for poly 0x04C11DB7
static unsigned long _Table[256];
public:
// get the CRC of a block of memory
static unsigned long Memory( unsigned char *data, unsigned long length, unsigned long crc = 0 );
// get the CRC of a null-terminated string
static unsigned long String( const char *string, unsigned long crc = 0 );
};
#endif

View File

@@ -0,0 +1,84 @@
/*
** Command & Conquer Generals(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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/wwlib/CallbackHook.h $
*
* DESCRIPTION
*
* PROGRAMMER
* Steven Clinard
* $Author: Denzil_l $
*
* VERSION INFO
* $Modtime: 7/03/01 4:59p $
* $Revision: 1 $
*
******************************************************************************/
#ifndef __CALLBACKHOOK_H__
#define __CALLBACKHOOK_H__
class CallbackHook
{
public:
CallbackHook()
{}
virtual ~CallbackHook()
{}
virtual bool DoCallback(void)
{return false;}
protected:
CallbackHook(const CallbackHook&);
const CallbackHook& operator=(const CallbackHook&);
};
template<class T> class Callback :
public CallbackHook
{
public:
Callback(bool (*callback)(T), T userdata) :
mCallback(callback),
mUserData(userdata)
{}
virtual ~Callback()
{}
virtual bool DoCallback(void)
{
if (mCallback)
{
return mCallback(mUserData);
}
return false;
}
private:
bool (*mCallback)(T);
T mUserData;
};
#endif // __CALLBACKHOOK_H__

View File

@@ -0,0 +1,173 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/Convert.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:59a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef CONVERT_H
#define CONVERT_H
#include "blitter.h"
#include "palette.h"
#include "surface.h"
/*
** Flags used to fetch the appropriate blitter object.
*/
typedef enum {
SHAPE_NORMAL = 0x0000, // Standard shape (which is transparent)
SHAPE_WIN_REL = 0x0400,
SHAPE_CENTER = 0x0200, // Coords are based on shape's center pt
SHAPE_DARKEN = 0x0001, // Force all pixels to darken the destination.
SHAPE_TRANSLUCENT25 = 0x0002, // Translucent to destination (25%).
SHAPE_TRANSLUCENT50 = 0x0004, // Translucent to destination (50%).
SHAPE_TRANSLUCENT75 = 0x0006, // Translucent to destination (75%).
SHAPE_PREDATOR = 0x0008, // Predator effect
SHAPE_REMAP = 0x0010, // Simple remap
SHAPE_NOTRANS = 0x0020 // A non transparent but otherwise standard shape
} ShapeFlags_Type;
/*
** This class is the data that represents the marriage between a source art
** palette and a destination palette/pixel-format. Facilities provied by this
** class allow conversion from the source 8 bit pixel format to the correct
** screen pixel format.
**
** Although this class can convert one pixel at a time through the conversion
** function, the preferred way to convert pixels is through the translation
** table provided. This table consists of 256 entries. Each entry is either
** an 8 bit or 16 bit pixel in the correct screen-space format. Use the
** Bytes_Per_Pixel() function to determine how to index into this translation
** table.
**
** Expected use of this class would be to create separate objects of this class for
** every source art palette. For an 8 bit display, an additional object will be
** required for every additional palette set to the video DAC registers. It is
** presumed that one general best-case palette will be used.
*/
class ConvertClass
{
public:
ConvertClass(PaletteClass const & artpalette, PaletteClass const & screenpalette, Surface const & typicalsurface);
~ConvertClass(void);
/*
** Convert from source pixel to dest screen pixel.
*/
int Convert_Pixel(int pixel) const {
if (BBP == 1) return(((unsigned char const *)Translator)[pixel]);
return(((unsigned short const *)Translator)[pixel]);
}
/*
** Fetch a blitter object to use according to the draw flags
** specified.
*/
Blitter const * Blitter_From_Flags(ShapeFlags_Type flags) const;
RLEBlitter const * RLEBlitter_From_Flags(ShapeFlags_Type flags) const;
/*
** This returns the bytes per pixel. Use this to determine how to index
** through the translation table.
*/
int Bytes_Per_Pixel(void) const {return(BBP);}
/*
** Fetches the translation table. Sometimes the provided blitter objects
** won't suffice and manual access to the translation process is necessary.
*/
void const * Get_Translate_Table(void) const {return(Translator);}
/*
** Sets the dynamic remap table so that the remapping blitters will use
** it without having to recreate the blitter objects.
*/
void Set_Remap(unsigned char const * remap) {RemapTable = remap;}
protected:
/*
** Bytes per pixel in screen format.
*/
int BBP;
/*
** These are the blitter objects used to handle all the draw styles that this
** drawing dispatcher implements.
*/
Blitter * PlainBlitter; // No transparency (rarely used).
Blitter * TransBlitter; // Skips transparent pixels.
Blitter * ShadowBlitter; // Shadowizes the destination pixels.
Blitter * RemapBlitter; // Remaps source pixels then draws with transparency.
Blitter * Translucent1Blitter; // 25% translucent.
Blitter * Translucent2Blitter; // 50% translucent.
Blitter * Translucent3Blitter; // 75% translucent.
/*
** These are the RLE aware blitters to handle all drawing styles that may
** be used by RLE compressed images.
*/
RLEBlitter * RLETransBlitter; // Skips transparent pixels.
RLEBlitter * RLEShadowBlitter; // Shadowizes the destination pixels.
RLEBlitter * RLERemapBlitter; // Remaps source pixels then draws with transparency.
RLEBlitter * RLETranslucent1Blitter; // 25% translucent.
RLEBlitter * RLETranslucent2Blitter; // 50% translucent.
RLEBlitter * RLETranslucent3Blitter; // 75% translucent.
/*
** This is a translation table pointer. All source artwork is in 8 bit format.
** This table will translate this source pixel into a screen dependant pixel
** format datum.
*/
void * Translator;
/*
** This will shade an 8 bit pixel to about 1/2 intensity.
*/
unsigned char * ShadowTable;
/*
** Remap table pointer used for blits that require remapping. This value
** will change according to the draw parameter. The blitting routines keep track
** of this member object and use it to determine the remap table to use.
*/
mutable unsigned char const * RemapTable;
};
#endif

View File

@@ -0,0 +1,70 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/font.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 11/28/00 2:40p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef FONT_H
#define FONT_H
#include "convert.h"
#include "point.h"
#include "trect.h"
#include <stddef.h>
class Surface;
/*
** A font object represent the data that comprises the individual characters as well
** as drawing text in the font to a surface. This is an abstract base class that is to be
** derived into a concrete version.
*/
class FontClass {
public:
virtual ~FontClass(void) {}
virtual int Char_Pixel_Width(char c) const = 0;
virtual int String_Pixel_Width(char const * string) const = 0;
virtual int Get_Width(void) const = 0;
virtual int Get_Height(void) const = 0;
virtual Point2D Print(char const * string, Surface & surface, Rect const & cliprect, Point2D const & point, ConvertClass const & converter, unsigned char const * remap=NULL) const = 0;
virtual int Set_XSpacing(int x) = 0;
virtual int Set_YSpacing(int y) = 0;
};
#endif

View File

@@ -0,0 +1,652 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/wwlib/hashlist.h 13 4/30/01 3:05p Joe_b $ */
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : G *
* *
* $Archive:: /Commando/Code/wwlib/hashlist.h $*
* *
* Creator::Scott K. Bowen - 5/4/99 *
* *
* $Author:: Joe_b $*
* *
* $Modtime:: 4/30/01 2:41p $*
* *
* $Revision:: 13 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* HashListClass::Find -- Find record in hash table. *
* HashListClass::Remove -- Remove record from hash table. *
* HashListClass::Add -- Add record to hash list. *
* HashListClass::Add -- Add record to list, list creates node for user. *
* HashListClass::Move_To -- Move nodes from one list to another. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef HASHLIST_H
#define HASHLIST_H
#pragma warning (push)
#pragma warning (disable: 4786)
#include "listnode.h"
#include <memory.h>
#ifndef NULL
#define NULL (0L)
#endif
#define A_LARGE_PRIME_NUMBER 257
// HashListClass<> and HashNodeClass<>:
// The purpose of these templates is to allow a user to insert records into
// a hash table that also contains a double linked list that includes every
// record in the hash table. The functionality of the hash list mirrors
// very closely that of the DataNode<> and List<> templates. The differences
// between them are:
// -User calls Add(?) to add to list instead of Add_Head() or others.
// -A key must be set to hash off of.
//
// Additional features of the HashList<> over List<> are:
// -Quick searching as long as key's are well hashed..
// -Node can inherit user class so additional data can be put in node.
// For example a timestamp to be set by user. Default is
// HashDefaluatUserClass that has no data.
// -If class T is actually a class (not a pointer), user may get a ptr
// to class with Get_Ptr() instead of Get() that returns an INSTANCE
// of the class.
// -Flags to tell user if record was just created or record was just put
// into a list (user must clear flags if desired.)
// -HashListClass<> can create and destroy nodes so that the nodes do not
// need to be put as members in classes. This allows an object to be
// put into an infinite (subject to memory constraints) lists.
// -User may specify number of hash node slots (default is A_LARGE_PRIME_NUMBER).
// You can typedef these templates with the the following:
// typedef HashListClass<TestHashClass *> HashTableClass;
// typedef HashNodeClass<TestHashClass *> HashTableNodeClass;
// or if using a UserClass
// typedef HashListClass<TestHashClass *, 4, UserClass> HashTableClass;
// typedef HashNodeClass<TestHashClass *, UserClass> HashTableNodeClass;
template<class T, class U> class HashNodeClass;
template<class T, class U> class HashNodeFriendClass;
template<class T, class U, int NumHashValues> class HashListClass;
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
// This is a default class that is stored in HashNodeClass. It's purpose is
// to allow the user to override it with his/her own class so that additional
// data may be stored in the node about the object.
// Since the object might be in various lists, this data is specific to
// the list that it in.
class HashDefaultUserClass {};
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
template<class T, class U = class HashDefaultUserClass>
class HashNodeClass : public DataNode<HashNodeClass<T,U> *>, public U
{
public:
// Creation when key and record are known.
HashNodeClass(T record, unsigned key) :
Flags(0),
Record(record),
Key(key)
{
DataNode<HashNodeClass<T,U> *>::Set(this);
Flag.NewRecord = true;
Flag.KeySet = true;
}
// Creation when key and record are to be set later.
// node may not be put into list until the key is set.
HashNodeClass() :
Flags(0),
Key(-1)
{
DataNode<HashNodeClass<T,U> *>::Set(this);
Flag.NewRecord = true;
}
virtual ~HashNodeClass() {
// Assert is raised when user tries to delete HashNodeClass still in a list
// NOTE: This might be raised because user expected node to clean
// itself up when deleted. Currently, this feature is not available
// because it would require an additional pointer to the HashListClass
// that the node is a member of.
assert(!Flag.InList);
}
// Get next and prev record given a node.
// A node may be retrieved from: HashListClass::Find();
HashNodeClass<T,U> *Next() {
return((HashNodeClass<T,U> *) DataNode<HashNodeClass<T,U> *>::Next());
}
HashNodeClass<T,U> *Prev() {
return((HashNodeClass<T,U> *) DataNode<HashNodeClass<T,U> *>::Prev());
}
// User may use these if he desires not to have to check for valid.
HashNodeClass<T,U> *Next_Valid() {
HashNodeClass<T,U> *next = Next();
if (next && next->Is_Valid()) {
return(next);
}
return(NULL);
}
HashNodeClass<T,U> *Prev_Valid() {
HashNodeClass<T,U> *prev = Prev();
if (prev && prev->Is_Valid()) {
return(prev);
}
return(NULL);
}
// Get record that is in hash table.
T Get_Record() {return(Record);}
T Get_Record_Ptr() {return(&Record);}
// Overload DataNode::Get() to get the record we are pointing to so
// that it behaves how people expect List to operate.
// To Get HashNodeClass - it is this.
T Get() {return(Record);}
// Get a pointer to Record to avoid a copy construction of Record if
// it is an instance of a class that does not want to be copied all
// over the place.
T *Get_Ptr() {return(&Record);}
// To mirror usage of DataNode().
void Set(T record) {Record = record;}
void Set_Key(unsigned key) {
// Can't change key once in a list, we would never find it.
assert(!Flag.InList);
Flag.KeySet = true;
Key = key;
}
// Get key of record for has table.
unsigned Get_Key() {
assert(Flag.KeySet);
return (Key);
}
// Enable user to know if a record has just been added to the list.
// It stays set until user clears it - not required.
int Is_New_Record() {return(Flag.NewRecord);}
void Clear_New_Record() {Flag.NewRecord = false;}
// Each time object gets put into a list NewInList is set.
// Stays set until user clears - not required.
int Is_New_In_List() {return(Flag.NewInList);}
void Clear_New_In_List() {Flag.NewInList = false;}
bool Is_In_List() {return(Flag.InList);}
bool Is_Key_Set() {return(Flag.KeySet);}
protected:
// Record that we are keeping in hash table.
// This is commonly a pointer to the actual record.
T Record;
// Key that user gives to identify record.
// WARNING: Duplicate keys are undefined behavior.
unsigned Key;
// Unioned flags so Flags can be initialized to 0.
union {
struct {
// When record collides in hash list, these ?InTable
// tell when to stop looking for object in hash entry.
unsigned FirstInTable:1;
unsigned LastInTable:1;
// This is set when record is first created. It is up to user
// to clear if he uses flag.
unsigned NewRecord:1;
// This is set when record is first put in list. It is up to user
// to clear if he uses flag.
unsigned NewInList:1;
// Certain functions may not happen if node is InList (in hash table)
// These include delete, Set_Key(), and possibly others.
unsigned InList:1;
// This is set so HashListClass knows if it should delete the
// node when removed from it's list.
unsigned ListCreated:1;
// Make sure someone does not insert a node into a list
// without setting it's key.
unsigned KeySet:1;
} Flag;
unsigned Flags;
};
private:
// Not something the casual user can call.
void Unlink(void) {
DataNode<HashNodeClass<T,U> *>::Unlink();
}
friend class HashNodeFriendClass<T,U>;
};
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
// This class is created so that HashListClass can access HashNodeClass.
// HashListClass cannot access directly because it is impossible
// (I could not figure out how) to tell HashNodeClass to be a friend
// to all creations of HashListClass<T,N> since HashNodeClass
// does not need the NumHashValues parameter.
#pragma warning(push)
#pragma warning(disable : 4786) // identifier was truncated to 255 chars in debug information.
template<class T, class U>
class HashNodeFriendClass
{
protected:
void Set_In_List(HashNodeClass<T,U> *ptr) {ptr->Flag.InList = true; ptr->Flag.NewInList = true;}
void Clear_In_List(HashNodeClass<T,U> *ptr) {ptr->Flag.InList = false; ptr->Flag.NewInList = false;}
bool Is_First(HashNodeClass<T,U> *ptr) {return(ptr->Flag.FirstInTable);}
bool Is_Last(HashNodeClass<T,U> *ptr) {return(ptr->Flag.LastInTable); }
void Set_First(HashNodeClass<T,U> *ptr) {ptr->Flag.FirstInTable = true; }
void Set_Last(HashNodeClass<T,U> *ptr) {ptr->Flag.LastInTable = true; }
void Clear_First(HashNodeClass<T,U> *ptr) {ptr->Flag.FirstInTable = false;}
void Clear_Last(HashNodeClass<T,U> *ptr) {ptr->Flag.LastInTable = false; }
void Set_List_Created(HashNodeClass<T,U> *ptr) {ptr->Flag.ListCreated = true; }
void Clear_List_Created(HashNodeClass<T,U> *ptr) {ptr->Flag.ListCreated = false; }
bool Is_List_Created(HashNodeClass<T,U> *ptr) {return(ptr->Flag.ListCreated);}
void Unlink(HashNodeClass<T,U> *ptr) {ptr->Unlink();}
};
#pragma warning(pop)
// The sole purpose of using NumHashValues as a template is to make it easier to
// view in a debugger. If it were an allocated array of pointers, the debugger does
// not easily show each element in the array.
template<class T, class U = class HashDefaultUserClass, int NumHashValues = A_LARGE_PRIME_NUMBER>
class HashListClass : protected HashNodeFriendClass<T,U>
{
public:
// Creation and destruction.
HashListClass() :
List(),NumRecords(0), UsedValues(0)
{
memset(HashTable, 0, sizeof(HashTable));
}
~HashListClass() {Delete();}
// Get first node in list so user can itterate through it.
// CAUTION: Do not destroy pointer returned or itterated though -
// you must call the Remove function on it.
// An assert() will come up if you try.
HashNodeClass<T,U> *First() {
return((HashNodeClass<T,U> *)List.First());
}
HashNodeClass<T,U> *First_Valid() {
return((HashNodeClass<T,U> *)List.First_Valid());
}
HashNodeClass<T,U> *Last() {
return((HashNodeClass<T,U> *)List.Last());
}
HashNodeClass<T,U> *Last_Valid() {
return((HashNodeClass<T,U> *)List.Last_Valid());
}
// Add a record to hash creating new HashNodeClass.
HashNodeClass<T,U> *Add(T record, unsigned key);
// Add an existing node not in a list to this list.
// This allows closer behavior to List class.
HashNodeClass<T,U> *Add(HashNodeClass<T,U> *node);
// Search for record based off key in hash table.
HashNodeClass<T,U> *Find(unsigned key);
// Use this remove if you know the node * already. It is quicker.
void Remove(HashNodeClass<T,U> *node);
// Use this remove if you need to do a find to get the node.
// OK if key does not exist in table.
bool Remove(unsigned key);
// Removes all nodes in list.
void Delete(void) {while (First()->Is_Valid()) Remove(First());}
// Move contents of one list to another (this becomes empty).
void Move_To(HashListClass<T,U> *newlist);
// So we always do it the same way.
unsigned Hash_Value(unsigned key) {
return(unsigned)(key % NumHashValues);
}
// Total number of records in hash table.
int Num_Records() {
return(NumRecords);
}
// how many hash values are used.
// The closer this number is to NumRecords, the
// better hashing going on.
int Num_Used_Values() {
return(UsedValues);
}
protected:
// This list can be walked from start to end of all objects in the list.
// User can use Get_First() to get first (valid) record in linked list.
List<DataNode<T> *> List;
// Points to first record in List that has the right 'value'.
// Must check LaastInTable to see if end of records in has list.
HashNodeClass<T,U> *HashTable[NumHashValues];
// Number of records we have in class.
int NumRecords;
int UsedValues;
};
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
/***********************************************************************************************
* HashListClass::Add -- Add record to hash list. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/26/1999 SKB : Created. *
*=============================================================================================*/
template <class T, class U, int NumHashValues>
HashNodeClass<T,U> *HashListClass<T, U, NumHashValues>::Add(HashNodeClass<T,U> *node)
{
// Get our index into the hash table.
int hashidx = Hash_Value(node->Get_Key());
assert(hashidx < NumHashValues);
// Tell system we are being put in the list (and make sure we weren't already in one).
assert(!node->Is_In_List());
Set_In_List(node);
// Get first hit in table.
HashNodeClass<T,U> *first = HashTable[hashidx];
if (first) {
// This will add the new node right after the first node in the list.
first->Link(node);
// If we are the first one to collide, then we will be at end of list.
// otherwise, we are at the end.
if (Is_Last(first)) {
Clear_Last(first);
Set_Last(node);
}
} else {
// We are first hit at hash index. Put ourselves at start of
List.Add_Head(node);
Set_First(node);
Set_Last(node);
HashTable[hashidx] = node;
UsedValues++;
}
NumRecords++;
return (node);
}
/***********************************************************************************************
* HashListClass::Add -- Add record to list, list creates node for user. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/03/1999 SKB : Created. *
*=============================================================================================*/
template <class T, class U, int NumHashValues>
HashNodeClass<T,U> *HashListClass<T, U, NumHashValues>::Add(T record, unsigned key)
{
// Create new node so we can add our record.
HashNodeClass<T,U> *node = W3DNEW HashNodeClass<T,U>(record, key);
Set_List_Created(node);
// Now let the other add do all the work.
Add(node);
return (node);
}
/***********************************************************************************************
* HashListClass::Find -- Find record in hash table. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/26/1999 SKB : Created. *
*=============================================================================================*/
template <class T, class U, int NumHashValues>
HashNodeClass<T,U> *HashListClass<T, U, NumHashValues>::Find(unsigned key)
{
int hashidx = Hash_Value(key);
assert(hashidx < NumHashValues);
HashNodeClass<T,U> *cur = HashTable[hashidx];
if (cur) for(;;) {
// Have we found our match?
if (cur->Get_Key() == key) {
return(cur);
}
// We have to find record before the end of the list.
if (Is_Last(cur)) {
break;
}
// Continue on because we appear to have some collisions.
cur = cur->Next();
// The end of a list should always be marked with Is_Last().
assert(cur);
assert(cur->Is_Valid());
}
return(NULL);
}
/***********************************************************************************************
* HashListClass::Remove_Node -- Remove node from hash table. *
* Protected function for usage by Remove() routines. *
* *
* INPUT: *
* HashNodeClass<T,U> *node - node to remove. *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/02/1999 SKB : Created. *
* 01/19/2000 SKB : Remove the node with Unlink. *
*=============================================================================================*/
template <class T, class U, int NumHashValues>
void HashListClass<T, U, NumHashValues>::Remove(HashNodeClass<T,U> *node)
{
assert(node);
assert(node->Is_In_List());
// See if entry is first in list for hash value.
if (Is_First(node)) {
int hashidx = Hash_Value(node->Get_Key());
assert(HashTable[hashidx]);
// SKB: 2/20/01 - clear incase inserted in new list later.
Clear_First(node);
// is it only one in hash index?
if (Is_Last(node)) {
// SKB: 2/20/01 - clear incase inserted in new list later.
Clear_Last(node);
HashTable[hashidx] = NULL;
UsedValues--;
} else {
HashTable[hashidx] = node->Next_Valid();
Set_First(HashTable[hashidx]);
}
} else if (Is_Last(node)) {
// SKB: 2/20/01 - clear incase inserted in new list later.
Clear_Last(node);
// There is one before us because it failed above.
Set_Last(node->Prev());
}
// All done with you. Set flag to avoid assert.
Clear_In_List(node);
// Delete node if it was created by the this class instead of by the user.
if (Is_List_Created(node)) {
delete node;
} else {
// Remove it from the link list at least so it can be put in another.
Unlink(node);
}
NumRecords--;
}
/***********************************************************************************************
* HashListClass::Remove -- Remove record from hash table. *
* *
* INPUT: *
* unsigned key - key to find node by. *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/26/1999 SKB : Created. *
*=============================================================================================*/
template <class T, class U, int NumHashValues>
bool HashListClass<T, U, NumHashValues>::Remove(unsigned key)
{
int hashidx = Hash_Value(key);
assert(hashidx < NumHashValues);
HashNodeClass<T,U> *node = Find(key);
if (node) {
Remove(node);
return(true);
}
return(false);
}
/***********************************************************************************************
* HashListClass::Move_To -- Move nodes from one list to another. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/04/1999 SKB : Created. *
*=============================================================================================*/
template <class T, class U, int NumHashValues>
void HashListClass<T, U, NumHashValues>::Move_To(HashListClass<T,U> *newlist)
{
HashNodeClass<T,U> *node = First_Valid();
while (node) {
HashNodeClass<T,U> *next = node->Next_Valid();
// If list created node, clear that fact for a moment so it
// will not get deleted in the remove.
if (Is_List_Created(node)) {
Clear_List_Created(node);
Remove(node);
newlist->Add(node);
Set_List_Created(node);
} else {
Remove(node);
newlist->Add(node);
}
node = next;
}
}
#pragma warning (pop)
#endif // HASHLIST_H

View File

@@ -0,0 +1,165 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/iff.h $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 9/23/99 1:46p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef IFF_H
#define IFF_H
#ifndef _WINDOWS
#define __cdecl
#endif
#include "buff.h"
#include <stddef.h>
#define LZW_SUPPORTED FALSE
/*=========================================================================*/
/* Iff and Load Picture system defines and enumerations */
/*=========================================================================*/
#define MAKE_ID(a,b,c,d) ((long) ((long) d << 24) | ((long) c << 16) | ((long) b << 8) | (long)(a))
#define IFFize_WORD(a) Reverse_Word(a)
#define IFFize_LONG(a) Reverse_Long(a)
//lint -strong(AJX,PicturePlaneType)
typedef enum {
BM_AMIGA, // Bit plane format (8K per bitplane).
BM_MCGA, // Byte per pixel format (64K).
BM_DEFAULT=BM_MCGA // Default picture format.
} PicturePlaneType;
/*
** This is the compression type code. This value is used in the compressed
** file header to indicate the method of compression used. Note that the
** LZW method may not be supported.
*/
//lint -strong(AJX,CompressionType)
typedef enum {
NOCOMPRESS, // No compression (raw data).
LZW12, // LZW 12 bit codes.
LZW14, // LZW 14 bit codes.
HORIZONTAL, // Run length encoding (RLE).
LCW // Westwood proprietary compression.
} CompressionType;
/*
** Compressed blocks of data must start with this header structure.
** Note that disk based compressed files have an additional two
** leading bytes that indicate the size of the entire file.
*/
//lint -strong(AJX,CompHeaderType)
typedef struct {
char Method; // Compression method (CompressionType).
char pad; // Reserved pad byte (always 0).
long Size; // Size of the uncompressed data.
short Skip; // Number of bytes to skip before data.
} CompHeaderType;
/*=========================================================================*/
/* The following prototypes are for the file: IFF.CPP */
/*=========================================================================*/
int __cdecl Open_Iff_File(char const *filename);
void __cdecl Close_Iff_File(int fh);
unsigned long __cdecl Get_Iff_Chunk_Size(int fh, long id);
unsigned long __cdecl Read_Iff_Chunk(int fh, long id, void *buffer, unsigned long maxsize);
void __cdecl Write_Iff_Chunk(int file, long id, void *buffer, long length);
/*=========================================================================*/
/* The following prototypes are for the file: LOADPICT.CPP */
/*=========================================================================*/
//int __cdecl Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette=NULL, PicturePlaneType format=BM_DEFAULT);
/*=========================================================================*/
/* The following prototypes are for the file: LOAD.CPP */
/*=========================================================================*/
unsigned long __cdecl Load_Data(char const *name, void *ptr, unsigned long size);
unsigned long __cdecl Write_Data(char const *name, void *ptr, unsigned long size);
//void * __cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags);
unsigned long __cdecl Load_Uncompress(char const *file, Buffer & uncomp_buff, Buffer & dest_buff, void *reserved_data=NULL);
unsigned long __cdecl Uncompress_Data(void const *src, void *dst);
void __cdecl Set_Uncomp_Buffer(int buffer_segment, int size_of_buffer);
/*=========================================================================*/
/* The following prototypes are for the file: WRITELBM.CPP */
/*=========================================================================*/
//bool Write_LBM_File(int lbmhandle, BufferClass& buff, int bitplanes, unsigned char *palette);
/*========================= Assembly Functions ============================*/
#ifdef __cplusplus
extern "C" {
#endif
/*=========================================================================*/
/* The following prototypes are for the file: PACK2PLN.ASM */
/*=========================================================================*/
extern void __cdecl Pack_2_Plane(void *buffer, void * pageptr, int planebit);
/*=========================================================================*/
/* The following prototypes are for the file: LCWCOMP.ASM */
/*=========================================================================*/
extern unsigned long __cdecl LCW_Compress(void *source, void *dest, unsigned long length);
/*=========================================================================*/
/* The following prototypes are for the file: LCWUNCMP.ASM */
/*=========================================================================*/
extern unsigned long __cdecl LCW_Uncompress(void *source, void *dest, unsigned long length);
#ifdef __cplusplus
}
#endif
/*=========================================================================*/
#endif //IFF_H

View File

@@ -0,0 +1,730 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/INDEX.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:59a $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* IndexClass<T>::Add_Index -- Add element to index tracking system. *
* IndexClass<T>::Clear -- Clear index handler to empty state. *
* IndexClass<T>::Count -- Fetch the number of index entries recorded. *
* IndexClass<T>::Fetch_Index -- Fetch data from specified index. *
* IndexClass<T>::Increase_Table_Size -- Increase the internal index table capacity. *
* IndexClass<T>::IndexClass -- Constructor for index handler. *
* IndexClass<T>::Invalidate_Archive -- Invalidate the archive pointer. *
* IndexClass<T>::Is_Archive_Same -- Checks to see if archive pointer is same as index. *
* IndexClass<T>::Is_Present -- Checks for presense of index entry. *
* IndexClass<T>::Remove_Index -- Find matching index and remove it from system. *
* IndexClass<T>::Search_For_Node -- Perform a search for the specified node ID *
* IndexClass<T>::Set_Archive -- Records the node pointer into the archive. *
* IndexClass<T>::Sort_Nodes -- Sorts nodes in preparation for a binary search. *
* IndexClass<T>::~IndexClass -- Destructor for index handler object. *
* compfunc -- Support function for bsearch and bsort. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef INDEX_H
#define INDEX_H
#include "bsearch.h"
#if !defined(__BORLANDC__) || !defined(_USERENTRY)
#define _USERENTRY
#endif
/*
** This class is used to create and maintain an index. It does this by assigning a unique
** identifier number to the type objects that it is indexing. The regular binary sort and search
** function are used for speedy index retrieval. Typical use of this would be to index pointers to
** normal data objects, but it can be used to hold the data objects themselves. Keep in mind that
** the data object "T" is copied around by this routine in the internal tables so not only must
** it have a valid copy constructor, it must also be efficient. The internal algorithm will
** create an arbitrary number of default constructed objects of type "T". Make sure it has a
** default constructor that is efficient and trivial. The constructor need not perform any actual
** initialization since this class has prior knowledge about the legality of these temporary
** objects and doesn't use them until after the copy constructor is used to initialize them.
** This means that the default constructed object of type "T" can be technically in an unusable
** state since it won't ever be used by this routine and won't ever be returned by any of
** this template's methods.
**
** This should properly be called a "map container class" since it is a container with a
** mapping of an identifier.
*/
template<class INDEX, class T>
class IndexClass
{
public:
IndexClass(void);
~IndexClass(void);
/*
** Add element to index table.
*/
bool Add_Index(INDEX const & id, T const & data);
/*
** Removes an index entry from the index table.
*/
bool Remove_Index(INDEX const & id);
/*
** Check to see if index is present.
*/
bool Is_Present(INDEX const & id) const;
/*
** Fetch number of index entries in the table.
*/
int Count(void) const;
/*
** Actually a fetch an index data element from the table.
*/
T const & operator [] (INDEX const & id) const;
/*
** Fetch a data element by position reference.
*/
T const & Fetch_By_Position(int id) const;
INDEX const Fetch_ID_By_Position(int pos) const {return(IndexTable[pos].ID);}
/*
** Clear out the index table to null (empty) state.
*/
void Clear(void);
private:
/*
** This node object is used to keep track of the connection between the data
** object and the index identifier number.
*/
struct NodeElement {
NodeElement(void) {} // Default constructor does nothing (by design).
NodeElement(INDEX const & id, T & data) : ID(id), Data(data) {}
INDEX ID; // ID number (must be first element in this structure).
T Data; // Data element assigned to this ID number.
bool operator == (NodeElement const & rvalue) const {return(ID == rvalue.ID);}
bool operator < (NodeElement const & rvalue) const {return(ID < rvalue.ID);}
};
/*
** This is the pointer to the allocated index table. It contains all valid nodes in
** a sorted order.
*/
NodeElement * IndexTable;
/*
** This records the number of valid nodes within the index table.
*/
int IndexCount;
/*
** The total size (in nodes) of the index table is recorded here. If adding a node
** would cause the index count to exceed this value, the index table must be resized
** to make room.
*/
int IndexSize;
/*
** If the index table is sorted and ready for searching, this flag will be true. Sorting
** of the table only occurs when absolutely necessary.
*/
mutable bool IsSorted;
/*
** This records a pointer to the last element found by the Is_Present() function. Using
** this last recorded value can allow quick fetches of data whenever possible.
*/
mutable NodeElement const * Archive;
/*
** Increase size of internal index table by amount specified.
*/
bool Increase_Table_Size(int amount);
/*
** Check if archive pointer is the same as that requested.
*/
bool Is_Archive_Same(INDEX const & id) const;
/*
** Invalidate the archive pointer.
*/
void Invalidate_Archive(void) const;
/*
** Set archive to specified value.
*/
void Set_Archive(NodeElement const * node) const;
/*
** Search for the node in the index table.
*/
NodeElement const * Search_For_Node(INDEX const & id) const;
static int _USERENTRY search_compfunc(void const * ptr, void const * ptr2);
};
/***********************************************************************************************
* IndexClass<T>::IndexClass -- Constructor for index handler. *
* *
* This constructs an empty index handler. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
IndexClass<INDEX, T>::IndexClass(void) :
IndexTable(0),
IndexCount(0),
IndexSize(0),
IsSorted(false),
Archive(0)
{
Invalidate_Archive();
}
/***********************************************************************************************
* IndexClass<T>::~IndexClass -- Destructor for index handler object. *
* *
* This will destruct and free any resources managed by this index handler. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
IndexClass<INDEX, T>::~IndexClass(void)
{
Clear();
}
/***********************************************************************************************
* IndexClass<T>::Clear -- Clear index handler to empty state. *
* *
* This routine will free all internal resources and bring the index handler into a *
* known empty state. After this routine, the index handler is free to be reused. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
void IndexClass<INDEX, T>::Clear(void)
{
delete [] IndexTable;
IndexTable = 0;
IndexCount = 0;
IndexSize = 0;
IsSorted = false;
Invalidate_Archive();
}
/***********************************************************************************************
* IndexClass<T>::Increase_Table_Size -- Increase the internal index table capacity. *
* *
* This helper function will increase the capacity of the internal index table without *
* performing any alterations to the index data. Use this routine prior to adding a new *
* element if the existing capacity is insufficient. *
* *
* INPUT: amount -- The number of index element spaces to add to its capacity. *
* *
* OUTPUT: bool; Was the internal capacity increased without error? *
* *
* WARNINGS: If there is insufficient RAM, then this routine will fail. *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
bool IndexClass<INDEX, T>::Increase_Table_Size(int amount)
{
/*
** Check size increase parameter for legality.
*/
if (amount < 0) return(false);
NodeElement * table = W3DNEWARRAY NodeElement[IndexSize + amount];
if (table != NULL) {
/*
** Copy all valid nodes into the new table.
*/
for (int index = 0; index < IndexCount; index++) {
table[index] = IndexTable[index];
}
/*
** Make the new table the current one (and delete the old one).
*/
delete [] IndexTable;
IndexTable = table;
IndexSize += amount;
Invalidate_Archive();
/*
** Return with success flag.
*/
return(true);
}
/*
** Failure to allocate the memory results in a failure to increase
** the size of the index table.
*/
return(false);
}
/***********************************************************************************************
* IndexClass<T>::Count -- Fetch the number of index entries recorded. *
* *
* This will return the quantity of index entries that have been recored by this index *
* handler. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with number of recored indecies present. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
int IndexClass<INDEX, T>::Count(void) const
{
return(IndexCount);
}
/***********************************************************************************************
* IndexClass<T>::Is_Present -- Checks for presense of index entry. *
* *
* This routine will scan for the specified index entry. If it was found, then 'true' is *
* returned. *
* *
* INPUT: id -- The index ID to search for. *
* *
* OUTPUT: bool; Was the index entry found in this index handler object? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
bool IndexClass<INDEX, T>::Is_Present(INDEX const & id) const
{
/*
** If there are no data elements in the index table, then it can
** never find the specified index. Check for and return failure
** in this case.
*/
if (IndexCount == 0) {
return(false);
}
/*
** Check to see if this same index element was previously searched for. If
** so and it was previously found, then there is no need to search for it
** again -- just return true.
*/
if (Is_Archive_Same(id)) {
return(true);
}
/*
** Perform a binary search on the index nodes in order to look for a
** matching index value.
*/
NodeElement const * nodeptr = Search_For_Node(id);
/*
** If a matching index was found, then record it for future reference and return success.
*/
if (nodeptr != 0) {
Set_Archive(nodeptr);
return(true);
}
/*
** Could not find element so return failure condition.
*/
return(false);
}
/***********************************************************************************************
* IndexClass<T>::Fetch_By_Index -- Fetch data from specified index. *
* *
* This routine will find the specified index and return the data value associated with it. *
* *
* INPUT: id -- The index ID to search for. *
* *
* OUTPUT: Returns with the data value associated with the index value. *
* *
* WARNINGS: This routine presumes that the index exists. If it doesn't exist, then the *
* default constructed object "T" is returned instead. To avoid this problem, *
* always verfiy the existance of the index by calling Is_Present() first. *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
#ifdef __BORLANDC__
#pragma warn -def
#endif
template<class INDEX, class T>
T const & IndexClass<INDEX, T>::operator [] (INDEX const & id) const
{
if (Is_Present(id)) {
/*
** Count on the fact that the archive pointer is always valid after a call to Is_Present
** that returns "true".
*/
return(Archive->Data);
}
static T x;
return(x);
}
#ifdef __BORLANDC__
#pragma warn .def
#endif
template<class INDEX, class T>
T const & IndexClass<INDEX, T>::Fetch_By_Position(int pos) const
{
assert(pos < IndexCount);
return(IndexTable[pos].Data);
}
/***********************************************************************************************
* IndexClass<T>::Is_Archive_Same -- Checks to see if archive pointer is same as index. *
* *
* This routine compares the specified index ID with the previously recorded index archive *
* pointer in order to determine if they match. *
* *
* INPUT: id -- The index ID to compare to the archive index object pointer. *
* *
* OUTPUT: bool; Does the specified index match the archive pointer? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
bool IndexClass<INDEX, T>::Is_Archive_Same(INDEX const & id) const
{
if (Archive != 0 && Archive->ID == id) {
return(true);
}
return(false);
}
/***********************************************************************************************
* IndexClass<T>::Invalidate_Archive -- Invalidate the archive pointer. *
* *
* This routine will set the archive pointer to an invalid state. This must be performed *
* if ever the archive pointer would become illegal (such as when the element it refers to *
* is deleted). *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
void IndexClass<INDEX, T>::Invalidate_Archive(void) const
{
Archive = 0;
}
/***********************************************************************************************
* IndexClass<T>::Set_Archive -- Records the node pointer into the archive. *
* *
* This routine records the specified node pointer. Use this routine when there is a *
* good chance that the specified node will be requested in the immediate future. *
* *
* INPUT: node -- Pointer to the node to assign to the archive. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
void IndexClass<INDEX, T>::Set_Archive(NodeElement const * node) const
{
Archive = node;
}
/***********************************************************************************************
* IndexClass<T>::Add_Index -- Add element to index tracking system. *
* *
* This routine will record the index information into this index manager object. It *
* associates the index number with the data specified. The data is copied to an internal *
* storage location. *
* *
* INPUT: id -- The ID number to associate with the data. *
* *
* data -- The data to store. *
* *
* OUTPUT: bool; Was the element added without error? Failure indicates that RAM has been *
* exhausted. *
* *
* WARNINGS: The data is COPIED to internal storage. This means that the data object must *
* have a functional and efficient copy constructor and assignment operator. *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
bool IndexClass<INDEX, T>::Add_Index(INDEX const & id, T const & data)
{
#ifdef _DEBUG
/*
** Ensure that two elements with the same index are not added to the
** array.
*/
for (int index = 0; index < IndexCount; index++) {
assert(IndexTable[index].ID != id);
}
#endif
/*
** Ensure that there is enough room to add this index. If not, then increase the
** capacity of the internal index table.
*/
if (IndexCount + 1 > IndexSize) {
if (!Increase_Table_Size(IndexSize == 0 ? 10 : IndexSize)) {
/*
** Failure to increase the size of the index table means failure to add
** the index element.
*/
return(false);
}
}
/*
** Add the data to the end of the index data and then sort the index table.
*/
IndexTable[IndexCount].ID = id;
IndexTable[IndexCount].Data = data;
IndexCount++;
IsSorted = false;
return(true);
}
/***********************************************************************************************
* IndexClass<T>::Remove_Index -- Find matching index and remove it from system. *
* *
* This will scan through the previously added index elements and if a match was found, it *
* will be removed. *
* *
* INPUT: id -- The index ID to search for and remove. *
* *
* OUTPUT: bool; Was the index element found and removed? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
bool IndexClass<INDEX, T>::Remove_Index(INDEX const & id)
{
/*
** Find the array index into the table that matches the specified id value.
*/
int found_index = -1;
for (int index = 0; index < IndexCount; index++) {
if (IndexTable[index].ID == id) {
found_index = index;
break;
}
}
/*
** Trying to remove something that isn't there could be an
** error in the calling routine?
*/
// assert(found_index);
/*
** If the array index was found, then copy all higher index entries
** downward to fill the vacated location. We cannot use memcpy here because the type
** object may not support raw copies. C++ defines the assignment operator to deal
** with this, so that is what we use.
*/
if (found_index != -1) {
for (int index = found_index+1; index < IndexCount; index++) {
IndexTable[index-1] = IndexTable[index];
}
IndexCount--;
NodeElement fake;
fake.ID = 0;
fake.Data = T();
IndexTable[IndexCount] = fake; // zap last (now unused) element
Invalidate_Archive();
return(true);
}
return(false);
}
/***********************************************************************************************
* compfunc -- Support function for bsearch and bsort. *
* *
* This compare function presumes that its parameters are pointing to NodeElements and that *
* the first "int" in the node is the index ID number to be used for comparison. *
* *
* INPUT: ptr1 -- Pointer to first node. *
* *
* ptr2 -- Pointer to second node. *
* *
* OUTPUT: Returns with the comparision value between the two nodes. *
* *
* WARNINGS: This is highly dependant upon the layout of the NodeElement structure. *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
int _USERENTRY IndexClass<INDEX, T>::search_compfunc(void const * ptr1, void const * ptr2)
{
if (*(int const *)ptr1 == *(int const *)ptr2) {
return(0);
}
if (*(int const *)ptr1 < *(int const *)ptr2) {
return(-1);
}
return(1);
}
/***********************************************************************************************
* IndexClass<T>::Search_For_Node -- Perform a search for the specified node ID *
* *
* This routine will perform a binary search on the previously recorded index values and *
* if a match was found, it will return a pointer to the NodeElement. *
* *
* INPUT: id -- The index ID to search for. *
* *
* OUTPUT: Returns with a pointer to the NodeElement that matches the index ID specified. If *
* no matching index could be found, then NULL is returned. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/02/1996 JLB : Created. *
*=============================================================================================*/
template<class INDEX, class T>
#ifdef __BORLANDC__
NodeElement const * IndexClass<INDEX, T>::Search_For_Node(INDEX const & id) const
#else
IndexClass<INDEX, T>::NodeElement const * IndexClass<INDEX, T>::Search_For_Node(INDEX const & id) const
#endif
{
/*
** If there are no elements in the list, then it certainly can't find any matches.
*/
if (IndexCount == 0) {
return(0);
}
/*
** If the list has not yet been sorted, then do so now. Binary searching requires
** the list to be sorted.
*/
if (!IsSorted) {
qsort(&IndexTable[0], IndexCount, sizeof(IndexTable[0]), search_compfunc);
Invalidate_Archive();
IsSorted = true;
}
/*
** This list is sorted and ready to perform a binary search upon it.
*/
NodeElement node;
node.ID = id;
return(Binary_Search(IndexTable, IndexCount, node));
// return((NodeElement const *)bsearch(&node, &IndexTable[0], IndexCount, sizeof(IndexTable[0]), search_compfunc));
}
#endif

View File

@@ -0,0 +1,211 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /VSS_Sync/wwlib/ini.h $*
* *
* $Author:: Vss_sync $*
* *
* $Modtime:: 3/21/01 12:01p $*
* *
* $Revision:: 12 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef INI_H
#define INI_H
//#include "listnode.h"
//#include "trect.h"
//#include "index.h"
//#include "pipe.h"
//#include "pk.h"
//#include "straw.h"
//#include "wwfile.h"
class PKey;
class FileClass;
class Straw;
class Pipe;
class StringClass;
class FileFactoryClass;
struct INISection;
struct INIEntry;
template<class T> class TPoint3D;
template<class T> class TPoint2D;
template<class T> class TRect;
template<class T> class List;
template<class T, class U> class IndexClass;
#ifndef NULL
#define NULL 0L
#endif
/*
** This is an INI database handler class. It handles a database with a disk format identical
** to the INI files commonly used by Windows.
*/
class INIClass {
public:
INIClass(void);
INIClass(FileClass & file);
INIClass(const char *filename);
virtual ~INIClass(void);
/*
** Fetch and store INI data.
*/
int Load(FileClass & file);
int Load(Straw & file);
int Load(const char *filename);
int Save(FileClass & file) const;
int Save(Pipe & file) const;
int Save(const char *filename) const;
/*
** Erase all data within this INI file manager.
*/
bool Clear(char const * section = NULL, char const * entry = NULL);
// int Line_Count(char const * section) const;
bool Is_Loaded(void) const;
int Size(void) const;
bool Is_Present(char const * section, char const * entry = NULL) const {if (entry == 0) return(Find_Section(section) != 0);return(Find_Entry(section, entry) != 0);}
/*
** Fetch the number of sections in the INI file or verify if a specific
** section is present.
*/
int Section_Count(void) const;
bool Section_Present(char const * section) const {return(Find_Section(section) != NULL);}
/*
** Fetch the number of entries in a section or get a particular entry in a section.
*/
int Entry_Count(char const * section) const;
char const * Get_Entry(char const * section, int index) const;
/*
** Cound how many entries with the indicated prefix followed by a number exist in the section.
*/
unsigned Enumerate_Entries(const char * section, const char * entry_prefix, unsigned startnumber = 0, unsigned endnumber = (unsigned) -1);
/*
** Get the various data types from the section and entry specified.
*/
PKey Get_PKey(bool fast) const;
bool Get_Bool(char const * section, char const * entry, bool defvalue=false) const;
float Get_Float(char const * section, char const * entry, float defvalue=0.0) const;
int Get_Hex(char const * section, char const * entry, int defvalue=0) const;
int Get_Int(char const * section, char const * entry, int defvalue=0) const;
int Get_String(char const * section, char const * entry, char const * defvalue, char * buffer, int size) const;
StringClass Get_String(char const * section, char const * entry, char const * defvalue="") const;
int Get_List_Index(char const * section, char const * entry, int const defvalue, char *list[]);
int * Get_Alloc_Int_Array(char const * section, char const * entry, int listend);
int Get_Int_Bitfield(char const * section, char const * entry, int defvalue, char *list[]);
char *Get_Alloc_String(char const * section, char const * entry, char const * defvalue) const;
int Get_TextBlock(char const * section, char * buffer, int len) const;
int Get_UUBlock(char const * section, void * buffer, int len) const;
TRect<int> const Get_Rect(char const * section, char const * entry, TRect<int> const & defvalue) const;
TPoint3D<int> const Get_Point(char const * section, char const * entry, TPoint3D<int> const & defvalue) const;
TPoint2D<int> const Get_Point(char const * section, char const * entry, TPoint2D<int> const & defvalue) const;
TPoint3D<float> const Get_Point(char const * section, char const * entry, TPoint3D<float> const & defvalue) const;
TPoint2D<float> const Get_Point(char const * section, char const * entry, TPoint2D<float> const & defvalue) const;
/*
** Put a data type to the section and entry specified.
*/
bool Put_Bool(char const * section, char const * entry, bool value);
bool Put_Float(char const * section, char const * entry, double number);
bool Put_Hex(char const * section, char const * entry, int number);
bool Put_Int(char const * section, char const * entry, int number, int format=0);
bool Put_PKey(PKey const & key);
bool Put_String(char const * section, char const * entry, char const * string);
bool Put_TextBlock(char const * section, char const * text);
bool Put_UUBlock(char const * section, void const * block, int len);
bool Put_Rect(char const * section, char const * entry, TRect<int> const & value);
bool Put_Point(char const * section, char const * entry, TPoint3D<int> const & value);
bool Put_Point(char const * section, char const * entry, TPoint3D<float> const & value);
bool Put_Point(char const * section, char const * entry, TPoint2D<int> const & value);
// protected:
enum {MAX_LINE_LENGTH=512};
/*
** Access to the list of all sections within this INI file.
*/
List<INISection *> & Get_Section_List() { return * SectionList; }
IndexClass<int, INISection *> & Get_Section_Index() { return * SectionIndex; }
/*
** Utility routines to help find the appropriate section and entry objects.
*/
INISection * Find_Section(char const * section) const;
INIEntry * Find_Entry(char const * section, char const * entry) const;
static void Strip_Comments(char * buffer);
// the CRC function is used to produce hopefully unique values for
// each of the entries in a section. Debug messages will be produced
// if redundant CRCs are generated for a particular INI file.
static int CRC(const char *string);
// the DuplicateCRCError function is used by Put_String and Load in the case
// that an entry's CRC matches one already in the database.
void DuplicateCRCError(const char *message, const char *entry);
private:
/*
** These functions are used to allocate and free the section list and section index
*/
void Initialize(void);
void Shutdown(void);
/*
** This is the list of all sections within this INI file.
*/
List<INISection *> * SectionList;
IndexClass<int, INISection *> * SectionIndex;
/*
** Ensure that the copy constructor and assignment operator never exist.
*/
INIClass(INIClass const & rvalue);
INIClass operator = (INIClass const & rvalue);
};
#endif

View File

@@ -0,0 +1,310 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /VSS_Sync/wwlib/int.h $*
* *
* $Author:: Vss_sync $*
* *
* $Modtime:: 3/21/01 12:01p $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef INT_H
#define INT_H
#include "mpmath.h"
#include "straw.h"
#include <assert.h>
#include <limits.h>
#include <memory.h>
#ifdef __BORLANDC__
#pragma warn -inl
#endif
template<class T> struct RemainderTable;
template<class T> T Gcd(const T & a, const T & n);
#ifdef _UNIX
#define FN_TEMPLATE <>
#else
#define FN_TEMPLATE
#endif
template<int PRECISION>
class Int {
public:
/*
** Constructors and initializers.
*/
Int(void) {XMP_Init(&reg[0], 0, PRECISION);}
Int(unsigned long value) {XMP_Init(&reg[0], value, PRECISION);}
void Randomize(Straw & rng, int bitcount) {XMP_Randomize(&reg[0], rng, bitcount, PRECISION);}
void Randomize(Straw & rng, const Int & minval, const Int & maxval) {XMP_Randomize_Bounded(&reg[0], rng, minval, maxval, PRECISION); reg[0] |= 1;}
/*
** Convenient conversion operators to get at the underlying array of
** integers. Big number math is basically manipulation of arbitrary
** length arrays.
*/
operator digit * () {return & reg[0];}
operator const digit * () const {return & reg[0];}
/*
** Array access operator (references bit position). Bit 0 is the first bit.
*/
bool operator[](unsigned bit) const {return(XMP_Test_Bit(&reg[0], bit));}
/*
** Unary operators.
*/
Int & operator ++ (void) {XMP_Inc(&reg[0], PRECISION);return(*this);}
Int & operator -- (void) {XMP_Dec(&reg[0], PRECISION);return(*this);}
int operator ! (void) const {return(XMP_Test_Eq_Int(&reg[0], 0, PRECISION));}
Int operator ~ (void) {XMP_Not(&reg[0], PRECISION);return(*this);}
Int operator - (void) const {Int a = *this;a.Negate();return (a);}
/*
** Attribute query functions.
*/
int ByteCount(void) const {return(XMP_Count_Bytes(&reg[0], PRECISION));}
int BitCount(void) const {return(XMP_Count_Bits(&reg[0], PRECISION));}
bool Is_Negative(void) const {return(XMP_Is_Negative(&reg[0], PRECISION));}
unsigned MaxBitPrecision() const {return PRECISION*(sizeof(unsigned long)*CHAR_BIT);}
bool IsSmallPrime(void) const {return(XMP_Is_Small_Prime(&reg[0], PRECISION));}
bool SmallDivisorsTest(void) const {return(XMP_Small_Divisors_Test(&reg[0], PRECISION));}
bool FermatTest(unsigned rounds) const {return(XMP_Fermat_Test(&reg[0], rounds, PRECISION));}
bool IsPrime(void) const {return(XMP_Is_Prime(&reg[0], PRECISION));}
bool RabinMillerTest(Straw & rng, unsigned int rounds) const {return(XMP_Rabin_Miller_Test(rng, &reg[0], rounds, PRECISION));}
/*
** 'in-place' binary operators.
*/
Int & operator += (const Int & number) {Carry = XMP_Add(&reg[0], &reg[0], number, 0, PRECISION);return(*this);}
Int & operator -= (const Int & number) {Borrow = XMP_Sub(&reg[0], &reg[0], number, 0, PRECISION);return(*this);}
Int & operator *= (const Int & multiplier) {Remainder = *this;Error=XMP_Signed_Mult(&reg[0], Remainder, multiplier, PRECISION);return(*this);}
Int & operator /= (const Int & t) {*this = (*this) / t;return *this;}
Int & operator %= (const Int & t) {*this = (*this) % t;return *this;}
Int & operator <<= (int bits) {XMP_Shift_Left_Bits(&reg[0], bits, PRECISION);return *this;}
Int & operator >>= (int bits) {XMP_Shift_Right_Bits(&reg[0], bits, PRECISION);return *this;}
/*
** Mathematical binary operators.
*/
Int operator + (const Int & number) const {Int term;Carry = XMP_Add(term, &reg[0], number, 0, PRECISION);return(term);}
Int operator + (unsigned short b) const {Int result;Carry=XMP_Add_Int(result, &reg[0], b, 0, PRECISION);return(result);}
Int operator - (const Int & number) const {Int term;Borrow = XMP_Sub(term, &reg[0], number, 0, PRECISION);return(term);}
Int operator - (unsigned short b) const {Int result;Borrow = XMP_Sub_Int(result, &reg[0], b, 0, PRECISION);return(result);}
Int operator * (const Int & multiplier) const {Int result;Error=XMP_Signed_Mult(result, &reg[0], multiplier, PRECISION);return result;}
Int operator * (unsigned short b) const {Int result;Error=XMP_Unsigned_Mult_Int(result, &reg[0], b, PRECISION);return(result);}
Int operator / (const Int & divisor) const {Int quotient = *this;XMP_Signed_Div(Remainder, quotient, &reg[0], divisor, PRECISION);return (quotient);}
Int operator / (unsigned long b) const {return(*this / Int<PRECISION>(b));}
Int operator / (unsigned short divisor) const {Int quotient;Error=XMP_Unsigned_Div_Int(quotient, &reg[0], divisor, PRECISION);return(quotient);}
Int operator % (const Int & divisor) const {Int remainder;XMP_Signed_Div(remainder, Remainder, &reg[0], divisor, PRECISION);return(remainder);}
Int operator % (unsigned long b) const {return(*this % Int<PRECISION>(b));}
unsigned short operator % (unsigned short divisor) const {return(XMP_Unsigned_Div_Int(Remainder, &reg[0], divisor, PRECISION));}
/*
** Bitwise binary operators.
*/
Int operator >> (int bits) const {Int result = *this; XMP_Shift_Right_Bits(result, bits, PRECISION);return result;}
Int operator << (int bits) const {Int result = *this; XMP_Shift_Left_Bits(result, bits, PRECISION);return result;}
/*
** Comparison binary operators.
*/
int operator == (const Int &b) const {return (memcmp(&reg[0], &b.reg[0], (MAX_BIT_PRECISION/CHAR_BIT))==0);}
int operator != (const Int& b) const {return !(*this == b);}
int operator > (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) > 0);}
int operator >= (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) >= 0);}
int operator < (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) < 0);}
int operator <= (const Int & number) const {return(XMP_Compare(&reg[0], number, PRECISION) <= 0);}
/*
** Misc. mathematical and logical functions.
*/
void Negate(void) {XMP_Neg(&reg[0], PRECISION);}
Int Abs(void) {XMP_Abs(&reg[0], PRECISION);return(*this);}
Int exp_b_mod_c(const Int & e, const Int & m) const {
Int result;
Error=XMP_Exponent_Mod(result, &reg[0], e, m, PRECISION);
return result;
}
void Set_Bit(int index) { XMP_Set_Bit(&reg[0], index); }
static Int Unsigned_Mult(Int const & multiplicand, Int const & multiplier) {Int product;Error=XMP_Unsigned_Mult(&product.reg[0], &multiplicand.reg[0], &multiplier.reg[0], PRECISION);return(product);}
static void Unsigned_Divide(Int & remainder, Int & quotient, const Int & dividend, const Int & divisor) {Error=XMP_Unsigned_Div(remainder, quotient, dividend, divisor, PRECISION);}
static void Signed_Divide(Int & remainder, Int & quotient, const Int & dividend, const Int & divisor) {XMP_Signed_Div(remainder, quotient, dividend, divisor, PRECISION);}
Int Inverse(const Int & modulus) const {Int result;XMP_Inverse_A_Mod_B(result, &reg[0], modulus, PRECISION);return(result);}
static Int Decode_ASCII(char const * string) {Int result;XMP_Decode_ASCII(string, result, PRECISION);return(result);}
// Number (sign independand) inserted into buffer.
int Encode(unsigned char *output) const {return(XMP_Encode(output, &reg[0], PRECISION));}
int Encode(unsigned char * output, unsigned length) const {return(XMP_Encode_Bounded(output, length, &reg[0], PRECISION));}
void Signed_Decode(const unsigned char * from, int frombytes) {XMP_Signed_Decode(&reg[0], from, frombytes, PRECISION);}
void Unsigned_Decode(const unsigned char * from, int frombytes) {XMP_Unsigned_Decode(&reg[0], from, frombytes, PRECISION);}
// encode Int using Distinguished Encoding Rules, returns size of output
int DEREncode(unsigned char * output) const {return(XMP_DER_Encode(&reg[0], output, PRECISION));}
void DERDecode(const unsigned char *input) {XMP_DER_Decode(&reg[0], input, PRECISION);}
// Friend helper functions.
friend Int<PRECISION> Gcd FN_TEMPLATE (const Int<PRECISION> &, const Int<PRECISION> &);
static int Error;
// Carry result from last addition.
static bool Carry;
// Borrow result from last subtraction.
static bool Borrow;
// Remainder value from the various division routines.
static Int Remainder;
digit reg[PRECISION];
friend struct RemainderTable< Int<PRECISION> >;
};
template<class T>
struct RemainderTable
{
RemainderTable(const T & p) : HasZeroEntry(false)
{
int primesize = XMP_Fetch_Prime_Size();
unsigned short const * primetable = XMP_Fetch_Prime_Table();
for (int i = 0; i < primesize; i++) {
table[i] = p % primetable[i];
}
}
bool HasZero() const {return(HasZeroEntry);}
void Increment(unsigned short increment = 1)
{
int primesize = XMP_Fetch_Prime_Size();
unsigned short const * primetable = XMP_Fetch_Prime_Table();
HasZeroEntry = false;
for (int i = 0; i < primesize; i++) {
table[i] += increment;
while (table[i] >= primetable[i]) {
table[i] -= primetable[i];
}
HasZeroEntry = (HasZeroEntry || !table[i]);
}
}
void Increment(const RemainderTable & rtQ)
{
HasZeroEntry = false;
int primesize = XMP_Fetch_Prime_Size();
unsigned short const * primetable = XMP_Fetch_Prime_Table();
for (int i = 0; i < primesize; i++) {
table[i] += rtQ.table[i];
if (table[i] >= primetable[i]) {
table[i] -= primetable[i];
}
HasZeroEntry = (HasZeroEntry || !table[i]);
}
}
bool HasZeroEntry;
unsigned short table[3511];
};
template<class T>
T Gcd(const T & a, const T & n)
{
T g[3]={n, a, 0UL};
unsigned int i = 1;
while (!!g[i%3]) {
g[(i+1)%3] = g[(i-1)%3] % g[i%3];
i++;
}
return g[(i-1)%3];
}
#if defined(__WATCOMC__)
#pragma warning 604 9
#pragma warning 595 9
#endif
template<class T>
T Generate_Prime(Straw & rng, int pbits, T const *)
{
T minQ = (T(1UL) << (unsigned short)(pbits-(unsigned short)2));
T maxQ = ((T(1UL) << (unsigned short)(pbits-(unsigned short)1)) - (unsigned short)1);
T q;
T p;
do {
q.Randomize(rng, minQ, maxQ);
p = (q*2) + (unsigned short)1;
RemainderTable<T> rtQ(q);
RemainderTable<T> rtP(p);
while (rtQ.HasZero() || rtP.HasZero() || !q.IsPrime() || !p.IsPrime()) {
q += 2;
p += 4;
if (q > maxQ) break;
rtQ.Increment(2);
rtP.Increment(4);
}
} while (q > maxQ);
return(p);
}
#define UNITSIZE 32
#define MAX_BIT_PRECISION 2048
#define MAX_UNIT_PRECISION (MAX_BIT_PRECISION/UNITSIZE)
typedef Int<MAX_UNIT_PRECISION> bignum;
typedef Int<MAX_UNIT_PRECISION> BigInt;
#endif

View File

@@ -0,0 +1,57 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/lcw.h $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 10/04/99 10:25a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef LCW_H
#define LCW_H
#ifdef _UNIX
#include "osdep.h"
#endif
int LCW_Uncomp(void const * source, void * dest, unsigned long length=0);
#ifdef _MSC_VER
int LCW_Comp(void const * source, void * dest, int length);
#else
extern "C" {
int __cdecl LCW_Comp(void const * source, void * dest, int length);
}
#endif
#endif

View File

@@ -0,0 +1,325 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/listnode.h $*
* *
* $Author:: David_m $*
* *
* $Modtime:: 4/05/00 12:34p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef LISTNODE_H
#define LISTNODE_H
/*
** Includes
*/
#include "assert.h"
#ifdef __BORLANDC__
#pragma warn -inl
#endif
/*
** This is a doubly linked list node. Typical use of this node is to derive
** objects from this node. The interface class for this node can be used for
** added convenience.
*/
class GenericList;
class GenericNode {
public:
GenericNode(void) : NextNode(0), PrevNode(0) {}
virtual ~GenericNode(void) {Unlink();}
GenericNode(GenericNode & node) {node.Link(this);}
GenericNode & operator = (GenericNode & node) {
if (&node != this) {
node.Link(this);
}
return(*this);
}
void Unlink(void) {
// note that this means that the special generic node at the head
// and tail of the list can not be unlinked. This is done because
// the user should never unlink them -- it will destroy the list in
// an evil way.
if (Is_Valid()) {
PrevNode->NextNode = NextNode;
NextNode->PrevNode = PrevNode;
PrevNode = 0;
NextNode = 0;
}
}
GenericList * Main_List(void) const {
GenericNode const * node = this;
while (node->PrevNode) {
node = PrevNode;
}
return((GenericList *)this);
}
void Link(GenericNode * node) {
assert(node != (GenericNode *)0);
node->Unlink();
node->NextNode = NextNode;
node->PrevNode = this;
if (NextNode) NextNode->PrevNode = node;
NextNode = node;
}
GenericNode * Next(void) const {return(NextNode);}
GenericNode * Next_Valid(void) const {
return ((NextNode && NextNode->NextNode) ? NextNode : (GenericNode *)0);
}
GenericNode * Prev(void) const {return(PrevNode);}
GenericNode * Prev_Valid(void) const {
return ((PrevNode && PrevNode->PrevNode) ? PrevNode : (GenericNode *)0);
}
bool Is_Valid(void) const {return(this != (GenericNode *)0 && NextNode != (GenericNode *)0 && PrevNode != (GenericNode *)0);}
protected:
GenericNode * NextNode;
GenericNode * PrevNode;
};
/*
** This is a generic list handler. It manages N generic nodes. Use the interface class
** to the generic list for added convenience.
*/
class GenericList {
public:
GenericList(void) {
FirstNode.Link(&LastNode);
}
virtual ~GenericList(void) {
while (FirstNode.Next()->Is_Valid()) {
FirstNode.Next()->Unlink();
}
}
GenericNode * First(void) const {return(FirstNode.Next());}
GenericNode * First_Valid(void) const
{
GenericNode *node = FirstNode.Next();
return (node->Next() ? node : (GenericNode *)0);
}
GenericNode * Last(void) const {return(LastNode.Prev());}
GenericNode * Last_Valid(void) const
{
GenericNode *node = LastNode.Prev();
return (node->Prev() ? node : (GenericNode *)0);
}
bool Is_Empty(void) const {return(!FirstNode.Next()->Is_Valid());}
void Add_Head(GenericNode * node) {FirstNode.Link(node);}
void Add_Tail(GenericNode * node) {LastNode.Prev()->Link(node);}
// void Delete(void) {while (FirstNode.Next()->Is_Valid()) delete FirstNode.Next();}
int Get_Valid_Count(void) const
{
GenericNode * node = First_Valid();
int counter = 0;
while(node) {
counter++;
node = node->Next_Valid();
}
return counter;
}
protected:
GenericNode FirstNode;
GenericNode LastNode;
private:
GenericList(GenericList & list);
GenericList & operator = (GenericList const &);
};
/*
** This node class serves only as an "interface class" for the normal node
** object. In order to use this interface class you absolutely must be sure
** that the node is the root base object of the "class T". If it is true that the
** address of the node is the same as the address of the "class T", then this
** interface class will work. You can usually ensure this by deriving the
** class T object from this node.
*/
template<class T> class List;
template<class T>
class Node : public GenericNode {
public:
List<T> * Main_List(void) const {return((List<T> *)GenericNode::Main_List());}
T Next(void) const {return((T)GenericNode::Next());}
T Next_Valid(void) const {return((T)GenericNode::Next_Valid());}
T Prev(void) const {return((T)GenericNode::Prev());}
T Prev_Valid(void) const {return((T)GenericNode::Prev_Valid());}
bool Is_Valid(void) const {return(GenericNode::Is_Valid());}
};
/*
** This is an "interface class" for a list of nodes. The rules for the class T object
** are the same as the requirements required of the node class.
*/
template<class T>
class List : public GenericList {
public:
List(void) {};
T First(void) const {return((T)GenericList::First());}
T First_Valid(void) const {return((T)GenericList::First_Valid());}
T Last(void) const {return((T)GenericList::Last());}
T Last_Valid(void) const {return((T)GenericList::Last_Valid());}
void Delete(void) {while (First()->Is_Valid()) delete First();}
private:
List(List<T> const & rvalue);
List<T> operator = (List<T> const & rvalue);
};
/*
The DataNode template class allows you to have a node with a peice of data associated with it.
Commonly used to maintain a list of objects which are not derived from GenericNode.
- EHC
*/
template<class T>
class DataNode : public GenericNode {
T Value;
public:
DataNode() {};
DataNode(T value) { Set(value); };
void Set(T value) { Value = value; };
T Get() const { return Value; };
DataNode<T> * Next(void) const { return (DataNode<T> *)GenericNode::Next(); }
DataNode<T> * Next_Valid(void) const { return (DataNode<T> *)GenericNode::Next_Valid(); }
DataNode<T> * Prev(void) const { return (DataNode<T> *)GenericNode::Prev(); }
DataNode<T> * Prev_Valid(void) const { return (DataNode<T> *)GenericNode::Prev_Valid(); }
};
/*
The ContextDataNode template class is an extension of the DataNode class and has an additional
data value associated with it. Commonly used for tracking the owner of a DataNode.
- EHC
*/
template<class C, class D>
class ContextDataNode : public DataNode<D> {
C Context;
public:
ContextDataNode() {};
ContextDataNode(C context, D data) { Set_Context(context); Set(data); }
void Set_Context(C context) { Context = context; };
C Get_Context() { return Context; };
};
/*
** A SafeContextDataNode requires the user to supply context and
** Data values to the constructor. This eliminates the problem of
** uninitialized ContextDataNodes. -DRM
*/
template<class C, class D>
class SafeContextDataNode : public ContextDataNode<C,D>
{
public:
SafeContextDataNode(C context, D data) : ContextDataNode<C,D>(context, data) { }
private:
// if the compiler complains that it can't access this constructor,
// you are trying to construct a SafeContextDataNode without providing
// context and data values. Perhaps you've included a SafeContextDataNode
// as a member variable, but forgotten to add it to the initializer list
// in your class constructor.
// DO NOT change the void constructor to public. That would defeat
// the purpose of the SafeContextDataNode. -DRM
SafeContextDataNode();
};
/*
The DoubleNode class has double everything a DataNode has!
Each DataNode's data member points to the DoubleNode object
that owns it. This type of object can therefore be in two distinct
lists, and when it is destroyed it is removed from both of them
automatically.
usage example:
typedef a symbol for the usage of the DoubleNode class as such:
typedef DoubleNode<int, bool> DOUBLENODE;
declare the head of the list as a DataNode with type DOUBLENODE
List<DOUBLENODE *> PrimaryList; // member of object1
List<DOUBLENODE *> SecondaryList; // member of object2
Iterate through the list starting at PrimaryList or SecondaryList.
These two lists are intended to be located in different
objects, such as an Active list and an Association list as used in G
Planet mode.
*/
template<class PRIMARY, class SECONDARY>
class DoubleNode {
void Initialize() { Primary.Set(this); Secondary.Set(this); };
PRIMARY PrimaryValue;
SECONDARY SecondaryValue;
public:
typedef DoubleNode<PRIMARY, SECONDARY> Type;
DataNode<Type *> Primary;
DataNode<Type *> Secondary;
DoubleNode() { Initialize(); };
DoubleNode(PRIMARY primary, SECONDARY secondary) { Initialize(); Set_Primary(primary); Set_Secondary(secondary); };
void Set_Primary(PRIMARY value) { PrimaryValue = value; };
void Set_Secondary(SECONDARY value) { SecondaryValue = value; };
PRIMARY Get_Primary() { return PrimaryValue; };
SECONDARY Get_Secondary() { return SecondaryValue; };
void Unlink() { Primary.Unlink(); Secondary.Unlink(); };
};
#endif

View File

@@ -0,0 +1,120 @@
/*
** Command & Conquer Generals(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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/wwlib/LaunchWeb.cpp $
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 2 $
* $Modtime: 6/22/01 4:39p $
*
******************************************************************************/
#include "LaunchWeb.h"
#include <windows.h>
#include <shellapi.h>
#include <stdio.h>
#include <assert.h>
/******************************************************************************
*
* NAME
* LaunchWebBrowser
*
* DESCRIPTION
* Launch the default browser to view the specified URL
*
* INPUTS
* URL - Website address
* Wait - Wait for user to close browser (default = false)
* Callback - User callback to invoke during wait (default = NULL callback)
*
* RESULT
* Success - True if successful; otherwise false
*
******************************************************************************/
bool LaunchWebBrowser(const char* url)
{
// Just return if no URL specified
if (!url || (strlen(url) == 0))
{
return false;
}
// Create a temporary file with HTML content
char tempPath[MAX_PATH];
GetWindowsDirectory(tempPath, MAX_PATH);
char filename[MAX_PATH];
GetTempFileName(tempPath, "WWS", 0, filename);
char* extPtr = strrchr(filename, '.');
strcpy(extPtr, ".html");
HANDLE file = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
assert(INVALID_HANDLE_VALUE != file && "Failed to create temporary HTML file.");
if (INVALID_HANDLE_VALUE == file)
{
return false;
}
// Write generic contents
const char* contents = "<title>ViewHTML</title>";
DWORD written;
WriteFile(file, contents, strlen(contents), &written, NULL);
CloseHandle(file);
// Find the executable that can launch this file
char exeName[MAX_PATH];
HINSTANCE hInst = FindExecutable(filename, NULL, exeName);
assert(((int)hInst > 32) && "Unable to find executable that will display HTML files.");
// Delete temporary file
DeleteFile(filename);
if ((int)hInst <= 32)
{
return false;
}
// Launch browser with specified URL
char commandLine[MAX_PATH];
sprintf(commandLine, "[open] %s", url);
STARTUPINFO startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
PROCESS_INFORMATION processInfo;
BOOL createSuccess = CreateProcess(exeName, commandLine, NULL, NULL, FALSE,
0, NULL, NULL, &startupInfo, &processInfo);
assert(createSuccess && "Failed to launch default WebBrowser.");
return (TRUE == createSuccess);
}

View File

@@ -0,0 +1,48 @@
/*
** Command & Conquer Generals(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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/wwlib/LaunchWeb.h $
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 1 $
* $Modtime: 4/20/01 3:22p $
*
******************************************************************************/
#ifndef __LAUNCHWEB_H__
#define __LAUNCHWEB_H__
#ifdef __cplusplus
extern "C" {
#endif
bool LaunchWebBrowser(const char* url);
#ifdef __cplusplus
}
#endif
#endif // __LAUNCHWEB_H__

View File

@@ -0,0 +1,103 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/mono.h $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 5/04/01 7:36p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef MONO_H
#define MONO_H
#include "win.h"
class MonoClass {
public:
typedef enum MonoAttribute {
INVISIBLE=0x00, // Black on black.
UNDERLINE=0x01, // Underline.
BLINKING=0x90, // Blinking white on black.
NORMAL=0x02, // White on black.
INVERSE=0x70 // Black on white.
} MonoAttribute;
MonoClass(void);
~MonoClass(void);
static void Enable(void) {Enabled = true;};
static void Disable(void) {Enabled = false;};
static bool Is_Enabled(void) {return Enabled;};
void Sub_Window(int x=0, int y=0, int w=80, int h=25);
void Fill_Attrib(int x, int y, int w, int h, MonoAttribute attrib);
void Clear(void);
void Set_Cursor(int x, int y);
void Print(char const *text);
void Print(int text);
void Printf(char const *text, ...);
void Printf(int text, ...);
void Text_Print(char const *text, int x, int y, MonoAttribute attrib=NORMAL);
void Text_Print(int text, int x, int y, MonoAttribute attrib=NORMAL);
void View(void);
void Scroll(int lines=1);
void Pan(int cols=1);
void Set_Default_Attribute(MonoAttribute attrib);
/*
** This merely makes a duplicate of the mono object into a newly created mono
** object.
*/
MonoClass (MonoClass const &);
static MonoClass * Current;
private:
/*
** Handle of the mono page.
*/
HANDLE Handle;
/*
** If this is true, then monochrome output is allowed. It defaults to false
** so that monochrome output must be explicitly enabled.
*/
static bool Enabled;
MonoClass & operator = (MonoClass const & );
};
#endif

View File

@@ -0,0 +1,131 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/monodrvr.h $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 10/04/99 10:25a $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifdef _MSC_VER
#pragma warning (push,3)
#endif
#ifdef _WINDOWS
#include <winioctl.h>
#endif
#ifdef _MSC_VER
#pragma warning (pop)
#endif
/*
** This is the identifier for the Monochrome Display Driver.
*/
#define FILE_DEVICE_MONO 0x00008000
/*
** These are the IOCTL commands supported by the Monochrome Display Driver.
*/
#define IOCTL_MONO_HELP_SCREEN CTL_CODE(FILE_DEVICE_MONO, 0x800, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_CLEAR_SCREEN CTL_CODE(FILE_DEVICE_MONO, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_PRINT_RAW CTL_CODE(FILE_DEVICE_MONO, 0x802, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_SET_CURSOR CTL_CODE(FILE_DEVICE_MONO, 0x803, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_SCROLL CTL_CODE(FILE_DEVICE_MONO, 0x804, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_BRING_TO_TOP CTL_CODE(FILE_DEVICE_MONO, 0x805, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_SET_ATTRIBUTE CTL_CODE(FILE_DEVICE_MONO, 0x806, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_PAN CTL_CODE(FILE_DEVICE_MONO, 0x807, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_LOCK CTL_CODE(FILE_DEVICE_MONO, 0x808, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_UNLOCK CTL_CODE(FILE_DEVICE_MONO, 0x809, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_SET_WINDOW CTL_CODE(FILE_DEVICE_MONO, 0x80A, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_RESET_WINDOW CTL_CODE(FILE_DEVICE_MONO, 0x80B, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_SET_FLAG CTL_CODE(FILE_DEVICE_MONO, 0x80C, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_CLEAR_FLAG CTL_CODE(FILE_DEVICE_MONO, 0x80D, METHOD_BUFFERED, FILE_WRITE_DATA)
#define IOCTL_MONO_FILL_ATTRIB CTL_CODE(FILE_DEVICE_MONO, 0x80E, METHOD_BUFFERED, FILE_WRITE_DATA)
/*
** These specify the various behavior flags available for the mono display driver. They
** default to being OFF (or FALSE).
*/
typedef enum MonoFlagType
{
MONOFLAG_WRAP, // Text will wrap to the next line when right margin is reached.
MONOFLAG_COUNT // Used to indicate the number of mono flags available.
} MonoFlagType;
/*
Here is a "C" example of how to use the Monochrome Display Driver.
int main(int argc, char *argv[])
{
HANDLE handle;
handle = CreateFile("\\\\.\\MONO", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle != INVALID_HANDLE_VALUE) {
long retval; // Return code from IoControl functions.
unsigned short * pointer; // Working pointer to mono RAM.
union {
int X,Y;
} cursor; // Cursor positioning parameter info.
// Prints a line of text to the screen [length of string is 13].
WriteFile(handle, "Test Message\n", 13, &retval, NULL);
// Fetches a pointer to the mono memory.
DeviceIoControl(handle, (DWORD)IOCTL_MONO_LOCK, NULL, 0, &pointer, sizeof(pointer), &retval, 0);
if (pointer != NULL) {
*pointer = 0x0721; // '!' character appears in upper left corner (attribute 0x07).
}
DeviceIoControl(handle, (DWORD)IOCTL_MONO_UNLOCK, NULL, 0, NULL, 0, &retval, 0);
// Set cursor to column 5, row 10.
cursor.X = 5;
cursor.Y = 10;
DeviceIoControl(handle, (DWORD)IOCTL_MONO_SET_CURSOR, &cursor, sizeof(cursor), NULL, 0, &retval, 0);
// Clear the screen.
DeviceIoControl(handle, (DWORD)IOCTL_MONO_CLEAR_SCREEN, NULL, 0, NULL, 0, &retval, 0);
CloseHandle(handle);
}
return 0;
}
*/

View File

@@ -0,0 +1,165 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /VSS_Sync/wwlib/mpmath.h $*
* *
* $Author:: Vss_sync $*
* *
* $Modtime:: 3/21/01 12:01p $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef MPMATH_H
#define MPMATH_H
#include "bool.h"
//lint -e740 -e534 -e537 -e760
//lint -d_LINT=1
#include "straw.h"
#include <stdlib.h>
#define UNITSIZE 32
#define MAX_BIT_PRECISION 2048
#define MAX_UNIT_PRECISION (MAX_BIT_PRECISION/UNITSIZE)
#define signeddigit signed long
#define LOG_UNITSIZE 5
//#define digit unsigned long
typedef unsigned long digit;
#define MPEXPORT
#ifdef _MSC_VER
#pragma warning( disable : 4236)
#endif
extern "C" {
extern int MPEXPORT XMP_Fetch_Prime_Size(void);
unsigned short const * MPEXPORT XMP_Fetch_Prime_Table(void);
int MPEXPORT XMP_Significance(const digit * r, int precision);
void MPEXPORT XMP_Inc(digit * r, int precision);
void MPEXPORT XMP_Dec(digit * r, int precision);
void MPEXPORT XMP_Neg(digit * r, int precision);
void MPEXPORT XMP_Abs(digit * r, int precision);
void MPEXPORT XMP_Shift_Right_Bits(digit * r1, int bits, int precision);
void MPEXPORT XMP_Shift_Left_Bits(digit * r1, int bits, int precision);
bool MPEXPORT XMP_Rotate_Left(digit * r1, bool carry, int precision);
void MPEXPORT XMP_Not(digit * digit_ptr, int precision);
int MPEXPORT XMP_Prepare_Modulus(const digit * n_modulus, int precision);
void MPEXPORT XMP_Init(digit * r, digit value, int precision);
unsigned MPEXPORT XMP_Count_Bits(const digit * r, int precision);
int MPEXPORT XMP_Count_Bytes(const digit * r, int precision);
void MPEXPORT XMP_Move(digit * dest, digit const * source, int precision);
int MPEXPORT XMP_Digits_To_Bits(int digits);
int MPEXPORT XMP_Compare(const digit * r1, const digit * r2, int precision);
int MPEXPORT XMP_Bits_To_Digits(int bits);
bool MPEXPORT XMP_Add(digit * result, const digit * r1, const digit * r2, bool carry, int precision);
bool MPEXPORT XMP_Add_Int(digit * result, const digit * r1, digit r2, bool carry, int precision);
bool MPEXPORT XMP_Test_Bit(const digit * r, unsigned bit);
void MPEXPORT XMP_Set_Bit(digit * r, unsigned bit);
digit MPEXPORT XMP_Bits_To_Mask(int bits);
bool MPEXPORT XMP_Is_Negative(const digit * r, int precision);
bool MPEXPORT XMP_Test_Eq_Int(digit const * r, int i, int p);
bool MPEXPORT XMP_Sub(digit * result, const digit * r1, const digit * r2, bool borrow, int precision);
bool MPEXPORT XMP_Sub_Int(digit * result, const digit * r1, unsigned short r2, bool borrow, int precision);
int MPEXPORT XMP_Unsigned_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);
int MPEXPORT XMP_Unsigned_Mult_Int(digit * prod, const digit * multiplicand, short multiplier, int precision);
int MPEXPORT XMP_Signed_Mult_Int(digit * prod, const digit * multiplicand, signed short multiplier, int precision);
int MPEXPORT XMP_Signed_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);
unsigned short MPEXPORT XMP_Unsigned_Div_Int(digit * quotient, digit const * dividend, unsigned short divisor, int precision);
int MPEXPORT XMP_Unsigned_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision);
void MPEXPORT XMP_Signed_Div(digit * remainder, digit * quotient, digit const * dividend, digit const * divisor, int precision);
int MPEXPORT XMP_Reciprocal(digit * quotient, const digit * divisor, int precision);
void MPEXPORT XMP_Decode_ASCII(char const * str, digit * mpn, int precision);
//void MPEXPORT xmp_single_mul(unsigned short * prod, unsigned short * multiplicand, unsigned short multiplier, int precision);
void MPEXPORT XMP_Double_Mul(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);
//int MPEXPORT xmp_stage_modulus(const digit * n_modulus, int precision);
int MPEXPORT XMP_Mod_Mult(digit * prod, const digit * multiplicand, const digit * multiplier, int precision);
void MPEXPORT XMP_Mod_Mult_Clear(int precision);
int MPEXPORT XMP_Exponent_Mod(digit * expout, const digit * expin, const digit * exponent_ptr, const digit * modulus, int precision);
bool MPEXPORT XMP_Is_Small_Prime(const digit * candidate, int precision);
bool MPEXPORT XMP_Small_Divisors_Test(const digit * candidate, int precision);
bool MPEXPORT XMP_Fermat_Test(const digit * candidate_prime, unsigned rounds, int precision);
void MPEXPORT XMP_Inverse_A_Mod_B(digit * result, digit const * number, digit const * modulus, int precision);
void MPEXPORT XMP_Signed_Decode(digit * result, const unsigned char * from, int frombytes, int precision);
void MPEXPORT XMP_Unsigned_Decode(digit * result, const unsigned char * from, int frombytes, int precision);
unsigned MPEXPORT XMP_Encode(unsigned char * to, digit const * from, int precision);
unsigned MPEXPORT XMP_Encode_Bounded(unsigned char * to, unsigned tobytes, digit const * from, int precision);
void MPEXPORT XMP_Randomize(digit * result, Straw & rng, int nbits, int precision);
void MPEXPORT XMP_Randomize_Bounded(digit * result, Straw & rng, digit const * min, digit const * max, int precision);
bool MPEXPORT XMP_Is_Prime(digit const * prime, int precision);
bool MPEXPORT XMP_Rabin_Miller_Test(Straw & rng, digit const * w, int rounds, int precision);
int MPEXPORT XMP_DER_Length_Encode(unsigned long length, unsigned char * output);
int MPEXPORT XMP_DER_Encode(digit const * from, unsigned char * output, int precision);
void MPEXPORT XMP_DER_Decode(digit * result, unsigned char const * input, int precision);
}
inline int MPEXPORT XMP_Digits_To_Bits(int digits)
{
return(digits << LOG_UNITSIZE);
}
inline int MPEXPORT XMP_Bits_To_Digits(int bits)
{
return ((bits + (UNITSIZE-1)) / UNITSIZE);
}
inline digit MPEXPORT XMP_Bits_To_Mask(int bits)
{
if (!bits) return(0);
return(1 << ((bits-1) % UNITSIZE));
}
inline bool MPEXPORT XMP_Is_Negative(const digit * r, int precision)
{
return((signeddigit) *(r + (precision-1)) < 0);
}
inline void MPEXPORT XMP_Set_Bit(digit * r, unsigned bit)
{
r[bit >> LOG_UNITSIZE] |= ((digit)1 << (bit & (UNITSIZE-1)));
}
inline bool MPEXPORT XMP_Test_Bit(const digit * r, unsigned bit)
{
return ((r[bit >> LOG_UNITSIZE] & ((digit)1 << (bit & (UNITSIZE-1)))) != 0);
}
#endif

View File

@@ -0,0 +1,46 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/mpu.h $*
* *
* $Author:: Denzil_l $*
* *
* $Modtime:: 8/17/01 6:11p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#pragma once
#ifndef MPU_H
#define MPU_H
unsigned long Get_CPU_Clock(unsigned long & high);
unsigned long Get_CPU_Rate(unsigned long & high);
int Get_RDTSC_CPU_Speed(void);
#endif

View File

@@ -0,0 +1,250 @@
/*
** Command & Conquer Generals(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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/wwlib/Notify.h $
*
* DESCRIPTION
* These templates provide implementation of the Subject-Observer pattern.
*
* PROGRAMMER
* Steve Clinard
* $Author: Denzil_l $
*
* VERSION INFO
* $Modtime: 8/04/01 12:13p $
* $Revision: 4 $
*
******************************************************************************/
#ifndef __NOTIFY_H__
#define __NOTIFY_H__
// Reduce warning level for STL
#if defined(_MSC_VER)
#pragma warning(push, 3)
#endif
#include <vector>
#include <algorithm>
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#include <assert.h>
template<typename Event> class Notifier;
template<typename Event> class Observer;
template<typename Event> class Observer
{
public:
typedef std::vector< Notifier<Event>* > NotifierColl;
Observer() :
mNotifiers(NULL)
{}
virtual ~Observer()
{StopObserving();}
//! Handle event notification
virtual void HandleNotification(Event&) = 0;
//! Notifier has ended notification of this event
virtual void NotificationEnded(const Notifier<Event>& notifier)
{
NotifierColl::iterator pos = std::find(mNotifiers.begin(),
mNotifiers.end(), &notifier);
if (pos != mNotifiers.end())
{
mNotifiers.erase(pos);
}
}
//! Request notification of this event
virtual void NotifyMe(Notifier<Event>& notifier)
{notifier.AddObserver(*this);}
//! Stop observing event
void StopObserving()
{
while (mNotifiers.size() > 0)
{
Notifier<Event>* notifier = mNotifiers.back();
assert(notifier && "ERROR: NULL pointer in collection.");
notifier->RemoveObserver(*this);
}
}
protected:
Observer(const Observer<Event>& observer);
const Observer<Event>& operator=(const Observer<Event>&);
private:
friend class Notifier<Event>;
NotifierColl mNotifiers;
};
#define DECLARE_OBSERVER(Event) \
virtual void NotifyMe(Notifier<Event>& observer) \
{Notifier<Event>::AddObserver(observer);}
template<typename Event> class Notifier
{
public:
typedef std::vector< Observer<Event>* > ObserverColl;
Notifier()
{}
virtual ~Notifier()
{
for (int index = mObservers.size(); index--;)
{
mObservers[index]->NotificationEnded(*this);
}
}
//! Send event notification to all observers of this event.
virtual void NotifyObservers(Event& event)
{
for (unsigned int index = 0; index < mObservers.size(); index++)
{
mObservers[index]->HandleNotification(event);
}
}
//! Add an observer of this event
virtual void AddObserver(Observer<Event>& observer)
{
ObserverColl::iterator pos = std::find(mObservers.begin(),
mObservers.end(), &observer);
if (pos == mObservers.end())
{
observer.mNotifiers.push_back(this);
mObservers.push_back(&observer);
}
}
//! Remove an observer of this event
virtual void RemoveObserver(Observer<Event>& observer)
{
ObserverColl::iterator pos = std::find(mObservers.begin(),
mObservers.end(), &observer);
if (pos != mObservers.end())
{
observer.NotificationEnded(*this);
mObservers.erase(pos);
}
}
virtual bool HasObservers(void) const
{return (mObservers.size() > 0);}
private:
//! Observer collection
ObserverColl mObservers;
};
#define DECLARE_NOTIFIER(Event) \
virtual void NotifyObservers(Event& event) \
{Notifier<Event>::NotifyObservers(event);} \
virtual void AddObserver(Observer<Event>& observer) \
{Notifier<Event>::AddObserver(observer);} \
virtual void RemoveObserver(Observer<Event>& observer) \
{Notifier<Event>::RemoveObserver(observer);}
/* The following template is useful for defining unique types to use as Events
* from types such as strings or integers.
*
* The first type must be a class or other unique type. This need not be a
* "real" class. It could be a forward declared class, which is enough to
* make the template class unique.
*
* The second type is the event data. UString and int are obvious choices.
*
* Typedef'ing the template class is a good thing to do.
*/
template<typename Type, typename Value>
class TypedEvent
{
public:
TypedEvent(Value& value) :
mValue(value)
{}
inline Value& operator()()
{return mValue;}
inline Value& Subject(void)
{return mValue;}
private:
Value& mValue;
};
template<typename T, typename Object>
class TypedEventPtr
{
public:
TypedEventPtr(Object* subject) :
mSubject(subject)
{}
inline Object* Subject(void)
{return mSubject;}
inline Object* operator()()
{return mSubject;}
private:
Object* mSubject;
};
template<typename A, typename B>
class TypedEventPair
{
public:
TypedEventPair(A itemA, B itemB) :
mItemA(itemA),
mItemB(itemB)
{}
inline A GetItemA(void)
{return mItemA;}
inline B GetItemB(void)
{return mItemB;}
protected:
A mItemA;
B mItemB;
};
#endif // __NOTIFY_H__

View File

@@ -0,0 +1,81 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/PALETTE.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:00p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef PALETTE_H
#define PALETTE_H
#include "rgb.h"
/*
** The palette class is used to manipulate a palette as a whole. All 256 colors are
** represented by the palette class object.
*/
class PaletteClass
{
public:
enum {
COLOR_COUNT=256 // Number of color indices on the palette.
};
PaletteClass(void) {};
PaletteClass(RGBClass const & rgb);
PaletteClass(unsigned char *binary_palette);
RGBClass & operator[] (int index) {return(Palette[index % COLOR_COUNT]);};
RGBClass const & operator[] (int index) const {return(Palette[index % COLOR_COUNT]);};
RGBClass & Get_Color(int index) {return(Palette[index % COLOR_COUNT]);};
RGBClass const & Get_Color(int index) const {return(Palette[index % COLOR_COUNT]);};
int operator == (PaletteClass const & palette) const;
int operator != (PaletteClass const & palette) const {return(!(operator ==(palette)));};
PaletteClass & operator = (PaletteClass const & palette);
operator const unsigned char * (void) const {return((const unsigned char *)&Palette[0]);};
operator unsigned char * (void) {return((unsigned char *)&Palette[0]);};
void Adjust(int ratio);
void Adjust(int ratio, PaletteClass const & palette);
void Partial_Adjust(int ratio, char *lut);
void Partial_Adjust(int ratio, PaletteClass const & palette, char *lut);
int Closest_Color(RGBClass const & rgb) const;
protected:
RGBClass Palette[COLOR_COUNT];
};
#endif

View File

@@ -0,0 +1,77 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/PIPE.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:00p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef PIPE_H
#define PIPE_H
/*
** A "push through" pipe interface abstract class used for such purposes as compression
** and translation of data. In STL terms, this is functionally similar to an output
** iterator but with a few enhancements. A pipe class object that is not derived into
** another useful class serves only as a pseudo null-pipe. It will accept data but
** just throw it away but pretend that it sent it somewhere.
*/
class Pipe
{
public:
Pipe(void) : ChainTo(0), ChainFrom(0) {}
virtual ~Pipe(void);
virtual int Flush(void);
virtual int End(void) {return(Flush());}
virtual void Put_To(Pipe * pipe);
void Put_To(Pipe & pipe) {Put_To(&pipe);}
virtual int Put(void const * source, int slen);
/*
** Pointer to the next pipe segment in the chain.
*/
Pipe * ChainTo;
Pipe * ChainFrom;
private:
/*
** Disable the copy constructor and assignment operator.
*/
Pipe(Pipe & rvalue);
Pipe & operator = (Pipe const & pipe);
};
#endif

View File

@@ -0,0 +1,99 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/PK.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:00p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef PK_H
#define PK_H
#ifndef STRAW_H
#include "straw.h"
#endif
#include "int.h"
/*
** This class holds a public or private key used in Public Key Cryptography. It also serves
** as the conduit for encrypting/decrypting data using that key. Cryptography, using this
** method, has a couple of characteristics that affect how it is used. One, the process of
** encrypting/decrypting is very slow. This limits the effective quantity of data that can
** be processed. Two, the ciphertext is larger than the plaintext. This property generally
** limits its use to streaming data as opposed to random access data. The data is processed
** in blocks. The size of the ciphertext and plaintext blocks can be determined only from
** the key itself.
**
** A reasonable use of this technology would be to encrypt only critical data such as the
** password for a fast general purpose cryptographic algorithm.
*/
class PKey
{
public:
PKey(void) : Modulus(0), Exponent(0), BitPrecision(0) {}
PKey(void const * exponent, void const * modulus); // DER initialization.
int Encrypt(void const * source, int slen, void * dest) const;
int Decrypt(void const * source, int slen, void * dest) const;
static void Generate(Straw & random, int bits, PKey & fastkey, PKey & slowkey);
int Plain_Block_Size(void) const {return((BitPrecision-1)/8);}
int Crypt_Block_Size(void) const {return(Plain_Block_Size()+1);}
int Block_Count(int plaintext_length) const {return((((plaintext_length-1)/Plain_Block_Size())+1));}
int Encode_Modulus(void * buffer) const;
int Encode_Exponent(void * buffer) const;
void Decode_Modulus(void * buffer);
void Decode_Exponent(void * buffer);
static long Fast_Exponent(void) {return(65537L);}
// private:
// p*q
BigInt Modulus;
// 65537 or
// inverse of (p-1)(q-1).
BigInt Exponent;
// Maximum bits allowed for block.
int BitPrecision;
};
#endif

View File

@@ -0,0 +1,202 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/Point.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/07/99 5:24p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef POINT_H
#define POINT_H
template<class T> class TRect;
/*
** This class describes a point in 2 dimensional space using arbitrary
** components. The interpretation of which is outside the scope
** of this class. This class is the successor to the old style COORDINATE
** and CELL types but also serves anywhere an X and Y value are treated
** as a logical object (e.g., pixel location).
*/
template<class T>
class TPoint2D {
public:
TPoint2D(void) {} // Default constructor does nothing by design.
TPoint2D(T x, T y) : X(x), Y(y) {}
// Equality comparison operators.
bool operator == (TPoint2D<T> const & rvalue) const {return(X==rvalue.X && Y==rvalue.Y);}
bool operator != (TPoint2D<T> const & rvalue) const {return(X!=rvalue.X || Y!=rvalue.Y);}
// Addition and subtraction operators.
TPoint2D<T> const & operator += (TPoint2D<T> const & rvalue) {X += rvalue.X;Y += rvalue.Y;return(*this);}
TPoint2D<T> const & operator -= (TPoint2D<T> const & rvalue) {X -= rvalue.X;Y -= rvalue.Y;return(*this);}
TPoint2D<T> const operator - (TPoint2D<T> const & rvalue) const {return(TPoint2D<T>(X - rvalue.X, Y - rvalue.Y));}
TPoint2D<T> const operator + (TPoint2D<T> const & rvalue) const {return(TPoint2D<T>(X + rvalue.X, Y + rvalue.Y));}
// Scalar multiplication and division.
TPoint2D<T> const operator * (T rvalue) const {return(TPoint2D<T>(X * rvalue, Y * rvalue));}
TPoint2D<T> const & operator *= (T rvalue) {X *= rvalue; Y *= rvalue;return(*this);}
TPoint2D<T> const operator / (T rvalue) const {if (rvalue == T(0)) return(TPoint2D<T>(0,0));return(TPoint2D<T>(X / rvalue, Y / rvalue));}
TPoint2D<T> const & operator /= (T rvalue) {if (rvalue != T(0)) {X /= rvalue;Y /= rvalue;}return(*this);}
// Dot and cross product.
TPoint2D<T> const operator * (TPoint2D<T> const & rvalue) const {return(TPoint2D<T>(X * rvalue.X, Y * rvalue.Y));}
TPoint2D<T> const Dot_Product(TPoint2D<T> const & rvalue) const {return(TPoint2D<T>(X * rvalue.X, Y * rvalue.Y));}
TPoint2D<T> const Cross_Product(TPoint2D<T> const & rvalue) const {return(TPoint2D<T>(Y - rvalue.Y, rvalue.X - X));}
// Negation operator -- simple and effective
TPoint2D<T> const operator - (void) const {return(TPoint2D<T>(-X, -Y));}
// Vector support functions.
T Length(void) const {return(T(sqrt(X*X + Y*Y)));}
TPoint2D<T> const Normalize(void) const {
double len = sqrt(X*X + Y*Y);
if (len != 0.0) {
return(TPoint2D<T>((T)((double)X / len), (T)((double)Y / len)));
} else {
return(*this);
}
}
// Bias a point into a clipping rectangle.
TPoint2D<T> const Bias_To(TRect<T> const & rect) const;
// Find distance between points.
T Distance_To(TPoint2D<T> const & point) const {return((*this - point).Length());}
public:
T X;
T Y;
};
template<class T>
TPoint2D<T> const operator * (T lvalue, TPoint2D<T> const & rvalue)
{
return(rvalue * lvalue);
}
/*
** This typedef provides an uncluttered type name for use by simple integer points.
*/
typedef TPoint2D<int> Point2D;
/*
** This describes a point in 3 dimensional space using arbitrary
** components. This is the successor to the COORDINATE type for those
** times when height needs to be tracked.
**
** Notice that it is not implemented as a virtually derived class. This
** is for efficiency reasons. This class chooses to be smaller and faster at the
** expense of polymorphism. However, since it is publicly derived, inheritance is
** the next best thing.
*/
template<class T>
class TPoint3D : public TPoint2D<T> {
typedef TPoint2D<T> BASECLASS;
public:
TPoint3D(void) {} // Default constructor does nothing by design.
TPoint3D(T x, T y, T z) : TPoint2D<T>(x, y), Z(z) {}
TPoint3D(BASECLASS const & rvalue) : TPoint2D<T>(rvalue), Z(0) {}
// Equality comparison operators.
bool operator == (TPoint3D<T> const & rvalue) const {return(X==rvalue.X && Y==rvalue.Y && Z==rvalue.Z);}
bool operator != (TPoint3D<T> const & rvalue) const {return(X!=rvalue.X || Y!=rvalue.Y || Z!=rvalue.Z);}
// Addition and subtraction operators.
TPoint3D<T> const & operator += (TPoint3D<T> const & rvalue) {X += rvalue.X;Y += rvalue.Y;Z += rvalue.Z;return(*this);}
TPoint2D<T> const & operator += (TPoint2D<T> const & rvalue) {BASECLASS::operator += (rvalue);return(*this);}
TPoint3D<T> const & operator -= (TPoint3D<T> const & rvalue) {X -= rvalue.X;Y -= rvalue.Y;Z -= rvalue.Z;return(*this);}
TPoint2D<T> const & operator -= (TPoint2D<T> const & rvalue) {BASECLASS::operator -= (rvalue);return(*this);}
TPoint3D<T> const operator - (TPoint3D<T> const & rvalue) const {return(TPoint3D<T>(X - rvalue.X, Y - rvalue.Y, Z - rvalue.Z));}
TPoint3D<T> const operator - (TPoint2D<T> const & rvalue) const {return(TPoint3D<T>(X - rvalue.X, Y - rvalue.Y, Z));}
TPoint3D<T> const operator + (TPoint3D<T> const & rvalue) const {return(TPoint3D<T>(X + rvalue.X, Y + rvalue.Y, Z + rvalue.Z));}
TPoint3D<T> const operator + (TPoint2D<T> const & rvalue) const {return(TPoint3D<T>(X + rvalue.X, Y + rvalue.Y, Z));}
// Scalar multiplication and division.
TPoint3D<T> const operator * (T rvalue) const {return(TPoint3D<T>(X * rvalue, Y * rvalue, Z * rvalue));}
TPoint3D<T> const & operator *= (T rvalue) {X *= rvalue;Y *= rvalue;Z *= rvalue;return(*this);}
TPoint3D<T> const operator / (T rvalue) const {if (rvalue == T(0)) return(TPoint3D<T>(0,0,0));return(TPoint3D<T>(X / rvalue, Y / rvalue, Z / rvalue));}
TPoint3D<T> const & operator /= (T rvalue) {if (rvalue != T(0)) {X /= rvalue;Y /= rvalue;Z /= rvalue;}return(*this);}
// Dot and cross product.
TPoint3D<T> const operator * (TPoint3D<T> const & rvalue) const {return(TPoint3D<T>(X * rvalue.X, Y * rvalue.Y, Z * rvalue.Z));}
TPoint3D<T> const Dot_Product(TPoint3D<T> const & rvalue) const {return(TPoint3D<T>(X * rvalue.X, Y * rvalue.Y, Z * rvalue.Z));}
TPoint3D<T> const Cross_Product(TPoint3D<T> const & rvalue) const {return TPoint3D<T>(Y * rvalue.Z - Z * rvalue.Y, Z * rvalue.X - X * rvalue.Z, X * rvalue.Y - Y * rvalue.X);}
// Negation operator -- simple and effective
TPoint3D<T> const operator - (void) const {return(TPoint3D<T>(-X, -Y, -Z));}
// Vector support functions.
T Length(void) const {return(T(sqrt(X*X + Y*Y + Z*Z)));}
TPoint3D<T> const Normalize(void) const {
double len = sqrt(X*X + Y*Y + Z*Z);
if (len != 0.0) {
return(TPoint3D<T>(X / len, Y / len, Z / len));
} else {
return(*this);
}
}
// Find distance between points.
T Distance_To(TPoint3D<T> const & point) const {return((*this - point).Length());}
T Distance_To(TPoint2D<T> const & point) const {return(BASECLASS::Distance_To(point));}
public:
/*
** The Z component of this point.
*/
T Z;
};
template<class T>
TPoint3D<T> const operator * (T lvalue, TPoint3D<T> const & rvalue)
{
return(rvalue * lvalue);
}
/*
** This typedef provides a simple uncluttered type name for use by
** integer 3D points.
*/
typedef TPoint3D<int> Point3D;
#endif

View File

@@ -0,0 +1,110 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/RAMFILE.H $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef RAMFILE_H
#define RAMFILE_H
#include "wwfile.h"
class RAMFileClass : public FileClass
{
public:
RAMFileClass(void * buffer, int len);
virtual ~RAMFileClass(void);
virtual char const * File_Name(void) const {return("UNKNOWN");}
virtual char const * Set_Name(char const * ) {return(File_Name());}
virtual int Create(void);
virtual int Delete(void);
virtual bool Is_Available(int forced=false);
virtual bool Is_Open(void) const;
virtual int Open(char const * filename, int access=READ);
virtual int Open(int access=READ);
virtual int Read(void * buffer, int size);
virtual int Seek(int pos, int dir=SEEK_CUR);
virtual int Size(void);
virtual int Write(void const * buffer, int size);
virtual void Close(void);
virtual unsigned long Get_Date_Time(void) {return(0);}
virtual bool Set_Date_Time(unsigned long ) {return(true);}
virtual void Error(int , int = false, char const * =NULL) {}
operator char const * () {return File_Name();}
private:
/*
** Pointer to the buffer that the "file" will reside in.
*/
char * Buffer;
/*
** The maximum size of the buffer. The file occupying the buffer
** may be smaller than this size.
*/
int MaxLength;
/*
** The number of bytes in the sub-file occupying the buffer.
*/
int Length;
/*
** The current file position offset within the buffer.
*/
int Offset;
/*
** The file was opened with this access mode.
*/
int Access;
/*
** Is the file currently open?
*/
bool IsOpen;
/*
** Was the file buffer allocated during construction of this object?
*/
bool IsAllocated;
};
#endif

View File

@@ -0,0 +1,270 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /VSS_Sync/wwlib/random.h $*
* *
* $Author:: Vss_sync $*
* *
* $Modtime:: 8/29/01 10:24p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Pick_Random_Number -- Picks a random number between two values (inclusive). *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef RANDOM_H
#define RANDOM_H
// "unreferenced inline function has been removed" Yea, so what?
#pragma warning(disable : 4514)
/*
** This class functions like a 'magic' int value that returns a random number
** every time it is read. To set the "random seed" for this, just assign a number
** to the object (just as you would if it were a true 'int' value). Take note that although
** this class will return an 'int', the actual significance of the random number is
** limited to 15 bits (0..32767).
*/
class RandomClass {
public:
RandomClass(unsigned seed=0);
operator int(void) {return(operator()());};
int operator() (void);
int operator() (int minval, int maxval);
enum {
SIGNIFICANT_BITS=15 // Random number bit significance.
};
protected:
unsigned long Seed;
/*
** Internal working constants that are used to generate the next
** random number.
*/
enum {
MULT_CONSTANT=0x41C64E6D, // K multiplier value.
ADD_CONSTANT=0x00003039, // K additive value.
THROW_AWAY_BITS=10 // Low bits to throw away.
};
};
/*
** This class functions like a 'magic' number where it returns a different value every
** time it is read. It is nearly identical in function to the RandomClass, but has the
** following improvements.
**
** 1> It generates random numbers very quickly. No multiplies are
** used in the algorithm.
**
** 2> The return value is a full 32 bits rather than 15 bits of
** the RandomClass.
**
** 3> The bit pattern won't ever repeat. (actually it will repeat
** in about 10 to the 50th power times).
*/
// WARNING!!!!
// This random number generator starts breaking down in 64 dimensions
// behaving very badly in that domain
// HY 6/14/01
class Random2Class {
public:
Random2Class(unsigned seed=0);
operator int(void) {return(operator()());};
int operator() (void);
int operator() (int minval, int maxval);
enum {
SIGNIFICANT_BITS=32 // Random number bit significance.
};
protected:
int Index1;
int Index2;
int Table[250];
};
/*
** This class functions like a 'magic' number where it returns a different value every
** time it is read. It is nearly identical in function to the RandomClass and Random2Class,
** but has the following improvements.
**
** 1> The random number returned is very strongly random. Approaching cryptographic
** quality.
**
** 2> The return value is a full 32 bits rather than 15 bits of
** the RandomClass.
**
** 3> The bit pattern won't repeat until 2^32 times.
*/
// WARNING!!!!
// This random number generator starts breaking down in 3 dimensions
// exhibiting a strange bias
// HY 6/14/01
class Random3Class {
public:
Random3Class(unsigned seed1=0, unsigned seed2=0);
operator int(void) {return(operator()());};
int operator() (void);
int operator() (int minval, int maxval);
enum {
SIGNIFICANT_BITS=32 // Random number bit significance.
};
protected:
static int Mix1[20];
static int Mix2[20];
int Seed;
int Index;
};
/*
** This class functions like a 'magic' number where it returns a different value every
** time it is read. It is based on the paper "Mersenne Twister: A 623-Dimensionally
** Equidistributed Uniform Pseudo-Random Number Generator
** by Makoto Matsumoto and Takuji Nishimura, ACM Transactions on Modeling and
** Computer Simulation, Vol 8, No 1, January 1998, Pages 3-30
** Hector Yee
**
** 1> The random number returned is very strongly random
**
** 2> The return value is a full 32 bits rather than 15 bits of
** the RandomClass.
**
** 3> The bit pattern won't repeat until 2^19937 -1 times
**
*/
// WARNING!!!!
// Do not use for cryptography. This random number generator is good for numerical
// simulation. Optimized, it's 4 times faster than rand()
// http://www.math.keio.ac.jp/~matumoto/emt.html
// HY 6/14/01
class Random4Class {
public:
Random4Class(unsigned int seed=4357);
operator int(void) {return(operator()());};
int operator() (void);
int operator() (int minval, int maxval);
float Get_Float();
enum {
SIGNIFICANT_BITS=32 // Random number bit significance.
};
protected:
unsigned int mt[624]; // state vector
int mti; // index
};
/***********************************************************************************************
* Pick_Random_Number -- Picks a random number between two values (inclusive). *
* *
* This is a utility template that works with one of the random number classes. Given a *
* random number generator, this routine will return with a value that lies between the *
* minimum and maximum values specified (subject to the bit precision limitations of the *
* random number generator itself). *
* *
* INPUT: generator -- Reference to the random number generator to use for the pick *
* process. *
* *
* minval -- The minimum legal return value (inclusive). *
* *
* maxval -- The maximum legal return value (inclusive). *
* *
* OUTPUT: Returns with a random number between the minval and maxval (inclusive). *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/23/1997 JLB : Created. *
*=============================================================================================*/
template<class T>
int Pick_Random_Number(T & generator, int minval, int maxval)
{
/*
** Test for shortcut case where the range is null and thus
** the number to return is actually implicit from the
** parameters.
*/
if (minval == maxval) return(minval);
/*
** Ensure that the min and max range values are in proper order.
*/
if (minval > maxval) {
int temp = minval;
minval = maxval;
maxval = temp;
}
/*
** Find the highest bit that fits within the magnitude of the
** range of random numbers desired. Notice that the scan is
** limited to the range of significant bits returned by the
** random number algorithm.
*/
int magnitude = maxval - minval;
int highbit = T::SIGNIFICANT_BITS-1;
while ((magnitude & (1 << highbit)) == 0 && highbit > 0) {
highbit--;
}
/*
** Create a full bit mask pattern that has all bits set that just
** barely covers the magnitude of the number range desired.
*/
int mask = ~( (~0L) << (highbit+1));
/*
** Keep picking random numbers until it fits within the magnitude desired. With a
** good random number generator, it will have to perform this loop an average
** of one and a half times.
*/
int pick = magnitude+1;
while (pick > magnitude) {
pick = generator() & mask;
}
/*
** Finally, bias the random number pick to the start of the range
** requested.
*/
return(pick + minval);
}
#endif

View File

@@ -0,0 +1,205 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/rawfile.h $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 10/04/99 10:25a $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* RawFileClass::File_Name -- Returns with the filename associate with the file object. *
* RawFileClass::RawFileClass -- Default constructor for a file object. *
* RawFileClass::~RawFileClass -- Default deconstructor for a file object. *
* RawFileClass::Is_Open -- Checks to see if the file is open or not. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef RAWFILE_Hx
#define RAWFILE_Hx
//#include <errno.h>
// #include "win.h"
#ifdef _UNIX
#include <stdio.h>
#include "osdep.h"
#define NULL_HANDLE NULL
#define HANDLE_TYPE FILE*
#else
#define NULL_HANDLE INVALID_HANDLE_VALUE
#define HANDLE_TYPE HANDLE
#endif
#include "wwfile.h"
#ifndef WWERROR
#define WWERROR -1
#endif
/*
** This is the definition of the raw file class. It is derived from the abstract base FileClass
** and handles the interface to the low level DOS routines. This is the first class in the
** chain of derived file classes that actually performs a useful function. With this class,
** I/O is possible. More sophisticated features, such as packed files, CD-ROM support,
** file caching, and XMS/EMS memory support, are handled by derived classes.
**
** Of particular importance is the need to override the error routine if more sophisticated
** error handling is required. This is more than likely if greater functionality is derived
** from this base class.
*/
class RawFileClass : public FileClass
{
typedef FileClass BASECLASS;
public:
/*
** This is a record of the access rights used to open the file. These rights are
** used if the file object is duplicated.
*/
int Rights;
RawFileClass(char const *filename);
RawFileClass(void);
RawFileClass (RawFileClass const & f);
RawFileClass & operator = (RawFileClass const & f);
virtual ~RawFileClass(void);
virtual char const * File_Name(void) const;
virtual char const * Set_Name(char const *filename);
virtual int Create(void);
virtual int Delete(void);
virtual bool Is_Available(int forced=false);
virtual bool Is_Open(void) const;
virtual int Open(char const *filename, int rights=READ);
virtual int Open(int rights=READ);
virtual int Read(void *buffer, int size);
virtual int Seek(int pos, int dir=SEEK_CUR);
virtual int Size(void);
virtual int Write(void const *buffer, int size);
virtual void Close(void);
virtual unsigned long Get_Date_Time(void);
virtual bool Set_Date_Time(unsigned long datetime);
virtual void Error(int error, int canretry = false, char const * filename=NULL);
void Bias(int start, int length=-1);
virtual void * Get_File_Handle(void) { return Handle; }
virtual void Attach (void *handle, int rights=READ);
virtual void Detach (void);
/*
** These bias values enable a sub-portion of a file to appear as if it
** were the whole file. This comes in very handy for multi-part files such as
** mixfiles.
*/
int BiasStart;
int BiasLength;
protected:
/*
** This function returns the largest size a low level DOS read or write may
** perform. Larger file transfers are performed in chunks of this size or less.
*/
int Transfer_Block_Size(void);
int Raw_Seek(int pos, int dir=SEEK_CUR);
void Reset(void);
private:
/*
** This is the low level DOS handle. A -1 indicates an empty condition.
*/
#ifdef _UNIX
FILE* Handle;
#else
void * Handle;
#endif
/*
** This points to the filename as a NULL terminated string. It may point to either a
** constant or an allocated string as indicated by the "Allocated" flag.
*/
char const * Filename;
//
// file date and time are in the following formats:
//
// date bits 0-4 day (0-31)
// bits 5-8 month (1-12)
// bits 9-15 year (0-119 representing 1980-2099)
//
// time bits 0-4 second/2 (0-29)
// bits 5-10 minutes (0-59)
// bits 11-15 hours (0-23)
//
unsigned short Date;
unsigned short Time;
/*
** Filenames that were assigned as part of the construction process
** are not allocated. It is assumed that the filename string is a
** constant in that case and thus making duplication unnecessary.
** This value will be non-zero if the filename has be allocated
** (using strdup()).
*/
bool Allocated;
};
/***********************************************************************************************
* RawFileClass::File_Name -- Returns with the filename associate with the file object. *
* *
* Use this routine to determine what filename is associated with this file object. If no *
* filename has yet been assigned, then this routing will return NULL. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with a pointer to the file name associated with this file object or NULL *
* if one doesn't exist. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/18/1994 JLB : Created. *
*=============================================================================================*/
inline char const * RawFileClass::File_Name(void) const
{
return(Filename);
}
#endif

View File

@@ -0,0 +1,95 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/RGB.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:00p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef RGB_H
#define RGB_H
class PaletteClass;
class HSVClass;
/*
** Each color entry is represented by this class. It holds the values for the color
** guns. The gun values are recorded in device dependant format, but the interface
** uses gun values from 0 to 255.
*/
class RGBClass
{
public:
RGBClass(void) : Red(0), Green(0), Blue(0) {}
RGBClass(unsigned char red, unsigned char green, unsigned char blue) : Red(red), Green(green), Blue(blue) {}
operator HSVClass (void) const;
RGBClass & operator = (RGBClass const & rgb) {
if (this == &rgb) return(*this);
Red = rgb.Red;
Green = rgb.Green;
Blue = rgb.Blue;
return(*this);
}
enum {
MAX_VALUE=255
};
void Adjust(int ratio, RGBClass const & rgb);
int Difference(RGBClass const & rgb) const;
int Get_Red(void) const {return (Red);}
int Get_Green(void) const {return(Green);}
int Get_Blue(void) const {return(Blue);}
void Set_Red(unsigned char value) {Red = value;}
void Set_Green(unsigned char value) {Green = value;}
void Set_Blue(unsigned char value) {Blue = value;}
private:
friend class PaletteClass;
/*
** These hold the actual color gun values in machine independant scale. This
** means the values range from 0 to 255.
*/
unsigned char Red;
unsigned char Green;
unsigned char Blue;
};
extern RGBClass const BlackColor;
#endif

View File

@@ -0,0 +1,63 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/RLE.H $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef RLE_H
#define RLE_H
/*
** This class will RLE compress and decompress arbitrary blocks of data. This RLE compression
** is geared to compressing only runs of 0 bytes. This makes it useful for sprite encoding.
*/
class RLEEngine
{
public:
/*
** Codec for arbitrary blocks.
*/
int Compress(void const * source, void * dest, int length) const;
int Decompress(void const * source, void * dest, int length) const;
/*
** Codec for length encoded blocks. This is useful for sprite storage.
*/
int Line_Compress(void const * source, void * dest, int length) const;
int Line_Decompress(void const * source, void * dest) const;
};
#endif

View File

@@ -0,0 +1,93 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/RNDSTRAW.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:00p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef RNDSTRAW_H
#define RNDSTRAW_H
#include "random.h"
#include "straw.h"
/*
** This is a straw terminator class. It will generate random numbers to fill the data request.
** Unlike regular straw terminators, this class will never run out of "data".
*/
class RandomStraw : public Straw
{
public:
RandomStraw(void);
virtual ~RandomStraw(void);
virtual int Get(void * source, int slen);
void Reset(void);
void Seed_Bit(int seed);
void Seed_Byte(char seed);
void Seed_Short(short seed);
void Seed_Long(long seed);
int Seed_Bits_Needed(void) const;
private:
/*
** Counter of the number of seed bits stored to this random number
** generator.
*/
int SeedBits;
/*
** The current random generator to use when fetching the next random
** byte of data.
*/
int Current;
/*
** Array of generators. There must be at least 448 bits of random number seed
** in order to be reasonably secure, however, using 1024 bits would be best.
*/
Random3Class Random[32];
void Scramble_Seed(void);
RandomStraw(RandomStraw & rvalue);
RandomStraw & operator = (RandomStraw const & pipe);
};
#endif

View File

@@ -0,0 +1,545 @@
/*
** Command & Conquer Generals(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/>.
*/
/***************************************************************************
* *
* Project Name : G *
* *
* File Name : SLIST.H *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 03/11/97 *
* *
* Last Update : March 11, 1997 [PWG] *
* *
* The Single List Class is responsible for all management functions that *
* can be performed on a singular linked list. It uses the SLNode class *
* to track the links and maintain a pointer to the object being tracked. *
* *
* The singlely linked list class is non destructive. That is only *
* pointers to the actual data being stored in the nodes are kept. The *
* users is responsible for creating the objects to be added and deleting *
* the objects once they are removed from the list if they need to be. *
*-------------------------------------------------------------------------*
* Functions: *
* *SList<T>::Remove_Head -- Removes the head of the list *
* *SList<T>::Remove_Tail -- Removes the tail element from the list *
* SList<T>::Get_Count -- Returns a count of the entries in the list *
* *SList<T>::Head -- Returns the head node of the list *
* *SList<T>::Tail -- Returns the tail node of the list *
* SList<T>::Is_Empty -- Returns true if the list is empty *
* SList<T>::Add_Head -- Adds a node to the head of the list *
* SList<T>::Add_Head -- Adds a list to to the head of the list *
* SList<T>::Add_Tail -- Adds a node to the tail of the list *
* SList<T>::Add_Tail -- Adds a list to the tail of the list *
* *SList<T>::Find_Node -- returns first node in list matching the input *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef __SLIST_H__
#define __SLIST_H__
#include "slnode.h"
#ifndef NULL
#define NULL 0L
#endif
template <class T>
class SList {
private:
SLNode<T> *HeadNode; // Note: Constructor not called for pointer.
SLNode<T> *TailNode;
public:
//
// This constructor is inlined because G++ will not create the
// constructor correctly if it is not defined within the class
// definition.
//
SList(void)
{
HeadNode = NULL;
TailNode = NULL;
};
virtual ~SList(void) { Remove_All(); };
//
// Returns the current head of the list. Used to walk the list.
//
SLNode<T> *Head(void) const;
SLNode<T> *Tail(void) const;
SLNode<T> *Find_Node(T * data) const;
virtual bool Add_Head(T *data); // Add object to head of list
virtual bool Add_Head(SList<T>& list); // Add a list to head of list
virtual bool Add_Tail(T *data); // Add object to tail of list
virtual bool Add_Tail(SList<T>& list); // Add a list to tail of list
virtual T *Remove_Head(void); // Remove head node from list
virtual T *Remove_Tail(void); // Remove tail node from list
virtual bool Remove(T *element); // remove an individual element
virtual void Remove_All(void); // Remove all nodes from list
// Insert before oldnode, if oldnode is NULL then before head node
virtual bool Insert_Before(T *newnode, T *oldnode = NULL);
// Could possibly implement an InsertBefore that operates on a whole list
// Insert after oldnode, if oldnode is NULL then insert at head
virtual bool Insert_After(T *newnode, T *oldnode = NULL);
// Could possibly implement an InsertAfter that operates on a whole list
virtual bool Is_Empty(void) const; // True if list is empty
virtual long Get_Count(void) const; // Returns number of nodes in list
};
/**************************************************************************
* SList<T>::Insert_Before -- Inserts entry prior to specified entry *
* *
* Inserts an entry prior to the specified entry in the list. If the *
* specified entry is null, it will add it prior to the head of the *
* list. Returns true if sucessfully added, false otherwise. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
bool SList<T>::Insert_Before(T *newnode, T *oldnode)
{
// if not adding anything then just skip the add.
if (newnode == NULL)
return false;
// if there is no head to the list then add it to head
if (oldnode == NULL || HeadNode == NULL || HeadNode->Data() == oldnode) {
return(Add_Head(newnode));
}
// now we need to walk the list in an attempt to add the
// node. since we are a singlely linked list we need
// to stop one prior to the entry.
SLNode<T> *cur;
for (cur=HeadNode; cur->Next() && cur->Next()->Data() != oldnode; cur=cur->Next()) {}
// Verify that we found the entry as it might not have been in the list.
// Note: Cur will be valid because it wont be assigned unless Next is
// valid.
if (cur->Next() != NULL && cur->Next()->Data() == oldnode) {
SLNode<T> *temp = new SLNode<T> (newnode);
temp->Set_Next(cur->Next());
cur->Set_Next(temp);
return(true);
}
return(false);
}
/**************************************************************************
* SList<T>::Insert_After -- Inserts an entry after specified entry *
* *
* Inserts an entry after to the specified entry in the list. If the *
* specified entry is null, it will add it prior to the head of the list. *
* Returns true if sucessfully added, false otherwise. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
bool SList<T>::Insert_After(T *newnode, T *oldnode)
{
if (newnode == NULL)
return false;
if (oldnode == NULL || HeadNode == NULL) {
return(Add_Head(newnode));
}
// Search for oldnode in list
SLNode<T> *cur;
for (cur = HeadNode; cur && cur->Data() != oldnode; cur = cur->Next()) {}
// Did we find the data we want to insert after?
if (cur != NULL && cur->Data() == oldnode) {
if (cur == TailNode) { // Inserting after tail
return(Add_Tail(newnode));
}
SLNode<T> *temp = new SLNode<T>(newnode);
temp->Set_Next(cur->Next());
cur->Set_Next(temp);
return true;
}
return false;
}
/**************************************************************************
* SList<T>::Remove_All -- Removes all of the entries in the current list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
void SList<T>::Remove_All(void)
{
SLNode<T> *next;
for (SLNode<T> *cur = HeadNode; cur; cur = next) {
next = cur->Next();
delete cur;
}
HeadNode = TailNode = NULL;
}
/**************************************************************************
* SList<T>::Remove -- Removes an element in the list. *
* *
* INPUT: *
* *
* OUTPUT: true if element could be removed, false if it could not be *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
bool SList<T>::Remove(T *element)
{
// if not adding anything then just skip the add.
if (element == NULL || HeadNode == NULL)
return false;
// if the head is the element in question remove it
if (HeadNode->Data() == element) {
return(Remove_Head() != NULL ? true : false);
}
// now we need to walk the list in an attempt to add the
// node. since we are a singlely linked list we need
// to stop one prior to the entry.
SLNode<T> *cur;
for (cur = HeadNode; cur->Next() && cur->Next()->Data() != element; cur=cur->Next()) { }
// Verify that we found the entry as it might not have been in the list.
// Note: Cur will be valid because it wont be assigned unless Next is
// valid.
if (cur->Next() != NULL && cur->Next()->Data() == element) {
SLNode<T> *temp = cur->Next();
cur->Set_Next(temp->Next());
if (temp == TailNode) TailNode = cur;
delete temp;
return true;
}
return(false);
}
/**************************************************************************
* *SList<T>::Remove_Head -- Removes the head of the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
T *SList<T>::Remove_Head(void)
{
if (HeadNode == NULL) // Should make an assertion here instead!
return ((T* )NULL);
SLNode<T> *temp = HeadNode;
HeadNode = HeadNode->Next();
if (HeadNode == NULL) // Do we have empty list now?
TailNode = NULL;
T *data = temp->Data();
delete temp;
return data;
}
//
// Removes the tail of the list and returns a data pointer to the
// element removed. Warning! On a singlely linked list it is
// slow as hell to remove a tail! If you need to frequently remove
// tails, then you should consider a doubly linked list.
//
/**************************************************************************
* *SList<T>::Remove_Tail -- Removes the tail element from the list *
* *
* INPUT: none *
* *
* OUTPUT: returns a pointer to the element removed *
* *
* WARNINGS: On a singlely linked list it is slow as hell to remove a *
* tail! If you need to frequently remove tails, then you *
* should consider a doubly linked list. *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
T *SList<T>::Remove_Tail(void)
{
if (HeadNode == NULL) // Should make an assertion here instead!
return ((T *)NULL);
T* data = TailNode->Data();
return (Remove(data) ? data : (T*)NULL);
}
/**************************************************************************
* SList<T>::Get_Count -- Returns a count of the entries in the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
inline long SList<T>::Get_Count(void) const
{
long count = 0;
for (SLNode<T> *cur = HeadNode; cur; cur = cur->Next())
count++;
return count;
}
/**************************************************************************
* *SList<T>::Head -- Returns the head node of the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
inline SLNode<T> *SList<T>::Head(void) const
{
return(HeadNode);
}
/**************************************************************************
* *SList<T>::Tail -- Returns the tail node of the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
inline SLNode<T> *SList<T>::Tail(void) const
{
return(TailNode);
}
/**************************************************************************
* SList<T>::Is_Empty -- Returns true if the list is empty *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
inline bool SList<T>::Is_Empty(void) const
{
return( HeadNode == NULL ? true : false);
}
/**************************************************************************
* SList<T>::Add_Head -- Adds a node to the head of the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
bool SList<T>::Add_Head(T *data)
{
// we don't deal with lists that point to nothing
if (!data) return false;
SLNode<T> *temp = new SLNode<T>(data);
temp->Set_Next(HeadNode);
HeadNode = temp;
if (!TailNode) TailNode = temp;
return true;
}
/**************************************************************************
* SList<T>::Add_Head -- Adds a list to to the head of the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
bool SList<T>::Add_Head(SList<T>& list)
{
if (list.HeadNode == NULL) return false;
// Save point for initial add of element.
SLNode<T> *addpoint = NULL;
// We traverse list backwards so nodes are added in right order.
for (SLNode<T> *cur = list.HeadNode; cur; cur = cur->Next())
if (addpoint) {
SLNode<T> *temp = new SLNode<T>(cur->Data());
temp->Set_Next(addpoint->Next());
addpoint->Set_Next(temp);
addpoint = temp;
} else {
Add_Head(cur->Data());
addpoint = HeadNode;
}
return true;
}
/**************************************************************************
* SList<T>::Add_Tail -- Adds a node to the tail of the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
bool SList<T>::Add_Tail(T *data)
{
if (data == NULL) return false;
SLNode<T> *temp = new SLNode<T> (data);
if (HeadNode == NULL) { // empty list
HeadNode = TailNode = temp;
} else { // non-empty list
TailNode->Set_Next(temp);
TailNode = temp;
}
return true;
}
/**************************************************************************
* SList<T>::Add_Tail -- Adds a list to the tail of the list *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/11/1997 PWG : Created. *
*========================================================================*/
template<class T>
bool SList<T>::Add_Tail(SList<T>& list)
{
if (list.HeadNode == NULL) return false;
for (SLNode<T> *cur = list.HeadNode; cur; cur = cur->Next())
Add_Tail(cur->Data());
return true;
}
/**************************************************************************
* *SList<T>::Find_Node -- returns first node in list matching the input *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/1997 GH : Created. *
*========================================================================*/
template<class T>
inline SLNode<T> *SList<T>::Find_Node(T * data) const
{
SLNode<T> * cur;
for (cur = HeadNode; cur && cur->Data() != data; cur = cur->Next());
return cur;
}
#endif

View File

@@ -0,0 +1,121 @@
/*
** Command & Conquer Generals(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/>.
*/
/***************************************************************************
* *
* Project Name : G *
* *
* File Name : SLNODE.H *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 03/11/97 *
* *
* Last Update : March 11, 1997 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef __SLNODE_H__
#define __SLNODE_H__
#ifndef ALWAYS_H
#include "always.h"
#endif
#include "mempool.h"
#ifndef NULL
#define NULL 0
#endif
// Forward references for friend classes
template <class T> class SList;
//
// The node class is responsible for maintaining the links between
// data in a linked list. It works with the Single List Class to
// manage a singularly linked list of objects.
//
class GenericSLNode : public AutoPoolClass<GenericSLNode, 256>
{
protected:
void* Internal_Get_Next(void) { return NodeNext; };
void Internal_Set_Next(void* n) { NodeNext=n; };
void *Internal_Get_Data(void) { return NodeData; };
void Internal_Get_Data(void* d) { NodeData=d; };
//
// Note that their is only one constructor for this class and it
// requires you to provide an object. Furthermore it can be
// created from anything but a friend or parent class.
//
GenericSLNode(void *obj)
{NodeData = obj; NodeNext = 0; };
//
// You cannot declare a node class without giving it a data object.
// Defining this type of constructor as private to the class insures
// that it cannot be used.
//
private:
GenericSLNode(void) {};
void *NodeNext; // Next Node in the list chain
void *NodeData; // Current Node in the list chain
};
template <class T>
class SLNode : public GenericSLNode
{
public:
//
// Since the list class manages the Node Class it must be able to
// access its private data.
//
friend class SList<T>;
SLNode<T>* Next(void) { return reinterpret_cast<SLNode<T>*>(Internal_Get_Next()); }
T *Data(void) { return reinterpret_cast<T*>(Internal_Get_Data()); }
void Set_Next(SLNode<T>* n) { Internal_Set_Next(reinterpret_cast<void*>(n)); }
protected:
//
// Note that their is only one constructor for this class and it
// requires you to provide an object. Furthermore it can be
// created from anything but a friend or parent class.
//
SLNode(T *obj) : GenericSLNode(obj) {}
//
// You cannot declare a node class without giving it a data object.
// Defining this type of constructor as private to the class insures
// that it cannot be used.
//
private:
SLNode(void) {};
};
#endif

View File

@@ -0,0 +1,76 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/STRAW.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:00p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef STRAW_H
#define STRAW_H
/*
** This is a demand driven data carrier. It will retrieve the byte request by passing
** the request down the chain (possibly processing on the way) in order to fulfill the
** data request. Without being derived, this class merely passes the data through. Derived
** versions are presumed to modify the data in some useful way or monitor the data
** flow.
*/
class Straw
{
public:
Straw(void) : ChainTo(0), ChainFrom(0) {}
virtual ~Straw(void);
virtual void Get_From(Straw * pipe);
void Get_From(Straw & pipe) {Get_From(&pipe);}
virtual int Get(void * buffer, int slen);
/*
** Pointer to the next pipe segment in the chain.
*/
Straw * ChainTo;
Straw * ChainFrom;
private:
/*
** Disable the copy constructor and assignment operator.
*/
Straw(Straw & rvalue);
Straw & operator = (Straw const & pipe);
};
#endif

View File

@@ -0,0 +1,80 @@
/*
** Command & Conquer Generals(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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/wwlib/Signaler.h $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Modtime: 8/17/01 7:08p $
* $Revision: 3 $
*
******************************************************************************/
#ifndef __SIGNALER_H__
#define __SIGNALER_H__
template<typename T> class Signaler
{
public:
void SignalMe(Signaler<T>& target)
{if (mConnection != &target) {Disconnect(); Connect(target); target.Connect(*this);}}
void StopSignaling(Signaler<T>& target)
{if (mConnection == &target) {Disconnect();}}
void SendSignal(T& signal)
{if (mConnection) {mConnection->ReceiveSignal(signal);}}
virtual void ReceiveSignal(T&)
{}
virtual void SignalDropped(Signaler<T>& signaler)
{mConnection = NULL;}
protected:
Signaler() :
mConnection(NULL)
{}
virtual ~Signaler()
{Disconnect();}
void Connect(Signaler<T>& source)
{mConnection = &source;}
void Disconnect(void)
{if (mConnection) {mConnection->SignalDropped(*this);} mConnection = NULL;}
// Prevent copy and assignment
Signaler(const Signaler&);
const Signaler& operator=(const Signaler&);
private:
Signaler<T>* mConnection;
};
#endif // __SIGNALER_H__

View File

@@ -0,0 +1,123 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/surface.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 11/28/00 2:40p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef SURFACE_H
#define SURFACE_H
#include "point.h"
#include "trect.h"
/*
** This is an abstract interface class for a graphic surface. Graphic operations will use this
** interface to perform their function. The philosphy behind this interface is that it represents
** a small but useful set of functions. Emphasis is placed on supporting those functions which are
** likely to have hardware assist.
*/
class Surface
{
public:
Surface(int width, int height) : Width(width), Height(height) {}
virtual ~Surface(void) {};
/*
** Copies regions from one surface to another.
*/
virtual bool Blit_From(Rect const & dcliprect, Rect const & destrect, Surface const & source, Rect const & scliprect, Rect const & sourcerect, bool trans=false) = 0;
virtual bool Blit_From(Rect const & destrect, Surface const & source, Rect const & sourcerect, bool trans=false) = 0;
virtual bool Blit_From(Surface const & source, bool trans=false) = 0;
/*
** Fills a region with a constant color.
*/
virtual bool Fill_Rect(Rect const & rect, int color) = 0;
virtual bool Fill_Rect(Rect const & cliprect, Rect const & fillrect, int color) = 0;
virtual bool Fill(int color) = 0;
/*
** Fetches and stores a pixel to the display (pixel is in surface format).
*/
virtual bool Put_Pixel(Point2D const & point, int color) = 0;
virtual int Get_Pixel(Point2D const & point) const = 0;
/*
** Draws lines onto the surface.
*/
virtual bool Draw_Line(Point2D const & startpoint, Point2D const & endpoint, int color) = 0;
virtual bool Draw_Line(Rect const & cliprect, Point2D const & startpoint, Point2D const & endpoint, int color) = 0;
/*
** Draws rectangle onto the surface.
*/
virtual bool Draw_Rect(Rect const & rect, int color) = 0;
virtual bool Draw_Rect(Rect const & cliprect, Rect const & rect, int color) = 0;
/*
** Gets and frees a direct pointer to the video memory.
*/
virtual void * Lock(Point2D point = Point2D(0, 0)) const = 0;
virtual bool Unlock(void) const = 0;
virtual bool Is_Locked(void) const = 0;
/*
** Queries information about the surface.
*/
virtual int Bytes_Per_Pixel(void) const = 0;
virtual int Stride(void) const = 0;
virtual Rect Get_Rect(void) const {return(Rect(0, 0, Width, Height));}
virtual int Get_Width(void) const {return(Width);}
virtual int Get_Height(void) const {return(Height);}
/*
** Hack function to serve the purpose that RTTI was invented for, but since
** the Watcom compiler doesn't support RTTI, we must resort to using this
** alternative.
*/
virtual bool Is_Direct_Draw(void) const {return(false);}
protected:
/*
** Records logical pixel dimensions of the surface.
*/
int Width;
int Height;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,320 @@
/*
** Command & Conquer Generals(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/>.
*/
#ifndef _TARGA_H_
#define _TARGA_H_
/****************************************************************************
*
* 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
*
*----------------------------------------------------------------------------
*
* FILE
* Targa.h
*
* DESCRIPTION
* Targa image file class definitions.
*
* PROGRAMMER
* Denzil E. Long, Jr.
*
* DATE
* July 15, 1998
*
****************************************************************************/
#pragma pack(push, 1)
// If you wish to display loading error messages call targa functions inside of
// the following macro - for example TARGA_ERROR_HANDLER(targa.Open(filename, TGA_READMODE));
// The error code is returned back from the handler so it can be used in an expression.
long Targa_Error_Handler(long error_code,const char* filename);
#define TARGA_ERROR_HANDLER(call,filename) Targa_Error_Handler(call,filename)
/*---------------------------------------------------------------------------
* STRUCTURES AND RELATED DEFINITIONS
*-------------------------------------------------------------------------*/
/* TGAHeader - Targa Image File header.
*
* IDLength - Size of Image ID field
* ColorMapType - Color map type.
* ImageType - Image type code.
* CMapStart - Color map origin.
* CMapLength - Color map length.
* CMapDepth - Depth of color map entries.
* XOffset - X origin of image.
* YOffset - Y origin of image.
* Width - Width of image.
* Height - Height of image.
* PixelDepth - Image pixel size
* ImageDescriptor - Image descriptor byte.
*/
typedef struct _TGAHeader
{
char IDLength;
char ColorMapType;
char ImageType;
short CMapStart;
short CMapLength;
char CMapDepth;
short XOffset;
short YOffset;
short Width;
short Height;
char PixelDepth;
char ImageDescriptor;
} TGAHeader;
/* ImageType definiton */
#define TGA_NOIMAGE 0 /* No image data included in file */
#define TGA_CMAPPED 1 /* Color-mapped image data */
#define TGA_TRUECOLOR 2 /* Truecolor image data */
#define TGA_MONO 3 /* Monochrome image data */
#define TGA_CMAPPED_ENCODED 9 /* Color-mapped image data (Encoded) */
#define TGA_TRUECOLOR_ENCODED 10 /* Truecolor image data (Encoded) */
#define TGA_MONO_ENCODED 11 /* Monochrome image data (Encoded) */
/* ImageDescriptor definition */
#define TGAIDF_ATTRIB_BITS (0x0F<<0) /* Number of attribute bits per pixel */
#define TGAIDF_XORIGIN (1<<4)
#define TGAIDF_YORIGIN (1<<5)
/* Access modes. */
#define TGA_READMODE 0
#define TGA_WRITEMODE 1
#define TGA_RDWRMODE 2
/* Error codes */
#define TGAERR_OPEN -1
#define TGAERR_READ -2
#define TGAERR_WRITE -3
#define TGAERR_SYNTAX -4
#define TGAERR_NOMEM -5
#define TGAERR_NOTSUPPORTED -6
/* Flags definitions */
#define TGAF_IMAGE (1<<0)
#define TGAF_PAL (1<<1)
#define TGAF_COMPRESS (1<<2)
#define TGAF_TGA2 (1<<3)
/* Macro definitions */
#define TGA_BytesPerPixel(a) ((a+7) >> 3)
/*---------------------------------------------------------------------------
* TARGA 2.0 DEFINITIONS
*-------------------------------------------------------------------------*/
#define TGA2_SIGNATURE "TRUEVISION-XFILE"
/* TGA2Footer - Targa 2.0 footer
*
* Extension - Offset to the Extension area from start of file.
* Developer - Offset to the Developer area from start of file.
* Signature - 16 byte Targa 2.0 signature "TRUEVISION-XFILE"
* RsvdChar - Reserved character, must be ASCII "." (period)
* BZST - Binary Zero String Terminator.
*/
typedef struct _TGA2Footer
{
long Extension;
long Developer;
char Signature[16];
char RsvdChar;
char BZST;
_TGA2Footer() {}
} TGA2Footer;
/* TGA2DateStamp - A series of 3 WORD values which define the integer value
* for the date the image was saved.
*
* Month - Month number (1 - 12)
* Day - Day number (1 - 31)
* Year - Year number (4 digit, ie. 1989)
*/
typedef struct _TGA2DateStamp
{
short Month;
short Day;
short Year;
} TGA2DateStamp;
/* TGA2TimeStamp - A series of 3 WORD values which define the integer value
* for the time the image was saved.
*
* Hour - Hour number, military time (0 - 23)
* Minute - Minute number (0 - 59)
* Second - Second number (0 - 59)
*/
typedef struct _TGA2TimeStamp
{
short Hour;
short Minute;
short Second;
} TGA2TimeStamp;
/* TGA2SoftVer - Define the version of the software used to generate file.
*
* Number - Version number * 100
* Letter - Version letter
*/
typedef struct _TGA2SoftVer
{
short Number;
char Letter;
} TGA2SoftVer;
/* TGA2Ratio - Numerator and denominator which when taken together specify
* a ratio.
*
* Numer - Numerator
* Denom - Denominator (a value of zero indicates no ratio specified)
*/
typedef struct _TGA2Ratio
{
short Numer;
short Denom;
} TGA2Ratio;
/* TGA2Extension - Extension area, provided for additional file information.
* This data is pointed to by the Extension offset in the
* TGA2Footer.
*
* ExtSize - Extension area size. (495 bytes for 2.0)
* AuthName - Name of the person who created image (NULL terminated ASCII)
* AuthComment - Comments of the author (NULL terminated ASCII)
* DateStamp - Date the file was created. (See TGA2DateStamp)
* TimeStamp - Time the file was created. (See TGA2TimeStamp)
* JobName - Name of job image belongs to (NULL terminated ASCII)
* JobTime - Elapsed time of the job.
* SoftID - ID of software used to create image (NULL terminated ASCII)
* SoftVer - Version number of software used.
* KeyColor - Tranparent color value.
* Aspect - Pixel aspect ratio.
* Gamma - Fractional gamma value.
* ColorCor - Color correction table offset.
* PostStamp - Postage stamp image offset.
* ScanLine - Scan line table offset.
* Attributes - Alpha channel attributes. (Set defines below)
*/
typedef struct _TGA2Extension
{
short ExtSize;
char AuthName[41];
char AuthComment[324];
TGA2DateStamp Date;
TGA2TimeStamp Time;
char JobName[41];
TGA2TimeStamp JobTime;
char SoftID[41];
TGA2SoftVer SoftVer;
long KeyColor;
TGA2Ratio Aspect;
TGA2Ratio Gamma;
long ColorCor;
long PostStamp;
long ScanLine;
char Attributes;
} TGA2Extension;
/* Alpha channel attributes (Extension Area) */
#define EXTA_NOALPHA 0 /* No alpha data included */
#define EXTA_IGNORE 1 /* Undefined alpha data, can ignore */
#define EXTA_RETAIN 2 /* Undefined alpha data, should retain */
#define EXTA_USEFUL 3 /* Useful alpha channel */
#define EXTA_PREMULT 4 /* Pre-Multiplied alpha data */
#pragma pack(pop)
/*
** This define changes this code from code that works with standard IO calls,
** to code that uses FileClass and FileFactoryClass.
*/
#define TGA_USES_WWLIB_FILE_CLASSES
#ifdef TGA_USES_WWLIB_FILE_CLASSES
class FileClass;
#endif
/*---------------------------------------------------------------------------
* CLASS DEFINITION
*-------------------------------------------------------------------------*/
class Targa
{
public:
/* Constructor/destructor */
Targa(void);
~Targa();
/* Function prototypes. */
long Open(const char* name, long mode);
void Close(void);
long Load(const char* name, char* palette, char* image,bool invert_image=true);
long Load(const char* name, long flags, bool invert_image=true);
long Save(const char* name, long flags, bool addextension = false);
void XFlip(void);
void YFlip(void);
char* SetImage(char* buffer);
char* GetImage(void) const {return (mImage);}
char* SetPalette(char* buffer);
char* GetPalette(void) const {return (mPalette);}
bool IsCompressed(void);
TGA2Extension* GetExtension(void);
TGAHeader Header;
protected:
#ifdef TGA_USES_WWLIB_FILE_CLASSES
FileClass *TGAFile;
#else
long mFH;
#endif
long mAccess;
long mFlags;
char* mImage;
char* mPalette;
TGA2Extension mExtension;
private:
// Utility functions
long DecodeImage(void);
long EncodeImage(void);
void InvertImage(void);
// These functions are for ease of ifdef'ing between standard io calls
// and FileClass.
void Clear_File(void);
bool Is_File_Open(void);
bool File_Open_Read(const char* name);
bool File_Open_Write(const char* name);
bool File_Open_ReadWrite(const char* name);
int File_Seek(int pos, int dir);
int File_Read(void *buffer, int size);
int File_Write(void *buffer, int size);
};
#endif /* _TARGA_H_ */

View File

@@ -0,0 +1,278 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /VSS_Sync/wwlib/tagblock.h 6 10/17/00 4:48p Vss_sync $ */
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWLib *
* *
* $Archive:: /VSS_Sync/wwlib/tagblock.h $*
* *
* $Author:: Vss_sync $*
* *
* $Modtime:: 10/16/00 11:42a $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef TAGBLOCK_H
#define TAGBLOCK_H
#include "slist.h"
#include "crc.h"
#include "rawfile.h"
#include <string.h>
class TagBlockHandle;
class TagBlockIndex;
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// Start of TagBlockHandle///////////////////////////////////////
// TagBlockFile: Enables a file to have named (tagged) variable size blocks. User can
// then open a block for reading. User may also create new blocks at the end of the
// file. There may only be one block open for writting, unlimited blocks can be open for
// reading. It can be thought of as a .MIX file that can have files added to it at any time.
// One problem is it is a Write Once/Read Many solution.
//
// Usage: All user access to a TagBlockFile is done through TagBlockHandle.
// A TagBlockHandle is created by TagBlockFile::Create_Tag() or Open_Tag(). It is destroyed
// by either TagBlockFile::Close_Tag() or you can just destroy the handle with delete().
//
//
class TagBlockFile : protected RawFileClass
{
public:
//////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Public Member Functions ///////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Open up the tag file. It may or may not exist.
TagBlockFile(const char *fname);
virtual ~TagBlockFile();
// DANGEROUS!! Resets entire file and makes small
virtual void Reset_File();
// Creation of a Handle so block can be crated/writen/read.
// Use delete to destroy handle or use Close_Tag().
// Open_Tag() returns NULL if tag not found.
// Create_Tag() returns NULL if tag already exists.
TagBlockHandle *Open_Tag(const char *tagname);
TagBlockHandle *Create_Tag(const char *tagname);
void Close_Tag(TagBlockHandle *handle);
int Does_Tag_Exist(const char *tagname) {
return(Find_Block(tagname) != NULL);
}
virtual unsigned long Get_Date_Time(void) {
return(FileTime);
}
// Methods to figure an offset of the tag name and the data
// given the offset of the start of the block (BlockHeader)..
static int Calc_Tag_Offset(int blockoffset) {
return(blockoffset + sizeof(BlockHeader));
}
static int Calc_Data_Offset(int blockoffset, const char *tagname) {
return(Calc_Tag_Offset(blockoffset) + strlen(tagname) + 1);
}
protected:
///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Supporting Structures /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
enum {
// Put in date when format is changed.
FILE_VERSION = 20000626,
MAX_TAG_NAME_SIZE = 1024,
};
// This is the header that is in both the IndexFile and the DataFile.
// They should be match except for the difference in the Version number as defined by enum.
struct FileHeader
{
FileHeader() {memset(this, 0, sizeof(*this));}
// Version number to make sure that it we are compatable and also to
// verify that this is the file we think it is.
unsigned Version;
// Number of blocks in file.
int NumBlocks;
// This is how much data is actually valid in the file. There may be
// extra room at end of file if file size is preset or the file is corrupt.
int FileSize;
};
// Each block in the file has a header before it.
struct BlockHeader
{
BlockHeader() {memset(this, 0, sizeof(*this));}
BlockHeader(int index, int tagsize, int datasize):Index(index),TagSize(tagsize),DataSize(datasize) {}
BlockHeader(BlockHeader& bh) {memcpy(this, &bh, sizeof(BlockHeader));}
// Used to verify file integrity.
int Index;
// Size of tagname (including NULL) that follows this block.
int TagSize;
// Size of block not including header.
int DataSize;
// A variable length name (NULL terminated) follows this structure.
// The name is then followed by the Data.
// The entire length of the block is sizeof(BlockHeader) + TagSize + DataSize.
};
protected:
///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Member Data Fields ////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// This is the data at the start of the file.
FileHeader Header;
// Only one handle has permission to write to the end of the file if any.
// This is a pointer to that handle.
TagBlockHandle *CreateHandle;
// To help those stupid programmers from leaving open handles when
// this file is closed down.
int NumOpenHandles;
// Last time file was written to before we opened it.
unsigned long FileTime;
// Keep list of all blocks in file. This list is sorted by CRC value.
// TagBlockIndex is defined in TagBlock.cpp.
SList<TagBlockIndex> IndexList;
protected:
///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Protected Member Functions ////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Search for block given tag.
TagBlockIndex *Find_Block(const char *tagname);
// Create an index that can be used for seaching.
TagBlockIndex *Create_Index(const char *tagname, int blockoffset);
// Is this the handle that has creation priveledges?
int Handle_Can_Write(TagBlockHandle *handle) {
return(CreateHandle == handle);
}
// Called only by ~TagBlockHandle!
void Destroy_Handle(TagBlockHandle *handle);
// Stop write access - flushes data out but keeps handle available for reading.
int End_Write_Access(TagBlockHandle *handle);
// Save the header when it has been updated.
void Save_Header() {
Seek(0, SEEK_SET);
Write(&Header, sizeof(Header));
}
void Empty_Index_List();
friend class TagBlockHandle;
};
///////////////////////////////////////// End of TagBlockFile /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// Start of TagBlockHandle/////////////////////////////////////
// All external access to the TagBlockFile is done through handles.
class TagBlockHandle
{
public:
// Access functions.
int Write(const void *buf, int nbytes);
int Read(void *buf, int nbytes);
int Seek(int pos, int dir = SEEK_CUR);
// Stop write access - flushes data out but keeps handle available for reading.
int End_Write_Access() {
return (File->End_Write_Access(this));
}
int Tell() {
return(Position);
}
int Get_Data_Size() {
return(BlockHeader->DataSize);
}
// User must call TagBlockFile::New_Handle() to create a TagBlockHandle object.
// User may call this delete to destry handle or
// he may call TagBlockFile::Close_Tag().
~TagBlockHandle();
private:
// Pointer to parent file object.
TagBlockFile *File;
// Pointer to index for aditional information.
TagBlockIndex *Index;
// Keep header infomation in memory so that it can be updated.
TagBlockFile::BlockHeader *BlockHeader;
// Current postion we are in the file.
int Position;
private:
// User must call TagBlockFile::New_Handle() to create a TagBlockHandle object.
// The constructor is private so only TagBlockFile can create the handle.
// This is so that a handle will not be created if the TagBlock
// does not exist on a CREAD or if there was already a WRITE access granted.
// User needs to call detete to destroy the handle.
TagBlockHandle(TagBlockFile *tagfile, TagBlockIndex *tagindex, TagBlockFile::BlockHeader *blockheader);
friend class TagBlockFile;
// Used to prevent TagBlockFile::Destroy_Handle() from being called
// except by this destructor.
static int _InDestructor;
int Called_By_Destructor() {
return(_InDestructor);
}
};
////////////////////////////////////// End of TagBlockHandle///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
#endif //TAGBLOCK_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,118 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/WATCOM.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:56a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#if !defined(WATCOM_H) && defined(__WATCOMC__)
#define WATCOM_H
/**********************************************************************
** The "bool" integral type was defined by the C++ comittee in
** November of '94. Until the compiler supports this, use the following
** definition.
*/
#include "bool.h"
// Turn all warnings into errors.
#pragma warning * 0
// Disables warning when "sizeof" is used on an object with virtual functions.
#pragma warning 549 9
// Disable the "Integral value may be truncated during assignment or initialization".
#pragma warning 389 9
// Allow constructing a temporary to be used as a parameter.
#pragma warning 604 9
// Disable the construct resolved as an expression warning.
#pragma warning 595 9
// Disable the strange "construct resolved as a declaration/type" warning.
#pragma warning 594 9
// Disable the "pre-compiled header file cannot be used" warning.
#pragma warning 698 9
// Disable the "temporary object used to initialize a non-constant reference" warning.
#pragma warning 665 9
// Disable the "pointer or reference truncated by cast. Cast is supposed to REMOVE warnings, not create them.
#pragma warning 579 9
// Disable the warning that suggests a null destructor be placed in class definition.
#pragma warning 656 9
// Disable the warning about moving empty constructors/destructors to the class declaration.
#pragma warning 657 9
// No virtual destructor is not an error in C&C.
#pragma warning 004 9
// Integral constant will be truncated warning is usually ok when dealing with bitfields.
#pragma warning 388 9
// Turns off unreferenced function parameter warning.
//#pragma off(unreferenced)
/*
** The "bool" integral type was defined by the C++ comittee in
** November of '94. Until the compiler supports this, use the following
** definition.
*/
#include "bool.h"
#if !defined(__BORLANDC__)
#define M_E 2.71828182845904523536
#define M_LOG2E 1.44269504088896340736
#define M_LOG10E 0.434294481903251827651
#define M_LN2 0.693147180559945309417
#define M_LN10 2.30258509299404568402
#define M_PI 3.14159265358979323846
#define M_PI_2 1.57079632679489661923
#define M_PI_4 0.785398163397448309616
#define M_1_PI 0.318309886183790671538
#define M_2_PI 0.636619772367581343076
#define M_1_SQRTPI 0.564189583547756286948
#define M_2_SQRTPI 1.12837916709551257390
#define M_SQRT2 1.41421356237309504880
#define M_SQRT_2 0.707106781186547524401
#endif
#endif

View File

@@ -0,0 +1,238 @@
/*
** Command & Conquer Generals(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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/wwlib/WWCOMUtil.cpp $
*
* DESCRIPTION
* COM utility functions and macros
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 2 $
* $Modtime: 8/02/01 3:00p $
*
******************************************************************************/
#include "WWCOMUtil.h"
/******************************************************************************
*
* NAME
* Dispatch_GetProperty
*
* DESCRIPTION
*
* INPUTS
* Dispatch - Dispatch interface pointer.
* Property - Name of property to get.
* Value - Property value.
*
* RESULT
*
******************************************************************************/
STDMETHODIMP Dispatch_GetProperty(IDispatch* object, const OLECHAR* propName,
VARIANT* result)
{
result->vt = VT_EMPTY;
result->lVal = 0;
// Get the dispid for the named property
OLECHAR* member = const_cast<OLECHAR*>(propName);
DISPID dispid;
HRESULT hr = object->GetIDsOfNames(IID_NULL, &member, 1,
LOCALE_SYSTEM_DEFAULT, &dispid);
if (SUCCEEDED(hr))
{
// Get the property
DISPPARAMS params = {NULL, NULL, 0, 0};
UINT argErr = 0;
hr = object->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, &params, result, NULL, &argErr);
}
return hr;
}
/******************************************************************************
*
* NAME
* Dispatch_PutProperty
*
* DESCRIPTION
*
* INPUTS
* Dispatch - Dispatch interface pointer.
* Property - Name of property to put.
* Value - Property value.
*
* RESULT
*
******************************************************************************/
STDMETHODIMP Dispatch_PutProperty(IDispatch* object, const OLECHAR* propName,
VARIANT* propValue)
{
// Get the dispid for the named property
OLECHAR* member = const_cast<OLECHAR*>(propName);
DISPID dispid;
HRESULT hr = object->GetIDsOfNames(IID_NULL, &member, 1,
LOCALE_SYSTEM_DEFAULT, &dispid);
if (SUCCEEDED(hr))
{
// Get the property
DISPPARAMS params = {NULL, NULL, 0, 0};
params.cArgs = 1;
params.rgvarg = propValue;
VARIANT result;
UINT argErr = 0;
hr = object->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYPUT, &params, &result, NULL, &argErr);
}
return hr;
}
/******************************************************************************
*
* NAME
* Dispatch_InvokeMethod
*
* DESCRIPTION
*
* INPUTS
* Dispatch - Dispatch interface pointer.
* Method - Method name
* Params - Parameters
* Result - On return; result of method call
*
* RESULT
*
******************************************************************************/
STDMETHODIMP Dispatch_InvokeMethod(IDispatch* object, const OLECHAR* methodName,
DISPPARAMS* params, VARIANT* result)
{
// Get the dispid for the named property
OLECHAR* member = const_cast<OLECHAR*>(methodName);
DISPID dispid;
HRESULT hr = object->GetIDsOfNames(IID_NULL, &member, 1,
LOCALE_SYSTEM_DEFAULT, &dispid);
if (SUCCEEDED(hr))
{
UINT argErr = 0;
hr = object->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, params, result, NULL, &argErr);
}
return hr;
}
/******************************************************************************
*
* NAME
* RegisterCOMServer
*
* DESCRIPTION
* Register an in-process COM server DLL.
*
* INPUTS
* DLLName - Name of DLL to register.
*
* RESULT
* Success - True if operation successful.
*
******************************************************************************/
bool RegisterCOMServer(const char* dllName)
{
bool success = false;
HINSTANCE hInst = LoadLibrary(dllName);
if (hInst != NULL)
{
FARPROC regServerProc = GetProcAddress(hInst, "DllRegisterServer");
if (regServerProc != NULL)
{
HRESULT hr = regServerProc();
success = SUCCEEDED(hr);
}
FreeLibrary(hInst);
}
return success;
}
/******************************************************************************
*
* NAME
* UnregisterCOMServer
*
* DESCRIPTION
* Unregister a in-process COM server DLL.
*
* INPUTS
* DLLName - Name of DLL to unregister.
*
* RESULT
* Success - True if operation successful.
*
******************************************************************************/
bool UnregisterCOMServer(const char* dllName)
{
bool success = false;
HINSTANCE hInst = LoadLibrary(dllName);
if (hInst != NULL)
{
FARPROC unregServerProc = GetProcAddress(hInst, "DllUnregisterServer");
if (unregServerProc != NULL)
{
HRESULT hr = unregServerProc();
success = SUCCEEDED(hr);
}
FreeLibrary(hInst);
}
return success;
}

View File

@@ -0,0 +1,60 @@
/*
** Command & Conquer Generals(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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/wwlib/WWCOMUtil.h $
*
* DESCRIPTION
* COM utility functions and macros
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 3 $
* $Modtime: 8/02/01 3:00p $
*
******************************************************************************/
#ifndef __WWCOMUTIL_H__
#define __WWCOMUTIL_H__
#include <oaidl.h>
//! Invoke PropertyGet on IDispatch interface.
HRESULT STDMETHODCALLTYPE Dispatch_GetProperty(IDispatch* object,
const OLECHAR* propName, VARIANT* result);
//! Invoke PropertyPut on IDispatch interface.
HRESULT STDMETHODCALLTYPE Dispatch_PutProperty(IDispatch* object,
const OLECHAR* propName, VARIANT* propValue);
//! Invoke Method on IDispatch interface.
HRESULT STDMETHODCALLTYPE Dispatch_InvokeMethod(IDispatch* object,
const OLECHAR* methodName, DISPPARAMS* params, VARIANT* result);
//! Register COM in-process DLL server
bool RegisterCOMServer(const char* dllName);
//! Unregister COM in-process DLL server
bool UnregisterCOMServer(const char* dllName);
#endif // __WWCOMUTIL_H__

View File

@@ -0,0 +1,112 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/wwfile.h $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 5/04/01 7:43p $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef WWFILE_Hx
#define WWFILE_Hx
#ifdef _UNIX
#include "osdep.h"
#endif
#define YEAR(dt) (((dt & 0xFE000000) >> (9 + 16)) + 1980)
#define MONTH(dt) ((dt & 0x01E00000) >> (5 + 16))
#define DAY(dt) ((dt & 0x001F0000) >> (0 + 16))
#define HOUR(dt) ((dt & 0x0000F800) >> 11)
#define MINUTE(dt) ((dt & 0x000007E0) >> 5)
#define SECOND(dt) ((dt & 0x0000001F) << 1)
#ifndef SEEK_SET
#define SEEK_SET 0 // Seek from start of file.
#define SEEK_CUR 1 // Seek relative from current location.
#define SEEK_END 2 // Seek from end of file.
#endif
#ifndef NULL
#define NULL 0
#endif
class FileClass
{
public:
enum
{
READ = 1,
WRITE = 2,
PRINTF_BUFFER_SIZE = 1024
};
virtual ~FileClass(void) {};
virtual char const * File_Name(void) const = 0;
virtual char const * Set_Name(char const *filename) = 0;
//virtual int Create(void) = 0;
//virtual int Delete(void) = 0;
virtual bool Is_Available(int forced=false) = 0;
virtual bool Is_Open(void) const = 0;
virtual int Open(char const *filename, int rights=READ) = 0;
virtual int Open(int rights=READ) = 0;
virtual int Read(void *buffer, int size) = 0;
virtual int Seek(int pos, int dir=SEEK_CUR) = 0;
virtual int Tell(void) { return Seek(0); }
virtual int Size(void) = 0;
virtual int Write(void const *buffer, int size) = 0;
virtual void Close(void) = 0;
//virtual unsigned long Get_Date_Time(void) {return(0);}
//virtual bool Set_Date_Time(unsigned long ) {return(false);}
//virtual void Error(int error, int canretry = false, char const * filename=NULL) = 0;
// virtual void * Get_File_Handle(void) { return reinterpret_cast<void *>(-1); }
operator char const * ()
{
return File_Name();
}
// this form uses a stack buffer of PRINTF_BUFFER_SIZE
int Printf(char *str, ...);
// this form uses the supplied buffer if PRINTF_BUFFER_SIZE is expected to be too small.
int Printf(char *buffer, int bufferSize, char *str, ...);
// this form uses the stack buffer but will prepend any output with the indicated number of tab characters '\t'
int Printf_Indented(unsigned depth, char *str, ...);
};
#endif

View File

@@ -0,0 +1,94 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/XPIPE.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:01p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef XPIPE_H
#define XPIPE_H
#include "buff.h"
#include "pipe.h"
#include "wwfile.h"
/*
** This is a simple store-into-buffer pipe terminator. Use it as the final link in a pipe process
** that needs to store the data into a memory buffer. This can only serve as the final
** link in the chain of pipe segments.
*/
class BufferPipe : public Pipe
{
public:
BufferPipe(Buffer const & buffer) : BufferPtr(buffer), Index(0) {}
BufferPipe(void * buffer, int length) : BufferPtr(buffer, length), Index(0) {}
virtual int Put(void const * source, int slen);
private:
Buffer BufferPtr;
int Index;
bool Is_Valid(void) {return(BufferPtr.Is_Valid());}
BufferPipe(BufferPipe & rvalue);
BufferPipe & operator = (BufferPipe const & pipe);
};
/*
** This is a store-to-file pipe terminator. Use it as the final link in a pipe process that
** needs to store the data to a file. This can only serve as the last link in the chain
** of pipe segments.
*/
class FilePipe : public Pipe
{
public:
FilePipe(FileClass * file) : File(file), HasOpened(false) {}
FilePipe(FileClass & file) : File(&file), HasOpened(false) {}
virtual ~FilePipe(void);
virtual int Put(void const * source, int slen);
virtual int End(void);
private:
FileClass * File;
bool HasOpened;
bool Valid_File(void) {return(File != NULL);}
FilePipe(FilePipe & rvalue);
FilePipe & operator = (FilePipe const & pipe);
};
#endif

View File

@@ -0,0 +1,92 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/XSTRAW.H $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 12:01p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef XSTRAW_H
#define XSTRAW_H
#include "buff.h"
#include "straw.h"
#include "wwfile.h"
#include <stddef.h>
/*
** This class is used to manage a buffer as a data source. Data requests will draw from the
** buffer supplied until the buffer is exhausted.
*/
class BufferStraw : public Straw
{
public:
BufferStraw(Buffer const & buffer) : BufferPtr(buffer), Index(0) {}
BufferStraw(void const * buffer, int length) : BufferPtr((void*)buffer, length), Index(0) {}
virtual int Get(void * source, int slen);
private:
Buffer BufferPtr;
int Index;
// void const * BufferPtr;
// int Length;
bool Is_Valid(void) {return(BufferPtr.Is_Valid());}
BufferStraw(BufferStraw & rvalue);
BufferStraw & operator = (BufferStraw const & pipe);
};
/*
** This class is used to manage a file as a data source. Data requests will draw from the
** file until the file has been completely read.
*/
class FileStraw : public Straw
{
public:
FileStraw(FileClass * file) : File(file), HasOpened(false) {}
FileStraw(FileClass & file) : File(&file), HasOpened(false) {}
virtual ~FileStraw(void);
virtual int Get(void * source, int slen);
private:
FileClass * File;
bool HasOpened;
bool Valid_File(void) {return(File != NULL);}
FileStraw(FileStraw & rvalue);
FileStraw & operator = (FileStraw const & pipe);
};
#endif

View File

@@ -0,0 +1,46 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/Library/_Convert.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 2/10/98 4:20p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "_convert.h"
ConvertClass * VoxelDrawer = NULL;
ConvertClass * UnitDrawer = NULL;
ConvertClass * TerrainDrawer = NULL;
ConvertClass * AnimDrawer = NULL;
ConvertClass * NormalDrawer = NULL;
ConvertClass * IsometricDrawer = NULL;

View File

@@ -0,0 +1,49 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/_Convert.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef _CONVERT_H
#define _CONVERT_H
#include "convert.h"
extern ConvertClass * VoxelDrawer;
extern ConvertClass * UnitDrawer;
extern ConvertClass * TerrainDrawer;
extern ConvertClass * AnimDrawer;
extern ConvertClass * NormalDrawer;
extern ConvertClass * IsometricDrawer;
#endif

View File

@@ -0,0 +1,47 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/_mono.cpp $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "_mono.h"
/*
** This is the global (general purpose) mono object. It exists only for the convenience of
** debugging mono printing.
*/
MonoClass Mono;

View File

@@ -0,0 +1,52 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/_mono.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:58a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef _MONO_H
#define _MONO_H
#include "mono.h"
/*
** This externs the global mono object. There can be only one.
*/
extern MonoClass Mono;
#endif

View File

@@ -0,0 +1,51 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/_Timer.cpp $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "_timer.h"
/***************************************************************************
** Game frame timer (this is synced between processes).
*/
CDTimerClass<SystemTimerClass> FrameTimer;
/***************************************************************************
** Tick Count global timer object.
*/
TTimerClass<SystemTimerClass> TickCount = 0;

View File

@@ -0,0 +1,46 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/_Timer.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef _TIMER_H
#define _TIMER_H
#include "stimer.h"
#include "timer.h"
extern CDTimerClass<SystemTimerClass> FrameTimer;
extern TTimerClass<SystemTimerClass> TickCount;
#endif

View File

@@ -0,0 +1,56 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/_xmouse.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef _XMOUSE_H
#define _XMOUSE_H
#include "xmouse.h"
extern Mouse * MouseCursor;
inline void Hide_Mouse(void) {MouseCursor->Hide_Mouse();}
inline void Show_Mouse(void) {MouseCursor->Show_Mouse();}
inline void Conditional_Hide_Mouse(Rect rect) {MouseCursor->Conditional_Hide_Mouse(rect);}
inline void Conditional_Show_Mouse(void) {MouseCursor->Conditional_Show_Mouse();}
inline int Get_Mouse_State(void) {return(MouseCursor->Get_Mouse_State());}
inline void Set_Mouse_Cursor(int hotx, int hoty, ShapeSet const * cursor, int shape) {MouseCursor->Set_Cursor(hotx, hoty, cursor, shape);}
inline int Get_Mouse_X(void) {return(MouseCursor->Get_Mouse_X());}
inline int Get_Mouse_Y(void) {return(MouseCursor->Get_Mouse_Y());}
#endif

View File

@@ -0,0 +1,254 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/always.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 8/28/01 3:21p $*
* *
* $Revision:: 13 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef ALWAYS_H
#define ALWAYS_H
#include <assert.h>
// Disable warning about exception handling not being enabled. It's used as part of STL - in a part of STL we don't use.
#pragma warning(disable : 4530)
/*
** Define for debug memory allocation to include __FILE__ and __LINE__ for every memory allocation.
** This helps find leaks.
*/
//#define STEVES_NEW_CATCHER
#ifdef _DEBUG
#ifdef _MSC_VER
#ifdef STEVES_NEW_CATCHER
#include <crtdbg.h>
#include <stdlib.h>
#include <malloc.h>
#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
#define _msize(p) _msize_dbg(p, _NORMAL_BLOCK)
void* __cdecl operator new(unsigned int s);
#endif //STEVES_NEW_CATCHER
#endif //_MSC_VER
#endif //_DEBUG
#ifndef _OPERATOR_NEW_DEFINED_
#define _OPERATOR_NEW_DEFINED_
extern void * __cdecl operator new (size_t size);
extern void __cdecl operator delete (void *p);
extern void * __cdecl operator new[] (size_t size);
extern void __cdecl operator delete[] (void *p);
// additional overloads to account for VC/MFC funky versions
extern void* __cdecl operator new (size_t nSize, const char *, int);
extern void __cdecl operator delete (void *, const char *, int);
extern void* __cdecl operator new[] (size_t nSize, const char *, int);
extern void __cdecl operator delete[] (void *, const char *, int);
// additional overloads for 'placement new'
//inline void* __cdecl operator new (size_t s, void *p) { return p; }
//inline void __cdecl operator delete (void *, void *p) { }
inline void* __cdecl operator new[] (size_t s, void *p) { return p; }
inline void __cdecl operator delete[] (void *, void *p) { }
#endif
#if (defined(_DEBUG) || defined(_INTERNAL))
#define MSGW3DNEW(MSG) new( MSG, 0 )
#define MSGW3DNEWARRAY(MSG) new( MSG, 0 )
#define W3DNEW new("W3D_" __FILE__, 0)
#define W3DNEWARRAY new("W3A_" __FILE__, 0)
#else
#define MSGW3DNEW(MSG) new
#define MSGW3DNEWARRAY(MSG) new
#define W3DNEW new
#define W3DNEWARRAY new
#endif
// ----------------------------------------------------------------------------
extern void* createW3DMemPool(const char *poolName, int allocationSize);
extern void* allocateFromW3DMemPool(void* p, int allocationSize);
extern void* allocateFromW3DMemPool(void* p, int allocationSize, const char* msg, int unused);
extern void freeFromW3DMemPool(void* pool, void* p);
// ----------------------------------------------------------------------------
#define W3DMPO_GLUE(ARGCLASS) \
private: \
static void* getClassMemoryPool() \
{ \
/* \
Note that this static variable will be initialized exactly once: the first time \
control flows over this section of code. This allows us to neatly resolve the \
order-of-execution problem for static variables, ensuring this is not executed \
prior to the initialization of TheMemoryPoolFactory. \
*/ \
static void* The##ARGCLASS##Pool = createW3DMemPool(#ARGCLASS, sizeof(ARGCLASS)); \
return The##ARGCLASS##Pool; \
} \
protected: \
virtual int glueEnforcer() const { return sizeof(this); } \
public: \
inline void* operator new(size_t s) { return allocateFromW3DMemPool(getClassMemoryPool(), s); } \
inline void operator delete(void *p) { freeFromW3DMemPool(getClassMemoryPool(), p); } \
inline void* operator new(size_t s, const char* msg, int unused) { return allocateFromW3DMemPool(getClassMemoryPool(), s, msg, unused); } \
inline void operator delete(void *p, const char* msg, int unused) { freeFromW3DMemPool(getClassMemoryPool(), p); } \
// ----------------------------------------------------------------------------
class W3DMPO
{
private:
static void* getClassMemoryPool()
{
assert(0); // must replace this via W3DMPO_GLUE
return 0;
}
protected:
// we never call this; it is present to cause compile errors in descendent classes
virtual int glueEnforcer() const = 0;
public:
virtual ~W3DMPO() { /* nothing */ }
};
// ----------------------------------------------------------------------------
// Jani: Intel's C++ compiler issues too many warnings in WW libraries when using warning level 4
#if defined (__ICL) // Detect Intel compiler
#pragma warning (3)
#pragma warning ( disable: 981 ) // parameters defined in unspecified order
#pragma warning ( disable: 279 ) // controlling expressaion is constant
#pragma warning ( disable: 271 ) // trailing comma is nonstandard
#pragma warning ( disable: 171 ) // invalid type conversion
#pragma warning ( disable: 1 ) // last line of file ends without a newline
#endif
// Jani: MSVC doesn't necessarily inline code with inline keyword. Using __forceinline results better inlining
// and also prints out a warning if inlining wasn't possible. __forceinline is MSVC specific.
#if defined(_MSC_VER)
#define WWINLINE __forceinline
#else
#define WWINLINE inline
#endif
/*
** Define the MIN and MAX macros.
** NOTE: Joe used to #include <minmax.h> in the various compiler header files. This
** header defines 'min' and 'max' macros which conflict with the surrender code so
** I'm relpacing all occurances of 'min' and 'max with 'MIN' and 'MAX'. For code which
** is out of our domain (e.g. Max sdk) I'm declaring template functions for 'min' and 'max'
*/
#define NOMINMAX
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
template <class T> T min(T a,T b)
{
if (a<b) {
return a;
} else {
return b;
}
}
template <class T> T max(T a,T b)
{
if (a>b) {
return a;
} else {
return b;
}
}
/*
** This includes the minimum set of compiler defines and pragmas in order to bring the
** various compilers to a common behavior such that the C&C engine will compile without
** error or warning.
*/
#if defined(__BORLANDC__)
#include "borlandc.h"
#endif
#if defined(_MSC_VER)
#include "visualc.h"
#endif
#if defined(__WATCOMC__)
#include "watcom.h"
#endif
#ifndef NULL
#define NULL 0
#endif
/**********************************************************************
** This macro serves as a general way to determine the number of elements
** within an array.
*/
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) int(sizeof(x)/sizeof(x[0]))
#endif
#ifndef size_of
#define size_of(typ,id) sizeof(((typ*)0)->id)
#endif
#endif

View File

@@ -0,0 +1,501 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /VSS_Sync/wwlib/argv.cpp 11 8/29/01 10:25p Vss_sync $ */
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Library *
* *
* $Archive:: /VSS_Sync/wwlib/argv.cpp $*
* *
* $Author:: Vss_sync $*
* *
* $Modtime:: 8/29/01 10:24p $*
* *
* $Revision:: 11 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* CurrentPos -- Create an instance to parse argv with. *
* ArgvClass::Free -- Release data allocated. *
* ArgvClass::Load_File -- Load args from a file. *
* *ArgvClass::Find_Value -- Find value of argument given prefix. *
* *ArgvClass::Get_Cur_Value -- Get value of current argugment. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "argv.h"
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ffactory.h"
#include "rawfile.h"
int ArgvClass::Argc = 0;
char *ArgvClass::Argv[MAX_ARGC];
/***********************************************************************************************
* CurrentPos -- Create an instance to parse argv with. *
* *
* INPUT: *
* bool case_sensitive - Do you want to perform a case sensitive search (stricmp)? *
* bool exact_size - Do you want string of same lenght (strncmp) ? *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/18/1999 SKB : Created. *
*=============================================================================================*/
ArgvClass::ArgvClass(bool case_sensitive, bool exact_size):
Flags(0),
LastArg(0),
CurrentPos(-1)
{
Case_Sensitive(case_sensitive);
Exact_Size(exact_size);
}
/***********************************************************************************************
* *ArgvClass::Find_Again -- Search for a string given the flags. *
* *
* INPUT: *
* const char *arg - String to search for. If NULL, LastArg will be used. *
* *
* OUTPUT: *
* const char *string found (null if not found) *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/17/1999 SKB : Created. *
*=============================================================================================*/
const char *ArgvClass::Find_Again(const char *arg)
{
if (arg) {
LastArg = arg;
} else {
arg = LastArg;
}
// Make sure user has given us something to work with here.
assert(LastArg);
CurrentPos++;
if (CurrentPos < Argc) {
if (Is_Case_Sensitive()) {
if (Is_Exact_Size()) {
// Case Sensitive, Exact Size.
for (; CurrentPos < Argc; CurrentPos++) {
if (!strcmp(arg, Argv[CurrentPos])) {
return Argv[CurrentPos];
}
}
} else {
// Case Sensitive, Match first strlen(arg).
int len = strlen(arg);
for (; CurrentPos < Argc; CurrentPos++) {
if (!strncmp(arg, Argv[CurrentPos], len)) {
return Argv[CurrentPos];
}
}
}
} else {
if (Is_Exact_Size()) {
// Note case sensitive, Exact Size.
for (; CurrentPos < Argc; CurrentPos++) {
if (!stricmp(arg, Argv[CurrentPos])) {
return Argv[CurrentPos];
}
}
} else {
// Note case sensitive, Match first strlen(arg).
int len = strlen(arg);
for (; CurrentPos < Argc; CurrentPos++) {
if (!strnicmp(arg, Argv[CurrentPos], len)) {
return Argv[CurrentPos];
}
}
}
}
}
return NULL;
}
/***********************************************************************************************
* ArgvClass::Init -- Setup the command line. *
* *
* INPUT: *
* LPSTR lpCmdLine - A string of white space seperated strings. Quotes force spaces to *
* be ignored. *
* char *fileprefix - A prefix on an arguement telling system to load postfix file name *
* as command line params. *
* *
* OUTPUT: *
* *
* WARNINGS: *
* This may be called multible times with different strings. *
* Once Argc reaches MAX_ARGC, no more will be added. *
* *
* HISTORY: *
* 06/17/1999 SKB : Created. *
* 07/15/2001 SKB : Put file arguements in the correct order they were included. *
*=============================================================================================*/
int ArgvClass::Init(char *lpCmdLine, char *fileprefix)
{
// Get pointer to command line.
char *ptr = lpCmdLine;
if (!ptr || !*ptr) {
return 0;
}
int fp_cmp_len = (fileprefix) ? strlen(fileprefix) : 0;
// Save original Argc for return.
int origargc = Argc;
while (*ptr) {
char *eos;
char save;
// Keep anything within quotes as one string.
if (*ptr == '"') {
ptr++;
eos = ptr;
// Search for next " or a null.
while (*eos && (*eos != '"')) {
eos++;
}
} else if (isspace(*ptr)) {
ptr++;
continue;
} else {
eos = ptr + 1;
// search for next white space or null.
while (*eos && !isspace(*eos)) {
eos++;
}
}
// Null out end of string so string function work.
// Save the end to restore later.
save = *eos;
*eos = 0;
bool was_file = false;
// See if we are to load a file with parameters in it.
if (fp_cmp_len && !strncmp(fileprefix, ptr, fp_cmp_len)) {
ptr += fp_cmp_len;
if (*ptr) {
was_file = Load_File(ptr);
}
}
// If it was not the file or the load failed...then add parameter.
if (!was_file) {
// Copy string over and continue.
Argv[Argc] = strdup(ptr);
Argc++;
}
// If save is null, then we are at the end and we can bail out.
if (!save) break;
// resore whitespace.
*eos = save;
ptr = eos + 1;
}
// Return number of params read in.
return(Argc - origargc);
}
/***********************************************************************************************
* ArgvClass::Load_File -- Load args from a file. *
* *
* INPUT: *
* const char *fname - file to load. *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/18/1999 SKB : Created. *
*=============================================================================================*/
bool ArgvClass::Load_File(const char *fname)
{
FILE *fp = fopen(fname, "r");
if (fp) {
while (Argc < MAX_ARGC) {
const int maxstrlen = 255;
char string[maxstrlen + 1];
// Get next line in file.
if (!fgets(string, maxstrlen - 1, fp)) {
break;
}
// Check for comments.
if ((*string != '#') && (*string != ';')) {
// Make sure null terminated.
string[maxstrlen - 1] = '\0';
char *ptr = string + (strlen(string) - 1);
while (*ptr <= ' ') {
*ptr = 0;
// Is it just a blank line?
if (ptr == string) {
break;
}
ptr--;
}
// If there is anyting in the string. (NAK: old code used to fail for 1 char options)
if (strlen(string)) {
Argv[Argc] = strdup(string);
Argc++;
}
}
}
fclose(fp);
return(true);
}
return(false);
}
/***********************************************************************************************
* ArgvClass::Free -- Release data allocated. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/18/1999 SKB : Created. *
*=============================================================================================*/
void ArgvClass::Free()
{
for (int lp = 0; lp < Argc; lp++) {
free(Argv[lp]);
Argv[lp] = 0;
}
Argc = -1;
}
/***********************************************************************************************
* *ArgvClass::Find_Value -- Find value of argument given prefix. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/23/1999 SKB : Created. *
*=============================================================================================*/
const char *ArgvClass::Find_Value(const char *arg)
{
if (arg && *arg) {
const char *ptr = Find(arg);
if (ptr) {
return(Get_Cur_Value(strlen(arg)));
}
}
return(NULL);
}
/***********************************************************************************************
* *ArgvClass::Get_Cur_Value -- Get value of current argugment. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/23/1999 SKB : Created. *
* 06/25/2001 SKB : add flag user can check to see if value was extracted from next location.*
*=============================================================================================*/
const char *ArgvClass::Get_Cur_Value(unsigned prefixlen, bool * val_in_next)
{
if (val_in_next) *val_in_next = false;
if (CurrentPos < 0) {
return NULL;
}
char *ptr = Argv[CurrentPos];
if (strlen(ptr) < prefixlen) {
return(NULL);
}
ptr += prefixlen;
// Look for non white space (or eol).
while (*ptr && !isgraph(*ptr)) {
ptr++;
}
if (*ptr) {
return ptr;
}
// Goto next line to handle '-P data' case on command line.
ptr = Argv[CurrentPos + 1];
if (!ptr) {
return NULL;
}
while (*ptr) {
if (isgraph(*ptr)) {
if (val_in_next) *val_in_next = true;
return ptr;
}
ptr++;
}
return (NULL);
}
/***********************************************************************************************
* void ArgvClass::Update_Value -- Add/Replace a value *
* *
* INPUT: *
* attrib = cmd line attrib to add/replace *
* value = new value for attrib *
* *
* OUTPUT: *
* *
* WARNINGS: Not Tested! *
* *
* HISTORY: *
* 12/13/1999 NAK : Created. *
*=============================================================================================*/
void ArgvClass::Update_Value(const char *attrib, const char *value)
{
if ((Find_Value(attrib))!=NULL)
{
if (((CurrentPos+1) < Argc) && (Argv[CurrentPos+1][0] != '-')) // update old value
{
free(Argv[CurrentPos+1]);
Argv[CurrentPos+1]=strdup(value);
}
else // add new value
{
// shift vals down to make room
memmove(&(Argv[CurrentPos+2]),&(Argv[CurrentPos+1]),sizeof(char *) * (MAX_ARGC-CurrentPos-2));
Argv[CurrentPos+1]=strdup(value);
Argc++;
}
}
else // just add the new stuff
Add_Value(attrib, value);
}
/***********************************************************************************************
* void ArgvClass::Add_Value -- Add a value *
* *
* INPUT: *
* attrib = thing to add *
* value = new optional value *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 12/13/1999 NAK : Created. *
*=============================================================================================*/
void ArgvClass::Add_Value(const char *attrib, const char *value)
{
if (attrib)
{
Argv[Argc]=strdup(attrib);
Argc++;
if (value)
{
Argv[Argc]=strdup(value);
Argc++;
}
}
}
/***********************************************************************************************
* bool ArgvClass::Remove_Value -- Remove a value *
* *
* INPUT: *
* attrib = thing to remove *
* *
* OUTPUT: *
* *
* WARNINGS: *
* THIS CONTAINS A POTENTIAL BUG - I don't want to fix it because it might be a desired *
* behavior. Given: *
* Argv[0] = "-i test" "*.txt" as values in Argv, *
* calling Remove_Value("-i") will remove *.txt as well. *
* *
* HISTORY: *
* 12/13/1999 NAK : Created. *
* 06/25/2001 SKB : WARNINGS message *
*=============================================================================================*/
bool ArgvClass::Remove_Value(const char *attrib)
{
int removeCount=1;
if ((Find_Value(attrib))!=NULL)
{
free(Argv[CurrentPos]);
if (((CurrentPos+1) < Argc)&&(Argv[CurrentPos+1][0]!='-')) // value for this arg
{
free(Argv[CurrentPos+1]);
removeCount=2;
}
memmove(&(Argv[CurrentPos]),&(Argv[CurrentPos+removeCount]),sizeof(char *) * (MAX_ARGC-CurrentPos-removeCount));
Argc-=removeCount;
return(true);
}
return(false);
}

View File

@@ -0,0 +1,166 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /VSS_Sync/wwlib/argv.h 7 8/29/01 10:25p Vss_sync $ */
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Library *
* *
* $Archive:: /VSS_Sync/wwlib/argv.h $*
* *
* $Author:: Vss_sync $*
* *
* $Modtime:: 8/29/01 10:24p $*
* *
* $Revision:: 7 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef ARGV_H
#define ARGV_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifdef _UNIX
#include "osdep.h"
#endif
// Used to parse command line that is passed into WinMain.
// It also has the ability to load a file with values to append to the command line.
// Normally in WinMain() there would be a call Argv::Init(lpCmdLine, fileprefix).
// Once this is done, user can create an ArgvClass object (say argv) then argv.Find() can be called.
// If there is a arguement <fileprefix><fname> (for example @file.arg) then the fname is loaded up,
// parsed, and put into the command line. The format of the parameter file is as follows:
// 1. a semicolon (;) at the start of the line is a comment and will be ignored.
// 2. Each line is a seperate parameter. This enables white space to be embeded.
// In typical Argv implementation, the first argument is the name of the application. This
// is not the case with this.
class ArgvClass
{
public:
// As passed into WinMain.
// Should be called before any objects are created.
// This can be called multible times.
static int Init(char *lpCmdLine, char *fileprefix = "@");
static bool Load_File(const char *fname);
static void Free();
// Create an object that can search the args.
ArgvClass(bool case_sensitive = false, bool exact_size = false);
~ArgvClass() {}
// Functions to find a value.
const char *Find(const char *arg) {
CurrentPos = -1;
return(Find_Again(arg));
}
// If NULL passed, original string will be used.
const char *Find_Again(const char *arg = 0L);
// Return pointer to data after 'arg'.
// White space is skipped.
// So give a line '-Pdata' or '-P data' and arg==-P, 'data' would be returned in
// both cases.
const char *Find_Value(const char *arg);
// Similar to Find_Value, only gets value of current arg. User needs to pass
// in the strlen of the prefix (2 for -P example above) to skip.
// Val_in_next is set if the value was extracted from the next Argv,
// this way the programmer can know if he needs to call an extra Next().
const char *Get_Cur_Value(unsigned prefixlen, bool * val_in_next = 0);
// Update an existing attrib to use this new value
void Update_Value(const char *attrib, const char *value);
// Add a new attrib value pair (or just an option)
void Add_Value(const char *attrib, const char *value=NULL);
// Remove an option (and its value)
bool Remove_Value(const char *attrib);
// First parameter.
const char *First() {
CurrentPos = 0;
return(Argv[0]);
}
// Next works after a Find() call also.
const char *Next() {
CurrentPos++;
if (CurrentPos < Argc) {
return(Argv[CurrentPos]);
}
return(0L);
}
// Can be called so Next() will return First()...
void Reset() {
CurrentPos = -1;
}
const char *Cur() {
if (CurrentPos < Argc) {
return(Argv[CurrentPos]);
}
return(0L);
}
// Allow user to change states.
void Case_Sensitive(bool on) {Flag.CaseSensitive = on;}
bool Is_Case_Sensitive() {return (Flag.CaseSensitive);}
// Allow user to change states.
void Exact_Size(bool on) {Flag.ExactSize = on;}
bool Is_Exact_Size() {return (Flag.ExactSize);}
protected:
// Current position to be used when Next or Find_Again are called.
int CurrentPos;
// Last arg that we are searching for.
const char *LastArg;
union {
unsigned Flags;
struct {
unsigned CaseSensitive:1;
unsigned ExactSize:1;
} Flag;
};
// Number of args.
static int Argc;
// The actual data.
enum {MAX_ARGC = 256};
static char *Argv[MAX_ARGC];
};
#endif

View File

@@ -0,0 +1,164 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/B64PIPE.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Base64Pipe::Flush -- Flushes the final pending data through the pipe. *
* Base64Pipe::Put -- Processes a block of data through the pipe. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "b64pipe.h"
#include "base64.h"
#include <string.h>
/***********************************************************************************************
* Base64Pipe::Put -- Processes a block of data through the pipe. *
* *
* This will take the data submitted and either Base64 encode or decode it (as specified *
* in the pipe's constructor). The nature of Base64 encoding means that the data will *
* grow 30% in size when encoding and decrease by a like amount when decoding. *
* *
* INPUT: source -- Pointer to the data to be translated. *
* *
* length -- The number of bytes to translate. *
* *
* OUTPUT: Returns with the actual number of bytes output at the far distant final end of *
* the pipe chain. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/03/1996 JLB : Created. *
*=============================================================================================*/
int Base64Pipe::Put(void const * source, int slen)
{
if (source == NULL || slen < 1) {
return(Pipe::Put(source, slen));
}
int total = 0;
char * from;
int fromsize;
char * to;
int tosize;
if (Control == ENCODE) {
from = PBuffer;
fromsize = sizeof(PBuffer);
to = CBuffer;
tosize = sizeof(CBuffer);
} else {
from = CBuffer;
fromsize = sizeof(CBuffer);
to = PBuffer;
tosize = sizeof(PBuffer);
}
if (Counter > 0) {
int len = (slen < (fromsize-Counter)) ? slen : (fromsize-Counter);
memmove(&from[Counter], source, len);
Counter += len;
slen -= len;
source = ((char *)source) + len;
if (Counter == fromsize) {
int outcount;
if (Control == ENCODE) {
outcount = Base64_Encode(from, fromsize, to, tosize);
} else {
outcount = Base64_Decode(from, fromsize, to, tosize);
}
total += Pipe::Put(to, outcount);
Counter = 0;
}
}
while (slen >= fromsize) {
int outcount;
if (Control == ENCODE) {
outcount = Base64_Encode(source, fromsize, to, tosize);
} else {
outcount = Base64_Decode(source, fromsize, to, tosize);
}
source = ((char *)source) + fromsize;
total += Pipe::Put(to, outcount);
slen -= fromsize;
}
if (slen > 0) {
memmove(from, source, slen);
Counter = slen;
}
return(total);
}
/***********************************************************************************************
* Base64Pipe::Flush -- Flushes the final pending data through the pipe. *
* *
* If there is any non-processed data accumulated in the holding buffer (quite likely when *
* encoding), then it will be processed and flushed out the end of the pipe. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with the number of bytes output at the far distant final end of the pipe *
* chain. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/03/1996 JLB : Created. *
*=============================================================================================*/
int Base64Pipe::Flush(void)
{
int len = 0;
if (Counter) {
if (Control == ENCODE) {
int chars = Base64_Encode(PBuffer, Counter, CBuffer, sizeof(CBuffer));
len += Pipe::Put(CBuffer, chars);
} else {
int chars = Base64_Decode(CBuffer, Counter, PBuffer, sizeof(PBuffer));
len += Pipe::Put(PBuffer, chars);
}
Counter = 0;
}
len += Pipe::Flush();
return(len);
}

View File

@@ -0,0 +1,93 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/b64pipe.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:58a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef B64PIPE_H
#define B64PIPE_H
#include "pipe.h"
/*
** This class performs Base64 encoding/decoding to the data that is piped through. Note that
** encoded data will grow in size by about 30%. The reverse occurs when decoding.
*/
class Base64Pipe : public Pipe
{
public:
typedef enum CodeControl {
ENCODE,
DECODE
} CodeControl;
Base64Pipe(CodeControl control) : Control(control), Counter(0) {}
virtual int Flush(void);
virtual int Put(void const * source, int slen);
private:
/*
** Indicates if this is for encoding or decoding of Base64 data.
*/
CodeControl Control;
/*
** The counter of the number of accumulated bytes pending for processing.
*/
int Counter;
/*
** Buffer that holds the Base64 coded bytes. This will be the staging buffer if
** this is for a decoding process. Otherwise, it will be used as a scratch buffer.
*/
char CBuffer[4];
/*
** Buffer that holds the plain bytes. This will be the staging buffer if this
** is for an encoding process. Otherwise, it will be used as a scratch buffer.
*/
char PBuffer[3];
/*
** Explicitly disable the copy constructor and the assignment operator.
*/
Base64Pipe(Base64Pipe & rvalue);
Base64Pipe & operator = (Base64Pipe const & pipe);
};
#endif

View File

@@ -0,0 +1,116 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/B64STRAW.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Base64Straw::Get -- Fetch data and convert it to/from base 64 encoding. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "b64straw.h"
#include "base64.h"
#include <string.h>
/***********************************************************************************************
* Base64Straw::Get -- Fetch data and convert it to/from base 64 encoding. *
* *
* This routine will fetch the number of bytes requested and perform any conversion as *
* necessary upon the data. The nature of Base 64 encoding means that the data will *
* increase in size by 30% when encoding and decrease in like manner when decoding. *
* *
* INPUT: source -- The buffer to hold the processed data. *
* *
* length -- The number of bytes requested. *
* *
* OUTPUT: Returns with the number of bytes stored into the buffer. If the number is less *
* than requested, then this indicates that the data stream has been exhausted. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/03/1996 JLB : Created. *
*=============================================================================================*/
int Base64Straw::Get(void * source, int slen)
{
int total = 0;
char * from;
int fromsize;
char * to;
int tosize;
if (Control == ENCODE) {
from = PBuffer;
fromsize = sizeof(PBuffer);
to = CBuffer;
tosize = sizeof(CBuffer);
} else {
from = CBuffer;
fromsize = sizeof(CBuffer);
to = PBuffer;
tosize = sizeof(PBuffer);
}
/*
** Process the byte request in code blocks until there are either
** no more source bytes available or the request has been fulfilled.
*/
while (slen > 0) {
/*
** Transfer any processed bytes available to the request buffer.
*/
if (Counter > 0) {
int len = (slen < Counter) ? slen : Counter;
memmove(source, &to[tosize-Counter], len);
Counter -= len;
slen -= len;
source = ((char *)source) + len;
total += len;
}
if (slen == 0) break;
/*
** More bytes are needed, so fetch and process another base 64 block.
*/
int incount = Straw::Get(from, fromsize);
if (Control == ENCODE) {
Counter = Base64_Encode(from, incount, to, tosize);
} else {
Counter = Base64_Decode(from, incount, to, tosize);
}
if (Counter == 0) break;
}
return(total);
}

View File

@@ -0,0 +1,92 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/b64straw.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:58a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef B64STRAW_H
#define B64STRAW_H
#include "straw.h"
/*
** Performs Base 64 encoding/decoding on the data that is drawn through the straw. Note that
** encoding increases the data size by about 30%. The reverse occurs when decoding.
*/
class Base64Straw : public Straw
{
public:
typedef enum CodeControl {
ENCODE,
DECODE
} CodeControl;
Base64Straw(CodeControl control) : Control(control), Counter(0) {}
virtual int Get(void * source, int slen);
private:
/*
** Indicates if this is for encoding or decoding of Base64 data.
*/
CodeControl Control;
/*
** The counter of the number of accumulated bytes pending for processing.
*/
int Counter;
/*
** Buffer that holds the Base64 coded bytes. This will be the staging buffer if
** this is for a decoding process. Otherwise, it will be used as a scratch buffer.
*/
char CBuffer[4];
/*
** Buffer that holds the plain bytes. This will be the staging buffer if this
** is for an encoding process. Otherwise, it will be used as a scratch buffer.
*/
char PBuffer[3];
/*
** Explicitly disable the copy constructor and the assignment operator.
*/
Base64Straw(Base64Straw & rvalue);
Base64Straw & operator = (Base64Straw const & pipe);
};
#endif

View File

@@ -0,0 +1,436 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/base64.cpp $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 5/04/01 8:08p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Base64_Decode -- Decodes Base 64 data into its original data form. *
* Base64_Encode -- Encode data into Base 64 format. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "base64.h"
//#include <stddef.h>
/*
** This is the magic padding character used to fill out the encoded data to a multiple of
** 4 characters even though the source data is less than necessary to accomplish this.
** The pad character lets the decoder know of this condition and it will compensate
** accordingly.
*/
static char const * const _pad = "=";
/*
** This encoder translation table will convert a 6 bit number into an ASCII character.
*/
static char const * const _encoder = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
** The decoder translation table takes an ASCII character and converts it into a
** 6 bit number.
*/
#define BAD 0xFE // Ignore this character in source data.
#define END 0xFF // Signifies premature end of input data.
static unsigned char const _decoder[256] = {
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,62,BAD,BAD,BAD,63,
52,53,54,55,56,57,58,59,60,61,BAD,BAD,BAD,END,BAD,BAD,
BAD,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
15,16,17,18,19,20,21,22,23,24,25,BAD,BAD,BAD,BAD,BAD,
BAD,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,51,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,
BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD,BAD
};
int const PacketChars = 4;
/*
** The packet type is used to construct and disect the Base64 data blocks. The data
** consists of three source data bytes mapped onto four 6 bit Base64 code elements.
*/
typedef union {
struct {
#ifdef BIG_ENDIAN
unsigned char C1;
unsigned char C2;
unsigned char C3;
#else
unsigned char C3;
unsigned char C2;
unsigned char C1;
#endif
unsigned char pad;
} Char;
struct {
#ifdef BIG_ENDIAN
unsigned O1:6;
unsigned O2:6;
unsigned O3:6;
unsigned O4:6;
#else
unsigned O4:6;
unsigned O3:6;
unsigned O2:6;
unsigned O1:6;
#endif
unsigned pad:8;
} SubCode;
unsigned int Raw;
} PacketType;
/***********************************************************************************************
* Base64_Encode -- Encode data into Base 64 format. *
* *
* This will take an arbitrary length of source data and transform it into base 64 format *
* data. Base 64 format has the property of being very portable across text editors and *
* country character encoding schemes. As such it is ideal for e-mail. Note that the output *
* data will be about 33% larger than the source. *
* *
* INPUT: source -- Pointer to the source data to convert. *
* *
* slen -- The number of bytes to encode. *
* *
* dest -- Pointer to the destination buffer that will hold the encoded data. *
* *
* dlen -- The size of the destination buffer. *
* *
* OUTPUT: Returns with the number of bytes stored into the destination buffer. *
* *
* WARNINGS: Be sure that the destination buffer is big enough to hold the encoded output. *
* *
* HISTORY: *
* 07/06/1996 JLB : Created. *
*=============================================================================================*/
int Base64_Encode(void const * source, int slen, void * dest, int dlen)
{
/*
** Check the parameters for legality.
*/
if (source == NULL || slen == 0 || dest == NULL || dlen == 0) {
return(0);
}
/*
** Process the source data in blocks of three bytes. Fewer than three bytes
** results in special padding output characters (automatically discarded
** during the decode process).
*/
int total = 0;
unsigned char const * sptr = (unsigned char const *)source;
unsigned char * dptr = (unsigned char *)dest;
while (slen > 0 && dlen >= PacketChars) {
/*
** Fetch 24 bits of source data.
*/
PacketType packet;
int pad = 0;
packet.Raw = 0;
packet.Char.C1 = *sptr++;
slen--;
if (slen) {
packet.Char.C2 = *sptr++;
slen--;
} else {
pad++;
}
if (slen) {
packet.Char.C3 = *sptr++;
slen--;
} else {
pad++;
}
/*
** Translate and write 4 characters of Base64 data. Pad with pad
** characters if there is insufficient source data for a full packet.
*/
*dptr++ = _encoder[packet.SubCode.O1];
*dptr++ = _encoder[packet.SubCode.O2];
if (pad < 2) {
*dptr++ = _encoder[packet.SubCode.O3];
} else {
*dptr++ = _pad[0];
}
if (pad < 1) {
*dptr++ = _encoder[packet.SubCode.O4];
} else {
*dptr++ = _pad[0];
}
dlen -= PacketChars;
total += PacketChars;
}
/*
** Add a trailing null as a courtesy measure.
*/
if (dlen > 0) {
*dptr = '\0';
}
/*
** Return with the total number of characters in the output buffer.
*/
return(total);
}
/***********************************************************************************************
* Base64_Decode -- Decodes Base 64 data into its original data form. *
* *
* Use this routine to decode base 64 data back into the original data. A property of this *
* decode process is that unrecognized input characters are ignored. This allows mangled *
* source (filled with line breaks or spaces) to be correctly decoded. The decode process *
* terminates when the end of the source data has been reached or the special end of data *
* marker is encountered. *
* *
* INPUT: source -- Pointer to the source data to decode. *
* *
* slen -- The number of bytes in the source data buffer. *
* *
* dest -- Pointer to the destination buffer to be filled with the decoded data. *
* *
* dlen -- The maximum size of the destination buffer. *
* *
* OUTPUT: Returns with the number of bytes stored into the destination buffer. This will *
* always be less than the number of source bytes (usually by about 33%). *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/06/1996 JLB : Created. *
*=============================================================================================*/
int Base64_Decode(void const * source, int slen, void * dest, int dlen)
{
/*
** Check the parameters for legality.
*/
if (source == NULL || slen == 0 || dest == NULL || dlen == 0) {
return(0);
}
int total = 0;
unsigned char const * sptr = (unsigned char const *)source;
unsigned char * dptr = (unsigned char *)dest;
while (slen > 0 && dlen > 0) {
PacketType packet;
packet.Raw = 0;
/*
** Process input until a full packet has been accumulated or the
** source is exhausted.
*/
int pcount = 0;
while (pcount < PacketChars && slen > 0) {
unsigned char c = *sptr++;
slen--;
unsigned char code = _decoder[c];
/*
** An unrecognized character is skipped.
*/
if (code == BAD) continue;
/*
** The "=" character signifies the end of data regardless of what
** the source buffer length value may be.
*/
if (code == END) {
slen = 0;
break;
}
/*
** A valid Base64 character was found so add it to the packet
** data.
*/
switch (pcount) {
case 0:
packet.SubCode.O1 = code;
break;
case 1:
packet.SubCode.O2 = code;
break;
case 2:
packet.SubCode.O3 = code;
break;
case 3:
packet.SubCode.O4 = code;
break;
}
pcount++;
}
/*
** A packet block is ready for output into the destination buffer.
*/
*dptr++ = packet.Char.C1;
dlen--;
total++;
if (dlen > 0 && pcount > 2) {
*dptr++ = packet.Char.C2;
dlen--;
total++;
}
if (dlen > 0 && pcount > 3) {
*dptr++ = packet.Char.C3;
dlen--;
total++;
}
}
/*
** Return with the total number of characters decoded into the
** output buffer.
*/
return(total);
}
/*
Base64 Content-Transfer-Encoding
The Base64 Content-Transfer-Encoding is designed to represent arbitrary
sequences of octets in a form that need not be humanly readable. The encoding
and decoding algorithms are simple, but the encoded data are consistently
only about 33 percent larger than the unencoded data. This encoding is
virtually identical to the one used in Privacy Enhanced Mail (PEM)
applications, as defined in RFC 1421. The base64 encoding is adapted from
RFC 1421, with one change: base64 eliminates the "*" mechanism for embedded
clear text.
A 65-character subset of US-ASCII is used, enabling 6 bits to be represented
per printable character. (The extra 65th character, "=", is used to signify a
special processing function.)
NOTE:
This subset has the important property that it is represented identically
in all versions of ISO 646, including US ASCII, and all characters in the
subset are also represented identically in all versions of EBCDIC. Other
popular encodings, such as the encoding used by the uuencode utility and
the base85 encoding specified as part of Level 2 PostScript, do not share
these properties, and thus do not fulfill the portability requirements a
binary transport encoding for mail must meet.
The encoding process represents 24-bit groups of input bits as output strings
of 4 encoded characters. Proceeding from left to right, a 24-bit input group is
formed by concatenating 3 8-bit input groups. These 24 bits are then treated as
4 concatenated 6-bit groups, each of which is translated into a single digit in
the base64 alphabet. When encoding a bit stream via the base64 encoding, the
bit stream must be presumed to be ordered with the most-significant-bit first.
That is, the first bit in the stream will be the high-order bit in the first
byte, and the eighth bit will be the low-order bit in the first byte, and so on.
Each 6-bit group is used as an index into an array of 64 printable characters.
The character referenced by the index is placed in the output string. These
characters, identified in Table 1, below, are selected so as to be universally
representable, and the set excludes characters with particular significance to
SMTP (e.g., ".", CR, LF) and to the encapsulation boundaries defined in this
document (e.g., "-").
Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
The output stream (encoded bytes) must be represented in lines of no more than
76 characters each. All line breaks or other characters not found in Table 1
must be ignored by decoding software. In base64 data, characters other than
those in Table 1, line breaks, and other white space probably indicate a
transmission error, about which a warning message or even a message rejection
might be appropriate under some circumstances.
Special processing is performed if fewer than 24 bits are available at the end
of the data being encoded. A full encoding quantum is always completed at the
end of a body. When fewer than 24 input bits are available in an input group,
zero bits are added (on the right) to form an integral number of 6-bit groups.
Padding at the end of the data is performed using the '=' character. Since all
base64 input is an integral number of octets, only the following cases can
arise: (1) the final quantum of encoding input is an integral multiple of 24
bits; here, the final unit of encoded output will be an integral multiple of 4
characters with no "=" padding, (2) the final quantum of encoding input is
exactly 8 bits; here, the final unit of encoded output will be two characters
followed by two "=" padding characters, or (3) the final quantum of encoding
input is exactly 16 bits; here, the final unit of encoded output will be three
characters followed by one "=" padding character.
Because it is used only for padding at the end of the data, the occurrence of
any '=' characters may be taken as evidence that the end of the data has been
reached (without truncation in transit). No such assurance is possible,
however, when the number of octets transmitted was a multiple of three.
Any characters outside of the base64 alphabet are to be ignored in
base64-encoded data. The same applies to any illegal sequence of characters in
the base64 encoding, such as "====="
Care must be taken to use the proper octets for line breaks if base64 encoding
is applied directly to text material that has not been converted to canonical
form. In particular, text line breaks must be converted into CRLF sequences
prior to base64 encoding. The important thing to note is that this may be done
directly by the encoder rather than in a prior canonicalization step in some
implementations.
NOTE:
There is no need to worry about quoting apparent encapsulation boundaries
within base64-encoded parts of multipart entities because no hyphen
characters are used in the base64 encoding.
*/

View File

@@ -0,0 +1,41 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/base64.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:58a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
int Base64_Encode(void const * source, int slen, void * dest, int dlen);
int Base64_Decode(void const * source, int slen, void * dest, int dlen);

View File

@@ -0,0 +1,96 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/BFIOFILE.H $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BFIOFILE_H
#define BFIOFILE_H
#include "rawfile.h"
/*
** This derivation of the raw file class handles buffering the input/output in order to
** achieve greater speed. The buffering is not active by default. It must be activated
** by setting the appropriate buffer through the Cache() function.
*/
class BufferIOFileClass : public RawFileClass
{
typedef RawFileClass BASECLASS;
public:
BufferIOFileClass(char const * filename);
BufferIOFileClass(void);
virtual ~BufferIOFileClass(void);
bool Cache( long size=0, void * ptr=NULL);
void Free( void);
bool Commit( void);
virtual char const * Set_Name(char const * filename);
virtual bool Is_Available(int forced=false);
virtual bool Is_Open(void) const;
virtual int Open(char const * filename, int rights=READ);
virtual int Open(int rights=READ);
virtual int Read(void * buffer, int size);
virtual int Seek(int pos, int dir=SEEK_CUR);
virtual int Size(void);
virtual int Write(void const * buffer, int size);
virtual void Close(void);
enum {MINIMUM_BUFFER_SIZE=1024};
private:
bool IsAllocated;
bool IsOpen;
bool IsDiskOpen;
bool IsCached;
bool IsChanged;
bool UseBuffer;
int BufferRights;
void *Buffer;
long BufferSize;
long BufferPos;
long BufferFilePos;
long BufferChangeBeg;
long BufferChangeEnd;
long FileSize;
long FilePos;
long TrueFileStart;
};
#endif

View File

@@ -0,0 +1,319 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project name : Buccaneer Bay *
* *
* File name : Binary_Heap.h *
* *
* Programmer : Mike Lytle *
* *
* Start date : 6/25/99 *
* *
* Last update : 6/25/99 *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BINARY_HEAP_CLASS_H
#define BINARY_HEAP_CLASS_H
/*=============================================================================================*/
// Includes.
/*=============================================================================================*/
#include <assert.h>
#include "bittype.h"
/*=============================================================================================*/
// Defines.
/*=============================================================================================*/
/*=============================================================================================*/
// Class declarations.
/*=============================================================================================*/
// WARNING!
// Any class used as an element of a heap for BinaryHeapClass must inherit HeapNodeClass.
template <class Key_Type>
class HeapNodeClass
{
public:
virtual uint32 Get_Heap_Location (void) const = 0;
virtual void Set_Heap_Location (uint32 location) = 0;
// This is pure virtual so that any type of key can be used as long as it uses the comparison operators.
virtual Key_Type Heap_Key (void) const = 0;
};
// WARNING!
// To reduce the number of compares, element [0] is a sentinel. It's key value must be the smallest or NULL.
// Keeps track of pointers to objects.
template <class Key_Type>
class BinaryHeapClass
{
public:
// This constructor uses elements that have already been allocated.
BinaryHeapClass(HeapNodeClass<Key_Type> **allocated_list, unsigned int max_number_of_elements)
{
assert(allocated_list);
assert(max_number_of_elements > 0);
Elements = allocated_list;
Max_Number_Of_Elements = max_number_of_elements;
Number_Of_Elements = 0;
Own_Array = false;
}
// This constructor allocates its own array of nodes
BinaryHeapClass(unsigned int max_number_of_elements)
: Max_Number_Of_Elements (max_number_of_elements),
Number_Of_Elements (0),
Elements (NULL),
Own_Array (false)
{
Resize_Array (max_number_of_elements);
}
// The destructor simply ensures the array is freed (if needs be)
~BinaryHeapClass ()
{
Release_Array ();
}
// Reset all entries in the array to NULL
void Flush_Array (void)
{
::memset (Elements, NULL, sizeof (HeapNodeClass<Key_Type> *) * Max_Number_Of_Elements);
Number_Of_Elements = 0;
}
// Reallocate an array large enough to hold the elements
void Resize_Array (unsigned int new_size)
{
// Start fresh
Release_Array ();
// Reallocate
Elements = W3DNEWARRAY HeapNodeClass<Key_Type> *[new_size];
Max_Number_Of_Elements = new_size;
Number_Of_Elements = 0;
Own_Array = true;
// Initialize to NULL
::memset (Elements, NULL, sizeof (HeapNodeClass<Key_Type> *) * new_size);
return ;
}
void Release_Array (void)
{
if (Own_Array) {
delete [] Elements;
Elements = NULL;
Number_Of_Elements = 0;
Max_Number_Of_Elements = 0;
}
Own_Array = false;
return ;
}
// Return the current number of elements.
unsigned int Get_Number_Of_Elements()
{
return (Number_Of_Elements);
}
// Return the maximum number of elements.
unsigned int Get_Max_Number_Of_Elements (void)
{
return (Max_Number_Of_Elements);
}
// Return a pointer to a node in the tree
HeapNodeClass<Key_Type> *Peek_Node (unsigned int location)
{
return Elements[location];
}
// Insert an element into the tree.
void Insert(HeapNodeClass<Key_Type> *node)
{
// Increment the number of elements in the heap.
unsigned int i = ++Number_Of_Elements;
// Doesn't handle the case of adding more elements than there is memory for.
assert(Number_Of_Elements < Max_Number_Of_Elements);
// Find the elements's place in the tree. Remember: the smallest element is the root.
while (Greater_Than(Elements[i / 2], node))
{
Elements[i] = Elements[i / 2];
Elements[i]->Set_Heap_Location(i);
i /= 2;
}
Elements[i] = node;
Elements[i]->Set_Heap_Location(i);
}
// Move the element up in the tree if necessary. Use this if the key value becomes smaller when it is
// already in the heap.
void Percolate_Up(unsigned int location)
{
assert(location < Max_Number_Of_Elements);
unsigned int i = location;
HeapNodeClass<Key_Type> *node = Elements[i];
// Find the elements's place in the tree. Remember: the smallest element is the root.
while (Greater_Than(Elements[i / 2], node))
{
Elements[i] = Elements[i / 2];
Elements[i]->Set_Heap_Location(i);
i /= 2;
}
Elements[i] = node;
Elements[i]->Set_Heap_Location(i);
}
// Take the smallest element out of the tree and reorder
HeapNodeClass<Key_Type>* Remove_Min (void)
{
unsigned int child;
HeapNodeClass<Key_Type>* last_element;
HeapNodeClass<Key_Type>* min_element;
if (Number_Of_Elements == 0) {
return NULL;
}
assert(Number_Of_Elements > 0);
assert(Elements);
// The smallest element is always at this position.
min_element = Elements[1];
if (min_element != NULL) {
min_element->Set_Heap_Location (0);
}
last_element = Elements[Number_Of_Elements];
// Decrement the number of elements in the tree.
Number_Of_Elements--;
for (unsigned int i = 1; (i * 2) <= Number_Of_Elements; i = child)
{
// Find a smaller child.
child = i * 2;
if ((child != Number_Of_Elements) && (Less_Than(Elements[child + 1], Elements[child])))
{
child++;
}
// Percolate down one level.
if (Greater_Than(last_element, Elements[child]))
{
Elements[i] = Elements[child];
Elements[i]->Set_Heap_Location(i);
}
else
{
break;
}
}
Elements[i] = last_element;
Elements[i]->Set_Heap_Location(i);
return (min_element);
}
private:
bool Less_Than(HeapNodeClass<Key_Type> *op1, HeapNodeClass<Key_Type> *op2)
{
if (op1 == 0)
{
return (true);
}
if (op2 == 0)
{
return (false);
}
return (op1->Heap_Key() < op2->Heap_Key());
}
bool Less_Than_Equal(HeapNodeClass<Key_Type> *op1, HeapNodeClass<Key_Type> *op2)
{
if (op1 == 0)
{
return (true);
}
if (op2 == 0)
{
return (false);
}
return (op1->Heap_Key() <= op2->Heap_Key());
}
bool Greater_Than(HeapNodeClass<Key_Type> *op1, HeapNodeClass<Key_Type> *op2)
{
if (op1 == 0)
{
return (false);
}
if (op2 == 0)
{
return (true);
}
return (op1->Heap_Key() > op2->Heap_Key());
}
private:
// The list of elements.
HeapNodeClass<Key_Type> **Elements;
// The number of allocated elements.
unsigned int Max_Number_Of_Elements;
// Current number of elements in the tree.
unsigned int Number_Of_Elements;
// Flag to indicate who owns the memory for the
// binary tree.
bool Own_Array;
};
#endif //BINARY_HEAP_CLASS_H

View File

@@ -0,0 +1,66 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /G/wwlib/bittype.h 4 4/02/99 1:37p Eric_c $ */
/***************************************************************************
*** Confidential - Westwood Studios ***
***************************************************************************
* *
* Project Name : Voxel Technology *
* *
* File Name : BITTYPE.H *
* *
* Programmer : Greg Hjelstrom *
* *
* Start Date : 02/24/97 *
* *
* Last Update : February 24, 1997 [GH] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef BITTYPE_H
#define BITTYPE_H
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
typedef unsigned int uint;
typedef signed char sint8;
typedef signed short sint16;
typedef signed long sint32;
typedef signed int sint;
typedef float float32;
typedef double float64;
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef int BOOL;
typedef unsigned short USHORT;
typedef const char * LPCSTR;
typedef unsigned int UINT;
typedef unsigned long ULONG;
#endif //BITTYPE_H

View File

@@ -0,0 +1,415 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/blit.cpp $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/15/99 10:13a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Bit_Blit -- Blit a block of pixels to the destination surface. *
* Bit_Blit -- Blits data to a surface w/ clipping. *
* Buffer_Size -- Determines size of buffer for given dimensions. *
* From_Buffer -- Copy graphic data from a buffer to a surface. *
* RLE_Blit -- Blits RLE compressed data without extra clipping. *
* RLE_Blit -- Blits a rectangle of RLE compressed data to a surface. *
* To_Buffer -- Copies a graphic region into a linear RAM buffer. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "blit.h"
#include "bsurface.h"
//#include "rle.h"
#include "xsurface.h"
//#include <stdlib.h>
/***********************************************************************************************
* Buffer_Size -- Determines size of buffer for given dimensions. *
* *
* This routine will determine the byte size of a buffer if it were to hold the pixels *
* of the dimensions specified. It takes into account the bytes per pixel. *
* *
* INPUT: surface -- The surface to base the buffer size calculation upon. *
* *
* width -- Pixel width of a graphic region. *
* *
* height -- Pixel height of a graphic region. *
* *
* OUTPUT: Returns with the number of bytes such a region would consume if it were linearly *
* packed into a memory buffer. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
int Buffer_Size(Surface const & surface, int width, int height)
{
return(width * height * surface.Bytes_Per_Pixel());
}
/***********************************************************************************************
* To_Buffer -- Copies a graphic region into a linear RAM buffer. *
* *
* This routine will copy the graphic rectangle specified, into a RAM buffer. The size of *
* the RAM buffer must be big enough to hold the pixel data. Use the Buffer_Size() function *
* to determine how big it must be. *
* *
* INPUT: surface -- The surface to copy the pixel data from. *
* *
* rect -- The graphic rectangle to copy from. *
* *
* buffer -- Reference to the buffer that will be filled with the pixel data. *
* *
* OUTPUT: bool; Was the data copy performed without error? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
bool To_Buffer(Surface const & surface, Rect const & rect, Buffer & buffer)
{
if (!rect.Is_Valid()) return(false);
BSurface from(rect.Width, rect.Height, surface.Bytes_Per_Pixel(), buffer);
return(from.Blit_From(Rect(0, 0, rect.Width, rect.Height), surface, rect));
}
/***********************************************************************************************
* From_Buffer -- Copy graphic data from a buffer to a surface. *
* *
* This routine will take pixel data and move it from the specified buffer and into the *
* surface rectangle specified. It is the counterpart routine of To_Buffer(). *
* *
* INPUT: surface -- The surface to store the pixel data to. *
* *
* rect -- The destination rectangle to store the pixel data to. *
* *
* buffer -- Reference to the buffer that contains the pixel data. *
* *
* OUTPUT: bool; Was the pixel data copy performed without error? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
bool From_Buffer(Surface & surface, Rect const & rect, Buffer const & buffer)
{
if (!rect.Is_Valid()) return(false);
BSurface from(rect.Width, rect.Height, surface.Bytes_Per_Pixel(), buffer);
return(surface.Blit_From(rect, from, Rect(0, 0, rect.Width, rect.Height)));
}
/***********************************************************************************************
* Bit_Blit -- Blits data to a surface w/ clipping. *
* *
* This routine will take source pixel data and blit it to the surface specified while *
* also performing clipping on both the source and the destination data. Typical users of *
* this routine would be to draw shape (sprite) data. *
* *
* INPUT: dest -- Destintaion surface rect. This specifies the destination surface and *
* any coordinate clipping rectangle. *
* *
* destrect -- The destination rectangle of the blit. The coordinates are relative *
* to the destination clipping rectangle. *
* *
* source -- Source surface rect. This specifies the source surface as well as any *
* clipping rectangle it may contain. *
* *
* srcrect -- The rectange, relative to the source clipping rectangle, that *
* specifies the source blit data. It is presumed that the dimensions of *
* the source rectangle are the same as the destination rectangle. *
* *
* blitter -- The blitter to use for moving the source pixels to the destination *
* surface. *
* *
* OUTPUT: bool; Was the blit performed even if it was for only a single pixel. Failure would *
* indicate that the blit was completely clipped away. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/19/1997 JLB : Created. *
*=============================================================================================*/
bool Bit_Blit(Surface & dest, Rect const & destrect, Surface const & source, Rect const & sourcerect, Blitter const & blitter)
{
return(Bit_Blit(dest, dest.Get_Rect(), destrect, source, source.Get_Rect(), sourcerect, blitter));
}
/***********************************************************************************************
* Bit_Blit -- Blit a block of pixels to the destination surface. *
* *
* This routine will blit a block of pixels and perform clipping on the blit as controlled *
* by the clipping rectangles. *
* *
* INPUT: dest -- Surface to blit to. *
* *
* dcliprect-- The destination surface clipping rectangle. *
* *
* ddrect -- The destination rect of the blit. It is relative to the clipping *
* rectangle and will be clipped against same. *
* *
* source -- The source surface to blit from. *
* *
* scliprect-- The source surface clipping rectangle. *
* *
* ssrect -- The source rectangle of the blit. It is relative to the source *
* clipping rectangle and will be clipped against same. *
* *
* blitter -- The blitter to use for blitting of this rectangle. *
* *
* OUTPUT: bool; Was the blit performed? A 'false' return value would indicate that the *
* blit was clipped into nothing. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/27/1997 JLB : Created. *
*=============================================================================================*/
bool Bit_Blit(Surface & dest, Rect const & dcliprect, Rect const & ddrect, Surface const & source, Rect const & scliprect, Rect const & ssrect, Blitter const & blitter)
{
Rect srect = ssrect;
Rect drect = ddrect;
bool overlapped = false;
void * dbuffer = NULL;
void * sbuffer = NULL;
/*
** Prepare for the blit by performing any clipping as well as fetching pointers into the
** pixel buffers. If there were any errors, then this blit cannot be performed.
*/
if (!XSurface::Prep_For_Blit(dest, dcliprect, drect, source, scliprect, srect, overlapped, dbuffer, sbuffer)) {
return(false);
}
/*
** If there is no difference between the width and the stride of the source and
** destination surfaces, then the copy can be performed as one huge copy operation.
** This is the simplist case and the one that is performed with a full screen
** blit.
*/
if (drect.Width * dest.Bytes_Per_Pixel() == dest.Stride() && dest.Stride() == source.Stride()) {
int length = MIN(srect.Height*srect.Width, drect.Height*drect.Width);
if (overlapped) {
blitter.BlitBackward(dbuffer, sbuffer, length);
} else {
blitter.BlitForward(dbuffer, sbuffer, length);
}
} else {
/*
** If the rectangles overlap, then the copy must proceed from the
** last row to the first rather than the normal direction.
*/
int sstride = source.Stride();
int dstride = dest.Stride();
if (overlapped) {
sstride = -sstride;
dstride = -dstride;
sbuffer = ((char*)sbuffer) + (srect.Height-1) * source.Stride();
dbuffer = ((char*)dbuffer) + (drect.Height-1) * dest.Stride();
}
/*
** This perform a line-by-line pixel copy.
*/
int height = MIN(srect.Height, drect.Height);
if (overlapped) {
for (int y = 0; y < height; y++) {
blitter.BlitBackward(dbuffer, sbuffer, srect.Width);
dbuffer = (void*)(((char*)dbuffer) + dstride);
sbuffer = (void*)(((char*)sbuffer) + sstride);
}
} else {
for (int y = 0; y < height; y++) {
blitter.BlitForward(dbuffer, sbuffer, srect.Width);
dbuffer = (void*)(((char*)dbuffer) + dstride);
sbuffer = (void*)(((char*)sbuffer) + sstride);
}
}
}
dest.Unlock();
source.Unlock();
return(true);
}
/***********************************************************************************************
* RLE_Blit -- Blits RLE compressed data without extra clipping. *
* *
* This routine will blit a rectangle of RLE compressed data to the specified surface. It *
* is functionally similar to the other RLE blit routine, but does not use any sub *
* clipping rectangles. The blit is naturally clipped to the edge of the destination *
* surface. *
* *
* INPUT: dest -- Reference to the destination surface. *
* *
* destrect -- The destination rectangle to draw the pixels to. *
* *
* source -- Reference to the source RLE surface data. *
* *
* sourcerect -- The source rectangle of from the RLE surface to blit from. *
* *
* blitter -- Reference to the blitter to perform the blit operation with. *
* *
* OUTPUT: bool; Was a blit performed? A 'false' value would mean that the blit has been *
* clipped into nothing. *
* *
* WARNINGS: The dimensions of the source and destination rectangles should be the same *
* until such time that the blitter can support scaling (as of this writing, it *
* cannot). *
* *
* HISTORY: *
* 05/27/1997 JLB : Created. *
*=============================================================================================*/
bool RLE_Blit(Surface & dest, Rect const & destrect, Surface const & source, Rect const & sourcerect, RLEBlitter const & blitter)
{
return(RLE_Blit(dest, dest.Get_Rect(), destrect, source, source.Get_Rect(), sourcerect, blitter));
}
/***********************************************************************************************
* RLE_Blit -- Blits a rectangle of RLE compressed data to a surface. *
* *
* This routine will blit a rectangle of REL compressed pixel data from a sprite to the *
* surface specified. Appropriate clipping and coordinate adjustments will occur as *
* controlled by the parameters. This is the workhorse RLE blit dispatcher routine. *
* *
* INPUT: dest -- The destination surface to blit to. *
* *
* dcliprect-- The clipping rectangle to use on the destination. Pixels won't be *
* drawn outside of this rectangle and the destination rect coordinates *
* are biased to this clipping rectange. *
* *
* ddrect -- The destination rectangle of the blit. The upper left coordinates are *
* biased to the destination clipping rectangle when blitted. Thus, *
* a dest X,Y position of 0,0 really means the upper left corner of the *
* destination clipping rectangle. *
* *
* source -- The source surface of the RLE compressed data. *
* *
* scliprect-- It is quite likely that this will be the full size of the source *
* surface. *
* *
* ssrect -- The source rectangle to blit from within the source surface. It *
* behaves similarly to the ddrect parameter, but for the source. The *
* width and height of this rectangle should match the width and height *
* of the ddrect parameter (scaling is not yet supported). *
* *
* blitter -- The blitter to use for this pixel copy. It must be an RLE blitter. *
* *
* OUTPUT: bool; Did the blit draw at least one pixel? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/24/1997 JLB : Created. *
*=============================================================================================*/
bool RLE_Blit(Surface & dest, Rect const & dcliprect, Rect const & ddrect, Surface const & source, Rect const & scliprect, Rect const & ssrect, RLEBlitter const & blitter)
{
Rect srect = ssrect; // Desired source rect.
Rect drect = ddrect; // Desired destination rect.
/*
** Adjust the desired draw rectangles to account for clipping. This is where the desired rectangles
** get clipped to the bounding rectangles of the surfaces.
*/
if (!Blit_Clip(drect, dcliprect, srect, scliprect)) {
return(false);
}
/*
** Determine the top and left skip margins. These require special handling
** since the shape is compressed.
*/
int leftmargin = srect.X - scliprect.X;
int topmargin = srect.Y - scliprect.Y;
void * dbuffer = dest.Lock(dcliprect.Top_Left() + drect.Top_Left());
// void * dbuffer = dest.Lock(Point2D(dcliprect.X + drect.X, dcliprect.Y + drect.Y));
if (dbuffer == NULL) return(false);
/*
** Lock the source pointer. This must always lock at location 0,0 since
** normal pixel offset logic does not work for RLE compressed buffers. If there
** is a pixel offset required, it is handled below.
*/
void * sbuffer = source.Lock();
if (sbuffer == NULL) {
dest.Unlock();
return(false);
}
/*
** Skip any top margin lines. This must be manually performed on a line
** by line basis because the length of each line is Variable.
*/
while (topmargin > 0) {
sbuffer = ((unsigned char *)sbuffer) + (*(unsigned short *)sbuffer);
topmargin--;
}
/*
** This perform a line-by-line pixel copy.
*/
int dstride = dest.Stride();
int height = MIN(srect.Height, drect.Height);
for (int y = 0; y < height; y++) {
/*
** Blit the correct sub-portion to the destination surface.
*/
blitter.Blit(dbuffer, ((unsigned short *)sbuffer)+1, srect.Width, leftmargin);
/*
** Advance the source and dest pointers for the next line processing.
*/
sbuffer = ((unsigned char *)sbuffer) + (*(unsigned short *)sbuffer);
dbuffer = (void*)(((char*)dbuffer) + dstride);
}
dest.Unlock();
source.Unlock();
return(true);
}

View File

@@ -0,0 +1,61 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/blit.h $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 5/04/01 7:49p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BLIT_H
#define BLIT_H
#include "blitter.h"
#include "buff.h"
#include "trect.h"
#include "surface.h"
bool Bit_Blit(Surface & dest, Rect const & destrect, Surface const & source, Rect const & sourcerect, Blitter const & blitter);
bool RLE_Blit(Surface & dest, Rect const & destrect, Surface const & source, Rect const & sourcerect, RLEBlitter const & blitter);
//bool Bit_Blit(SurfaceRect & dest, Rect const & ddrect, SurfaceRect const & source, Rect const & ssrect, Blitter const & blitter);
//bool RLE_Blit(SurfaceRect & dest, Rect const & ddrect, SurfaceRect const & source, Rect const & ssrect, RLEBlitter const & blitter);
bool Bit_Blit(Surface & dest, Rect const & dcliprect, Rect const & ddrect, Surface const & source, Rect const & scliprect, Rect const & ssrect, Blitter const & blitter);
bool RLE_Blit(Surface & dest, Rect const & dcliprect, Rect const & ddrect, Surface const & source, Rect const & scliprect, Rect const & ssrect, RLEBlitter const & blitter);
int Buffer_Size(Surface & surface, int width, int height);
bool To_Buffer(Surface const & surface, Rect const & rect, Buffer & buffer);
bool From_Buffer(Surface & surface, Rect const & rect, Buffer const & buffer);
#endif

View File

@@ -0,0 +1,614 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/blitblit.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BLITBLIT_H
#define BLITBLIT_H
/*
** This module contains the pixel-pushing blitter objects. These objects only
** serve one purpose. That is, to move pixels from one location to another. These
** are prime candidates for optimization since they are called frequently and
** loop greatly.
**
** The large variety of blitter objects is necessary because there is a rich
** set of pixel operations required by the game engine. Complicating this is that
** the game engine must support both 16 bit and 8 bit pixel formats. Some of these
** blitter objects are templates (this reduces the need for both 8 and 16 bit
** counterparts if the algorithm is constant between pixel formats). Also note
** that there are some assembly implementations where it seems appropriate.
**
** If the blitter object has "Xlat" in the name, then this means that the source
** pixel is 8 bit and the destination pixel is 16 bit (probably). This hybrid system
** allows the game artwork to be shared between the two pixel format displays. To
** accomplish this, a translation table is supplied to the blit operation so that
** the 8 bit pixel can be converted into the appropriate 16 bit destination pixel.
** If the destination surface is also 8 bit, then the translation table converts
** the pixel to the logical palette color index appropriate for the display.
*/
#include "blitter.h"
#include <assert.h>
#include <string.h>
/*
** Blits without translation and source and dest are same pixel format. Note that
** this uses the memcpy and memmove routines. The C library has optimized these for
** maximum performance. This includes alignment issues and performing REP MOVSD
** instruction. This might be further optimized by using MMX instructions. However,
** this blitter process is not often required by the game.
*/
template<class T>
class BlitPlain : public Blitter {
public:
virtual void BlitForward(void * dest, void const * source, int length) const {memcpy(dest, source, length*sizeof(T));}
virtual void BlitBackward(void * dest, void const * source, int length) const {memmove(dest, source, length*sizeof(T));}
};
/*
** Blits with transparency checking when and source and dest are same pixel format.
** This process is not often used.
*/
template<class T>
class BlitTrans : public Blitter {
public:
virtual void BlitForward(void * dest, void const * source, int len) const
{
for (int index = 0; index < len; index++) {
T color = *(T const *)source;
source = ((T *)source) + 1;
if (color != 0) *((T *)dest) = color;
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
};
/*
** Blits when source 8 bits and dest is T. This process is typically used
** when loading screen bitmaps or perform other non-transparent image blitting.
** It is used fairly frequently and is a good candidate for optimization.
*/
template<class T>
class BlitPlainXlat : public Blitter {
public:
BlitPlainXlat(T const * translator) : TranslateTable(translator) {assert(TranslateTable != NULL);}
virtual void BlitForward(void * dest, void const * source, int len) const
{
for (int index = 0; index < len; index++) {
unsigned char color = *(unsigned char const *)source;
source = ((unsigned char const *)source)+1;
*((T *)dest) = TranslateTable[color];
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
T const * TranslateTable;
};
/*
** Blits with source 8 bit with transparency and dest is T. This process is used
** frequently by trees and other terrain objects. It is a good candidate for
** optimization.
*/
template<class T>
class BlitTransXlat : public Blitter {
public:
BlitTransXlat(T const * translator) : TranslateTable(translator) {assert(TranslateTable != NULL);}
virtual void BlitForward(void * dest, void const * source, int len) const
{
for (int index = 0; index < len; index++) {
unsigned char color = *(unsigned char const *)source;
source = ((unsigned char const *)source)+1;
if (color != 0) {
*((T *)dest) = TranslateTable[color];
}
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
T const * TranslateTable;
};
/*
** Blits with source 8 bit, transparency check, then translate to pixel format T. This
** is occasionally used to render special remapping effects. Since the remap table is
** not doubly indirected, it is fixed to only using the remap table specified in the
** constructor. As such, it has limited value.
*/
template<class T>
class BlitTransRemapXlat : public Blitter {
public:
BlitTransRemapXlat(unsigned char const * remapper, T const * translator) : RemapTable(remapper), TranslateTable(translator) {assert(RemapTable != NULL);assert(TranslateTable != NULL);}
virtual void BlitForward(void * dest, void const * source, int length) const
{
for (int index = 0; index < length; index++) {
unsigned char color = *(unsigned char const *)source;
source = ((unsigned char const *)source)+1;
if (color != 0) {
*((T *)dest) = TranslateTable[RemapTable[color]];
}
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
unsigned char const * RemapTable;
T const * TranslateTable;
};
/*
** Blits with source 8 bit with transparency then remap and dest is T. This is probably
** the most used blitter process. Units, infantry, buildings, and aircraft use this for
** their normal drawing needs. If any blitter process is to be optimized, this would be
** the one. Take note that the remapper table is doubly indirected. This allows a single
** blitter object to dynamically use alternate remap tables.
*/
template<class T>
class BlitTransZRemapXlat : public Blitter {
public:
BlitTransZRemapXlat(unsigned char const * const * remapper, T const * translator) : RemapTable(remapper), TranslateTable(translator) {assert(RemapTable != NULL);assert(TranslateTable != NULL);}
virtual void BlitForward(void * dest, void const * source, int length) const
{
unsigned char const * rtable = *RemapTable;
for (int index = 0; index < length; index++) {
unsigned char color = *(unsigned char const *)source;
source = ((unsigned char const *)source)+1;
if (color != 0) {
*((T *)dest) = TranslateTable[rtable[color]];
}
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
unsigned char const * const * RemapTable;
T const * TranslateTable;
};
/*
** Algorithmic darkening of hicolor pixels controlled by the source pixels. The source
** pixels are examined only to determine if the destination pixel should be darkened.
** If the source pixel is transparent, then the dest pixel is skipped. The darkening
** algorithm works only for hicolor pixels.
*/
template<class T>
class BlitTransDarken : public Blitter {
public:
BlitTransDarken(T mask) : Mask(mask) {}
virtual void BlitForward(void * dest, void const * source, int length) const
{
for (int index = 0; index < length; index++) {
unsigned char color = *(unsigned char const *)source;
source = ((unsigned char const *)source)+1;
if (color != 0) {
*((T *)dest) = (T)((((*(T *)dest) >> 1) & Mask));
}
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
T Mask;
};
/*
** This will remap the destination pixels but under the control of the source pixels.
** Where the source pixel is not transparent, the dest pixel is remapped. This algorithm
** really only applies to lowcolor display.
*/
template<class T>
class BlitTransRemapDest : public Blitter {
public:
BlitTransRemapDest(T const * remap) : RemapTable(remap) {}
virtual void BlitForward(void * dest, void const * source, int length) const
{
for (int index = 0; index < length; index++) {
unsigned char color = *(unsigned char const *)source;
source = ((unsigned char const *)source)+1;
if (color != 0) {
*((T *)dest) = RemapTable[*((T *)dest)];
}
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
T const * RemapTable;
};
/*
** This is similar to BlitTransDarken but instead of examining the source to determine what
** pixels should be darkened, every destination pixel is darkened. This means that the source
** pointer is unused.
*/
template<class T>
class BlitDarken : public Blitter {
public:
BlitDarken(T mask) : Mask(mask) {}
virtual void BlitForward(void * dest, void const * , int length) const
{
for (int index = 0; index < length; index++) {
*((T *)dest) = (T)(((*(T *)dest) >> 1) & Mask);
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
T Mask;
};
/*
** This blitter performs 50% translucency as it draws. It is commonly used for animation
** effects and other stealth like images. It only works with hicolor pixels but is a good
** candidate for optimization.
*/
template<class T>
class BlitTransLucent50 : public Blitter {
public:
BlitTransLucent50(T const * translator, T mask) : TranslateTable(translator), Mask(mask) {assert(TranslateTable != NULL);}
virtual void BlitForward(void * dest, void const * source, int length) const
{
for (int index = 0; index < length; index++) {
unsigned char color = *(unsigned char const *)source;
source = ((unsigned char *)source) + 1;
if (color != 0) {
*((T *)dest) = (T)((((*(T *)dest) >> 1) & Mask) + ((TranslateTable[color] >> 1) & Mask));
}
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
T const * TranslateTable;
T Mask;
};
/*
** This blitter performs 25% translucency as it draws. This effect is less than spectacular,
** but there are some uses for it. It only works with hicolor pixels.
*/
template<class T>
class BlitTransLucent25 : public Blitter {
public:
BlitTransLucent25(T const * translator, T mask) : TranslateTable(translator), Mask(mask) {assert(TranslateTable != NULL);}
virtual void BlitForward(void * dest, void const * source, int length) const
{
for (int index = 0; index < length; index++) {
unsigned char color = *(unsigned char const *)source;
source = ((unsigned char *)source) + 1;
if (color != 0) {
T qsource = (T)(((TranslateTable[color] >> 2) & Mask));
T qdest = (T)((((*(T *)dest) >> 2) & Mask));
*((T *)dest) = (T)(qdest + qsource + qsource + qsource);
}
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
T const * TranslateTable;
T Mask;
};
/*
** This blitter performs 75% translucency as it draws. This is quite useful for explosions and
** other gas animation effects. It only works with hicolor pixels and is a good candidate
** for optimization.
*/
template<class T>
class BlitTransLucent75 : public Blitter {
public:
BlitTransLucent75(T const * translator, T mask) : TranslateTable(translator), Mask(mask) {assert(TranslateTable != NULL);}
virtual void BlitForward(void * dest, void const * source, int length) const
{
for (int index = 0; index < length; index++) {
unsigned char color = *(unsigned char const *)source;
source = ((unsigned char *)source) + 1;
if (color != 0) {
T qsource = (T)(((TranslateTable[color] >> 2) & Mask));
T qdest = (T)(((*(T *)dest) >> 2) & Mask);
*((T *)dest) = (T)(qdest + qdest + qdest + qsource);
}
dest = ((T *)dest) + 1;
}
}
/*
** The backward moving method will probably never be called in actual practice.
** Implement in terms of the forward copying method until the need for this
** version arrises.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
private:
T const * TranslateTable;
T Mask;
};
/*
** Assembly versions of some of the templated blitter object functions. Borland and
** Visual C++ support a compatible inline-assembly formats. However, Borland compiler
** does not allow inline-assembly to be part of an inline function -- go figure.
** It will still compile, it just generates warning messages.
*/
#if defined(_MSC_VER)
inline void BlitTrans<unsigned char>::BlitForward(void * dest, void const * source, int len) const
{
__asm {
mov esi,[source]
mov edi,[dest]
mov ecx,[len]
dec edi
inc ecx
}
again:
__asm {
dec ecx
jz fini
mov al,[esi]
inc edi
inc esi
test al,al
jz again
mov [edi],al
jmp again
}
fini:;
}
inline void BlitTransXlat<unsigned short>::BlitForward(void * dest, void const * source, int len) const
{
unsigned short const * xlator = TranslateTable;
__asm {
mov ebx,[xlator]
mov ecx,[len]
inc ecx
mov edi,[dest]
sub edi,2
mov esi,[source]
xor eax,eax
}
again:
__asm {
dec ecx
jz over
add edi,2
mov al,[esi]
inc esi
or al,al
jz again
mov dx,[ebx+eax*2]
mov [edi],dx
jmp again
}
over:;
}
inline void BlitTransRemapXlat<unsigned short>::BlitForward(void * dest, void const * source, int len) const
{
unsigned short const * translator = TranslateTable;
unsigned char const * remapper = RemapTable;
__asm {
mov ecx,[len]
mov edi,[dest]
sub edi,2
mov esi,[source]
mov ebx,[remapper]
mov edx,[translator]
xor eax,eax
}
/*
** This block is 11 cycles per pixel, if not transparent, and 5
** cycles per pixel, if transparent.
*/
again:
__asm {
dec ecx
jz over
add edi,2
xor eax,eax
lodsb
or al,al
jz again
mov al,[ebx+eax] // First remap step (8 bit to 8 bit).
mov ax,[edx+eax*2] // Second remap step (8 bit to 16 bit).
mov [edi],ax
jmp again
}
over:;
}
inline void BlitTransZRemapXlat<unsigned short>::BlitForward(void * dest, void const * source, int len) const
{
unsigned short const * translator = TranslateTable;
unsigned char const * remapper = *RemapTable;
__asm {
mov ecx,[len]
mov edi,[dest]
sub edi,2
mov esi,[source]
mov ebx,[remapper]
mov edx,[translator]
xor eax,eax
}
/*
** This block is 11 cycles per pixel, if not transparent, and 5
** cycles per pixel, if transparent.
*/
again:
__asm {
dec ecx
jz over
add edi,2
xor eax,eax
lodsb
or al,al
jz again
mov al,[ebx+eax] // First remap step (8 bit to 8 bit).
mov ax,[edx+eax*2] // Second remap step (8 bit to 16 bit).
mov [edi],ax
jmp again
}
over:;
}
inline void BlitPlainXlat<unsigned short>::BlitForward(void * dest, void const * source, int len) const
{
unsigned short const * remapper = TranslateTable;
__asm {
mov ebx,[remapper]
mov ecx,[len]
mov esi,[source]
mov edi,[dest]
sub edi,2
}
again:
/*
** This block processes pixels at 7 clocks per pixel.
*/
__asm {
xor eax,eax
add edi,2
mov al,[esi]
inc esi
mov ax,[ebx+eax*2]
mov [edi],ax
dec ecx
jnz again
}
}
#endif
#endif

View File

@@ -0,0 +1,94 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/blitter.h $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 5/04/01 7:48p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef BLITTER_H
#define BLITTER_H
/*
** This is the interface class to the blitter object. The blitter object handles moving
** pixels. That's all it does. For every type of pixel translation, there should be a
** blitter object created that supports this interface. The blit blitting routines will
** call the appropriate method as the pixel are being processed.
*/
class Blitter {
public:
/*
** Blits from source to dest (starts at first pixel). This is the preferred
** method of pixel blitting and this routine will be called 99% of the time under
** normal circumstances.
*/
virtual void BlitForward(void * dest, void const * source, int length) const = 0;
/*
** Copies the pixel in reverse order. This only required if the source and dest
** pixel regions overlap in a certain way. This routine will rarely be called.
*/
virtual void BlitBackward(void * dest, void const * source, int length) const = 0;
/*
** This routine calls the appropriate blit routine. A proper overlap check cannot
** be performed by this routine because the pixel size information is not present.
** as such, you should call the appropriate blit routine rather than letting this
** routine perform the check and call.
*/
void Blit(void * dest, void const * source, int length) const {if (dest < source) BlitBackward(dest, source, length); else BlitForward(dest, source, length);}
};
/*
** This is the blitter object interface for dealing with RLE compressed pixel data. For
** every type of RLE compressed blitter operation desired, there would be an object created
** that supports this interface.
*/
class RLEBlitter {
public:
/*
** Blits from the RLE compressed source to the destination buffer. An optional
** leading pixel skip value can be supplied when a sub-section of an RLE
** compressed pixel sequence is desired. This is necessary because RLE decompression
** must begin at the start of the compressed data sequence.
*/
virtual void Blit(void * dest, void const * source, int length, int leadskip=0) const = 0;
};
#endif

View File

@@ -0,0 +1,597 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/BLOWFISH.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* BlowfishEngine::Decrypt -- Decrypts data using blowfish algorithm. *
* BlowfishEngine::Encrypt -- Encrypt an arbitrary block of data. *
* BlowfishEngine::Process_Block -- Process a block of data using Blowfish algorithm. *
* BlowfishEngine::Sub_Key_Encrypt -- Encrypts a block for use in S-Box processing. *
* BlowfishEngine::Submit_Key -- Submit a key that will allow data processing. *
* BlowfishEngine::~BlowfishEngine -- Destructor for the Blowfish engine. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "blowfish.h"
#include <string.h>
#include <assert.h>
/*
** Byte order controlled long integer. This integer is constructed
** so that character 0 (C0) is the most significant byte of the
** integer. This is biased toward big endian architecture, but that
** just happens to be how the Blowfish algorithm was designed.
*/
typedef union {
unsigned long Long;
struct {
unsigned char C3;
unsigned char C2;
unsigned char C1;
unsigned char C0;
} Char;
} Int;
/***********************************************************************************************
* BlowfishEngine::~BlowfishEngine -- Destructor for the Blowfish engine. *
* *
* This destructor will clear out the s-box tables so that even if the memory for the *
* class remains, it will contain no compromising data. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/08/1996 JLB : Created. *
*=============================================================================================*/
BlowfishEngine::~BlowfishEngine(void)
{
if (IsKeyed) {
Submit_Key(NULL, 0);
}
}
/***********************************************************************************************
* BlowfishEngine::Submit_Key -- Submit a key that will allow data processing. *
* *
* This routine must be called before any data can be encrypted or decrypted. This routine *
* need only be called when the key is to be changed or set for the first time. Once the *
* key has been set, the engine may be used to encrypt, decrypt, or both operations *
* indefinitely. The key must be 56 bytes or less in length. This is necessary because *
* any keys longer than that will not correctly affect the encryption process. *
* *
* If the key pointer is NULL, then the S-Box tables are reset to identity. This will *
* mask the previous key setting. Use this method to clear the engine after processing in *
* order to gain a measure of security. *
* *
* INPUT: key -- Pointer to the key data block. *
* *
* length -- The length of the submitted key. *
* *
* OUTPUT: none *
* *
* WARNINGS: This is a time consuming process. *
* *
* HISTORY: *
* 04/14/1996 JLB : Created. *
*=============================================================================================*/
void BlowfishEngine::Submit_Key(void const * key, int length)
{
assert(length <= MAX_KEY_LENGTH);
/*
** Initialize the permutation and S-Box tables to a known
** constant value.
*/
memcpy(P_Encrypt, P_Init, sizeof(P_Init));
memcpy(P_Decrypt, P_Init, sizeof(P_Init));
memcpy(bf_S, S_Init, sizeof(S_Init));
/*
** Validate parameters.
*/
if (key == 0 || length == 0) {
IsKeyed = false;
return;
}
/*
** Combine the key with the permutation table. Wrap the key
** as many times as necessary to ensure that the entire
** permutation table has been modified. The key is lifted
** into a long by using endian independent means.
*/
int j = 0;
unsigned char const * key_ptr = (unsigned char const *)key;
unsigned long * p_ptr = &P_Encrypt[0];
for (int index = 0; index < ROUNDS+2; index++) {
unsigned long data = 0;
data = (data << CHAR_BIT) | key_ptr[j++ % length];
data = (data << CHAR_BIT) | key_ptr[j++ % length];
data = (data << CHAR_BIT) | key_ptr[j++ % length];
data = (data << CHAR_BIT) | key_ptr[j++ % length];
*p_ptr++ ^= data;
}
/*
** The permutation table must be scrambled by means of the key. This
** is how the key is factored into the encryption -- by merely altering
** the permutation (and S-Box) tables. Because this transformation alters
** the table data WHILE it is using the table data, the tables are
** thoroughly obfuscated by this process.
*/
unsigned long left = 0x00000000L;
unsigned long right = 0x00000000L;
unsigned long * p_en = &P_Encrypt[0]; // Encryption table.
unsigned long * p_de = &P_Decrypt[ROUNDS+1]; // Decryption table.
for (int p_index = 0; p_index < ROUNDS+2; p_index += 2) {
Sub_Key_Encrypt(left, right);
*p_en++ = left;
*p_en++ = right;
*p_de-- = left;
*p_de-- = right;
}
/*
** Perform a similar transmutation to the S-Box tables. Also notice that the
** working 64 bit number is carried into this process from the previous
** operation.
*/
for (int sbox_index = 0; sbox_index < 4; sbox_index++) {
for (int ss_index = 0; ss_index < UCHAR_MAX+1; ss_index += 2) {
Sub_Key_Encrypt(left, right);
bf_S[sbox_index][ss_index] = left;
bf_S[sbox_index][ss_index + 1] = right;
}
}
IsKeyed = true;
}
/***********************************************************************************************
* BlowfishEngine::Encrypt -- Encrypt an arbitrary block of data. *
* *
* Use this routine to encrypt an arbitrary block of data. The block must be an even *
* multiple of 8 bytes. Any bytes left over will not be encrypted. The 8 byte requirement *
* is necessary because the underlying algorithm processes blocks in 8 byte chunks. *
* Partial blocks are unrecoverable and useless. *
* *
* INPUT: plaintext-- Pointer to the data block to be encrypted. *
* *
* length -- The length of the data block. *
* *
* cyphertext- Pointer to the output buffer that will hold the encrypted data. *
* *
* OUTPUT: Returns with the actual number of bytes encrypted. *
* *
* WARNINGS: You must submit the key before calling this routine. This will only encrypt *
* the plaintext in 8 byte increments. Modulo bytes left over are not processed. *
* *
* HISTORY: *
* 04/14/1996 JLB : Created. *
*=============================================================================================*/
int BlowfishEngine::Encrypt(void const * plaintext, int length, void * cyphertext)
{
if (plaintext == 0 || length == 0) {
return(0);
}
if (cyphertext == 0) cyphertext = (void *)plaintext;
if (IsKeyed) {
/*
** Validate parameters.
*/
int blocks = length / BYTES_PER_BLOCK;
/*
** Process the buffer in 64 bit chunks.
*/
for (int index = 0; index < blocks; index++) {
Process_Block(plaintext, cyphertext, P_Encrypt);
plaintext = ((char *)plaintext) + BYTES_PER_BLOCK;
cyphertext = ((char *)cyphertext) + BYTES_PER_BLOCK;
}
int encrypted = blocks * BYTES_PER_BLOCK;
/*
** Copy over any trailing left over appendix bytes.
*/
if (encrypted < length) {
memmove(cyphertext, plaintext, length - encrypted);
}
return(encrypted);
}
/*
** Non-keyed processing merely copies the data.
*/
if (plaintext != cyphertext) {
memmove(cyphertext, plaintext, length);
}
return(length);
}
/***********************************************************************************************
* BlowfishEngine::Decrypt -- Decrypt an arbitrary block of data. *
* *
* Use this routine to decrypt an arbitrary block of data. The block must be an even *
* multiple of 8 bytes. Any bytes left over will not be decrypted. The 8 byte requirement *
* is necessary because the underlying algorithm processes blocks in 8 byte chunks. *
* Partial blocks are unrecoverable and useless. *
* *
* INPUT: cyphertext- Pointer to the data block to be decrypted. *
* *
* length -- The length of the data block. *
* *
* plaintext-- Pointer to the output buffer that will hold the decrypted data. *
* *
* OUTPUT: Returns with the actual number of bytes decrypted. *
* *
* WARNINGS: You must submit the key before calling this routine. This will only decrypt *
* the cyphertext in 8 byte increments. Modulo bytes left over are not processed. *
* *
* HISTORY: *
* 04/14/1996 JLB : Created. *
*=============================================================================================*/
int BlowfishEngine::Decrypt(void const * cyphertext, int length, void * plaintext)
{
if (cyphertext == 0 || length == 0) {
return(0);
}
if (plaintext == 0) plaintext = (void *)cyphertext;
if (IsKeyed) {
/*
** Validate parameters.
*/
int blocks = length / BYTES_PER_BLOCK;
/*
** Process the buffer in 64 bit chunks.
*/
for (int index = 0; index < blocks; index++) {
Process_Block(cyphertext, plaintext, P_Decrypt);
cyphertext = ((char *)cyphertext) + BYTES_PER_BLOCK;
plaintext = ((char *)plaintext) + BYTES_PER_BLOCK;
}
int encrypted = blocks * BYTES_PER_BLOCK;
/*
** Copy over any trailing left over appendix bytes.
*/
if (encrypted < length) {
memmove(plaintext, cyphertext, length - encrypted);
}
return(encrypted);
}
/*
** Non-keyed processing merely copies the data.
*/
if (plaintext != cyphertext) {
memmove(plaintext, cyphertext, length);
}
return(length);
}
/***********************************************************************************************
* BlowfishEngine::Process_Block -- Process a block of data using Blowfish algorithm. *
* *
* This is the main processing routine for encryption and decryption. The algorithm *
* consists of a 16 round Feistal network and uses mathematics from different algebraic *
* groups (strengthens against differential cryptanalysis). The large S-Boxes and the *
* rounds strengthen it against linear cryptanalysis. *
* *
* INPUT: plaintext -- Pointer to the source text (it actually might be a pointer to *
* the cyphertext if this is called as a decryption process). *
* *
* cyphertext -- Pointer to the output buffer that will hold the processed block. *
* *
* ptable -- Pointer to the permutation table. This algorithm will encrypt *
* and decrypt using the same S-Box tables. The encryption control *
* is handled by the permutation table. *
* *
* OUTPUT: none *
* *
* WARNINGS: The source and destination buffers must be 8 bytes long. *
* *
* HISTORY: *
* 04/19/1996 JLB : Created. *
*=============================================================================================*/
void BlowfishEngine::Process_Block(void const * plaintext, void * cyphertext, unsigned long const * ptable)
{
/*
** Input the left and right halves of the source block such that
** the byte order is constant regardless of the endian
** persuasion of the current processor. The blowfish algorithm is
** biased toward "big endian" architecture and some optimizations
** could be done for big endian processors in that case.
*/
unsigned char const * source = (unsigned char const *)plaintext;
Int left;
left.Char.C0 = *source++;
left.Char.C1 = *source++;
left.Char.C2 = *source++;
left.Char.C3 = *source++;
Int right;
right.Char.C0 = *source++;
right.Char.C1 = *source++;
right.Char.C2 = *source++;
right.Char.C3 = *source;
/*
** Perform all Feistal rounds on the block. This is the encryption/decryption
** process. Since there is an exchange that occurs after each round, two
** rounds are combined in this loop to avoid unnecessary exchanging.
*/
for (int index = 0; index < ROUNDS/2; index++) {
left.Long ^= *ptable++;
right.Long ^= ((( bf_S[0][left.Char.C0] + bf_S[1][left.Char.C1]) ^ bf_S[2][left.Char.C2]) + bf_S[3][left.Char.C3]);
right.Long ^= *ptable++;
left.Long ^= ((( bf_S[0][right.Char.C0] + bf_S[1][right.Char.C1]) ^ bf_S[2][right.Char.C2]) + bf_S[3][right.Char.C3]);
}
/*
** The final two longs in the permutation table are processed into the block.
** The left and right halves are still reversed as a side effect of the last
** round.
*/
left.Long ^= *ptable++;
right.Long ^= *ptable;
/*
** The final block data is output in endian architecture
** independent format. Notice that the blocks are output as
** right first and left second. This is to counteract the final
** superfluous exchange that occurs as a side effect of the
** encryption rounds.
*/
unsigned char * out = (unsigned char *)cyphertext;
*out++ = right.Char.C0;
*out++ = right.Char.C1;
*out++ = right.Char.C2;
*out++ = right.Char.C3;
*out++ = left.Char.C0;
*out++ = left.Char.C1;
*out++ = left.Char.C2;
*out = left.Char.C3;
}
/***********************************************************************************************
* BlowfishEngine::Sub_Key_Encrypt -- Encrypts a block for use in S-Box processing. *
* *
* This is the same as the normal process block function but it doesn't have the endian *
* fixup logic. Since this routine is only called for S-Box table generation and it is *
* known that the S-Box initial data is already in local machine endian format, the *
* byte order fixups are not needed. This also has a tendency to speed up S-Box generation *
* as well. *
* *
* INPUT: left -- The left half of the data block. *
* *
* right -- The right half of the data block. *
* *
* OUTPUT: none, but the processed block is stored back into the left and right half *
* integers. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 04/19/1996 JLB : Created. *
*=============================================================================================*/
void BlowfishEngine::Sub_Key_Encrypt(unsigned long & left, unsigned long & right)
{
Int l;
l.Long = left;
Int r;
r.Long = right;
for (int index = 0; index < ROUNDS; index += 2) {
l.Long ^= P_Encrypt[index];
r.Long ^= ((( bf_S[0][l.Char.C0] + bf_S[1][l.Char.C1]) ^ bf_S[2][l.Char.C2]) + bf_S[3][l.Char.C3]);
r.Long ^= P_Encrypt[index+1];
l.Long ^= ((( bf_S[0][r.Char.C0] + bf_S[1][r.Char.C1]) ^ bf_S[2][r.Char.C2]) + bf_S[3][r.Char.C3]);
}
left = r.Long ^ P_Encrypt[ROUNDS+1];
right = l.Long ^ P_Encrypt[ROUNDS];
}
/*
** These tables have the bytes stored in machine endian format. Because of this,
** a special block cypher routine is needed when the sub-keys are generated.
** This is kludgier than it otherwise should be. However, storing these
** integers in machine independent format would be even more painful.
*/
unsigned long const BlowfishEngine::P_Init[BlowfishEngine::ROUNDS+2] = {
0x243F6A88U,0x85A308D3U,0x13198A2EU,0x03707344U,0xA4093822U,0x299F31D0U,0x082EFA98U,0xEC4E6C89U,
0x452821E6U,0x38D01377U,0xBE5466CFU,0x34E90C6CU,0xC0AC29B7U,0xC97C50DDU,0x3F84D5B5U,0xB5470917U,
0x9216D5D9U,0x8979FB1BU
};
unsigned long const BlowfishEngine::S_Init[4][UCHAR_MAX+1] = {
{
0xD1310BA6U,0x98DFB5ACU,0x2FFD72DBU,0xD01ADFB7U,0xB8E1AFEDU,0x6A267E96U,0xBA7C9045U,0xF12C7F99U,
0x24A19947U,0xB3916CF7U,0x0801F2E2U,0x858EFC16U,0x636920D8U,0x71574E69U,0xA458FEA3U,0xF4933D7EU,
0x0D95748FU,0x728EB658U,0x718BCD58U,0x82154AEEU,0x7B54A41DU,0xC25A59B5U,0x9C30D539U,0x2AF26013U,
0xC5D1B023U,0x286085F0U,0xCA417918U,0xB8DB38EFU,0x8E79DCB0U,0x603A180EU,0x6C9E0E8BU,0xB01E8A3EU,
0xD71577C1U,0xBD314B27U,0x78AF2FDAU,0x55605C60U,0xE65525F3U,0xAA55AB94U,0x57489862U,0x63E81440U,
0x55CA396AU,0x2AAB10B6U,0xB4CC5C34U,0x1141E8CEU,0xA15486AFU,0x7C72E993U,0xB3EE1411U,0x636FBC2AU,
0x2BA9C55DU,0x741831F6U,0xCE5C3E16U,0x9B87931EU,0xAFD6BA33U,0x6C24CF5CU,0x7A325381U,0x28958677U,
0x3B8F4898U,0x6B4BB9AFU,0xC4BFE81BU,0x66282193U,0x61D809CCU,0xFB21A991U,0x487CAC60U,0x5DEC8032U,
0xEF845D5DU,0xE98575B1U,0xDC262302U,0xEB651B88U,0x23893E81U,0xD396ACC5U,0x0F6D6FF3U,0x83F44239U,
0x2E0B4482U,0xA4842004U,0x69C8F04AU,0x9E1F9B5EU,0x21C66842U,0xF6E96C9AU,0x670C9C61U,0xABD388F0U,
0x6A51A0D2U,0xD8542F68U,0x960FA728U,0xAB5133A3U,0x6EEF0B6CU,0x137A3BE4U,0xBA3BF050U,0x7EFB2A98U,
0xA1F1651DU,0x39AF0176U,0x66CA593EU,0x82430E88U,0x8CEE8619U,0x456F9FB4U,0x7D84A5C3U,0x3B8B5EBEU,
0xE06F75D8U,0x85C12073U,0x401A449FU,0x56C16AA6U,0x4ED3AA62U,0x363F7706U,0x1BFEDF72U,0x429B023DU,
0x37D0D724U,0xD00A1248U,0xDB0FEAD3U,0x49F1C09BU,0x075372C9U,0x80991B7BU,0x25D479D8U,0xF6E8DEF7U,
0xE3FE501AU,0xB6794C3BU,0x976CE0BDU,0x04C006BAU,0xC1A94FB6U,0x409F60C4U,0x5E5C9EC2U,0x196A2463U,
0x68FB6FAFU,0x3E6C53B5U,0x1339B2EBU,0x3B52EC6FU,0x6DFC511FU,0x9B30952CU,0xCC814544U,0xAF5EBD09U,
0xBEE3D004U,0xDE334AFDU,0x660F2807U,0x192E4BB3U,0xC0CBA857U,0x45C8740FU,0xD20B5F39U,0xB9D3FBDBU,
0x5579C0BDU,0x1A60320AU,0xD6A100C6U,0x402C7279U,0x679F25FEU,0xFB1FA3CCU,0x8EA5E9F8U,0xDB3222F8U,
0x3C7516DFU,0xFD616B15U,0x2F501EC8U,0xAD0552ABU,0x323DB5FAU,0xFD238760U,0x53317B48U,0x3E00DF82U,
0x9E5C57BBU,0xCA6F8CA0U,0x1A87562EU,0xDF1769DBU,0xD542A8F6U,0x287EFFC3U,0xAC6732C6U,0x8C4F5573U,
0x695B27B0U,0xBBCA58C8U,0xE1FFA35DU,0xB8F011A0U,0x10FA3D98U,0xFD2183B8U,0x4AFCB56CU,0x2DD1D35BU,
0x9A53E479U,0xB6F84565U,0xD28E49BCU,0x4BFB9790U,0xE1DDF2DAU,0xA4CB7E33U,0x62FB1341U,0xCEE4C6E8U,
0xEF20CADAU,0x36774C01U,0xD07E9EFEU,0x2BF11FB4U,0x95DBDA4DU,0xAE909198U,0xEAAD8E71U,0x6B93D5A0U,
0xD08ED1D0U,0xAFC725E0U,0x8E3C5B2FU,0x8E7594B7U,0x8FF6E2FBU,0xF2122B64U,0x8888B812U,0x900DF01CU,
0x4FAD5EA0U,0x688FC31CU,0xD1CFF191U,0xB3A8C1ADU,0x2F2F2218U,0xBE0E1777U,0xEA752DFEU,0x8B021FA1U,
0xE5A0CC0FU,0xB56F74E8U,0x18ACF3D6U,0xCE89E299U,0xB4A84FE0U,0xFD13E0B7U,0x7CC43B81U,0xD2ADA8D9U,
0x165FA266U,0x80957705U,0x93CC7314U,0x211A1477U,0xE6AD2065U,0x77B5FA86U,0xC75442F5U,0xFB9D35CFU,
0xEBCDAF0CU,0x7B3E89A0U,0xD6411BD3U,0xAE1E7E49U,0x00250E2DU,0x2071B35EU,0x226800BBU,0x57B8E0AFU,
0x2464369BU,0xF009B91EU,0x5563911DU,0x59DFA6AAU,0x78C14389U,0xD95A537FU,0x207D5BA2U,0x02E5B9C5U,
0x83260376U,0x6295CFA9U,0x11C81968U,0x4E734A41U,0xB3472DCAU,0x7B14A94AU,0x1B510052U,0x9A532915U,
0xD60F573FU,0xBC9BC6E4U,0x2B60A476U,0x81E67400U,0x08BA6FB5U,0x571BE91FU,0xF296EC6BU,0x2A0DD915U,
0xB6636521U,0xE7B9F9B6U,0xFF34052EU,0xC5855664U,0x53B02D5DU,0xA99F8FA1U,0x08BA4799U,0x6E85076AU,
},{
0x4B7A70E9U,0xB5B32944U,0xDB75092EU,0xC4192623U,0xAD6EA6B0U,0x49A7DF7DU,0x9CEE60B8U,0x8FEDB266U,
0xECAA8C71U,0x699A17FFU,0x5664526CU,0xC2B19EE1U,0x193602A5U,0x75094C29U,0xA0591340U,0xE4183A3EU,
0x3F54989AU,0x5B429D65U,0x6B8FE4D6U,0x99F73FD6U,0xA1D29C07U,0xEFE830F5U,0x4D2D38E6U,0xF0255DC1U,
0x4CDD2086U,0x8470EB26U,0x6382E9C6U,0x021ECC5EU,0x09686B3FU,0x3EBAEFC9U,0x3C971814U,0x6B6A70A1U,
0x687F3584U,0x52A0E286U,0xB79C5305U,0xAA500737U,0x3E07841CU,0x7FDEAE5CU,0x8E7D44ECU,0x5716F2B8U,
0xB03ADA37U,0xF0500C0DU,0xF01C1F04U,0x0200B3FFU,0xAE0CF51AU,0x3CB574B2U,0x25837A58U,0xDC0921BDU,
0xD19113F9U,0x7CA92FF6U,0x94324773U,0x22F54701U,0x3AE5E581U,0x37C2DADCU,0xC8B57634U,0x9AF3DDA7U,
0xA9446146U,0x0FD0030EU,0xECC8C73EU,0xA4751E41U,0xE238CD99U,0x3BEA0E2FU,0x3280BBA1U,0x183EB331U,
0x4E548B38U,0x4F6DB908U,0x6F420D03U,0xF60A04BFU,0x2CB81290U,0x24977C79U,0x5679B072U,0xBCAF89AFU,
0xDE9A771FU,0xD9930810U,0xB38BAE12U,0xDCCF3F2EU,0x5512721FU,0x2E6B7124U,0x501ADDE6U,0x9F84CD87U,
0x7A584718U,0x7408DA17U,0xBC9F9ABCU,0xE94B7D8CU,0xEC7AEC3AU,0xDB851DFAU,0x63094366U,0xC464C3D2U,
0xEF1C1847U,0x3215D908U,0xDD433B37U,0x24C2BA16U,0x12A14D43U,0x2A65C451U,0x50940002U,0x133AE4DDU,
0x71DFF89EU,0x10314E55U,0x81AC77D6U,0x5F11199BU,0x043556F1U,0xD7A3C76BU,0x3C11183BU,0x5924A509U,
0xF28FE6EDU,0x97F1FBFAU,0x9EBABF2CU,0x1E153C6EU,0x86E34570U,0xEAE96FB1U,0x860E5E0AU,0x5A3E2AB3U,
0x771FE71CU,0x4E3D06FAU,0x2965DCB9U,0x99E71D0FU,0x803E89D6U,0x5266C825U,0x2E4CC978U,0x9C10B36AU,
0xC6150EBAU,0x94E2EA78U,0xA5FC3C53U,0x1E0A2DF4U,0xF2F74EA7U,0x361D2B3DU,0x1939260FU,0x19C27960U,
0x5223A708U,0xF71312B6U,0xEBADFE6EU,0xEAC31F66U,0xE3BC4595U,0xA67BC883U,0xB17F37D1U,0x018CFF28U,
0xC332DDEFU,0xBE6C5AA5U,0x65582185U,0x68AB9802U,0xEECEA50FU,0xDB2F953BU,0x2AEF7DADU,0x5B6E2F84U,
0x1521B628U,0x29076170U,0xECDD4775U,0x619F1510U,0x13CCA830U,0xEB61BD96U,0x0334FE1EU,0xAA0363CFU,
0xB5735C90U,0x4C70A239U,0xD59E9E0BU,0xCBAADE14U,0xEECC86BCU,0x60622CA7U,0x9CAB5CABU,0xB2F3846EU,
0x648B1EAFU,0x19BDF0CAU,0xA02369B9U,0x655ABB50U,0x40685A32U,0x3C2AB4B3U,0x319EE9D5U,0xC021B8F7U,
0x9B540B19U,0x875FA099U,0x95F7997EU,0x623D7DA8U,0xF837889AU,0x97E32D77U,0x11ED935FU,0x16681281U,
0x0E358829U,0xC7E61FD6U,0x96DEDFA1U,0x7858BA99U,0x57F584A5U,0x1B227263U,0x9B83C3FFU,0x1AC24696U,
0xCDB30AEBU,0x532E3054U,0x8FD948E4U,0x6DBC3128U,0x58EBF2EFU,0x34C6FFEAU,0xFE28ED61U,0xEE7C3C73U,
0x5D4A14D9U,0xE864B7E3U,0x42105D14U,0x203E13E0U,0x45EEE2B6U,0xA3AAABEAU,0xDB6C4F15U,0xFACB4FD0U,
0xC742F442U,0xEF6ABBB5U,0x654F3B1DU,0x41CD2105U,0xD81E799EU,0x86854DC7U,0xE44B476AU,0x3D816250U,
0xCF62A1F2U,0x5B8D2646U,0xFC8883A0U,0xC1C7B6A3U,0x7F1524C3U,0x69CB7492U,0x47848A0BU,0x5692B285U,
0x095BBF00U,0xAD19489DU,0x1462B174U,0x23820E00U,0x58428D2AU,0x0C55F5EAU,0x1DADF43EU,0x233F7061U,
0x3372F092U,0x8D937E41U,0xD65FECF1U,0x6C223BDBU,0x7CDE3759U,0xCBEE7460U,0x4085F2A7U,0xCE77326EU,
0xA6078084U,0x19F8509EU,0xE8EFD855U,0x61D99735U,0xA969A7AAU,0xC50C06C2U,0x5A04ABFCU,0x800BCADCU,
0x9E447A2EU,0xC3453484U,0xFDD56705U,0x0E1E9EC9U,0xDB73DBD3U,0x105588CDU,0x675FDA79U,0xE3674340U,
0xC5C43465U,0x713E38D8U,0x3D28F89EU,0xF16DFF20U,0x153E21E7U,0x8FB03D4AU,0xE6E39F2BU,0xDB83ADF7U,
},{
0xE93D5A68U,0x948140F7U,0xF64C261CU,0x94692934U,0x411520F7U,0x7602D4F7U,0xBCF46B2EU,0xD4A20068U,
0xD4082471U,0x3320F46AU,0x43B7D4B7U,0x500061AFU,0x1E39F62EU,0x97244546U,0x14214F74U,0xBF8B8840U,
0x4D95FC1DU,0x96B591AFU,0x70F4DDD3U,0x66A02F45U,0xBFBC09ECU,0x03BD9785U,0x7FAC6DD0U,0x31CB8504U,
0x96EB27B3U,0x55FD3941U,0xDA2547E6U,0xABCA0A9AU,0x28507825U,0x530429F4U,0x0A2C86DAU,0xE9B66DFBU,
0x68DC1462U,0xD7486900U,0x680EC0A4U,0x27A18DEEU,0x4F3FFEA2U,0xE887AD8CU,0xB58CE006U,0x7AF4D6B6U,
0xAACE1E7CU,0xD3375FECU,0xCE78A399U,0x406B2A42U,0x20FE9E35U,0xD9F385B9U,0xEE39D7ABU,0x3B124E8BU,
0x1DC9FAF7U,0x4B6D1856U,0x26A36631U,0xEAE397B2U,0x3A6EFA74U,0xDD5B4332U,0x6841E7F7U,0xCA7820FBU,
0xFB0AF54EU,0xD8FEB397U,0x454056ACU,0xBA489527U,0x55533A3AU,0x20838D87U,0xFE6BA9B7U,0xD096954BU,
0x55A867BCU,0xA1159A58U,0xCCA92963U,0x99E1DB33U,0xA62A4A56U,0x3F3125F9U,0x5EF47E1CU,0x9029317CU,
0xFDF8E802U,0x04272F70U,0x80BB155CU,0x05282CE3U,0x95C11548U,0xE4C66D22U,0x48C1133FU,0xC70F86DCU,
0x07F9C9EEU,0x41041F0FU,0x404779A4U,0x5D886E17U,0x325F51EBU,0xD59BC0D1U,0xF2BCC18FU,0x41113564U,
0x257B7834U,0x602A9C60U,0xDFF8E8A3U,0x1F636C1BU,0x0E12B4C2U,0x02E1329EU,0xAF664FD1U,0xCAD18115U,
0x6B2395E0U,0x333E92E1U,0x3B240B62U,0xEEBEB922U,0x85B2A20EU,0xE6BA0D99U,0xDE720C8CU,0x2DA2F728U,
0xD0127845U,0x95B794FDU,0x647D0862U,0xE7CCF5F0U,0x5449A36FU,0x877D48FAU,0xC39DFD27U,0xF33E8D1EU,
0x0A476341U,0x992EFF74U,0x3A6F6EABU,0xF4F8FD37U,0xA812DC60U,0xA1EBDDF8U,0x991BE14CU,0xDB6E6B0DU,
0xC67B5510U,0x6D672C37U,0x2765D43BU,0xDCD0E804U,0xF1290DC7U,0xCC00FFA3U,0xB5390F92U,0x690FED0BU,
0x667B9FFBU,0xCEDB7D9CU,0xA091CF0BU,0xD9155EA3U,0xBB132F88U,0x515BAD24U,0x7B9479BFU,0x763BD6EBU,
0x37392EB3U,0xCC115979U,0x8026E297U,0xF42E312DU,0x6842ADA7U,0xC66A2B3BU,0x12754CCCU,0x782EF11CU,
0x6A124237U,0xB79251E7U,0x06A1BBE6U,0x4BFB6350U,0x1A6B1018U,0x11CAEDFAU,0x3D25BDD8U,0xE2E1C3C9U,
0x44421659U,0x0A121386U,0xD90CEC6EU,0xD5ABEA2AU,0x64AF674EU,0xDA86A85FU,0xBEBFE988U,0x64E4C3FEU,
0x9DBC8057U,0xF0F7C086U,0x60787BF8U,0x6003604DU,0xD1FD8346U,0xF6381FB0U,0x7745AE04U,0xD736FCCCU,
0x83426B33U,0xF01EAB71U,0xB0804187U,0x3C005E5FU,0x77A057BEU,0xBDE8AE24U,0x55464299U,0xBF582E61U,
0x4E58F48FU,0xF2DDFDA2U,0xF474EF38U,0x8789BDC2U,0x5366F9C3U,0xC8B38E74U,0xB475F255U,0x46FCD9B9U,
0x7AEB2661U,0x8B1DDF84U,0x846A0E79U,0x915F95E2U,0x466E598EU,0x20B45770U,0x8CD55591U,0xC902DE4CU,
0xB90BACE1U,0xBB8205D0U,0x11A86248U,0x7574A99EU,0xB77F19B6U,0xE0A9DC09U,0x662D09A1U,0xC4324633U,
0xE85A1F02U,0x09F0BE8CU,0x4A99A025U,0x1D6EFE10U,0x1AB93D1DU,0x0BA5A4DFU,0xA186F20FU,0x2868F169U,
0xDCB7DA83U,0x573906FEU,0xA1E2CE9BU,0x4FCD7F52U,0x50115E01U,0xA70683FAU,0xA002B5C4U,0x0DE6D027U,
0x9AF88C27U,0x773F8641U,0xC3604C06U,0x61A806B5U,0xF0177A28U,0xC0F586E0U,0x006058AAU,0x30DC7D62U,
0x11E69ED7U,0x2338EA63U,0x53C2DD94U,0xC2C21634U,0xBBCBEE56U,0x90BCB6DEU,0xEBFC7DA1U,0xCE591D76U,
0x6F05E409U,0x4B7C0188U,0x39720A3DU,0x7C927C24U,0x86E3725FU,0x724D9DB9U,0x1AC15BB4U,0xD39EB8FCU,
0xED545578U,0x08FCA5B5U,0xD83D7CD3U,0x4DAD0FC4U,0x1E50EF5EU,0xB161E6F8U,0xA28514D9U,0x6C51133CU,
0x6FD5C7E7U,0x56E14EC4U,0x362ABFCEU,0xDDC6C837U,0xD79A3234U,0x92638212U,0x670EFA8EU,0x406000E0U,
},{
0x3A39CE37U,0xD3FAF5CFU,0xABC27737U,0x5AC52D1BU,0x5CB0679EU,0x4FA33742U,0xD3822740U,0x99BC9BBEU,
0xD5118E9DU,0xBF0F7315U,0xD62D1C7EU,0xC700C47BU,0xB78C1B6BU,0x21A19045U,0xB26EB1BEU,0x6A366EB4U,
0x5748AB2FU,0xBC946E79U,0xC6A376D2U,0x6549C2C8U,0x530FF8EEU,0x468DDE7DU,0xD5730A1DU,0x4CD04DC6U,
0x2939BBDBU,0xA9BA4650U,0xAC9526E8U,0xBE5EE304U,0xA1FAD5F0U,0x6A2D519AU,0x63EF8CE2U,0x9A86EE22U,
0xC089C2B8U,0x43242EF6U,0xA51E03AAU,0x9CF2D0A4U,0x83C061BAU,0x9BE96A4DU,0x8FE51550U,0xBA645BD6U,
0x2826A2F9U,0xA73A3AE1U,0x4BA99586U,0xEF5562E9U,0xC72FEFD3U,0xF752F7DAU,0x3F046F69U,0x77FA0A59U,
0x80E4A915U,0x87B08601U,0x9B09E6ADU,0x3B3EE593U,0xE990FD5AU,0x9E34D797U,0x2CF0B7D9U,0x022B8B51U,
0x96D5AC3AU,0x017DA67DU,0xD1CF3ED6U,0x7C7D2D28U,0x1F9F25CFU,0xADF2B89BU,0x5AD6B472U,0x5A88F54CU,
0xE029AC71U,0xE019A5E6U,0x47B0ACFDU,0xED93FA9BU,0xE8D3C48DU,0x283B57CCU,0xF8D56629U,0x79132E28U,
0x785F0191U,0xED756055U,0xF7960E44U,0xE3D35E8CU,0x15056DD4U,0x88F46DBAU,0x03A16125U,0x0564F0BDU,
0xC3EB9E15U,0x3C9057A2U,0x97271AECU,0xA93A072AU,0x1B3F6D9BU,0x1E6321F5U,0xF59C66FBU,0x26DCF319U,
0x7533D928U,0xB155FDF5U,0x03563482U,0x8ABA3CBBU,0x28517711U,0xC20AD9F8U,0xABCC5167U,0xCCAD925FU,
0x4DE81751U,0x3830DC8EU,0x379D5862U,0x9320F991U,0xEA7A90C2U,0xFB3E7BCEU,0x5121CE64U,0x774FBE32U,
0xA8B6E37EU,0xC3293D46U,0x48DE5369U,0x6413E680U,0xA2AE0810U,0xDD6DB224U,0x69852DFDU,0x09072166U,
0xB39A460AU,0x6445C0DDU,0x586CDECFU,0x1C20C8AEU,0x5BBEF7DDU,0x1B588D40U,0xCCD2017FU,0x6BB4E3BBU,
0xDDA26A7EU,0x3A59FF45U,0x3E350A44U,0xBCB4CDD5U,0x72EACEA8U,0xFA6484BBU,0x8D6612AEU,0xBF3C6F47U,
0xD29BE463U,0x542F5D9EU,0xAEC2771BU,0xF64E6370U,0x740E0D8DU,0xE75B1357U,0xF8721671U,0xAF537D5DU,
0x4040CB08U,0x4EB4E2CCU,0x34D2466AU,0x0115AF84U,0xE1B00428U,0x95983A1DU,0x06B89FB4U,0xCE6EA048U,
0x6F3F3B82U,0x3520AB82U,0x011A1D4BU,0x277227F8U,0x611560B1U,0xE7933FDCU,0xBB3A792BU,0x344525BDU,
0xA08839E1U,0x51CE794BU,0x2F32C9B7U,0xA01FBAC9U,0xE01CC87EU,0xBCC7D1F6U,0xCF0111C3U,0xA1E8AAC7U,
0x1A908749U,0xD44FBD9AU,0xD0DADECBU,0xD50ADA38U,0x0339C32AU,0xC6913667U,0x8DF9317CU,0xE0B12B4FU,
0xF79E59B7U,0x43F5BB3AU,0xF2D519FFU,0x27D9459CU,0xBF97222CU,0x15E6FC2AU,0x0F91FC71U,0x9B941525U,
0xFAE59361U,0xCEB69CEBU,0xC2A86459U,0x12BAA8D1U,0xB6C1075EU,0xE3056A0CU,0x10D25065U,0xCB03A442U,
0xE0EC6E0EU,0x1698DB3BU,0x4C98A0BEU,0x3278E964U,0x9F1F9532U,0xE0D392DFU,0xD3A0342BU,0x8971F21EU,
0x1B0A7441U,0x4BA3348CU,0xC5BE7120U,0xC37632D8U,0xDF359F8DU,0x9B992F2EU,0xE60B6F47U,0x0FE3F11DU,
0xE54CDA54U,0x1EDAD891U,0xCE6279CFU,0xCD3E7E6FU,0x1618B166U,0xFD2C1D05U,0x848FD2C5U,0xF6FB2299U,
0xF523F357U,0xA6327623U,0x93A83531U,0x56CCCD02U,0xACF08162U,0x5A75EBB5U,0x6E163697U,0x88D273CCU,
0xDE966292U,0x81B949D0U,0x4C50901BU,0x71C65614U,0xE6C6C7BDU,0x327A140AU,0x45E1D006U,0xC3F27B9AU,
0xC9AA53FDU,0x62A80F00U,0xBB25BFE2U,0x35BDD2F6U,0x71126905U,0xB2040222U,0xB6CBCF7CU,0xCD769C2BU,
0x53113EC0U,0x1640E3D3U,0x38ABBD60U,0x2547ADF0U,0xBA38209CU,0xF746CE76U,0x77AFA1C5U,0x20756060U,
0x85CBFE4EU,0x8AE88DD8U,0x7AAAF9B0U,0x4CF9AA7EU,0x1948C25CU,0x02FB8A8CU,0x01C36AE4U,0xD6EBE1F9U,
0x90D4F869U,0xA65CDEA0U,0x3F09252DU,0xC208E69FU,0xB74E6132U,0xCE77E25BU,0x578FDFE3U,0x3AC372E6U
}
};

View File

@@ -0,0 +1,112 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/BLOWFISH.H $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BLOWFISH_H
#define BLOWFISH_H
#include <limits.h>
/*
** The "bool" integral type was defined by the C++ committee in
** November of '94. Until the compiler supports this, use the following
** definition.
*/
#include "bool.h"
/*
** This engine will process data blocks by encryption and decryption.
** The "Blowfish" algorithm is in the public domain. It uses
** a Feistal network (similar to IDEA). It has no known
** weaknesses, but is still relatively new. Blowfish is particularly strong
** against brute force attacks. It is also quite strong against linear and
** differential cryptanalysis. Unlike public key encription, it is very
** fast at encryption, as far as cryptography goes. Its weakness is that
** it takes a relatively long time to set up with a new key (1/100th of
** a second on a P6-200). The time to set up a key is equivalent to
** encrypting 4240 bytes.
*/
class BlowfishEngine {
public:
BlowfishEngine(void) : IsKeyed(false) {}
~BlowfishEngine(void);
void Submit_Key(void const * key, int length);
int Encrypt(void const * plaintext, int length, void * cyphertext);
int Decrypt(void const * cyphertext, int length, void * plaintext);
/*
** This is the maximum key length supported.
*/
enum {MAX_KEY_LENGTH=56};
private:
bool IsKeyed;
void Sub_Key_Encrypt(unsigned long & left, unsigned long & right);
void Process_Block(void const * plaintext, void * cyphertext, unsigned long const * ptable);
void Initialize_Tables(void);
enum {
ROUNDS = 16, // Feistal round count (16 is standard).
BYTES_PER_BLOCK=8 // The number of bytes in each cypher block (don't change).
};
/*
** Initialization data for sub keys. The initial values are constant and
** filled with a number generated from pi. Thus they are not random but
** they don't hold a weak pattern either.
*/
static unsigned long const P_Init[ROUNDS+2];
static unsigned long const S_Init[4][UCHAR_MAX+1];
/*
** Permutation tables for encryption and decryption.
*/
unsigned long P_Encrypt[ROUNDS+2];
unsigned long P_Decrypt[ROUNDS+2];
/*
** S-Box tables (four).
*/
unsigned long bf_S[4][UCHAR_MAX+1];
};
#endif

View File

@@ -0,0 +1,83 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/blowpipe.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BLOWPIPE_H
#define BLOWPIPE_H
#include "pipe.h"
#include "blowfish.h"
/*
** Performs Blowfish encryption/decryption on the data stream that is piped
** through this class.
*/
class BlowPipe : public Pipe
{
public:
typedef enum CryptControl {
ENCRYPT,
DECRYPT
} CryptControl;
BlowPipe(CryptControl control) : BF(NULL), Counter(0), Control(control) {}
virtual ~BlowPipe(void) {delete BF;BF = NULL;}
virtual int Flush(void);
virtual int Put(void const * source, int slen);
// Submit key for blowfish engine.
void Key(void const * key, int length);
protected:
/*
** The Blowfish engine used for encryption/decryption. If this pointer is
** NULL, then this indicates that the blowfish engine is not active and no
** key has been submitted. All data would pass through this pipe unchanged
** in that case.
*/
BlowfishEngine * BF;
private:
char Buffer[8];
int Counter;
CryptControl Control;
BlowPipe(BlowPipe & rvalue);
BlowPipe & operator = (BlowPipe const & pipe);
};
#endif

View File

@@ -0,0 +1,85 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/BLWSTRAW.H $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BLWSTRAW_H
#define BLWSTRAW_H
#include "straw.h"
#include "blowfish.h"
/*
** Performs Blowfish encryption/decryption to the data that is drawn through this straw. The
** process is controlled by the key which must be submitted to the class before any data
** manipulation will occur. The Blowfish algorithm is symmetric, thus the same key is used
** for encryption as is for decryption.
*/
class BlowStraw : public Straw
{
public:
typedef enum CryptControl {
ENCRYPT,
DECRYPT
} CryptControl;
BlowStraw(CryptControl control) : BF(NULL), Counter(0), Control(control) {}
virtual ~BlowStraw(void) {delete BF;BF = NULL;}
virtual int Get(void * source, int slen);
// Submit key for blowfish engine.
void Key(void const * key, int length);
protected:
/*
** The Blowfish engine used for encryption/decryption. If this pointer is
** NULL, then this indicates that the blowfish engine is not active and no
** key has been submitted. All data would pass through this straw unchanged
** in that case.
*/
BlowfishEngine * BF;
private:
char Buffer[8];
int Counter;
CryptControl Control;
BlowStraw(BlowStraw & rvalue);
BlowStraw & operator = (BlowStraw const & straw);
};
#endif

View File

@@ -0,0 +1,64 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/bool.h $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 9/23/99 1:46p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#if !defined(TRUE_FALSE_DEFINED) && !defined(__BORLANDC__) && (_MSC_VER < 1100) && !defined(__WATCOMC__)
#define TRUE_FALSE_DEFINED
/**********************************************************************
** The "bool" integral type was defined by the C++ comittee in
** November of '94. Until the compiler supports this, use the following
** definition.
*/
#ifdef _MSC_VER
#include "yvals.h"
#define bool unsigned
#elif defined(_UNIX)
/////#define bool unsigned
#else
enum {false=0,true=1};
typedef int bool;
#endif
#endif

View File

@@ -0,0 +1,48 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/borlandc.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:57a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#if !defined(BORLANDC_H) && defined(__BORLANDC__)
#define BORLANDC_H
/*
** Funny, but there are no required overrides to make Borland C match C++ standards. This
** is because Borland C more closely matches the C++ standard than the other compilers.
*/
#endif

View File

@@ -0,0 +1,61 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/bound.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:58a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef BOUND_H
#define BOUND_H
template<class T> inline
T Bound(T original, T minval, T maxval)
{
if (original < minval) return(minval);
if (original > maxval) return(maxval);
return(original);
};
#if defined(__WATCOMC__)
//int Bound(int, int, int);
//signed int Bound(signed int, signed int, signed int);
//unsigned Bound(unsigned, unsigned, unsigned);
//long Bound(long, long, long);
//float Bound(float, float, float);
//double Bound(double, double, double);
#endif
#endif

View File

@@ -0,0 +1,87 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/bsurface.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:59a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef BSURFACE_H
#define BSURFACE_H
#include "buff.h"
#include "xsurface.h"
/*
** This class handles a simple surface that exists in system RAM.
*/
class BSurface : public XSurface
{
public:
BSurface(int width, int height, int bbp, void * buffer=NULL) :
XSurface(width, height),
BBP(bbp),
Buff(buffer, width * height * bbp)
{
}
/*
** Gets and frees a direct pointer to the buffer.
*/
virtual void * Lock(Point2D point = Point2D(0, 0)) const
{
XSurface::Lock();
return(((char*)Buff.Get_Buffer()) + point.Y * Stride() + point.X * Bytes_Per_Pixel());
}
/*
** Queries information about the surface.
*/
virtual int Bytes_Per_Pixel(void) const {return(BBP);}
virtual int Stride(void) const {return(Get_Width() * BBP);}
protected:
/*
** Recorded bytes per pixel (used when determining pixel positions).
*/
int BBP;
/*
** Tracks the buffer that this surface represents.
*/
Buffer Buff;
};
#endif

View File

@@ -0,0 +1,231 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/BUFF.CPP $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/15/99 10:14a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Buffer::Buffer -- Constructor for buffer object. *
* Buffer::Buffer -- Copy constructor for buffer object. *
* Buffer::Buffer -- Self-allocating constructor for buffer object. *
* Buffer::Reset -- Clears the buffer object to null state. *
* Buffer::operator = -- Assignment operator for the buffer object. *
* Buffer::~Buffer -- Destructor for buffer object. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "buff.h"
//#include <stddef.h>
/***********************************************************************************************
* Buffer::Buffer -- Constructor for buffer object. *
* *
* This is the normal constructor for a buffer object. The buffer pointer and size are *
* specified as parameters. *
* *
* INPUT: buffer -- Pointer to the buffer. *
* *
* size -- The size of the buffer. *
* *
* OUTPUT: none *
* *
* WARNINGS: It is possible to construct a Buffer object that has a pointer but a size *
* value of zero. The Buffer object can still be used for its pointer, but it *
* any function that requires a size will fail. *
* *
* HISTORY: *
* 07/29/1996 JLB : Created. *
*=============================================================================================*/
Buffer::Buffer(void * buffer, long size) :
BufferPtr(buffer),
Size(size),
IsAllocated(false)
{
if (buffer == NULL && size > 0) {
BufferPtr = W3DNEWARRAY char[size];
IsAllocated = true;
}
}
// Alternate constructor for char * pointer.
Buffer::Buffer(char * buffer, long size) :
BufferPtr(buffer),
Size(size),
IsAllocated(false)
{
if (buffer == NULL && size > 0) {
BufferPtr = W3DNEWARRAY char[size];
IsAllocated = true;
}
}
// Alternate constructor for void const * pointer.
Buffer::Buffer(void const * buffer, long size) :
BufferPtr((void*)buffer),
Size(size),
IsAllocated(false)
{
if (buffer == NULL && size > 0) {
BufferPtr = W3DNEWARRAY char[size];
IsAllocated = true;
}
}
/***********************************************************************************************
* Buffer::Buffer -- Self-allocating constructor for buffer object. *
* *
* This construtor for a buffer object will automatically allocate the bytes necessary *
* to fulfill the size requested. This object is also responsible for deleting the buffer *
* it allocated. *
* *
* INPUT: size -- The size of the buffer to allocated. *
* *
* OUTPUT: none *
* *
* WARNINGS: There is no way to tell if the allocation failed. To verify, call Get_Buffer *
* and compare with NULL. *
* *
* HISTORY: *
* 07/29/1996 JLB : Created. *
*=============================================================================================*/
Buffer::Buffer(long size) :
BufferPtr(NULL),
Size(size),
IsAllocated(false)
{
if (size > 0) {
BufferPtr = W3DNEWARRAY char[size];
IsAllocated = true;
}
}
/***********************************************************************************************
* Buffer::Buffer -- Copy constructor for buffer object. *
* *
* This will make a duplicate of the specified buffer object. The ownership of the pointer *
* remains with the original object. This prevents multiple deletion of the same pointer. *
* *
* INPUT: buffer -- Reference to the buffer object to be dupilcated. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/02/1996 JLB : Created. *
*=============================================================================================*/
Buffer::Buffer(Buffer const & buffer) :
IsAllocated(false)
{
BufferPtr = buffer.BufferPtr;
Size = buffer.Size;
}
/***********************************************************************************************
* Buffer::operator = -- Assignment operator for the buffer object. *
* *
* This will make a duplicate of the buffer object specified. Any buffer pointed to by the *
* left hand buffer will be lost (possibley freed as a result). *
* *
* INPUT: buffer -- Reference to the right hand buffer object. *
* *
* OUTPUT: Returns with a reference to the copied buffer object. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/02/1996 JLB : Created. *
*=============================================================================================*/
Buffer & Buffer::operator = (Buffer const & buffer)
{
if (&buffer != this) {
if (IsAllocated) {
delete [] BufferPtr;
}
IsAllocated = false;
BufferPtr = buffer.BufferPtr;
Size = buffer.Size;
}
return(*this);
}
/***********************************************************************************************
* Buffer::~Buffer -- Destructor for buffer object. *
* *
* This destructor will free any buffer it is responsible for. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/29/1996 JLB : Created. *
*=============================================================================================*/
Buffer::~Buffer(void)
{
Reset();
}
/***********************************************************************************************
* Buffer::Reset -- Clears the buffer object to null state. *
* *
* This routine will bring the buffer object into a null (newly constructed) state. If *
* there was any buffer allocated or referred to by this object, it will be freed or *
* dereferenced as necessary. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: This routine will free the buffer if it is responsible for doing so when *
* it is no longer referenced. *
* *
* HISTORY: *
* 09/07/1996 JLB : Created. *
*=============================================================================================*/
void Buffer::Reset(void)
{
if (IsAllocated) {
delete [] BufferPtr;
}
BufferPtr = NULL;
Size = 0;
IsAllocated = false;
}

View File

@@ -0,0 +1,252 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/bufffile.cpp $*
* *
* $Author:: Naty_h $*
* *
* $Modtime:: 4/20/01 4:23p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "bufffile.h"
#include "wwdebug.h"
#include <string.h>
int BufferedFileClass::_DesiredBufferSize = 1024;
/***********************************************************************************************
* BufferedFileClass::BufferedFileClass -- Default constructor for a file object. *
*=============================================================================================*/
BufferedFileClass::BufferedFileClass(void) :
RawFileClass(),
Buffer( NULL ),
BufferSize( 0 ),
BufferAvailable( 0 ),
BufferOffset( 0 )
{
}
/***********************************************************************************************
* BufferedFileClass::BufferedFileClass -- Simple constructor for a file object. *
*=============================================================================================*/
BufferedFileClass::BufferedFileClass(char const * filename) :
RawFileClass( filename ),
Buffer( NULL ),
BufferSize( 0 ),
BufferAvailable( 0 ),
BufferOffset( 0 )
{
}
/***********************************************************************************************
* BufferedFileClass::~BufferedFileClass -- Default deconstructor for a file object. *
*=============================================================================================*/
BufferedFileClass::~BufferedFileClass(void)
{
Reset_Buffer();
}
/***********************************************************************************************
* BufferedFileClass::Close -- Perform a closure of the file. *
*=============================================================================================*/
void BufferedFileClass::Close(void)
{
BASECLASS::Close();
Reset_Buffer();
}
/***********************************************************************************************
* BufferedFileClass::Read -- Reads the specified number of bytes into a memory buffer. *
* *
* This routine will read the specified number of bytes and place the data into the buffer *
* indicated. It is legal to call this routine with a request for more bytes than are in *
* the file. This condition can result in fewer bytes being read than requested. Determine *
* this by examining the return value. *
* *
* INPUT: buffer -- Pointer to the buffer to read data into. If NULL is passed, no read *
* is performed. *
* *
* size -- The number of bytes to read. If NULL is passed, then no read is *
* performed. *
* *
* OUTPUT: Returns with the number of bytes read into the buffer. If this number is less *
* than requested, it indicates that the file has been exhausted. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/18/1994 JLB : Created. *
*=============================================================================================*/
int BufferedFileClass::Read(void * buffer, int size)
{
int read = 0;
// If there is anything in the buffer, copy it in.
if ( BufferAvailable > 0 ) {
int amount = min( size, BufferAvailable );
::memcpy( buffer, &Buffer[BufferOffset], amount );
BufferAvailable -= amount;
BufferOffset += amount;
size -= amount;
buffer = (char *)buffer + amount;
read += amount;
}
if ( size == 0 ) {
return read;
}
// We need to get a copy of the _DesiredBufferSize into
// a local variable to protect us from modifications
// from another thread. Otherwise, we could pass the test
// (size > amount) below, only to allocate a buffer that's
// too small in the next block. (DRM, 04/20/01)
int desired_buffer_size = _DesiredBufferSize;
// If we need more than the buffer will hold, just read it
int amount = BufferSize;
if ( amount == 0 ) {
amount = desired_buffer_size;
}
if ( size > amount ) {
return BASECLASS::Read( buffer, size ) + read;
}
// If we dont have a buffer, get one
if ( BufferSize == 0 ) {
BufferSize = desired_buffer_size;
Buffer = W3DNEWARRAY unsigned char [BufferSize];
BufferAvailable = 0;
BufferOffset = 0;
}
// Fill the buffer
if ( BufferAvailable == 0 ) {
BufferAvailable = BASECLASS::Read( Buffer, BufferSize );
BufferOffset = 0;
}
// If there is anything in the buffer, copy it in.
if ( BufferAvailable > 0 ) {
int amount = min( size, BufferAvailable );
::memcpy( buffer, &Buffer[BufferOffset], amount );
BufferAvailable -= amount;
BufferOffset += amount;
read += amount;
}
return read;
}
/***********************************************************************************************
* BufferedFileClass::Write -- Writes the specified data to the buffer specified. *
* *
* This routine will write the data specified to the file. *
* *
* INPUT: buffer -- The buffer that holds the data to write. *
* *
* size -- The number of bytes to write to the file. *
* *
* OUTPUT: Returns with the number of bytes written to the file. This routine catches the *
* case of a disk full condition, so this routine will always return with the number *
* matching the size request. *
* *
* WARNINGS: A fatal file condition could cause this routine to never return. *
* *
* HISTORY: *
* 10/18/1994 JLB : Created. *
*=============================================================================================*/
int BufferedFileClass::Write(void const * buffer, int size)
{
if ( BufferSize != 0 ) {
WWASSERT( 0 );
}
return BASECLASS::Write( buffer, size );
}
/***********************************************************************************************
* BufferedFileClass::Seek -- Reposition the file pointer as indicated. *
* *
* Use this routine to move the filepointer to the position indicated. It can move either *
* relative to current position or absolute from the beginning or ending of the file. This *
* routine will only return if it successfully performed the seek. *
* *
* INPUT: pos -- The position to seek to. This is interpreted as relative to the position *
* indicated by the "dir" parameter. *
* *
* dir -- The relative position to relate the seek to. This can be either SEEK_SET *
* for the beginning of the file, SEEK_CUR for the current position, or *
* SEEK_END for the end of the file. *
* *
* OUTPUT: This routine returns the position that the seek ended up at. *
* *
* WARNINGS: If there was a file error, then this routine might never return. *
* *
* HISTORY: *
* 10/18/1994 JLB : Created. *
*=============================================================================================*/
int BufferedFileClass::Seek(int pos, int dir)
{
if ( (dir != SEEK_CUR) || (pos < 0) ) {
Reset_Buffer();
}
// If not buffered, pass through
if ( BufferAvailable == 0 ) {
return BASECLASS::Seek( pos, dir );
}
// use up what we can of the buffer
int amount = min( pos, BufferAvailable );
pos -= amount;
BufferAvailable -= amount;
BufferOffset += amount;
return BASECLASS::Seek( pos, dir ) - BufferAvailable;
}
/*
**
*/
void BufferedFileClass::Reset_Buffer( void )
{
if ( Buffer != NULL ) {
delete [] Buffer;
Buffer = NULL;
BufferSize = 0;
BufferAvailable = 0;
BufferOffset = 0;
}
}

View File

@@ -0,0 +1,85 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/bufffile.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 5/02/00 11:09a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* RawFileClass::File_Name -- Returns with the filename associate with the file object. *
* RawFileClass::RawFileClass -- Default constructor for a file object. *
* RawFileClass::~RawFileClass -- Default deconstructor for a file object. *
* RawFileClass::Is_Open -- Checks to see if the file is open or not. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef BUFFFILE_H
#define BUFFFILE_H
#include "rawfile.h"
/*
** This is the definition of a buffered read raw file class.
*/
class BufferedFileClass : public RawFileClass
{
typedef RawFileClass BASECLASS;
public:
BufferedFileClass(char const *filename);
BufferedFileClass(void);
BufferedFileClass (RawFileClass const & f);
BufferedFileClass & operator = (BufferedFileClass const & f);
virtual ~BufferedFileClass(void);
virtual int Read(void *buffer, int size);
virtual int Seek(int pos, int dir=SEEK_CUR);
virtual int Write(void const *buffer, int size);
virtual void Close(void);
protected:
void Reset_Buffer( void );
static void Set_Desired_Buffer_Size( int size ) { _DesiredBufferSize = size; }
private:
unsigned char * Buffer; // The read buffer
unsigned int BufferSize; // The allocated size of the read buffer
int BufferAvailable; // The amount of data in the read buffer
int BufferOffset; // The data already given out
static int _DesiredBufferSize;
};
#endif

View File

@@ -0,0 +1,796 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/wwlib/chunkio.cpp 11 7/12/01 7:44p Jani_p $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Tiberian Sun / Commando / G Library *
* *
* $Archive:: /Commando/Code/wwlib/chunkio.cpp $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 7/10/01 7:38p $*
* *
* $Revision:: 11 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* ChunkSaveClass::ChunkSaveClass -- Constructor *
* ChunkSaveClass::Begin_Chunk -- Begin a new chunk in the file *
* ChunkSaveClass::End_Chunk -- Close a chunk, computes the size and adds to the header *
* ChunkSaveClass::Begin_Micro_Chunk -- begins a new "micro-chunk" *
* ChunkSaveClass::End_Micro_Chunk -- close a micro-chunk *
* ChunkSaveClass::Write -- Write data into the current chunk *
* ChunkSaveClass::Write -- write an IOVector2Struct *
* ChunkSaveClass::Write -- write an IOVector3Struct *
* ChunkSaveClass::Write -- write an IOVector4Struct *
* ChunkSaveClass::Write -- write an IOQuaternionStruct *
* ChunkSaveClass::Cur_Chunk_Depth -- returns the current chunk recursion depth (debugging) *
* ChunkLoadClass::ChunkLoadClass -- Constructor *
* ChunkLoadClass::Open_Chunk -- Open a chunk in the file, reads in the chunk header *
* ChunkLoadClass::Close_Chunk -- Close a chunk, seeks to the end if needed *
* ChunkLoadClass::Cur_Chunk_ID -- Returns the ID of the current chunk *
* ChunkLoadClass::Cur_Chunk_Length -- Returns the current length of the current chunk *
* ChunkLoadClass::Cur_Chunk_Depth -- returns the current chunk recursion depth *
* ChunkLoadClass::Contains_Chunks -- Test whether the current chunk contains chunks (or dat *
* ChunkLoadClass::Open_Micro_Chunk -- reads in a micro-chunk header *
* ChunkLoadClass::Close_Micro_Chunk -- closes a micro-chunk *
* ChunkLoadClass::Cur_Micro_Chunk_ID -- returns the ID of the current micro-chunk (asserts *
* ChunkLoadClass::Cur_Micro_Chunk_Length -- returns the size of the current micro chunk *
* ChunkLoadClass::Read -- Read data from the file *
* ChunkLoadClass::Read -- read an IOVector2Struct *
* ChunkLoadClass::Read -- read an IOVector3Struct *
* ChunkLoadClass::Read -- read an IOVector4Struct *
* ChunkLoadClass::Read -- read an IOQuaternionStruct *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "chunkio.h"
#include <string.h>
#include <assert.h>
/***********************************************************************************************
* ChunkSaveClass::ChunkSaveClass -- Constructor *
* *
* INPUT: *
* file - pointer to a FileClass object to write to *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
ChunkSaveClass::ChunkSaveClass(FileClass * file) :
File(file),
StackIndex(0),
InMicroChunk(false),
MicroChunkPosition(0)
{
memset(PositionStack,0,sizeof(PositionStack));
memset(HeaderStack,0,sizeof(HeaderStack));
memset(&MCHeader,0,sizeof(MCHeader));
}
/***********************************************************************************************
* ChunkSaveClass::Begin_Chunk -- Begin a new chunk in the file *
* *
* INPUT: *
* id - id of the chunk *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
bool ChunkSaveClass::Begin_Chunk(uint32 id)
{
ChunkHeader chunkh;
int filepos;
// If we have a parent chunk, set its 'Contains_Chunks' flag
if (StackIndex > 0) {
HeaderStack[StackIndex-1].Set_Sub_Chunk_Flag(true);
}
// Save the current file position and chunk header
// for the call to End_Chunk.
chunkh.Set_Type(id);
chunkh.Set_Size(0);
filepos = File->Seek(0);
PositionStack[StackIndex] = filepos;
HeaderStack[StackIndex] = chunkh;
StackIndex++;
// write a temporary chunk header (size = 0)
if (File->Write(&chunkh,sizeof(chunkh)) != sizeof(chunkh)) {
return false;
}
return true;
}
/***********************************************************************************************
* ChunkSaveClass::End_Chunk -- Close a chunk, computes the size and adds to the header *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
bool ChunkSaveClass::End_Chunk(void)
{
// If the user didn't close his micro chunks bad things are gonna happen
assert(!InMicroChunk);
// Save the current position
int curpos = File->Seek(0);
// Pop the position and chunk header off the stacks
StackIndex--;
int chunkpos = PositionStack[StackIndex];
ChunkHeader chunkh = HeaderStack[StackIndex];
// write the completed header
File->Seek(chunkpos,SEEK_SET);
if (File->Write(&chunkh,sizeof(chunkh)) != sizeof(chunkh)) {
return false;
}
// Add the total bytes written to any encompasing chunk
if (StackIndex != 0) {
HeaderStack[StackIndex-1].Add_Size(chunkh.Get_Size() + sizeof(chunkh));
}
// Go back to the end of the file
File->Seek(curpos,SEEK_SET);
return true;
}
/***********************************************************************************************
* ChunkSaveClass::Begin_Micro_Chunk -- begins a new "micro-chunk" *
* *
* Micro chunks are used to wrap individual variables. They aren't hierarchical so if you *
* attempt to open a micro chunk while already in one, an assert will occur. *
* *
* INPUT: *
* id - 8bit id *
* *
* OUTPUT: *
* *
* WARNINGS: *
* id is asserted to be between 0 and 255 *
* cannot nest micro chunks so it asserts that you are currently not in another micro-chunk *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
bool ChunkSaveClass::Begin_Micro_Chunk(uint32 id)
{
assert(id < 256);
assert(!InMicroChunk);
// Save the current file position and chunk header
// for the call to End_Micro_Chunk.
MCHeader.Set_Type(id);
MCHeader.Set_Size(0);
MicroChunkPosition = File->Seek(0);
// Write a temporary chunk header
// NOTE: I'm calling the ChunkSaveClass::Write method so that the bytes for
// this header are tracked in the wrapping chunk. This is because micro-chunks
// are simply data inside the normal chunks...
if (Write(&MCHeader,sizeof(MCHeader)) != sizeof(MCHeader)) {
return false;
}
InMicroChunk = true;
return true;
}
/***********************************************************************************************
* ChunkSaveClass::End_Micro_Chunk -- close a micro-chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
bool ChunkSaveClass::End_Micro_Chunk(void)
{
assert(InMicroChunk);
// Save the current position
int curpos = File->Seek(0);
// Seek back and write the micro chunk header
File->Seek(MicroChunkPosition,SEEK_SET);
if (File->Write(&MCHeader,sizeof(MCHeader)) != sizeof(MCHeader)) {
return false;
}
// Go back to the end of the file
File->Seek(curpos,SEEK_SET);
InMicroChunk = false;
return true;
}
/***********************************************************************************************
* ChunkSaveClass::Write -- Write data into the current chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const void * buf, uint32 nbytes)
{
// If this assert hits, you mixed data and chunks within the same chunk NO NO!
assert(HeaderStack[StackIndex-1].Get_Sub_Chunk_Flag() == 0);
// If this assert hits, you didnt open any chunks yet
assert(StackIndex > 0);
// write the bytes into the file
if (File->Write(buf,nbytes) != (int)nbytes) return 0;
// track them in the wrapping chunk
HeaderStack[StackIndex-1].Add_Size(nbytes);
// track them if you are using a micro-chunk too.
if (InMicroChunk) {
assert(MCHeader.Get_Size() < 255 - nbytes); // micro chunks can only be 255 bytes
MCHeader.Add_Size(nbytes);
}
return nbytes;
}
/***********************************************************************************************
* ChunkSaveClass::Write -- write an IOVector2Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const IOVector2Struct & v)
{
return Write(&v,sizeof(v));
}
/***********************************************************************************************
* ChunkSaveClass::Write -- write an IOVector3Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const IOVector3Struct & v)
{
return Write(&v,sizeof(v));
}
/***********************************************************************************************
* ChunkSaveClass::Write -- write an IOVector4Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const IOVector4Struct & v)
{
return Write(&v,sizeof(v));
}
/***********************************************************************************************
* ChunkSaveClass::Write -- write an IOQuaternionStruct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkSaveClass::Write(const IOQuaternionStruct & q)
{
return Write(&q,sizeof(q));
}
/***********************************************************************************************
* ChunkSaveClass::Cur_Chunk_Depth -- returns the current chunk recursion depth (debugging) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
int ChunkSaveClass::Cur_Chunk_Depth(void)
{
return StackIndex;
}
/***********************************************************************************************
* ChunkLoadClass::ChunkLoadClass -- Constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
ChunkLoadClass::ChunkLoadClass(FileClass * file) :
File(file),
StackIndex(0),
InMicroChunk(false),
MicroChunkPosition(0)
{
memset(PositionStack,0,sizeof(PositionStack));
memset(HeaderStack,0,sizeof(HeaderStack));
memset(&MCHeader,0,sizeof(MCHeader));
}
/***********************************************************************************************
* ChunkLoadClass::Open_Chunk -- Open a chunk in the file, reads in the chunk header *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
bool ChunkLoadClass::Open_Chunk()
{
// if user didn't close any micro chunks that he opened, bad things could happen
assert(InMicroChunk == false);
// check for stack overflow
assert(StackIndex < MAX_STACK_DEPTH-1);
// if the parent chunk has been completely eaten, return false
if ((StackIndex > 0) && (PositionStack[StackIndex-1] == HeaderStack[StackIndex-1].Get_Size())) {
return false;
}
// read the chunk header
if (File->Read(&HeaderStack[StackIndex],sizeof(ChunkHeader)) != sizeof(ChunkHeader)) {
return false;
}
PositionStack[StackIndex] = 0;
StackIndex++;
return true;
}
/***********************************************************************************************
* ChunkLoadClass::Close_Chunk -- Close a chunk, seeks to the end if needed *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
bool ChunkLoadClass::Close_Chunk()
{
// if user didn't close any micro chunks that he opened, bad things could happen
assert(InMicroChunk == false);
// check for stack overflow
assert(StackIndex > 0);
int csize = HeaderStack[StackIndex-1].Get_Size();
int pos = PositionStack[StackIndex-1];
if (pos < csize) {
File->Seek(csize - pos,SEEK_CUR);
}
StackIndex--;
if (StackIndex > 0) {
PositionStack[StackIndex - 1] += csize + sizeof(ChunkHeader);
}
return true;
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Chunk_ID -- Returns the ID of the current chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Cur_Chunk_ID()
{
assert(StackIndex >= 1);
return HeaderStack[StackIndex-1].Get_Type();
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Chunk_Length -- Returns the current length of the current chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Cur_Chunk_Length()
{
assert(StackIndex >= 1);
return HeaderStack[StackIndex-1].Get_Size();
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Chunk_Depth -- returns the current chunk recursion depth *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
int ChunkLoadClass::Cur_Chunk_Depth()
{
return StackIndex;
}
/***********************************************************************************************
* ChunkLoadClass::Contains_Chunks -- Test whether the current chunk contains chunks (or data) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/24/99 GTH : Created. *
*=============================================================================================*/
int ChunkLoadClass::Contains_Chunks()
{
return HeaderStack[StackIndex-1].Get_Sub_Chunk_Flag();
}
/***********************************************************************************************
* ChunkLoadClass::Open_Micro_Chunk -- reads in a micro-chunk header *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
bool ChunkLoadClass::Open_Micro_Chunk()
{
assert(!InMicroChunk);
// read the chunk header
// calling the ChunkLoadClass::Read fn so that if we exhaust the chunk, the read will fail
if (Read(&MCHeader,sizeof(MCHeader)) != sizeof(MCHeader)) {
return false;
}
InMicroChunk = true;
MicroChunkPosition = 0;
return true;
}
/***********************************************************************************************
* ChunkLoadClass::Close_Micro_Chunk -- closes a micro-chunk (seeks to end) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
bool ChunkLoadClass::Close_Micro_Chunk()
{
assert(InMicroChunk);
InMicroChunk = false;
int csize = MCHeader.Get_Size();
int pos = MicroChunkPosition;
// seek the file past this micro chunk
if (pos < csize) {
File->Seek(csize - pos,SEEK_CUR);
// update the tracking variables for where we are in the normal chunk.
if (StackIndex > 0) {
PositionStack[StackIndex-1] += csize - pos;
}
}
return true;
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Micro_Chunk_ID -- returns the ID of the current micro-chunk (asserts if *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* Asserts if you are not currently inside a micro-chunk *
* Micro chunks have an id between 0 and 255 *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Cur_Micro_Chunk_ID()
{
assert(InMicroChunk);
return MCHeader.Get_Type();
}
/***********************************************************************************************
* ChunkLoadClass::Cur_Micro_Chunk_Length -- returns the size of the current micro chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* Asserts if you are not currently inside a micro-chunk *
* Micro chunks have a maximum size of 255 bytes *
* *
* HISTORY: *
* 9/3/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Cur_Micro_Chunk_Length()
{
assert(InMicroChunk);
return MCHeader.Get_Size();
}
// Seek over nbytes in the stream
uint32 ChunkLoadClass::Seek(uint32 nbytes)
{
assert(StackIndex >= 1);
// Don't seek if we would go past the end of the current chunk
if (PositionStack[StackIndex-1] + nbytes > (int)HeaderStack[StackIndex-1].Get_Size()) {
return 0;
}
// Don't read if we are in a micro chunk and would go past the end of it
if (InMicroChunk && MicroChunkPosition + nbytes > MCHeader.Get_Size()) {
return 0;
}
uint32 curpos=File->Tell();
if (File->Seek(nbytes,SEEK_CUR)-curpos != (int)nbytes) {
return 0;
}
// Update our position in the chunk
PositionStack[StackIndex-1] += nbytes;
// Update our position in the micro chunk if we are in one
if (InMicroChunk) {
MicroChunkPosition += nbytes;
}
return nbytes;
}
/***********************************************************************************************
* ChunkLoadClass::Read -- Read data from the file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/17/1997 GH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(void * buf,uint32 nbytes)
{
assert(StackIndex >= 1);
// Don't read if we would go past the end of the current chunk
if (PositionStack[StackIndex-1] + nbytes > (int)HeaderStack[StackIndex-1].Get_Size()) {
return 0;
}
// Don't read if we are in a micro chunk and would go past the end of it
if (InMicroChunk && MicroChunkPosition + nbytes > MCHeader.Get_Size()) {
return 0;
}
if (File->Read(buf,nbytes) != (int)nbytes) {
return 0;
}
// Update our position in the chunk
PositionStack[StackIndex-1] += nbytes;
// Update our position in the micro chunk if we are in one
if (InMicroChunk) {
MicroChunkPosition += nbytes;
}
return nbytes;
}
/***********************************************************************************************
* ChunkLoadClass::Read -- read an IOVector2Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(IOVector2Struct * v)
{
assert(v != NULL);
return Read(v,sizeof(v));
}
/***********************************************************************************************
* ChunkLoadClass::Read -- read an IOVector3Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(IOVector3Struct * v)
{
assert(v != NULL);
return Read(v,sizeof(v));
}
/***********************************************************************************************
* ChunkLoadClass::Read -- read an IOVector4Struct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(IOVector4Struct * v)
{
assert(v != NULL);
return Read(v,sizeof(v));
}
/***********************************************************************************************
* ChunkLoadClass::Read -- read an IOQuaternionStruct *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/4/99 GTH : Created. *
*=============================================================================================*/
uint32 ChunkLoadClass::Read(IOQuaternionStruct * q)
{
assert(q != NULL);
return Read(q,sizeof(q));
}

View File

@@ -0,0 +1,380 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Code/wwlib/chunkio.h 21 7/31/01 6:41p Patrick $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Tiberian Sun / Commando / G Library *
* *
* $Archive:: /Commando/Code/wwlib/chunkio.h $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 7/27/01 2:47p $*
* *
* $Revision:: 21 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef CHUNKIO_H
#define CHUNKIO_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef BITTYPE_H
#include "bittype.h"
#endif
#ifndef WWFILE_H
#include "wwfile.h"
#endif
#ifndef IOSTRUCT_H
#include "iostruct.h"
#endif
/************************************************************************************
ChunkIO
(gth) This module provides classes for reading and writing chunk-based files.
For example, all of the w3d files are stored in a hierarchical-chunk format.
Basically the format is similar to IFF. All data in the file has chunk headers
wrapped around it. A chunk header contains an ID, and a Size. The size
is the number of bytes in the chunk (not including the header). The
contents of a chunk may be either: more "sub-chunks" or raw data. These classes
will automatically keep track of your positions within all of the sub and parent
chunks (to some maximum recursion depth).
Sept 3, 1999
(gth) Adding the new concept of "micro-chunks". Instead of filling the contents of a
chunk with data, you can fill it with "micro-chunks" which contain a single byte
id and a single byte size. Micro-chunks are used for storing simple variables
in a form that can survive revisions to the file format without paying the price
for a full chunk header. You CANNOT recursively embed micro-chunks due to their
size limitations....
Sept 24, 1999
(gth) Using the MSB of the chunksize to indicate whether a chunk contains other
chunks or pure data. If the MSB is 0, the chunk contains data (so that the reader
I'm going to write doesn't break on older files) and if it is 1 then it is
assumed to contain other chunks. This does not apply to micro-chunks as they
are considered data.
**************************************************************************************/
struct ChunkHeader
{
// Functions.
ChunkHeader() : ChunkType(0), ChunkSize(0) {}
ChunkHeader(uint32 type, uint32 size) {ChunkType = type; ChunkSize = size;}
// Use these accessors to ensure you correctly deal with the data in the chunk header
void Set_Type(uint32 type) { ChunkType = type; }
uint32 Get_Type(void) { return ChunkType; }
void Set_Size(uint32 size) { ChunkSize &= 0x80000000; ChunkSize |= (size & 0x7FFFFFFF); }
void Add_Size(uint32 add) { Set_Size(Get_Size() + add); }
uint32 Get_Size(void) { return (ChunkSize & 0x7FFFFFFF); }
void Set_Sub_Chunk_Flag(bool onoff) { if (onoff) { ChunkSize |= 0x80000000; } else { ChunkSize &= 0x7FFFFFFF; } }
int Get_Sub_Chunk_Flag(void) { return (ChunkSize & 0x80000000); }
// Chunk type and size.
// Note: MSB of ChunkSize is used to indicate whether this chunk
// contains other chunks or data.
uint32 ChunkType;
uint32 ChunkSize;
};
struct MicroChunkHeader
{
MicroChunkHeader() {}
MicroChunkHeader(uint8 type, uint8 size) { ChunkType = type, ChunkSize = size; }
void Set_Type(uint8 type) { ChunkType = type; }
uint8 Get_Type(void) { return ChunkType; }
void Set_Size(uint8 size) { ChunkSize = size; }
void Add_Size(uint8 add) { Set_Size(Get_Size() + add); }
uint8 Get_Size(void) { return ChunkSize; }
uint8 ChunkType;
uint8 ChunkSize;
};
/**************************************************************************************
**
** ChunkSaveClass
** Wrap an instance of this class around an opened file for easy chunk
** creation.
**
**************************************************************************************/
class ChunkSaveClass
{
public:
ChunkSaveClass(FileClass * file);
// Chunk methods
bool Begin_Chunk(uint32 id);
bool End_Chunk();
int Cur_Chunk_Depth();
// Micro chunk methods
bool Begin_Micro_Chunk(uint32 id);
bool End_Micro_Chunk();
// Write data into the file
uint32 Write(const void *buf, uint32 nbytes);
uint32 Write(const IOVector2Struct & v);
uint32 Write(const IOVector3Struct & v);
uint32 Write(const IOVector4Struct & v);
uint32 Write(const IOQuaternionStruct & q);
private:
enum { MAX_STACK_DEPTH = 256 };
FileClass * File;
// Chunk building support
int StackIndex;
int PositionStack[MAX_STACK_DEPTH];
ChunkHeader HeaderStack[MAX_STACK_DEPTH];
// MicroChunk building support
bool InMicroChunk;
int MicroChunkPosition;
MicroChunkHeader MCHeader;
};
/**************************************************************************************
**
** ChunkLoadClass
** wrap an instance of one of these objects around an opened file
** to easily parse the chunks in the file
**
**************************************************************************************/
class ChunkLoadClass
{
public:
ChunkLoadClass(FileClass * file);
// Chunk methods
bool Open_Chunk();
bool Close_Chunk();
uint32 Cur_Chunk_ID();
uint32 Cur_Chunk_Length();
int Cur_Chunk_Depth();
int Contains_Chunks();
// Micro Chunk methods
bool Open_Micro_Chunk();
bool Close_Micro_Chunk();
uint32 Cur_Micro_Chunk_ID();
uint32 Cur_Micro_Chunk_Length();
// Read a block of bytes from the output stream.
uint32 Read(void *buf, uint32 nbytes);
uint32 Read(IOVector2Struct * v);
uint32 Read(IOVector3Struct * v);
uint32 Read(IOVector4Struct * v);
uint32 Read(IOQuaternionStruct * q);
// Seek over a block of bytes in the stream (same as Read but don't copy the data to a buffer)
uint32 Seek(uint32 nbytes);
private:
enum { MAX_STACK_DEPTH = 256 };
FileClass * File;
// Chunk reading support
int StackIndex;
uint32 PositionStack[MAX_STACK_DEPTH];
ChunkHeader HeaderStack[MAX_STACK_DEPTH];
// Micro-chunk reading support
bool InMicroChunk;
int MicroChunkPosition;
MicroChunkHeader MCHeader;
};
/*
** WRITE_WWSTRING_CHUNK - use this one-line macro to easily create a chunk to save a potentially
** long string. Note: This macro does NOT create a micro chunk...
** Example:
**
** csave.Begin_Chunk(CHUNKID_PARENT);
** ParentClass::Save (csave);
** csave.End_Chunk();
**
** WRITE_WWSTRING_CHUNK(csave, CHUNKID_NAME, string);
** WRITE_WIDESTRING_CHUNK(csave, CHUNKID_WIDE_NAME, wide_string);
**
** csave.Begin_Chunk(PHYSGRID_CHUNK_VARIABLES);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_VERSION,version);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_DUMMYVISID,DummyVisId);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_BASEVISID,BaseVisId);
** csave.End_Chunk();
**
*/
#define WRITE_WWSTRING_CHUNK(csave,id,var) { \
csave.Begin_Chunk(id); \
csave.Write((const TCHAR *)var, var.Get_Length () + 1); \
csave.End_Chunk(); }
#define WRITE_WIDESTRING_CHUNK(csave,id,var) { \
csave.Begin_Chunk(id); \
csave.Write((const WCHAR *)var, (var.Get_Length () + 1) * 2); \
csave.End_Chunk(); }
/*
** READ_WWSTRING_CHUNK - use this macro in a switch statement to read the contents
** of a chunk into a string object.
** Example:
**
** while (cload.Open_Chunk()) {
**
** switch(cload.Cur_Chunk_ID()) {
** READ_WWSTRING_CHUNK(cload,CHUNKID_NAME,string);
** READ_WIDESTRING_CHUNK(cload,CHUNKID_WIDE_NAME,wide_string);
** }
** cload.Close_Chunk();
** }
**
*/
#define READ_WWSTRING_CHUNK(cload,id,var) \
case (id): cload.Read(var.Get_Buffer(cload.Cur_Chunk_Length()),cload.Cur_Chunk_Length()); break; \
#define READ_WIDESTRING_CHUNK(cload,id,var) \
case (id): cload.Read(var.Get_Buffer((cload.Cur_Chunk_Length()+1)/2),cload.Cur_Chunk_Length()); break; \
/*
** WRITE_MICRO_CHUNK - use this one-line macro to easily make a micro chunk for an individual variable.
** Note that you should always wrap your micro-chunks inside a normal chunk.
** Example:
**
** csave.Begin_Chunk(PHYSGRID_CHUNK_VARIABLES);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_VERSION,version);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_DUMMYVISID,DummyVisId);
** WRITE_MICRO_CHUNK(csave,PHYSGRID_VARIABLE_BASEVISID,BaseVisId);
** csave.End_Chunk();
*/
#define WRITE_MICRO_CHUNK(csave,id,var) { \
csave.Begin_Micro_Chunk(id); \
csave.Write(&var,sizeof(var)); \
csave.End_Micro_Chunk(); }
#define WRITE_SAFE_MICRO_CHUNK(csave,id,var,type) { \
csave.Begin_Micro_Chunk(id); \
type data = (type)var; \
csave.Write(&data,sizeof(data)); \
csave.End_Micro_Chunk(); }
#define WRITE_MICRO_CHUNK_STRING(csave,id,var) { \
csave.Begin_Micro_Chunk(id); \
csave.Write(var, strlen(var) + 1); \
csave.End_Micro_Chunk(); }
#define WRITE_MICRO_CHUNK_WWSTRING(csave,id,var) { \
csave.Begin_Micro_Chunk(id); \
csave.Write((const TCHAR *)var, var.Get_Length () + 1); \
csave.End_Micro_Chunk(); }
#define WRITE_MICRO_CHUNK_WIDESTRING(csave,id,var) { \
csave.Begin_Micro_Chunk(id); \
csave.Write((const WCHAR *)var, (var.Get_Length () + 1) * 2); \
csave.End_Micro_Chunk(); }
/*
** READ_MICRO_CHUNK - use this macro in a switch statement to read a micro chunk into a variable
** Example:
**
** while (cload.Open_Micro_Chunk()) {
**
** switch(cload.Cur_Micro_Chunk_ID()) {
** READ_MICRO_CHUNK(cload,PHYSGRID_VARIABLE_VERSION,version);
** READ_MICRO_CHUNK(cload,PHYSGRID_VARIABLE_DUMMYVISID,DummyVisId);
** READ_MICRO_CHUNK(cload,PHYSGRID_VARIABLE_BASEVISID,BaseVisId);
** }
** cload.Close_Micro_Chunk();
** }
*/
#define READ_MICRO_CHUNK(cload,id,var) \
case (id): cload.Read(&var,sizeof(var)); break; \
/*
** Like READ_MICRO_CHUNK but reads items straight into the data safe.
*/
#define READ_SAFE_MICRO_CHUNK(cload,id,var,type) \
case (id): { \
void *temp_read_buffer_on_the_stack = _alloca(sizeof(var)); \
cload.Read(temp_read_buffer_on_the_stack, sizeof(var)); \
var = *((type*)temp_read_buffer_on_the_stack); \
break; \
}
#define READ_MICRO_CHUNK_STRING(cload,id,var,size) \
case (id): WWASSERT(cload.Cur_Micro_Chunk_Length() <= size); cload.Read(var,cload.Cur_Micro_Chunk_Length()); break; \
#define READ_MICRO_CHUNK_WWSTRING(cload,id,var) \
case (id): cload.Read(var.Get_Buffer(cload.Cur_Micro_Chunk_Length()),cload.Cur_Micro_Chunk_Length()); break; \
#define READ_MICRO_CHUNK_WIDESTRING(cload,id,var) \
case (id): cload.Read(var.Get_Buffer((cload.Cur_Micro_Chunk_Length()+1)/2),cload.Cur_Micro_Chunk_Length()); break; \
/*
** These load macros make it easier to add extra code to a specifc case
*/
#define LOAD_MICRO_CHUNK(cload,var) \
cload.Read(&var,sizeof(var)); \
#define LOAD_MICRO_CHUNK_WWSTRING(cload,var) \
cload.Read(var.Get_Buffer(cload.Cur_Micro_Chunk_Length()),cload.Cur_Micro_Chunk_Length()); \
#define LOAD_MICRO_CHUNK_WIDESTRING(cload,var) \
cload.Read(var.Get_Buffer((cload.Cur_Micro_Chunk_Length()+1)/2),cload.Cur_Micro_Chunk_Length()); \
/*
** OBSOLETE_MICRO_CHUNK - use this macro in a switch statement when you want your code
** to skip a given micro chunk but not fall through to your 'default' case statement which
** prints an "unrecognized chunk" warning message.
*/
#define OBSOLETE_MICRO_CHUNK(id) \
case (id): break;
#endif CHUNKIO_H

View File

@@ -0,0 +1,266 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/Convert.cpp $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 2/19/99 11:51a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "blitblit.h"
#include "convert.h"
#include "dsurface.h"
#include "hsv.h"
#include "rlerle.h"
ConvertClass::ConvertClass(PaletteClass const & artpalette, PaletteClass const & screenpalette, Surface const & surface) :
BBP(surface.Bytes_Per_Pixel()),
PlainBlitter(NULL),
TransBlitter(NULL),
ShadowBlitter(NULL),
RemapBlitter(NULL),
Translucent1Blitter(NULL),
Translucent2Blitter(NULL),
Translucent3Blitter(NULL),
RLETransBlitter(NULL),
RLEShadowBlitter(NULL),
RLERemapBlitter(NULL),
RLETranslucent1Blitter(NULL),
RLETranslucent2Blitter(NULL),
RLETranslucent3Blitter(NULL),
Translator(NULL),
ShadowTable(NULL),
RemapTable(NULL)
{
/*
** The draw data initialization is greatly dependant upon the pixel format
** of the display surface. Check the pixel format and set the values accordingly.
*/
if (BBP == 1) {
/*
** Build the shadow table by creating a slightly darker version of
** the color and then finding the closest match to it.
*/
ShadowTable = W3DNEWARRAY unsigned char [256];
ShadowTable[0] = 0;
for (int shadow = 1; shadow < 256; shadow++) {
HSVClass hsv = artpalette[shadow];
hsv.Set_Value((unsigned char)(hsv.Get_Value() / 2));
ShadowTable[shadow] = (unsigned char)artpalette.Closest_Color(hsv);
}
/*
** The translator table is created by finding the closest color
** in the display palette from each color in the source art
** palette.
*/
unsigned char * trans = W3DNEWARRAY unsigned char [256];
trans[0] = 0;
for (int index = 1; index < 256; index++) {
trans[index] = (unsigned char)screenpalette.Closest_Color(artpalette[index]);
}
Translator = (void *)trans;
/*
** Construct all the blitter objects necessary to support the functionality
** required for the draw permutations.
*/
PlainBlitter = W3DNEW BlitPlainXlat<unsigned char>((unsigned char const *)Translator);
TransBlitter = W3DNEW BlitTransXlat<unsigned char>((unsigned char const *)Translator);
RemapBlitter = W3DNEW BlitTransZRemapXlat<unsigned char>(&RemapTable, (unsigned char const *)Translator);
ShadowBlitter = W3DNEW BlitTransRemapDest<unsigned char>(ShadowTable);
Translucent1Blitter = W3DNEW BlitTransRemapXlat<unsigned char>(ShadowTable, (unsigned char const *)Translator);
Translucent2Blitter = W3DNEW BlitTransRemapXlat<unsigned char>(ShadowTable, (unsigned char const *)Translator);
Translucent3Blitter = W3DNEW BlitTransRemapXlat<unsigned char>(ShadowTable, (unsigned char const *)Translator);
/*
** Create the RLE aware blitter objects.
*/
RLETransBlitter = W3DNEW RLEBlitTransXlat<unsigned char>((unsigned char const *)Translator);
RLERemapBlitter = W3DNEW RLEBlitTransZRemapXlat<unsigned char>(&RemapTable, (unsigned char const *)Translator);
RLEShadowBlitter = W3DNEW RLEBlitTransRemapDest<unsigned char>(ShadowTable);
RLETranslucent1Blitter = W3DNEW RLEBlitTransRemapXlat<unsigned char>(ShadowTable, (unsigned char const *)Translator);
RLETranslucent2Blitter = W3DNEW RLEBlitTransRemapXlat<unsigned char>(ShadowTable, (unsigned char const *)Translator);
RLETranslucent3Blitter = W3DNEW RLEBlitTransRemapXlat<unsigned char>(ShadowTable, (unsigned char const *)Translator);
} else {
/*
** The hicolor translation table is constructed according to the pixel
** format of the display and the source art palette.
*/
//assert(surface.Is_Direct_Draw());
Translator = W3DNEWARRAY unsigned short [256];
((DSurface &)surface).Build_Remap_Table((unsigned short *)Translator, artpalette);
/*
** Fetch the pixel mask values to be used for the various algorithmic
** pixel processing performed for hicolor displays.
*/
int maskhalf = ((DSurface &)surface).Get_Halfbright_Mask();
int maskquarter = ((DSurface &)surface).Get_Quarterbright_Mask();
/*
** Construct all the blitter objects necessary to support the functionality
** required for the draw permutations.
*/
PlainBlitter = W3DNEW BlitPlainXlat<unsigned short>((unsigned short const *)Translator);
TransBlitter = W3DNEW BlitTransXlat<unsigned short>((unsigned short const *)Translator);
RemapBlitter = W3DNEW BlitTransZRemapXlat<unsigned short>(&RemapTable, (unsigned short const *)Translator);
ShadowBlitter = W3DNEW BlitTransDarken<unsigned short>((unsigned short)maskhalf);
Translucent1Blitter = W3DNEW BlitTransLucent75<unsigned short>((unsigned short const *)Translator, (unsigned short)maskquarter);
Translucent2Blitter = W3DNEW BlitTransLucent50<unsigned short>((unsigned short const *)Translator, (unsigned short)maskhalf);
Translucent3Blitter = W3DNEW BlitTransLucent25<unsigned short>((unsigned short const *)Translator, (unsigned short)maskquarter);
/*
** Create the RLE aware blitter objects.
*/
RLETransBlitter = W3DNEW RLEBlitTransXlat<unsigned short>((unsigned short const *)Translator);
RLERemapBlitter = W3DNEW RLEBlitTransZRemapXlat<unsigned short>(&RemapTable, (unsigned short const *)Translator);
RLEShadowBlitter = W3DNEW RLEBlitTransDarken<unsigned short>((unsigned short)maskhalf);
RLETranslucent1Blitter = W3DNEW RLEBlitTransLucent75<unsigned short>((unsigned short const *)Translator, (unsigned short)maskquarter);
RLETranslucent2Blitter = W3DNEW RLEBlitTransLucent50<unsigned short>((unsigned short const *)Translator, (unsigned short)maskhalf);
RLETranslucent3Blitter = W3DNEW RLEBlitTransLucent25<unsigned short>((unsigned short const *)Translator, (unsigned short)maskquarter);
}
}
ConvertClass::~ConvertClass(void)
{
delete PlainBlitter;
PlainBlitter = NULL;
delete TransBlitter;
TransBlitter = NULL;
delete ShadowBlitter;
ShadowBlitter = NULL;
delete RemapBlitter;
RemapBlitter = NULL;
delete Translucent1Blitter;
Translucent1Blitter = NULL;
delete Translucent2Blitter;
Translucent2Blitter = NULL;
delete Translucent3Blitter;
Translucent3Blitter = NULL;
delete [] Translator;
Translator = NULL;
delete [] ShadowTable;
ShadowTable = NULL;
delete RLETransBlitter;
RLETransBlitter = NULL;
delete RLEShadowBlitter;
RLEShadowBlitter = NULL;
delete RLERemapBlitter;
RLERemapBlitter = NULL;
delete RLETranslucent1Blitter;
RLETranslucent1Blitter = NULL;
delete RLETranslucent2Blitter;
RLETranslucent2Blitter = NULL;
delete RLETranslucent3Blitter;
RLETranslucent3Blitter = NULL;
}
Blitter const * ConvertClass::Blitter_From_Flags(ShapeFlags_Type flags) const
{
if (flags & SHAPE_REMAP) return(RemapBlitter);
/*
** Quick check to see if this is a translucent operation. If so, then no
** further examination of the flags is necessary.
*/
switch (flags & (SHAPE_TRANSLUCENT25 | SHAPE_TRANSLUCENT50 | SHAPE_TRANSLUCENT75)) {
case SHAPE_TRANSLUCENT25:
return(Translucent3Blitter);
case SHAPE_TRANSLUCENT50:
return(Translucent2Blitter);
case SHAPE_TRANSLUCENT75:
return(Translucent1Blitter);
}
if (flags & SHAPE_DARKEN) return(ShadowBlitter);
if (flags & SHAPE_NOTRANS) return(PlainBlitter);
return(TransBlitter);
}
RLEBlitter const * ConvertClass::RLEBlitter_From_Flags(ShapeFlags_Type flags) const
{
if (flags & SHAPE_REMAP) return(RLERemapBlitter);
/*
** Quick check to see if this is a translucent operation. If so, then no
** further examination of the flags is necessary.
*/
switch (flags & (SHAPE_TRANSLUCENT25 | SHAPE_TRANSLUCENT50 | SHAPE_TRANSLUCENT75)) {
case SHAPE_TRANSLUCENT25:
return(RLETranslucent3Blitter);
case SHAPE_TRANSLUCENT50:
return(RLETranslucent2Blitter);
case SHAPE_TRANSLUCENT75:
return(RLETranslucent1Blitter);
}
if (flags & SHAPE_DARKEN) return(RLEShadowBlitter);
// This should be fixed to return the RLEPlainBlitter when one is available
// but if you need to use this in the mean time just don't RLE compress the
// shape (since it only compresses transparent pixels and the reason we compress
// them is so we can skip them easily.)
if (flags & SHAPE_NOTRANS) return(RLETransBlitter);
return(RLETransBlitter);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,325 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : wwlib *
* *
* $Archive:: /Commando/Code/wwlib/cpudetect.h $*
* *
* Original Author:: Jani Penttinen *
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 3/29/02 4:09p $*
* *
* $Revision:: 11 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef WWLIB_CPU_DETECT_H__
#define WWLIB_CPU_DETECT_H__
#include "always.h"
#include "wwstring.h"
#ifdef WIN32
typedef signed __int64 sint64;
#elif defined (_UNIX)
typedef signed long long sint64;
#endif
class CPUDetectInitClass;
class CPUDetectClass
{
public:
typedef enum
{
MANUFACTURER_UNKNOWN = 0,
MANUFACTURER_INTEL,
MANUFACTURER_UMC,
MANUFACTURER_AMD,
MANUFACTURER_CYRIX,
MANUFACTURER_NEXTGEN,
MANUFACTURER_VIA,
MANUFACTURER_RISE,
MANUFACTURER_TRANSMETA
} ProcessorManufacturerType;
typedef enum
{
INTEL_PROCESSOR_UNKNOWN,
INTEL_PROCESSOR_80386,
INTEL_PROCESSOR_80486DX,
INTEL_PROCESSOR_80486SX,
INTEL_PROCESSOR_80486DX2,
INTEL_PROCESSOR_80486SL,
INTEL_PROCESSOR_80486SX2,
INTEL_PROCESSOR_80486DX2_WB,
INTEL_PROCESSOR_80486DX4,
INTEL_PROCESSOR_80486DX4_WB,
INTEL_PROCESSOR_PENTIUM,
INTEL_PROCESSOR_PENTIUM_OVERDRIVE,
INTEL_PROCESSOR_PENTIUM_MMX,
INTEL_PROCESSOR_PENTIUM_PRO_SAMPLE,
INTEL_PROCESSOR_PENTIUM_PRO,
INTEL_PROCESSOR_PENTIUM_II_OVERDRIVE,
INTEL_PROCESSOR_PENTIUM_II_MODEL_3,
INTEL_PROCESSOR_PENTIUM_II_MODEL_4,
INTEL_PROCESSOR_CELERON_MODEL_5,
INTEL_PROCESSOR_PENTIUM_II_MODEL_5,
INTEL_PROCESSOR_PENTIUM_II_XEON_MODEL_5,
INTEL_PROCESSOR_CELERON_MODEL_6,
INTEL_PROCESSOR_PENTIUM_III_MODEL_7,
INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_7,
INTEL_PROCESSOR_CELERON_MODEL_8,
INTEL_PROCESSOR_PENTIUM_III_MODEL_8,
INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_8,
INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_A,
INTEL_PROCESSOR_PENTIUM_III_MODEL_B,
INTEL_PROCESSOR_PENTIUM4
} IntelProcessorType;
typedef enum
{
AMD_PROCESSOR_UNKNOWN,
AMD_PROCESSOR_486DX2,
AMD_PROCESSOR_486DX4,
AMD_PROCESSOR_5x86,
AMD_PROCESSOR_486,
AMD_PROCESSOR_K5_MODEL0,
AMD_PROCESSOR_K5_MODEL1,
AMD_PROCESSOR_K5_MODEL2,
AMD_PROCESSOR_K5_MODEL3,
AMD_PROCESSOR_K6_MODEL6,
AMD_PROCESSOR_K6_MODEL7,
AMD_PROCESSOR_K6_2_3DNOW_MODEL8,
AMD_PROCESSOR_K6_3_3DNOW_MODEL9,
AMD_PROCESSOR_K6_3_PLUS,
AMD_PROCESSOR_K6,
AMD_PROCESSOR_ATHLON_025,
AMD_PROCESSOR_ATHLON_018,
AMD_PROCESSOR_DURON,
AMD_PROCESSOR_ATHLON_018_IL2,
AMD_PROCESSOR_ATHLON
} AMDProcessorType;
typedef enum
{
VIA_PROCESSOR_UNKNOWN,
VIA_PROCESSOR_IDT_C6_WINCHIP,
VIA_PROCESSOR_IDT_C6_WINCHIP2,
VIA_PROCESSOR_IDT_C6_WINCHIP3,
VIA_PROCESSOR_CYRIX_III_SAMUEL
} VIAProcessorType;
typedef enum
{
RISE_PROCESSOR_UNKNOWN,
RISE_PROCESSOR_DRAGON_025,
RISE_PROCESSOR_DRAGON_018,
RISE_PROCESSOR_DRAGON2_025,
RISE_PROCESSOR_DRAGON2_018
} RiseProcessorType;
inline static ProcessorManufacturerType Get_Processor_Manufacturer() {return ProcessorManufacturer;}
static const char* Get_Processor_Manufacturer_Name();
inline static bool Has_CPUID_Instruction() { return HasCPUIDInstruction; }
inline static bool Has_RDTSC_Instruction() { return HasRDTSCInstruction; }
inline static bool Has_CMOV_Instruction() { return HasCMOVSupport; }
inline static bool Has_MMX_Instruction_Set() { return HasMMXSupport; }
inline static bool Has_SSE_Instruction_Set() { return HasSSESupport; }
inline static bool Has_SSE2_Instruction_Set() { return HasSSE2Support; }
inline static bool Has_3DNow_Instruction_Set() { return Has3DNowSupport; }
inline static bool Has_Extended_3DNow_Instruction_Set() { return HasExtended3DNowSupport; }
// Call these functions after determining the manufacturer to find out which of the manufacturers processors
// the system has.
inline static IntelProcessorType Get_Intel_Processor() { return IntelProcessor; }
inline static AMDProcessorType Get_AMD_Processor() { return AMDProcessor; }
inline static VIAProcessorType Get_VIA_Processor() { return VIAProcessor; }
inline static RiseProcessorType Get_Rise_Processor() { return RiseProcessor; }
// Note that processor speed is only calculated at start and could change during execution, so
// this number is not to be relied on!
inline static int Get_Processor_Speed() { return ProcessorSpeed; }
inline static sint64 Get_Processor_Ticks_Per_Second() { return ProcessorTicksPerSecond; } // Ticks per second
inline static double Get_Inv_Processor_Ticks_Per_Second() { return InvProcessorTicksPerSecond; } // 1.0 / Ticks per second
static unsigned Get_Feature_Bits() { return FeatureBits; }
static unsigned Get_Extended_Feature_Bits() { return ExtendedFeatureBits; }
// L2 cache
static unsigned Get_L2_Cache_Size() { return L2CacheSize; }
static unsigned Get_L2_Cache_Line_Size() { return L2CacheLineSize; }
static unsigned Get_L2_Cache_Set_Associative() { return L2CacheSetAssociative; }
// L1 data cache
static unsigned Get_L1_Data_Cache_Size() { return L1DataCacheSize; }
static unsigned Get_L1_Data_Cache_Line_Size() { return L1DataCacheLineSize; }
static unsigned Get_L1_Data_Cache_Set_Associative() { return L1DataCacheSetAssociative; }
// L1 instruction cache
static unsigned Get_L1_Instruction_Cache_Size() { return L1InstructionCacheSize; }
static unsigned Get_L1_Instruction_Cache_Line_Size() { return L1InstructionCacheLineSize; }
static unsigned Get_L1_Instruction_Cache_Set_Associative() { return L1InstructionCacheSetAssociative; }
// L1 instruction trace cache
static unsigned Get_L1_Instruction_Trace_Cache_Size() { return L1InstructionTraceCacheSize; }
static unsigned Get_L1_Instruction_Trace_Cache_Set_Associative() { return L1InstructionTraceCacheSetAssociative; }
// System memory
static unsigned Get_Total_Physical_Memory() { return TotalPhysicalMemory; }
static unsigned Get_Available_Physical_Memory() { return AvailablePhysicalMemory; }
static unsigned Get_Total_Page_File_Size() { return TotalPageMemory; }
static unsigned Get_Available_Page_File_Size() { return AvailablePageMemory; }
static unsigned Get_Total_Virtual_Memory() { return TotalVirtualMemory; }
static unsigned Get_Available_Virtual_Memory() { return AvailableVirtualMemory; }
static unsigned Get_Processor_Type() { return ProcessorType; }
inline static const char* Get_Processor_String() { return ProcessorString; }
inline static const StringClass& Get_Processor_Log() { return ProcessorLog; }
inline static const StringClass& Get_Compact_Log() { return CompactLog; }
static bool CPUID(
unsigned& u_eax_,
unsigned& u_ebx_,
unsigned& u_ecx_,
unsigned& u_edx_,
unsigned cpuid_type);
private:
// static void Detect_CPU_Type();
static void Init_CPUID_Instruction();
static void Init_Processor_Speed();
static void Init_Processor_String();
static void Init_Processor_Manufacturer();
static void Init_Processor_Family();
static void Init_Processor_Features();
static void Init_Memory();
static void Init_OS();
static void Init_Intel_Processor_Type();
static void Init_AMD_Processor_Type();
static void Init_VIA_Processor_Type();
static void Init_Rise_Processor_Type();
static void Init_Cache();
static void Init_Processor_Log();
static void Init_Compact_Log();
static void Process_Cache_Info(unsigned value);
static void Process_Extended_Cache_Info();
friend class CPUDetectInitClass;
static StringClass ProcessorLog;
static StringClass CompactLog;
static int ProcessorType;
static int ProcessorFamily;
static int ProcessorModel;
static int ProcessorRevision;
static int ProcessorSpeed;
static sint64 ProcessorTicksPerSecond; // Ticks per second
static double InvProcessorTicksPerSecond; // 1.0 / Ticks per second
static ProcessorManufacturerType ProcessorManufacturer;
static IntelProcessorType IntelProcessor;
static AMDProcessorType AMDProcessor;
static VIAProcessorType VIAProcessor;
static RiseProcessorType RiseProcessor;
static unsigned FeatureBits;
static unsigned ExtendedFeatureBits;
// L2 cache information
static unsigned L2CacheSize;
static unsigned L2CacheLineSize;
static unsigned L2CacheSetAssociative;
// L1 data cache information
static unsigned L1DataCacheSize;
static unsigned L1DataCacheLineSize;
static unsigned L1DataCacheSetAssociative;
// L1 instruction cache information
static unsigned L1InstructionCacheSize;
static unsigned L1InstructionCacheLineSize;
static unsigned L1InstructionCacheSetAssociative;
// L1 instruction trace cache information
static unsigned L1InstructionTraceCacheSize;
static unsigned L1InstructionTraceCacheSetAssociative;
static unsigned TotalPhysicalMemory;
static unsigned AvailablePhysicalMemory;
static unsigned TotalPageMemory;
static unsigned AvailablePageMemory;
static unsigned TotalVirtualMemory;
static unsigned AvailableVirtualMemory;
static unsigned OSVersionNumberMajor;
static unsigned OSVersionNumberMinor;
static unsigned OSVersionBuildNumber;
static unsigned OSVersionPlatformId;
static StringClass OSVersionExtraInfo;
static bool HasCPUIDInstruction;
static bool HasRDTSCInstruction;
static bool HasSSESupport;
static bool HasSSE2Support;
static bool HasCMOVSupport;
static bool HasMMXSupport;
static bool Has3DNowSupport;
static bool HasExtended3DNowSupport;
static char VendorID[20];
static char ProcessorString[48];
};
struct CPUIDStruct
{
unsigned Eax;
unsigned Ebx;
unsigned Ecx;
unsigned Edx;
CPUIDStruct(unsigned cpuid_type)
{
if (!CPUDetectClass::Has_CPUID_Instruction()) {
Eax=Ebx=Ecx=Edx=0;
return;
}
CPUDetectClass::CPUID(Eax,Ebx,Ecx,Edx,cpuid_type);
}
};
#endif // WWLIB_CPU_DETECT_H__

View File

@@ -0,0 +1,222 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/CRC.CPP $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 10/22/98 2:46p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* CRCEngine::operator() -- Submits one byte of data to the CRC engine. *
* CRCEngine::operator() -- Submits an arbitrary data block to the CRC engine. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "crc.h"
/***********************************************************************************************
* CRCEngine::operator() -- Submits one byte of data to the CRC engine. *
* *
* This routine will take the specified byte of data and submit it to the CRC engine *
* for processing. This routine is designed to be as fast as possible since the typical *
* use of this routine is to feed one of presumably many byte sized chunks of data to the *
* CRC engine. *
* *
* INPUT: datum -- One byte of data to submit to the CRC engine. *
* *
* OUTPUT: none *
* *
* WARNINGS: If possible, use the buffer/size operator to submit data rather than repeated *
* calls to this routine. *
* *
* HISTORY: *
* 03/02/1996 JLB : Created. *
*=============================================================================================*/
void CRCEngine::operator() (char datum)
{
StagingBuffer.Buffer[Index++] = datum;
if (Index == sizeof(long)) {
CRC = Value();
StagingBuffer.Composite = 0;
Index = 0;
}
}
/***********************************************************************************************
* CRCEngine::operator() -- Submits an arbitrary data block to the CRC engine. *
* *
* This routine will submit the specified block to the CRC engine. The block can be of *
* arbitrary length. *
* *
* INPUT: buffer -- Pointer to the buffer that contains the data. The buffer will not *
* be modified. *
* *
* length -- The length of the buffer (in bytes). *
* *
* OUTPUT: Returns with the current CRC value accumulated so far. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/02/1996 JLB : Created. *
*=============================================================================================*/
long CRCEngine::operator() (void const * buffer, int length)
{
if (buffer != NULL && length > 0) {
char const * dataptr = (char const *)buffer;
int bytes_left = length;
/*
** If there are any leader bytes (needed to fill the staging buffer)
** then process those by first using them to fill up the staging
** buffer. The bulk of the data block will be processed by the high
** speed longword processing loop.
*/
while (bytes_left && Buffer_Needs_Data()) {
operator()(*dataptr);
dataptr++;
bytes_left--;
}
/*
** Perform the fast 'bulk' processing by reading long word sized
** data blocks.
*/
long const * longptr = (long const *)dataptr;
int longcount = bytes_left / sizeof(long); // Whole 'long' elements remaining.
while (longcount--) {
CRC = _lrotl(CRC, 1) + *longptr++;
bytes_left -= sizeof(long);
}
/*
** If there are remainder bytes, then process these by adding them
** to the staging buffer.
*/
dataptr = (char const *)longptr;
while (bytes_left) {
operator()(*dataptr);
dataptr++;
bytes_left--;
}
}
/*
** Return the current CRC value.
*/
return(Value());
}
// CRC for poly 0x04C11DB7
unsigned long CRC::_Table[ 256 ] =
{
0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
};
unsigned long CRC::Memory( unsigned char *data, unsigned long length, unsigned long crc )
{
crc ^= 0xFFFFFFFF; // invert previous CRC
while ( length-- ) {
crc = CRC32( *data++, crc ); // calc crc for each byte
}
return (crc ^ 0xFFFFFFFF); // invert new CRC and return it
}
unsigned long CRC::String( const char *string, unsigned long crc)
{
crc ^= 0xFFFFFFFF; // invert previous CRC
while ( *string ) {
crc = CRC32( *string++, crc ); // calc crc for each byte
}
return (crc ^ 0xFFFFFFFF); // invert new CRC and return it
}

View File

@@ -0,0 +1,64 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/crcpipe.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef CRCPIPE_H
#define CRCPIPE_H
#include "crc.h"
#include "pipe.h"
/*
** This class doesn't modify the data being piped through, but it does examine it and build
** a CRC value from the data.
*/
class CRCPipe : public Pipe
{
public:
CRCPipe(void) {}
virtual int Put(void const * source, int slen);
// Fetch the CRC value.
long Result(void) const;
protected:
CRCEngine CRC;
private:
CRCPipe(CRCPipe & rvalue);
CRCPipe & operator = (CRCPipe const & pipe);
};
#endif

View File

@@ -0,0 +1,65 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/crcstraw.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef CRCSTRAW_H
#define CRCSTRAW_H
#include "crc.h"
#include "straw.h"
/*
** This class will build a CRC value from the data stream that is drawn through this class.
** The data is not modified, but it is examined as it passes through.
*/
class CRCStraw : public Straw
{
public:
CRCStraw(void) {}
virtual int Get(void * source, int slen);
// Calculate and return the CRC value.
long Result(void) const;
protected:
CRCEngine CRC;
private:
CRCStraw(CRCStraw & rvalue);
CRCStraw & operator = (CRCStraw const & pipe);
};
#endif

View File

@@ -0,0 +1,100 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/CSTRAW.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* CacheStraw::Get -- Fetch data from the data source. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "cstraw.h"
#include <string.h>
/***********************************************************************************************
* CacheStraw::Get -- Fetch data from the data source. *
* *
* This will supply the data quantity requested. It performs a regulating influence on the *
* data requests passed through it. The data is requested from the next straw in the *
* chain such that the data stream is requested in chunks. This serves to lessen the *
* impact of multiple small data requests. *
* *
* INPUT: source -- Pointer to the buffer to hold the data. *
* *
* slen -- The number of data bytes requested. *
* *
* OUTPUT: Returns with the number of data bytes stored into the buffer specified. If this *
* number is less than that requested, it indicates that the data source has been *
* exhausted. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/10/1996 JLB : Created. *
*=============================================================================================*/
int CacheStraw::Get(void * source, int slen)
{
int total = 0;
if (Is_Valid() && source != NULL && slen > 0) {
/*
** Keep processing the data request until there is no more data to supply or the request
** has been fulfilled.
*/
while (slen > 0) {
/*
** First try to fetch the data from data previously loaded into the buffer.
*/
if (Length > 0) {
int tocopy = (Length < slen) ? Length : slen;
memmove(source, ((char *)BufferPtr.Get_Buffer()) + Index, tocopy);
slen -= tocopy;
Index += tocopy;
total += tocopy;
Length -= tocopy;
source = (char*)source + tocopy;
}
if (slen == 0) break;
/*
** Since there is more to be fulfilled yet the holding buffer is empty,
** refill the buffer with a fresh block of data from the source.
*/
Length = Straw::Get(BufferPtr, BufferPtr.Get_Size());
Index = 0;
if (Length == 0) break;
}
}
return(total);
}

View File

@@ -0,0 +1,72 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/cstraw.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:59a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef CSTRAW_H
#define CSTRAW_H
#include "buff.h"
#include "straw.h"
/*
** This class handles transfer of data by perform regulated requests for data from the next
** class in the chain. It performs no translation on the data. By using this segment in a
** straw chain, data throughput can be regulated. This can yield great performance increases
** when dealing with a file source.
*/
class CacheStraw : public Straw
{
public:
CacheStraw(Buffer const & buffer) : BufferPtr(buffer), Index(0), Length(0) {}
CacheStraw(int length=4096) : BufferPtr(length), Index(0), Length(0) {}
virtual int Get(void * source, int slen);
private:
Buffer BufferPtr;
int Index;
int Length;
bool Is_Valid(void) {return(BufferPtr.Is_Valid());}
CacheStraw(CacheStraw & rvalue);
CacheStraw & operator = (CacheStraw const & pipe);
};
#endif

View File

@@ -0,0 +1,325 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/data.cpp $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 9/24/99 4:52p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Load_Alloc_Data -- Allocates a buffer and loads the file into it. *
* Load_Uncompress -- Loads and uncompresses data to a buffer. *
* Hires_Load -- Allocates memory for, and loads, a resolution dependant file. *
* Fetch_String -- Fetches a string resource. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "data.h"
/***********************************************************************************************
* Load_Alloc_Data -- Allocates a buffer and loads the file into it. *
* *
* This is the C++ replacement for the Load_Alloc_Data function. It will allocate the *
* memory big enough to hold the file and then read the file into it. *
* *
* INPUT: file -- The file to read. *
* *
* mem -- The memory system to use for allocation. *
* *
* OUTPUT: Returns with a pointer to the allocated and filled memory block. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void * Load_Alloc_Data(FileClass & file)
{
void * ptr = NULL;
if (file.Is_Available()) {
long size = file.Size();
ptr = W3DNEWARRAY char[size];
if (ptr != NULL) {
file.Read(ptr, size);
}
}
return(ptr);
}
/***********************************************************************************************
* Load_Uncompress -- Loads and uncompresses data to a buffer. *
* *
* This is the C++ counterpart to the Load_Uncompress function. It will load the file *
* specified into the graphic buffer indicated and uncompress it. *
* *
* INPUT: file -- The file to load and uncompress. *
* *
* uncomp_buff -- The graphic buffer that initial loading will use. *
* *
* dest_buff -- The buffer that will hold the uncompressed data. *
* *
* reserved_data -- This is an optional pointer to a buffer that will hold any *
* reserved data the compressed file may contain. This is *
* typically a palette. *
* *
* OUTPUT: Returns with the size of the uncompressed data in the destination buffer. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
long Load_Uncompress(FileClass & file, Buffer & uncomp_buff, Buffer & dest_buff, void * reserved_data)
{
unsigned short size;
void * sptr = uncomp_buff.Get_Buffer();
void * dptr = dest_buff.Get_Buffer();
int opened = false;
CompHeaderType header;
/*
** The file must be opened in order to be read from. If the file
** isn't opened, then open it. Record this fact so that it can be
** restored to its closed state at the end.
*/
if (!file.Is_Open()) {
if (!file.Open()) {
return(0);
}
opened = true;
}
/*
** Read in the size of the file (supposedly).
*/
file.Read(&size, sizeof(size));
/*
** Read in the header block. This block contains the compression type
** and skip data (among other things).
*/
file.Read(&header, sizeof(header));
size -= (unsigned short)sizeof(header);
/*
** If there are skip bytes then they must be processed. Either read
** them into the buffer provided or skip past them. No check is made
** to ensure that the reserved data buffer is big enough (watch out!).
*/
if (header.Skip) {
size -= header.Skip;
if (reserved_data) {
file.Read(reserved_data, header.Skip);
} else {
file.Seek(header.Skip, SEEK_CUR);
}
header.Skip = 0;
}
/*
** Determine where is the proper place to load the data. If both buffers
** specified are identical, then the data should be loaded at the end of
** the buffer and decompressed at the beginning.
*/
if (uncomp_buff.Get_Buffer() == dest_buff.Get_Buffer()) {
sptr = (char *)sptr + uncomp_buff.Get_Size()-(size+sizeof(header));
}
/*
** Read in the bulk of the data.
*/
memmove(sptr, &header, sizeof(header));
// Mem_Copy(&header, sptr, sizeof(header));
file.Read((char *)sptr + sizeof(header), size);
/*
** Decompress the data.
*/
size = (unsigned short) Uncompress_Data(sptr, dptr);
/*
** Close the file if necessary.
*/
if (opened) {
file.Close();
}
return((long)size);
}
typedef struct SRecord {
int ID; // ID number of the string resource.
int TimeStamp; // 'Time' that this string was last requested.
char String[2048]; // Copy of string resource.
SRecord(void) : ID(-1), TimeStamp(-1) {}
} SRecord;
/***********************************************************************************************
* Fetch_String -- Fetches a string resource. *
* *
* Fetches a string resource and returns a pointer to its text. *
* *
* INPUT: id -- The ID number of the string resource to fetch. *
* *
* OUTPUT: Returns with a pointer to the actual text of the string resource. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 12/25/1996 JLB : Created. *
*=============================================================================================*/
char const * Fetch_String(int id)
{
#ifdef _UNIX
return("");
#else
static SRecord _buffers[64];
static int _time = 0;
/*
** Determine if the string ID requested is valid. If not then return an empty string pointer.
*/
if (id == -1 || id == TXT_NONE) return("");
/*
** Adjust the 'time stamp' tracking value. This is an artificial value used merely to track
** the relative age of the strings requested.
*/
_time = _time+1;
/*
** Check to see if the requested string has already been fetched into a buffer. If so, then
** return a pointer to that string (update the time stamp as well).
*/
for (int index = 0; index < ARRAY_SIZE(_buffers); index++) {
if (_buffers[index].ID == id) {
_buffers[index].TimeStamp = _time;
return(_buffers[index].String);
}
}
/*
** Find a suitable buffer to hold the string to be fetched. The buffer should either be
** empty or have the oldest fetched string.
*/
int oldest = -1;
int oldtime = -1;
for (int text = 0; text < ARRAY_SIZE(_buffers); text++) {
if (oldest == -1 || oldtime > _buffers[text].TimeStamp) {
oldest = text;
oldtime = _buffers[text].TimeStamp;
if (oldtime == -1 || _buffers[text].ID == -1) break;
}
}
/*
** A suitable buffer has been found so fetch the string resource and then return a pointer
** to the string.
*/
char * stringptr = _buffers[oldest].String;
_buffers[oldest].ID = id;
_buffers[oldest].TimeStamp = _time;
if (LoadString(ProgramInstance, id, stringptr, sizeof(_buffers[oldest].String)) == 0) {
return("");
}
stringptr[sizeof(_buffers[oldest].String)-1] = '\0';
return(stringptr);
#endif
}
void const * Fetch_Resource(LPCSTR resname, LPCSTR restype)
{
#ifdef _UNIX
return(NULL);
#else
/*
** Fetch the program instance if it hasn't already been recorded.
*/
// if (ProgramInstance == 0) {
// ProgramInstance = GetModuleHandle("LANGUAGE");
// }
HRSRC handle = FindResource(ProgramInstance, resname, restype);
if (handle == NULL) {
return(NULL);
}
HGLOBAL rhandle = LoadResource(ProgramInstance, handle);
if (rhandle == NULL) {
return(NULL);
}
return(LockResource(rhandle));
#endif
}
int Load_Picture(FileClass & file, Buffer & scratchbuf, Buffer & destbuf, unsigned char * palette, PicturePlaneType )
{
return(Load_Uncompress(file, scratchbuf, destbuf, palette ) / 8000);
}
/***********************************************************************************************
* Hires_Load -- Allocates memory for, and loads, a resolution dependant file. *
* *
* *
* *
* INPUT: Name of file to load *
* *
* OUTPUT: Ptr to loaded file *
* *
* WARNINGS: Caller is responsible for releasing the memory allocated *
* *
* *
* HISTORY: *
* 5/13/96 3:20PM ST : Created *
*=============================================================================================*/
void * Hires_Load(FileClass & file)
{
int length;
void * return_ptr;
if (file.Is_Available()) {
length = file.Size();
return_ptr = W3DNEWARRAY char[length];
file.Read(return_ptr, length);
return (return_ptr);
} else {
return (NULL);
}
}

View File

@@ -0,0 +1,56 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/data.h $*
* *
* $Author:: Eric_c $*
* *
* $Modtime:: 4/02/99 11:59a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef DATA_H
#define DATA_H
#include "buff.h"
#include "iff.h"
#include "win.h"
#include "wwfile.h"
#define TXT_NONE 0
int Load_Picture(FileClass &file, Buffer & scratchbuf, Buffer & destbuf, unsigned char * palette, PicturePlaneType format);
void * Load_Alloc_Data(FileClass & file);
long Load_Uncompress(FileClass & file, Buffer & uncomp_buff, Buffer & dest_buff, void * reserved_data);
char const * Fetch_String(int id);
void const * Fetch_Resource(LPCSTR resname, LPCSTR restype);
#endif

View File

@@ -0,0 +1,646 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/Library/DDRAW.CPP $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 10/15/98 11:05a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Set_Video_Mode -- Initializes Direct Draw and sets the required Video Mode *
* Process_DD_Result -- Does a message box based on the result of a DD command *
* Reset_Video_Mode -- Resets video mode and deletes Direct Draw Object *
* Get_Free_Video_Memory -- returns amount of free video memory *
* Get_Video_Hardware_Caps -- returns bitmask of direct draw video hardware support *
* Wait_Vert_Blank -- Waits for the start (leading edge) of a vertical blank *
* Set_Palette -- set a direct draw palette *
* Check_Overlapped_Blit_Capability -- See if video driver supports blitting overlapped regions*
* Wait_Blit -- waits for the DirectDraw blitter to become idle *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "misc.h"
#include "dsurface.h"
#include "data.h"
#include "_timer.h"
#include <assert.h>
#include <stdio.h>
LPDIRECTDRAW DirectDrawObject = NULL; // Pointer to the direct draw object
LPDIRECTDRAW2 DirectDraw2Interface = NULL; // Pointer to direct draw 2 interface
static PALETTEENTRY PaletteEntries[256]; // 256 windows palette entries
static LPDIRECTDRAWPALETTE PalettePtr; // Pointer to direct draw palette object
static bool FirstPaletteSet = false; // Is this the first time 'Set_Palette' has been called?
LPDIRECTDRAWSURFACE PaletteSurface = NULL;
bool SurfacesRestored = false;
static bool CanVblankSync = true;
unsigned char CurrentPalette[768];
bool Debug_Windowed;
int (*DirectDrawErrorHandler)(HRESULT error) = NULL;
void Set_Palette(PaletteClass const & pal, int time, void (*callback)())
{
CDTimerClass<SystemTimerClass> timer = time;
PaletteClass original;
memcpy(&original, CurrentPalette, sizeof(CurrentPalette));
PaletteClass newpal = pal;
while (timer) {
/*
** Build an intermediate palette that is as close to the destination palette
** as the current time is proportional to the ending time.
*/
PaletteClass palette = original;
int adjust = ((time - timer) * 256) / time;
adjust = MIN(adjust, 255);
palette.Adjust(adjust, newpal);
/*
** Remember the current time so that multiple palette sets within the same game
** time tick won't occur. This is probably unnecessary since the palette setting
** code, at the time of this writing, delays at least one game tick in the process
** of setting the palette.
*/
int holdtime = timer;
/*
** Set the palette to this intermediate palette and then loop back
** to calculate and set a new intermediate palette.
*/
Set_Palette((void*)&palette[0]);
/*
** If the callback routine was specified, then call it once per palette
** setting loop.
*/
if (callback) {
callback();
}
/*
** This loop ensures that the palette won't be set more than once per game tick. Setting
** the palette more than once per game tick will have no effect since the calculation will
** result in the same intermediate palette that was previously calculated.
*/
while (timer == holdtime && holdtime != 0) {
if (callback) callback();
}
}
/*
** Ensure that the final palette exactly matches the requested
** palette before exiting the fading routine.
*/
Set_Palette((void*)&newpal[0]);
}
/***********************************************************************************************
* Process_DD_Result -- Does a message box based on the result of a DD command *
* *
* INPUT: HRESULT result - the result returned from the direct draw command *
* int display_ok_msg - should a message be displayed if command ok * *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 09/27/1995 PWG : Created. *
*=============================================================================================*/
void Process_DD_Result(HRESULT result, int display_ok_msg)
{
#ifdef _DEBUG
static struct {
HRESULT Error;
char const * Message;
} _errors[] = {
{DDERR_ALREADYINITIALIZED, "This object is already initialized"},
{DDERR_BLTFASTCANTCLIP, "Return if a clipper object is attached to the source surface passed into a BltFast call."},
{DDERR_CANNOTATTACHSURFACE, "This surface can not be attached to the requested surface."},
{DDERR_CANNOTDETACHSURFACE, "This surface can not be detached from the requested surface."},
{DDERR_CANTCREATEDC, "Windows can not create any more DCs"},
{DDERR_CANTDUPLICATE, "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created."},
{DDERR_CANTLOCKSURFACE, "Unable to lock surface because no driver exists which can supply a pointer to the surface."},
{DDERR_CLIPPERISUSINGHWND, "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd."},
{DDERR_COLORKEYNOTSET, "No src color key specified for this operation."},
{DDERR_CURRENTLYNOTAVAIL, "Support is currently not available."},
{DDERR_DIRECTDRAWALREADYCREATED, "A DirectDraw object representing this driver has already been created for this process."},
{DDERR_EXCEPTION, "An exception was encountered while performing the requested operation."},
{DDERR_EXCLUSIVEMODEALREADYSET, "An attempt was made to set the cooperative level when it was already set to exclusive."},
{DDERR_GENERIC, "Generic failure."},
{DDERR_HEIGHTALIGN, "Height of rectangle provided is not a multiple of reqd alignment."},
{DDERR_HWNDALREADYSET, "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created."},
{DDERR_HWNDSUBCLASSED, "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state."},
{DDERR_IMPLICITLYCREATED, "This surface can not be restored because it is an implicitly created surface."},
{DDERR_INCOMPATIBLEPRIMARY, "Unable to match primary surface creation request with existing primary surface."},
{DDERR_INVALIDCAPS, "One or more of the caps bits passed to the callback are incorrect."},
{DDERR_INVALIDCLIPLIST, "DirectDraw does not support the provided cliplist."},
{DDERR_INVALIDDIRECTDRAWGUID, "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier."},
{DDERR_INVALIDMODE, "DirectDraw does not support the requested mode."},
{DDERR_INVALIDOBJECT, "DirectDraw received a pointer that was an invalid DIRECTDRAW object."},
{DDERR_INVALIDPARAMS, "One or more of the parameters passed to the function are incorrect."},
{DDERR_INVALIDPIXELFORMAT, "The pixel format was invalid as specified."},
{DDERR_INVALIDPOSITION, "Returned when the position of the overlay on the destination is no longer legal for that destination."},
{DDERR_INVALIDRECT, "Rectangle provided was invalid."},
{DDERR_INVALIDSURFACETYPE, "The requested action could not be performed because the surface was of the wrong type."},
{DDERR_LOCKEDSURFACES, "Operation could not be carried out because one or more surfaces are locked."},
{DDERR_NO3D, "There is no 3D present."},
{DDERR_NOALPHAHW, "Operation could not be carried out because there is no alpha accleration hardware present or available."},
// {DDERR_NOANTITEARHW, "Operation could not be carried out because there is no hardware support for synchronizing blts to avoid tearing. "},
{DDERR_NOBLTHW, "No blter hardware present."},
// {DDERR_NOBLTQUEUEHW, "Operation could not be carried out because there is no hardware support for asynchronous blting."},
{DDERR_NOCLIPLIST, "No cliplist available."},
{DDERR_NOCLIPPERATTACHED, "No clipper object attached to surface object."},
{DDERR_NOCOLORCONVHW, "Operation could not be carried out because there is no color conversion hardware present or available."},
{DDERR_NOCOLORKEY, "Surface doesn't currently have a color key"},
{DDERR_NOCOLORKEYHW, "Operation could not be carried out because there is no hardware support of the destination color key."},
{DDERR_NOCOOPERATIVELEVELSET, "Create function called without DirectDraw object method SetCooperativeLevel being called."},
{DDERR_NODC, "No DC was ever created for this surface."},
{DDERR_NODDROPSHW, "No DirectDraw ROP hardware."},
{DDERR_NODIRECTDRAWHW, "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware."},
{DDERR_NODIRECTDRAWSUPPORT, "No DirectDraw support possible with current display driver."},
{DDERR_NOEMULATION, "Software emulation not available."},
{DDERR_NOEXCLUSIVEMODE, "Operation requires the application to have exclusive mode but the application does not have exclusive mode."},
{DDERR_NOFLIPHW, "Flipping visible surfaces is not supported."},
{DDERR_NOGDI, "There is no GDI present."},
{DDERR_NOHWND, "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND."},
{DDERR_NOMIRRORHW, "Operation could not be carried out because there is no hardware present or available."},
{DDERR_NOOVERLAYDEST, "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination."},
{DDERR_NOOVERLAYHW, "Operation could not be carried out because there is no overlay hardware present or available."},
{DDERR_NOPALETTEATTACHED, "No palette object attached to this surface. "},
{DDERR_NOPALETTEHW, "No hardware support for 16 or 256 color palettes."},
{DDERR_NORASTEROPHW, "Operation could not be carried out because there is no appropriate raster op hardware present or available."},
{DDERR_NOROTATIONHW, "Operation could not be carried out because there is no rotation hardware present or available."},
{DDERR_NOSTRETCHHW, "Operation could not be carried out because there is no hardware support for stretching."},
{DDERR_NOT4BITCOLOR, "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette."},
{DDERR_NOT4BITCOLORINDEX, "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette."},
{DDERR_NOT8BITCOLOR, "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color."},
{DDERR_NOTAOVERLAYSURFACE, "Returned when an overlay member is called for a non-overlay surface."},
{DDERR_NOTEXTUREHW, "Operation could not be carried out because there is no texture mapping hardware present or available."},
{DDERR_NOTFLIPPABLE, "An attempt has been made to flip a surface that is not flippable."},
{DDERR_NOTFOUND, "Requested item was not found."},
{DDERR_NOTLOCKED, "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this process, has been attempted."},
{DDERR_NOTPALETTIZED, "The surface being used is not a palette-based surface."},
{DDERR_NOVSYNCHW, "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations."},
{DDERR_NOZBUFFERHW, "Operation could not be carried out because there is no hardware support for zbuffer blting."},
{DDERR_NOZOVERLAYHW, "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays."},
{DDERR_OUTOFCAPS, "The hardware needed for the requested operation has already been allocated."},
{DDERR_OUTOFMEMORY, "DirectDraw does not have enough memory to perform the operation."},
{DDERR_OUTOFVIDEOMEMORY, "DirectDraw does not have enough memory to perform the operation."},
{DDERR_OVERLAYCANTCLIP, "The hardware does not support clipped overlays."},
{DDERR_OVERLAYCOLORKEYONLYONEACTIVE, "Can only have ony color key active at one time for overlays."},
{DDERR_OVERLAYNOTVISIBLE, "Returned when GetOverlayPosition is called on a hidden overlay."},
{DDERR_PALETTEBUSY, "Access to this palette is being refused because the palette is already locked by another thread."},
{DDERR_PRIMARYSURFACEALREADYEXISTS, "This process already has created a primary surface."},
{DDERR_REGIONTOOSMALL, "Region passed to Clipper::GetClipList is too small."},
{DDERR_SURFACEALREADYATTACHED, "This surface is already attached to the surface it is being attached to."},
{DDERR_SURFACEALREADYDEPENDENT, "This surface is already a dependency of the surface it is being made a dependency of."},
{DDERR_SURFACEBUSY, "Access to this surface is being refused because the surface is already locked by another thread."},
{DDERR_SURFACEISOBSCURED, "Access to surface refused because the surface is obscured."},
{DDERR_SURFACELOST, "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it."},
{DDERR_SURFACENOTATTACHED, "The requested surface is not attached."},
{DDERR_TOOBIGHEIGHT, "Height requested by DirectDraw is too large."},
{DDERR_TOOBIGSIZE, "Size requested by DirectDraw is too large -- the individual height and width are OK."},
{DDERR_TOOBIGWIDTH, "Width requested by DirectDraw is too large."},
{DDERR_UNSUPPORTED, "Action not supported."},
{DDERR_UNSUPPORTEDFORMAT, "FOURCC format requested is unsupported by DirectDraw."},
{DDERR_UNSUPPORTEDMASK, "Bitmask in the pixel format requested is unsupported by DirectDraw."},
{DDERR_VERTICALBLANKINPROGRESS, "Vertical blank is in progress."},
{DDERR_WASSTILLDRAWING, "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete."},
{DDERR_WRONGMODE, "This surface can not be restored because it was created in a different mode."},
{DDERR_XALIGN, "Rectangle provided was not horizontally aligned on required boundary."}
};
#endif
/*
** If there iwas no error detected, then either bail out or display a message to
** this effect as indicated by the "display_ok_msg" parameter.
*/
if (result == DD_OK) {
if (display_ok_msg) {
MessageBox(MainWindow, "Direct Draw operation processed without error", "Note", MB_OK);
}
return;
}
if (DirectDrawErrorHandler) {
DirectDrawErrorHandler(result);
return;
}
#ifdef _DEBUG
/*
** Scan for a matching error code and display the appropriate message.
*/
for (int index = 0; index < ARRAY_SIZE(_errors); index++) {
if (_errors[index].Error == result) {
MessageBox(MainWindow, _errors[index].Message, "Westwood Library Direct Draw Error", MB_ICONEXCLAMATION|MB_OK);
return;
}
}
#endif
/*
** Since it fell out of the above loop, this must be an unrecognized error code.
*/
char str[80];
sprintf(str, "DDRAW.DLL Error code = %08X", result);
MessageBox(MainWindow, str, "Direct X", MB_ICONEXCLAMATION|MB_OK);
}
/***********************************************************************************************
* Check_Overlapped_Blit_Capability -- See if video driver supports blitting overlapped regions*
* *
* We will check for this by drawing something to a video page and blitting it over itself. *
* If we end up with the top line repeating then overlapped region blits dont work. *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 6/7/96 5:06PM ST : Created *
*=============================================================================================*/
void Check_Overlapped_Blit_Capability(void)
{
// OverlappedVideoBlits = false;
#ifdef NEVER
/*
** Assume we can until we find out otherwise
*/
OverlappedVideoBlits = true;
GraphicBufferClass test_buffer;
test_buffer.Init (64, 64, NULL, 0, (GBC_Enum)GBC_VIDEOMEM);
test_buffer.Clear();
/*
** Plot a pixel in the top left corner of the buffer.
*/
test_buffer.Put_Pixel(0, 0, 255);
/*
** Blit the buffer down by one line. If we end up with a vertical strip of pixel 255's then
** overlapped blits dont work
*/
test_buffer.Blit(test_buffer, 0, 0, 0, 1, test_buffer.Get_Width(), test_buffer.Get_Height()-1);
if (test_buffer.Get_Pixel(0, 5) == 255) OverlappedVideoBlits = false;
#endif
}
void Prep_Direct_Draw(void)
{
//
// If there is not currently a direct draw object then we need to define one.
//
if ( DirectDrawObject == NULL ) {
HRESULT result = DirectDrawCreate(NULL, &DirectDrawObject, NULL);
Process_DD_Result(result, false);
if (result == DD_OK) {
if (Debug_Windowed) {
result = DirectDrawObject->SetCooperativeLevel(MainWindow, DDSCL_NORMAL);
} else {
result = DirectDrawObject->SetCooperativeLevel(MainWindow, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
}
Process_DD_Result(result, false);
}
}
}
/***********************************************************************************************
* Set_Video_Mode -- Initializes Direct Draw and sets the required Video Mode *
* *
* INPUT: int width - the width of the video mode in pixels *
* int height - the height of the video mode in pixels *
* int bits_per_pixel - the number of bits per pixel the video mode supports *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 09/26/1995 PWG : Created. *
*=============================================================================================*/
bool Set_Video_Mode(HWND , int w, int h, int bits_per_pixel)
{
HRESULT result;
Prep_Direct_Draw();
//
// Set the required display mode with 8 bits per pixel
//
//MessageBox(MainWindow, "In Set_Video_Mode. About to call call SetDisplayMode.","Note", MB_ICONEXCLAMATION|MB_OK);
result = DirectDrawObject->SetDisplayMode(w, h, bits_per_pixel);
if (result != DD_OK) {
// Process_DD_Result(result, false);
DirectDrawObject->Release();
DirectDrawObject = NULL;
return(false);
}
//
// Create a direct draw palette object
//
//MessageBox(MainWindow, "In Set_Video_Mode. About to call CreatePalette.","Note", MB_ICONEXCLAMATION|MB_OK);
result = DirectDrawObject->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, &PaletteEntries[0], &PalettePtr, NULL);
Process_DD_Result(result, false);
if (result != DD_OK) {
return (false);
}
Check_Overlapped_Blit_Capability();
//MessageBox(MainWindow, "In Set_Video_Mode. About to return success.","Note", MB_ICONEXCLAMATION|MB_OK);
#if (0)
/*
** Find out if DirectX 2 extensions are available
*/
result = DirectDrawObject->QueryInterface (IID_IDirectDraw2, (LPVOID*)&DirectDraw2Interface);
SystemToVideoBlits = false;
VideoToSystemBlits = false;
SystemToSystemBlits= false;
if (result != DD_OK) {
DirectDraw2Interface = NULL;
} else {
DDCAPS capabilities;
DDCAPS emulated_capabilities;
memset ((char*)&capabilities, 0, sizeof(capabilities));
memset ((char*)&emulated_capabilities, 0, sizeof(emulated_capabilities));
capabilities.dwSize = sizeof (capabilities);
emulated_capabilities.dwSize = sizeof (emulated_capabilities);
DirectDrawObject->GetCaps (&capabilities, &emulated_capabilities);
if (capabilities.dwCaps & DDCAPS_CANBLTSYSMEM) {
SystemToVideoBlits = (capabilities.dwSVBCaps & DDCAPS_BLT) ? true : false;
VideoToSystemBlits = (capabilities.dwVSBCaps & DDCAPS_BLT) ? true : false;
SystemToSystemBlits = (capabilities.dwSSBCaps & DDCAPS_BLT) ? true : false;
}
}
#endif //(0)
//MessageBox(MainWindow, "In Set_Video_Mode. About to return success.","Note", MB_ICONEXCLAMATION|MB_OK);
return (true);
}
/***********************************************************************************************
* Reset_Video_Mode -- Resets video mode and deletes Direct Draw Object *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: *
* *
* HISTORY: *
* 09/26/1995 PWG : Created. *
*=============================================================================================*/
void Reset_Video_Mode(void)
{
HRESULT result;
//
// If a direct draw object has been declared and a video mode has been set
// then reset the video mode and release the direct draw object.
//
if ( DirectDrawObject ) {
result = DirectDrawObject->RestoreDisplayMode();
Process_DD_Result(result, false);
result = DirectDrawObject->Release();
Process_DD_Result(result, false);
DirectDrawObject = NULL;
}
}
/***********************************************************************************************
* Get_Free_Video_Memory -- returns amount of free video memory *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: bytes of available video RAM *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/29/95 12:52PM ST : Created *
*=============================================================================================*/
unsigned int Get_Free_Video_Memory(void)
{
DDCAPS video_capabilities;
if (DirectDrawObject) {
video_capabilities.dwSize = sizeof (video_capabilities);
if (DD_OK == DirectDrawObject->GetCaps (&video_capabilities, NULL)) {
char string [256];
wsprintf (string, "In Get_Free_Video_Memory. About to return %d bytes",video_capabilities.dwVidMemFree);
return (video_capabilities.dwVidMemFree);
}
}
return (0);
}
/***********************************************************************************************
* Get_Video_Hardware_Caps -- returns bitmask of direct draw video hardware support *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: hardware flags *
* *
* WARNINGS: Must call Set_Video_Mode 1st to create the direct draw object *
* *
* HISTORY: *
* 1/12/96 9:14AM ST : Created *
*=============================================================================================*/
unsigned Get_Video_Hardware_Capabilities(void)
{
DDCAPS video_capabilities;
unsigned video;
/*
** Fail if the direct draw object has not been initialised
*/
if (!DirectDrawObject) return (0);
/*
** Get the capabilities of the direct draw object
*/
video_capabilities.dwSize = sizeof(video_capabilities);
//MessageBox(MainWindow, "In Get_Video_Hardware_Capabilities. About to call GetCaps","Note", MB_ICONEXCLAMATION|MB_OK);
HRESULT result = DirectDrawObject->GetCaps (&video_capabilities, NULL);
if (result != DD_OK) {
Process_DD_Result(result, false);
return (0);
}
/*
** Set flags to indicate the presence of the features we are interested in
*/
video = 0;
/* Hardware blits supported? */
if (video_capabilities.dwCaps & DDCAPS_BLT) video |= VIDEO_BLITTER;
/* Hardware blits asyncronous? */
if (video_capabilities.dwCaps & DDCAPS_BLTQUEUE) video |= VIDEO_BLITTER_ASYNC;
/* Can palette changes be synced to vertical refresh? */
if (video_capabilities.dwCaps & DDCAPS_PALETTEVSYNC) video |= VIDEO_SYNC_PALETTE;
/* Is the video cards memory bank switched? */
if (video_capabilities.dwCaps & DDCAPS_BANKSWITCHED) video |= VIDEO_BANK_SWITCHED;
/* Can the blitter do filled rectangles? */
if (video_capabilities.dwCaps & DDCAPS_BLTCOLORFILL) video |= VIDEO_COLOR_FILL;
/* Is there no hardware assistance avaailable at all? */
if (video_capabilities.dwCaps & DDCAPS_NOHARDWARE) video |= VIDEO_NO_HARDWARE_ASSIST;
//MessageBox(MainWindow, "In Get_Video_Hardware_Capabilities. About to return success.","Note", MB_ICONEXCLAMATION|MB_OK);
return (video);
}
/***********************************************************************************************
* Wait_Vert_Blank -- Waits for the start (leading edge) of a vertical blank *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
void Wait_Vert_Blank(void)
{
if (CanVblankSync) {
HRESULT result = DirectDrawObject->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
if (result == E_NOTIMPL) {
CanVblankSync = false;
return;
}
Process_DD_Result(result, false);
}
}
/***********************************************************************************************
* Set_Palette -- set a direct draw palette *
* *
* *
* *
* INPUT: ptr to 768 rgb palette bytes *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/11/95 3:33PM ST : Created *
*=============================================================================================*/
void Set_Palette(void const * palette)
{
assert(palette != NULL);
if (&CurrentPalette[0] != palette) {
memmove(CurrentPalette, palette, sizeof(CurrentPalette));
}
if (DirectDrawObject != NULL && PaletteSurface != NULL) {
unsigned char * palette_get = (unsigned char *)palette;
for (int index = 0; index < 256; index++) {
int red = *palette_get++;
int green = *palette_get++;
int blue = *palette_get++;
PaletteEntries[index].peRed = (unsigned char)red;
PaletteEntries[index].peGreen = (unsigned char)green;
PaletteEntries[index].peBlue = (unsigned char)blue;
}
if (PalettePtr != NULL) {
if (!FirstPaletteSet) {
PaletteSurface->SetPalette(PalettePtr);
FirstPaletteSet = true;
}
PalettePtr->SetEntries(0, 0, 256, &PaletteEntries[0]);
}
}
}
/***********************************************************************************************
* Wait_Blit -- waits for the DirectDraw blitter to become idle *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 07-25-95 03:53pm ST : Created *
*=============================================================================================*/
void Wait_Blit (void)
{
HRESULT return_code;
do {
return_code=PaletteSurface->GetBltStatus (DDGBS_ISBLTDONE);
} while (return_code != DD_OK && return_code != DDERR_SURFACELOST);
}

View File

@@ -0,0 +1,75 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/Library/dib.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/26/97 11:33a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef DIB_H
#define DIB_H
#include "always.h"
#include "bsurface.h"
#include "palette.h"
#include "win.h"
class DIB8Class
{
public:
DIB8Class(HWND hwnd,int width, int height, PaletteClass & pal);
~DIB8Class(void);
HBITMAP Get_Handle() { return Handle; }
int Get_Width(void) { return Width; }
int Get_Height(void) { return Height; }
Surface & Get_Surface(void) { return *Surface; }
void Clear(unsigned char color);
private:
bool IsZombie; // object constructor failed, its a living-dead object!
BITMAPINFO * Info; // info used in creating the dib + the palette.
HBITMAP Handle; // handle to the actual dib
unsigned char * Pixels; // address of memory containing the pixel data
int Width; // width of the dib
int Height; // height of the dib
unsigned char * PixelBase; // address of upper left pixel (this and DIBPitch abstract up/down DIBS)
int Pitch; // offset from DIBPixelBase to next row (can be negative for bottom-up DIBS)
BSurface * Surface; // Bsurface wrapped around the pixel buffer.
};
#endif /*DIB_H*/

View File

@@ -0,0 +1,47 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Library/Draw.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/22/97 11:37a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef DRAW_H
#define DRAW_H
#include "convert.h"
#include "point.h"
#include "shapeset.h"
void Draw_Shape(Surface & surface, ConvertClass & convert, ShapeSet const * shapefile, int shapenum, Point2D const & point, Rect const & window, ShapeFlags_Type flags = SHAPE_NORMAL, unsigned char const * remap = NULL);
void Blit_Block(Surface & surface, ConvertClass & convert, Surface const & source, Rect const & sourcerect, Point2D const & point, Rect const & clipwindow, unsigned char const * remap = NULL, Blitter const * blitter = NULL);
#endif

View File

@@ -0,0 +1,931 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/dsurface.cpp $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 6/23/00 2:26p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* DSurface::Blit_From -- Blit from one surface to this one. *
* DSurface::Blit_From -- Blit graphic memory from one rectangle to another. *
* DSurface::Build_Hicolor_Pixel -- Construct a hicolor pixel according to the surface pixel *
* DSurface::Build_Remap_Table -- Build a highcolor remap table. *
* DSurface::Bytes_Per_Pixel -- Fetches the bytes per pixel of the surface. *
* DSurface::Create_Primary -- Creates a primary (visible) surface. *
* DSurface::DSurface -- Create a surface attached to specified DDraw Surface Object. *
* DSurface::DSurface -- Default constructor for surface object. *
* DSurface::DSurface -- Off screen direct draw surface constructor. *
* DSurface::Fill_Rect -- Fills a rectangle with clipping control. *
* DSurface::Fill_Rect -- This routine will fill the specified rectangle. *
* DSurface::Lock -- Fetches a working pointer into surface memory. *
* DSurface::Restore_Check -- Checks for and restores surface memory if necessary. *
* DSurface::Stride -- Fetches the bytes between rows. *
* DSurface::Unlock -- Unlock a previously locked surface. *
* DSurface::~DSurface -- Destructor for a direct draw surface object. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "dsurface.h"
#include <assert.h>
extern LPDIRECTDRAW DirectDrawObject; //pointer to direct draw object
extern LPDIRECTDRAWSURFACE PaletteSurface;
/*
** Clipper object (for primary surface).
*/
LPDIRECTDRAWCLIPPER DSurface::Clipper = NULL;
int DSurface::RedRight = 0;
int DSurface::RedLeft = 0;
int DSurface::BlueRight = 0;
int DSurface::BlueLeft = 0;
int DSurface::GreenRight = 0;
int DSurface::GreenLeft = 0;
unsigned short DSurface::HalfbrightMask = 0;
unsigned short DSurface::QuarterbrightMask = 0;
unsigned short DSurface::EighthbrightMask = 0;
DDPIXELFORMAT DSurface::PixelFormat;
/***********************************************************************************************
* DSurface::DSurface -- Off screen direct draw surface constructor. *
* *
* This constructor will create a Direct Draw enabled surface in video memory if possible. *
* Such a surface will be able to use hardware assist if possible. The surface created *
* is NOT visible. It only exists as a work surface and cannot be flipped to the visible *
* surface. It can only be blitted to the visible surface. *
* *
* INPUT: width -- The width of the surface to create. *
* *
* height -- The height of the surface to create. *
* *
* OUTPUT: none *
* *
* WARNINGS: The surface pixel format is the same as that of the visible display mode. It *
* is important to construct surfaces using this routine, only AFTER the display *
* mode has been set. *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
DSurface::DSurface(int width, int height, bool system_memory, DDPIXELFORMAT *pixform) :
XSurface(width, height),
BytesPerPixel(0),
LockPtr(NULL),
IsPrimary(false),
IsVideoRam(false),
SurfacePtr(NULL),
Description(NULL),
DCUnlockCount(0)
{
Description = W3DNEW DDSURFACEDESC;
if (Description != NULL) {
memset(Description, '\0', sizeof(DDSURFACEDESC));
Description->dwSize = sizeof(DDSURFACEDESC);
Description->dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
Description->dwWidth = width;
Description->dwHeight = height;
Description->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
if (system_memory == true)
Description->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
/*
** Was a custom (non-display-depth) pixel format specified?
*/
if (pixform)
{
Description->ddpfPixelFormat=*pixform;
Description->dwFlags |= DDSD_PIXELFORMAT;
}
DirectDrawObject->CreateSurface(Description, &SurfacePtr, NULL);
/*
** Get a description of the surface that was just allocated.
*/
if (SurfacePtr != NULL) {
memset(Description, '\0', sizeof(DDSURFACEDESC));
Description->dwSize = sizeof(DDSURFACEDESC);
SurfacePtr->GetSurfaceDesc(Description);
BytesPerPixel = (Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
IsVideoRam = ((Description->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) != 0);
/*
** If this is a hicolor surface, then build the shift values for
** building and extracting the colors from the hicolor pixel.
*/
if (BytesPerPixel == 2) {
int index;
int shift = Description->ddpfPixelFormat.dwRBitMask;
ThisRedRight = 0;
ThisRedLeft = 0;
for (index = 0; index < 16; index++) {
if (shift & 0x01) break;
shift >>= 1;
ThisRedRight++;
}
for (index = 0; index < 8; index++) {
if (shift & 0x80) break;
shift <<= 1;
ThisRedLeft++;
}
shift = Description->ddpfPixelFormat.dwGBitMask;
ThisGreenRight = 0;
ThisGreenLeft = 0;
for (index = 0; index < 16; index++) {
if (shift & 0x01) break;
ThisGreenRight++;
shift >>= 1;
}
for (index = 0; index < 8; index++) {
if (shift & 0x80) break;
ThisGreenLeft++;
shift <<= 1;
}
shift = Description->ddpfPixelFormat.dwBBitMask;
ThisBlueRight = 0;
ThisBlueLeft = 0;
for (index = 0; index < 16; index++) {
if (shift & 0x01) break;
ThisBlueRight++;
shift >>= 1;
}
for (index = 0; index < 8; index++) {
if (shift & 0x80) break;
ThisBlueLeft++;
shift <<= 1;
}
}
}
}
}
/***********************************************************************************************
* DSurface::~DSurface -- Destructor for a direct draw surface object. *
* *
* This will destruct (make invalid) the direct draw surface. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
DSurface::~DSurface(void)
{
/*
** If this is the primary surface, then the clipper must be detached from
** this surface and the clipper object deleted.
*/
if (IsPrimary && SurfacePtr != NULL && Clipper != NULL) {
SurfacePtr->SetClipper(NULL);
Clipper->Release();
Clipper = NULL;
}
/*
** Delete the description of the surface.
*/
delete Description;
Description = NULL;
if (SurfacePtr != NULL) {
SurfacePtr->Release();
}
SurfacePtr = NULL;
}
/***********************************************************************************************
* DSurface::DSurface -- Default constructor for surface object. *
* *
* This default constructor for a surface object should not be used. Although it properly *
* creates a non-functional surface, there is no use for such a surface. This default *
* constructor is provided for those rare cases where symatics require a default *
* constructor. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
DSurface::DSurface(void) :
BytesPerPixel(0),
LockPtr(NULL),
SurfacePtr(NULL),
Description(NULL),
DCUnlockCount(0)
{
Description = W3DNEW DDSURFACEDESC;
memset(Description, '\0', sizeof(DDSURFACEDESC));
Description->dwSize = sizeof(DDSURFACEDESC);
}
/***********************************************************************************************
* DSurface::GetDC -- Get the windows device context from our surface *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: Any current locks will get unlocked while the DC is held *
* *
* HISTORY: *
* 06/21/2000 NAK : Created. *
*=============================================================================================*/
HDC DSurface::GetDC(void)
{
HDC hdc = NULL;
HRESULT hr;
// We have to remove all current locks to get the device context unfortunately...
while (LockCount) {
Unlock();
DCUnlockCount++;
}
hr = SurfacePtr->GetDC(&hdc);
if (hr != DD_OK)
{
while(DCUnlockCount) // restore the lock state
{
Lock();
DCUnlockCount--;
}
return(NULL);
}
// GetDC() locks the surface internally, so we need to reflect that here
if (hr == DD_OK) {
LockCount++;
}else{
hdc = NULL;
}
return (hdc);
}
/***********************************************************************************************
* DSurface::ReleaseDC -- Release the windows device context from our surface *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: Restores any locks held before the call to GetDC() *
* *
* HISTORY: *
* 06/21/2000 NAK : Created. *
*=============================================================================================*/
int DSurface::ReleaseDC(HDC hdc)
{
HRESULT hr;
hr = SurfacePtr->ReleaseDC(hdc);
assert(hr == DD_OK);
// ReleaseDC() unlocks the surface internally, so we need to reflect that here.
if ((hr == DD_OK) && (LockCount > 0)) {
LockCount--;
}
while(DCUnlockCount) // restore the lock state
{
Lock();
DCUnlockCount--;
}
return (1);
}
/***********************************************************************************************
* DSurface::Create_Primary -- Creates a primary (visible) surface. *
* *
* This routine is used to create the surface object that represents the currently *
* visible display. The surface is not allocated, it is merely linked to the preexisting *
* surface that the Windows GDI is also currently using. *
* *
* INPUT: backsurface -- Optional pointer to specify where the backpage (flip enabled) *
* pointer will be placed. If this parameter is NULL, then no *
* back surface will be created. *
* *
* OUTPUT: Returns with a pointer to the primary surface. *
* *
* WARNINGS: There can be only one primary surface. If an additional call to this routine *
* is made, another surface pointer will be returned, but it will point to the *
* same surface as before. *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
DSurface * DSurface::Create_Primary(DSurface ** backsurface1)
{
DSurface * surface = W3DNEW DSurface();
int backcount = (backsurface1 != NULL) ? 1 : 0;
/*
** Setup parameter for creating the primary surface. This will
** always be the visible surface plus optional back buffers of identical
** dimensions.
*/
surface->Description->dwFlags = DDSD_CAPS;
surface->Description->ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (backcount > 0) {
surface->Description->ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX;
surface->Description->dwFlags |= DDSD_BACKBUFFERCOUNT;
surface->Description->dwBackBufferCount = backcount;
}
HRESULT result = DirectDrawObject->CreateSurface(surface->Description, &surface->SurfacePtr, NULL);
/*
** If the primary surface object was created, then fetch a pointer to the
** back buffer if there is one present.
*/
if (result == DD_OK) {
if (backcount > 0) {
LPDIRECTDRAWSURFACE back;
DDSCAPS caps;
caps.dwCaps = DDSCAPS_BACKBUFFER;
result = surface->SurfacePtr->GetAttachedSurface(&caps, &back);
if (result == DD_OK) {
*backsurface1 = W3DNEW DSurface(back);
}
}
/*
** Get a description of the surface that was just allocated.
*/
memset(surface->Description, '\0', sizeof(DDSURFACEDESC));
surface->Description->dwSize = sizeof(DDSURFACEDESC);
surface->SurfacePtr->GetSurfaceDesc(surface->Description);
surface->BytesPerPixel = (surface->Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
surface->IsPrimary = true;
// surface->Window.Set(Rect(0, 0, surface->Description->dwWidth, surface->Description->dwHeight));
surface->Width = surface->Description->dwWidth;
surface->Height = surface->Description->dwHeight;
PaletteSurface = surface->SurfacePtr;
/*
** Attach a clipper object to the surface so that it can cooperate
** with the system GDI. This only comes into play if there are going
** to be GDI graphical elements on top of the surface (normally this
** isn't the case for full screen games). It doesn't hurt to attach
** a clipper object anyway -- just in case.
*/
if (DirectDrawObject->CreateClipper(0, &Clipper, NULL) == DD_OK) {
if (Clipper->SetHWnd(0, GetActiveWindow()) == DD_OK) {
surface->SurfacePtr->SetClipper(Clipper);
}
}
/*
** Fetch the pixel format for the surface.
*/
memcpy(&PixelFormat, &surface->Description->ddpfPixelFormat, sizeof(DDPIXELFORMAT));
/*
** If this is a hicolor surface, then build the shift values for
** building and extracting the colors from the hicolor pixel.
*/
if (surface->Bytes_Per_Pixel() == 2) {
int index;
int shift = PixelFormat.dwRBitMask;
RedRight = 0;
RedLeft = 0;
for (index = 0; index < 16; index++) {
if (shift & 0x01) break;
shift >>= 1;
RedRight++;
}
for (index = 0; index < 8; index++) {
if (shift & 0x80) break;
shift <<= 1;
RedLeft++;
}
shift = PixelFormat.dwGBitMask;
GreenRight = 0;
GreenLeft = 0;
for (index = 0; index < 16; index++) {
if (shift & 0x01) break;
GreenRight++;
shift >>= 1;
}
for (index = 0; index < 8; index++) {
if (shift & 0x80) break;
GreenLeft++;
shift <<= 1;
}
shift = PixelFormat.dwBBitMask;
BlueRight = 0;
BlueLeft = 0;
for (index = 0; index < 16; index++) {
if (shift & 0x01) break;
BlueRight++;
shift >>= 1;
}
for (index = 0; index < 8; index++) {
if (shift & 0x80) break;
BlueLeft++;
shift <<= 1;
}
/*
** Create the halfbright mask.
*/
HalfbrightMask = (unsigned short)Build_Hicolor_Pixel(127, 127, 127);
QuarterbrightMask = (unsigned short)Build_Hicolor_Pixel(63, 63, 63);
EighthbrightMask = (unsigned short)Build_Hicolor_Pixel(31, 31, 31);
}
} else {
delete surface;
surface = NULL;
}
return(surface);
}
/***********************************************************************************************
* DSurface::DSurface -- Create a surface attached to specified DDraw Surface Object. *
* *
* If an existing Direct Draw Surface Object is available, use this constructor to create *
* a DSurface object that is attached to the surface specified. *
* *
* INPUT: surfaceptr -- Pointer to a preexisting Direct Draw Surface Object. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
DSurface::DSurface(LPDIRECTDRAWSURFACE surfaceptr) :
BytesPerPixel(0),
LockPtr(NULL),
SurfacePtr(surfaceptr),
Description(NULL)
{
if (SurfacePtr != NULL) {
Description = W3DNEW DDSURFACEDESC;
memset(Description, '\0', sizeof(DDSURFACEDESC));
Description->dwSize = sizeof(DDSURFACEDESC);
HRESULT result = SurfacePtr->GetSurfaceDesc(Description);
if (result == DD_OK) {
BytesPerPixel = (Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
// Window.Set(Rect(0, 0, Description->dwWidth, Description->dwHeight));
Width = Description->dwWidth;
Height = Description->dwHeight;
}
}
}
/***********************************************************************************************
* DSurface::Bytes_Per_Pixel -- Fetches the bytes per pixel of the surface. *
* *
* This routine will return with the number of bytes that each pixel consumes. The value *
* is dependant upon the graphic mode of the display. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with the bytes per pixel of the surface object. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
int DSurface::Bytes_Per_Pixel(void) const
{
return(BytesPerPixel);
}
/***********************************************************************************************
* DSurface::Stride -- Fetches the bytes between rows. *
* *
* This routine will return the number of bytes to add so that the pointer will be *
* positioned at the same column, but one row down the screen. This value may very well *
* NOT be equal to the width multiplied by the bytes per pixel. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with the byte difference between subsequent pixel rows. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
int DSurface::Stride(void) const
{
return(Description->lPitch);
}
/***********************************************************************************************
* DSurface::Lock -- Fetches a working pointer into surface memory. *
* *
* This routine will return with a pointer to the pixel at the location specified. In order *
* to directly manipulate surface memory, the surface memory must be mapped into the *
* program's logical address space. In addition, all blitter activity on the surface will *
* be suspended. Every call to Lock must be have a corresponding call to Unlock if the *
* pointer returned is not equal to NULL. *
* *
* INPUT: point -- Pixel coordinate to return a pointer to. *
* *
* OUTPUT: Returns with a pointer to the pixel specified. If the return value is NULL, then *
* the surface could not be locked and no call to Unlock should be performed. *
* *
* WARNINGS: It is important not to keep a surface locked indefinately since the blitter *
* will not be able to function. Due to the time that locking consumes, it is *
* also important to not perform unnecessarily frequent Lock calls. *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
void * DSurface::Lock(Point2D point) const
{
Restore_Check();
if (LockCount == 0) {
DDSURFACEDESC desc;
memset(&desc, '\0', sizeof(desc));
desc.dwSize = sizeof(desc);
HRESULT result = SurfacePtr->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL);
if (result != DD_OK) return(NULL);
memcpy(Description, &desc, sizeof(DDSURFACEDESC));
BytesPerPixel = (Description->ddpfPixelFormat.dwRGBBitCount+7)/8;
LockPtr = Description->lpSurface;
}
XSurface::Lock();
return(((char*)LockPtr) + point.Y * Stride() + point.X * Bytes_Per_Pixel());
}
/***********************************************************************************************
* DSurface::Unlock -- Unlock a previously locked surface. *
* *
* After a surface has been successfully locked, a call to the Unlock() function is *
* required. *
* *
* INPUT: none *
* *
* OUTPUT: bool; Was the unlock successful? *
* *
* WARNINGS: Only pair a call to Unlock if the prior Lock actually returned a non-NULL *
* value. *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
bool DSurface::Unlock(void) const
{
Restore_Check();
if (LockCount > 0) {
XSurface::Unlock();
if (LockCount == 0) {
SurfacePtr->Unlock(LockPtr);
LockPtr = NULL;
}
return(true);
}
return(false);
}
/***********************************************************************************************
* DSurface::Restore_Check -- Checks for and restores surface memory if necessary. *
* *
* This routine will check to see if surface memory has been lost to the surface. If it *
* has, then the surface memory will be restored. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
void DSurface::Restore_Check(void) const
{
if (SurfacePtr->IsLost() == DDERR_SURFACELOST) {
SurfacePtr->Restore();
if (LockCount > 0 && SurfacePtr->IsLost() != DDERR_SURFACELOST) {
int oldlockcount = LockCount;
LockCount = 0;
Lock();
LockCount++;
Unlock();
LockCount = oldlockcount;
}
}
}
/***********************************************************************************************
* DSurface::Blit_From -- Blit graphic memory from one rectangle to another. *
* *
* This routine will use the blitter (if possible) to blit a block of graphic memory from *
* one screen rectangle to another. If the rectangles do no match in size, scaling may *
* be performed. *
* *
* INPUT: destrect -- The destination rectangle. *
* *
* ssource -- The source surface to blit from. *
* *
* sourecrect -- The source rectangle. *
* *
* trans -- Should transparency checking be performed? *
* *
* OUTPUT: bool; Was the blit performed without error? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
bool DSurface::Blit_From(Rect const & destrect, Surface const & ssource, Rect const & sourcerect, bool trans)
{
return(Blit_From(Get_Rect(), destrect, ssource, ssource.Get_Rect(), sourcerect, trans));
}
/***********************************************************************************************
* DSurface::Blit_From -- Blit from one surface to this one. *
* *
* Use this routine to blit a rectangle from the specified surface to this surface while *
* performing clipping upon the blit rectangles specified. *
* *
* INPUT: dcliprect -- The clipping rectangle to use for this surface. *
* *
* destrect -- The destination rectangle of the blit. The is relative to the *
* dcliprect parameter. *
* *
* ssource -- The source surface of the blit. *
* *
* scliprect -- The source clipping rectangle. *
* *
* sourcrect -- The source rectangle of the blit. This rectangle is relative to *
* the source clipping rectangle. *
* *
* trans -- Is this a transparent blit request? *
* *
* OUTPUT: bool; Was there a blit performed? A 'false' return value would indicate that the *
* blit was clipped into nothing. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/27/1997 JLB : Created. *
*=============================================================================================*/
bool DSurface::Blit_From(Rect const & dcliprect, Rect const & destrect, Surface const & ssource, Rect const & scliprect, Rect const & sourcerect, bool trans)
{
if (!dcliprect.Is_Valid() || !scliprect.Is_Valid() || !destrect.Is_Valid() || !sourcerect.Is_Valid()) return(false);
/*
** For non-direct draw surfaces, perform a manual blit operation. This is also
** necessary if any of the surfaces are currently locked. It is also necessary if the
** blit regions overlap and the blitter cannot handle overlapped regions.
**
** NOTE: Its legal to blit to a locked surface but not from a locked surface.
** ST - 4/23/97 1:03AM
*/
if (!ssource.Is_Direct_Draw() || ((DSurface&)ssource).Is_Locked() || trans || Bytes_Per_Pixel() != ssource.Bytes_Per_Pixel()) {
return(XSurface::Blit_From(destrect, ssource, sourcerect, trans));
}
Restore_Check();
DSurface const & source = (DSurface const &)ssource;
Rect drect = destrect;
Rect srect = sourcerect;
Rect swindow = scliprect.Intersect(ssource.Get_Rect());
Rect dwindow = dcliprect.Intersect(Get_Rect());
if (Blit_Clip(drect, dwindow, srect, swindow)) {
RECT xdestrect;
xdestrect.left = drect.X+dwindow.X;
xdestrect.top = drect.Y+dwindow.Y;
xdestrect.right = drect.X+dwindow.X+drect.Width;
xdestrect.bottom = drect.Y+dwindow.Y+drect.Height;
RECT xsrcrect;
xsrcrect.left = srect.X+swindow.X;
xsrcrect.top = srect.Y+swindow.Y;
xsrcrect.right = srect.X+swindow.X+srect.Width;
xsrcrect.bottom = srect.Y+swindow.Y+srect.Height;
HRESULT result = SurfacePtr->Blt(&xdestrect, source.SurfacePtr, &xsrcrect, DDBLT_WAIT, NULL);
return(result == DD_OK);
}
return(false);
}
/***********************************************************************************************
* DSurface::Fill_Rect -- This routine will fill the specified rectangle. *
* *
* This routine will fill the specified rectangle with a color. *
* *
* INPUT: fillrect -- The rectangle to fill. *
* *
* color -- The color to fill with. *
* *
* OUTPUT: bool; Was the fill performed without error? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 02/07/1997 JLB : Created. *
*=============================================================================================*/
bool DSurface::Fill_Rect(Rect const & fillrect, int color)
{
return(DSurface::Fill_Rect(Get_Rect(), fillrect, color));
}
/***********************************************************************************************
* DSurface::Fill_Rect -- Fills a rectangle with clipping control. *
* *
* This routine will fill a rectangle on this surface, but will clip the request against *
* a clipping rectangle first. *
* *
* INPUT: cliprect -- The clipping rectangle to use for this surface. *
* *
* fillrect -- The rectangle to fill with the specified color. The rectangle is *
* relative to the clipping rectangle. *
* *
* color -- The color (surface dependant format) to use when filling the rectangle *
* pixels. *
* *
* OUTPUT: bool; Was a fill operation performed? A 'false' return value would mean that the *
* fill request was clipped into nothing. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/27/1997 JLB : Created. *
*=============================================================================================*/
bool DSurface::Fill_Rect(Rect const & cliprect, Rect const & fillrect, int color)
{
if (!fillrect.Is_Valid()) return(false);
/*
** If the buffer is locked, then using the blitter to perform the fill is not possible.
** In such a case, perform a manual fill of the region.
*/
if (Is_Locked()) {
return(XSurface::Fill_Rect(cliprect, fillrect, color));
}
Restore_Check();
/*
** Ensure that the clipping rectangle is legal.
*/
Rect crect = cliprect.Intersect(Get_Rect());
/*
** Bias the fill rect to the clipping rectangle.
*/
Rect frect = fillrect.Bias_To(cliprect);
/*
** Find the region that should be filled after being clipped by the
** clipping rectangle. This could result in no fill operation being performed
** if the desired fill rectangle has been completely clipped away.
*/
frect = frect.Intersect(crect);
if (!frect.Is_Valid()) return(false);
RECT rect;
rect.left = frect.X;
rect.top = frect.Y;
rect.right = rect.left + frect.Width;
rect.bottom = rect.top + frect.Height;
DDBLTFX fx;
memset(&fx, '\0', sizeof(fx));
fx.dwSize = sizeof(fx);
fx.dwFillColor = color;
HRESULT result = SurfacePtr->Blt(&rect, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
return(result == DD_OK);
}
/***********************************************************************************************
* DSurface::Build_Hicolor_Pixel -- Construct a hicolor pixel according to the surface pixel f *
* *
* This routine will construct a pixel according to the highcolor pixel format for this *
* surface. *
* *
* INPUT: red -- The red component of the color (0..255). *
* *
* green -- The green component of the color (0..255). *
* *
* blue -- The blue component of the color (0..255). *
* *
* OUTPUT: Returns with a screen format pixel number that most closesly matches the color *
* specified. *
* *
* WARNINGS: The return value is card dependant and only applies to hicolor displays. *
* *
* HISTORY: *
* 05/27/1997 JLB : Created. *
*=============================================================================================*/
int DSurface::Build_Hicolor_Pixel(int red, int green, int blue)
{
return(((red >> RedLeft) << RedRight) | ((green >> GreenLeft) << GreenRight) | ((blue >> BlueLeft) << BlueRight));
}
/***********************************************************************************************
* DSurface::Build_Remap_Table -- Build a highcolor remap table. *
* *
* This will build a complete hicolor remap table for the palette specified. This table *
* can then be used to quickly fetch a pixel that matches the color index of the palette. *
* *
* INPUT: table -- The location to store the hicolor table. The buffer must be 256*2 bytes *
* long. *
* *
* palette -- The palette to use to create the remap table. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/27/1997 JLB : Created. *
*=============================================================================================*/
void DSurface::Build_Remap_Table(unsigned short * table, PaletteClass const & palette)
{
assert(table != NULL);
/*
** Build the hicolor index table according to the palette.
*/
for (int index = 0; index < 256; index++) {
table[index] = (unsigned short)Build_Hicolor_Pixel(palette[index].Get_Red(), palette[index].Get_Green(), palette[index].Get_Blue());
}
}

View File

@@ -0,0 +1,205 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /G/wwlib/dsurface.h $*
* *
* $Author:: Neal_k $*
* *
* $Modtime:: 6/23/00 2:24p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef DSURFACE_H
#define DSURFACE_H
#include "palette.h"
#include "win.h"
#include "xsurface.h"
#include <ddraw.h>
/*
** This is a concrete surface class that is based on the DirectDraw
** API.
*/
class DSurface : public XSurface
{
typedef XSurface BASECLASS;
public:
virtual ~DSurface(void);
/*
** Default constructor.
*/
DSurface(void);
/*
** Constructs a working surface (not visible).
*/
DSurface(int width, int height, bool system_memory = false, DDPIXELFORMAT *pixform=NULL);
/*
** Creates a surface from a previously created DirectDraw surface object.
*/
DSurface(LPDIRECTDRAWSURFACE surfaceptr);
/*
** Get/Release a windows device context from a DirectX surface
*/
HDC GetDC(void);
int ReleaseDC(HDC hdc);
/*
** Create a surface object that represents the currently visible screen.
*/
static DSurface * Create_Primary(DSurface ** backsurface1=NULL);
/*
** Copies regions from one surface to another.
*/
virtual bool Blit_From(Rect const & dcliprect, Rect const & destrect, Surface const & source, Rect const & scliprect, Rect const & sourcerect, bool trans=false);
virtual bool Blit_From(Rect const & destrect, Surface const & source, Rect const & sourcerect, bool trans=false);
virtual bool Blit_From(Surface const & source, bool trans=false) {return(XSurface::Blit_From(source, trans));}
/*
** Fills a region with a constant color.
*/
virtual bool Fill_Rect(Rect const & rect, int color);
virtual bool Fill_Rect(Rect const & cliprect, Rect const & fillrect, int color);
/*
** Gets and frees a direct pointer to the video memory.
*/
virtual void * Lock(Point2D point = Point2D(0, 0)) const;
virtual bool Unlock(void) const;
/*
** Queries information about the surface.
*/
virtual int Bytes_Per_Pixel(void) const;
virtual int Stride(void) const;
bool In_Video_Ram(void) const {return(IsVideoRam);}
/*
** Verifies that this is a direct draw enabled surface.
*/
virtual bool Is_Direct_Draw(void) const {return(true);}
static int Build_Hicolor_Pixel(int red, int green, int blue);
static void Build_Remap_Table(unsigned short * table, PaletteClass const & palette);
static unsigned short Get_Halfbright_Mask(void) {return(HalfbrightMask);}
static unsigned short Get_Quarterbright_Mask(void) {return(QuarterbrightMask);}
static unsigned short Get_Eighthbright_Mask(void) {return(EighthbrightMask);}
protected:
void Restore_Check(void) const;
/*
** Convenient copy of the bytes per pixel value to speed accessing it. It
** gets accessed frequently.
*/
mutable int BytesPerPixel;
/*
** Lock count and pointer values. This is used to keep track of the levels
** of locking the graphic data. This is only here because DirectDraw prohibits
** the blitter from working on a surface that has been locked.
*/
mutable void * LockPtr;
/*
** If this surface object represents the one that is visible and associated
** with the system GDI, then this flag will be true.
*/
bool IsPrimary;
/*
** Is this surface represented in video ram?
*/
bool IsVideoRam;
/*
** Direct draw specific data.
*/
LPDIRECTDRAWSURFACE SurfacePtr;
DDSURFACEDESC * Description;
/*
** Pointer to the clipper object that is attached to the primary
** surface.
*/
static LPDIRECTDRAWCLIPPER Clipper;
/*
** Pixel format of primary surface.
*/
static DDPIXELFORMAT PixelFormat;
/*
** Shift values to extract the gun value from a hicolor pixel such that the
** gun component is normalized to a byte value.
*/
static int RedRight;
static int RedLeft;
static int BlueRight;
static int BlueLeft;
static int GreenRight;
static int GreenLeft;
public:
/*
** Shift values specific to this surface (the above are for the primary surface)
*/
int ThisRedRight;
int ThisRedLeft;
int ThisBlueRight;
int ThisBlueLeft;
int ThisGreenRight;
int ThisGreenLeft;
protected:
static unsigned short HalfbrightMask;
static unsigned short QuarterbrightMask;
static unsigned short EighthbrightMask;
/*
** Number of locks we had to remove in order to get the device context...
*/
int DCUnlockCount;
private:
/*
** This prevents the creation of a surface in ways that are not
** supported.
*/
DSurface(DSurface const & rvalue);
DSurface const operator = (DSurface const & rvalue);
};
#endif

View File

@@ -0,0 +1,310 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/ffactory.cpp $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 8/24/01 11:50a $*
* *
* $Revision:: 17 $*
* *
*---------------------------------------------------------------------------------------------*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "ffactory.h"
#include "rawfile.h"
#include "bufffile.h"
#include "realcrc.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
/*
** Statics
** NOTE: If _TheFileFactory is ever changed to point to an object of a different class which does
** not derive from SimpleFileFactoryClass, _TheSimpleFileFactory should be set to NULL.
*/
SimpleFileFactoryClass _DefaultFileFactory;
FileFactoryClass * _TheFileFactory = &_DefaultFileFactory;
RawFileFactoryClass _DefaultWritingFileFactory;
RawFileFactoryClass * _TheWritingFileFactory = &_DefaultWritingFileFactory;
/*
**
*/
file_auto_ptr::file_auto_ptr(FileFactoryClass *fac, const char *filename) :
_Ptr(NULL), _Fac(fac)
{
assert(_Fac);
_Ptr=_Fac->Get_File(filename);
if ( _Ptr == NULL ) {
_Ptr = W3DNEW BufferedFileClass();
}
}
file_auto_ptr::~file_auto_ptr()
{
_Fac->Return_File(_Ptr);
}
/*
** RawFileFactoryClass implementation
*/
RawFileClass * RawFileFactoryClass::Get_File( char const *filename )
{
return W3DNEW RawFileClass( filename );
}
void RawFileFactoryClass::Return_File( FileClass *file )
{
delete file;
}
/*
** SimpleFileFactoryClass implementation
*/
SimpleFileFactoryClass::SimpleFileFactoryClass( void ) :
IsStripPath( false ),
Mutex( )
{
}
void SimpleFileFactoryClass::Get_Sub_Directory( StringClass& new_dir ) const
{
// BEGIN SERIALIZATION
// We cannot return a const char * here because the StringClass
// may reallocate its buffer during a call to Set_Sub_Directory.
// I opted to return a StringClass instead of a reference to
// StringClass because it seems like that would behave more
// reasonably. (no sudden changes from or to empty string in
// the middle of a calling function.) (DRM, 04/19/01)
// Jani: Returning a StringClass object causes a memory allocation
// and release so it is better to take a reference to the
// destination StringClass object and modify that.
CriticalSectionClass::LockClass lock(Mutex);
new_dir=SubDirectory;
// END SERIALIZATION
}
void SimpleFileFactoryClass::Set_Sub_Directory( const char * sub_directory )
{
// BEGIN SERIALIZATION
// StringClass makes no guarantees on the atomicity of assignment.
// Just to be safe, we lock before executing the assignment code.
// (DRM, 04/19/01)
CriticalSectionClass::LockClass lock(Mutex);
SubDirectory = sub_directory;
// END SERIALIZATION
}
void SimpleFileFactoryClass::Prepend_Sub_Directory( const char * sub_directory )
{
int sub_len = strlen(sub_directory);
// Overflow prevention
if (sub_len > 1021) {
WWASSERT(0);
return;
} else if (sub_len < 1) {
return;
}
// Ensure sub_directory ends with a slash, and append a semicolon
char temp_sub_dir[1024];
strcpy(temp_sub_dir, sub_directory);
if (temp_sub_dir[sub_len - 1] != '\\') {
temp_sub_dir[sub_len] = '\\';
temp_sub_dir[sub_len + 1] = 0;
sub_len++;
}
temp_sub_dir[sub_len] = ';';
temp_sub_dir[sub_len + 1] = 0;
// BEGIN SERIALIZATION
// StringClass makes no guarantees on the atomicity of concatenation.
// Just to be safe, we lock before executing the concatenation code.
// (NH, 04/23/01)
CriticalSectionClass::LockClass lock(Mutex);
SubDirectory = temp_sub_dir + SubDirectory;
// END SERIALIZATION
}
void SimpleFileFactoryClass::Append_Sub_Directory( const char * sub_directory )
{
int sub_len = strlen(sub_directory);
// Overflow prevention
if (sub_len > 1022) {
WWASSERT(0);
return;
} else if (sub_len < 1) {
return;
}
// Ensure sub_directory ends with a slash
char temp_sub_dir[1024];
strcpy(temp_sub_dir, sub_directory);
if (temp_sub_dir[sub_len - 1] != '\\') {
temp_sub_dir[sub_len] = '\\';
temp_sub_dir[sub_len + 1] = 0;
sub_len++;
}
// BEGIN SERIALIZATION
// We are doing various dependent operations on SubDirectory.
// Just to be safe, we lock before this section.
// (NH, 04/23/01)
CriticalSectionClass::LockClass lock(Mutex);
// Ensure a trailing semicolon is present, unless the directory list is empty
int len = SubDirectory.Get_Length();
if (len && SubDirectory[len - 1] != ';') {
SubDirectory += ';';
}
SubDirectory += temp_sub_dir;
// END SERIALIZATION
}
/*
** Is_Full_Path
*/
static bool
Is_Full_Path (const char *path)
{
bool retval = false;
if (path != NULL && path[0] != 0) {
// Check for drive designation
retval = bool(path[1] == ':');
// Check for network path
retval |= bool((path[0] == '\\') && (path[1] == '\\'));
}
return retval;
}
/*
**
*/
FileClass * SimpleFileFactoryClass::Get_File( char const *filename )
{
// strip off the path (if needed). Note that if path stripping is off, and the requested file
// has a path in its name, and the current subdirectory is not empty, the paths will just be
// concatenated which may not produce reasonable results.
StringClass stripped_name(true);
if (IsStripPath) {
const char * ptr = ::strrchr( filename, '\\' );
if (ptr != 0) {
ptr++;
stripped_name = ptr;
} else {
stripped_name = filename;
}
} else {
stripped_name = filename;
}
RawFileClass *file = W3DNEW BufferedFileClass();// new RawWritingFileClass();
assert( file );
//
// Do we need to find the path for this file request?
//
StringClass new_name(stripped_name,true);
if (Is_Full_Path ( new_name ) == false) {
// BEGIN SERIALIZATION
// We need to lock here because we are using the contents of SubDirectory
// in two places. I'd rather be overly cautious about the implementation
// of StringClass and wrap all calls to it. We can optimize later if this
// proves too slow. (DRM, 04/19/01)
CriticalSectionClass::LockClass lock(Mutex);
if (!SubDirectory.Is_Empty()) {
//
// SubDirectory may contain a semicolon seperated search path...
// If the file doesn't exist, we'll set the path to the last dir in
// the search path. Therefore newly created files will always go in the
// last dir in the search path.
//
StringClass subdir(SubDirectory,true);
if (strchr(subdir,';'))
{
char *tokstart=subdir.Peek_Buffer();
const char *tok;
while((tok=strtok(tokstart, ";")) != NULL) {
tokstart=NULL;
new_name.Format("%s%s",tok,stripped_name.Peek_Buffer());
file->Set_Name( new_name ); // Call Set_Name to force an allocated name
if (file->Open()) {
file->Close();
break;
}
}
} else {
new_name.Format("%s%s",SubDirectory,stripped_name);
}
}
// END SERIALIZATION
}
file->Set_Name( new_name ); // Call Set_Name to force an allocated name
return file;
}
void SimpleFileFactoryClass::Return_File( FileClass *file )
{
delete file;
}

View File

@@ -0,0 +1,160 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/wwlib/ffactory.h $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 8/24/01 11:50a $*
* *
* $Revision:: 13 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef FFACTORY_H
#define FFACTORY_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#include "mutex.h"
#include "vector.h"
#include "wwstring.h"
/*
**
*/
#include "rawfile.h"
class FileClass;
/*
** FileFactoryClass is a pure virtual class used to
** create FileClasses.
*/
class FileFactoryClass {
public:
virtual FileClass * Get_File( char const *filename ) = 0;
virtual void Return_File( FileClass *file ) = 0;
};
//
// Handy auto pointer class. Prevents you from having to call Return_File manually
//
class file_auto_ptr
{
public:
explicit file_auto_ptr(FileFactoryClass *fac, const char *filename);
~file_auto_ptr();
operator FileClass*(void) const
{return (get()); }
FileClass& operator*() const
{return (*get()); }
FileClass *operator->() const
{return (get()); }
FileClass *get() const
{return (_Ptr); }
private:
// prevent these from getting auto-generated or used
file_auto_ptr(const file_auto_ptr &other);
file_auto_ptr &operator=(const file_auto_ptr &other);
FileClass *_Ptr;
FileFactoryClass *_Fac;
};
/*
** RawFileFactoryClass is a derived FileFactoryClass which
** gives RawFileClass objects
*/
class RawFileFactoryClass {
public:
RawFileClass * Get_File( char const *filename );
void Return_File( FileClass *file );
};
#define no_SIMPLE_FILE
/*
** SimpleFileFactoryClass is a slightly more capable derivative of
** FileFactoryClass which adds some simple extra functionality. It supports a
** current subdirectory, and also adds some logging capabilities. Note that
** it currently creates BufferedFileClass objects instead of RawFileClass
** objects.
*/
class SimpleFileFactoryClass : public FileFactoryClass {
public:
SimpleFileFactoryClass( void );
~SimpleFileFactoryClass( void ) {}
virtual FileClass * Get_File( char const *filename );
virtual void Return_File( FileClass *file );
// sub_directory may be a semicolon seperated search path. New files will always
// go in the last dir in the path.
void Get_Sub_Directory( StringClass& new_dir ) const;
void Set_Sub_Directory( const char * sub_directory );
void Prepend_Sub_Directory( const char * sub_directory );
void Append_Sub_Directory( const char * sub_directory );
bool Get_Strip_Path( void ) const { return IsStripPath; }
void Set_Strip_Path( bool set ) { IsStripPath = set; }
protected:
StringClass SubDirectory;
bool IsStripPath;
// Mutex must be mutable because const functions lock on it.
mutable CriticalSectionClass Mutex;
};
extern FileFactoryClass * _TheFileFactory;
extern RawFileFactoryClass * _TheWritingFileFactory;
// No simple file factory. jba.
//extern SimpleFileFactoryClass * _TheSimpleFileFactory;
#endif

View File

@@ -0,0 +1,220 @@
/*
** Command & Conquer Generals(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/>.
*/
/* $Header: /Commando/Library/FIXED.H 1 7/22/97 12:00p Greg_h $ */
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* File Name : FIXED.H *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : 06/19/96 *
* *
* Last Update : June 19, 1996 [JLB] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef FIXED_H
#define FIXED_H
#include "bool.h"
//#pragma warning 604 9
//#pragma warning 595 9
/*
** This is a very simple fixed point class that functions like a regular integral type. However
** it is under certain restrictions. The whole part must not exceed 255. The fractional part is
** limited to an accuracy of 1/256. It cannot represent or properly handle negative values. It
** really isn't all that fast (if an FPU is guaranteed to be present than using "float" might be
** more efficient). It doesn't detect overflow or underflow in mathematical or bit-shift operations.
**
** Take careful note that the normal mathematical operators return integers and not fixed point
** values if either of the components is an integer. This is the normal C auto-upcasting rule
** as it would apply presuming that integers are considered to be of higher precision than
** fixed point numbers. This allows the result of these operators to generate values with greater
** magnitude than is normally possible if the result were coerced into a fixed point number.
** If the result should be fixed point, then ensure that both parameters are fixed point.
**
** Note that although integers are used as the parameters in the mathematical operators, this
** does not imply that negative parameters are supported. The use of integers is as a convenience
** to the programmer -- constant integers are presumed signed. If unsigned parameters were
** specified, then the compiler would have ambiguous conversion situation in the case of constant
** integers (e.g. 1, 10, 32, etc). This is most important for the constructor when dealing with the
** "0" parameter case. In that situation the compiler might interpret the "0" as a null pointer rather
** than an unsigned integer. There should be no adverse consequences of using signed integer parameters
** since the precision/magnitude of these integers far exceeds the fixed point component counterparts.
**
** Note that when integer values are returns from the arithmetic operators, the value is rounded
** to the nearest whole integer value. This differs from normal integer math that always rounds down.
*/
class fixed
{
public:
// The default constructor must not touch the data members in any way.
fixed(void) {}
// Convenient constructor if numerator and denominator components are known.
fixed(int numerator, int denominator);
// Conversion constructor to get fixed point from integer.
fixed(int value) {Data.Composite.Fraction = 0;Data.Composite.Whole = (unsigned char)value;}
// Constructor if ASCII image of number is known.
fixed(char const * ascii);
// Convert to integer when implicitly required.
operator unsigned (void) const {return(((unsigned)Data.Raw+(256/2)) / 256);}
/*
** The standard operators as they apply to in-place operation.
*/
fixed & operator *= (fixed const & rvalue) {Data.Raw = (unsigned short)(((int)Data.Raw * rvalue.Data.Raw) / 256);return(*this);}
fixed & operator *= (int rvalue) {Data.Raw = (unsigned short)(Data.Raw * rvalue);return(*this);}
fixed & operator /= (fixed const & rvalue) {if (rvalue.Data.Raw != 0 && rvalue.Data.Raw != 256) Data.Raw = (unsigned short)(((int)Data.Raw * 256) / rvalue);return(*this);}
fixed & operator /= (int rvalue) {if (rvalue) Data.Raw = (unsigned short)((unsigned)Data.Raw / rvalue);return(*this);}
fixed & operator += (fixed const & rvalue) {Data.Raw += rvalue.Data.Raw;return(*this);}
fixed & operator -= (fixed const & rvalue) {Data.Raw -= rvalue.Data.Raw;return(*this);}
/*
** The standard "My Dear Aunt Sally" operators. The integer versions of multiply
** and divide are more efficient than using the fixed point counterparts.
*/
// const fixed operator * (fixed const & rvalue) const {return(fixed(*this) *= rvalue);}
const fixed operator * (fixed const & rvalue) const {fixed temp = *this;temp.Data.Raw = (unsigned short)(((int)temp.Data.Raw * (int)rvalue.Data.Raw) / 256);return(temp);}
const int operator * (int rvalue) const {return ((((unsigned)Data.Raw * rvalue) + (256/2)) / 256);}
// const fixed operator / (fixed const & rvalue) const {return(fixed(*this) /= rvalue);}
const fixed operator / (fixed const & rvalue) const {fixed temp = *this;if (rvalue.Data.Raw != 0 && rvalue.Data.Raw != 256) temp.Data.Raw = (unsigned short)(((int)temp.Data.Raw * 256) / rvalue.Data.Raw);return(temp);}
const int operator / (int rvalue) const {if (rvalue) return(((unsigned)Data.Raw+(256/2)) / ((unsigned)rvalue*256));return(*this);}
// const fixed operator + (fixed const & rvalue) const {return(fixed(*this) += rvalue);}
const fixed operator + (fixed const & rvalue) const {fixed temp = *this;temp += rvalue;return(temp);}
const int operator + (int rvalue) const {return((((unsigned)Data.Raw+(256/2))/256) + rvalue);}
// const fixed operator - (fixed const & rvalue) const {return(fixed(*this) -= rvalue);}
const fixed operator - (fixed const & rvalue) const {fixed temp = *this;temp -= rvalue;return(temp);}
const int operator - (int rvalue) const {return((((unsigned)Data.Raw+(256/2))/256) - rvalue);}
/*
** The Shift operators are more efficient than using multiplies or divides by power-of-2 numbers.
*/
fixed & operator >>= (unsigned rvalue) {Data.Raw >>= rvalue;return(*this);}
fixed & operator <<= (unsigned rvalue) {Data.Raw <<= rvalue;return(*this);}
const fixed operator >> (unsigned rvalue) const {fixed temp = *this;temp >>= rvalue;return(temp);}
const fixed operator << (unsigned rvalue) const {fixed temp = *this;temp <<= rvalue;return(temp);}
/*
** The full set of comparison operators.
*/
bool operator == (fixed const & rvalue) const {return(Data.Raw == rvalue.Data.Raw);}
bool operator != (fixed const & rvalue) const {return(Data.Raw != rvalue.Data.Raw);}
bool operator < (fixed const & rvalue) const {return(Data.Raw < rvalue.Data.Raw);}
bool operator > (fixed const & rvalue) const {return(Data.Raw > rvalue.Data.Raw);}
bool operator <= (fixed const & rvalue) const {return(Data.Raw <= rvalue.Data.Raw);}
bool operator >= (fixed const & rvalue) const {return(Data.Raw >= rvalue.Data.Raw);}
bool operator ! (void) const {return(Data.Raw == 0);}
/*
** Comparison to integers requires consideration of fractional component.
*/
bool operator < (int rvalue) const {return(Data.Raw < (rvalue*256));}
bool operator > (int rvalue) const {return(Data.Raw > (rvalue*256));}
bool operator <= (int rvalue) const {return(Data.Raw <= (rvalue*256));}
bool operator >= (int rvalue) const {return(Data.Raw >= (rvalue*256));}
bool operator == (int rvalue) const {return(Data.Raw == (rvalue*256));}
bool operator != (int rvalue) const {return(Data.Raw != (rvalue*256));}
/*
** Friend functions to handle the alternate positioning of fixed and integer parameters.
*/
friend const int operator * (int lvalue, fixed const & rvalue) {return(rvalue * lvalue);}
friend const int operator / (int lvalue, fixed const & rvalue) {if (rvalue.Data.Raw == 0 || rvalue.Data.Raw == 256) return (lvalue); return(((unsigned)(lvalue * 256)+(256/2)) / rvalue.Data.Raw);}
friend const int operator + (int lvalue, fixed const & rvalue) {return(rvalue + lvalue);}
friend const int operator - (int lvalue, fixed const & rvalue) {return((((lvalue*256) - rvalue.Data.Raw) + (256/2)) / 256);}
friend bool operator < (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) < rvalue.Data.Raw);}
friend bool operator > (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) > rvalue.Data.Raw);}
friend bool operator <= (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) <= rvalue.Data.Raw);}
friend bool operator >= (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) >= rvalue.Data.Raw);}
friend bool operator == (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) == rvalue.Data.Raw);}
friend bool operator != (unsigned lvalue, fixed const & rvalue) {return((lvalue*256) != rvalue.Data.Raw);}
friend int operator *= (int & lvalue, fixed const & rvalue) {lvalue = lvalue * rvalue;return(lvalue);}
friend int operator /= (int & lvalue, fixed const & rvalue) {lvalue = lvalue / rvalue;return(lvalue);}
friend int operator += (int & lvalue, fixed const & rvalue) {lvalue = lvalue + rvalue;return(lvalue);}
friend int operator -= (int & lvalue, fixed const & rvalue) {lvalue = lvalue - rvalue;return(lvalue);}
/*
** Helper functions to handle simple and common operations on fixed point numbers.
*/
void Round_Up(void) {Data.Raw += (unsigned short)(256-1);Data.Composite.Fraction = 0;}
void Round_Down(void) {Data.Composite.Fraction = 0;}
void Round(void) {if (Data.Composite.Fraction >= 256/2) Round_Up();Round_Down();}
void Saturate(unsigned capvalue) {if (Data.Raw > (capvalue*256)) Data.Raw = (unsigned short)(capvalue*256);}
void Saturate(fixed const & capvalue) {if (*this > capvalue) *this = capvalue;}
void Sub_Saturate(unsigned capvalue) {if (Data.Raw >= (capvalue*256)) Data.Raw = (unsigned short)((capvalue*256)-1);}
void Sub_Saturate(fixed const & capvalue) {if (*this >= capvalue) Data.Raw = (unsigned short)(capvalue.Data.Raw-1);}
void Inverse(void) {*this = fixed(1) / *this;}
/*
** Friend helper functions that work in the typical C fashion of passing the object to
** be processed as a parameter to the function.
*/
friend const fixed Round_Up(fixed const & value) {fixed temp = value; temp.Round_Up();return(temp);}
friend const fixed Round_Down(fixed const & value) {fixed temp = value; temp.Round_Down();return(temp);}
friend const fixed Round(fixed const & value) {fixed temp = value; temp.Round();return(temp);}
friend const fixed Saturate(fixed const & value, unsigned capvalue) {fixed temp = value;temp.Saturate(capvalue);return(temp);}
friend const fixed Saturate(fixed const & value, fixed const & capvalue) {fixed temp = value;temp.Saturate(capvalue);return(temp);}
friend const fixed Sub_Saturate(fixed const & value, unsigned capvalue) {fixed temp = value;temp.Sub_Saturate(capvalue);return(temp);}
friend const fixed Sub_Saturate(fixed const & value, fixed const & capvalue) {fixed temp = value;temp.Sub_Saturate(capvalue);return(temp);}
friend const fixed Inverse(fixed const & value) {fixed temp = value;temp.Inverse();return(temp);}
/*
** Conversion of the fixed point number into an ASCII string.
*/
int To_ASCII(char * buffer, int maxlen=-1) const;
char const * As_ASCII(void) const;
/*
** Helper constants that provide some convenient fixed point values.
*/
static const fixed _1_2;
static const fixed _1_3;
static const fixed _1_4;
static const fixed _3_4;
static const fixed _2_3;
private:
union {
struct {
#ifdef BIG_ENDIAN
unsigned char Whole;
unsigned char Fraction;
#else
unsigned char Fraction;
unsigned char Whole;
#endif
} Composite;
unsigned short Raw;
} Data;
};
#endif

View File

@@ -0,0 +1,52 @@
/*
** Command & Conquer Generals(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : G *
* *
* $Archive:: /G/wwlib/gcd_lcm.cpp $*
* *
* $Author:: Naty_h $*
* *
* $Modtime:: 8/25/99 11:31a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "gcd_lcm.h"
unsigned int Greatest_Common_Divisor(unsigned int a, unsigned int b)
{
// This uses Euclid's algorithm
if (b == 0) {
return a;
} else {
return Greatest_Common_Divisor(b, a % b);
}
}
unsigned int Least_Common_Multiple(unsigned int a, unsigned int b)
{
return (a * b) / Greatest_Common_Divisor(a, b);
}

Some files were not shown because too many files have changed in this diff Show More