INICODE.CPP (10561B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: F:\projects\c&c0\vcs\code\inicode.cpv 4.38 03 Jul 1996 05:14:04 JOE_BOSTIC $ */ 17 /*************************************************************************** 18 ** 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 ** 19 *************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : INICODE.CPP * 24 * * 25 * Programmer : David R Dettmer * 26 * * 27 * Start Date : November 7, 1995 * 28 * * 29 * Last Update : February 20, 1996 [JLB] * 30 * * 31 *-------------------------------------------------------------------------* 32 * Functions: * 33 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 34 35 #include "function.h" 36 37 38 #ifdef TOFIX 39 40 void Get_Scenario_Digest(char * digest, char * buffer) 41 { 42 char buf[128]; // Working string staging buffer. 43 char stage[sizeof(BigInt)*2]; 44 45 char * stage_ptr = &stage[0]; 46 int len = strlen(buffer) + 2; 47 char * tbuffer = buffer + len; 48 49 WWGetPrivateProfileString("DIGEST", NULL, NULL, tbuffer, sizeof(_staging_buffer)-len, buffer); 50 stage[0] = '\0'; 51 while (*tbuffer != '\0') { 52 53 WWGetPrivateProfileString("DIGEST", tbuffer, NULL, buf, sizeof(buf)-1, buffer); 54 strcat(stage, buf); 55 tbuffer += strlen(tbuffer)+1; 56 } 57 58 len = strlen(stage); 59 char * dbuffer = &stage[0]; 60 tbuffer = &stage[0]; 61 for (int index = 0; index < len/2; index++) { 62 int c; 63 if (isdigit(*tbuffer)) { 64 c = (*tbuffer) - '0'; 65 } else { 66 c = 10 + (toupper(*tbuffer) - 'A'); 67 } 68 tbuffer++; 69 c <<= 4; 70 if (isdigit(*tbuffer)) { 71 c |= (*tbuffer) - '0'; 72 } else { 73 c |= 10 + (toupper(*tbuffer) - 'A'); 74 } 75 tbuffer++; 76 *dbuffer++ = c; 77 } 78 79 /* 80 ** Decode and decrypt the number. 81 */ 82 BigInt hash = 0; 83 hash.DERDecode((unsigned char*)stage); 84 85 BigInt d; 86 d = d.Decode_ASCII(KEY_D); 87 BigInt n; 88 n = n.Decode_ASCII(KEY_N); 89 90 hash = hash.exp_b_mod_c(d, n); 91 92 memcpy(digest, &hash, 20); 93 94 buffer = strstr(buffer, "[DIGEST]"); 95 if (buffer) { 96 *buffer = '\0'; 97 } 98 } 99 100 101 bool Read_Scenario_INI_Write_INB( char *root, bool fresh) 102 { 103 char *buffer; // Scenario.ini staging buffer pointer. 104 char *binbuf; // Scenario.inb staging buffer pointer. 105 char fname[_MAX_FNAME+_MAX_EXT]; // full INI filename 106 char buf[256]; // Working string staging buffer. 107 char scenarioname[40]; 108 int len; 109 unsigned char val; 110 111 /* 112 ** Fetch working pointer to the INI staging buffer. Make sure that the buffer 113 ** is cleared out before proceeding. (Don't use the HidPage for this, since 114 ** the HidPage may be needed for various uncompressions during the INI 115 ** parsing.) 116 */ 117 buffer = (char *)_staging_buffer; 118 memset(buffer, '\0', sizeof(_staging_buffer)); 119 120 /* 121 ** Create scenario filename and read the file. 122 ** The previous routine verifies that the file is available. 123 */ 124 125 sprintf(fname,"%s.INI",root); 126 CCFileClass file(fname); 127 128 file.Read(buffer, sizeof(_staging_buffer)-1); 129 130 /* 131 ** Fetch and slice off any message digest attached. 132 */ 133 char digest[20]; 134 Get_Scenario_Digest(digest, buffer); 135 136 char real_digest[20]; 137 SHAEngine digest_engine; 138 digest_engine.Hash(buffer, strlen(buffer)); 139 digest_engine.Result(real_digest); 140 141 if (memcmp(digest, real_digest, sizeof(real_digest)) != 0) { 142 WWMessageBox().Process(TXT_SCENARIO_ERROR, TXT_OK); 143 } 144 145 /* 146 ** Init the Scenario CRC value 147 */ 148 ScenarioCRC = 0; 149 len = strlen(buffer); 150 for (int i = 0; i < len; i++) { 151 val = (unsigned char)buffer[i]; 152 Add_CRC(&ScenarioCRC, (unsigned long)val); 153 } 154 155 sprintf(fname,"%s.INB",root); 156 file.Set_Name(fname); 157 file.Cache(16384); 158 file.Open(WRITE); 159 160 unsigned long crc = Ini_Binary_Version(); 161 162 file.Write( (char *)&crc, sizeof(crc) ); 163 164 binbuf = (char *)Alloc( sizeof(_staging_buffer), MEM_NORMAL ); 165 166 if (binbuf) { 167 Write_Bin_Init( binbuf, sizeof(_staging_buffer) ); 168 } else { 169 Print_Error_End_Exit( "Unable to alloc space for writing INB" ); 170 } 171 172 /* 173 ** Fetch the appropriate movie names from the INI file. 174 */ 175 WWGetPrivateProfileString("Basic", "Name", "", scenarioname, sizeof(scenarioname), buffer); 176 WWGetPrivateProfileString("Basic", "Intro", "x", Scen.IntroMovie, sizeof(Scen.IntroMovie), buffer); 177 WWGetPrivateProfileString("Basic", "Brief", "x", Scen.BriefMovie, sizeof(Scen.BriefMovie), buffer); 178 WWGetPrivateProfileString("Basic", "Win", "x", Scen.WinMovie, sizeof(Scen.WinMovie), buffer); 179 WWGetPrivateProfileString("Basic", "Lose", "x", Scen.LoseMovie, sizeof(Scen.LoseMovie), buffer); 180 WWGetPrivateProfileString("Basic", "Action", "x", Scen.ActionMovie, sizeof(Scen.ActionMovie), buffer); 181 Scen.IsToCarryOver = WWGetPrivateProfileInt("Basic", "ToCarryOver", 0, buffer); 182 Scen.IsToInherit = WWGetPrivateProfileInt("Basic", "ToInherit", 0, buffer); 183 184 Write_Bin_String( scenarioname, strlen(scenarioname), binbuf ); 185 Write_Bin_String( Scen.IntroMovie, strlen(Scen.IntroMovie), binbuf ); 186 Write_Bin_String( Scen.BriefMovie, strlen(Scen.BriefMovie), binbuf ); 187 Write_Bin_String( Scen.WinMovie, strlen(Scen.WinMovie), binbuf ); 188 Write_Bin_String( Scen.LoseMovie, strlen(Scen.LoseMovie), binbuf ); 189 Write_Bin_String( Scen.ActionMovie, strlen(Scen.ActionMovie), binbuf ); 190 191 /* 192 ** Fetch the transition theme for this scenario. 193 */ 194 Scen.TransitTheme = THEME_NONE; 195 WWGetPrivateProfileString("Basic", "Theme", "No Theme", buf, sizeof(buf), buffer); 196 Scen.TransitTheme = Theme.From_Name(buf); 197 198 WWGetPrivateProfileString( "Basic", "Player", "Greece", buf, 127, buffer); 199 Scen.PlayerHouse = HouseTypeClass::From_Name(buf); 200 if (Scen.PlayerHouse >= HOUSE_MULTI1) { 201 Scen.PlayerHouse = HOUSE_GREECE; 202 } 203 // TCTC To Fix? 204 // Scen.CarryOverPercent = WWGetPrivateProfileInt( "Basic", "CarryOverMoney", 100, buffer); 205 Scen.CarryOverCap = WWGetPrivateProfileInt( "Basic", "CarryOverCap", -1, buffer); 206 Scen.Percent = WWGetPrivateProfileInt( "Basic", "Percent", 0, buffer); 207 208 Write_Bin_Num( &Scen.TransitTheme, sizeof(Scen.TransitTheme), binbuf ); 209 Write_Bin_Num( &Scen.PlayerHouse, sizeof(Scen.PlayerHouse), binbuf ); 210 Write_Bin_Num( &Scen.CarryOverPercent, 1, binbuf ); 211 Write_Bin_Num( &Scen.CarryOverCap, 2, binbuf ); 212 Write_Bin_Num( &Scen.Percent, 1, binbuf ); 213 214 /* 215 ** Read in the specific information for each of the house types. This creates 216 ** the houses of different types. 217 */ 218 HouseClass::Read_INI(buffer); 219 Call_Back(); 220 221 /* 222 ** Read in the team-type data. The team types must be created before any 223 ** triggers can be created. 224 */ 225 TeamTypeClass::Read_INI(buffer); 226 Call_Back(); 227 228 /* 229 ** Assign PlayerPtr by reading the player's house from the INI; 230 ** Must be done before any TechnoClass objects are created. 231 */ 232 if (Session.Type == GAME_NORMAL) { 233 Scen.CarryOverPercent = Cardinal_To_Fixed(100, Scen.CarryOverPercent); 234 235 PlayerPtr = HouseClass::As_Pointer( Scen.PlayerHouse ); 236 assert(PlayerPtr != NULL); 237 PlayerPtr->IsHuman = true; 238 239 int carryover; 240 if (Scen.CarryOverCap != -1) { 241 carryover = MIN(Fixed_To_Cardinal(Scen.CarryOverMoney, Scen.CarryOverPercent), (Scen.CarryOverCap * 100) ); 242 } else { 243 carryover = Fixed_To_Cardinal(Scen.CarryOverMoney, Scen.CarryOverPercent); 244 } 245 PlayerPtr->Credits += carryover; 246 PlayerPtr->Control.InitialCredits += carryover; 247 } else { 248 249 Assign_Houses(); 250 } 251 252 /* 253 ** Read in the trigger data. The triggers must be created before any other 254 ** objects can be initialized. 255 */ 256 TriggerClass::Read_INI(buffer); 257 Call_Back(); 258 259 /* 260 ** Read in the map control values. This includes dimensions 261 ** as well as theater information. 262 */ 263 Map.Read_INI(buffer); 264 Call_Back(); 265 266 /* 267 ** Attempt to read the map's binary image file; if fails, read the 268 ** template data from the INI, for backward compatibility 269 */ 270 if (fresh) { 271 if (!Map.Read_Binary(root, &ScenarioCRC)) { 272 return( false ); 273 } 274 } 275 Call_Back(); 276 277 /* 278 ** Read in and place the 3D terrain objects. 279 */ 280 TerrainClass::Read_INI(buffer); 281 Call_Back(); 282 283 /* 284 ** Read in and place the units (all sides). 285 */ 286 UnitClass::Read_INI(buffer); 287 Call_Back(); 288 289 AircraftClass::Read_INI(buffer); 290 Call_Back(); 291 292 VesselClass::Read_INI(buffer); 293 Call_Back(); 294 295 /* 296 ** Read in and place the infantry units (all sides). 297 */ 298 InfantryClass::Read_INI(buffer); 299 Call_Back(); 300 301 /* 302 ** Read in and place all the buildings on the map. 303 */ 304 BuildingClass::Read_INI(buffer); 305 Call_Back(); 306 307 /* 308 ** Read in the AI's base information. 309 */ 310 Base.Read_INI(buffer); 311 Call_Back(); 312 313 /* 314 ** Read in any normal overlay objects. 315 */ 316 OverlayClass::Read_INI(buffer); 317 Call_Back(); 318 319 /* 320 ** Read in any smudge overlays. 321 */ 322 SmudgeClass::Read_INI(buffer); 323 Call_Back(); 324 325 /* 326 ** Read in any briefing text. 327 */ 328 char * stage = &Scen.BriefingText[0]; 329 *stage = '\0'; 330 int index = 1; 331 332 /* 333 ** Build the full text of the mission objective. 334 */ 335 for (;;) { 336 char buff[16]; 337 338 sprintf(buff, "%d", index++); 339 *stage = '\0'; 340 WWGetPrivateProfileString("Briefing", buff, "", stage, 255, buffer); 341 if (strlen(stage) == 0) break; 342 strcat(stage, " "); 343 stage += strlen(stage); 344 } 345 346 len = Write_Bin_Length( binbuf ); 347 if (len != -1) { 348 file.Write( binbuf, len ); 349 } 350 351 Free( binbuf ); 352 file.Close(); 353 354 return(true); 355 } 356 357 #endif 358 359 360 361 362 363 364 365 366