JSHELL.CPP (30188B)
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: /CounterStrike/JSHELL.CPP 2 3/13/97 2:05p Steve_tall $ */ 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 : JSHELL.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : April 2, 1994 * 28 * * 29 * Last Update : May 11, 1995 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * Build_Translucent_Table -- Creates a translucent control table. * 34 * Conquer_Build_Translucent_Table -- Builds fading table for shadow colors only. * 35 * Fatal -- General purpose fatal error handler. * 36 * Load_Alloc_Data -- Allocates a buffer and loads the file into it. * 37 * Load_Uncompress -- Loads and uncompresses data to a buffer. * 38 * Set_Window -- Sets the window dimensions to that specified. * 39 * Small_Icon -- Create a small icon from a big one. * 40 * Translucent_Table_Size -- Determines the size of a translucent table. * 41 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 42 43 #include "function.h" 44 #include "wwfile.h" 45 46 47 /*********************************************************************************************** 48 * Small_Icon -- Create a small icon from a big one. * 49 * * 50 * This routine will extract the specified icon from the icon data file and convert that * 51 * icon into a small (3x3) representation. Typical use of this mini-icon is for the radar * 52 * map. * 53 * * 54 * INPUT: iconptr -- Pointer to the icon data file. * 55 * * 56 * iconnum -- The embedded icon number to convert into a small image. * 57 * * 58 * OUTPUT: Returns with a pointer to the small icon imagery. This is exactly 9 bytes long. * 59 * * 60 * WARNINGS: none * 61 * * 62 * HISTORY: * 63 * 05/11/1995 JLB : Created. * 64 *=============================================================================================*/ 65 void * Small_Icon(void const * iconptr, int iconnum) 66 { 67 static unsigned char _icon[9]; 68 IControl_Type const * iptr = (IControl_Type const *)iconptr; 69 unsigned char * data; 70 71 if (iconptr) { 72 iconnum = ((char *)((char *)iptr + iptr->Map))[iconnum]; 73 data = &((unsigned char *)((unsigned char *)iptr + iptr->Icons))[iconnum*(24*24)]; 74 // data = &iptr->Icons[iconnum*(24*24)]; 75 76 for (int index = 0; index < 9; index++) { 77 int _offsets[9] = { 78 4+4*24, 79 12+4*24, 80 20+4*24, 81 4+12*24, 82 12+12*24, 83 20+12*24, 84 4+20*24, 85 12+20*24, 86 20+20*24 87 }; 88 _icon[index] = data[_offsets[index]]; 89 } 90 } 91 92 return(_icon); 93 } 94 95 96 /*********************************************************************************************** 97 * Set_Window -- Sets the window dimensions to that specified. * 98 * * 99 * Use this routine to set the windows dimensions to the coordinates and dimensions * 100 * specified. * 101 * * 102 * INPUT: x -- Window X pixel position. * 103 * * 104 * y -- Window Y pixel position. * 105 * * 106 * w -- Window width in pixels. * 107 * * 108 * h -- Window height in pixels. * 109 * * 110 * OUTPUT: none * 111 * * 112 * WARNINGS: The X and width values are truncated to an even 8 pixel boundary. This is * 113 * the same as stripping off the lower 3 bits. * 114 * * 115 * HISTORY: * 116 * 01/15/1995 JLB : Created. * 117 *=============================================================================================*/ 118 void Set_Window(int window, int x, int y, int w, int h) 119 { 120 WindowList[window][WINDOWWIDTH] = w; 121 WindowList[window][WINDOWHEIGHT] = h; 122 WindowList[window][WINDOWX] = x; 123 WindowList[window][WINDOWY] = y; 124 } 125 126 127 /*********************************************************************************************** 128 * Fatal -- General purpose fatal error handler. * 129 * * 130 * This is a very simple general purpose fatal error handler. It goes directly to text * 131 * mode, prints the error, and then aborts with a failure code. * 132 * * 133 * INPUT: message -- The text message to display. * 134 * * 135 * ... -- Any optional parameters that are used in formatting the message. * 136 * * 137 * OUTPUT: none * 138 * * 139 * WARNINGS: This routine never returns. The game exits immediately. * 140 * * 141 * HISTORY: * 142 * 10/17/1994 JLB : Created. * 143 *=============================================================================================*/ 144 void Fatal(char const * message, ...) 145 { 146 va_list va; 147 148 va_start(va, message); 149 Prog_End(message, true); 150 vfprintf(stderr, message, va); 151 Mono_Printf(message); 152 if (!RunningAsDLL) { //PG 153 Emergency_Exit(EXIT_FAILURE); 154 } 155 } 156 157 158 #ifdef NEVER 159 void File_Fatal(char const * message) 160 { 161 //Prog_End(); 162 perror(message); 163 Emergency_Exit(EXIT_FAILURE); 164 } 165 #endif 166 167 168 169 /*********************************************************************************************** 170 * Load_Uncompress -- Loads and uncompresses data to a buffer. * 171 * * 172 * This is the C++ counterpart to the Load_Uncompress function. It will load the file * 173 * specified into the graphic buffer indicated and uncompress it. * 174 * * 175 * INPUT: file -- The file to load and uncompress. * 176 * * 177 * uncomp_buff -- The graphic buffer that initial loading will use. * 178 * * 179 * dest_buff -- The buffer that will hold the uncompressed data. * 180 * * 181 * reserved_data -- This is an optional pointer to a buffer that will hold any * 182 * reserved data the compressed file may contain. This is * 183 * typically a palette. * 184 * * 185 * OUTPUT: Returns with the size of the uncompressed data in the destination buffer. * 186 * * 187 * WARNINGS: none * 188 * * 189 * HISTORY: * 190 * 10/17/1994 JLB : Created. * 191 *=============================================================================================*/ 192 long Load_Uncompress(FileClass &file, BuffType &uncomp_buff, BuffType &dest_buff, void * reserved_data) 193 { 194 unsigned short size; 195 void * sptr = uncomp_buff.Get_Buffer(); 196 void * dptr = dest_buff.Get_Buffer(); 197 int opened = false; 198 CompHeaderType header; 199 200 /* 201 ** The file must be opened in order to be read from. If the file 202 ** isn't opened, then open it. Record this fact so that it can be 203 ** restored to its closed state at the end. 204 */ 205 if (!file.Is_Open()) { 206 if (!file.Open()) { 207 return(0); 208 } 209 opened = true; 210 } 211 212 /* 213 ** Read in the size of the file (supposedly). 214 */ 215 file.Read(&size, sizeof(size)); 216 217 /* 218 ** Read in the header block. This block contains the compression type 219 ** and skip data (among other things). 220 */ 221 file.Read(&header, sizeof(header)); 222 size -= sizeof(header); 223 224 /* 225 ** If there are skip bytes then they must be processed. Either read 226 ** them into the buffer provided or skip past them. No check is made 227 ** to ensure that the reserved data buffer is big enough (watch out!). 228 */ 229 if (header.Skip) { 230 size -= header.Skip; 231 if (reserved_data) { 232 file.Read(reserved_data, header.Skip); 233 } else { 234 file.Seek(header.Skip, SEEK_CUR); 235 } 236 header.Skip = 0; 237 } 238 239 /* 240 ** Determine where is the proper place to load the data. If both buffers 241 ** specified are identical, then the data should be loaded at the end of 242 ** the buffer and decompressed at the beginning. 243 */ 244 if (uncomp_buff.Get_Buffer() == dest_buff.Get_Buffer()) { 245 sptr = (char *)sptr + uncomp_buff.Get_Size()-(size+sizeof(header)); 246 } 247 248 /* 249 ** Read in the bulk of the data. 250 */ 251 Mem_Copy(&header, sptr, sizeof(header)); 252 file.Read((char *)sptr + sizeof(header), size); 253 254 /* 255 ** Decompress the data. 256 */ 257 size = (unsigned int) Uncompress_Data(sptr, dptr); 258 259 /* 260 ** Close the file if necessary. 261 */ 262 if (opened) { 263 file.Close(); 264 } 265 return((long)size); 266 } 267 268 269 int Load_Picture(char const * filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char * palette, PicturePlaneType ) 270 { 271 return(Load_Uncompress(CCFileClass(filename), scratchbuf, destbuf, palette ) / 8000); 272 } 273 274 275 /*********************************************************************************************** 276 * Load_Alloc_Data -- Allocates a buffer and loads the file into it. * 277 * * 278 * This is the C++ replacement for the Load_Alloc_Data function. It will allocate the * 279 * memory big enough to hold the file and then read the file into it. * 280 * * 281 * INPUT: file -- The file to read. * 282 * * 283 * mem -- The memory system to use for allocation. * 284 * * 285 * OUTPUT: Returns with a pointer to the allocated and filled memory block. * 286 * * 287 * WARNINGS: none * 288 * * 289 * HISTORY: * 290 * 10/17/1994 JLB : Created. * 291 *=============================================================================================*/ 292 void * Load_Alloc_Data(FileClass &file) 293 { 294 void * ptr = 0; 295 long size = file.Size(); 296 297 ptr = new char [size]; 298 if (ptr) { 299 file.Read(ptr, size); 300 } 301 return(ptr); 302 } 303 304 305 /*********************************************************************************************** 306 * Translucent_Table_Size -- Determines the size of a translucent table. * 307 * * 308 * Use this routine to determine how big the translucent table needs * 309 * to be given the specified number of colors. This value is typically * 310 * used when allocating the buffer for the translucent table. * 311 * * 312 * INPUT: count -- The number of colors that are translucent. * 313 * * 314 * OUTPUT: Returns the size of the translucent table. * 315 * * 316 * WARNINGS: none * 317 * * 318 * HISTORY: * 319 * 04/02/1994 JLB : Created. * 320 *=============================================================================================*/ 321 long Translucent_Table_Size(int count) 322 { 323 return(256L + (256L * count)); 324 } 325 326 327 /*********************************************************************************************** 328 * Build_Translucent_Table -- Creates a translucent control table. * 329 * * 330 * The table created by this routine is used by Draw_Shape (GHOST) to * 331 * achieve a translucent affect. The original color of the shape will * 332 * show through. This differs from the fading effect, since that * 333 * affect only alters the background color toward a single destination * 334 * color. * 335 * * 336 * INPUT: palette -- Pointer to the control palette. * 337 * * 338 * control -- Pointer to array of structures that control how * 339 * the translucent table will be built. * 340 * * 341 * count -- The number of entries in the control array. * 342 * * 343 * buffer -- Pointer to buffer to place the translucent table. * 344 * If NULL is passed in, then the buffer will be * 345 * allocated. * 346 * * 347 * OUTPUT: Returns with pointer to the translucent table. * 348 * * 349 * WARNINGS: This routine is exceedingly slow. Use sparingly. * 350 * * 351 * HISTORY: * 352 * 04/02/1994 JLB : Created. * 353 *=============================================================================================*/ 354 void * Build_Translucent_Table(PaletteClass const & palette, TLucentType const * control, int count, void * buffer) 355 { 356 unsigned char const *table; // Remap table pointer. 357 int index; // Working color index. 358 359 if (count && control/* && palette*/) { // palette can't be NULL... ST - 5/9/2019 360 if (!buffer) { 361 buffer = new char [Translucent_Table_Size(count)]; 362 } 363 364 if (buffer) { 365 memset(buffer, -1, 256); 366 table = (unsigned char*)buffer + 256; 367 368 /* 369 ** Build the individual remap tables for each translucent color. 370 */ 371 for (index = 0; index < count; index++) { 372 ((unsigned char*)buffer)[control[index].SourceColor] = index; 373 Build_Fading_Table(palette.Get_Data(), (void*)table, control[index].DestColor, control[index].Fading); 374 table = (unsigned char*)table + 256; 375 } 376 } 377 } 378 return(buffer); 379 } 380 381 382 /*********************************************************************************************** 383 * Conquer_Build_Translucent_Table -- Builds fading table for shadow colors only. * 384 * * 385 * This routine will build a translucent (fading) table to remap colors into the shadow * 386 * color region of the palette. Shadow colors are not affected by this translucent table. * 387 * This means that a shape can be overlapped any number of times and the imagery will * 388 * remain deterministic (and constant). * 389 * * 390 * INPUT: palette -- Pointer to the palette to base the translucent process on. * 391 * * 392 * control -- Pointer to special control structure that specifies the * 393 * target color, and percentage of fade. * 394 * * 395 * count -- The number of colors to be remapped (entries in the control array). * 396 * * 397 * buffer -- Pointer to the staging buffer that will hold the translucent table * 398 * data. If this parameter is NULL, then an appropriate sized table * 399 * will be allocated. * 400 * * 401 * OUTPUT: Returns with a pointer to the translucent table data. * 402 * * 403 * WARNINGS: none * 404 * * 405 * HISTORY: * 406 * 06/27/1994 JLB : Created. * 407 *=============================================================================================*/ 408 void * Conquer_Build_Translucent_Table(PaletteClass const & palette, TLucentType const * control, int count, void * buffer) 409 { 410 unsigned char const *table; // Remap table pointer. 411 412 if (count && control) { 413 if (!buffer) { 414 buffer = new char [Translucent_Table_Size(count)]; 415 } 416 417 if (buffer) { 418 memset(buffer, -1, 256); 419 table = (unsigned char*)buffer + 256; 420 421 /* 422 ** Build the individual remap tables for each translucent color. 423 */ 424 for (int index = 0; index < count; index++) { 425 ((unsigned char*)buffer)[control[index].SourceColor] = index; 426 Conquer_Build_Fading_Table(palette, (void*)table, control[index].DestColor, control[index].Fading); 427 table = (unsigned char*)table + 256; 428 } 429 } 430 } 431 return(buffer); 432 } 433 434 435 void * Make_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac) 436 { 437 if (dest) { 438 unsigned char * ptr = (unsigned char *)dest; 439 440 /* 441 ** Find an appropriate remap color index for every color in the palette. 442 ** There are certain exceptions to this, but they are trapped within the 443 ** loop. 444 */ 445 for (int index = 0; index < PaletteClass::COLOR_COUNT; index++) { 446 447 /* 448 ** Find the color that, ideally, the working color should be remapped 449 ** to in the special remap range. 450 */ 451 RGBClass trycolor = palette[index]; 452 trycolor.Adjust(frac, palette[color]); // Try to match this color. 453 454 /* 455 ** Search through the remap range to find the color that should be remapped 456 ** to. This special range is used for shadows or other effects that are 457 ** not compounded if additively applied. 458 */ 459 *ptr++ = palette.Closest_Color(trycolor); 460 } 461 } 462 return(dest); 463 } 464 465 466 void * Conquer_Build_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac) 467 { 468 if (dest) { 469 unsigned char * ptr = (unsigned char *)dest; 470 // HSVClass desthsv = palette[color]; 471 472 /* 473 ** Find an appropriate remap color index for every color in the palette. 474 ** There are certain exceptions to this, but they are trapped within the 475 ** loop. 476 */ 477 for (int index = 0; index < PaletteClass::COLOR_COUNT; index++) { 478 479 /* 480 ** If this color should not be remapped, then it will be stored as a remap 481 ** to itself. This is effectively no remap. 482 */ 483 if (index > PaletteClass::COLOR_COUNT-16 || index == 0) { 484 *ptr++ = index; 485 } else { 486 487 /* 488 ** Find the color that, ideally, the working color should be remapped 489 ** to in the special remap range. 490 */ 491 RGBClass trycolor = palette[index]; 492 trycolor.Adjust(frac, palette[color]); // Try to match this color. 493 494 /* 495 ** Search through the remap range to find the color that should be remapped 496 ** to. This special range is used for shadows or other effects that are 497 ** not compounded if additively applied. 498 */ 499 int best = -1; 500 int bvalue = 0; 501 for (int id = PaletteClass::COLOR_COUNT-16; id < PaletteClass::COLOR_COUNT-1; id++) { 502 int diff = palette[id].Difference(trycolor); 503 if (best == -1 || diff < bvalue) { 504 best = id; 505 bvalue = diff; 506 } 507 } 508 *ptr++ = best; 509 } 510 } 511 } 512 return(dest); 513 } 514 515 516 #ifdef OBSOLETE 517 //int Desired_Facing8(int x1, int y1, int x2, int y2) 518 DirType xDesired_Facing8(int x1, int y1, int x2, int y2) 519 { 520 int index = 0; // Facing composite value. 521 522 /* 523 ** Figure the absolute X difference. This determines 524 ** if the facing is leftward or not. 525 */ 526 int xdiff = x2-x1; 527 if (xdiff < 0) { 528 index |= 0x00C0; 529 xdiff = -xdiff; 530 } 531 532 /* 533 ** Figure the absolute Y difference. This determines 534 ** if the facing is downward or not. This also clarifies 535 ** exactly which quadrant the facing lies. 536 */ 537 int ydiff = y1-y2; 538 if (ydiff < 0) { 539 index ^= 0x0040; 540 ydiff = -ydiff; 541 } 542 543 /* 544 ** Determine which of the two direction offsets it bigger. The 545 ** offset direction that is bigger (X or Y) will indicate which 546 ** orthogonal direction the facing is closer to. 547 */ 548 unsigned bigger; 549 unsigned smaller; 550 if (xdiff < ydiff) { 551 smaller = xdiff; 552 bigger = ydiff; 553 } else { 554 smaller = ydiff; 555 bigger = xdiff; 556 } 557 558 /* 559 ** If on the diagonal, then incorporate this into the facing 560 ** and then bail. The facing is known. 561 */ 562 if (((bigger+1)/2) <= smaller) { 563 index += 0x0020; 564 return(DirType(index)); 565 } 566 567 /* 568 ** Determine if the facing is closer to the Y axis or 569 ** the X axis. 570 */ 571 int adder = (index & 0x0040); 572 if (xdiff == bigger) { 573 adder ^= 0x0040; 574 } 575 index += adder; 576 577 return(DirType(index)); 578 } 579 580 581 //int Desired_Facing256(int srcx, int srcy, int dstx, int dsty) 582 DirType xDesired_Facing256(int srcx, int srcy, int dstx, int dsty) 583 { 584 int composite=0; // Facing built from intermediate calculations. 585 586 /* 587 ** Fetch the absolute X difference. This also gives a clue as 588 ** to which hemisphere the direction lies. 589 */ 590 int xdiff = dstx - srcx; 591 if (xdiff < 0) { 592 composite |= 0x00C0; 593 xdiff = -xdiff; 594 } 595 596 /* 597 ** Fetch the absolute Y difference. This clarifies the exact 598 ** quadrant that the direction lies. 599 */ 600 int ydiff = srcy - dsty; 601 if (ydiff < 0) { 602 composite ^= 0x0040; 603 ydiff = -ydiff; 604 } 605 606 /* 607 ** Bail early if the coordinates are the same. This check also 608 ** has the added bonus of ensuring that checking for division 609 ** by zero is not needed in the following section. 610 */ 611 if (xdiff == 0 && ydiff == 0) return(DirType(0xFF)); 612 613 /* 614 ** Determine which of the two direction offsets it bigger. The 615 ** offset direction that is bigger (X or Y) will indicate which 616 ** orthogonal direction the facing is closer to. 617 */ 618 unsigned bigger; 619 unsigned smaller; 620 if (xdiff < ydiff) { 621 smaller = xdiff; 622 bigger = ydiff; 623 } else { 624 smaller = ydiff; 625 bigger = xdiff; 626 } 627 628 /* 629 ** Now that the quadrant is known, we need to determine how far 630 ** from the orthogonal directions, the facing lies. This value 631 ** is calculated as a ratio from 0 (matches orthogonal) to 31 632 ** (matches diagonal). 633 */ 634 int frac = (smaller * 32U) / bigger; 635 636 /* 637 ** Given the quadrant and knowing whether the facing is closer 638 ** to the X or Y axis, we must make an adjustment toward the 639 ** subsequent quadrant if necessary. 640 */ 641 int adder = (composite & 0x0040); 642 if (xdiff > ydiff) { 643 adder ^= 0x0040; 644 } 645 if (adder) { 646 frac = (adder - frac)-1; 647 } 648 649 /* 650 ** Integrate the fraction value into the quadrant. 651 */ 652 composite += frac; 653 654 /* 655 ** Return with the final facing value. 656 */ 657 return(DirType(composite & 0x00FF)); 658 } 659 #endif