Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
parent
2e338c00cb
commit
3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions
597
Generals/Code/Tools/Launcher/BFISH.CPP
Normal file
597
Generals/Code/Tools/Launcher/BFISH.CPP
Normal file
|
@ -0,0 +1,597 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Blowfish Component *
|
||||
* *
|
||||
* $Archive:: /Sun/Blowfish/bfish.cpp $*
|
||||
* *
|
||||
* $Author:: Joe_b $*
|
||||
* *
|
||||
* $Modtime:: 12/02/97 9:35p $*
|
||||
* *
|
||||
* $Revision:: 6 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* 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. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#pragma warning(disable : 4514)
|
||||
#include "bfish.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
|
||||
}
|
||||
};
|
||||
|
105
Generals/Code/Tools/Launcher/BFISH.H
Normal file
105
Generals/Code/Tools/Launcher/BFISH.H
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Blowfish Component *
|
||||
* *
|
||||
* $Archive:: /Sun/Blowfish/bfish.h $*
|
||||
* *
|
||||
* $Author:: Joe_b $*
|
||||
* *
|
||||
* $Modtime:: 12/02/97 9:35p $*
|
||||
* *
|
||||
* $Revision:: 6 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef BFISH_H
|
||||
#define BFISH_H
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
/*
|
||||
** This engine will process data blocks by encryption and decryption.
|
||||
** The "Blowfish" algorithm is in the public domain. It uses
|
||||
** a Feistal network (similar to IDEA). It has no known
|
||||
** weaknesses, but is still relatively new. Blowfish is particularly strong
|
||||
** against brute force attacks. It is also quite strong against linear and
|
||||
** differential cryptanalysis. Unlike public key encription, it is very
|
||||
** fast at encryption, as far as cryptography goes. Its weakness is that
|
||||
** it takes a relatively long time to set up with a new key (1/100th of
|
||||
** a second on a P6-200). The time to set up a key is equivalent to
|
||||
** encrypting 4240 bytes.
|
||||
*/
|
||||
class BlowfishEngine {
|
||||
public:
|
||||
BlowfishEngine(void) : IsKeyed(false) {}
|
||||
~BlowfishEngine(void);
|
||||
|
||||
void Submit_Key(void const * key, int length);
|
||||
|
||||
int Encrypt(void const * plaintext, int length, void * cyphertext);
|
||||
int Decrypt(void const * cyphertext, int length, void * plaintext);
|
||||
|
||||
/*
|
||||
** This is the maximum key length supported.
|
||||
*/
|
||||
enum {MAX_KEY_LENGTH=56,
|
||||
BYTES_PER_BLOCK=8 // The number of bytes in each cypher block (don't change).
|
||||
};
|
||||
|
||||
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).
|
||||
};
|
||||
|
||||
/*
|
||||
** Initialization data for sub keys. The initial values are constant and
|
||||
** filled with a number generated from pi. Thus they are not random but
|
||||
** they don't hold a weak pattern either.
|
||||
*/
|
||||
static unsigned long const P_Init[ROUNDS+2];
|
||||
static unsigned long const S_Init[4][UCHAR_MAX+1];
|
||||
|
||||
/*
|
||||
** Permutation tables for encryption and decryption.
|
||||
*/
|
||||
unsigned long P_Encrypt[ROUNDS+2];
|
||||
unsigned long P_Decrypt[ROUNDS+2];
|
||||
|
||||
/*
|
||||
** S-Box tables (four).
|
||||
*/
|
||||
unsigned long bf_S[4][UCHAR_MAX+1];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
193
Generals/Code/Tools/Launcher/DatGen/DatGen.cpp
Normal file
193
Generals/Code/Tools/Launcher/DatGen/DatGen.cpp
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// DatGen.cpp : Defines the entry point for the application.
|
||||
//
|
||||
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "bfish.h"
|
||||
#include "SafeDisk\CdaPfn.h"
|
||||
#include <Debug\DebugPrint.h>
|
||||
|
||||
void __cdecl doIt(void);
|
||||
|
||||
CDAPFN_DECLARE_GLOBAL(doIt, CDAPFN_OVERHEAD_L5, CDAPFN_CONSTRAINT_NONE);
|
||||
|
||||
static void doIt(void)
|
||||
{
|
||||
// Generate passkey
|
||||
char passKey[128];
|
||||
passKey[0] = '\0';
|
||||
unsigned char installPath[MAX_PATH] = "";
|
||||
|
||||
// Get game information
|
||||
HKEY hKey;
|
||||
bool usesHKeycurrentUser = false;
|
||||
LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Electronic Arts\\EA Games\\Generals", 0, KEY_READ, &hKey);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Electronic Arts\\EA Games\\Generals", 0, KEY_READ, &hKey);
|
||||
usesHKeycurrentUser = true;
|
||||
}
|
||||
assert((result == ERROR_SUCCESS) && "Failed to open game registry key");
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve install path
|
||||
DWORD type;
|
||||
DWORD sizeOfBuffer = sizeof(installPath);
|
||||
result = RegQueryValueEx(hKey, "InstallPath", NULL, &type, installPath, &sizeOfBuffer);
|
||||
|
||||
assert((result == ERROR_SUCCESS) && "Failed to obtain game install path!");
|
||||
assert((strlen((const char*)installPath) > 0) && "Game install path invalid!");
|
||||
DebugPrint("Game install path: %s\n", installPath);
|
||||
|
||||
// Retrieve Hard drive S/N
|
||||
char drive[8];
|
||||
_splitpath((const char*)installPath, drive, NULL, NULL, NULL);
|
||||
strcat(drive, "\\");
|
||||
|
||||
DWORD volumeSerialNumber = 0;
|
||||
DWORD maxComponentLength;
|
||||
DWORD fileSystemFlags;
|
||||
BOOL volInfoSuccess = GetVolumeInformation((const char*)drive, NULL, 0,
|
||||
&volumeSerialNumber, &maxComponentLength, &fileSystemFlags, NULL, 0);
|
||||
|
||||
if (volInfoSuccess == FALSE)
|
||||
{
|
||||
PrintWin32Error("***** GetVolumeInformation() Failed!");
|
||||
}
|
||||
|
||||
DebugPrint("Drive Serial Number: %lx\n", volumeSerialNumber);
|
||||
|
||||
// Add hard drive serial number portion
|
||||
char volumeSN[16];
|
||||
sprintf(volumeSN, "%lx-", volumeSerialNumber);
|
||||
strcat(passKey, volumeSN);
|
||||
|
||||
// Retrieve game serial #
|
||||
unsigned char gameSerialNumber[64];
|
||||
gameSerialNumber[0] = '\0';
|
||||
sizeOfBuffer = sizeof(gameSerialNumber);
|
||||
if (usesHKeycurrentUser)
|
||||
{
|
||||
result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Electronic Arts\\EA Games\\Generals\\ergc", 0, KEY_READ, &hKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Electronic Arts\\EA Games\\Generals\\ergc", 0, KEY_READ, &hKey);
|
||||
}
|
||||
assert((result == ERROR_SUCCESS) && "Failed to open game serial registry key");
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
result = RegQueryValueEx(hKey, "", NULL, &type, gameSerialNumber, &sizeOfBuffer);
|
||||
assert((result == ERROR_SUCCESS) && "Failed to obtain game serial number!");
|
||||
assert((strlen((const char*)gameSerialNumber) > 0) && "Game serial number invalid!");
|
||||
}
|
||||
|
||||
DebugPrint("Game serial number: %s\n", gameSerialNumber);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
// Add game serial number portion
|
||||
strcat(passKey, (char*)gameSerialNumber);
|
||||
|
||||
// Obtain windows product ID
|
||||
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, &hKey);
|
||||
assert((result == ERROR_SUCCESS) && "Failed to open windows registry key!");
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
// Retrieve Windows Product ID
|
||||
unsigned char winProductID[64];
|
||||
winProductID[0] = '\0';
|
||||
|
||||
DWORD type;
|
||||
DWORD sizeOfBuffer = sizeof(winProductID);
|
||||
result = RegQueryValueEx(hKey, "ProductID", NULL, &type, winProductID, &sizeOfBuffer);
|
||||
|
||||
assert((result == ERROR_SUCCESS) && "Failed to obtain windows product ID!");
|
||||
assert((strlen((const char*)winProductID) > 0) && "Invalid windows product ID");
|
||||
|
||||
DebugPrint("Windows Product ID: %s\n", winProductID);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
// Add windows product ID portion
|
||||
strcat(passKey, "-");
|
||||
strcat(passKey, (char*)winProductID);
|
||||
}
|
||||
|
||||
DebugPrint("Retrieved PassKey: %s\n", passKey);
|
||||
|
||||
const char *plainText = "Play the \"Command & Conquer: Generals\" Multiplayer Test.";
|
||||
int textLen = strlen(plainText);
|
||||
char cypherText[128];
|
||||
|
||||
DebugPrint("Retrieved PassKey: %s\n", passKey);
|
||||
|
||||
// Decrypt protected data into the memory mapped file
|
||||
BlowfishEngine blowfish;
|
||||
int len = strlen(passKey);
|
||||
if (len > BlowfishEngine::MAX_KEY_LENGTH)
|
||||
len = BlowfishEngine::MAX_KEY_LENGTH;
|
||||
blowfish.Submit_Key(passKey, len);
|
||||
|
||||
blowfish.Encrypt(plainText, textLen, cypherText);
|
||||
cypherText[textLen] = 0;
|
||||
DebugPrint("Encrypted data: %s\n", cypherText);
|
||||
|
||||
DebugPrint("Install dir = '%s'\n", installPath);
|
||||
|
||||
char *lastBackslash = strrchr((char *)installPath, '\\');
|
||||
if (lastBackslash)
|
||||
*lastBackslash = 0; // strip of \\game.exe from install path
|
||||
|
||||
strcat((char *)installPath, "\\Generals.dat");
|
||||
|
||||
DebugPrint("DAT file = '%s'\n", installPath);
|
||||
|
||||
FILE *fp = fopen((char *)installPath, "wb");
|
||||
if (fp)
|
||||
{
|
||||
fwrite(cypherText, textLen, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
CDAPFN_ENDMARK(doIt);
|
||||
}
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine,
|
||||
int nCmdShow)
|
||||
{
|
||||
doIt();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
131
Generals/Code/Tools/Launcher/DatGen/DatGen.dsp
Normal file
131
Generals/Code/Tools/Launcher/DatGen/DatGen.dsp
Normal file
|
@ -0,0 +1,131 @@
|
|||
# Microsoft Developer Studio Project File - Name="DatGen" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||
|
||||
CFG=DatGen - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "DatGen.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "DatGen.mak" CFG="DatGen - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "DatGen - Win32 Release" (based on "Win32 (x86) Application")
|
||||
!MESSAGE "DatGen - Win32 Debug" (based on "Win32 (x86) Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "DatGen"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "DatGen - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I ".." /I "../toolkit" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /pdb:"../../../../Run/DatGen.pdb" /map:"../../../../Run/DatGen.map" /debug /machine:I386 /out:"../../../../Run/DatGen.exe"
|
||||
# SUBTRACT LINK32
|
||||
|
||||
!ELSEIF "$(CFG)" == "DatGen - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "../toolkit" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /pdb:"../../../../Run/DatGenD.pdb" /map:"../../../../Run/DatGenD.map" /debug /machine:I386 /out:"../../../../Run/DatGenD.exe"
|
||||
# SUBTRACT LINK32
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "DatGen - Win32 Release"
|
||||
# Name "DatGen - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\BFISH.CPP
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\DatGen.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Toolkit\Debug\DebugPrint.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\BFISH.H
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\SafeDisk\CdaPfn.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Toolkit\Debug\DebugPrint.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
BIN
Generals/Code/Tools/Launcher/Generals.ico
Normal file
BIN
Generals/Code/Tools/Launcher/Generals.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
336
Generals/Code/Tools/Launcher/Protect.cpp
Normal file
336
Generals/Code/Tools/Launcher/Protect.cpp
Normal file
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: /APILauncher/Protect.cpp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: Mcampbell $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: 6/21/01 5:09p $
|
||||
* $Revision: 6 $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "Protect.h"
|
||||
|
||||
#ifdef COPY_PROTECT
|
||||
|
||||
#include "BFish.h"
|
||||
#include <Support\UString.h>
|
||||
#include <Support\RefPtr.h>
|
||||
#include <Storage\File.h>
|
||||
#include <windows.h>
|
||||
#include <memory>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <Debug\DebugPrint.h>
|
||||
|
||||
#include "SafeDisk\CdaPfn.h"
|
||||
|
||||
// This GUID should be unique for each product. (CHANGE IT WHEN DOING THE
|
||||
// NEXT PRODUCT) Note that the game will need to agree on this GUID also, so
|
||||
// the game will have to be modified also.
|
||||
const char* const LAUNCHER_GUID =
|
||||
"150C6462-4E49-4ccf-B073-57579569D994"; // Generals Multiplayer Test Launcher GUID
|
||||
const char* const protectGUID =
|
||||
"6096561D-8A70-48ed-9FF8-18552419E50D"; // Generals Multiplayer Test Protect GUID
|
||||
|
||||
/*
|
||||
const char* const LAUNCHER_GUID =
|
||||
"FB327081-64F2-43d8-9B72-503C3B765134"; // Generals Launcher GUID
|
||||
const char* const protectGUID =
|
||||
"7BEB9006-CC19-4aca-913A-C870A88DE01A"; // Generals Protect GUID
|
||||
*/
|
||||
|
||||
HANDLE mLauncherMutex = NULL;
|
||||
HANDLE mMappedFile = NULL;
|
||||
|
||||
void InitializeProtect(void)
|
||||
{
|
||||
ShutdownProtect();
|
||||
|
||||
DebugPrint("Initializing protection\n");
|
||||
|
||||
mLauncherMutex = NULL;
|
||||
mMappedFile = NULL;
|
||||
|
||||
// Secure launcher mutex
|
||||
mLauncherMutex = CreateMutex(NULL, FALSE, LAUNCHER_GUID);
|
||||
|
||||
if ((mLauncherMutex == NULL) || (mLauncherMutex && (GetLastError() == ERROR_ALREADY_EXISTS)))
|
||||
{
|
||||
DebugPrint("***** Failed to create launcher mutex\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create memory mapped file to mirror protected file
|
||||
File file("Generals.dat", Rights_ReadOnly);
|
||||
|
||||
if (!file.IsAvailable())
|
||||
{
|
||||
DebugPrint("***** Unable to find Generals.dat\n");
|
||||
return;
|
||||
}
|
||||
|
||||
UInt32 fileSize = file.GetLength();
|
||||
|
||||
SECURITY_ATTRIBUTES security;
|
||||
security.nLength = sizeof(security);
|
||||
security.lpSecurityDescriptor = NULL;
|
||||
security.bInheritHandle = TRUE;
|
||||
|
||||
mMappedFile = CreateFileMapping(INVALID_HANDLE_VALUE, &security, PAGE_READWRITE, 0, fileSize, NULL);
|
||||
|
||||
if ((mMappedFile == NULL) || (mMappedFile && (GetLastError() == ERROR_ALREADY_EXISTS)))
|
||||
{
|
||||
PrintWin32Error("***** CreateFileMapping() Failed!");
|
||||
CloseHandle(mMappedFile);
|
||||
mMappedFile = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CDAPFN_DECLARE_GLOBAL(SendProtectMessage, CDAPFN_OVERHEAD_L5, CDAPFN_CONSTRAINT_NONE);
|
||||
|
||||
void SendProtectMessage(HANDLE process, DWORD threadID)
|
||||
{
|
||||
// Decrypt protected file contents to mapping file
|
||||
File file("Generals.dat", Rights_ReadOnly);
|
||||
|
||||
if (!file.IsAvailable())
|
||||
{
|
||||
DebugPrint("***** Unable to find Generals.dat\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Map file to programs address space
|
||||
LPVOID mapAddress = MapViewOfFileEx(mMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
|
||||
|
||||
if (mapAddress == NULL)
|
||||
{
|
||||
PrintWin32Error("***** MapViewOfFileEx() Failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
void* buffer = NULL;
|
||||
UInt32 bufferSize = 0;
|
||||
file.Load(buffer, bufferSize);
|
||||
|
||||
if (buffer && (bufferSize > 0))
|
||||
{
|
||||
DebugPrint("Generating PassKey\n");
|
||||
|
||||
// Generate passkey
|
||||
char passKey[128];
|
||||
passKey[0] = '\0';
|
||||
|
||||
// Get game information
|
||||
HKEY hKey;
|
||||
bool usesHKeycurrentUser = false;
|
||||
LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Electronic Arts\\EA Games\\Generals", 0, KEY_READ, &hKey);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Electronic Arts\\EA Games\\Generals", 0, KEY_READ, &hKey);
|
||||
usesHKeycurrentUser = true;
|
||||
}
|
||||
assert((result == ERROR_SUCCESS) && "Failed to open game registry key");
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
// Retrieve install path
|
||||
unsigned char installPath[MAX_PATH];
|
||||
DWORD type;
|
||||
DWORD sizeOfBuffer = sizeof(installPath);
|
||||
result = RegQueryValueEx(hKey, "InstallPath", NULL, &type, installPath, &sizeOfBuffer);
|
||||
|
||||
assert((result == ERROR_SUCCESS) && "Failed to obtain game install path!");
|
||||
assert((strlen((const char*)installPath) > 0) && "Game install path invalid!");
|
||||
DebugPrint("Game install path: %s\n", installPath);
|
||||
|
||||
// Retrieve Hard drive S/N
|
||||
char drive[8];
|
||||
_splitpath((const char*)installPath, drive, NULL, NULL, NULL);
|
||||
strcat(drive, "\\");
|
||||
|
||||
DWORD volumeSerialNumber = 0;
|
||||
DWORD maxComponentLength;
|
||||
DWORD fileSystemFlags;
|
||||
BOOL volInfoSuccess = GetVolumeInformation((const char*)drive, NULL, 0,
|
||||
&volumeSerialNumber, &maxComponentLength, &fileSystemFlags, NULL, 0);
|
||||
|
||||
if (volInfoSuccess == FALSE)
|
||||
{
|
||||
PrintWin32Error("***** GetVolumeInformation() Failed!");
|
||||
}
|
||||
|
||||
DebugPrint("Drive Serial Number: %lx\n", volumeSerialNumber);
|
||||
|
||||
// Add hard drive serial number portion
|
||||
char volumeSN[16];
|
||||
sprintf(volumeSN, "%lx-", volumeSerialNumber);
|
||||
strcat(passKey, volumeSN);
|
||||
|
||||
// Retrieve game serial #
|
||||
unsigned char gameSerialNumber[64];
|
||||
gameSerialNumber[0] = '\0';
|
||||
sizeOfBuffer = sizeof(gameSerialNumber);
|
||||
if (usesHKeycurrentUser)
|
||||
{
|
||||
result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Electronic Arts\\EA Games\\Generals\\ergc", 0, KEY_READ, &hKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Electronic Arts\\EA Games\\Generals\\ergc", 0, KEY_READ, &hKey);
|
||||
}
|
||||
assert((result == ERROR_SUCCESS) && "Failed to open game serial registry key");
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
result = RegQueryValueEx(hKey, "", NULL, &type, gameSerialNumber, &sizeOfBuffer);
|
||||
assert((result == ERROR_SUCCESS) && "Failed to obtain game serial number!");
|
||||
assert((strlen((const char*)gameSerialNumber) > 0) && "Game serial number invalid!");
|
||||
}
|
||||
|
||||
DebugPrint("Game serial number: %s\n", gameSerialNumber);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
// Add game serial number portion
|
||||
strcat(passKey, (char*)gameSerialNumber);
|
||||
}
|
||||
|
||||
// Obtain windows product ID
|
||||
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, &hKey);
|
||||
assert((result == ERROR_SUCCESS) && "Failed to open windows registry key!");
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
// Retrieve Windows Product ID
|
||||
unsigned char winProductID[64];
|
||||
winProductID[0] = '\0';
|
||||
|
||||
DWORD type;
|
||||
DWORD sizeOfBuffer = sizeof(winProductID);
|
||||
result = RegQueryValueEx(hKey, "ProductID", NULL, &type, winProductID, &sizeOfBuffer);
|
||||
|
||||
assert((result == ERROR_SUCCESS) && "Failed to obtain windows product ID!");
|
||||
assert((strlen((const char*)winProductID) > 0) && "Invalid windows product ID");
|
||||
|
||||
DebugPrint("Windows Product ID: %s\n", winProductID);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
// Add windows product ID portion
|
||||
strcat(passKey, "-");
|
||||
strcat(passKey, (char*)winProductID);
|
||||
}
|
||||
|
||||
DebugPrint("Retrieved PassKey: %s\n", passKey);
|
||||
|
||||
// Decrypt protected data into the memory mapped file
|
||||
BlowfishEngine blowfish;
|
||||
int len = strlen(passKey);
|
||||
if (len > BlowfishEngine::MAX_KEY_LENGTH)
|
||||
len = BlowfishEngine::MAX_KEY_LENGTH;
|
||||
blowfish.Submit_Key(passKey, len);
|
||||
blowfish.Decrypt(buffer, bufferSize, mapAddress);
|
||||
|
||||
DebugPrint("Decrypted data: %s\n", mapAddress);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
UnmapViewOfFile(mapAddress);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Send protection message
|
||||
//---------------------------------------------------------------------------
|
||||
DebugPrint("Sending protect message\n");
|
||||
|
||||
DebugPrint("Creating running notification event.\n");
|
||||
HANDLE event = CreateEvent(NULL, FALSE, FALSE, protectGUID);
|
||||
|
||||
if ((event == NULL) || (event && (GetLastError() == ERROR_ALREADY_EXISTS)))
|
||||
{
|
||||
PrintWin32Error("***** CreateEvent() Failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
DebugPrint("Waiting for game (timeout in %.02f seconds)...\n", ((float)((5 * 60) * 1000) * 0.001));
|
||||
|
||||
#ifdef _DEBUG
|
||||
unsigned long start = timeGetTime();
|
||||
#endif
|
||||
|
||||
HANDLE handles[2];
|
||||
handles[0] = event;
|
||||
handles[1] = process;
|
||||
DWORD waitResult = WaitForMultipleObjects(2, &handles[0], FALSE, ((5 * 60) * 1000));
|
||||
|
||||
#ifdef _DEBUG
|
||||
unsigned long stop = timeGetTime();
|
||||
#endif
|
||||
|
||||
DebugPrint("WaitResult = %ld (WAIT_OBJECT_0 = %ld)\n", waitResult, WAIT_OBJECT_0);
|
||||
|
||||
if (waitResult == WAIT_OBJECT_0)
|
||||
{
|
||||
if (mMappedFile != NULL)
|
||||
{
|
||||
DebugPrint("Sending game the beef. (%lx)\n", mMappedFile);
|
||||
BOOL sent = PostThreadMessage(threadID, 0xBEEF, 0, (LPARAM)mMappedFile);
|
||||
assert(sent == TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugPrint("***** Timeout!\n");
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
DebugPrint("Waited %.02f seconds\n", ((float)(stop - start) * 0.001));
|
||||
#endif
|
||||
|
||||
CloseHandle(event);
|
||||
CDAPFN_ENDMARK(SendProtectMessage);
|
||||
}
|
||||
|
||||
|
||||
void ShutdownProtect(void)
|
||||
{
|
||||
if (mMappedFile)
|
||||
{
|
||||
CloseHandle(mMappedFile);
|
||||
mMappedFile = NULL;
|
||||
}
|
||||
|
||||
if (mLauncherMutex)
|
||||
{
|
||||
CloseHandle(mLauncherMutex);
|
||||
mLauncherMutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // COPY_PROTECT
|
89
Generals/Code/Tools/Launcher/Protect.h
Normal file
89
Generals/Code/Tools/Launcher/Protect.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: /APILauncher/Protect.h $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Copy protection
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: Mcampbell $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: 6/18/01 8:24p $
|
||||
* $Revision: 4 $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __PROTECT_H__
|
||||
#define __PROTECT_H__
|
||||
|
||||
#ifdef COPY_PROTECT
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
//#define OLDWAY
|
||||
|
||||
#ifdef OLDWAY
|
||||
template<typename T> class RefPtr;
|
||||
class UString;
|
||||
|
||||
|
||||
class Protect
|
||||
{
|
||||
public:
|
||||
Protect();
|
||||
~Protect();
|
||||
|
||||
void SendMappedFileHandle(HANDLE process, DWORD threadID) const;
|
||||
|
||||
private:
|
||||
// Prevent copy & assignment
|
||||
Protect(const Protect&);
|
||||
const Protect& operator=(const Protect&);
|
||||
|
||||
// Retrieve machine unique key
|
||||
RefPtr<UString> GetPassKey(void) const;
|
||||
|
||||
HANDLE mLauncherMutex;
|
||||
HANDLE mMappedFile;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void __cdecl InitializeProtect(void);
|
||||
void __cdecl ShutdownProtect(void);
|
||||
void __cdecl SendProtectMessage(HANDLE process, DWORD threadID);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // COPY_PROTECT
|
||||
|
||||
#endif // PROTECT_H
|
4
Generals/Code/Tools/Launcher/SafeDisk/.gitignore
vendored
Normal file
4
Generals/Code/Tools/Launcher/SafeDisk/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
185
Generals/Code/Tools/Launcher/Toolkit/Debug/DebugPrint.cpp
Normal file
185
Generals/Code/Tools/Launcher/Toolkit/Debug/DebugPrint.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Debug printing mechanism
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
#include "DebugPrint.h"
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
char debugLogName[_MAX_PATH];
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* DebugPrint(String, ArgList...)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Ouput debug print messages to the debugger and log file.
|
||||
*
|
||||
* INPUTS
|
||||
* String - String to output.
|
||||
* ArgList - Argument list
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void __cdecl DebugPrint(const char* string, ...)
|
||||
{
|
||||
static char _buffer[1024];
|
||||
static char _filename[512] = "";
|
||||
|
||||
if (string != NULL)
|
||||
{
|
||||
// Format string
|
||||
va_list va;
|
||||
va_start(va, string);
|
||||
vsprintf(&_buffer[0], string, va);
|
||||
va_end(va);
|
||||
|
||||
// Open log file
|
||||
HANDLE file = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (strlen(_filename) == 0)
|
||||
{
|
||||
char path[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
|
||||
GetModuleFileName(GetModuleHandle(NULL), &path[0], sizeof(path));
|
||||
_splitpath(path, drive, dir, NULL, NULL);
|
||||
_makepath(_filename, drive, dir, debugLogName, "txt");
|
||||
|
||||
OutputDebugString("Creating ");
|
||||
OutputDebugString(_filename);
|
||||
OutputDebugString("\n");
|
||||
|
||||
file = CreateFile(_filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = CreateFile(_filename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
}
|
||||
|
||||
// Send string to debugger
|
||||
OutputDebugString(_buffer);
|
||||
|
||||
// Insert carriage return after newlines
|
||||
int i = 0;
|
||||
|
||||
while (_buffer[i] != '\0')
|
||||
{
|
||||
if (_buffer[i] == '\n')
|
||||
{
|
||||
int end = strlen(_buffer);
|
||||
assert((end + 1) <= sizeof(_buffer));
|
||||
|
||||
while (end >= i)
|
||||
{
|
||||
_buffer[end + 1] = _buffer[end];
|
||||
end--;
|
||||
}
|
||||
|
||||
_buffer[i] = '\r';
|
||||
i++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Send string to log file
|
||||
assert(file != INVALID_HANDLE_VALUE);
|
||||
|
||||
if (file != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SetFilePointer(file, 0, NULL, FILE_END);
|
||||
|
||||
DWORD written;
|
||||
WriteFile(file, &_buffer[0], strlen(_buffer), &written, NULL);
|
||||
|
||||
CloseHandle(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* PrintWin32Error
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Display Win32 error message (Error retrieved from GetLastError())
|
||||
*
|
||||
* INPUTS
|
||||
* Message string
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void __cdecl PrintWin32Error(const char* string, ...)
|
||||
{
|
||||
static char _buffer[1024];
|
||||
|
||||
if (string != NULL)
|
||||
{
|
||||
// Format string
|
||||
va_list va;
|
||||
va_start(va, string);
|
||||
vsprintf(&_buffer[0], string, va);
|
||||
va_end(va);
|
||||
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
|
||||
|
||||
DebugPrint("***** Win32 Error: %s\n", _buffer);
|
||||
DebugPrint(" Reason: %s\n", (char*)lpMsgBuf);
|
||||
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _DEBUG
|
65
Generals/Code/Tools/Launcher/Toolkit/Debug/DebugPrint.h
Normal file
65
Generals/Code/Tools/Launcher/Toolkit/Debug/DebugPrint.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Debug printing mechanism
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _DEBUGPRINT_H_
|
||||
#define _DEBUGPRINT_H_
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
//! Ouput debug print messages to the debugger and log file.
|
||||
void __cdecl DebugPrint(const char* string, ...);
|
||||
void __cdecl PrintWin32Error(const char* string, ...);
|
||||
|
||||
extern char debugLogName[];
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else // _DEBUG
|
||||
|
||||
#define DebugPrint
|
||||
#define PrintWin32Error
|
||||
|
||||
#endif // _DEBUG
|
||||
|
||||
#endif // _DEBUGPRINT_H_
|
1109
Generals/Code/Tools/Launcher/Toolkit/Storage/File.cpp
Normal file
1109
Generals/Code/Tools/Launcher/Toolkit/Storage/File.cpp
Normal file
File diff suppressed because it is too large
Load diff
153
Generals/Code/Tools/Launcher/Toolkit/Storage/File.h
Normal file
153
Generals/Code/Tools/Launcher/Toolkit/Storage/File.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* File definitions (Windows)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef FILE_H
|
||||
#define FILE_H
|
||||
|
||||
#include <Support\UTypes.h>
|
||||
#include "Stream.h"
|
||||
#include "Rights.h"
|
||||
#include <Support\UString.h>
|
||||
#include <windows.h>
|
||||
|
||||
class File : public Stream
|
||||
{
|
||||
public:
|
||||
// File Error conditions
|
||||
typedef enum
|
||||
{
|
||||
FileError_None = 0,
|
||||
FileError_FNF,
|
||||
FileError_Access,
|
||||
FileError_Open,
|
||||
FileError_Read,
|
||||
FileError_Write,
|
||||
FileError_Seek,
|
||||
FileError_Nomem,
|
||||
FileError_Fault,
|
||||
} EFileError;
|
||||
|
||||
//! Default constructor - Create an unassociated File
|
||||
File();
|
||||
|
||||
//! Name constructor - Create a File with an associated name
|
||||
File(const Char* name, ERights rights = Rights_ReadOnly);
|
||||
File(const UString& name, ERights rights = Rights_ReadOnly);
|
||||
|
||||
//! Destructor
|
||||
virtual ~File();
|
||||
|
||||
//! Retrieve name of file
|
||||
const UString& GetName(void) const;
|
||||
|
||||
//! Associate a name to the file
|
||||
virtual void SetName(const UString& name);
|
||||
|
||||
//! Retrieve file access rights
|
||||
virtual ERights GetRights(void) const;
|
||||
|
||||
//! Set file access rights
|
||||
virtual void SetRights(ERights rights);
|
||||
|
||||
//! Check if the file is available
|
||||
virtual bool IsAvailable(bool force = false);
|
||||
|
||||
//! Check if te file is open
|
||||
virtual bool IsOpen(void) const;
|
||||
|
||||
//! Open the file for access.
|
||||
virtual EFileError Open(ERights rights);
|
||||
|
||||
//! Open the file with the associated name for access
|
||||
virtual EFileError Open(const UString& name, ERights rights);
|
||||
|
||||
//! Close the file
|
||||
virtual void Close(void);
|
||||
|
||||
//! Create a new file
|
||||
virtual EFileError Create(void);
|
||||
|
||||
//! Delete an existing file
|
||||
virtual EFileError Delete(void);
|
||||
|
||||
//! Load the file into memory
|
||||
virtual EFileError Load(void*& outBuffer, UInt32& outSize);
|
||||
|
||||
//! Write file data
|
||||
virtual EFileError Save(const void* buffer, UInt32 size);
|
||||
|
||||
//! Error handling hook
|
||||
virtual bool OnFileError(EFileError error, bool canRetry);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// STREAM INTERFACE
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//! Get the length of the file
|
||||
virtual UInt32 GetLength(void);
|
||||
|
||||
//! Set the length of the file
|
||||
virtual void SetLength(UInt32 length);
|
||||
|
||||
//! Get file position marker
|
||||
virtual UInt32 GetMarker(void);
|
||||
|
||||
//! Set file position marker
|
||||
virtual void SetMarker(Int32 offset, EStreamFrom from);
|
||||
|
||||
//! End of file test
|
||||
virtual bool AtEnd(void);
|
||||
|
||||
//! Read bytes from the file
|
||||
virtual UInt32 GetBytes(void* ptr, UInt32 bytes);
|
||||
|
||||
//! Write bytes to the file
|
||||
virtual UInt32 PutBytes(const void* ptr, UInt32 bytes);
|
||||
|
||||
//! Read bytes from the file without marker adjustment
|
||||
virtual UInt32 PeekBytes(void* ptr, UInt32 bytes);
|
||||
|
||||
//! Flush the stream
|
||||
virtual void Flush(void);
|
||||
|
||||
private:
|
||||
UString mName;
|
||||
ERights mRights;
|
||||
HANDLE mHandle;
|
||||
static const HANDLE INVALID_HANDLE;
|
||||
};
|
||||
|
||||
#endif // FILE_H
|
48
Generals/Code/Tools/Launcher/Toolkit/Storage/Rights.h
Normal file
48
Generals/Code/Tools/Launcher/Toolkit/Storage/Rights.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Access privilege definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef RIGHTS_H
|
||||
#define RIGHTS_H
|
||||
|
||||
// Access rights
|
||||
typedef enum
|
||||
{
|
||||
Rights_ReadOnly = 0,
|
||||
Rights_WriteOnly,
|
||||
Rights_ReadWrite,
|
||||
} ERights;
|
||||
|
||||
#endif // RIGHTS_H
|
81
Generals/Code/Tools/Launcher/Toolkit/Storage/Stream.h
Normal file
81
Generals/Code/Tools/Launcher/Toolkit/Storage/Stream.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Base class for data streaming functionality
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef STREAM_H
|
||||
#define STREAM_H
|
||||
|
||||
#include <Support\UTypes.h>
|
||||
|
||||
class Stream
|
||||
{
|
||||
public:
|
||||
// Stream marker positioning
|
||||
typedef enum
|
||||
{
|
||||
FromStart = 0,
|
||||
FromMarker,
|
||||
FromEnd,
|
||||
} EStreamFrom;
|
||||
|
||||
//! Get the length of the stream
|
||||
virtual UInt32 GetLength(void) = 0;
|
||||
|
||||
//! Set the length of the stream
|
||||
virtual void SetLength(UInt32 length) = 0;
|
||||
|
||||
//! Get current position of stream marker
|
||||
virtual UInt32 GetMarker(void) = 0;
|
||||
|
||||
//! Set position of stream marker
|
||||
virtual void SetMarker(Int32 offset, EStreamFrom from) = 0;
|
||||
|
||||
//! End of stream test
|
||||
virtual bool AtEnd(void) = 0;
|
||||
|
||||
//! Retrieve a sequence of bytes.
|
||||
virtual UInt32 GetBytes(void* ptr, UInt32 bytes) = 0;
|
||||
|
||||
//! Write a sequence of bytes
|
||||
virtual UInt32 PutBytes(const void* ptr, UInt32 bytes) = 0;
|
||||
|
||||
//! Retrieve a sequence of bytes without advancing marker.
|
||||
virtual UInt32 PeekBytes(void* ptr, UInt32 bytes) = 0;
|
||||
|
||||
//! Flush the stream
|
||||
virtual void Flush(void) = 0;
|
||||
};
|
||||
|
||||
#endif // STREAM_H
|
86
Generals/Code/Tools/Launcher/Toolkit/Support/RefCounted.h
Normal file
86
Generals/Code/Tools/Launcher/Toolkit/Support/RefCounted.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Base class for reference counted classes.
|
||||
* Use with the reference counting smart pointer RefPtr<Type>
|
||||
*
|
||||
* Release() is virtual. This helps support cached object and singletons
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Steven Clinard
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef REFCOUNTED_H
|
||||
#define REFCOUNTED_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
class RefCounted
|
||||
{
|
||||
protected:
|
||||
RefCounted()
|
||||
: mRefCount(0)
|
||||
{}
|
||||
|
||||
RefCounted(const RefCounted&)
|
||||
: mRefCount(0)
|
||||
{}
|
||||
|
||||
inline const RefCounted& operator=(const RefCounted&)
|
||||
{}
|
||||
|
||||
virtual ~RefCounted()
|
||||
{assert(mRefCount == 0);}
|
||||
|
||||
// Should not be allowed by default
|
||||
inline virtual bool operator==(const RefCounted&) const
|
||||
{return false;}
|
||||
|
||||
inline bool operator!=(const RefCounted&) const
|
||||
{return false;}
|
||||
|
||||
// Add reference
|
||||
inline void AddReference(void)
|
||||
{++mRefCount;}
|
||||
|
||||
// Release reference
|
||||
inline virtual void Release(void)
|
||||
{if (--mRefCount == 0) delete this;}
|
||||
|
||||
inline int ReferenceCount(void) const
|
||||
{return mRefCount;}
|
||||
|
||||
private:
|
||||
friend class RefPtrBase;
|
||||
|
||||
unsigned int mRefCount;
|
||||
};
|
||||
|
||||
#endif // REFCOUNTED_H
|
361
Generals/Code/Tools/Launcher/Toolkit/Support/RefPtr.h
Normal file
361
Generals/Code/Tools/Launcher/Toolkit/Support/RefPtr.h
Normal file
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* RefPtr<> and RefPtrConst<> are const-friendly, polymorphic reference
|
||||
* counting smart pointers.
|
||||
*
|
||||
* The pointed-to class must be derived from RefCount.
|
||||
*
|
||||
* RefPtr<X> replaces X*
|
||||
* RefPtrConst<X> replaces const X*
|
||||
*
|
||||
* Dynamic_Cast<X> replaces dynamic_cast<X*> and dynamic_cast<X&>
|
||||
* Reinterpret_Cast<X> replaces reinterpret_cast<X*> and reinterpret_cast<X&>
|
||||
* Const_Cast<X> replaces const_cast<X*> and const_cast<X&>
|
||||
*
|
||||
* IsValid() replaces (x != NULL)
|
||||
*
|
||||
* Member function Attach() or assigning RefPtr<X>() will NULL a pointer.
|
||||
*
|
||||
* Generally, RefPtr<> and RefPtrConst<> behave like their raw pointer
|
||||
* counterparts, except of course they are reference counted and will delete
|
||||
* the pointed-to object when the last reference is lost. The major
|
||||
* syntatical differences are the use of RefPtrConst<> to represent a pointer
|
||||
* to a constant object (I found it impossible to represent this within rc_ptr)
|
||||
* and the use of the upper-case cast functions (it is not possible to overload
|
||||
* these built-in functions).
|
||||
*
|
||||
* An explicit goal of this class is to completely avoid the "new" and "delete"
|
||||
* operators in client code. The constructors for these pointers are private;
|
||||
* they are friends of the pointed-to class. This forces the use of Factory
|
||||
* Method functions (or similar) in the pointed-to class. Pointed-to classes
|
||||
* should make the constructor protected or private to disallow clients from
|
||||
* creating an instance with "new". If this is done, it becomes very difficult
|
||||
* for the client to accidentally leak objects and/or misuse the pointed-to
|
||||
* class or the reference counting pointers.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Steven Clinard
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef REFPTR_H
|
||||
#define REFPTR_H
|
||||
|
||||
#include "VisualC.h"
|
||||
#include "RefCounted.h"
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
template<typename Type> class RefPtr;
|
||||
template<typename Type> class RefPtrConst;
|
||||
|
||||
class RefPtrBase
|
||||
{
|
||||
public:
|
||||
inline bool operator==(const RefPtrBase& rhs) const
|
||||
{return (mRefObject == rhs.mRefObject);}
|
||||
|
||||
inline bool operator!=(const RefPtrBase& rhs) const
|
||||
{return !operator==(rhs);}
|
||||
|
||||
inline bool IsValid(void) const
|
||||
{return (mRefObject != NULL);}
|
||||
|
||||
inline void Detach(void)
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
mRefObject->Release();
|
||||
mRefObject = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
RefPtrBase()
|
||||
: mRefObject(NULL)
|
||||
{}
|
||||
|
||||
RefPtrBase(RefCounted* object)
|
||||
: mRefObject(object)
|
||||
{
|
||||
assert((mRefObject == NULL) || (mRefObject->mRefCount == 0));
|
||||
|
||||
if (IsValid())
|
||||
{
|
||||
mRefObject->AddReference();
|
||||
}
|
||||
}
|
||||
|
||||
RefPtrBase(const RefPtrBase& object)
|
||||
: mRefObject(object.mRefObject)
|
||||
{
|
||||
assert(false); // why is this being called?
|
||||
|
||||
if (IsValid())
|
||||
{
|
||||
mRefObject->AddReference();
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~RefPtrBase()
|
||||
{Detach();}
|
||||
|
||||
const RefPtrBase& operator=(const RefPtrBase&);
|
||||
|
||||
inline RefCounted* const GetRefObject(void)
|
||||
{return mRefObject;}
|
||||
|
||||
inline const RefCounted* const GetRefObject(void) const
|
||||
{return mRefObject;}
|
||||
|
||||
inline void Attach(RefCounted* object)
|
||||
{
|
||||
// If objects are different
|
||||
if (object != mRefObject)
|
||||
{
|
||||
// Add reference to new object
|
||||
if (object != NULL)
|
||||
{
|
||||
object->AddReference();
|
||||
}
|
||||
|
||||
// Release reference to old object
|
||||
Detach();
|
||||
|
||||
// Assign new object
|
||||
mRefObject = object;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RefCounted* mRefObject;
|
||||
|
||||
template<typename Derived>
|
||||
friend RefPtr<Derived> Dynamic_Cast(RefPtrBase&);
|
||||
|
||||
template<typename Type>
|
||||
friend RefPtr<Type> Reinterpret_Cast(RefPtrBase&);
|
||||
};
|
||||
|
||||
|
||||
template<typename Type> class RefPtr
|
||||
: public RefPtrBase
|
||||
{
|
||||
public:
|
||||
RefPtr()
|
||||
: RefPtrBase()
|
||||
{}
|
||||
|
||||
template<typename Derived>
|
||||
RefPtr(const RefPtr<Derived>& derived)
|
||||
: RefPtrBase()
|
||||
{
|
||||
Attach(const_cast<Derived*>(derived.ReferencedObject()));
|
||||
}
|
||||
|
||||
RefPtr(const RefPtr<Type>& object)
|
||||
: RefPtrBase()
|
||||
{
|
||||
Attach(const_cast<Type*>(object.ReferencedObject()));
|
||||
}
|
||||
|
||||
virtual ~RefPtr()
|
||||
{}
|
||||
|
||||
template<typename Derived>
|
||||
inline const RefPtr<Type>& operator=(const RefPtr<Derived>& derived)
|
||||
{
|
||||
Attach(const_cast<Derived*>(derived.ReferencedObject()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const RefPtr<Type>& operator=(const RefPtr<Type>& object)
|
||||
{
|
||||
Attach(const_cast<Type*>(object.ReferencedObject()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Type& operator*() const
|
||||
{
|
||||
assert(IsValid());
|
||||
return *const_cast<Type*>(ReferencedObject());
|
||||
}
|
||||
|
||||
inline Type* const operator->() const
|
||||
{
|
||||
assert(IsValid());
|
||||
return const_cast<Type*>(ReferencedObject());
|
||||
}
|
||||
|
||||
// These are public mostly because I can't seem to declare rc_ptr<Other> as a friend
|
||||
inline Type* const ReferencedObject(void)
|
||||
{return reinterpret_cast<Type*>(GetRefObject());}
|
||||
|
||||
inline const Type* const ReferencedObject(void) const
|
||||
{return reinterpret_cast<const Type*>(GetRefObject());}
|
||||
|
||||
RefPtr(Type* object)
|
||||
: RefPtrBase()
|
||||
{
|
||||
Attach(object);
|
||||
}
|
||||
|
||||
inline const RefPtr<Type>& operator=(Type* object)
|
||||
{
|
||||
Attach(object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
friend RefPtr<Type> Dynamic_Cast(RefPtrBase&);
|
||||
friend RefPtr<Type> Reinterpret_Cast(RefPtrBase&);
|
||||
friend RefPtr<Type> Const_Cast(RefPtrConst<Type>&);
|
||||
};
|
||||
|
||||
|
||||
template<typename Type> class RefPtrConst
|
||||
: public RefPtrBase
|
||||
{
|
||||
public:
|
||||
RefPtrConst()
|
||||
: RefPtrConst()
|
||||
{}
|
||||
|
||||
template<typename Derived>
|
||||
RefPtrConst(const RefPtr<Derived>& derived)
|
||||
: RefPtrBase()
|
||||
{
|
||||
Attach(derived.ReferencedObject());
|
||||
}
|
||||
|
||||
RefPtrConst(const RefPtr<Type>& object)
|
||||
: RefPtrBase()
|
||||
{
|
||||
Attach(const_cast<Type* const >(object.ReferencedObject()));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
RefPtrConst(const RefPtrConst<Derived>& derived)
|
||||
: RefPtrBase()
|
||||
{
|
||||
Attach(derived.ReferencedObject());
|
||||
}
|
||||
|
||||
RefPtrConst(const RefPtrConst<Type>& object)
|
||||
: RefPtrBase()
|
||||
{
|
||||
Attach(object.ReferencedObject());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline const RefPtrConst<Type>& operator=(const RefPtr<Derived>& derived)
|
||||
{
|
||||
Attach(derived.ReferencedObject());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const RefPtrConst<Type>& operator=(const RefPtr<Type>& object)
|
||||
{
|
||||
Attach(object.ReferencedObject());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline const RefPtrConst<Type>& operator=(const RefPtrConst<Derived>& derived)
|
||||
{
|
||||
Attach(derived.ReferencedObject());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const RefPtrConst<Type>& operator=(const RefPtrConst<Type>& object)
|
||||
{
|
||||
Attach(object.ReferencedObject());
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~RefPtrConst()
|
||||
{}
|
||||
|
||||
inline const Type& operator*() const
|
||||
{
|
||||
assert(IsValid());
|
||||
return *ReferencedObject();
|
||||
}
|
||||
|
||||
inline const Type* const operator->() const
|
||||
{
|
||||
assert(IsValid());
|
||||
return ReferencedObject();
|
||||
}
|
||||
|
||||
// This is public mostly because I can't seem to declare rc_ptr<Other> as a friend
|
||||
inline const Type* const ReferencedObject() const
|
||||
{return reinterpret_cast<const Type*>(GetRefObject());}
|
||||
|
||||
RefPtrConst(const Type* object)
|
||||
: RefPtrBase()
|
||||
{
|
||||
Attach(object);
|
||||
}
|
||||
|
||||
const RefPtrConst<Type>& operator=(const Type* object)
|
||||
{
|
||||
Attach(object);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Derived>
|
||||
RefPtr<Derived> Dynamic_Cast(RefPtrBase& base)
|
||||
{
|
||||
RefPtr<Derived> derived;
|
||||
derived.Attach(base.GetRefObject());
|
||||
return derived;
|
||||
}
|
||||
|
||||
|
||||
template<typename Type>
|
||||
RefPtr<Type> Reinterpret_Cast(RefPtrBase& rhs)
|
||||
{
|
||||
RefPtr<Type> object;
|
||||
object.Attach(rhs.GetRefObject());
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
template<typename Type>
|
||||
RefPtr<Type> Const_Cast(RefPtrConst<Type>& rhs)
|
||||
{
|
||||
RefPtr<Type> object;
|
||||
object.Attach(rhs.ReferencedObject());
|
||||
return object;
|
||||
}
|
||||
|
||||
#endif // RC_PTR_H
|
107
Generals/Code/Tools/Launcher/Toolkit/Support/StringConvert.cpp
Normal file
107
Generals/Code/Tools/Launcher/Toolkit/Support/StringConvert.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Perform ANSI <-> Unicode string conversions
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "StringConvert.h"
|
||||
#include "UString.h"
|
||||
#include <windows.h>
|
||||
#include <Debug\DebugPrint.h>
|
||||
#include <assert.h>
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* UStringToANSI
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Convert UString to an ANSI string
|
||||
*
|
||||
* INPUTS
|
||||
* String - String to convert
|
||||
* Buffer - Pointer to buffer to receive conversion.
|
||||
* BufferLength - Length of buffer
|
||||
*
|
||||
* RESULT
|
||||
* ANSI - Pointer to ANSI string
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
Char* UStringToANSI(const UString& string, Char* buffer, UInt bufferLength)
|
||||
{
|
||||
return UnicodeToANSI(string.Get(), buffer, bufferLength);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* UnicodeToANSI
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Convert Unicode string to an ANSI string
|
||||
*
|
||||
* INPUTS
|
||||
* String - Unicode string to convert
|
||||
* Buffer - Pointer to buffer to receive conversion.
|
||||
* BufferLength - Length of buffer
|
||||
*
|
||||
* RESULT
|
||||
* ANSI - Pointer to ANSI string
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
Char* UnicodeToANSI(const WChar* string, Char* buffer, UInt bufferLength)
|
||||
{
|
||||
if ((string == NULL) || (buffer == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
int result =
|
||||
#endif
|
||||
WideCharToMultiByte(CP_ACP, 0, string, -1, buffer, bufferLength,
|
||||
NULL, NULL);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (result == 0)
|
||||
{
|
||||
PrintWin32Error("ConvertToANSI() Failed");
|
||||
assert(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
return buffer;
|
||||
}
|
47
Generals/Code/Tools/Launcher/Toolkit/Support/StringConvert.h
Normal file
47
Generals/Code/Tools/Launcher/Toolkit/Support/StringConvert.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* ANSI <-> Unicode string conversions
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef STRINGCONVERT_H
|
||||
#define STRINGCONVERT_H
|
||||
|
||||
#include "UTypes.h"
|
||||
|
||||
class UString;
|
||||
|
||||
Char* UStringToANSI(const UString& string, Char* buffer, UInt bufferLength);
|
||||
Char* UnicodeToANSI(const WChar* string, Char* buffer, UInt bufferLength);
|
||||
|
||||
#endif // STRINGCONVERT_H
|
1335
Generals/Code/Tools/Launcher/Toolkit/Support/UString.cpp
Normal file
1335
Generals/Code/Tools/Launcher/Toolkit/Support/UString.cpp
Normal file
File diff suppressed because it is too large
Load diff
239
Generals/Code/Tools/Launcher/Toolkit/Support/UString.h
Normal file
239
Generals/Code/Tools/Launcher/Toolkit/Support/UString.h
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* String management class (Unicode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef USTRING_H
|
||||
#define USTRING_H
|
||||
|
||||
#include "UTypes.h"
|
||||
#include "RefCounted.h"
|
||||
|
||||
class UString
|
||||
: public RefCounted
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
UString();
|
||||
UString(UInt capacity);
|
||||
UString(const Char* s);
|
||||
UString(const WChar* ws);
|
||||
UString(const UString& s);
|
||||
virtual ~UString();
|
||||
|
||||
//! Get the length of the string
|
||||
UInt Length(void) const;
|
||||
|
||||
//! Copy string
|
||||
void Copy(const Char* s);
|
||||
void Copy(const WChar* ws);
|
||||
void Copy(const UString& s);
|
||||
|
||||
//! Concatenate string
|
||||
void Concat(const Char* s);
|
||||
void Concat(const WChar* ws);
|
||||
void Concat(const UString& s);
|
||||
|
||||
//! Compare strings
|
||||
Int Compare(const Char* s) const;
|
||||
Int Compare(const WChar* s) const;
|
||||
Int Compare(const UString& s) const;
|
||||
|
||||
//! Compare strings not case-sensitive
|
||||
Int CompareNoCase(const Char* s) const;
|
||||
Int CompareNoCase(const WChar* ws) const;
|
||||
Int CompareNoCase(const UString& s) const;
|
||||
|
||||
//! Find the first occurance of character
|
||||
Int Find(Char c) const;
|
||||
Int Find(WChar wc) const;
|
||||
|
||||
//! Find the last occurance of a character
|
||||
Int FindLast(Char c) const;
|
||||
Int FindLast(WChar c) const;
|
||||
|
||||
//! Find a substring
|
||||
UString SubString(const Char* s);
|
||||
UString SubString(const WChar* ws);
|
||||
UString SubString(const UString& s);
|
||||
|
||||
//! Extract left part of the string
|
||||
UString Left(UInt count);
|
||||
|
||||
//! Extract middle part of the string.
|
||||
UString Middle(UInt first, UInt count);
|
||||
|
||||
//! Extract right part of the string.
|
||||
UString Right(UInt count);
|
||||
|
||||
//! Convert string to uppercase
|
||||
void ToUpper(void);
|
||||
|
||||
//! Convert string to lowercase
|
||||
void ToLower(void);
|
||||
|
||||
//! Reverse characters of string
|
||||
void Reverse(void);
|
||||
|
||||
//! Remove leading and trailing characters from string.
|
||||
// Returns true if any characters removed
|
||||
bool Trim(const Char* trimChars);
|
||||
bool Trim(const WChar* trimChars);
|
||||
bool Trim(const UString& trimChars);
|
||||
|
||||
//! Remove characters from left side of string
|
||||
// Returns true if any characters removed
|
||||
bool TrimLeft(const Char* trimChars);
|
||||
bool TrimLeft(const WChar* trimChars);
|
||||
bool TrimLeft(const UString& trimChars);
|
||||
|
||||
//! Remove characters from right side of string
|
||||
// Returns true if any characters removed
|
||||
bool TrimRight(const Char* trimChars);
|
||||
bool TrimRight(const WChar* trimChars);
|
||||
bool TrimRight(const UString& trimChars);
|
||||
|
||||
// Convert string to ANSI
|
||||
void ConvertToANSI(Char* buffer, UInt bufferLength) const;
|
||||
|
||||
//! Get the size (in bytes) of the string.
|
||||
UInt Size(void) const;
|
||||
|
||||
//! Get the maximum number of characters this string can hold.
|
||||
UInt Capacity(void) const;
|
||||
|
||||
//! Resize the string
|
||||
bool Resize(UInt size);
|
||||
|
||||
const WChar* Get(void) const
|
||||
{return (mData != NULL) ? mData : L"";}
|
||||
|
||||
//! Assignment operator
|
||||
UString operator=(const Char* s)
|
||||
{Copy(s); return *this;};
|
||||
|
||||
UString operator=(const WChar* ws)
|
||||
{Copy(ws); return *this;};
|
||||
|
||||
UString operator=(const UString& s)
|
||||
{Copy(s); return *this;};
|
||||
|
||||
//! Addition operator (concatenate)
|
||||
UString operator+(const Char* s)
|
||||
{UString ns(*this); ns += s; return ns;}
|
||||
|
||||
UString operator+(const WChar* ws)
|
||||
{UString ns(*this); ns += ws; return ns;}
|
||||
|
||||
UString operator+(const UString& s)
|
||||
{UString ns(*this); ns += s; return ns;}
|
||||
|
||||
UString operator+=(const Char* s)
|
||||
{Concat(s); return *this;}
|
||||
|
||||
UString operator+=(const WChar* ws)
|
||||
{Concat(ws); return *this;}
|
||||
|
||||
UString operator+=(const UString& s)
|
||||
{Concat(s); return *this;}
|
||||
|
||||
//! Equal operator (case sensitive compare)
|
||||
bool operator==(const Char* s)
|
||||
{return (Compare(s) == 0);}
|
||||
|
||||
bool operator==(const WChar* ws)
|
||||
{return (Compare(ws) == 0);}
|
||||
|
||||
bool operator==(const UString& s)
|
||||
{return (Compare(s) == 0);}
|
||||
|
||||
bool operator!=(const Char* s)
|
||||
{return (Compare(s) != 0);}
|
||||
|
||||
bool operator!=(const WChar* ws)
|
||||
{return (Compare(ws) != 0);}
|
||||
|
||||
bool operator!=(const UString& s)
|
||||
{return (Compare(s) != 0);}
|
||||
|
||||
//! Less than operator (case sensitive compare)
|
||||
bool operator<(const Char* s)
|
||||
{return (Compare(s) == -1);}
|
||||
|
||||
bool operator<(const WChar* ws)
|
||||
{return (Compare(ws) == -1);}
|
||||
|
||||
bool operator<(const UString& s)
|
||||
{return (Compare(s) == -1);}
|
||||
|
||||
bool operator<=(const Char* s)
|
||||
{return (Compare(s) <= 0);}
|
||||
|
||||
bool operator<=(const WChar* ws)
|
||||
{return (Compare(ws) <= 0);}
|
||||
|
||||
bool operator<=(const UString& s)
|
||||
{return (Compare(s) <= 0);}
|
||||
|
||||
//! Greater than operator (case sensitive compare)
|
||||
bool operator>(const Char* s)
|
||||
{return (Compare(s) == 1);}
|
||||
|
||||
bool operator>(const WChar* ws)
|
||||
{return (Compare(ws) == 1);}
|
||||
|
||||
bool operator>(const UString& s)
|
||||
{return (Compare(s) == 1);}
|
||||
|
||||
bool operator>=(const Char* s)
|
||||
{return (Compare(s) >= 0);}
|
||||
|
||||
bool operator>=(const WChar* ws)
|
||||
{return (Compare(ws) >= 0);}
|
||||
|
||||
bool operator>=(const UString& s)
|
||||
{return (Compare(s) >= 0);}
|
||||
|
||||
// Conversion operator
|
||||
operator const WChar*() const
|
||||
{return Get();}
|
||||
|
||||
private:
|
||||
bool AllocString(UInt size);
|
||||
|
||||
WChar* mData;
|
||||
UInt mCapacity;
|
||||
};
|
||||
|
||||
#endif // USTRING_H
|
90
Generals/Code/Tools/Launcher/Toolkit/Support/UTypes.h
Normal file
90
Generals/Code/Tools/Launcher/Toolkit/Support/UTypes.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Generic user type definitions
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef UTYPES_H
|
||||
#define UTYPES_H
|
||||
|
||||
//! Signed integer value
|
||||
typedef int Int;
|
||||
|
||||
//! Unsigned integer value
|
||||
typedef unsigned int UInt;
|
||||
|
||||
//! Signed 8bit value (-127 - 128)
|
||||
typedef char Int8;
|
||||
|
||||
//! Unsigned 8bit value (0 - 255)
|
||||
typedef unsigned char UInt8;
|
||||
|
||||
//! Signed 16bit value (-32767 - 32768)
|
||||
typedef short Int16;
|
||||
|
||||
//! Unsigned 16bit value (0 - 65535)
|
||||
typedef unsigned short UInt16;
|
||||
|
||||
//! Signed 32bit value
|
||||
typedef long Int32;
|
||||
|
||||
//! Unsigned 32bit value
|
||||
typedef unsigned long UInt32;
|
||||
|
||||
//! Signed character (ASCII)
|
||||
typedef char Char;
|
||||
|
||||
//! Unsigned character (ANSI)
|
||||
typedef unsigned char UChar;
|
||||
|
||||
//! Wide character (Unicode)
|
||||
typedef unsigned short WChar;
|
||||
|
||||
//! 32bit floating point value
|
||||
typedef float Float32;
|
||||
|
||||
//! 64bit floating point value
|
||||
typedef double Float64;
|
||||
|
||||
//! Floating point value
|
||||
typedef Float32 Float;
|
||||
|
||||
//! TriState
|
||||
typedef enum {OFF = false, ON = true, PENDING = -1} TriState;
|
||||
|
||||
//! Empty pointer
|
||||
#ifndef NULL
|
||||
#define NULL (0L)
|
||||
#endif
|
||||
|
||||
#endif // UTYPES_H
|
90
Generals/Code/Tools/Launcher/Toolkit/Support/Visualc.h
Normal file
90
Generals/Code/Tools/Launcher/Toolkit/Support/Visualc.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FILE
|
||||
* $Archive: $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Disable specific warnings generated by Microsoft Visual C++ 6.0
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* $Author: $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Modtime: $
|
||||
* $Revision: $
|
||||
*
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#ifndef _VISUALC_H_
|
||||
#define _VISUALC_H_
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
// "unreferenced inline function has been removed"
|
||||
// Inline functions are used in headers and this warning will appear everywhere
|
||||
// without explicitly being disabled.
|
||||
#pragma warning(disable:4514)
|
||||
|
||||
// "conversion from 'double' to 'float', possible loss of data"
|
||||
// This occurs during non-constant floating point arithmetic. Since all floating
|
||||
// point math is silently upcasted to doubles, it should silently downcast
|
||||
// back to 'float' when complete -- hence this warning should not be displayed.
|
||||
#pragma warning(disable:4244)
|
||||
|
||||
// "overflow in floating-point constant arithmetic"
|
||||
// This warning occurs even when there is no overflow. It occurs when a double
|
||||
// is downcasted to a float during constant arithmetic (this is not worthy of
|
||||
// a warning message).
|
||||
#pragma warning(disable:4056)
|
||||
|
||||
// "argument trunation from const double to float"
|
||||
// This warning is of little use since the compiler uses doubles whenever
|
||||
// possible, therfore this warning will appear frequently. It is similar to
|
||||
// warning 4244 and is similarly irrelevant.
|
||||
#pragma warning(disable:4305)
|
||||
|
||||
// "'this' used in base member initializer list"
|
||||
// Using "this" in a base member initializer is valid -- no need for this warning.
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
// "typedef-name used as a synonym for class-name"
|
||||
// This is by design and should not be a warning.
|
||||
#pragma warning(disable:4097)
|
||||
|
||||
// "function not inlined"
|
||||
// This warning is typically useless. The inline keyword only serves as a
|
||||
// suggestion to the compiler and it may or may not inline a function on a
|
||||
// case by case basis. No need to be told of this.
|
||||
#pragma warning(disable:4710)
|
||||
|
||||
// "function selected for automatic inline expansion"
|
||||
// There is no need to announce this with a warning message.
|
||||
#pragma warning(disable:4711)
|
||||
|
||||
// "identifier was truncated to 'number' characters in the debug information"
|
||||
// The debugger cannot debug code with symbols longer than 255 characters.
|
||||
// In the debugger, you cannot view, evaluate, update, or watch the truncated symbols.
|
||||
#pragma warning(disable:4786)
|
||||
|
||||
#endif // _MSC_VER
|
||||
#endif // _VISUALC_H_
|
165
Generals/Code/Tools/Launcher/configfile.cpp
Normal file
165
Generals/Code/Tools/Launcher/configfile.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************\
|
||||
* C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *
|
||||
******************************************************************************
|
||||
Project Name: Carpenter (The RedAlert ladder creator)
|
||||
File Name : configfile.cpp
|
||||
Author : Neal Kettler
|
||||
Start Date : June 9, 1997
|
||||
Last Update : June 17, 1997
|
||||
|
||||
|
||||
This class will read in a config file and store the key value pairs for
|
||||
later access. This is a fairly simple class, the config file is assumed
|
||||
to be of the form:
|
||||
|
||||
#comment
|
||||
key = value
|
||||
|
||||
The value can then be retrieved as a string or an integer. The key on
|
||||
the left is used for retrieval and it must be specified in uppercase
|
||||
for the 'get' functions. E.g. getString("KEY",valWstring);
|
||||
\***************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "configfile.h"
|
||||
|
||||
static uint32 Wstring_Hash(Wstring &string);
|
||||
static char *Eat_Spaces(char *string);
|
||||
|
||||
ConfigFile::ConfigFile() : dictionary(Wstring_Hash)
|
||||
{ }
|
||||
|
||||
ConfigFile::~ConfigFile()
|
||||
{ }
|
||||
|
||||
// Read and parse the config file. The key value pairs will be stored
|
||||
// for later access by the getString/getInt functions.
|
||||
bit8 ConfigFile::readFile(FILE *in)
|
||||
{
|
||||
char string[256];
|
||||
Wstring key;
|
||||
Wstring value;
|
||||
char *cptr;
|
||||
|
||||
memset(string,0,256);
|
||||
while (fgets(string,256,in))
|
||||
{
|
||||
cptr=Eat_Spaces(string);
|
||||
if ((*cptr==0)||(*cptr=='#')) // '#' signals a comment
|
||||
continue;
|
||||
if (strchr(cptr,'=')==NULL) // All config entries must have a '='
|
||||
continue;
|
||||
key=cptr;
|
||||
key.truncate('=');
|
||||
key.removeSpaces(); // No spaces allowed in the key
|
||||
key.toUpper(); // make key all caps
|
||||
cptr=Eat_Spaces(strchr(cptr,'=')+1); // Jump to after the '='
|
||||
value=cptr;
|
||||
value.truncate('\r');
|
||||
value.truncate('\n');
|
||||
dictionary.add(key,value);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// Get a config entry as a string
|
||||
bit8 ConfigFile::getString(Wstring &key,Wstring &value)
|
||||
{
|
||||
return(dictionary.getValue(key,value));
|
||||
}
|
||||
|
||||
// Get a config entry as a string
|
||||
bit8 ConfigFile::getString(char *key,Wstring &value)
|
||||
{
|
||||
Wstring sKey;
|
||||
sKey.set(key);
|
||||
return(getString(sKey,value));
|
||||
}
|
||||
|
||||
// Get a config entry as an integer
|
||||
bit8 ConfigFile::getInt(Wstring &key,sint32 &value)
|
||||
{
|
||||
Wstring svalue;
|
||||
bit8 retval=dictionary.getValue(key,svalue);
|
||||
if (retval==FALSE)
|
||||
return(FALSE);
|
||||
value=atol(svalue.get());
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// Get a config entry as an integer
|
||||
bit8 ConfigFile::getInt(char *key,sint32 &value)
|
||||
{
|
||||
Wstring sKey;
|
||||
sKey.set(key);
|
||||
return(getInt(sKey,value));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Get a config entry as an integer
|
||||
bit8 ConfigFile::getInt(Wstring &key,sint16 &value)
|
||||
{
|
||||
Wstring svalue;
|
||||
bit8 retval=dictionary.getValue(key,svalue);
|
||||
if (retval==FALSE)
|
||||
return(FALSE);
|
||||
value=atoi(svalue.get());
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// Get a config entry as an integer
|
||||
bit8 ConfigFile::getInt(char *key,sint16 &value)
|
||||
{
|
||||
Wstring sKey;
|
||||
sKey.set(key);
|
||||
return(getInt(sKey,value));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************* Static functions below **************/
|
||||
|
||||
// Given a Wstring, return a 32 bit integer that has a good numeric
|
||||
// distributation for the purposes of indexing into a hash table.
|
||||
static uint32 Wstring_Hash(Wstring &string)
|
||||
{
|
||||
uint32 retval=0;
|
||||
retval=string.length();
|
||||
for (uint32 i=0; i<string.length(); i++)
|
||||
{
|
||||
retval+=*(string.get()+i);
|
||||
retval+=i;
|
||||
retval=(retval<<8)^(retval>>24); // ROL 8
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
static char *Eat_Spaces(char *string)
|
||||
{
|
||||
char *retval=string;
|
||||
while (isspace(*retval))
|
||||
retval++;
|
||||
return(retval);
|
||||
}
|
55
Generals/Code/Tools/Launcher/configfile.h
Normal file
55
Generals/Code/Tools/Launcher/configfile.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************\
|
||||
* C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *
|
||||
******************************************************************************
|
||||
Project Name: Carpenter (The RedAlert ladder creator)
|
||||
File Name : configfile.h
|
||||
Author : Neal Kettler
|
||||
Start Date : June 9, 1997
|
||||
Last Update : June 17, 1997
|
||||
\***************************************************************************/
|
||||
|
||||
#ifndef CONFIGFILE_HEADER
|
||||
#define CONFIGFILE_HEADER
|
||||
|
||||
#include "dictionary.h"
|
||||
#include "wstring.h"
|
||||
|
||||
class ConfigFile
|
||||
{
|
||||
public:
|
||||
ConfigFile();
|
||||
~ConfigFile();
|
||||
bit8 readFile(IN FILE *config);
|
||||
bit8 getString(IN Wstring &key,OUT Wstring &value);
|
||||
bit8 getString(IN char *key,OUT Wstring &value);
|
||||
|
||||
bit8 getInt(IN Wstring &key,OUT sint32 &value);
|
||||
bit8 getInt(IN char *key,OUT sint32 &value);
|
||||
|
||||
bit8 getInt(IN Wstring &key,OUT sint16 &value);
|
||||
bit8 getInt(IN char *key,OUT sint16 &value);
|
||||
|
||||
private:
|
||||
Dictionary<Wstring,Wstring> dictionary; // stores the mappings from keys
|
||||
// to value strings
|
||||
};
|
||||
|
||||
#endif
|
80
Generals/Code/Tools/Launcher/dialog.cpp
Normal file
80
Generals/Code/Tools/Launcher/dialog.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//
|
||||
// Create the dialog used during the patching process.
|
||||
//
|
||||
#include"winblows.h"
|
||||
#include"resource.h"
|
||||
#include"loadbmp.h"
|
||||
#include<commctrl.h>
|
||||
|
||||
HWND PatchDialog;
|
||||
BOOL CALLBACK Patch_Window_Proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
HWND Create_Patch_Dialog(void)
|
||||
{
|
||||
PatchDialog=CreateDialog(Global_instance, MAKEINTRESOURCE(IDD_PATCHPROGRESS),
|
||||
NULL, (DLGPROC)Patch_Window_Proc);
|
||||
|
||||
ShowWindow(PatchDialog, SW_NORMAL);
|
||||
SetForegroundWindow(PatchDialog);
|
||||
return(PatchDialog);
|
||||
}
|
||||
|
||||
BOOL CALLBACK Patch_Window_Proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
||||
static LoadBmp bmpLoader;
|
||||
|
||||
switch(iMsg) {
|
||||
case WM_INITDIALOG:
|
||||
// progress bar
|
||||
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS2),PBM_SETRANGE,
|
||||
0,MAKELPARAM(0,100));
|
||||
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS2),PBM_SETPOS,0,0);
|
||||
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS2),PBM_SETSTEP,10,0);
|
||||
|
||||
bmpLoader.init("launcher.bmp",GetDlgItem(hwnd,IDC_SPLASH));
|
||||
return(TRUE); // True means windows handles focus issues
|
||||
break;
|
||||
case WM_PAINT:
|
||||
bmpLoader.drawBmp();
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
/* May want to add cancel later
|
||||
switch(wParam) {
|
||||
case IDCANCEL:
|
||||
{
|
||||
// do some stuff
|
||||
return(TRUE);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*************/
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
DestroyWindow(hwnd);
|
||||
PostQuitMessage(0);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
28
Generals/Code/Tools/Launcher/dialog.h
Normal file
28
Generals/Code/Tools/Launcher/dialog.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_HEADER
|
||||
#define DIALOG_HEADER
|
||||
|
||||
#include"winblows.h"
|
||||
#include<commctrl.h>
|
||||
HWND Create_Patch_Dialog(void);
|
||||
|
||||
extern HWND PatchDialog;
|
||||
|
||||
#endif
|
586
Generals/Code/Tools/Launcher/dictionary.h
Normal file
586
Generals/Code/Tools/Launcher/dictionary.h
Normal file
|
@ -0,0 +1,586 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************\
|
||||
* C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *
|
||||
******************************************************************************
|
||||
Project Name: Carpenter (The RedAlert ladder creator)
|
||||
File Name : dictionary.h
|
||||
Author : Neal Kettler
|
||||
Start Date : June 1, 1997
|
||||
Last Update : June 17, 1997
|
||||
|
||||
This template file implements a hash dictionary. A hash dictionary is
|
||||
used to quickly match a value with a key. This works well for very
|
||||
large sets of data. A table is constructed that has some power of two
|
||||
number of pointers in it. Any value to be put in the table has a hashing
|
||||
function applied to the key. That key/value pair is then put in the
|
||||
linked list at the slot the hashing function specifies. If everything
|
||||
is working well, this is much faster than a linked list, but only if
|
||||
your hashing function is good.
|
||||
\****************************************************************************/
|
||||
|
||||
#ifndef DICTIONARY_HEADER
|
||||
#define DICTIONARY_HEADER
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "wstypes.h"
|
||||
#include "wdebug.h"
|
||||
|
||||
// Every entry in the hash dictionary must be an instance of the DNode
|
||||
// template. 'K' and 'V' denote Key and Value.
|
||||
template <class K,class V>
|
||||
class DNode
|
||||
{
|
||||
public:
|
||||
K key;
|
||||
V value;
|
||||
DNode<K,V> *hashNext;
|
||||
};
|
||||
|
||||
template <class K,class V>
|
||||
class Dictionary
|
||||
{
|
||||
public:
|
||||
Dictionary(uint32 (* hashFn)(K &key));
|
||||
~Dictionary();
|
||||
|
||||
void clear(void);
|
||||
bit8 add(IN K &key,IN V &value);
|
||||
bit8 getValue(IN K &key, OUT V &value);
|
||||
void print(IN FILE *out) const;
|
||||
uint32 getSize(void) const;
|
||||
uint32 getEntries(void) const;
|
||||
bit8 contains(IN K &key);
|
||||
bit8 updateValue(IN K &key,IN V &value);
|
||||
bit8 remove(IN K &key,OUT V &value);
|
||||
bit8 remove(IN K &key);
|
||||
bit8 removeAny(OUT K &key,OUT V &value);
|
||||
bit8 iterate(INOUT int &index,INOUT int &offset, OUT V &value) const;
|
||||
|
||||
private:
|
||||
void shrink(void); // halve the number of slots
|
||||
void expand(void); // double the number of slots
|
||||
|
||||
|
||||
DNode<K,V> **table; // This stores the lists at each slot
|
||||
|
||||
uint32 entries; // number of entries
|
||||
uint32 size; // size of table
|
||||
uint32 tableBits; // table is 2^tableBits big
|
||||
uint32 log2Size; // Junk variable
|
||||
bit8 keepSize; // If true don't shrink or expand
|
||||
|
||||
uint32 (* hashFunc)(K &key); // User provided hash function
|
||||
uint32 keyHash(IN K &key); // This will reduce to correct range
|
||||
|
||||
|
||||
// See initilizer list of constructor for values
|
||||
const double SHRINK_THRESHOLD; // When table is this % full shrink it
|
||||
const double EXPAND_THRESHOLD; // When table is this % full grow it
|
||||
const int MIN_TABLE_SIZE; // must be a power of 2
|
||||
};
|
||||
|
||||
|
||||
//Create the empty hash dictionary
|
||||
template <class K,class V>
|
||||
Dictionary<K,V>::Dictionary(uint32 (* hashFn)(K &key)) :
|
||||
SHRINK_THRESHOLD(0.20), // When table is only 20% full shrink it
|
||||
EXPAND_THRESHOLD(0.80), // When table is 80% full grow it
|
||||
MIN_TABLE_SIZE(32) // must be a power of 2
|
||||
{
|
||||
log2Size=MIN_TABLE_SIZE;
|
||||
size=MIN_TABLE_SIZE;
|
||||
assert(size>=4);
|
||||
tableBits=0;
|
||||
while(log2Size) { tableBits++; log2Size>>=1; }
|
||||
tableBits--;
|
||||
size=1<<tableBits; //Just in case MIN_TABLE_SIZE wasn't a power of 2
|
||||
entries=0;
|
||||
keepSize=FALSE;
|
||||
|
||||
//Table is a pointer to a list of pointers (the hash table)
|
||||
table=(DNode<K,V> **)new DNode<K,V>* [size];
|
||||
assert(table!=NULL);
|
||||
|
||||
memset((void *)table,0,size*sizeof(void *));
|
||||
hashFunc=hashFn;
|
||||
}
|
||||
|
||||
//Free all the memory...
|
||||
template <class K,class V>
|
||||
Dictionary<K,V>::~Dictionary()
|
||||
{
|
||||
clear(); // Remove the entries
|
||||
delete[](table); // And the table as well
|
||||
}
|
||||
|
||||
// Remove all the entries and free the memory
|
||||
template <class K,class V>
|
||||
void Dictionary<K,V>::clear()
|
||||
{
|
||||
DNode<K,V> *temp,*del;
|
||||
uint32 i;
|
||||
//free all the data
|
||||
for (i=0; i<size; i++)
|
||||
{
|
||||
temp=table[i];
|
||||
while(temp!=NULL)
|
||||
{
|
||||
del=temp;
|
||||
temp=temp->hashNext;
|
||||
delete(del);
|
||||
}
|
||||
table[i]=NULL;
|
||||
}
|
||||
entries=0;
|
||||
|
||||
while ((getSize()>(uint32)MIN_TABLE_SIZE)&&(keepSize==FALSE))
|
||||
shrink();
|
||||
}
|
||||
|
||||
template <class K,class V>
|
||||
uint32 Dictionary<K,V>::keyHash(IN K &key)
|
||||
{
|
||||
uint32 retval=hashFunc(key);
|
||||
retval &= ((1<<tableBits)-1);
|
||||
assert(retval<getSize());
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
template <class K,class V>
|
||||
void Dictionary<K,V>::print(IN FILE *out) const
|
||||
{
|
||||
DNode<K,V> *temp;
|
||||
uint32 i;
|
||||
|
||||
fprintf(out,"--------------------\n");
|
||||
for (i=0; i<getSize(); i++)
|
||||
{
|
||||
temp=table[i];
|
||||
|
||||
fprintf(out," |\n");
|
||||
fprintf(out,"[ ]");
|
||||
|
||||
while (temp!=NULL)
|
||||
{
|
||||
fprintf(out,"--[ ]");
|
||||
temp=temp->hashNext;
|
||||
}
|
||||
fprintf(out,"\n");
|
||||
}
|
||||
fprintf(out,"--------------------\n");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Iterate through all the records. Index is for the table, offset specifies the
|
||||
// element in the linked list. Set both to 0 and continue calling till false
|
||||
// is returned.
|
||||
template <class K,class V>
|
||||
bit8 Dictionary<K,V>::iterate(INOUT int &index,INOUT int &offset,
|
||||
OUT V &value) const
|
||||
{
|
||||
DNode<K,V> *temp;
|
||||
|
||||
// index out of range
|
||||
if ((index<0)||(index >= getSize()))
|
||||
return(FALSE);
|
||||
|
||||
temp=table[index];
|
||||
while ((temp==NULL)&&((++index) < getSize()))
|
||||
{
|
||||
temp=table[index];
|
||||
offset=0;
|
||||
}
|
||||
|
||||
if (temp==NULL) // no more slots with data
|
||||
return(FALSE);
|
||||
|
||||
uint32 i=0;
|
||||
while ((temp!=NULL) && (i < offset))
|
||||
{
|
||||
temp=temp->hashNext;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (temp==NULL) // should never happen
|
||||
return(FALSE);
|
||||
|
||||
value=temp->value;
|
||||
if (temp->hashNext==NULL)
|
||||
{
|
||||
index++;
|
||||
offset=0;
|
||||
}
|
||||
else
|
||||
offset++;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Return the current size of the hash table
|
||||
template <class K,class V>
|
||||
uint32 Dictionary<K,V>::getSize(void) const
|
||||
{ return(size); }
|
||||
|
||||
|
||||
// Return the current number of entries in the table
|
||||
template <class K,class V>
|
||||
uint32 Dictionary<K,V>::getEntries(void) const
|
||||
{ return(entries); }
|
||||
|
||||
|
||||
// Does the Dictionary contain the key?
|
||||
template <class K,class V>
|
||||
bit8 Dictionary<K,V>::contains(IN K &key)
|
||||
{
|
||||
int offset;
|
||||
DNode<K,V> *node;
|
||||
|
||||
offset=keyHash(key);
|
||||
|
||||
node=table[offset];
|
||||
|
||||
if (node==NULL)
|
||||
{ return(FALSE); } // can't find it
|
||||
|
||||
while(node!=NULL)
|
||||
{
|
||||
if ((node->key)==key)
|
||||
{ return(TRUE); }
|
||||
node=node->hashNext;
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
// Try and update the value of an already existing object
|
||||
template <class K,class V>
|
||||
bit8 Dictionary<K,V>::updateValue(IN K &key,IN V &value)
|
||||
{
|
||||
sint32 retval;
|
||||
|
||||
retval=remove(key);
|
||||
if (retval==FALSE)
|
||||
return(FALSE);
|
||||
|
||||
add(key,value);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
// Add to the dictionary (if key exists, value is updated with the new V)
|
||||
template <class K, class V>
|
||||
bit8 Dictionary<K,V>::add(IN K &key,IN V &value)
|
||||
{
|
||||
int offset;
|
||||
DNode<K,V> *node,*item,*temp;
|
||||
float percent;
|
||||
|
||||
item=(DNode<K,V> *)new DNode<K,V>;
|
||||
assert(item!=NULL);
|
||||
|
||||
#ifdef KEY_MEM_OPS
|
||||
memcpy(&(item->key),&key,sizeof(K));
|
||||
#else
|
||||
item->key=key;
|
||||
#endif
|
||||
|
||||
#ifdef VALUE_MEM_OPS
|
||||
memcpy(&(item->value),&value,sizeof(V));
|
||||
#else
|
||||
item->value=value;
|
||||
#endif
|
||||
|
||||
item->hashNext=NULL;
|
||||
|
||||
//If key already exists, it will be overwritten
|
||||
remove(key);
|
||||
|
||||
offset=keyHash(key);
|
||||
|
||||
node=table[offset];
|
||||
|
||||
if (node==NULL)
|
||||
{ table[offset]=item; }
|
||||
else
|
||||
{
|
||||
temp=table[offset];
|
||||
table[offset]=item;
|
||||
item->hashNext=temp;
|
||||
}
|
||||
|
||||
entries++;
|
||||
percent=(float)entries;
|
||||
percent/=(float)getSize();
|
||||
if (percent>= EXPAND_THRESHOLD ) expand();
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// Remove an item from the dictionary
|
||||
template <class K,class V>
|
||||
bit8 Dictionary<K,V>::remove(IN K &key,OUT V &value)
|
||||
{
|
||||
int offset;
|
||||
DNode<K,V> *node,*last,*temp;
|
||||
float percent;
|
||||
|
||||
if (entries==0)
|
||||
return(FALSE);
|
||||
|
||||
percent=(float)(entries-1);
|
||||
percent/=(float)getSize();
|
||||
|
||||
offset=keyHash(key);
|
||||
node=table[offset];
|
||||
|
||||
last=node;
|
||||
if (node==NULL) return(FALSE);
|
||||
|
||||
//special case table points to thing to delete
|
||||
|
||||
#ifdef KEY_MEM_OPS
|
||||
if (0==memcmp(&(node->key),&key,sizeof(K)))
|
||||
#else
|
||||
if ((node->key)==key)
|
||||
#endif
|
||||
{
|
||||
#ifdef VALUE_MEM_OPS
|
||||
memcpy(&value,&(node->value),sizeof(V));
|
||||
#else
|
||||
value=node->value;
|
||||
#endif
|
||||
temp=table[offset]->hashNext;
|
||||
delete(table[offset]);
|
||||
table[offset]=temp;
|
||||
entries--;
|
||||
if (percent <= SHRINK_THRESHOLD)
|
||||
shrink();
|
||||
return(TRUE);
|
||||
}
|
||||
node=node->hashNext;
|
||||
|
||||
//Now the case if the thing to delete is not the first
|
||||
while (node!=NULL)
|
||||
{
|
||||
#ifdef KEY_MEM_OPS
|
||||
if (0==memcmp(&(node->key),&key,sizeof(K)))
|
||||
#else
|
||||
if (node->key==key)
|
||||
#endif
|
||||
{
|
||||
#ifdef VALUE_MEM_OPS
|
||||
memcpy(&value,&(node->value),sizeof(V));
|
||||
#else
|
||||
value=node->value;
|
||||
#endif
|
||||
last->hashNext=node->hashNext;
|
||||
entries--;
|
||||
delete(node);
|
||||
break;
|
||||
}
|
||||
last=node;
|
||||
node=node->hashNext;
|
||||
}
|
||||
|
||||
if (percent <= SHRINK_THRESHOLD)
|
||||
shrink();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
template <class K,class V>
|
||||
bit8 Dictionary<K,V>::remove(IN K &key)
|
||||
{
|
||||
V temp;
|
||||
return(remove(key,temp));
|
||||
}
|
||||
|
||||
|
||||
// Remove some random K/V pair that's in the Dictionary
|
||||
template <class K,class V>
|
||||
bit8 Dictionary<K,V>::removeAny(OUT K &key,OUT V &value)
|
||||
{
|
||||
int offset;
|
||||
DNode<K,V> *node,*last,*temp;
|
||||
float percent;
|
||||
|
||||
if (entries==0)
|
||||
return(FALSE);
|
||||
|
||||
percent=(entries-1);
|
||||
percent/=(float)getSize();
|
||||
|
||||
int i;
|
||||
offset=-1;
|
||||
for (i=0; i<(int)getSize(); i++)
|
||||
if (table[i]!=NULL)
|
||||
{
|
||||
offset=i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (offset==-1) // Nothing there
|
||||
return(FALSE);
|
||||
|
||||
node=table[offset];
|
||||
last=node;
|
||||
|
||||
#ifdef KEY_MEM_OPS
|
||||
memcpy(&key,&(node->key),sizeof(K));
|
||||
#else
|
||||
key=node->key;
|
||||
#endif
|
||||
#ifdef VALUE_MEM_OPS
|
||||
memcpy(&value,&(node->value),sizeof(V));
|
||||
#else
|
||||
value=node->value;
|
||||
#endif
|
||||
|
||||
temp=table[offset]->hashNext;
|
||||
delete(table[offset]);
|
||||
table[offset]=temp;
|
||||
entries--;
|
||||
if (percent <= SHRINK_THRESHOLD)
|
||||
shrink();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
template <class K,class V>
|
||||
bit8 Dictionary<K,V>::getValue(IN K &key,OUT V &value)
|
||||
{
|
||||
int offset;
|
||||
DNode<K,V> *node;
|
||||
|
||||
offset=keyHash(key);
|
||||
|
||||
node=table[offset];
|
||||
|
||||
if (node==NULL) return(FALSE);
|
||||
|
||||
#ifdef KEY_MEM_OPS
|
||||
while ((node!=NULL)&&(memcmp(&(node->key),&key,sizeof(K))))
|
||||
#else
|
||||
while ((node!=NULL)&&( ! ((node->key)==key)) ) // odd syntax so you don't
|
||||
#endif // have to do oper !=
|
||||
{ node=node->hashNext; }
|
||||
|
||||
if (node==NULL)
|
||||
{ return(FALSE); }
|
||||
|
||||
#ifdef VALUE_MEM_OPS
|
||||
memcpy(&value,&(node->value),sizeof(V));
|
||||
#else
|
||||
value=(node->value);
|
||||
#endif
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
//A note about Shrink and Expand: They are never necessary, they are
|
||||
//only here to improve performance of the hash table by reducing
|
||||
//the length of the linked list at each table entry.
|
||||
|
||||
// Shrink the hash table by a factor of 2 (and relocate entries)
|
||||
template <class K,class V>
|
||||
void Dictionary<K,V>::shrink(void)
|
||||
{
|
||||
int i;
|
||||
int oldsize;
|
||||
uint32 offset;
|
||||
DNode<K,V> **oldtable,*temp,*first,*next;
|
||||
|
||||
if ((size<=(uint32)MIN_TABLE_SIZE)||(keepSize==TRUE))
|
||||
return;
|
||||
|
||||
//fprintf(stderr,"Shrinking....\n");
|
||||
|
||||
oldtable=table;
|
||||
oldsize=size;
|
||||
size/=2;
|
||||
tableBits--;
|
||||
|
||||
table=(DNode<K,V> **)new DNode<K,V>*[size];
|
||||
assert(table!=NULL);
|
||||
memset((void *)table,0,size*sizeof(void *));
|
||||
|
||||
for (i=0; i<oldsize; i++)
|
||||
{
|
||||
temp=oldtable[i];
|
||||
while (temp!=NULL)
|
||||
{
|
||||
offset=keyHash(temp->key);
|
||||
first=table[offset];
|
||||
table[offset]=temp;
|
||||
next=temp->hashNext;
|
||||
temp->hashNext=first;
|
||||
temp=next;
|
||||
}
|
||||
}
|
||||
delete[](oldtable);
|
||||
}
|
||||
|
||||
|
||||
template <class K,class V>
|
||||
void Dictionary<K,V>::expand(void)
|
||||
{
|
||||
int i;
|
||||
int oldsize;
|
||||
uint32 offset;
|
||||
DNode<K,V> **oldtable,*temp,*first,*next;
|
||||
|
||||
if (keepSize==TRUE)
|
||||
return;
|
||||
|
||||
//fprintf(stderr,"Expanding...\n");
|
||||
|
||||
oldtable=table;
|
||||
oldsize=size;
|
||||
size*=2;
|
||||
tableBits++;
|
||||
|
||||
table=(DNode<K,V> **)new DNode<K,V>* [size];
|
||||
assert(table!=NULL);
|
||||
memset((void *)table,0,size*sizeof(void *));
|
||||
|
||||
for (i=0; i<oldsize; i++)
|
||||
{
|
||||
temp=oldtable[i];
|
||||
while (temp!=NULL)
|
||||
{
|
||||
offset=keyHash(temp->key);
|
||||
first=table[offset];
|
||||
table[offset]=temp;
|
||||
next=temp->hashNext;
|
||||
temp->hashNext=first;
|
||||
temp=next;
|
||||
}
|
||||
}
|
||||
delete[](oldtable);
|
||||
}
|
||||
|
||||
#endif
|
56
Generals/Code/Tools/Launcher/filed.h
Normal file
56
Generals/Code/Tools/Launcher/filed.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FILED_HEADER
|
||||
#define FILED_HEADER
|
||||
|
||||
#include "odevice.h"
|
||||
|
||||
class FileD : public OutputDevice
|
||||
{
|
||||
public:
|
||||
FileD(char *filename, bool outputDebug) : m_outputDebug(outputDebug)
|
||||
{
|
||||
out=fopen(filename,"w");
|
||||
if (out==NULL)
|
||||
out=fopen("FileDev.out","w");
|
||||
}
|
||||
|
||||
virtual ~FileD()
|
||||
{ fclose(out); }
|
||||
|
||||
virtual int print(const char *str,int len)
|
||||
{
|
||||
char *string=new char[len+1];
|
||||
memset(string,0,len+1);
|
||||
memcpy(string,str,len);
|
||||
fprintf(out,"%s",string);
|
||||
if (m_outputDebug)
|
||||
{
|
||||
OutputDebugString(string);
|
||||
}
|
||||
delete[](string);
|
||||
fflush(out);
|
||||
return(len);
|
||||
}
|
||||
|
||||
FILE *out;
|
||||
bool m_outputDebug;
|
||||
};
|
||||
|
||||
#endif
|
213
Generals/Code/Tools/Launcher/findpatch.cpp
Normal file
213
Generals/Code/Tools/Launcher/findpatch.cpp
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "findpatch.h"
|
||||
|
||||
//
|
||||
// Locate a patch file
|
||||
// If a patch can be found then TRUE is returned and the name is filled in,
|
||||
// otherwise FALSE is returned.
|
||||
//
|
||||
// Patch Types:
|
||||
// - *.rtp = RTPatch file that can be applied right now
|
||||
// - *.exe = Executable that should be put in the RunOnce registry entry & reboot
|
||||
// - *.exn = Executable that should be run right now
|
||||
// - *.web = Link to a web page that will have the patch
|
||||
// - else = File is ignored, possibly a resource file for one of the other types
|
||||
//
|
||||
int Find_Patch(OUT char *filename,int maxlen, ConfigFile &config)
|
||||
{
|
||||
WIN32_FIND_DATA findData;
|
||||
char string[128];
|
||||
HANDLE hFile;
|
||||
char *extensions[]={"web","exe","exn","rtp",NULL};
|
||||
int i;
|
||||
int skuIndex=0;
|
||||
Wstring key;
|
||||
Wstring path;
|
||||
Wstring sku;
|
||||
char gamePath[MAX_PATH] = "";
|
||||
bit8 ok;
|
||||
|
||||
|
||||
while(1)
|
||||
{
|
||||
//
|
||||
// Loop through the apps we're responsible for
|
||||
//
|
||||
skuIndex++;
|
||||
ok=Get_App_Dir(gamePath,MAX_PATH,config,skuIndex);
|
||||
if (ok==FALSE)
|
||||
break;
|
||||
|
||||
i=0;
|
||||
while(extensions[i++])
|
||||
{
|
||||
_chdir(gamePath); // goto the directory with the game
|
||||
|
||||
// should probably get the registry entry for the wchat install path
|
||||
sprintf(string,"patches\\*.%s",extensions[i]);
|
||||
hFile=FindFirstFile(string,&findData);
|
||||
if (hFile!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
_getcwd(filename,MAX_PATH);
|
||||
strcat(filename,"\\patches\\");
|
||||
strcat(filename,findData.cFileName);
|
||||
FindClose(hFile);
|
||||
return(skuIndex);
|
||||
}
|
||||
sprintf(string,"download\\*.%s",extensions[i]);
|
||||
hFile=FindFirstFile(string,&findData);
|
||||
if (hFile!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
_getcwd(filename,MAX_PATH);
|
||||
strcat(filename,"\\download\\");
|
||||
strcat(filename,findData.cFileName);
|
||||
FindClose(hFile);
|
||||
return(skuIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Get the directory for the N'th application in the config file
|
||||
//
|
||||
// Returns FALSE if not in the config file or invalid for some reason.
|
||||
//
|
||||
bit8 Get_App_Dir(OUT char *filename,int maxlen, ConfigFile &config,int index)
|
||||
{
|
||||
char string[128];
|
||||
Wstring key;
|
||||
Wstring path;
|
||||
Wstring sku;
|
||||
int temp;
|
||||
char gamePath[MAX_PATH];
|
||||
|
||||
|
||||
sprintf(string,"SKU%d",index);
|
||||
|
||||
// Can't find this product
|
||||
if (config.getString(string,key)==FALSE)
|
||||
return(FALSE);
|
||||
|
||||
|
||||
DBGMSG("KEY = "<<key.get());
|
||||
// Get the InstallPath from the specified registry key
|
||||
temp=0;
|
||||
temp=key.getToken(temp," ",sku);
|
||||
path=key;
|
||||
path.remove(0,temp);
|
||||
while((*(path.get()))==' ') // remove leading spaces
|
||||
path.remove(0,1);
|
||||
|
||||
|
||||
DBGMSG("CONFIG: SKU = "<<sku.get()<<" PATH = '"<<path.get()<<"'");
|
||||
HKEY regKey;
|
||||
LONG regRetval;
|
||||
/////////////DWORD regPrevious;
|
||||
regRetval=RegOpenKeyEx(HKEY_LOCAL_MACHINE,path.get(),0,KEY_READ,®Key);
|
||||
if (regRetval!=ERROR_SUCCESS)
|
||||
{
|
||||
DBGMSG("RegOpenKey failed");
|
||||
return(FALSE);
|
||||
}
|
||||
DWORD type;
|
||||
DWORD length=MAX_PATH;
|
||||
regRetval=RegQueryValueEx(regKey,"InstallPath",NULL,&type,(uint8 *)gamePath,
|
||||
&length);
|
||||
DBGMSG("GAME PATH = "<<gamePath);
|
||||
if ((regRetval!=ERROR_SUCCESS)||(type!=REG_SZ))
|
||||
{
|
||||
DBGMSG("Reg failure");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
// Find the last '\\' in a string and put a 0 after it
|
||||
// If you only put a directory in the InstallPath key instead of a full
|
||||
// path to a file, you better end the directory with a trailing '\\'!!!
|
||||
char *cptr=gamePath;
|
||||
char *tempPtr;
|
||||
while( (tempPtr=strchr(cptr,'\\')) !=NULL)
|
||||
cptr=tempPtr+1;
|
||||
if (cptr)
|
||||
*cptr=0;
|
||||
|
||||
DBGMSG("Game path = "<<gamePath);
|
||||
strncpy(filename,gamePath,maxlen);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Delete any patch files
|
||||
//
|
||||
void Delete_Patches(ConfigFile &config)
|
||||
{
|
||||
char dir[MAX_PATH];
|
||||
int i=1;
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE hFile;
|
||||
|
||||
DBGMSG("IN DELPATCH");
|
||||
|
||||
//
|
||||
// Loop through all the application directories in the config file
|
||||
//
|
||||
while (Get_App_Dir(dir,MAX_PATH,config,i++)==TRUE)
|
||||
{
|
||||
// Make sure path is at least 3 for "c:\". I really hope nobody's
|
||||
// dumb enough to install a game to the root directory. (It's OK though
|
||||
// since only the '\patches' folder is cleared out.
|
||||
if (strlen(dir)<3)
|
||||
continue;
|
||||
|
||||
//
|
||||
// Delete everything in case a .exe patch had some data files it used.
|
||||
//
|
||||
strcat(dir,"patches\\*.*");
|
||||
|
||||
DBGMSG("DELPATCH: "<<dir);
|
||||
|
||||
hFile=FindFirstFile(dir,&findData);
|
||||
if (hFile!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (findData.cFileName[0]!='.')
|
||||
{
|
||||
//_unlink(findData.cFileName);
|
||||
DBGMSG("UNLINK: "<<findData.cFileName);
|
||||
}
|
||||
while(FindNextFile(hFile,&findData))
|
||||
{
|
||||
if (findData.cFileName[0]!='.')
|
||||
{
|
||||
//_unlink(findData.cFileName);
|
||||
DBGMSG("UNLINK: "<<findData.cFileName);
|
||||
}
|
||||
}
|
||||
} // If there's at least one file
|
||||
FindClose(hFile);
|
||||
} // while there's apps in config
|
||||
return;
|
||||
}
|
33
Generals/Code/Tools/Launcher/findpatch.h
Normal file
33
Generals/Code/Tools/Launcher/findpatch.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FINDPATCH_HEADER
|
||||
#define FINDPATCH_HEADER
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include "wstypes.h"
|
||||
#include "configfile.h"
|
||||
|
||||
int Find_Patch(OUT char *file,int maxlen, ConfigFile &config);
|
||||
bit8 Get_App_Dir(OUT char *file,int maxlen, ConfigFile &config, int index);
|
||||
void Delete_Patches(ConfigFile &config);
|
||||
|
||||
#endif
|
326
Generals/Code/Tools/Launcher/launcher.dsp
Normal file
326
Generals/Code/Tools/Launcher/launcher.dsp
Normal file
|
@ -0,0 +1,326 @@
|
|||
# Microsoft Developer Studio Project File - Name="launcher" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||
|
||||
CFG=launcher - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "launcher.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "launcher.mak" CFG="launcher - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "launcher - Win32 Release" (based on "Win32 (x86) Application")
|
||||
!MESSAGE "launcher - Win32 Debug" (based on "Win32 (x86) Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/APILauncher", DJDAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "launcher - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "ToolKit" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_NOTEPAD" /FR /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /pdb:"../../../Run/Generals.pdb" /map:"../../../Run/Generals.map" /debug /machine:I386 /out:"../../../Run/Generals.exe"
|
||||
# SUBTRACT LINK32
|
||||
|
||||
!ELSEIF "$(CFG)" == "launcher - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "ToolKit" /D "_DEBUG" /D "DEBUG" /D "USE_GAMEDIR_FROM_LCF" /D "WIN32" /D "_WINDOWS" /D "USE_NOTEPAD" /FR /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib winmm.lib /nologo /subsystem:windows /pdb:"../../../Run/GeneralsD.pdb" /map:"../../../Run/GeneralsD.map" /debug /machine:I386 /out:"../../../Run/GeneralsD.exe" /libpath:"."
|
||||
# SUBTRACT LINK32
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "launcher - Win32 Release"
|
||||
# Name "launcher - Win32 Debug"
|
||||
# Begin Group "dbglib"
|
||||
|
||||
# PROP Default_Filter ".cpp,.h"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\configfile.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\configfile.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dictionary.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\filed.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\monod.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\monod.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\odevice.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\streamer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\streamer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wdebug.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wdebug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wstring.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wstring.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "util"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# End Group
|
||||
# Begin Group "Support"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Support\RefCounted.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Support\RefPtr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Support\StringConvert.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Support\StringConvert.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Support\UString.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Support\UString.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Support\UTypes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Support\Visualc.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Debug"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Debug\DebugPrint.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Debug\DebugPrint.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Storage"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Storage\File.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Storage\File.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Storage\Rights.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Toolkit\Storage\Stream.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "SafeDisk"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\SafeDisk\CdaPfn.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BFISH.CPP
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BFISH.H
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dialog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dialog.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\findpatch.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\findpatch.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Generals.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Run\generals.lcf
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Run\launcher.bmp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\launcher1.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\loadbmp.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\loadbmp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\main.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\patch.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\patch.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Run\patchw32.dll
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\process.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\process.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Protect.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Protect.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\winblows.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\winblows.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wstypes.h
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
151
Generals/Code/Tools/Launcher/launcher1.rc
Normal file
151
Generals/Code/Tools/Launcher/launcher1.rc
Normal file
|
@ -0,0 +1,151 @@
|
|||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_PATCHPROGRESS DIALOG DISCARDABLE 0, 0, 243, 126
|
||||
STYLE DS_MODALFRAME | DS_SETFOREGROUND | WS_MINIMIZEBOX | WS_POPUP |
|
||||
WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Patching"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CONTROL "",IDC_SPLASH,"Static",SS_GRAYRECT | SS_SUNKEN,7,7,229,
|
||||
70
|
||||
GROUPBOX "File",IDC_CAPTION,7,78,229,22
|
||||
CONTROL "Progress1",IDC_PROGRESS2,"msctls_progress32",WS_BORDER,
|
||||
7,105,229,13
|
||||
CONTROL "",IDC_FILENAME,"Static",SS_LEFTNOWORDWRAP |
|
||||
SS_CENTERIMAGE | WS_GROUP,13,85,217,13
|
||||
END
|
||||
|
||||
IDD_CHANGELOG DIALOG DISCARDABLE 0, 0, 332, 204
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Update Information"
|
||||
FONT 10, "Lucida Console"
|
||||
BEGIN
|
||||
EDITTEXT IDC_TEXT,5,5,322,178,ES_MULTILINE | ES_AUTOHSCROLL |
|
||||
ES_READONLY | WS_VSCROLL | WS_HSCROLL
|
||||
PUSHBUTTON "OK",IDOK,128,185,76,14
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO DISCARDABLE
|
||||
BEGIN
|
||||
IDD_PATCHPROGRESS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 236
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 119
|
||||
END
|
||||
|
||||
IDD_CHANGELOG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 5
|
||||
RIGHTMARGIN, 327
|
||||
TOPMARGIN, 5
|
||||
BOTTOMMARGIN, 199
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_GENERALS ICON DISCARDABLE "Generals.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_SYS_RESTART "Your computer needs to be restarted to continue the patch. Press OK to continue."
|
||||
IDS_SYS_RESTART_TITLE "About to restart"
|
||||
IDS_WEBPATCH "You need to download a patch from our website.\rWhen you press OK, your browser will automatically open to the download page."
|
||||
IDS_WEBPATCH_TITLE "Web Patch"
|
||||
IDS_FILE_X_OF_Y "File (%d of %d)"
|
||||
IDS_MUST_RESTART "You must restart your computer now."
|
||||
IDS_RUNONCE_ERR "Could not set the patch to run on system reboot!\rYou must exit the game and run %s to complete the patch."
|
||||
IDS_ERROR "Error"
|
||||
IDS_ERR_MISSING_FILE "Error: Couldn't find file: %s"
|
||||
IDS_BAD_LIBRARY "A required DLL is corrupt."
|
||||
IDS_ERR_PATCH "Patch error. Existing game files may have been modified. You should re-install the game from the CD."
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
215
Generals/Code/Tools/Launcher/loadbmp.cpp
Normal file
215
Generals/Code/Tools/Launcher/loadbmp.cpp
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include"loadbmp.h"
|
||||
|
||||
|
||||
LoadBmp::LoadBmp()
|
||||
{
|
||||
BitmapHandle_=NULL;
|
||||
PalHandle_=NULL;
|
||||
}
|
||||
|
||||
LoadBmp::~LoadBmp()
|
||||
{
|
||||
// free resources
|
||||
DeleteObject(BitmapHandle_);
|
||||
DeleteObject(PalHandle_);
|
||||
}
|
||||
|
||||
//
|
||||
// Load a specified bitmap for later display on a window
|
||||
//
|
||||
bit8 LoadBmp::init(char *filename,HWND hwnd)
|
||||
{
|
||||
int i;
|
||||
HANDLE hBitmapFile;
|
||||
DWORD dwRead;
|
||||
BITMAPFILEHEADER bitmapHeader;
|
||||
BITMAPINFOHEADER bitmapInfoHeader;
|
||||
LPLOGPALETTE lpLogPalette;
|
||||
char *palData;
|
||||
HGLOBAL hmem2;
|
||||
LPVOID lpvBits;
|
||||
HDC hdc;
|
||||
HPALETTE select;
|
||||
UINT realize;
|
||||
RECT rect;
|
||||
|
||||
|
||||
// Set the member for future reference
|
||||
WindowHandle_=hwnd;
|
||||
|
||||
// Retrieve a handle identifying the file.
|
||||
hBitmapFile = CreateFile(
|
||||
filename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
(LPSECURITY_ATTRIBUTES) NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_READONLY,
|
||||
(HANDLE) NULL);
|
||||
|
||||
if (hBitmapFile==NULL)
|
||||
return(FALSE);
|
||||
|
||||
// Retrieve the BITMAPFILEHEADER structure.
|
||||
ReadFile(hBitmapFile, &bitmapHeader, sizeof(BITMAPFILEHEADER), &dwRead,
|
||||
(LPOVERLAPPED)NULL);
|
||||
|
||||
|
||||
// Retrieve the BITMAPFILEHEADER structure.
|
||||
ReadFile(hBitmapFile, &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(hBitmapFile, 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++;
|
||||
}
|
||||
PalHandle_=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(hBitmapFile, 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,PalHandle_,0);
|
||||
if (select==NULL)
|
||||
return(FALSE);
|
||||
realize=RealizePalette(hdc);
|
||||
if (realize==GDI_ERROR)
|
||||
return(FALSE);
|
||||
BitmapHandle_=CreateDIBitmap(hdc, &bitmapInfoHeader, CBM_INIT, lpvBits, lpHeaderMem, DIB_RGB_COLORS);
|
||||
ReleaseDC(hwnd,hdc);
|
||||
|
||||
|
||||
if (BitmapHandle_==NULL)
|
||||
return(FALSE);
|
||||
|
||||
// Unlock the global memory objects and close the .BMP file.
|
||||
GlobalUnlock(infoHeaderMem);
|
||||
GlobalUnlock(hmem2);
|
||||
CloseHandle(hBitmapFile);
|
||||
|
||||
if (BitmapHandle_==NULL)
|
||||
return(FALSE);
|
||||
|
||||
// Inform windows the window needs to be repainted
|
||||
GetClientRect(hwnd, &rect);
|
||||
InvalidateRect(hwnd, &rect, TRUE);
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
bit8 LoadBmp::drawBmp(void)
|
||||
{
|
||||
// Paint the window (and draw the bitmap).
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc;
|
||||
char string[128];
|
||||
|
||||
if (BitmapHandle_ == NULL) // NAK - new
|
||||
return(FALSE);
|
||||
|
||||
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);
|
||||
}
|
46
Generals/Code/Tools/Launcher/loadbmp.h
Normal file
46
Generals/Code/Tools/Launcher/loadbmp.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOADBMP_HEADER
|
||||
#define LOADBMP_HEADER
|
||||
|
||||
#include<stdlib.h>
|
||||
#include<stdio.h>
|
||||
#include "wstypes.h"
|
||||
#include "winblows.h"
|
||||
|
||||
|
||||
//
|
||||
// Functions and data assocated with a loaded bitmap on a single window.
|
||||
//
|
||||
class LoadBmp
|
||||
{
|
||||
public:
|
||||
LoadBmp();
|
||||
~LoadBmp();
|
||||
bit8 init(char *filename,HWND hwnd); // must call before the drawBmp
|
||||
bit8 drawBmp(void); // call this from your WM_PAINT message
|
||||
|
||||
private:
|
||||
HBITMAP BitmapHandle_;
|
||||
HPALETTE PalHandle_;
|
||||
HWND WindowHandle_;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
399
Generals/Code/Tools/Launcher/main.cpp
Normal file
399
Generals/Code/Tools/Launcher/main.cpp
Normal file
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
C O N F I D E N T I A L --- W E S T W O O D S T U D I O S
|
||||
*******************************************************************************
|
||||
File: main.cpp
|
||||
Programmer: Neal Kettler
|
||||
|
||||
StartDate: Feb 6, 1998
|
||||
LastUpdate: Feb 10, 1998
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Launcher application for games/apps using the chat API. This should be
|
||||
run by the user and it will start the actual game executable. If a patch
|
||||
file has been downloaded the patch will be applied before starting the game.
|
||||
|
||||
This does not download patches or do version checks, the game/app is responsible
|
||||
for that. This just applies patches that are in the correct location for the
|
||||
game. All patches should be in the "Patches" folder of the app.
|
||||
|
||||
The launcher should have a config file (launcher.cfg) so it knows which apps
|
||||
should be checked for patches. The file should look like this:
|
||||
|
||||
# comment
|
||||
# RUN = the game to launch
|
||||
RUN = . notepad.exe # directory and app name
|
||||
# RUN2 = the 2nd launcher if using one
|
||||
RUN2 = . wordpad.exe
|
||||
# FLAG = time in seconds of when to stop using 2nd launcher
|
||||
FLAG = 996778113
|
||||
#
|
||||
# Sku's to check for patches
|
||||
#
|
||||
SKU1 = 1100 SOFTWARE\Westwood\WOnline # skus and registry keys
|
||||
SKU2 = 1234 SOFTWARE\Westwood\FakeGame
|
||||
|
||||
\*****************************************************************************/
|
||||
#include "dialog.h"
|
||||
#include "patch.h"
|
||||
#include "findpatch.h"
|
||||
#include "process.h"
|
||||
|
||||
#include "wdebug.h"
|
||||
#include "monod.h"
|
||||
#include "filed.h"
|
||||
#include "configfile.h"
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef COPY_PROTECT
|
||||
#include "Protect.h"
|
||||
#endif
|
||||
#include <Debug\DebugPrint.h>
|
||||
|
||||
#define UPDATE_RETVAL 123456789 // if a program returns this it means it wants to check for patches
|
||||
|
||||
void CreatePrimaryWin(char *prefix);
|
||||
void myChdir(char *path);
|
||||
|
||||
void RunGame(char *thePath, ConfigFile &config, Process &proc)
|
||||
{
|
||||
char patchFile[MAX_PATH];
|
||||
bool launchgame = true;
|
||||
|
||||
// MDC 8/23/2001 Wait 3 seconds for the installer to release the mutex
|
||||
///Sleep(3000);
|
||||
|
||||
while (true)
|
||||
{
|
||||
int skuIndex;
|
||||
|
||||
while ((skuIndex = Find_Patch(patchFile, MAX_PATH, config)) != 0)
|
||||
{
|
||||
Apply_Patch(patchFile, config, skuIndex);
|
||||
launchgame = true;
|
||||
}
|
||||
|
||||
// launch the game if first pass, or found a patch
|
||||
if (launchgame)
|
||||
{
|
||||
// don't relaunch unless we find a patch (or checking for patches)
|
||||
launchgame = false;
|
||||
myChdir(thePath);
|
||||
|
||||
#ifndef COPY_PROTECT
|
||||
Create_Process(proc);
|
||||
#else // COPY_PROTECT
|
||||
|
||||
InitializeProtect();
|
||||
Create_Process(proc);
|
||||
SendProtectMessage(proc.hProcess, proc.dwThreadID);
|
||||
|
||||
#endif // COPY_PROTECT
|
||||
|
||||
DWORD exit_code;
|
||||
Wait_Process(proc, &exit_code);
|
||||
|
||||
if (exit_code == UPDATE_RETVAL)
|
||||
{
|
||||
// They just want to check for patches
|
||||
launchgame = true;
|
||||
|
||||
// Start patchgrabber
|
||||
Process patchgrab;
|
||||
strcpy(patchgrab.directory,proc.directory); // same dir as game
|
||||
strcpy(patchgrab.command,"patchget.dat"); // the program that grabs game patches
|
||||
strcpy(patchgrab.args,"");
|
||||
Create_Process(patchgrab);
|
||||
Wait_Process(patchgrab); // wait for completion
|
||||
}
|
||||
|
||||
#ifdef COPY_PROTECT
|
||||
ShutdownProtect();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Delete_Patches(config); // delete all patches
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The other launcher will handle itself. Just fire and forget.
|
||||
void RunLauncher(char *thePath, Process &proc)
|
||||
{
|
||||
myChdir(thePath);
|
||||
Create_Process(proc);
|
||||
}
|
||||
|
||||
//
|
||||
// Called by WinMain
|
||||
//
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char patchFile[MAX_PATH];
|
||||
|
||||
char cwd[MAX_PATH]; // save current directory before game start
|
||||
_getcwd(cwd, MAX_PATH);
|
||||
|
||||
// Goto the folder where launcher is installed
|
||||
myChdir(argv[0]);
|
||||
|
||||
// extract the program name from argv[0]. Change the extension to
|
||||
// .lcf (Launcher ConFig). This is the name of our config file.
|
||||
char configName[MAX_PATH + 3];
|
||||
strcpy(configName, argv[0]);
|
||||
char* extension = configName;
|
||||
char* tempptr;
|
||||
|
||||
while ((tempptr = strchr(extension + 1, '.')))
|
||||
{
|
||||
extension = tempptr;
|
||||
}
|
||||
|
||||
if (*extension == '.')
|
||||
{
|
||||
*extension = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
///MonoD outputDevice;
|
||||
char debugFile[MAX_PATH + 3];
|
||||
strcpy(debugFile, configName);
|
||||
strcat(debugFile, ".txt");
|
||||
strcpy(debugLogName, strrchr(configName, '\\'));
|
||||
strcat(debugLogName, "Log");
|
||||
FileD outputDevice(debugFile, true);
|
||||
MsgManager::setAllStreams(&outputDevice);
|
||||
DBGMSG("Launcher initialized");
|
||||
#endif
|
||||
|
||||
CreatePrimaryWin("generals");
|
||||
|
||||
InitCommonControls();
|
||||
|
||||
strcat(configName, ".lcf");
|
||||
|
||||
DBGMSG("Config Name: "<<configName);
|
||||
|
||||
ConfigFile config;
|
||||
FILE* in = fopen(configName, "r");
|
||||
|
||||
if (in == NULL)
|
||||
{
|
||||
MessageBox(NULL,"You must run the game from its install directory.",
|
||||
"Launcher config file missing",MB_OK);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
bit8 ok = config.readFile(in);
|
||||
fclose(in);
|
||||
|
||||
if (ok == FALSE)
|
||||
{
|
||||
MessageBox(NULL,"File 'launcher.cfg' is corrupt","Error",MB_OK);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Load process info
|
||||
Process proc;
|
||||
Read_Process_Info(config,proc);
|
||||
|
||||
// Possible 2nd EXE
|
||||
Process proc2;
|
||||
int hasSecondEXE = Read_Process_Info(config,proc2,"RUN2");
|
||||
|
||||
DBGMSG("Read process info");
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
strcat(proc.args, " ");
|
||||
strcat(proc.args, argv[i]);
|
||||
|
||||
if (hasSecondEXE)
|
||||
{
|
||||
strcat(proc2.args, " ");
|
||||
strcat(proc2.args, argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
DBGMSG("ARGS: "<<proc.args);
|
||||
|
||||
// Just spawn the patchgrabber & apply any patches it downloads
|
||||
if ((argc >= 2) && (strcmp(argv[1], "GrabPatches") == 0))
|
||||
{
|
||||
// Start patchgrabber
|
||||
Process patchgrab;
|
||||
|
||||
// same dir as game
|
||||
strcpy(patchgrab.directory, proc.directory);
|
||||
|
||||
// the program that grabs game patches
|
||||
strcpy(patchgrab.command, "patchget.dat");
|
||||
strcpy(patchgrab.args, "");
|
||||
|
||||
Create_Process(patchgrab);
|
||||
Wait_Process(patchgrab);
|
||||
|
||||
// Apply any patches I find
|
||||
int skuIndex;
|
||||
|
||||
while ((skuIndex = Find_Patch(patchFile, MAX_PATH, config)) != 0)
|
||||
{
|
||||
Apply_Patch(patchFile, config, skuIndex);
|
||||
}
|
||||
|
||||
myChdir(cwd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Look for patch file(s) to apply
|
||||
bool launchgame = true;
|
||||
|
||||
time_t cutoffTime = 0;
|
||||
if (hasSecondEXE)
|
||||
{
|
||||
Wstring timeStr;
|
||||
if (config.getString("FLAG", timeStr)!=FALSE)
|
||||
{
|
||||
cutoffTime = atoi(timeStr.get());
|
||||
}
|
||||
|
||||
if (cutoffTime == 0)
|
||||
{
|
||||
// We didn't have the FLAG parameter; somebody's been hacking. No game for you! Bad hacker!
|
||||
DBGMSG("Saw cutoffTime of 0; real time is " << time(NULL));
|
||||
MessageBox(NULL,"File 'launcher.cfg' is corrupt","Error",MB_OK);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (time(NULL) > cutoffTime)
|
||||
{
|
||||
// The future is now! Just run the game.
|
||||
RunGame(argv[0], config, proc);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Its still early in the product's lifetime, so run the 2nd (SafeDisk'd) launcher.
|
||||
// We don't have to wait around since it'll do the entire talk to game, look for patches,
|
||||
// etc. deal.
|
||||
RunLauncher(argv[0], proc2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're the second (or only) launcher, so act normally
|
||||
RunGame(argv[0], config, proc);
|
||||
}
|
||||
|
||||
myChdir(cwd);
|
||||
|
||||
// Exit normally
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Create a primary window
|
||||
//
|
||||
void CreatePrimaryWin(char *prefix)
|
||||
{
|
||||
char name[256];
|
||||
sprintf(name, "launcher_%s", prefix);
|
||||
|
||||
DBGMSG("CreatePrimary: "<<name);
|
||||
|
||||
/*
|
||||
** set up and register window class
|
||||
*/
|
||||
WNDCLASS wc;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.cbClsExtra = 0; // Don't need any extra class data
|
||||
wc.cbWndExtra = 0; // No extra win data
|
||||
wc.hInstance = Global_instance;
|
||||
wc.hIcon=LoadIcon(Global_instance, MAKEINTRESOURCE(IDI_GENERALS));
|
||||
wc.hCursor = NULL; /////////LoadCursor( NULL, IDC_ARROW );
|
||||
wc.hbrBackground = NULL;
|
||||
wc.lpszMenuName = name;
|
||||
wc.lpszClassName = name;
|
||||
RegisterClass(&wc);
|
||||
|
||||
/*
|
||||
** create a window
|
||||
*/
|
||||
HWND hwnd = CreateWindowEx(WS_EX_TOPMOST, name, name, WS_POPUP, 0, 0,
|
||||
GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
|
||||
NULL, NULL, Global_instance, NULL);
|
||||
|
||||
if(!hwnd)
|
||||
{
|
||||
DBGMSG("Couldn't make window!");
|
||||
}
|
||||
else
|
||||
{
|
||||
DBGMSG("Window created!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//void DestroyPrimaryWin(void)
|
||||
//{
|
||||
// DestroyWindow(PrimaryWin);
|
||||
// UnregisterClass(classname);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// If given a file, it'll goto it's directory. If on a diff drive,
|
||||
// it'll go there.
|
||||
//
|
||||
void myChdir(char *path)
|
||||
{
|
||||
char drive[10];
|
||||
char dir[255];
|
||||
char file[255];
|
||||
char ext[64];
|
||||
char filepath[513];
|
||||
int abc;
|
||||
|
||||
_splitpath( path, drive, dir, file, ext );
|
||||
_makepath ( filepath, drive, dir, NULL, NULL );
|
||||
|
||||
if ( filepath[ strlen( filepath ) - 1 ] == '\\' )
|
||||
{
|
||||
filepath[ strlen( filepath ) - 1 ] = '\0';
|
||||
}
|
||||
abc = (unsigned)( toupper( filepath[0] ) - 'A' + 1 );
|
||||
if ( !_chdrive( abc ))
|
||||
{
|
||||
abc = chdir( filepath ); // Will fail with ending '\\'
|
||||
}
|
||||
// should be in proper folder now....
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
57
Generals/Code/Tools/Launcher/monod.cpp
Normal file
57
Generals/Code/Tools/Launcher/monod.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "monod.h"
|
||||
|
||||
MonoD::MonoD(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
unsigned long retval;
|
||||
handle = CreateFile("\\\\.\\MONO", GENERIC_READ|GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DeviceIoControl(handle, (DWORD)IOCTL_MONO_CLEAR_SCREEN, NULL, 0, NULL, 0,
|
||||
&retval,0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MonoD::~MonoD()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CloseHandle(handle);
|
||||
handle=NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int MonoD::print(const char *str, int len)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
unsigned long retval;
|
||||
WriteFile(handle, str, len, &retval, NULL);
|
||||
//DeviceIoControl(handle, (DWORD)IOCTL_MONO_PRINT_RAW, (void *)str, len, NULL, 0,
|
||||
// &retval,0);
|
||||
return(len);
|
||||
#else
|
||||
for (int i=0; i<len; i++)
|
||||
fprintf(stderr,"%c",str[i]);
|
||||
return(len);
|
||||
#endif
|
||||
}
|
74
Generals/Code/Tools/Launcher/monod.h
Normal file
74
Generals/Code/Tools/Launcher/monod.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MONOD_HEADER
|
||||
#define MONOD_HEADER
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "odevice.h"
|
||||
|
||||
///////////////////////// WIN32 ONLY ///////////////////////////////////
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
|
||||
/*
|
||||
** This is the identifier for the Monochrome Display Driver
|
||||
*/
|
||||
#define FILE_DEVICE_MONO 0x00008000
|
||||
|
||||
/*
|
||||
** These are the IOCTL commands supported by the Monochrome Display Driver.
|
||||
*/
|
||||
#define IOCTL_MONO_HELP_SCREEN CTL_CODE(FILE_DEVICE_MONO, 0x800, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_CLEAR_SCREEN CTL_CODE(FILE_DEVICE_MONO, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_PRINT_RAW CTL_CODE(FILE_DEVICE_MONO, 0x802, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_SET_CURSOR CTL_CODE(FILE_DEVICE_MONO, 0x803, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_SCROLL CTL_CODE(FILE_DEVICE_MONO, 0x804, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_BRING_TO_TOP CTL_CODE(FILE_DEVICE_MONO, 0x805, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_SET_ATTRIBUTE CTL_CODE(FILE_DEVICE_MONO, 0x806, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_PAN CTL_CODE(FILE_DEVICE_MONO, 0x807, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_LOCK CTL_CODE(FILE_DEVICE_MONO, 0x808, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_UNLOCK CTL_CODE(FILE_DEVICE_MONO, 0x809, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_SET_WINDOW CTL_CODE(FILE_DEVICE_MONO, 0x80A, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_RESET_WINDOW CTL_CODE(FILE_DEVICE_MONO, 0x80B, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_SET_FLAG CTL_CODE(FILE_DEVICE_MONO, 0x80C, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_CLEAR_FLAG CTL_CODE(FILE_DEVICE_MONO, 0x80D, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
#define IOCTL_MONO_FILL_ATTRIB CTL_CODE(FILE_DEVICE_MONO, 0x80E, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
|
||||
#endif // ifdef _WIN32
|
||||
|
||||
class MonoD : public OutputDevice
|
||||
{
|
||||
public:
|
||||
MonoD();
|
||||
~MonoD();
|
||||
|
||||
virtual int print(const char *str,int len);
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
HANDLE handle;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
32
Generals/Code/Tools/Launcher/odevice.h
Normal file
32
Generals/Code/Tools/Launcher/odevice.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ODEVICE_HEADER
|
||||
#define ODEVICE_HEADER
|
||||
|
||||
// This virtual base class provides an interface for output devices
|
||||
// that can be used for the debugging package.
|
||||
class OutputDevice
|
||||
{
|
||||
public:
|
||||
OutputDevice() {}
|
||||
virtual ~OutputDevice() {};
|
||||
virtual int print(const char *s,int len)=0;
|
||||
};
|
||||
|
||||
#endif
|
574
Generals/Code/Tools/Launcher/patch.cpp
Normal file
574
Generals/Code/Tools/Launcher/patch.cpp
Normal file
|
@ -0,0 +1,574 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
C O N F I D E N T I A L --- W E S T W O O D S T U D I O S
|
||||
*******************************************************************************
|
||||
File: patch.cpp
|
||||
Programmer: Neal Kettler
|
||||
|
||||
StartDate: Feb 6, 1998
|
||||
LastUpdate: Feb 10, 1998
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
This is where all the code is for applying various types of patches.
|
||||
|
||||
\*****************************************************************************/
|
||||
|
||||
|
||||
#include "patch.h"
|
||||
#include <shellapi.h>
|
||||
#include <direct.h>
|
||||
|
||||
|
||||
//
|
||||
// For the text box showing patch info
|
||||
//
|
||||
BOOL CALLBACK Update_Info_Proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
||||
static int unselectText=0;
|
||||
|
||||
switch(iMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
FILE *in = fopen("launcher.txt","r");
|
||||
if (in==NULL)
|
||||
{
|
||||
EndDialog(hwnd,-1);
|
||||
return(1);
|
||||
}
|
||||
|
||||
char line[270];
|
||||
int lastsel=0;
|
||||
char *cptr=NULL;
|
||||
while(fgets(line,255,in))
|
||||
{
|
||||
//Get rid of any trailing junk
|
||||
while(1)
|
||||
{
|
||||
if (strlen(line)<1)
|
||||
break;
|
||||
cptr=line+(strlen(line))-1;
|
||||
if ((*cptr=='\r')||(*cptr=='\n'))
|
||||
*cptr=0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
// ...and add back the gunk that windows likes
|
||||
strcat(line,"\r\r\n");
|
||||
|
||||
SendDlgItemMessage(hwnd, IDC_TEXT, EM_SETSEL, (WPARAM)lastsel, (LPARAM)lastsel );
|
||||
SendDlgItemMessage(hwnd, IDC_TEXT, EM_REPLACESEL, 0, (LPARAM)(line) );
|
||||
SendDlgItemMessage(hwnd, IDC_TEXT, EM_GETSEL, (WPARAM)NULL, (LPARAM)&lastsel );
|
||||
}
|
||||
unselectText=1;
|
||||
fclose(in);
|
||||
|
||||
return(1); // 1 means windows handles focus issues
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
if (unselectText)
|
||||
SendDlgItemMessage(hwnd, IDC_TEXT, EM_SETSEL, -1, 0);
|
||||
unselectText=0;
|
||||
return(0);
|
||||
break;
|
||||
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(wParam) {
|
||||
case IDOK:
|
||||
{
|
||||
EndDialog(hwnd,0);
|
||||
return(1);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
EndDialog(hwnd,0);
|
||||
return(1);
|
||||
break;
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Restart the computer for certain types of patches
|
||||
void Shutdown_Computer_Now(void);
|
||||
|
||||
|
||||
__declspec(dllexport) LPVOID CALLBACK PatchCallBack(UINT ID, LPVOID Param);
|
||||
|
||||
typedef LPVOID (CALLBACK* PATCHCALLBACK)(UINT, LPVOID);
|
||||
typedef UINT (CALLBACK *PATCHFUNC)( LPSTR, PATCHCALLBACK, BOOL);
|
||||
|
||||
//
|
||||
// Apply any type of patch. Filename in patchfile. Product base registry
|
||||
// (eg: "SOFTWARE\Westwood\Red Alert") should be in the config file as
|
||||
// SKUX SKU base reg dir where X = index
|
||||
//
|
||||
void Apply_Patch(char *patchfile,ConfigFile &config,int skuIndex)
|
||||
{
|
||||
DBGMSG("PATCHFILE : "<<patchfile);
|
||||
char cwdbuf[256];
|
||||
_getcwd(cwdbuf,255);
|
||||
DBGMSG("CWD : "<<cwdbuf);
|
||||
|
||||
//
|
||||
// If patch is a .exe type patch
|
||||
//
|
||||
if (strcasecmp(patchfile+strlen(patchfile)-strlen(".exe"),".exe")==0)
|
||||
{
|
||||
// Set this as a run once service thing
|
||||
HKEY regKey;
|
||||
LONG regRetval;
|
||||
DWORD regPrevious;
|
||||
regRetval=RegCreateKeyEx(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
|
||||
0,
|
||||
"",
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS,
|
||||
NULL,
|
||||
®Key,
|
||||
®Previous);
|
||||
|
||||
if (regRetval==ERROR_SUCCESS)
|
||||
{
|
||||
RegSetValueEx(regKey,"EXEPatch",0,REG_SZ,(const uint8*)patchfile,strlen(patchfile)+1);
|
||||
|
||||
char message[256];
|
||||
LoadString(NULL,IDS_SYS_RESTART,message,256);
|
||||
char title[128];
|
||||
LoadString(NULL,IDS_SYS_RESTART_TITLE,title,128);
|
||||
|
||||
MessageBox(NULL,message,title,MB_OK);
|
||||
|
||||
Shutdown_Computer_Now();
|
||||
}
|
||||
else
|
||||
{
|
||||
char message[256];
|
||||
LoadString(NULL,IDS_RUNONCE_ERR,message,256);
|
||||
char string[256];
|
||||
sprintf(string,message,patchfile);
|
||||
MessageBox(NULL,string,"ERROR",MB_OK);
|
||||
}
|
||||
}
|
||||
//
|
||||
// RTPatch type patch
|
||||
//
|
||||
else if (strcasecmp(patchfile+strlen(patchfile)-strlen(".rtp"),".rtp")==0)
|
||||
{
|
||||
MSG msg;
|
||||
HWND dialog=Create_Patch_Dialog();
|
||||
while(PeekMessage(&msg,NULL,0,0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
HINSTANCE hInst=LoadLibrary("patchw32.dll");
|
||||
if (hInst==NULL)
|
||||
{
|
||||
char message[256];
|
||||
LoadString(NULL,IDS_ERR_MISSING_FILE,message,256);
|
||||
char string[256];
|
||||
sprintf(string,message,"patchw32.dll");
|
||||
char title[128];
|
||||
LoadString(NULL,IDS_ERROR,title,128);
|
||||
MessageBox(NULL,string,title,MB_OK);
|
||||
exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
DBGMSG("Patch SKU = "<<skuIndex);
|
||||
|
||||
|
||||
PATCHFUNC patchFunc;
|
||||
patchFunc=(PATCHFUNC)GetProcAddress(hInst,"RTPatchApply32@12");
|
||||
if (patchFunc==NULL)
|
||||
{
|
||||
char message[256];
|
||||
LoadString(NULL,IDS_BAD_LIBRARY,message,256);
|
||||
char title[128];
|
||||
LoadString(NULL,IDS_ERROR,title,128);
|
||||
MessageBox(NULL,message,title,MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
char patchArgs[200];
|
||||
sprintf(patchArgs,"\"%s\" .",patchfile);
|
||||
int rtpErrCode=patchFunc(patchArgs,PatchCallBack,TRUE);
|
||||
FreeLibrary(hInst); // unload the DLL
|
||||
_unlink(patchfile); // delete the patch
|
||||
|
||||
DestroyWindow(dialog); // get rid of the dialog
|
||||
|
||||
// Don't update the registry if the patch failed to update.
|
||||
if (rtpErrCode != 0)
|
||||
{
|
||||
ERRMSG("Patch error: " << rtpErrCode);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we have to update the registry so the version is correct
|
||||
// The version is the first integer in the filename
|
||||
// Eg: 22456_patch.rtp means version 22456 goes into the registry
|
||||
|
||||
// The version# starts after the last '\' char
|
||||
char *cptr=patchfile;
|
||||
char *tempPtr;
|
||||
DWORD version;
|
||||
while( (tempPtr=strchr(cptr,'\\')) !=NULL)
|
||||
cptr=tempPtr+1;
|
||||
if (cptr)
|
||||
version=atol(cptr);
|
||||
DBGMSG("VERSION TO = "<<version);
|
||||
|
||||
|
||||
char string[256];
|
||||
Wstring key;
|
||||
// Get the InstallPath from the specified registry key
|
||||
sprintf(string,"SKU%d",skuIndex);
|
||||
if (config.getString(string,key)==FALSE)
|
||||
{
|
||||
ERRMSG("SKU is missing from config file!");
|
||||
return;
|
||||
}
|
||||
|
||||
int temp=0;
|
||||
Wstring sku;
|
||||
Wstring path;
|
||||
temp=key.getToken(temp," ",sku);
|
||||
path=key;
|
||||
path.remove(0,temp);
|
||||
while((*(path.get()))==' ') // remove leading spaces
|
||||
path.remove(0,1);
|
||||
// Open the registry key for modifying now...
|
||||
HKEY regKey;
|
||||
LONG regRetval;
|
||||
regRetval=RegOpenKeyEx(HKEY_LOCAL_MACHINE,path.get(),0,
|
||||
KEY_ALL_ACCESS,®Key);
|
||||
if (regRetval!=ERROR_SUCCESS)
|
||||
DBGMSG("Can't open reg key for writing");
|
||||
regRetval=RegSetValueEx(regKey,"Version",0,REG_DWORD,(uint8 *)&version,
|
||||
sizeof(version));
|
||||
|
||||
|
||||
// Create blocking DLG for update info
|
||||
#ifdef USE_NOTEPAD
|
||||
{
|
||||
Process notepad;
|
||||
|
||||
// same dir as game
|
||||
strcpy(notepad.directory, ".");
|
||||
|
||||
// the program that grabs game patches
|
||||
strcpy(notepad.command, "notepad");
|
||||
strcpy(notepad.args, " launcher.txt");
|
||||
|
||||
Create_Process(notepad);
|
||||
Wait_Process(notepad);
|
||||
}
|
||||
#else
|
||||
DialogBox(Global_instance,MAKEINTRESOURCE(IDD_CHANGELOG),NULL,(DLGPROC)Update_Info_Proc);
|
||||
#endif
|
||||
}
|
||||
//
|
||||
// Execute now (without rebooting) type patch
|
||||
//
|
||||
else if (strcasecmp(patchfile+strlen(patchfile)-strlen(".exn"),".exn")==0)
|
||||
{
|
||||
Process proc;
|
||||
strcpy(proc.directory,".");
|
||||
strcpy(proc.command,patchfile);
|
||||
Create_Process(proc);
|
||||
Wait_Process(proc);
|
||||
_unlink(patchfile);
|
||||
}
|
||||
//
|
||||
// Web link type patch
|
||||
//
|
||||
// Im about 99.44% sure that this is completely useless.
|
||||
//
|
||||
else if (strcasecmp(patchfile+strlen(patchfile)-strlen(".web"),".web")==0)
|
||||
{
|
||||
char message[256];
|
||||
LoadString(NULL,IDS_WEBPATCH,message,256);
|
||||
char title[128];
|
||||
LoadString(NULL,IDS_WEBPATCH_TITLE,title,128);
|
||||
MessageBox(NULL,message,title,MB_OK);
|
||||
|
||||
FILE *in=fopen(patchfile,"r");
|
||||
if (in!=NULL)
|
||||
{
|
||||
char URL[256];
|
||||
fgets(URL,255,in);
|
||||
fclose(in);
|
||||
ShellExecute(NULL,NULL,URL,NULL,".",SW_SHOW);
|
||||
_unlink(patchfile);
|
||||
//// This is somewhat skanky, but we can't wait
|
||||
//// for the viewer to exit (I tried).
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox(NULL,patchfile,"Patchfile vanished?",MB_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Shutdown_Computer_Now(void)
|
||||
{
|
||||
HANDLE hToken;
|
||||
TOKEN_PRIVILEGES tkp;
|
||||
|
||||
// Get a token for this process.
|
||||
if (!OpenProcessToken(GetCurrentProcess(),
|
||||
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
||||
{
|
||||
//error("OpenProcessToken");
|
||||
}
|
||||
|
||||
// Get the LUID for the shutdown privilege.
|
||||
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
|
||||
&tkp.Privileges[0].Luid);
|
||||
|
||||
tkp.PrivilegeCount = 1; // one privilege to set
|
||||
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
// Get the shutdown privilege for this process.
|
||||
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
|
||||
(PTOKEN_PRIVILEGES)NULL, 0);
|
||||
|
||||
// Cannot test the return value of AdjustTokenPrivileges.
|
||||
if (GetLastError() != ERROR_SUCCESS)
|
||||
{
|
||||
//error("AdjustTokenPrivileges");
|
||||
}
|
||||
|
||||
// Shut down the system and force all applications to close.
|
||||
if (!ExitWindowsEx(EWX_REBOOT, 0))
|
||||
{
|
||||
// Should never happen
|
||||
char restart[128];
|
||||
LoadString(NULL,IDS_MUST_RESTART,restart,128);
|
||||
MessageBox(NULL,restart,"OK",MB_OK);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Callback during the patching process
|
||||
//
|
||||
__declspec(dllexport) LPVOID CALLBACK PatchCallBack(UINT Id, LPVOID Param)
|
||||
{
|
||||
char string[128];
|
||||
static int fileCount=0; // number of files to be patched
|
||||
static int currFile=0;
|
||||
|
||||
// Make sure our windows get updated
|
||||
MSG msg;
|
||||
int counter=0;
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE ))
|
||||
{
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessage( &msg );
|
||||
counter++;
|
||||
if (counter==100) // just in case...
|
||||
break;
|
||||
}
|
||||
|
||||
LPVOID RetVal="";
|
||||
bit8 Abort=FALSE;
|
||||
|
||||
//// using the global Dialog pointer, set the current "error" code
|
||||
//g_DlgPtr->SetRTPErrCode(Id);
|
||||
|
||||
int percent;
|
||||
|
||||
switch( Id )
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
// Warning message header/text
|
||||
DBGMSG("P_MSG: "<<((char *)Param));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Error message header
|
||||
DBGMSG("P_MSG: "<<((char *)Param));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// Error message header/text
|
||||
///////*g_LogFile << (char *)Parm << endl;
|
||||
char errmsg[256];
|
||||
LoadString(NULL,IDS_ERR_PATCH,errmsg,256);
|
||||
MessageBox(NULL,(char *)Param,errmsg,MB_OK);
|
||||
{
|
||||
FILE *out=fopen("patch.err","a");
|
||||
time_t timet=time(NULL);
|
||||
fprintf(out,"\n\nPatch Error: %s\n",ctime(&timet));
|
||||
fprintf(out,"%s\n",(char *)Param);
|
||||
fclose(out);
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
// progress message
|
||||
break;
|
||||
|
||||
case 0xa:
|
||||
// help message
|
||||
break;
|
||||
|
||||
case 0xb:
|
||||
// patch file comment
|
||||
break;
|
||||
|
||||
case 0xc:
|
||||
// copyright message
|
||||
break; // these just display text
|
||||
|
||||
case 5:
|
||||
// % completed
|
||||
// so adjust the progress bar using the global Dialog pointer
|
||||
/////////g_DlgPtr->SetProgressBar((int)((float)(*(UINT *)Parm)/(float)0x8000*(float)100));
|
||||
percent=((*(UINT *)Param)*100)/0x8000;
|
||||
SendMessage(GetDlgItem(PatchDialog,IDC_PROGRESS2),PBM_SETPOS,percent,0);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// Number of patch files
|
||||
DBGMSG("6: "<<*((uint32 *)Param));
|
||||
fileCount=*((uint32 *)Param);
|
||||
currFile=0;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
//// begin patch
|
||||
//LoadString(g_AppInstance, IDS_PROCESSING, lpcBuf, 256);
|
||||
//strcpy(buf,lpcBuf);
|
||||
//strcat(buf,(char *)Parm);
|
||||
//g_DlgPtr->SetProgressText(buf);
|
||||
//*g_LogFile << buf << " : ";
|
||||
//fileModified = true;
|
||||
|
||||
DBGMSG("7: "<<(char *)Param);
|
||||
SetWindowText(GetDlgItem(PatchDialog,IDC_FILENAME),(char *)Param);
|
||||
percent=0;
|
||||
SendMessage(GetDlgItem(PatchDialog,IDC_PROGRESS2),PBM_SETPOS,percent,0);
|
||||
|
||||
currFile++;
|
||||
char xofy[64];
|
||||
LoadString(NULL,IDS_FILE_X_OF_Y,xofy,64);
|
||||
sprintf(string,xofy,currFile,fileCount);
|
||||
SetWindowText(GetDlgItem(PatchDialog,IDC_CAPTION),string);
|
||||
|
||||
break;
|
||||
|
||||
case 8:
|
||||
//// end patch
|
||||
//LoadString(g_AppInstance, IDS_PROCCOMPLETE, lpcBuf, 256);
|
||||
//g_DlgPtr->SetProgressText(lpcBuf);
|
||||
//*g_LogFile << " complete" << endl;
|
||||
percent=100;
|
||||
SendMessage(GetDlgItem(PatchDialog,IDC_PROGRESS2),PBM_SETPOS,percent,0);
|
||||
DBGMSG("P_DONE");
|
||||
break;
|
||||
|
||||
case 0xd:
|
||||
//// this one shouldn't happen (only occurs if the command line
|
||||
//// doesn't have a patch file in it, and we insure that it does).
|
||||
//Abort = TRUE;
|
||||
//*g_LogFile << "Incorrect (or none) patch file specified in command line." << endl;
|
||||
break;
|
||||
|
||||
case 0xe:
|
||||
//// this one shouldn't happen either (same reason)
|
||||
//Abort = TRUE;
|
||||
//*g_LogFile << "Incorrect (or none) path specified in command line." << endl;
|
||||
break;
|
||||
|
||||
case 0xf:
|
||||
//// Password Dialog
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
//// Invalid Password Alert
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
//// Disk Change Dialog
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
//// Disk Change Alert
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
//// Confirmation Dialog
|
||||
break;
|
||||
|
||||
case 0x14:
|
||||
//// Location Dialog
|
||||
//Abort = TRUE;
|
||||
//*g_LogFile << "Specified path is incorrect." << endl;
|
||||
break;
|
||||
|
||||
case 0x16:
|
||||
//// Searching Call-back
|
||||
break;
|
||||
|
||||
case 0x15:
|
||||
//// Idle...
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(Abort)
|
||||
return (NULL);
|
||||
else
|
||||
return (RetVal);
|
||||
}
|
30
Generals/Code/Tools/Launcher/patch.h
Normal file
30
Generals/Code/Tools/Launcher/patch.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PATCH_HEADER
|
||||
#define PATCH_HEADER
|
||||
|
||||
#include "winblows.h"
|
||||
#include "dialog.h"
|
||||
#include "resource.h"
|
||||
#include "wdebug.h"
|
||||
#include "process.h"
|
||||
|
||||
void Apply_Patch(char *patchfile,ConfigFile &config,int skuIndex);
|
||||
|
||||
#endif
|
176
Generals/Code/Tools/Launcher/process.cpp
Normal file
176
Generals/Code/Tools/Launcher/process.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "process.h"
|
||||
|
||||
Process::Process()
|
||||
{
|
||||
directory[0]=0;
|
||||
command[0]=0;
|
||||
args[0]=0;
|
||||
hProcess=NULL;
|
||||
hThread=NULL;
|
||||
}
|
||||
|
||||
// Create a process
|
||||
bit8 Create_Process(Process &process)
|
||||
{
|
||||
int retval;
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION piProcess;
|
||||
ZeroMemory(&si,sizeof(si));
|
||||
si.cb=sizeof(si);
|
||||
|
||||
char cmdargs[513];
|
||||
memset(cmdargs,0,513);
|
||||
strcpy(cmdargs,process.command);
|
||||
strcat(cmdargs,process.args);
|
||||
|
||||
DBGMSG("PROCESS CMD="<<cmdargs<<" DIR="<<process.directory);
|
||||
|
||||
#ifndef COPY_PROTECT
|
||||
retval=CreateProcess(NULL,cmdargs,NULL,NULL,FALSE, 0 ,NULL, NULL/*process.directory*/,&si,&piProcess);
|
||||
#else
|
||||
#ifdef USE_GAMEDIR_FROM_LCF
|
||||
retval=CreateProcess(NULL,cmdargs,NULL,NULL,TRUE, 0 ,NULL, process.directory,&si,&piProcess);
|
||||
#else
|
||||
retval=CreateProcess(NULL,cmdargs,NULL,NULL,TRUE, 0 ,NULL, NULL/*process.directory*/,&si,&piProcess);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
DBGMSG("("<<retval<<") New process: HANDLE " << (void *)piProcess.hProcess << " ID "
|
||||
<< (DWORD)piProcess.dwProcessId);
|
||||
DBGMSG("("<<retval<<") New thread: HANDLE " << (void *)piProcess.hThread << " ID "
|
||||
<< (DWORD)piProcess.dwThreadId);
|
||||
if (retval==0)
|
||||
{
|
||||
char message_buffer[256];
|
||||
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &message_buffer[0], 256, NULL );
|
||||
DBGMSG("ERR: "<<message_buffer);
|
||||
}
|
||||
process.hProcess=piProcess.hProcess;
|
||||
process.dwProcessID = piProcess.dwProcessId;
|
||||
process.hThread=piProcess.hThread;
|
||||
process.dwThreadID = piProcess.dwThreadId;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
// Wait for a process to complete, and fill in the exit code
|
||||
//
|
||||
bit8 Wait_Process(Process &process, DWORD *exit_code)
|
||||
{
|
||||
DWORD retval;
|
||||
retval=WaitForSingleObject(process.hProcess,INFINITE);
|
||||
if (exit_code != NULL)
|
||||
*exit_code=-1;
|
||||
if (retval==WAIT_OBJECT_0) // process exited
|
||||
{
|
||||
// MDC 1/10/2003 Inserting sleep here to let game exit before applying patch
|
||||
Sleep(3000);
|
||||
|
||||
if (exit_code != NULL)
|
||||
GetExitCodeProcess(process.hProcess,exit_code);
|
||||
return(TRUE);
|
||||
}
|
||||
else // can this happen?
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Get the process to run from the config object
|
||||
//
|
||||
bit8 Read_Process_Info(ConfigFile &config,OUT Process &info, IN char *key)
|
||||
{
|
||||
|
||||
Wstring keyStr = "RUN";
|
||||
if (key)
|
||||
keyStr = key;
|
||||
|
||||
Wstring procinfo;
|
||||
if (config.getString(keyStr.get(), procinfo)==FALSE)
|
||||
{
|
||||
DBGMSG("Couldn't read the RUN line");
|
||||
return(FALSE);
|
||||
}
|
||||
int offset=0;
|
||||
Wstring dir;
|
||||
Wstring executable;
|
||||
Wstring args;
|
||||
offset=procinfo.getToken(offset," ",dir);
|
||||
offset=procinfo.getToken(offset," ",executable);
|
||||
args=procinfo;
|
||||
args.remove(0,offset);
|
||||
|
||||
///
|
||||
///
|
||||
DBGMSG("RUN: EXE = "<<executable.get()<<" DIR = "<<dir.get()<<
|
||||
" ARGS = "<<args.get());
|
||||
strcpy(info.command,executable.get());
|
||||
strcpy(info.directory,dir.get());
|
||||
strcpy(info.args,args.get());
|
||||
return(TRUE);
|
||||
|
||||
|
||||
/*********************************************************
|
||||
FILE *in;
|
||||
char string[256];
|
||||
bit8 found_space;
|
||||
int i;
|
||||
|
||||
if ((in=fopen(config,"r"))==NULL)
|
||||
return(FALSE);
|
||||
|
||||
while(fgets(string,256,in))
|
||||
{
|
||||
i=0;
|
||||
while ((isspace(string[i]))&&(i<int(strlen(string))))
|
||||
i++;
|
||||
|
||||
// do nothing with empty line or commented line
|
||||
if ((string[i]=='#')||(i==int(strlen(string)-1)))
|
||||
continue;
|
||||
|
||||
strcpy(info.directory,string);
|
||||
found_space=FALSE;
|
||||
for (; i<int(strlen(string)); i++)
|
||||
{
|
||||
if (isspace(info.directory[i]))
|
||||
{
|
||||
info.directory[i]=0;
|
||||
found_space=TRUE;
|
||||
}
|
||||
else if (found_space)
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(info.command,string+i);
|
||||
for (i=0; i<int(strlen(info.command)); i++)
|
||||
if ((info.command[i]=='\n')||(info.command[i]=='\r'))
|
||||
info.command[i]=0;
|
||||
|
||||
//printf("DIR = '%s' CMD = '%s'\n",info.directory,info.command);
|
||||
|
||||
// We only have 1 process for this
|
||||
break;
|
||||
}
|
||||
fclose(in);
|
||||
return(TRUE);
|
||||
**********************************************/
|
||||
}
|
46
Generals/Code/Tools/Launcher/process.h
Normal file
46
Generals/Code/Tools/Launcher/process.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PROCESS_HEADER
|
||||
#define PROCESS_HEADER
|
||||
|
||||
#include <windows.h>
|
||||
#include "wstypes.h"
|
||||
#include "wdebug.h"
|
||||
#include "configfile.h"
|
||||
|
||||
class Process
|
||||
{
|
||||
public:
|
||||
Process();
|
||||
|
||||
char directory[256];
|
||||
char command[256];
|
||||
char args[256];
|
||||
HANDLE hProcess;
|
||||
DWORD dwProcessID;
|
||||
HANDLE hThread;
|
||||
DWORD dwThreadID;
|
||||
};
|
||||
|
||||
bit8 Read_Process_Info(ConfigFile &config,OUT Process &info, IN char *key = NULL);
|
||||
bit8 Create_Process(Process &process);
|
||||
bit8 Wait_Process(Process &process, DWORD *exit_code=NULL);
|
||||
|
||||
|
||||
#endif
|
35
Generals/Code/Tools/Launcher/resource.h
Normal file
35
Generals/Code/Tools/Launcher/resource.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by launcher1.rc
|
||||
//
|
||||
#define IDS_SYS_RESTART 1
|
||||
#define IDS_SYS_RESTART_TITLE 2
|
||||
#define IDS_WEBPATCH 3
|
||||
#define IDS_WEBPATCH_TITLE 4
|
||||
#define IDS_FILE_X_OF_Y 5
|
||||
#define IDS_MUST_RESTART 6
|
||||
#define IDS_RUNONCE_ERR 7
|
||||
#define IDS_ERROR 8
|
||||
#define IDS_ERR_MISSING_FILE 9
|
||||
#define IDS_BAD_LIBRARY 10
|
||||
#define IDS_ERR_PATCH 11
|
||||
#define IDD_DIALOG1 101
|
||||
#define IDD_PATCHPROGRESS 101
|
||||
#define IDI_GENERALS 102
|
||||
#define IDD_CHANGELOG 103
|
||||
#define IDC_PROGRESS2 1001
|
||||
#define IDC_SPLASH 1004
|
||||
#define IDC_FILENAME 1009
|
||||
#define IDC_CAPTION 1010
|
||||
#define IDC_TEXT 1011
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 104
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1013
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
142
Generals/Code/Tools/Launcher/streamer.cpp
Normal file
142
Generals/Code/Tools/Launcher/streamer.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "streamer.h"
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
Streamer::Streamer() : streambuf()
|
||||
{
|
||||
int state=unbuffered();
|
||||
unbuffered(0); // 0 = buffered, 1 = unbuffered
|
||||
}
|
||||
|
||||
Streamer::~Streamer()
|
||||
{
|
||||
sync();
|
||||
delete[](base());
|
||||
}
|
||||
|
||||
int Streamer::setOutputDevice(OutputDevice *device)
|
||||
{
|
||||
Output_Device=device;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
// put n chars from string into buffer
|
||||
int Streamer::xsputn(const char* buf, int size) //implementation of sputn
|
||||
{
|
||||
|
||||
if (size<=0) // Nothing to do
|
||||
return(0);
|
||||
|
||||
const unsigned char *ptr=(const unsigned char *)buf;
|
||||
for (int i=0; i<size; i++, ptr++)
|
||||
{
|
||||
if(*ptr=='\n')
|
||||
{
|
||||
if (overflow(*ptr)==EOF)
|
||||
return(i);
|
||||
}
|
||||
else if (sputc(*ptr)==EOF)
|
||||
return(i);
|
||||
}
|
||||
return(size);
|
||||
}
|
||||
|
||||
// Flush the buffer and make more room if needed
|
||||
int Streamer::overflow(int c)
|
||||
{
|
||||
|
||||
if (c==EOF)
|
||||
return(sync());
|
||||
if ((pbase()==0) && (doallocate()==0))
|
||||
return(EOF);
|
||||
if((pptr() >= epptr()) && (sync()==EOF))
|
||||
return(EOF);
|
||||
else {
|
||||
sputc(c);
|
||||
if ((unbuffered() && c=='\n' || pptr() >= epptr())
|
||||
&& sync()==EOF) {
|
||||
return(EOF);
|
||||
}
|
||||
return(c);
|
||||
}
|
||||
}
|
||||
|
||||
// This is a write only stream, this should never happen
|
||||
int Streamer::underflow(void)
|
||||
{
|
||||
return(EOF);
|
||||
}
|
||||
|
||||
int Streamer::doallocate()
|
||||
{
|
||||
|
||||
if (base()==NULL)
|
||||
{
|
||||
char *buf=new char[(2*STREAMER_BUFSIZ)]; // deleted by destructor
|
||||
memset(buf,0,2*STREAMER_BUFSIZ);
|
||||
|
||||
// Buffer
|
||||
setb(
|
||||
buf, // base pointer
|
||||
buf+STREAMER_BUFSIZ, // ebuf pointer (end of buffer);
|
||||
0); // 0 = manual deletion of buff
|
||||
|
||||
// Get area
|
||||
setg(
|
||||
buf, // eback
|
||||
buf, // gptr
|
||||
buf); // egptr
|
||||
|
||||
buf+=STREAMER_BUFSIZ;
|
||||
// Put area
|
||||
setp(buf,buf+STREAMER_BUFSIZ);
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int Streamer::sync()
|
||||
{
|
||||
if (pptr()<=pbase()) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
int wlen=pptr()-pbase();
|
||||
|
||||
if (Output_Device)
|
||||
{
|
||||
Output_Device->print(pbase(),wlen);
|
||||
}
|
||||
|
||||
if (unbuffered()) {
|
||||
setp(pbase(),pbase());
|
||||
}
|
||||
else {
|
||||
setp(pbase(),pbase()+STREAMER_BUFSIZ);
|
||||
}
|
||||
return(0);
|
||||
}
|
60
Generals/Code/Tools/Launcher/streamer.h
Normal file
60
Generals/Code/Tools/Launcher/streamer.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef STREAMER_HEADER
|
||||
#define STREAMER_HEADER
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <iostream.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "odevice.h"
|
||||
|
||||
#ifndef STREAMER_BUFSIZ
|
||||
// This limits the number of characters that can be sent to a single 'print'
|
||||
// call. If your debug message is bigger than this, it will get split over
|
||||
// multiple 'print' calls. That's usually not a problem.
|
||||
#define STREAMER_BUFSIZ 2048
|
||||
#endif
|
||||
|
||||
|
||||
// Provide a streambuf interface for a class that can 'print'
|
||||
class Streamer : public streambuf
|
||||
{
|
||||
public:
|
||||
Streamer();
|
||||
virtual ~Streamer();
|
||||
|
||||
int setOutputDevice(OutputDevice *output_device);
|
||||
|
||||
protected:
|
||||
// Virtual methods from streambuf
|
||||
int xsputn(const char* s, int n); // buffer some characters
|
||||
int overflow(int = EOF); // flush buffer and make more room
|
||||
int underflow(void); // Does nothing
|
||||
int sync();
|
||||
|
||||
int doallocate(); // allocate a buffer
|
||||
|
||||
|
||||
OutputDevice *Output_Device;
|
||||
};
|
||||
|
||||
#endif
|
143
Generals/Code/Tools/Launcher/wdebug.cpp
Normal file
143
Generals/Code/Tools/Launcher/wdebug.cpp
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "wdebug.h"
|
||||
#include "streamer.h"
|
||||
#include "odevice.h"
|
||||
|
||||
|
||||
static MsgManager *msg_manager=NULL;
|
||||
|
||||
static int debug_enabled=0;
|
||||
static ostream *debug_ostream=NULL;
|
||||
static Streamer debug_streamer;
|
||||
|
||||
static int info_enabled=0;
|
||||
static ostream *info_ostream=NULL;
|
||||
static Streamer info_streamer;
|
||||
|
||||
static int warn_enabled=0;
|
||||
static ostream *warn_ostream=NULL;
|
||||
static Streamer warn_streamer;
|
||||
|
||||
static int error_enabled=0;
|
||||
static ostream *error_ostream=NULL;
|
||||
static Streamer error_streamer;
|
||||
|
||||
|
||||
|
||||
int MsgManager::setAllStreams(OutputDevice *device)
|
||||
{
|
||||
if (device==NULL)
|
||||
return(1);
|
||||
|
||||
|
||||
debug_streamer.setOutputDevice(device);
|
||||
delete(debug_ostream);
|
||||
debug_ostream=new ostream(&debug_streamer);
|
||||
|
||||
info_streamer.setOutputDevice(device);
|
||||
delete(info_ostream);
|
||||
info_ostream=new ostream(&info_streamer);
|
||||
|
||||
warn_streamer.setOutputDevice(device);
|
||||
delete(warn_ostream);
|
||||
warn_ostream=new ostream(&warn_streamer);
|
||||
|
||||
error_streamer.setOutputDevice(device);
|
||||
delete(error_ostream);
|
||||
error_ostream=new ostream(&error_streamer);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int MsgManager::setDebugStream(OutputDevice *device)
|
||||
{
|
||||
if (device==NULL)
|
||||
return(1);
|
||||
|
||||
|
||||
debug_streamer.setOutputDevice(device);
|
||||
delete(debug_ostream);
|
||||
debug_ostream=new ostream(&debug_streamer);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int MsgManager::setInfoStream(OutputDevice *device)
|
||||
{
|
||||
if (device==NULL)
|
||||
return(1);
|
||||
|
||||
|
||||
info_streamer.setOutputDevice(device);
|
||||
delete(info_ostream);
|
||||
info_ostream=new ostream(&info_streamer);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int MsgManager::setWarnStream(OutputDevice *device)
|
||||
{
|
||||
if (device==NULL)
|
||||
return(1);
|
||||
|
||||
|
||||
warn_streamer.setOutputDevice(device);
|
||||
delete(warn_ostream);
|
||||
warn_ostream=new ostream(&warn_streamer);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int MsgManager::setErrorStream(OutputDevice *device)
|
||||
{
|
||||
if (device==NULL)
|
||||
return(1);
|
||||
|
||||
|
||||
error_streamer.setOutputDevice(device);
|
||||
delete(error_ostream);
|
||||
error_ostream=new ostream(&error_streamer);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ostream *MsgManager::debugStream(void)
|
||||
{
|
||||
return(debug_ostream);
|
||||
}
|
||||
|
||||
ostream *MsgManager::infoStream(void)
|
||||
{
|
||||
return(info_ostream);
|
||||
}
|
||||
|
||||
ostream *MsgManager::warnStream(void)
|
||||
{
|
||||
return(warn_ostream);
|
||||
}
|
||||
|
||||
ostream *MsgManager::errorStream(void)
|
||||
{
|
||||
return(error_ostream);
|
||||
}
|
193
Generals/Code/Tools/Launcher/wdebug.h
Normal file
193
Generals/Code/Tools/Launcher/wdebug.h
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
wdebug Neal Kettler
|
||||
|
||||
MT-LEVEL
|
||||
MT-UnSafe! (UNIX version is safe though)
|
||||
|
||||
The debugging module is pretty good for debugging and it has some message
|
||||
printing stuff as well. The basic idea is that you write a class that
|
||||
inherits from OutputDevice (severall are provided) and assign that output
|
||||
device to a stream. There are seperate streams for debugging, information,
|
||||
warning, and error messages. Each one can have a seperate output device,
|
||||
or they can all have the same one. Debugging messages only get compiled
|
||||
in if your module defines 'DEBUG'. If you don't define debug, then not even
|
||||
the text of the debugging message gets into the binary. All the other
|
||||
output streams get printed regardless of whether DEBUG is defined.
|
||||
|
||||
Sample usage:
|
||||
FileD debug_device("gameres.debug"); // create a file device
|
||||
MsgManager::setDebugStream(&debug_device);
|
||||
DBGMSG("This debug message #" << 1 << " you use C++ streams");
|
||||
|
||||
Note that since these are defines you really don't need to put a semicolon
|
||||
at the end, and it can be bad in situations like this:
|
||||
|
||||
if (x)
|
||||
DBGMSG("Stuff is broken");
|
||||
else
|
||||
DBGMSG("Stuff is NOT broken");
|
||||
|
||||
This won't compile, read the code until you figure it out. Only then
|
||||
will you be ready to leave grasshopper.
|
||||
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef WDEBUG_HEADER
|
||||
#define WDEBUG_HEADER
|
||||
|
||||
#include <iostream.h>
|
||||
#include "odevice.h"
|
||||
#include "streamer.h"
|
||||
#include <time.h>
|
||||
|
||||
|
||||
|
||||
// Print an information message
|
||||
#define INFMSG(X)\
|
||||
{\
|
||||
char timebuf[40]; \
|
||||
time_t clock=time(NULL); \
|
||||
cftime(timebuf,"%D %T",&clock); \
|
||||
if (MsgManager::infoStream()) \
|
||||
(*(MsgManager::infoStream())) << "INF " << timebuf << " [" << \
|
||||
__FILE__ << " " << __LINE__ << "] " << X << endl; \
|
||||
}
|
||||
|
||||
// Print a warning message
|
||||
#define WRNMSG(X)\
|
||||
{\
|
||||
char timebuf[40]; \
|
||||
time_t clock=time(NULL); \
|
||||
cftime(timebuf,"%D %T",&clock); \
|
||||
if (MsgManager::warnStream()) \
|
||||
(*(MsgManager::warnStream())) << "WRN " << timebuf << " [" << \
|
||||
__FILE__ << " " << __LINE__ << "] " << X << endl; \
|
||||
}
|
||||
|
||||
// Print an error message
|
||||
#define ERRMSG(X)\
|
||||
{\
|
||||
char timebuf[40]; \
|
||||
time_t clock=time(NULL); \
|
||||
strcpy(timebuf,ctime(&clock)); \
|
||||
if (MsgManager::errorStream()) \
|
||||
(*(MsgManager::errorStream())) << "ERR " << timebuf << " [" << \
|
||||
__FILE__ << " " << __LINE__ << "] " << X << endl; \
|
||||
}
|
||||
|
||||
|
||||
// Just get a stream to the information device, no extra junk
|
||||
#define INFSTREAM(X)\
|
||||
{\
|
||||
if (MsgManager::infoStream()) \
|
||||
(*(MsgManager::infoStream())) << X;\
|
||||
}
|
||||
|
||||
// Just get a stream to the warning device, no extra junk
|
||||
#define WRNSTREAM(X)\
|
||||
{\
|
||||
if (MsgManager::warnStream()) \
|
||||
(*(MsgManager::warnStream())) << X;\
|
||||
}
|
||||
|
||||
// Just get a stream to the error device, no extra junk
|
||||
#define ERRSTREAM(X)\
|
||||
{\
|
||||
if (MsgManager::errorStream()) \
|
||||
(*(MsgManager::errorStream())) << X;\
|
||||
}
|
||||
|
||||
#ifndef DEBUG
|
||||
|
||||
// No debugging, no debug messages.
|
||||
// Note that anything enclosed in "DBG()" will NOT get executed
|
||||
// unless DEBUG is defined.
|
||||
// They are defined to {} for consistency when DEBUG is defined
|
||||
|
||||
#define DBG(X)
|
||||
#define DBGSTREAM(X) {}
|
||||
#define PVAR(v) {}
|
||||
#define DBGMSG(X) {}
|
||||
#define VERBOSE(X) {}
|
||||
|
||||
#else // DEBUG _is_ defined
|
||||
|
||||
// Execute only if in debugging mode
|
||||
#define DBG(X) X
|
||||
|
||||
// Print a variable
|
||||
#define PVAR(v) \
|
||||
{ \
|
||||
if (MsgManager::debugStream()) \
|
||||
(*(MsgManager::debugStream())) << __FILE__ << "[" << __LINE__ << \
|
||||
"]: " << ##V << " = " << V << endl; \
|
||||
}
|
||||
|
||||
|
||||
#define DBGMSG(X)\
|
||||
{\
|
||||
if (MsgManager::debugStream()) \
|
||||
(*(MsgManager::debugStream())) << "DBG [" << __FILE__ << \
|
||||
" " << __LINE__ << "] " << X << endl;\
|
||||
}
|
||||
|
||||
// Just get a stream to the debugging device, no extra junk
|
||||
#define DBGSTREAM(X)\
|
||||
{\
|
||||
if (MsgManager::debugStream()) \
|
||||
(*(MsgManager::debugStream())) << X;\
|
||||
}
|
||||
|
||||
// Verbosely execute a statement
|
||||
#define VERBOSE(X)\
|
||||
{ \
|
||||
if (MsgManager::debugStream()) \
|
||||
(*(DebugManager::debugStream())) << __FILE__ << "[" << __LINE__ << \
|
||||
"]: " << ##X << endl; X \
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
class MsgManager
|
||||
{
|
||||
protected:
|
||||
MsgManager();
|
||||
|
||||
public:
|
||||
static int setAllStreams(OutputDevice *device);
|
||||
static int setDebugStream(OutputDevice *device);
|
||||
static int setInfoStream(OutputDevice *device);
|
||||
static int setWarnStream(OutputDevice *device);
|
||||
static int setErrorStream(OutputDevice *device);
|
||||
|
||||
static void enableDebug(int flag);
|
||||
static void enableInfo(int flag);
|
||||
static void enableWarn(int flag);
|
||||
static void enableError(int flag);
|
||||
|
||||
static ostream *debugStream(void);
|
||||
static ostream *infoStream(void);
|
||||
static ostream *warnStream(void);
|
||||
static ostream *errorStream(void);
|
||||
};
|
||||
|
||||
#endif
|
186
Generals/Code/Tools/Launcher/winblows.cpp
Normal file
186
Generals/Code/Tools/Launcher/winblows.cpp
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "winblows.h"
|
||||
|
||||
|
||||
HINSTANCE Global_instance;
|
||||
LPSTR Global_commandline;
|
||||
int Global_commandshow;
|
||||
|
||||
|
||||
/*
|
||||
* WinMain - initialization, message loop
|
||||
*/
|
||||
int PASCAL WinMain( HINSTANCE instance, HINSTANCE, char *command_line, int command_show)
|
||||
{
|
||||
//////MSG msg;
|
||||
|
||||
Global_instance = instance;
|
||||
Global_commandline = command_line;
|
||||
Global_commandshow = command_show;
|
||||
|
||||
int argc;
|
||||
char *argv[64];
|
||||
|
||||
char path_to_exe[512];
|
||||
GetModuleFileName(instance,(char *)&path_to_exe,512);
|
||||
argc=1;
|
||||
argv[0]=path_to_exe;
|
||||
|
||||
|
||||
int command_scan=0;
|
||||
char command_char;
|
||||
do
|
||||
{
|
||||
/*
|
||||
** Scan for non-space character on command line
|
||||
*/
|
||||
do
|
||||
{
|
||||
command_char = *( command_line+command_scan++ );
|
||||
} while ( command_char==' ' );
|
||||
|
||||
if ( command_char!=0 && command_char != 13 )
|
||||
{
|
||||
argv[argc++]=command_line+command_scan-1;
|
||||
|
||||
/*
|
||||
** Scan for space character on command line
|
||||
*/
|
||||
do
|
||||
{
|
||||
command_char = *( command_line+command_scan++ );
|
||||
} while ( command_char!=' ' && command_char != 0 && command_char!=13);
|
||||
*( command_line+command_scan-1 ) = 0;
|
||||
}
|
||||
|
||||
} while ( command_char != 0 && command_char != 13 && argc<20 );
|
||||
|
||||
return(main(argc,argv));
|
||||
|
||||
} /* WinMain */
|
||||
|
||||
|
||||
int Print_WM(UINT message,char *out)
|
||||
{
|
||||
switch(message)
|
||||
{
|
||||
case WM_NULL:
|
||||
sprintf(out,"WM_NULL");
|
||||
break;
|
||||
case WM_CREATE:
|
||||
sprintf(out,"WM_CREATE");
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
sprintf(out,"WM_DESTROY");
|
||||
break;
|
||||
case WM_CANCELMODE:
|
||||
sprintf(out,"WM_CANCELMODE");
|
||||
break;
|
||||
case WM_ERASEBKGND:
|
||||
sprintf(out,"WM_ERASEBKGND");
|
||||
break;
|
||||
case WM_GETTEXT:
|
||||
sprintf(out,"WM_GETTEXT");
|
||||
break;
|
||||
case WM_QUERYOPEN:
|
||||
sprintf(out,"WM_QUERYOPEN");
|
||||
break;
|
||||
case WM_MOVE:
|
||||
sprintf(out,"WM_MOVE");
|
||||
break;
|
||||
case WM_SIZE:
|
||||
sprintf(out,"WM_SIZE");
|
||||
break;
|
||||
case WM_ACTIVATE:
|
||||
sprintf(out,"WM_ACTIVATE");
|
||||
break;
|
||||
case WM_SETFOCUS:
|
||||
sprintf(out,"WM_SETFOCUS");
|
||||
break;
|
||||
case WM_KILLFOCUS:
|
||||
sprintf(out,"WM_KILLFOCUS");
|
||||
break;
|
||||
case WM_ENABLE:
|
||||
sprintf(out,"WM_ENABLE");
|
||||
break;
|
||||
case WM_SETREDRAW:
|
||||
sprintf(out,"WM_REDRAW");
|
||||
break;
|
||||
case WM_PAINT:
|
||||
sprintf(out,"WM_PAINT");
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
sprintf(out,"WM_CLOSE");
|
||||
break;
|
||||
case WM_QUIT:
|
||||
sprintf(out,"WM_QUIT");
|
||||
break;
|
||||
case WM_ACTIVATEAPP:
|
||||
sprintf(out,"WM_ACTIVATEAPP");
|
||||
break;
|
||||
case WM_SETCURSOR:
|
||||
sprintf(out,"WM_SETCURSOR");
|
||||
break;
|
||||
case WM_KEYDOWN:
|
||||
sprintf(out,"WM_KEYDOWN");
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
sprintf(out,"WM_MOUSEMOVE");
|
||||
break;
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
sprintf(out,"WM_WINDOWPOSCHANGING");
|
||||
break;
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
sprintf(out,"WM_WINDOWPOSCHANGED");
|
||||
break;
|
||||
case WM_DISPLAYCHANGE:
|
||||
sprintf(out,"WM_DISPLAYCHANGE");
|
||||
break;
|
||||
case WM_NCPAINT:
|
||||
sprintf(out,"WM_NCPAINT");
|
||||
break;
|
||||
case WM_PALETTEISCHANGING:
|
||||
sprintf(out,"WM_PALETTEISCHANGING");
|
||||
break;
|
||||
case WM_PALETTECHANGED:
|
||||
sprintf(out,"WM_PALETTECHANGED");
|
||||
break;
|
||||
case WM_NCACTIVATE:
|
||||
sprintf(out,"WM_NCACTIVATE");
|
||||
break;
|
||||
case WM_NCCALCSIZE:
|
||||
sprintf(out,"WM_NCCALCSIZE");
|
||||
break;
|
||||
case WM_SYSCOMMAND:
|
||||
sprintf(out,"WM_SYSCOMMAND");
|
||||
break;
|
||||
default:
|
||||
sprintf(out,"? UNKNOWN ?");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
37
Generals/Code/Tools/Launcher/winblows.h
Normal file
37
Generals/Code/Tools/Launcher/winblows.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WINBLOWS_HEADER
|
||||
#define WINBLOWS_HEADER
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include"wstypes.h"
|
||||
|
||||
extern HINSTANCE Global_instance;
|
||||
extern LPSTR Global_commandline;
|
||||
extern int Global_commandshow;
|
||||
|
||||
extern int main(int argc, char *argv[]);
|
||||
|
||||
int Print_WM(UINT wm,char *out);
|
||||
|
||||
#endif
|
611
Generals/Code/Tools/Launcher/wstring.cpp
Normal file
611
Generals/Code/Tools/Launcher/wstring.cpp
Normal file
|
@ -0,0 +1,611 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************\
|
||||
* C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *
|
||||
******************************************************************************
|
||||
Project Name: Carpenter (The RedAlert ladder creator)
|
||||
File Name : string.cpp
|
||||
Author : Neal Kettler
|
||||
Start Date : June 1, 1997
|
||||
Last Update : June 17, 1997
|
||||
|
||||
A fairly typical string class. This string class always copies any input
|
||||
string to it's own memory (for assignment or construction).
|
||||
\***************************************************************************/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "wstring.h"
|
||||
|
||||
Wstring::Wstring():str(NULL)
|
||||
{ }
|
||||
|
||||
Wstring::Wstring(IN char *string):str(NULL)
|
||||
{ set(string); }
|
||||
|
||||
Wstring::Wstring(IN const Wstring &other):str(NULL)
|
||||
{
|
||||
if (other.str!=NULL)
|
||||
{
|
||||
str=new char[strlen(other.str)+1];
|
||||
strcpy(str,other.str);
|
||||
}
|
||||
}
|
||||
|
||||
Wstring::~Wstring()
|
||||
{ clear(); }
|
||||
|
||||
bit8 Wstring::operator==(IN char *other)
|
||||
{
|
||||
if ((str==NULL)&&(other==NULL))
|
||||
return(TRUE);
|
||||
if(strcmp(str, other) != 0)
|
||||
return(FALSE);
|
||||
else
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
bit8 Wstring::operator==(IN Wstring &other)
|
||||
{
|
||||
if((str == NULL) && (other.str == NULL))
|
||||
return(TRUE);
|
||||
|
||||
if((str == NULL) || (other.str == NULL))
|
||||
return(FALSE);
|
||||
|
||||
if(strcmp(str, other.str) != 0)
|
||||
return(FALSE);
|
||||
else
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
bit8 Wstring::operator!=(IN char *other)
|
||||
{
|
||||
if(strcmp(str, other) != 0)
|
||||
return(TRUE);
|
||||
else
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
bit8 Wstring::operator!=(IN Wstring &other)
|
||||
{
|
||||
if((str == NULL) && (other.str == NULL))
|
||||
return(FALSE);
|
||||
|
||||
if((str == NULL) || (other.str == NULL))
|
||||
return(TRUE);
|
||||
|
||||
if(strcmp(str, other.str) != 0)
|
||||
return(TRUE);
|
||||
else
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
Wstring &Wstring::operator=(char *other)
|
||||
{
|
||||
set(other);
|
||||
return(*this);
|
||||
}
|
||||
|
||||
|
||||
Wstring &Wstring::operator=(IN Wstring &other)
|
||||
{
|
||||
if(*this == other)
|
||||
return(*this);
|
||||
|
||||
set(other.get());
|
||||
return(*this);
|
||||
}
|
||||
|
||||
|
||||
bit8 Wstring::cat(IN char *s)
|
||||
{
|
||||
char *oldStr;
|
||||
uint32 len;
|
||||
|
||||
if (s==NULL) // it's OK to cat nothing
|
||||
return(TRUE);
|
||||
|
||||
// Save the contents of the string.
|
||||
oldStr = str;
|
||||
|
||||
// Determine the length of the resultant string.
|
||||
len = strlen(s) + 1;
|
||||
if(oldStr)
|
||||
len += strlen(oldStr);
|
||||
|
||||
// Allocate memory for the new string.
|
||||
|
||||
if(!(str = new char[(len * sizeof(char))]))
|
||||
{
|
||||
str = oldStr;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
// Copy the contents of the old string and concatenate the passed
|
||||
// string.
|
||||
if(oldStr) strcpy(str, oldStr);
|
||||
else str[0] = 0;
|
||||
|
||||
strcat(str, s);
|
||||
|
||||
// delete the old string.
|
||||
if(oldStr)
|
||||
delete[](oldStr);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
bit8 Wstring::cat(uint32 size, IN char *s)
|
||||
{
|
||||
char *oldStr;
|
||||
uint32 len;
|
||||
|
||||
// Save the contents of the string.
|
||||
oldStr = str;
|
||||
|
||||
// Determine the length of the resultant string.
|
||||
len = size + 1;
|
||||
if(oldStr)
|
||||
len += strlen(oldStr);
|
||||
|
||||
// Allocate memory for the new string.
|
||||
if(!(str = new char[(len * sizeof(char))]))
|
||||
{
|
||||
str = oldStr;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
// Copy the contents of the old string and concatenate the passed
|
||||
// string.
|
||||
if(oldStr)
|
||||
strcpy(str, oldStr);
|
||||
else
|
||||
str[0] = 0;
|
||||
|
||||
strncat(str, s, size);
|
||||
|
||||
// delete the old string.
|
||||
if(oldStr)
|
||||
delete[](oldStr);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
bit8 Wstring::cat(IN Wstring &other)
|
||||
{
|
||||
return cat(other.get());
|
||||
}
|
||||
|
||||
Wstring &Wstring::operator+=(IN char *string)
|
||||
{
|
||||
cat(string);
|
||||
return(*this);
|
||||
}
|
||||
|
||||
Wstring &Wstring::operator+=(IN Wstring &other)
|
||||
{
|
||||
cat(other.get());
|
||||
return(*this);
|
||||
}
|
||||
|
||||
Wstring Wstring::operator+(IN char *string)
|
||||
{
|
||||
Wstring temp = *this;
|
||||
temp.cat(string);
|
||||
return(temp);
|
||||
}
|
||||
|
||||
Wstring Wstring::operator+(IN Wstring &s)
|
||||
{
|
||||
Wstring temp = *this;
|
||||
temp.cat(s);
|
||||
return(temp);
|
||||
}
|
||||
|
||||
//
|
||||
// This function deletes 'count' characters indexed by `pos' from the Wstring.
|
||||
// If `pos'+'count' is > the length of the array, the last 'count' characters
|
||||
// of the string are removed. If an error occurs, FALSE is returned.
|
||||
// Otherwise, TRUE is returned. Note: count has a default value of 1.
|
||||
//
|
||||
//
|
||||
char Wstring::remove(sint32 pos,sint32 count)
|
||||
{
|
||||
char *s;
|
||||
sint32 len;
|
||||
|
||||
if (!str)
|
||||
return(FALSE);
|
||||
|
||||
len = (sint32)strlen(str);
|
||||
|
||||
if(pos+count > len)
|
||||
pos = len - count;
|
||||
if (pos < 0)
|
||||
{
|
||||
count+=pos; // If they remove before 0, ignore up till beginning
|
||||
pos=0;
|
||||
}
|
||||
if (count<=0)
|
||||
return(FALSE);
|
||||
|
||||
if(!(s = new char[len-count+1]))
|
||||
{
|
||||
//ErrorMessage(SET_EM, "Insufficient memory to modify Wstring.");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
///////DBGMSG("Wstring::remove POS: "<<pos<<" LEN: "<<len);
|
||||
|
||||
// put nulls on both ends of substring to be removed
|
||||
str[pos] = 0;
|
||||
str[pos+count-1] = 0;
|
||||
|
||||
strcpy(s, str);
|
||||
strcat(s, &(str[pos + count]));
|
||||
delete[](str);
|
||||
str = s;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// Remove all instances of a char from the string
|
||||
bit8 Wstring::removeChar(char c)
|
||||
{
|
||||
int len=0;
|
||||
char *cptr=NULL;
|
||||
bit8 removed=FALSE;
|
||||
|
||||
if (str==NULL)
|
||||
return(FALSE);
|
||||
|
||||
len=strlen(str);
|
||||
while ((cptr=strchr(str,c)) !=NULL)
|
||||
{
|
||||
memmove(cptr,cptr+1,len-1-((int)(cptr-str)));
|
||||
len--;
|
||||
str[len]=0;
|
||||
removed=TRUE;
|
||||
}
|
||||
if (removed)
|
||||
{
|
||||
char *newStr=new char[strlen(str)+1];
|
||||
strcpy(newStr,str);
|
||||
delete[](str);
|
||||
str=newStr;
|
||||
}
|
||||
return(removed);
|
||||
}
|
||||
|
||||
void Wstring::removeSpaces(void)
|
||||
{
|
||||
removeChar(' ');
|
||||
removeChar('\t');
|
||||
}
|
||||
|
||||
void Wstring::clear(void)
|
||||
{
|
||||
if(str)
|
||||
delete[](str);
|
||||
str=NULL;
|
||||
}
|
||||
|
||||
void Wstring::setSize(sint32 size)
|
||||
{
|
||||
clear();
|
||||
if (size<0)
|
||||
return;
|
||||
str=new char[size];
|
||||
memset(str,0,size);
|
||||
}
|
||||
|
||||
void Wstring::cellCopy(char *dest, uint32 len)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
strncpy(dest, str, len);
|
||||
for(i = (uint32)strlen(str); i < len; i++)
|
||||
dest[i] = ' ';
|
||||
dest[len] = 0;
|
||||
}
|
||||
|
||||
char *Wstring::get(void)
|
||||
{
|
||||
if(!str)
|
||||
return "";
|
||||
return str;
|
||||
}
|
||||
|
||||
char Wstring::get(uint32 index)
|
||||
{
|
||||
if(index < strlen(str))
|
||||
return str[index];
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint32 Wstring::length(void)
|
||||
{
|
||||
if(str == NULL)
|
||||
return(0);
|
||||
return((uint32)strlen(str));
|
||||
}
|
||||
|
||||
|
||||
// Insert at given position and shift old stuff to right
|
||||
bit8 Wstring::insert(char *instring, uint32 pos)
|
||||
{
|
||||
if (str==NULL)
|
||||
return(set(instring));
|
||||
if (pos>strlen(str))
|
||||
pos=strlen(str);
|
||||
char *newstr=new char[strlen(str)+strlen(instring)+1];
|
||||
memset(newstr,0,strlen(str)+strlen(instring)+1);
|
||||
strcpy(newstr,str);
|
||||
// move the old data out of the way
|
||||
int bytes=strlen(str)+1-pos;
|
||||
memmove(newstr+pos+strlen(instring),newstr+pos,bytes);
|
||||
// move the new data into place
|
||||
memmove(newstr+pos,instring,strlen(instring));
|
||||
delete[](str);
|
||||
str=newstr;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// This function inserts the character specified by `k' into the string at the
|
||||
// position indexed by `pos'. If `pos' is >= the length of the string, it is
|
||||
// appended to the string. If an error occurs, FALSE is returned. Otherwise,
|
||||
// TRUE is returned.
|
||||
bit8 Wstring::insert(char k, uint32 pos)
|
||||
{
|
||||
char *s;
|
||||
uint32 len;
|
||||
char c[2];
|
||||
|
||||
if(!str)
|
||||
{
|
||||
c[0] = k;
|
||||
c[1] = 0;
|
||||
return(set(c));
|
||||
}
|
||||
|
||||
len = (uint32)strlen(str);
|
||||
|
||||
if(pos > len)
|
||||
pos = len;
|
||||
|
||||
if(!(s = (char *)new char[(len + 2)]))
|
||||
{
|
||||
//ErrorMessage(SET_EM, "Insufficient memory to modify Wstring.");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
c[0] = str[pos];
|
||||
str[pos] = 0;
|
||||
c[1] = 0;
|
||||
strcpy(s, str);
|
||||
str[pos] = c[0];
|
||||
c[0] = k;
|
||||
strcat(s, c);
|
||||
strcat(s, &(str[pos]));
|
||||
delete[](str);
|
||||
str = s;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
// This function replaces any occurences of the string pointed to by
|
||||
// `replaceThis' with the string pointed to by `withThis'. If an error
|
||||
// occurs, FALSE is returned. Otherwise, TRUE is returned.
|
||||
bit8 Wstring::replace(char *replaceThis, char *withThis)
|
||||
{
|
||||
Wstring dest;
|
||||
char *foundStr, *src;
|
||||
uint32 len;
|
||||
|
||||
src=get();
|
||||
while(src && src[0])
|
||||
{
|
||||
foundStr = strstr(src, replaceThis);
|
||||
if(foundStr)
|
||||
{
|
||||
len = (uint32)foundStr - (uint32)src;
|
||||
if(len)
|
||||
{
|
||||
if(!dest.cat(len, src))
|
||||
return(FALSE);
|
||||
}
|
||||
if(!dest.cat(withThis))
|
||||
return(FALSE);
|
||||
src = foundStr + strlen(replaceThis);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!dest.cat(src))
|
||||
return(FALSE);
|
||||
|
||||
src=NULL;
|
||||
}
|
||||
}
|
||||
return(set(dest.get()));
|
||||
}
|
||||
|
||||
|
||||
bit8 Wstring::set(IN char *s)
|
||||
{
|
||||
uint32 len;
|
||||
|
||||
clear();
|
||||
|
||||
len = (uint32)strlen(s) + 1;
|
||||
|
||||
if(!(str = new char[len]))
|
||||
{
|
||||
//ErrorMessage(SET_EM, "Insufficient memory to set Wstring.");
|
||||
return(FALSE);
|
||||
}
|
||||
strcpy(str, s);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
bit8 Wstring::set(char c, uint32 index)
|
||||
{
|
||||
if(index >= (uint32)strlen(str))
|
||||
return FALSE;
|
||||
|
||||
str[index] = c;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
char Wstring::set(uint32 size, IN char *string)
|
||||
{
|
||||
uint32 len;
|
||||
|
||||
clear();
|
||||
len = size + 1;
|
||||
|
||||
if(!(str = new char[len]))
|
||||
{
|
||||
//ErrorMessage(SET_EM, "Insufficient memory to set Wstring.");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
// Copy the bytes in the string, and NULL-terminate it.
|
||||
strncpy(str, string, size);
|
||||
str[size] = 0;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
// This function converts all alphabetical characters in the string to lower
|
||||
// case.
|
||||
void Wstring::toLower(void)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for(i = 0; i < length(); i++)
|
||||
{
|
||||
if((str[i] >= 'A') && (str[i] <= 'Z'))
|
||||
str[i] = tolower(str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function converts all alphabetical characters in the string to upper
|
||||
// case.
|
||||
void Wstring::toUpper(void)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for(i = 0; i < length(); i++)
|
||||
{
|
||||
if((str[i] >= 'a') && (str[i] <= 'z'))
|
||||
str[i] = toupper(str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function truncates the string so its length will match the specified
|
||||
// `len'. If an error occurs, FALSE is returned. Otherwise, TRUE is returned.
|
||||
bit8 Wstring::truncate(uint32 len)
|
||||
{
|
||||
Wstring tmp;
|
||||
if(!tmp.set(len, get()) || !set(tmp.get()))
|
||||
return(FALSE);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// Truncate the string after the character 'c' (gets rid of 'c' as well)
|
||||
// Do nothing if 'c' isn't in the string
|
||||
bit8 Wstring::truncate(char c)
|
||||
{
|
||||
sint32 len;
|
||||
|
||||
if (str==NULL)
|
||||
return(FALSE);
|
||||
|
||||
char *cptr=strchr(str,c);
|
||||
if (cptr==NULL)
|
||||
return(FALSE);
|
||||
len=(sint32)(cptr-str);
|
||||
truncate((uint32)len);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// Get a token from this string that's seperated by one or more
|
||||
// chars from the 'delim' string , start at offset & return offset
|
||||
sint32 Wstring::getToken(int offset,char *delim,Wstring &out)
|
||||
{
|
||||
int i;
|
||||
sint32 start;
|
||||
sint32 stop;
|
||||
for (i=offset; i<(int)length(); i++) {
|
||||
if(strchr(delim,str[i])==NULL)
|
||||
break;
|
||||
}
|
||||
if (i>=(int)length())
|
||||
return(-1);
|
||||
start=i;
|
||||
|
||||
for (; i<(int)length(); i++) {
|
||||
if(strchr(delim,str[i])!=NULL)
|
||||
break;
|
||||
}
|
||||
stop=i-1;
|
||||
out.set(str+start);
|
||||
out.truncate((uint32)stop-start+1);
|
||||
return(stop+1);
|
||||
}
|
||||
|
||||
// Get the first line of text after offset. Lines are terminated by '\r\n' or '\n'
|
||||
sint32 Wstring::getLine(int offset, Wstring &out)
|
||||
{
|
||||
int i;
|
||||
sint32 start;
|
||||
sint32 stop;
|
||||
|
||||
start=i=offset;
|
||||
if (start >= (int)length())
|
||||
return(-1);
|
||||
|
||||
for (; i<(int)length(); i++) {
|
||||
if(strchr("\r\n",str[i])!=NULL)
|
||||
break;
|
||||
}
|
||||
stop=i;
|
||||
if ((str[stop]=='\r')&&(str[stop+1]=='\n'))
|
||||
stop++;
|
||||
|
||||
out.set(str+start);
|
||||
out.truncate((uint32)stop-start+1);
|
||||
return(stop+1);
|
||||
}
|
87
Generals/Code/Tools/Launcher/wstring.h
Normal file
87
Generals/Code/Tools/Launcher/wstring.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************\
|
||||
* C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *
|
||||
******************************************************************************
|
||||
Project Name: Carpenter (The RedAlert ladder creator)
|
||||
File Name : main.cpp
|
||||
Author : Neal Kettler
|
||||
Start Date : June 1, 1997
|
||||
Last Update : June 17, 1997
|
||||
\****************************************************************************/
|
||||
|
||||
#ifndef WSTRING_HEADER
|
||||
#define WSTRING_HEADER
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "wstypes.h"
|
||||
|
||||
class Wstring
|
||||
{
|
||||
public:
|
||||
Wstring();
|
||||
Wstring(IN const Wstring &other);
|
||||
Wstring(IN char *string);
|
||||
~Wstring();
|
||||
|
||||
void clear(void);
|
||||
|
||||
bit8 cat(IN char *string);
|
||||
bit8 cat(uint32 size,IN char *string);
|
||||
bit8 cat(IN Wstring &string);
|
||||
|
||||
void cellCopy(OUT char *dest, uint32 len);
|
||||
char remove(sint32 pos, sint32 count);
|
||||
bit8 removeChar(char c);
|
||||
void removeSpaces(void);
|
||||
char *get(void);
|
||||
char get(uint32 index);
|
||||
uint32 length(void);
|
||||
bit8 insert(char c, uint32 pos);
|
||||
bit8 insert(char *instring, uint32 pos);
|
||||
bit8 replace(IN char *replaceThis,IN char *withThis);
|
||||
char set(IN char *str);
|
||||
char set(uint32 size,IN char *str);
|
||||
bit8 set(char c, uint32 index);
|
||||
void setSize(sint32 bytes); // create an empty string
|
||||
void toLower(void);
|
||||
void toUpper(void);
|
||||
bit8 truncate(uint32 len);
|
||||
bit8 truncate(char c); // trunc after char c
|
||||
sint32 getToken(int offset,char *delim,Wstring &out);
|
||||
sint32 getLine(int offset, Wstring &out);
|
||||
|
||||
bit8 operator==(IN char *other);
|
||||
bit8 operator==(IN Wstring &other);
|
||||
bit8 operator!=(IN char *other);
|
||||
bit8 operator!=(IN Wstring &other);
|
||||
|
||||
Wstring &operator=(IN char *other);
|
||||
Wstring &operator=(IN Wstring &other);
|
||||
Wstring &operator+=(IN char *other);
|
||||
Wstring &operator+=(IN Wstring &other);
|
||||
Wstring operator+(IN char *other);
|
||||
Wstring operator+(IN Wstring &other);
|
||||
|
||||
private:
|
||||
char *str; // Pointer to allocated string.
|
||||
};
|
||||
|
||||
#endif
|
82
Generals/Code/Tools/Launcher/wstypes.h
Normal file
82
Generals/Code/Tools/Launcher/wstypes.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************\
|
||||
* C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *
|
||||
******************************************************************************
|
||||
Project Name:
|
||||
File Name : wtypes.h
|
||||
Author : Neal Kettler
|
||||
Start Date : June 3, 1997
|
||||
Last Update : June 17, 1997
|
||||
|
||||
Standard type definitions for the sake of portability and readability.
|
||||
\***************************************************************************/
|
||||
|
||||
#ifndef WTYPES_HEADER
|
||||
#define WTYPES_HEADER
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x,y) (((x)<(y))?(x):(y))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(x,y) (((x)>(y))?(x):(y))
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
//These are used for readability purposes mostly, when a method takes a
|
||||
// pointer or reference these help specify what will happen to the data
|
||||
// that is sent in.
|
||||
#define IN
|
||||
#define OUT
|
||||
#define INOUT
|
||||
|
||||
typedef char bit8;
|
||||
typedef char sint8;
|
||||
typedef unsigned char uint8;
|
||||
typedef signed short int sint16;
|
||||
typedef unsigned short int uint16;
|
||||
typedef signed int sint32;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
#define MAX_BIT8 0x1
|
||||
#define MAX_UINT32 0xFFFFFFFF
|
||||
#define MAX_UINT16 0xFFFF
|
||||
#define MAX_UINT8 0xFF
|
||||
#define MAX_SINT32 0x7FFFFFFF
|
||||
#define MAX_SINT16 0x7FFF
|
||||
#define MAX_SINT8 0x7F
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
#endif
|
Reference in a new issue