mirror of
https://github.com/electronicarts/CnC_Red_Alert.git
synced 2025-06-06 21:28:22 +02:00
Initial commit of Command & Conquer Red Alert source code.
This commit is contained in:
parent
b685cea758
commit
5e733d5dcc
4848
CODE/2KEYFBUF.ASM
Normal file
4848
CODE/2KEYFBUF.ASM
Normal file
File diff suppressed because it is too large
Load Diff
583
CODE/2KEYFRAM.CPP
Normal file
583
CODE/2KEYFRAM.CPP
Normal file
@ -0,0 +1,583 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/2KEYFRAM.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : KEYFRAME.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 06/25/95 *
|
||||
* *
|
||||
* Last Update : June 25, 1995 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Get_Build_Frame_Count -- Fetches the number of frames in data block. *
|
||||
* Get_Build_Frame_Width -- Fetches the width of the shape image. *
|
||||
* Get_Build_Frame_Height -- Fetches the height of the shape image. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "function.h"
|
||||
|
||||
#define SUBFRAMEOFFS 7 // 3 1/2 frame offsets loaded (2 offsets/frame)
|
||||
|
||||
|
||||
#define Apply_Delta(buffer, delta) Apply_XOR_Delta((char*)(buffer), (char*)(delta))
|
||||
|
||||
typedef struct {
|
||||
unsigned short frames;
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
unsigned short largest_frame_size;
|
||||
short flags;
|
||||
} KeyFrameHeaderType;
|
||||
|
||||
#define INITIAL_BIG_SHAPE_BUFFER_SIZE 8000000
|
||||
#define THEATER_BIG_SHAPE_BUFFER_SIZE 4000000
|
||||
#define UNCOMPRESS_MAGIC_NUMBER 56789
|
||||
|
||||
unsigned BigShapeBufferLength = INITIAL_BIG_SHAPE_BUFFER_SIZE;
|
||||
unsigned TheaterShapeBufferLength = THEATER_BIG_SHAPE_BUFFER_SIZE;
|
||||
extern "C"{
|
||||
char *BigShapeBufferStart = NULL;
|
||||
char *TheaterShapeBufferStart = NULL;
|
||||
BOOL UseBigShapeBuffer = FALSE;
|
||||
bool IsTheaterShape = false;
|
||||
}
|
||||
#ifdef FIXIT_SCORE_CRASH
|
||||
/*
|
||||
** Global required to fix the score screen crash bug by allowing disabling of uncompressed shapes.
|
||||
*/
|
||||
bool OriginalUseBigShapeBuffer = false;
|
||||
#endif //FIXIT
|
||||
char *BigShapeBufferPtr = NULL;
|
||||
int TotalBigShapes=0;
|
||||
BOOL ReallocShapeBufferFlag = FALSE;
|
||||
|
||||
char *TheaterShapeBufferPtr = NULL;
|
||||
int TotalTheaterShapes = 0;
|
||||
|
||||
|
||||
#define MAX_SLOTS 1500
|
||||
#define THEATER_SLOT_START 1000
|
||||
|
||||
char **KeyFrameSlots [MAX_SLOTS];
|
||||
int TotalSlotsUsed=0;
|
||||
int TheaterSlotsUsed = THEATER_SLOT_START;
|
||||
|
||||
|
||||
|
||||
typedef struct tShapeHeaderType{
|
||||
unsigned draw_flags;
|
||||
char *shape_data;
|
||||
int shape_buffer; //1 if shape is in theater buffer
|
||||
} ShapeHeaderType;
|
||||
|
||||
static int Length;
|
||||
|
||||
void *Get_Shape_Header_Data(void *ptr)
|
||||
{
|
||||
if (UseBigShapeBuffer) {
|
||||
|
||||
ShapeHeaderType *header = (ShapeHeaderType*) ptr;
|
||||
return ((void*) (header->shape_data + (long)(header->shape_buffer ? TheaterShapeBufferStart : BigShapeBufferStart) ) );
|
||||
|
||||
} else {
|
||||
return (ptr);
|
||||
}
|
||||
}
|
||||
|
||||
int Get_Last_Frame_Length(void)
|
||||
{
|
||||
return(Length);
|
||||
}
|
||||
|
||||
|
||||
void Reset_Theater_Shapes (void)
|
||||
{
|
||||
/*
|
||||
** Delete any previously allocated slots
|
||||
*/
|
||||
for (int i=THEATER_SLOT_START ; i<TheaterSlotsUsed ; i++) {
|
||||
delete [] KeyFrameSlots [i];
|
||||
}
|
||||
|
||||
TheaterShapeBufferPtr = TheaterShapeBufferStart;
|
||||
TotalTheaterShapes = 0;
|
||||
TheaterSlotsUsed = THEATER_SLOT_START;
|
||||
}
|
||||
|
||||
|
||||
void Reallocate_Big_Shape_Buffer(void)
|
||||
{
|
||||
if (ReallocShapeBufferFlag) {
|
||||
BigShapeBufferLength += 2000000; //Extra 2 Mb of uncompressed shape space
|
||||
BigShapeBufferPtr -= (unsigned)BigShapeBufferStart;
|
||||
Memory_Error = NULL;
|
||||
BigShapeBufferStart = (char*)Resize_Alloc(BigShapeBufferStart, BigShapeBufferLength);
|
||||
Memory_Error = &Memory_Error_Handler;
|
||||
/*
|
||||
** If we have run out of memory then disable the uncompressed shapes
|
||||
** It may still be possible to continue with compressed shapes
|
||||
*/
|
||||
if (!BigShapeBufferStart) {
|
||||
UseBigShapeBuffer = false;
|
||||
return;
|
||||
}
|
||||
BigShapeBufferPtr += (unsigned)BigShapeBufferStart;
|
||||
ReallocShapeBufferFlag = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef FIXIT_SCORE_CRASH
|
||||
/***********************************************************************************************
|
||||
* Disable_Uncompressed_Shapes -- Temporarily turns off shape decompression *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/19/96 2:37PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void Disable_Uncompressed_Shapes (void)
|
||||
{
|
||||
UseBigShapeBuffer = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Enable_Uncompressed_Shapes -- Restores state of shape decompression before it was disabled *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/19/96 2:37PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void Enable_Uncompressed_Shapes (void)
|
||||
{
|
||||
UseBigShapeBuffer = OriginalUseBigShapeBuffer;
|
||||
}
|
||||
#endif //FIXIT
|
||||
|
||||
void Check_Use_Compressed_Shapes (void)
|
||||
{
|
||||
MEMORYSTATUS mem_info;
|
||||
|
||||
mem_info.dwLength=sizeof(mem_info);
|
||||
GlobalMemoryStatus(&mem_info);
|
||||
|
||||
UseBigShapeBuffer = (mem_info.dwTotalPhys > 16*1024*1024) ? TRUE : FALSE;
|
||||
#ifdef FIXIT_SCORE_CRASH
|
||||
/*
|
||||
** Keep track of our original decision about whether to use cached shapes.
|
||||
** This is needed for the score screen crash fix.
|
||||
*/
|
||||
OriginalUseBigShapeBuffer = UseBigShapeBuffer;
|
||||
#endif //FIXIT
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned long Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr)
|
||||
{
|
||||
#ifdef FIXIT_SCORE_CRASH
|
||||
char *ptr;
|
||||
unsigned long offcurr, offdiff;
|
||||
#else
|
||||
char *ptr, *lockptr;//, *uncomp_ptr;
|
||||
unsigned long offcurr, off16, offdiff;
|
||||
#endif
|
||||
unsigned long offset[SUBFRAMEOFFS];
|
||||
KeyFrameHeaderType *keyfr;
|
||||
unsigned short buffsize, currframe, subframe;
|
||||
unsigned long length = 0;
|
||||
char frameflags;
|
||||
unsigned long return_value;
|
||||
char *temp_shape_ptr;
|
||||
|
||||
//
|
||||
// valid pointer??
|
||||
//
|
||||
Length = 0;
|
||||
if ( !dataptr || !buffptr ) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
//
|
||||
// look at header then check that frame to build is not greater
|
||||
// than total frames
|
||||
//
|
||||
keyfr = (KeyFrameHeaderType *) dataptr;
|
||||
|
||||
if ( framenumber >= keyfr->frames ) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
if (UseBigShapeBuffer) {
|
||||
/*
|
||||
** If we havnt yet allocated memory for uncompressed shapes then do so now.
|
||||
**
|
||||
*/
|
||||
if (!BigShapeBufferStart) {
|
||||
BigShapeBufferStart = (char*)Alloc(BigShapeBufferLength, MEM_NORMAL);
|
||||
BigShapeBufferPtr = BigShapeBufferStart;
|
||||
|
||||
/*
|
||||
** Allocate memory for theater specific uncompressed shapes
|
||||
*/
|
||||
TheaterShapeBufferStart = (char*) Alloc (TheaterShapeBufferLength, MEM_NORMAL);
|
||||
TheaterShapeBufferPtr = TheaterShapeBufferStart;
|
||||
}
|
||||
|
||||
/*
|
||||
** If we are running out of memory (<10k left) for uncompressed shapes
|
||||
** then allocate some more.
|
||||
*/
|
||||
if (( (unsigned)BigShapeBufferStart + BigShapeBufferLength) - (unsigned)BigShapeBufferPtr < 128000) {
|
||||
ReallocShapeBufferFlag = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
** If this animation was not previously uncompressed then
|
||||
** allocate memory to keep the pointers to the uncompressed data
|
||||
** for these animation frames
|
||||
*/
|
||||
if (keyfr->x != UNCOMPRESS_MAGIC_NUMBER) {
|
||||
keyfr->x = UNCOMPRESS_MAGIC_NUMBER;
|
||||
if (IsTheaterShape) {
|
||||
keyfr->y = TheaterSlotsUsed;
|
||||
TheaterSlotsUsed++;
|
||||
} else {
|
||||
keyfr->y = TotalSlotsUsed;
|
||||
TotalSlotsUsed++;
|
||||
}
|
||||
/*
|
||||
** Allocate and clear the memory for the shape info
|
||||
*/
|
||||
KeyFrameSlots[keyfr->y]= new char *[keyfr->frames];
|
||||
memset (KeyFrameSlots[keyfr->y] , 0 , keyfr->frames*4);
|
||||
}
|
||||
|
||||
/*
|
||||
** If this frame was previously uncompressed then just return
|
||||
** a pointer to the raw data
|
||||
*/
|
||||
if (*(KeyFrameSlots[keyfr->y]+framenumber)) {
|
||||
if (IsTheaterShape) {
|
||||
return ((unsigned long)TheaterShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));
|
||||
} else {
|
||||
return ((unsigned long)BigShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calc buff size
|
||||
buffsize = keyfr->width * keyfr->height;
|
||||
|
||||
// get offset into data
|
||||
ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)framenumber << 3) + sizeof(KeyFrameHeaderType)) );
|
||||
Mem_Copy( ptr, &offset[0], 12L );
|
||||
frameflags = (char)(offset[0] >> 24);
|
||||
|
||||
|
||||
if ( (frameflags & KF_KEYFRAME) ) {
|
||||
|
||||
ptr = (char *)Add_Long_To_Pointer( dataptr, (offset[0] & 0x00FFFFFFL) );
|
||||
|
||||
if (keyfr->flags & 1 ) {
|
||||
ptr = (char *)Add_Long_To_Pointer( ptr, 768L );
|
||||
}
|
||||
length = LCW_Uncompress( ptr, buffptr, buffsize );
|
||||
} else { // key delta or delta
|
||||
|
||||
if ( (frameflags & KF_DELTA) ) {
|
||||
currframe = (unsigned short)offset[1];
|
||||
|
||||
ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)currframe << 3) + sizeof(KeyFrameHeaderType)) );
|
||||
Mem_Copy( ptr, &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );
|
||||
}
|
||||
|
||||
// key frame
|
||||
offcurr = offset[1] & 0x00FFFFFFL;
|
||||
|
||||
// key delta
|
||||
offdiff = (offset[0] & 0x00FFFFFFL) - offcurr;
|
||||
|
||||
ptr = (char *)Add_Long_To_Pointer( dataptr, offcurr );
|
||||
|
||||
if (keyfr->flags & 1 ) {
|
||||
ptr = (char *)Add_Long_To_Pointer( ptr, 768L );
|
||||
}
|
||||
|
||||
#ifndef FIXIT_SCORE_CRASH
|
||||
off16 = (unsigned long)lockptr & 0x00003FFFL;
|
||||
#endif
|
||||
|
||||
length = LCW_Uncompress( ptr, buffptr, buffsize );
|
||||
|
||||
if (length > buffsize) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifndef FIXIT_SCORE_CRASH
|
||||
if ( ((offset[2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {
|
||||
|
||||
ptr = (char *)Add_Long_To_Pointer( ptr, offdiff );
|
||||
off16 = (unsigned long)ptr & 0x00003FFFL;
|
||||
|
||||
offcurr += offdiff;
|
||||
offdiff = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
length = buffsize;
|
||||
Apply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));
|
||||
|
||||
if ( (frameflags & KF_DELTA) ) {
|
||||
// adjust to delta after the keydelta
|
||||
|
||||
currframe++;
|
||||
subframe = 2;
|
||||
|
||||
while (currframe <= framenumber) {
|
||||
offdiff = (offset[subframe] & 0x00FFFFFFL) - offcurr;
|
||||
|
||||
#ifndef FIXIT_SCORE_CRASH
|
||||
if ( ((offset[subframe+2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {
|
||||
|
||||
ptr = (char *)Add_Long_To_Pointer( ptr, offdiff );
|
||||
off16 = (unsigned long)lockptr & 0x00003FFFL;
|
||||
|
||||
offcurr += offdiff;
|
||||
offdiff = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
length = buffsize;
|
||||
Apply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));
|
||||
|
||||
currframe++;
|
||||
subframe += 2;
|
||||
|
||||
if ( subframe >= (SUBFRAMEOFFS - 1) &&
|
||||
currframe <= framenumber ) {
|
||||
Mem_Copy( Add_Long_To_Pointer( dataptr,
|
||||
(((unsigned long)currframe << 3) +
|
||||
sizeof(KeyFrameHeaderType)) ),
|
||||
&offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );
|
||||
subframe = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (UseBigShapeBuffer) {
|
||||
/*
|
||||
** Save the uncompressed shape data so we dont have to uncompress it
|
||||
** again next time its drawn.
|
||||
** We keep a space free before the raw shape data so we can add line
|
||||
** header info before the shape is drawn for the first time
|
||||
*/
|
||||
|
||||
if (IsTheaterShape) {
|
||||
/*
|
||||
** Shape is a theater specific shape
|
||||
*/
|
||||
return_value = (unsigned long) TheaterShapeBufferPtr;
|
||||
temp_shape_ptr = TheaterShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);
|
||||
/*
|
||||
** align the actual shape data
|
||||
*/
|
||||
if (3 & (unsigned)temp_shape_ptr) {
|
||||
temp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);
|
||||
}
|
||||
|
||||
memcpy (temp_shape_ptr , buffptr , length);
|
||||
((ShapeHeaderType *)TheaterShapeBufferPtr)->draw_flags = -1; //Flag that headers need to be generated
|
||||
((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)TheaterShapeBufferStart; //pointer to old raw shape data
|
||||
((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_buffer = 1; //Theater buffer
|
||||
*(KeyFrameSlots[keyfr->y]+framenumber) = TheaterShapeBufferPtr - (unsigned)TheaterShapeBufferStart;
|
||||
TheaterShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);
|
||||
/*
|
||||
** Align the next shape
|
||||
*/
|
||||
if (3 & (unsigned)TheaterShapeBufferPtr) {
|
||||
TheaterShapeBufferPtr = (char *)((unsigned)(TheaterShapeBufferPtr + 3) & 0xfffffffc);
|
||||
}
|
||||
Length = length;
|
||||
return (return_value);
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
return_value=(unsigned long)BigShapeBufferPtr;
|
||||
temp_shape_ptr = BigShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);
|
||||
/*
|
||||
** align the actual shape data
|
||||
*/
|
||||
if (3 & (unsigned)temp_shape_ptr) {
|
||||
temp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);
|
||||
}
|
||||
memcpy (temp_shape_ptr , buffptr , length);
|
||||
((ShapeHeaderType *)BigShapeBufferPtr)->draw_flags = -1; //Flag that headers need to be generated
|
||||
((ShapeHeaderType *)BigShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)BigShapeBufferStart; //pointer to old raw shape data
|
||||
((ShapeHeaderType *)BigShapeBufferPtr)->shape_buffer = 0; //Normal Big Shape Buffer
|
||||
*(KeyFrameSlots[keyfr->y]+framenumber) = BigShapeBufferPtr - (unsigned)BigShapeBufferStart;
|
||||
BigShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);
|
||||
// Align the next shape
|
||||
if (3 & (unsigned)BigShapeBufferPtr) {
|
||||
BigShapeBufferPtr = (char *)((unsigned)(BigShapeBufferPtr + 3) & 0xfffffffc);
|
||||
}
|
||||
Length = length;
|
||||
return (return_value);
|
||||
}
|
||||
|
||||
} else {
|
||||
return ((unsigned long)buffptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Get_Build_Frame_Count -- Fetches the number of frames in data block. *
|
||||
* *
|
||||
* Use this routine to determine the number of shapes within the data block. *
|
||||
* *
|
||||
* INPUT: dataptr -- Pointer to the keyframe shape data block. *
|
||||
* *
|
||||
* OUTPUT: Returns with the number of shapes in the data block. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/25/1995 JLB : Commented. *
|
||||
*=============================================================================================*/
|
||||
unsigned short Get_Build_Frame_Count(void const *dataptr)
|
||||
{
|
||||
if (dataptr) {
|
||||
return(((KeyFrameHeaderType const *)dataptr)->frames);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
unsigned short Get_Build_Frame_X(void const *dataptr)
|
||||
{
|
||||
if (dataptr) {
|
||||
return(((KeyFrameHeaderType const *)dataptr)->x);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
unsigned short Get_Build_Frame_Y(void const *dataptr)
|
||||
{
|
||||
if (dataptr) {
|
||||
return(((KeyFrameHeaderType const *)dataptr)->y);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Get_Build_Frame_Width -- Fetches the width of the shape image. *
|
||||
* *
|
||||
* Use this routine to fetch the width of the shapes within the keyframe shape data block. *
|
||||
* All shapes within the block have the same width. *
|
||||
* *
|
||||
* INPUT: dataptr -- Pointer to the keyframe shape data block. *
|
||||
* *
|
||||
* OUTPUT: Returns with the width of the shapes in the block -- expressed in pixels. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/25/1995 JLB : Commented *
|
||||
*=============================================================================================*/
|
||||
unsigned short Get_Build_Frame_Width(void const *dataptr)
|
||||
{
|
||||
if (dataptr) {
|
||||
return(((KeyFrameHeaderType const *)dataptr)->width);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Get_Build_Frame_Height -- Fetches the height of the shape image. *
|
||||
* *
|
||||
* Use this routine to fetch the height of the shapes within the keyframe shape data block. *
|
||||
* All shapes within the block have the same height. *
|
||||
* *
|
||||
* INPUT: dataptr -- Pointer to the keyframe shape data block. *
|
||||
* *
|
||||
* OUTPUT: Returns with the height of the shapes in the block -- expressed in pixels. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/25/1995 JLB : Commented *
|
||||
*=============================================================================================*/
|
||||
unsigned short Get_Build_Frame_Height(void const *dataptr)
|
||||
{
|
||||
if (dataptr) {
|
||||
return(((KeyFrameHeaderType const *)dataptr)->height);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
bool Get_Build_Frame_Palette(void const * dataptr, void * palette)
|
||||
{
|
||||
if (dataptr && (((KeyFrameHeaderType const *)dataptr)->flags & 1)) {
|
||||
char const * ptr = (char const *)Add_Long_To_Pointer( dataptr,
|
||||
( (( (long)sizeof(unsigned long) << 1) *
|
||||
((KeyFrameHeaderType *) dataptr)->frames ) +
|
||||
16 + sizeof(KeyFrameHeaderType) ) );
|
||||
|
||||
memcpy(palette, ptr, 768L);
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
564
CODE/2SUPPORT.ASM
Normal file
564
CODE/2SUPPORT.ASM
Normal file
@ -0,0 +1,564 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(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: F:\projects\c&c0\vcs\code\2support.asv 5.0 11 Nov 1996 09:40:36 JOE_BOSTIC $
|
||||
;***************************************************************************
|
||||
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||||
;***************************************************************************
|
||||
;* *
|
||||
;* Project Name : Command & Conquer *
|
||||
;* *
|
||||
;* File Name : SUPPORT.ASM *
|
||||
;* *
|
||||
;* Programmer : Joe L. Bostic *
|
||||
;* *
|
||||
;* Start Date : September 23, 1993 *
|
||||
;* *
|
||||
;* Last Update : May 10, 1994 [JLB] *
|
||||
;* *
|
||||
;*-------------------------------------------------------------------------*
|
||||
;* Functions: *
|
||||
;* strtrim -- Remove the trailing white space from a string. *
|
||||
;* Fat_Put_Pixel -- Draws a fat pixel. *
|
||||
;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.*
|
||||
;* Remove_From_List -- Removes a pointer from a list of pointers. *
|
||||
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
|
||||
INCLUDE "gbuffer.inc"
|
||||
DISPLAY "Command & Conquer assembly support routines."
|
||||
|
||||
CODESEG
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
;* Fat_Put_Pixel -- Draws a fat pixel. *
|
||||
;* *
|
||||
;* Use this routine to draw a "pixel" that is bigger than 1 pixel *
|
||||
;* across. This routine is faster than drawing a similar small shape *
|
||||
;* and faster than calling Fill_Rect. *
|
||||
;* *
|
||||
;* INPUT: x,y -- Screen coordinates to draw the pixel's upper *
|
||||
;* left corner. *
|
||||
;* *
|
||||
;* color -- The color to render the pixel in. *
|
||||
;* *
|
||||
;* size -- The number of pixels width of the big "pixel". *
|
||||
;* *
|
||||
;* page -- The pointer to a GraphicBuffer class or something *
|
||||
;* *
|
||||
;* OUTPUT: none *
|
||||
;* *
|
||||
;* WARNINGS: none *
|
||||
;* *
|
||||
;* HISTORY: *
|
||||
;* 03/17/1994 JLB : Created. *
|
||||
;*=========================================================================*
|
||||
; VOID cdecl Fat_Put_Pixel(long x, long y, long color, long size, void *page)
|
||||
GLOBAL C Fat_Put_Pixel:NEAR
|
||||
PROC Fat_Put_Pixel C near
|
||||
USES eax, ebx, ecx, edx, edi, esi
|
||||
|
||||
ARG x:DWORD ; X coordinate of upper left pixel corner.
|
||||
ARG y:DWORD ; Y coordinate of upper left pixel corner.
|
||||
ARG color:DWORD ; Color to use for the "pixel".
|
||||
ARG siz:DWORD ; Size of "pixel" to plot (square).
|
||||
ARG gpage:DWORD ; graphic page address to plot onto
|
||||
|
||||
cmp [siz],0
|
||||
je short ??exit
|
||||
|
||||
; Set EDI to point to start of logical page memory.
|
||||
;*===================================================================
|
||||
; Get the viewport information and put bytes per row in ecx
|
||||
;*===================================================================
|
||||
mov ebx,[gpage] ; get a pointer to viewport
|
||||
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get the correct offset
|
||||
|
||||
; Verify the the Y pixel offset is legal.
|
||||
mov eax,[y]
|
||||
cmp eax,[(GraphicViewPort ebx).GVPHeight] ;YPIXEL_MAX
|
||||
jae short ??exit
|
||||
mov ecx,[(GraphicViewPort ebx).GVPWidth]
|
||||
add ecx,[(GraphicViewPort ebx).GVPXAdd]
|
||||
add ecx,[(GraphicViewPort ebx).GVPPitch]
|
||||
mul ecx
|
||||
add edi,eax
|
||||
|
||||
; Verify the the X pixel offset is legal.
|
||||
|
||||
mov edx,[(GraphicViewPort ebx).GVPWidth]
|
||||
cmp edx,[x]
|
||||
mov edx,ecx
|
||||
jbe short ??exit
|
||||
add edi,[x]
|
||||
|
||||
; Write the pixel to the screen.
|
||||
mov ebx,[siz] ; Copy of pixel size.
|
||||
sub edx,ebx ; Modulo to reach start of next row.
|
||||
mov eax,[color]
|
||||
??again:
|
||||
mov ecx,ebx
|
||||
rep stosb
|
||||
add edi,edx ; EDI points to start of next row.
|
||||
dec [siz]
|
||||
jnz short ??again
|
||||
|
||||
??exit:
|
||||
ret
|
||||
|
||||
ENDP Fat_Put_Pixel
|
||||
|
||||
|
||||
if 0
|
||||
|
||||
;***************************************************************************
|
||||
;* strtrim -- Remove the trailing white space from a string. *
|
||||
;* *
|
||||
;* Use this routine to remove white space characters from the beginning *
|
||||
;* and end of the string. The string is modified in place by *
|
||||
;* this routine. *
|
||||
;* *
|
||||
;* INPUT: buffer -- Pointer to the string to modify. *
|
||||
;* *
|
||||
;* OUTPUT: none *
|
||||
;* *
|
||||
;* WARNINGS: none *
|
||||
;* *
|
||||
;* HISTORY: *
|
||||
;* 10/07/1992 JLB : Created. *
|
||||
;*=========================================================================*
|
||||
; VOID cdecl strtrim(BYTE *buffer);
|
||||
GLOBAL C strtrim :NEAR
|
||||
PROC strtrim C near
|
||||
USES ax, edi, esi
|
||||
|
||||
ARG buffer:DWORD ; Pointer to string to modify.
|
||||
|
||||
cmp [buffer],0
|
||||
je short ??fini
|
||||
|
||||
; Prepare for string scanning by loading pointers.
|
||||
cld
|
||||
mov esi,[buffer]
|
||||
mov edi,esi
|
||||
|
||||
; Strip white space from the start of the string.
|
||||
??looper:
|
||||
lodsb
|
||||
cmp al,20h ; Space
|
||||
je short ??looper
|
||||
cmp al,9 ; TAB
|
||||
je short ??looper
|
||||
stosb
|
||||
|
||||
; Copy the rest of the string.
|
||||
??gruntloop:
|
||||
lodsb
|
||||
stosb
|
||||
or al,al
|
||||
jnz short ??gruntloop
|
||||
dec edi
|
||||
; Strip the white space from the end of the string.
|
||||
??looper2:
|
||||
mov [edi],al
|
||||
dec edi
|
||||
mov ah,[edi]
|
||||
cmp ah,20h
|
||||
je short ??looper2
|
||||
cmp ah,9
|
||||
je short ??looper2
|
||||
|
||||
??fini:
|
||||
ret
|
||||
|
||||
ENDP strtrim
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table. *
|
||||
;* *
|
||||
;* This routine is used to build a special fading table for C&C. There *
|
||||
;* are certain colors that get faded to and cannot be faded again. *
|
||||
;* With this rule, it is possible to draw a shadow multiple times and *
|
||||
;* not have it get any lighter or darker. *
|
||||
;* *
|
||||
;* INPUT: palette -- Pointer to the 768 byte IBM palette to build from. *
|
||||
;* *
|
||||
;* dest -- Pointer to the 256 byte remap table. *
|
||||
;* *
|
||||
;* color -- Color index of the color to "fade to". *
|
||||
;* *
|
||||
;* frac -- The fraction to fade to the specified color *
|
||||
;* *
|
||||
;* OUTPUT: Returns with pointer to the remap table. *
|
||||
;* *
|
||||
;* WARNINGS: none *
|
||||
;* *
|
||||
;* HISTORY: *
|
||||
;* 10/07/1992 JLB : Created. *
|
||||
;*=========================================================================*/
|
||||
;VOID * cdecl Conquer_Build_Fading_Table(VOID *palette, VOID *dest, long color, long frac);
|
||||
GLOBAL C Conquer_Build_Fading_Table : NEAR
|
||||
PROC Conquer_Build_Fading_Table C near
|
||||
USES ebx, ecx, edi, esi
|
||||
|
||||
ARG palette:DWORD
|
||||
ARG dest:DWORD
|
||||
ARG color:DWORD
|
||||
ARG frac:DWORD
|
||||
|
||||
LOCAL matchvalue:DWORD ; Last recorded match value.
|
||||
LOCAL targetred:BYTE ; Target gun red.
|
||||
LOCAL targetgreen:BYTE ; Target gun green.
|
||||
LOCAL targetblue:BYTE ; Target gun blue.
|
||||
LOCAL idealred:BYTE
|
||||
LOCAL idealgreen:BYTE
|
||||
LOCAL idealblue:BYTE
|
||||
LOCAL matchcolor:BYTE ; Tentative match color.
|
||||
|
||||
ALLOWED_COUNT EQU 16
|
||||
ALLOWED_START EQU 256-ALLOWED_COUNT
|
||||
|
||||
cld
|
||||
|
||||
; If the source palette is NULL, then just return with current fading table pointer.
|
||||
cmp [palette],0
|
||||
je ??fini1
|
||||
cmp [dest],0
|
||||
je ??fini1
|
||||
|
||||
; Fractions above 255 become 255.
|
||||
mov eax,[frac]
|
||||
cmp eax,0100h
|
||||
jb short ??ok
|
||||
mov [frac],0FFh
|
||||
??ok:
|
||||
|
||||
; Record the target gun values.
|
||||
mov esi,[palette]
|
||||
mov ebx,[color]
|
||||
add esi,ebx
|
||||
add esi,ebx
|
||||
add esi,ebx
|
||||
lodsb
|
||||
mov [targetred],al
|
||||
lodsb
|
||||
mov [targetgreen],al
|
||||
lodsb
|
||||
mov [targetblue],al
|
||||
|
||||
; Main loop.
|
||||
xor ebx,ebx ; Remap table index.
|
||||
|
||||
; Transparent black never gets remapped.
|
||||
mov edi,[dest]
|
||||
mov [edi],bl
|
||||
inc edi
|
||||
|
||||
; EBX = source palette logical number (1..255).
|
||||
; EDI = running pointer into dest remap table.
|
||||
??mainloop:
|
||||
inc ebx
|
||||
mov esi,[palette]
|
||||
add esi,ebx
|
||||
add esi,ebx
|
||||
add esi,ebx
|
||||
|
||||
mov edx,[frac]
|
||||
shr edx,1
|
||||
; new = orig - ((orig-target) * fraction);
|
||||
|
||||
lodsb ; orig
|
||||
mov dh,al ; preserve it for later.
|
||||
sub al,[targetred] ; al = (orig-target)
|
||||
imul dl ; ax = (orig-target)*fraction
|
||||
shl eax,1
|
||||
sub dh,ah ; dh = orig - ((orig-target) * fraction)
|
||||
mov [idealred],dh ; preserve ideal color gun value.
|
||||
|
||||
lodsb ; orig
|
||||
mov dh,al ; preserve it for later.
|
||||
sub al,[targetgreen] ; al = (orig-target)
|
||||
imul dl ; ax = (orig-target)*fraction
|
||||
shl eax,1
|
||||
sub dh,ah ; dh = orig - ((orig-target) * fraction)
|
||||
mov [idealgreen],dh ; preserve ideal color gun value.
|
||||
|
||||
lodsb ; orig
|
||||
mov dh,al ; preserve it for later.
|
||||
sub al,[targetblue] ; al = (orig-target)
|
||||
imul dl ; ax = (orig-target)*fraction
|
||||
shl eax,1
|
||||
sub dh,ah ; dh = orig - ((orig-target) * fraction)
|
||||
mov [idealblue],dh ; preserve ideal color gun value.
|
||||
|
||||
; Sweep through a limited set of existing colors to find the closest
|
||||
; matching color.
|
||||
|
||||
mov eax,[color]
|
||||
mov [matchcolor],al ; Default color (self).
|
||||
mov [matchvalue],-1 ; Ridiculous match value init.
|
||||
mov ecx,ALLOWED_COUNT
|
||||
|
||||
mov esi,[palette] ; Pointer to original palette.
|
||||
add esi,(ALLOWED_START)*3
|
||||
|
||||
; BH = color index.
|
||||
mov bh,ALLOWED_START
|
||||
??innerloop:
|
||||
|
||||
xor edx,edx ; Comparison value starts null.
|
||||
|
||||
; Build the comparison value based on the sum of the differences of the color
|
||||
; guns squared.
|
||||
lodsb
|
||||
sub al,[idealred]
|
||||
mov ah,al
|
||||
imul ah
|
||||
add edx,eax
|
||||
|
||||
lodsb
|
||||
sub al,[idealgreen]
|
||||
mov ah,al
|
||||
imul ah
|
||||
add edx,eax
|
||||
|
||||
lodsb
|
||||
sub al,[idealblue]
|
||||
mov ah,al
|
||||
imul ah
|
||||
add edx,eax
|
||||
jz short ??perfect ; If perfect match found then quit early.
|
||||
|
||||
cmp edx,[matchvalue]
|
||||
jae short ??notclose
|
||||
mov [matchvalue],edx ; Record new possible color.
|
||||
mov [matchcolor],bh
|
||||
??notclose:
|
||||
inc bh ; Checking color index.
|
||||
loop ??innerloop
|
||||
mov bh,[matchcolor]
|
||||
??perfect:
|
||||
mov [matchcolor],bh
|
||||
xor bh,bh ; Make BX valid main index again.
|
||||
|
||||
; When the loop exits, we have found the closest match.
|
||||
mov al,[matchcolor]
|
||||
stosb
|
||||
cmp ebx,ALLOWED_START-1
|
||||
jne ??mainloop
|
||||
|
||||
; Fill the remainder of the remap table with values
|
||||
; that will remap the color to itself.
|
||||
mov ecx,ALLOWED_COUNT
|
||||
??fillerloop:
|
||||
inc bl
|
||||
mov al,bl
|
||||
stosb
|
||||
loop ??fillerloop
|
||||
|
||||
??fini1:
|
||||
mov esi,[dest]
|
||||
mov eax,esi
|
||||
ret
|
||||
|
||||
ENDP Conquer_Build_Fading_Table
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
;* Remove_From_List -- Removes a pointer from a list of pointers. *
|
||||
;* *
|
||||
;* This low level routine is used to remove a pointer from a list of *
|
||||
;* pointers. The trailing pointers are moved downward to fill the *
|
||||
;* hole. *
|
||||
;* *
|
||||
;* INPUT: list -- Pointer to list of pointer. *
|
||||
;* *
|
||||
;* index -- Pointer to length of pointer list. *
|
||||
;* *
|
||||
;* ptr -- The pointer value to search for and remove. *
|
||||
;* *
|
||||
;* OUTPUT: none *
|
||||
;* *
|
||||
;* WARNINGS: none *
|
||||
;* *
|
||||
;* HISTORY: *
|
||||
;* 04/11/1994 JLB : Created. *
|
||||
;* 04/22/1994 JLB : Convert to assembly language. *
|
||||
;* 05/10/1994 JLB : Short pointers now. *
|
||||
;*=========================================================================*/
|
||||
;VOID cdecl Remove_From_List(VOID **list, long *index, long ptr);
|
||||
GLOBAL C Remove_From_List:NEAR
|
||||
PROC Remove_From_List C near
|
||||
USES edi, esi, ecx, eax
|
||||
ARG list:DWORD ; Pointer to list.
|
||||
ARG index:DWORD ; Pointer to count.
|
||||
ARG element:DWORD ; Element to remove.
|
||||
|
||||
; Fetch the number of elements in the list. If there are no
|
||||
; elements, then just exit quickly.
|
||||
mov edi,[index]
|
||||
mov ecx,[edi]
|
||||
jcxz short ??fini2
|
||||
|
||||
; Fetch pointer to list.
|
||||
cmp [list],0
|
||||
je short ??fini2
|
||||
mov edi,[list]
|
||||
|
||||
; Loop through all elements searching for a match.
|
||||
mov eax,[element]
|
||||
repne scasd
|
||||
jne short ??fini2 ; No match found.
|
||||
|
||||
; Copy all remaining elements down. If this is the
|
||||
; last element in the list then nothing needs to be
|
||||
; copied -- just decrement the list size.
|
||||
jcxz short ??nocopy ; No copy necessary.
|
||||
mov esi,edi
|
||||
sub edi,4
|
||||
rep movsd
|
||||
|
||||
; Reduce the list count by one.
|
||||
??nocopy:
|
||||
mov edi,[index]
|
||||
dec [DWORD PTR edi]
|
||||
|
||||
??fini2:
|
||||
ret
|
||||
|
||||
ENDP Remove_From_List
|
||||
|
||||
|
||||
; long cdecl Get_EAX();
|
||||
GLOBAL C Get_EAX :NEAR
|
||||
PROC Get_EAX C near
|
||||
ret
|
||||
|
||||
ENDP Get_EAX
|
||||
endif
|
||||
|
||||
|
||||
DATASEG
|
||||
|
||||
TabA DD 6949350
|
||||
DD 4913933
|
||||
DD 3474675
|
||||
DD 2456966
|
||||
DD 1737338
|
||||
DD 1228483
|
||||
DD 868669
|
||||
DD 614242
|
||||
DD 434334
|
||||
DD 307121
|
||||
DD 217167
|
||||
DD 153560
|
||||
DD 108584
|
||||
DD 76780
|
||||
DD 54292
|
||||
DD 38390
|
||||
DD 27146
|
||||
DD 19195
|
||||
DD 13573
|
||||
DD 9598
|
||||
DD 6786
|
||||
DD 4799
|
||||
DD 3393
|
||||
DD 2399
|
||||
DD 1697
|
||||
DD 1200
|
||||
DD 848
|
||||
DD 600
|
||||
DD 424
|
||||
DD 300
|
||||
DD 212
|
||||
DD 150
|
||||
DD 106
|
||||
|
||||
TabB DD 154
|
||||
DD 218
|
||||
DD 309
|
||||
DD 437
|
||||
DD 618
|
||||
DD 874
|
||||
DD 1236
|
||||
DD 1748
|
||||
DD 2472
|
||||
DD 3496
|
||||
DD 4944
|
||||
DD 6992
|
||||
DD 9888
|
||||
DD 13983
|
||||
DD 19775
|
||||
DD 27967
|
||||
DD 39551
|
||||
DD 55933
|
||||
DD 79101
|
||||
DD 111866
|
||||
DD 158203
|
||||
DD 223732
|
||||
DD 316405
|
||||
DD 447465
|
||||
DD 632811
|
||||
DD 894929
|
||||
DD 1265621
|
||||
DD 1789859
|
||||
DD 2531243
|
||||
DD 3579718
|
||||
DD 5062486
|
||||
DD 7159436
|
||||
DD 10124971
|
||||
|
||||
CODESEG
|
||||
|
||||
;***********************************************************************************************
|
||||
;* Square_Root -- Finds the square root of the fixed pointer parameter. *
|
||||
;* *
|
||||
;* INPUT: val -- The fixed point (16:16) value to find the square root of. *
|
||||
;* *
|
||||
;* OUTPUT: Returns with the square root of the fixed pointer parameter. *
|
||||
;* *
|
||||
;* WARNINGS: none *
|
||||
;* *
|
||||
;* HISTORY: *
|
||||
;* 10/04/1995 JLB : Adapted. *
|
||||
;*=============================================================================================*/
|
||||
;unsigned Square_Root(unsigned val);
|
||||
GLOBAL C Square_Root :NEAR
|
||||
PROC Square_Root C near
|
||||
USES ebx,edx
|
||||
|
||||
bsr ebx,eax
|
||||
jz ??zero
|
||||
|
||||
mul [DWORD 4*ebx + OFFSET TabA]
|
||||
shrd eax,edx,10h
|
||||
add eax, [4*ebx + OFFSET TabB]
|
||||
??zero:
|
||||
ret
|
||||
|
||||
ENDP Square_Root
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
END
|
||||
|
507
CODE/2TXTPRNT.ASM
Normal file
507
CODE/2TXTPRNT.ASM
Normal file
@ -0,0 +1,507 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(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 : Westwood 32 bit Library *
|
||||
;* *
|
||||
;* File Name : TXTPRNT.ASM *
|
||||
;* *
|
||||
;* Programmer : Phil W. Gorrow *
|
||||
;* *
|
||||
;* Start Date : January 17, 1995 *
|
||||
;* *
|
||||
;* Last Update : January 17, 1995 [PWG] *
|
||||
;* *
|
||||
;*-------------------------------------------------------------------------*
|
||||
;* Functions: *
|
||||
;* MCGA_Print -- Assembly MCGA text print routine *
|
||||
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
|
||||
;INCLUDE "mcgaprim.inc"
|
||||
;INCLUDE ".\gbuffer.inc"
|
||||
|
||||
GLOBAL C Buffer_Print : NEAR
|
||||
|
||||
STRUC GraphicViewPort
|
||||
GVPOffset DD ? ; offset to virtual viewport
|
||||
GVPWidth DD ? ; width of virtual viewport
|
||||
GVPHeight DD ? ; height of virtual viewport
|
||||
GVPXAdd DD ? ; x mod to get to next line
|
||||
GVPXPos DD ? ; x pos relative to Graphic Buff
|
||||
GVPYPos DD ? ; y pos relative to Graphic Buff
|
||||
GVPPitch dd ? ; modulo of graphic view port
|
||||
GVPBuffPtr DD ? ; ptr to associated Graphic Buff
|
||||
ENDS
|
||||
|
||||
|
||||
|
||||
;*=========================================================================*
|
||||
;* Extern the font pointer which is defined by the font class *
|
||||
;*=========================================================================*
|
||||
GLOBAL C FontPtr:DWORD
|
||||
GLOBAL C FontXSpacing:DWORD
|
||||
GLOBAL C FontYSpacing:DWORD
|
||||
GLOBAL C ColorXlat:BYTE
|
||||
|
||||
;*=========================================================================*
|
||||
;* Define the necessary equates for structures and bounds checking *
|
||||
;*=========================================================================*
|
||||
; The header of the font file looks like this:
|
||||
; UWORD FontLength; 0
|
||||
; BYTE FontCompress; 2
|
||||
; BYTE FontDataBlocks; 3
|
||||
; UWORD InfoBlockOffset; 4
|
||||
; UWORD OffsetBlockOffset; 6
|
||||
; UWORD WidthBlockOffset; 8
|
||||
; UWORD DataBlockOffset; 10
|
||||
; UWORD HeightOffset; 12
|
||||
; For this reason the following equates have these values:
|
||||
FONTINFOBLOCK EQU 4
|
||||
FONTOFFSETBLOCK EQU 6
|
||||
FONTWIDTHBLOCK EQU 8
|
||||
FONTDATABLOCK EQU 10
|
||||
FONTHEIGHTBLOCK EQU 12
|
||||
|
||||
FONTINFOMAXHEIGHT EQU 4
|
||||
FONTINFOMAXWIDTH EQU 5
|
||||
|
||||
|
||||
LOCALS ??
|
||||
;*=========================================================================*
|
||||
;* Define the color xlate table in the data segment *
|
||||
;*=========================================================================*
|
||||
DATASEG
|
||||
ColorXlat DB 000H,001H,002H,003H,004H,005H,006H,007H
|
||||
DB 008H,009H,00AH,00BH,00CH,00DH,00EH,00FH
|
||||
|
||||
DB 001H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 002H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 003H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 004H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 005H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 006H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 007H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 008H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 009H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00AH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00BH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00CH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00DH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00EH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00FH
|
||||
CODESEG
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
;* MCGA_PRINT -- Assembly MCGA text print routine *
|
||||
;* *
|
||||
;* *
|
||||
;* *
|
||||
;* INPUT: *
|
||||
;* *
|
||||
;* OUTPUT: *
|
||||
;* *
|
||||
;* PROTO: *
|
||||
;* *
|
||||
;* WARNINGS: *
|
||||
;* *
|
||||
;* HISTORY: *
|
||||
;* 01/17/1995 PWG : Created. *
|
||||
;*=========================================================================*
|
||||
PROC Buffer_Print C near
|
||||
USES ebx,ecx,edx,esi,edi
|
||||
|
||||
ARG this:DWORD
|
||||
ARG string:DWORD
|
||||
ARG x_pixel:DWORD
|
||||
ARG y_pixel:DWORD
|
||||
ARG fcolor:DWORD
|
||||
ARG bcolor:DWORD
|
||||
|
||||
LOCAL infoblock:DWORD ; pointer to info block
|
||||
LOCAL offsetblock:DWORD ; pointer to offset block (UWORD *)
|
||||
LOCAL widthblock:DWORD ; pointer to width block (BYTE *)
|
||||
LOCAL heightblock:DWORD ; pointer to height block (UWORD *)
|
||||
|
||||
LOCAL curline:DWORD ; pointer to first column of current row.
|
||||
LOCAL bufferwidth:DWORD ; width of buffer (vpwidth + Xadd)
|
||||
LOCAL nextdraw:DWORD ; bufferwidth - width of cur character.
|
||||
LOCAL startdraw:DWORD ; where next character will start being drawn.
|
||||
|
||||
LOCAL char:DWORD ; current character value.
|
||||
|
||||
LOCAL maxheight:BYTE ; max height of characters in font.
|
||||
LOCAL bottomblank:BYTE ; amount of empty space below current character.
|
||||
LOCAL charheight:BYTE ; true height of current character.
|
||||
LOCAL vpwidth:DWORD
|
||||
LOCAL vpheight:DWORD
|
||||
LOCAL original_x:DWORD ; Starting X position.
|
||||
|
||||
|
||||
;-------------------------------- Where to draw -----------------------------------------------
|
||||
; Set up memory location to start drawing.
|
||||
mov ebx,[this] ; get a pointer to dest
|
||||
mov eax,[(GraphicViewPort ebx).GVPHeight] ; get height of viewport
|
||||
mov [vpheight],eax ; save off height of viewport
|
||||
mov eax,[(GraphicViewPort ebx).GVPWidth] ; get width of viewport
|
||||
mov [vpwidth],eax ; save it off for later
|
||||
add eax,[(GraphicViewPort ebx).GVPXAdd] ; add in xadd for bytes_per_line
|
||||
add eax,[(GraphicViewPort ebx).GVPPitch] ; add in pitch of direct draw surface
|
||||
mov [bufferwidth],eax ; save it off for later use.
|
||||
|
||||
mul [y_pixel] ; multiply rowsize * y_pixel start.
|
||||
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get start of the viewport
|
||||
add edi,eax ; add y position to start of vp
|
||||
mov [curline],edi ; save 0,y address for line feed stuff.
|
||||
add edi,[x_pixel] ; add to get starting column in starting row.
|
||||
mov [startdraw],edi ; save it off.
|
||||
|
||||
mov eax,[x_pixel]
|
||||
mov [original_x],eax
|
||||
|
||||
;-------------------------------- Create block pointers ----------------------------------------
|
||||
; Get the pointer to the font.
|
||||
; We could check for NULL but why waste the time.
|
||||
; It is up to programmer to make sure it is set.
|
||||
mov esi,[FontPtr] ; Get the font pointer
|
||||
or esi,esi
|
||||
jz ??overflow
|
||||
|
||||
; Set up some pointers to the different memory blocks.
|
||||
; esi (FontPtr) is added to each to get the true address of each block.
|
||||
; Many registers are used for P5 optimizations.
|
||||
; ebx is used for InfoBlock which is then used in the next section.
|
||||
movzx eax,[WORD PTR esi+FONTOFFSETBLOCK] ; get offset to offset block
|
||||
movzx ebx,[WORD PTR esi+FONTINFOBLOCK] ; get offset to info block (must be ebx for height test)
|
||||
movzx ecx,[WORD PTR esi+FONTWIDTHBLOCK] ; get offset to width block
|
||||
movzx edx,[WORD PTR esi+FONTHEIGHTBLOCK] ; get offset to height block
|
||||
|
||||
add eax,esi ; add offset of FontPtr to offset block
|
||||
add ebx,esi ; add offset of FontPtr to info block
|
||||
add ecx,esi ; add offset of FontPtr to width block
|
||||
add edx,esi ; add offset of FontPtr to height block
|
||||
|
||||
mov [offsetblock],eax ; save offset to offset block
|
||||
mov [infoblock],ebx ; save offset to info block
|
||||
mov [widthblock],ecx ; save offset to width block
|
||||
mov [heightblock],edx ; save offset to height block
|
||||
|
||||
;------------------------------------------ Test for fit ----------------------------------------------
|
||||
; Test to make sure the height of the max character will fit on this line
|
||||
; and and not fall out of the viewport.
|
||||
; remember we set ebx to FONTINFOBLOCK above.
|
||||
movzx eax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.
|
||||
mov [maxheight],al ; save it for later use.
|
||||
add eax,[y_pixel] ; add current y_value.
|
||||
cmp eax,[vpheight] ; are we over the edge?
|
||||
jg ??overflow ; if so, we're outa here.
|
||||
|
||||
mov [y_pixel],eax ; save for next line feed. y value for next line.
|
||||
|
||||
cld ; Make sure we are always forward copying.
|
||||
|
||||
;------------------------ Set palette foreground and background ----------------------------------
|
||||
mov eax,[fcolor] ; foreground color
|
||||
mov [ColorXlat+1],al
|
||||
mov [ColorXlat+16],al
|
||||
|
||||
mov eax,[bcolor] ; background color
|
||||
mov [ColorXlat],al
|
||||
|
||||
;-------------------------------------------------------------------------------------------------
|
||||
;----------------------------------------- Main loop ----------------------------------------------
|
||||
; Now we go into the main loop of reading each character in the string and doing
|
||||
; something with it.
|
||||
??next_char:
|
||||
; while (*string++)
|
||||
xor eax,eax ; zero out since we will just load al.
|
||||
mov esi,[string] ; get address on next character.
|
||||
lodsb ; load the character into al.
|
||||
test eax,0FFH ; test to see if character is a NULL
|
||||
jz ??done ; character is NULL, get outa here.
|
||||
|
||||
mov edi,[startdraw] ; Load the starting address.
|
||||
|
||||
mov [string],esi ; save index into string. (incremented by lodsb)
|
||||
|
||||
cmp al,10 ; is the character a line feed?
|
||||
je ??line_feed ; if so, go to special case.
|
||||
|
||||
cmp al,13 ; is the character a line feed?
|
||||
je ??line_feed ; if so, go to special case.
|
||||
|
||||
mov [char],eax ; save the character off for later reference.
|
||||
mov ebx,eax ; save it in ebx for later use also.
|
||||
|
||||
add eax,[widthblock] ; figure address of width of character.
|
||||
mov ecx,[x_pixel] ; get current x_pixel.
|
||||
movzx edx,[BYTE PTR eax] ; get the width of the character in dl.
|
||||
add ecx,edx ; add width of char to current x_pixel.
|
||||
mov eax,[FontXSpacing]
|
||||
add ecx,eax
|
||||
add [startdraw],edx ; save start draw for next character.
|
||||
add [startdraw],eax ; adjust for the font spacing value
|
||||
|
||||
cmp ecx,[vpwidth] ; is the pixel greater then the vp width?
|
||||
jg ??force_line_feed ; if so, force a line feed.
|
||||
|
||||
mov [x_pixel],ecx ; save value of start of next character.
|
||||
mov ecx,[bufferwidth] ; get amount to next y same x (one row down)
|
||||
sub ecx,edx ; take the current width off.
|
||||
mov [nextdraw],ecx ; save it to add to edi when done with a row.
|
||||
|
||||
; At this point we got the character. It is now time to find out specifics
|
||||
; about drawing the darn thing.
|
||||
; ebx = char so they can be used as an indexes.
|
||||
; edx = width of character for loop later.
|
||||
|
||||
; get offset of data for character into esi.
|
||||
shl ebx,1 ; mult by 2 to later use as a WORD index.
|
||||
mov esi,[offsetblock] ; get pointer to begining of offset block.
|
||||
add esi,ebx ; index into offset block.
|
||||
movzx esi,[WORD PTR esi] ; get true offset into data block from FontPtr.
|
||||
add esi,[FontPtr] ; Now add FontPtr address to get true address.
|
||||
|
||||
; Get top and bottom blank sizes and the true height of the character.
|
||||
add ebx,[heightblock] ; point ebx to element in height array.
|
||||
mov al,[ebx+1] ; load the data height into dl.
|
||||
mov cl,[ebx] ; load the first data row into cl.
|
||||
mov bl,[maxheight] ; get the max height of characters.
|
||||
mov [charheight],al ; get number of rows with data.
|
||||
add al,cl ; add the two heights.
|
||||
sub bl,al ; subract topblank + char height from maxheight.
|
||||
mov [bottomblank],bl ; save off the number of blank rows on the bottom.
|
||||
; leaving this section:
|
||||
; dl is still the width of the character.
|
||||
; cl is the height of the top blank area.
|
||||
|
||||
mov ebx,OFFSET ColorXlat ; setup ebx for xlat commands.
|
||||
mov dh,dl ; save the width of the character to restore each loop.
|
||||
|
||||
cmp cl,0 ; is there any blank rows on top?
|
||||
jz ??draw_char ; if not go and draw the real character.
|
||||
|
||||
xor eax,eax ; get color 0 for background.
|
||||
xlat [ebx] ; get translated color into al
|
||||
test al,al ; is it transparent black
|
||||
jnz ??loop_top ; if not go and write the color
|
||||
|
||||
;----------------------------------------- skip Top blank area ----------------------------------------
|
||||
; this case, the top is transparrent, but we need to increase our dest pointer to correct row.
|
||||
movzx eax,cl ; get number of rows into eax;
|
||||
mov ecx,edx ; save width since edx will be destroyed by mul.
|
||||
mul [bufferwidth] ; multiply that by the width of the buffer.
|
||||
mov edx,ecx ; restore the width
|
||||
add edi,eax ; update the pointer.
|
||||
jmp short ??draw_char ; now go draw the character.
|
||||
|
||||
;----------------------------------------- fill Top blank area ----------------------------------------
|
||||
; edi was set a long time ago.
|
||||
; al is the translated color
|
||||
??loop_top:
|
||||
stosb ; store the value
|
||||
dec dh ; decrement our width.
|
||||
jnz ??loop_top ; if more width, continue on.
|
||||
|
||||
add edi,[nextdraw] ; add amount for entire row.
|
||||
|
||||
dec cl ; decrement or row count
|
||||
mov dh,dl ; restore width in dh for loop.
|
||||
jz ??draw_char ; we are done here, go draw the character.
|
||||
jmp short ??loop_top ; go back to top of loop.
|
||||
|
||||
|
||||
;----------------------------------------- Draw character ----------------------------------------------
|
||||
??draw_char:
|
||||
movzx ecx,[charheight] ; get the height of character to count down rows.
|
||||
test ecx,ecx ; is there any data? (blank would not have any)
|
||||
jz ??next_char ; if no data, go on to next character.
|
||||
|
||||
??while_data:
|
||||
lodsb ; get byte value from font data
|
||||
mov ah,al ; save hinibble
|
||||
and eax,0F00FH ; mask of low nibble in al hi nibble in ah.
|
||||
xlat [ebx] ; get new color
|
||||
|
||||
test al,al ; is it a transparent?
|
||||
jz short ??skiplo ; skip over write
|
||||
mov [es:edi],al ; write it out
|
||||
??skiplo:
|
||||
inc edi
|
||||
dec dh ; decrement our width.
|
||||
jz short ??nextrow ; check if done with width of char
|
||||
|
||||
mov al,ah ; restore to get
|
||||
; test the time difference between looking up in a large table when shr al,4 is not done as
|
||||
; compared to using only a 16 byte table when using the shr al,4
|
||||
;shr al,4 ; shift the hi nibble down to low nibble
|
||||
xlat [ebx] ; get new color
|
||||
|
||||
test al,al ; is it a transparent?
|
||||
jz short ??skiphi ; skip over write
|
||||
mov [es:edi],al ; write it out
|
||||
??skiphi:
|
||||
|
||||
inc edi
|
||||
dec dh ; decrement our width.
|
||||
jnz short ??while_data ; check if done with width of char
|
||||
|
||||
??nextrow:
|
||||
add edi,[nextdraw] ; go to next line.
|
||||
dec ecx ; decrement the number of rows to go
|
||||
mov dh,dl ; restore our column count for row.
|
||||
jnz ??while_data ; more data for character.
|
||||
|
||||
; Now it is time to setup for clearing out the bottom of the character.
|
||||
movzx ecx,[bottomblank] ; get amount on bottom that is blank
|
||||
cmp ecx,0 ; if there is no blank bottom...
|
||||
jz ??next_char ; then skip to go to next character
|
||||
|
||||
xor eax,eax ; get color 0 for background.
|
||||
xlat [ebx] ; get translated color into al
|
||||
test al,al ; is it transparent black
|
||||
jz ??next_char ; skip the top black section to let the background through
|
||||
|
||||
mov dh,dl ; restore width in dh for loop.
|
||||
|
||||
;----------------------------------------- Blank below character -----------------------------------
|
||||
??loop_bottom:
|
||||
stosb ; store the value
|
||||
dec dh ; decrement our width.
|
||||
jnz ??loop_bottom ; if more width, continue on.
|
||||
|
||||
add edi,[nextdraw] ; add amount for entire row.
|
||||
|
||||
mov dh,dl ; restore width in dh for loop.
|
||||
dec cl ; decrement or row count
|
||||
jz ??next_char ; we are done here, go to the next character.
|
||||
jmp short ??loop_bottom ; go back to top of loop.
|
||||
|
||||
;----------------------------------- end of next_char (main) loop ------------------------------------
|
||||
;-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
;----------------------------------- special case line feeds ----------------------------------------
|
||||
|
||||
??force_line_feed:
|
||||
; decrement pointer *string so that it will be back at same character
|
||||
; when it goes through the loop.
|
||||
mov eax,[string] ; get string pointer.
|
||||
dec eax ; decrement it to point to previos char
|
||||
mov [string],eax ; save it back off.
|
||||
xor eax,eax
|
||||
; Now go into the line feed code.....
|
||||
|
||||
??line_feed:
|
||||
mov bl,al
|
||||
mov edx,[y_pixel] ; get the current y pixel value.
|
||||
movzx ecx,[maxheight] ; get max height for later use.
|
||||
add ecx,[FontYSpacing]
|
||||
add edx,ecx ; add max height to y_pixel
|
||||
cmp edx,[vpheight] ; are we over the edge?
|
||||
jg ??overflow ; if so, we are outa here.
|
||||
|
||||
mov eax,[bufferwidth] ; get bytes to next line.
|
||||
mov edi,[curline] ; get start of current line.
|
||||
mul ecx ; mult max height * next line.
|
||||
|
||||
add edi,eax ; add adjustment to current line.
|
||||
add [y_pixel],ecx ; increment to our next y position.
|
||||
;;; DRD
|
||||
mov [curline],edi ; save it off for next line_feed.
|
||||
|
||||
; Move the cursor to either the left edge of the screen
|
||||
; or the left margin of the print position depending
|
||||
; on whether <CR> or <LF> was specified. <CR> = left margin
|
||||
; <LF> = left edge of screen
|
||||
xor eax,eax
|
||||
cmp bl,10
|
||||
je ??lfeed
|
||||
mov eax,[original_x]
|
||||
??lfeed:
|
||||
mov [x_pixel],eax ; zero out x_pixel
|
||||
|
||||
add edi,eax
|
||||
;;; DRD mov [curline],edi ; save it off for next line_feed.
|
||||
mov [startdraw],edi ; save it off so we know where to draw next char.w
|
||||
|
||||
jmp ??next_char
|
||||
|
||||
??overflow:
|
||||
mov [startdraw],0 ; Indicate that there is no valid next pos.
|
||||
??done:
|
||||
mov eax,[startdraw] ; return this so calling routine
|
||||
ret ; can figure out where to draw next.
|
||||
|
||||
ENDP Buffer_Print
|
||||
;***************************************************************************
|
||||
;* GET_FONT_PALETTE_PTR -- Returns a pointer to the 256 byte font palette *
|
||||
;* *
|
||||
;* INPUT: none *
|
||||
;* *
|
||||
;* OUTPUT: none *
|
||||
;* *
|
||||
;* PROTO: void *Get_Font_Palette_Ptr(void); *
|
||||
;* *
|
||||
;* HISTORY: *
|
||||
;* 08/18/1995 PWG : Created. *
|
||||
;*=========================================================================*
|
||||
|
||||
GLOBAL C Get_Font_Palette_Ptr:NEAR
|
||||
PROC Get_Font_Palette_Ptr C near
|
||||
mov eax, OFFSET ColorXlat
|
||||
ret
|
||||
ENDP Get_Font_Palette_Ptr
|
||||
|
||||
|
||||
END
|
655
CODE/AADATA.CPP
Normal file
655
CODE/AADATA.CPP
Normal file
@ -0,0 +1,655 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/AADATA.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : AADATA.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : July 22, 1994 *
|
||||
* *
|
||||
* Last Update : July 9, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* AircraftTypeClass::AircraftTypeClass -- Constructor for aircraft objects. *
|
||||
* AircraftTypeClass::As_Reference -- Given an aircraft type, find the matching type object. *
|
||||
* AircraftTypeClass::Create_And_Place -- Creates and places aircraft using normal game syste*
|
||||
* AircraftTypeClass::Create_One_Of -- Creates an aircraft object of the appropriate type. *
|
||||
* AircraftTypeClass::Dimensions -- Fetches the graphic dimensions of the aircraft type. *
|
||||
* AircraftTypeClass::Display -- Displays a generic version of the aircraft type. *
|
||||
* AircraftTypeClass::From_Name -- Converts an ASCII name into an aircraft type number. *
|
||||
* AircraftTypeClass::Init_Heap -- Initialize the aircraft type class heap. *
|
||||
* AircraftTypeClass::Max_Pips -- Fetches the maximum number of pips allowed. *
|
||||
* AircraftTypeClass::Occupy_List -- Returns with occupation list for landed aircraft. *
|
||||
* AircraftTypeClass::One_Time -- Performs one time initialization of the aircraft type class*
|
||||
* AircraftTypeClass::Overlap_List -- Determines the overlap list for a landed aircraft. *
|
||||
* AircraftTypeClass::Prep_For_Add -- Prepares the scenario editor for adding an aircraft obj*
|
||||
* AircraftTypeClass::operator delete -- Returns aircraft type to special memory pool. *
|
||||
* AircraftTypeClass::operator new -- Allocates an aircraft type object from special pool. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
void const * AircraftTypeClass::LRotorData = NULL;
|
||||
void const * AircraftTypeClass::RRotorData = NULL;
|
||||
|
||||
// Badger bomber
|
||||
static AircraftTypeClass const BadgerPlane(
|
||||
AIRCRAFT_BADGER, // What kind of aircraft is this.
|
||||
TXT_BADGER, // Translated text number for aircraft.
|
||||
"BADR", // INI name of aircraft.
|
||||
0x0000, // Vertical offset.
|
||||
0x0000, // Primary weapon offset along turret centerline.
|
||||
0x0000, // Primary weapon lateral offset along turret centerline.
|
||||
true, // Fixed wing aircraft?
|
||||
false, // Equipped with a rotor?
|
||||
false, // Custom rotor sets for each facing?
|
||||
false, // Can this aircraft land on clear terrain?
|
||||
true, // Is it invisible on radar?
|
||||
false, // Can the player select it so as to give it orders?
|
||||
true, // Can it be assigned as a target for attack.
|
||||
false, // Is it insignificant (won't be announced)?
|
||||
false, // Is it immune to normal combat damage?
|
||||
STRUCT_NONE, // Preferred landing building.
|
||||
0xFF, // Landing speed
|
||||
16, // Number of rotation stages.
|
||||
MISSION_HUNT // Default mission for aircraft.
|
||||
);
|
||||
|
||||
// Photo recon plane.
|
||||
static AircraftTypeClass const U2Plane(
|
||||
AIRCRAFT_U2, // What kind of aircraft is this.
|
||||
TXT_U2, // Translated text number for aircraft.
|
||||
"U2", // INI name of aircraft.
|
||||
0x0000, // Vertical offset.
|
||||
0x0000, // Primary weapon offset along turret centerline.
|
||||
0x0000, // Primary weapon lateral offset along turret centerline.
|
||||
true, // Fixed wing aircraft?
|
||||
false, // Equipped with a rotor?
|
||||
false, // Custom rotor sets for each facing?
|
||||
false, // Can this aircraft land on clear terrain?
|
||||
true, // Is it invisible on radar?
|
||||
false, // Can the player select it so as to give it orders?
|
||||
true, // Can it be assigned as a target for attack.
|
||||
false, // Is it insignificant (won't be announced)?
|
||||
false, // Is it immune to normal combat damage?
|
||||
STRUCT_NONE, // Preferred landing building.
|
||||
0xFF, // Landing speed
|
||||
16, // Number of rotation stages.
|
||||
MISSION_HUNT // Default mission for aircraft.
|
||||
);
|
||||
|
||||
// Mig attack aircraft.
|
||||
static AircraftTypeClass const MigPlane(
|
||||
AIRCRAFT_MIG, // What kind of aircraft is this.
|
||||
TXT_MIG, // Translated text number for aircraft.
|
||||
"MIG", // INI name of aircraft.
|
||||
0x0000, // Vertical offset.
|
||||
0x0020, // Primary weapon offset along turret centerline.
|
||||
0x0020, // Primary weapon lateral offset along turret centerline.
|
||||
true, // Fixed wing aircraft?
|
||||
false, // Equipped with a rotor?
|
||||
false, // Custom rotor sets for each facing?
|
||||
false, // Can this aircraft land on clear terrain?
|
||||
true, // Is it invisible on radar?
|
||||
true, // Can the player select it so as to give it orders?
|
||||
true, // Can it be assigned as a target for attack.
|
||||
false, // Is it insignificant (won't be announced)?
|
||||
false, // Is it immune to normal combat damage?
|
||||
STRUCT_AIRSTRIP, // Preferred landing building.
|
||||
0xC0, // Landing speed
|
||||
16, // Number of rotation stages.
|
||||
MISSION_HUNT // Default mission for aircraft.
|
||||
);
|
||||
|
||||
// Yak attack aircraft.
|
||||
static AircraftTypeClass const YakPlane(
|
||||
AIRCRAFT_YAK, // What kind of aircraft is this.
|
||||
TXT_YAK, // Translated text number for aircraft.
|
||||
"YAK", // INI name of aircraft.
|
||||
0x0000, // Vertical offset.
|
||||
0x0020, // Primary weapon offset along turret centerline.
|
||||
0x0020, // Primary weapon lateral offset along turret centerline.
|
||||
true, // Fixed wing aircraft?
|
||||
false, // Equipped with a rotor?
|
||||
false, // Custom rotor sets for each facing?
|
||||
false, // Can this aircraft land on clear terrain?
|
||||
true, // Is it invisible on radar?
|
||||
true, // Can the player select it so as to give it orders?
|
||||
true, // Can it be assigned as a target for attack.
|
||||
false, // Is it insignificant (won't be announced)?
|
||||
false, // Is it immune to normal combat damage?
|
||||
STRUCT_AIRSTRIP, // Preferred landing building.
|
||||
0xFF, // Landing speed
|
||||
16, // Number of rotation stages.
|
||||
MISSION_HUNT // Default mission for aircraft.
|
||||
);
|
||||
|
||||
// Transport helicopter.
|
||||
static AircraftTypeClass const TransportHeli(
|
||||
AIRCRAFT_TRANSPORT, // What kind of aircraft is this.
|
||||
TXT_TRANS, // Translated text number for aircraft.
|
||||
"TRAN", // INI name of aircraft.
|
||||
0x0000, // Vertical offset.
|
||||
0x0000, // Primary weapon offset along turret centerline.
|
||||
0x0000, // Primary weapon lateral offset along turret centerline.
|
||||
false, // Fixed wing aircraft?
|
||||
true, // Equipped with a rotor?
|
||||
true, // Custom rotor sets for each facing?
|
||||
true, // Can this aircraft land on clear terrain?
|
||||
true, // Is it invisible on radar?
|
||||
true, // Can the player select it so as to give it orders?
|
||||
true, // Can it be assigned as a target for attack.
|
||||
false, // Is it insignificant (won't be announced)?
|
||||
false, // Is it immune to normal combat damage?
|
||||
STRUCT_NONE, // Preferred landing building.
|
||||
0xFF, // Landing speed
|
||||
32, // Number of rotation stages.
|
||||
MISSION_HUNT // Default mission for aircraft.
|
||||
);
|
||||
|
||||
// Longbow attack helicopter
|
||||
static AircraftTypeClass const AttackHeli(
|
||||
AIRCRAFT_LONGBOW, // What kind of aircraft is this.
|
||||
TXT_HELI, // Translated text number for aircraft.
|
||||
"HELI", // INI name of aircraft.
|
||||
0x0000, // Vertical offset.
|
||||
0x0040, // Primary weapon offset along turret centerline.
|
||||
0x0000, // Primary weapon lateral offset along turret centerline.
|
||||
false, // Fixed wing aircraft?
|
||||
true, // Equipped with a rotor?
|
||||
false, // Custom rotor sets for each facing?
|
||||
false, // Can this aircraft land on clear terrain?
|
||||
true, // Is it invisible on radar?
|
||||
true, // Can the player select it so as to give it orders?
|
||||
true, // Can it be assigned as a target for attack.
|
||||
false, // Is it insignificant (won't be announced)?
|
||||
false, // Is it immune to normal combat damage?
|
||||
STRUCT_HELIPAD, // Preferred landing building.
|
||||
0xFF, // Landing speed
|
||||
32, // Number of rotation stages.
|
||||
MISSION_HUNT // Default mission for aircraft.
|
||||
);
|
||||
|
||||
|
||||
// Hind
|
||||
static AircraftTypeClass const OrcaHeli(
|
||||
AIRCRAFT_HIND, // What kind of aircraft is this.
|
||||
TXT_ORCA, // Translated text number for aircraft.
|
||||
"HIND", // INI name of aircraft.
|
||||
0x0000, // Vertical offset.
|
||||
0x0040, // Primary weapon offset along turret centerline.
|
||||
0x0000, // Primary weapon lateral offset along turret centerline.
|
||||
false, // Fixed wing aircraft?
|
||||
true, // Equipped with a rotor?
|
||||
false, // Custom rotor sets for each facing?
|
||||
false, // Can this aircraft land on clear terrain?
|
||||
true, // Is it invisible on radar?
|
||||
true, // Can the player select it so as to give it orders?
|
||||
true, // Can it be assigned as a target for attack.
|
||||
false, // Is it insignificant (won't be announced)?
|
||||
false, // Is it immune to normal combat damage?
|
||||
STRUCT_HELIPAD, // Preferred landing building.
|
||||
0xFF, // Landing speed
|
||||
32, // Number of rotation stages.
|
||||
MISSION_HUNT // Default mission for aircraft.
|
||||
);
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::AircraftTypeClass -- Constructor for aircraft objects. *
|
||||
* *
|
||||
* This is the constructor for the aircraft object. *
|
||||
* *
|
||||
* INPUT: see below... *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/26/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
AircraftTypeClass::AircraftTypeClass(
|
||||
AircraftType airtype,
|
||||
int name,
|
||||
char const * ininame,
|
||||
int verticaloffset,
|
||||
int primaryoffset,
|
||||
int primarylateral,
|
||||
bool is_fixedwing,
|
||||
bool is_rotorequipped,
|
||||
bool is_rotorcustom,
|
||||
bool is_landable,
|
||||
bool is_stealthy,
|
||||
bool is_selectable,
|
||||
bool is_legal_target,
|
||||
bool is_insignificant,
|
||||
bool is_immune,
|
||||
StructType building,
|
||||
int landingspeed,
|
||||
int rotation,
|
||||
MissionType deforder
|
||||
) :
|
||||
TechnoTypeClass(RTTI_AIRCRAFTTYPE,
|
||||
int(airtype),
|
||||
name,
|
||||
ininame,
|
||||
REMAP_NORMAL,
|
||||
verticaloffset,
|
||||
primaryoffset,
|
||||
primarylateral,
|
||||
primaryoffset,
|
||||
primarylateral,
|
||||
false,
|
||||
is_stealthy,
|
||||
is_selectable,
|
||||
is_legal_target,
|
||||
is_insignificant,
|
||||
is_immune,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
rotation,
|
||||
SPEED_WINGED),
|
||||
IsFixedWing(is_fixedwing),
|
||||
IsLandable(is_landable),
|
||||
IsRotorEquipped(is_rotorequipped),
|
||||
IsRotorCustom(is_rotorcustom),
|
||||
Type(airtype),
|
||||
Mission(deforder),
|
||||
Building(building),
|
||||
LandingSpeed(landingspeed)
|
||||
{
|
||||
/*
|
||||
** Forced aircraft overrides from the default.
|
||||
*/
|
||||
Speed = SPEED_WINGED;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::operator new -- Allocates an aircraft type object from special pool. *
|
||||
* *
|
||||
* This will allocate an aircraft type class object from the memory pool of that purpose. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to the newly allocated aircraft type class object. If there *
|
||||
* was insufficient memory to fulfill the request, then NULL is returned. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/09/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void * AircraftTypeClass::operator new(size_t)
|
||||
{
|
||||
return(AircraftTypes.Alloc());
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::operator delete -- Returns aircraft type to special memory pool. *
|
||||
* *
|
||||
* This will return the aircraft type class object back to the special memory pool that *
|
||||
* it was allocated from. *
|
||||
* *
|
||||
* INPUT: pointer -- Pointer to the aircraft type class object to delete. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/09/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void AircraftTypeClass::operator delete(void * pointer)
|
||||
{
|
||||
AircraftTypes.Free((AircraftTypeClass *)pointer);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::Init_Heap -- Initialize the aircraft type class heap. *
|
||||
* *
|
||||
* This will initialize the aircraft type class heap by pre-allocating all known aircraft *
|
||||
* types. It should be called once and before the rules.ini file is processed. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/09/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void AircraftTypeClass::Init_Heap(void)
|
||||
{
|
||||
/*
|
||||
** These aircraft type class objects must be allocated in the exact order that they
|
||||
** are specified in the AircraftSmen enumeration. This is necessary because the heap
|
||||
** allocation block index serves double duty as the type number index.
|
||||
*/
|
||||
new AircraftTypeClass(TransportHeli);
|
||||
new AircraftTypeClass(BadgerPlane);
|
||||
new AircraftTypeClass(U2Plane);
|
||||
new AircraftTypeClass(MigPlane);
|
||||
new AircraftTypeClass(YakPlane);
|
||||
new AircraftTypeClass(AttackHeli);
|
||||
new AircraftTypeClass(OrcaHeli);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::From_Name -- Converts an ASCII name into an aircraft type number. *
|
||||
* *
|
||||
* This routine is used to convert an ASCII representation of an aircraft into the *
|
||||
* matching aircraft type number. This is used by the scenario INI reader code. *
|
||||
* *
|
||||
* INPUT: name -- Pointer to ASCII name to translate. *
|
||||
* *
|
||||
* OUTPUT: Returns the aircraft type number that matches the ASCII name provided. If no *
|
||||
* match could be found, then AIRCRAFT_NONE is returned. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/26/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
AircraftType AircraftTypeClass::From_Name(char const * name)
|
||||
{
|
||||
if (name != NULL) {
|
||||
for (AircraftType classid = AIRCRAFT_FIRST; classid < AIRCRAFT_COUNT; classid++) {
|
||||
if (stricmp(As_Reference(classid).IniName, name) == 0) {
|
||||
return(classid);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(AIRCRAFT_NONE);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::One_Time -- Performs one time initialization of the aircraft type class. *
|
||||
* *
|
||||
* This routine is used to perform the onetime initialization of the aircraft type. This *
|
||||
* includes primarily the shape and other graphic data loading. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: This goes to disk and also must only be called ONCE. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/26/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void AircraftTypeClass::One_Time(void)
|
||||
{
|
||||
for (AircraftType index = AIRCRAFT_FIRST; index < AIRCRAFT_COUNT; index++) {
|
||||
char fullname[_MAX_FNAME+_MAX_EXT];
|
||||
AircraftTypeClass const & uclass = As_Reference(index);
|
||||
|
||||
/*
|
||||
** Fetch the supporting data files for the unit.
|
||||
*/
|
||||
char buffer[_MAX_FNAME];
|
||||
sprintf(buffer, "%sICON", uclass.Graphic_Name());
|
||||
_makepath(fullname, NULL, NULL, buffer, ".SHP");
|
||||
((void const *&)uclass.CameoData) = MFCD::Retrieve(fullname);
|
||||
|
||||
/*
|
||||
** Generic shape for all houses load method.
|
||||
*/
|
||||
_makepath(fullname, NULL, NULL, uclass.Graphic_Name(), ".SHP");
|
||||
((void const *&)uclass.ImageData) = MFCD::Retrieve(fullname);
|
||||
}
|
||||
|
||||
LRotorData = MFCD::Retrieve("LROTOR.SHP");
|
||||
RRotorData = MFCD::Retrieve("RROTOR.SHP");
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::Create_One_Of -- Creates an aircraft object of the appropriate type. *
|
||||
* *
|
||||
* This routine is used to create an aircraft object that matches the aircraft type. It *
|
||||
* serves as a shortcut to creating an object using the "new" operator and "if" checks. *
|
||||
* *
|
||||
* INPUT: house -- The house owner of the aircraft that is to be created. *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to the aircraft created. If the aircraft could not be *
|
||||
* created, then a NULL is returned. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/26/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
ObjectClass * AircraftTypeClass::Create_One_Of(HouseClass * house) const
|
||||
{
|
||||
return(new AircraftClass(Type, house->Class->House));
|
||||
}
|
||||
|
||||
|
||||
#ifdef SCENARIO_EDITOR
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::Prep_For_Add -- Prepares the scenario editor for adding an aircraft objec*
|
||||
* *
|
||||
* This routine is used by the scenario editor to prepare for the adding operation. It *
|
||||
* builds a list of pointers to object types that can be added. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/26/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void AircraftTypeClass::Prep_For_Add(void)
|
||||
{
|
||||
for (AircraftType index = AIRCRAFT_FIRST; index < AIRCRAFT_COUNT; index++) {
|
||||
if (As_Reference(index).Get_Image_Data()) {
|
||||
Map.Add_To_List(&As_Reference(index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::Display -- Displays a generic version of the aircraft type. *
|
||||
* *
|
||||
* This routine is used by the scenario editor to display a generic version of the object *
|
||||
* type. This is displayed in the object selection dialog box. *
|
||||
* *
|
||||
* INPUT: x,y -- The coordinates to draw the aircraft at (centered). *
|
||||
* *
|
||||
* window -- The window to base the coordinates upon. *
|
||||
* *
|
||||
* house -- The owner of this generic aircraft. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/26/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void AircraftTypeClass::Display(int x, int y, WindowNumberType window, HousesType ) const
|
||||
{
|
||||
int shape = 0;
|
||||
void const * ptr = Get_Cameo_Data();
|
||||
if (ptr == NULL) {
|
||||
ptr = Get_Image_Data();
|
||||
shape = 5;
|
||||
}
|
||||
CC_Draw_Shape(ptr, shape, x, y, window, SHAPE_CENTER|SHAPE_WIN_REL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::Occupy_List -- Returns with occupation list for landed aircraft. *
|
||||
* *
|
||||
* This determines the occupation list for the aircraft (if it was landed). *
|
||||
* *
|
||||
* INPUT: placement -- Is this for placement legality checking only? The normal condition *
|
||||
* is for marking occupation flags. *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to a cell offset occupation list for the aircraft. *
|
||||
* *
|
||||
* WARNINGS: This occupation list is only valid if the aircraft is landed. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/26/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
short const * AircraftTypeClass::Occupy_List(bool) const
|
||||
{
|
||||
static short const _list[] = {0, REFRESH_EOL};
|
||||
return(_list);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::Overlap_List -- Determines the overlap list for a landed aircraft. *
|
||||
* *
|
||||
* This routine figures out the overlap list for the aircraft as if it were landed. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the cell offset overlap list for the aircraft. *
|
||||
* *
|
||||
* WARNINGS: This overlap list is only valid when the aircraft is landed. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/26/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
short const * AircraftTypeClass::Overlap_List(void) const
|
||||
{
|
||||
static short const _list[] = {-(MAP_CELL_W-1), -MAP_CELL_W, -(MAP_CELL_W+1), -1, 1, (MAP_CELL_W-1), MAP_CELL_W, (MAP_CELL_W+1), REFRESH_EOL};
|
||||
return(_list);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::Max_Pips -- Fetches the maximum number of pips allowed. *
|
||||
* *
|
||||
* Use this routine to retrieve the maximum pip count allowed for this aircraft. This is *
|
||||
* the maximum number of passengers. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the maximum number of pips for this aircraft. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/26/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int AircraftTypeClass::Max_Pips(void) const
|
||||
{
|
||||
if (PrimaryWeapon != NULL) {
|
||||
return(5);
|
||||
}
|
||||
return(Max_Passengers());
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::Create_And_Place -- Creates and places aircraft using normal game system *
|
||||
* *
|
||||
* This routine is used to create and place an aircraft through the normal game system. *
|
||||
* Since creation of aircraft in this fashion is prohibited, this routine does nothing. *
|
||||
* *
|
||||
* INPUT: na *
|
||||
* *
|
||||
* OUTPUT: Always returns a failure code (false). *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/07/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
bool AircraftTypeClass::Create_And_Place(CELL, HousesType) const
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::Dimensions -- Fetches the graphic dimensions of the aircraft type. *
|
||||
* *
|
||||
* This routine will fetch the pixel dimensions of this aircraft type. These dimensions *
|
||||
* are used to control map refresh and select box rendering. *
|
||||
* *
|
||||
* INPUT: width -- Reference to variable that will be filled in with aircraft width. *
|
||||
* *
|
||||
* height -- Reference to variable that will be filled in with aircraft height. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/07/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void AircraftTypeClass::Dimensions(int &width, int &height) const
|
||||
{
|
||||
if (Type == AIRCRAFT_BADGER) {
|
||||
width = 56;
|
||||
height = 56;
|
||||
} else {
|
||||
width = 21;
|
||||
height = 20;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AircraftTypeClass::As_Reference -- Given an aircraft type, find the matching type object. *
|
||||
* *
|
||||
* This routine is used to fetch a reference to the aircraft type class object that matches *
|
||||
* the aircraft type specified. *
|
||||
* *
|
||||
* INPUT: aircraft -- The aircraft type to fetch a reference to the type class object of. *
|
||||
* *
|
||||
* OUTPUT: Returns with a reference to the type class object of this aircraft type. *
|
||||
* *
|
||||
* WARNINGS: Be sure that the aircraft type specified is legal. Illegal values will result *
|
||||
* in undefined behavior. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/09/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
AircraftTypeClass & AircraftTypeClass::As_Reference(AircraftType aircraft)
|
||||
{
|
||||
return(*AircraftTypes.Ptr(aircraft));
|
||||
}
|
216
CODE/ABSTRACT.CPP
Normal file
216
CODE/ABSTRACT.CPP
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/ABSTRACT.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : ABSTRACT.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 01/26/95 *
|
||||
* *
|
||||
* Last Update : July 10, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* AbstractClass::Debug_Dump -- Display debug information to mono screen. *
|
||||
* AbstractClass::Distance -- Determines distance to target. *
|
||||
* AbstractTypeClass::AbstractTypeClass -- Constructor for abstract type objects. *
|
||||
* AbstractTypeClass::Coord_Fixup -- Performs custom adjustments to location coordinate. *
|
||||
* AbstractTypeClass::Full_Name -- Returns the full name (number) of this object type. *
|
||||
* AbstractTypeClass::Get_Ownable -- Fetch the ownable bits for this object. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AbstractClass::Debug_Dump -- Display debug information to mono screen. *
|
||||
* *
|
||||
* This debug only routine will display various information about this abstract class *
|
||||
* object to the monochrome screen specified. *
|
||||
* *
|
||||
* INPUT: mono -- Pointer to the monochrome screen to display the debug information to. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/10/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
#ifdef CHEAT_KEYS
|
||||
void AbstractClass::Debug_Dump(MonoClass * mono) const
|
||||
{
|
||||
assert(IsActive);
|
||||
|
||||
mono->Set_Cursor(11, 5);mono->Printf("%08X", As_Target());
|
||||
mono->Set_Cursor(20, 1);mono->Printf("%08X", Coord);
|
||||
mono->Set_Cursor(29, 1);mono->Printf("%3d", Height);
|
||||
if (Owner() != HOUSE_NONE) {
|
||||
mono->Set_Cursor(1, 3);
|
||||
mono->Printf("%-18s", Text_String(HouseTypeClass::As_Reference(Owner()).FullName));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AbstractClass::Distance -- Determines distance to target. *
|
||||
* *
|
||||
* This will determine the distance (direct line) to the target. The distance is in *
|
||||
* 'leptons'. This routine is typically used for weapon range checks. *
|
||||
* *
|
||||
* INPUT: target -- The target to determine range to. *
|
||||
* *
|
||||
* OUTPUT: Returns with the range to the specified target (in leptons). *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/17/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int AbstractClass::Distance(TARGET target) const
|
||||
{
|
||||
/*
|
||||
** Should subtract a fudge-factor distance for building targets.
|
||||
*/
|
||||
BuildingClass * obj = As_Building(target);
|
||||
int dist = Distance(As_Coord(target));
|
||||
|
||||
/*
|
||||
** If the object is a building the adjust it by the average radius
|
||||
** of the object.
|
||||
*/
|
||||
if (obj) {
|
||||
dist -= ((obj->Class->Width() + obj->Class->Height()) * (0x100 / 4));
|
||||
if (dist < 0) dist = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the distance to the target
|
||||
*/
|
||||
return(dist);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AbstractTypeClass::AbstractTypeClass -- Constructor for abstract type objects. *
|
||||
* *
|
||||
* This is the constructor for AbstractTypeClass objects. It initializes the INI name and *
|
||||
* the text name for this object type. *
|
||||
* *
|
||||
* INPUT: name -- Text number for the full name of the object. *
|
||||
* *
|
||||
* ini -- The ini name for this object type. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/22/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
AbstractTypeClass::AbstractTypeClass(RTTIType rtti, int id, int name, char const * ini) :
|
||||
RTTI(rtti),
|
||||
ID(id),
|
||||
FullName(name)
|
||||
{
|
||||
strncpy((char *)IniName, ini, sizeof(IniName));
|
||||
((char &)IniName[sizeof(IniName)-1]) = '\0';
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AbstractTypeClass::Coord_Fixup -- Performs custom adjustments to location coordinate. *
|
||||
* *
|
||||
* This routine is called when the placement coordinate should be fixed up according *
|
||||
* to any special rules specific to this object type. At this level, no transformation *
|
||||
* occurs. Derived classes will transform the coordinate as necessary. *
|
||||
* *
|
||||
* INPUT: coord -- The proposed coordinate that this object type will be placed down at. *
|
||||
* *
|
||||
* OUTPUT: Returns with the adjusted coordinate that the object should be placed down at. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/21/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
COORDINATE AbstractTypeClass::Coord_Fixup(COORDINATE coord) const
|
||||
{
|
||||
return(coord);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AbstractTypeClass::Full_Name -- Returns the full name (number) of this object type. *
|
||||
* *
|
||||
* This routine is used to fetch the full name of this object type. The name value *
|
||||
* returned is actually the index number into the text array. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the full name index number for this object type. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/21/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int AbstractTypeClass::Full_Name(void) const
|
||||
{
|
||||
#ifdef FIXIT_NAME_OVERRIDE
|
||||
for (int index = 0; index < ARRAY_SIZE(NameOverride); index++) {
|
||||
if (NameIDOverride[index] == ((RTTI+1) * 100) + ID) {
|
||||
return(-(index+1));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return(FullName);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* AbstractTypeClass::Get_Ownable -- Fetch the ownable bits for this object. *
|
||||
* *
|
||||
* This returns a bit flag that indicates which houses are allowed to own this object *
|
||||
* type. At this level, all houses have ownership rights. This routine will be overridden *
|
||||
* by object types that restrict ownership. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with a bit flag indicating which houses have ownership rights. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/21/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int AbstractTypeClass::Get_Ownable(void) const
|
||||
{
|
||||
return(HOUSEF_ALLIES | HOUSEF_SOVIET | HOUSEF_OTHERS);
|
||||
}
|
||||
|
||||
|
||||
|
135
CODE/ABSTRACT.H
Normal file
135
CODE/ABSTRACT.H
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/ABSTRACT.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : ABSTRACT.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 01/26/95 *
|
||||
* *
|
||||
* Last Update : January 26, 1995 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef ABSTRACT_H
|
||||
#define ABSTRACT_H
|
||||
|
||||
DirType Direction(CELL cell1, CELL cell2);
|
||||
DirType Direction(COORDINATE coord1, COORDINATE coord2);
|
||||
int Distance(COORDINATE coord1, COORDINATE coord2);
|
||||
COORDINATE As_Coord(TARGET target);
|
||||
|
||||
class AbstractTypeClass;
|
||||
|
||||
/*
|
||||
** This class is the base class for all game objects that have an existence on the
|
||||
** battlefield.
|
||||
*/
|
||||
class AbstractClass
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
** This specifies the type of object and the unique ID number
|
||||
** associated with it. The ID number happens to match the index into
|
||||
** the object heap appropriate for this object type.
|
||||
*/
|
||||
RTTIType RTTI;
|
||||
int ID;
|
||||
|
||||
/*
|
||||
** The coordinate location of the unit. For vehicles, this is the center
|
||||
** point. For buildings, it is the upper left corner.
|
||||
*/
|
||||
COORDINATE Coord;
|
||||
|
||||
/*
|
||||
** This is the height of the object above ground (expressed in leptons).
|
||||
*/
|
||||
int Height;
|
||||
|
||||
/*
|
||||
** The actual object ram-space is located in arrays in the data segment. This flag
|
||||
** is used to indicate which objects are free to be reused and which are currently
|
||||
** in use by the game.
|
||||
*/
|
||||
unsigned IsActive:1;
|
||||
|
||||
/*-----------------------------------------------------------------------------------
|
||||
** Constructor & destructors.
|
||||
*/
|
||||
AbstractClass(RTTIType rtti, int id) : RTTI(rtti), ID(id), Coord(0xFFFFFFFFL), Height(0) {};
|
||||
AbstractClass(NoInitClass const & x) {x();};
|
||||
virtual ~AbstractClass(void) {};
|
||||
|
||||
/*
|
||||
** Query functions.
|
||||
*/
|
||||
virtual char const * Name(void) const {return("");}
|
||||
virtual HousesType Owner(void) const {return HOUSE_NONE;};
|
||||
TARGET As_Target(void) const {return(Build_Target(RTTI, ID));};
|
||||
RTTIType What_Am_I(void) const {return(RTTI);};
|
||||
|
||||
/*
|
||||
** Scenario and debug support.
|
||||
*/
|
||||
#ifdef CHEAT_KEYS
|
||||
virtual void Debug_Dump(MonoClass * mono) const;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Coordinate query support functions.
|
||||
*/
|
||||
virtual COORDINATE Center_Coord(void) const {return Coord;};
|
||||
virtual COORDINATE Target_Coord(void) const {return Coord;};
|
||||
|
||||
/*
|
||||
** Coordinate inquiry functions. These are used for both display and
|
||||
** combat purposes.
|
||||
*/
|
||||
DirType Direction(AbstractClass const * object) const {return ::Direction(Center_Coord(), object->Target_Coord());};
|
||||
DirType Direction(COORDINATE coord) const {return ::Direction(Center_Coord(), coord);};
|
||||
DirType Direction(TARGET target) const {return ::Direction(Center_Coord(), As_Coord(target));};
|
||||
DirType Direction(CELL cell) const {return ::Direction(Coord_Cell(Center_Coord()), cell);};
|
||||
int Distance(TARGET target) const;
|
||||
int Distance(COORDINATE coord) const {return ::Distance(Center_Coord(), coord);};
|
||||
int Distance(AbstractClass const * object) const {return ::Distance(Center_Coord(), object->Target_Coord());};
|
||||
|
||||
/*
|
||||
** Object entry and exit from the game system.
|
||||
*/
|
||||
virtual MoveType Can_Enter_Cell(CELL , FacingType = FACING_NONE) const {return MOVE_OK;};
|
||||
|
||||
/*
|
||||
** AI.
|
||||
*/
|
||||
virtual void AI(void) {};
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
1847
CODE/ADAMTEMP.MAK
Normal file
1847
CODE/ADAMTEMP.MAK
Normal file
File diff suppressed because it is too large
Load Diff
2361
CODE/ADATA.CPP
Normal file
2361
CODE/ADATA.CPP
Normal file
File diff suppressed because it is too large
Load Diff
83
CODE/ADPCM.CPP
Normal file
83
CODE/ADPCM.CPP
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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/>.
|
||||
*/
|
||||
|
||||
#include "function.h"
|
||||
|
||||
extern "C" {
|
||||
#include "soscomp.h"
|
||||
#include "itable.cpp"
|
||||
#include "dtable.cpp"
|
||||
|
||||
|
||||
void sosCODECInitStream(_SOS_COMPRESS_INFO* info)
|
||||
{
|
||||
info->dwSampleIndex = 0;
|
||||
info->dwPredicted = 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned long sosCODECDecompressData(_SOS_COMPRESS_INFO* info, unsigned long numbytes)
|
||||
{
|
||||
unsigned long token;
|
||||
long sample;
|
||||
unsigned int fastindex;
|
||||
unsigned char *inbuff;
|
||||
unsigned short *outbuff;
|
||||
|
||||
inbuff = (unsigned char *)info->lpSource;
|
||||
outbuff = (unsigned short *)info->lpDest;
|
||||
|
||||
// Preload variables before the big loop
|
||||
fastindex = (unsigned int)info->dwSampleIndex;
|
||||
sample = info->dwPredicted;
|
||||
|
||||
if (!numbytes)
|
||||
goto SkipLoop;
|
||||
|
||||
do {
|
||||
// First nibble
|
||||
token = *inbuff++;
|
||||
fastindex += token & 0x0f;
|
||||
sample += DiffTable[fastindex];
|
||||
fastindex = IndexTable[fastindex];
|
||||
if (sample > 32767L)
|
||||
sample = 32767L;
|
||||
if (sample < -32768L)
|
||||
sample = -32768L;
|
||||
*outbuff++ = (unsigned short)sample;
|
||||
|
||||
// Second nibble
|
||||
fastindex += token >> 4;
|
||||
sample += DiffTable[fastindex];
|
||||
fastindex = IndexTable[fastindex];
|
||||
if (sample > 32767L)
|
||||
sample = 32767L;
|
||||
if (sample < -32768L)
|
||||
sample = -32768L;
|
||||
*outbuff++ = (unsigned short)sample;
|
||||
} while(--numbytes);
|
||||
|
||||
SkipLoop:
|
||||
|
||||
// Put local vars back
|
||||
info->dwSampleIndex = (unsigned long)fastindex;
|
||||
info->dwPredicted = sample;
|
||||
return(numbytes << 2);
|
||||
}
|
||||
|
||||
}
|
4375
CODE/AIRCRAFT.CPP
Normal file
4375
CODE/AIRCRAFT.CPP
Normal file
File diff suppressed because it is too large
Load Diff
248
CODE/AIRCRAFT.H
Normal file
248
CODE/AIRCRAFT.H
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/AIRCRAFT.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : AIRCRAFT.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : July 22, 1994 *
|
||||
* *
|
||||
* Last Update : November 28, 1994 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef AIRCRAFT_H
|
||||
#define AIRCRAFT_H
|
||||
|
||||
#include "radio.h"
|
||||
#include "fly.h"
|
||||
#include "target.h"
|
||||
|
||||
|
||||
/*
|
||||
** This aircraft class is used for all flying sentient objects. This includes fixed wing
|
||||
** aircraft as well as helicopters. It excludes bullets even though some bullets might
|
||||
** be considered to be "flying" in a loose interpretatin of the word.
|
||||
*/
|
||||
class AircraftClass : public FootClass, public FlyClass
|
||||
{
|
||||
public:
|
||||
/*
|
||||
** This is a pointer to the class control structure for the aircraft.
|
||||
*/
|
||||
CCPtr<AircraftTypeClass> Class;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void * operator new(size_t);
|
||||
static void * operator new(size_t, void * ptr) {return(ptr);};
|
||||
static void operator delete(void *);
|
||||
operator AircraftType(void) const {return Class->Type;};
|
||||
AircraftClass(AircraftType classid, HousesType house);
|
||||
AircraftClass(NoInitClass const & x) : FootClass(x), FlyClass(x), Class(x), SecondaryFacing(x), SightTimer(x) {};
|
||||
virtual ~AircraftClass(void);
|
||||
|
||||
static void Init(void);
|
||||
|
||||
virtual int Mission_Attack(void);
|
||||
virtual int Mission_Unload(void);
|
||||
virtual int Mission_Hunt(void);
|
||||
virtual int Mission_Retreat(void);
|
||||
virtual int Mission_Move(void);
|
||||
virtual int Mission_Enter(void);
|
||||
virtual int Mission_Guard(void);
|
||||
virtual int Mission_Guard_Area(void);
|
||||
|
||||
virtual void Assign_Destination(TARGET target);
|
||||
/*
|
||||
** State machine support routines.
|
||||
*/
|
||||
bool Process_Take_Off(void);
|
||||
bool Process_Landing(void);
|
||||
int Process_Fly_To(bool slowdown, TARGET dest);
|
||||
|
||||
/*
|
||||
** Query functions.
|
||||
*/
|
||||
virtual LayerType In_Which_Layer(void) const;
|
||||
virtual DirType Turret_Facing(void) const {return(SecondaryFacing.Current());}
|
||||
int Shape_Number(void) const;
|
||||
virtual MoveType Can_Enter_Cell(CELL cell, FacingType facing=FACING_NONE) const;
|
||||
virtual ObjectTypeClass const & Class_Of(void) const {return *Class;};
|
||||
virtual ActionType What_Action(ObjectClass const * target) const;
|
||||
virtual ActionType What_Action(CELL cell) const;
|
||||
virtual DirType Desired_Load_Dir(ObjectClass * passenger, CELL & moveto) const;
|
||||
virtual int Pip_Count(void) const;
|
||||
TARGET Good_Fire_Location(TARGET target) const;
|
||||
bool Cell_Seems_Ok(CELL cell, bool landing=false) const;
|
||||
DirType Pose_Dir(void) const;
|
||||
TARGET Good_LZ(void) const;
|
||||
virtual DirType Fire_Direction(void) const;
|
||||
virtual FireErrorType Can_Fire(TARGET target, int which) const;
|
||||
|
||||
/*
|
||||
** Landing zone support functionality.
|
||||
*/
|
||||
virtual void Per_Cell_Process(PCPType why);
|
||||
bool Is_LZ_Clear(TARGET target) const;
|
||||
TARGET New_LZ(TARGET oldlz) const;
|
||||
|
||||
/*
|
||||
** Coordinate inquiry functions. These are used for both display and
|
||||
** combat purposes.
|
||||
*/
|
||||
virtual COORDINATE Sort_Y(void) const;
|
||||
|
||||
/*
|
||||
** Object entry and exit from the game system.
|
||||
*/
|
||||
virtual bool Unlimbo(COORDINATE , DirType facing = DIR_N);
|
||||
|
||||
/*
|
||||
** Display and rendering support functionality. Supports imagery and how
|
||||
** object interacts with the map and thus indirectly controls rendering.
|
||||
*/
|
||||
virtual void Look(bool incremental=false);
|
||||
void Draw_Rotors(int x, int y, WindowNumberType window) const;
|
||||
virtual int Exit_Object(TechnoClass *);
|
||||
virtual short const * Overlap_List(bool redraw=false) const;
|
||||
virtual void Draw_It(int x, int y, WindowNumberType window) const;
|
||||
virtual void Set_Speed(int speed);
|
||||
|
||||
/*
|
||||
** User I/O.
|
||||
*/
|
||||
virtual void Active_Click_With(ActionType action, ObjectClass * object);
|
||||
virtual void Active_Click_With(ActionType action, CELL cell);
|
||||
virtual void Player_Assign_Mission(MissionType mission, TARGET target=TARGET_NONE, TARGET destination=TARGET_NONE);
|
||||
virtual void Response_Select(void);
|
||||
virtual void Response_Move(void);
|
||||
virtual void Response_Attack(void);
|
||||
|
||||
/*
|
||||
** Combat related.
|
||||
*/
|
||||
virtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source, bool forced=false);
|
||||
virtual BulletClass * Fire_At(TARGET target, int which);
|
||||
|
||||
/*
|
||||
** AI.
|
||||
*/
|
||||
bool Landing_Takeoff_AI(void);
|
||||
bool Edge_Of_World_AI(void);
|
||||
void Movement_AI(void);
|
||||
void Rotation_AI(void);
|
||||
int Paradrop_Cargo(void);
|
||||
virtual void AI(void);
|
||||
virtual void Enter_Idle_Mode(bool initial = false);
|
||||
virtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);
|
||||
virtual void Scatter(COORDINATE threat, bool forced=false, bool nokidding=false);
|
||||
|
||||
/*
|
||||
** Scenario and debug support.
|
||||
*/
|
||||
#ifdef CHEAT_KEYS
|
||||
virtual void Debug_Dump(MonoClass *mono) const;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** File I/O.
|
||||
*/
|
||||
static void Read_INI(CCINIClass & ini);
|
||||
static char * INI_Name(void) {return "AIRCRAFT";};
|
||||
bool Load(Straw & file);
|
||||
bool Save(Pipe & file) const;
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
** This is the facing used for the body of the aircraft. Typically, this is the same
|
||||
** as the PrimaryFacing, but in the case of helicopters, it can be different.
|
||||
*/
|
||||
FacingClass SecondaryFacing;
|
||||
|
||||
/*
|
||||
** If this is a passenger carrying aircraft then this flag will be set. This is
|
||||
** necessary because once the passengers are unloaded, the fact that it was a
|
||||
** passenger carrier must still be known.
|
||||
*/
|
||||
bool Passenger;
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
** Aircraft can be in either state of landing, taking off, or in steady altitude.
|
||||
** These flags are used to control transition between flying and landing. It is
|
||||
** necessary to handle the transition in this manner so that it occurs smoothly
|
||||
** during the graphic processing section.
|
||||
*/
|
||||
unsigned IsLanding:1;
|
||||
unsigned IsTakingOff:1;
|
||||
|
||||
/*
|
||||
** It is very common for aircraft to be homing in on a target. When this flag is
|
||||
** true, the aircraft will constantly adjust its facing toward the TarCom. When the
|
||||
** target is very close (one cell away or less), then this flag is automatically cleared.
|
||||
** This is because the homing algorithm is designed to get the aircraft to the destination
|
||||
** but no more. Checking when this flag is cleared is a way of flagging transition into
|
||||
** a new mode. Example: Transport helicopters go into a hovering into correct position
|
||||
** mode when the target is reached.
|
||||
*/
|
||||
unsigned IsHoming:1;
|
||||
|
||||
/*
|
||||
** Helicopters that are about to land must hover into a position exactly above the landing
|
||||
** zone. When this flag is true, the aircraft will be adjusted so that it is exactly over
|
||||
** the TarCom. The facing of the aircraft is not altered by this movement. The affect
|
||||
** like the helicopter is hovering and shifting sideways to position over the landing
|
||||
** zone. When the position is over the landing zone, then this flag is set to false.
|
||||
*/
|
||||
unsigned IsHovering:1;
|
||||
|
||||
/*
|
||||
** This is the jitter tracker to be used when the aircraft is a helicopter and
|
||||
** is flying. It is most noticeable when the helicopter is hovering.
|
||||
*/
|
||||
unsigned char Jitter;
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
** This timer controls when the aircraft will reveal the terrain around itself.
|
||||
** When this timer expires and this aircraft has a sight range, then the
|
||||
** look around process will occur.
|
||||
*/
|
||||
CDTimerClass<FrameTimerClass> SightTimer;
|
||||
|
||||
/*
|
||||
** Most attack aircraft can make several attack runs. This value contains the
|
||||
** number of attack runs the aircraft has left. When this value reaches
|
||||
** zero then the aircraft is technically out of ammo.
|
||||
*/
|
||||
char AttacksRemaining;
|
||||
};
|
||||
|
||||
#endif
|
590
CODE/ALLOC.CPP
Normal file
590
CODE/ALLOC.CPP
Normal file
@ -0,0 +1,590 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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 A S S O C I A T E S **
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : Westwood Library *
|
||||
* *
|
||||
* File Name : ALLOC.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : February 1, 1992 *
|
||||
* *
|
||||
* Last Update : March 9, 1995 [JLB] *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Alloc -- Allocates system RAM. *
|
||||
* Ram_Free -- Determines the largest free chunk of RAM. *
|
||||
* Free -- Free an Alloc'ed block of RAM. *
|
||||
* Resize_Alloc -- Change the size of an allocated block. *
|
||||
* Heap_Size -- Size of the heap we have. *
|
||||
* Total_Ram_Free -- Total amount of free RAM. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dos.h>
|
||||
#include <bios.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#ifndef WWMEM_H
|
||||
#include "wwmem.h"
|
||||
#endif
|
||||
|
||||
|
||||
extern "C" unsigned long Largest_Mem_Block ( void ) ;
|
||||
|
||||
//
|
||||
// use double-word alignment for allocs
|
||||
//
|
||||
#define LONG_ALIGNMENT 1
|
||||
|
||||
/*
|
||||
** Define the equates necessary to call a DPMI interrupt.
|
||||
*/
|
||||
#define DPMI_INT 0x0031
|
||||
#define DPMI_LOCK_MEM 0x0600
|
||||
#define DPMI_UNLOCK_MEM 0x0601
|
||||
#define LOGGING FALSE
|
||||
/*=========================================================================*/
|
||||
/* The following PRIVATE functions are in this file: */
|
||||
/*=========================================================================*/
|
||||
|
||||
|
||||
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
|
||||
|
||||
unsigned long MinRam=0L; // Record of least memory at worst case.
|
||||
unsigned long MaxRam=0L; // Record of total allocated at worst case.
|
||||
static unsigned long TotalRam = 0L;
|
||||
static unsigned long Memory_Calls = 0L;
|
||||
static unsigned long RequestedSystemRam = 8*1024*1024;
|
||||
static unsigned long LargestRamBlock = 0L;
|
||||
|
||||
void (*Memory_Error)(void) = NULL;
|
||||
void (*Memory_Error_Exit)(char *string) = NULL;
|
||||
|
||||
/***************************************************************************
|
||||
* DPMI_LOCK -- handles locking a block of DPMI memory *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/23/1995 PWG : Created. *
|
||||
*=========================================================================*/
|
||||
#include"mono.h"
|
||||
void DPMI_Lock(VOID const *ptr, long const size)
|
||||
{
|
||||
union REGS regs;
|
||||
struct SREGS sregs;
|
||||
|
||||
/*
|
||||
** Lock memory
|
||||
** AX = 0x600
|
||||
** BX:CX = starting linear address of memory to lock
|
||||
** SI:DI = size of region to lock (in bytes)
|
||||
** - If Failure, carry flag is set.
|
||||
*/
|
||||
memset (®s, 0 ,sizeof(regs));
|
||||
segread (&sregs);
|
||||
regs.x.eax = DPMI_LOCK_MEM;
|
||||
regs.x.ebx = ((long)ptr & 0xffff0000) >> 16;
|
||||
regs.x.ecx = ((long)ptr & 0x0000ffff);
|
||||
regs.x.esi = ((long)size & 0xffff0000) >> 16;
|
||||
regs.x.edi = ((long)size & 0x0000ffff);
|
||||
int386x (DPMI_INT, ®s, ®s, &sregs); // call DPMI
|
||||
// if (regs.x.cflag) {
|
||||
// }
|
||||
#if(0)
|
||||
char *temp = (char *)ptr;
|
||||
char hold;
|
||||
for (int lp = 0; lp < size; lp += 2048) {
|
||||
hold = *temp;
|
||||
temp += 2048;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* DPMI_UNLOCK -- Handles unlocking a locked block of DPMI *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/23/1995 PWG : Created. *
|
||||
*=========================================================================*/
|
||||
void DPMI_Unlock(void const *ptr, long const size)
|
||||
{
|
||||
union REGS regs;
|
||||
struct SREGS sregs;
|
||||
|
||||
/*
|
||||
** Unlock the memory
|
||||
*/
|
||||
memset (®s, 0 ,sizeof(regs));
|
||||
segread (&sregs);
|
||||
regs.x.eax = DPMI_UNLOCK_MEM; // DPMI function to call
|
||||
regs.x.ebx = ((long)ptr & 0xffff0000) >> 16;
|
||||
regs.x.ecx = ((long)ptr & 0x0000ffff);
|
||||
regs.x.esi = ((long)size & 0xffff0000) >> 16;
|
||||
regs.x.edi = ((long)size & 0x0000ffff);
|
||||
int386x (DPMI_INT, ®s, ®s, &sregs); // call DPMI
|
||||
// if (regs.x.cflag) {
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Alloc -- Allocates system RAM. *
|
||||
* *
|
||||
* This is the basic RAM allocation function. It is used for all *
|
||||
* memory allocations needed by the system or the main program. *
|
||||
* *
|
||||
* INPUT: bytes_to_alloc -- LONG value of the number of bytes to alloc. *
|
||||
* *
|
||||
* flags -- Memory allocation control flags. *
|
||||
* MEM_NORMAL: No special flags. *
|
||||
* MEM_CLEAR: Zero out memory block. *
|
||||
* MEM_NEW: Called by a new. *
|
||||
* *
|
||||
* OUTPUT: Returns with pointer to allocated block. If NULL was returned *
|
||||
* it indicates a failure to allocate. Note: NULL will never be *
|
||||
* returned if the standard library allocation error routine is *
|
||||
* used. *
|
||||
* *
|
||||
* WARNINGS: If you replace the standard memory allocation error routine *
|
||||
* and make it so that Alloc CAN return with a NULL, be sure *
|
||||
* and check for this in your code. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/03/1991 JLB : Documented. *
|
||||
* 08/09/1993 JLB : Updated with EMS memory support. *
|
||||
* 04/28/1994 JAW : Updated to 32bit Protected mode. *
|
||||
* 03/09/1995 JLB : Fixed *
|
||||
*=========================================================================*/
|
||||
void *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)
|
||||
{
|
||||
union REGS regs ;
|
||||
struct SREGS sregs ;
|
||||
unsigned char *retval=NULL; // Pointer to allocated block.
|
||||
unsigned long original_size; // Original allocation size.
|
||||
unsigned long bytesfree; // Number of free bytes.
|
||||
long *longptr=NULL; // Pointer used to store selector
|
||||
static unsigned char _allocinit=0;
|
||||
|
||||
|
||||
//
|
||||
// Init memory system by finding largest block to alloc
|
||||
// then allocate it to get one large heap and free it.
|
||||
// There may be more memory available from DPMI but we only are
|
||||
// for now allocating and freeing the first largest block.
|
||||
//
|
||||
if ( !_allocinit ) {
|
||||
unsigned long largestblock = Largest_Mem_Block();
|
||||
largestblock -= 1024; // subtract for heap header and misc
|
||||
largestblock &= 0xffff0000; // forcing to 64K boundary
|
||||
|
||||
if ( largestblock ) {
|
||||
LargestRamBlock = MIN( largestblock, RequestedSystemRam );
|
||||
unsigned char *lptr = (unsigned char *)malloc( LargestRamBlock );
|
||||
if ( lptr ) {
|
||||
free( (void *)lptr );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize the total ram available value.
|
||||
*/
|
||||
TotalRam = Total_Ram_Free(MEM_NORMAL);
|
||||
|
||||
_allocinit = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Save the original allocated space size so that we can clear the
|
||||
** exact amount of RAM if they specified MEM_CLEAR.
|
||||
*/
|
||||
original_size = bytes_to_alloc;
|
||||
|
||||
/*
|
||||
** Reserve one byte for the header of the memory we allocated.
|
||||
** We will store the flags variable there for later use.
|
||||
*/
|
||||
#if (LONG_ALIGNMENT)
|
||||
bytes_to_alloc += (flags & MEM_LOCK) ? 8 : 4;
|
||||
#else
|
||||
bytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;
|
||||
#endif
|
||||
|
||||
|
||||
// Try to allocate the memory out of the protected mode memory
|
||||
// chain if we did not require a real mode allocation. If this
|
||||
// fails we will have to try to allocate it out of real mode memory.
|
||||
// Real mode memory is a last resort because some types of applications
|
||||
// require real mode memory.
|
||||
if (!(flags & MEM_REAL)) {
|
||||
retval = (unsigned char*)malloc(bytes_to_alloc);
|
||||
}
|
||||
|
||||
// Try to allocate the memory out of the real mode memory using DPMI
|
||||
// service 0x100. Note that retval will be null if we are requesting
|
||||
// real mode memory so that we do not have to explicitly check for the
|
||||
// real mode flag. Remember we need to reserve room for the dos
|
||||
// selector value at the beginning of our allocated block so rather than
|
||||
// adding fifteen and rounding, we need to add 19 and round.
|
||||
if (!retval) {
|
||||
flags = (MemoryFlagType)(flags | MEM_REAL);
|
||||
regs.x.eax = 0x100;
|
||||
regs.x.ebx = (bytes_to_alloc + 19) >> 4;
|
||||
if (regs.x.ebx & 0xFFFF0000) {
|
||||
retval = NULL;
|
||||
} else {
|
||||
segread ( & sregs ) ;
|
||||
int386x ( 0x31 , & regs, & regs , & sregs ) ;
|
||||
if (regs.x.cflag)
|
||||
retval = NULL;
|
||||
else {
|
||||
#if (LONG_ALIGNMENT)
|
||||
longptr = (long *)(((regs.x.eax & 0xFFFF) << 4)+ 4);
|
||||
#else
|
||||
longptr = (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);
|
||||
#endif
|
||||
*longptr++ = regs.x.edx & 0xFFFF;
|
||||
retval = (unsigned char *)longptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the alloc failed then we need to signify a memory error.
|
||||
if (retval == NULL) {
|
||||
if (Memory_Error != NULL)
|
||||
Memory_Error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If the memory needs to be DPMI locked then we should store the
|
||||
// original size in the header before we store the flags.
|
||||
if (flags & MEM_LOCK) {
|
||||
longptr = (long *)retval;
|
||||
*longptr++ = original_size;
|
||||
retval = (unsigned char *)longptr;
|
||||
}
|
||||
|
||||
|
||||
// Now that we know the alloc was sucessful (and for an extra byte
|
||||
// more than the user wanted) we need to stick in the memory flags.
|
||||
#if (LONG_ALIGNMENT)
|
||||
if ( !(flags & (MEM_LOCK|MEM_REAL)) ) {
|
||||
//
|
||||
// WARNING!!!!!!!!!!
|
||||
// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!
|
||||
// it reads the actual block size before the ptr returned.
|
||||
// then eors and uses the upper word for a validation later on free.
|
||||
//
|
||||
longptr = (long *)retval;
|
||||
*longptr = ((*(longptr - 1)) ^ 0xffffffff) & 0xffff0000;
|
||||
*retval++ = flags;
|
||||
*retval++ = (unsigned char)(flags ^ 0xff);
|
||||
retval += 2;
|
||||
}
|
||||
else {
|
||||
*retval++ = flags;
|
||||
*retval++ = (unsigned char)(flags ^ 0xff);
|
||||
*retval++ = 0;
|
||||
*retval++ = 0;
|
||||
}
|
||||
#else
|
||||
*retval++ = (unsigned char)(flags | (((flags ^ 0x07) & 0x07) << 5));
|
||||
#endif
|
||||
|
||||
// If the memory needed to be DPMI locked then set it up so it
|
||||
// is locked.
|
||||
if (flags & MEM_LOCK) {
|
||||
DPMI_Lock(retval, original_size);
|
||||
}
|
||||
|
||||
/* Clear the space if they wanted it clear */
|
||||
|
||||
if (flags & MEM_CLEAR) {
|
||||
unsigned char *ptr; // Working memory block pointer.
|
||||
|
||||
ptr = retval;
|
||||
memset(ptr, '\0', original_size);
|
||||
}
|
||||
|
||||
bytesfree = Total_Ram_Free(MEM_NORMAL);
|
||||
if (bytesfree < MinRam) {
|
||||
MinRam = bytesfree;
|
||||
}
|
||||
if (TotalRam-bytesfree > MaxRam) {
|
||||
MaxRam = TotalRam-bytesfree;
|
||||
}
|
||||
|
||||
Memory_Calls++;
|
||||
|
||||
#if(LOGGING)
|
||||
int val = _heapchk();
|
||||
|
||||
FILE *file = fopen("mem.txt","at");
|
||||
fprintf(file, "%P Alloc size = %d, Actual Size = %d, flags = %d, heap = %d\n",
|
||||
retval,
|
||||
original_size,
|
||||
bytes_to_alloc,
|
||||
flags,
|
||||
val);
|
||||
fclose(file);
|
||||
#endif
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Free -- Free an Alloc'ed block of RAM. *
|
||||
* *
|
||||
* FUNCTION: *
|
||||
* *
|
||||
* INPUT: A pointer to a block of RAM from Alloc. *
|
||||
* *
|
||||
* OUTPUT: None. *
|
||||
* *
|
||||
* WARNINGS: Don't use this for an Alloc_Block'ed RAM block. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/25/1990 : Created. *
|
||||
***************************************************************************/
|
||||
void Free(void const *pointer)
|
||||
{
|
||||
union REGS regs ;
|
||||
struct SREGS sregs ;
|
||||
|
||||
// void const *original = pointer;
|
||||
char string[80];
|
||||
|
||||
if (pointer) {
|
||||
/*
|
||||
** Get a pointer to the flags that we stored off.
|
||||
*/
|
||||
#if (LONG_ALIGNMENT)
|
||||
unsigned char *byteptr = ((unsigned char *)pointer) - 4;
|
||||
|
||||
//
|
||||
// validate the flags with and eor of the flags
|
||||
//
|
||||
if ( *byteptr != ((*(byteptr + 1)) ^ 0xff) ) {
|
||||
if (Memory_Error_Exit != NULL) {
|
||||
sprintf( string, "Error freeing pointer %p. Header invalid!!!\n", pointer );
|
||||
Memory_Error_Exit( string );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( !(*byteptr & (MEM_LOCK|MEM_REAL)) ) {
|
||||
unsigned short *wordptr = (unsigned short *)(byteptr - 2);
|
||||
|
||||
//
|
||||
// WARNING!!!!!!!!!!
|
||||
// USE this only with the WATCOM malloc ALLOCATION!!!!!!!!!
|
||||
// it reads the actual block size before the ptr to be freed.
|
||||
// then compares with the EOR to the value stored during allocation.
|
||||
//
|
||||
if ( *wordptr != ((*(wordptr + 2)) ^ 0xffff) ) {
|
||||
if (Memory_Error_Exit != NULL) {
|
||||
sprintf( string, "Error freeing pointer %p. Header invalid!!!\n", pointer );
|
||||
Memory_Error_Exit( string );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( *(byteptr + 2) || *(byteptr + 3) ) {
|
||||
if (Memory_Error_Exit != NULL) {
|
||||
sprintf( string, "Error freeing pointer %p. Header invalid!!!\n", pointer );
|
||||
Memory_Error_Exit( string );
|
||||
}
|
||||
}
|
||||
}
|
||||
// if ( *byteptr != (*(byteptr + 1) ^ 0xff) ||
|
||||
// *(byteptr + 2) || *(byteptr + 3) ) {
|
||||
// if (Memory_Error_Exit != NULL) {
|
||||
// sprintf( string, "Error freeing pointer %p. Header invalid!!!\n", pointer );
|
||||
// Memory_Error_Exit( string );
|
||||
// }
|
||||
// }
|
||||
#else
|
||||
unsigned char *byteptr = ((unsigned char *)pointer) - 1;
|
||||
|
||||
if ( (*byteptr & 0xe0) != (((*byteptr ^ 0x07) & 0x07) << 5) ) {
|
||||
if (Memory_Error_Exit != NULL) {
|
||||
sprintf( string, "Error freeing pointer %p. Header invalid!!!\n", pointer );
|
||||
Memory_Error_Exit( string );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Check to see if this was locked me and if it was unlock it.
|
||||
*/
|
||||
if (*byteptr & MEM_LOCK) {
|
||||
long *longptr = ((long *)byteptr) - 1;
|
||||
DPMI_Unlock(pointer, *longptr);
|
||||
pointer = (void *)longptr;
|
||||
} else
|
||||
pointer = (void *)byteptr;
|
||||
|
||||
#if(LOGGING)
|
||||
int val = _heapchk();
|
||||
FILE *file = fopen("mem.txt","at");
|
||||
fprintf(file, "%P Free flags = %d, Heap = %d\n",
|
||||
original,
|
||||
*byteptr,
|
||||
val);
|
||||
fclose(file);
|
||||
#endif
|
||||
|
||||
// If the pointer is a real mode pointer than it will point to the
|
||||
// first megabyte of system memory. If it does than we need to
|
||||
// use DPMI to free it.
|
||||
if (*byteptr & MEM_REAL) {
|
||||
regs.x.eax = 0x101;
|
||||
regs.x.edx = *(((long *)pointer) - 1);
|
||||
segread ( & sregs ) ;
|
||||
int386x(0x31, ®s, ®s, &sregs);
|
||||
} else {
|
||||
free((void *)pointer);
|
||||
}
|
||||
Memory_Calls--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Resize_Alloc -- Change the size of an allocated block. *
|
||||
* *
|
||||
* This routine will take a previously allocated block and change its *
|
||||
* size without unnecessarily altering its contents. *
|
||||
* *
|
||||
* INPUT: pointer -- Pointer to the original memory allocation. *
|
||||
* *
|
||||
* new_size -- Size in bytes that it will be converted to. *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to the new allocation. *
|
||||
* *
|
||||
* WARNINGS: ??? *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 02/01/1992 JLB : Commented. *
|
||||
*=========================================================================*/
|
||||
void *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)
|
||||
{
|
||||
|
||||
unsigned long *temp;
|
||||
// unsigned long diff, flags;
|
||||
|
||||
temp = (unsigned long*)original_ptr;
|
||||
|
||||
/* ReAlloc the space */
|
||||
temp = (unsigned long *)realloc(temp, new_size_in_bytes);
|
||||
if (temp == NULL) {
|
||||
if (Memory_Error != NULL)
|
||||
Memory_Error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return(temp);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Ram_Free -- Determines the largest free chunk of RAM. *
|
||||
* *
|
||||
* Use this routine to determine the largest free chunk of available *
|
||||
* RAM for allocation. It also performs a check of the memory chain. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the size of the largest free chunk of RAM. *
|
||||
* *
|
||||
* WARNINGS: This does not return the TOTAL memory free, only the *
|
||||
* largest free chunk. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/03/1991 JLB : Commented. *
|
||||
*=========================================================================*/
|
||||
long Ram_Free(MemoryFlagType)
|
||||
{
|
||||
return(_memmax());
|
||||
// return Largest_Mem_Block();
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Heap_Size -- Size of the heap we have. *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/21/1994 SKB : Created. *
|
||||
*=========================================================================*/
|
||||
long Heap_Size(MemoryFlagType )
|
||||
{
|
||||
if (!TotalRam) {
|
||||
TotalRam = Total_Ram_Free(MEM_NORMAL);
|
||||
}
|
||||
return(TotalRam);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Total_Ram_Free -- Total amount of free RAM. *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/21/1994 SKB : Created. *
|
||||
* 03/09/1995 JLB : Uses prerecorded heap size maximum. *
|
||||
*=========================================================================*/
|
||||
long Total_Ram_Free(MemoryFlagType )
|
||||
{
|
||||
return(_memavl());
|
||||
// return Largest_Mem_Block () ;
|
||||
}
|
||||
|
1108
CODE/ANIM.CPP
Normal file
1108
CODE/ANIM.CPP
Normal file
File diff suppressed because it is too large
Load Diff
1062
CODE/ANIM.CPP.BAK
Normal file
1062
CODE/ANIM.CPP.BAK
Normal file
File diff suppressed because it is too large
Load Diff
156
CODE/ANIM.H
Normal file
156
CODE/ANIM.H
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/ANIM.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : ANIM.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : May 30, 1994 *
|
||||
* *
|
||||
* Last Update : May 30, 1994 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef ANIM_H
|
||||
#define ANIM_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
|
||||
/**********************************************************************************************
|
||||
** This is the class that controls the shape animation objects. Shape animation objects are
|
||||
** displayed over the top of the game map. Typically, they are used for explosion and fire
|
||||
** effects.
|
||||
*/
|
||||
class AnimClass : public ObjectClass, public StageClass {
|
||||
/*
|
||||
** This points to the type of animation object this is.
|
||||
*/
|
||||
CCPtr<AnimTypeClass> Class;
|
||||
|
||||
public:
|
||||
|
||||
AnimClass(AnimType animnum, COORDINATE coord, unsigned char timedelay=0, unsigned char loop=1);
|
||||
AnimClass(NoInitClass const & x) : ObjectClass(x), Class(x), StageClass(x) {};
|
||||
virtual ~AnimClass(void);
|
||||
|
||||
operator AnimType(void) const {return Class->Type;};
|
||||
|
||||
static void * operator new(size_t size);
|
||||
static void * operator new(size_t , void * ptr) {return(ptr);};
|
||||
static void operator delete(void *ptr);
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
** Member function prototypes.
|
||||
*/
|
||||
static void Init(void);
|
||||
|
||||
void Attach_To(ObjectClass *obj);
|
||||
void Make_Invisible(void) {IsInvisible = true;};
|
||||
static void Do_Atom_Damage(HousesType ownerhouse, CELL cell);
|
||||
|
||||
virtual bool Can_Place_Here(COORDINATE ) const {return true;}
|
||||
virtual bool Mark(MarkType mark=MARK_CHANGE);
|
||||
virtual bool Render(bool forced) const;
|
||||
virtual COORDINATE Center_Coord(void) const;
|
||||
virtual COORDINATE Sort_Y(void) const;
|
||||
virtual LayerType In_Which_Layer(void) const;
|
||||
virtual ObjectTypeClass const & Class_Of(void) const {return *Class;};
|
||||
virtual short const * Occupy_List(bool = false) const;
|
||||
virtual short const * Overlap_List(void) const;
|
||||
virtual void Draw_It(int x, int y, WindowNumberType window) const;
|
||||
virtual void AI(void);
|
||||
virtual void Detach(TARGET target, bool all);
|
||||
|
||||
/*
|
||||
** File I/O.
|
||||
*/
|
||||
bool Load(Straw & file);
|
||||
bool Save(FileClass & file);
|
||||
|
||||
/*
|
||||
** If this animation is attached to an object, then this points to that object. An
|
||||
** animation that is attached will follow that object as it moves. This is important
|
||||
** for animations such as flames and smoke.
|
||||
*/
|
||||
TARGET xObject;
|
||||
|
||||
/*
|
||||
** If this animation has an owner, then it will be recorded here. An owner
|
||||
** is used when damage is caused by this animation during the middle of its
|
||||
** animation.
|
||||
*/
|
||||
HousesType OwnerHouse;
|
||||
|
||||
/*
|
||||
** This counter tells how many more times the animation should loop before it
|
||||
** terminates.
|
||||
*/
|
||||
unsigned char Loops;
|
||||
|
||||
protected:
|
||||
void Middle(void);
|
||||
void Start(void);
|
||||
|
||||
private:
|
||||
/*
|
||||
** Delete this animation at the next opportunity. This is flagged when the
|
||||
** animation is to be prematurely ended as a result of some outside event.
|
||||
*/
|
||||
unsigned IsToDelete:1;
|
||||
|
||||
/*
|
||||
** If the animation has just been created, then don't do any animation
|
||||
** processing until it has been through the render loop at least once.
|
||||
*/
|
||||
unsigned IsBrandNew:1;
|
||||
|
||||
/*
|
||||
** If this animation is invisible, then this flag will be true. An invisible
|
||||
** animation is one that is created for the sole purpose of keeping all
|
||||
** machines synchronized. It will not be displayed.
|
||||
*/
|
||||
unsigned IsInvisible:1;
|
||||
|
||||
/*
|
||||
** Is this animation in a temporary suspended state? If so, then it won't
|
||||
** be rendered until this value is zero. The flag will be set to false
|
||||
** after the first countdown timer reaches 0.
|
||||
*/
|
||||
int Delay;
|
||||
|
||||
/*
|
||||
** If this is an animation that damages whatever it is attached to, then this
|
||||
** value holds the accumulation of fractional damage points. When the accumulated
|
||||
** fractions reach 256, then one damage point is applied to the attached object.
|
||||
*/
|
||||
fixed Accum;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
763
CODE/AUDIO.CPP
Normal file
763
CODE/AUDIO.CPP
Normal file
@ -0,0 +1,763 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/AUDIO.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : AUDIO.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : September 10, 1993 *
|
||||
* *
|
||||
* Last Update : November 1, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Is_Speaking -- Checks to see if the eva voice is still playing. *
|
||||
* Sound_Effect -- General purpose sound player. *
|
||||
* Sound_Effect -- Plays a sound effect in the tactical map. *
|
||||
* Speak -- Computer speaks to the player. *
|
||||
* Speak_AI -- Handles starting the EVA voices. *
|
||||
* Speech_Name -- Fetches the name for the voice specified. *
|
||||
* Stop_Speaking -- Forces the EVA voice to stop talking. *
|
||||
* Voc_From_Name -- Fetch VocType from ASCII name specified. *
|
||||
* Voc_Name -- Fetches the name for the sound effect. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Controls what special effects may occur on the sound effect.
|
||||
*/
|
||||
typedef enum {
|
||||
IN_NOVAR, // No variation or alterations allowed.
|
||||
IN_VAR // Infantry variance response modification.
|
||||
} ContextType;
|
||||
|
||||
static struct {
|
||||
char const * Name; // Digitized voice file name.
|
||||
int Priority; // Playback priority of this sample.
|
||||
ContextType Where; // In what game context does this sample exist.
|
||||
} SoundEffectName[VOC_COUNT] = {
|
||||
|
||||
/*
|
||||
** Civilian voices (technicians too).
|
||||
*/
|
||||
{"GIRLOKAY", 20, IN_NOVAR}, // VOC_GIRL_OKAY
|
||||
{"GIRLYEAH", 20, IN_NOVAR}, // VOC_GIRL_YEAH
|
||||
{"GUYOKAY1", 20, IN_NOVAR}, // VOC_GUY_OKAY
|
||||
{"GUYYEAH1", 20, IN_NOVAR}, // VOC_GUY_YEAH
|
||||
|
||||
{"MINELAY1", 5, IN_VAR}, // VOC_MINELAY1
|
||||
|
||||
/*
|
||||
** Infantry and vehicle responses.
|
||||
*/
|
||||
{"ACKNO", 20, IN_VAR}, // VOC_ACKNOWL "acknowledged"
|
||||
{"AFFIRM1", 20, IN_VAR}, // VOC_AFFIRM "affirmative"
|
||||
{"AWAIT1", 20, IN_VAR}, // VOC_AWAIT1 "awaiting orders"
|
||||
{"EAFFIRM1", 20, IN_NOVAR}, // VOC_ENG_AFFIRM Engineer: "affirmative"
|
||||
{"EENGIN1", 20, IN_NOVAR}, // VOC_ENG_ENG Engineer: "engineering"
|
||||
{"NOPROB", 20, IN_VAR}, // VOC_NO_PROB "not a problem"
|
||||
{"READY", 20, IN_VAR}, // VOC_READY "ready and waiting"
|
||||
{"REPORT1", 20, IN_VAR}, // VOC_REPORT "reporting"
|
||||
{"RITAWAY", 20, IN_VAR}, // VOC_RIGHT_AWAY "right away sir"
|
||||
{"ROGER", 20, IN_VAR}, // VOC_ROGER "roger"
|
||||
{"UGOTIT", 20, IN_VAR}, // VOC_UGOTIT "you got it"
|
||||
{"VEHIC1", 20, IN_VAR}, // VOC_VEHIC1 "vehicle reporting"
|
||||
{"YESSIR1", 20, IN_VAR}, // VOC_YESSIR "yes sir"
|
||||
|
||||
{"DEDMAN1", 10, IN_NOVAR}, // VOC_SCREAM1 short infantry scream
|
||||
{"DEDMAN2", 10, IN_NOVAR}, // VOC_SCREAM3 short infantry scream
|
||||
{"DEDMAN3", 10, IN_NOVAR}, // VOC_SCREAM4 short infantry scream
|
||||
{"DEDMAN4", 10, IN_NOVAR}, // VOC_SCREAM5 short infantry scream
|
||||
{"DEDMAN5", 10, IN_NOVAR}, // VOC_SCREAM6 short infantry scream
|
||||
{"DEDMAN6", 10, IN_NOVAR}, // VOC_SCREAM7 short infantry scream
|
||||
{"DEDMAN7", 10, IN_NOVAR}, // VOC_SCREAM10 short infantry scream
|
||||
{"DEDMAN8", 10, IN_NOVAR}, // VOC_SCREAM11 short infantry scream
|
||||
{"DEDMAN10", 10, IN_NOVAR}, // VOC_YELL1 long infantry scream
|
||||
|
||||
{"CHRONO2", 5, IN_NOVAR}, // VOC_CHRONO Chronosphere sound
|
||||
{"CANNON1", 1, IN_NOVAR}, // VOC_CANNON1 Cannon sound (medium).
|
||||
{"CANNON2", 1, IN_NOVAR}, // VOC_CANNON2 Cannon sound (short).
|
||||
{"IRONCUR9", 10, IN_NOVAR}, // VOC_IRON1
|
||||
{"EMOVOUT1", 20, IN_NOVAR}, // VOC_ENG_MOVEOUT Engineer: "movin' out"
|
||||
{"SONPULSE", 10, IN_NOVAR}, // VOC_SONAR
|
||||
{"SANDBAG2", 5, IN_NOVAR}, // VOC_SANDBAG sand bag crunch
|
||||
{"MINEBLO1", 5, IN_NOVAR}, // VOC_MINEBLOW weird mine explosion
|
||||
{"CHUTE1", 1, IN_NOVAR}, // VOC_CHUTE1 Wind swoosh sound.
|
||||
{"DOGY1", 5, IN_NOVAR}, // VOC_DOG_BARK Dog bark.
|
||||
{"DOGW5", 10, IN_NOVAR}, // VOC_DOG_WHINE Dog whine.
|
||||
{"DOGG5P", 10, IN_NOVAR}, // VOC_DOG_GROWL2 Strong dog growl.
|
||||
{"FIREBL3", 1, IN_NOVAR}, // VOC_FIRE_LAUNCH Fireball launch sound.
|
||||
{"FIRETRT1", 1, IN_NOVAR}, // VOC_FIRE_EXPLODE Fireball explode sound.
|
||||
{"GRENADE1", 1, IN_NOVAR}, // VOC_GRENADE_TOSS Grenade toss.
|
||||
{"GUN11", 1, IN_NOVAR}, // VOC_GUN_5 5 round gun burst (slow).
|
||||
{"GUN13", 1, IN_NOVAR}, // VOC_GUN_7 7 round gun burst (fast).
|
||||
{"EYESSIR1", 20, IN_NOVAR}, // VOC_ENG_YES, Engineer: "yes sir"
|
||||
{"GUN27", 1, IN_NOVAR}, // VOC_GUN_RIFLE Rifle shot.
|
||||
{"HEAL2", 1, IN_NOVAR}, // VOC_HEAL Healing effect.
|
||||
{"HYDROD1", 1, IN_NOVAR}, // VOC_DOOR Hyrdrolic door.
|
||||
{"INVUL2", 1, IN_NOVAR}, // VOC_INVULNERABLE Invulnerability effect.
|
||||
{"KABOOM1", 1, IN_NOVAR}, // VOC_KABOOM1 Long explosion (muffled).
|
||||
{"KABOOM12", 1, IN_NOVAR}, // VOC_KABOOM12 Very long explosion (muffled).
|
||||
{"KABOOM15", 1, IN_NOVAR}, // VOC_KABOOM15 Very long explosion (muffled).
|
||||
{"SPLASH9", 5, IN_NOVAR}, // VOC_SPLASH water splash
|
||||
{"KABOOM22", 1, IN_NOVAR}, // VOC_KABOOM22 Long explosion (sharp).
|
||||
{"AACANON3", 1, IN_NOVAR},
|
||||
{"TANDETH1", 10, IN_NOVAR},
|
||||
{"MGUNINF1", 1, IN_NOVAR}, // VOC_GUN_5F 5 round gun burst (fast).
|
||||
{"MISSILE1", 1, IN_NOVAR}, // VOC_MISSILE_1 Missile with high tech effect.
|
||||
{"MISSILE6", 1, IN_NOVAR}, // VOC_MISSILE_2 Long missile launch.
|
||||
{"MISSILE7", 1, IN_NOVAR}, // VOC_MISSILE_3 Short missile launch.
|
||||
{"x", 1, IN_NOVAR},
|
||||
{"PILLBOX1", 1, IN_NOVAR}, // VOC_GUN_5R 5 round gun burst (rattles).
|
||||
{"RABEEP1", 1, IN_NOVAR}, // VOC_BEEP Generic beep sound.
|
||||
{"RAMENU1", 1, IN_NOVAR}, // VOC_CLICK Generic click sound.
|
||||
{"SILENCER", 1, IN_NOVAR}, // VOC_SILENCER Silencer.
|
||||
{"TANK5", 1, IN_NOVAR}, // VOC_CANNON6 Long muffled cannon shot.
|
||||
{"TANK6", 1, IN_NOVAR}, // VOC_CANNON7 Sharp mechanical cannon fire.
|
||||
{"TORPEDO1", 1, IN_NOVAR}, // VOC_TORPEDO Torpedo launch.
|
||||
{"TURRET1", 1, IN_NOVAR}, // VOC_CANNON8 Sharp cannon fire.
|
||||
{"TSLACHG2", 10, IN_NOVAR}, // VOC_TESLA_POWER_UP Hum charge up.
|
||||
{"TESLA1", 10, IN_NOVAR}, // VOC_TESLA_ZAP Tesla zap effect.
|
||||
{"SQUISHY2", 10, IN_NOVAR}, // VOC_SQUISH Squish effect.
|
||||
{"SCOLDY1", 10, IN_NOVAR}, // VOC_SCOLD Scold bleep.
|
||||
{"RADARON2", 20, IN_NOVAR}, // VOC_RADAR_ON Powering up electronics.
|
||||
{"RADARDN1", 10, IN_NOVAR}, // VOC_RADAR_OFF B movie power down effect.
|
||||
{"PLACBLDG", 10, IN_NOVAR}, // VOC_PLACE_BUILDING_DOWN Building slam down sound.
|
||||
{"KABOOM30", 1, IN_NOVAR}, // VOC_KABOOM30 Short explosion (HE).
|
||||
{"KABOOM25", 10, IN_NOVAR}, // VOC_KABOOM25 Short growling explosion.
|
||||
{"x", 10, IN_NOVAR},
|
||||
{"DOGW7", 10, IN_NOVAR}, // VOC_DOG_HURT Dog whine (loud).
|
||||
{"DOGW3PX", 10, IN_NOVAR}, // VOC_DOG_YES Dog 'yes sir'.
|
||||
{"CRMBLE2", 10, IN_NOVAR}, // VOC_CRUMBLE Building crumble.
|
||||
{"CASHUP1", 10, IN_NOVAR}, // VOC_MONEY_UP Rising money tick.
|
||||
{"CASHDN1", 10, IN_NOVAR}, // VOC_MONEY_DOWN Falling money tick.
|
||||
{"BUILD5", 10, IN_NOVAR}, // VOC_CONSTRUCTION Building construction sound.
|
||||
{"BLEEP9", 10, IN_NOVAR}, // VOC_GAME_CLOSED Long bleep.
|
||||
{"BLEEP6", 10, IN_NOVAR}, // VOC_INCOMING_MESSAGE Soft happy warble.
|
||||
{"BLEEP5", 10, IN_NOVAR}, // VOC_SYS_ERROR Sharp soft warble.
|
||||
{"BLEEP17", 10, IN_NOVAR}, // VOC_OPTIONS_CHANGED Mid range soft warble.
|
||||
{"BLEEP13", 10, IN_NOVAR}, // VOC_GAME_FORMING Long warble.
|
||||
{"BLEEP12", 10, IN_NOVAR}, // VOC_PLAYER_LEFT Chirp sequence.
|
||||
{"BLEEP11", 10, IN_NOVAR}, // VOC_PLAYER_JOINED Reverse chirp sequence.
|
||||
{"H2OBOMB2", 10, IN_NOVAR}, // VOC_DEPTH_CHARGE Distant explosion sound.
|
||||
{"CASHTURN", 10, IN_NOVAR}, // VOC_CASHTURN Airbrake.
|
||||
{"TUFFGUY1", 20, IN_NOVAR}, // VOC_TANYA_CHEW Tanya: "Chew on this"
|
||||
{"ROKROLL1", 20, IN_NOVAR}, // VOC_TANYA_ROCK Tanya: "Let's rock"
|
||||
{"LAUGH1", 20, IN_NOVAR}, // VOC_TANYA_LAUGH Tanya: "ha ha ha"
|
||||
{"CMON1", 20, IN_NOVAR}, // VOC_TANYA_SHAKE Tanya: "Shake it baby"
|
||||
{"BOMBIT1", 20, IN_NOVAR}, // VOC_TANYA_CHING Tanya: "Cha Ching"
|
||||
{"GOTIT1", 20, IN_NOVAR}, // VOC_TANYA_GOT Tanya: "That's all you got"
|
||||
{"KEEPEM1", 20, IN_NOVAR}, // VOC_TANYA_KISS Tanya: "Kiss it bye bye"
|
||||
{"ONIT1", 20, IN_NOVAR}, // VOC_TANYA_THERE Tanya: "I'm there"
|
||||
{"LEFTY1", 20, IN_NOVAR}, // VOC_TANYA_GIVE Tanya: "Give it to me"
|
||||
{"YEAH1", 20, IN_NOVAR}, // VOC_TANYA_YEA Tanya: "Yea?"
|
||||
{"YES1", 20, IN_NOVAR}, // VOC_TANYA_YES Tanya: "Yes sir?"
|
||||
{"YO1", 20, IN_NOVAR}, // VOC_TANYA_WHATS Tanya: "What's up."
|
||||
{"WALLKIL2", 5, IN_NOVAR}, // VOC_WALLKILL2 Crushing wall sound.
|
||||
{"x", 10, IN_NOVAR},
|
||||
{"GUN5", 5, IN_NOVAR}, // VOC_TRIPLE_SHOT Three quick shots in succession.
|
||||
{"SUBSHOW1", 5, IN_NOVAR}, // VOC_SUBSHOW Submarine surface sound.
|
||||
{"EINAH1", 20, IN_NOVAR}, // VOC_E_AH, Einstien "ah"
|
||||
{"EINOK1", 20, IN_NOVAR}, // VOC_E_OK, Einstien "ok"
|
||||
{"EINYES1", 20, IN_NOVAR}, // VOC_E_YES, Einstien "yes"
|
||||
{"MINE1", 10, IN_NOVAR}, // VOC_TRIP_MINE mine explosion sound
|
||||
|
||||
{"SCOMND1", 20, IN_NOVAR}, // VOC_SPY_COMMANDER Spy: "commander?"
|
||||
{"SYESSIR1", 20, IN_NOVAR}, // VOC_SPY_YESSIR Spy: "yes sir"
|
||||
{"SINDEED1", 20, IN_NOVAR}, // VOC_SPY_INDEED Spy: "indeed"
|
||||
{"SONWAY1", 20, IN_NOVAR}, // VOC_SPY_ONWAY Spy: "on my way"
|
||||
{"SKING1", 20, IN_NOVAR}, // VOC_SPY_KING Spy: "for king and country"
|
||||
{"MRESPON1", 20, IN_NOVAR}, // VOC_MED_REPORTING Medic: "reporting"
|
||||
{"MYESSIR1", 20, IN_NOVAR}, // VOC_MED_YESSIR Medic: "yes sir"
|
||||
{"MAFFIRM1", 20, IN_NOVAR}, // VOC_MED_AFFIRM Medic: "affirmative"
|
||||
{"MMOVOUT1", 20, IN_NOVAR}, // VOC_MED_MOVEOUT Medic: "movin' out"
|
||||
{"BEEPSLCT", 10, IN_NOVAR}, // VOC_BEEP_SELECT map selection beep
|
||||
|
||||
{"SYEAH1", 20, IN_NOVAR}, // VOC_THIEF_YEA Thief: "yea?"
|
||||
{"ANTDIE", 20, IN_NOVAR}, // VOC_ANTDIE
|
||||
{"ANTBITE", 20, IN_NOVAR}, // VOC_ANTBITE
|
||||
{"SMOUT1", 20, IN_NOVAR}, // VOC_THIEF_MOVEOUT Thief: "movin' out"
|
||||
{"SOKAY1", 20, IN_NOVAR}, // VOC_THIEF_OKAY Thief: "ok"
|
||||
{"x", 20, IN_NOVAR},
|
||||
{"SWHAT1", 20, IN_NOVAR}, // VOC_THIEF_WHAT Thief: "what"
|
||||
{"SAFFIRM1", 20, IN_NOVAR}, // VOC_THIEF_AFFIRM Thief: "affirmative"
|
||||
//ADDED VG 2/24/97
|
||||
{"STAVCMDR", 20, IN_NOVAR},
|
||||
{"STAVCRSE", 20, IN_NOVAR},
|
||||
{"STAVYES", 20, IN_NOVAR},
|
||||
{"STAVMOV", 20, IN_NOVAR},
|
||||
{"BUZZY1", 20, IN_NOVAR},
|
||||
{"RAMBO1", 20, IN_NOVAR},
|
||||
{"RAMBO2", 20, IN_NOVAR},
|
||||
{"RAMBO3", 20, IN_NOVAR},
|
||||
#ifdef FIXIT_CSII // checked - ajw 9/28/98
|
||||
{"MYES1", 20, IN_NOVAR}, // VOC_MECHYES1 Mechanic: "Yes sir!"
|
||||
{"MHOWDY1", 20, IN_NOVAR}, // VOC_MECHHOWDY1 Mechanic: "Howdy!"
|
||||
{"MRISE1", 20, IN_NOVAR}, // VOC_MECHRISE1 Mechanic: "Rise 'n shine!"
|
||||
{"MHUH1", 20, IN_NOVAR}, // VOC_MECHHUH1 Mechanic: "Huh?"
|
||||
{"MHEAR1", 20, IN_NOVAR}, // VOC_MECHHEAR1 Mechanic: "I Hear Ya!"
|
||||
{"MLAFF1", 20, IN_NOVAR}, // VOC_MECHLAFF1 Mechanic: guffaw
|
||||
{"MBOSS1", 20, IN_NOVAR}, // VOC_MECHBOSS1 Mechanic: "Sure Thing, Boss!"
|
||||
{"MYEEHAW1", 20, IN_NOVAR}, // VOC_MECHYEEHAW1 Mechanic: "Yee Haw!"
|
||||
{"MHOTDIG1", 20, IN_NOVAR}, // VOC_MECHHOTDIG1 Mechanic: "Hot Diggity Dog!"
|
||||
{"MWRENCH1", 20, IN_NOVAR}, // VOC_MECHWRENCH1 Mechanic: "I'll get my wrench."
|
||||
|
||||
{"JBURN1", 20, IN_NOVAR}, // VOC_STBURN1 Shock Trooper: "Burn baby burn!"
|
||||
{"JCHRGE1", 20, IN_NOVAR}, // VOC_STCHRGE1 Shock Trooper: "Fully charged!"
|
||||
{"JCRISP1", 20, IN_NOVAR}, // VOC_STCRISP1 Shock Trooper: "Extra Crispy!"
|
||||
{"JDANCE1", 20, IN_NOVAR}, // VOC_STDANCE1 Shock Trooper: "Let's Dance!"
|
||||
{"JJUICE1", 20, IN_NOVAR}, // VOC_STJUICE1 Shock Trooper: "Got juice?"
|
||||
{"JJUMP1", 20, IN_NOVAR}, // VOC_STJUMP1 Shock Trooper: "Need a jump?"
|
||||
{"JLIGHT1", 20, IN_NOVAR}, // VOC_STLIGHT1 Shock Trooper: "Lights out!"
|
||||
{"JPOWER1", 20, IN_NOVAR}, // VOC_STPOWER1 Shock Trooper: "Power on!"
|
||||
{"JSHOCK1", 20, IN_NOVAR}, // VOC_STSHOCK1 Shock Trooper: "Shocking!"
|
||||
{"JYES1", 20, IN_NOVAR}, // VOC_STYES1 Shock Trooper: "Yesssss!"
|
||||
|
||||
{"CHROTNK1", 20, IN_NOVAR}, // VOC_CHRONOTANK1 Chrono tank teleport
|
||||
{"FIXIT1", 20, IN_NOVAR}, // VOC_MECH_FIXIT1 Mechanic fixes something
|
||||
{"MADCHRG2", 20, IN_NOVAR}, // VOC_MAD_CHARGE MAD tank charges up
|
||||
{"MADEXPLO", 20, IN_NOVAR}, // VOC_MAD_EXPLODE MAD tank explodes
|
||||
{"SHKTROP1", 20, IN_NOVAR}, // VOC_SHOCK_TROOP1 Shock Trooper fires
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Voc_From_Name -- Fetch VocType from ASCII name specified. *
|
||||
* *
|
||||
* This will find the corresponding VocType from the ASCII string specified. It does this *
|
||||
* by finding a root filename that matches the string. *
|
||||
* *
|
||||
* INPUT: name -- Pointer to the ASCII string that will be converted into a VocType. *
|
||||
* *
|
||||
* OUTPUT: Returns with the VocType that matches the string specified. If no match could be *
|
||||
* found, then VOC_NONE is returned. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
VocType Voc_From_Name(char const * name)
|
||||
{
|
||||
if (name == NULL) return(VOC_NONE);
|
||||
|
||||
for (VocType voc = VOC_FIRST; voc < VOC_COUNT; voc++) {
|
||||
if (stricmp(name, SoundEffectName[voc].Name) == 0) {
|
||||
return(voc);
|
||||
}
|
||||
}
|
||||
|
||||
return(VOC_NONE);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Voc_Name -- Fetches the name for the sound effect. *
|
||||
* *
|
||||
* This routine returns the descriptive name of the sound effect. Currently, this is just *
|
||||
* the root of the file name. *
|
||||
* *
|
||||
* INPUT: voc -- The VocType that the corresponding name is requested. *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to the text string the represents the sound effect. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
char const * Voc_Name(VocType voc)
|
||||
{
|
||||
if (voc == VOC_NONE) return("none");
|
||||
return(SoundEffectName[voc].Name);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Sound_Effect -- Plays a sound effect in the tactical map. *
|
||||
* *
|
||||
* This routine is used when a sound effect occurs in the game world. It handles fading *
|
||||
* the sound according to distance. *
|
||||
* *
|
||||
* INPUT: voc -- The sound effect number to play. *
|
||||
* *
|
||||
* coord -- The world location that the sound originates from. *
|
||||
* *
|
||||
* variation -- This is the optional variation number to use when playing special *
|
||||
* sound effects that have variations. For normal sound effects, this *
|
||||
* parameter is ignored. *
|
||||
* *
|
||||
* house -- This specifies the optional house override value to use when playing *
|
||||
* sound effects that have a variation. If not specified, then the current *
|
||||
* player is examined for the house variation to use. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/12/1994 JLB : Created. *
|
||||
* 01/05/1995 JLB : Reduces sound more dramatically when off screen. *
|
||||
* 09/15/1996 JLB : Revamped volume logic. *
|
||||
* 11/01/1996 JLB : House override control. *
|
||||
*=============================================================================================*/
|
||||
void Sound_Effect(VocType voc, COORDINATE coord, int variation, HousesType house)
|
||||
{
|
||||
CELL cell_pos = 0;
|
||||
int pan_value;
|
||||
|
||||
if (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {
|
||||
return;
|
||||
}
|
||||
if (coord) {
|
||||
cell_pos = Coord_Cell(coord);
|
||||
}
|
||||
|
||||
fixed volume = 1;
|
||||
pan_value = 0;
|
||||
if (coord && !Map.In_View(cell_pos)) {
|
||||
int distance = Distance(coord, Map.TacticalCoord) / CELL_LEPTON_W;
|
||||
fixed dfixed = fixed(distance, 128+64);
|
||||
dfixed.Sub_Saturate(1);
|
||||
volume = fixed(1) - dfixed;
|
||||
|
||||
pan_value = Cell_X(cell_pos);
|
||||
pan_value -= Coord_XCell(Map.TacticalCoord) + (Lepton_To_Cell(Map.TacLeptonWidth) / 2);
|
||||
if (ABS(pan_value) > Lepton_To_Cell(Map.TacLeptonWidth / 2)) {
|
||||
pan_value *= 0x8000;
|
||||
pan_value /= (MAP_CELL_W >> 2);
|
||||
pan_value = Bound(pan_value, -0x7FFF, 0x7FFF);
|
||||
} else {
|
||||
pan_value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Sound_Effect(voc, volume, variation, pan_value, house);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Sound_Effect -- General purpose sound player. *
|
||||
* *
|
||||
* This is used for general purpose sound effects. These are sounds that occur outside *
|
||||
* of the game world. They do not have a corresponding game world location as their source. *
|
||||
* *
|
||||
* INPUT: voc -- The sound effect number to play. *
|
||||
* *
|
||||
* volume -- The volume to assign to this sound effect. *
|
||||
* *
|
||||
* variation -- This is the optional variation number to use when playing special *
|
||||
* sound effects that have variations. For normal sound effects, this *
|
||||
* parameter is ignored. *
|
||||
* *
|
||||
* house -- This specifies the optional house override value to use when playing *
|
||||
* sound effects that have a variation. If not specified, then the current *
|
||||
* player is examined for the house variation to use. *
|
||||
* *
|
||||
* OUTPUT: Returns with the sound handle (-1 if no sound was played). *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/12/1994 JLB : Created. *
|
||||
* 11/12/1994 JLB : Handles cache logic. *
|
||||
* 05/04/1995 JLB : Variation adjustments. *
|
||||
* 11/01/1996 JLB : House override control. *
|
||||
*=============================================================================================*/
|
||||
int Sound_Effect(VocType voc, fixed volume, int variation, signed short pan_value, HousesType house)
|
||||
{
|
||||
char name[_MAX_FNAME+_MAX_EXT]; // Working filename of sound effect.
|
||||
|
||||
if (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Alter the volume according to the game volume setting.
|
||||
*/
|
||||
volume = volume * Options.Volume;
|
||||
|
||||
/*
|
||||
** Fetch a pointer to the sound effect data. Modify the sound as appropriate and desired.
|
||||
*/
|
||||
char const * ext = ".AUD";
|
||||
if (SoundEffectName[voc].Where == IN_VAR) {
|
||||
|
||||
/*
|
||||
** If there is no forced house, then use the current player
|
||||
** act like house.
|
||||
*/
|
||||
if (house == HOUSE_NONE) {
|
||||
house = PlayerPtr->ActLike;
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the extension based on the variation and house accent requested.
|
||||
*/
|
||||
if (((1 << house) & HOUSEF_ALLIES) != 0) {
|
||||
|
||||
/*
|
||||
** For infantry, use a variation on the response. For vehicles, always
|
||||
** use the vehicle response table.
|
||||
*/
|
||||
if (variation < 0) {
|
||||
if (ABS(variation) % 2) {
|
||||
ext = ".V00";
|
||||
} else {
|
||||
ext = ".V02";
|
||||
}
|
||||
} else {
|
||||
if (variation % 2) {
|
||||
ext = ".V01";
|
||||
} else {
|
||||
ext = ".V03";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (variation < 0) {
|
||||
if (ABS(variation) % 2) {
|
||||
ext = ".R00";
|
||||
} else {
|
||||
ext = ".R02";
|
||||
}
|
||||
} else {
|
||||
if (variation % 2) {
|
||||
ext = ".R01";
|
||||
} else {
|
||||
ext = ".R03";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_makepath(name, NULL, NULL, SoundEffectName[voc].Name, ext);
|
||||
void const * ptr = MFCD::Retrieve(name);
|
||||
|
||||
/*
|
||||
** If the sound data pointer is not null, then presume that it is valid.
|
||||
*/
|
||||
if (ptr != NULL) {
|
||||
volume.Sub_Saturate(1);
|
||||
return(Play_Sample(ptr, SoundEffectName[voc].Priority * volume, volume*256, pan_value));
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This elaborates all the EVA speech voices.
|
||||
*/
|
||||
static char const * Speech[VOX_COUNT] = {
|
||||
"MISNWON1", // VOX_ACCOMPLISHED mission accomplished
|
||||
"MISNLST1", // VOX_FAIL your mission has failed
|
||||
"PROGRES1", // VOX_NO_FACTORY unable to comply, building in progress
|
||||
"CONSCMP1", // VOX_CONSTRUCTION construction complete
|
||||
"UNITRDY1", // VOX_UNIT_READY unit ready
|
||||
"NEWOPT1", // VOX_NEW_CONSTRUCT new construction options
|
||||
"NODEPLY1", // VOX_DEPLOY cannot deploy here
|
||||
"STRCKIL1", // VOX_STRUCTURE_DESTROYED, structure destroyed
|
||||
"NOPOWR1", // VOX_INSUFFICIENT_POWER, insufficient power
|
||||
"NOFUNDS1", // VOX_NO_CASH insufficient funds
|
||||
"BCT1", // VOX_CONTROL_EXIT battle control terminated
|
||||
"REINFOR1", // VOX_REINFORCEMENTS reinforcements have arrived
|
||||
"CANCLD1", // VOX_CANCELED canceled
|
||||
"ABLDGIN1", // VOX_BUILDING building
|
||||
"LOPOWER1", // VOX_LOW_POWER low power
|
||||
"NOFUNDS1", // VOX_NEED_MO_MONEY insufficent funds
|
||||
"BASEATK1", // VOX_BASE_UNDER_ATTACK our base is under attack
|
||||
"NOBUILD1", // VOX_UNABLE_TO_BUILD unable to build more
|
||||
"PRIBLDG1", // VOX_PRIMARY_SELECTED primary building selected
|
||||
#ifdef FIXIT_CSII // checked - ajw 9/28/98
|
||||
#ifdef ENGLISH
|
||||
"TANK01", // VOX_MADTANK_DEPLOYED M.A.D. Tank Deployed
|
||||
#else
|
||||
"none",
|
||||
#endif
|
||||
#else
|
||||
"none",
|
||||
#endif
|
||||
"none", // VOX_SOVIET_CAPTURED Allied building captured
|
||||
"UNITLST1", // VOX_UNIT_LOST unit lost
|
||||
"SLCTTGT1", // VOX_SELECT_TARGET select target
|
||||
"ENMYAPP1", // VOX_PREPARE enemy approaching
|
||||
"SILOND1", // VOX_NEED_MO_CAPACITY silos needed
|
||||
"ONHOLD1", // VOX_SUSPENDED on hold
|
||||
"REPAIR1", // VOX_REPAIRING repairing
|
||||
"none",
|
||||
"none",
|
||||
"AUNITL1", // VOX_AIRCRAFT_LOST airborne unit lost
|
||||
"none",
|
||||
"AAPPRO1", // VOX_ALLIED_FORCES_APPROACHING allied forces approaching
|
||||
"AARRIVE1", // VOX_ALLIED_APPROACHING allied reinforcements have arrived
|
||||
"none",
|
||||
"none",
|
||||
"BLDGINF1", // VOX_BUILDING_INFILTRATED building infiltrated
|
||||
"CHROCHR1", // VOX_CHRONO_CHARGING chronosphere charging
|
||||
"CHRORDY1", // VOX_CHRONO_READY chronosphere ready
|
||||
"CHROYES1", // VOX_CHRONO_TEST chronosphere test successful
|
||||
"CMDCNTR1", // VOX_HQ_UNDER_ATTACK command center under attack
|
||||
"CNTLDED1", // VOX_CENTER_DEACTIVATED control center deactivated
|
||||
"CONVYAP1", // VOX_CONVOY_APPROACHING convoy approaching
|
||||
"CONVLST1", // VOX_CONVOY_UNIT_LOST convoy unit lost
|
||||
"XPLOPLC1", // VOX_EXPLOSIVE_PLACED explosive charge placed
|
||||
"CREDIT1", // VOX_MONEY_STOLEN credits stolen
|
||||
"NAVYLST1", // VOX_SHIP_LOST naval unit lost
|
||||
"SATLNCH1", // VOX_SATALITE_LAUNCHED satalite launched
|
||||
"PULSE1", // VOX_SONAR_AVAILABLE sonar pulse available
|
||||
"none",
|
||||
"SOVFAPP1", // VOX_SOVIET_FORCES_APPROACHING soviet forces approaching
|
||||
"SOVREIN1", // VOX_SOVIET_REINFROCEMENTS soviet reinforcements have arrived
|
||||
"TRAIN1", // VOX_TRAINING training
|
||||
"AREADY1", // VOX_ABOMB_READY
|
||||
"ALAUNCH1", // VOX_ABOMB_LAUNCH
|
||||
"AARRIVN1", // VOX_ALLIES_N
|
||||
"AARRIVS1", // VOX_ALLIES_S
|
||||
"AARIVE1", // VOX_ALLIES_E
|
||||
"AARRIVW1", // VOX_ALLIES_W
|
||||
"1OBJMET1", // VOX_OBJECTIVE1
|
||||
"2OBJMET1", // VOX_OBJECTIVE2
|
||||
"3OBJMET1", // VOX_OBJECTIVE3
|
||||
"IRONCHG1", // VOX_IRON_CHARGING
|
||||
"IRONRDY1", // VOX_IRON_READY
|
||||
"KOSYRES1", // VOX_RESCUED
|
||||
"OBJNMET1", // VOX_OBJECTIVE_NOT
|
||||
"FLAREN1", // VOX_SIGNAL_N
|
||||
"FLARES1", // VOX_SIGNAL_S
|
||||
"FLAREE1", // VOX_SIGNAL_E
|
||||
"FLAREW1", // VOX_SIGNAL_W
|
||||
"SPYPLN1", // VOX_SPY_PLANE
|
||||
"TANYAF1", // VOX_FREED
|
||||
"ARMORUP1", // VOX_UPGRADE_ARMOR
|
||||
"FIREPO1", // VOX_UPGRADE_FIREPOWER
|
||||
"UNITSPD1", // VOX_UPGRADE_SPEED
|
||||
"MTIMEIN1", // VOX_MISSION_TIMER
|
||||
"UNITFUL1", // VOX_UNIT_FULL
|
||||
"UNITREP1", // VOX_UNIT_REPAIRED
|
||||
"40MINR", // VOX_TIME_40
|
||||
"30MINR", // VOX_TIME_30
|
||||
"20MINR", // VOX_TIME_20
|
||||
"10MINR", // VOX_TIME_10
|
||||
"5MINR", // VOX_TIME_5
|
||||
"4MINR", // VOX_TIME_4
|
||||
"3MINR", // VOX_TIME_3
|
||||
"2MINR", // VOX_TIME_2
|
||||
"1MINR", // VOX_TIME_1
|
||||
"TIMERNO1", // VOX_TIME_STOP
|
||||
"UNITSLD1", // VOX_UNIT_SOLD
|
||||
"TIMERGO1", // VOX_TIMER_STARTED
|
||||
"TARGRES1", // VOX_TARGET_RESCUED
|
||||
"TARGFRE1", // VOX_TARGET_FREED
|
||||
"TANYAR1", // VOX_TANYA_RESCUED
|
||||
"STRUSLD1", // VOX_STRUCTURE_SOLD
|
||||
"SOVFORC1", // VOX_SOVIET_FORCES_FALLEN
|
||||
"SOVEMP1", // VOX_SOVIET_SELECTED
|
||||
"SOVEFAL1", // VOX_SOVIET_EMPIRE_FALLEN
|
||||
"OPTERM1", // VOX_OPERATION_TERMINATED
|
||||
"OBJRCH1", // VOX_OBJECTIVE_REACHED
|
||||
"OBJNRCH1", // VOX_OBJECTIVE_NOT_REACHED
|
||||
"OBJMET1", // VOX_OBJECTIVE_MET
|
||||
"MERCR1", // VOX_MERCENARY_RESCUED
|
||||
"MERCF1", // VOX_MERCENARY_FREED
|
||||
"KOSYFRE1", // VOX_KOSOYGEN_FREED
|
||||
"FLARE1", // VOX_FLARE_DETECTED
|
||||
"COMNDOR1", // VOX_COMMANDO_RESCUED
|
||||
"COMNDOF1", // VOX_COMMANDO_FREED
|
||||
"BLDGPRG1", // VOX_BUILDING_IN_PROGRESS
|
||||
"ATPREP1", // VOX_ATOM_PREPPING
|
||||
"ASELECT1", // VOX_ALLIED_SELECTED
|
||||
"APREP1", // VOX_ABOMB_PREPPING
|
||||
"ATLNCH1", // VOX_ATOM_LAUNCHED
|
||||
"AFALLEN1", // VOX_ALLIED_FORCES_FALLEN
|
||||
"AAVAIL1", // VOX_ABOMB_AVAILABLE
|
||||
"AARRIVE1", // VOX_ALLIED_REINFORCEMENTS
|
||||
"SAVE1", // VOX_MISSION_SAVED
|
||||
"LOAD1" // VOX_MISSION_LOADED
|
||||
};
|
||||
|
||||
|
||||
static VoxType CurrentVoice = VOX_NONE;
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Speech_Name -- Fetches the name for the voice specified. *
|
||||
* *
|
||||
* Use this routine to fetch the ASCII name of the speech id specified. Typical use of this *
|
||||
* would be to build a displayable list of the speech types. The trigger system uses this *
|
||||
* so that a speech type can be selected. *
|
||||
* *
|
||||
* INPUT: speech -- The speech type id to convert to ASCII string. *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to the speech ASCII representation of the speech id type. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/01/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
char const * Speech_Name(VoxType speech)
|
||||
{
|
||||
if (speech == VOX_NONE) return("none");
|
||||
return(Speech[speech]);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Speak -- Computer speaks to the player. *
|
||||
* *
|
||||
* This routine is used to have the game computer (EVA) speak to the player. *
|
||||
* *
|
||||
* INPUT: voice -- The voice number to speak (see defines.h). *
|
||||
* *
|
||||
* OUTPUT: Returns with the handle of the playing speech (-1 if no voice started). *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/12/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void Speak(VoxType voice)
|
||||
{
|
||||
if (!Debug_Quiet && Options.Volume != 0 && SampleType != 0 && voice != VOX_NONE && voice != SpeakQueue && voice != CurrentVoice && SpeakQueue == VOX_NONE) {
|
||||
SpeakQueue = voice;
|
||||
Speak_AI();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Speak_AI -- Handles starting the EVA voices. *
|
||||
* *
|
||||
* This starts the EVA voice talking as well. If there is any speech request in the queue, *
|
||||
* it will be started when the current voice is finished. Call this routine as often as *
|
||||
* possible (once per game tick is sufficient). *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/27/1994 JLB : Created. *
|
||||
* 10/11/1996 JLB : Handles multiple speech buffers. *
|
||||
*=============================================================================================*/
|
||||
void Speak_AI(void)
|
||||
{
|
||||
static int _index = 0;
|
||||
if (Debug_Quiet || SampleType == 0) return;
|
||||
|
||||
if (!Is_Sample_Playing(SpeechBuffer[_index])) {
|
||||
CurrentVoice = VOX_NONE;
|
||||
if (SpeakQueue != VOX_NONE) {
|
||||
|
||||
/*
|
||||
** Try to find a previously loaded copy of the EVA speech in one of the
|
||||
** speech buffers.
|
||||
*/
|
||||
void const * speech = NULL;
|
||||
for (int index = 0; index < ARRAY_SIZE(SpeechRecord); index++) {
|
||||
if (SpeechRecord[index] == SpeakQueue) break;
|
||||
}
|
||||
|
||||
/*
|
||||
** If a previous copy could not be located, then load the requested
|
||||
** voice into the oldest buffer available.
|
||||
*/
|
||||
if (speech == NULL) {
|
||||
_index = (_index + 1) % ARRAY_SIZE(SpeechRecord);
|
||||
|
||||
char name[_MAX_FNAME+_MAX_EXT];
|
||||
|
||||
_makepath(name, NULL, NULL, Speech[SpeakQueue], ".AUD");
|
||||
CCFileClass file(name);
|
||||
if (file.Is_Available() && file.Read(SpeechBuffer[_index], SPEECH_BUFFER_SIZE)) {
|
||||
speech = SpeechBuffer[_index];
|
||||
SpeechRecord[_index] = SpeakQueue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Since the speech file was loaded, play it.
|
||||
*/
|
||||
if (speech != NULL) {
|
||||
Play_Sample(speech, 254, Options.Volume * 256);
|
||||
CurrentVoice = SpeakQueue;
|
||||
}
|
||||
|
||||
SpeakQueue = VOX_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Stop_Speaking -- Forces the EVA voice to stop talking. *
|
||||
* *
|
||||
* Use this routine to immediately stop the EVA voice from speaking. It also clears out *
|
||||
* the pending voice queue. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/27/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void Stop_Speaking(void)
|
||||
{
|
||||
SpeakQueue = VOX_NONE;
|
||||
Stop_Sample_Playing(SpeechBuffer);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Is_Speaking -- Checks to see if the eva voice is still playing. *
|
||||
* *
|
||||
* Call this routine when the EVA voice being played needs to be checked. A typical use *
|
||||
* of this would be when some action needs to be delayed until the voice has finished -- *
|
||||
* say the end of the game. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Is the EVA voice still playing? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/12/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
bool Is_Speaking(void)
|
||||
{
|
||||
Speak_AI();
|
||||
if (!Debug_Quiet && SampleType != 0 && (SpeakQueue != VOX_NONE || Is_Sample_Playing(SpeechBuffer))) {
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
656
CODE/AUDIO.CPP.BAK
Normal file
656
CODE/AUDIO.CPP.BAK
Normal file
@ -0,0 +1,656 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: F:\projects\c&c0\vcs\code\audio.cpv 4.78 03 Oct 1996 09:20:46 JOE_BOSTIC $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : AUDIO.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : September 10, 1993 *
|
||||
* *
|
||||
* Last Update : September 15, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Is_Speaking -- Checks to see if the eva voice is still playing. *
|
||||
* Sound_Effect -- General purpose sound player. *
|
||||
* Sound_Effect -- Plays a sound effect in the tactical map. *
|
||||
* Speak -- Computer speaks to the player. *
|
||||
* Speak_AI -- Handles starting the EVA voices. *
|
||||
* Speech_Name -- Fetches the name for the voice specified. *
|
||||
* Stop_Speaking -- Forces the EVA voice to stop talking. *
|
||||
* Voc_From_Name -- Fetch VocType from ASCII name specified. *
|
||||
* Voc_Name -- Fetches the name for the sound effect. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Controls what special effects may occur on the sound effect.
|
||||
*/
|
||||
typedef enum {
|
||||
IN_NOVAR, // No variation or alterations allowed.
|
||||
IN_VAR // Infantry variance response modification.
|
||||
} ContextType;
|
||||
|
||||
static struct {
|
||||
char const * Name; // Digitized voice file name.
|
||||
int Priority; // Playback priority of this sample.
|
||||
ContextType Where; // In what game context does this sample exist.
|
||||
} SoundEffectName[VOC_COUNT] = {
|
||||
|
||||
/*
|
||||
** Civilian voices (technicians too).
|
||||
*/
|
||||
{"GIRLOKAY", 20, IN_NOVAR}, // VOC_GIRL_OKAY
|
||||
{"GIRLYEAH", 20, IN_NOVAR}, // VOC_GIRL_YEAH
|
||||
{"GUYOKAY1", 20, IN_NOVAR}, // VOC_GUY_OKAY
|
||||
{"GUYYEAH1", 20, IN_NOVAR}, // VOC_GUY_YEAH
|
||||
|
||||
{"MINELAY1", 5, IN_VAR}, // VOC_MINELAY1
|
||||
|
||||
/*
|
||||
** Infantry and vehicle responses.
|
||||
*/
|
||||
{"ACKNO", 20, IN_VAR}, // VOC_ACKNOWL "acknowledged"
|
||||
{"AFFIRM1", 20, IN_VAR}, // VOC_AFFIRM "affirmative"
|
||||
{"AWAIT1", 20, IN_VAR}, // VOC_AWAIT1 "awaiting orders"
|
||||
{"EAFFIRM1", 20, IN_NOVAR}, // VOC_ENG_AFFIRM Engineer: "affirmative"
|
||||
{"EENGIN1", 20, IN_VAR}, // VOC_ENG_ENG Engineer: "engineering"
|
||||
{"NOPROB", 20, IN_VAR}, // VOC_NO_PROB "not a problem"
|
||||
{"READY", 20, IN_VAR}, // VOC_READY "ready and waiting"
|
||||
{"REPORT1", 20, IN_VAR}, // VOC_REPORT "reporting"
|
||||
{"RITAWAY", 20, IN_VAR}, // VOC_RIGHT_AWAY "right away sir"
|
||||
{"ROGER", 20, IN_VAR}, // VOC_ROGER "roger"
|
||||
{"UGOTIT", 20, IN_VAR}, // VOC_UGOTIT "you got it"
|
||||
{"VEHIC1", 20, IN_VAR}, // VOC_VEHIC1 "vehicle reporting"
|
||||
{"YESSIR1", 20, IN_VAR}, // VOC_YESSIR "yes sir"
|
||||
|
||||
{"DEDMAN1", 10, IN_NOVAR}, // VOC_SCREAM1 short infantry scream
|
||||
{"DEDMAN2", 10, IN_NOVAR}, // VOC_SCREAM3 short infantry scream
|
||||
{"DEDMAN3", 10, IN_NOVAR}, // VOC_SCREAM4 short infantry scream
|
||||
{"DEDMAN4", 10, IN_NOVAR}, // VOC_SCREAM5 short infantry scream
|
||||
{"DEDMAN5", 10, IN_NOVAR}, // VOC_SCREAM6 short infantry scream
|
||||
{"DEDMAN6", 10, IN_NOVAR}, // VOC_SCREAM7 short infantry scream
|
||||
{"DEDMAN7", 10, IN_NOVAR}, // VOC_SCREAM10 short infantry scream
|
||||
{"DEDMAN8", 10, IN_NOVAR}, // VOC_SCREAM11 short infantry scream
|
||||
{"DEDMAN10", 10, IN_NOVAR}, // VOC_YELL1 long infantry scream
|
||||
|
||||
{"CHRONO2", 5, IN_NOVAR}, // VOC_CHRONO Chronosphere sound
|
||||
{"CANNON1", 1, IN_NOVAR}, // VOC_CANNON1 Cannon sound (medium).
|
||||
{"CANNON2", 1, IN_NOVAR}, // VOC_CANNON2 Cannon sound (short).
|
||||
{"IRONCUR1", 5, IN_NOVAR}, // VOC_IRON1
|
||||
{"EMOVOUT1", 20, IN_NOVAR}, // VOC_ENG_MOVEOUT Engineer: "movin' out"
|
||||
{"IRONCUR2", 5, IN_NOVAR}, // VOC_IRON2
|
||||
{"x", 1, IN_NOVAR},
|
||||
{"x", 1, IN_NOVAR},
|
||||
{"CHUTE1", 1, IN_NOVAR}, // VOC_CHUTE1 Wind swoosh sound.
|
||||
{"DOGY1", 5, IN_NOVAR}, // VOC_DOG_BARK Dog bark.
|
||||
{"DOGW5", 10, IN_NOVAR}, // VOC_DOG_WHINE Dog whine.
|
||||
{"DOGG5P", 10, IN_NOVAR}, // VOC_DOG_GROWL2 Strong dog growl.
|
||||
{"FIREBL3", 1, IN_NOVAR}, // VOC_FIRE_LAUNCH Fireball launch sound.
|
||||
{"FIRETRT1", 1, IN_NOVAR}, // VOC_FIRE_EXPLODE Fireball explode sound.
|
||||
{"GRENADE1", 1, IN_NOVAR}, // VOC_GRENADE_TOSS Grenade toss.
|
||||
{"GUN11", 1, IN_NOVAR}, // VOC_GUN_5 5 round gun burst (slow).
|
||||
{"GUN13", 1, IN_NOVAR}, // VOC_GUN_7 7 round gun burst (fast).
|
||||
{"EYESSIR1", 20, IN_NOVAR}, // VOC_ENG_YES, Engineer: "yes sir"
|
||||
{"GUN27", 1, IN_NOVAR}, // VOC_GUN_RIFLE Rifle shot.
|
||||
{"HEAL2", 1, IN_NOVAR}, // VOC_HEAL Healing effect.
|
||||
{"HYDROD1", 1, IN_NOVAR}, // VOC_DOOR Hyrdrolic door.
|
||||
{"INVUL2", 1, IN_NOVAR}, // VOC_INVULNERABLE Invulnerability effect.
|
||||
{"KABOOM1", 1, IN_NOVAR}, // VOC_KABOOM1 Long explosion (muffled).
|
||||
{"KABOOM12", 1, IN_NOVAR}, // VOC_KABOOM12 Very long explosion (muffled).
|
||||
{"KABOOM15", 1, IN_NOVAR}, // VOC_KABOOM15 Very long explosion (muffled).
|
||||
{"x", 1, IN_NOVAR},
|
||||
{"KABOOM22", 1, IN_NOVAR}, // VOC_KABOOM22 Long explosion (sharp).
|
||||
{"x", 1, IN_NOVAR},
|
||||
{"x", 1, IN_NOVAR},
|
||||
{"MGUNINF1", 1, IN_NOVAR}, // VOC_GUN_5F 5 round gun burst (fast).
|
||||
{"MISSILE1", 1, IN_NOVAR}, // VOC_MISSILE_1 Missile with high tech effect.
|
||||
{"MISSILE6", 1, IN_NOVAR}, // VOC_MISSILE_2 Long missile launch.
|
||||
{"MISSILE7", 1, IN_NOVAR}, // VOC_MISSILE_3 Short missile launch.
|
||||
{"x", 1, IN_NOVAR},
|
||||
{"PILLBOX1", 1, IN_NOVAR}, // VOC_GUN_5R 5 round gun burst (rattles).
|
||||
{"RABEEP1", 1, IN_NOVAR}, // VOC_BEEP Generic beep sound.
|
||||
{"RAMENU1", 1, IN_NOVAR}, // VOC_CLICK Generic click sound.
|
||||
{"SILENCER", 1, IN_NOVAR}, // VOC_SILENCER Silencer.
|
||||
{"TANK5", 1, IN_NOVAR}, // VOC_CANNON6 Long muffled cannon shot.
|
||||
{"TANK6", 1, IN_NOVAR}, // VOC_CANNON7 Sharp mechanical cannon fire.
|
||||
{"TORPEDO1", 1, IN_NOVAR}, // VOC_TORPEDO Torpedo launch.
|
||||
{"TURRET1", 1, IN_NOVAR}, // VOC_CANNON8 Sharp cannon fire.
|
||||
{"TSLACHG2", 10, IN_NOVAR}, // VOC_TESLA_POWER_UP Hum charge up.
|
||||
{"TESLA1", 10, IN_NOVAR}, // VOC_TESLA_ZAP Tesla zap effect.
|
||||
{"SQUISHY2", 10, IN_NOVAR}, // VOC_SQUISH Squish effect.
|
||||
{"SCOLDY1", 10, IN_NOVAR}, // VOC_SCOLD Scold bleep.
|
||||
{"RADARON2", 20, IN_NOVAR}, // VOC_RADAR_ON Powering up electronics.
|
||||
{"RADARDN1", 10, IN_NOVAR}, // VOC_RADAR_OFF B movie power down effect.
|
||||
{"PLACBLDG", 10, IN_NOVAR}, // VOC_PLACE_BUILDING_DOWN Building slam down sound.
|
||||
{"KABOOM30", 1, IN_NOVAR}, // VOC_KABOOM30 Short explosion (HE).
|
||||
{"KABOOM25", 10, IN_NOVAR}, // VOC_KABOOM25 Short growling explosion.
|
||||
{"x", 10, IN_NOVAR},
|
||||
{"DOGW7", 10, IN_NOVAR}, // VOC_DOG_HURT Dog whine (loud).
|
||||
{"DOGW3PX", 10, IN_NOVAR}, // VOC_DOG_YES Dog 'yes sir'.
|
||||
{"CRMBLE2", 10, IN_NOVAR}, // VOC_CRUMBLE Building crumble.
|
||||
{"CASHUP1", 10, IN_NOVAR}, // VOC_MONEY_UP Rising money tick.
|
||||
{"CASHDN1", 10, IN_NOVAR}, // VOC_MONEY_DOWN Falling money tick.
|
||||
{"BUILD5", 10, IN_NOVAR}, // VOC_CONSTRUCTION Building construction sound.
|
||||
{"BLEEP9", 10, IN_NOVAR}, // VOC_GAME_CLOSED Long bleep.
|
||||
{"BLEEP6", 10, IN_NOVAR}, // VOC_INCOMING_MESSAGE Soft happy warble.
|
||||
{"BLEEP5", 10, IN_NOVAR}, // VOC_SYS_ERROR Sharp soft warble.
|
||||
{"BLEEP17", 10, IN_NOVAR}, // VOC_OPTIONS_CHANGED Mid range soft warble.
|
||||
{"BLEEP13", 10, IN_NOVAR}, // VOC_GAME_FORMING Long warble.
|
||||
{"BLEEP12", 10, IN_NOVAR}, // VOC_PLAYER_LEFT Chirp sequence.
|
||||
{"BLEEP11", 10, IN_NOVAR}, // VOC_PLAYER_JOINED Reverse chirp sequence.
|
||||
{"H2OBOMB2", 10, IN_NOVAR}, // VOC_DEPTH_CHARGE Distant explosion sound.
|
||||
{"CASHTURN", 10, IN_NOVAR}, // VOC_CASHTURN Airbrake.
|
||||
{"TUFFGUY1", 20, IN_NOVAR}, // VOC_TANYA_CHEW Tanya: "Chew on this"
|
||||
{"ROKROLL1", 20, IN_NOVAR}, // VOC_TANYA_ROCK Tanya: "Let's rock"
|
||||
{"LAUGH1", 20, IN_NOVAR}, // VOC_TANYA_LAUGH Tanya: "ha ha ha"
|
||||
{"CMON1", 20, IN_NOVAR}, // VOC_TANYA_SHAKE Tanya: "Shake it baby"
|
||||
{"BOMBIT1", 20, IN_NOVAR}, // VOC_TANYA_CHING Tanya: "Cha Ching"
|
||||
{"GOTIT1", 20, IN_NOVAR}, // VOC_TANYA_GOT Tanya: "That's all you got"
|
||||
{"KEEPEM1", 20, IN_NOVAR}, // VOC_TANYA_KISS Tanya: "Kiss it bye bye"
|
||||
{"ONIT1", 20, IN_NOVAR}, // VOC_TANYA_THERE Tanya: "I'm there"
|
||||
{"LEFTY1", 20, IN_NOVAR}, // VOC_TANYA_GIVE Tanya: "Give it to me"
|
||||
{"YEAH1", 20, IN_NOVAR}, // VOC_TANYA_YEA Tanya: "Yea?"
|
||||
{"YES1", 20, IN_NOVAR}, // VOC_TANYA_YES Tanya: "Yes sir?"
|
||||
{"YO1", 20, IN_NOVAR}, // VOC_TANYA_WHATS Tanya: "What's up."
|
||||
{"WALLKIL2", 5, IN_NOVAR}, // VOC_WALLKILL2 Crushing wall sound.
|
||||
{"x", 10, IN_NOVAR},
|
||||
{"GUN5", 5, IN_NOVAR}, // VOC_TRIPLE_SHOT Three quick shots in succession.
|
||||
{"SUBSHOW1", 5, IN_NOVAR}, // VOC_SUBSHOW Submarine surface sound.
|
||||
{"EINAH1", 20, IN_NOVAR}, // VOC_E_AH, Einstien "ah"
|
||||
{"EINOK1", 20, IN_NOVAR}, // VOC_E_OK, Einstien "ok"
|
||||
{"EINYES1", 20, IN_NOVAR}, // VOC_E_YES, Einstien "yes"
|
||||
{"MINE1", 10, IN_NOVAR}, // VOC_TRIP_MINE mine explosion sound
|
||||
|
||||
{"SCOMND1", 20, IN_NOVAR}, // VOC_SPY_COMMANDER Spy: "commander?"
|
||||
{"SYESSIR1", 20, IN_NOVAR}, // VOC_SPY_YESSIR Spy: "yes sir"
|
||||
{"SINDEED1", 20, IN_NOVAR}, // VOC_SPY_INDEED Spy: "indeed"
|
||||
{"SONWAY1", 20, IN_NOVAR}, // VOC_SPY_ONWAY Spy: "on my way"
|
||||
{"SKING1", 20, IN_NOVAR}, // VOC_SPY_KING Spy: "for king and country"
|
||||
{"MRESPON1", 20, IN_NOVAR}, // VOC_MED_REPORTING Medic: "reporting"
|
||||
{"MYESSIR1", 20, IN_NOVAR}, // VOC_MED_YESSIR Medic: "yes sir"
|
||||
{"MAFFIRM1", 20, IN_NOVAR}, // VOC_MED_AFFIRM Medic: "affirmative"
|
||||
{"MMOVOUT1", 20, IN_NOVAR}, // VOC_MED_MOVEOUT Medic: "movin' out"
|
||||
{"BEEPSLCT", 10, IN_NOVAR}, // VOC_BEEP_SELECT map selection beep
|
||||
|
||||
{"SYEAH1", 20, IN_NOVAR}, // VOC_THIEF_YEA Thief: "yea?"
|
||||
{"x", 20, IN_NOVAR},
|
||||
{"x", 20, IN_NOVAR},
|
||||
{"SMOUT1", 20, IN_NOVAR}, // VOC_THIEF_MOVEOUT Thief: "movin' out"
|
||||
{"SOKAY1", 20, IN_NOVAR}, // VOC_THIEF_OKAY Thief: "ok"
|
||||
{"x", 20, IN_NOVAR},
|
||||
{"SWHAT1", 20, IN_NOVAR}, // VOC_THIEF_WHAT Thief: "what"
|
||||
{"SAFFIRM1", 20, IN_NOVAR}, // VOC_THIEF_AFFIRM Thief: "affirmative"
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Voc_From_Name -- Fetch VocType from ASCII name specified. *
|
||||
* *
|
||||
* This will find the corresponding VocType from the ASCII string specified. It does this *
|
||||
* by finding a root filename that matches the string. *
|
||||
* *
|
||||
* INPUT: name -- Pointer to the ASCII string that will be converted into a VocType. *
|
||||
* *
|
||||
* OUTPUT: Returns with the VocType that matches the string specified. If no match could be *
|
||||
* found, then VOC_NONE is returned. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
VocType Voc_From_Name(char const * name)
|
||||
{
|
||||
#ifdef 0
|
||||
if (name == NULL) return(VOC_NONE);
|
||||
|
||||
for (VocType voc = VOC_FIRST; voc < VOC_COUNT; voc++) {
|
||||
if (stricmp(name, SoundEffectName[voc].Name) == 0) {
|
||||
return(voc);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return(VOC_NONE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Voc_Name -- Fetches the name for the sound effect. *
|
||||
* *
|
||||
* This routine returns the descriptive name of the sound effect. Currently, this is just *
|
||||
* the root of the file name. *
|
||||
* *
|
||||
* INPUT: voc -- The VocType that the corresponding name is requested. *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to the text string the represents the sound effect. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
char const * Voc_Name(VocType voc)
|
||||
{
|
||||
if (voc == VOC_NONE) return("none");
|
||||
return(SoundEffectName[voc].Name);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Sound_Effect -- Plays a sound effect in the tactical map. *
|
||||
* *
|
||||
* This routine is used when a sound effect occurs in the game world. It handles fading *
|
||||
* the sound according to distance. *
|
||||
* *
|
||||
* INPUT: voc -- The sound effect number to play. *
|
||||
* *
|
||||
* coord -- The world location that the sound originates from. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/12/1994 JLB : Created. *
|
||||
* 01/05/1995 JLB : Reduces sound more dramatically when off screen. *
|
||||
* 09/15/1996 JLB : Revamped volume logic. *
|
||||
*=============================================================================================*/
|
||||
void Sound_Effect(VocType voc, COORDINATE coord, int variation)
|
||||
{
|
||||
#ifdef 0
|
||||
CELL cell_pos = 0;
|
||||
int pan_value;
|
||||
|
||||
if (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {
|
||||
return;
|
||||
}
|
||||
if (coord) {
|
||||
cell_pos = Coord_Cell(coord);
|
||||
}
|
||||
|
||||
fixed volume = 1;
|
||||
pan_value = 0;
|
||||
if (coord && !Map.In_View(cell_pos)) {
|
||||
int distance = Distance(coord, Map.TacticalCoord) / CELL_LEPTON_W;
|
||||
fixed dfixed = fixed(distance, 128+64);
|
||||
dfixed.Sub_Saturate(1);
|
||||
volume = fixed(1) - dfixed;
|
||||
|
||||
pan_value = Cell_X(cell_pos);
|
||||
pan_value -= Coord_XCell(Map.TacticalCoord) + (Lepton_To_Cell(Map.TacLeptonWidth) / 2);
|
||||
if (ABS(pan_value) > Lepton_To_Cell(Map.TacLeptonWidth / 2)) {
|
||||
pan_value *= 0x8000;
|
||||
pan_value /= (MAP_CELL_W >> 2);
|
||||
pan_value = Bound(pan_value, -0x7FFF, 0x7FFF);
|
||||
} else {
|
||||
pan_value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Sound_Effect(voc, volume, variation, pan_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Sound_Effect -- General purpose sound player. *
|
||||
* *
|
||||
* This is used for general purpose sound effects. These are sounds that occur outside *
|
||||
* of the game world. They do not have a corresponding game world location as their source. *
|
||||
* *
|
||||
* INPUT: voc -- The sound effect number to play. *
|
||||
* *
|
||||
* volume -- The volume to assign to this sound effect. *
|
||||
* *
|
||||
* OUTPUT: Returns with the sound handle (-1 if no sound was played). *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/12/1994 JLB : Created. *
|
||||
* 11/12/1994 JLB : Handles cache logic. *
|
||||
* 05/04/1995 JLB : Variation adjustments. *
|
||||
*=============================================================================================*/
|
||||
int Sound_Effect(VocType voc, fixed volume, int variation, signed short pan_value)
|
||||
{
|
||||
#ifdef 0
|
||||
char name[_MAX_FNAME+_MAX_EXT]; // Working filename of sound effect.
|
||||
|
||||
if (Debug_Quiet || Options.Volume == 0 || voc == VOC_NONE || !SoundOn || SampleType == SAMPLE_NONE) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Alter the volume according to the game volume setting.
|
||||
*/
|
||||
volume = volume * Options.Volume;
|
||||
|
||||
/*
|
||||
** Fetch a pointer to the sound effect data. Modify the sound as appropriate and desired.
|
||||
*/
|
||||
char const * ext = ".AUD";
|
||||
if (SoundEffectName[voc].Where == IN_VAR) {
|
||||
|
||||
/*
|
||||
** For infantry, use a variation on the response. For vehicles, always
|
||||
** use the vehicle response table.
|
||||
*/
|
||||
if (variation < 0) {
|
||||
if (ABS(variation) % 2) {
|
||||
ext = ".V00";
|
||||
} else {
|
||||
ext = ".V02";
|
||||
}
|
||||
} else {
|
||||
if (variation % 2) {
|
||||
ext = ".V01";
|
||||
} else {
|
||||
ext = ".V03";
|
||||
}
|
||||
}
|
||||
}
|
||||
_makepath(name, NULL, NULL, SoundEffectName[voc].Name, ext);
|
||||
void const * ptr = MFCD::Retrieve(name);
|
||||
|
||||
/*
|
||||
** If the sound data pointer is not null, then presume that it is valid.
|
||||
*/
|
||||
if (ptr != NULL) {
|
||||
volume.Sub_Saturate(1);
|
||||
return(Play_Sample(ptr, SoundEffectName[voc].Priority * volume, volume*256, pan_value));
|
||||
// } else {
|
||||
// Mono_Printf("Cannot find '%s'.\n", name);
|
||||
}
|
||||
#endif
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This elaborates all the EVA speech voices.
|
||||
*/
|
||||
static char const * Speech[VOX_COUNT] = {
|
||||
"MISNWON1", // VOX_ACCOMPLISHED mission accomplished
|
||||
"MISNLST1", // VOX_FAIL your mission has failed
|
||||
"PROGRES1", // VOX_NO_FACTORY unable to comply, building in progress
|
||||
"CONSCMP1", // VOX_CONSTRUCTION construction complete
|
||||
"UNITRDY1", // VOX_UNIT_READY unit ready
|
||||
"NEWOPT1", // VOX_NEW_CONSTRUCT new construction options
|
||||
"NODEPLY1", // VOX_DEPLOY cannot deploy here
|
||||
"STRCKIL1", // VOX_STRUCTURE_DESTROYED, structure destroyed
|
||||
"NOPOWR1", // VOX_INSUFFICIENT_POWER, insufficient power
|
||||
"NOFUNDS1", // VOX_NO_CASH insufficient funds
|
||||
"BCT1", // VOX_CONTROL_EXIT battle control terminated
|
||||
"REINFOR1", // VOX_REINFORCEMENTS reinforcements have arrived
|
||||
"CANCLD1", // VOX_CANCELED canceled
|
||||
"ABLDGIN1", // VOX_BUILDING building
|
||||
"LOPOWER1", // VOX_LOW_POWER low power
|
||||
"NOFUNDS1", // VOX_NEED_MO_MONEY insufficent funds
|
||||
"BASEATK1", // VOX_BASE_UNDER_ATTACK our base is under attack
|
||||
"NOBUILD1", // VOX_UNABLE_TO_BUILD unable to build more
|
||||
"PRIBLDG1", // VOX_PRIMARY_SELECTED primary building selected
|
||||
"none",
|
||||
"none", // VOX_SOVIET_CAPTURED Allied building captured
|
||||
"UNITLST1", // VOX_UNIT_LOST unit lost
|
||||
"SLCTTGT1", // VOX_SELECT_TARGET select target
|
||||
"ENMYAPP1", // VOX_PREPARE enemy approaching
|
||||
"SILOND1", // VOX_NEED_MO_CAPACITY silos needed
|
||||
"ONHOLD1", // VOX_SUSPENDED on hold
|
||||
"REPAIR1", // VOX_REPAIRING repairing
|
||||
"none",
|
||||
"none",
|
||||
"AUNITL1", // VOX_AIRCRAFT_LOST airborne unit lost
|
||||
"none",
|
||||
"AAPPRO1", // VOX_ALLIED_FORCES_APPROACHING allied forces approaching
|
||||
"AARRIVE1", // VOX_ALLIED_APPROACHING allied reinforcements have arrived
|
||||
"none",
|
||||
"none",
|
||||
"BLDGINF1", // VOX_BUILDING_INFILTRATED building infiltrated
|
||||
"CHROCHR1", // VOX_CHRONO_CHARGING chronosphere charging
|
||||
"CHRORDY1", // VOX_CHRONO_READY chronosphere ready
|
||||
"CHROYES1", // VOX_CHRONO_TEST chronosphere test successful
|
||||
"CMDCNTR1", // VOX_HQ_UNDER_ATTACK command center under attack
|
||||
"CNTLDED1", // VOX_CENTER_DEACTIVATED control center deactivated
|
||||
"CONVYAP1", // VOX_CONVOY_APPROACHING convoy approaching
|
||||
"CONVLST1", // VOX_CONVOY_UNIT_LOST convoy unit lost
|
||||
"XPLOPLC1", // VOX_EXPLOSIVE_PLACED explosive charge placed
|
||||
"CREDIT1", // VOX_MONEY_STOLEN credits stolen
|
||||
"NAVYLST1", // VOX_SHIP_LOST naval unit lost
|
||||
"SATLNCH1", // VOX_SATALITE_LAUNCHED satalite launched
|
||||
"PULSE1", // VOX_SONAR_AVAILABLE sonar pulse available
|
||||
"none",
|
||||
"SOVFAPP1", // VOX_SOVIET_FORCES_APPROACHING soviet forces approaching
|
||||
"SOVREIN1", // VOX_SOVIET_REINFROCEMENTS soviet reinforcements have arrived
|
||||
"TRAIN1", // VOX_TRAINING training
|
||||
"AREADY1", // VOX_ABOMB_READY
|
||||
"ALAUNCH1", // VOX_ABOMB_LAUNCH
|
||||
"AARRIVN1", // VOX_ALLIES_N
|
||||
"AARRIVS1", // VOX_ALLIES_S
|
||||
"AARIVE1", // VOX_ALLIES_E
|
||||
"AARRIVW1", // VOX_ALLIES_W
|
||||
"1OBJMET1", // VOX_OBJECTIVE1
|
||||
"2OBJMET1", // VOX_OBJECTIVE2
|
||||
"3OBJMET1", // VOX_OBJECTIVE3
|
||||
"IRONCHG1", // VOX_IRON_CHARGING
|
||||
"IRONRDY1", // VOX_IRON_READY
|
||||
"KOSYRES1", // VOX_RESCUED
|
||||
"OBJNMET1", // VOX_OBJECTIVE_NOT
|
||||
"FLAREN1", // VOX_SIGNAL_N
|
||||
"FLARES1", // VOX_SIGNAL_S
|
||||
"FLAREE1", // VOX_SIGNAL_E
|
||||
"FLAREW1", // VOX_SIGNAL_W
|
||||
"SPYPLN1", // VOX_SPY_PLANE
|
||||
"TANYAF1", // VOX_FREED
|
||||
"ARMORUP1", // VOX_UPGRADE_ARMOR
|
||||
"FIREPO1", // VOX_UPGRADE_FIREPOWER
|
||||
"UNITSPD1", // VOX_UPGRADE_SPEED
|
||||
"MTIMEIN1", // VOX_MISSION_TIMER
|
||||
"UNITFUL1", // VOX_UNIT_FULL
|
||||
"UNITREP1", // VOX_UNIT_REPAIRED
|
||||
"40MINR", // VOX_TIME_40
|
||||
"30MINR", // VOX_TIME_30
|
||||
"20MINR", // VOX_TIME_20
|
||||
"10MINR", // VOX_TIME_10
|
||||
"5MINR", // VOX_TIME_5
|
||||
"4MINR", // VOX_TIME_4
|
||||
"3MINR", // VOX_TIME_3
|
||||
"2MINR", // VOX_TIME_2
|
||||
"1MINR", // VOX_TIME_1
|
||||
"TIMERNO1", // VOX_TIME_STOP
|
||||
"UNITSLD1", // VOX_UNIT_SOLD
|
||||
"TIMERGO1", // VOX_TIMER_STARTED
|
||||
"TARGRES1", // VOX_TARGET_RESCUED
|
||||
"TARGFRE1", // VOX_TARGET_FREED
|
||||
"TANYAR1", // VOX_TANYA_RESCUED
|
||||
"STRUSLD1", // VOX_STRUCTURE_SOLD
|
||||
"SOVFORC1", // VOX_SOVIET_FORCES_FALLEN
|
||||
"SOVEMP1", // VOX_SOVIET_SELECTED
|
||||
"SOVEFAL1", // VOX_SOVIET_EMPIRE_FALLEN
|
||||
"OPTERM1", // VOX_OPERATION_TERMINATED
|
||||
"OBJRCH1", // VOX_OBJECTIVE_REACHED
|
||||
"OBJNRCH1", // VOX_OBJECTIVE_NOT_REACHED
|
||||
"OBJMET1", // VOX_OBJECTIVE_MET
|
||||
"MERCR1", // VOX_MERCENARY_RESCUED
|
||||
"MERCF1", // VOX_MERCENARY_FREED
|
||||
"KOSYFRE1", // VOX_KOSOYGEN_FREED
|
||||
"FLARE1", // VOX_FLARE_DETECTED
|
||||
"COMNDOR1", // VOX_COMMANDO_RESCUED
|
||||
"COMNDOF1", // VOX_COMMANDO_FREED
|
||||
"BLDGPRG1", // VOX_BUILDING_IN_PROGRESS
|
||||
"ATPREP1", // VOX_ATOM_PREPPING
|
||||
"ASELECT1", // VOX_ALLIED_SELECTED
|
||||
"APREP1", // VOX_ABOMB_PREPPING
|
||||
"ATLNCH1", // VOX_ATOM_LAUNCHED
|
||||
"AFALLEN1", // VOX_ALLIED_FORCES_FALLEN
|
||||
"AAVAIL1", // VOX_ABOMB_AVAILABLE
|
||||
"AARRIVE1", // VOX_ALLIED_REINFORCEMENTS
|
||||
"SAVE1", // VOX_MISSION_SAVED
|
||||
"LOAD1" // VOX_MISSION_LOADED
|
||||
};
|
||||
|
||||
|
||||
static VoxType CurrentVoice = VOX_NONE;
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Speech_Name -- Fetches the name for the voice specified. *
|
||||
* *
|
||||
* Use this routine to fetch the ASCII name of the speech id specified. Typical use of this *
|
||||
* would be to build a displayable list of the speech types. The trigger system uses this *
|
||||
* so that a speech type can be selected. *
|
||||
* *
|
||||
* INPUT: speech -- The speech type id to convert to ASCII string. *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to the speech ASCII representation of the speech id type. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/01/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
char const * Speech_Name(VoxType speech)
|
||||
{
|
||||
if (speech == VOX_NONE) return("none");
|
||||
return(Speech[speech]);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Speak -- Computer speaks to the player. *
|
||||
* *
|
||||
* This routine is used to have the game computer (EVA) speak to the player. *
|
||||
* *
|
||||
* INPUT: voice -- The voice number to speak (see defines.h). *
|
||||
* *
|
||||
* OUTPUT: Returns with the handle of the playing speech (-1 if no voice started). *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/12/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void Speak(VoxType voice)
|
||||
{
|
||||
if (!Debug_Quiet && Options.Volume != 0 && SampleType != 0 && voice != VOX_NONE && voice != SpeakQueue && voice != CurrentVoice && SpeakQueue == VOX_NONE) {
|
||||
SpeakQueue = voice;
|
||||
Speak_AI();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Speak_AI -- Handles starting the EVA voices. *
|
||||
* *
|
||||
* This starts the EVA voice talking as well. If there is any speech request in the queue, *
|
||||
* it will be started when the current voice is finished. Call this routine as often as *
|
||||
* possible (once per game tick is sufficient). *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/27/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void Speak_AI(void)
|
||||
{
|
||||
static VoxType _last = VOX_NONE;
|
||||
if (Debug_Quiet || SampleType == 0) return;
|
||||
|
||||
if (!Is_Sample_Playing(SpeechBuffer)) {
|
||||
CurrentVoice = VOX_NONE;
|
||||
if (SpeakQueue != VOX_NONE) {
|
||||
if (SpeakQueue != _last) {
|
||||
char name[_MAX_FNAME+_MAX_EXT];
|
||||
|
||||
_makepath(name, NULL, NULL, Speech[SpeakQueue], ".AUD");
|
||||
CCFileClass file(name);
|
||||
if (file.Is_Available() && file.Read(SpeechBuffer, SPEECH_BUFFER_SIZE)) {
|
||||
Play_Sample(SpeechBuffer, 254, Options.Volume * 256);
|
||||
CurrentVoice = SpeakQueue;
|
||||
}
|
||||
_last = SpeakQueue;
|
||||
} else {
|
||||
Play_Sample(SpeechBuffer, 254, Options.Volume * 256);
|
||||
}
|
||||
SpeakQueue = VOX_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Stop_Speaking -- Forces the EVA voice to stop talking. *
|
||||
* *
|
||||
* Use this routine to immediately stop the EVA voice from speaking. It also clears out *
|
||||
* the pending voice queue. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/27/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void Stop_Speaking(void)
|
||||
{
|
||||
SpeakQueue = VOX_NONE;
|
||||
Stop_Sample_Playing(SpeechBuffer);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Is_Speaking -- Checks to see if the eva voice is still playing. *
|
||||
* *
|
||||
* Call this routine when the EVA voice being played needs to be checked. A typical use *
|
||||
* of this would be when some action needs to be delayed until the voice has finished -- *
|
||||
* say the end of the game. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Is the EVA voice still playing? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/12/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
bool Is_Speaking(void)
|
||||
{
|
||||
Speak_AI();
|
||||
if (!Debug_Quiet && SampleType != 0 && (SpeakQueue != VOX_NONE || Is_Sample_Playing(SpeechBuffer))) {
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
99
CODE/AUDIO.H
Normal file
99
CODE/AUDIO.H
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: F:\projects\c&c0\vcs\code\audio.h_v 4.43 05 Jul 1996 17:58:10 JOE_BOSTIC $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : AUDIO.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : June 21, 1994 *
|
||||
* *
|
||||
* Last Update : June 21, 1994 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
class AudioClass {
|
||||
char const * Name; // Name of audio asset.
|
||||
void const * Data; // Loaded audio data.
|
||||
int Handle; // Handle of asset (as it is playing).
|
||||
MemoryClass *Mem; // Pointer to memory handler class.
|
||||
unsigned IsMIDI:1; // Is this a midi file?
|
||||
|
||||
public:
|
||||
AudioClass(void);
|
||||
AudioClass(char const *name, MemoryClass &mem);
|
||||
virtual ~AudioClass(void);
|
||||
|
||||
bool Load(char const *name = 0);
|
||||
bool Free(void);
|
||||
bool Play(int volume = 0xFF);
|
||||
bool Stop(void);
|
||||
bool Pause(void);
|
||||
bool Resume(void);
|
||||
bool Set_Name(char const *name);
|
||||
bool Is_Playing(void) const;
|
||||
bool Is_Loaded(void) const;
|
||||
bool Is_MIDI(void) const;
|
||||
};
|
||||
|
||||
inline AudioClass::AudioClass(void)
|
||||
{
|
||||
Name = 0;
|
||||
Data = 0;
|
||||
Mem = 0;
|
||||
Handle = -1;
|
||||
};
|
||||
|
||||
inline AudioClass::AudioClass(char const *name, MemoryClass &mem)
|
||||
{
|
||||
if (mem) {
|
||||
Mem = &mem;
|
||||
} else {
|
||||
Mem = &::Mem; // Uses global default memory handler.
|
||||
}
|
||||
Name = strdup(name);
|
||||
Data = 0;
|
||||
Handle = -1;
|
||||
};
|
||||
|
||||
inline AudioClass::~AudioClass(void)
|
||||
{
|
||||
if (GameActive) {
|
||||
if (Name) free(Name);
|
||||
if (Data) Mem->Free(Data);
|
||||
Name = 0;
|
||||
Data = 0;
|
||||
Handle = -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
165
CODE/B64PIPE.CPP
Normal file
165
CODE/B64PIPE.CPP
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/B64PIPE.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : B64PIPE.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 06/30/96 *
|
||||
* *
|
||||
* Last Update : July 3, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Base64Pipe::Put -- Processes a block of data through the pipe. *
|
||||
* Base64Pipe::Flush -- Flushes the final pending data through the pipe. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
|
92
CODE/B64PIPE.H
Normal file
92
CODE/B64PIPE.H
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/B64PIPE.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : B64PIPE.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 06/30/96 *
|
||||
* *
|
||||
* Last Update : June 30, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#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
|
117
CODE/B64STRAW.CPP
Normal file
117
CODE/B64STRAW.CPP
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/B64STRAW.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : B64STRAW.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 07/02/96 *
|
||||
* *
|
||||
* Last Update : July 3, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Base64Straw::Get -- Fetch data and convert it to/from base 64 encoding. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#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);
|
||||
}
|
91
CODE/B64STRAW.H
Normal file
91
CODE/B64STRAW.H
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/B64STRAW.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : B64STRAW.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 07/02/96 *
|
||||
* *
|
||||
* Last Update : July 2, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#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
|
239
CODE/BAR.CPP
Normal file
239
CODE/BAR.CPP
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BAR.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BAR.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 08/16/96 *
|
||||
* *
|
||||
* Last Update : August 16, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* ProgressBarClass::Is_Horizontal -- Determines if the bargraph is horizontal or not. *
|
||||
* ProgressBarClass::Outline -- Draw an outline around the bargraph if supposed to. *
|
||||
* ProgressBarClass::ProgressBarClass -- Constructor for the bargraph object. *
|
||||
* ProgressBarClass::Redraw -- Redraw the bargraph. *
|
||||
* ProgressBarClass::Set_Limit -- Set the logic tracking value. *
|
||||
* ProgressBarClass::Update -- Update the value and redraw as necessary. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
#include "bar.h"
|
||||
#include "fixed.h"
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ProgressBarClass::ProgressBarClass -- Constructor for the bargraph object. *
|
||||
* *
|
||||
* This is the constructor for the bargraph object. It establishes the dimensions and *
|
||||
* coordinate of the bargraph as well as the colors it will use when drawn. *
|
||||
* *
|
||||
* INPUT: w,y -- Pixel coordinate of the upper left corner of the bargraph. *
|
||||
* *
|
||||
* width,height -- Dimensions of the bargraph. *
|
||||
* *
|
||||
* forecolor -- The color to use for the filled portion of the bargraph. *
|
||||
* *
|
||||
* backcolor -- The color to use for the non-filled portion of the bargraph. *
|
||||
* *
|
||||
* bordercolor -- Optional border color. If not zero, then the bargraph will be *
|
||||
* outlined with this color. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/16/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
ProgressBarClass::ProgressBarClass(int x, int y, int width, int height, int forecolor, int backcolor, int bordercolor) :
|
||||
X(x),
|
||||
Y(y),
|
||||
Width(width),
|
||||
Height(height),
|
||||
BarColor(forecolor),
|
||||
BackColor(backcolor),
|
||||
BorderColor(bordercolor),
|
||||
CurrentValue(0),
|
||||
LastDisplayCurrent(0),
|
||||
IsDrawn(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ProgressBarClass::Is_Horizontal -- Determines if the bargraph is horizontal or not. *
|
||||
* *
|
||||
* If the bargraph is oriented horizontally, then this function will return TRUE. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Is this bargraph horizontal? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/16/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
bool ProgressBarClass::Is_Horizontal(void) const
|
||||
{
|
||||
if (Width > Height) return(true);
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ProgressBarClass::Update -- Update the value and redraw as necessary. *
|
||||
* *
|
||||
* This will update the value of the bargraph to the fill ratio specified and then *
|
||||
* redraw it if required. Very small changes to the bargraph value might not result in a *
|
||||
* visual change. *
|
||||
* *
|
||||
* INPUT: value -- The new value to assign to this bargraph. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: bool; Did this update result in a redraw? *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/16/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
bool ProgressBarClass::Update(fixed value)
|
||||
{
|
||||
CurrentValue = value;
|
||||
|
||||
if (!IsDrawn || value - LastDisplayCurrent >= fixed(1, 10)) {
|
||||
Redraw();
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ProgressBarClass::Outline -- Draw an outline around the bargraph if supposed to. *
|
||||
* *
|
||||
* This routine will draw a border around the bargraph if this bargraph has a color *
|
||||
* specified for the border. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/16/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void ProgressBarClass::Outline(void) const
|
||||
{
|
||||
if (Is_Outlined()) {
|
||||
LogicPage->Draw_Line(X, Y, X+Width, Y, BorderColor);
|
||||
LogicPage->Draw_Line(X, Y, X, Y+Height, BorderColor);
|
||||
LogicPage->Draw_Line(X, Y+Height, X, Y+Height, BorderColor);
|
||||
LogicPage->Draw_Line(X+Width, Y, X+Width, Y+Height, BorderColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ProgressBarClass::Redraw -- Redraw the bargraph. *
|
||||
* *
|
||||
* This will redraw the entire bargraph. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/16/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void ProgressBarClass::Redraw(void) const
|
||||
{
|
||||
Hide_Mouse();
|
||||
|
||||
Outline();
|
||||
|
||||
/*
|
||||
** Determine the inner dimensions of the bargraph. This will be
|
||||
** somewhat smaller than indicated if it has a border.
|
||||
*/
|
||||
int x = X;
|
||||
int y = Y;
|
||||
int w = Width;
|
||||
int h = Height;
|
||||
if (Is_Outlined()) {
|
||||
x += 1;
|
||||
y += 1;
|
||||
w -= 2;
|
||||
h -= 2;
|
||||
}
|
||||
|
||||
/*
|
||||
** The working "length" of the bargraph is dependant on whether the
|
||||
** bargraph is horizontal or vertical.
|
||||
*/
|
||||
int size = Is_Horizontal() ? w : h;
|
||||
|
||||
/*
|
||||
** Determine the number of pixels to fill in the bargraph depending on the
|
||||
** size of the internal value. The larger the internal value the more
|
||||
** filled the bargraph becomes.
|
||||
*/
|
||||
int fill = CurrentValue * size;
|
||||
|
||||
/*
|
||||
** Draw the filled portion of the bargraph if there is any pixels to draw.
|
||||
*/
|
||||
if (fill > 0) {
|
||||
if (Is_Horizontal()) {
|
||||
LogicPage->Fill_Rect(x, y, x+fill, y+h, BarColor);
|
||||
} else {
|
||||
LogicPage->Fill_Rect(x, y+fill, x+w, y+h, BarColor);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Draw the unfilled portion of the bargraph if there are any pixels to
|
||||
** draw of it.
|
||||
*/
|
||||
if (w-fill > 0) {
|
||||
if (Is_Horizontal()) {
|
||||
LogicPage->Fill_Rect(x+fill, y, x+w, y+h, BackColor);
|
||||
} else {
|
||||
LogicPage->Fill_Rect(x, y, x+w, y+fill-1, BackColor);
|
||||
}
|
||||
}
|
||||
|
||||
Show_Mouse();
|
||||
|
||||
ProgressBarClass * me = (ProgressBarClass *)this;
|
||||
me->LastDisplayCurrent = CurrentValue;
|
||||
me->IsDrawn = true;
|
||||
}
|
111
CODE/BAR.H
Normal file
111
CODE/BAR.H
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BAR.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BAR.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 08/16/96 *
|
||||
* *
|
||||
* Last Update : August 16, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef BAR_H
|
||||
#define BAR_H
|
||||
|
||||
/*
|
||||
** The "bool" integral type was defined by the C++ committee in
|
||||
** November of '94. Until the compiler supports this, use the following
|
||||
** definition.
|
||||
*/
|
||||
#ifndef __BORLANDC__
|
||||
#ifndef TRUE_FALSE_DEFINED
|
||||
#define TRUE_FALSE_DEFINED
|
||||
enum {false=0,true=1};
|
||||
typedef int bool;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "fixed.h"
|
||||
|
||||
|
||||
/*
|
||||
** This is a manager for a progress (or other) bargraph. Such a graph consists of a fill
|
||||
** and a background region. The fill percentage of the bargraph is controlled by an
|
||||
** update value. The bargraph can be optionally outlined.
|
||||
*/
|
||||
class ProgressBarClass
|
||||
{
|
||||
public:
|
||||
ProgressBarClass(int x, int y, int width, int height, int forecolor, int backcolor, int bordercolor=0);
|
||||
|
||||
bool Update(fixed value);
|
||||
void Redraw(void) const;
|
||||
|
||||
private:
|
||||
|
||||
void Outline(void) const;
|
||||
bool Is_Horizontal(void) const;
|
||||
bool Is_Outlined(void) const {return(BorderColor != 0);}
|
||||
|
||||
/*
|
||||
** This is the upper left coordinates of the bargraph.
|
||||
*/
|
||||
int X,Y;
|
||||
|
||||
/*
|
||||
** This is the dimensions of the bargraph.
|
||||
*/
|
||||
int Width, Height;
|
||||
|
||||
/*
|
||||
** These are the colors to use when drawing the progress bar.
|
||||
*/
|
||||
int BarColor;
|
||||
int BackColor;
|
||||
int BorderColor;
|
||||
|
||||
/*
|
||||
** This is the current value of the bargraph.
|
||||
*/
|
||||
fixed CurrentValue;
|
||||
|
||||
/*
|
||||
** This is the current value as of the last time the bargraph was rendered.
|
||||
*/
|
||||
fixed LastDisplayCurrent;
|
||||
|
||||
/*
|
||||
** If the bargraph has been drawn at least once, then this flag will
|
||||
** be true.
|
||||
*/
|
||||
unsigned IsDrawn:1;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
548
CODE/BASE.CPP
Normal file
548
CODE/BASE.CPP
Normal file
@ -0,0 +1,548 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BASE.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BASE.CPP *
|
||||
* *
|
||||
* Programmer : Bill Randolph *
|
||||
* *
|
||||
* Start Date : 03/27/95 *
|
||||
* *
|
||||
* Last Update : July 30, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* BaseClass::Get_Building -- Returns ptr to the built building for the given node *
|
||||
* BaseClass::Get_Node -- Finds the node that matches the cell specified. *
|
||||
* BaseClass::Get_Node -- Returns ptr to the node corresponding to given object *
|
||||
* BaseClass::Is_Built -- Tells if given item in the list has been built yet *
|
||||
* BaseClass::Is_Node -- Tells if the given building is part of our base list *
|
||||
* BaseClass::Load -- loads from a saved game file *
|
||||
* BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built *
|
||||
* BaseClass::Read_INI -- INI reading routine *
|
||||
* BaseClass::Save -- saves to a saved game file *
|
||||
* BaseClass::Write_INI -- Writes all the base information to the INI database. *
|
||||
* BaseNodeClass::operator != -- inequality operator *
|
||||
* BaseNodeClass::operator == -- equality operator *
|
||||
* BaseNodeClass::operator > -- greater-than operator *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseNodeClass::operator == -- equality operator *
|
||||
* *
|
||||
* INPUT: *
|
||||
* node node to test against *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* true = equal, false = not equal *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
*=============================================================================================*/
|
||||
int BaseNodeClass::operator == (BaseNodeClass const & node)
|
||||
{
|
||||
return(Type == node.Type && Cell == node.Cell);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseNodeClass::operator != -- inequality operator *
|
||||
* *
|
||||
* INPUT: *
|
||||
* node node to test against *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* comparison result *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
*=============================================================================================*/
|
||||
int BaseNodeClass::operator !=(BaseNodeClass const & node)
|
||||
{
|
||||
return(!(*this == node));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseNodeClass::operator > -- greater-than operator *
|
||||
* *
|
||||
* INPUT: *
|
||||
* node node to test against *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* comparison result *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
*=============================================================================================*/
|
||||
int BaseNodeClass::operator > (BaseNodeClass const & )
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Load -- loads from a saved game file *
|
||||
* *
|
||||
* INPUT: *
|
||||
* file open file *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* true = success, false = failure *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
* 07/04/1996 JLB : Converted to demand driven data source. *
|
||||
*=============================================================================================*/
|
||||
bool BaseClass::Load(Straw & file)
|
||||
{
|
||||
int num_struct;
|
||||
int i;
|
||||
BaseNodeClass node;
|
||||
|
||||
/*
|
||||
** Read in & check the size of this class
|
||||
*/
|
||||
if (file.Get(&i, sizeof(i)) != sizeof(i)) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
if (i != sizeof(*this)) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*
|
||||
** Read in the House & the number of structures in the base
|
||||
*/
|
||||
if (file.Get(&House, sizeof(House)) != sizeof(House)) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
if (file.Get(&num_struct, sizeof(num_struct)) != sizeof(num_struct)) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*
|
||||
** Read each node entry & add it to the list
|
||||
*/
|
||||
for (i = 0; i < num_struct; i++) {
|
||||
if (file.Get(&node, sizeof(node)) != sizeof(node)) {
|
||||
return(false);
|
||||
}
|
||||
Nodes.Add(node);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Save -- saves to a saved game file *
|
||||
* *
|
||||
* INPUT: *
|
||||
* file open file *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* true = success, false = failure *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
* 07/04/1996 JLB : Converted to supply driven data output. *
|
||||
*=============================================================================================*/
|
||||
bool BaseClass::Save(Pipe & file) const
|
||||
{
|
||||
int num_struct;
|
||||
int i;
|
||||
BaseNodeClass node;
|
||||
|
||||
/*
|
||||
** Write the size of this class
|
||||
*/
|
||||
i = sizeof(*this);
|
||||
file.Put(&i, sizeof(i));
|
||||
|
||||
/*
|
||||
** Write the House & the number of structures in the base
|
||||
*/
|
||||
file.Put(&House, sizeof(House));
|
||||
|
||||
num_struct = Nodes.Count();
|
||||
file.Put(&num_struct, sizeof(num_struct));
|
||||
|
||||
/*
|
||||
** Write each node entry
|
||||
*/
|
||||
for (i = 0; i < num_struct; i++) {
|
||||
node = Nodes[i];
|
||||
file.Put(&node, sizeof(node));
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Is_Built -- Tells if given item in the list has been built yet *
|
||||
* *
|
||||
* INPUT: *
|
||||
* index index into base list *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* true = yes, false = no *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
*=============================================================================================*/
|
||||
bool BaseClass::Is_Built(int index) const
|
||||
{
|
||||
if (Get_Building(index) != NULL) {
|
||||
return(true);
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Get_Building -- Returns ptr to the built building for the given node *
|
||||
* *
|
||||
* INPUT: *
|
||||
* obj pointer to building to test *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* ptr to already-built building, NULL if none *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
* 07/30/1996 JLB : Handle arbitrary overlapper list length. *
|
||||
*=============================================================================================*/
|
||||
BuildingClass * BaseClass::Get_Building(int index) const
|
||||
{
|
||||
ObjectClass * obj[1 + ARRAY_SIZE(Map[(CELL)0].Overlapper)];
|
||||
|
||||
/*
|
||||
** Check the location on the map where this building should be; if it's
|
||||
** there, return a pointer to it.
|
||||
*/
|
||||
CELL cell = Nodes[index].Cell;
|
||||
|
||||
obj[0] = Map[cell].Cell_Building();
|
||||
int count = 1;
|
||||
for (int xindex = 0; xindex < ARRAY_SIZE(Map[cell].Overlapper); xindex++) {
|
||||
if (Map[cell].Overlapper[xindex] != NULL) {
|
||||
obj[count++] = Map[cell].Overlapper[xindex];
|
||||
}
|
||||
}
|
||||
|
||||
BuildingClass * bldg = NULL;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (obj[i] &&
|
||||
Coord_Cell(obj[i]->Coord) == Nodes[index].Cell &&
|
||||
obj[i]->What_Am_I() == RTTI_BUILDING &&
|
||||
((BuildingClass *)obj[i])->Class->Type == Nodes[index].Type) {
|
||||
|
||||
bldg = (BuildingClass *)obj[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(bldg);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Is_Node -- Tells if the given building is part of our base list *
|
||||
* *
|
||||
* INPUT: *
|
||||
* obj pointer to building to test *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* true = building is a node in the list, false = isn't *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
*=============================================================================================*/
|
||||
bool BaseClass::Is_Node(BuildingClass const * obj)
|
||||
{
|
||||
if (Get_Node(obj) != NULL) {
|
||||
return(true);
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Get_Node -- Returns ptr to the node corresponding to given object *
|
||||
* *
|
||||
* INPUT: *
|
||||
* obj pointer to building to test *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* ptr to node *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
*=============================================================================================*/
|
||||
BaseNodeClass * BaseClass::Get_Node(BuildingClass const * obj)
|
||||
{
|
||||
for (int i = 0; i < Nodes.Count(); i++) {
|
||||
if (obj->Class->Type == Nodes[i].Type && Coord_Cell(obj->Coord) == Nodes[i].Cell) {
|
||||
return(&Nodes[i]);
|
||||
}
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Get_Node -- Finds the node that matches the cell specified. *
|
||||
* *
|
||||
* This routine is used to find a matching node the corresponds to the cell specified. *
|
||||
* *
|
||||
* INPUT: cell -- The cell to use in finding a match. *
|
||||
* *
|
||||
* OUTPUT: Returns a pointer to the matching node if found. If not found, then NULL is *
|
||||
* returned. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/12/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
BaseNodeClass * BaseClass::Get_Node(CELL cell)
|
||||
{
|
||||
for (int index = 0; index < Nodes.Count(); index++) {
|
||||
if (cell == Nodes[index].Cell) {
|
||||
return(&Nodes[index]);
|
||||
}
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built *
|
||||
* *
|
||||
* If 'type' is not NONE, returns ptr to the next "hole" in the list of the given type. *
|
||||
* Otherwise, returns ptr to the next hole in the list of any type. *
|
||||
* *
|
||||
* INPUT: *
|
||||
* type type of building to check for *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* ptr to a BaseNodeClass, NULL if none *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
*=============================================================================================*/
|
||||
BaseNodeClass * BaseClass::Next_Buildable(StructType type)
|
||||
{
|
||||
/*
|
||||
** Loop through all node entries, returning a pointer to the first
|
||||
** un-built one that matches the requested type.
|
||||
*/
|
||||
for (int i = 0; i < Nodes.Count(); i++) {
|
||||
|
||||
/*
|
||||
** For STRUCT_NONE, return the first hole found
|
||||
*/
|
||||
if (type == STRUCT_NONE) {
|
||||
if (!Is_Built(i)) {
|
||||
return(&Nodes[i]);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
** For a "real" building type, return the first hold for that type
|
||||
*/
|
||||
if (Nodes[i].Type==type && !Is_Built(i)) {
|
||||
return(&Nodes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If no entry could be found, then create a fake one that will allow
|
||||
// placement of the building. Make it static and reuse the next time this
|
||||
// routine is called.
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Read_INI -- INI reading routine *
|
||||
* *
|
||||
* INI entry format: *
|
||||
* BLDG=COORDINATE *
|
||||
* BLDG=COORDINATE *
|
||||
* ... *
|
||||
* *
|
||||
* INPUT: *
|
||||
* buffer pointer to loaded INI file *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* This routines assumes there is only one base defined for the scenario. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/24/1995 BRR : Created. *
|
||||
* 02/20/1996 JLB : Fixed to know what house to build base from. *
|
||||
*=============================================================================================*/
|
||||
void BaseClass::Read_INI(CCINIClass & ini)
|
||||
{
|
||||
char buf[128];
|
||||
char uname[10];
|
||||
BaseNodeClass node; // node to add to list
|
||||
|
||||
Mono_Clear_Screen();
|
||||
/*
|
||||
** First, determine the house of the human player, and set the Base's house
|
||||
** accordingly.
|
||||
*/
|
||||
House = ini.Get_HousesType(INI_Name(), "Player", PlayerPtr->Class->House);
|
||||
|
||||
/*
|
||||
** Read the number of buildings that will go into the base node list
|
||||
*/
|
||||
int count = ini.Get_Int(INI_Name(), "Count", 0);
|
||||
|
||||
/*
|
||||
** Read each entry in turn, in the same order they were written out.
|
||||
*/
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
||||
/*
|
||||
** Get an INI entry
|
||||
*/
|
||||
sprintf(uname,"%03d",i);
|
||||
ini.Get_String(INI_Name(), uname, NULL, buf, sizeof(buf));
|
||||
|
||||
/*
|
||||
** Set the node's building type
|
||||
*/
|
||||
node.Type = BuildingTypeClass::From_Name(strtok(buf,","));
|
||||
|
||||
/*
|
||||
** Read & set the node's coordinate
|
||||
*/
|
||||
node.Cell = atoi(strtok(NULL,","));
|
||||
|
||||
/*
|
||||
** Add this node to the Base's list
|
||||
*/
|
||||
Nodes.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BaseClass::Write_INI -- Writes all the base information to the INI database. *
|
||||
* *
|
||||
* Use this routine to write all prebuild base information to the INI database specified. *
|
||||
* *
|
||||
* INPUT: ini -- Reference to the INI database to store the data to. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: If there was any preexisting prebuild base data in the database, it will be *
|
||||
* be erased by this routine. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/30/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void BaseClass::Write_INI(CCINIClass & ini)
|
||||
{
|
||||
/*
|
||||
** Clear out all existing base data from the ini file.
|
||||
*/
|
||||
ini.Clear(INI_Name());
|
||||
|
||||
if (House != HOUSE_NONE) {
|
||||
|
||||
/*
|
||||
** Write out the owner of this buildable list.
|
||||
*/
|
||||
ini.Put_HousesType(INI_Name(), "Player", House);
|
||||
|
||||
/*
|
||||
** Save the # of buildings in the Nodes list. This is essential because
|
||||
** they must be read in the same order they were created, so "000" must be
|
||||
** read first, etc.
|
||||
*/
|
||||
ini.Put_Int(INI_Name(), "Count", Nodes.Count());
|
||||
|
||||
/*
|
||||
** Write each entry into the INI
|
||||
*/
|
||||
for (int i = 0; i < Nodes.Count(); i++) {
|
||||
char buf[128];
|
||||
char uname[10];
|
||||
|
||||
sprintf(uname,"%03d",i);
|
||||
sprintf(buf,"%s,%d",
|
||||
BuildingTypeClass::As_Reference(Nodes[i].Type).IniName,
|
||||
Nodes[i].Cell);
|
||||
|
||||
ini.Put_String(INI_Name(), uname, buf);
|
||||
}
|
||||
}
|
||||
}
|
130
CODE/BASE.H
Normal file
130
CODE/BASE.H
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BASE.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BASE.H *
|
||||
* *
|
||||
* Programmer : Bill Randolph *
|
||||
* *
|
||||
* Start Date : 03/27/95 *
|
||||
* *
|
||||
* Last Update : March 27, 1995 *
|
||||
* *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef BASE_H
|
||||
#define BASE_H
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** This class defines one "node" in the pre-built base list. Each node
|
||||
** contains a type of building to build, and the COORDINATE to build it at.
|
||||
*/
|
||||
class BaseNodeClass
|
||||
{
|
||||
public:
|
||||
BaseNodeClass(void) {};
|
||||
BaseNodeClass(StructType building, CELL cell) : Type(building), Cell(cell) {};
|
||||
int operator == (BaseNodeClass const & node);
|
||||
int operator != (BaseNodeClass const & node);
|
||||
int operator > (BaseNodeClass const & node);
|
||||
|
||||
StructType Type;
|
||||
CELL Cell;
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** This is the class that defines a pre-built base for the computer AI.
|
||||
** (Despite its name, this is NOT the "base" class for C&C's class hierarchy!)
|
||||
*/
|
||||
class BaseClass
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
** Constructor/Destructor
|
||||
*/
|
||||
BaseClass(void) {};
|
||||
virtual ~BaseClass() {Nodes.Clear();}
|
||||
|
||||
/*
|
||||
** Initialization
|
||||
*/
|
||||
void Init(void) {House = HOUSE_NONE; Nodes.Clear();}
|
||||
|
||||
/*
|
||||
** The standard suite of load/save support routines
|
||||
*/
|
||||
void Read_INI(CCINIClass & ini);
|
||||
void Write_INI(CCINIClass & ini);
|
||||
static char *INI_Name(void) {return "Base";}
|
||||
bool Load(Straw & file);
|
||||
bool Save(Pipe & file) const;
|
||||
virtual void Code_Pointers(void) {};
|
||||
virtual void Decode_Pointers(void) {};
|
||||
|
||||
/*
|
||||
** Tells if the given node has been built or not
|
||||
*/
|
||||
bool Is_Built(int index) const;
|
||||
|
||||
/*
|
||||
** Returns a pointer to the object for the given node
|
||||
*/
|
||||
BuildingClass * Get_Building(int index) const;
|
||||
|
||||
/*
|
||||
** Tells if the given building ptr is a node in this base's list.
|
||||
*/
|
||||
bool Is_Node(BuildingClass const * obj);
|
||||
|
||||
/*
|
||||
** Returns a pointer to the requested node.
|
||||
*/
|
||||
BaseNodeClass * Get_Node(BuildingClass const * obj);
|
||||
BaseNodeClass * Get_Node(int index) { return (&Nodes[index]); }
|
||||
BaseNodeClass * Get_Node(CELL cell);
|
||||
|
||||
/*
|
||||
** Returns a pointer to the next "hole" in the Nodes list.
|
||||
*/
|
||||
BaseNodeClass * Next_Buildable(StructType type = STRUCT_NONE);
|
||||
|
||||
/*
|
||||
** This is the list of "nodes" that define the base. Portions of this
|
||||
** list can be pre-built by simply saving those buildings in the INI
|
||||
** along with non-base buildings, so Is_Built will return true for them.
|
||||
*/
|
||||
DynamicVectorClass<BaseNodeClass> Nodes;
|
||||
|
||||
/*
|
||||
** This is the house this base belongs to.
|
||||
*/
|
||||
HousesType House;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
437
CODE/BASE64.CPP
Normal file
437
CODE/BASE64.CPP
Normal file
@ -0,0 +1,437 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BASE64.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BASE64.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 06/29/96 *
|
||||
* *
|
||||
* Last Update : July 6, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Base64_Decode -- Decodes Base 64 data into its original data form. *
|
||||
* Base64_Encode -- Encode data into Base 64 format. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#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.
|
||||
|
||||
*/
|
40
CODE/BASE64.H
Normal file
40
CODE/BASE64.H
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BASE64.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BASE64.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 06/29/96 *
|
||||
* *
|
||||
* Last Update : June 29, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
int Base64_Encode(void const * source, int slen, void * dest, int dlen);
|
||||
int Base64_Decode(void const * source, int slen, void * dest, int dlen);
|
300
CODE/BBDATA.CPP
Normal file
300
CODE/BBDATA.CPP
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BBDATA.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BBDATA.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : May 23, 1994 *
|
||||
* *
|
||||
* Last Update : July 19, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* BulletTypeClass::As_Reference -- Returns with a reference to the bullet type object specif*
|
||||
* BulletTypeClass::BulletTypeClass -- Constructor for bullet type objects. *
|
||||
* BulletTypeClass::Init_Heap -- Initialize the heap objects for the bullet type. *
|
||||
* BulletTypeClass::Load_Shapes -- Load shape data for bullet types. *
|
||||
* BulletTypeClass::One_Time -- Performs the one time processing for bullets. *
|
||||
* BulletTypeClass::Read_INI -- Fetch the bullet type data from the INI database. *
|
||||
* BulletTypeClass::operator delete -- Deletes a bullet type object from the special heap. *
|
||||
* BulletTypeClass::operator new -- Allocates a bullet type object from the special heap. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BulletTypeClass::BulletTypeClass -- Constructor for bullet type objects. *
|
||||
* *
|
||||
* This is basically a constructor for static type objects used by bullets. All bullets *
|
||||
* are of a type constructed by this routine at game initialization time. *
|
||||
* *
|
||||
* INPUT: see below... *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/17/1994 JLB : Created. *
|
||||
* 07/17/1996 JLB : Uses correct default values. *
|
||||
*=============================================================================================*/
|
||||
BulletTypeClass::BulletTypeClass(char const * name) :
|
||||
ObjectTypeClass( RTTI_BULLETTYPE,
|
||||
BulletTypes.ID(this),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
TXT_NONE,
|
||||
name
|
||||
),
|
||||
IsHigh(false),
|
||||
IsShadow(true),
|
||||
IsArcing(false),
|
||||
IsDropping(false),
|
||||
IsInvisible(false),
|
||||
IsProximityArmed(false),
|
||||
IsFlameEquipped(false),
|
||||
IsFueled(false),
|
||||
IsFaceless(true),
|
||||
IsInaccurate(false),
|
||||
IsTranslucent(false),
|
||||
IsAntiAircraft(false),
|
||||
IsAntiGround(true),
|
||||
IsAntiSub(false),
|
||||
IsDegenerate(false),
|
||||
IsSubSurface(false),
|
||||
IsParachuted(false),
|
||||
IsGigundo(false),
|
||||
Type(BulletType(ID)),
|
||||
ROT(0),
|
||||
Arming(0),
|
||||
Tumble(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BulletTypeClass::operator new -- Allocates a bullet type object from the special heap. *
|
||||
* *
|
||||
* This allocates a bullet type object from a special heap that is used just for *
|
||||
* objects of this type. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to an allocated block or NULL if the allocation could not *
|
||||
* occur. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void * BulletTypeClass::operator new(size_t)
|
||||
{
|
||||
return(BulletTypes.Alloc());
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BulletTypeClass::operator delete -- Deletes a bullet type object from the special heap. *
|
||||
* *
|
||||
* This is the counterpart to the operator new function for bullet type objects. It will *
|
||||
* return the bullet type object back to the special heap used for bullet type object *
|
||||
* allocation. *
|
||||
* *
|
||||
* INPUT: ptr -- Pointer to the bullet type object to free. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void BulletTypeClass::operator delete(void * ptr)
|
||||
{
|
||||
BulletTypes.Free((BulletTypeClass *)ptr);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BulletTypeClass::Init_Heap -- Initialize the heap objects for the bullet type. *
|
||||
* *
|
||||
* This performs any necessary initialization for the bullet types. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void BulletTypeClass::Init_Heap(void)
|
||||
{
|
||||
/*
|
||||
** These bullet type class objects must be allocated in the exact order that they
|
||||
** are specified in the BulletType enumeration. This is necessary because the heap
|
||||
** allocation block index serves double duty as the type number index.
|
||||
*/
|
||||
new BulletTypeClass("Invisible"); // BULLET_INVISIBLE
|
||||
new BulletTypeClass("Cannon"); // BULLET_CANNON
|
||||
new BulletTypeClass("Ack"); // BULLET_ACK
|
||||
new BulletTypeClass("Torpedo"); // BULLET_TORPEDO
|
||||
new BulletTypeClass("FROG"); // BULLET_FROG
|
||||
new BulletTypeClass("HeatSeeker"); // BULLET_HEAT_SEEKER
|
||||
new BulletTypeClass("LaserGuided"); // BULLET_LASER_GUIDED
|
||||
new BulletTypeClass("Lobbed"); // BULLET_LOBBED
|
||||
new BulletTypeClass("Bomblet"); // BULLET_BOMBLET
|
||||
new BulletTypeClass("Ballistic"); // BULLET_BALLISTIC
|
||||
new BulletTypeClass("Parachute"); // BULLET_PARACHUTE
|
||||
new BulletTypeClass("Fireball"); // BULLET_FIREBALL
|
||||
new BulletTypeClass("LeapDog"); // BULLET_DOG
|
||||
new BulletTypeClass("Catapult"); // BULLET_CATAPULT
|
||||
new BulletTypeClass("AAMissile"); // BULLET_AAMISSILE
|
||||
new BulletTypeClass("GPSSatellite");// BULLET_GPS_SATELLITE
|
||||
new BulletTypeClass("NukeUp"); // BULLET_NUKE_UP
|
||||
new BulletTypeClass("NukeDown"); // BULLET_NUKE_DOWN
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BulletTypeClass::One_Time -- Performs the one time processing for bullets. *
|
||||
* *
|
||||
* This routine is used to perform any one time processing for the bullet type class. It *
|
||||
* handles loading of the shape files. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: This routine must be called before any rendering of bullets occurs and should *
|
||||
* only be called once. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/28/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void BulletTypeClass::One_Time(void)
|
||||
{
|
||||
/*
|
||||
** Load the bullet shapes.
|
||||
*/
|
||||
for (BulletType index = BULLET_FIRST; index < BULLET_COUNT; index++) {
|
||||
BulletTypeClass const & bullet = As_Reference(index);
|
||||
char fullname[_MAX_FNAME+_MAX_EXT];
|
||||
|
||||
if (!bullet.IsInvisible) {
|
||||
_makepath(fullname, NULL, NULL, bullet.GraphicName, ".SHP");
|
||||
|
||||
#ifdef NDEBUG
|
||||
((void const *&)bullet.ImageData) = MFCD::Retrieve(fullname);
|
||||
#else
|
||||
RawFileClass file(fullname);
|
||||
|
||||
if (file.Is_Available()) {
|
||||
((void const *&)bullet.ImageData) = Load_Alloc_Data(file);
|
||||
} else {
|
||||
((void const *&)bullet.ImageData) = MFCD::Retrieve(fullname);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BulletTypeClass::As_Reference -- Returns with a reference to the bullet type object specifi *
|
||||
* *
|
||||
* Given a bullet type identifier, this routine will return a reference to the bullet type *
|
||||
* object it refers to. *
|
||||
* *
|
||||
* INPUT: type -- The bullet type identifier to convert to a reference. *
|
||||
* *
|
||||
* OUTPUT: Returns with a reference to the bullet type object. *
|
||||
* *
|
||||
* WARNINGS: Make sure that the type parameter specified is a valid bullet type. If not, *
|
||||
* then the results are undefined. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
BulletTypeClass & BulletTypeClass::As_Reference(BulletType type)
|
||||
{
|
||||
return(*BulletTypes.Ptr(type));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BulletTypeClass::Read_INI -- Fetch the bullet type data from the INI database. *
|
||||
* *
|
||||
* Use this routine to fetch override information about this bullet type class object *
|
||||
* from the INI database specified. *
|
||||
* *
|
||||
* INPUT: ini -- Reference to the INI database to examine. *
|
||||
* *
|
||||
* OUTPUT: bool; Was the section for this bullet found and the data extracted? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/19/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
bool BulletTypeClass::Read_INI(CCINIClass & ini)
|
||||
{
|
||||
if (ini.Is_Present(Name())) {
|
||||
Arming = ini.Get_Int(Name(), "Arm", Arming);
|
||||
ROT = ini.Get_Int(Name(), "ROT", ROT);
|
||||
Tumble = ini.Get_Int(Name(), "Frames", Tumble);
|
||||
IsHigh = ini.Get_Bool(Name(), "High", IsHigh);
|
||||
IsShadow = ini.Get_Bool(Name(), "Shadow", IsShadow);
|
||||
IsArcing = ini.Get_Bool(Name(), "Arcing", IsArcing);
|
||||
IsDropping = ini.Get_Bool(Name(), "Dropping", IsDropping);
|
||||
IsInvisible = ini.Get_Bool(Name(), "Inviso", IsInvisible);
|
||||
IsProximityArmed = ini.Get_Bool(Name(), "Proximity", IsProximityArmed);
|
||||
IsFlameEquipped = ini.Get_Bool(Name(), "Animates", IsFlameEquipped);
|
||||
IsFueled = ini.Get_Bool(Name(), "Ranged", IsFueled);
|
||||
IsInaccurate = ini.Get_Bool(Name(), "Inaccuate", IsInaccurate);
|
||||
IsAntiAircraft = ini.Get_Bool(Name(), "AA", IsAntiAircraft);
|
||||
IsAntiGround = ini.Get_Bool(Name(), "AG", IsAntiGround);
|
||||
IsAntiSub = ini.Get_Bool(Name(), "ASW", IsAntiSub);
|
||||
IsDegenerate = ini.Get_Bool(Name(), "Degenerates", IsDegenerate);
|
||||
IsSubSurface = ini.Get_Bool(Name(), "UnderWater", IsSubSurface);
|
||||
IsParachuted = ini.Get_Bool(Name(), "Parachuted", IsParachuted);
|
||||
IsFaceless = !ini.Get_Bool(Name(), "Rotates", !IsFaceless);
|
||||
IsTranslucent = ini.Get_Bool(Name(), "Translucent", IsTranslucent);
|
||||
IsGigundo = ini.Get_Bool(Name(), "Gigundo", IsGigundo);
|
||||
ini.Get_String(Name(), "Image", "none", GraphicName, sizeof(GraphicName));
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
3834
CODE/BDATA.CPP
Normal file
3834
CODE/BDATA.CPP
Normal file
File diff suppressed because it is too large
Load Diff
167
CODE/BENCH.CPP
Normal file
167
CODE/BENCH.CPP
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BENCH.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BENCH.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 07/17/96 *
|
||||
* *
|
||||
* Last Update : July 18, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Benchmark::Begin -- Start the benchmark operation. *
|
||||
* Benchmark::Benchmark -- Constructor for the benchmark object. *
|
||||
* Benchmark::End -- Mark the end of a benchmarked operation *
|
||||
* Benchmark::Reset -- Clear out the benchmark statistics. *
|
||||
* Benchmark::Value -- Fetch the current average benchmark time. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "bench.h"
|
||||
#include "mpu.h"
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Benchmark::Benchmark -- Constructor for the benchmark object. *
|
||||
* *
|
||||
* This will construct the benchmark object. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/18/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
Benchmark::Benchmark(void) :
|
||||
Average(0),
|
||||
Counter(0),
|
||||
TotalCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Benchmark::Reset -- Clear out the benchmark statistics. *
|
||||
* *
|
||||
* Use this routine to clear out all the accumulated statistics within this benchmark *
|
||||
* object. The object is set just as if it was freshly constructed. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/18/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void Benchmark::Reset(void)
|
||||
{
|
||||
Average = 0;
|
||||
Counter = 0;
|
||||
TotalCount = 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Benchmark::Begin -- Start the benchmark operation. *
|
||||
* *
|
||||
* Call this routine before the operation to be benchmarked is begun. The corresponding *
|
||||
* End() function must be called after the operation has completed. *
|
||||
* *
|
||||
* INPUT: reset -- Should the entire benchmark object be reset at this time as well? *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: The Begin() and End() functions are NOT nestable. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/18/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void Benchmark::Begin(bool reset)
|
||||
{
|
||||
if (reset) Reset();
|
||||
Clock = 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Benchmark::End -- Mark the end of a benchmarked operation *
|
||||
* *
|
||||
* This routine is called at the end of the operation that is being benchmarked. It is *
|
||||
* important to call this routine as soon as possible after the event being benchmarked *
|
||||
* has completed. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: The Being() and End() functions are NOT nestable. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/18/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void Benchmark::End(void)
|
||||
{
|
||||
unsigned long value = Clock;
|
||||
|
||||
if (Counter == MAXIMUM_EVENT_COUNT) {
|
||||
Average -= Average / MAXIMUM_EVENT_COUNT;
|
||||
Average += value;
|
||||
} else {
|
||||
Average += value;
|
||||
Counter++;
|
||||
}
|
||||
TotalCount++;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Benchmark::Value -- Fetch the current average benchmark time. *
|
||||
* *
|
||||
* This routine will take the statistics already accumulated and determine the average *
|
||||
* time recorded. This value will be returned. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the average time that all events tracked by this object. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/18/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
unsigned long Benchmark::Value(void) const
|
||||
{
|
||||
if (Counter) {
|
||||
return(Average / Counter);
|
||||
}
|
||||
return(0);
|
||||
}
|
122
CODE/BENCH.H
Normal file
122
CODE/BENCH.H
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BENCH.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BENCH.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 07/17/96 *
|
||||
* *
|
||||
* Last Update : July 17, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#ifndef BENCH_H
|
||||
#define BENCH_H
|
||||
|
||||
#include "mpu.h"
|
||||
#include "ftimer.h"
|
||||
|
||||
/*
|
||||
** The "bool" integral type was defined by the C++ committee in
|
||||
** November of '94. Until the compiler supports this, use the following
|
||||
** definition.
|
||||
*/
|
||||
#ifndef __BORLANDC__
|
||||
#ifndef TRUE_FALSE_DEFINED
|
||||
#define TRUE_FALSE_DEFINED
|
||||
enum {false=0,true=1};
|
||||
typedef int bool;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This is a timer access object that will fetch the internal Pentium
|
||||
** clock value.
|
||||
*/
|
||||
class PentiumTimerClass
|
||||
{
|
||||
public:
|
||||
unsigned long operator () (void) const {unsigned long h;unsigned long l = Get_CPU_Clock(h);return((l >> 4) | (h << 28));}
|
||||
operator unsigned long (void) const {unsigned long h;unsigned long l = Get_CPU_Clock(h);return((l >> 4) | (h << 28));}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** A performance tracking tool object. It is used to track elapsed time. Unlike a simple clock, this
|
||||
** class will keep a running average of the duration. Typical use of this would be to benchmark some
|
||||
** process that occurs multiple times. By benchmarking an average time, inconsistencies in a particular
|
||||
** run can be overcome.
|
||||
*/
|
||||
class Benchmark
|
||||
{
|
||||
public:
|
||||
Benchmark(void);
|
||||
|
||||
void Begin(bool reset=false);
|
||||
void End(void);
|
||||
|
||||
void Reset(void);
|
||||
unsigned long Value(void) const;
|
||||
unsigned long Count(void) const {return(TotalCount);}
|
||||
|
||||
private:
|
||||
/*
|
||||
** The maximum number of events to keep running average of. If
|
||||
** events exceed this number, then older events drop off the
|
||||
** accumulated time. This number needs to be as small as
|
||||
** is reasonable. The larger this number gets, the less magnitude
|
||||
** that the benchmark timer can handle. Example; At a value of
|
||||
** 256, the magnitude of the timer can only be 24 bits.
|
||||
*/
|
||||
enum {MAXIMUM_EVENT_COUNT=256};
|
||||
|
||||
/*
|
||||
** This is the timer the is used to clock the events.
|
||||
*/
|
||||
BasicTimerClass<PentiumTimerClass> Clock;
|
||||
|
||||
/*
|
||||
** The total time off all events tracked so far.
|
||||
*/
|
||||
unsigned long Average;
|
||||
|
||||
/*
|
||||
** The total number of events tracked so far.
|
||||
*/
|
||||
unsigned long Counter;
|
||||
|
||||
/*
|
||||
** Absolute total number of events (possibly greater than the
|
||||
** number of events tracked in the average).
|
||||
*/
|
||||
unsigned long TotalCount;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
2122
CODE/BFILE.MAK
Normal file
2122
CODE/BFILE.MAK
Normal file
File diff suppressed because it is too large
Load Diff
2098
CODE/BFILE2.MAK
Normal file
2098
CODE/BFILE2.MAK
Normal file
File diff suppressed because it is too large
Load Diff
987
CODE/BFIOFILE.CPP
Normal file
987
CODE/BFIOFILE.CPP
Normal file
@ -0,0 +1,987 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BFIOFILE.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Westwood Library *
|
||||
* *
|
||||
* File Name : RAMFILE.CPP *
|
||||
* *
|
||||
* Programmer : David R. Dettmer *
|
||||
* *
|
||||
* Start Date : November 10, 1995 *
|
||||
* *
|
||||
* Last Update : November 10, 1995 [DRD] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object. *
|
||||
* BufferIOFileClass::BufferIOFileClass -- default constructor for a file object. *
|
||||
* BufferIOFileClass::Cache -- Load part or all of a file data into RAM. *
|
||||
* BufferIOFileClass::Close -- Perform a closure of the file. *
|
||||
* BufferIOFileClass::Commit -- Writes the cache to the file if it has changed. *
|
||||
* BufferIOFileClass::Free -- Frees the allocated buffer. *
|
||||
* BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk. *
|
||||
* BufferIOFileClass::Is_Open -- Determines if the file is open. *
|
||||
* BufferIOFileClass::Open -- Assigns name and opens file in one operation. *
|
||||
* BufferIOFileClass::Open -- Opens the file object with the rights specified. *
|
||||
* BufferIOFileClass::Read -- Reads data from the file cache. *
|
||||
* BufferIOFileClass::Seek -- Moves the current file pointer in the file. *
|
||||
* BufferIOFileClass::Set_Name -- Checks for name changed for a cached file. *
|
||||
* BufferIOFileClass::Size -- Determines size of file (in bytes). *
|
||||
* BufferIOFileClass::Write -- Writes data to the file cache. *
|
||||
* BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "bfiofile.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object. *
|
||||
* *
|
||||
* This constructor is called when a file object is created with a supplied filename, but *
|
||||
* not opened at the same time. In this case, an assumption is made that the supplied *
|
||||
* filename is a constant string. A duplicate of the filename string is not created since *
|
||||
* it would be wasteful in that case. *
|
||||
* *
|
||||
* INPUT: filename -- The filename to assign to this file object. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
BufferIOFileClass::BufferIOFileClass(char const * filename) :
|
||||
IsAllocated(false),
|
||||
IsOpen(false),
|
||||
IsDiskOpen(false),
|
||||
IsCached(false),
|
||||
IsChanged(false),
|
||||
UseBuffer(false),
|
||||
BufferRights(0),
|
||||
Buffer(0),
|
||||
BufferSize(0),
|
||||
BufferPos(0),
|
||||
BufferFilePos(0),
|
||||
BufferChangeBeg(-1),
|
||||
BufferChangeEnd(-1),
|
||||
FileSize(0),
|
||||
FilePos(0),
|
||||
TrueFileStart(0)
|
||||
{
|
||||
BufferIOFileClass::Set_Name(filename);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::BufferIOFileClass -- default constructor for a file object. *
|
||||
* *
|
||||
* This is the default constructor for a file object. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
BufferIOFileClass::BufferIOFileClass(void) :
|
||||
IsAllocated(false),
|
||||
IsOpen(false),
|
||||
IsDiskOpen(false),
|
||||
IsCached(false),
|
||||
IsChanged(false),
|
||||
UseBuffer(false),
|
||||
BufferRights(0),
|
||||
Buffer(0),
|
||||
BufferSize(0),
|
||||
BufferPos(0),
|
||||
BufferFilePos(0),
|
||||
BufferChangeBeg(-1),
|
||||
BufferChangeEnd(-1),
|
||||
FileSize(0),
|
||||
FilePos(0),
|
||||
TrueFileStart(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object. *
|
||||
* *
|
||||
* This destructor will free all memory allocated thru using Cache routines. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
BufferIOFileClass::~BufferIOFileClass(void)
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Cache -- Load part or all of a file data into RAM. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file load successful? It could fail if there wasn't enough room *
|
||||
* to allocate the raw data block. *
|
||||
* *
|
||||
* WARNINGS: This routine goes to disk for a potentially very long time. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
bool BufferIOFileClass::Cache( long size, void * ptr )
|
||||
{
|
||||
if (Buffer) {
|
||||
//
|
||||
// if trying to cache again with size or ptr fail
|
||||
//
|
||||
if (size || ptr) {
|
||||
return( false );
|
||||
} else {
|
||||
return( true );
|
||||
}
|
||||
}
|
||||
|
||||
if ( Is_Available() ) {
|
||||
FileSize = Size();
|
||||
} else {
|
||||
FileSize = 0;
|
||||
}
|
||||
|
||||
if (size) {
|
||||
//
|
||||
// minimum buffer size for performance
|
||||
//
|
||||
if (size < MINIMUM_BUFFER_SIZE) {
|
||||
size = MINIMUM_BUFFER_SIZE;
|
||||
|
||||
/*
|
||||
** Specifying a size smaller than the minimum is an error
|
||||
** IF a buffer pointer was also specified. In such a case the
|
||||
** system cannot use the buffer.
|
||||
*/
|
||||
if (ptr) {
|
||||
Error(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
BufferSize = size;
|
||||
} else {
|
||||
BufferSize = FileSize;
|
||||
}
|
||||
|
||||
//
|
||||
// if size == 0 and a ptr to a buffer is specified then that is invalid.
|
||||
// if the BufferSize is 0 then this must be a new file and no size was
|
||||
// specified so exit.
|
||||
//
|
||||
if ( (size == 0 && ptr) || !BufferSize) {
|
||||
return( false );
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
Buffer = ptr;
|
||||
} else {
|
||||
Buffer = new char [BufferSize];
|
||||
}
|
||||
|
||||
if (Buffer) {
|
||||
IsAllocated = true;
|
||||
IsDiskOpen = false;
|
||||
BufferPos = 0;
|
||||
BufferFilePos = 0;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
FilePos = 0;
|
||||
TrueFileStart = 0;
|
||||
|
||||
//
|
||||
// the file was checked for availability then set the FileSize
|
||||
//
|
||||
if (FileSize) {
|
||||
long readsize;
|
||||
int opened = false;
|
||||
long prevpos = 0;
|
||||
|
||||
|
||||
if (FileSize <= BufferSize) {
|
||||
readsize = FileSize;
|
||||
} else {
|
||||
readsize = BufferSize;
|
||||
}
|
||||
|
||||
if ( Is_Open() ) {
|
||||
//
|
||||
// get previous file position
|
||||
//
|
||||
prevpos = Seek(0);
|
||||
|
||||
//
|
||||
// get true file position
|
||||
//
|
||||
if ( RawFileClass::Is_Open() ) {
|
||||
TrueFileStart = RawFileClass::Seek(0);
|
||||
} else {
|
||||
TrueFileStart = prevpos;
|
||||
}
|
||||
|
||||
if (FileSize <= BufferSize) {
|
||||
//
|
||||
// if previous position is non-zero seek to the beginning
|
||||
//
|
||||
if (prevpos) {
|
||||
Seek(0, SEEK_SET);
|
||||
}
|
||||
|
||||
//
|
||||
// set the buffer position for future reads/writes
|
||||
//
|
||||
BufferPos = prevpos;
|
||||
} else {
|
||||
BufferFilePos = prevpos;
|
||||
}
|
||||
|
||||
FilePos = prevpos;
|
||||
} else {
|
||||
if ( Open() ) {
|
||||
TrueFileStart = RawFileClass::Seek(0);
|
||||
opened = true;
|
||||
}
|
||||
}
|
||||
|
||||
long actual = Read(Buffer, readsize);
|
||||
|
||||
if (actual != readsize) {
|
||||
Error(EIO);
|
||||
}
|
||||
|
||||
if (opened) {
|
||||
Close();
|
||||
} else {
|
||||
//
|
||||
// seek to the previous position in the file
|
||||
//
|
||||
Seek(prevpos, SEEK_SET);
|
||||
}
|
||||
|
||||
IsCached = true;
|
||||
}
|
||||
|
||||
UseBuffer = true;
|
||||
return(true);
|
||||
}
|
||||
|
||||
Error(ENOMEM);
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Free -- Frees the allocated buffer. *
|
||||
* *
|
||||
* This routine will free the buffer. By using this in conjunction with the *
|
||||
* Cache() function, one can maintain tight control of memory usage. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
void BufferIOFileClass::Free(void)
|
||||
{
|
||||
if (Buffer) {
|
||||
if (IsAllocated) {
|
||||
delete [] Buffer;
|
||||
IsAllocated = false;
|
||||
}
|
||||
|
||||
Buffer = 0;
|
||||
}
|
||||
|
||||
BufferSize = 0;
|
||||
IsOpen = false;
|
||||
IsCached = false;
|
||||
IsChanged = false;
|
||||
UseBuffer = false;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Commit -- Writes the cache to the file if it has changed. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: false, did not need to write the buffer. *
|
||||
* true, wrote the buffer. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
bool BufferIOFileClass::Commit( void )
|
||||
{
|
||||
long size;
|
||||
|
||||
|
||||
if (UseBuffer) {
|
||||
if (IsChanged) {
|
||||
size = BufferChangeEnd - BufferChangeBeg;
|
||||
|
||||
if (IsDiskOpen) {
|
||||
RawFileClass::Seek( TrueFileStart + BufferFilePos +
|
||||
BufferChangeBeg, SEEK_SET );
|
||||
RawFileClass::Write( Buffer, size );
|
||||
RawFileClass::Seek( TrueFileStart + FilePos, SEEK_SET );
|
||||
} else {
|
||||
RawFileClass::Open();
|
||||
RawFileClass::Seek( TrueFileStart + BufferFilePos +
|
||||
BufferChangeBeg, SEEK_SET );
|
||||
RawFileClass::Write( Buffer, size );
|
||||
RawFileClass::Close();
|
||||
}
|
||||
|
||||
IsChanged = false;
|
||||
return( true );
|
||||
} else {
|
||||
return( false );
|
||||
}
|
||||
} else {
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Set_Name -- Checks for name changed for a cached file. *
|
||||
* *
|
||||
* Checks for a previous filename and that it is cached. If so, then check the *
|
||||
* new filename against the old. If they are the same then return that filename. *
|
||||
* Otherwise, the file object's name is set with just the raw filename as passed *
|
||||
* to this routine. *
|
||||
* *
|
||||
* INPUT: filename -- Pointer to the filename to set as the name of this file object. *
|
||||
* *
|
||||
* OUTPUT: Returns a pointer to the final and complete filename of this file object. This *
|
||||
* may have a path attached to the file. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
char const * BufferIOFileClass::Set_Name(char const * filename)
|
||||
{
|
||||
if ( File_Name() && UseBuffer) {
|
||||
if ( strcmp(filename, File_Name() ) == 0) {
|
||||
return( File_Name() );
|
||||
} else {
|
||||
Commit();
|
||||
IsCached = false;
|
||||
}
|
||||
}
|
||||
|
||||
RawFileClass::Set_Name(filename);
|
||||
return( File_Name() );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Is the file available for opening? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/16/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
int BufferIOFileClass::Is_Available(int )
|
||||
{
|
||||
if (UseBuffer) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
return( RawFileClass::Is_Available() );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Is_Open -- Determines if the file is open. *
|
||||
* *
|
||||
* If part or all of the file is cached, then return that it is opened. A closed file *
|
||||
* doesn't have a valid pointer. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Is the file open? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
int BufferIOFileClass::Is_Open(void) const
|
||||
{
|
||||
if (IsOpen && UseBuffer) {
|
||||
return( true );
|
||||
}
|
||||
|
||||
return( RawFileClass::Is_Open() );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Open -- Assigns name and opens file in one operation. *
|
||||
* *
|
||||
* This routine will assign the specified filename to the file object and open it at the *
|
||||
* same time. If the file object was already open, then it will be closed first. If the *
|
||||
* file object was previously assigned a filename, then it will be replaced with the new *
|
||||
* name. Typically, this routine is used when an anonymous file object has been crated and *
|
||||
* now it needs to be assigned a name and opened. *
|
||||
* *
|
||||
* INPUT: filename -- The filename to assign to this file object. *
|
||||
* *
|
||||
* rights -- The open file access rights to use. *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file opened? The return value of this is moot, since the open file *
|
||||
* is designed to never return unless it succeeded. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
int BufferIOFileClass::Open(char const * filename, int rights)
|
||||
{
|
||||
Set_Name(filename);
|
||||
return( BufferIOFileClass::Open( rights ) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Open -- Opens the file object with the rights specified. *
|
||||
* *
|
||||
* This routine is used to open the specified file object with the access rights indicated. *
|
||||
* This only works if the file has already been assigned a filename. It is guaranteed, by *
|
||||
* the error handler, that this routine will always return with success. *
|
||||
* *
|
||||
* INPUT: rights -- The file access rights to use when opening this file. This is a *
|
||||
* combination of READ and/or WRITE bit flags. *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file opened successfully? This will always return true by reason of *
|
||||
* the error handler. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
int BufferIOFileClass::Open(int rights)
|
||||
{
|
||||
BufferIOFileClass::Close();
|
||||
|
||||
if (UseBuffer) {
|
||||
|
||||
BufferRights = rights; // save rights requested for checks later
|
||||
|
||||
if (rights != READ ||
|
||||
(rights == READ && FileSize > BufferSize) ) {
|
||||
|
||||
if (rights == WRITE) {
|
||||
RawFileClass::Open( rights );
|
||||
RawFileClass::Close();
|
||||
rights = READ | WRITE;
|
||||
TrueFileStart = 0; // now writing to single file
|
||||
}
|
||||
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Open( rights );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Open( rights );
|
||||
}
|
||||
|
||||
IsDiskOpen = true;
|
||||
|
||||
if (BufferRights == WRITE) {
|
||||
FileSize = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
IsDiskOpen = false;
|
||||
}
|
||||
|
||||
BufferPos = 0;
|
||||
BufferFilePos = 0;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
FilePos = 0;
|
||||
IsOpen = true;
|
||||
} else {
|
||||
RawFileClass::Open( rights );
|
||||
}
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Write -- Writes data to the file cache. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: buffer -- Pointer to the buffer that holds the data to be written. *
|
||||
* *
|
||||
* size -- The number of bytes to write. *
|
||||
* *
|
||||
* OUTPUT: Returns the number of bytes actually written. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
long BufferIOFileClass::Write(void const * buffer, long size)
|
||||
{
|
||||
int opened = false;
|
||||
|
||||
if ( !Is_Open() ) {
|
||||
if (!Open(WRITE)) {
|
||||
return(0);
|
||||
}
|
||||
TrueFileStart = RawFileClass::Seek(0);
|
||||
opened = true;
|
||||
}
|
||||
|
||||
if (UseBuffer) {
|
||||
long sizewritten = 0;
|
||||
|
||||
if (BufferRights != READ) {
|
||||
while (size) {
|
||||
long sizetowrite;
|
||||
|
||||
if (size >= (BufferSize - BufferPos) ) {
|
||||
sizetowrite = (BufferSize - BufferPos);
|
||||
} else {
|
||||
sizetowrite = size;
|
||||
}
|
||||
|
||||
if (sizetowrite != BufferSize) {
|
||||
|
||||
if ( !IsCached ) {
|
||||
long readsize;
|
||||
|
||||
if (FileSize < BufferSize) {
|
||||
readsize = FileSize;
|
||||
BufferFilePos = 0;
|
||||
} else {
|
||||
readsize = BufferSize;
|
||||
BufferFilePos = FilePos;
|
||||
}
|
||||
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek( FilePos, SEEK_SET );
|
||||
Read( Buffer, BufferSize );
|
||||
Seek( FilePos, SEEK_SET );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek( BufferFilePos, SEEK_SET );
|
||||
RawFileClass::Read( Buffer, readsize );
|
||||
}
|
||||
|
||||
BufferPos = 0;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
|
||||
IsCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
memmove((char *)Buffer + BufferPos, (char *)buffer + sizewritten, sizetowrite);
|
||||
|
||||
IsChanged = true;
|
||||
sizewritten += sizetowrite;
|
||||
size -= sizetowrite;
|
||||
|
||||
if (BufferChangeBeg == -1) {
|
||||
BufferChangeBeg = BufferPos;
|
||||
BufferChangeEnd = BufferPos;
|
||||
} else {
|
||||
if (BufferChangeBeg > BufferPos) {
|
||||
BufferChangeBeg = BufferPos;
|
||||
}
|
||||
}
|
||||
|
||||
BufferPos += sizetowrite;
|
||||
|
||||
if (BufferChangeEnd < BufferPos) {
|
||||
BufferChangeEnd = BufferPos;
|
||||
}
|
||||
|
||||
FilePos = BufferFilePos + BufferPos;
|
||||
|
||||
if (FileSize < FilePos) {
|
||||
FileSize = FilePos;
|
||||
}
|
||||
|
||||
//
|
||||
// end of buffer reached?
|
||||
//
|
||||
if (BufferPos == BufferSize) {
|
||||
Commit();
|
||||
|
||||
BufferPos = 0;
|
||||
BufferFilePos = FilePos;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
|
||||
if (size && FileSize > FilePos) {
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek( FilePos, SEEK_SET );
|
||||
Read( Buffer, BufferSize );
|
||||
Seek( FilePos, SEEK_SET );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek( FilePos, SEEK_SET );
|
||||
RawFileClass::Read( Buffer, BufferSize );
|
||||
}
|
||||
} else {
|
||||
IsCached = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Error(EACCES);
|
||||
}
|
||||
|
||||
size = sizewritten;
|
||||
} else {
|
||||
size = RawFileClass::Write(buffer, size);
|
||||
}
|
||||
|
||||
if (opened) {
|
||||
Close();
|
||||
}
|
||||
|
||||
return( size );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Read -- Reads data from the file cache. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: buffer -- Pointer to the buffer to place the read data. *
|
||||
* *
|
||||
* size -- The number of bytes to read. *
|
||||
* *
|
||||
* OUTPUT: Returns the actual number of bytes read (this could be less than requested). *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
long BufferIOFileClass::Read(void * buffer, long size)
|
||||
{
|
||||
int opened = false;
|
||||
|
||||
if ( !Is_Open() ) {
|
||||
if ( Open() ) {
|
||||
TrueFileStart = RawFileClass::Seek(0);
|
||||
opened = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (UseBuffer) {
|
||||
long sizeread = 0;
|
||||
|
||||
if (BufferRights != WRITE) {
|
||||
while (size) {
|
||||
long sizetoread;
|
||||
|
||||
if (size >= (BufferSize - BufferPos) ) {
|
||||
sizetoread = (BufferSize - BufferPos);
|
||||
} else {
|
||||
sizetoread = size;
|
||||
}
|
||||
|
||||
if ( !IsCached ) {
|
||||
long readsize;
|
||||
|
||||
if (FileSize < BufferSize) {
|
||||
readsize = FileSize;
|
||||
BufferFilePos = 0;
|
||||
} else {
|
||||
readsize = BufferSize;
|
||||
BufferFilePos = FilePos;
|
||||
}
|
||||
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek( FilePos, SEEK_SET );
|
||||
Read( Buffer, BufferSize );
|
||||
Seek( FilePos, SEEK_SET );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek( BufferFilePos, SEEK_SET );
|
||||
RawFileClass::Read( Buffer, readsize );
|
||||
}
|
||||
|
||||
BufferPos = 0;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
|
||||
IsCached = true;
|
||||
}
|
||||
|
||||
memmove((char *)buffer + sizeread, (char *)Buffer + BufferPos, sizetoread);
|
||||
|
||||
sizeread += sizetoread;
|
||||
size -= sizetoread;
|
||||
BufferPos += sizetoread;
|
||||
FilePos = BufferFilePos + BufferPos;
|
||||
|
||||
//
|
||||
// end of buffer reached?
|
||||
//
|
||||
if (BufferPos == BufferSize) {
|
||||
Commit();
|
||||
|
||||
BufferPos = 0;
|
||||
BufferFilePos = FilePos;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
|
||||
if (size && FileSize > FilePos) {
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek( FilePos, SEEK_SET );
|
||||
Read( Buffer, BufferSize );
|
||||
Seek( FilePos, SEEK_SET );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek( FilePos, SEEK_SET );
|
||||
RawFileClass::Read( Buffer, BufferSize );
|
||||
}
|
||||
} else {
|
||||
IsCached = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Error(EACCES);
|
||||
}
|
||||
|
||||
size = sizeread;
|
||||
} else {
|
||||
size = RawFileClass::Read(buffer, size);
|
||||
}
|
||||
|
||||
if (opened) {
|
||||
Close();
|
||||
}
|
||||
|
||||
return( size );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Seek -- Moves the current file pointer in the file. *
|
||||
* *
|
||||
* This routine will change the current file pointer to the position specified. It follows *
|
||||
* the same rules the a normal Seek() does, but if the file is part of the mixfile system, *
|
||||
* then only the position value needs to be updated. *
|
||||
* *
|
||||
* INPUT: pos -- The position to move the file to relative to the position indicated *
|
||||
* by the "dir" parameter. *
|
||||
* *
|
||||
* dir -- The direction to affect the position change against. This can be *
|
||||
* either SEEK_CUR, SEEK_END, or SEEK_SET. *
|
||||
* *
|
||||
* OUTPUT: Returns with the position of the new location. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
long BufferIOFileClass::Seek(long pos, int dir)
|
||||
{
|
||||
if (UseBuffer) {
|
||||
bool adjusted = false;
|
||||
|
||||
switch (dir) {
|
||||
case SEEK_END:
|
||||
FilePos = FileSize;
|
||||
break;
|
||||
|
||||
case SEEK_SET:
|
||||
FilePos = 0;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (TrueFileStart) {
|
||||
if (pos >= TrueFileStart) {
|
||||
pos -= TrueFileStart;
|
||||
adjusted = true;
|
||||
}
|
||||
}
|
||||
|
||||
FilePos += pos;
|
||||
|
||||
if (FilePos < 0) {
|
||||
FilePos = 0;
|
||||
}
|
||||
|
||||
if (FilePos > FileSize ) {
|
||||
FilePos = FileSize;
|
||||
}
|
||||
|
||||
if (FileSize <= BufferSize) {
|
||||
BufferPos = FilePos;
|
||||
} else {
|
||||
if (FilePos >= BufferFilePos &&
|
||||
FilePos < (BufferFilePos + BufferSize) ) {
|
||||
BufferPos = FilePos - BufferFilePos;
|
||||
} else {
|
||||
Commit();
|
||||
// check!!
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek(FilePos, SEEK_SET);
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek(FilePos, SEEK_SET);
|
||||
}
|
||||
|
||||
IsCached = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (TrueFileStart && adjusted) {
|
||||
return( FilePos + TrueFileStart );
|
||||
}
|
||||
|
||||
return( FilePos );
|
||||
}
|
||||
|
||||
return( RawFileClass::Seek(pos, dir) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Size -- Determines size of file (in bytes). *
|
||||
* *
|
||||
* If part or all of the file is cached, then the size of the file is already *
|
||||
* determined and available. Otherwise, go to the low level system to find the file *
|
||||
* size. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the number of bytes in the file. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
long BufferIOFileClass::Size(void)
|
||||
{
|
||||
if (IsOpen && UseBuffer) {
|
||||
return( FileSize );
|
||||
}
|
||||
|
||||
return( RawFileClass::Size() );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Close -- Perform a closure of the file. *
|
||||
* *
|
||||
* Call Commit() to write the buffer if the file is cached and the buffer has changed, *
|
||||
* then call lower level Close(). *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
void BufferIOFileClass::Close(void)
|
||||
{
|
||||
if (UseBuffer) {
|
||||
Commit();
|
||||
|
||||
if (IsDiskOpen) {
|
||||
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Close();
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Close();
|
||||
}
|
||||
|
||||
IsDiskOpen = false;
|
||||
}
|
||||
|
||||
IsOpen = false;
|
||||
} else {
|
||||
RawFileClass::Close();
|
||||
}
|
||||
}
|
||||
|
95
CODE/BFIOFILE.H
Normal file
95
CODE/BFIOFILE.H
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BFIOFILE.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Westwood Library *
|
||||
* *
|
||||
* File Name : BFIOFILE.H *
|
||||
* *
|
||||
* Programmer : David R. Dettmer *
|
||||
* *
|
||||
* Start Date : November 10, 1995 *
|
||||
* *
|
||||
* Last Update : November 10, 1995 [DRD] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* 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
|
||||
{
|
||||
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 int Is_Available(int forced=false);
|
||||
virtual int Is_Open(void) const;
|
||||
virtual int Open(char const *filename, int rights=READ);
|
||||
virtual int Open(int rights=READ);
|
||||
virtual long Read(void *buffer, long size);
|
||||
virtual long Seek(long pos, int dir=SEEK_CUR);
|
||||
virtual long Size(void);
|
||||
virtual long Write(void const *buffer, long size);
|
||||
virtual void Close(void);
|
||||
|
||||
enum {MINIMUM_BUFFER_SIZE=1024};
|
||||
|
||||
private:
|
||||
|
||||
unsigned IsAllocated:1;
|
||||
unsigned IsOpen:1;
|
||||
unsigned IsDiskOpen:1;
|
||||
unsigned IsCached:1;
|
||||
unsigned IsChanged:1;
|
||||
unsigned UseBuffer:1;
|
||||
|
||||
int BufferRights;
|
||||
|
||||
void *Buffer;
|
||||
|
||||
long BufferSize;
|
||||
long BufferPos;
|
||||
long BufferFilePos;
|
||||
long BufferChangeBeg;
|
||||
long BufferChangeEnd;
|
||||
long FileSize;
|
||||
long FilePos;
|
||||
long TrueFileStart;
|
||||
};
|
||||
|
||||
#endif
|
84
CODE/BIGCHECK.CPP
Normal file
84
CODE/BIGCHECK.CPP
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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/>.
|
||||
*/
|
||||
|
||||
// BigCheck.cpp
|
||||
// ajw 9/14/98
|
||||
|
||||
#ifdef WOLAPI_INTEGRATION
|
||||
|
||||
#include "function.h"
|
||||
#include "bigcheck.h"
|
||||
|
||||
//***********************************************************************************************
|
||||
int BigCheckBoxClass::Draw_Me( int forced )
|
||||
{
|
||||
if (ToggleClass::Draw_Me(forced))
|
||||
{
|
||||
Hide_Mouse();
|
||||
|
||||
if( !IsOn )
|
||||
{
|
||||
if( !IsDisabled )
|
||||
CC_Draw_Shape( MFCD::Retrieve( "bigcheck.shp" ), 0, X, Y, WINDOW_MAIN, SHAPE_NORMAL );
|
||||
else
|
||||
CC_Draw_Shape( MFCD::Retrieve( "bigcheck.shp" ), 2, X, Y, WINDOW_MAIN, SHAPE_NORMAL );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !IsDisabled )
|
||||
CC_Draw_Shape( MFCD::Retrieve( "bigcheck.shp" ), 1, X, Y, WINDOW_MAIN, SHAPE_NORMAL );
|
||||
else
|
||||
CC_Draw_Shape( MFCD::Retrieve( "bigcheck.shp" ), 3, X, Y, WINDOW_MAIN, SHAPE_NORMAL );
|
||||
}
|
||||
|
||||
TextPrintType flags = TextFlags;
|
||||
|
||||
RemapControlType* pScheme;
|
||||
|
||||
// if( !IsDisabled )
|
||||
pScheme = GadgetClass::Get_Color_Scheme();
|
||||
// else
|
||||
// {
|
||||
// pScheme = &GreyScheme;
|
||||
// flags = flags | TPF_MEDIUM_COLOR;
|
||||
// }
|
||||
|
||||
Conquer_Clip_Text_Print( szCaption, X + BIGCHECK_OFFSETX, Y + BIGCHECK_OFFSETY, pScheme, TBLACK, flags, Width, 0 );
|
||||
|
||||
Show_Mouse();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
int BigCheckBoxClass::Action(unsigned flags, KeyNumType & key)
|
||||
{
|
||||
/* if( flags & LEFTPRESS )
|
||||
{
|
||||
if (IsOn) {
|
||||
Turn_Off();
|
||||
} else {
|
||||
Turn_On();
|
||||
}
|
||||
}
|
||||
*/
|
||||
return(ToggleClass::Action(flags, key));
|
||||
}
|
||||
|
||||
#endif
|
74
CODE/BIGCHECK.H
Normal file
74
CODE/BIGCHECK.H
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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/>.
|
||||
*/
|
||||
|
||||
// Bigcheck.h
|
||||
// ajw 9/14/98
|
||||
|
||||
#ifdef WOLAPI_INTEGRATION
|
||||
|
||||
#ifndef BIGCHECKBOX_H
|
||||
#define BIGCHECKBOX_H
|
||||
|
||||
#include "toggle.h"
|
||||
|
||||
#define BIGCHECK_OFFSETX 20
|
||||
#define BIGCHECK_OFFSETY 0
|
||||
|
||||
//***********************************************************************************************
|
||||
class BigCheckBoxClass : public ToggleClass
|
||||
{
|
||||
public:
|
||||
BigCheckBoxClass( unsigned id, int x, int y, int w, int h, const char* szCaptionIn, TextPrintType TextFlags,
|
||||
bool bInitiallyChecked = false ) :
|
||||
ToggleClass( id, x, y, w, h ),
|
||||
TextFlags( TextFlags )
|
||||
{
|
||||
szCaption = new char[ strlen( szCaptionIn ) + 1 ];
|
||||
strcpy( szCaption, szCaptionIn );
|
||||
if( bInitiallyChecked )
|
||||
Turn_On();
|
||||
IsToggleType = 1;
|
||||
}
|
||||
virtual ~BigCheckBoxClass()
|
||||
{
|
||||
delete [] szCaption;
|
||||
}
|
||||
|
||||
virtual int Draw_Me(int forced=false);
|
||||
virtual int Action(unsigned flags, KeyNumType & key);
|
||||
|
||||
bool Toggle()
|
||||
{
|
||||
if( IsOn )
|
||||
{
|
||||
Turn_Off();
|
||||
return false;
|
||||
}
|
||||
Turn_On();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
TextPrintType TextFlags;
|
||||
char* szCaption;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
598
CODE/BLOWFISH.CPP
Normal file
598
CODE/BLOWFISH.CPP
Normal file
@ -0,0 +1,598 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BLOWFISH.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BLOWFISH.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 04/14/96 *
|
||||
* *
|
||||
* Last Update : July 8, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* 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 "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
|
||||
}
|
||||
};
|
||||
|
117
CODE/BLOWFISH.H
Normal file
117
CODE/BLOWFISH.H
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BLOWFISH.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BLOWFISH.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 04/14/96 *
|
||||
* *
|
||||
* Last Update : April 14, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __BORLANDC__
|
||||
#ifndef TRUE_FALSE_DEFINED
|
||||
#define TRUE_FALSE_DEFINED
|
||||
enum {false=0,true=1};
|
||||
typedef int bool;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** 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. 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[(int)ROUNDS+2];
|
||||
static unsigned long const S_Init[4][UCHAR_MAX+1];
|
||||
|
||||
/*
|
||||
** Permutation tables for encryption and decryption.
|
||||
*/
|
||||
unsigned long P_Encrypt[(int)ROUNDS+2];
|
||||
unsigned long P_Decrypt[(int)ROUNDS+2];
|
||||
|
||||
/*
|
||||
** S-Box tables (four).
|
||||
*/
|
||||
unsigned long bf_S[4][UCHAR_MAX+1];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
202
CODE/BLOWPIPE.CPP
Normal file
202
CODE/BLOWPIPE.CPP
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BLOWPIPE.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BLOWPIPE.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 06/30/96 *
|
||||
* *
|
||||
* Last Update : July 3, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* BlowPipe::Flush -- Flushes any pending data out the pipe. *
|
||||
* BlowPipe::Key -- Submit a key to the blowfish pipe handler. *
|
||||
* BlowPipe::Put -- Submit a block of data for encrypt/decrypt. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "blowpipe.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BlowPipe::Flush -- Flushes any pending data out the pipe. *
|
||||
* *
|
||||
* If there is any pending data in the holding buffer, then this routine will force it to *
|
||||
* be flushed out the end of the pipe. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the actual number of bytes output at the end final distant pipe *
|
||||
* segment in the chain. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/03/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int BlowPipe::Flush(void)
|
||||
{
|
||||
int total = 0;
|
||||
if (Counter > 0 && BF != NULL) {
|
||||
total += Pipe::Put(Buffer, Counter);
|
||||
}
|
||||
Counter = 0;
|
||||
total += Pipe::Flush();
|
||||
return(total);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BlowPipe::Put -- Submit a block of data for encrypt/decrypt. *
|
||||
* *
|
||||
* This will take the data block specified and process it before passing it on to the next *
|
||||
* link in the pipe chain. A key must be submitted before this routine will actually perform*
|
||||
* any processing. Prior to key submission, the data is passed through unchanged. *
|
||||
* *
|
||||
* INPUT: source -- Pointer to the buffer that contains the data to pass through. *
|
||||
* *
|
||||
* length -- The length of the data in the buffer. *
|
||||
* *
|
||||
* OUTPUT: Returns with then actual number of bytes output at the final distant end link in *
|
||||
* the pipe chain. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/03/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int BlowPipe::Put(void const * source, int slen)
|
||||
{
|
||||
if (source == NULL || slen < 1) {
|
||||
return(Pipe::Put(source, slen));
|
||||
}
|
||||
|
||||
/*
|
||||
** If there is no blowfish engine present, then merely pass the data through
|
||||
** unchanged in any way.
|
||||
*/
|
||||
if (BF == NULL) {
|
||||
return(Pipe::Put(source, slen));
|
||||
}
|
||||
|
||||
int total = 0;
|
||||
|
||||
/*
|
||||
** If there is a partial block accumulated, then tag on the new data to
|
||||
** this block and process it if the block is full. Proceed with the bulk
|
||||
** processing if there are any left over bytes from this step. This step
|
||||
** can be skipped if there are no pending bytes in the buffer.
|
||||
*/
|
||||
if (Counter) {
|
||||
int sublen = (sizeof(Buffer)-Counter < slen) ? (sizeof(Buffer)-Counter) : slen;
|
||||
memmove(&Buffer[Counter], source, sublen);
|
||||
Counter += sublen;
|
||||
source = ((char *)source) + sublen;
|
||||
slen -= sublen;
|
||||
|
||||
if (Counter == sizeof(Buffer)) {
|
||||
if (Control == DECRYPT) {
|
||||
BF->Decrypt(Buffer, sizeof(Buffer), Buffer);
|
||||
} else {
|
||||
BF->Encrypt(Buffer, sizeof(Buffer), Buffer);
|
||||
}
|
||||
total += Pipe::Put(Buffer, sizeof(Buffer));
|
||||
Counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Process the input data in blocks until there is not enough
|
||||
** source data to fill a full block of data.
|
||||
*/
|
||||
while (slen >= sizeof(Buffer)) {
|
||||
if (Control == DECRYPT) {
|
||||
BF->Decrypt(source, sizeof(Buffer), Buffer);
|
||||
} else {
|
||||
BF->Encrypt(source, sizeof(Buffer), Buffer);
|
||||
}
|
||||
total += Pipe::Put(Buffer, sizeof(Buffer));
|
||||
source = ((char *)source) + sizeof(Buffer);
|
||||
slen -= sizeof(Buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
** If there are any left over bytes, then they must be less than the size of
|
||||
** the staging buffer. Store the bytes in the staging buffer for later
|
||||
** processing.
|
||||
*/
|
||||
if (slen > 0) {
|
||||
memmove(Buffer, source, slen);
|
||||
Counter = slen;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return with the total number of bytes flushed out to the final end of the
|
||||
** pipe chain.
|
||||
*/
|
||||
return(total);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BlowPipe::Key -- Submit a key to the blowfish pipe handler. *
|
||||
* *
|
||||
* This routine will take the key provided and use it to process the data that passes *
|
||||
* through this pipe. Prior to a key being submitted, the data passes through the pipe *
|
||||
* unchanged. *
|
||||
* *
|
||||
* INPUT: key -- Pointer to the key data to use. *
|
||||
* *
|
||||
* length-- The length of the key. The key length must not be greater than 56 bytes. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/03/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void BlowPipe::Key(void const * key, int length)
|
||||
{
|
||||
/*
|
||||
** Create the blowfish engine if one isn't already present.
|
||||
*/
|
||||
if (BF == NULL) {
|
||||
BF = new BlowfishEngine;
|
||||
}
|
||||
|
||||
assert(BF != NULL);
|
||||
|
||||
if (BF != NULL) {
|
||||
BF->Submit_Key(key, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
85
CODE/BLOWPIPE.H
Normal file
85
CODE/BLOWPIPE.H
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BLOWPIPE.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BLOWPIPE.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 06/30/96 *
|
||||
* *
|
||||
* Last Update : June 30, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* 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
|
161
CODE/BLWSTRAW.CPP
Normal file
161
CODE/BLWSTRAW.CPP
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BLWSTRAW.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BLWSTRAW.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 07/02/96 *
|
||||
* *
|
||||
* Last Update : July 3, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* BlowStraw::Get -- Fetch a block of data from the straw. *
|
||||
* BlowStraw::Key -- Submit a key to the Blowfish straw. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "blwstraw.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BlowStraw::Get -- Fetch a block of data from the straw. *
|
||||
* *
|
||||
* This routine will take a block of data from the straw and process it according to the *
|
||||
* encrypt/decrypt flag and the key supplied. Prior to a key be supplied, the data passes *
|
||||
* through this straw unchanged. *
|
||||
* *
|
||||
* INPUT: source -- Pointer to the buffer to hold the data being requested. *
|
||||
* *
|
||||
* length -- The length of the data being requested. *
|
||||
* *
|
||||
* OUTPUT: Returns with the actual number of bytes stored into the buffer. If the number *
|
||||
* returned is less than the number requested, then this indicates that the data *
|
||||
* source has been exhausted. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/03/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int BlowStraw::Get(void * source, int slen)
|
||||
{
|
||||
/*
|
||||
** Verify the parameter for legality.
|
||||
*/
|
||||
if (source == NULL || slen <= 0) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** If there is no blowfish engine present, then merely pass the data through
|
||||
** unchanged.
|
||||
*/
|
||||
if (BF == NULL) {
|
||||
return(Straw::Get(source, slen));
|
||||
}
|
||||
|
||||
int total = 0;
|
||||
|
||||
while (slen > 0) {
|
||||
|
||||
/*
|
||||
** If there are any left over bytes in the buffer, pass them
|
||||
** through first.
|
||||
*/
|
||||
if (Counter > 0) {
|
||||
int sublen = (slen < Counter) ? slen : Counter;
|
||||
memmove(source, &Buffer[sizeof(Buffer)-Counter], sublen);
|
||||
Counter -= sublen;
|
||||
source = ((char *)source) + sublen;
|
||||
slen -= sublen;
|
||||
total += sublen;
|
||||
}
|
||||
if (slen == 0) break;
|
||||
|
||||
/*
|
||||
** Fetch and encrypt/decrypt the next block.
|
||||
*/
|
||||
int incount = Straw::Get(Buffer, sizeof(Buffer));
|
||||
if (incount == 0) break;
|
||||
|
||||
/*
|
||||
** Only full blocks are processed. Partial blocks are
|
||||
** merely passed through unchanged.
|
||||
*/
|
||||
if (incount == sizeof(Buffer)) {
|
||||
if (Control == DECRYPT) {
|
||||
BF->Decrypt(Buffer, incount, Buffer);
|
||||
} else {
|
||||
BF->Encrypt(Buffer, incount, Buffer);
|
||||
}
|
||||
} else {
|
||||
memmove(&Buffer[sizeof(Buffer)-incount], Buffer, incount);
|
||||
}
|
||||
Counter = incount;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return with the total number of bytes placed into the buffer.
|
||||
*/
|
||||
return(total);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BlowStraw::Key -- Submit a key to the Blowfish straw. *
|
||||
* *
|
||||
* This will take the key specified and use it to process the data that flows through this *
|
||||
* straw segment. Prior to a key being submitted, the data will flow through unchanged. *
|
||||
* *
|
||||
* INPUT: key -- Pointer to the key to submit. *
|
||||
* *
|
||||
* length-- The length of the key. The length must not exceed 56 bytes. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/03/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void BlowStraw::Key(void const * key, int length)
|
||||
{
|
||||
/*
|
||||
** Create the blowfish engine if one isn't already present.
|
||||
*/
|
||||
if (BF == NULL) {
|
||||
BF = new BlowfishEngine;
|
||||
}
|
||||
|
||||
assert(BF != NULL);
|
||||
|
||||
if (BF != NULL) {
|
||||
BF->Submit_Key(key, length);
|
||||
}
|
||||
}
|
87
CODE/BLWSTRAW.H
Normal file
87
CODE/BLWSTRAW.H
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BLWSTRAW.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BLWSTRAW.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 07/02/96 *
|
||||
* *
|
||||
* Last Update : July 2, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* 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
|
189
CODE/BMP8.CPP
Normal file
189
CODE/BMP8.CPP
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "bmp8.h"
|
||||
|
||||
//***********************************************************************************************
|
||||
BMP8::~BMP8()
|
||||
{
|
||||
// free resources
|
||||
if( hBitmap )
|
||||
::DeleteObject( hBitmap );
|
||||
if( hPal )
|
||||
::DeleteObject( hPal );
|
||||
}
|
||||
|
||||
//***********************************************************************************************
|
||||
bool BMP8::Init( const char* szFile, HWND hWnd )
|
||||
{
|
||||
int i;
|
||||
char string[128];
|
||||
DWORD dwRead;
|
||||
BITMAPFILEHEADER bitmapHeader;
|
||||
BITMAPINFOHEADER bitmapInfoHeader;
|
||||
LPLOGPALETTE lpLogPalette;
|
||||
char *palData;
|
||||
HGLOBAL hmem2;
|
||||
LPVOID lpvBits;
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc;
|
||||
HPALETTE select;
|
||||
UINT realize;
|
||||
RECT rect;
|
||||
|
||||
|
||||
// Remember window handle for use later.
|
||||
this->hWnd = hWnd;
|
||||
|
||||
// Retrieve a handle identifying the file.
|
||||
HANDLE hFile = ::CreateFile(
|
||||
szFile,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
(LPSECURITY_ATTRIBUTES)NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_READONLY,
|
||||
(HANDLE)NULL );
|
||||
|
||||
if( !hFile )
|
||||
return false;
|
||||
|
||||
// Retrieve the BITMAPFILEHEADER structure.
|
||||
::ReadFile( hFile, &bitmapHeader, sizeof(BITMAPFILEHEADER), &dwRead, (LPOVERLAPPED)NULL );
|
||||
|
||||
// Retrieve the BITMAPFILEHEADER structure.
|
||||
::ReadFile( hFile, &bitmapInfoHeader, sizeof(BITMAPINFOHEADER), &dwRead, (LPOVERLAPPED)NULL );
|
||||
|
||||
// Allocate memory for the BITMAPINFO structure.
|
||||
HGLOBAL infoHeaderMem = ::GlobalAlloc( GHND, sizeof(BITMAPINFOHEADER) + ((1<<bitmapInfoHeader.biBitCount) * sizeof(RGBQUAD)) );
|
||||
|
||||
LPBITMAPINFO lpHeaderMem = (LPBITMAPINFO)::GlobalLock( infoHeaderMem );
|
||||
|
||||
// Load BITMAPINFOHEADER into the BITMAPINFO structure.
|
||||
lpHeaderMem->bmiHeader.biSize = bitmapInfoHeader.biSize;
|
||||
lpHeaderMem->bmiHeader.biWidth = bitmapInfoHeader.biWidth;
|
||||
lpHeaderMem->bmiHeader.biHeight = bitmapInfoHeader.biHeight;
|
||||
lpHeaderMem->bmiHeader.biPlanes = bitmapInfoHeader.biPlanes;
|
||||
lpHeaderMem->bmiHeader.biBitCount = bitmapInfoHeader.biBitCount;
|
||||
lpHeaderMem->bmiHeader.biCompression = bitmapInfoHeader.biCompression;
|
||||
lpHeaderMem->bmiHeader.biSizeImage = bitmapInfoHeader.biSizeImage;
|
||||
lpHeaderMem->bmiHeader.biXPelsPerMeter = bitmapInfoHeader.biXPelsPerMeter;
|
||||
lpHeaderMem->bmiHeader.biYPelsPerMeter = bitmapInfoHeader.biYPelsPerMeter;
|
||||
lpHeaderMem->bmiHeader.biClrUsed = bitmapInfoHeader.biClrUsed;
|
||||
lpHeaderMem->bmiHeader.biClrImportant = bitmapInfoHeader.biClrImportant;
|
||||
|
||||
// Retrieve the color table.
|
||||
// 1 << bitmapInfoHeader.biBitCount == 2 ^ bitmapInfoHeader.biBitCount
|
||||
::ReadFile( hFile, lpHeaderMem->bmiColors, ((1<<bitmapInfoHeader.biBitCount) * sizeof(RGBQUAD)),
|
||||
&dwRead, (LPOVERLAPPED)NULL );
|
||||
|
||||
|
||||
lpLogPalette = (LPLOGPALETTE)new char[ (sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*256) ];
|
||||
lpLogPalette->palVersion=0x300;
|
||||
lpLogPalette->palNumEntries=256;
|
||||
|
||||
palData = (char*)lpHeaderMem->bmiColors;
|
||||
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
lpLogPalette->palPalEntry[i].peRed = *palData++;
|
||||
lpLogPalette->palPalEntry[i].peGreen = *palData++;
|
||||
lpLogPalette->palPalEntry[i].peBlue = *palData++;
|
||||
lpLogPalette->palPalEntry[i].peFlags = *palData++;
|
||||
}
|
||||
hPal = ::CreatePalette( lpLogPalette );
|
||||
delete [] lpLogPalette;
|
||||
|
||||
// Allocate memory for the required number of bytes.
|
||||
hmem2 = ::GlobalAlloc( GHND, (bitmapHeader.bfSize - bitmapHeader.bfOffBits) );
|
||||
|
||||
lpvBits = ::GlobalLock( hmem2 );
|
||||
|
||||
// Retrieve the bitmap data.
|
||||
::ReadFile( hFile, lpvBits, (bitmapHeader.bfSize - bitmapHeader.bfOffBits), &dwRead, (LPOVERLAPPED)NULL );
|
||||
|
||||
// Create a bitmap from the data stored in the .BMP file.
|
||||
hdc = ::GetDC( hWnd );
|
||||
select = ::SelectPalette( hdc, hPal, 0 );
|
||||
if( !select )
|
||||
return false;
|
||||
realize = ::RealizePalette( hdc );
|
||||
if( realize == GDI_ERROR )
|
||||
return false;
|
||||
|
||||
hBMP = ::CreateDIBitmap( hdc, &bitmapInfoHeader, CBM_INIT, lpvBits, lpHeaderMem, DIB_RGB_COLORS );
|
||||
::ReleaseDC( hWnd, hdc );
|
||||
|
||||
// Unlock the global memory objects and close the .BMP file.
|
||||
::GlobalUnlock( infoHeaderMem );
|
||||
::GlobalUnlock( hmem2 );
|
||||
::CloseHandle( hFile );
|
||||
|
||||
if( !hBMP )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bit8 BMP8::drawBmp(void)
|
||||
{
|
||||
// Paint the window (and draw the bitmap).
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc;
|
||||
char string[128];
|
||||
|
||||
InvalidateRect(WindowHandle_,NULL,FALSE); // keep windows from screwing up the
|
||||
// redrawing (as much).
|
||||
hdc=BeginPaint(WindowHandle_,&ps);
|
||||
|
||||
//Do palette stuff
|
||||
HPALETTE select=SelectPalette(ps.hdc,PalHandle_,0);
|
||||
if (select==NULL)
|
||||
{
|
||||
sprintf(string,"Select Pal Fail: %d",GetLastError());
|
||||
MessageBox(NULL,string,"OK",MB_OK);
|
||||
}
|
||||
UINT realize=RealizePalette(ps.hdc);
|
||||
if (realize==GDI_ERROR)
|
||||
{
|
||||
sprintf(string,"Realize Pal Fail: %d",GetLastError());
|
||||
MessageBox(NULL,string,"OK",MB_OK);
|
||||
}
|
||||
|
||||
HDC hdcMem = CreateCompatibleDC(ps.hdc);
|
||||
SelectObject(hdcMem, BitmapHandle_);
|
||||
BITMAP bm;
|
||||
GetObject(BitmapHandle_, sizeof(BITMAP), (LPSTR) &bm);
|
||||
|
||||
/// for non-stretching version
|
||||
///////BitBlt(ps.hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
|
||||
|
||||
RECT clientRect;
|
||||
GetClientRect(WindowHandle_,&clientRect);
|
||||
SetStretchBltMode(ps.hdc,COLORONCOLOR);
|
||||
StretchBlt(ps.hdc,0,0,clientRect.right,clientRect.bottom,hdcMem,0,0,bm.bmWidth,
|
||||
bm.bmHeight,SRCCOPY);
|
||||
|
||||
|
||||
DeleteDC(hdcMem);
|
||||
EndPaint(WindowHandle_,&ps);
|
||||
return(TRUE);
|
||||
}
|
43
CODE/BMP8.H
Normal file
43
CODE/BMP8.H
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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 BMP8_H
|
||||
#define BMP8_H
|
||||
|
||||
//#include<stdlib.h>
|
||||
//#include<stdio.h>
|
||||
//#include "wstypes.h"
|
||||
//#include "winblows.h"
|
||||
|
||||
class BMP8
|
||||
{
|
||||
public:
|
||||
BMP8() : hBMP( NULL ), hPal( NULL ), hWnd( NULL ) {}
|
||||
~BMP8();
|
||||
|
||||
bool Init( const char* szFile, HWND hWnd );
|
||||
bool Draw(void); // call this from your WM_PAINT message
|
||||
|
||||
private:
|
||||
HBITMAP hBMP;
|
||||
HPALETTE hPal;
|
||||
HWND hWnd;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
220
CODE/BUFF.CPP
Normal file
220
CODE/BUFF.CPP
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BUFF.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BUFF.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 07/29/96 *
|
||||
* *
|
||||
* Last Update : September 7, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* 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 "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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Alternate constructor for char * pointer.
|
||||
Buffer::Buffer(char * buffer, long size) :
|
||||
BufferPtr(buffer),
|
||||
Size(size),
|
||||
IsAllocated(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Alternate constructor for void const * pointer.
|
||||
Buffer::Buffer(void const * buffer, long size) :
|
||||
BufferPtr((void*)buffer),
|
||||
Size(size),
|
||||
IsAllocated(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* 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 = new 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;
|
||||
}
|
99
CODE/BUFF.H
Normal file
99
CODE/BUFF.H
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BUFF.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BUFF.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 07/29/96 *
|
||||
* *
|
||||
* Last Update : July 29, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#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.
|
||||
*/
|
||||
#ifndef __BORLANDC__
|
||||
#ifndef TRUE_FALSE_DEFINED
|
||||
#define TRUE_FALSE_DEFINED
|
||||
enum {false=0,true=1};
|
||||
typedef int bool;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** 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
|
101
CODE/BUFFERX.H
Normal file
101
CODE/BUFFERX.H
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BUFFERX.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BUFFER.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 05/04/96 *
|
||||
* *
|
||||
* Last Update : May 4, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#ifndef BUFFERx_H
|
||||
#define BUFFERx_H
|
||||
|
||||
#include "wwfile.h"
|
||||
|
||||
/*
|
||||
** This is a transmuter interface designed to aid implementation of compression, encryption, or
|
||||
** data analysis classes. The Transmuter should be derived into a class that performs the necessary
|
||||
** processing.
|
||||
*/
|
||||
class Transmuter {
|
||||
public:
|
||||
Transmuter(void) : Output(0) {}
|
||||
virtual ~Transmuter(void) {}
|
||||
|
||||
/*
|
||||
** These are the interface function that are used to pass data to the transmuter. The
|
||||
** default implementation of these functions do nothing other than pass the data onto
|
||||
** the subsequent transmuter. For practical use, these functions should be overloaded to
|
||||
** do something more useful.
|
||||
*/
|
||||
virtual void Attach(Transmuter * transmuter) {Output = transmuter;}
|
||||
virtual void Flush(void) {if (Output) Output->Flush();}
|
||||
virtual void Put(const void * input, unsigned length) {if (Output) Output->Put(input, length);}
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
** Pointer to the output transmuter.
|
||||
*/
|
||||
Transmuter * Output;
|
||||
};
|
||||
|
||||
|
||||
class FileTransmuter {
|
||||
public:
|
||||
FileTransmuter(FileClass * file = NULL) : OutputFile(file) {}
|
||||
|
||||
virtual void Attach(FileClass * file) {OutputFile = file;}
|
||||
virtual void Flush(void) {}
|
||||
virtual void Put(const void * input, unsigned length) {if (OutputFile) OutputFile->Write(input, length);}
|
||||
|
||||
protected:
|
||||
FileClass * OutputFile;
|
||||
};
|
||||
|
||||
|
||||
class BufferTransmuter {
|
||||
public:
|
||||
BufferTransmuter(void * buffer = NULL) : BufferPtr(buffer) {}
|
||||
|
||||
virtual void Attach(void * buffer) {BufferPtr = buffer;}
|
||||
virtual void Flush(void) {}
|
||||
virtual void Put(const void * input, unsigned length) {if (BufferPtr) {memcpy(BufferPtr, input, length);((char *&)BufferPtr) += length;}}
|
||||
|
||||
protected:
|
||||
void * BufferPtr;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
64
CODE/BUGS.TXT
Normal file
64
CODE/BUGS.TXT
Normal file
@ -0,0 +1,64 @@
|
||||
Fixed:
|
||||
A415,A436,A437,A446,A447,A453,A466,A475,A488,
|
||||
B171,B326,B407,B443,B530,B550,B566,B578,B600,
|
||||
B609,B626,B628,B632,B637,B641,B644,B655,B658,
|
||||
B675,B678,B684,B685,B688,B690,B698,B711,B715,
|
||||
B726,B730,B731,B729,B732,B733,B738,B743,B744,
|
||||
B747,B748,B750,B753,B759,B762,B766,B767,B768,
|
||||
B770,B774,B775,B777,B778,B780,B781,B786,B795,
|
||||
B797,B798,B805,C1001,C1007,C1011,C1012,C1014,
|
||||
C1017,C1018,C1020,C1024,C1031,C1037,C1042,C1045,
|
||||
C1052,C1061,C1054,C288,C487,C543,C546,
|
||||
C666,C671,C697,C702,C773,C841,C856,C869,C871,
|
||||
C887,C888,C904,C919,C922,C923,C925,C926
|
||||
C927,C930,C932,C936,C938,C939,C942,C945,C947,
|
||||
C953,C954,C962,C966,C967,C968,C975,C976,C977
|
||||
C981,C982
|
||||
|
||||
Unsolved:
|
||||
A035,A248,A352,A383,A417,A419,A420,A427,A445,A449,
|
||||
A450,A455,A456,A457,A469,A470,A477,A478,A480,B005,
|
||||
B042,B206,B207,B247,B284,B356,B418,B430,B467,B536,
|
||||
B548,B549,B559,B633,B674,B686,B703,B714,B725,B740,
|
||||
B745,B785,B787,B794,B796,B799,B802,B809,B817,B823,
|
||||
C033,C072,C1000,C1002,C1004,C1006,C1008,C1009,C1013,C1016,
|
||||
C1022,C1026,C1028,C1029,C1030,C1047,C1053,C1054,C1056,C1057,
|
||||
C1059,C197,C318,C407,C409,C453,C502,C527,C530,C551,
|
||||
C554,C573,C606,C676,C682,C694,C750,C776,C793,C811,
|
||||
C821,C834,C867,C872,C877,C881,C896,C898,C901,C921,
|
||||
C928,C929,C931,C933,C934,C940,C941,C943,C944,C946,
|
||||
C952,C961,C964,C965,C969,C971,C794,C987,C988,C992,
|
||||
C997
|
||||
|
||||
Old / Need more info / non-repeatable (maybe it's fixed now?):
|
||||
A380,A388,A401,A414,A482,B445,B791,
|
||||
A342,A402,A413,A434,A443,A460,A461,A462,A463,A468,
|
||||
A472,A473,A476,A485,A489,A490,B1044,B513,B524,B608
|
||||
B721,B773,B789,B807,B812,C570,C633,C654,C744,C778,
|
||||
C853,C913,C963,C991,C998
|
||||
|
||||
Modem/Net Bug (for Bill):
|
||||
A431,A452,A454,A464,A471,A481,A483,A486,A487,
|
||||
B742,B760,B761,B764,B765,B772,B792,C1025,C1036,C1038
|
||||
C883,C886,C895,C950,C951,C956,C993,C995
|
||||
|
||||
Design Bug (for Erik):
|
||||
A432,A433,A448,A479,B041,B414,B659,B717,B719,B720,
|
||||
B722,B723,B727,B728,B735,B736,B737,B741,
|
||||
B756,B757,B758,B784,B802,B803,B808,B810,B815,
|
||||
B816,B818,B822,C1010,C1023,C1027,C1035,C1044,
|
||||
C1062,C534,C568,C637,C663,C918,C920,C924,C948,
|
||||
C949,C986,C996,C999
|
||||
|
||||
Setup/Install/README.TXT Bug:
|
||||
A458,A467,A484,B395,C957,C958,C959
|
||||
|
||||
Not Bug, repeated bug, suggestion, can't fix, or huh?:
|
||||
A459,B1024,B218,B507,B522,B541,B546,B592,B593,B596,
|
||||
B687,B724,B739,B746,B749,B763,B776,B779,B782,B783,
|
||||
B790,B793,B806,B819,B820,B821,C1003,C1005,C1015,C1019,
|
||||
C1032,C1033,C1034,C1039,C1040,C1043,C1048,
|
||||
C1050,C1051,C1055,C1058,C1060,C1063,C336,C377,
|
||||
C491,C537,C541,C578,C691,C703,C716,C781,C792,C838,
|
||||
C854,C860,C879,C912,C915,C935,C937,C955,C970,C978,
|
||||
C979,C980,C983,C984,C985,C990
|
5712
CODE/BUILDING.CPP
Normal file
5712
CODE/BUILDING.CPP
Normal file
File diff suppressed because it is too large
Load Diff
356
CODE/BUILDING.H
Normal file
356
CODE/BUILDING.H
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BUILDING.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BUILDING.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : April 14, 1994 *
|
||||
* *
|
||||
* Last Update : April 14, 1994 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef BUILDING_H
|
||||
#define BUILDING_H
|
||||
|
||||
#include "radio.h"
|
||||
#include "cargo.h"
|
||||
#include "mission.h"
|
||||
#include "bullet.h"
|
||||
#include "target.h"
|
||||
#include "factory.h"
|
||||
#include "techno.h"
|
||||
|
||||
#define MAX_DOOR_STAGE 18 // # of frames of door opening on weapons factory
|
||||
#define DOOR_OPEN_STAGE 9 // frame on which the door is entirely open
|
||||
#define MAX_REPAIR_ANIM_STAGE 5 // # of stages of anim for repair center cycling
|
||||
|
||||
/****************************************************************************
|
||||
** For each instance of a building in the game, there is one of
|
||||
** these structures. This structure holds information that is specific
|
||||
** and dynamic for a particular building.
|
||||
*/
|
||||
class BuildingClass : public TechnoClass
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
** This points to the control data that gives this building its characteristics.
|
||||
*/
|
||||
CCPtr<BuildingTypeClass> Class;
|
||||
|
||||
/*
|
||||
** If this building is in the process of producing something, then this
|
||||
** will point to the factory manager.
|
||||
*/
|
||||
CCPtr<FactoryClass> Factory;
|
||||
|
||||
/*
|
||||
** This is the house that originally owned this factory. Objects buildable
|
||||
** by this house type will be produced from this factory regardless of who
|
||||
** the current owner is.
|
||||
*/
|
||||
HousesType ActLike;
|
||||
|
||||
/*
|
||||
** This building should be rebuilt if it is destroyed. This is in spite
|
||||
** of the condition of the prebuilt base list.
|
||||
*/
|
||||
unsigned IsToRebuild:1;
|
||||
|
||||
/*
|
||||
** Is the building allowed to repair itself?
|
||||
*/
|
||||
unsigned IsToRepair:1;
|
||||
|
||||
/*
|
||||
** If the computer owns this building, then it is allowed to sell it if
|
||||
** the situation warrants it. In the other case, it cannot sell the
|
||||
** building regardless of conditions.
|
||||
*/
|
||||
unsigned IsAllowedToSell:1;
|
||||
|
||||
/*
|
||||
** If the building is at a good point to change orders, then this
|
||||
** flag will be set to true.
|
||||
*/
|
||||
unsigned IsReadyToCommence:1;
|
||||
|
||||
/*
|
||||
** If this building is currently spending money to repair itself, then
|
||||
** this flag is true. It will automatically be set to false when the building
|
||||
** has reached full strength, when money is exhausted, or if the player
|
||||
** specifically stops the repair process.
|
||||
*/
|
||||
unsigned IsRepairing:1;
|
||||
|
||||
/*
|
||||
** If repair is currently in progress and this flag is true, then a wrench graphic
|
||||
** will be overlaid on the building to give visual feedback for the repair process.
|
||||
*/
|
||||
unsigned IsWrenchVisible:1;
|
||||
|
||||
/*
|
||||
** This flag is set when a commando has raided the building and planted
|
||||
** plastic explosives. When the CommandoCountDown timer expires, the
|
||||
** building takes massive damage.
|
||||
*/
|
||||
unsigned IsGoingToBlow:1;
|
||||
|
||||
/*
|
||||
** If this building was destroyed by some method that would prevent
|
||||
** survivors, then this flag will be true.
|
||||
*/
|
||||
unsigned IsSurvivorless:1;
|
||||
|
||||
/*
|
||||
** These state control variables are used by the obelisk for the charging
|
||||
** animation.
|
||||
*/
|
||||
unsigned IsCharging:1;
|
||||
unsigned IsCharged:1;
|
||||
|
||||
/*
|
||||
** A building that has been captured will not contain the full compliment
|
||||
** of crew. This is true even if it subsequently gets captured back.
|
||||
*/
|
||||
unsigned IsCaptured:1;
|
||||
|
||||
/*
|
||||
** Used by the gap generator to decide if it should jam or unjam
|
||||
*/
|
||||
unsigned IsJamming:1;
|
||||
|
||||
/*
|
||||
** Used by radar facilities to know if they're being jammed by a mobile
|
||||
** radar jammer
|
||||
*/
|
||||
unsigned IsJammed:1;
|
||||
|
||||
/*
|
||||
** Used only by advanced tech center, this keeps track of whether the
|
||||
** GPS satellite has been fired or not.
|
||||
*/
|
||||
unsigned HasFired:1;
|
||||
|
||||
/*
|
||||
** If Grand_Opening was already called for this building, then this
|
||||
** flag will be true. By utilizing this flag, multiple inadvertant
|
||||
** calls to Grand_Opening won't cause problems.
|
||||
*/
|
||||
unsigned HasOpened:1;
|
||||
|
||||
/*
|
||||
** Special countdown to destruction value. If the building is destroyed,
|
||||
** it won't actually be removed from the map until this value reaches
|
||||
** zero. This delay is for cosmetic reasons.
|
||||
*/
|
||||
CDTimerClass<FrameTimerClass> CountDown;
|
||||
|
||||
/*
|
||||
** This is the current animation processing state that the building is
|
||||
** in.
|
||||
*/
|
||||
BStateType BState;
|
||||
BStateType QueueBState;
|
||||
|
||||
/*
|
||||
** For multiplayer games, this keeps track of the last house to damage
|
||||
** this building, so if it burns to death or otherwise gradually dies,
|
||||
** proper credit can be given for the kill.
|
||||
*/
|
||||
HousesType WhoLastHurtMe;
|
||||
|
||||
/*
|
||||
** This is the saboteur responsible for this building's destruction.
|
||||
*/
|
||||
TARGET WhomToRepay;
|
||||
|
||||
/*
|
||||
** This is a record of the last strength of the building. Every so often,
|
||||
** it will compare this strength to the current strength. If there is a
|
||||
** discrepancy, then the owner power is adjusted accordingly.
|
||||
*/
|
||||
int LastStrength;
|
||||
|
||||
/*
|
||||
** This is a target id of an animation we're keeping track of. Examples
|
||||
** of this usage are the advanced tech center, which needs to know
|
||||
** when the sputdoor animation has reached a certain stage.
|
||||
*/
|
||||
TARGET AnimToTrack;
|
||||
|
||||
/*
|
||||
** This is the countdown timer that regulates placement retry logic
|
||||
** for factory type buildings.
|
||||
*/
|
||||
CDTimerClass<FrameTimerClass> PlacementDelay;
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
** Constructors, Destructors, and overloaded operators.
|
||||
*/
|
||||
static void * operator new(size_t size);
|
||||
static void * operator new(size_t , void * ptr) {return(ptr);};
|
||||
static void operator delete(void *ptr);
|
||||
BuildingClass(StructType type, HousesType house);
|
||||
#ifdef FIXIT_MULTI_SAVE
|
||||
BuildingClass(NoInitClass const & x) : TechnoClass(x), Class(x), Factory(x), CountDown(x), PlacementDelay(x) {};
|
||||
#else
|
||||
BuildingClass(NoInitClass const & x) : TechnoClass(x), Class(x), CountDown(x), PlacementDelay(x) {};
|
||||
#endif
|
||||
virtual ~BuildingClass(void);
|
||||
operator StructType(void) const {return Class->Type;};
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
** Member function prototypes.
|
||||
*/
|
||||
static void Init(void);
|
||||
|
||||
TARGET Target_Scan(void);
|
||||
BuildingTypeClass::AnimControlType const * Fetch_Anim_Control(void) {return (&Class->Anims[BState]);};
|
||||
|
||||
/*
|
||||
** Query functions.
|
||||
*/
|
||||
virtual int Value(void) const;
|
||||
virtual void const * Get_Image_Data(void) const;
|
||||
virtual int How_Many_Survivors(void) const;
|
||||
virtual DirType Turret_Facing(void) const;
|
||||
virtual CELL Find_Exit_Cell(TechnoClass const * techno) const;
|
||||
virtual InfantryType Crew_Type(void) const;
|
||||
virtual int Pip_Count(void) const;
|
||||
virtual bool Can_Player_Move(void) const;
|
||||
virtual ActionType What_Action(ObjectClass const * target) const;
|
||||
virtual ActionType What_Action(CELL cell) const;
|
||||
virtual bool Can_Demolish(void) const;
|
||||
virtual ObjectTypeClass const & Class_Of(void) const {return *Class;};
|
||||
virtual DirType Fire_Direction(void) const;
|
||||
virtual short const * Overlap_List(bool redraw=false) const;
|
||||
int Shape_Number(void) const;
|
||||
int Power_Output(void) const;
|
||||
CELL Check_Point(CheckPointType cp) const;
|
||||
|
||||
/*
|
||||
** Coordinate inquiry functions. These are used for both display and
|
||||
** combat purposes.
|
||||
*/
|
||||
virtual COORDINATE Target_Coord(void) const;
|
||||
virtual COORDINATE Docking_Coord(void) const;
|
||||
virtual COORDINATE Center_Coord(void) const;
|
||||
virtual COORDINATE Sort_Y(void) const;
|
||||
virtual COORDINATE Exit_Coord(void) const;
|
||||
|
||||
/*
|
||||
** Object entry and exit from the game system.
|
||||
*/
|
||||
virtual void Detach(TARGET target, bool all);
|
||||
virtual void Detach_All(bool all=true);
|
||||
virtual void Grand_Opening(bool captured = false);
|
||||
virtual void Update_Buildables(void);
|
||||
virtual MoveType Can_Enter_Cell(CELL cell, FacingType = FACING_NONE) const;
|
||||
virtual bool Unlimbo(COORDINATE , DirType dir = DIR_N);
|
||||
virtual bool Limbo(void);
|
||||
|
||||
/*
|
||||
** Display and rendering support functionality. Supports imagery and how
|
||||
** object interacts with the map and thus indirectly controls rendering.
|
||||
*/
|
||||
virtual void const * Remap_Table(void);
|
||||
virtual int Exit_Object(TechnoClass * base);
|
||||
virtual void Draw_It(int x, int y, WindowNumberType window) const;
|
||||
virtual bool Mark(MarkType mark=MARK_CHANGE);
|
||||
virtual void Fire_Out(void);
|
||||
void Begin_Mode(BStateType bstate);
|
||||
|
||||
/*
|
||||
** User I/O.
|
||||
*/
|
||||
virtual void Active_Click_With(ActionType action, ObjectClass * object);
|
||||
virtual void Active_Click_With(ActionType action, CELL cell);
|
||||
|
||||
/*
|
||||
** Combat related.
|
||||
*/
|
||||
virtual void Death_Announcement(TechnoClass const * source=0) const;
|
||||
virtual FireErrorType Can_Fire(TARGET, int which) const;
|
||||
virtual TARGET Greatest_Threat(ThreatType threat) const;
|
||||
virtual ResultType Take_Damage(int & damage, int distance, WarheadType warhead, TechnoClass * source=0, bool forced=false);
|
||||
virtual bool Captured(HouseClass * newowner);
|
||||
void Update_Radar_Spied(void);
|
||||
|
||||
/*
|
||||
** AI.
|
||||
*/
|
||||
void Charging_AI(void);
|
||||
void Rotation_AI(void);
|
||||
void Factory_AI(void);
|
||||
void Repair_AI(void);
|
||||
void Animation_AI(void);
|
||||
virtual bool Revealed(HouseClass * house);
|
||||
virtual void Repair(int control);
|
||||
virtual void Sell_Back(int control);
|
||||
virtual RadioMessageType Receive_Message(RadioClass * from, RadioMessageType message, long & param);
|
||||
virtual void AI(void);
|
||||
virtual void Assign_Target(TARGET target);
|
||||
virtual bool Toggle_Primary(void);
|
||||
bool Flush_For_Placement(TechnoClass * techno, CELL cell);
|
||||
|
||||
virtual int Mission_Unload(void);
|
||||
virtual int Mission_Repair(void);
|
||||
virtual int Mission_Attack(void);
|
||||
virtual int Mission_Harvest(void);
|
||||
virtual int Mission_Guard(void);
|
||||
virtual int Mission_Construction(void);
|
||||
virtual int Mission_Deconstruction(void);
|
||||
virtual int Mission_Missile(void);
|
||||
virtual void Enter_Idle_Mode(bool initial=false);
|
||||
void Remove_Gap_Effect(void);
|
||||
|
||||
/*
|
||||
** Scenario and debug support.
|
||||
*/
|
||||
#ifdef CHEAT_KEYS
|
||||
virtual void Debug_Dump(MonoClass *mono) const;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** File I/O.
|
||||
*/
|
||||
static void Read_INI(CCINIClass & ini);
|
||||
static void Write_INI(CCINIClass & ini);
|
||||
static char *INI_Name(void) {return "STRUCTURES";};
|
||||
bool Load(Straw & file);
|
||||
bool Save(Pipe & file) const;
|
||||
|
||||
private:
|
||||
void Drop_Debris(TARGET source = TARGET_NONE);
|
||||
|
||||
static COORDINATE const CenterOffset[BSIZE_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
1070
CODE/BULLET.CPP
Normal file
1070
CODE/BULLET.CPP
Normal file
File diff suppressed because it is too large
Load Diff
149
CODE/BULLET.H
Normal file
149
CODE/BULLET.H
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/BULLET.H 2 3/06/97 1:46p Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : BULLET.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : April 23, 1994 *
|
||||
* *
|
||||
* Last Update : April 23, 1994 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef BULLET_H
|
||||
#define BULLET_H
|
||||
|
||||
#include "object.h"
|
||||
#include "fly.h"
|
||||
#include "fuse.h"
|
||||
|
||||
|
||||
class BulletClass : public ObjectClass,
|
||||
public FlyClass,
|
||||
public FuseClass
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
** This specifies exactly what kind of bullet this is. All of the static attributes
|
||||
** for this bullet is located in the BulletTypeClass pointed to by this variable.
|
||||
*/
|
||||
CCPtr<BulletTypeClass> Class;
|
||||
|
||||
private:
|
||||
/*
|
||||
** Records who sent this "present" so that an appropriate "thank you" can
|
||||
** be returned.
|
||||
*/
|
||||
TechnoClass * Payback;
|
||||
|
||||
/*
|
||||
** This is the facing that the projectile is travelling.
|
||||
*/
|
||||
FacingClass PrimaryFacing;
|
||||
|
||||
public:
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
** Constructors, Destructors, and overloaded operators.
|
||||
*/
|
||||
static void * operator new(size_t size);
|
||||
static void * operator new(size_t , void * ptr) {return(ptr);};
|
||||
static void operator delete(void *ptr);
|
||||
BulletClass(BulletType id, TARGET target, TechnoClass * Payback, int strength, WarheadType warhead, int speed);
|
||||
#ifdef FIXIT_MULTI_SAVE
|
||||
BulletClass(NoInitClass const & x) : ObjectClass(x), Class(x), FlyClass(x), FuseClass(x), PrimaryFacing(x) {};
|
||||
#else
|
||||
BulletClass(NoInitClass const & x) : ObjectClass(x), Class(x), FlyClass(x), FuseClass(x) {};
|
||||
#endif
|
||||
virtual ~BulletClass(void);
|
||||
operator BulletType(void) const {return Class->Type;};
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
** Member function prototypes.
|
||||
*/
|
||||
static void Init(void);
|
||||
|
||||
bool Is_Forced_To_Explode(COORDINATE & coord) const;
|
||||
void Bullet_Explodes(bool forced);
|
||||
int Shape_Number(void) const;
|
||||
virtual LayerType In_Which_Layer(void) const;
|
||||
virtual COORDINATE Sort_Y(void) const;
|
||||
virtual void Assign_Target(TARGET target) {TarCom = target;};
|
||||
virtual bool Unlimbo(COORDINATE , DirType facing = DIR_N);
|
||||
virtual ObjectTypeClass const & Class_Of(void) const {return *Class;};
|
||||
virtual void Detach(TARGET target, bool all);
|
||||
virtual void Draw_It(int x, int y, WindowNumberType window) const;
|
||||
virtual bool Mark(MarkType mark=MARK_CHANGE);
|
||||
virtual void AI(void);
|
||||
virtual short const * Occupy_List(bool = false) const;
|
||||
virtual short const * Overlap_List(void) const {return Occupy_List(false);};
|
||||
virtual COORDINATE Target_Coord(void) const;
|
||||
|
||||
/*
|
||||
** File I/O.
|
||||
*/
|
||||
bool Load(Straw & file);
|
||||
bool Save(Pipe & file) const;
|
||||
virtual void Code_Pointers(void);
|
||||
virtual void Decode_Pointers(void);
|
||||
|
||||
/*
|
||||
** If this bullet is forced to be inaccurate because of some outside means. A tank
|
||||
** firing while moving is a good example.
|
||||
*/
|
||||
unsigned IsInaccurate:1;
|
||||
|
||||
private:
|
||||
// Crude animation flag.
|
||||
unsigned IsToAnimate:1;
|
||||
|
||||
/*
|
||||
** Is this missile allowed to come in from out of bounds?
|
||||
*/
|
||||
unsigned IsLocked:1;
|
||||
|
||||
/*
|
||||
** This is the target of the projectile. It is especially significant for those projectiles
|
||||
** that home in on a target.
|
||||
*/
|
||||
TARGET TarCom;
|
||||
|
||||
/*
|
||||
** The speed of this projectile.
|
||||
*/
|
||||
int MaxSpeed;
|
||||
|
||||
/*
|
||||
** The warhead of this projectile.
|
||||
*/
|
||||
WarheadType Warhead;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
410
CODE/C&CZERO.PJT
Normal file
410
CODE/C&CZERO.PJT
Normal file
@ -0,0 +1,410 @@
|
||||
;Codewright Project File (do not remove or modify this line)
|
||||
[ProjInit]
|
||||
ProjSetConfigFlags=0x00010140
|
||||
|
||||
[Files]
|
||||
c:\projects\c&c\code\aadata.cpp
|
||||
c:\projects\c&czero\code\aadata.cpp
|
||||
c:\projects\c&czero\code\abstract.cpp
|
||||
c:\projects\c&czero\code\abstract.h
|
||||
c:\projects\c&czero\code\adata.cpp
|
||||
c:\projects\c&czero\code\ADPCM.CPP
|
||||
c:\projects\c&czero\code\aircraft.cpp
|
||||
c:\projects\c&czero\code\aircraft.h
|
||||
c:\projects\c&czero\code\alloc.cpp
|
||||
c:\projects\c&czero\code\anim.cpp
|
||||
c:\projects\c&czero\code\anim.h
|
||||
c:\projects\c&czero\code\audio.cpp
|
||||
c:\projects\c&czero\code\audio.h
|
||||
c:\projects\c&czero\code\base.cpp
|
||||
c:\projects\c&czero\code\base.h
|
||||
c:\projects\c&czero\code\bbdata.cpp
|
||||
c:\projects\c&czero\code\bdata.cpp
|
||||
c:\projects\c&czero\code\BFIOFILE.CPP
|
||||
c:\projects\c&czero\code\BFIOFILE.H
|
||||
c:\projects\c&czero\code\building.cpp
|
||||
c:\projects\c&czero\code\building.h
|
||||
c:\projects\c&czero\code\bullet.cpp
|
||||
c:\projects\c&czero\code\bullet.h
|
||||
c:\projects\c&czero\code\cargo.cpp
|
||||
c:\projects\c&czero\code\cargo.h
|
||||
c:\projects\c&czero\code\CARRY.CPP
|
||||
c:\projects\c&czero\code\CARRY.H
|
||||
c:\projects\c&czero\code\ccfile.cpp
|
||||
c:\projects\c&czero\code\ccfile.h
|
||||
c:\projects\c&czero\code\cdata.cpp
|
||||
c:\projects\c&czero\code\cdfile.cpp
|
||||
c:\projects\c&czero\code\cdfile.h
|
||||
c:\projects\c&czero\code\cell.cpp
|
||||
c:\projects\c&czero\code\cell.h
|
||||
c:\projects\c&czero\code\checkbox.cpp
|
||||
c:\projects\c&czero\code\checkbox.h
|
||||
c:\projects\c&czero\code\cheklist.cpp
|
||||
c:\projects\c&czero\code\cheklist.h
|
||||
c:\projects\c&czero\code\colrlist.cpp
|
||||
c:\projects\c&czero\code\colrlist.h
|
||||
c:\projects\c&czero\code\combat.cpp
|
||||
c:\projects\c&czero\code\combuf.cpp
|
||||
c:\projects\c&czero\code\combuf.h
|
||||
c:\projects\c&czero\code\compat.h
|
||||
c:\projects\c&czero\code\comqueue.cpp
|
||||
c:\projects\c&czero\code\comqueue.h
|
||||
c:\projects\c&czero\code\confdlg.cpp
|
||||
c:\projects\c&czero\code\confdlg.h
|
||||
c:\projects\c&czero\code\connect.cpp
|
||||
c:\projects\c&czero\code\connect.h
|
||||
c:\projects\c&czero\code\connmgr.h
|
||||
c:\projects\c&czero\code\conquer.cpp
|
||||
c:\projects\c&czero\code\conquer.h
|
||||
c:\projects\c&czero\code\const.cpp
|
||||
c:\projects\c&czero\code\control.cpp
|
||||
c:\projects\c&czero\code\control.h
|
||||
c:\projects\c&czero\code\coord.cpp
|
||||
c:\projects\c&czero\code\crc.cpp
|
||||
c:\projects\c&czero\code\crc.h
|
||||
c:\projects\c&czero\code\credits.cpp
|
||||
c:\projects\c&czero\code\credits.h
|
||||
c:\projects\c&czero\code\crew.cpp
|
||||
c:\projects\c&czero\code\crew.h
|
||||
c:\projects\c&czero\code\cwstub.c
|
||||
c:\projects\c&czero\code\debug.cpp
|
||||
c:\projects\c&czero\code\debug.h
|
||||
c:\projects\c&czero\code\defines.h
|
||||
c:\projects\c&czero\code\descdlg.cpp
|
||||
c:\projects\c&czero\code\descdlg.h
|
||||
c:\projects\c&czero\code\dial8.cpp
|
||||
c:\projects\c&czero\code\dial8.h
|
||||
c:\projects\c&czero\code\dialog.cpp
|
||||
c:\projects\c&czero\code\display.cpp
|
||||
c:\projects\c&czero\code\display.h
|
||||
c:\projects\c&czero\code\door.cpp
|
||||
c:\projects\c&czero\code\door.h
|
||||
c:\projects\c&czero\code\dpmi.cpp
|
||||
c:\projects\c&czero\code\dpmi.h
|
||||
c:\projects\c&czero\code\drive.cpp
|
||||
c:\projects\c&czero\code\drive.h
|
||||
c:\projects\c&czero\code\drop.cpp
|
||||
c:\projects\c&czero\code\drop.h
|
||||
c:\projects\c&czero\code\DTABLE.CPP
|
||||
c:\projects\c&czero\code\edit.cpp
|
||||
c:\projects\c&czero\code\edit.h
|
||||
c:\projects\c&czero\code\ending.cpp
|
||||
c:\projects\c&czero\code\ending.h
|
||||
c:\projects\c&czero\code\event.cpp
|
||||
c:\projects\c&czero\code\event.h
|
||||
c:\projects\c&czero\code\expand.cpp
|
||||
c:\projects\c&czero\code\externs.h
|
||||
c:\projects\c&czero\code\FACE.CPP
|
||||
c:\projects\c&czero\code\FACE.H
|
||||
c:\projects\c&czero\code\facing.cpp
|
||||
c:\projects\c&czero\code\facing.h
|
||||
c:\projects\c&czero\code\factory.cpp
|
||||
c:\projects\c&czero\code\factory.h
|
||||
c:\projects\c&czero\code\findpath.cpp
|
||||
c:\projects\c&czero\code\flasher.cpp
|
||||
c:\projects\c&czero\code\flasher.h
|
||||
c:\projects\c&czero\code\fly.cpp
|
||||
c:\projects\c&czero\code\fly.h
|
||||
c:\projects\c&czero\code\foot.cpp
|
||||
c:\projects\c&czero\code\foot.h
|
||||
c:\projects\c&czero\code\ftimer.h
|
||||
c:\projects\c&czero\code\function.h
|
||||
c:\projects\c&czero\code\fuse.cpp
|
||||
c:\projects\c&czero\code\fuse.h
|
||||
c:\projects\c&czero\code\gadget.cpp
|
||||
c:\projects\c&czero\code\gadget.h
|
||||
c:\projects\c&czero\code\gamedlg.cpp
|
||||
c:\projects\c&czero\code\gamedlg.h
|
||||
c:\projects\c&czero\code\gauge.cpp
|
||||
c:\projects\c&czero\code\gauge.h
|
||||
c:\projects\c&czero\code\globals.cpp
|
||||
c:\projects\c&czero\code\goptions.cpp
|
||||
c:\projects\c&czero\code\goptions.h
|
||||
c:\projects\c&czero\code\gscreen.cpp
|
||||
c:\projects\c&czero\code\gscreen.h
|
||||
c:\projects\c&czero\code\hdata.cpp
|
||||
c:\projects\c&czero\code\heap.cpp
|
||||
c:\projects\c&czero\code\heap.h
|
||||
c:\projects\c&czero\code\help.cpp
|
||||
c:\projects\c&czero\code\help.h
|
||||
c:\projects\c&czero\code\house.cpp
|
||||
c:\projects\c&czero\code\house.h
|
||||
c:\projects\c&czero\code\HSV.CPP
|
||||
c:\projects\c&czero\code\HSV.H
|
||||
c:\projects\c&czero\code\idata.cpp
|
||||
c:\projects\c&czero\code\infantry.cpp
|
||||
c:\projects\c&czero\code\infantry.h
|
||||
c:\projects\c&czero\code\ini.cpp
|
||||
c:\projects\c&czero\code\inibin.cpp
|
||||
c:\projects\c&czero\code\inicode.cpp
|
||||
c:\projects\c&czero\code\init.cpp
|
||||
c:\projects\c&czero\code\intro.cpp
|
||||
c:\projects\c&czero\code\intro.h
|
||||
c:\projects\c&czero\code\iomap.cpp
|
||||
c:\projects\c&czero\code\ioobj.cpp
|
||||
c:\projects\c&czero\code\ipx.cpp
|
||||
c:\projects\c&czero\code\ipx.h
|
||||
c:\projects\c&czero\code\ipxaddr.cpp
|
||||
c:\projects\c&czero\code\ipxaddr.h
|
||||
c:\projects\c&czero\code\ipxconn.cpp
|
||||
c:\projects\c&czero\code\ipxconn.h
|
||||
c:\projects\c&czero\code\ipxgconn.cpp
|
||||
c:\projects\c&czero\code\ipxgconn.h
|
||||
c:\projects\c&czero\code\ipxmgr.cpp
|
||||
c:\projects\c&czero\code\ipxmgr.h
|
||||
c:\projects\c&czero\code\itable.cpp
|
||||
c:\projects\c&czero\code\jshell.cpp
|
||||
c:\projects\c&czero\code\jshell.h
|
||||
c:\projects\c&czero\code\keyframe.cpp
|
||||
c:\projects\c&czero\code\layer.cpp
|
||||
c:\projects\c&czero\code\layer.h
|
||||
c:\projects\c&czero\code\lcwuncmp.cpp
|
||||
c:\projects\c&czero\code\led.h
|
||||
c:\projects\c&czero\code\link.cpp
|
||||
c:\projects\c&czero\code\link.h
|
||||
c:\projects\c&czero\code\lint.h
|
||||
c:\projects\c&czero\code\list.cpp
|
||||
c:\projects\c&czero\code\list.h
|
||||
c:\projects\c&czero\code\loaddlg.cpp
|
||||
c:\projects\c&czero\code\loaddlg.h
|
||||
c:\projects\c&czero\code\logic.cpp
|
||||
c:\projects\c&czero\code\logic.h
|
||||
c:\projects\c&czero\code\map.cpp
|
||||
c:\projects\c&czero\code\map.h
|
||||
c:\projects\c&czero\code\mapeddlg.cpp
|
||||
c:\projects\c&czero\code\mapedit.cpp
|
||||
c:\projects\c&czero\code\mapedit.h
|
||||
c:\projects\c&czero\code\mapedplc.cpp
|
||||
c:\projects\c&czero\code\mapedsel.cpp
|
||||
c:\projects\c&czero\code\mapedtm.cpp
|
||||
c:\projects\c&czero\code\mapsel.cpp
|
||||
c:\projects\c&czero\code\menus.cpp
|
||||
c:\projects\c&czero\code\message.h
|
||||
c:\projects\c&czero\code\mission.cpp
|
||||
c:\projects\c&czero\code\mission.h
|
||||
c:\projects\c&czero\code\mixfile.cpp
|
||||
c:\projects\c&czero\code\mixfile.h
|
||||
c:\projects\c&czero\code\monoc.cpp
|
||||
c:\projects\c&czero\code\monoc.h
|
||||
c:\projects\c&czero\code\mouse.cpp
|
||||
c:\projects\c&czero\code\mouse.h
|
||||
c:\projects\c&czero\code\mplayer.cpp
|
||||
c:\projects\c&czero\code\msgbox.cpp
|
||||
c:\projects\c&czero\code\msgbox.h
|
||||
c:\projects\c&czero\code\msglist.cpp
|
||||
c:\projects\c&czero\code\msglist.h
|
||||
c:\projects\c&czero\code\netdlg.cpp
|
||||
c:\projects\c&czero\code\nullconn.cpp
|
||||
c:\projects\c&czero\code\nullconn.h
|
||||
c:\projects\c&czero\code\nulldlg.cpp
|
||||
c:\projects\c&czero\code\nullmgr.cpp
|
||||
c:\projects\c&czero\code\nullmgr.h
|
||||
c:\projects\c&czero\code\object.cpp
|
||||
c:\projects\c&czero\code\object.h
|
||||
c:\projects\c&czero\code\odata.cpp
|
||||
c:\projects\c&czero\code\options.cpp
|
||||
c:\projects\c&czero\code\options.h
|
||||
c:\projects\c&czero\code\overlay.cpp
|
||||
c:\projects\c&czero\code\overlay.h
|
||||
c:\projects\c&czero\code\PALETTE.CPP
|
||||
c:\projects\c&czero\code\PALETTE.H
|
||||
c:\projects\c&czero\code\phone.h
|
||||
c:\projects\c&czero\code\power.cpp
|
||||
c:\projects\c&czero\code\power.h
|
||||
c:\projects\c&czero\code\profile.cpp
|
||||
c:\projects\c&czero\code\queue.cpp
|
||||
c:\projects\c&czero\code\queue.h
|
||||
c:\projects\c&czero\code\radar.cpp
|
||||
c:\projects\c&czero\code\radar.h
|
||||
c:\projects\c&czero\code\radio.cpp
|
||||
c:\projects\c&czero\code\radio.h
|
||||
c:\projects\c&czero\code\rand.cpp
|
||||
c:\projects\c&czero\code\RANDOM.CPP
|
||||
c:\projects\c&czero\code\RANDOM.H
|
||||
c:\projects\c&czero\code\rawfile.cpp
|
||||
c:\projects\c&czero\code\rawfile.h
|
||||
c:\projects\c&czero\code\region.h
|
||||
c:\projects\c&czero\code\reinf.cpp
|
||||
c:\projects\c&czero\code\RGB.CPP
|
||||
c:\projects\c&czero\code\RGB.H
|
||||
c:\projects\c&czero\code\ROTBMP.CPP
|
||||
c:\projects\c&czero\code\ROTBMP.H
|
||||
c:\projects\c&czero\code\savedlg.h
|
||||
c:\projects\c&czero\code\saveload.cpp
|
||||
c:\projects\c&czero\code\scenario.cpp
|
||||
c:\projects\c&czero\code\SCENARIO.H
|
||||
c:\projects\c&czero\code\score.cpp
|
||||
c:\projects\c&czero\code\score.h
|
||||
c:\projects\c&czero\code\screen.h
|
||||
c:\projects\c&czero\code\scroll.cpp
|
||||
c:\projects\c&czero\code\scroll.h
|
||||
c:\projects\c&czero\code\sdata.cpp
|
||||
c:\projects\c&czero\code\SESSION.CPP
|
||||
c:\projects\c&czero\code\SESSION.H
|
||||
c:\projects\c&czero\code\shapebtn.cpp
|
||||
c:\projects\c&czero\code\shapebtn.h
|
||||
c:\projects\c&czero\code\sidebar.cpp
|
||||
c:\projects\c&czero\code\sidebar.h
|
||||
c:\projects\c&czero\code\slider.cpp
|
||||
c:\projects\c&czero\code\slider.h
|
||||
c:\projects\c&czero\code\smudge.cpp
|
||||
c:\projects\c&czero\code\smudge.h
|
||||
c:\projects\c&czero\code\sounddlg.cpp
|
||||
c:\projects\c&czero\code\sounddlg.h
|
||||
c:\projects\c&czero\code\special.cpp
|
||||
c:\projects\c&czero\code\special.h
|
||||
c:\projects\c&czero\code\SPRITE.CPP
|
||||
c:\projects\c&czero\code\stage.h
|
||||
c:\projects\c&czero\code\startup.cpp
|
||||
c:\projects\c&czero\code\super.cpp
|
||||
c:\projects\c&czero\code\super.h
|
||||
c:\projects\c&czero\code\tab.cpp
|
||||
c:\projects\c&czero\code\tab.h
|
||||
c:\projects\c&czero\code\TACTION.CPP
|
||||
c:\projects\c&czero\code\TACTION.H
|
||||
c:\projects\c&czero\code\target.cpp
|
||||
c:\projects\c&czero\code\target.h
|
||||
c:\projects\c&czero\code\tdata.cpp
|
||||
c:\projects\c&czero\code\team.cpp
|
||||
c:\projects\c&czero\code\team.h
|
||||
c:\projects\c&czero\code\teamtype.cpp
|
||||
c:\projects\c&czero\code\teamtype.h
|
||||
c:\projects\c&czero\code\techno.cpp
|
||||
c:\projects\c&czero\code\techno.h
|
||||
c:\projects\c&czero\code\template.cpp
|
||||
c:\projects\c&czero\code\template.h
|
||||
c:\projects\c&czero\code\terrain.cpp
|
||||
c:\projects\c&czero\code\terrain.h
|
||||
c:\projects\c&czero\code\TEVENT.CPP
|
||||
c:\projects\c&czero\code\TEVENT.H
|
||||
c:\projects\c&czero\code\textbtn.cpp
|
||||
c:\projects\c&czero\code\textbtn.h
|
||||
c:\projects\c&czero\code\theme.cpp
|
||||
c:\projects\c&czero\code\theme.h
|
||||
c:\projects\c&czero\code\toggle.cpp
|
||||
c:\projects\c&czero\code\toggle.h
|
||||
c:\projects\c&czero\code\trigger.cpp
|
||||
c:\projects\c&czero\code\trigger.h
|
||||
c:\projects\c&czero\code\txtlabel.cpp
|
||||
c:\projects\c&czero\code\txtlabel.h
|
||||
c:\projects\c&czero\code\type.h
|
||||
c:\projects\c&czero\code\udata.cpp
|
||||
c:\projects\c&czero\code\unit.cpp
|
||||
c:\projects\c&czero\code\unit.h
|
||||
c:\projects\c&czero\code\vdata.cpp
|
||||
c:\projects\c&czero\code\vector.cpp
|
||||
c:\projects\c&czero\code\vector.h
|
||||
c:\projects\c&czero\code\VERSION.CPP
|
||||
c:\projects\c&czero\code\VERSION.H
|
||||
c:\projects\c&czero\code\vessel.cpp
|
||||
c:\projects\c&czero\code\vessel.h
|
||||
c:\projects\c&czero\code\visudlg.cpp
|
||||
c:\projects\c&czero\code\visudlg.h
|
||||
c:\projects\c&czero\code\watcom.h
|
||||
c:\projects\c&czero\code\wwalloc.h
|
||||
c:\projects\c&czero\code\wwfile.h
|
||||
C:\projects\c&czero\code\2KEYFRAM.CPP
|
||||
C:\projects\c&czero\code\BLOWFISH.CPP
|
||||
C:\projects\c&czero\code\BLOWFISH.H
|
||||
C:\projects\c&czero\code\FILEPCX.H
|
||||
C:\projects\c&czero\code\INT.CPP
|
||||
C:\projects\c&czero\code\INT.H
|
||||
C:\projects\c&czero\code\interpal.cpp
|
||||
C:\projects\c&czero\code\language.h
|
||||
C:\projects\c&czero\code\MP.CPP
|
||||
C:\projects\c&czero\code\MP.H
|
||||
C:\projects\c&czero\code\RNG.H
|
||||
C:\projects\c&czero\code\SHA.CPP
|
||||
C:\projects\c&czero\code\SHA.H
|
||||
C:\projects\c&czero\code\tarcom.cpp
|
||||
C:\projects\c&czero\code\tcpip.h
|
||||
C:\projects\c&czero\code\winstub.cpp
|
||||
c:\projects\c&czero\code\BUFFERX.H
|
||||
c:\projects\c&czero\code\ini.h
|
||||
c:\projects\c&czero\code\listnode.h
|
||||
c:\projects\c&czero\code\rules.cpp
|
||||
c:\projects\c&czero\code\rules.h
|
||||
c:\projects\c&czero\code\tarcom.h
|
||||
c:\projects\c&czero\code\turret.cpp
|
||||
c:\projects\c&czero\code\turret.h
|
||||
c:\projects\c&czero\code\warhead.h
|
||||
c:\projects\c&czero\code\weapon.h
|
||||
|
||||
[State]
|
||||
SysSetCwd='C:\projects\c&czero\code'
|
||||
SrchSetFlags=0x000320aa
|
||||
FileSortMode=0x0
|
||||
StateWindowFrame=37,16,923,511,0x62c9f5fa
|
||||
_StateWindow=0,0,990,647,0x00100018,'C:\projects\c&czero\code\palette.cpp',240,15,244,32,32,0,32,32,32,32,8,4294967295,4294967295,1,10,'',12,255,48,0,7,243,252,253,247,249,247,93,1,400,0,246,252,248,244,247,15,15,15,15,0,0
|
||||
_StateBuffer='C:\projects\c&czero\code\palette.cpp',0x0400048e,93,1,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\jshell.h',0x0400048e,1,2,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\sprite.cpp',0x0400048e,35,1,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\wwfile.h',0x0400048e,21,1,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\win32lib\INCLUDE\RAWFILE.H',0x0400048e,1,1,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\ROTBMP.H',0x0400048e,9,1,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\rotbmp.cpp',0x0400048e,6,1,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\function.h',0x0400048e,157,1,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\wwflat32\INCLUDE\gbuffer.h',0x0400048e,265,26,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\anim.cpp',0x0400048e,682,1,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\makefile',0x0400048e,420,1,25,'5 9','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\crc.cpp',0x0400048e,1,1,25,'4 7','',0x0,''
|
||||
_StateBuffer='C:\projects\c&czero\code\PALETTE.H',0x0400048e,1,1,25,'4 7','',0x0,''
|
||||
_StateHistory=SEARCH,'::Mission_U','Force_','MOUSE_','jshell','WindowsTim','LINKFILE','game.dat','wwflat','wwlib','Bitmap'
|
||||
_StateHistory=REPLACE,'building','bindex','vindex','iindex','AIRCRAFT','AircraftType','aircraft','aindex','_Scale_To_256','tech'
|
||||
_StateHistory=XMACRO,'small','sort','SORT','sort','SORT','sort','SORT','sort','SORT','sort'
|
||||
_StateHistory=FILELIST,'C:\projects\c&czero\wwflat32\INCLUDE\gbuffer.h','C:\projects\c&czero\code\function.h','C:\projects\c&czero\code\rotbmp.cpp','C:\projects\c&czero\code\ROTBMP.H','C:\projects\c&czero\code\jshell.h','C:\projects\c&czero\code\palette.cpp','C:\projects\c&czero\code\crc.cpp','C:\projects\c&czero\code\makefile','C:\projects\c&czero\code\PALETTE.H','C:\projects\c&czero\code\anim.cpp'
|
||||
_StateHistory=EDITFILE,'palette.cpp','crc.cpp','makefile','palette.cpp','palette.h','makefile','anim.cpp','palette.cpp','function.h','jshell.h'
|
||||
_StateHistory=DIRECTORY,'c:\\','c:\projects\c&c\code','e:\c&czero\code','e:','c:\projects\c&czero\code','c:','C:\PROJECTS\C&Czero\code','c:\projects\C&Czero\code'
|
||||
_StateHistory=GOTOMARK,'2','1','2','1','2','3','1','2','3','1'
|
||||
_StateHistory=OUTNAME,'tab.cpp','power.cpp','2txtprnt.asm','display.cpp','scroll.cpp','sidebar.cpp','power.cpp','help.cpp','tab.cpp','mapeddlg.cpp'
|
||||
_StateHistory=GOTOLINE,'1665','410','93','375','590','231','246','616','384','686'
|
||||
_StateHistory=WBLOCK,'c:\temp\face.cpp','c:\temp\face.h'
|
||||
_StateHistory=FILTER,'sort'
|
||||
_StateHistory=DOSHISTORY,'eset path','ndos','eset path','set path=%PATH%;c:\utils','ts *.cpp Interpolated','n','d:','exit','ts *.cpp Interpolated','exit'
|
||||
_StateMark=MARK_POSITION,1,'C:\projects\c&czero\wwflat32\INCLUDE\gbuffer.h',265,25,0
|
||||
_StateMark=MARK_POSITION,1,'C:\projects\c&czero\code\jshell.h',1,1,0
|
||||
|
||||
[Editor]
|
||||
ClipboardSetTermStr='\r\n',0
|
||||
ClipboardEnableTermStr=1
|
||||
ClipboardSetSepStr='\r\n',0
|
||||
ClipboardEnableSepStr=1
|
||||
ScrapSetCount=1
|
||||
VCSProject=''
|
||||
VCSProjectPath=''
|
||||
VCSProjectLocalPath=''
|
||||
_RestoreSysFlags=0x6249f5fa, 0xfffffffc
|
||||
|
||||
[Compiler]
|
||||
TagSetCmd='${HOME}${WTAGS} -oc -d -t${TAGFILE}.tag -p${TAGFILE}.ptg',0x8000060
|
||||
BrowseSetFile='c:\projects\c&czero\code\c&czero.ptg'
|
||||
TagSetFile='c:\projects\c&czero\code\c&czero.tag'
|
||||
CompilerAddCmd='Microsoft Assembler','ftee masm -w2 -zi %r%e;',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'
|
||||
CompilerAddResponse='Microsoft Assembler',
|
||||
CompilerAddCmd='Borland C++','ftee bcc -S %r.c',1073741824,'',0,'ftee make %r.obj',16,'ftee make %r.obj',16,'',0,'',0,'_BorlandCppErrorInfo','','','','%v%p'
|
||||
CompilerAddResponse='Borland C++',
|
||||
CompilerAddCmd='Borland Turbo Assembler','ftee make %r.obj',1073741824,'',0,'ftee make %r.obj',16,'',16,'',0,'',0,'_TasmErrorInfo','','','','%v%p'
|
||||
CompilerAddResponse='Borland Turbo Assembler',
|
||||
CompilerAddCmd='$_cw_proj_hash_$','',1073741825,'',1,'ftee watcom\binw\wmake %r.obj',209,'ftee m.bat',209,'ftee joemake',209,'g.bat -hansolo cheater -xm -editor',224,'_MSLinkErrorInfo','_MicrosoftErrorInfo','_NMakeErrorInfo','proj.err','c:\projects\c&czero\code'
|
||||
CompilerAddResponse='$_cw_proj_hash_$',
|
||||
CompilerAddCmd='Default Project','',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_ErrorInfoDefault','','','proj.err','%v%p'
|
||||
CompilerAddResponse='Default Project',
|
||||
CompilerAddCmd='Microsoft C','ftee cl -c -AL -Gsw -Ow -Zpe %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_MicrosoftErrorInfo','','','','%v%p'
|
||||
CompilerAddResponse='Microsoft C',
|
||||
CompilerAddCmd='Script','ftee make %r.inf',1073741824,'',0,'ftee make',16,'ftee make',16,'',0,'',0,'_BorlandCppErrorInfo','','','',''
|
||||
CompilerAddResponse='Script',
|
||||
CompilerAddCmd='Zortech C++','ftee ztc -a -b -c -g -ml -W %r%e',1073741824,'',0,'',16,'',16,'',0,'',0,'_ZortechCppErrorInfo','','','','%v%p'
|
||||
CompilerAddResponse='Zortech C++',
|
||||
CompilerAddCmd='Microsoft C(NT-i386)','${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',1073741936,'${FTEE} cl -DSTRICT -c -W3 -G3 -D_X86_=1 -DWIN32 %r%e',112,'',144,'',144,'',0,'',0,'_MicrosoftErrorInfo','','','',''
|
||||
CompilerAddResponse='Microsoft C(NT-i386)',
|
||||
CompilerAssign='Borland C++','.scr'
|
||||
CompilerNewExt=.bas
|
||||
CompilerAssign='Borland C++','.int'
|
||||
CompilerAssign='Borland C++','.c'
|
||||
CompilerNewExt=.prg
|
||||
CompilerAssign='Microsoft C','.h'
|
||||
CompilerAssign='Borland C++','.cpp'
|
||||
CompilerAssign='Default Project','.*'
|
||||
CompilerAssign='Microsoft C(NT-i386)','.cxx'
|
||||
CompilerAssign='Borland Turbo Assembler','.asm'
|
||||
CompilerAssign='Microsoft C(NT-i386)','.hpp'
|
183
CODE/CARGO.CPP
Normal file
183
CODE/CARGO.CPP
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CARGO.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CARGO.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : April 23, 1994 *
|
||||
* *
|
||||
* Last Update : 10/31/94 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* CargoClass::Attach -- Add unit to cargo hold. *
|
||||
* CargoClass::Attached_Object -- Determine attached unit pointer. *
|
||||
* CargoClass::Debug_Dump -- Displays the cargo value to the monochrome screen. *
|
||||
* CargoClass::Detach_Object -- Removes a unit from the cargo hold. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
#ifdef CHEAT_KEYS
|
||||
/***********************************************************************************************
|
||||
* CargoClass::Debug_Dump -- Displays the cargo value to the monochrome screen. *
|
||||
* *
|
||||
* This routine is used to dump the current cargo value to the monochrome monitor. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 06/02/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void CargoClass::Debug_Dump(MonoClass * mono) const
|
||||
{
|
||||
if (How_Many()) {
|
||||
mono->Set_Cursor(63, 3);
|
||||
mono->Printf("(%d)%04X", How_Many(), Attached_Object());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CargoClass::Attach -- Add unit to cargo hold. *
|
||||
* *
|
||||
* This routine will add the specified unit to the cargo hold. The *
|
||||
* unit will chain to any existing units in the hold. The chaining is *
|
||||
* in a LIFO order. *
|
||||
* *
|
||||
* INPUT: object-- Pointer to the object to attach to the cargo hold. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/23/1994 JLB : Created. *
|
||||
* 10/31/94 JLB : Handles chained objects. *
|
||||
*=============================================================================================*/
|
||||
void CargoClass::Attach(FootClass * object)
|
||||
{
|
||||
/*
|
||||
** If there is no object, then no action is necessary.
|
||||
*/
|
||||
if (object == NULL) return;
|
||||
|
||||
object->Limbo();
|
||||
|
||||
/*
|
||||
** Attach any existing cargo hold object to the end of the list as indicated by the
|
||||
** object pointer passed into this routine. This is necessary because several objects may
|
||||
** be attached at one time or several objects may be attached as a result of several calls
|
||||
** to this routine. Either case must be handled properly.
|
||||
*/
|
||||
ObjectClass * o = object->Next;
|
||||
while (o != NULL) {
|
||||
if (o->Next == (void*)NULL) break;
|
||||
o = o->Next;
|
||||
}
|
||||
if (o != NULL) {
|
||||
o->Next = CargoHold;
|
||||
} else {
|
||||
object->Next = CargoHold;
|
||||
}
|
||||
|
||||
/*
|
||||
** Finally, assign the object pointer as the first object attached to this cargo hold.
|
||||
*/
|
||||
CargoHold = object;
|
||||
Quantity = 0;
|
||||
object = CargoHold;
|
||||
while (object != NULL) {
|
||||
Quantity++;
|
||||
object = (FootClass *)(ObjectClass *)object->Next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CargoClass::Detach_Object -- Removes a unit from the cargo hold. *
|
||||
* *
|
||||
* This routine will take a unit from the cargo hold and extract it. *
|
||||
* The unit extracted is the last unit added to the hold. If there *
|
||||
* is no unit in the hold or the occupant is not a unit, then NULL is *
|
||||
* returned. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with a pointer to the unit that has been extracted. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/23/1994 JLB : Created. *
|
||||
* 06/07/1994 JLB : Handles generic object types. *
|
||||
*=============================================================================================*/
|
||||
FootClass * CargoClass::Detach_Object(void)
|
||||
{
|
||||
TechnoClass * unit = Attached_Object();
|
||||
|
||||
if (unit != NULL) {
|
||||
CargoHold = (FootClass *)(ObjectClass *)unit->Next;
|
||||
unit->Next = 0;
|
||||
Quantity--;
|
||||
}
|
||||
return((FootClass *)unit);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CargoClass::Attached_Object -- Determine attached unit pointer. *
|
||||
* *
|
||||
* This routine will return with a pointer to the attached unit if one *
|
||||
* is present. One would need to know this if this is a transport *
|
||||
* unit and it needs to unload. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns a pointer to the attached unit. If there is no *
|
||||
* attached unit, then return NULL. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/07/1992 JLB : Created. *
|
||||
* 06/07/1994 JLB : Handles generic object types. *
|
||||
*=============================================================================================*/
|
||||
FootClass * CargoClass::Attached_Object(void) const
|
||||
{
|
||||
if (Is_Something_Attached()) {
|
||||
return(CargoHold);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
93
CODE/CARGO.H
Normal file
93
CODE/CARGO.H
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CARGO.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CARGO.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : April 23, 1994 *
|
||||
* *
|
||||
* Last Update : April 23, 1994 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef CARGO_H
|
||||
#define CARGO_H
|
||||
|
||||
class FootClass;
|
||||
|
||||
/****************************************************************************
|
||||
** This class handles the basic cargo logic.
|
||||
*/
|
||||
class CargoClass {
|
||||
public:
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
** Constructors, Destructors, and overloaded operators.
|
||||
*/
|
||||
CargoClass(void) : Quantity(0), CargoHold(0) {};
|
||||
CargoClass(NoInitClass const & ) {};
|
||||
~CargoClass(void) {CargoHold=0;};
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
** Member function prototypes.
|
||||
*/
|
||||
|
||||
#ifdef CHEAT_KEYS
|
||||
void Debug_Dump(MonoClass *mono) const;
|
||||
#endif
|
||||
void AI(void) {};
|
||||
|
||||
int How_Many(void) const {return Quantity;};
|
||||
bool Is_Something_Attached(void) const {return (CargoHold != 0);};
|
||||
FootClass * Attached_Object(void) const;
|
||||
FootClass * Detach_Object(void);
|
||||
void Attach(FootClass * object);
|
||||
|
||||
/*
|
||||
** File I/O.
|
||||
*/
|
||||
void Code_Pointers(void);
|
||||
void Decode_Pointers(void);
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
** This is the number of objects attached to this cargo hold. For transporter
|
||||
** objects, they might contain more than one object.
|
||||
*/
|
||||
unsigned char Quantity;
|
||||
|
||||
/*
|
||||
** This is the target value of any attached object. A value of zero indicates
|
||||
** that no object is attached.
|
||||
*/
|
||||
FootClass * CargoHold;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
153
CODE/CARRY.CPP
Normal file
153
CODE/CARRY.CPP
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CARRY.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CARRY.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 02/26/96 *
|
||||
* *
|
||||
* Last Update : May 10, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* CarryoverClass::CarryoverClass -- Constructor for carry over objects. *
|
||||
* CarryoverClass::Create -- Creates a carried over object. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CarryoverClass::CarryoverClass -- Constructor for carry over objects. *
|
||||
* *
|
||||
* This is the constructor for a carry over object. Such an object is used to record the *
|
||||
* object that will be "carried over" into a new scenario at some future time. *
|
||||
* *
|
||||
* INPUT: techno -- Pointer to the object that will be carried over. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/10/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
CarryoverClass::CarryoverClass(TechnoClass * techno) :
|
||||
RTTI(RTTI_NONE),
|
||||
Cell(0),
|
||||
Strength(0),
|
||||
House(HOUSE_NONE)
|
||||
{
|
||||
if (techno) {
|
||||
RTTI = techno->What_Am_I();
|
||||
|
||||
switch (RTTI) {
|
||||
case RTTI_UNIT:
|
||||
Type.Unit = ((UnitClass *)techno)->Class->Type;
|
||||
break;
|
||||
|
||||
case RTTI_BUILDING:
|
||||
Type.Building = ((BuildingClass *)techno)->Class->Type;
|
||||
break;
|
||||
|
||||
case RTTI_INFANTRY:
|
||||
Type.Infantry = ((InfantryClass *)techno)->Class->Type;
|
||||
break;
|
||||
|
||||
case RTTI_VESSEL:
|
||||
Type.Vessel = ((VesselClass *)techno)->Class->Type;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
House = techno->Owner();
|
||||
Strength = techno->Strength;
|
||||
Cell = Coord_Cell(techno->Coord);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CarryoverClass::Create -- Creates a carried over object. *
|
||||
* *
|
||||
* Use this routine to convert a carried over object into an actual object that will be *
|
||||
* placed on the map. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Was the object successfully created and placed on the map? *
|
||||
* *
|
||||
* WARNINGS: This routine might not place the object if the old map location was invalid *
|
||||
* or there are other barriers to the object's creation and placement. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/10/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
bool CarryoverClass::Create(void) const
|
||||
{
|
||||
TechnoClass * techno = 0;
|
||||
TechnoTypeClass const * ttype = 0;
|
||||
|
||||
switch (RTTI) {
|
||||
case RTTI_UNIT:
|
||||
ttype = &UnitTypeClass::As_Reference(Type.Unit);
|
||||
techno = new UnitClass(Type.Unit, House);
|
||||
break;
|
||||
|
||||
case RTTI_INFANTRY:
|
||||
ttype = &InfantryTypeClass::As_Reference(Type.Infantry);
|
||||
techno = new InfantryClass(Type.Infantry, House);
|
||||
break;
|
||||
|
||||
case RTTI_BUILDING:
|
||||
ttype = &BuildingTypeClass::As_Reference(Type.Building);
|
||||
techno = new BuildingClass(Type.Building, House);
|
||||
break;
|
||||
|
||||
case RTTI_VESSEL:
|
||||
ttype = &VesselTypeClass::As_Reference(Type.Vessel);
|
||||
techno = new VesselClass(Type.Vessel, House);
|
||||
break;
|
||||
}
|
||||
|
||||
if (techno) {
|
||||
bool oldscen = ScenarioInit;
|
||||
techno->Strength = Strength;
|
||||
if (RTTI == RTTI_INFANTRY) {
|
||||
ScenarioInit = 0;
|
||||
}
|
||||
techno->Unlimbo(Cell_Coord(Cell));
|
||||
if (RTTI == RTTI_INFANTRY) {
|
||||
ScenarioInit = oldscen;
|
||||
}
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
84
CODE/CARRY.H
Normal file
84
CODE/CARRY.H
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CARRY.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CARRY.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 02/26/96 *
|
||||
* *
|
||||
* Last Update : February 26, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#ifndef CARRY_H
|
||||
#define CARRY_H
|
||||
|
||||
class CarryoverClass : public LinkClass {
|
||||
public:
|
||||
CarryoverClass(TechnoClass * techno = 0);
|
||||
CarryoverClass(NoInitClass const & x) : LinkClass(x) {}
|
||||
|
||||
bool Create(void) const;
|
||||
|
||||
protected:
|
||||
/*
|
||||
** What type of object this is.
|
||||
*/
|
||||
RTTIType RTTI;
|
||||
|
||||
/*
|
||||
** This is the object type that is to be carried over. The exact nature of
|
||||
** this type depends on the RTTI value. Only certain object types are
|
||||
** recorded.
|
||||
*/
|
||||
union {
|
||||
StructType Building;
|
||||
UnitType Unit;
|
||||
InfantryType Infantry;
|
||||
VesselType Vessel;
|
||||
} Type;
|
||||
|
||||
/*
|
||||
** The location of the object.
|
||||
*/
|
||||
CELL Cell;
|
||||
|
||||
/*
|
||||
** The strength of the object at the time is was recorded.
|
||||
*/
|
||||
int Strength;
|
||||
|
||||
/*
|
||||
** This is the owner of the object.
|
||||
*/
|
||||
HousesType House;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
431
CODE/CCDDE.CPP
Normal file
431
CODE/CCDDE.CPP
Normal file
@ -0,0 +1,431 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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 - Red Alert *
|
||||
* *
|
||||
* File Name : CCDDE.CPP *
|
||||
* *
|
||||
* Programmer : Steve Tall *
|
||||
* *
|
||||
* Start Date : 10/04/95 *
|
||||
* *
|
||||
* Last Update : August 5th, 1996 [ST] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Overview: *
|
||||
* C&C's interface to the DDE class *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Functions: *
|
||||
* DDE_Callback -- DDE server callback function *
|
||||
* DDEServerClass::DDEServerClass -- class constructor *
|
||||
* DDEServerClass::Enable -- Enables the DDE callback *
|
||||
* DDEServerClass::Disable -- Disables the DDE callback *
|
||||
* DDEServerClass::~DDEServerClass -- class destructor *
|
||||
* DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function *
|
||||
* DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat *
|
||||
* DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info *
|
||||
* DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*
|
||||
* *
|
||||
* Send_Data_To_DDE_Server -- sends a packet to WChat *
|
||||
* *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <WINDOWS.H>
|
||||
#include "ccdde.h"
|
||||
#include <stdio.h>
|
||||
#include <timer.h>
|
||||
|
||||
DDEServerClass DDEServer; //Instance of the DDE Server class
|
||||
|
||||
Instance_Class *DDE_Class = NULL; // pointer for client callback
|
||||
// this *must* be called DDE_Class
|
||||
|
||||
BOOL RA95AlreadyRunning = FALSE; //Was there an instance of Red Alert 95 already running when we started?
|
||||
|
||||
/*
|
||||
** Misc externs so we dont have to include FUNCTION.H
|
||||
*/
|
||||
extern HWND MainWindow;
|
||||
extern TimerClass GameTimer;
|
||||
extern BOOL GameTimerInUse;
|
||||
extern void WWDebugString (char *string);
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* DDE_Callback -- DDE server callback function *
|
||||
* *
|
||||
* Just acts as a wrapper for the DDEServerClass callback function *
|
||||
* *
|
||||
* INPUT: ptr to data from client *
|
||||
* length of data *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 6/8/96 3:19PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
BOOL CALLBACK DDE_Callback (unsigned char *data, long length)
|
||||
{
|
||||
return (DDEServer.Callback(data, length));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* DDEServerClass::DDEServerClass -- class constructor *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 6/8/96 3:20PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
DDEServerClass::DDEServerClass(void)
|
||||
{
|
||||
MPlayerGameInfo = NULL; //Flag that we havnt received a start game info packet yet
|
||||
|
||||
//DDE_Class = new Instance_Class ("CONQUER", "WCHAT");
|
||||
DDE_Class = new Instance_Class ("REDALERT", "WCHAT");
|
||||
|
||||
DDE_Class->Enable_Callback( TRUE );
|
||||
IsEnabled = TRUE;
|
||||
|
||||
if (DDE_Class->Test_Server_Running(DDE_Class->local_name)){
|
||||
RA95AlreadyRunning = TRUE;
|
||||
}else{
|
||||
DDE_Class->Register_Server( DDE_Callback );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* DDEServerClass::Enable -- Enables the DDE callback *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 8/5/96 9:44PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void DDEServerClass::Enable(void)
|
||||
{
|
||||
if (!IsEnabled){
|
||||
DDE_Class->Enable_Callback( TRUE );
|
||||
IsEnabled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* DDEServerClass::Disable -- Disables the DDE callback *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 8/5/96 9:44PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void DDEServerClass::Disable(void)
|
||||
{
|
||||
if (IsEnabled){
|
||||
DDE_Class->Enable_Callback( FALSE );
|
||||
IsEnabled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* DDEServerClass::~DDEServerClass -- class destructor *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 6/8/96 3:20PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
DDEServerClass::~DDEServerClass(void)
|
||||
{
|
||||
Delete_MPlayer_Game_Info();
|
||||
delete( DDE_Class );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: data from DDE client *
|
||||
* length of data *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: Data has length and type as first 2 ints *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 6/8/96 3:21PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
BOOL DDEServerClass::Callback(unsigned char *data, long length)
|
||||
{
|
||||
|
||||
/*
|
||||
** If the packet length < 0 then this is a special advisory packet
|
||||
*/
|
||||
if ( length<0 ) {
|
||||
|
||||
switch( length ) {
|
||||
|
||||
case DDE_ADVISE_CONNECT:
|
||||
WWDebugString("RA95 - DDE advisory: client connect detected.");
|
||||
return TRUE;
|
||||
|
||||
case DDE_ADVISE_DISCONNECT:
|
||||
WWDebugString("RA95 - DDE advisory: client disconnect detected.");
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
WWDebugString("RA95 - DDE advisory: Unknown DDE advise type.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
/*
|
||||
** Packet must be at least the length of the packet type & size fields to be valid
|
||||
*/
|
||||
if (length < 2*sizeof(int)) {
|
||||
WWDebugString ("RA95 - Received invalid packet.");
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
** Find out what kind of packet this is and its length.
|
||||
*/
|
||||
int *packet_pointer = (int *)data;
|
||||
int actual_length = ntohl(*packet_pointer++);
|
||||
int packet_type = ntohl(*packet_pointer++);
|
||||
|
||||
/*
|
||||
** Strip the ID int from the start of the packet
|
||||
*/
|
||||
data += 2*sizeof (int);
|
||||
length -= 2*sizeof (int);
|
||||
actual_length -= 2*sizeof (int);
|
||||
|
||||
/*
|
||||
** Take the appropriate action for the packet type
|
||||
*/
|
||||
switch ( packet_type ){
|
||||
|
||||
/*
|
||||
** This is a packet with the info required for starting a new internet game. This is really
|
||||
* just C&CSPAWN.INI sent from WChat instead of read from disk.
|
||||
*/
|
||||
case DDE_PACKET_START_MPLAYER_GAME:
|
||||
WWDebugString("RA95 - Received start game packet.");
|
||||
Delete_MPlayer_Game_Info();
|
||||
MPlayerGameInfo = new char [actual_length + 1];
|
||||
memcpy (MPlayerGameInfo, data, actual_length);
|
||||
*(MPlayerGameInfo + actual_length) = 0; //Terminator in case we treat it as a string
|
||||
MPlayerGameInfoLength = actual_length;
|
||||
LastHeartbeat = 0;
|
||||
break;
|
||||
|
||||
case DDE_TICKLE:
|
||||
WWDebugString("RA95 - Received 'tickle' packet.");
|
||||
//SetForegroundWindow ( MainWindow );
|
||||
//ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
|
||||
break;
|
||||
|
||||
case DDE_PACKET_HEART_BEAT:
|
||||
WWDebugString("RA95 - Received heart beat packet.");
|
||||
if (GameTimerInUse){
|
||||
LastHeartbeat = GameTimer.Time();
|
||||
}else{
|
||||
LastHeartbeat = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
WWDebugString("RA95 - Received unrecognised packet.");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: ptr to data in .INI file format *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 6/8/96 3:23PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
char *DDEServerClass::Get_MPlayer_Game_Info (void)
|
||||
{
|
||||
return (MPlayerGameInfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 6/8/96 3:24PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void DDEServerClass::Delete_MPlayer_Game_Info(void)
|
||||
{
|
||||
if (MPlayerGameInfo){
|
||||
delete [] MPlayerGameInfo;
|
||||
MPlayerGameInfo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: time since heartbeat *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 6/9/96 11:05PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
int DDEServerClass::Time_Since_Heartbeat(void)
|
||||
{
|
||||
return (GameTimer.Time() - LastHeartbeat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Send_Data_To_DDE_Server -- sends a packet to WChat *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: ptr to the data to send *
|
||||
* length of data *
|
||||
* packet type identifier *
|
||||
* *
|
||||
* OUTPUT: true if packet successfully sent *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 6/9/96 11:07PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
BOOL Send_Data_To_DDE_Server (char *data, int length, int packet_type)
|
||||
{
|
||||
if( DDE_Class->Open_Poke_Connection(DDE_Class->remote_name) == FALSE) {
|
||||
WWDebugString("RA95 - Failed to connect for POKE!");
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
char *poke_data = new char [length + 2*sizeof(int)];
|
||||
|
||||
int *poke_data_int = (int*)poke_data;
|
||||
|
||||
*poke_data_int = htonl (length + 2*sizeof(int));
|
||||
*(poke_data_int+1)= htonl (packet_type);
|
||||
|
||||
memcpy (poke_data + 8, data, length);
|
||||
|
||||
|
||||
if(DDE_Class->Poke_Server( (LPBYTE) poke_data, ntohl(*poke_data_int) ) == FALSE) {
|
||||
WWDebugString("RA95 - POKE failed!\n");
|
||||
DDE_Class->Close_Poke_Connection(); // close down the link
|
||||
delete poke_data;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
DDE_Class->Close_Poke_Connection(); // close down the link
|
||||
|
||||
delete poke_data;
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
#endif //WIN32
|
89
CODE/CCDDE.H
Normal file
89
CODE/CCDDE.H
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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 - Red Alert *
|
||||
* *
|
||||
* File Name : CCDDE.H *
|
||||
* *
|
||||
* Programmer : Steve Tall *
|
||||
* *
|
||||
* Start Date : 10/04/95 *
|
||||
* *
|
||||
* Last Update : August 5th, 1996 [ST] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Overview: *
|
||||
* C&C's interface to the DDE class *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "dde.h"
|
||||
|
||||
class DDEServerClass {
|
||||
|
||||
public:
|
||||
|
||||
DDEServerClass (void);
|
||||
~DDEServerClass (void);
|
||||
|
||||
|
||||
char *Get_MPlayer_Game_Info (void); //Returns pointer to game info
|
||||
int Get_MPlayer_Game_Info_Length(){return(MPlayerGameInfoLength);}; //Len of game info
|
||||
BOOL Callback(unsigned char *data, long length); //DDE callback function
|
||||
void Delete_MPlayer_Game_Info(void); //release the game info memory
|
||||
void Enable(void); //Enable the DDE callback
|
||||
void Disable(void); //Disable the DDE callback
|
||||
int Time_Since_Heartbeat(void); //Returns the time since the last hearbeat from WChat
|
||||
|
||||
/*
|
||||
** Enumeration for DDE packet types from WChat
|
||||
*/
|
||||
enum {
|
||||
DDE_PACKET_START_MPLAYER_GAME, //Start game packet. This includes game options
|
||||
DDE_PACKET_GAME_RESULTS, //Game results packet. The game statistics.
|
||||
DDE_PACKET_HEART_BEAT, //Heart beat packet so we know WChat is still there.
|
||||
DDE_TICKLE, //Message to prompt other app to take focus.
|
||||
DDE_CONNECTION_FAILED
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
char *MPlayerGameInfo; //Pointer to game start packet
|
||||
int MPlayerGameInfoLength; //Length of game start packet.
|
||||
BOOL IsEnabled; //Flag for DDE callback enable
|
||||
int LastHeartbeat; // Time since last heartbeat packet was received from WChat
|
||||
|
||||
};
|
||||
|
||||
|
||||
extern DDEServerClass DDEServer;
|
||||
extern BOOL Send_Data_To_DDE_Server (char *data, int length, int packet_type);
|
||||
|
||||
|
||||
#endif //WIN32
|
693
CODE/CCFILE.CPP
Normal file
693
CODE/CCFILE.CPP
Normal file
@ -0,0 +1,693 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CCFILE.CPP 2 3/13/97 2:05p Steve_tall $ */
|
||||
/***********************************************************************************************
|
||||
*** 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 : CCFILE.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : August 8, 1994 *
|
||||
* *
|
||||
* Last Update : August 5, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* CCFileClass::CCFileClass -- Default constructor for file object. *
|
||||
* CCFileClass::CCFileClass -- Filename based constructor for C&C file. *
|
||||
* CCFileClass::Close -- Closes the file. *
|
||||
* CCFileClass::Error -- Handles displaying a file error message. *
|
||||
* CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile. *
|
||||
* CCFileClass::Is_Open -- Determines if the file is open. *
|
||||
* CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system. *
|
||||
* CCFileClass::Read -- Reads data from the file. *
|
||||
* CCFileClass::Seek -- Moves the current file pointer in the file. *
|
||||
* CCFileClass::Size -- Determines the size of the file. *
|
||||
* CCFileClass::Write -- Writes data to the file (non mixfile files only). *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "function.h"
|
||||
#include <errno.h>
|
||||
#include "ccfile.h"
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::CCFileClass -- Filename based constructor for C&C file. *
|
||||
* *
|
||||
* Use this constructor for a file when the filename is known at construction time. *
|
||||
* *
|
||||
* INPUT: filename -- Pointer to the filename to use for this file object. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: The filename pointer is presumed to be inviolate throughout the duration of *
|
||||
* the file object. If this is not guaranteed, then use the default constructor *
|
||||
* and then set the name manually. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/20/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
CCFileClass::CCFileClass(char const * filename) :
|
||||
Position(0)
|
||||
{
|
||||
CCFileClass::Set_Name(filename);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::CCFileClass -- Default constructor for file object. *
|
||||
* *
|
||||
* This is the default constructor for a C&C file object. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 03/20/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
CCFileClass::CCFileClass(void) :
|
||||
Position(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Error -- Handles displaying a file error message. *
|
||||
* *
|
||||
* Display an error message as indicated. If it is allowed to retry, then pressing a key *
|
||||
* will return from this function. Otherwise, it will exit the program with "exit()". *
|
||||
* *
|
||||
* INPUT: error -- The error number (same as the DOSERR.H error numbers). *
|
||||
* *
|
||||
* canretry -- Can this routine exit normally so that retrying can occur? If this is *
|
||||
* false, then the program WILL exit in this routine. *
|
||||
* *
|
||||
* filename -- Optional filename to report with this error. If no filename is *
|
||||
* supplied, then no filename is listed in the error message. *
|
||||
* *
|
||||
* OUTPUT: none, but this routine might not return at all if the "canretry" parameter is *
|
||||
* false or the player pressed ESC. *
|
||||
* *
|
||||
* WARNINGS: This routine may not return at all. It handles being in text mode as well as *
|
||||
* if in a graphic mode. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/17/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void CCFileClass::Error(int , int , char const * )
|
||||
{
|
||||
if (!Force_CD_Available(RequiredCD)) {
|
||||
//Prog_End();
|
||||
Emergency_Exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Write -- Writes data to the file (non mixfile files only). *
|
||||
* *
|
||||
* This routine will write data to the file, but NOT to a file that is part of a mixfile. *
|
||||
* *
|
||||
* INPUT: buffer -- Pointer to the buffer that holds the data to be written. *
|
||||
* *
|
||||
* size -- The number of bytes to write. *
|
||||
* *
|
||||
* OUTPUT: Returns the number of bytes actually written. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/08/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
long CCFileClass::Write(void const * buffer, long size)
|
||||
{
|
||||
/*
|
||||
** If this is part of a mixfile, then writing is not allowed. Error out with a fatal
|
||||
** message.
|
||||
*/
|
||||
if (Is_Resident()) {
|
||||
Error(EACCES, false, File_Name());
|
||||
}
|
||||
|
||||
return(CDFileClass::Write(buffer, size));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Read -- Reads data from the file. *
|
||||
* *
|
||||
* This routine determines if the file is part of the mixfile system. If it is, then *
|
||||
* the file is copied from RAM if it is located there. Otherwise it is read from disk *
|
||||
* according to the correct position of the file within the parent mixfile. *
|
||||
* *
|
||||
* INPUT: buffer -- Pointer to the buffer to place the read data. *
|
||||
* *
|
||||
* size -- The number of bytes to read. *
|
||||
* *
|
||||
* OUTPUT: Returns the actual number of bytes read (this could be less than requested). *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/08/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
long CCFileClass::Read(void * buffer, long size)
|
||||
{
|
||||
bool opened = false;
|
||||
|
||||
/*
|
||||
** If the file isn't currently open, then open it.
|
||||
*/
|
||||
if (!Is_Open()) {
|
||||
if (Open()) {
|
||||
opened = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If the file is part of a loaded mixfile, then a mere copy is
|
||||
** all that is required for the read.
|
||||
*/
|
||||
if (Is_Resident()) {
|
||||
long maximum = Data.Get_Size() - Position;
|
||||
|
||||
size = maximum < size ? maximum : size;
|
||||
// size = MIN(maximum, size);
|
||||
if (size) {
|
||||
memmove(buffer, (char *)Data + Position, size);
|
||||
// Mem_Copy((char *)Pointer + Position, buffer, size);
|
||||
Position += size;
|
||||
}
|
||||
if (opened) Close();
|
||||
return(size);
|
||||
}
|
||||
|
||||
long s = CDFileClass::Read(buffer, size);
|
||||
|
||||
/*
|
||||
** If the file was opened by this routine, then close it at this time.
|
||||
*/
|
||||
if (opened) Close();
|
||||
|
||||
/*
|
||||
** Return with the number of bytes read.
|
||||
*/
|
||||
return(s);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Seek -- Moves the current file pointer in the file. *
|
||||
* *
|
||||
* This routine will change the current file pointer to the position specified. It follows *
|
||||
* the same rules the a normal Seek() does, but if the file is part of the mixfile system, *
|
||||
* then only the position value needs to be updated. *
|
||||
* *
|
||||
* INPUT: pos -- The position to move the file to relative to the position indicated *
|
||||
* by the "dir" parameter. *
|
||||
* *
|
||||
* dir -- The direction to affect the position change against. This can be *
|
||||
* either SEEK_CUR, SEEK_END, or SEEK_SET. *
|
||||
* *
|
||||
* OUTPUT: Returns with the position of the new location. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/08/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
long CCFileClass::Seek(long pos, int dir)
|
||||
{
|
||||
/*
|
||||
** When the file is resident, a mere adjustment of the virtual file position is
|
||||
** all that is required of a seek.
|
||||
*/
|
||||
if (Is_Resident()) {
|
||||
switch (dir) {
|
||||
case SEEK_END:
|
||||
Position = Data.Get_Size();
|
||||
break;
|
||||
|
||||
case SEEK_SET:
|
||||
Position = 0;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Position += pos;
|
||||
Position = Position < 0 ? 0 : Position;
|
||||
Position = Position > Data.Get_Size() ? Data.Get_Size() : Position;
|
||||
// Position = Bound(Position+pos, 0L, Length);
|
||||
return(Position);
|
||||
}
|
||||
return(CDFileClass::Seek(pos, dir));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Size -- Determines the size of the file. *
|
||||
* *
|
||||
* If the file is part of the mixfile system, then the size of the file is already *
|
||||
* determined and available. Otherwise, go to the low level system to find the file *
|
||||
* size. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the size of the file in bytes. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/08/1994 JLB : Created. *
|
||||
* 08/05/1996 JLB : Handles returning size of embedded file. *
|
||||
*=============================================================================================*/
|
||||
long CCFileClass::Size(void)
|
||||
{
|
||||
/*
|
||||
** If the file is resident, the the size is already known. Just return the size in this
|
||||
** case.
|
||||
*/
|
||||
if (Is_Resident()) return(Data.Get_Size());
|
||||
|
||||
/*
|
||||
** If the file is not available as a stand alone file, then search for it in the
|
||||
** mixfiles in order to get its size.
|
||||
*/
|
||||
if (!CDFileClass::Is_Available()) {
|
||||
long length = 0;
|
||||
MFCD::Offset(File_Name(), NULL, NULL, NULL, &length);
|
||||
return(length);
|
||||
}
|
||||
|
||||
return(CDFileClass::Size());
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile. *
|
||||
* *
|
||||
* This routine will examine the mixfile system looking for the file. If the file could *
|
||||
* not be found there, then the disk is examined directly. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Is the file available for opening? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/08/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int CCFileClass::Is_Available(int )
|
||||
{
|
||||
/*
|
||||
** A file that is open is presumed available.
|
||||
*/
|
||||
if (Is_Open()) return(true);
|
||||
|
||||
/*
|
||||
** A file that is part of a mixfile is also presumed available.
|
||||
*/
|
||||
if (MFCD::Offset(File_Name())) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*
|
||||
** Otherwise a manual check of the file system is required to
|
||||
** determine if the file is actually available.
|
||||
*/
|
||||
return(CDFileClass::Is_Available());
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Is_Open -- Determines if the file is open. *
|
||||
* *
|
||||
* A mixfile is open if there is a pointer to the mixfile data. In absence of this, *
|
||||
* the the file is open if the file handle is valid. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Is the file open? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/08/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int CCFileClass::Is_Open(void) const
|
||||
{
|
||||
/*
|
||||
** If the file is part of a cached file, then return that it is opened. A closed file
|
||||
** doesn't have a valid pointer.
|
||||
*/
|
||||
if (Is_Resident()) return(true);
|
||||
|
||||
/*
|
||||
** Otherwise, go to a lower level to determine if the file is open.
|
||||
*/
|
||||
return(CDFileClass::Is_Open());
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Close -- Closes the file. *
|
||||
* *
|
||||
* If this is a mixfile file, then only the pointers need to be adjusted. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/08/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void CCFileClass::Close(void)
|
||||
{
|
||||
new(&Data) ::Buffer;
|
||||
Position = 0; // Starts at beginning offset.
|
||||
CDFileClass::Close();
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system. *
|
||||
* *
|
||||
* This routine will open the specified file. It examines the mixfile system to find a *
|
||||
* match. If one is found then the file is "opened" in a special cached way. Otherwise *
|
||||
* it is opened as a standard DOS file. *
|
||||
* *
|
||||
* INPUT: rights -- The access rights desired. *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file opened successfully? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/08/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int CCFileClass::Open(int rights)
|
||||
{
|
||||
/*
|
||||
** Always close the file if it was open.
|
||||
*/
|
||||
Close();
|
||||
|
||||
/*
|
||||
** Perform a preliminary check to see if the specified file
|
||||
** exists on the disk. If it does, then open this file regardless
|
||||
** of whether it also exists in RAM. This is slower, but allows
|
||||
** upgrade files to work.
|
||||
*/
|
||||
if ((rights & WRITE) || CDFileClass::Is_Available()) {
|
||||
return(CDFileClass::Open(rights));
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if file is part of a mixfile and that mixfile is currently loaded
|
||||
** into RAM.
|
||||
*/
|
||||
MFCD * mixfile = NULL;
|
||||
void * pointer = NULL;
|
||||
long length = 0;
|
||||
long start = 0;
|
||||
if (MFCD::Offset(File_Name(), &pointer, &mixfile, &start, &length)) {
|
||||
|
||||
assert(mixfile != NULL);
|
||||
|
||||
/*
|
||||
** If the mixfile is located on disk, then fake out the file system to read from
|
||||
** the mixfile, but think it is reading from a solitary file.
|
||||
*/
|
||||
if (pointer == NULL && mixfile != NULL) {
|
||||
|
||||
/*
|
||||
** This is a legitimate open to the file. All access to the file through this
|
||||
** file object will be appropriately adjusted for mixfile support however. Also
|
||||
** note that the filename attached to this object is NOT the same as the file
|
||||
** attached to the file handle.
|
||||
*/
|
||||
char * dupfile = strdup(File_Name());
|
||||
Open(mixfile->Filename, READ);
|
||||
Searching(false); // Disable multi-drive search.
|
||||
Set_Name(dupfile);
|
||||
Searching(true);
|
||||
free(dupfile);
|
||||
Bias(0);
|
||||
Bias(start, length);
|
||||
Seek(0, SEEK_SET);
|
||||
} else {
|
||||
new (&Data) ::Buffer(pointer, length);
|
||||
Position = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
** The file cannot be found in any mixfile, so it must reside as
|
||||
** an individual file on the disk. Or else it is just plain missing.
|
||||
*/
|
||||
return(CDFileClass::Open(rights));
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Get_Date_Time -- Gets the date and time the file was last modified. *
|
||||
* *
|
||||
* Use this routine to get the date and time of the file. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the file date and time as a long. *
|
||||
* Use the YEAR(long), MONTH(),.... *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
unsigned long CCFileClass::Get_Date_Time(void)
|
||||
{
|
||||
unsigned long datetime;
|
||||
MFCD * mixfile;
|
||||
|
||||
datetime = CDFileClass::Get_Date_Time();
|
||||
|
||||
if ( !datetime ) {
|
||||
if (MFCD::Offset(File_Name(), NULL, &mixfile, NULL, NULL)) {
|
||||
//
|
||||
// check for nested MIX files
|
||||
//
|
||||
return( CCFileClass(mixfile->Filename).Get_Date_Time() );
|
||||
}
|
||||
// else return 0 indicating no file
|
||||
}
|
||||
|
||||
return( datetime );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCFileClass::Set_Date_Time -- Sets the date and time the file was last modified. *
|
||||
* *
|
||||
* Use this routine to set the date and time of the file. *
|
||||
* *
|
||||
* INPUT: the file date and time as a long *
|
||||
* *
|
||||
* OUTPUT: successful or not if the file date and time was changed. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
bool CCFileClass::Set_Date_Time( unsigned long datetime )
|
||||
{
|
||||
bool status;
|
||||
MFCD * mixfile;
|
||||
|
||||
status = CDFileClass::Set_Date_Time( datetime );
|
||||
|
||||
if ( !status ) {
|
||||
if (MFCD::Offset(File_Name(), NULL, &mixfile, NULL, NULL)) {
|
||||
//
|
||||
// check for nested MIX files
|
||||
//
|
||||
return( CCFileClass(mixfile->Filename).Set_Date_Time( datetime ) );
|
||||
}
|
||||
// else return 0 indicating no file
|
||||
}
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
** Backward compatibility section.
|
||||
*/
|
||||
//extern "C" {
|
||||
|
||||
|
||||
static CCFileClass Handles[10];
|
||||
|
||||
int __cdecl Open_File(char const * file_name, int mode)
|
||||
{
|
||||
for (int index = 0; index < ARRAY_SIZE(Handles); index++) {
|
||||
if (!Handles[index].Is_Open()) {
|
||||
if (Handles[index].Open(file_name, mode)) {
|
||||
return(index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(WWERROR);
|
||||
}
|
||||
|
||||
void __cdecl Close_File(int handle)
|
||||
{
|
||||
if (handle != WWERROR && Handles[handle].Is_Open()) {
|
||||
Handles[handle].Close();
|
||||
}
|
||||
}
|
||||
|
||||
long __cdecl Read_File(int handle, void * buf, unsigned long bytes)
|
||||
{
|
||||
if (handle != WWERROR && Handles[handle].Is_Open()) {
|
||||
return(Handles[handle].Read(buf, bytes));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
long __cdecl Write_File(int handle, void const * buf, unsigned long bytes)
|
||||
{
|
||||
if (handle != WWERROR && Handles[handle].Is_Open()) {
|
||||
return(Handles[handle].Write(buf, bytes));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int __cdecl Find_File(char const * file_name)
|
||||
{
|
||||
CCFileClass file(file_name);
|
||||
return(file.Is_Available());
|
||||
}
|
||||
|
||||
#ifdef NEVER
|
||||
int __cdecl Delete_File(char const * file_name)
|
||||
{
|
||||
return(CCFileClass(file_name).Delete());
|
||||
}
|
||||
|
||||
int __cdecl Create_File(char const * file_name)
|
||||
{
|
||||
return(CCFileClass(file_name).Create());
|
||||
}
|
||||
|
||||
unsigned long __cdecl Load_Data(char const * name, void * ptr, unsigned long size)
|
||||
{
|
||||
return(CCFileClass(name).Read(ptr, size));
|
||||
}
|
||||
#endif
|
||||
|
||||
void * __cdecl Load_Alloc_Data(char const * name, int )
|
||||
{
|
||||
CCFileClass file(name);
|
||||
|
||||
return(Load_Alloc_Data(file));
|
||||
}
|
||||
|
||||
unsigned long __cdecl File_Size(int handle)
|
||||
{
|
||||
if (handle != WWERROR && Handles[handle].Is_Open()) {
|
||||
return(Handles[handle].Size());
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef NEVER
|
||||
unsigned long __cdecl Write_Data(char const * name, void const * ptr, unsigned long size)
|
||||
{
|
||||
return(CCFileClass(name).Write(ptr, size));
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long __cdecl Seek_File(int handle, long offset, int starting)
|
||||
{
|
||||
if (handle != WWERROR && Handles[handle].Is_Open()) {
|
||||
return(Handles[handle].Seek(offset, starting));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef NEVER
|
||||
bool __cdecl Multi_Drive_Search(bool on)
|
||||
{
|
||||
// return(CCFileClass::Multi_Drive_Search(on));
|
||||
return(on);
|
||||
}
|
||||
|
||||
void __cdecl WWDOS_Init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __cdecl WWDOS_Shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
int __cdecl Find_Disk_Number(char const *)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
//unsigned long __cdecl Load_Uncompress(char const * file, BuffType uncomp_buff, BuffType dest_buff, void * reserved_data)
|
||||
//{
|
||||
// return(Load_Uncompress(CCFileClass(file), uncomp_buff, dest_buff, reserved_data));
|
||||
// return(CCFileClass(file).Load_Uncompress(uncomp_buff, dest_buff, reserved_data));
|
||||
//}
|
||||
|
||||
#ifdef WIN32
|
||||
extern "C" {
|
||||
int MaxDevice;
|
||||
int DefaultDrive;
|
||||
char CallingDOSInt;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Unfragment_File_Cache(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
107
CODE/CCFILE.H
Normal file
107
CODE/CCFILE.H
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CCFILE.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CCFILE.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : October 17, 1994 *
|
||||
* *
|
||||
* Last Update : October 17, 1994 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef CCFILE_H
|
||||
#define CCFILE_H
|
||||
|
||||
//#include <wwlib32.h>
|
||||
#include <limits.h>
|
||||
#include "mixfile.h"
|
||||
#include "cdfile.h"
|
||||
#include "buff.h"
|
||||
|
||||
|
||||
/*
|
||||
** This derived class for file access knows about mixfiles (packed files). It can handle opening
|
||||
** a file that is embedded within a mixfile. This is true if the mixfile is cached or resides on
|
||||
** disk. It is functionally similar to pakfiles, except much faster and less RAM intensive.
|
||||
*/
|
||||
class CCFileClass : public CDFileClass
|
||||
{
|
||||
public:
|
||||
CCFileClass(char const * filename);
|
||||
CCFileClass(void);
|
||||
virtual ~CCFileClass(void) {Position = 0;};
|
||||
|
||||
// Delete should be overloaded here as well. Don't allow deletes of mixfiles.
|
||||
|
||||
bool Is_Resident(void) const {return(Data.Get_Buffer() != NULL);}
|
||||
virtual int Is_Available(int forced=false);
|
||||
virtual int Is_Open(void) const;
|
||||
virtual int Open(char const * filename, int rights=READ) {Set_Name(filename);return Open(rights);};
|
||||
virtual int Open(int rights=READ);
|
||||
virtual long Read(void * buffer, long size);
|
||||
virtual long Seek(long pos, int dir=SEEK_CUR);
|
||||
virtual long Size(void);
|
||||
virtual long Write(void const * buffer, long 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);
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
** This indicates the file is actually part of a resident image of the mixfile
|
||||
** itself. In this case, the embedded file handle is invalid. All file access actually
|
||||
** gets routed through the cached version of the file. This is a pointer to the start
|
||||
** of the RAM image of the file.
|
||||
*/
|
||||
::Buffer Data;
|
||||
// void * Pointer;
|
||||
|
||||
/*
|
||||
** This is the size of the file if it was embedded in a mixfile. The size must be manually
|
||||
** kept track of because the DOS file size is invalid.
|
||||
*/
|
||||
// long Length;
|
||||
|
||||
/*
|
||||
** This is the current seek position of the file. It is duplicated here if the file is
|
||||
** part of a mixfile since the DOS seek position is not accurate. This value will
|
||||
** range from zero to the size of the file in bytes.
|
||||
*/
|
||||
long Position;
|
||||
|
||||
// Force these to never be invoked.
|
||||
CCFileClass const & operator = (CCFileClass const & c);
|
||||
CCFileClass (CCFileClass const & );
|
||||
};
|
||||
|
||||
class MixFileClass<CDFileClass>;
|
||||
|
||||
#endif
|
1487
CODE/CCINI.CPP
Normal file
1487
CODE/CCINI.CPP
Normal file
File diff suppressed because it is too large
Load Diff
120
CODE/CCINI.H
Normal file
120
CODE/CCINI.H
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CCINI.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CCINI.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 05/24/96 *
|
||||
* *
|
||||
* Last Update : May 24, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef CCINI_H
|
||||
#define CCINI_H
|
||||
|
||||
#include "ini.h"
|
||||
#include "fixed.h"
|
||||
#include "pk.h"
|
||||
|
||||
class TriggerTypeClass;
|
||||
|
||||
/*
|
||||
** The advanced version of the INI database manager. It handles the C&C expansion types and
|
||||
** identifiers. In addition, it automatically stores a message digest with the INI data
|
||||
** so that verification can occur.
|
||||
*/
|
||||
class CCINIClass : public INIClass
|
||||
{
|
||||
public:
|
||||
CCINIClass(void) : IsDigestPresent(false) {}
|
||||
|
||||
bool Load(FileClass & file, bool withdigest);
|
||||
bool Load(Straw & file, bool withdigest);
|
||||
int Save(FileClass & file, bool withdigest) const;
|
||||
int Save(Pipe & pipe, bool withdigest) const;
|
||||
|
||||
long Get_Buildings(char const * section, char const * entry, long defvalue) const;
|
||||
UnitType Get_UnitType(char const * section, char const * entry, UnitType defvalue) const;
|
||||
AnimType Get_AnimType(char const * section, char const * entry, AnimType defvalue) const;
|
||||
ArmorType Get_ArmorType(char const * section, char const * entry, ArmorType defvalue) const;
|
||||
BulletType Get_BulletType(char const * section, char const * entry, BulletType defvalue) const;
|
||||
HousesType Get_HousesType(char const * section, char const * entry, HousesType defvalue) const;
|
||||
LEPTON Get_Lepton(char const * section, char const * entry, LEPTON defvalue) const;
|
||||
MPHType Get_MPHType(char const * section, char const * entry, MPHType defvalue) const;
|
||||
OverlayType Get_OverlayType(char const * section, char const * entry, OverlayType defvalue) const;
|
||||
SourceType Get_SourceType(char const * section, char const * entry, SourceType defvalue) const;
|
||||
TerrainType Get_TerrainType(char const * section, char const * entry, TerrainType defvalue) const;
|
||||
TheaterType Get_TheaterType(char const * section, char const * entry, TheaterType defvalue) const;
|
||||
ThemeType Get_ThemeType(char const * section, char const * entry, ThemeType defvalue) const;
|
||||
TriggerTypeClass * Get_TriggerType(char const * section, char const * entry) const;
|
||||
VQType Get_VQType(char const * section, char const * entry, VQType defvalue) const;
|
||||
VocType Get_VocType(char const * section, char const * entry, VocType defvalue) const;
|
||||
WarheadType Get_WarheadType(char const * section, char const * entry, WarheadType defvalue) const;
|
||||
WeaponType Get_WeaponType(char const * section, char const * entry, WeaponType defvalue) const;
|
||||
long Get_Owners(char const * section, char const * entry, long defvalue) const;
|
||||
CrateType Get_CrateType(char const * section, char const * entry, CrateType defvalue) const;
|
||||
|
||||
|
||||
bool Put_Buildings(char const * section, char const * entry, long value);
|
||||
bool Put_AnimType(char const * section, char const * entry, AnimType value);
|
||||
bool Put_UnitType(char const * section, char const * entry, UnitType value);
|
||||
bool Put_ArmorType(char const * section, char const * entry, ArmorType value);
|
||||
bool Put_BulletType(char const * section, char const * entry, BulletType value);
|
||||
bool Put_HousesType(char const * section, char const * entry, HousesType value);
|
||||
bool Put_Lepton(char const * section, char const * entry, LEPTON value);
|
||||
bool Put_MPHType(char const * section, char const * entry, MPHType value);
|
||||
bool Put_VQType(char const * section, char const * entry, VQType value);
|
||||
bool Put_OverlayType(char const * section, char const * entry, OverlayType value);
|
||||
bool Put_Owners(char const * section, char const * entry, long value);
|
||||
bool Put_SourceType(char const * section, char const * entry, SourceType value);
|
||||
bool Put_TerrainType(char const * section, char const * entry, TerrainType value);
|
||||
bool Put_TheaterType(char const * section, char const * entry, TheaterType value);
|
||||
bool Put_ThemeType(char const * section, char const * entry, ThemeType value);
|
||||
bool Put_TriggerType(char const * section, char const * entry, TriggerTypeClass * value);
|
||||
bool Put_VocType(char const * section, char const * entry, VocType value);
|
||||
bool Put_WarheadType(char const * section, char const * entry, WarheadType value);
|
||||
bool Put_WeaponType(char const * section, char const * entry, WeaponType value);
|
||||
bool Put_CrateType(char const * section, char const * entry, CrateType value);
|
||||
|
||||
int Get_Unique_ID(void) const;
|
||||
|
||||
private:
|
||||
void Calculate_Message_Digest(void);
|
||||
void Invalidate_Message_Digest(void);
|
||||
|
||||
bool IsDigestPresent:1;
|
||||
|
||||
/*
|
||||
** This is the message digest (SHA) of the INI database that was embedded as part of
|
||||
** the INI file.
|
||||
*/
|
||||
unsigned char Digest[20];
|
||||
};
|
||||
|
||||
#endif
|
421
CODE/CCMPATH.CPP
Normal file
421
CODE/CCMPATH.CPP
Normal file
@ -0,0 +1,421 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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 : Command & Conquer *
|
||||
* *
|
||||
* File Name : CCMPATH.CPP *
|
||||
* *
|
||||
* Programmer : Bill R. Randolph *
|
||||
* *
|
||||
* Start Date : 01/09/96 *
|
||||
* *
|
||||
* Last Update : January 11, 1996 [BRR] *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Init_MPATH -- Performs MPATH-specific initialization *
|
||||
* Shutdown_MPATH -- Shuts down MPATH connections *
|
||||
* Connect_MPATH -- Waits for connections to other players *
|
||||
* Destroy_MPATH_Connection -- Destroys the given connection *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
#include "function.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Init_MPATH -- Performs MPATH-specific initialization *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = OK, 0 = error *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 01/09/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
int Init_MPATH(void)
|
||||
{
|
||||
#if(MPATH)
|
||||
//------------------------------------------------------------------------
|
||||
// Allocate a packet buffer for MPATH's use
|
||||
//------------------------------------------------------------------------
|
||||
Session.MPathPacket = new char[Session.MPathSize];
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Read the multiplayer settings from the CONQUER.INI file, and the game
|
||||
// options from the options file.
|
||||
//------------------------------------------------------------------------
|
||||
Session.Read_MultiPlayer_Settings();
|
||||
|
||||
if (!Read_MPATH_Game_Options()) {
|
||||
WWMessageBox().Process("Unable to load game settings!");
|
||||
//Prog_End();
|
||||
Emergency_Exit(0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Flush all incoming packets
|
||||
//------------------------------------------------------------------------
|
||||
MPath->Flush_All();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Form connections to all other players
|
||||
//------------------------------------------------------------------------
|
||||
Connect_MPATH();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Set multiplayer values for the local system, and timing values.
|
||||
//------------------------------------------------------------------------
|
||||
Session.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;
|
||||
|
||||
return (1);
|
||||
#else
|
||||
return (1);
|
||||
#endif
|
||||
|
||||
} // end of Init_MPATH
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Shutdown_MPATH -- Shuts down MPATH connections *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 01/09/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Shutdown_MPATH(void)
|
||||
{
|
||||
#if(MPATH)
|
||||
CDTimerClass<SystemTimerClass> timer;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Wait a full second before exiting, to ensure all packets get sent.
|
||||
//------------------------------------------------------------------------
|
||||
timer = 60;
|
||||
while (timer) ;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Free memory
|
||||
//------------------------------------------------------------------------
|
||||
if (Session.MPathPacket) {
|
||||
delete [] Session.MPathPacket;
|
||||
Session.MPathPacket = NULL;
|
||||
}
|
||||
|
||||
if (MPath) {
|
||||
delete MPath;
|
||||
MPath = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
#endif
|
||||
} // end of Shutdown_MPATH
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Connect_MPATH -- Waits for connections to other players *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 01/10/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Connect_MPATH(void)
|
||||
{
|
||||
#if(MPATH)
|
||||
typedef struct ConnectPacketTag {
|
||||
NetCommandType Dummy; // packet type; set to PING
|
||||
char Name[MPLAYER_NAME_MAX]; // player's name
|
||||
HousesType House; // player's ActLike
|
||||
unsigned char Color; // player's Color
|
||||
} ConnectPacketType;
|
||||
int num_players;
|
||||
int num_found;
|
||||
ConnectPacketType send_packet;
|
||||
ConnectPacketType receive_packet;
|
||||
int address;
|
||||
int found;
|
||||
int size;
|
||||
int i;
|
||||
CDTimerClass<SystemTimerClass> send_timer;
|
||||
NodeNameType *who;
|
||||
|
||||
enum {
|
||||
D_TXT6_H = 7,
|
||||
D_MARGIN = 5,
|
||||
};
|
||||
static int x,y,w,h;
|
||||
char const *buf1;
|
||||
char const *buf2;
|
||||
|
||||
int display = 0;
|
||||
RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
|
||||
|
||||
//
|
||||
// Clear the Players list
|
||||
//
|
||||
while (Session.Players.Count() > 0) {
|
||||
delete Session.Players[0];
|
||||
Session.Players.Delete(Session.Players[0]);
|
||||
}
|
||||
|
||||
//
|
||||
// Add myself to the list first thing
|
||||
//
|
||||
who = new NodeNameType;
|
||||
strcpy(who->Name, Session.Handle);
|
||||
who->Player.House = Session.House;
|
||||
who->Player.Color = Session.ColorIdx;
|
||||
Session.Players.Add (who);
|
||||
|
||||
//
|
||||
// Find out how many players to wait for
|
||||
//
|
||||
num_players = MPath->Find_Num_Connections();
|
||||
num_found = 0;
|
||||
Session.NumPlayers = num_players + 1;
|
||||
|
||||
//
|
||||
// Send out a packet announcing my presence
|
||||
//
|
||||
send_packet.Dummy = NET_PING;
|
||||
strcpy(send_packet.Name, Session.Handle);
|
||||
send_packet.House = Session.House;
|
||||
send_packet.Color = Session.ColorIdx;
|
||||
MPath->Send_Global_Message(&send_packet, sizeof(send_packet), 0, 0);
|
||||
|
||||
//
|
||||
// Start our packet-sending timer
|
||||
//
|
||||
send_timer = 240;
|
||||
|
||||
//
|
||||
// Wait for all players to enter the game
|
||||
//
|
||||
display = 1;
|
||||
while (num_found < num_players) {
|
||||
|
||||
#ifdef WIN32
|
||||
/*
|
||||
** If we have just received input focus again after running in the background then
|
||||
** we need to redraw.
|
||||
*/
|
||||
if (AllSurfaces.SurfacesRestored) {
|
||||
AllSurfaces.SurfacesRestored=FALSE;
|
||||
display = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display) {
|
||||
Fancy_Text_Print("", 0, 0, 0, 0, TPF_TEXT);
|
||||
buf1 = Text_String(TXT_WAITING_FOR_CONNECTIONS);
|
||||
buf2 = Text_String(TXT_PRESS_ESC);
|
||||
w = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));
|
||||
w += (D_MARGIN * 2);
|
||||
h = (D_TXT6_H * 2) + (D_MARGIN * 7);
|
||||
x = 160 - (w / 2);
|
||||
y = 100 - (h / 2);
|
||||
Hide_Mouse();
|
||||
//Set_Logic_Page(SeenBuff);
|
||||
Dialog_Box(x * RESFACTOR, y * RESFACTOR, w * RESFACTOR, h * RESFACTOR);
|
||||
|
||||
Fancy_Text_Print(buf1,
|
||||
160 * RESFACTOR,
|
||||
(y + (D_MARGIN * 2)) * RESFACTOR,
|
||||
scheme, TBLACK, TPF_CENTER | TPF_TEXT);
|
||||
Fancy_Text_Print(buf2,
|
||||
160 * RESFACTOR,
|
||||
(y + (D_MARGIN * 2) + D_TXT6_H + D_MARGIN) * RESFACTOR,
|
||||
scheme, TBLACK, TPF_CENTER | TPF_TEXT);
|
||||
Show_Mouse();
|
||||
display = 0;
|
||||
}
|
||||
|
||||
MPath->Service();
|
||||
|
||||
//
|
||||
// Check for an incoming packet; if a PING comes in, see if we already
|
||||
// have this player in our Players list. If not, add him.
|
||||
//
|
||||
if (MPath->Get_Global_Message (&receive_packet, &size, &address) &&
|
||||
receive_packet.Dummy == NET_PING) {
|
||||
found = 0;
|
||||
for (i = 1; i < Session.Players.Count(); i++) {
|
||||
if (Session.Players[i]->MPathAddress == address) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new connection and a new node in the list.
|
||||
//
|
||||
if (!found) {
|
||||
|
||||
who = new NodeNameType;
|
||||
strcpy(who->Name, receive_packet.Name);
|
||||
who->MPathAddress = address;
|
||||
who->Player.House = receive_packet.House;
|
||||
who->Player.Color = (PlayerColorType)receive_packet.Color;
|
||||
Session.Players.Add (who);
|
||||
|
||||
num_found++;
|
||||
|
||||
MPath->Send_Global_Message(&send_packet, sizeof(send_packet), 1,
|
||||
address);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If the user hits ESC, bail out.
|
||||
//
|
||||
if (Keyboard->Check()) {
|
||||
if (Keyboard->Get() == KN_ESC) {
|
||||
//Prog_End();
|
||||
Emergency_Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// When our timer expires, re-send the packet.
|
||||
//
|
||||
if (!send_timer) {
|
||||
send_packet.Dummy = NET_PING;
|
||||
MPath->Send_Global_Message(&send_packet, sizeof(send_packet), 0, 0);
|
||||
send_timer = 240;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Destroy_MPATH_Connection -- Destroys the given connection *
|
||||
* *
|
||||
* INPUT: *
|
||||
* id connection ID to destroy *
|
||||
* error 0 = user signed off; 1 = connection error; otherwise, *
|
||||
* no error is shown. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 01/11/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Destroy_MPATH_Connection(int id, int error)
|
||||
{
|
||||
#if(MPATH)
|
||||
int i;
|
||||
HouseClass *housep;
|
||||
char txt[80];
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Do nothing if the house isn't human.
|
||||
//------------------------------------------------------------------------
|
||||
housep = HouseClass::As_Pointer((HousesType)id);
|
||||
if (!housep || !housep->IsHuman)
|
||||
return;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Create a message to display to the user
|
||||
------------------------------------------------------------------------*/
|
||||
txt[0] = '\0';
|
||||
if (error==1) {
|
||||
sprintf(txt,Text_String(TXT_CONNECTION_LOST),MPath->Connection_Name(id));
|
||||
} else if (error==0) {
|
||||
sprintf(txt,Text_String(TXT_LEFT_GAME),MPath->Connection_Name(id));
|
||||
}
|
||||
|
||||
if (strlen(txt)) {
|
||||
Session.Messages.Add_Message (NULL,0, txt, housep->RemapColor,
|
||||
TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
|
||||
Map.Flag_To_Redraw(false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Remove this player from the Players vector
|
||||
//------------------------------------------------------------------------
|
||||
for (i = 0; i < Session.Players.Count(); i++) {
|
||||
if (!stricmp(Session.Players[i]->Name,housep->IniName)) {
|
||||
delete Session.Players[i];
|
||||
Session.Players.Delete(Session.Players[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Delete the MPATH connection
|
||||
------------------------------------------------------------------------*/
|
||||
MPath->Delete_Connection(id);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Turn the player's house over to the computer's AI
|
||||
//------------------------------------------------------------------------
|
||||
housep->IsHuman = false;
|
||||
housep->IQ = Rule.MaxIQ;
|
||||
strcpy (housep->IniName,Text_String(TXT_COMPUTER));
|
||||
|
||||
Session.NumPlayers--;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
If we're the last player left, tell the user.
|
||||
------------------------------------------------------------------------*/
|
||||
if (Session.NumPlayers == 1) {
|
||||
sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME));
|
||||
Session.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,
|
||||
TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
|
||||
Map.Flag_To_Redraw(false);
|
||||
}
|
||||
|
||||
#else
|
||||
id = id;
|
||||
error = error;
|
||||
|
||||
#endif
|
||||
} // end of Destroy_MPATH_Connection
|
||||
|
||||
|
||||
/***************************** end of ccmpath.cpp **************************/
|
76
CODE/CCPTR.CPP
Normal file
76
CODE/CCPTR.CPP
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CCPTR.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CCPTR.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 06/07/96 *
|
||||
* *
|
||||
* Last Update : July 6, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* CCPtr<T>::operator > -- Greater than comparison operator. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "function.h"
|
||||
|
||||
/*
|
||||
** These member functions for the CCPtr class cannot be declared inside the
|
||||
** class definition since they could refer to other objects that themselves
|
||||
** contain CCPtr objects. The recursive nature of this type of declaration
|
||||
** is not handled by Watcom, hence the body declaration is dislocated here.
|
||||
*/
|
||||
template<class T>
|
||||
CCPtr<T>::CCPtr(T * ptr) : ID(-1)
|
||||
{
|
||||
if (ptr != NULL) {
|
||||
ID = ptr->ID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CCPtr<T>::operator > -- Greater than comparison operator. *
|
||||
* *
|
||||
* This will compare two pointer value to see if the left hand value is greater than the *
|
||||
* right hand. The values are compared by comparing based on their Name() functions. *
|
||||
* *
|
||||
* INPUT: rvalue -- The right handle CCPtr value. *
|
||||
* *
|
||||
* OUTPUT: Is the left hand value greater than the right hand value? *
|
||||
* *
|
||||
* WARNINGS: The values pointed to by CCPtr must have a Name() function defined. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
template<class T>
|
||||
bool CCPtr<T>::operator > (CCPtr<T> const & rvalue) const
|
||||
{
|
||||
return (stricmp((*this)->Name(), rvalue->Name()) > 0);
|
||||
}
|
115
CODE/CCPTR.H
Normal file
115
CODE/CCPTR.H
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CCPTR.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CCPTR.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 06/07/96 *
|
||||
* *
|
||||
* Last Update : June 7, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#ifndef CCPTR_H
|
||||
#define CCPTR_H
|
||||
|
||||
/*
|
||||
** The CCPtr class is designed for a specific purpose. It functions like a pointer except that
|
||||
** it requires no fixups for saving and loading. If pointer fixups are not an issue, than using
|
||||
** regular pointers would be more efficient.
|
||||
*/
|
||||
template<class T>
|
||||
class CCPtr
|
||||
{
|
||||
public:
|
||||
CCPtr(void) : ID(-1) {};
|
||||
CCPtr(NoInitClass const & ) {};
|
||||
CCPtr(T * ptr);
|
||||
|
||||
operator T * (void) const {
|
||||
if (ID == -1) return(NULL);
|
||||
assert(Heap != NULL && (unsigned)ID < Heap->Length());
|
||||
return((T*) (*Heap)[ID]);
|
||||
}
|
||||
T & operator * (void) const {
|
||||
assert(Heap != NULL && (unsigned)ID < Heap->Length());
|
||||
return(*(T*)(*Heap)[ID]);
|
||||
}
|
||||
T * operator -> (void) const {
|
||||
if (ID == -1) return(NULL);
|
||||
assert(Heap != NULL && (unsigned)ID < Heap->Length());
|
||||
return((T*) (*Heap)[ID]);
|
||||
}
|
||||
|
||||
bool Is_Valid(void) const {return(ID != -1);}
|
||||
|
||||
bool operator == (CCPtr<T> const & rvalue) const {return(ID == rvalue.ID);}
|
||||
bool operator != (CCPtr<T> const & rvalue) const {return(ID != rvalue.ID);}
|
||||
bool operator > (CCPtr<T> const & rvalue) const;
|
||||
bool operator <= (CCPtr<T> const & rvalue) const {return (rvalue > *this);}
|
||||
bool operator < (CCPtr<T> const & rvalue) const {return (*this != rvalue && rvalue > *this);}
|
||||
bool operator >= (CCPtr<T> const & rvalue) const {return (*this == rvalue || rvalue > *this);}
|
||||
|
||||
long Raw(void) const {return(ID);}
|
||||
void Set_Raw(long value) {ID = value;}
|
||||
|
||||
private:
|
||||
|
||||
static FixedIHeapClass * Heap;
|
||||
|
||||
/*
|
||||
** This is the ID number of the object it refers to. By using an ID number, this class can
|
||||
** be saved and loaded without pointer fixups.
|
||||
*/
|
||||
int ID;
|
||||
};
|
||||
|
||||
/*
|
||||
** These template helper functions tell the compiler what to do in the
|
||||
** ambiguous case of a CCPtr on one side and a regular type pointer on the
|
||||
** other side. In such a case the compiler could create a temp CCPtr object
|
||||
** OR call the conversion operator on the existing CCPtr object. Either way
|
||||
** is technically valid, but the compiler doesn't know which is better so it
|
||||
** generates an error. These routines force the conversion operator rather than
|
||||
** creating a temporary object. This presumes that the conversion operator is
|
||||
** cheaper than constructing a temporary and that cheaper solutions are desirable.
|
||||
*/
|
||||
template<class T>
|
||||
int operator == (CCPtr<T> & lvalue, T * rvalue)
|
||||
{
|
||||
return((T*)lvalue == rvalue);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int operator == (T * lvalue, CCPtr<T> & rvalue)
|
||||
{
|
||||
return(lvalue == (T*)rvalue);
|
||||
}
|
||||
|
||||
#endif
|
603
CODE/CCTEN.CPP
Normal file
603
CODE/CCTEN.CPP
Normal file
@ -0,0 +1,603 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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 : Command & Conquer *
|
||||
* *
|
||||
* File Name : CCTEN.CPP *
|
||||
* *
|
||||
* Programmer : Bill R. Randolph *
|
||||
* *
|
||||
* Start Date : 01/09/96 *
|
||||
* *
|
||||
* Last Update : November 27, 1996 [BRR] *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Init_TEN -- Performs TEN-specific initialization *
|
||||
* Shutdown_TEN -- Shuts down TEN connections *
|
||||
* Connect_TEN -- Waits for connections to other players *
|
||||
* Destroy_TEN_Connection -- Destroys the given connection *
|
||||
* Debug_Mono -- Custom mono prints *
|
||||
* Send_TEN_Win_Packet -- Sends a win packet to server *
|
||||
* Send_TEN_Alliance -- Sends an ally/enemy packet to server *
|
||||
* Send_TEN_Out_Of_Sync -- Announces this game out of sync *
|
||||
* Send_TEN_Packet_Too_Late -- Announces packet-received-too-late *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
#include "function.h"
|
||||
|
||||
#if(TEN)
|
||||
#ifdef WIN32
|
||||
#define WINDOWS
|
||||
#endif
|
||||
#include "ten.h"
|
||||
#endif
|
||||
|
||||
void Connect_TEN(void);
|
||||
void Debug_Mono(void);
|
||||
|
||||
/***************************************************************************
|
||||
* Init_TEN -- Performs TEN-specific initialization *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = OK, 0 = error *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 01/09/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
int Init_TEN(void)
|
||||
{
|
||||
#if(TEN)
|
||||
//------------------------------------------------------------------------
|
||||
// Allocate a packet buffer for TEN's use
|
||||
//------------------------------------------------------------------------
|
||||
Session.TenPacket = new char[Session.TenSize];
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Read the multiplayer settings from the CONQUER.INI file, and the game
|
||||
// options from the options file.
|
||||
//------------------------------------------------------------------------
|
||||
Session.Read_MultiPlayer_Settings();
|
||||
|
||||
if (!Read_TEN_Game_Options()) {
|
||||
WWMessageBox().Process("Unable to load game settings!");
|
||||
//Prog_End();
|
||||
Emergency_Exit(0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Flush all incoming packets
|
||||
//------------------------------------------------------------------------
|
||||
Ten->Flush_All();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Form connections to all other players
|
||||
//------------------------------------------------------------------------
|
||||
Connect_TEN();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Set multiplayer values for the local system, and timing values.
|
||||
//------------------------------------------------------------------------
|
||||
Session.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;
|
||||
|
||||
return (1);
|
||||
#else
|
||||
return (1);
|
||||
#endif
|
||||
|
||||
} // end of Init_TEN
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Shutdown_TEN -- Shuts down TEN connections *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 01/09/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Shutdown_TEN(void)
|
||||
{
|
||||
#if(TEN)
|
||||
CDTimerClass<SystemTimerClass> timer;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Wait a full second before exiting, to ensure all packets get sent.
|
||||
//------------------------------------------------------------------------
|
||||
timer = 60;
|
||||
while (timer) ;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Free memory
|
||||
//------------------------------------------------------------------------
|
||||
if (Session.TenPacket) {
|
||||
delete [] Session.TenPacket;
|
||||
Session.TenPacket = NULL;
|
||||
}
|
||||
|
||||
if (Ten) {
|
||||
delete Ten;
|
||||
Ten = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
#endif
|
||||
} // end of Shutdown_TEN
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Connect_TEN -- Waits for connections to other players *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* MPlayerCount must have been initialized at this point. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 01/10/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Connect_TEN(void)
|
||||
{
|
||||
#if(TEN)
|
||||
typedef struct ConnectPacketTag {
|
||||
NetCommandType Dummy; // packet type; set to PING
|
||||
char Name[MPLAYER_NAME_MAX]; // player's name
|
||||
HousesType House; // player's ActLike
|
||||
unsigned char Color; // player's Color
|
||||
} ConnectPacketType;
|
||||
int num_players;
|
||||
int num_found;
|
||||
ConnectPacketType send_packet;
|
||||
ConnectPacketType receive_packet;
|
||||
int address;
|
||||
int found;
|
||||
int size;
|
||||
int i;
|
||||
CDTimerClass<SystemTimerClass> send_timer;
|
||||
NodeNameType *who;
|
||||
|
||||
enum {
|
||||
D_TXT6_H = 7,
|
||||
D_MARGIN = 5,
|
||||
};
|
||||
static int x,y,w,h;
|
||||
char const *buf1;
|
||||
char const *buf2;
|
||||
|
||||
int display = 0;
|
||||
RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
|
||||
|
||||
//
|
||||
// Clear the Players list
|
||||
//
|
||||
while (Session.Players.Count() > 0) {
|
||||
delete Session.Players[0];
|
||||
Session.Players.Delete(Session.Players[0]);
|
||||
}
|
||||
|
||||
//
|
||||
// Add myself to the list first thing
|
||||
//
|
||||
who = new NodeNameType;
|
||||
strcpy(who->Name, Session.Handle);
|
||||
who->Player.House = Session.House;
|
||||
who->Player.Color = Session.ColorIdx;
|
||||
Session.Players.Add (who);
|
||||
|
||||
//
|
||||
// Find out how many players to wait for
|
||||
//
|
||||
num_players = Session.NumPlayers - 1;
|
||||
num_found = 0;
|
||||
|
||||
//
|
||||
// Send out a packet announcing my presence
|
||||
//
|
||||
send_packet.Dummy = NET_PING;
|
||||
strcpy(send_packet.Name, Session.Handle);
|
||||
send_packet.House = Session.House;
|
||||
send_packet.Color = Session.ColorIdx;
|
||||
Ten->Send_Global_Message(&send_packet, sizeof(send_packet), 0, -1);
|
||||
|
||||
//
|
||||
// Start our packet-sending timer
|
||||
//
|
||||
send_timer = 240;
|
||||
|
||||
//
|
||||
// Wait for all players to enter the game
|
||||
//
|
||||
display = 1;
|
||||
while (num_found < num_players) {
|
||||
|
||||
#ifdef WIN32
|
||||
/*
|
||||
** If we have just received input focus again after running in the background then
|
||||
** we need to redraw.
|
||||
*/
|
||||
if (AllSurfaces.SurfacesRestored) {
|
||||
AllSurfaces.SurfacesRestored=FALSE;
|
||||
display = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display) {
|
||||
Fancy_Text_Print("", 0, 0, 0, 0, TPF_TEXT);
|
||||
buf1 = Text_String(TXT_WAITING_FOR_CONNECTIONS);
|
||||
buf2 = Text_String(TXT_PRESS_ESC);
|
||||
w = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));
|
||||
w += (D_MARGIN * 2);
|
||||
h = (D_TXT6_H * 2) + (D_MARGIN * 7);
|
||||
x = 160 - (w / 2);
|
||||
y = 100 - (h / 2);
|
||||
Hide_Mouse();
|
||||
//Set_Logic_Page(SeenBuff);
|
||||
Dialog_Box(x * RESFACTOR, y * RESFACTOR, w * RESFACTOR, h * RESFACTOR);
|
||||
|
||||
Fancy_Text_Print(buf1,
|
||||
160 * RESFACTOR,
|
||||
(y + (D_MARGIN * 2)) * RESFACTOR,
|
||||
scheme, TBLACK, TPF_CENTER | TPF_TEXT);
|
||||
Fancy_Text_Print(buf2,
|
||||
160 * RESFACTOR,
|
||||
(y + (D_MARGIN * 2) + D_TXT6_H + D_MARGIN) * RESFACTOR,
|
||||
scheme, TBLACK, TPF_CENTER | TPF_TEXT);
|
||||
Show_Mouse();
|
||||
display = 0;
|
||||
}
|
||||
|
||||
Ten->Service();
|
||||
|
||||
//
|
||||
// Check for an incoming packet; if a PING comes in, see if we already
|
||||
// have this player in our Players list. If not, add him.
|
||||
//
|
||||
if (Ten->Get_Global_Message (&receive_packet, &size, &address) &&
|
||||
receive_packet.Dummy == NET_PING) {
|
||||
found = 0;
|
||||
for (i = 1; i < Session.Players.Count(); i++) {
|
||||
if (Session.Players[i]->TenAddress == address) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new connection and a new node in the list.
|
||||
//
|
||||
if (!found) {
|
||||
|
||||
who = new NodeNameType;
|
||||
strcpy(who->Name, receive_packet.Name);
|
||||
who->TenAddress = address;
|
||||
who->Player.House = receive_packet.House;
|
||||
who->Player.Color = (PlayerColorType)receive_packet.Color;
|
||||
Session.Players.Add (who);
|
||||
|
||||
num_found++;
|
||||
|
||||
Ten->Send_Global_Message(&send_packet, sizeof(send_packet), 1,
|
||||
address);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If the user hits ESC, bail out.
|
||||
//
|
||||
if (Keyboard->Check()) {
|
||||
if (Keyboard->Get() == KN_ESC) {
|
||||
//Prog_End();
|
||||
Emergency_Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// When our timer expires, re-send the packet.
|
||||
//
|
||||
if (!send_timer) {
|
||||
send_packet.Dummy = NET_PING;
|
||||
Ten->Send_Global_Message(&send_packet, sizeof(send_packet), 0, -1);
|
||||
send_timer = 240;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Destroy_TEN_Connection -- Destroys the given connection *
|
||||
* *
|
||||
* INPUT: *
|
||||
* id connection ID to destroy (must be a HousesType) *
|
||||
* error 0 = user signed off; 1 = connection error; otherwise, *
|
||||
* no error is shown. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 01/11/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Destroy_TEN_Connection(int id, int error)
|
||||
{
|
||||
#if(TEN)
|
||||
int i;
|
||||
HouseClass *housep;
|
||||
char txt[80];
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Do nothing if the house isn't human.
|
||||
//------------------------------------------------------------------------
|
||||
housep = HouseClass::As_Pointer((HousesType)id);
|
||||
if (!housep || !housep->IsHuman)
|
||||
return;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Create a message to display to the user
|
||||
------------------------------------------------------------------------*/
|
||||
txt[0] = '\0';
|
||||
if (error==1) {
|
||||
sprintf(txt,Text_String(TXT_CONNECTION_LOST),Ten->Connection_Name(id));
|
||||
} else if (error==0) {
|
||||
sprintf(txt,Text_String(TXT_LEFT_GAME),Ten->Connection_Name(id));
|
||||
}
|
||||
|
||||
if (strlen(txt)) {
|
||||
Session.Messages.Add_Message (NULL,0, txt, housep->RemapColor,
|
||||
TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
|
||||
Map.Flag_To_Redraw(false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Remove this player from the Players vector
|
||||
//------------------------------------------------------------------------
|
||||
for (i = 0; i < Session.Players.Count(); i++) {
|
||||
if (!stricmp(Session.Players[i]->Name,housep->IniName)) {
|
||||
delete Session.Players[i];
|
||||
Session.Players.Delete(Session.Players[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Delete the TEN connection
|
||||
------------------------------------------------------------------------*/
|
||||
Ten->Delete_Connection(id);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Turn the player's house over to the computer's AI
|
||||
//------------------------------------------------------------------------
|
||||
housep->IsHuman = false;
|
||||
housep->IQ = Rule.MaxIQ;
|
||||
strcpy (housep->IniName,Text_String(TXT_COMPUTER));
|
||||
|
||||
Session.NumPlayers--;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
If we're the last player left, tell the user.
|
||||
------------------------------------------------------------------------*/
|
||||
if (Session.NumPlayers == 1) {
|
||||
sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME));
|
||||
Session.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,
|
||||
TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
|
||||
Map.Flag_To_Redraw(false);
|
||||
}
|
||||
|
||||
#else
|
||||
id = id;
|
||||
error = error;
|
||||
|
||||
#endif
|
||||
} // end of Destroy_TEN_Connection
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Debug_Mono -- Custom mono prints *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/27/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Debug_Mono(void)
|
||||
{
|
||||
#if(TEN)
|
||||
int i;
|
||||
int id;
|
||||
|
||||
Mono_Printf("STATE: # Connections:%d\n",Ten->Num_Connections());
|
||||
for (i=0;i<Ten->Num_Connections();i++) {
|
||||
id = Ten->Connection_ID(i);
|
||||
Mono_Printf("Connection %d: Name:%s, ID:%d, Address:%d\n",
|
||||
i,
|
||||
Ten->Connection_Name(id),
|
||||
Ten->Connection_ID(i),
|
||||
Ten->Connection_Address(id));
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Send_TEN_Win_Packet -- Sends a win packet to server *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/27/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Send_TEN_Win_Packet(void)
|
||||
{
|
||||
#if(TEN)
|
||||
char winbuf[80];
|
||||
char idbuf[20];
|
||||
int first = 1;
|
||||
HouseClass *hptr;
|
||||
int i;
|
||||
|
||||
//
|
||||
// Build a special text buffer to send to the TEN server. Format:
|
||||
// "winner 'id id'", where 'id' is the Ten Player ID of each player
|
||||
// on the winning team. (For TEN, the color index is the player ID.)
|
||||
//
|
||||
sprintf(winbuf,"winner '");
|
||||
for (i = 0; i < Session.Players.Count(); i++) {
|
||||
hptr = HouseClass::As_Pointer(Session.Players[i]->Player.ID);
|
||||
if (!hptr->IsDefeated) {
|
||||
if (!first) {
|
||||
strcat(winbuf," ");
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
sprintf(idbuf,"%d", Session.Players[i]->Player.Color);
|
||||
strcat (winbuf, idbuf);
|
||||
}
|
||||
}
|
||||
strcat (winbuf,"' ");
|
||||
tenArSetPlayerState(winbuf);
|
||||
#endif // TEN
|
||||
|
||||
} // end of Send_TEN_Win_Packet
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Send_TEN_Alliance -- Sends an ally/enemy packet to server *
|
||||
* *
|
||||
* INPUT: *
|
||||
* whom name of player we're allying / enemying with *
|
||||
* ally 1 = we're allying; 0 = we're breaking the alliance *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/27/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Send_TEN_Alliance(char *whom, int ally)
|
||||
{
|
||||
#if(TEN)
|
||||
char buf[80];
|
||||
|
||||
if (ally) {
|
||||
sprintf(buf,"ally '%s' ",whom);
|
||||
} else {
|
||||
sprintf(buf,"enemy '%s' ",whom);
|
||||
}
|
||||
|
||||
tenArSetPlayerState(buf);
|
||||
|
||||
#else
|
||||
whom = whom;
|
||||
ally = ally;
|
||||
#endif // TEN
|
||||
|
||||
} // end of Send_TEN_Alliance
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Send_TEN_Out_Of_Sync -- Announces this game out of sync *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/27/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Send_TEN_Out_Of_Sync(void)
|
||||
{
|
||||
#if(TEN)
|
||||
tenArSetPlayerState("sync '1' ");
|
||||
#endif // TEN
|
||||
|
||||
} // end of Send_TEN_Out_Of_Sync
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Send_TEN_Packet_Too_Late -- Announces packet-received-too-late *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/27/1996 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void Send_TEN_Packet_Too_Late(void)
|
||||
{
|
||||
#if(TEN)
|
||||
tenArSetPlayerState("toolate '1' ");
|
||||
#endif // TEN
|
||||
|
||||
} // end of Send_TEN_Packet_Too_Late
|
||||
|
||||
|
||||
/***************************** end of ccten.cpp *****************************/
|
6
CODE/CC_ICON.RC
Normal file
6
CODE/CC_ICON.RC
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
#define ICON_1 1
|
||||
|
||||
|
||||
ICON_1 ICON "redalert.ico"
|
||||
|
1
CODE/CC_ICON.RH
Normal file
1
CODE/CC_ICON.RH
Normal file
@ -0,0 +1 @@
|
||||
#define ICON_1 1
|
3324
CODE/CDATA.CPP
Normal file
3324
CODE/CDATA.CPP
Normal file
File diff suppressed because it is too large
Load Diff
720
CODE/CDFILE.CPP
Normal file
720
CODE/CDFILE.CPP
Normal file
@ -0,0 +1,720 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CDFILE.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Westwood Library *
|
||||
* *
|
||||
* File Name : CDFILE.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : October 18, 1994 *
|
||||
* *
|
||||
* Last Update : September 22, 1995 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* CDFileClass::Clear_Search_Drives -- Removes all record of a search path. *
|
||||
* CDFileClass::Open -- Opens the file object -- with path search. *
|
||||
* CDFileClass::Open -- Opens the file wherever it can be found. *
|
||||
* CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename. *
|
||||
* CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access. *
|
||||
* Is_Disk_Inserted -- Checks to see if a disk is inserted in specified drive. *
|
||||
* harderr_handler -- Handles hard DOS errors. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "cdfile.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <wwstd.h>
|
||||
#include <playcd.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Pointer to the first search path record.
|
||||
*/
|
||||
CDFileClass::SearchDriveType * CDFileClass::First = 0;
|
||||
|
||||
int CDFileClass::CurrentCDDrive = 0;
|
||||
int CDFileClass::LastCDDrive = 0;
|
||||
char CDFileClass::RawPath[512] = {0};
|
||||
|
||||
CDFileClass::CDFileClass(char const *filename) :
|
||||
IsDisabled(false)
|
||||
{
|
||||
CDFileClass::Set_Name(filename);
|
||||
// memset (RawPath, 0, sizeof(RawPath));
|
||||
}
|
||||
|
||||
|
||||
CDFileClass::CDFileClass(void) :
|
||||
IsDisabled(false)
|
||||
{
|
||||
}
|
||||
extern int Get_CD_Index (int cd_drive, int timeout);
|
||||
|
||||
/***********************************************************************************************
|
||||
* harderr_handler -- Handles hard DOS errors. *
|
||||
* *
|
||||
* This routine will handle the low level DOS error trapper. Instead of displaying the *
|
||||
* typical "Abort, Retry, Ignore" message, it simply returns with the failure code. The *
|
||||
* cause of the error will fail. The likely case would be with disk I/O. *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: Return the failure code. *
|
||||
* *
|
||||
* WARNINGS: Do no processing in this routine that could possibly generate another *
|
||||
* hard error condition. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/22/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
#ifdef WIN32
|
||||
int harderr_handler(unsigned int , unsigned int , unsigned int *)
|
||||
#else
|
||||
int harderr_handler(unsigned int , unsigned int , unsigned int __far *)
|
||||
#endif
|
||||
{
|
||||
return(_HARDERR_FAIL);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Is_Disk_Inserted -- Checks to see if a disk is inserted in specified drive. *
|
||||
* *
|
||||
* This routine will examine the drive specified to see if there is a disk inserted. It *
|
||||
* can be used for floppy drives as well as for the CD-ROM. *
|
||||
* *
|
||||
* INPUT: disk -- The drive number to examine. 0=A, 1=B, etc. *
|
||||
* *
|
||||
* OUTPUT: bool; Is a disk inserted into the specified drive? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 09/20/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int cdecl Is_Disk_Inserted(int disk)
|
||||
{
|
||||
#ifndef OBSOLETE
|
||||
struct find_t fb;
|
||||
char scan[] = "?:\\*.*";
|
||||
|
||||
#ifndef WIN32
|
||||
_harderr(harderr_handler); // BG: Install hard error handler
|
||||
#endif
|
||||
|
||||
scan[0] = (char)('A' + disk);
|
||||
return(_dos_findfirst(scan, _A_SUBDIR, &fb) == 0);
|
||||
#else
|
||||
struct {
|
||||
struct {
|
||||
char Length;
|
||||
char Unit;
|
||||
char Function;
|
||||
char Status;
|
||||
char Reserved[8];
|
||||
} ReqHdr;
|
||||
char MediaDescriptor; // Media descriptor byte from BPB.
|
||||
void *Transfer; // Pointer to transfer address block.
|
||||
short Length; // Number of bytes to transfer.
|
||||
short Sector; // Starting sector number.
|
||||
void *Volume; // Pointer to requested volume.
|
||||
} IOCTLI;
|
||||
char status[5];
|
||||
|
||||
memset(IOCTLI, 0, sizeof(IOCTLI));
|
||||
IOCTLI.ReqHdr.Length = 26;
|
||||
IOCTLI.ReqHdr.Unit = 0; // First CD-ROM controlled by this driver.
|
||||
//IOCTLI.ReqHdr.Unit = 11; // Hard coded for K:
|
||||
IOCTLI.ReqHdr.Function = 3; // IOCTL read
|
||||
IOCTLI.Transfer = &status[0];
|
||||
IOCTLI.Length = sizeof(status);
|
||||
status[0] = 6; // Fetch device status code.
|
||||
_AX = 0x440D;
|
||||
_CX = 0x0003;
|
||||
geninterrupt(0x21);
|
||||
return(!(_AX & (1<<11)));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CDFileClass::Open -- Opens the file object -- with path search. *
|
||||
* *
|
||||
* This will open the file object, but since the file object could have been constructed *
|
||||
* with a pathname, this routine will try to find the file first. For files opened for *
|
||||
* writing, then use the existing filename without performing a path search. *
|
||||
* *
|
||||
* INPUT: rights -- The access rights to use when opening the file *
|
||||
* *
|
||||
* OUTPUT: bool; Was the open successful? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int CDFileClass::Open(int rights)
|
||||
{
|
||||
return(BufferIOFileClass::Open(rights));
|
||||
}
|
||||
/***********************************************************************************************
|
||||
* CDFC::Refresh_Search_Drives -- Updates the search path when a CD changes or is added *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 5/22/96 9:01AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void CDFileClass::Refresh_Search_Drives (void)
|
||||
{
|
||||
Clear_Search_Drives();
|
||||
Set_Search_Drives(RawPath);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/***********************************************************************************************
|
||||
* CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access. *
|
||||
* *
|
||||
* This routine sets up a list of search paths to use when accessing files. The path list *
|
||||
* is scanned if the file could not be found in the current directory. This is the primary *
|
||||
* method of supporting CD-ROM drives, but is also useful for scanning network and other *
|
||||
* directories. The pathlist as passed to this routine is of the same format as the path *
|
||||
* list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.*
|
||||
* *
|
||||
* If a path entry begins with "?:" then the question mark will be replaced with the first *
|
||||
* CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path *
|
||||
* entry will be ignored. By using this feature, you can always pass the CD-ROM path *
|
||||
* specification to this routine and it will not break if the CD-ROM is not loaded (as in *
|
||||
* the case during development). *
|
||||
* *
|
||||
* Here is an example path specification: *
|
||||
* *
|
||||
* Set_Search_Drives("DATA;?:\DATA;F:\PROJECT\DATA"); *
|
||||
* *
|
||||
* In this example, the current directory will be searched first, followed by a the *
|
||||
* subdirectory "DATA" located off of the current directory. If not found, then the CD-ROM *
|
||||
* will be searched in a directory called "\DATA". If not found or the CD-ROM is not *
|
||||
* present, then it will look to the hard coded path of "F:\PROJECTS\DATA" (maybe a *
|
||||
* network?). If all of these searches fail, the file system will default to the current *
|
||||
* directory and let the normal file error system take over. *
|
||||
* *
|
||||
* INPUT: pathlist -- Pointer to string of path specifications (separated by semicolons) *
|
||||
* that will be used to search for files. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int CDFileClass::Set_Search_Drives(char * pathlist)
|
||||
{
|
||||
int found = false;
|
||||
int empty = false;
|
||||
|
||||
/*
|
||||
** If there is no pathlist to add, then just return.
|
||||
*/
|
||||
if (!pathlist) return(0);
|
||||
|
||||
char const * ptr = strtok(pathlist, ";");
|
||||
while (ptr) {
|
||||
char path[PATH_MAX]; // Working path buffer.
|
||||
SearchDriveType *srch; // Working pointer to path object.
|
||||
|
||||
/*
|
||||
** Fixup the path to be legal. Legal is defined as all that is necessary to
|
||||
** create a pathname is to append the actual filename submitted to the
|
||||
** file system. This means that it must have either a trailing ':' or '\'
|
||||
** character.
|
||||
*/
|
||||
strcpy(path, ptr);
|
||||
switch (path[strlen(path)-1]) {
|
||||
case ':':
|
||||
case '\\':
|
||||
break;
|
||||
|
||||
default:
|
||||
strcat(path, "\\");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** If there is a drive letter specified, and this drive letter is '?', then it should
|
||||
** be substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then
|
||||
** merely ignore this path entry.
|
||||
*/
|
||||
if (strncmp(path, "?:", 2) == 0) {
|
||||
#ifndef WIN32
|
||||
GetCDClass temp;
|
||||
int cd = temp.GetCDDrive();
|
||||
#else
|
||||
int cd = 10;
|
||||
#endif
|
||||
found = cd;
|
||||
empty = !Is_Disk_Inserted(cd);
|
||||
if (!found || empty) goto nextpath;
|
||||
path[0] = (char)('A' + cd);
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate a record structure.
|
||||
*/
|
||||
srch = new SearchDriveType;
|
||||
if (srch) {
|
||||
found = true;
|
||||
|
||||
/*
|
||||
** Attach the path to this structure.
|
||||
*/
|
||||
srch->Path = strdup(path);
|
||||
srch->Next = NULL;
|
||||
|
||||
/*
|
||||
** Attach this path record to the end of the path chain.
|
||||
*/
|
||||
if (!First) {
|
||||
First = srch;
|
||||
} else {
|
||||
SearchDriveType * chain = First;
|
||||
|
||||
while (chain->Next) {
|
||||
chain = (SearchDriveType *)chain->Next;
|
||||
}
|
||||
chain->Next = srch;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Find the next path string and resubmit.
|
||||
*/
|
||||
nextpath:
|
||||
ptr = strtok(NULL, ";");
|
||||
}
|
||||
if (!found) return(1);
|
||||
if (empty) return(2);
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access. *
|
||||
* *
|
||||
* This routine sets up a list of search paths to use when accessing files. The path list *
|
||||
* is scanned if the file could not be found in the current directory. This is the primary *
|
||||
* method of supporting CD-ROM drives, but is also useful for scanning network and other *
|
||||
* directories. The pathlist as passed to this routine is of the same format as the path *
|
||||
* list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.*
|
||||
* *
|
||||
* If a path entry begins with "?:" then the question mark will be replaced with the first *
|
||||
* CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path *
|
||||
* entry will be ignored. By using this feature, you can always pass the CD-ROM path *
|
||||
* specification to this routine and it will not break if the CD-ROM is not loaded (as in *
|
||||
* the case during development). *
|
||||
* *
|
||||
* Here is an example path specification: *
|
||||
* *
|
||||
* Set_Search_Drives("DATA;?:\DATA;F:\PROJECT\DATA"); *
|
||||
* *
|
||||
* In this example, the current directory will be searched first, followed by a the *
|
||||
* subdirectory "DATA" located off of the current directory. If not found, then the CD-ROM *
|
||||
* will be searched in a directory called "\DATA". If not found or the CD-ROM is not *
|
||||
* present, then it will look to the hard coded path of "F:\PROJECTS\DATA" (maybe a *
|
||||
* network?). If all of these searches fail, the file system will default to the current *
|
||||
* directory and let the normal file error system take over. *
|
||||
* *
|
||||
* INPUT: pathlist -- Pointer to string of path specifications (separated by semicolons) *
|
||||
* that will be used to search for files. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
* 05/21/1996 ST : Modified to recognise multiple CD drives *
|
||||
*=============================================================================================*/
|
||||
int CDFileClass::Set_Search_Drives(char * pathlist)
|
||||
{
|
||||
int found = FALSE;
|
||||
int empty = FALSE;
|
||||
|
||||
/*
|
||||
** If there is no pathlist to add, then just return.
|
||||
*/
|
||||
if (!pathlist) return(0);
|
||||
|
||||
/*
|
||||
** Save the path as it was passed in so we can parse it again later.
|
||||
** Check for the case where RawPath was passed in.
|
||||
*/
|
||||
if (pathlist != RawPath) {
|
||||
strcat (RawPath, ";");
|
||||
strcat (RawPath, pathlist);
|
||||
}
|
||||
|
||||
char const * ptr = strtok(pathlist, ";");
|
||||
while (ptr != NULL) {
|
||||
if (strlen(ptr) > 0) {
|
||||
|
||||
char path[PATH_MAX]; // Working path buffer.
|
||||
|
||||
/*
|
||||
** Fixup the path to be legal. Legal is defined as all that is necessary to
|
||||
** create a pathname is to append the actual filename submitted to the
|
||||
** file system. This means that it must have either a trailing ':' or '\'
|
||||
** character.
|
||||
*/
|
||||
strcpy(path, ptr);
|
||||
switch (path[strlen(path)-1]) {
|
||||
case ':':
|
||||
case '\\':
|
||||
break;
|
||||
|
||||
default:
|
||||
strcat(path, "\\");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** If there is a drive letter specified, and this drive letter is '?', then it should
|
||||
** be substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then
|
||||
** merely ignore this path entry.
|
||||
** Adds an extra entry for each CD drive in the system that has a C&C disc inserted.
|
||||
** ST - 5/21/96 4:40PM
|
||||
*/
|
||||
if (strncmp(path, "?:", 2) == 0) {
|
||||
if (CurrentCDDrive) {
|
||||
found = true;
|
||||
|
||||
/*
|
||||
** If the drive has a C&C CD in it then add it to the path
|
||||
*/
|
||||
if (Get_CD_Index(CurrentCDDrive, 2*60) >= 0) {
|
||||
path[0] = (char)(CurrentCDDrive + 'A');
|
||||
Add_Search_Drive(path);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Find the next path string and resubmit.
|
||||
*/
|
||||
ptr = strtok(NULL, ";");
|
||||
continue;
|
||||
}
|
||||
|
||||
found = true;
|
||||
Add_Search_Drive(path);
|
||||
}
|
||||
|
||||
/*
|
||||
** Find the next path string and resubmit.
|
||||
*/
|
||||
ptr = strtok(NULL, ";");
|
||||
}
|
||||
if (!found) return(1);
|
||||
if (empty) return(2);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CDFC::Add_Search_Drive -- Add a new path to the search path list *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: path *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 5/22/96 10:12AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void CDFileClass::Add_Search_Drive(char *path)
|
||||
{
|
||||
SearchDriveType *srch; // Working pointer to path object.
|
||||
/*
|
||||
** Allocate a record structure.
|
||||
*/
|
||||
srch = new SearchDriveType;
|
||||
|
||||
/*
|
||||
** Attach the path to this structure.
|
||||
*/
|
||||
srch->Path = strdup(path);
|
||||
srch->Next = NULL;
|
||||
|
||||
/*
|
||||
** Attach this path record to the end of the path chain.
|
||||
*/
|
||||
if (!First) {
|
||||
First = srch;
|
||||
} else {
|
||||
SearchDriveType * chain = First;
|
||||
|
||||
while (chain->Next) {
|
||||
chain = (SearchDriveType *)chain->Next;
|
||||
}
|
||||
chain->Next = srch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CDFC::Set_CD_Drive -- sets the current CD drive letter *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 5/22/96 9:39AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void CDFileClass::Set_CD_Drive (int drive)
|
||||
{
|
||||
LastCDDrive = CurrentCDDrive;
|
||||
CurrentCDDrive = drive;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CDFileClass::Clear_Search_Drives -- Removes all record of a search path. *
|
||||
* *
|
||||
* Use this routine to clear out any previous path(s) set with Set_Search_Drives() *
|
||||
* function. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void CDFileClass::Clear_Search_Drives(void)
|
||||
{
|
||||
SearchDriveType * chain; // Working pointer to path chain.
|
||||
|
||||
chain = First;
|
||||
while (chain) {
|
||||
SearchDriveType *next;
|
||||
|
||||
next = (SearchDriveType *)chain->Next;
|
||||
if (chain->Path) {
|
||||
free((char *)chain->Path);
|
||||
}
|
||||
delete chain;
|
||||
|
||||
chain = next;
|
||||
}
|
||||
First = 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename. *
|
||||
* *
|
||||
* This routine will scan all the directories specified in the path list and if the file *
|
||||
* was found in one of the directories, it will set the filename to a composite of the *
|
||||
* correct directory and the filename. It is used to allow path searching when searching *
|
||||
* for files. Typical use is to support CD-ROM drives. This routine examines the current *
|
||||
* directory first before scanning through the path list. If after scanning the entire *
|
||||
* path list, the file still could not be found, then the file object's name is set with *
|
||||
* just the raw filename as passed to this routine. *
|
||||
* *
|
||||
* INPUT: filename -- Pointer to the filename to set as the name of this file object. *
|
||||
* *
|
||||
* OUTPUT: Returns a pointer to the final and complete filename of this file object. This *
|
||||
* may have a path attached to the file. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
char const * CDFileClass::Set_Name(char const *filename)
|
||||
{
|
||||
/*
|
||||
** Try to find the file in the current directory first. If it can be found, then
|
||||
** just return with the normal file name setting process. Do the same if there is
|
||||
** no multi-drive search path.
|
||||
*/
|
||||
BufferIOFileClass::Set_Name(filename);
|
||||
if (IsDisabled || !First || BufferIOFileClass::Is_Available()) return(File_Name());
|
||||
|
||||
/*
|
||||
** Attempt to find the file first. Check the current directory. If not found there, then
|
||||
** search all the path specifications available. If it still can't be found, then just
|
||||
** fall into the normal raw file filename setting system.
|
||||
*/
|
||||
SearchDriveType * srch = First;
|
||||
|
||||
while (srch) {
|
||||
char path[_MAX_PATH];
|
||||
|
||||
/*
|
||||
** Build a pathname to search for.
|
||||
*/
|
||||
strcpy(path, srch->Path);
|
||||
strcat(path, filename);
|
||||
|
||||
/*
|
||||
** Check to see if the file could be found. The low level Is_Available logic will
|
||||
** prompt if necessary when the CD-ROM drive has been removed. In all other cases,
|
||||
** it will return false and the search process will continue.
|
||||
*/
|
||||
BufferIOFileClass::Set_Name(path);
|
||||
if (BufferIOFileClass::Is_Available()) {
|
||||
return(File_Name());
|
||||
}
|
||||
|
||||
/*
|
||||
** It wasn't found, so try the next path entry.
|
||||
*/
|
||||
srch = (SearchDriveType *)srch->Next;
|
||||
}
|
||||
|
||||
/*
|
||||
** At this point, all path searching has failed. Just set the file name to the
|
||||
** plain text passed to this routine and be done with it.
|
||||
*/
|
||||
BufferIOFileClass::Set_Name(filename);
|
||||
return(File_Name());
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CDFileClass::Open -- Opens the file wherever it can be found. *
|
||||
* *
|
||||
* This routine is similar to the RawFileClass open except that if the file is being *
|
||||
* opened only for READ access, it will search all specified directories looking for the *
|
||||
* file. If after a complete search the file still couldn't be found, then it is opened *
|
||||
* using the normal BufferIOFileClass system -- resulting in normal error procedures. *
|
||||
* *
|
||||
* INPUT: filename -- Pointer to the override filename to supply for this file object. It *
|
||||
* would be the base filename (sans any directory specification). *
|
||||
* *
|
||||
* rights -- The access rights to use when opening the file. *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file opened successfully? If so then the filename may be different *
|
||||
* than requested. The location of the file can be determined by examining the *
|
||||
* filename of this file object. The filename will contain the complete *
|
||||
* pathname used to open the file. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/18/1994 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int CDFileClass::Open(char const *filename, int rights)
|
||||
{
|
||||
CDFileClass::Close();
|
||||
|
||||
/*
|
||||
** Verify that there is a filename associated with this file object. If not, then this is a
|
||||
** big error condition.
|
||||
*/
|
||||
if (!filename) {
|
||||
Error(ENOENT, false);
|
||||
}
|
||||
|
||||
/*
|
||||
** If writing is requested, then multiple drive searching is not performed.
|
||||
*/
|
||||
if (IsDisabled || rights == WRITE) {
|
||||
|
||||
BufferIOFileClass::Set_Name( filename );
|
||||
return( BufferIOFileClass::Open( rights ) );
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform normal multiple drive searching for the filename and open
|
||||
** using the normal procedure.
|
||||
*/
|
||||
Set_Name(filename);
|
||||
return(BufferIOFileClass::Open(rights));
|
||||
}
|
||||
|
||||
|
||||
#ifdef NEVER
|
||||
/*
|
||||
** Get the drive letters if the CD's online */
|
||||
*/
|
||||
WORD cdecl GetCDDrive(VOID)
|
||||
{
|
||||
_ES = FP_SEG(&cdDrive[0]);
|
||||
_BX = FP_OFF(&cdDrive[0]);
|
||||
_AX = 0x150d;
|
||||
geninterrupt(0x2F);
|
||||
return((WORD)(*cdDrive));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int Get_CD_Drive(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return(10);
|
||||
#else
|
||||
|
||||
#ifdef NEVER
|
||||
for (int index = 0; index < 26; index++) {
|
||||
union REGS regs;
|
||||
|
||||
regs.w.ax = 0x150B;
|
||||
regs.w.bx = 0;
|
||||
regs.w.cx = index;
|
||||
int386(0x2F, ®s, ®s);
|
||||
if (regs.w.bx == 0xADAD) {
|
||||
return(index);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
#else
|
||||
GetCDClass temp;
|
||||
return(temp.GetCDDrive());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
113
CODE/CDFILE.H
Normal file
113
CODE/CDFILE.H
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CDFILE.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Westwood LIbrary *
|
||||
* *
|
||||
* File Name : CDFILE.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : October 18, 1994 *
|
||||
* *
|
||||
* Last Update : October 18, 1994 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef CDFILE_H
|
||||
#define CDFILE_H
|
||||
|
||||
#include <dos.h>
|
||||
#include "bfiofile.h"
|
||||
|
||||
/*
|
||||
** This class is derived from the BufferIOFileClass. This class adds the functionality of searching
|
||||
** across multiple directories or drives. It is designed for the typical case of a CD-ROM game
|
||||
** were some data exists in the current directory (hard drive) and the rest exists on the CD-ROM.
|
||||
** Searching for the file occurs by first examining the current directory. If the file does not
|
||||
** exist there, then all the paths available are examined in turn until the file can be found.
|
||||
** For opening files to write, only the current directory is examined. The directory search order
|
||||
** is controlled by the path list as submitted to Set_Search_Drives(). The format of the path
|
||||
** string is the same as the DOS path string.
|
||||
*/
|
||||
class CDFileClass : public BufferIOFileClass
|
||||
{
|
||||
public:
|
||||
CDFileClass(char const *filename);
|
||||
CDFileClass(void);
|
||||
virtual ~CDFileClass(void) {};
|
||||
|
||||
virtual char const * Set_Name(char const *filename);
|
||||
virtual int Open(char const *filename, int rights=READ);
|
||||
virtual int Open(int rights=READ);
|
||||
|
||||
void Searching(int on) {IsDisabled = !on;};
|
||||
|
||||
static bool Is_There_Search_Drives(void) {return(First != NULL);};
|
||||
static int Set_Search_Drives(char * pathlist);
|
||||
static void Add_Search_Drive(char *path);
|
||||
static void Clear_Search_Drives(void);
|
||||
static void Refresh_Search_Drives(void);
|
||||
static void Set_CD_Drive(int drive);
|
||||
static int Get_CD_Drive(void) {return(CurrentCDDrive);};
|
||||
static int Get_Last_CD_Drive(void) {return(LastCDDrive);};
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
** Is multi-drive searching disabled for this file object?
|
||||
*/
|
||||
unsigned IsDisabled:1;
|
||||
|
||||
/*
|
||||
** This is the control record for each of the drives specified in the search
|
||||
** path. There can be many such search paths available.
|
||||
*/
|
||||
typedef struct {
|
||||
void * Next; // Pointer to next search record.
|
||||
char const * Path; // Pointer to path string.
|
||||
} SearchDriveType;
|
||||
|
||||
/*
|
||||
** This points to the first path record.
|
||||
*/
|
||||
static SearchDriveType * First;
|
||||
/*
|
||||
** This is a copy of the unparsed search path list
|
||||
*/
|
||||
static char RawPath[512];
|
||||
|
||||
/*
|
||||
** The drive letter of the current cd drive
|
||||
*/
|
||||
static int CurrentCDDrive;
|
||||
|
||||
/*
|
||||
** The drive letter of the last used CD drive
|
||||
*/
|
||||
static int LastCDDrive;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
3014
CODE/CELL.CPP
Normal file
3014
CODE/CELL.CPP
Normal file
File diff suppressed because it is too large
Load Diff
295
CODE/CELL.H
Normal file
295
CODE/CELL.H
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CELL.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CELL.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : April 29, 1994 *
|
||||
* *
|
||||
* Last Update : April 29, 1994 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef CELL_H
|
||||
#define CELL_H
|
||||
|
||||
#include "building.h"
|
||||
#include "unit.h"
|
||||
#include "template.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** Each cell on the map is controlled by the following structure.
|
||||
*/
|
||||
class CellClass
|
||||
{
|
||||
public:
|
||||
/*
|
||||
** This is the ID number of this cell. By placing the ID number here, it doesn't have
|
||||
** be calculated. Calculating this number requires a divide and would occur about
|
||||
** 5.72031 bijillion times per second.
|
||||
*/
|
||||
short ID;
|
||||
|
||||
/*
|
||||
** Does this cell need to be updated on the radar map? If something changes in the cell
|
||||
** that might change the radar map imagery, then this flag will be set. It gets cleared
|
||||
** when the cell graphic is updated to the radar map.
|
||||
*/
|
||||
unsigned IsPlot:1;
|
||||
|
||||
/*
|
||||
** Does this cell contain the special placement cursor graphic? This graphic is
|
||||
** present when selecting a site for building placement.
|
||||
*/
|
||||
unsigned IsCursorHere:1;
|
||||
|
||||
/*
|
||||
** A mapped cell has some portion of it visible. Maybe it has a shroud piece
|
||||
** over it and maybe not.
|
||||
*/
|
||||
unsigned IsMapped:1;
|
||||
|
||||
/*
|
||||
** A visible cell means that it is completely visible with no shroud over
|
||||
** it at all.
|
||||
*/
|
||||
unsigned IsVisible:1;
|
||||
|
||||
/*
|
||||
** Every cell can be assigned a waypoint. A waypoint can only be assigned
|
||||
** to one cell, and vice-versa. This bit simply indicates whether this
|
||||
** cell is assigned a waypoint or not.
|
||||
*/
|
||||
unsigned IsWaypoint:1;
|
||||
|
||||
/*
|
||||
** Is this cell currently under the radar map cursor? If so then it
|
||||
** needs to be updated whenever the map is updated.
|
||||
*/
|
||||
unsigned IsRadarCursor:1;
|
||||
|
||||
/*
|
||||
** If this cell contains a house flag, then this will be true. The actual house
|
||||
** flag it contains is specified by the Owner field.
|
||||
*/
|
||||
unsigned IsFlagged:1;
|
||||
|
||||
/*
|
||||
** This is a working flag used to help keep track of what cells should be
|
||||
** shrouded. By using this flag it allows a single pass through the map
|
||||
** cells for determining shadow regrowth logic.
|
||||
*/
|
||||
unsigned IsToShroud:1;
|
||||
|
||||
/*
|
||||
** This records the movement zone for this map. Movement zones share the
|
||||
** same number if they are contiguous (terrain consideration only). There
|
||||
** are basically two kinds of zones. The difference being determined by
|
||||
** walls that can be crushed by movement. A vehicle that can crush walls
|
||||
** will only consider the CrushZone. All other terrestrial travellers will
|
||||
** use the normal Zone.
|
||||
*/
|
||||
unsigned char Zones[MZONE_COUNT];
|
||||
|
||||
/*
|
||||
** This field controls whether an area is being jammed by a gap
|
||||
** generator.
|
||||
*/
|
||||
unsigned short Jammed;
|
||||
|
||||
/*
|
||||
** This is the trigger ID for any trigger that might be attached to
|
||||
** this cell.
|
||||
*/
|
||||
CCPtr<TriggerClass> Trigger;
|
||||
|
||||
/*
|
||||
** This contains the icon number and set to use for the base
|
||||
** of the terrain. All rendering on an icon occurs AFTER the icon
|
||||
** specified by this element is rendered. It is the lowest of the low.
|
||||
*/
|
||||
TemplateType TType;
|
||||
unsigned char TIcon;
|
||||
|
||||
/*
|
||||
** The second layer of 'terrain' icons is represented by a simple
|
||||
** type number and a value byte. This is sufficient for handling
|
||||
** concrete and walls.
|
||||
*/
|
||||
OverlayType Overlay;
|
||||
unsigned char OverlayData;
|
||||
|
||||
/*
|
||||
** This is used to specify any special 'stain' overlay icon. This
|
||||
** typically includes infantry bodies or other temporary marks.
|
||||
*/
|
||||
SmudgeType Smudge;
|
||||
unsigned char SmudgeData;
|
||||
|
||||
/*
|
||||
** Smudges and walls need to record ownership values. For walls, this
|
||||
** allows adjacent building placement logic to work. For smudges, it
|
||||
** allows building over smudges that are no longer attached to buildings
|
||||
** in addition to fixing the adjacent placement logic.
|
||||
*/
|
||||
HousesType Owner;
|
||||
|
||||
/*
|
||||
** This flag tells you what type of infantry currently occupy the
|
||||
** cell or are moving into it.
|
||||
*/
|
||||
HousesType InfType;
|
||||
|
||||
/*
|
||||
** These point to the object(s) that are located in this cell or overlap
|
||||
** this cell.
|
||||
*/
|
||||
private:
|
||||
ObjectClass * OccupierPtr;
|
||||
|
||||
public:
|
||||
#ifdef SORTDRAW
|
||||
ObjectClass * Overlapper[10];
|
||||
#else
|
||||
ObjectClass * Overlapper[6];
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This array of bit flags is used to indicate which sub positions
|
||||
** within the cell are either occupied or are soon going to be
|
||||
** occupied. For vehicles, the cells that the vehicle is passing over
|
||||
** will be flagged with the vehicle bit. For infantry, the the sub
|
||||
** position the infantry is stopped at or headed toward will be marked.
|
||||
** The sub positions it passes over will NOT be marked.
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
unsigned Center:1;
|
||||
unsigned NW:1;
|
||||
unsigned NE:1;
|
||||
unsigned SW:1;
|
||||
unsigned SE:1;
|
||||
unsigned Vehicle:1; // Reserved for vehicle occupation.
|
||||
unsigned Monolith:1; // Some immovable blockage is in cell.
|
||||
unsigned Building:1; // A building of some time (usually blocks movement).
|
||||
} Occupy;
|
||||
unsigned char Composite;
|
||||
} Flag;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
CellClass(void);
|
||||
CellClass(NoInitClass const & x) : Trigger(x) {}
|
||||
~CellClass(void) {OccupierPtr=0;}
|
||||
|
||||
int operator == (CellClass const & cell) const {return &cell == this;}
|
||||
|
||||
/*
|
||||
** Query functions.
|
||||
*/
|
||||
bool Can_Tiberium_Germinate(void) const;
|
||||
bool Can_Tiberium_Grow(void) const;
|
||||
bool Can_Tiberium_Spread(void) const;
|
||||
bool Is_Bridge_Here(void) const;
|
||||
RTTIType What_Am_I(void) const {return(RTTI_CELL);}
|
||||
BuildingClass * Cell_Building(void) const;
|
||||
CELL Cell_Number(void) const {return(ID);}
|
||||
COORDINATE Cell_Coord(void) const;
|
||||
COORDINATE Closest_Free_Spot(COORDINATE coord, bool any=false) const;
|
||||
COORDINATE Free_Spot(void) const {return Closest_Free_Spot(Cell_Coord());}
|
||||
CellClass & Adjacent_Cell(FacingType face) {return (CellClass &)((*((CellClass const *)this)).Adjacent_Cell(face));}
|
||||
CellClass const & Adjacent_Cell(FacingType face) const;
|
||||
InfantryClass * Cell_Infantry(void) const;
|
||||
LandType Land_Type(void) const {return(Land);}
|
||||
ObjectClass * Cell_Find_Object(RTTIType rtti) const;
|
||||
ObjectClass * Cell_Object(int x=0, int y=0) const;
|
||||
ObjectClass * Cell_Occupier(void) const {return(OccupierPtr);}
|
||||
ObjectClass * Fetch_Occupier(void) const;
|
||||
TARGET As_Target(void) const {return ::As_Target(Cell_Number());}
|
||||
TechnoClass * Cell_Techno(int x=0, int y=0) const;
|
||||
TerrainClass * Cell_Terrain(void) const;
|
||||
UnitClass * Cell_Unit(void) const;
|
||||
VesselClass * Cell_Vessel(void) const;
|
||||
bool Goodie_Check(FootClass * object);
|
||||
bool Is_Clear_To_Build(SpeedType loco = SPEED_TRACK) const;
|
||||
bool Is_Clear_To_Move(SpeedType loco, bool ignoreinfantry, bool ignorevehicles, int zone=-1, MZoneType check=MZONE_NORMAL) const;
|
||||
bool Is_Spot_Free(int spot_index) const {return (! (Flag.Composite & (1 << spot_index)) ); }
|
||||
int Cell_Color(bool override=false) const;
|
||||
int Clear_Icon(void) const;
|
||||
static int Spot_Index(COORDINATE coord);
|
||||
|
||||
/*
|
||||
** Object placement and removal flag operations.
|
||||
*/
|
||||
void Occupy_Down(ObjectClass * object);
|
||||
void Occupy_Up(ObjectClass * object);
|
||||
void Overlap_Down(ObjectClass * object);
|
||||
void Overlap_Up(ObjectClass * object);
|
||||
bool Flag_Place(HousesType house);
|
||||
bool Flag_Remove(void);
|
||||
|
||||
/*
|
||||
** File I/O.
|
||||
*/
|
||||
bool Should_Save(void) const;
|
||||
bool Save(Pipe & file) const;
|
||||
bool Load(Straw & file);
|
||||
void Code_Pointers(void);
|
||||
void Decode_Pointers(void);
|
||||
|
||||
/*
|
||||
** Display and rendering controls.
|
||||
*/
|
||||
void Draw_It(int x, int y, bool objects=false) const;
|
||||
void Redraw_Objects(bool forced=false);
|
||||
void Shimmer(void);
|
||||
|
||||
/*
|
||||
** Maintenance calculation support.
|
||||
*/
|
||||
bool Grow_Tiberium(void);
|
||||
bool Spread_Tiberium(bool forced=false);
|
||||
long Tiberium_Adjust(bool pregame=false);
|
||||
void Wall_Update(void);
|
||||
void Concrete_Calc(void);
|
||||
void Recalc_Attributes(void);
|
||||
int Reduce_Tiberium(int levels);
|
||||
int Reduce_Wall(int damage);
|
||||
void Incoming(COORDINATE threat=0, bool forced=false, bool nokidding=false);
|
||||
void Adjust_Threat(HousesType house, int threat_value);
|
||||
|
||||
int operator != (CellClass const &) const {return 0;}
|
||||
|
||||
private:
|
||||
CellClass (CellClass const &) ;
|
||||
|
||||
LandType Land; // The land type of this cell.
|
||||
};
|
||||
|
||||
#endif
|
||||
|
102
CODE/CHECKBOX.CPP
Normal file
102
CODE/CHECKBOX.CPP
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CHECKBOX.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CHECKBOX.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 05/26/95 *
|
||||
* *
|
||||
* Last Update : July 6, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* CheckBoxClass::Action -- Handles a button action on a checkbox object. *
|
||||
* CheckBoxClass::Draw_Me -- Draws the checkbox imagery. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
#include "checkbox.h"
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CheckBoxClass::Draw_Me -- Draws the checkbox imagery. *
|
||||
* *
|
||||
* This routine will draw the checkbox either filled or empty as necessary. *
|
||||
* *
|
||||
* INPUT: forced -- Should the check box be drawn even if it doesn't think it needs to? *
|
||||
* *
|
||||
* OUTPUT: Was the check box rendered? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/01/1995 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int CheckBoxClass::Draw_Me(int forced)
|
||||
{
|
||||
if (ToggleClass::Draw_Me(forced)) {
|
||||
|
||||
Hide_Mouse();
|
||||
Draw_Box(X, Y, Width, Height, BOXSTYLE_DOWN, false);
|
||||
LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, Y+Height-2, DKGREY);
|
||||
if (IsOn) {
|
||||
LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, Y+Height-2, LTGREEN);
|
||||
}
|
||||
Show_Mouse();
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CheckBoxClass::Action -- Handles a button action on a checkbox object. *
|
||||
* *
|
||||
* This routine will detect if the mouse has been clicked on the checkbox object. If so, *
|
||||
* the check box state will be toggled. *
|
||||
* *
|
||||
* INPUT: flags -- The event flags that resulted in this routine being called. *
|
||||
* *
|
||||
* key -- The key that resulted in this routine being called. *
|
||||
* *
|
||||
* OUTPUT: bool; Should normal processing occur? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int CheckBoxClass::Action(unsigned flags, KeyNumType & key)
|
||||
{
|
||||
if (flags & LEFTRELEASE) {
|
||||
if (IsOn) {
|
||||
Turn_Off();
|
||||
} else {
|
||||
Turn_On();
|
||||
}
|
||||
}
|
||||
return(ToggleClass::Action(flags, key));
|
||||
}
|
56
CODE/CHECKBOX.H
Normal file
56
CODE/CHECKBOX.H
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CHECKBOX.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CHECKBOX.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 05/26/95 *
|
||||
* *
|
||||
* Last Update : May 26, 1995 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef CHECKBOX_H
|
||||
#define CHECKBOX_H
|
||||
|
||||
#include "toggle.h"
|
||||
|
||||
class CheckBoxClass : public ToggleClass
|
||||
{
|
||||
public:
|
||||
CheckBoxClass(unsigned id, int x, int y) :
|
||||
ToggleClass(id, x, y, 7, 7)
|
||||
{};
|
||||
|
||||
virtual int Draw_Me(int forced=false);
|
||||
virtual int Action(unsigned flags, KeyNumType & key);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif
|
365
CODE/CHEKLIST.CPP
Normal file
365
CODE/CHEKLIST.CPP
Normal file
@ -0,0 +1,365 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CHEKLIST.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CHEKLIST.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 07/05/96 *
|
||||
* *
|
||||
* Last Update : July 6, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* CheckListClass::Action -- action function for this class *
|
||||
* CheckListClass::Add_Item -- Adds specifies text to check list box. *
|
||||
* CheckListClass::CheckListClass -- constructor *
|
||||
* CheckListClass::Check_Item -- [un]checks an items *
|
||||
* CheckListClass::Draw_Entry -- draws a list box entry *
|
||||
* CheckListClass::Get_Item -- Fetches a pointer to the text associated with the index. *
|
||||
* CheckListClass::Remove_Item -- Remove the item that matches the text pointer specified. *
|
||||
* CheckListClass::Set_Selected_Index -- Set the selected index to match the text pointer spe*
|
||||
* CheckListClass::~CheckListClass -- Destructor for check list object. *
|
||||
* CheckListClass::~CheckListClass -- destructor *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* CheckListClass::CheckListClass -- constructor *
|
||||
* *
|
||||
* INPUT: *
|
||||
* id control ID for this list box *
|
||||
* x x-coord *
|
||||
* y y-coord *
|
||||
* w width *
|
||||
* h height *
|
||||
* flags mouse event flags *
|
||||
* up ptr to Up-arrow shape *
|
||||
* down ptr to Down-arrow shape *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 02/16/1995 BR : Created. *
|
||||
*=========================================================================*/
|
||||
CheckListClass::CheckListClass(int id, int x, int y, int w, int h, TextPrintType flags,
|
||||
void const * up, void const * down) :
|
||||
ListClass (id, x, y, w, h, flags, up, down),
|
||||
IsReadOnly(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CheckListClass::~CheckListClass -- Destructor for check list object. *
|
||||
* *
|
||||
* This destructor will delete all entries attached to it. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
CheckListClass::~CheckListClass(void)
|
||||
{
|
||||
while (CheckListClass::Count()) {
|
||||
CheckObject * obj = (CheckObject *)ListClass::Get_Item(0);
|
||||
|
||||
ListClass::Remove_Item(0);
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CheckListClass::Add_Item -- Adds specifies text to check list box. *
|
||||
* *
|
||||
* This routine will add the specified text string to the check list. *
|
||||
* *
|
||||
* INPUT: text -- Pointer to the text string to add to the list box. *
|
||||
* *
|
||||
* OUTPUT: Returns the index number where the text object was added. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 02/14/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
int CheckListClass::Add_Item(char const * text)
|
||||
{
|
||||
CheckObject * obj = new CheckObject(text, false);
|
||||
return(ListClass::Add_Item((char const *)obj));
|
||||
}
|
||||
|
||||
|
||||
char const * CheckListClass::Current_Item(void) const
|
||||
{
|
||||
CheckObject * obj = (CheckObject *)ListClass::Current_Item();
|
||||
if (obj) {
|
||||
return(obj->Text);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CheckListClass::Get_Item -- Fetches a pointer to the text associated with the index. *
|
||||
* *
|
||||
* This routine will find the text associated with the entry specified and return a pointer *
|
||||
* to that text. *
|
||||
* *
|
||||
* INPUT: index -- The entry (index) to fetch a pointer to. *
|
||||
* *
|
||||
* OUTPUT: Returns with the text pointer associated with the index specified. *
|
||||
* *
|
||||
* WARNINGS: If the index is out of range, then NULL is returned. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
char const * CheckListClass::Get_Item(int index) const
|
||||
{
|
||||
CheckObject * obj = (CheckObject *)ListClass::Get_Item(index);
|
||||
if (obj) {
|
||||
return(obj->Text);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CheckListClass::Remove_Item -- Remove the item that matches the text pointer specified. *
|
||||
* *
|
||||
* This routine will find the entry that matches the text pointer specified and then *
|
||||
* delete that entry. *
|
||||
* *
|
||||
* INPUT: text -- The text pointer to use to find the exact match in the list. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void CheckListClass::Remove_Item(char const * text)
|
||||
{
|
||||
for (int index = 0; index < Count(); index++) {
|
||||
CheckObject * obj = (CheckObject *)ListClass::Get_Item(index);
|
||||
if (obj && stricmp(obj->Text, text) == 0) {
|
||||
ListClass::Remove_Item(index);
|
||||
delete obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* CheckListClass::Set_Selected_Index -- Set the selected index to match the text pointer spec *
|
||||
* *
|
||||
* This routine will find the entry that exactly matches the text pointer specified. If *
|
||||
* found, then that entry will be set as the currently selected index. *
|
||||
* *
|
||||
* INPUT: text -- Pointer to the text string to find the match for. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: If an exact match to the specified text string could not be found, then the *
|
||||
* currently selected index is not changed. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/06/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void CheckListClass::Set_Selected_Index(char const * text)
|
||||
{
|
||||
for (int index = 0; index < Count(); index++) {
|
||||
CheckObject * obj = (CheckObject *)ListClass::Get_Item(index);
|
||||
if (obj && stricmp(obj->Text, text) == 0) {
|
||||
Set_Selected_Index(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* CheckListClass::Check_Item -- [un]checks an items *
|
||||
* *
|
||||
* INPUT: *
|
||||
* index index of item to check or uncheck *
|
||||
* checked 0 = uncheck, non-zero = check *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 02/16/1995 BR : Created. *
|
||||
* 02/14/1996 JLB : Revamped. *
|
||||
*=========================================================================*/
|
||||
void CheckListClass::Check_Item(int index, bool checked)
|
||||
{
|
||||
CheckObject * obj = (CheckObject *)ListClass::Get_Item(index);
|
||||
if (obj && obj->IsChecked != checked) {
|
||||
obj->IsChecked = checked;
|
||||
Flag_To_Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* CheckListClass::Is_Checked -- returns checked state of an item *
|
||||
* *
|
||||
* INPUT: *
|
||||
* index index of item to query *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 0 = item is unchecked, 1 = item is checked *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 02/16/1995 BR : Created. *
|
||||
* 02/14/1996 JLB : Revamped. *
|
||||
*=========================================================================*/
|
||||
bool CheckListClass::Is_Checked(int index) const
|
||||
{
|
||||
CheckObject * obj = (CheckObject *)ListClass::Get_Item(index);
|
||||
if (obj) {
|
||||
return(obj->IsChecked);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* CheckListClass::Action -- action function for this class *
|
||||
* *
|
||||
* INPUT: *
|
||||
* flags the reason we're being called *
|
||||
* key the KN_number that was pressed *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* true = event was processed, false = event not processed *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 02/16/1995 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int CheckListClass::Action(unsigned flags, KeyNumType &key)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/*
|
||||
** If this is a read-only list, it's a display-only device
|
||||
*/
|
||||
if (IsReadOnly) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*
|
||||
** Invoke parents Action first, so it can set the SelectedIndex if needed.
|
||||
*/
|
||||
rc = ListClass::Action(flags, key);
|
||||
|
||||
/*
|
||||
** Now, if this event was a left-press, toggle the checked state of the
|
||||
** current item.
|
||||
*/
|
||||
if (flags & LEFTPRESS) {
|
||||
Check_Item(SelectedIndex, !Is_Checked(SelectedIndex));
|
||||
}
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* CheckListClass::Draw_Entry -- draws a list box entry *
|
||||
* *
|
||||
* INPUT: *
|
||||
* index index into List of item to draw *
|
||||
* x,y x,y coords to draw at *
|
||||
* width maximum width allowed for text *
|
||||
* selected true = this item is selected *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/14/1995 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void CheckListClass::Draw_Entry(int index, int x, int y, int width, int selected)
|
||||
{
|
||||
if (index >= Count()) return;
|
||||
|
||||
CheckObject * obj = (CheckObject *)ListClass::Get_Item(index);
|
||||
|
||||
if (obj) {
|
||||
char buffer[100] = "";
|
||||
|
||||
if (obj->IsChecked) {
|
||||
buffer[0] = CHECK_CHAR;
|
||||
} else {
|
||||
buffer[0] = UNCHECK_CHAR;
|
||||
}
|
||||
buffer[1] = ' ';
|
||||
sprintf(&buffer[2], obj->Text);
|
||||
|
||||
TextPrintType flags = TextFlags;
|
||||
RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
|
||||
|
||||
if (selected) {
|
||||
flags = flags | TPF_BRIGHT_COLOR;
|
||||
LogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, scheme->Shadow);
|
||||
} else {
|
||||
if (!(flags & TPF_USE_GRAD_PAL)) {
|
||||
flags = flags | TPF_MEDIUM_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
Conquer_Clip_Text_Print(buffer, x, y, scheme, TBLACK, flags, width, Tabs);
|
||||
}
|
||||
}
|
||||
|
105
CODE/CHEKLIST.H
Normal file
105
CODE/CHEKLIST.H
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CHEKLIST.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***************************************************************************
|
||||
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CHEKLIST.H *
|
||||
* *
|
||||
* Programmer : Bill Randolph *
|
||||
* *
|
||||
* Start Date : February 16, 1995 *
|
||||
* *
|
||||
* Last Update : February 16, 1995 [BR] *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* This class behaves just like the standard list box, except that if the *
|
||||
* first character of a list entry is a space, clicking on it toggles the *
|
||||
* space with a check-mark ('\3'). This makes each entry in the list box *
|
||||
* "toggle-able". *
|
||||
*-------------------------------------------------------------------------*
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef CHEKLIST_H
|
||||
#define CHEKLIST_H
|
||||
|
||||
#include "list.h"
|
||||
|
||||
class CheckObject
|
||||
{
|
||||
public:
|
||||
CheckObject(char const * text = 0, bool checked=false) :
|
||||
Text(text),
|
||||
IsChecked(checked)
|
||||
{};
|
||||
|
||||
char const * Text;
|
||||
bool IsChecked;
|
||||
};
|
||||
|
||||
|
||||
class CheckListClass : public ListClass
|
||||
{
|
||||
public:
|
||||
/*
|
||||
** Constructor/Destructor
|
||||
*/
|
||||
CheckListClass(int id, int x, int y, int w, int h, TextPrintType flags,
|
||||
void const * up, void const * down);
|
||||
~CheckListClass(void);
|
||||
|
||||
virtual int Add_Item(int text) {return ListClass::Add_Item(text);}
|
||||
virtual int Add_Item(char const * text);
|
||||
virtual char const * Current_Item(void) const;
|
||||
virtual char const * Get_Item(int index) const;
|
||||
virtual void Remove_Item(char const * text);
|
||||
virtual void Remove_Item(int text) {ListClass::Remove_Item(text);}
|
||||
virtual void Set_Selected_Index(char const * text);
|
||||
virtual void Set_Selected_Index(int index) {ListClass::Set_Selected_Index(index);};
|
||||
|
||||
/*
|
||||
** Checkmark utility functions
|
||||
*/
|
||||
void Check_Item(int index, bool checked); // sets checked state of item
|
||||
bool Is_Checked(int index) const; // gets checked state of item
|
||||
|
||||
void Set_Read_Only(int rdonly) {IsReadOnly = rdonly;}
|
||||
|
||||
/*
|
||||
** This defines the ASCII value of the checkmark character & non-checkmark
|
||||
** character.
|
||||
*/
|
||||
typedef enum CheckListClassEnum {
|
||||
CHECK_CHAR = '\3',
|
||||
UNCHECK_CHAR = ' '
|
||||
} CheckListClassEnum;
|
||||
|
||||
protected:
|
||||
virtual int Action(unsigned flags, KeyNumType &key);
|
||||
virtual void Draw_Entry(int index, int x, int y, int width, int selected);
|
||||
|
||||
private:
|
||||
bool IsReadOnly;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
19
CODE/CLASS.CPP
Normal file
19
CODE/CLASS.CPP
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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/>.
|
||||
*/
|
||||
|
||||
|
67
CODE/CO-WC32.LNT
Normal file
67
CODE/CO-WC32.LNT
Normal file
@ -0,0 +1,67 @@
|
||||
// Compiler Options for Watcom C, C++ 32 bit
|
||||
|
||||
-cwc
|
||||
|
||||
// This file contains options to allow PC-lint to process source
|
||||
// files for your compiler. It is used as follows:
|
||||
//
|
||||
// lint co-wc32.lnt source-file(s)
|
||||
//
|
||||
-d_M_IX86=200 // assume Intel 80286 architecture -- modify to suit
|
||||
-d__declspec()= // ignore this construct
|
||||
|
||||
// additional reserve words needed
|
||||
+rw(_loadds,_export)
|
||||
+rw(__interrupt,__near,__far,__huge,__fortran,__pascal,__cdecl)
|
||||
+rw(__export,__loadds,__saveregs,__asm,__fastcall,__stdcall)
|
||||
+rw(_export)
|
||||
|
||||
+fcd // makes cdecl significant -- used for proto generation
|
||||
+fcu // chars are by default unsigned
|
||||
+fsu // so are strings
|
||||
-d__386__ // pre-defined macro for 386 version, not set by -cwc
|
||||
-d__FLAT__ // not set by -cwc
|
||||
-si4 // sizeof(int) is 4
|
||||
-spN4 // sizeof(near pointer) is 4
|
||||
-spF6 // sizeof( far pointer) is 6
|
||||
-sld10 // sizeof(long double) is 10.
|
||||
-function(exit,_exit) // _exit() is like exit()
|
||||
-emacro(734,putc) // don't complain about items being too large.
|
||||
-emacro(506,putc) // don't complain about constant Boolean
|
||||
-emacro(???,va_arg) // the va_arg() macro can yield 415, 416, 661, 662
|
||||
// 796 and 797 (out-of-bounds errors).
|
||||
|
||||
// While processing compiler (library) header files ...
|
||||
-elib(46) // an unsigned short bit field is used as __FILLER__
|
||||
-elib(522) // function return value ignored
|
||||
-elib(537) // repeated include file (ios.h)
|
||||
-elib(641) // converting enum to int
|
||||
-elib(652) // suppress message about #define of earlier declared symbols
|
||||
-elib(655) // ORing enum's
|
||||
-elib(726) // extraneous comma in enumeration
|
||||
-elib(760) // suppress message about multiple identical macro defs
|
||||
-elib(762) // suppress message about multiple identical declarations and
|
||||
-elib(806) // small bit field is signed
|
||||
-elib(1053) // prototypes cannot be distinguished
|
||||
-elib(1511) // member (rdbuf) hides nonvirtual member
|
||||
-elib(1704) // private copy constructor
|
||||
-elib(1712) // default constructor missing
|
||||
-elib(1717) // empty prototypes
|
||||
-elib(1720) // strange argument to assignment operator
|
||||
-elib(1721) // unusual operator =() declaration
|
||||
-elib(1722) // assignment operator does not return ref to class
|
||||
-elib(1724) // strange argument to copy constructor
|
||||
|
||||
-esym(1702,operator<<,operator>>)
|
||||
|
||||
// The following functions exhibit variable return modes.
|
||||
// That is, they may equally-usefully be called for a value
|
||||
// as called just for their effects. Accordingly we inhibit
|
||||
// Warning 534 for these functions.
|
||||
// Feel free to add to or subtract from this list.
|
||||
|
||||
-esym(534,close,creat,fclose,fflush,fprintf,fputc)
|
||||
-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset)
|
||||
-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy)
|
||||
-esym(534,strncat,strncpy,unlink,write)
|
||||
|
278
CODE/COLRLIST.CPP
Normal file
278
CODE/COLRLIST.CPP
Normal file
@ -0,0 +1,278 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/COLRLIST.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : COLRLIST.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 01/15/95 *
|
||||
* *
|
||||
* Last Update : April 19, 1995 [BRR] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* ColorListClass::Add_Item -- Adds an item to the list *
|
||||
* ColorListClass::ColorListClass -- Class constructor *
|
||||
* ColorListClass::Draw_Entry -- Draws one text line *
|
||||
* ColorListClass::Remove_Item -- Removes an item from the list *
|
||||
* ColorListClass::Set_Selected_Style -- tells how to draw selected item *
|
||||
* ColorListClass::~ColorListClass -- Class destructor *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ColorListClass::ColorListClass -- class constructor *
|
||||
* *
|
||||
* INPUT: *
|
||||
* id button ID *
|
||||
* x,y upper-left corner, in pixels *
|
||||
* w,h width, height, in pixels *
|
||||
* list ptr to array of char strings to list *
|
||||
* flags flags for mouse, style of listbox *
|
||||
* up,down pointers to shapes for up/down buttons *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: 01/05/1995 MML : Created. *
|
||||
*=========================================================================*/
|
||||
ColorListClass::ColorListClass (int id, int x, int y, int w, int h,
|
||||
TextPrintType flags, void const * up, void const * down) :
|
||||
ListClass (id, x, y, w, h, flags, up, down),
|
||||
Style(SELECT_HIGHLIGHT),
|
||||
SelectColor(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ColorListClass::~ColorListClass -- Class destructor *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1995 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
ColorListClass::~ColorListClass(void)
|
||||
{
|
||||
Colors.Clear();
|
||||
SelectColor = 0;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ColorListClass::Add_Item -- Adds an item to the list *
|
||||
* *
|
||||
* INPUT: *
|
||||
* text text to add to list *
|
||||
* color color for item *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* position of item in the list *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1995 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
int ColorListClass::Add_Item(char const * text, RemapControlType * color)
|
||||
{
|
||||
Colors.Add(color);
|
||||
return(ListClass::Add_Item(text));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ColorListClass::Add_Item -- Adds an item to the list *
|
||||
* *
|
||||
* INPUT: *
|
||||
* text text to add to list *
|
||||
* color color for item *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* position of item in the list *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1995 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
int ColorListClass::Add_Item(int text, RemapControlType * color)
|
||||
{
|
||||
Colors.Add(color);
|
||||
return(ListClass::Add_Item(text));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ColorListClass::Remove_Item -- Removes an item from the list *
|
||||
* *
|
||||
* INPUT: *
|
||||
* text ptr to item to remove *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1995 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void ColorListClass::Remove_Item(char const * text)
|
||||
{
|
||||
int index = List.ID(text);
|
||||
if (index != -1) {
|
||||
Colors.Delete(index);
|
||||
ListClass::Remove_Item(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ColorListClass::Set_Selected_Style -- tells how to draw selected item *
|
||||
* *
|
||||
* INPUT: *
|
||||
* style style to draw *
|
||||
* color color to draw the special style in; -1 = use item's color *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1995 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void ColorListClass::Set_Selected_Style(SelectStyleType style, RemapControlType * color)
|
||||
{
|
||||
Style = style;
|
||||
SelectColor = color;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ColorListClass::Draw_Entry -- Draws one text line *
|
||||
* *
|
||||
* INPUT: *
|
||||
* index index into List of item to draw *
|
||||
* x,y x,y coords to draw at *
|
||||
* width maximum width allowed for text *
|
||||
* selected true = this item is selected *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/19/1995 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
void ColorListClass::Draw_Entry(int index, int x, int y, int width, int selected)
|
||||
{
|
||||
RemapControlType * color;
|
||||
|
||||
/*
|
||||
** Draw a non-selected item in its color
|
||||
*/
|
||||
if (!selected) {
|
||||
Conquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags, width, Tabs);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** For selected items, choose the right color & style:
|
||||
*/
|
||||
if (SelectColor == NULL) {
|
||||
color = Colors[index];
|
||||
} else {
|
||||
color = SelectColor;
|
||||
}
|
||||
|
||||
switch (Style) {
|
||||
/*
|
||||
** NONE: Just print the string in its native color
|
||||
*/
|
||||
case SELECT_NORMAL:
|
||||
Conquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK,
|
||||
TextFlags, width, Tabs);
|
||||
break;
|
||||
|
||||
/*
|
||||
** HIGHLIGHT: Draw the string in the highlight color (SelectColor must
|
||||
** be set)
|
||||
*/
|
||||
case SELECT_HIGHLIGHT:
|
||||
if (TextFlags & TPF_6PT_GRAD) {
|
||||
Conquer_Clip_Text_Print(List[index], x, y, color, TBLACK, TextFlags | TPF_BRIGHT_COLOR, width, Tabs);
|
||||
} else {
|
||||
Conquer_Clip_Text_Print(List[index], x, y, color, TBLACK, TextFlags, width, Tabs);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
** BOX: Draw a box around the item in the current select color
|
||||
*/
|
||||
case SELECT_BOX:
|
||||
LogicPage->Draw_Rect (x, y, x + width - 2, y + LineHeight - 2, color->Color);
|
||||
Conquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags, width, Tabs);
|
||||
break;
|
||||
|
||||
/*
|
||||
** BAR: draw a color bar under the text
|
||||
*/
|
||||
case SELECT_BAR:
|
||||
if (TextFlags & TPF_6PT_GRAD) {
|
||||
LogicPage->Fill_Rect(x, y, x + width - 1, y + LineHeight - 1, color->Color);
|
||||
Conquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags | TPF_BRIGHT_COLOR, width, Tabs);
|
||||
} else {
|
||||
LogicPage->Fill_Rect(x, y, x + width - 2, y + LineHeight - 2, color->Color);
|
||||
Conquer_Clip_Text_Print(List[index], x, y, Colors[index], TBLACK, TextFlags, width, Tabs);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
** INVERT: Draw text as the background color on foreground color
|
||||
*/
|
||||
case SELECT_INVERT:
|
||||
LogicPage->Fill_Rect (x, y, x + width - 1, y + LineHeight - 1, Colors[index]->Color);
|
||||
break;
|
||||
}
|
||||
}
|
87
CODE/COLRLIST.H
Normal file
87
CODE/COLRLIST.H
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/COLRLIST.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : COLRLIST.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 01/15/95 *
|
||||
* *
|
||||
* Last Update : January 15, 1995 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef COLORLIST_H
|
||||
#define COLORLIST_H
|
||||
|
||||
#include "list.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** This class adds the ability for every list item to have a different color.
|
||||
*/
|
||||
class ColorListClass : public ListClass
|
||||
{
|
||||
public:
|
||||
/*********************************************************************
|
||||
** These enums are the ways a selected item can be drawn
|
||||
*/
|
||||
//lint -esym(578,SELECT_NONE)
|
||||
typedef enum SelectEnum {
|
||||
SELECT_NORMAL, // selected items aren't drawn differently
|
||||
SELECT_HIGHLIGHT, // item is highlighted
|
||||
SELECT_BOX, // draw a box around the item
|
||||
SELECT_BAR, // draw a bar behind the item
|
||||
SELECT_INVERT // draw the string inverted
|
||||
} SelectStyleType;
|
||||
|
||||
ColorListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down);
|
||||
virtual ~ColorListClass(void);
|
||||
|
||||
virtual int Add_Item(char const * text, RemapControlType * color = NULL);
|
||||
virtual int Add_Item(int text, RemapControlType * color = NULL);
|
||||
virtual void Remove_Item(char const * text);
|
||||
|
||||
virtual void Set_Selected_Style(SelectStyleType style, RemapControlType * color = NULL);
|
||||
|
||||
/*
|
||||
** This is the list of colors for each item.
|
||||
*/
|
||||
DynamicVectorClass<RemapControlType *> Colors;
|
||||
|
||||
protected:
|
||||
virtual void Draw_Entry(int index, int x, int y, int width, int selected);
|
||||
|
||||
/*
|
||||
** This tells how to draw the selected item.
|
||||
*/
|
||||
SelectStyleType Style;
|
||||
RemapControlType * SelectColor;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
425
CODE/COMBAT.CPP
Normal file
425
CODE/COMBAT.CPP
Normal file
@ -0,0 +1,425 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/COMBAT.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : COMBAT.CPP *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : September 19, 1994 *
|
||||
* *
|
||||
* Last Update : July 26, 1996 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* Combat_Anim -- Determines explosion animation to play. *
|
||||
* Explosion_Damage -- Inflict an explosion damage affect. *
|
||||
* Modify_Damage -- Adjusts damage to reflect the nature of the target. *
|
||||
* Wide_Area_Damage -- Apply wide area damage to the map. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Modify_Damage -- Adjusts damage to reflect the nature of the target. *
|
||||
* *
|
||||
* This routine is the core of combat tactics. It implements the *
|
||||
* affect various armor types have against various weapon types. By *
|
||||
* careful exploitation of this table, tactical advantage can be *
|
||||
* obtained. *
|
||||
* *
|
||||
* INPUT: damage -- The damage points to process. *
|
||||
* *
|
||||
* warhead -- The source of the damage points. *
|
||||
* *
|
||||
* armor -- The type of armor defending against the damage. *
|
||||
* *
|
||||
* distance -- The distance (in leptons) from the source of the damage. *
|
||||
* *
|
||||
* OUTPUT: Returns with the adjusted damage points to inflict upon the *
|
||||
* target. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 04/16/1994 JLB : Created. *
|
||||
* 04/17/1994 JLB : Always does a minimum of damage. *
|
||||
* 01/01/1995 JLB : Takes into account distance from damage source. *
|
||||
* 04/11/1996 JLB : Changed damage fall-off formula for less damage fall-off. *
|
||||
*=============================================================================================*/
|
||||
int Modify_Damage(int damage, WarheadType warhead, ArmorType armor, int distance)
|
||||
{
|
||||
if (!damage) return(damage);
|
||||
|
||||
/*
|
||||
** If there is no raw damage value to start with, then
|
||||
** there can be no modified damage either.
|
||||
*/
|
||||
if (Special.IsInert || !damage || warhead == WARHEAD_NONE) return(0);
|
||||
|
||||
/*
|
||||
** Negative damage (i.e., heal) is always applied full strength, but only if the heal
|
||||
** effect is close enough.
|
||||
*/
|
||||
if (damage < 0) {
|
||||
#ifdef FIXIT_CSII // checked - ajw 9/28/98
|
||||
if (distance < 0x008) {
|
||||
if(warhead != WARHEAD_MECHANICAL && armor == ARMOR_NONE) return(damage);
|
||||
if(warhead == WARHEAD_MECHANICAL && armor != ARMOR_NONE) return(damage);
|
||||
}
|
||||
#else
|
||||
if (distance < 0x008 && armor == ARMOR_NONE) return(damage);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
WarheadTypeClass const * whead = WarheadTypeClass::As_Pointer(warhead);
|
||||
// WarheadTypeClass const * whead = &Warheads[warhead];
|
||||
|
||||
damage = damage * whead->Modifier[armor];
|
||||
|
||||
/*
|
||||
** Reduce damage according to the distance from the impact point.
|
||||
*/
|
||||
if (damage) {
|
||||
if (!whead->SpreadFactor) {
|
||||
distance /= PIXEL_LEPTON_W/4;
|
||||
} else {
|
||||
distance /= whead->SpreadFactor * (PIXEL_LEPTON_W/2);
|
||||
}
|
||||
distance = Bound(distance, 0, 16);
|
||||
if (distance) {
|
||||
damage = damage / distance;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allow damage to drop to zero only if the distance would have
|
||||
** reduced damage to less than 1/4 full damage. Otherwise, ensure
|
||||
** that at least one damage point is done.
|
||||
*/
|
||||
if (distance < 4) {
|
||||
damage = max(damage, Rule.MinDamage);
|
||||
}
|
||||
}
|
||||
|
||||
damage = min(damage, Rule.MaxDamage);
|
||||
return(damage);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Explosion_Damage -- Inflict an explosion damage affect. *
|
||||
* *
|
||||
* Processes the collateral damage affects typically caused by an *
|
||||
* explosion. *
|
||||
* *
|
||||
* INPUT: coord -- The coordinate of ground zero. *
|
||||
* *
|
||||
* strength -- Raw damage points at ground zero. *
|
||||
* *
|
||||
* source -- Source of the explosion (who is responsible). *
|
||||
* *
|
||||
* warhead -- The kind of explosion to process. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: This routine can consume some time and will affect the AI *
|
||||
* of nearby enemy units (possibly). *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 08/16/1991 JLB : Created. *
|
||||
* 11/30/1991 JLB : Uses coordinate system. *
|
||||
* 12/27/1991 JLB : Radius of explosion damage effect. *
|
||||
* 04/13/1994 JLB : Streamlined. *
|
||||
* 04/16/1994 JLB : Warhead damage type modifier. *
|
||||
* 04/17/1994 JLB : Cleaned up. *
|
||||
* 06/20/1994 JLB : Uses object pointers to distribute damage. *
|
||||
* 06/20/1994 JLB : Source is a pointer. *
|
||||
* 06/18/1996 JLB : Strength could be negative for healing effects. *
|
||||
*=============================================================================================*/
|
||||
void Explosion_Damage(COORDINATE coord, int strength, TechnoClass * source, WarheadType warhead)
|
||||
{
|
||||
CELL cell; // Cell number under explosion.
|
||||
ObjectClass * object; // Working object pointer.
|
||||
ObjectClass * objects[32]; // Maximum number of objects that can be damaged.
|
||||
int distance; // Distance to unit.
|
||||
int range; // Damage effect radius.
|
||||
int count; // Number of vehicle IDs in list.
|
||||
|
||||
if (!strength || Special.IsInert || warhead == WARHEAD_NONE) return;
|
||||
|
||||
WarheadTypeClass const * whead = WarheadTypeClass::As_Pointer(warhead);
|
||||
// WarheadTypeClass const * whead = &Warheads[warhead];
|
||||
// range = ICON_LEPTON_W*2;
|
||||
range = ICON_LEPTON_W + (ICON_LEPTON_W >> 1);
|
||||
cell = Coord_Cell(coord);
|
||||
if ((unsigned)cell >= MAP_CELL_TOTAL) return;
|
||||
|
||||
CellClass * cellptr = &Map[cell];
|
||||
ObjectClass * impacto = cellptr->Cell_Occupier();
|
||||
|
||||
/*
|
||||
** Fill the list of unit IDs that will have damage
|
||||
** assessed upon them. The units can be lifted from
|
||||
** the cell data directly.
|
||||
*/
|
||||
count = 0;
|
||||
for (FacingType i = FACING_NONE; i < FACING_COUNT; i++) {
|
||||
/*
|
||||
** Fetch a pointer to the cell to examine. This is either
|
||||
** an adjacent cell or the center cell. Damage never spills
|
||||
** further than one cell away.
|
||||
*/
|
||||
if (i != FACING_NONE) {
|
||||
cellptr = &Map[cell].Adjacent_Cell(i);
|
||||
}
|
||||
|
||||
/*
|
||||
** Add all objects in this cell to the list of objects to possibly apply
|
||||
** damage to. The list stops building when the object pointer list becomes
|
||||
** full. Do not include overlapping objects; selection state can affect
|
||||
** the overlappers, and this causes multiplayer games to go out of sync.
|
||||
*/
|
||||
object = cellptr->Cell_Occupier();
|
||||
while (object) {
|
||||
if (!object->IsToDamage && object != source) {
|
||||
object->IsToDamage = true;
|
||||
objects[count++] = object;
|
||||
if (count >= ARRAY_SIZE(objects)) break;
|
||||
}
|
||||
object = object->Next;
|
||||
}
|
||||
if (count >= ARRAY_SIZE(objects)) break;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sweep through the units to be damaged and damage them. When damaging
|
||||
** buildings, consider a hit on any cell the building occupies as if it
|
||||
** were a direct hit on the building's center.
|
||||
*/
|
||||
for (int index = 0; index < count; index++) {
|
||||
object = objects[index];
|
||||
|
||||
object->IsToDamage = false;
|
||||
if (object->IsActive) {
|
||||
if (object->What_Am_I() == RTTI_BUILDING && impacto == object) {
|
||||
distance = 0;
|
||||
} else {
|
||||
distance = Distance(coord, object->Center_Coord());
|
||||
}
|
||||
if (object->IsDown && !object->IsInLimbo && distance < range) {
|
||||
int damage = strength;
|
||||
object->Take_Damage(damage, distance, warhead, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If there is a wall present at this location, it may be destroyed. Check to
|
||||
** make sure that the warhead is of the kind that can destroy walls.
|
||||
*/
|
||||
cellptr = &Map[cell];
|
||||
if (cellptr->Overlay != OVERLAY_NONE) {
|
||||
OverlayTypeClass const * optr = &OverlayTypeClass::As_Reference(cellptr->Overlay);
|
||||
|
||||
if (optr->IsTiberium && whead->IsTiberiumDestroyer) {
|
||||
cellptr->Reduce_Tiberium(strength / 10);
|
||||
}
|
||||
if (optr->IsWall) {
|
||||
if (whead->IsWallDestroyer || (whead->IsWoodDestroyer && optr->IsWooden)) {
|
||||
Map[cell].Reduce_Wall(strength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If there is a bridge at this location, then it may be destroyed by the
|
||||
** combat damage.
|
||||
*/
|
||||
if (cellptr->TType == TEMPLATE_BRIDGE1 || cellptr->TType == TEMPLATE_BRIDGE2 ||
|
||||
cellptr->TType == TEMPLATE_BRIDGE1H || cellptr->TType == TEMPLATE_BRIDGE2H ||
|
||||
cellptr->TType == TEMPLATE_BRIDGE_1A || cellptr->TType == TEMPLATE_BRIDGE_1B ||
|
||||
cellptr->TType == TEMPLATE_BRIDGE_2A || cellptr->TType == TEMPLATE_BRIDGE_2B ||
|
||||
cellptr->TType == TEMPLATE_BRIDGE_3A || cellptr->TType == TEMPLATE_BRIDGE_3B ) {
|
||||
|
||||
if (((warhead == WARHEAD_AP || warhead == WARHEAD_HE) && Random_Pick(1, Rule.BridgeStrength) < strength)) {
|
||||
Map.Destroy_Bridge_At(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Combat_Anim -- Determines explosion animation to play. *
|
||||
* *
|
||||
* This routine is called when a projectile impacts. This routine will determine what *
|
||||
* animation should be played. *
|
||||
* *
|
||||
* INPUT: damage -- The amount of damage this warhead possess (warhead size). *
|
||||
* *
|
||||
* warhead -- The type of warhead. *
|
||||
* *
|
||||
* land -- The land type that this explosion is over. Sometimes, this makes *
|
||||
* a difference (especially over water). *
|
||||
* *
|
||||
* OUTPUT: Returns with the animation to play. If no animation is to be played, then *
|
||||
* ANIM_NONE is returned. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/19/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
AnimType Combat_Anim(int damage, WarheadType warhead, LandType land)
|
||||
{
|
||||
/*
|
||||
** For cases of no damage or invalid warhead, don't have any
|
||||
** animation effect at all.
|
||||
*/
|
||||
if (damage == 0 || warhead == WARHEAD_NONE) {
|
||||
return(ANIM_NONE);
|
||||
}
|
||||
|
||||
static AnimType _aplist[] = {
|
||||
ANIM_VEH_HIT3, // Small fragment throwing explosion -- burn/exp mix.
|
||||
ANIM_VEH_HIT2, // Small fragment throwing explosion -- pop & sparkles.
|
||||
ANIM_FRAG1, // Medium fragment throwing explosion -- short decay.
|
||||
ANIM_FBALL1, // Large fireball explosion (bulges rightward).
|
||||
};
|
||||
|
||||
static AnimType _helist[] = {
|
||||
ANIM_VEH_HIT1, // Small fireball explosion (bulges rightward).
|
||||
ANIM_VEH_HIT2, // Small fragment throwing explosion -- pop & sparkles.
|
||||
ANIM_ART_EXP1, // Large fragment throwing explosion -- many sparkles.
|
||||
ANIM_FBALL1, // Large fireball explosion (bulges rightward).
|
||||
};
|
||||
|
||||
static AnimType _firelist[] = {
|
||||
ANIM_NAPALM1, // Small napalm burn.
|
||||
ANIM_NAPALM2, // Medium napalm burn.
|
||||
ANIM_NAPALM3, // Large napalm burn.
|
||||
};
|
||||
|
||||
static AnimType _waterlist[] = {
|
||||
ANIM_WATER_EXP3,
|
||||
ANIM_WATER_EXP2,
|
||||
ANIM_WATER_EXP1,
|
||||
};
|
||||
|
||||
WarheadTypeClass const * wptr = WarheadTypeClass::As_Pointer(warhead);
|
||||
// WarheadTypeClass const * wptr = &Warheads[warhead];
|
||||
switch (wptr->ExplosionSet) {
|
||||
case 6:
|
||||
return(ANIM_ATOM_BLAST);
|
||||
|
||||
case 2:
|
||||
if (damage > 15) {
|
||||
return(ANIM_PIFFPIFF);
|
||||
}
|
||||
return(ANIM_PIFF);
|
||||
|
||||
case 4:
|
||||
if (land == LAND_NONE) return(ANIM_FLAK);
|
||||
// Fixed math error
|
||||
if (land == LAND_WATER) return(_waterlist[(ARRAY_SIZE(_waterlist)-1) * fixed(min(damage, 90), 90)]);
|
||||
return(_aplist[(ARRAY_SIZE(_aplist)-1) * fixed(min(damage, 90), 90)]);
|
||||
|
||||
case 5:
|
||||
if (land == LAND_NONE) return(ANIM_FLAK);
|
||||
if (land == LAND_WATER) return(_waterlist[(ARRAY_SIZE(_waterlist)-1) * fixed(min(damage, 130), 130)]);
|
||||
return(_helist[(ARRAY_SIZE(_helist)-1) * fixed(min(damage, 130), 130)]);
|
||||
|
||||
case 3:
|
||||
if (land == LAND_NONE) return(ANIM_FLAK);
|
||||
if (land == LAND_WATER) return(_waterlist[(ARRAY_SIZE(_waterlist)-1) * fixed(min(damage, 150), 150)]);
|
||||
return(_firelist[(ARRAY_SIZE(_firelist)-1) * fixed(min(damage, 150), 150)]);
|
||||
|
||||
case 1:
|
||||
return(ANIM_PIFF);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return(ANIM_NONE);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Wide_Area_Damage -- Apply wide area damage to the map. *
|
||||
* *
|
||||
* This routine will apply damage to a very wide area on the map. The damage will be *
|
||||
* spread out from the coordinate specified by the radius specified. The amount of damage *
|
||||
* will attenuate according to the distance from center. *
|
||||
* *
|
||||
* INPUT: coord -- The coordinate that the explosion damage will center about. *
|
||||
* *
|
||||
* radius -- The radius of the explosion. *
|
||||
* *
|
||||
* damage -- The amount of damage to apply at the center location. *
|
||||
* *
|
||||
* source -- Pointer to the purpetrator of the damage (if any). *
|
||||
* *
|
||||
* warhead -- The type of warhead that is causing the damage. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 07/26/1996 JLB : Created. *
|
||||
*=============================================================================================*/
|
||||
void Wide_Area_Damage(COORDINATE coord, LEPTON radius, int rawdamage, TechnoClass * source, WarheadType warhead)
|
||||
{
|
||||
int cell_radius = (radius + CELL_LEPTON_W-1) / CELL_LEPTON_W;
|
||||
CELL cell = Coord_Cell(coord);
|
||||
|
||||
for (int x = -cell_radius; x <= cell_radius; x++) {
|
||||
for (int y = -cell_radius; y <= cell_radius; y++) {
|
||||
int xpos = Cell_X(cell) + x;
|
||||
int ypos = Cell_Y(cell) + y;
|
||||
|
||||
/*
|
||||
** If the potential damage cell is outside of the map bounds,
|
||||
** then don't process it. This unusual check method ensures that
|
||||
** damage won't wrap from one side of the map to the other.
|
||||
*/
|
||||
if ((unsigned)xpos > MAP_CELL_W) {
|
||||
continue;
|
||||
}
|
||||
if ((unsigned)ypos > MAP_CELL_H) {
|
||||
continue;
|
||||
}
|
||||
CELL tcell = XY_Cell(xpos, ypos);
|
||||
if (!Map.In_Radar(tcell)) continue;
|
||||
|
||||
int dist_from_center = Distance(XY_Coord(x+cell_radius, y+cell_radius), XY_Coord(cell_radius, cell_radius));
|
||||
int damage = rawdamage * Inverse(fixed(cell_radius, dist_from_center));
|
||||
Explosion_Damage(Cell_Coord(tcell), damage, source, warhead);
|
||||
if (warhead == WARHEAD_FIRE && damage > 100) {
|
||||
new SmudgeClass(Random_Pick(SMUDGE_SCORCH1, SMUDGE_SCORCH6), Cell_Coord(tcell));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1164
CODE/COMBUF.CPP
Normal file
1164
CODE/COMBUF.CPP
Normal file
File diff suppressed because it is too large
Load Diff
193
CODE/COMBUF.H
Normal file
193
CODE/COMBUF.H
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/COMBUF.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***************************************************************************
|
||||
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : COMBUF.H *
|
||||
* *
|
||||
* Programmer : Bill Randolph *
|
||||
* *
|
||||
* Start Date : December 19, 1994 *
|
||||
* *
|
||||
* Last Update : April 1, 1995 [BR] *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* *
|
||||
* This class's job is to store outgoing messages & incoming messages, *
|
||||
* and serves as a storage area for various flags for ACK & Retry logic. *
|
||||
* *
|
||||
* This class stores buffers in a non-sequenced order; it allows freeing *
|
||||
* any entry, so the buffers can be kept clear, even if packets come in *
|
||||
* out of order. *
|
||||
* *
|
||||
* The class also contains routines to maintain a cumulative response time *
|
||||
* for this queue. It's up to the caller to call Add_Delay() whenever *
|
||||
* it detects that an outgoing message has been ACK'd; this class adds *
|
||||
* that delay into a computed average delay over the last few message *
|
||||
* delays. *
|
||||
* *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef COMBUF_H
|
||||
#define COMBUF_H
|
||||
|
||||
|
||||
/*
|
||||
********************************** Defines **********************************
|
||||
*/
|
||||
/*---------------------------------------------------------------------------
|
||||
This is one output queue entry
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
unsigned int IsActive : 1; // 1 = this entry is ready to be processed
|
||||
unsigned int IsACK : 1; // 1 = ACK received for this packet
|
||||
unsigned long FirstTime; // time this packet was first sent
|
||||
unsigned long LastTime; // time this packet was last sent
|
||||
unsigned long SendCount; // # of times this packet has been sent
|
||||
int BufLen; // size of the packet stored in this entry
|
||||
char *Buffer; // the data packet
|
||||
int ExtraLen; // size of extra data
|
||||
char *ExtraBuffer; // extra data buffer
|
||||
} SendQueueType;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This is one input queue entry
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
unsigned int IsActive : 1; // 1 = this entry is ready to be processed
|
||||
unsigned int IsRead : 1; // 1 = caller has read this entry
|
||||
unsigned int IsACK : 1; // 1 = ACK sent for this packet
|
||||
int BufLen; // size of the packet stored in this entry
|
||||
char *Buffer; // the data packet
|
||||
int ExtraLen; // size of extra data
|
||||
char *ExtraBuffer; // extra data buffer
|
||||
} ReceiveQueueType;
|
||||
|
||||
/*
|
||||
***************************** Class Declaration *****************************
|
||||
*/
|
||||
class CommBufferClass
|
||||
{
|
||||
/*
|
||||
---------------------------- Public Interface ----------------------------
|
||||
*/
|
||||
public:
|
||||
/*
|
||||
....................... Constructor/Destructor ........................
|
||||
*/
|
||||
CommBufferClass(int numsend, int numrecieve, int maxlen,
|
||||
int extralen = 0);
|
||||
virtual ~CommBufferClass();
|
||||
void Init(void);
|
||||
void Init_Send_Queue(void);
|
||||
|
||||
/*
|
||||
......................... Send Queue routines .........................
|
||||
*/
|
||||
int Queue_Send(void *buf, int buflen, void *extrabuf = NULL,
|
||||
int extralen = 0);
|
||||
int UnQueue_Send(void *buf, int *buflen, int index,
|
||||
void *extrabuf = NULL, int *extralen = NULL);
|
||||
int Num_Send(void) {return (SendCount);} // # entries in queue
|
||||
int Max_Send(void) { return (MaxSend);} // max # send queue entries
|
||||
SendQueueType * Get_Send(int index); // random access to queue
|
||||
unsigned long Send_Total(void) {return (SendTotal);}
|
||||
|
||||
/*
|
||||
....................... Receive Queue routines ........................
|
||||
*/
|
||||
int Queue_Receive(void *buf, int buflen, void *extrabuf = NULL,
|
||||
int extralen = 0);
|
||||
int UnQueue_Receive(void *buf, int *buflen, int index,
|
||||
void *extrabuf = NULL, int *extralen = NULL);
|
||||
int Num_Receive(void) {return (ReceiveCount);} // # entries in queue
|
||||
int Max_Receive(void) { return (MaxReceive); } // max # recv queue entries
|
||||
ReceiveQueueType * Get_Receive(int index); // random access to queue
|
||||
unsigned long Receive_Total(void) {return (ReceiveTotal);}
|
||||
|
||||
/*
|
||||
....................... Response time routines ........................
|
||||
*/
|
||||
void Add_Delay(unsigned long delay); // accumulates response time
|
||||
unsigned long Avg_Response_Time(void); // gets mean response time
|
||||
unsigned long Max_Response_Time(void); // gets max response time
|
||||
void Reset_Response_Time(void); // resets computations
|
||||
|
||||
/*
|
||||
........................ Debug output routines ........................
|
||||
*/
|
||||
void Configure_Debug(int type_offset, int type_size, char **names,
|
||||
int namestart, int namecount);
|
||||
void Mono_Debug_Print(int refresh = 0);
|
||||
void Mono_Debug_Print2(int refresh = 0);
|
||||
|
||||
/*
|
||||
--------------------------- Private Interface ----------------------------
|
||||
*/
|
||||
private:
|
||||
/*
|
||||
.......................... Limiting variables .........................
|
||||
*/
|
||||
int MaxSend; // max # send queue entries
|
||||
int MaxReceive; // max # receive queue entries
|
||||
int MaxPacketSize; // max size of a packet, in bytes
|
||||
int MaxExtraSize; // max size of extra bytes
|
||||
|
||||
/*
|
||||
....................... Response time variables .......................
|
||||
*/
|
||||
unsigned long DelaySum; // sum of last 4 delay times
|
||||
unsigned long NumDelay; // current # delay times summed
|
||||
unsigned long MeanDelay; // current average delay time
|
||||
unsigned long MaxDelay; // max delay ever for this queue
|
||||
|
||||
/*
|
||||
........................ Send Queue variables .........................
|
||||
*/
|
||||
SendQueueType * SendQueue; // incoming packets
|
||||
int SendCount; // # packets in the queue
|
||||
unsigned long SendTotal; // total # added to send queue
|
||||
int *SendIndex; // array of Send entry indices
|
||||
|
||||
/*
|
||||
....................... Receive Queue variables .......................
|
||||
*/
|
||||
ReceiveQueueType * ReceiveQueue; // outgoing packets
|
||||
int ReceiveCount; // # packets in the queue
|
||||
unsigned long ReceiveTotal; // total # added to receive queue
|
||||
int *ReceiveIndex; // array of Receive entry indices
|
||||
|
||||
/*
|
||||
......................... Debugging Variables .........................
|
||||
*/
|
||||
int DebugOffset; // offset into app's packet for ID
|
||||
int DebugSize; // size of app's ID
|
||||
char **DebugNames; // ptr to array of app-specific names
|
||||
int DebugNameStart; // number of 1st ID
|
||||
int DebugNameCount; // # of names in array
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**************************** end of combuf.h ******************************/
|
||||
|
51
CODE/COMINIT.CPP
Normal file
51
CODE/COMINIT.CPP
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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 you link with this it will automatically call the COM initialization stuff
|
||||
//
|
||||
|
||||
#include "cominit.h"
|
||||
//#include <stdlib.h>
|
||||
//#include <stdio.h>
|
||||
//#include <windows.h>
|
||||
#include <objbase.h>
|
||||
//#include "externs.h"
|
||||
//#include "text.rh"
|
||||
|
||||
//#include "WolDebug.h"
|
||||
|
||||
ComInit::ComInit()
|
||||
{
|
||||
//HRESULT hRes = CoInitialize(NULL);
|
||||
// if (SUCCEEDED(hRes)==FALSE)
|
||||
// exit(0);
|
||||
HRESULT hRes = OleInitialize(NULL);
|
||||
}
|
||||
|
||||
ComInit::~ComInit()
|
||||
{
|
||||
// CoUninitialize();
|
||||
// debugprint( "pre OleUninitialize\n" );
|
||||
OleUninitialize();
|
||||
// debugprint( "post OleUninitialize\n" );
|
||||
}
|
||||
|
||||
// Creating this instance will setup all COM stuff & do cleanup on program exit
|
||||
ComInit Global_COM_Initializer;
|
||||
|
34
CODE/COMINIT.H
Normal file
34
CODE/COMINIT.H
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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 COMINIT_HEADER
|
||||
#define COMINIT_HEADER
|
||||
|
||||
//
|
||||
// Link with this to automatically initialize COM at startup
|
||||
// - See cominit.cpp for more info
|
||||
//
|
||||
|
||||
class ComInit
|
||||
{
|
||||
public:
|
||||
ComInit();
|
||||
~ComInit();
|
||||
};
|
||||
|
||||
#endif
|
217
CODE/COMPAT.H
Normal file
217
CODE/COMPAT.H
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/COMPAT.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : COMPAT.H *
|
||||
* *
|
||||
* Programmer : Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : 03/02/95 *
|
||||
* *
|
||||
* Last Update : March 2, 1995 [JLB] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef COMPAT_H
|
||||
#define COMPAT_H
|
||||
|
||||
|
||||
#define BuffType BufferClass
|
||||
//#define movmem(a,b,c) memmove(b,a,c)
|
||||
#define ShapeBufferSize _ShapeBufferSize
|
||||
|
||||
/*=========================================================================*/
|
||||
/* Define some equates for the different graphic routines we will install */
|
||||
/* later. */
|
||||
/*=========================================================================*/
|
||||
#define HIDBUFF ((void *)(0xA0000))
|
||||
#define Size_Of_Region(a, b) ((a)*(b))
|
||||
|
||||
/*=========================================================================*/
|
||||
/* Define some Graphic Routines which will only be fixed by these defines */
|
||||
/*=========================================================================*/
|
||||
#define Set_Font_Palette(a) Set_Font_Palette_Range(a, 0, 15)
|
||||
|
||||
/*
|
||||
** These are the Open_File, Read_File, and Seek_File constants.
|
||||
*/
|
||||
#define READ 1 // Read access.
|
||||
#define WRITE 2 // Write access.
|
||||
|
||||
#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
|
||||
|
||||
#define ERROR_WINDOW 1
|
||||
#define ErrorWindow 1
|
||||
|
||||
|
||||
//extern unsigned char *Palette;
|
||||
extern unsigned char MDisabled; // Is mouse disabled?
|
||||
extern WORD Hard_Error_Occured;
|
||||
|
||||
/*
|
||||
** This is the menu control structures.
|
||||
*/
|
||||
typedef enum MenuIndexType {
|
||||
MENUX,
|
||||
MENUY,
|
||||
ITEMWIDTH,
|
||||
ITEMSHIGH,
|
||||
MSELECTED,
|
||||
NORMCOL,
|
||||
HILITE,
|
||||
MENUPADDING=0x1000
|
||||
} MenuIndexType;
|
||||
|
||||
|
||||
#ifdef NEVER
|
||||
#define BITSPERBYTE 8
|
||||
#define MAXSHORT 0x7FFF
|
||||
#define HIBITS 0x8000
|
||||
#define MAXLONG 0x7FFFFFFFL
|
||||
#define HIBITL 0x80000000
|
||||
|
||||
#define MAXINT MAXLONG
|
||||
#define HIBITI HIBITL
|
||||
|
||||
#define DMAXEXP 308
|
||||
#define FMAXEXP 38
|
||||
#define DMINEXP -307
|
||||
#define FMINEXP -37
|
||||
|
||||
#define MAXDOUBLE 1.797693E+308
|
||||
#define MAXFLOAT 3.37E+38F
|
||||
#define MINDOUBLE 2.225074E-308
|
||||
#define MINFLOAT 8.43E-37F
|
||||
|
||||
#define DSIGNIF 53
|
||||
#define FSIGNIF 24
|
||||
|
||||
#define DMAXPOWTWO 0x3FF
|
||||
#define FMAXPOWTWO 0x7F
|
||||
#define DEXPLEN 11
|
||||
#define FEXPLEN 8
|
||||
#define EXPBASE 2
|
||||
#define IEEE 1
|
||||
#define LENBASE 1
|
||||
#define HIDDENBIT 1
|
||||
#define LN_MAXDOUBLE 7.0978E+2
|
||||
#define LN_MINDOUBLE -7.0840E+2
|
||||
#endif
|
||||
|
||||
/* These defines handle the various names given to the same color. */
|
||||
#define DKGREEN GREEN
|
||||
#define DKBLUE BLUE
|
||||
#define GRAY GREY
|
||||
#define DKGREY GREY
|
||||
#define DKGRAY GREY
|
||||
#define LTGRAY LTGREY
|
||||
|
||||
|
||||
class IconsetClass;
|
||||
#ifndef WIN32
|
||||
typedef struct {
|
||||
short Width; // Width of icons (pixels).
|
||||
short Height; // Height of icons (pixels).
|
||||
short Count; // Number of (logical) icons in this set.
|
||||
short Allocated; // Was this iconset allocated?
|
||||
short MapWidth; // Width of map (in icons).
|
||||
short MapHeight; // Height of map (in icons).
|
||||
long Size; // Size of entire iconset memory block.
|
||||
long Icons; // Offset from buffer start to icon data.
|
||||
// unsigned char * Icons; // Offset from buffer start to icon data.
|
||||
long Palettes; // Offset from buffer start to palette data.
|
||||
long Remaps; // Offset from buffer start to remap index data.
|
||||
long TransFlag; // Offset for transparency flag table.
|
||||
long ColorMap; // Offset for color control value table.
|
||||
long Map; // Icon map offset (if present).
|
||||
// unsigned char * Map; // Icon map offset (if present).
|
||||
} IControl_Type;
|
||||
#endif
|
||||
|
||||
inline int Get_IconSet_MapWidth(void const * data)
|
||||
{
|
||||
if (data) {
|
||||
return(((IControl_Type *)data)->MapWidth);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
inline int Get_IconSet_MapHeight(void const * data)
|
||||
{
|
||||
if (data) {
|
||||
return(((IControl_Type *)data)->MapHeight);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
inline unsigned char const * Get_IconSet_ControlMap(void const * data)
|
||||
{
|
||||
if (data) {
|
||||
return((unsigned char const *)((char *)data + ((IControl_Type *)data)->ColorMap));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
class IconsetClass : protected IControl_Type
|
||||
{
|
||||
public:
|
||||
/*
|
||||
** Query functions.
|
||||
*/
|
||||
int Map_Width(void) const {return(MapWidth);};
|
||||
int Map_Height(void) const {return(MapHeight);};
|
||||
unsigned char * Control_Map(void) {return((unsigned char *)this + ColorMap);};
|
||||
unsigned char const * Control_Map(void) const {return((unsigned char const *)this + ColorMap);};
|
||||
int Icon_Count(void) const {return(Count);};
|
||||
int Pixel_Width(void) const {return(Width);};
|
||||
int Pixel_Height(void) const {return(Height);};
|
||||
int Total_Size(void) const {return(Size);};
|
||||
unsigned char const * Palette_Data(void) const {return((unsigned char const *)this + Palettes);};
|
||||
unsigned char * Palette_Data(void) {return((unsigned char *)this + Palettes);};
|
||||
unsigned char const * Icon_Data(void) const {return((unsigned char const *)this + Icons);};
|
||||
unsigned char * Icon_Data(void) {return((unsigned char *)this + Icons);};
|
||||
unsigned char const * Map_Data(void) const {return((unsigned char const *)this + Map);};
|
||||
unsigned char * Map_Data(void) {return((unsigned char *)this + Map);};
|
||||
unsigned char const * Remap_Data(void) const {return((unsigned char const *)this + Remaps);};
|
||||
unsigned char * Remap_Data(void) {return((unsigned char *)this + Remaps);};
|
||||
unsigned char const * Trans_Data(void) const {return((unsigned char const *)this + TransFlag);};
|
||||
unsigned char * Trans_Data(void) {return((unsigned char *)this + TransFlag);};
|
||||
|
||||
/*
|
||||
** Disallow these operations with an IconsetClass object.
|
||||
*/
|
||||
private:
|
||||
IconsetClass & operator = (IconsetClass const &);
|
||||
IconsetClass(void);
|
||||
static void * operator new(size_t);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
1003
CODE/COMQUEUE.CPP
Normal file
1003
CODE/COMQUEUE.CPP
Normal file
File diff suppressed because it is too large
Load Diff
193
CODE/COMQUEUE.H
Normal file
193
CODE/COMQUEUE.H
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: F:\projects\c&c0\vcs\code\comqueue.h_v 4.1 11 Apr 1996 18:26:02 JOE_BOSTIC $ */
|
||||
/***************************************************************************
|
||||
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : COMQUEUE.H *
|
||||
* *
|
||||
* Programmer : Bill Randolph *
|
||||
* *
|
||||
* Start Date : December 19, 1994 *
|
||||
* *
|
||||
* Last Update : April 1, 1995 [BR] *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* *
|
||||
* This class's job is to queue up outgoing messages & incoming messages, *
|
||||
* and serves as a storage area for various flags for ACK & Retry logic. *
|
||||
* It allows the application to keep track of how many messages have *
|
||||
* passed through this queue, in & out, so packets can use this as a *
|
||||
* unique ID. (If packets have a unique ID, the application can use this *
|
||||
* to detect re-sends.) *
|
||||
* *
|
||||
* The queues act as FIFO buffers (First-In, First-Out). The first entry *
|
||||
* placed in a queue is the first one read from it, and so on. The *
|
||||
* controlling application must ensure it places the entries on the queue *
|
||||
* in the order it wants to access them. *
|
||||
* *
|
||||
* The queue is implemented as an array of Queue Entries. Index 0 is the *
|
||||
* first element placed on the queue, and is the first retrieved. Index *
|
||||
* 1 is the next, and so on. When Index 0 is retrieved, the next-available*
|
||||
* entry becomes Index 1. The array is circular; when the end is reached, *
|
||||
* the indices wrap around to the beginning. *
|
||||
* *
|
||||
* The class also contains routines to maintain a cumulative response time *
|
||||
* for this queue. It's up to the caller to call Add_Delay() whenever *
|
||||
* it detects that an outgoing message has been ACK'd; this class adds *
|
||||
* that delay into a computed average delay over the last few message *
|
||||
* delays. *
|
||||
* *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef COMQUEUE_H
|
||||
#define COMQUEUE_H
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This is one output queue entry
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
unsigned int IsActive : 1; // 1 = this entry is ready to be processed
|
||||
unsigned int IsACK : 1; // 1 = ACK received for this packet
|
||||
unsigned long FirstTime; // time this packet was first sent
|
||||
unsigned long LastTime; // time this packet was last sent
|
||||
unsigned long SendCount; // # of times this packet has been sent
|
||||
int BufLen; // size of the packet stored in this entry
|
||||
char *Buffer; // the data packet
|
||||
} SendQueueType;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This is one input queue entry
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
unsigned int IsActive : 1; // 1 = this entry is ready to be processed
|
||||
unsigned int IsRead : 1; // 1 = caller has read this entry
|
||||
unsigned int IsACK : 1; // 1 = ACK sent for this packet
|
||||
int BufLen; // size of the packet stored in this entry
|
||||
char *Buffer; // the data packet
|
||||
} ReceiveQueueType;
|
||||
|
||||
/*
|
||||
***************************** Class Declaration *****************************
|
||||
*/
|
||||
class CommQueueClass
|
||||
{
|
||||
/*
|
||||
---------------------------- Public Interface ----------------------------
|
||||
*/
|
||||
public:
|
||||
/*
|
||||
....................... Constructor/Destructor ........................
|
||||
*/
|
||||
CommQueueClass(int numsend, int numrecieve, int maxlen);
|
||||
virtual ~CommQueueClass();
|
||||
void Init(void);
|
||||
|
||||
/*
|
||||
......................... Send Queue routines .........................
|
||||
*/
|
||||
int Queue_Send(void *buf, int buflen); // add to Send queue
|
||||
int UnQueue_Send(void *buf, int *buflen); // remove from Send queue
|
||||
SendQueueType * Next_Send(void); // ptr to next avail entry
|
||||
int Num_Send(void) {return (SendCount);} // # entries in queue
|
||||
int Max_Send(void) { return (MaxSend);} // max # send queue entries
|
||||
SendQueueType * Get_Send(int index); // random access to queue
|
||||
unsigned long Send_Total(void) {return (SendTotal);}
|
||||
|
||||
/*
|
||||
....................... Receive Queue routines ........................
|
||||
*/
|
||||
int Queue_Receive(void *buf, int buflen); // add to Receive queue
|
||||
int UnQueue_Receive(void *buf, int *buflen); // remove from Receive queue
|
||||
ReceiveQueueType * Next_Receive(void); // ptr to next avail entry
|
||||
int Num_Receive(void) {return (ReceiveCount);} // # entries in queue
|
||||
int Max_Receive(void) { return (MaxReceive); } // max # recv queue entries
|
||||
ReceiveQueueType * Get_Receive(int index); // random access to queue
|
||||
unsigned long Receive_Total(void) {return (ReceiveTotal);}
|
||||
|
||||
/*
|
||||
....................... Response time routines ........................
|
||||
*/
|
||||
void Add_Delay(unsigned long delay); // accumulates response time
|
||||
unsigned long Avg_Response_Time(void); // gets mean response time
|
||||
unsigned long Max_Response_Time(void); // gets max response time
|
||||
void Reset_Response_Time(void); // resets computations
|
||||
|
||||
/*
|
||||
........................ Debug output routines ........................
|
||||
*/
|
||||
void Configure_Debug(int offset, int size, char **names, int maxnames);
|
||||
void Mono_Debug_Print(int refresh = 0);
|
||||
void Mono_Debug_Print2(int refresh = 0);
|
||||
|
||||
/*
|
||||
--------------------------- Private Interface ----------------------------
|
||||
*/
|
||||
private:
|
||||
/*
|
||||
.......................... Limiting variables .........................
|
||||
*/
|
||||
int MaxSend; // max # send queue entries
|
||||
int MaxReceive; // max # receive queue entries
|
||||
int MaxPacketSize; // max size of a packet, in bytes
|
||||
|
||||
/*
|
||||
....................... Response time variables .......................
|
||||
*/
|
||||
unsigned long DelaySum; // sum of last 4 delay times
|
||||
unsigned long NumDelay; // current # delay times summed
|
||||
unsigned long MeanDelay; // current average delay time
|
||||
unsigned long MaxDelay; // max delay ever for this queue
|
||||
|
||||
/*
|
||||
........................ Send Queue variables .........................
|
||||
*/
|
||||
SendQueueType * SendQueue; // incoming packets
|
||||
int SendCount; // # packets in the queue
|
||||
int SendNext; // next entry read from queue
|
||||
int SendEmpty; // next empty spot in queue
|
||||
unsigned long SendTotal; // total # added to send queue
|
||||
|
||||
/*
|
||||
....................... Receive Queue variables .......................
|
||||
*/
|
||||
ReceiveQueueType * ReceiveQueue; // outgoing packets
|
||||
int ReceiveCount; // # packets in the queue
|
||||
int ReceiveNext; // next entry read from queue
|
||||
int ReceiveEmpty; // next empty spot in queue
|
||||
unsigned long ReceiveTotal; // total # added to receive queue
|
||||
|
||||
/*
|
||||
......................... Debugging Variables .........................
|
||||
*/
|
||||
int DebugOffset; // offset into app's packet for ID
|
||||
int DebugSize; // size of app's ID
|
||||
char **DebugNames; // ptr to array of app-specific names
|
||||
int DebugMaxNames; // max # of names in array
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*************************** end of comqueue.h *****************************/
|
||||
|
244
CODE/CONFDLG.CPP
Normal file
244
CODE/CONFDLG.CPP
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: F:\projects\c&c0\vcs\code\confdlg.cpv 4.67 27 Aug 1996 15:46:52 JOE_BOSTIC $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CONFDLG.CPP *
|
||||
* *
|
||||
* Programmer : Maria del Mar McCready Legg *
|
||||
* Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : Jan 30, 1995 *
|
||||
* *
|
||||
* Last Update : Jan 30, 1995 [MML] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* ConfirmationClass::Process -- Handles all the options graphic interface. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "function.h"
|
||||
#include "confdlg.h"
|
||||
|
||||
|
||||
bool ConfirmationClass::Process(int text)
|
||||
{
|
||||
return(Process(Text_String(text)));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ConfirmationClass::Process -- Handles all the options graphic interface. *
|
||||
* *
|
||||
* This dialog uses an edit box to confirm a deletion. *
|
||||
* *
|
||||
* INPUT: char * string - display in edit box. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: 12/31/1994 MML : Created. *
|
||||
*=============================================================================================*/
|
||||
bool ConfirmationClass::Process(char const * string)
|
||||
{
|
||||
enum {
|
||||
NUM_OF_BUTTONS = 2
|
||||
};
|
||||
|
||||
char buffer[80*3];
|
||||
int result = true;
|
||||
int width;
|
||||
int bwidth, bheight; // button width and height
|
||||
int height;
|
||||
int selection = 0;
|
||||
bool pressed;
|
||||
int curbutton;
|
||||
TextButtonClass * buttons[NUM_OF_BUTTONS];
|
||||
|
||||
/*
|
||||
** Set up the window. Window x-coords are in bytes not pixels.
|
||||
*/
|
||||
strcpy(buffer, string);
|
||||
Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW);
|
||||
Format_Window_String(buffer, 200, width, height);
|
||||
width += 60;
|
||||
height += 60;
|
||||
int x = (320 - width) / 2;
|
||||
int y = (200 - height) / 2;
|
||||
|
||||
Set_Logic_Page(SeenBuff);
|
||||
|
||||
/*
|
||||
** Create Buttons. Button coords are in pixels, but are window-relative.
|
||||
*/
|
||||
bheight = FontHeight + FontYSpacing + 2;
|
||||
bwidth = max( (String_Pixel_Width( Text_String( TXT_YES ) ) + 8), 30);
|
||||
|
||||
TextButtonClass yesbtn(BUTTON_YES, TXT_YES,
|
||||
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
|
||||
x + 10, y + height - (bheight + 5), bwidth );
|
||||
|
||||
TextButtonClass nobtn(BUTTON_NO, TXT_NO,
|
||||
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
|
||||
x + width - (bwidth + 10),
|
||||
y + height - (bheight + 5), bwidth );
|
||||
|
||||
nobtn.Add_Tail(yesbtn);
|
||||
|
||||
curbutton = 1;
|
||||
buttons[0] = &yesbtn;
|
||||
buttons[1] = &nobtn;
|
||||
buttons[curbutton]->Turn_On();
|
||||
|
||||
/*
|
||||
** This causes left mouse button clicking within the confines of the dialog to
|
||||
** be ignored if it wasn't recognized by any other button or slider.
|
||||
*/
|
||||
GadgetClass dialog(x, y, width, height, GadgetClass::LEFTPRESS);
|
||||
dialog.Add_Tail(yesbtn);
|
||||
|
||||
/*
|
||||
** This causes a right click anywhere or a left click outside the dialog region
|
||||
** to be equivalent to clicking on the return to options dialog.
|
||||
*/
|
||||
ControlClass background(BUTTON_NO, 0, 0, 320, 200, GadgetClass::LEFTPRESS|GadgetClass::RIGHTPRESS);
|
||||
background.Add_Tail(yesbtn);
|
||||
|
||||
/*
|
||||
** Main Processing Loop.
|
||||
*/
|
||||
bool display = true;
|
||||
bool process = true;
|
||||
pressed = false;
|
||||
while (process) {
|
||||
|
||||
/*
|
||||
** Invoke game callback.
|
||||
*/
|
||||
if (Session.Type == GAME_NORMAL) {
|
||||
Call_Back();
|
||||
} else {
|
||||
if (Main_Loop()) {
|
||||
process = false;
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Refresh display if needed.
|
||||
*/
|
||||
if (display) {
|
||||
Hide_Mouse();
|
||||
|
||||
/*
|
||||
** Draw the background.
|
||||
*/
|
||||
Dialog_Box(x, y, width, height);
|
||||
Draw_Caption(TXT_CONFIRMATION, x, y, width);
|
||||
Fancy_Text_Print(buffer, x+20, y+30, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);
|
||||
|
||||
/*
|
||||
** Draw the titles.
|
||||
*/
|
||||
yesbtn.Draw_All();
|
||||
Show_Mouse();
|
||||
display = false;
|
||||
}
|
||||
|
||||
/*
|
||||
** Get user input.
|
||||
*/
|
||||
KeyNumType input = yesbtn.Input();
|
||||
|
||||
/*
|
||||
** Process Input.
|
||||
*/
|
||||
switch (input) {
|
||||
case KeyNumType(BUTTON_YES | KN_BUTTON):
|
||||
selection = BUTTON_YES;
|
||||
pressed = true;
|
||||
break;
|
||||
|
||||
case (KN_ESC):
|
||||
case KeyNumType(BUTTON_NO | KN_BUTTON):
|
||||
selection = BUTTON_NO;
|
||||
pressed = true;
|
||||
break;
|
||||
|
||||
case (KN_LEFT):
|
||||
buttons[curbutton]->Turn_Off();
|
||||
buttons[curbutton]->Flag_To_Redraw();
|
||||
|
||||
curbutton--;
|
||||
if (curbutton < 0) {
|
||||
curbutton = NUM_OF_BUTTONS - 1;
|
||||
}
|
||||
|
||||
buttons[curbutton]->Turn_On();
|
||||
buttons[curbutton]->Flag_To_Redraw();
|
||||
break;
|
||||
|
||||
case (KN_RIGHT):
|
||||
buttons[curbutton]->Turn_Off();
|
||||
buttons[curbutton]->Flag_To_Redraw();
|
||||
|
||||
curbutton++;
|
||||
if (curbutton > (NUM_OF_BUTTONS - 1) ) {
|
||||
curbutton = 0;
|
||||
}
|
||||
|
||||
buttons[curbutton]->Turn_On();
|
||||
buttons[curbutton]->Flag_To_Redraw();
|
||||
break;
|
||||
|
||||
case (KN_RETURN):
|
||||
selection = curbutton + BUTTON_YES;
|
||||
pressed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pressed) {
|
||||
switch (selection) {
|
||||
case (BUTTON_YES):
|
||||
result = true;
|
||||
process = false;
|
||||
break;
|
||||
|
||||
case (BUTTON_NO):
|
||||
result = false;
|
||||
process = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pressed = false;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
56
CODE/CONFDLG.H
Normal file
56
CODE/CONFDLG.H
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: F:\projects\c&c0\vcs\code\confdlg.h_v 4.69 27 Aug 1996 15:43:36 JOE_BOSTIC $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CONFDLG.H *
|
||||
* *
|
||||
* Programmer : Maria del Mar McCready Legg *
|
||||
* Joe L. Bostic *
|
||||
* *
|
||||
* Start Date : Jan 30, 1995 *
|
||||
* *
|
||||
* Last Update : Jan 30, 1995 [MML] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CONFDLG_H
|
||||
#define CONFDLG_H
|
||||
|
||||
#include "gadget.h"
|
||||
|
||||
class ConfirmationClass
|
||||
{
|
||||
private:
|
||||
enum ConfirmationClassEnum {
|
||||
BUTTON_YES=1, // Button number for "Options menu"
|
||||
BUTTON_NO // Button number for "Options menu"
|
||||
};
|
||||
|
||||
public:
|
||||
ConfirmationClass(void) { };
|
||||
bool Process(char const * string);
|
||||
bool Process(int text);
|
||||
};
|
||||
|
||||
#endif
|
838
CODE/CONNECT.CPP
Normal file
838
CODE/CONNECT.CPP
Normal file
@ -0,0 +1,838 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CONNECT.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***************************************************************************
|
||||
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CONNECT.CPP *
|
||||
* *
|
||||
* Programmer : Bill Randolph *
|
||||
* *
|
||||
* Start Date : December 20, 1994 *
|
||||
* *
|
||||
* Last Update : May 31, 1995 [BRR] *
|
||||
*-------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* ConnectionClass::ConnectionClass -- class constructor *
|
||||
* ConnectionClass::~ConnectionClass -- class destructor *
|
||||
* ConnectionClass::Init -- Initializes connection queue to empty *
|
||||
* ConnectionClass::Send_Packet -- adds a packet to the send queue *
|
||||
* ConnectionClass::Receive_Packet -- adds packet to receive queue *
|
||||
* ConnectionClass::Get_Packet -- gets a packet from receive queue *
|
||||
* ConnectionClass::Service -- main polling routine; services packets *
|
||||
* ConnectionClass::Service_Send_Queue -- services the send queue *
|
||||
* ConnectionClass::Service_Receive_Queue -- services receive queue *
|
||||
* ConnectionClass::Time -- gets current time *
|
||||
* ConnectionClass::Command_Name -- returns name for a packet command *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
|
||||
#include "function.h"
|
||||
#include <stdio.h>
|
||||
#include <mem.h>
|
||||
#include <sys\timeb.h>
|
||||
#include "connect.h"
|
||||
|
||||
#include "WolDebug.h"
|
||||
|
||||
/*
|
||||
********************************* Globals ***********************************
|
||||
*/
|
||||
static char *ConnectionClass::Commands[PACKET_COUNT] = {
|
||||
"ADATA",
|
||||
"NDATA",
|
||||
"ACK"
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::ConnectionClass -- class constructor *
|
||||
* *
|
||||
* INPUT: *
|
||||
* numsend desired # of entries for the send queue *
|
||||
* numreceive desired # of entries for the receive queue *
|
||||
* maxlen max length of an application packet *
|
||||
* magicnum the packet "magic number" for this connection *
|
||||
* retry_delta the time to wait between sends *
|
||||
* max_retries the max # of retries allowed for a packet *
|
||||
* (-1 means retry forever, based on this parameter) *
|
||||
* timeout the max amount of time before we give up on a packet *
|
||||
* (-1 means retry forever, based on this parameter) *
|
||||
* extralen max size of app-specific extra bytes (optional) *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
ConnectionClass::ConnectionClass (int numsend, int numreceive,
|
||||
int maxlen, unsigned short magicnum, unsigned long retry_delta,
|
||||
unsigned long max_retries, unsigned long timeout, int extralen)
|
||||
{
|
||||
/*------------------------------------------------------------------------
|
||||
Compute our maximum packet length
|
||||
------------------------------------------------------------------------*/
|
||||
MaxPacketLen = maxlen + sizeof(CommHeaderType);
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Assign the magic number
|
||||
------------------------------------------------------------------------*/
|
||||
MagicNum = magicnum;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Initialize the retry time. This is the time that t2 - t1 must be greater
|
||||
than before a retry will occur.
|
||||
------------------------------------------------------------------------*/
|
||||
RetryDelta = retry_delta;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Set the maximum allowable retries.
|
||||
------------------------------------------------------------------------*/
|
||||
MaxRetries = max_retries;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Set the timeout for this connection.
|
||||
------------------------------------------------------------------------*/
|
||||
Timeout = timeout;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Allocate the packet staging buffer. This will be used to
|
||||
------------------------------------------------------------------------*/
|
||||
PacketBuf = new char[ MaxPacketLen ];
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Allocate the packet Queue. This will store incoming packets (placed there
|
||||
by Receive_Packet), and outgoing packets (placed there by Send_Packet).
|
||||
It can optionally store "extra" bytes, which are stored along with each
|
||||
packet, but aren't transmitted as part of the packet. If 'extralen'
|
||||
is 0, the CommBufferClass ignores this parameter.
|
||||
------------------------------------------------------------------------*/
|
||||
Queue = new CommBufferClass (numsend, numreceive, MaxPacketLen, extralen);
|
||||
|
||||
} /* end of ConnectionClass */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::~ConnectionClass -- class destructor *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
ConnectionClass::~ConnectionClass ()
|
||||
{
|
||||
/*------------------------------------------------------------------------
|
||||
Free memory.
|
||||
------------------------------------------------------------------------*/
|
||||
delete [] PacketBuf;
|
||||
delete Queue;
|
||||
|
||||
} /* end of ~ConnectionClass */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Init -- Initializes connection queue to empty *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
void ConnectionClass::Init (void)
|
||||
{
|
||||
NumRecNoAck = 0;
|
||||
NumRecAck = 0;
|
||||
NumSendNoAck = 0;
|
||||
NumSendAck = 0;
|
||||
|
||||
LastSeqID = 0xffffffff;
|
||||
LastReadID = 0xffffffff;
|
||||
|
||||
Queue->Init();
|
||||
|
||||
} /* end of Init */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Send_Packet -- adds a packet to the send queue *
|
||||
* *
|
||||
* This routine prefixes the given buffer with a CommHeaderType and *
|
||||
* queues the resulting packet into the Send Queue. (It's actually the *
|
||||
* Service() routine that handles the hardware-dependent Send of the data).*
|
||||
* The packet's MagicNumber, Code, and PacketID are set here. *
|
||||
* *
|
||||
* INPUT: *
|
||||
* buf buffer to send *
|
||||
* buflen length of buffer *
|
||||
* ack_req 1 = ACK is required for this packet; 0 = isn't *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = packet was queue'd OK, 0 = wasn't *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Send_Packet (void * buf, int buflen, int ack_req)
|
||||
{
|
||||
/*------------------------------------------------------------------------
|
||||
Set the magic # for the packet
|
||||
------------------------------------------------------------------------*/
|
||||
((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Set the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't
|
||||
Set the packet ID to the appropriate counter value.
|
||||
------------------------------------------------------------------------*/
|
||||
if (ack_req) {
|
||||
((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;
|
||||
((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;
|
||||
}
|
||||
else {
|
||||
((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;
|
||||
((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Now build the packet
|
||||
------------------------------------------------------------------------*/
|
||||
memcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Add it to the queue; don't add any extra data with it.
|
||||
------------------------------------------------------------------------*/
|
||||
if (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType), NULL, 0)) {
|
||||
if (ack_req) {
|
||||
NumSendAck++;
|
||||
}
|
||||
else {
|
||||
NumSendNoAck++;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
else {
|
||||
return(0);
|
||||
}
|
||||
|
||||
} /* end of Send_Packet */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Receive_Packet -- adds packet to receive queue *
|
||||
* *
|
||||
* INPUT: *
|
||||
* buf buffer to process (already includes CommHeaderType) *
|
||||
* buflen length of buffer to process *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = packet was processed OK, 0 = error *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Receive_Packet (void * buf, int buflen)
|
||||
{
|
||||
CommHeaderType *packet; // ptr to packet header
|
||||
SendQueueType *send_entry; // ptr to send entry header
|
||||
ReceiveQueueType *rec_entry; // ptr to recv entry header
|
||||
CommHeaderType *entry_data; // ptr to queue entry data
|
||||
CommHeaderType ackpacket; // ACK packet to send
|
||||
int i;
|
||||
int save_packet = 1; // 0 = this is a resend
|
||||
int found;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Check the magic #
|
||||
------------------------------------------------------------------------*/
|
||||
packet = (CommHeaderType *)buf;
|
||||
if (packet->MagicNumber != MagicNum) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Handle an incoming ACK
|
||||
------------------------------------------------------------------------*/
|
||||
if (packet->Code == PACKET_ACK) {
|
||||
|
||||
for (i = 0; i < Queue->Num_Send(); i++) {
|
||||
/*..................................................................
|
||||
Get queue entry ptr
|
||||
..................................................................*/
|
||||
send_entry = Queue->Get_Send(i);
|
||||
|
||||
/*..................................................................
|
||||
If ptr is valid, get ptr to its data
|
||||
..................................................................*/
|
||||
if (send_entry != NULL) {
|
||||
entry_data = (CommHeaderType *)send_entry->Buffer;
|
||||
|
||||
/*...............................................................
|
||||
If ACK is for this entry, mark it
|
||||
...............................................................*/
|
||||
if (packet->PacketID==entry_data->PacketID &&
|
||||
entry_data->Code == PACKET_DATA_ACK) {
|
||||
send_entry->IsACK = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Handle an incoming PACKET_DATA_NOACK packet
|
||||
------------------------------------------------------------------------*/
|
||||
else if (packet->Code == PACKET_DATA_NOACK) {
|
||||
/*.....................................................................
|
||||
If there's only one slot left, don't tie up the queue with this packet
|
||||
.....................................................................*/
|
||||
if (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*.....................................................................
|
||||
Error if we can't queue the packet
|
||||
.....................................................................*/
|
||||
if (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
NumRecNoAck++;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Handle an incoming PACKET_DATA_ACK packet
|
||||
------------------------------------------------------------------------*/
|
||||
else if (packet->Code == PACKET_DATA_ACK) {
|
||||
/*.....................................................................
|
||||
If this is a packet requires an ACK, and it's ID is older than our
|
||||
"oldest" ID, we know it's a resend; send an ACK, but don't queue it
|
||||
.....................................................................*/
|
||||
if (packet->PacketID <= LastSeqID && LastSeqID != 0xffffffff) {
|
||||
save_packet = 0;
|
||||
}
|
||||
|
||||
/*.....................................................................
|
||||
Otherwise, scan the queue for this entry; if it's found, it's a
|
||||
resend, so don't save it.
|
||||
.....................................................................*/
|
||||
else {
|
||||
save_packet = 1;
|
||||
for (i = 0; i < Queue->Num_Receive(); i++) {
|
||||
rec_entry = Queue->Get_Receive(i);
|
||||
|
||||
if (rec_entry) {
|
||||
|
||||
entry_data = (CommHeaderType *)rec_entry->Buffer;
|
||||
|
||||
/*...........................................................
|
||||
Packet is found; it's a resend
|
||||
...........................................................*/
|
||||
if (entry_data->Code == PACKET_DATA_ACK &&
|
||||
entry_data->PacketID == packet->PacketID) {
|
||||
save_packet = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* end of scan for resend */
|
||||
|
||||
/*.....................................................................
|
||||
Queue the packet & update our LastSeqID value.
|
||||
.....................................................................*/
|
||||
if (save_packet) {
|
||||
/*..................................................................
|
||||
If there's only one slot left, make sure we only put a packet in it
|
||||
if this packet will let us increment our LastSeqID; otherwise, we'll
|
||||
get stuck, forever unable to increment LastSeqID.
|
||||
..................................................................*/
|
||||
if (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {
|
||||
if (packet->PacketID != (LastSeqID + 1) ) {
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*..................................................................
|
||||
If we can't queue the packet, return; don't send an ACK.
|
||||
..................................................................*/
|
||||
if (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
NumRecAck++;
|
||||
|
||||
/*..................................................................
|
||||
Update our LastSeqID value if we can. Anything less than LastSeqID
|
||||
we'll know is a resend.
|
||||
..................................................................*/
|
||||
if (packet->PacketID == (LastSeqID + 1)) {
|
||||
LastSeqID = packet->PacketID;
|
||||
/*...............................................................
|
||||
Now that we have a new 'LastSeqID', search our Queue to see if
|
||||
the next ID is there; if so, keep checking for the next one;
|
||||
break only when the next one isn't found. This forces
|
||||
LastSeqID to be the largest possible value.
|
||||
...............................................................*/
|
||||
do {
|
||||
found = 0;
|
||||
for (i = 0; i < Queue->Num_Receive(); i++) {
|
||||
|
||||
rec_entry = Queue->Get_Receive(i);
|
||||
|
||||
if (rec_entry) {
|
||||
entry_data = (CommHeaderType *)rec_entry->Buffer;
|
||||
|
||||
/*......................................................
|
||||
Entry is found
|
||||
......................................................*/
|
||||
if (entry_data->Code == PACKET_DATA_ACK &&
|
||||
entry_data->PacketID == (LastSeqID + 1)) {
|
||||
|
||||
LastSeqID = entry_data->PacketID;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (found);
|
||||
}
|
||||
} /* end of save packet */
|
||||
|
||||
/*.....................................................................
|
||||
Send an ACK, regardless of whether this was a resend or not.
|
||||
.....................................................................*/
|
||||
ackpacket.MagicNumber = Magic_Num();
|
||||
ackpacket.Code = PACKET_ACK;
|
||||
ackpacket.PacketID = packet->PacketID;
|
||||
Send ((char *)&ackpacket, sizeof(CommHeaderType), NULL, 0);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
||||
} /* end of Receive_Packet */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Get_Packet -- gets a packet from receive queue *
|
||||
* *
|
||||
* INPUT: *
|
||||
* buf location to store buffer *
|
||||
* buflen filled in with length of 'buf' *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = packet was read, 0 = wasn't *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Get_Packet (void * buf, int *buflen)
|
||||
{
|
||||
ReceiveQueueType *rec_entry; // ptr to receive entry header
|
||||
int packetlen; // size of received packet
|
||||
CommHeaderType *entry_data;
|
||||
int i;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Ensure that we read the packets in order. LastReadID is the ID of the
|
||||
last PACKET_DATA_ACK packet we read.
|
||||
------------------------------------------------------------------------*/
|
||||
for (i = 0; i < Queue->Num_Receive(); i++) {
|
||||
|
||||
rec_entry = Queue->Get_Receive(i);
|
||||
|
||||
/*.....................................................................
|
||||
Only read this entry if it hasn't been yet
|
||||
.....................................................................*/
|
||||
if (rec_entry && rec_entry->IsRead==0) {
|
||||
|
||||
entry_data = (CommHeaderType *)rec_entry->Buffer;
|
||||
|
||||
/*..................................................................
|
||||
If this is a DATA_ACK packet, its ID must be one greater than
|
||||
the last one we read.
|
||||
..................................................................*/
|
||||
if ( (entry_data->Code == PACKET_DATA_ACK) &&
|
||||
(entry_data->PacketID == (LastReadID + 1))) {
|
||||
|
||||
LastReadID = entry_data->PacketID;
|
||||
rec_entry->IsRead = 1;
|
||||
|
||||
packetlen = rec_entry->BufLen - sizeof(CommHeaderType);
|
||||
if (packetlen > 0) {
|
||||
memcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),
|
||||
packetlen);
|
||||
}
|
||||
(*buflen) = packetlen;
|
||||
return(1);
|
||||
}
|
||||
/*..................................................................
|
||||
If this is a DATA_NOACK packet, who cares what the ID is?
|
||||
..................................................................*/
|
||||
else if (entry_data->Code == PACKET_DATA_NOACK) {
|
||||
rec_entry->IsRead = 1;
|
||||
|
||||
packetlen = rec_entry->BufLen - sizeof(CommHeaderType);
|
||||
if (packetlen > 0) {
|
||||
memcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),
|
||||
packetlen);
|
||||
}
|
||||
(*buflen) = packetlen;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
||||
} /* end of Get_Packet */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Service -- main polling routine; services packets *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = OK, 0 = error (connection is broken!) *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Service (void)
|
||||
{
|
||||
/*------------------------------------------------------------------------
|
||||
Service the Send Queue: This [re]sends packets in the Send Queue which
|
||||
haven't been ACK'd yet, and if their retry timeout has expired, and
|
||||
updates the FirstTime, LastTime & SendCount values in the Queue entry.
|
||||
Entries that have been ACK'd should be removed.
|
||||
|
||||
Service the Receive Queue: This sends ACKs for packets that haven't
|
||||
been ACK'd yet. Entries that the app has read, and have been ACK'd,
|
||||
should be removed.
|
||||
------------------------------------------------------------------------*/
|
||||
if ( Service_Send_Queue() && Service_Receive_Queue() ) {
|
||||
return(1);
|
||||
}
|
||||
else {
|
||||
return(0);
|
||||
}
|
||||
|
||||
} /* end of Service */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Service_Send_Queue -- services the send queue *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = OK, 0 = error *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Service_Send_Queue (void)
|
||||
{
|
||||
int i;
|
||||
int num_entries;
|
||||
SendQueueType *send_entry; // ptr to send queue entry
|
||||
CommHeaderType *packet_hdr; // packet header
|
||||
unsigned long curtime; // current time
|
||||
int bad_conn = 0;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Remove any ACK'd packets from the queue
|
||||
------------------------------------------------------------------------*/
|
||||
for (i = 0; i < Queue->Num_Send(); i++) {
|
||||
/*.....................................................................
|
||||
Get this queue entry
|
||||
.....................................................................*/
|
||||
send_entry = Queue->Get_Send(i);
|
||||
|
||||
/*.....................................................................
|
||||
If ACK has been received, unqueue it
|
||||
.....................................................................*/
|
||||
if (send_entry->IsACK) {
|
||||
|
||||
/*..................................................................
|
||||
Update this queue's response time
|
||||
..................................................................*/
|
||||
packet_hdr = (CommHeaderType *)send_entry->Buffer;
|
||||
if (packet_hdr->Code == PACKET_DATA_ACK) {
|
||||
Queue->Add_Delay(Time() - send_entry->FirstTime);
|
||||
}
|
||||
|
||||
/*..................................................................
|
||||
Unqueue the packet
|
||||
..................................................................*/
|
||||
Queue->UnQueue_Send(NULL,NULL,i,NULL,NULL);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Loop through all entries in the Send queue. [Re]Send any entries that
|
||||
need it.
|
||||
------------------------------------------------------------------------*/
|
||||
num_entries = Queue->Num_Send();
|
||||
|
||||
for (i = 0; i < num_entries; i++) {
|
||||
send_entry = Queue->Get_Send(i);
|
||||
|
||||
if (send_entry->IsACK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*.....................................................................
|
||||
Only send the message if time has elapsed. (The message's Time
|
||||
fields are init'd to 0 when a message is queue'd or unqueue'd, so the
|
||||
first time through, the delta time will appear large.)
|
||||
.....................................................................*/
|
||||
curtime = Time();
|
||||
if (curtime - send_entry->LastTime > RetryDelta) {
|
||||
|
||||
/*..................................................................
|
||||
Send the message
|
||||
..................................................................*/
|
||||
Send (send_entry->Buffer, send_entry->BufLen, send_entry->ExtraBuffer,
|
||||
send_entry->ExtraLen);
|
||||
|
||||
/*..................................................................
|
||||
Fill in Time fields
|
||||
..................................................................*/
|
||||
send_entry->LastTime = curtime;
|
||||
if (send_entry->SendCount==0) {
|
||||
send_entry->FirstTime = curtime;
|
||||
|
||||
/*...............................................................
|
||||
If this is the 1st time we're sending this packet, and it doesn't
|
||||
require an ACK, mark it as ACK'd; then, the next time through,
|
||||
it will just be removed from the queue.
|
||||
...............................................................*/
|
||||
packet_hdr = (CommHeaderType *)send_entry->Buffer;
|
||||
if (packet_hdr->Code == PACKET_DATA_NOACK) {
|
||||
send_entry->IsACK = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*..................................................................
|
||||
Update SendCount
|
||||
..................................................................*/
|
||||
send_entry->SendCount++;
|
||||
|
||||
/*..................................................................
|
||||
Perform error detection, based on either MaxRetries or Timeout
|
||||
..................................................................*/
|
||||
if (MaxRetries != -1 && send_entry->SendCount > MaxRetries) {
|
||||
bad_conn = 1;
|
||||
}
|
||||
|
||||
if (Timeout != -1 &&
|
||||
(send_entry->LastTime - send_entry->FirstTime) > Timeout) {
|
||||
bad_conn = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
If the connection is going bad, return an error
|
||||
------------------------------------------------------------------------*/
|
||||
if (bad_conn) {
|
||||
return(0);
|
||||
}
|
||||
else {
|
||||
return(1);
|
||||
}
|
||||
|
||||
} /* end of Service_Send_Queue */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Service_Receive_Queue -- services receive queue *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = OK, 0 = error *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Service_Receive_Queue (void)
|
||||
{
|
||||
ReceiveQueueType *rec_entry; // ptr to receive entry header
|
||||
CommHeaderType *packet_hdr; // packet header
|
||||
int i;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Remove all dead packets.
|
||||
PACKET_DATA_NOACK: if it's been read, throw it away.
|
||||
PACKET_DATA_ACK: if it's been read, and its ID is older than LastSeqID,
|
||||
throw it away.
|
||||
------------------------------------------------------------------------*/
|
||||
for (i = 0; i < Queue->Num_Receive(); i++) {
|
||||
rec_entry = Queue->Get_Receive(i);
|
||||
|
||||
if (rec_entry->IsRead) {
|
||||
packet_hdr = (CommHeaderType *)(rec_entry->Buffer);
|
||||
|
||||
if (packet_hdr->Code == PACKET_DATA_NOACK) {
|
||||
Queue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);
|
||||
i--;
|
||||
|
||||
}
|
||||
else if (packet_hdr->PacketID < LastSeqID) {
|
||||
Queue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(1);
|
||||
|
||||
} /* end of Service_Receive_Queue */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Time -- gets current time *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
unsigned long ConnectionClass::Time (void)
|
||||
{
|
||||
static struct timeb mytime; // DOS time
|
||||
unsigned long msec;
|
||||
|
||||
#ifdef WWLIB32_H
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
If the Westwood timer system has been activated, use TickCount's value
|
||||
------------------------------------------------------------------------*/
|
||||
if (TimerSystemOn) {
|
||||
return(TickCount); // Westwood Library time
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
Otherwise, use the DOS timer
|
||||
------------------------------------------------------------------------*/
|
||||
else {
|
||||
ftime(&mytime);
|
||||
msec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;
|
||||
return((msec / 100) * 6);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
If the Westwood library isn't being used, use the DOS timer.
|
||||
------------------------------------------------------------------------*/
|
||||
ftime(&mytime);
|
||||
msec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;
|
||||
return((msec / 100) * 6);
|
||||
|
||||
#endif
|
||||
|
||||
} /* end of Time */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Command_Name -- returns name for given packet command *
|
||||
* *
|
||||
* INPUT: *
|
||||
* command packet Command value to get name for *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* ptr to command name, NULL if invalid *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/31/1995 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
char *ConnectionClass::Command_Name(int command)
|
||||
{
|
||||
if (command >= 0 && command < PACKET_COUNT) {
|
||||
return(Commands[command]);
|
||||
}
|
||||
else {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
} /* end of Command_Name */
|
||||
|
||||
/************************** end of connect.cpp *****************************/
|
||||
|
||||
|
833
CODE/CONNECT.CPP.BAK
Normal file
833
CODE/CONNECT.CPP.BAK
Normal file
@ -0,0 +1,833 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: F:\projects\c&c0\vcs\code\connect.cpv 4.76 03 Oct 1996 09:20:28 JOE_BOSTIC $ */
|
||||
/***************************************************************************
|
||||
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CONNECT.CPP *
|
||||
* *
|
||||
* Programmer : Bill Randolph *
|
||||
* *
|
||||
* Start Date : December 20, 1994 *
|
||||
* *
|
||||
* Last Update : May 31, 1995 [BRR] *
|
||||
*-------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* ConnectionClass::ConnectionClass -- class constructor *
|
||||
* ConnectionClass::~ConnectionClass -- class destructor *
|
||||
* ConnectionClass::Init -- Initializes connection queue to empty *
|
||||
* ConnectionClass::Send_Packet -- adds a packet to the send queue *
|
||||
* ConnectionClass::Receive_Packet -- adds packet to receive queue *
|
||||
* ConnectionClass::Get_Packet -- gets a packet from receive queue *
|
||||
* ConnectionClass::Service -- main polling routine; services packets *
|
||||
* ConnectionClass::Service_Send_Queue -- services the send queue *
|
||||
* ConnectionClass::Service_Receive_Queue -- services receive queue *
|
||||
* ConnectionClass::Time -- gets current time *
|
||||
* ConnectionClass::Command_Name -- returns name for a packet command *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "function.h"
|
||||
#include <stdio.h>
|
||||
#include <mem.h>
|
||||
#include <sys\timeb.h>
|
||||
#include "connect.h"
|
||||
|
||||
/*
|
||||
********************************* Globals ***********************************
|
||||
*/
|
||||
static char *ConnectionClass::Commands[PACKET_COUNT] = {
|
||||
"ADATA",
|
||||
"NDATA",
|
||||
"ACK"
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::ConnectionClass -- class constructor *
|
||||
* *
|
||||
* INPUT: *
|
||||
* numsend desired # of entries for the send queue *
|
||||
* numreceive desired # of entries for the receive queue *
|
||||
* maxlen max length of an application packet *
|
||||
* magicnum the packet "magic number" for this connection *
|
||||
* retry_delta the time to wait between sends *
|
||||
* max_retries the max # of retries allowed for a packet *
|
||||
* (-1 means retry forever, based on this parameter) *
|
||||
* timeout the max amount of time before we give up on a packet *
|
||||
* (-1 means retry forever, based on this parameter) *
|
||||
* extralen max size of app-specific extra bytes (optional) *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
ConnectionClass::ConnectionClass (int numsend, int numreceive,
|
||||
int maxlen, unsigned short magicnum, unsigned long retry_delta,
|
||||
unsigned long max_retries, unsigned long timeout, int extralen)
|
||||
{
|
||||
/*------------------------------------------------------------------------
|
||||
Compute our maximum packet length
|
||||
------------------------------------------------------------------------*/
|
||||
MaxPacketLen = maxlen + sizeof(CommHeaderType);
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Assign the magic number
|
||||
------------------------------------------------------------------------*/
|
||||
MagicNum = magicnum;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Initialize the retry time. This is the time that t2 - t1 must be greater
|
||||
than before a retry will occur.
|
||||
------------------------------------------------------------------------*/
|
||||
RetryDelta = retry_delta;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Set the maximum allowable retries.
|
||||
------------------------------------------------------------------------*/
|
||||
MaxRetries = max_retries;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Set the timeout for this connection.
|
||||
------------------------------------------------------------------------*/
|
||||
Timeout = timeout;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Allocate the packet staging buffer. This will be used to
|
||||
------------------------------------------------------------------------*/
|
||||
PacketBuf = new char[ MaxPacketLen ];
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Allocate the packet Queue. This will store incoming packets (placed there
|
||||
by Receive_Packet), and outgoing packets (placed there by Send_Packet).
|
||||
It can optionally store "extra" bytes, which are stored along with each
|
||||
packet, but aren't transmitted as part of the packet. If 'extralen'
|
||||
is 0, the CommBufferClass ignores this parameter.
|
||||
------------------------------------------------------------------------*/
|
||||
Queue = new CommBufferClass (numsend, numreceive, MaxPacketLen, extralen);
|
||||
|
||||
} /* end of ConnectionClass */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::~ConnectionClass -- class destructor *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
ConnectionClass::~ConnectionClass ()
|
||||
{
|
||||
/*------------------------------------------------------------------------
|
||||
Free memory.
|
||||
------------------------------------------------------------------------*/
|
||||
delete [] PacketBuf;
|
||||
delete Queue;
|
||||
|
||||
} /* end of ~ConnectionClass */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Init -- Initializes connection queue to empty *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
void ConnectionClass::Init (void)
|
||||
{
|
||||
NumRecNoAck = 0;
|
||||
NumRecAck = 0;
|
||||
NumSendNoAck = 0;
|
||||
NumSendAck = 0;
|
||||
|
||||
LastSeqID = 0xffffffff;
|
||||
LastReadID = 0xffffffff;
|
||||
|
||||
Queue->Init();
|
||||
|
||||
} /* end of Init */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Send_Packet -- adds a packet to the send queue *
|
||||
* *
|
||||
* This routine prefixes the given buffer with a CommHeaderType and *
|
||||
* queues the resulting packet into the Send Queue. (It's actually the *
|
||||
* Service() routine that handles the hardware-dependent Send of the data).*
|
||||
* The packet's MagicNumber, Code, and PacketID are set here. *
|
||||
* *
|
||||
* INPUT: *
|
||||
* buf buffer to send *
|
||||
* buflen length of buffer *
|
||||
* ack_req 1 = ACK is required for this packet; 0 = isn't *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = packet was queue'd OK, 0 = wasn't *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Send_Packet (void * buf, int buflen, int ack_req)
|
||||
{
|
||||
/*------------------------------------------------------------------------
|
||||
Set the magic # for the packet
|
||||
------------------------------------------------------------------------*/
|
||||
((CommHeaderType *)PacketBuf)->MagicNumber = MagicNum;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Set the packet Code: DATA_ACK if it requires an ACK, NOACK if it doesn't
|
||||
Set the packet ID to the appropriate counter value.
|
||||
------------------------------------------------------------------------*/
|
||||
if (ack_req) {
|
||||
((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_ACK;
|
||||
((CommHeaderType *)PacketBuf)->PacketID = NumSendAck;
|
||||
}
|
||||
else {
|
||||
((CommHeaderType *)PacketBuf)->Code = PACKET_DATA_NOACK;
|
||||
((CommHeaderType *)PacketBuf)->PacketID = NumSendNoAck;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Now build the packet
|
||||
------------------------------------------------------------------------*/
|
||||
memcpy(PacketBuf + sizeof(CommHeaderType), buf, buflen);
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Add it to the queue; don't add any extra data with it.
|
||||
------------------------------------------------------------------------*/
|
||||
if (Queue->Queue_Send(PacketBuf,buflen + sizeof(CommHeaderType), NULL, 0)) {
|
||||
if (ack_req) {
|
||||
NumSendAck++;
|
||||
}
|
||||
else {
|
||||
NumSendNoAck++;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
else {
|
||||
return(0);
|
||||
}
|
||||
|
||||
} /* end of Send_Packet */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Receive_Packet -- adds packet to receive queue *
|
||||
* *
|
||||
* INPUT: *
|
||||
* buf buffer to process (already includes CommHeaderType) *
|
||||
* buflen length of buffer to process *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = packet was processed OK, 0 = error *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Receive_Packet (void * buf, int buflen)
|
||||
{
|
||||
CommHeaderType *packet; // ptr to packet header
|
||||
SendQueueType *send_entry; // ptr to send entry header
|
||||
ReceiveQueueType *rec_entry; // ptr to recv entry header
|
||||
CommHeaderType *entry_data; // ptr to queue entry data
|
||||
CommHeaderType ackpacket; // ACK packet to send
|
||||
int i;
|
||||
int save_packet = 1; // 0 = this is a resend
|
||||
int found;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Check the magic #
|
||||
------------------------------------------------------------------------*/
|
||||
packet = (CommHeaderType *)buf;
|
||||
if (packet->MagicNumber != MagicNum) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Handle an incoming ACK
|
||||
------------------------------------------------------------------------*/
|
||||
if (packet->Code == PACKET_ACK) {
|
||||
|
||||
for (i = 0; i < Queue->Num_Send(); i++) {
|
||||
/*..................................................................
|
||||
Get queue entry ptr
|
||||
..................................................................*/
|
||||
send_entry = Queue->Get_Send(i);
|
||||
|
||||
/*..................................................................
|
||||
If ptr is valid, get ptr to its data
|
||||
..................................................................*/
|
||||
if (send_entry != NULL) {
|
||||
entry_data = (CommHeaderType *)send_entry->Buffer;
|
||||
|
||||
/*...............................................................
|
||||
If ACK is for this entry, mark it
|
||||
...............................................................*/
|
||||
if (packet->PacketID==entry_data->PacketID &&
|
||||
entry_data->Code == PACKET_DATA_ACK) {
|
||||
send_entry->IsACK = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Handle an incoming PACKET_DATA_NOACK packet
|
||||
------------------------------------------------------------------------*/
|
||||
else if (packet->Code == PACKET_DATA_NOACK) {
|
||||
/*.....................................................................
|
||||
If there's only one slot left, don't tie up the queue with this packet
|
||||
.....................................................................*/
|
||||
if (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*.....................................................................
|
||||
Error if we can't queue the packet
|
||||
.....................................................................*/
|
||||
if (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
NumRecNoAck++;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Handle an incoming PACKET_DATA_ACK packet
|
||||
------------------------------------------------------------------------*/
|
||||
else if (packet->Code == PACKET_DATA_ACK) {
|
||||
/*.....................................................................
|
||||
If this is a packet requires an ACK, and it's ID is older than our
|
||||
"oldest" ID, we know it's a resend; send an ACK, but don't queue it
|
||||
.....................................................................*/
|
||||
if (packet->PacketID <= LastSeqID && LastSeqID != 0xffffffff) {
|
||||
save_packet = 0;
|
||||
}
|
||||
|
||||
/*.....................................................................
|
||||
Otherwise, scan the queue for this entry; if it's found, it's a
|
||||
resend, so don't save it.
|
||||
.....................................................................*/
|
||||
else {
|
||||
save_packet = 1;
|
||||
for (i = 0; i < Queue->Num_Receive(); i++) {
|
||||
rec_entry = Queue->Get_Receive(i);
|
||||
|
||||
if (rec_entry) {
|
||||
|
||||
entry_data = (CommHeaderType *)rec_entry->Buffer;
|
||||
|
||||
/*...........................................................
|
||||
Packet is found; it's a resend
|
||||
...........................................................*/
|
||||
if (entry_data->Code == PACKET_DATA_ACK &&
|
||||
entry_data->PacketID == packet->PacketID) {
|
||||
save_packet = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* end of scan for resend */
|
||||
|
||||
/*.....................................................................
|
||||
Queue the packet & update our LastSeqID value.
|
||||
.....................................................................*/
|
||||
if (save_packet) {
|
||||
/*..................................................................
|
||||
If there's only one slot left, make sure we only put a packet in it
|
||||
if this packet will let us increment our LastSeqID; otherwise, we'll
|
||||
get stuck, forever unable to increment LastSeqID.
|
||||
..................................................................*/
|
||||
if (Queue->Max_Receive() - Queue->Num_Receive() <= 1) {
|
||||
if (packet->PacketID != (LastSeqID + 1) ) {
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*..................................................................
|
||||
If we can't queue the packet, return; don't send an ACK.
|
||||
..................................................................*/
|
||||
if (!Queue->Queue_Receive (buf, buflen, NULL, 0)) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
NumRecAck++;
|
||||
|
||||
/*..................................................................
|
||||
Update our LastSeqID value if we can. Anything less than LastSeqID
|
||||
we'll know is a resend.
|
||||
..................................................................*/
|
||||
if (packet->PacketID == (LastSeqID + 1)) {
|
||||
LastSeqID = packet->PacketID;
|
||||
/*...............................................................
|
||||
Now that we have a new 'LastSeqID', search our Queue to see if
|
||||
the next ID is there; if so, keep checking for the next one;
|
||||
break only when the next one isn't found. This forces
|
||||
LastSeqID to be the largest possible value.
|
||||
...............................................................*/
|
||||
do {
|
||||
found = 0;
|
||||
for (i = 0; i < Queue->Num_Receive(); i++) {
|
||||
|
||||
rec_entry = Queue->Get_Receive(i);
|
||||
|
||||
if (rec_entry) {
|
||||
entry_data = (CommHeaderType *)rec_entry->Buffer;
|
||||
|
||||
/*......................................................
|
||||
Entry is found
|
||||
......................................................*/
|
||||
if (entry_data->Code == PACKET_DATA_ACK &&
|
||||
entry_data->PacketID == (LastSeqID + 1)) {
|
||||
|
||||
LastSeqID = entry_data->PacketID;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (found);
|
||||
}
|
||||
} /* end of save packet */
|
||||
|
||||
/*.....................................................................
|
||||
Send an ACK, regardless of whether this was a resend or not.
|
||||
.....................................................................*/
|
||||
ackpacket.MagicNumber = Magic_Num();
|
||||
ackpacket.Code = PACKET_ACK;
|
||||
ackpacket.PacketID = packet->PacketID;
|
||||
Send ((char *)&ackpacket, sizeof(CommHeaderType), NULL, 0);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
||||
} /* end of Receive_Packet */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Get_Packet -- gets a packet from receive queue *
|
||||
* *
|
||||
* INPUT: *
|
||||
* buf location to store buffer *
|
||||
* buflen filled in with length of 'buf' *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = packet was read, 0 = wasn't *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Get_Packet (void * buf, int *buflen)
|
||||
{
|
||||
ReceiveQueueType *rec_entry; // ptr to receive entry header
|
||||
int packetlen; // size of received packet
|
||||
CommHeaderType *entry_data;
|
||||
int i;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Ensure that we read the packets in order. LastReadID is the ID of the
|
||||
last PACKET_DATA_ACK packet we read.
|
||||
------------------------------------------------------------------------*/
|
||||
for (i = 0; i < Queue->Num_Receive(); i++) {
|
||||
|
||||
rec_entry = Queue->Get_Receive(i);
|
||||
|
||||
/*.....................................................................
|
||||
Only read this entry if it hasn't been yet
|
||||
.....................................................................*/
|
||||
if (rec_entry && rec_entry->IsRead==0) {
|
||||
|
||||
entry_data = (CommHeaderType *)rec_entry->Buffer;
|
||||
|
||||
/*..................................................................
|
||||
If this is a DATA_ACK packet, its ID must be one greater than
|
||||
the last one we read.
|
||||
..................................................................*/
|
||||
if ( (entry_data->Code == PACKET_DATA_ACK) &&
|
||||
(entry_data->PacketID == (LastReadID + 1))) {
|
||||
|
||||
LastReadID = entry_data->PacketID;
|
||||
rec_entry->IsRead = 1;
|
||||
|
||||
packetlen = rec_entry->BufLen - sizeof(CommHeaderType);
|
||||
if (packetlen > 0) {
|
||||
memcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),
|
||||
packetlen);
|
||||
}
|
||||
(*buflen) = packetlen;
|
||||
return(1);
|
||||
}
|
||||
/*..................................................................
|
||||
If this is a DATA_NOACK packet, who cares what the ID is?
|
||||
..................................................................*/
|
||||
else if (entry_data->Code == PACKET_DATA_NOACK) {
|
||||
rec_entry->IsRead = 1;
|
||||
|
||||
packetlen = rec_entry->BufLen - sizeof(CommHeaderType);
|
||||
if (packetlen > 0) {
|
||||
memcpy(buf, rec_entry->Buffer + sizeof(CommHeaderType),
|
||||
packetlen);
|
||||
}
|
||||
(*buflen) = packetlen;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
||||
} /* end of Get_Packet */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Service -- main polling routine; services packets *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = OK, 0 = error (connection is broken!) *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Service (void)
|
||||
{
|
||||
/*------------------------------------------------------------------------
|
||||
Service the Send Queue: This [re]sends packets in the Send Queue which
|
||||
haven't been ACK'd yet, and if their retry timeout has expired, and
|
||||
updates the FirstTime, LastTime & SendCount values in the Queue entry.
|
||||
Entries that have been ACK'd should be removed.
|
||||
|
||||
Service the Receive Queue: This sends ACKs for packets that haven't
|
||||
been ACK'd yet. Entries that the app has read, and have been ACK'd,
|
||||
should be removed.
|
||||
------------------------------------------------------------------------*/
|
||||
if ( Service_Send_Queue() && Service_Receive_Queue() ) {
|
||||
return(1);
|
||||
}
|
||||
else {
|
||||
return(0);
|
||||
}
|
||||
|
||||
} /* end of Service */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Service_Send_Queue -- services the send queue *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = OK, 0 = error *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Service_Send_Queue (void)
|
||||
{
|
||||
int i;
|
||||
int num_entries;
|
||||
SendQueueType *send_entry; // ptr to send queue entry
|
||||
CommHeaderType *packet_hdr; // packet header
|
||||
unsigned long curtime; // current time
|
||||
int bad_conn = 0;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Remove any ACK'd packets from the queue
|
||||
------------------------------------------------------------------------*/
|
||||
for (i = 0; i < Queue->Num_Send(); i++) {
|
||||
/*.....................................................................
|
||||
Get this queue entry
|
||||
.....................................................................*/
|
||||
send_entry = Queue->Get_Send(i);
|
||||
|
||||
/*.....................................................................
|
||||
If ACK has been received, unqueue it
|
||||
.....................................................................*/
|
||||
if (send_entry->IsACK) {
|
||||
|
||||
/*..................................................................
|
||||
Update this queue's response time
|
||||
..................................................................*/
|
||||
packet_hdr = (CommHeaderType *)send_entry->Buffer;
|
||||
if (packet_hdr->Code == PACKET_DATA_ACK) {
|
||||
Queue->Add_Delay(Time() - send_entry->FirstTime);
|
||||
}
|
||||
|
||||
/*..................................................................
|
||||
Unqueue the packet
|
||||
..................................................................*/
|
||||
Queue->UnQueue_Send(NULL,NULL,i,NULL,NULL);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Loop through all entries in the Send queue. [Re]Send any entries that
|
||||
need it.
|
||||
------------------------------------------------------------------------*/
|
||||
num_entries = Queue->Num_Send();
|
||||
|
||||
for (i = 0; i < num_entries; i++) {
|
||||
send_entry = Queue->Get_Send(i);
|
||||
|
||||
if (send_entry->IsACK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*.....................................................................
|
||||
Only send the message if time has elapsed. (The message's Time
|
||||
fields are init'd to 0 when a message is queue'd or unqueue'd, so the
|
||||
first time through, the delta time will appear large.)
|
||||
.....................................................................*/
|
||||
curtime = Time();
|
||||
if (curtime - send_entry->LastTime > RetryDelta) {
|
||||
|
||||
/*..................................................................
|
||||
Send the message
|
||||
..................................................................*/
|
||||
Send (send_entry->Buffer, send_entry->BufLen, send_entry->ExtraBuffer,
|
||||
send_entry->ExtraLen);
|
||||
|
||||
/*..................................................................
|
||||
Fill in Time fields
|
||||
..................................................................*/
|
||||
send_entry->LastTime = curtime;
|
||||
if (send_entry->SendCount==0) {
|
||||
send_entry->FirstTime = curtime;
|
||||
|
||||
/*...............................................................
|
||||
If this is the 1st time we're sending this packet, and it doesn't
|
||||
require an ACK, mark it as ACK'd; then, the next time through,
|
||||
it will just be removed from the queue.
|
||||
...............................................................*/
|
||||
packet_hdr = (CommHeaderType *)send_entry->Buffer;
|
||||
if (packet_hdr->Code == PACKET_DATA_NOACK) {
|
||||
send_entry->IsACK = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*..................................................................
|
||||
Update SendCount
|
||||
..................................................................*/
|
||||
send_entry->SendCount++;
|
||||
|
||||
/*..................................................................
|
||||
Perform error detection, based on either MaxRetries or Timeout
|
||||
..................................................................*/
|
||||
if (MaxRetries != -1 && send_entry->SendCount > MaxRetries) {
|
||||
bad_conn = 1;
|
||||
}
|
||||
|
||||
if (Timeout != -1 &&
|
||||
(send_entry->LastTime - send_entry->FirstTime) > Timeout) {
|
||||
bad_conn = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
If the connection is going bad, return an error
|
||||
------------------------------------------------------------------------*/
|
||||
if (bad_conn) {
|
||||
return(0);
|
||||
}
|
||||
else {
|
||||
return(1);
|
||||
}
|
||||
|
||||
} /* end of Service_Send_Queue */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Service_Receive_Queue -- services receive queue *
|
||||
* *
|
||||
* INPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* 1 = OK, 0 = error *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
int ConnectionClass::Service_Receive_Queue (void)
|
||||
{
|
||||
ReceiveQueueType *rec_entry; // ptr to receive entry header
|
||||
CommHeaderType *packet_hdr; // packet header
|
||||
int i;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Remove all dead packets.
|
||||
PACKET_DATA_NOACK: if it's been read, throw it away.
|
||||
PACKET_DATA_ACK: if it's been read, and its ID is older than LastSeqID,
|
||||
throw it away.
|
||||
------------------------------------------------------------------------*/
|
||||
for (i = 0; i < Queue->Num_Receive(); i++) {
|
||||
rec_entry = Queue->Get_Receive(i);
|
||||
|
||||
if (rec_entry->IsRead) {
|
||||
packet_hdr = (CommHeaderType *)(rec_entry->Buffer);
|
||||
|
||||
if (packet_hdr->Code == PACKET_DATA_NOACK) {
|
||||
Queue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);
|
||||
i--;
|
||||
|
||||
}
|
||||
else if (packet_hdr->PacketID < LastSeqID) {
|
||||
Queue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(1);
|
||||
|
||||
} /* end of Service_Receive_Queue */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Time -- gets current time *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* none. *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/20/1994 BR : Created. *
|
||||
*=========================================================================*/
|
||||
unsigned long ConnectionClass::Time (void)
|
||||
{
|
||||
static struct timeb mytime; // DOS time
|
||||
unsigned long msec;
|
||||
|
||||
#ifdef WWLIB32_H
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
If the Westwood timer system has been activated, use TickCount's value
|
||||
------------------------------------------------------------------------*/
|
||||
if (TimerSystemOn) {
|
||||
return(TickCount); // Westwood Library time
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
Otherwise, use the DOS timer
|
||||
------------------------------------------------------------------------*/
|
||||
else {
|
||||
ftime(&mytime);
|
||||
msec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;
|
||||
return((msec / 100) * 6);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
If the Westwood library isn't being used, use the DOS timer.
|
||||
------------------------------------------------------------------------*/
|
||||
ftime(&mytime);
|
||||
msec = (unsigned long)mytime.time * 1000L + (unsigned long)mytime.millitm;
|
||||
return((msec / 100) * 6);
|
||||
|
||||
#endif
|
||||
|
||||
} /* end of Time */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* ConnectionClass::Command_Name -- returns name for given packet command *
|
||||
* *
|
||||
* INPUT: *
|
||||
* command packet Command value to get name for *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* ptr to command name, NULL if invalid *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* none. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 05/31/1995 BRR : Created. *
|
||||
*=========================================================================*/
|
||||
char *ConnectionClass::Command_Name(int command)
|
||||
{
|
||||
if (command >= 0 && command < PACKET_COUNT) {
|
||||
return(Commands[command]);
|
||||
}
|
||||
else {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
} /* end of Command_Name */
|
||||
|
||||
/************************** end of connect.cpp *****************************/
|
281
CODE/CONNECT.H
Normal file
281
CODE/CONNECT.H
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CONNECT.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***************************************************************************
|
||||
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CONNECT.H *
|
||||
* *
|
||||
* Programmer : Bill Randolph *
|
||||
* *
|
||||
* Start Date : December 19, 1994 *
|
||||
* *
|
||||
* Last Update : April 1, 1995 [BR] *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* *
|
||||
* DESCRIPTION: *
|
||||
* This class represents a single "connection" with another system. It's *
|
||||
* a pure virtual base class that acts as a framework for other classes. *
|
||||
* *
|
||||
* This class contains a CommBufferClass member, which stores received *
|
||||
* & transmitted packets. The ConnectionClass has virtual functions to *
|
||||
* handle adding packets to the queue, reading them from the queue, *
|
||||
* a Send routine for actually sending data, and a Receive_Packet function *
|
||||
* which is used to tell the connection that a new packet has come in. *
|
||||
* *
|
||||
* The virtual Service routines handle all ACK & Retry logic for *
|
||||
* communicating between this system & another. Thus, any class derived *
|
||||
* from this class may overload the basic ACK/Retry logic. *
|
||||
* *
|
||||
* THE PACKET HEADER: *
|
||||
* The Connection Classes prefix every packet sent with a header that's *
|
||||
* local to this class. The header contains a "Magic Number" which should *
|
||||
* be unique for each product, and Packet "Code", which will tell the *
|
||||
* receiving end if this is DATA, or an ACK packet, and a packet ID, which *
|
||||
* is a unique numerical ID for this packet (useful for detecting resends).*
|
||||
* The header is stored with each packet in the send & receive Queues; *
|
||||
* it's removed before it's passed back to the application, via *
|
||||
* Get_Packet() *
|
||||
* *
|
||||
* THE CONNECTION MANAGER: *
|
||||
* It is assumed that there will be a "Connection Manager" class which *
|
||||
* will handle parsing incoming packets; it will then tell the connection *
|
||||
* that new packets have come in, and the connection will process them in *
|
||||
* whatever way it needs to for its protocol (check for resends, handle *
|
||||
* ACK packets, etc). The job of the connection manager is to parse *
|
||||
* incoming packets & distribute them to the connections that need to *
|
||||
* store them (for multi-connection protocols). *
|
||||
* *
|
||||
* NOTES ON ACK/RETRY: *
|
||||
* This class provides a "non-sequenced" ACK/Retry approach to packet *
|
||||
* transmission. It sends out as many packets as are in the queue, whose *
|
||||
* resend delta times have expired; and it ACK's any packets its received *
|
||||
* who haven't been ACK'd yet. Thus, order of delivery is NOT guaranteed; *
|
||||
* but, the performance is better than a "sequenced" approach. Also, the *
|
||||
* Packet ID scheme (see below) ensures that the application will read *
|
||||
* the packets in the proper order. Thus, this class guarantees delivery *
|
||||
* and order of deliver. *
|
||||
* *
|
||||
* Each packet has a unique numerical ID; the ID is set to a count of the *
|
||||
* number of packets sent. Different count values are provided, for both *
|
||||
* DATA_ACK & DATA_NOACK packets. This ensures that the counter can be *
|
||||
* used to detect resends of DATA_ACK packets; the counters for DATA_NOACK *
|
||||
* packets aren't currently used. Other counters keep track of the *
|
||||
* last-sequentially-received packet ID (for DATA_ACK packets), so we *
|
||||
* can check for resends & missed packets, and the last-sequentially-read *
|
||||
* packet ID, so we can ensure the app reads the packets in order. *
|
||||
* *
|
||||
* If the protocol being used already guarantees delivery of packets, *
|
||||
* no ACK is required for the packets. In this case, the connection *
|
||||
* class for this protocol can overload the Service routine to avoid *
|
||||
* sending ACK packets, or the Connection Manager can just mark the *
|
||||
* packet as ACK'd when it adds it to the Receive Queue for the connection.*
|
||||
* *
|
||||
* Derived classes must provide: *
|
||||
* - Init: Initialization of any hardware-specific values. *
|
||||
* - Send: a hardware-dependent send routine. *
|
||||
* *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
#ifndef CONNECTION_H
|
||||
#define CONNECTION_H
|
||||
|
||||
/*
|
||||
********************************* Includes **********************************
|
||||
*/
|
||||
#include "combuf.h"
|
||||
|
||||
/*
|
||||
********************************** Defines **********************************
|
||||
*/
|
||||
#define CONN_DEBUG 0
|
||||
/*---------------------------------------------------------------------------
|
||||
This structure is the header prefixed to any packet sent by the application.
|
||||
MagicNumber: This is a number unique to the application; it's up to the
|
||||
Receive_Packet routine to check this value, to be sure we're
|
||||
not getting data from some other product. This value should
|
||||
be unique for each application.
|
||||
Code: This will be one of the below-defined codes.
|
||||
PacketID: This is a unique numerical ID for this packet. The Connection
|
||||
sets this ID on all packets sent out.
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
unsigned short MagicNumber;
|
||||
unsigned char Code;
|
||||
unsigned long PacketID;
|
||||
} CommHeaderType;
|
||||
|
||||
|
||||
/*
|
||||
***************************** Class Declaration *****************************
|
||||
*/
|
||||
class ConnectionClass
|
||||
{
|
||||
/*
|
||||
---------------------------- Public Interface ----------------------------
|
||||
*/
|
||||
public:
|
||||
/*.....................................................................
|
||||
These are the possible values for the Code field of the CommHeaderType:
|
||||
.....................................................................*/
|
||||
enum ConnectionEnum {
|
||||
PACKET_DATA_ACK, // this is a data packet requiring an ACK
|
||||
PACKET_DATA_NOACK, // this is a data packet not requiring an ACK
|
||||
PACKET_ACK, // this is an ACK for a packet
|
||||
PACKET_COUNT // for computational purposes
|
||||
};
|
||||
|
||||
/*.....................................................................
|
||||
Constructor/destructor.
|
||||
.....................................................................*/
|
||||
ConnectionClass (int numsend, int numrecieve, int maxlen,
|
||||
unsigned short magicnum, unsigned long retry_delta,
|
||||
unsigned long max_retries, unsigned long timeout, int extralen = 0);
|
||||
virtual ~ConnectionClass ();
|
||||
|
||||
/*.....................................................................
|
||||
Initialization.
|
||||
.....................................................................*/
|
||||
virtual void Init (void);
|
||||
|
||||
/*.....................................................................
|
||||
Send/Receive routines.
|
||||
.....................................................................*/
|
||||
virtual int Send_Packet (void * buf, int buflen, int ack_req);
|
||||
virtual int Receive_Packet (void * buf, int buflen);
|
||||
virtual int Get_Packet (void * buf, int * buflen);
|
||||
|
||||
/*.....................................................................
|
||||
The main polling routine for the connection. Should be called as often
|
||||
as possible.
|
||||
.....................................................................*/
|
||||
virtual int Service (void);
|
||||
|
||||
/*.....................................................................
|
||||
This routine is used by the retry logic; returns the current time in
|
||||
60ths of a second.
|
||||
.....................................................................*/
|
||||
static unsigned long Time (void);
|
||||
|
||||
/*.....................................................................
|
||||
Utility routines.
|
||||
.....................................................................*/
|
||||
unsigned short Magic_Num (void) { return (MagicNum); }
|
||||
unsigned long Retry_Delta (void) { return (RetryDelta); }
|
||||
void Set_Retry_Delta (unsigned long delta) { RetryDelta = delta;}
|
||||
unsigned long Max_Retries (void) { return (MaxRetries); }
|
||||
void Set_Max_Retries (unsigned long retries) { MaxRetries = retries;}
|
||||
unsigned long Time_Out (void) { return (Timeout); }
|
||||
void Set_TimeOut (unsigned long t) { Timeout = t;}
|
||||
unsigned long Max_Packet_Len (void) { return (MaxPacketLen); }
|
||||
static char * Command_Name(int command);
|
||||
|
||||
/*.....................................................................
|
||||
The packet "queue"; this non-sequenced version isn't really much of
|
||||
a queue, but more of a repository.
|
||||
.....................................................................*/
|
||||
CommBufferClass *Queue;
|
||||
|
||||
/*
|
||||
-------------------------- Protected Interface ---------------------------
|
||||
*/
|
||||
protected:
|
||||
/*.....................................................................
|
||||
Routines to service the Send & Receive queues.
|
||||
.....................................................................*/
|
||||
virtual int Service_Send_Queue(void);
|
||||
virtual int Service_Receive_Queue(void);
|
||||
|
||||
/*.....................................................................
|
||||
This routine actually performs a hardware-dependent data send. It's
|
||||
pure virtual, so it must be defined by a derived class. The routine
|
||||
is protected; it's only called by the ACK/Retry logic, not the
|
||||
application.
|
||||
.....................................................................*/
|
||||
virtual int Send(char *buf, int buflen, void *extrabuf,
|
||||
int extralen) = 0;
|
||||
|
||||
/*.....................................................................
|
||||
This is the maximum packet length, including our own internal header.
|
||||
.....................................................................*/
|
||||
int MaxPacketLen;
|
||||
|
||||
/*.....................................................................
|
||||
Packet staging area; this is where the CommHeaderType gets tacked onto
|
||||
the application's packet before it's sent.
|
||||
.....................................................................*/
|
||||
char *PacketBuf;
|
||||
|
||||
/*.....................................................................
|
||||
This is the magic number assigned to this connection. It is the first
|
||||
few bytes of any transmission.
|
||||
.....................................................................*/
|
||||
unsigned short MagicNum;
|
||||
|
||||
/*.....................................................................
|
||||
This value determines the time delay before a packet is re-sent.
|
||||
.....................................................................*/
|
||||
unsigned long RetryDelta;
|
||||
|
||||
/*.....................................................................
|
||||
This is the maximum number of retries allowed for a packet; if this
|
||||
value is exceeded, the connection is probably broken.
|
||||
.....................................................................*/
|
||||
unsigned long MaxRetries;
|
||||
|
||||
/*.....................................................................
|
||||
This is the total timeout for this connection; if this time is exceeded
|
||||
on a packet, the connection is probably broken.
|
||||
.....................................................................*/
|
||||
unsigned long Timeout;
|
||||
|
||||
/*.....................................................................
|
||||
Running totals of # of packets we send & receive which require an ACK,
|
||||
and those that don't.
|
||||
.....................................................................*/
|
||||
unsigned long NumRecNoAck;
|
||||
unsigned long NumRecAck;
|
||||
unsigned long NumSendNoAck;
|
||||
unsigned long NumSendAck;
|
||||
|
||||
/*.....................................................................
|
||||
This is the ID of the last consecutively-received packet; anything older
|
||||
than this, we know is a resend. Anything newer than this MUST be lying
|
||||
around in the Queue for us to detect it as a resend.
|
||||
.....................................................................*/
|
||||
unsigned long LastSeqID;
|
||||
|
||||
/*.....................................................................
|
||||
This is the ID of the PACKET_DATA_ACK packet we read last; it ensures
|
||||
that the application reads that type of packet in order.
|
||||
.....................................................................*/
|
||||
unsigned long LastReadID;
|
||||
|
||||
/*.....................................................................
|
||||
Names of all packet commands
|
||||
.....................................................................*/
|
||||
static char * Commands[PACKET_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**************************** end of connect.h *****************************/
|
154
CODE/CONNMGR.H
Normal file
154
CODE/CONNMGR.H
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(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: /CounterStrike/CONNMGR.H 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***************************************************************************
|
||||
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : Command & Conquer *
|
||||
* *
|
||||
* File Name : CONNMGR.H *
|
||||
* *
|
||||
* Programmer : Bill Randolph *
|
||||
* *
|
||||
* Start Date : December 19, 1994 *
|
||||
* *
|
||||
* Last Update : April 3, 1995 [BR] *
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* *
|
||||
* This is the Connection Manager base class. This is an abstract base *
|
||||
* class that's just a shell for more functional derived classes. *
|
||||
* The main job of the Connection Manager classes is to parse a "pool" of *
|
||||
* incoming packets, which may be from different computers, and distribute *
|
||||
* those packets to Connection Classes via their Receive_Packet function. *
|
||||
* *
|
||||
* This class should be the only access to the network/modem for the *
|
||||
* application, so if the app needs any functions to access the *
|
||||
* connections or the queue's, the derived versions of this class should *
|
||||
* provide them. *
|
||||
* *
|
||||
* It's up to the derived class to define: *
|
||||
* - Service: polling routine; should Service each connection *
|
||||
* - Init: initialization; should perform hardware-dependent *
|
||||
* initialization, then Init each connection; this function *
|
||||
* isn't defined in this class, since the parameters will *
|
||||
* be highly protocol-dependent) *
|
||||
* - Send_Message:sends a packet across the connection (this function *
|
||||
* isn't defined in this class, since the parameters will *
|
||||
* be highly protocol-dependent) *
|
||||
* - Get_Message: gets a message from the connection (this function *
|
||||
* isn't defined in this class, since the parameters will *
|
||||
* be highly protocol-dependent) *
|
||||
* *
|
||||
* If the derived class supports multiple connections, it should provide *
|
||||
* functions for creating the connections, associating them with a name *
|
||||
* or ID or both, destroying them, and sending data through all or any *
|
||||
* connection. *
|
||||
* *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef CONNMGR_H
|
||||
#define CONNMGR_H
|
||||
|
||||
|
||||
/*
|
||||
***************************** Class Declaration *****************************
|
||||
*/
|
||||
class ConnManClass
|
||||
{
|
||||
/*
|
||||
---------------------------- Public Interface ----------------------------
|
||||
*/
|
||||
public:
|
||||
/*.....................................................................
|
||||
Various useful enums:
|
||||
.....................................................................*/
|
||||
enum IPXConnTag {
|
||||
CONNECTION_NONE = -1 // value of an invalid connection ID
|
||||
};
|
||||
|
||||
/*.....................................................................
|
||||
Constructor/Destructor. These currently do nothing.
|
||||
.....................................................................*/
|
||||
ConnManClass (void) {};
|
||||
virtual ~ConnManClass () {};
|
||||
|
||||
/*.....................................................................
|
||||
The Service routine:
|
||||
- Parses incoming packets, and adds them to the Receive Queue for the
|
||||
Connection Class(s) for this protocol
|
||||
- Invokes each connection's Service routine; returns an error if the
|
||||
connection's Service routine indicates an error.
|
||||
.....................................................................*/
|
||||
virtual int Service (void) = 0;
|
||||
|
||||
/*.....................................................................
|
||||
Sending & receiving data
|
||||
.....................................................................*/
|
||||
virtual int Send_Private_Message (void *buf, int buflen,
|
||||
int ack_req = 1, int conn_id = CONNECTION_NONE) = 0;
|
||||
virtual int Get_Private_Message (void *buf, int *buflen,
|
||||
int *conn_id) = 0;
|
||||
|
||||
/*.....................................................................
|
||||
Connection management
|
||||
.....................................................................*/
|
||||
virtual int Num_Connections(void) = 0;
|
||||
virtual int Connection_ID(int index) = 0;
|
||||
virtual int Connection_Index(int id) = 0;
|
||||
|
||||
/*.....................................................................
|
||||
Queue utility routines
|
||||
.....................................................................*/
|
||||
virtual int Global_Num_Send(void) = 0;
|
||||
virtual int Global_Num_Receive(void) = 0;
|
||||
virtual int Private_Num_Send(int id = CONNECTION_NONE) = 0;
|
||||
virtual int Private_Num_Receive(int id = CONNECTION_NONE) = 0;
|
||||
|
||||
/*.....................................................................
|
||||
Timing management
|
||||
.....................................................................*/
|
||||
virtual void Reset_Response_Time(void) = 0;
|
||||
virtual unsigned long Response_Time(void) = 0;
|
||||
virtual void Set_Timing (unsigned long retrydelta,
|
||||
unsigned long maxretries, unsigned long timeout) = 0;
|
||||
|
||||
/*.....................................................................
|
||||
Debugging
|
||||
.....................................................................*/
|
||||
virtual void Configure_Debug(int index, int type_offset, int type_size,
|
||||
char **names, int namestart, int namecount) = 0;
|
||||
#ifdef CHEAT_KEYS
|
||||
virtual void Mono_Debug_Print(int index, int refresh) = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
--------------------------- Private Interface ----------------------------
|
||||
*/
|
||||
private:
|
||||
/*.....................................................................
|
||||
This abstract class contains no data members; but a derived class
|
||||
will contain:
|
||||
- An instance of one or more derived Connection Classes
|
||||
- A buffer to store incoming packets
|
||||
.....................................................................*/
|
||||
};
|
||||
|
||||
#endif
|
5558
CODE/CONQUER.CPP
Normal file
5558
CODE/CONQUER.CPP
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user